diff -uNr linux-2.4.37.9/Documentation/Configure.help linux-2.4.37.9-vrs1-5mx2/Documentation/Configure.help --- linux-2.4.37.9/Documentation/Configure.help Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/Configure.help Mon Jun 7 18:59:41 2010 @@ -4959,6 +4959,13 @@ Say Y to enable support for Permedia2 AGP frame buffer card from 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus. +Permedia3 support (EXPERIMENTAL) +CONFIG_FB_PM3 + This is the frame buffer device driver for the 3DLabs Permedia3 + chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & + similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 + and maybe other boards. + Phase5 CVisionPPC/BVisionPPC support CONFIG_FB_PM2_CVPPC Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC @@ -13421,6 +13428,17 @@ The module will be called tmspci.o. If you want to compile it as a module, say M here and read . +Altera ether00 support +CONFIG_ETHER00 + This is the driver for Altera's ether00 ethernet mac IP core. Say + Y here if you want to build support for this into the kernel. It + is also available as a module (say M here) that can be inserted/ + removed from the kernel at the same time as the PLD is configured. + If this driver is running on an epxa10 development board then it + will generate a suitable hw address based on the board serial + number (MTD support is required for this). Otherwise you will + need to set a suitable hw address using ifconfig. + Generic TMS380 ISA support CONFIG_TMSISA This tms380 module supports generic TMS380-based ISA cards. @@ -15394,6 +15412,16 @@ support" be compiled as a module for this driver to be used properly. +Altera's uart00 serial driver +CONFIG_SERIAL_UART00 + Say Y here if you want to use the hard logic uart on Excalibur. This + driver also supports soft logic implentations of this uart core. + +Serial console on uart00 +CONFIG_SERIAL_UART00_CONSOLE + Say Y here if you want to support a serial console on an Excalibur + hard logic uart or uart00 IP core. + USB ConnectTech WhiteHEAT Serial Driver CONFIG_USB_SERIAL_WHITEHEAT Say Y here if you want to use a ConnectTech WhiteHEAT 4 port @@ -19429,6 +19457,20 @@ . The module will be called i2c-velleman.o. +Guide GPIO adapter +CONFIG_I2C_GUIDE + This supports the Iders GUIDE I2C bit-bashing adapter. If you have + selected the GUIDE A07 as your ARM system type, you cannot deselect + this option, as it is required for proper operation of the GUIDE. + + This interface uses /dev/i2c-0 (major 89, minor 0). + + Say Y if you own such an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-guide.o. + I2C PCF 8584 interfaces CONFIG_I2C_ALGOPCF This allows you to use a range of I2C adapters called PCF adapters. @@ -20589,6 +20631,17 @@ . The module will be called softdog.o. +SA1100 Internal Watchdog +CONFIG_SA1100_WATCHDOG + Watchdog timer embedded into SA11x0 chips. This will reboot your + system when timeout is reached. + NOTE, that once enabled, this timer cannot be disabled. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + If you want to compile it as a module, say M here and read + Documentation/modules.txt. The module will be called sa1100_wdt.o. + Berkshire Products PC Watchdog CONFIG_PCWATCHDOG This is the driver for the Berkshire Products PC Watchdog card. @@ -22266,6 +22319,30 @@ from RME. If you want to acess advanced features of the card, read Documentation/sound/rme96xx. +Assabet audio (UDA1341) support +CONFIG_SOUND_ASSABET_UDA1341 + Say Y or M if you have an Intel Assabet evaluation board and want to + use the Philips UDA 1341 audio chip (the one that drives the stereo + audio output) on the SA1100 SSP port. + +Compaq iPAQ audio support +CONFIG_SOUND_H3600_UDA1341 + Say Y or M if you have a Compaq iPaq handheld computer and want to + use its Philips UDA 1341 audio chip. + +Audio support for SA1111/UDA1341 +CONFIG_SOUND_SA1111_UDA1341 + Say Y or M if you have an SA11x0 system with a Philips UDA 1341 + connected to the SA11x1. An example of such a system is the Intel + Assabet evaluation board connected to a Neponset expansion board. + +Generic DAC on the SA11x0 SSP port +CONFIG_SOUND_SA1100SSP + Say Y or M if you have an SA-11x0 system with a DAC on the SSP port. + The LART has an Burr-Brown PCM 1710 digital to analog convertor on + the SSP port, so you want to say Y or M for the LART. It might work + on other SA-1100 platforms, too, but this is not tested. + Are you using a crosscompiler CONFIG_CROSSCOMPILE Say Y here if you are compiling the kernel on a different @@ -25960,6 +26037,20 @@ Say Y if configuring for a Pangolin. Say N otherwise. +Shannon +CONFIG_SA1100_SHANNON + The Shannon (also known as a Tuxscreen, and also as a IS2630) was a + limited edition webphone produced by Philips. The Shannon is a SA1100 + platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots, + and a telco interface. + +Simputer +CONFIG_SA1100_SIMPUTER + Say Y here if you are using an Intel(R) StrongARM(R) SA-1110 + based Simputer. See http://www.simputer.org/ for information + on the Simputer. The Simputer software is actively maintained + by PicoPeta Simputers Pvt. Ltd. (http://www.picopeta.com) + Victor CONFIG_SA1100_VICTOR Say Y here if you are using a Visu Aide Intel(R) StrongARM(R) @@ -25967,6 +26058,14 @@ for information on this system. +Radisys Corp. Tulsa +CONFIG_SA1100_PFS168 + The Radisys Corp. PFS-168 (aka Tulsa) is an Intel® StrongArm® SA-1110 based + computer which includes the SA-1111 Microprocessor Companion Chip and other + custom I/O designed to add connectivity and multimedia features for vending + and business machine applications. Say Y here if you require support for + this target. + # Choice: cerf_ram Cerf on-board RAM size CONFIG_SA1100_CERF_8MB @@ -26034,37 +26133,65 @@ Say Y if you want support for the ARM920T processor. Otherwise, say N. -Support ARM1020 processor -CONFIG_CPU_ARM1020 - The ARM1020 is the cached version of the ARM10 processor, - with an addition of a floating-point unit. +Support ARM922T processor +CONFIG_CPU_ARM922T + The ARM922T is a version of the ARM920T, but with smaller + instruction and data caches. It is used in Altera's + Excalibur XA device family. - Say Y if you want support for the ARM1020 processor. + Say Y if you want support for the ARM922T processor. Otherwise, say N. -Disable I-Cache +Disable instruction cache CONFIG_CPU_ICACHE_DISABLE - Say Y here to disable the processor instruction cache. Unless - you have a reason not to or are unsure, say N. + Say Y here to disable the processor instruction cache. Unless + you have a reason to do this, say N. -Disable D-Cache +Disable data cache CONFIG_CPU_DCACHE_DISABLE - Say Y here to disable the processor data cache. Unless - you have a reason not to or are unsure, say N. + Say Y here to disable the processor data cache. Unless + you have a reason to do this, say N. -Force write through D-cache +Use data cache in writethrough mode CONFIG_CPU_DCACHE_WRITETHROUGH - Say Y here to use the data cache in write-through mode. Unless you - specifically require this or are unsure, say N. + Say Y here to use the data cache in writethough mode. Unless you + specifically require this, say N. -Round robin I and D cache replacement algorithm +Support ARM1020 processor +CONFIG_CPU_ARM1020 + The ARM1020 is the 32K cached version of the ARM10 processor, + with an addition of a floating-point unit. + + Say Y if you want support for the ARM1020 processor. + Otherwise, say N. + +Support ARM1022 processor +CONFIG_CPU_ARM1022 + The ARM1022E is the 16K cached version of the ARM10 processor, + with an addition of a floating-point unit. + + Say Y if you want support for the ARM1022 processor. + Otherwise, say N. + +Force round-robin cache line replacement CONFIG_CPU_CACHE_ROUND_ROBIN - Say Y here to use the predictable round-robin cache replacement - policy. Unless you specifically require this or are unsure, say N. + Say Y here to force the caches to use a round-robin + algorithm when picking a cache line to evict. Unless you + specifically require this, say N. + +Disable the write buffer +CONFIG_CPU_WB_DISABLE + Say Y here to turn off the write buffer (if possible) + Unless you specifically require this, say N. Note that + not all ARM processors allow the write buffer to be + disabled. Disable branch prediction CONFIG_CPU_BPREDICT_DISABLE - Say Y here to disable branch prediction. If unsure, say N. + The ARM10 family of processors support branch prediction, + which can significantly speed up execution of loops. + Say Y here to disable branch prediction. Unless you + specifically require this, say N. Compressed boot loader in ROM/flash CONFIG_ZBOOT_ROM @@ -26111,6 +26238,11 @@ Say Y here if you are using the inhand electronics OmniMeter. See for details. +HP Laboratories BadgePAD 4 +CONFIG_SA1100_BADGE4 + Say Y here if you want to build a kernel for the HP Laboratories + BadgePAD 4. + Load kernel using Angel Debug Monitor CONFIG_ANGELBOOT Say Y if you plan to load the kernel using Angel, ARM Ltd's target @@ -26123,6 +26255,15 @@ board includes 2 serial ports, Ethernet, IRDA, and expansion headers. It comes with 16 MB SDRAM and 8 MB flash ROM. +GUIDEA07 +CONFIG_ARCH_GUIDEA07 + Say Y if you are using a GUIDE (A07) board. + + This board is based on the cs89712 processor and shares much common + hardware with the CDB89712 configuration. When you select this + option and the CDB89712 becomes enabled also, don't worry. It's + supposed to be that way. + CLPS-711X internal ROM bootstrap CONFIG_EP72XX_ROM_BOOT If you say Y here, your CLPS711x-based kernel will use the bootstrap @@ -26151,24 +26292,44 @@ You may say N here if you are going to load the Acorn FPEmulator early in the bootup. +Math emulation 80-bit support +CONFIG_FPE_NWFPE_XP + Say Y to include 80-bit support in the kernel floating-point + emulator. Otherwise, only 32 and 64-bit support is compiled in. + Note that gcc does not generate 80-bit operations by default, + so in most cases this option only enlarges the size of the + floating point emulator without any good reason. + + You almost surely want to say N here. + FastFPE math emulation CONFIG_FPE_FASTFPE Say Y here to include the FAST floating point emulator in the kernel. - This is an experimental much faster emulator which has only 32 bit - precision for the mantissa. It does not support any exceptions. - This makes it very simple, it is approximately 4-8 times faster than - NWFPE. - - It should be sufficient for most programs. It is definitely not - suitable if you do scientific calculations that need double - precision for iteration formulas that sum up lots of very small - numbers. If you do not feel you need a faster FP emulation you - should better choose NWFPE. + This is an experimental much faster emulator which is written + completely in ARM assembly. All instructions that are not marked as + deprecated in the ARM7500FE data sheet are implemented. It supports + single, double and double extended precision. It does support + exception flags, but not raising exceptions. It gives an average + 5 times speed increase over NWFPE for FP only code. + + FastFPE does not require long multiply instruction anymore and is + now suitable for all ARM cpus. The presence of the long multiply + instruction is detected during initialisation and used to speedup + multiply and divide. + + Compliance to IEEE Std 754-1985 was verified using the testfloat + program of the SoftFloat package version 2a by John Hauser. All + operations except square root were reported to be compliant. However, + this is not a proof, and especially does not verify the instruction + parser. + + You can compile both emulators into the kernel and choose one + of them at boot time by passing "fpe=fastfpe" or "fpe=nwfpe" as + kernel parameter. It is also possible to say M to build the emulator as a module - (fastfpe.o). But keep in mind that you should only load the FP - emulator early in the bootup. You should never change from NWFPE to - FASTFPE or vice versa in an active system! + (fastfpe.o). This was never tested. Only do it if you know what + you are doing! DS1620 thermometer support CONFIG_DS1620 diff -uNr linux-2.4.37.9/Documentation/arm/Porting linux-2.4.37.9-vrs1-5mx2/Documentation/arm/Porting --- linux-2.4.37.9/Documentation/arm/Porting Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/arm/Porting Wed May 26 15:43:45 2010 @@ -0,0 +1,135 @@ +Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html + +Initial definitions +------------------- + +The following symbol definitions rely on you knowing the translation that +__virt_to_phys() does for your machine. This macro converts the passed +virtual address to a physical address. Normally, it is simply: + + phys = virt - PAGE_OFFSET + PHYS_OFFSET + + +Decompressor Symbols +-------------------- + +ZTEXTADDR + Start address of decompressor. There's no point in talking about + virtual or physical addresses here, since the MMU will be off at + the time when you call the decompressor code. You normally call + the kernel at this address to start it booting. This doesn't have + to be located in RAM, it can be in flash or other read-only or + read-write addressable medium. + +ZBSSADDR + Start address of zero-initialised work area for the decompressor. + This must be pointing at RAM. The decompressor will zero initialise + this for you. Again, the MMU will be off. + +ZRELADDR + This is the address where the decompressed kernel will be written, + and eventually executed. The following constraint must be valid: + + __virt_to_phys(TEXTADDR) == ZRELADDR + + The initial part of the kernel is carefully coded to be position + independent. + +INITRD_PHYS + Physical address to place the initial RAM disk. Only relevant if + you are using the bootpImage stuff (which only works on the old + struct param_struct). + +INITRD_VIRT + Virtual address of the initial RAM disk. The following constraint + must be valid: + + __virt_to_phys(INITRD_VIRT) == INITRD_PHYS + +PARAMS_PHYS + Physical address of the struct param_struct or tag list, giving the + kernel various parameters about its execution environment. + + +Kernel Symbols +-------------- + +PHYS_OFFSET + Physical start address of the first bank of RAM. + +PAGE_OFFSET + Virtual start address of the first bank of RAM. During the kernel + boot phase, virtual address PAGE_OFFSET will be mapped to physical + address PHYS_OFFSET, along with any other mappings you supply. + This should be the same value as TASK_SIZE. + +TASK_SIZE + The maximum size of a user process in bytes. Since user space + always starts at zero, this is the maximum address that a user + process can access+1. The user space stack grows down from this + address. + + Any virtual address below TASK_SIZE is deemed to be user process + area, and therefore managed dynamically on a process by process + basis by the kernel. I'll call this the user segment. + + Anything above TASK_SIZE is common to all processes. I'll call + this the kernel segment. + + (In other words, you can't put IO mappings below TASK_SIZE, and + hence PAGE_OFFSET). + +TEXTADDR + Virtual start address of kernel, normally PAGE_OFFSET + 0x8000. + This is where the kernel image ends up. With the latest kernels, + it must be located at 32768 bytes into a 128MB region. Previous + kernels placed a restriction of 256MB here. + +DATAADDR + Virtual address for the kernel data segment. Must not be defined + when using the decompressor. + +VMALLOC_START +VMALLOC_END + Virtual addresses bounding the vmalloc() area. There must not be + any static mappings in this area; vmalloc will overwrite them. + The addresses must also be in the kernel segment (see above). + Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the + last virtual RAM address (found using variable high_memory). + +VMALLOC_OFFSET + Offset normally incorporated into VMALLOC_START to provide a hole + between virtual RAM and the vmalloc area. We do this to allow + out of bounds memory accesses (eg, something writing off the end + of the mapped memory map) to be caught. Normally set to 8MB. + +Architecture Specific Macros +---------------------------- + +BOOT_MEM(pram,pio,vio) + `pram' specifies the physical start address of RAM. Must always + be present, and should be the same as PHYS_OFFSET. + + `pio' is the physical address of an 8MB region containing IO for + use with the debugging macros in arch/arm/kernel/debug-armv.S. + + `vio' is the virtual address of the 8MB debugging region. + + It is expected that the debugging region will be re-initialised + by the architecture specific code later in the code (via the + MAPIO function). + +BOOT_PARAMS + Same as, and see PARAMS_PHYS. + +FIXUP(func) + Machine specific fixups, run before memory subsystems have been + initialised. + +MAPIO(func) + Machine specific function to map IO areas (including the debug + region above). + +INITIRQ(func) + Machine specific function to initialise interrupts. + diff -uNr linux-2.4.37.9/Documentation/arm/mem_alignment linux-2.4.37.9-vrs1-5mx2/Documentation/arm/mem_alignment --- linux-2.4.37.9/Documentation/arm/mem_alignment Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/arm/mem_alignment Wed May 26 15:43:45 2010 @@ -0,0 +1,58 @@ +Too many problems poped up because of unnoticed misaligned memory access in +kernel code lately. Therefore the alignment fixup is now unconditionally +configured in for SA11x0 based targets. According to Alan Cox, this is a +bad idea to configure it out, but Russell King has some good reasons for +doing so on some f***ed up ARM architectures like the EBSA110. However +this is not the case on many design I'm aware of, like all SA11x0 based +ones. + +Of course this is a bad idea to rely on the alignment trap to perform +unaligned memory access in general. If those access are predictable, you +are better to use the macros provided by include/asm/unaligned.h. The +alignment trap can fixup misaligned access for the exception cases, but at +a high performance cost. It better be rare. + +Now for user space applications, it is possible to configure the alignment +trap to SIGBUS any code performing unaligned access (good for debugging bad +code), or even fixup the access by software like for kernel code. The later +mode isn't recommended for performance reasons (just think about the +floating point emulation that works about the same way). Fix your code +instead! + +Please note that randomly changing the behaviour without good thought is +real bad - it changes the behaviour of all unaligned instructions in user +space, and might cause programs to fail unexpectedly. + +To change the alignment trap behavior, simply echo a number into +/proc/cpu/alignment. The number is made up from various bits: + +bit behavior when set +--- ----------------- + +0 A user process performing an unaligned memory access + will cause the kernel to print a message indicating + process name, pid, pc, instruction, address, and the + fault code. + +1 The kernel will attempt to fix up the user process + performing the unaligned access. This is of course + slow (think about the floating point emulator) and + not recommended for production use. + +2 The kernel will send a SIGBUS signal to the user process + performing the unaligned access. + +Note that not all combinations are supported - only values 0 through 5. +(6 and 7 don't make sense). + +For example, the following will turn on the warnings, but without +fixing up or sending SIGBUS signals: + + echo 1 > /proc/cpu/alignment + +You can also read the content of the same file to get statistical +information on unaligned access occurrences plus the current mode of +operation for user space code. + + +Nicolas Pitre, Mar 13, 2001. Modified Russell King, Nov 30, 2001. diff -uNr linux-2.4.37.9/Documentation/arm/memory.txt linux-2.4.37.9-vrs1-5mx2/Documentation/arm/memory.txt --- linux-2.4.37.9/Documentation/arm/memory.txt Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/arm/memory.txt Wed May 26 15:43:45 2010 @@ -0,0 +1,74 @@ + Kernel Memory Layout on ARM Linux + + Russell King + April 27, 2003 (2.5.68) + +This document describes the virtual memory layout which the Linux +kernel uses for ARM processors. It indicates which regions are +free for platforms to use, and which are used by generic code. + +The ARM CPU is capable of addressing a maximum of 4GB virtual memory +space, and this must be shared between user space processes, the +kernel, and hardware devices. + +As the ARM architecture matures, it becomes necessary to reserve +certain regions of VM space for use for new facilities; therefore +this document may reserve more VM space over time. + +Start End Use +-------------------------------------------------------------------------- +ffff8000 ffffffff copy_user_page / clear_user_page use. + For SA11xx and Xscale, this is used to + setup a minicache mapping. + +ffff1000 ffff7fff Reserved. + Platforms must not use this address range. + +ffff0000 ffff0fff CPU vector page. + The CPU vectors are mapped here if the + CPU supports vector relocation (control + register V bit.) + +ffe00000 fffeffff Free for platform use, not recommended. + +ffc00000 ffdfffff 2MB consistent memory mapping. + Memory returned by the consistent_alloc + low level function will be dynamically + mapped here. + +ff000000 ffbfffff Free for platform use, not recommended. + +VMALLOC_END ff000000 Free for platform use, recommended. + +VMALLOC_START VMALLOC_END vmalloc() / ioremap() space. + Memory returned by vmalloc/ioremap will + be dynamically placed in this region. + VMALLOC_START may be based upon the value + of the high_memory variable. + +PAGE_OFFSET high_memory Kernel direct-mapped RAM region. + This maps the platforms RAM, and typically + maps all platform RAM in a 1:1 relationship. + +TASK_SIZE PAGE_OFFSET Kernel module space + Kernel modules inserted via insmod are + placed here using dynamic mappings. + +00001000 TASK_SIZE User space mappings + Per-thread mappings are placed here via + the mmap() system call. + +00000000 00000fff CPU vector page / null pointer trap + CPUs which do not support vector remapping + place their vector page here. NULL pointer + dereferences by both the kernel and user + space are also caught via this mapping. + +Please note that mappings which collide with the above areas may result +in a non-bootable kernel, or may cause the kernel to (eventually) panic +at run time. + +Since future CPUs may impact the kernel mapping layout, user programs +must not access any memory which is not mapped inside their 0x0001000 +to TASK_SIZE address range. If they wish to access these areas, they +must set up their own mappings using open() and mmap(). diff -uNr linux-2.4.37.9/Documentation/cpufreq/core.txt linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/core.txt --- linux-2.4.37.9/Documentation/cpufreq/core.txt Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/core.txt Wed May 26 15:43:20 2010 @@ -0,0 +1,94 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + C P U F r e q C o r e + + + Dominik Brodowski + David Kimdon + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. CPUFreq core and interfaces +2. CPUFreq notifiers + +1. General Information +======================= + +The CPUFreq core code is located in linux/kernel/cpufreq.c. This +cpufreq code offers a standardized interface for the CPUFreq +architecture drivers (those pieces of code that do actual +frequency transitions), as well as to "notifiers". These are device +drivers or other part of the kernel that need to be informed of +policy changes (ex. thermal modules like ACPI) or of all +frequency changes (ex. timing code) or even need to force certain +speed limits (like LCD drivers on ARM architecture). Additionally, the +kernel "constant" loops_per_jiffy is updated on frequency changes +here. + +Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu, +which make sure that the cpufreq processor driver is correctly +registered with the core, and will not be unloaded until +cpufreq_put_cpu is called. + +2. CPUFreq notifiers +==================== + +CPUFreq notifiers conform to the standard kernel notifier interface. +See linux/include/linux/notifier.h for details on notifiers. + +There are two different CPUFreq notifiers - policy notifiers and +transition notifiers. + + +2.1 CPUFreq policy notifiers +---------------------------- + +These are notified when a new policy is intended to be set. Each +CPUFreq policy notifier is called three times for a policy transition: + +1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if + they see a need for this - may it be thermal considerations or + hardware limitations. + +2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid + hardware failure. + +3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy + - if two hardware drivers failed to agree on a new policy before this + stage, the incompatible hardware shall be shut down, and the user + informed of this. + +The phase is specified in the second argument to the notifier. + +The third argument, a void *pointer, points to a struct cpufreq_policy +consisting of five values: cpu, min, max, policy and max_cpu_freq. min +and max are the lower and upper frequencies (in kHz) of the new +policy, policy the new policy, cpu the number of the affected CPU or +CPUFREQ_ALL_CPUS for all CPUs; and max_cpu_freq the maximum supported +CPU frequency. This value is given for informational purposes only. + + +2.2 CPUFreq transition notifiers +-------------------------------- + +These are notified twice when the CPUfreq driver switches the CPU core +frequency and this change has any external implications. + +The second argument specifies the phase - CPUFREQ_PRECHANGE or +CPUFREQ_POSTCHANGE. + +The third argument is a struct cpufreq_freqs with the following +values: +cpu - number of the affected CPU or CPUFREQ_ALL_CPUS +old - old frequency +new - new frequency diff -uNr linux-2.4.37.9/Documentation/cpufreq/cpu-drivers.txt linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/cpu-drivers.txt --- linux-2.4.37.9/Documentation/cpufreq/cpu-drivers.txt Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/cpu-drivers.txt Wed May 26 15:43:20 2010 @@ -0,0 +1,210 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + C P U D r i v e r s + + - information for developers - + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. What To Do? +1.1 Initialization +1.2 Per-CPU Initialization +1.3 verify +1.4 target or setpolicy? +1.5 target +1.6 setpolicy +2. Frequency Table Helpers + + + +1. What To Do? +============== + +So, you just got a brand-new CPU / chipset with datasheets and want to +add cpufreq support for this CPU / chipset? Great. Here are some hints +on what is neccessary: + + +1.1 Initialization +------------------ + +First of all, in an __initcall level 7 or later (preferrably +module_init() so that your driver is modularized) function check +whether this kernel runs on the right CPU and the right chipset. If +so, register a struct cpufreq_driver with the CPUfreq core using +cpufreq_register_driver() + +What shall this struct cpufreq_driver contain? + +cpufreq_driver.name - The name of this driver. + +cpufreq_driver.init - A pointer to the per-CPU initialization + function. + +cpufreq_driver.verify - A pointer to a "verfication" funciton. + +cpufreq_driver.setpolicy _or_ +cpufreq_driver.target - See below on the differences. + +And optionally + +cpufreq_driver.exit - A pointer to a per-CPU cleanup function. + +cpufreq_driver.attr - A pointer to a NULL-terminated list of + "struct freq_attr" which allow to + export values to sysfs. + + +1.2 Per-CPU Initialization +-------------------------- + +Whenever a new CPU is registered with the device model, or after the +cpufreq driver registers itself, the per-CPU initialization fucntion +cpufreq_driver.init is called. It takes a struct cpufreq_policy +*policy as argument. What to do now? + +If necessary, activate the CPUfreq support on your CPU (unlock that +register etc.). + +Then, the driver must fill in the following values: + +policy->cpuinfo.min_freq _and_ +policy->cpuinfo.max_freq - the minimum and maximum frequency + (in kHz) which is supported by + this CPU +policy->cpuinfo.transition_latency the time it takes on this CPU to + switch between two frequencies (if + appropriate, else specify + CPUFREQ_ETERNAL) + +policy->cur The current operating frequency of + this CPU (if appropriate) +policy->min, +policy->max, +policy->policy and, if neccessary, +policy->governor must contain the "default policy" for + this CPU. A few moments later, + cpufreq_driver.verify and either + cpufreq_driver.setpolicy or + cpufreq_driver.target is called with + these values. + +For setting some of these values, the frequency table helpers might be +helpful. See the section 2 for more information on them. + + +1.3 verify +------------ + +When the user decides a new policy (consisting of +"policy,governor,min,max") shall be set, this policy must be validated +so that incompatible values can be corrected. For verifying these +values, a frequency table helper and/or the +cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned +int min_freq, unsigned int max_freq) function might be helpful. See +section 2 for details on frequency table helpers. + +You need to make sure that at least one valid frequency (or operating +range) is within policy->min and policy->max. If necessary, increase +policy->max fist, and only if this is no solution, decreas policy->min. + + +1.4 target or setpolicy? +---------------------------- + +Most cpufreq drivers or even most cpu frequency scaling algorithms +only allow the CPU to be set to one frequency. For these, you use the +->target call. + +Some cpufreq-capable processors switch the frequency between certain +limits on their own. These shall use the ->setpolicy call + + +1.4. target +------------- + +The target call has three arguments: struct cpufreq_policy *policy, +unsigned int target_frequency, unsigned int relation. + +The CPUfreq driver must set the new frequency when called here. The +actual frequency must be determined using the following rules: + +- keep close to "target_freq" +- policy->min <= new_freq <= policy->max (THIS MUST BE VALID!!!) +- if relation==CPUFREQ_REL_L, try to select a new_freq higher than or equal + target_freq. ("L for lowest, but no lower than") +- if relation==CPUFREQ_REL_H, try to select a new_freq lower than or equal + target_freq. ("H for highest, but no higher than") + +Here again the frequency table helper might assist you - see section 3 +for details. + + +1.5 setpolicy +--------------- + +The setpolicy call only takes a struct cpufreq_policy *policy as +argument. You need to set the lower limit of the in-processor or +in-chipset dynamic frequency switching to policy->min, the upper limit +to policy->max, and -if supported- select a performance-oriented +setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a +powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check +the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c + + + +2. Frequency Table Helpers +========================== + +As most cpufreq processors only allow for being set to a few specific +frequencies, a "frequency table" with some functions might assist in +some work of the processor driver. Such a "frequency table" consists +of an array of struct cpufreq_freq_table entries, with any value in +"index" you want to use, and the corresponding frequency in +"frequency". At the end of the table, you need to add a +cpufreq_freq_table entry with frequency set to CPUFREQ_TABLE_END. And +if you want to skip one entry in the table, set the frequency to +CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending +order. + +By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table); +the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and +policy->min and policy->max are set to the same values. This is +helpful for the per-CPU initialization stage. + +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table); +assures that at least one valid frequency is within policy->min and +policy->max, and all other criteria are met. This is helpful for the +->verify call. + +int cpufreq_frequency_table_target(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table, + unsigned int target_freq, + unsigned int relation, + unsigned int *index); + +is the corresponding frequency table helper for the ->target +stage. Just pass the values to this function, and the unsigned int +index returns the number of the frequency table entry which contains +the frequency the CPU shall be set to. PLEASE NOTE: This is not the +"index" which is in this cpufreq_table_entry.index, but instead +cpufreq_table[index]. So, the new frequency is +cpufreq_table[index].frequency, and the value you stored into the +frequency table "index" field is +cpufreq_table[index].index. + diff -uNr linux-2.4.37.9/Documentation/cpufreq/governors.txt linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/governors.txt --- linux-2.4.37.9/Documentation/cpufreq/governors.txt Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/governors.txt Wed May 26 15:43:20 2010 @@ -0,0 +1,155 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + C P U F r e q G o v e r n o r s + + - information for users and developers - + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. What is a CPUFreq Governor? + +2. Governors In the Linux Kernel +2.1 Performance +2.2 Powersave +2.3 Userspace + +3. The Governor Interface in the CPUfreq Core + + + +1. What Is A CPUFreq Governor? +============================== + +Most cpufreq drivers (in fact, all except one, longrun) or even most +cpu frequency scaling algorithms only offer the CPU to be set to one +frequency. In order to offer dynamic frequency scaling, the cpufreq +core must be able to tell these drivers of a "target frequency". So +these specific drivers will be transformed to offer a "->target" +call instead of the existing "->setpolicy" call. For "longrun", all +stays the same, though. + +How to decide what frequency within the CPUfreq policy should be used? +That's done using "cpufreq governors". Two are already in this patch +-- they're the already existing "powersave" and "performance" which +set the frequency statically to the lowest or highest frequency, +respectively. At least two more such governors will be ready for +addition in the near future, but likely many more as there are various +different theories and models about dynamic frequency scaling +around. Using such a generic interface as cpufreq offers to scaling +governors, these can be tested extensively, and the best one can be +selected for each specific use. + +Basically, it's the following flow graph: + +CPU can be set to switch independetly | CPU can only be set + within specific "limits" | to specific frequencies + + "CPUfreq policy" + consists of frequency limits (policy->{min,max}) + and CPUfreq governor to be used + / \ + / \ + / the cpufreq governor decides + / (dynamically or statically) + / what target_freq to set within + / the limits of policy->{min,max} + / \ + / \ + Using the ->setpolicy call, Using the ->target call, + the limits and the the frequency closest + "policy" is set. to target_freq is set. + It is assured that it + is within policy->{min,max} + + +2. Governors In the Linux Kernel +================================ + +2.1 Performance +--------------- + +The CPUfreq governor "performance" sets the CPU statically to the +highest frequency within the borders of scaling_min_freq and +scaling_max_freq. + + +2.1 Powersave +------------- + +The CPUfreq governor "powersave" sets the CPU statically to the +lowest frequency within the borders of scaling_min_freq and +scaling_max_freq. + + +2.2 Userspace +------------- + +The CPUfreq governor "userspace" allows the user, or any userspace +program running with UID "root", to set the CPU to a specifc frequency +by making a sysfs file "scaling_setspeed" available in the CPU-device +directory. + + + +3. The Governor Interface in the CPUfreq Core +============================================= + +A new governor must register itself with the CPUfreq core using +"cpufreq_register_governor". The struct cpufreq_governor, which has to +be passed to that function, must contain the following values: + +governor->name - A unique name for this governor +governor->governor - The governor callback function +governor->owner - .THIS_MODULE for the governor module (if + appropriate) + +The governor->governor callback is called with the current (or to-be-set) +cpufreq_policy struct for that CPU, and an unsigned int event. The +following events are currently defined: + +CPUFREQ_GOV_START: This governor shall start its duty for the CPU + policy->cpu +CPUFREQ_GOV_STOP: This governor shall end its duty for the CPU + policy->cpu +CPUFREQ_GOV_LIMITS: The limits for CPU policy->cpu have changed to + policy->min and policy->max. + +If you need other "events" externally of your driver, _only_ use the +cpufreq_governor_l(unsigned int cpu, unsigned int event) call to the +CPUfreq core to ensure proper locking. + + +The CPUfreq governor may call the CPU processor driver using one of +these two functions: + +inline int cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); + +inline int cpufreq_driver_target_l(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); + +target_freq must be within policy->min and policy->max, of course. +What's the difference between these two functions? When your governor +still is in a direct code path of a call to governor->governor, the +cpufreq_driver_sem lock is still held in the cpufreq core, and there's +no need to lock it again (in fact, this would cause a deadlock). So +use cpufreq_driver_target only in these cases. In all other cases (for +example, when there's a "daemonized" function that wakes up every +second), use cpufreq_driver_target_l to lock the cpufreq_driver_sem +before the command is passed to the cpufreq processor driver. + diff -uNr linux-2.4.37.9/Documentation/cpufreq/index.txt linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/index.txt --- linux-2.4.37.9/Documentation/cpufreq/index.txt Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/index.txt Wed May 26 15:43:20 2010 @@ -0,0 +1,56 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + + +Documents in this directory: +---------------------------- +core.txt - General description of the CPUFreq core and + of CPUFreq notifiers + +cpu-drivers.txt - How to implement a new cpufreq processor driver + +governors.txt - What are cpufreq governors and how to + implement them? + +index.txt - File index, Mailing list and Links (this document) + +user-guide.txt - User Guide to CPUFreq + + +Mailing List +------------ +There is a CPU frequency changing CVS commit and general list where +you can report bugs, problems or submit patches. To post a message, +send an email to cpufreq@www.linux.org.uk, to subscribe go to +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the +mailing list are available to subscribers at +http://www.linux.org.uk/mailman/private/cpufreq/. + + +Links +----- +the FTP archives: +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/ + +how to access the CVS repository: +* http://cvs.arm.linux.org.uk/ + +the CPUFreq Mailing list: +* http://www.linux.org.uk/mailman/listinfo/cpufreq + +Clock and voltage scaling for the SA-1100: +* http://www.lart.tudelft.nl/projects/scaling diff -uNr linux-2.4.37.9/Documentation/cpufreq/user-guide.txt linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/user-guide.txt --- linux-2.4.37.9/Documentation/cpufreq/user-guide.txt Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq/user-guide.txt Wed May 26 15:43:20 2010 @@ -0,0 +1,166 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + U S E R G U I D E + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + +Contents: +--------- +1. Supported Architectures and Processors +1.1 ARM +1.2 x86 +1.3 sparc64 + +2. "Policy" / "Governor"? +2.1 Policy +2.2 Governor + +3. How to change the CPU cpufreq policy and/or speed +3.1 Preferred interface: sysfs +3.2 Deprecated interfaces + + + +1. Supported Architectures and Processors +========================================= + +1.1 ARM +------- + +The following ARM processors are supported by cpufreq: + +ARM Integrator +ARM-SA1100 +ARM-SA1110 + + +1.2 x86 +------- + +The following processors for the x86 architecture are supported by cpufreq: + +AMD Elan - SC400, SC410 +AMD mobile K6-2+ +AMD mobile K6-3+ +Cyrix Media GXm +Intel mobile PIII [*] and Intel mobile PIII-M on certain chipsets +Intel Pentium 4, Intel Xeon +National Semiconductors Geode GX +Transmeta Crusoe +varios processors on some ACPI 2.0-compatible systems [**] + +[*] only certain Intel mobile PIII processors are supported. If you +know that you own a speedstep-capable processor, pass the option +"speedstep_coppermine=1" to the module speedstep.o + +[**] Only if "ACPI Processor Performance States" are available +to the ACPI<->BIOS interface. + + +1.3 sparc64 +----------- + +The following processors for the sparc64 architecture are supported by +cpufreq: + +UltraSPARC-III + + + +2. "Policy" / "Governor" ? +========================== + +Some CPU frequency scaling-capable processor switch between varios +frequencies and operating voltages "on the fly" without any kernel or +user involvement. This guarantuees very fast switching to a frequency +which is high enough to serve the user's needs, but low enough to save +power. + + +2.1 Policy +---------- + +On these systems, all you can do is select the lower and upper +frequency limit as well as whether you want more aggressive +power-saving or more instantly avaialble processing power. + + +2.2 Governor +------------ + +On all other cpufreq implementations, these boundaries still need to +be set. Then, a "governor" must be selected. Such a "governor" decides +what speed the processor shall run within the boundaries. One such +"governor" is the "userspace" governor. This one allows the user - or +a yet-to-implement userspace program - to decide what specific speed +the processor shall run at. + + +3. How to change the CPU cpufreq policy and/or speed +==================================================== + +3.1 Preferred Interface: sysfs +------------------------------ + +The preferred interface is located in the sysfs filesystem. If you +mounted it at /sys, the cpufreq interface is located in a subdirectory +"cpufreq" within the cpu-device directory +(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU). + +cpuinfo_min_freq : this file shows the minimum operating + frequency the processor can run at(in kHz) +cpuinfo_max_freq : this file shows the maximum operating + frequency the processor can run at(in kHz) +scaling_driver : this file shows what cpufreq driver is + used to set the frequency on this CPU + +scaling_available_governors : this file shows the CPUfreq governors + available in this kernel. You can see the + currently activated governor in + +scaling_governor, and by "echoing" the name of another + governor you can change it. Please note + that some governors won't load - they only + work on some specific architectures or + processors. +scaling_min_freq and +scaling_max_freq show the current "policy limits" (in + kHz). By echoing new values into these + files, you can change these limits. + + +If you have selected the "userspace" governor which allows you to +set the CPU operating frequency to a specific value, you can read out +the current frequency in + +scaling_setspeed. By "echoing" a new frequency into this + you can change the speed of the CPU, + but only within the limits of + scaling_min_freq and scaling_max_freq. + + +3.2 Deprecated Interfaces +------------------------- + +Depending on your kernel configuration, you might find the following +cpufreq-related files: +/proc/cpufreq +/proc/sys/cpu/*/speed +/proc/sys/cpu/*/speed-min +/proc/sys/cpu/*/speed-max + +These are files for deprecated interfaces to cpufreq, which offer far +less functionality. Because of this, these interfaces aren't described +here. + diff -uNr linux-2.4.37.9/Documentation/cpufreq-old linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq-old --- linux-2.4.37.9/Documentation/cpufreq-old Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/cpufreq-old Wed May 26 15:43:51 2010 @@ -0,0 +1,332 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + + + + Dominik Brodowski + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + + +Contents: +--------- +1. Supported architectures +2. User interface +2.1 Sample script for command line interface +3. CPUFreq core and interfaces +3.1 General information +3.2 CPUFreq notifiers +3.3 CPUFreq architecture drivers +4. Mailing list and Links + + + +1. Supported architectures +========================== + +Some architectures detect the lowest and highest possible speed +settings, while others rely on user information on this. For the +latter, a boot parameter is required, for the former, you can specify +one to set the limits between speed settings may occur. +The boot parameter has the following syntax: + + cpufreq=minspeed-maxspeed + +with both minspeed and maxspeed being given in kHz. To set the lower +limit to 59 MHz and the upper limit to 221 MHz, specify: + + cpufreq=59000-221000 + +Check the "Speed Limits Detection" information below on whether +the driver detects the lowest and highest allowed speed setting +automatically. + + +ARM Integrator: + SA 1100, SA1110 +-------------------------------- + Speed Limits Detection: On Integrators, the minimum speed is set + and the maximum speed has to be specified using the boot + parameter. On SA11x0s, the frequencies are fixed (59 - 287 MHz) + + +AMD Elan: + SC400, SC410 +-------------------------------- + Speed Limits Detection: Not implemented. You need to specify the + minimum and maximum frequency in the boot parameter (see above). + + +VIA Cyrix Longhaul: + VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3, + VIA Cyrix Ezra, VIA Cyrix Ezra-T +-------------------------------- + Speed Limits Detection: working. No need for boot parameters. + NOTE: Support for certain processors is currently disabled, + waiting on updated docs from VIA. + + +Intel SpeedStep: + certain mobile Intel Pentium III (Coppermine), and all mobile + Intel Pentium III-M (Tulatin) and mobile Intel Pentium 4 P4-Ms. +-------------------------------- + Speed Limits Detection: working. No need for boot parameters. + NOTE: + 1.) mobile Intel Pentium III (Coppermine): + The SpeedStep interface may only be used on SpeedStep + capable processors. Unforunately, due to lack of documentation, + such detection is not yet possible on mobile Intel PIII + (Coppermine) processors. In order to activate SpeedStep on such a + processor, you have to remove one line manually in + linux/drivers/arch/i386/speedstep.c + + +P4 CPU Clock Modulation: + Intel Pentium 4 Xeon processors +-------------------------------- + Speed Limits Detection: Not implemented. You need to specify the + minimum and maximum frequency in the boot parameter (see above). + + + +2. User Interface +================= + +CPUFreq uses a "sysctl" interface which is located in + /proc/sys/cpu/0/ on UP (uniprocessor) kernels, or + /proc/sys/cpu/any/ on SMP (symmetric multiprocessoring) kernels. + + +In this directory, you will find three files of importance for +CPUFreq: speed-max, speed-min, and speed: + +speed shows the current CPU frequency in kHz, +speed-min the minimal supported CPU frequency, and +speed-max the maximal supported CPU frequency. + +Please note that you might have to specify these limits as a boot +parameter depending on the architecture (see above). + + +To change the CPU frequency, "echo" the desired CPU frequency (in kHz) +to speed. For example, to set the CPU speed to the lowest/highest +allowed frequency do: + +root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed +root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed + + +2.1 Sample script for command line interface +********************************************** + + +Michael Ossmann has written a small command line +interface for the infinitely lazy. + +#!/bin/bash +# +# /usr/local/bin/freq +# simple command line interface to cpufreq + +[ -n "$1" ] && case "$1" in + "min" ) + # set frequency to minimum + cat /proc/sys/cpu/0/speed-min >/proc/sys/cpu/0/speed + ;; + "max" ) + # set frequency to maximum + cat /proc/sys/cpu/0/speed-max >/proc/sys/cpu/0/speed + ;; + * ) + echo "Usage: $0 [min|max]" + echo " min: set frequency to minimum and display new frequency" + echo " max: set frequency to maximum and display new frequency" + echo " no options: display current frequency" + exit 1 + ;; +esac + +# display current frequency +cat /proc/sys/cpu/0/speed +exit 0 + + + +3. CPUFreq core and interfaces +=============================== + +3.1 General information +************************* + +The CPUFreq core code is located in linux/kernel/cpufreq.c. This +cpufreq code offers a standardized interface for the CPUFreq +architecture drivers (those pieces of code that do the actual +frequency transition), as well as to "notifiers". These are device +drivers or other part of the kernel that need to be informed of +frequency changes (like timing code) or even need to force certain +speed limits (like LCD drivers on ARM architecture). Aditionally, the +kernel "constant" loops_per_jiffy is updated on frequency changes +here. + + +3.2 CPUFreq notifiers +*********************** + +CPUFreq notifiers are kernel code that need to be called to either +a) define certain minimum or maximum speed settings, +b) be informed of frequency changes in advance of the transition, or +c) be informed of frequency changes directly after the transition. + +A standard kernel notifier interface is offered for this. See +linux/include/linux/notifier.h for details on notifiers. + + +Data and value passed to CPUFreq notifiers +------------------------------------------ +The second argument passed to any notifier is an unsigned int stating +the phase of the transition: +CPUFREQ_MINMAX during the process of determing a valid new CPU + frequency, +CPUFREQ_PRECHANGE right before the transition, and +CPUFREQ_POSTCHANGE right after the transition. + +The third argument, a void *pointer, points to a struct +cpufreq_freqs. This consists of four values: min, max, cur and new. + +min and max are the current speed limits. Please note: Never update +these values directly, use cpufreq_updateminmax(struct cpufreq_freqs +*freqs, unsigned int min, unsigned int max) instead. cur is the +current/old speed, and new is the new speed, but might only be valid +on CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE. + +Each notifier gets called all three times on any transition: + +CPUFREQ_MINMAX +Here the notifier is supposed to update the min and max values to the +limits the protected device / kernel code needs. As stated above, +always use cpufreq_updateminmax for this. + +CPUFREQ_PRECHANGE +CPUFREQ_POSTCHANGE +Here the notifier is supposed to update all internal (e.g. device +driver) code which is dependend on the CPU frequency. + + +3.3 CPUFreq architecture drivers +********************************** + +CPUFreq architecture drivers are the pieces of kernel code that +actually perform CPU frequency transitions. These need to be +initialised seperately (seperate initcalls), and may be +modularized. They interact with the CPUFreq core in the following way: + + +cpufreq_register() +------------------ +cpufreq_register registers an arch driver to the CPUFreq core. Please +note that only one arch driver may be registered at any time, -EBUSY +is returned when an arch driver is already registered. The argument to +cpufreq_register, cpufreq_driver_t driver, is described later. + + +cpufreq_unregister() +-------------------- +cpufreq_unregister unregisters an arch driver, e.g. on module +unloading. Please note that there is no check done that this is called +from the driver which actually registered itself to the core, so +please only call this function when you are sure the arch driver got +registered correctly before. + + +struct cpufreq_driver +---------------- +On initialisation, the arch driver is supposed to pass the following +entries in struct cpufreq_driver cpufreq_driver: + +cpufreq_verify_t validate: This is a pointer to a function with the +following definition: + unsigned int validating_function (unsigned int kHz). +It is called right before a transition occurs. The proposed new +speed setting is passed as an argument in kHz; the validating code +should verify this is a valid speed setting which is currently +supported by the CPU. It shall return the closest valid CPU frequency +in kHz. + +cpufreq_setspeed_t setspeed: This is a pointer to a function with the +following definition: + void setspeed_function (unsigned int kHz). +This function shall perform the transition to the new CPU frequency +given as argument in kHz. Note that this argument is exactly the same +as the one returned by cpufreq_verify_t validate. + + +unsigned int freq.cur: The current CPU core frequency. Note that this +is a requirement while the next two entries are optional. + + +unsigned int freq.min (optional): The minimal CPU core frequency this +CPU supports. This value may be limited further by the +cpufreq_verify_t validate function, and so this value should be the +minimal core frequency allowed "theoretically" on this system in this +configuration. + + +unsigned int freq.max (optional): The maximum CPU core frequency this +CPU supports. This value may be limited further by the +cpufreq_verify_t validate function, and so this value should be the +maximum core frequency allowed "theoretically" on this system in this +configuration. + + +Some Requirements to CPUFreq architecture drivers +------------------------------------------------- +* Only call cpufreq_register() when the ability to switch CPU + frequencies is _verified_ or can't be missing +* cpufreq_unregister() may only be called if cpufreq_register() has + been successfully(!) called before +* All CPUs have to be set to the same speed whenever setspeed() is + called +* Be aware that there is currently no error management in the + setspeed() code in the CPUFreq core. So only call yourself a + cpufreq_driver if you are really a working cpufreq_driver! + + + +4. Mailing list and Links +************************** + + +Mailing List +------------ +There is a CPU frequency changing CVS commit and general list where +you can report bugs, problems or submit patches. To post a message, +send an email to cpufreq@www.linux.org.uk, to subscribe go to +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the +mailing list are available to subscribers at +http://www.linux.org.uk/mailman/private/cpufreq/. + + +Links +----- +the FTP archives: +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/ + +how to access the CVS repository: +* http://www.arm.linux.org.uk/cvs/ + +the CPUFreq Mailing list: +* http://www.linux.org.uk/mailman/listinfo/cpufreq + +Clock and voltage scaling for the SA-1100: +* http://www.lart.tudelft.nl/projects/scaling + +CPUFreq project homepage +* http://www.brodo.de/cpufreq/ diff -uNr linux-2.4.37.9/Documentation/l3/structure linux-2.4.37.9-vrs1-5mx2/Documentation/l3/structure --- linux-2.4.37.9/Documentation/l3/structure Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/l3/structure Wed May 26 15:43:20 2010 @@ -0,0 +1,36 @@ +L3 Bus Driver +------------- + +The structure of the driver is as follows: + + +----------+ +----------+ +----------+ + | client 1 | | client 2 | | client 3 | + +-----^----+ +----^-----+ +----^-----+ + | | | + +-----v--------------v---------------v-----+ + | | + +-----^-------+ +-------^-----+ + | | core | | + +-----v----+ | | +----v-----+ + | device | | | | device | + | driver 1 | | | | driver 2 | + +-----^----+ | | +----^-----+ + | | services | | + +-----v-------+ +-------v-----+ + | | + +-----------------^----^-------------------+ + | | + | +-v---------+ + | | algorithm | + | | driver | + | +-v---------+ + | | + +-v----v-+ + | bus | + | driver | + +--------+ + +Clients talk to the core to attach device drivers and bus adapters, and +to instruct device drivers to perform actions. Device drivers then talk +to the core to perform L3 bus transactions via the algorithm driver and +ultimately bus driver. diff -uNr linux-2.4.37.9/Documentation/serial/driver linux-2.4.37.9-vrs1-5mx2/Documentation/serial/driver --- linux-2.4.37.9/Documentation/serial/driver Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/Documentation/serial/driver Wed May 26 15:43:19 2010 @@ -0,0 +1,208 @@ + + Low Level Serial API + -------------------- + + + $Id: driver,v 1.3 2001/11/24 23:24:47 rmk Exp $ + + +This document is meant as a brief overview of some aspects of the new serial +driver. It is not complete, any questions you have should be directed to + + +The reference implementation is contained within serial_amba.c. + + + +Low Level Serial Hardware Driver +-------------------------------- + +The low level serial hardware driver is responsible for supplying port +information (defined by uart_port) and a set of control methods (defined +by uart_ops) to the core serial driver. The low level driver is also +responsible for handling interrupts for the port, and providing any +console support. + + +Console Support +--------------- + +The serial core provides a few helper functions. This includes identifing +the correct port structure (via uart_get_console) and decoding command line +arguments (uart_parse_options). + + +Locking +------- + +Generally, all locking is done by the core driver, except for the interrupt +functions. It is the responsibility of the low level hardware driver to +perform the necessary locking there using info->lock. (since it is running +in an interrupt, you only need to use spin_lock() and spin_unlock() from +the interrupt handler). + + +uart_ops +-------- + +The uart_ops structure is the main interface between serial_core and the +hardware specific driver. It contains all the methods to control the +hardware. + + tx_empty(port) + This function tests whether the transmitter fifo and shifter + for the port described by 'port' is empty. If it is empty, + this function should return TIOCSER_TEMT, otherwise return 0. + If the port does not support this operation, then it should + return TIOCSER_TEMT. + + set_mctrl(port, mctrl) + This function sets the modem control lines for port described + by 'port' to the state described by mctrl. The relevant bits + of mctrl are: + - TIOCM_RTS RTS signal. + - TIOCM_DTR DTR signal. + - TIOCM_OUT1 OUT1 signal. + - TIOCM_OUT2 OUT2 signal. + If the appropriate bit is set, the signal should be driven + active. If the bit is clear, the signal should be driven + inactive. + + get_mctrl(port) + Returns the current state of modem control inputs. The state + of the outputs should not be returned, since the core keeps + track of their state. The state information should include: + - TIOCM_DCD state of DCD signal + - TIOCM_CTS state of CTS signal + - TIOCM_DSR state of DSR signal + - TIOCM_RI state of RI signal + The bit is set if the signal is currently driven active. If + the port does not support CTS, DCD or DSR, the driver should + indicate that the signal is permanently active. If RI is + not available, the signal should not be indicated as active. + + stop_tx(port,from_tty) + Stop transmitting characters. This might be due to the CTS + line becoming inactive or the tty layer indicating we want + to stop transmission. + + start_tx(port,nonempty,from_tty) + start transmitting characters. (incidentally, nonempty will + always be nonzero, and shouldn't be used - it will be dropped). + + stop_rx(port) + Stop receiving characters; the port is in the process of + being closed. + + enable_ms(port) + Enable the modem status interrupts. + + break_ctl(port,ctl) + Control the transmission of a break signal. If ctl is + nonzero, the break signal should be transmitted. The signal + should be terminated when another call is made with a zero + ctl. + + startup(port,info) + Grab any interrupt resources and initialise any low level driver + state. Enable the port for reception. It should not activate + RTS nor DTR; this will be done via a separate call to set_mctrl. + + shutdown(port,info) + Disable the port, disable any break condition that may be in + effect, and free any interrupt resources. It should not disable + RTS nor DTR; this will have already been done via a separate + call to set_mctrl. + + change_speed(port,cflag,iflag,quot) + Change the port parameters, including word length, parity, stop + bits. Update read_status_mask and ignore_status_mask to indicate + the types of events we are interested in receiving. Relevant + cflag bits are: + CSIZE - word size + CSTOPB - 2 stop bits + PARENB - parity enable + PARODD - odd parity (when PARENB is in force) + CREAD - enable reception of characters (if not set, + still receive characters from the port, but + throw them away. + CRTSCTS - if set, enable CTS status change reporting + CLOCAL - if not set, enable modem status change + reporting. + Relevant iflag bits are: + INPCK - enable frame and parity error events to be + passed to the TTY layer. + BRKINT + PARMRK - both of these enable break events to be + passed to the TTY layer. + + IGNPAR - ignore parity and framing errors + IGNBRK - ignore break errors, If IGNPAR is also + set, ignore overrun errors as well. + The interaction of the iflag bits is as follows (parity error + given as an example): + Parity error INPCK IGNPAR + None n/a n/a character received + Yes n/a 0 character discarded + Yes 0 1 character received, marked as + TTY_NORMAL + Yes 1 1 character received, marked as + TTY_PARITY + + pm(port,state,oldstate) + perform any power management related activities on the specified + port. state indicates the new state (defined by ACPI D0-D3), + oldstate indicates the previous state. Essentially, D0 means + fully on, D3 means powered down. + + This function should not be used to grab any resources. + + type(port) + Return a pointer to a string constant describing the specified + port, or return NULL, in which case the string 'unknown' is + substituted. + + release_port(port) + Release any memory and IO region resources currently in use by + the port. + + request_port(port) + Request any memory and IO region resources required by the port. + If any fail, no resources should be registered when this function + returns, and it should return -EBUSY on failure. + + config_port(port,type) + Perform any autoconfiguration steps required for the port. `type` + contains a bit mask of the required configuration. UART_CONFIG_TYPE + indicates that the port requires detection and identification. + port->type should be set to the type found, or PORT_UNKNOWN if + no port was detected. + + UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal, + which should be probed using standard kernel autoprobing techniques. + This is not necessary on platforms where ports have interrupts + internally hard wired (eg, system on a chip implementations). + + verify_port(port,serinfo) + Verify the new serial port information contained within serinfo is + suitable for this port type. + + ioctl(port,cmd,arg) + Perform any port specific IOCTLs. IOCTL commands must be defined + using the standard numbering system found in + + +Other notes +----------- + +It is intended some day to drop the 'unused' entries from uart_port, and +allow low level drivers to register their own individual uart_port's with +the core. This will allow drivers to use uart_port as a pointer to a +structure containing both the uart_port entry with their own extensions, +thus: + + struct my_port { + struct uart_port port; + int my_stuff; + }; + diff -uNr linux-2.4.37.9/MAINTAINERS linux-2.4.37.9-vrs1-5mx2/MAINTAINERS --- linux-2.4.37.9/MAINTAINERS Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/MAINTAINERS Mon Jun 7 18:59:41 2010 @@ -251,6 +251,8 @@ ARM/STRONGARM110 PORT P: Russell King M: rmk@arm.linux.org.uk +P: Vincent Sanders +M: vince@arm.linux.org.uk L: linux-arm-kernel@lists.arm.linux.org.uk W: http://www.arm.linux.org.uk/ S: Maintained diff -uNr linux-2.4.37.9/Makefile linux-2.4.37.9-vrs1-5mx2/Makefile --- linux-2.4.37.9/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/Makefile Mon Jun 7 19:05:23 2010 @@ -1,11 +1,12 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 37 -EXTRAVERSION = .9 +EXTRAVERSION = .9-vrs1-5mx2 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) -ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) +#ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) +ARCH := arm KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -19,7 +20,7 @@ HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -CROSS_COMPILE = +CROSS_COMPILE = arm-linux- # # Include the make variables (CC, etc...) @@ -147,7 +148,9 @@ DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o -DRIVERS-y += drivers/char/char.o \ +DRIVERS-$(CONFIG_L3) += drivers/l3/l3.o +DRIVERS-y += drivers/serial/serial.o \ + drivers/char/char.o \ drivers/block/block.o \ drivers/misc/misc.o \ drivers/net/net.o @@ -171,6 +174,7 @@ DRIVERS-y += drivers/cdrom/driver.o endif +DRIVERS-$(CONFIG_SSI) += drivers/ssi/ssi.o DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o @@ -204,6 +208,8 @@ DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o +DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o +DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o DRIVERS := $(DRIVERS-y) @@ -283,11 +289,6 @@ export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS - -.S.s: - $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $< -.S.o: - $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -c -o $*.o $< Version: dummy @rm -f include/linux/compile.h diff -uNr linux-2.4.37.9/Rules.make linux-2.4.37.9-vrs1-5mx2/Rules.make --- linux-2.4.37.9/Rules.make Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/Rules.make Mon Jun 7 19:04:33 2010 @@ -51,15 +51,15 @@ # %.s: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@ + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o $@ %.i: %.c - $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@ + $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) $< > $@ %.o: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $< + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -c -o $@ $< @ ( \ - echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@))))' ; \ + echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$(*F)) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$(*F)) $$(CFLAGS_$@))))' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'endif' \ ) > $(dir $@)/.$(notdir $@).flags @@ -272,7 +272,8 @@ endif # CONFIG_MODVERSIONS ifneq "$(strip $(export-objs))" "" -$(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h +$(export-objs): $(TOPDIR)/include/linux/modversions.h +$(export-objs): %.o: %.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c) @ ( \ echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \ diff -uNr linux-2.4.37.9/arch/alpha/config.in linux-2.4.37.9-vrs1-5mx2/arch/alpha/config.in --- linux-2.4.37.9/arch/alpha/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/alpha/config.in Wed May 26 15:44:44 2010 @@ -7,6 +7,7 @@ define_bool CONFIG_UID16 n define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y +define_bool CONFIG_GENERIC_ISA_DMA y mainmenu_name "Kernel configuration of Linux for Alpha machines" diff -uNr linux-2.4.37.9/arch/arm/Makefile linux-2.4.37.9-vrs1-5mx2/arch/arm/Makefile --- linux-2.4.37.9/arch/arm/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/Makefile Wed May 26 15:44:05 2010 @@ -52,7 +52,7 @@ CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm -AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float +AFLAGS +=$(apcs-y) $(arch-y) -msoft-float ifeq ($(CONFIG_CPU_26),y) PROCESSOR := armo @@ -154,6 +154,11 @@ ifeq ($(CONFIG_ARCH_FORTUNET),y) TEXTADDR = 0xc0208000 +endif + +ifeq ($(CONFIG_ARCH_PSIONW),y) +TEXTADDR = 0xc0048000 +MACHINE = psionw endif ifeq ($(CONFIG_ARCH_ANAKIN),y) diff -uNr linux-2.4.37.9/arch/arm/boot/compressed/head.S linux-2.4.37.9-vrs1-5mx2/arch/arm/boot/compressed/head.S --- linux-2.4.37.9/arch/arm/boot/compressed/head.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/boot/compressed/head.S Wed May 26 15:44:01 2010 @@ -40,6 +40,14 @@ .macro writeb, rb strb \rb, [r3, #0x3f8 << 2] .endm +#elif defined(CONFIG_ARCH_RISCSTATION) + .macro loadsp, rb + mov \rb, #0x03000000 + orr \rb, \rb, #0x00010000 + .endm + .macro writeb, rb + strb \rb, [r3, #0x3f8 << 2] + .endm #elif defined(CONFIG_ARCH_INTEGRATOR) .macro loadsp, rb mov \rb, #0x16000000 @@ -396,6 +404,20 @@ mcr p15, 0, r0, c1, c0, 0 @ load control register mov pc, r12 +__arm7_cache_on: + mov r12, lr + bl __setup_mmu + mov r0, #0 + mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 + mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 + mcr p15, 0, r3, c2, c0, 0 @ load page table pointer + mov r0, #-1 + mcr p15, 0, r0, c3, c0, 0 @ load domain access control + mov r0, #0x7d + mcr p15, 0, r0, c1, c0, 0 @ load control register + mov pc, r12 + + /* * All code following this line is relocatable. It is relocated by * the above code to the end of the decompressed kernel image and @@ -480,9 +502,9 @@ .word 0x41007000 @ ARM7/710 .word 0xfff8fe00 + b __arm7_cache_on b __arm7_cache_off - b __arm7_cache_off - mov pc, lr + b __armv3_cache_flush .word 0x41807200 @ ARM720T (writethrough) .word 0xffffff00 @@ -490,14 +512,14 @@ b __armv4_cache_off mov pc, lr - .word 0x41129200 @ ARM920T - .word 0xff00fff0 + .word 0x41009200 @ ARM920T, ARM922T, ARM926TEJ-S + .word 0xff00ff90 b __armv4_cache_on b __armv4_cache_off b __armv4_cache_flush - .word 0x41029220 @ ARM922T - .word 0xff00fff0 + .word 0x4100a200 @ ARM1020T/E, ARM1022E, ARM1026TEJ-S + .word 0xff00ff90 b __armv4_cache_on b __armv4_cache_off b __armv4_cache_flush diff -uNr linux-2.4.37.9/arch/arm/config.in linux-2.4.37.9-vrs1-5mx2/arch/arm/config.in --- linux-2.4.37.9/arch/arm/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/config.in Wed May 26 15:44:05 2010 @@ -45,6 +45,7 @@ Omaha CONFIG_ARCH_OMAHA \ LinkUp-L7200 CONFIG_ARCH_L7200 \ Motorola-MX1ADS CONFIG_ARCH_MX1ADS \ + Psion-Windermere CONFIG_ARCH_PSIONW \ RiscPC CONFIG_ARCH_RPC \ RiscStation CONFIG_ARCH_RISCSTATION \ SA1100-based CONFIG_ARCH_SA1100 \ @@ -144,6 +145,7 @@ mainmenu_option next_comment comment 'AT91RM9200 Implementations' dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200 +dep_bool ' Cogent CSB337' CONFIG_MACH_CSB337 $CONFIG_ARCH_AT91RM9200 endmenu mainmenu_option next_comment @@ -181,6 +183,19 @@ endmenu +if [ "$CONFIG_ARCH_PSIONW" = "y" ]; then +mainmenu_option next_comment +comment 'Psion Windermere Implementations' +choice 'Psion-Windermere Implementations' \ + "Psion-5MX-16MB-and-Ericsson-MC218 CONFIG_PSIONW_5MX \ + Psion-5MX-Pro-16MB CONFIG_PSIONW_5MXPRO16MB \ + Psion-5MX-Pro-24MB CONFIG_PSIONW_5MXPRO24MB \ + Psion-5MX-Pro-32MB CONFIG_PSIONW_5MXPRO32MB \ + Psion-Revo-8MB CONFIG_PSIONW_REVO \ + Psion-Revo-Plus-16MB-and-Diamond-Mako CONFIG_PSIONW_REVOPLUS" CONFIG_PSIONW_5MX +endmenu +fi + # Definitions to make life easier if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \ "$CONFIG_ARCH_RPC" = "y" ]; then @@ -189,6 +204,12 @@ define_bool CONFIG_ARCH_ACORN n fi +if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then + define_bool CONFIG_PLD y +else + define_bool CONFIG_PLD n +fi + ##################################################################### # Footbridge support if [ "$CONFIG_ARCH_CO285" = "y" -o \ @@ -287,6 +308,7 @@ # ARM720T if [ "$CONFIG_ARCH_CLPS711X" = "y" -o \ + "$CONFIG_ARCH_PSIONW" = "y" -o \ "$CONFIG_ARCH_L7200" = "y" -o \ "$CONFIG_ARCH_CDB89712" = "y" ]; then define_bool CONFIG_CPU_ARM720T y @@ -315,26 +337,42 @@ # ARM922T if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then define_bool CONFIG_CPU_ARM922T y - define_bool CONFIG_PLD y else - define_bool CONFIG_CPU_ARM922T n - define_bool CONFIG_PLD n + if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then + bool 'Support ARM922T(Excalibur) processor' CONFIG_ARM922T + else + define_bool CONFIG_CPU_ARM922T n + fi fi # ARM926T if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then - bool 'Support ARM926T processor' CONFIG_CPU_ARM926T + bool 'Support ARM926TEJ-S processor' CONFIG_CPU_ARM926T else define_bool CONFIG_CPU_ARM926T n fi # ARM1020 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then - bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020 + bool 'Support ARM1020T (Rev0) processor' CONFIG_CPU_ARM1020 else define_bool CONFIG_CPU_ARM1020 n fi +# ARM1020E +if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then + bool 'Support ARM1020E (Rev1) processor' CONFIG_CPU_ARM1020E +else + define_bool CONFIG_CPU_ARM1020E n +fi + +# ARM1022 +if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then + bool 'Support ARM1022 processor' CONFIG_CPU_ARM1020E +else + define_bool CONFIG_CPU_ARM1022 n +fi + # ARM1026EJ-S if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then bool 'Support ARM1026EJ-S processor' CONFIG_CPU_ARM1026 @@ -388,31 +426,36 @@ if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \ "$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \ - "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then + "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \ + "$CONFIG_CPU_ARM1022" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then dep_bool 'Support Thumb instructions (EXPERIMENTAL)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL fi if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \ "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \ + "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \ "$CONFIG_CPU_ARM1026" = "y" ]; then bool 'Disable I-Cache' CONFIG_CPU_ICACHE_DISABLE bool 'Disable D-Cache' CONFIG_CPU_DCACHE_DISABLE - if [ "$CONFIG_CPU_DISABLE_DCACHE" = "n" ]; then + if [ "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then bool 'Force write through D-cache' CONFIG_CPU_DCACHE_WRITETHROUGH fi fi if [ "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \ + "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \ "$CONFIG_CPU_ARM1026" = "y" ]; then if [ "$CONFIG_CPU_ICACHE_DISABLE" = "n" -o "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then bool 'Round robin I and D cache replacement algorithm' CONFIG_CPU_CACHE_ROUND_ROBIN fi fi -if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then +if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \ + "$CONFIG_CPU_ARM1026" = "y" -o "$CONFIG_CPU_ARM1022" = "y" ]; then bool 'Disable branch prediction' CONFIG_CPU_BPREDICT_DISABLE fi # Select various configuration options depending on the machine type if [ "$CONFIG_ARCH_EDB7211" = "y" -o \ + "$CONFIG_ARCH_PSIONW" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_RISCSTATION" = "y" ]; then define_bool CONFIG_DISCONTIGMEM y @@ -491,7 +534,7 @@ if [ "$CONFIG_FPE_NWFPE" != "n" ]; then bool ' Support extended precision' CONFIG_FPE_NWFPE_XP fi -if [ "$CONFIG_CPU_26" = "n" -a "$CONFIG_CPU_32v3" = "n" ]; then +if [ "$CONFIG_CPU_26" = "n" ]; then dep_tristate 'FastFPE math emulation (EXPERIMENTAL)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL fi choice 'Kernel core (/proc/kcore) format' \ @@ -511,10 +554,12 @@ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_CO285" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_PSIONW" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ "$CONFIG_ARCH_CDB89712" = "y" -o \ "$CONFIG_ARCH_P720T" = "y" -o \ - "$CONFIG_ARCH_OMAHA" = "y" ]; then + "$CONFIG_ARCH_OMAHA" = "y" -o \ + "$CONFIG_ARCH_AT91RM9200" = "y" ]; then bool 'Timer and CPU usage LEDs' CONFIG_LEDS if [ "$CONFIG_LEDS" = "y" ]; then if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ @@ -522,9 +567,11 @@ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_CO285" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_PSIONW" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ "$CONFIG_ARCH_P720T" = "y" -o \ - "$CONFIG_ARCH_OMAHA" = "y" ]; then + "$CONFIG_ARCH_OMAHA" = "y" -o \ + "$CONFIG_ARCH_AT91RM9200" = "y" ]; then bool ' Timer LED' CONFIG_LEDS_TIMER bool ' CPU usage LED' CONFIG_LEDS_CPU fi @@ -599,7 +646,8 @@ fi endmenu -if [ "$CONFIG_ARCH_CLPS711X" = "y" ]; then +if [ "$CONFIG_ARCH_CLPS711X" = "y" -o \ + "$CONFIG_ARCH_PSIONW" = "y" ]; then # This is _meant_ to be ssi _not_ scsi. It is not a spelling error. source drivers/ssi/Config.in fi @@ -678,6 +726,7 @@ "$CONFIG_ARCH_TBOX" = "y" -o \ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_PSIONW" = "y" -o \ "$CONFIG_PCI" = "y" ]; then mainmenu_option next_comment comment 'Sound' @@ -729,10 +778,7 @@ dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X - -int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0 - endmenu -source crypto/Config.in source lib/Config.in + diff -uNr linux-2.4.37.9/arch/arm/def-configs/at91rm9200dk linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/at91rm9200dk --- linux-2.4.37.9/arch/arm/def-configs/at91rm9200dk Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/at91rm9200dk Wed May 26 15:43:59 2010 @@ -111,6 +111,7 @@ # AT91RM9200 Implementations # CONFIG_ARCH_AT91RM9200DK=y +# CONFIG_MACH_CSB337 is not set # # CLPS711X/EP721X Implementations @@ -125,6 +126,7 @@ # CONFIG_ARCH_EP7211 is not set # CONFIG_ARCH_EP7212 is not set # CONFIG_ARCH_ACORN is not set +# CONFIG_PLD is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set @@ -135,9 +137,10 @@ # CONFIG_CPU_ARM720T is not set CONFIG_CPU_ARM920T=y # CONFIG_CPU_ARM922T is not set -# CONFIG_PLD is not set # CONFIG_CPU_ARM926T is not set # CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1020E is not set +# CONFIG_CPU_ARM1022 is not set # CONFIG_CPU_ARM1026 is not set # CONFIG_CPU_SA110 is not set # CONFIG_CPU_SA1100 is not set @@ -146,6 +149,7 @@ # CONFIG_ARM_THUMB is not set # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set # CONFIG_DISCONTIGMEM is not set # @@ -164,6 +168,7 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set @@ -173,6 +178,9 @@ # CONFIG_PM is not set # CONFIG_ARTHUR is not set CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20210000,3145728 root=/dev/ram rw" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU is not set CONFIG_ALIGNMENT_TRAP=y # @@ -204,6 +212,7 @@ # CONFIG_MTD_CFI_ADV_OPTIONS is not set # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set @@ -230,7 +239,9 @@ # CONFIG_MTD_AUTCPU12 is not set # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_CEIVA is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set # # Self-contained MTD device drivers @@ -250,9 +261,9 @@ # NAND Flash Device Drivers # CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ECC=y # CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_AT91_SMARTMEDIA=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_AT91_SMARTMEDIA is not set # # Plug and Play configuration @@ -269,6 +280,7 @@ # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_CISS_MONITOR_THREAD is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set @@ -276,6 +288,7 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_STATS is not set # # Multi-device support (RAID and LVM) @@ -312,6 +325,12 @@ # CONFIG_SYN_COOKIES is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set # CONFIG_IPX is not set @@ -382,10 +401,12 @@ # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set +# CONFIG_E1000 is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set # CONFIG_FDDI is not set @@ -455,6 +476,8 @@ # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_MX1TS is not set # # Character devices @@ -502,6 +525,7 @@ # CONFIG_I2C=y # CONFIG_I2C_ALGOBIT is not set +# CONFIG_SCx200_ACB is not set # CONFIG_I2C_ALGOPCF is not set CONFIG_I2C_AT91=y CONFIG_I2C_CHARDEV=y @@ -528,6 +552,11 @@ # # CONFIG_INPUT_GAMEPORT is not set # CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_IPMI_PANIC_EVENT is not set +# CONFIG_IPMI_DEVICE_INTERFACE is not set +# CONFIG_IPMI_KCS is not set +# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards @@ -536,12 +565,14 @@ CONFIG_WATCHDOG_NOWAYOUT=y # CONFIG_ACQUIRE_WDT is not set # CONFIG_ADVANTECH_WDT is not set +# CONFIG_ALIM1535_WDT is not set # CONFIG_ALIM7101_WDT is not set # CONFIG_SC520_WDT is not set # CONFIG_PCWATCHDOG is not set # CONFIG_21285_WATCHDOG is not set # CONFIG_977_WATCHDOG is not set # CONFIG_SA1100_WATCHDOG is not set +# CONFIG_EPXA_WATCHDOG is not set # CONFIG_OMAHA_WATCHDOG is not set CONFIG_AT91_WATCHDOG=y # CONFIG_EUROTECH_WDT is not set @@ -551,11 +582,16 @@ # CONFIG_MIXCOMWD is not set # CONFIG_60XX_WDT is not set # CONFIG_SC1200_WDT is not set +# CONFIG_SCx200_WDT is not set # CONFIG_SOFT_WATCHDOG is not set # CONFIG_W83877F_WDT is not set # CONFIG_WDT is not set # CONFIG_WDTPCI is not set # CONFIG_MACHZ_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_SCx200 is not set +# CONFIG_SCx200_GPIO is not set +# CONFIG_AMD_PM768 is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set CONFIG_AT91_RTC=y @@ -568,6 +604,10 @@ # # CONFIG_FTAPE is not set # CONFIG_AGP is not set + +# +# Direct Rendering Manager (XFree86 DRI support) +# # CONFIG_DRM is not set # @@ -579,6 +619,7 @@ # File systems # # CONFIG_QUOTA is not set +# CONFIG_QFMT_V2 is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set @@ -588,6 +629,9 @@ # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BEFS_DEBUG is not set # CONFIG_BFS_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set @@ -605,6 +649,9 @@ # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set # CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set @@ -624,6 +671,11 @@ # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set # CONFIG_UFS_FS_WRITE is not set +# CONFIG_XFS_FS is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_TRACE is not set +# CONFIG_XFS_DEBUG is not set # # Network File Systems @@ -632,9 +684,11 @@ # CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set # CONFIG_NFS_V3 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set # CONFIG_SUNRPC is not set # CONFIG_LOCKD is not set # CONFIG_SMB_FS is not set @@ -648,7 +702,6 @@ # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set # CONFIG_ZISOFS_FS is not set -# CONFIG_ZLIB_FS_INFLATE is not set # # Partition Types @@ -674,16 +727,18 @@ # CONFIG_USB_DEBUG is not set # CONFIG_USB_DEVICEFS is not set # CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set # CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_UHCI is not set # CONFIG_USB_UHCI_ALT is not set # CONFIG_USB_OHCI is not set # CONFIG_USB_OHCI_SA1111 is not set +# CONFIG_USB_SL811HS_ALT is not set +# CONFIG_USB_SL811HS is not set CONFIG_USB_OHCI_AT91=y # CONFIG_USB_AUDIO is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_MIDI is not set # CONFIG_USB_STORAGE is not set # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set @@ -692,6 +747,7 @@ # CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_HP8200e is not set # CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -700,7 +756,10 @@ # CONFIG_USB_HIDDEV is not set # CONFIG_USB_KBD is not set # CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set # CONFIG_USB_DC2XX is not set # CONFIG_USB_MDC800 is not set # CONFIG_USB_SCANNER is not set @@ -718,35 +777,16 @@ # USB Serial Converter support # # CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_TIGL is not set # CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set + +# +# Support for USB gadgets +# +# CONFIG_USB_GADGET is not set # # Bluetooth support @@ -770,3 +810,10 @@ CONFIG_DEBUG_LL=y # CONFIG_DEBUG_DC21285_PORT is not set # CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +CONFIG_CRC32=y +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -uNr linux-2.4.37.9/arch/arm/def-configs/csb337 linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/csb337 --- linux-2.4.37.9/arch/arm/def-configs/csb337 Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/csb337 Wed May 26 15:43:59 2010 @@ -0,0 +1,760 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_OMAHA is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_RISCSTATION is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set +CONFIG_ARCH_AT91RM9200=y + +# +# Archimedes/A5000 Implementations +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSAGC is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_ADSBITSYPLUS is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_H3600_SLEEVE is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_HACKKIT is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SIMPUTER is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_SA1100_SSP is not set + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set +CONFIG_MACH_CSB337=y + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_GUIDEA07 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_PLD is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +CONFIG_CPU_ARM920T=y +# CONFIG_CPU_ARM922T is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1020E is not set +# CONFIG_CPU_ARM1022 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20210000,3145728 root=/dev/ram rw" +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_PARTITIONS is not set +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=10000000 +CONFIG_MTD_PHYSMAP_LEN=200000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=2 +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_CEIVA is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_AT91_SMARTMEDIA is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_CISS_MONITOR_THREAD is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_STATS is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_ARM_CIRRUS is not set +CONFIG_AT91_ETHER=y +# CONFIG_AT91_ETHER_RMII is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_MX1TS is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_AT91_SPIDEV=y + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_AT91=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y +CONFIG_I2C_DS1307=y + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_IPMI_PANIC_EVENT is not set +# CONFIG_IPMI_DEVICE_INTERFACE is not set +# CONFIG_IPMI_KCS is not set +# CONFIG_IPMI_WATCHDOG is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_ALIM1535_WDT is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_21285_WATCHDOG is not set +# CONFIG_977_WATCHDOG is not set +# CONFIG_SA1100_WATCHDOG is not set +# CONFIG_EPXA_WATCHDOG is not set +# CONFIG_OMAHA_WATCHDOG is not set +CONFIG_AT91_WATCHDOG=y +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_SCx200 is not set +# CONFIG_SCx200_GPIO is not set +# CONFIG_AMD_PM768 is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +CONFIG_AT91_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set + +# +# Direct Rendering Manager (XFree86 DRI support) +# +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_QFMT_V2 is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BEFS_DEBUG is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_XFS_FS is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_TRACE is not set +# CONFIG_XFS_DEBUG is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Support for USB gadgets +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +CONFIG_CRC32=y +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -uNr linux-2.4.37.9/arch/arm/def-configs/psion_5mx_ericsson_mc218_16mb linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/psion_5mx_ericsson_mc218_16mb --- linux-2.4.37.9/arch/arm/def-configs/psion_5mx_ericsson_mc218_16mb Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/psion_5mx_ericsson_mc218_16mb Wed May 26 15:43:59 2010 @@ -0,0 +1,977 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +CONFIG_ARCH_PSIONW=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Archimedes/A5000 Implementations (select only ONE) +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set + +# +# Psion Windermere Implementations +# +CONFIG_PSIONW_5MX=y +# CONFIG_PSIONW_5MXPRO24MB is not set +# CONFIG_PSIONW_5MXPRO32MB is not set +# CONFIG_PSIONW_REVO is not set +# CONFIG_PSIONW_REVOPLUS is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set + +# +# Processor Type +# +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +CONFIG_CPU_ARM720T=y +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_ARM_THUMB=y +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +CONFIG_PCMCIA_ETNA=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# At least one math emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="dummy=dummy" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +# CONFIG_ALIGNMENT_TRAP is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +CONFIG_NET_POCKET=y +# CONFIG_DE600 is not set +# CONFIG_DE620 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=y +# CONFIG_PPPOE is not set +CONFIG_SLIP=y +CONFIG_SLIP_COMPRESSED=y +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_NET_PCMCIA_RADIO is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=y + +# +# IrDA protocols +# +CONFIG_IRLAN=y +CONFIG_IRNET=y +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +# CONFIG_IRPORT_SIR is not set + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Synchronous Serial Interface +# +CONFIG_SSI=y + +# +# SSI Bus Drivers +# +# CONFIG_SSI_CLPS711X is not set +CONFIG_SSI_PS5MX=y + +# +# SSI Device Drivers +# +# CONFIG_SSI_JUNO is not set +CONFIG_SSI_ADC7843=y + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +CONFIG_SERIAL_PSIONW=y +CONFIG_SERIAL_PSIONW_CONSOLE=y +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y + +# +# Psion Windermere Keyboard Locale +# +# CONFIG_PSION_KBD_DE is not set +CONFIG_PSION_KBD_UK=y +# CONFIG_PSION_KBD_US is not set +CONFIG_PROCFS_PSION=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set + +# +# Other L3 adapters +# +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_ACORN is not set +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +CONFIG_FB_PSIONW=y +# CONFIG_FB_SA1100 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +# CONFIG_FBCON_CFB8 is not set +# CONFIG_FBCON_CFB16 is not set +# CONFIG_FBCON_CFB24 is not set +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set +# CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_HGA is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +CONFIG_SOUND_PSIONW=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_WAVEARTIST is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set +# CONFIG_USB_OHCI_SA1111 is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set + +# +# SCSI support is needed for USB Storage +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_RIO500 is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -uNr linux-2.4.37.9/arch/arm/def-configs/psion_revo_8mb linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/psion_revo_8mb --- linux-2.4.37.9/arch/arm/def-configs/psion_revo_8mb Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/psion_revo_8mb Wed May 26 15:43:59 2010 @@ -0,0 +1,915 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +CONFIG_ARCH_PSIONW=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Archimedes/A5000 Implementations (select only ONE) +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set + +# +# Psion Windermere Implementations +# +# CONFIG_PSIONW_5MX is not set +# CONFIG_PSIONW_5MXPRO24MB is not set +# CONFIG_PSIONW_5MXPRO32MB is not set +CONFIG_PSIONW_REVO=y +# CONFIG_PSIONW_REVOPLUS is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set + +# +# Processor Type +# +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +CONFIG_CPU_ARM720T=y +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_ARM_THUMB=y +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +# CONFIG_PCMCIA_ETNA is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# At least one math emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="dummy=dummy" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +# CONFIG_ALIGNMENT_TRAP is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +CONFIG_NET_POCKET=y +# CONFIG_DE600 is not set +# CONFIG_DE620 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=y +# CONFIG_PPPOE is not set +CONFIG_SLIP=y +CONFIG_SLIP_COMPRESSED=y +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=y + +# +# IrDA protocols +# +CONFIG_IRLAN=y +CONFIG_IRNET=y +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +# CONFIG_IRPORT_SIR is not set + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Synchronous Serial Interface +# +CONFIG_SSI=y + +# +# SSI Bus Drivers +# +# CONFIG_SSI_CLPS711X is not set +CONFIG_SSI_PS5MX=y + +# +# SSI Device Drivers +# +# CONFIG_SSI_JUNO is not set +CONFIG_SSI_ADC7843=y + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +CONFIG_SERIAL_PSIONW=y +CONFIG_SERIAL_PSIONW_CONSOLE=y +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y + +# +# Psion Windermere Keyboard Locale +# +# CONFIG_PSION_KBD_DE is not set +CONFIG_PSION_KBD_UK=y +# CONFIG_PSION_KBD_US is not set +CONFIG_PROCFS_PSION=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set + +# +# Other L3 adapters +# +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_ACORN is not set +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +CONFIG_FB_PSIONW=y +# CONFIG_FB_SA1100 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +# CONFIG_FBCON_CFB8 is not set +# CONFIG_FBCON_CFB16 is not set +# CONFIG_FBCON_CFB24 is not set +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set +# CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_HGA is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +CONFIG_SOUND_PSIONW=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_WAVEARTIST is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set +# CONFIG_USB_OHCI_SA1111 is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set + +# +# SCSI support is needed for USB Storage +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_RIO500 is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -uNr linux-2.4.37.9/arch/arm/def-configs/psion_revo_plus_diamond_mako_16mb linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/psion_revo_plus_diamond_mako_16mb --- linux-2.4.37.9/arch/arm/def-configs/psion_revo_plus_diamond_mako_16mb Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/def-configs/psion_revo_plus_diamond_mako_16mb Wed May 26 15:43:59 2010 @@ -0,0 +1,915 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +CONFIG_ARCH_PSIONW=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Archimedes/A5000 Implementations (select only ONE) +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set + +# +# Psion Windermere Implementations +# +# CONFIG_PSIONW_5MX is not set +# CONFIG_PSIONW_5MXPRO24MB is not set +# CONFIG_PSIONW_5MXPRO32MB is not set +# CONFIG_PSIONW_REVO is not set +CONFIG_PSIONW_REVOPLUS=y +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set + +# +# Processor Type +# +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +CONFIG_CPU_ARM720T=y +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_ARM_THUMB=y +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +# CONFIG_PCMCIA_ETNA is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# At least one math emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="dummy=dummy" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +# CONFIG_ALIGNMENT_TRAP is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +CONFIG_NET_POCKET=y +# CONFIG_DE600 is not set +# CONFIG_DE620 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=y +# CONFIG_PPPOE is not set +CONFIG_SLIP=y +CONFIG_SLIP_COMPRESSED=y +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=y + +# +# IrDA protocols +# +CONFIG_IRLAN=y +CONFIG_IRNET=y +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +# CONFIG_IRPORT_SIR is not set + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Synchronous Serial Interface +# +CONFIG_SSI=y + +# +# SSI Bus Drivers +# +# CONFIG_SSI_CLPS711X is not set +CONFIG_SSI_PS5MX=y + +# +# SSI Device Drivers +# +# CONFIG_SSI_JUNO is not set +CONFIG_SSI_ADC7843=y + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +CONFIG_SERIAL_PSIONW=y +CONFIG_SERIAL_PSIONW_CONSOLE=y +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y + +# +# Psion Windermere Keyboard Locale +# +# CONFIG_PSION_KBD_DE is not set +CONFIG_PSION_KBD_UK=y +# CONFIG_PSION_KBD_US is not set +CONFIG_PROCFS_PSION=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set + +# +# Other L3 adapters +# +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_ACORN is not set +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +CONFIG_FB_PSIONW=y +# CONFIG_FB_SA1100 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +# CONFIG_FBCON_CFB8 is not set +# CONFIG_FBCON_CFB16 is not set +# CONFIG_FBCON_CFB24 is not set +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set +# CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_HGA is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +CONFIG_SOUND_PSIONW=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_WAVEARTIST is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set +# CONFIG_USB_OHCI_SA1111 is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set + +# +# SCSI support is needed for USB Storage +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# + +# +# Input core support is needed for USB HID +# + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_RIO500 is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -uNr linux-2.4.37.9/arch/arm/fastfpe/CPDO.S linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/CPDO.S --- linux-2.4.37.9/arch/arm/fastfpe/CPDO.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/CPDO.S Wed May 26 15:43:59 2010 @@ -0,0 +1,1786 @@ +/* +The FP structure has 4 words reserved for each register, the first is used just +for the sign in bit 31, the second and third are for the mantissa (unsigned +integer, high 32 bit first) and the fourth is the exponent (signed integer). +The mantissa is always normalized. + +If the exponent is 0x80000000, that is the most negative value, the number +represented is 0 and both mantissa words are also 0. + +If the exponent is 0x7fffffff, that is the biggest positive value, the number +represented is infinity if the mantissa is 0, otherwise it is a NaN. + +Decimal and packed decimal numbers are not supported yet. + +The parameters to these functions are r0=destination pointer, r1 and r2 +source pointers. r4 is the instruction. They may use r0-r8, r11. They return +to r14, which contains the address of a rounding function. The rounding +function expects r0=address, r1-r4=sign, mantissa high, mantissa low, +exponent, r5=additional lower mantissa bits. + +CPDO_rnf_core expects the return address in r14. +*/ + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_adf +CPDO_adf: + ldmia r2,{r6,r7,r8,r11} + ldmia r1,{r1,r2,r3,r4} + + cmp r11,#0x7fffffff + cmpne r11,#0x80000000 + cmpne r4,#0x7fffffff + cmpne r4,#0x80000000 + beq CPDO_adf_extra + + cmp r1,r6 + bne CPDO_suf_s + +CPDO_adf_s: + subs r6,r4,r11 + bmi CPDO_adf_normalize1st + +CPDO_adf_normalize2nd: + cmp r6,#32 + ble CPDO_adf_normalize2nd_1 + cmp r6,#64 + bgt CPDO_adf_normalize2nd_3 + +CPDO_adf_normalize2nd_2: + sub r6,r6,#32 + rsb r11,r6,#32 + mov r5,r8,lsr r6 + add r5,r5,r7,lsl r11 + movs r11,r8,lsl r11 + orrne r5,r5,#1 + mov r8,r7,lsr r6 + mov r7,#0 + b CPDO_adf_add + +CPDO_adf_normalize2nd_1: + rsb r11,r6,#32 + mov r5,r8,lsl r11 + mov r8,r8,lsr r6 + add r8,r8,r7,lsl r11 + mov r7,r7,lsr r6 + b CPDO_adf_add + +CPDO_adf_normalize2nd_3: + mov r5,#0x40000000 + mov pc,r14 + +CPDO_adf_normalize1st: + mov r4,r11 + rsb r6,r6,#0 + cmp r6,#32 + ble CPDO_adf_normalize1st_1 + cmp r6,#64 + bgt CPDO_adf_normalize1st_3 + +CPDO_adf_normalize1st_2: + sub r6,r6,#32 + rsb r11,r6,#32 + mov r5,r3,lsr r6 + add r5,r5,r2,lsl r11 + movs r11,r3,lsl r11 + orrne r5,r5,#1 + mov r3,r2,lsr r6 + mov r2,#0 + b CPDO_adf_add + +CPDO_adf_normalize1st_1: + rsb r11,r6,#32 + mov r5,r3,lsl r11 + mov r3,r3,lsr r6 + add r3,r3,r2,lsl r11 + mov r2,r2,lsr r6 + b CPDO_adf_add + +CPDO_adf_normalize1st_3: + mov r5,#0x40000000 + mov r2,r7 + mov r3,r8 + mov pc,r14 + +CPDO_adf_add: + adds r3,r3,r8 + adcs r2,r2,r7 + bcc CPDO_adf_add_no_overflow + + movs r2,r2,rrx + movs r3,r3,rrx + movs r5,r5,rrx + orrcs r5,r5,#1 + add r4,r4,#1 + +CPDO_adf_add_no_overflow: + mov pc,r14 + +CPDO_adf_extra: + cmp r4,#0x7fffffff + beq CPDO_adf_1st_infnan + cmp r11,#0x7fffffff + beq CPDO_adf_2nd_infnan + cmp r11,#0x80000000 + beq CPDO_adf_2nd_0 + +CPDO_adf_1st_0: + mov r1,r6 + mov r2,r7 + mov r3,r8 + mov r4,r11 + mov r5,#0 + mov pc,r14 + +CPDO_adf_2nd_0: + cmp r4,#0x80000000 + beq CPDO_adf_both_0 + mov r5,#0 + mov pc,r14 + +CPDO_adf_both_0: + cmp r1,r6 + beq CPDO_adf_both_0_equal_sign + and r5,r5,#0x00000060 + cmp r5,#0x00000040 // rounding mode M? + moveq r1,#0x80000000 + movne r1,#0 +CPDO_adf_both_0_equal_sign: + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_adf_1st_infnan: + cmp r11,#0x7fffffff + beq CPDO_adf_both_infnan +CPDO_adf_1st_infnan_entry: + orrs r5,r3,r2,lsl#1 // ignore MSB + moveq pc,r14 // Inf + tst r2,#0x40000000 + movne pc,r14 // QNaN +CPDO_adf_generate_qnan: + mov r1,#0x80000000 + mov r2,#0x7fffffff + mov r3,#0xffffffff + mov r4,#0x7fffffff + ldr r5,[r10,#128] + orr r5,r5,#1 // set invalid operation flag + str r5,[r10,#128] + mov pc,r14 + +CPDO_adf_2nd_infnan: + mov r1,r6 + mov r2,r7 + mov r3,r8 + mov r4,r11 + b CPDO_adf_1st_infnan_entry + +CPDO_adf_both_infnan: + orrs r5,r3,r2,lsl#1 // ignore MSB + beq CPDO_adf_1st_inf + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_adf_2nd_inf + tst r2,#0x40000000 + tstne r7,#0x40000000 + beq CPDO_adf_generate_qnan // at least one is SNaN + orrs r5,r3,r2,lsl#1 // ignore MSB, FIXME! what is going on here? + moveq r1,r6 // if first is not NaN + moveq r2,r7 // give second as result + moveq r3,r8 + mov pc,r14 + +CPDO_adf_1st_inf: + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_adf_both_inf + tst r7,#0x40000000 + beq CPDO_adf_generate_qnan + mov r1,r6 //if 2nd no SNaN return 2nd + mov r2,r7 + mov r3,r8 + mov pc,r14 + +CPDO_adf_2nd_inf: + tst r2,#0x40000000 + beq CPDO_adf_generate_qnan + mov pc,r14 // if 1st no SNaN just return it + +CPDO_adf_both_inf: + cmp r1,r6 + bne CPDO_adf_generate_qnan // signs of both inf are different + mov pc,r14 + +/*--------------------------------------------------------------------------*/ + + .globl CPDO_suf +CPDO_suf: + ldmia r2,{r6,r7,r8,r11} + ldmia r1,{r1,r2,r3,r4} + +CPDO_suf_l: + cmp r11,#0x7fffffff + cmpne r11,#0x80000000 + cmpne r4,#0x7fffffff + cmpne r4,#0x80000000 + beq CPDO_suf_extra + + cmp r1,r6 + bne CPDO_adf_s + +CPDO_suf_s: + subs r6,r4,r11 + blt CPDO_suf_normalize1st + bgt CPDO_suf_normalize2nd + cmp r2,r7 + cmpeq r3,r8 + beq CPDO_suf_zero + mov r5,#0 + bcs CPDO_suf_sub_1stbigger + eor r1,r1,#0x80000000 + b CPDO_suf_sub_2ndbigger + +CPDO_suf_normalize2nd: + cmp r6,#32 + ble CPDO_suf_normalize2nd_1 + cmp r6,#64 + bgt CPDO_suf_normalize2nd_3 + +CPDO_suf_normalize2nd_2: + sub r6,r6,#32 + rsb r11,r6,#32 + mov r5,r8,lsr r6 + add r5,r5,r7,lsl r11 + movs r11,r8,lsl r11 + orrne r5,r5,#1 + mov r8,r7,lsr r6 + mov r7,#0 + b CPDO_suf_sub_1stbigger + +CPDO_suf_normalize2nd_1: + rsb r11,r6,#32 + mov r5,r8,lsl r11 + mov r8,r8,lsr r6 + add r8,r8,r7,lsl r11 + mov r7,r7,lsr r6 + b CPDO_suf_sub_1stbigger + +CPDO_suf_normalize2nd_3: + sub r6,r6,#64 + cmp r6,#32 + bge CPDO_suf_normalize2nd_4 + rsb r11,r6,#32 + mov r5,r7,lsr r6 + orrs r11,r8,r7,lsl r11 + orrne r5,r5,#1 + mov r7,#0 + mov r8,#0 + b CPDO_suf_sub_1stbigger + +CPDO_suf_normalize2nd_4: + mov r5,#1 + mov r7,#0 + mov r8,#0 + b CPDO_suf_sub_1stbigger + +CPDO_suf_normalize1st: + eor r1,r1,#0x80000000 + mov r4,r11 + rsb r6,r6,#0 + cmp r6,#32 + ble CPDO_suf_normalize1st_1 + cmp r6,#64 + bgt CPDO_suf_normalize1st_3 + +CPDO_suf_normalize1st_2: + sub r6,r6,#32 + rsb r11,r6,#32 + mov r5,r3,lsr r6 + add r5,r5,r2,lsl r11 + movs r11,r3,lsl r11 + orrne r5,r5,#1 + mov r3,r2,lsr r6 + mov r2,#0 + b CPDO_suf_sub_2ndbigger + +CPDO_suf_normalize1st_1: + rsb r11,r6,#32 + mov r5,r3,lsl r11 + mov r3,r3,lsr r6 + add r3,r3,r2,lsl r11 + mov r2,r2,lsr r6 + b CPDO_suf_sub_2ndbigger + +CPDO_suf_normalize1st_3: + sub r6,r6,#64 + cmp r6,#32 + bge CPDO_suf_normalize1st_4 + rsb r11,r6,#32 + mov r5,r2,lsr r6 + orrs r11,r3,r2,lsl r11 + orrne r5,r5,#1 + mov r2,#0 + mov r3,#0 + b CPDO_suf_sub_2ndbigger + +CPDO_suf_normalize1st_4: + mov r5,#1 + mov r2,#0 + mov r3,#0 + b CPDO_suf_sub_2ndbigger + +CPDO_suf_sub_1stbigger: + rsbs r5,r5,#0 + sbcs r3,r3,r8 + sbcs r2,r2,r7 + movmi pc,r14 + b CPDO_suf_norm + +CPDO_suf_sub_2ndbigger: + rsbs r5,r5,#0 + sbcs r3,r8,r3 + sbcs r2,r7,r2 + movmi pc,r14 + +CPDO_suf_norm: + teq r2,#0 // normalize 32 bit + bne CPDO_suf_norm16 + teq r3,#0 // normalize 64 bit + bne CPDO_suf_norm32 + mov r2,r5 + mov r3,#0 + mov r5,#0 + sub r4,r4,#64 + mov pc,r14 +CPDO_suf_norm32: + mov r2,r3 + mov r3,r5 + mov r5,#0 + sub r4,r4,#32 +CPDO_suf_norm16: + cmp r2,#0x00010000 // normalize 16 bit + bcs CPDO_suf_norm8 + mov r2,r2,lsl#16 + orr r2,r2,r3,lsr#16 + mov r3,r3,lsl#16 + orr r3,r3,r5,lsr#16 + mov r5,r5,lsl#16 + sub r4,r4,#16 +CPDO_suf_norm8: + cmp r2,#0x01000000 // normalize 8 bit + bcs CPDO_suf_norm4 + mov r2,r2,lsl#8 + orr r2,r2,r3,lsr#24 + mov r3,r3,lsl#8 + orr r3,r3,r5,lsr#24 + mov r5,r5,lsl#8 + sub r4,r4,#8 +CPDO_suf_norm4: + cmp r2,#0x10000000 // normalize 4 bit + bcs CPDO_suf_norm2 + mov r2,r2,lsl#4 + orr r2,r2,r3,lsr#28 + mov r3,r3,lsl#4 + orr r3,r3,r5,lsr#28 + mov r5,r5,lsl#4 + sub r4,r4,#4 +CPDO_suf_norm2: + cmp r2,#0x40000000 // normalize 2 bit + bcs CPDO_suf_norm1 + mov r2,r2,lsl#2 + orr r2,r2,r3,lsr#30 + mov r3,r3,lsl#2 + orr r3,r3,r5,lsr#30 + mov r5,r5,lsl#2 + sub r4,r4,#2 +CPDO_suf_norm1: + cmp r2,#0x80000000 // normalize 1 bit + bcs CPDO_suf_norme + mov r2,r2,lsl#1 + orr r2,r2,r3,lsr#31 + mov r3,r3,lsl#1 + orr r3,r3,r5,lsr#31 + mov r5,r5,lsl#1 + sub r4,r4,#1 +CPDO_suf_norme: + mov pc,r14 + +CPDO_suf_zero: + and r5,r5,#0x00000060 + cmp r5,#0x00000040 // rounding mode M? + moveq r1,#0x80000000 + movne r1,#0 + mov r2,#0 + mov r3,#0 + mov r4,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_suf_extra: // nearly the same as with adf + cmp r11,#0x7fffffff // the only thing we need to do is + bne CPDO_suf_extra_sign // to invert the second sign if + orrnes r5,r8,r7,lsl#1 // it is not a NaN, ignore MSB + bne CPDO_adf_extra +CPDO_suf_extra_sign: + eor r6,r6,#0x80000000 + b CPDO_adf_extra + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rsf +CPDO_rsf: + ldmia r1,{r6,r7,r8,r11} + ldmia r2,{r1,r2,r3,r4} + b CPDO_suf_l + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_muf +CPDO_muf: + ldmia r2,{r6,r7,r8,r11} + ldmia r1,{r1,r2,r3,r4} + + cmp r11,#0x7fffffff + cmpne r4,#0x7fffffff + beq CPDO_muf_extra + eor r1,r1,r6 // sign + cmp r11,#0x80000000 + cmpne r4,#0x80000000 + beq CPDO_muf_zero + + add r4,r4,r11 // exponent +#if 0 + +#define x4 r0 +#define x3 r1 +#define x2 r4 +#define x1 r6 +#define y4 r9 +#define y3 r7 +#define y2 r10 +#define y1 r8 +#define z4 r2 +#define z3 r3 +#define z2 r5 +#define z1 r11 +#define tmp r12 + + stmdb r13!, {r0, r1, r4, r9, r10, r12} + mov x4,r2,lsr#16 + bic x3,r2,x4,lsl#16 + mov x2,r3,lsr#16 + bic x1,r3,x2,lsl#16 + mov y4,r7,lsr#16 + bic y3,r7,y4,lsl#16 + mov y2,r8,lsr#16 + bic y1,r8,y2,lsl#16 + mul z1,x1,y1 + mul tmp,x1,y2 + mov z2,#0 + adds z1,z1,tmp,lsl#16 + adc z2,z2,tmp,lsr#16 + mul tmp,x2,y1 + adds z1,z1,tmp,lsl#16 + adcs z2,z2,tmp,lsr#16 + mul tmp,x1,y4 + mov z3,#0 + adds z2,z2,tmp,lsl#16 + adc z3,z3,tmp,lsr#16 + mul tmp,x2,y3 + adds z2,z2,tmp,lsl#16 + adc z3,z3,tmp,lsr#16 + mul tmp,x3,y2 + adds z2,z2,tmp,lsl#16 + adc z3,z3,tmp,lsr#16 + mul tmp,x4,y1 + adds z2,z2,tmp,lsl#16 + adc z3,z3,tmp,lsr#16 + mul tmp,x3,y4 + mul z4,x4,y4 + adds z3,z3,tmp,lsl#16 + adc z4,z4,tmp,lsr#16 + mul tmp,x4,y3 + adds z3,z3,tmp,lsl#16 + adc z4,z4,tmp,lsr#16 + mul tmp,x1,y3 + adds z2,z2,tmp + mul tmp,x2,y4 + adcs z3,z3,tmp + mul tmp,x2,y2 + adc z4,z4,#0 + adds z2,z2,tmp + mul tmp,x3,y3 + adcs z3,z3,tmp + mul tmp,x3,y1 + adc z4,z4,#0 + adds z2,z2,tmp + teq z1,#0 + orrne z2,z2,#1 // z1 must not be lost for rounding + mul tmp,x4,y2 + adcs z3,z3,tmp + adcs z4,z4,#0 + ldmia r13!, {r0, r1, r4, r9, r10, r12} +#else + +#define x32 r2 +#define x10 r3 +#define y32 r7 +#define y10 r8 +#define z3 r0 +#define z2 r1 +#define z1 r4 +#define z0 r6 +#define v1 r9 +#define v0 r11 +#define tmp r5 + + stmdb r13!,{r0,r1,r4,r9} + + mov z3,x32,lsr#16 + bic z2,x32,z3,lsl#16 + movs v1,y32,lsr#16 + bic v0,y32,v1,lsl#16 + + mul tmp,z3,v0 + mul z3,v1,z3 + mulne v1,z2,v1 + mul z2,v0,z2 + adds z2,z2,tmp,lsl#16 + adc z3,z3,tmp,lsr#16 + adds z2,z2,v1,lsl#16 + adc z3,z3,v1,lsr#16 + + mov z1,x10,lsr#16 + bic z0,x10,z1,lsl#16 + movs v1,y10,lsr#16 + bic v0,y10,v1,lsl#16 + + mul tmp,z1,v0 + mul z1,v1,z1 + mulne v1,z0,v1 + mul z0,v0,z0 + adds z0,z0,tmp,lsl#16 + adc z1,z1,tmp,lsr#16 + adds z0,z0,v1,lsl#16 + adc z1,z1,v1,lsr#16 + + adds z2,z2,z1 // z3 is max. 0xfffffffe + adc z3,z3,#0 // so this trick is possible + adds z1,z2,z0 // to save one addition + adcs z2,z2,z3 + adc z3,z3,#0 + + subs x10,x32,x10 + mov v0,#0 + mov v1,v0,rrx + + sublo v0,y32,y10 + subnes y10,y10,y32 + + orreq v1,v1,#1<<31 + eorcs v1,v1,#1<<31 + subcc v0,v0,x10 + + movs x32,x10,lsr#16 + bic x10,x10,x32,lsl#16 + mov y32,y10,lsr#16 + bic y10,y10,y32,lsl#16 + + mul tmp,x10,y10 + mla v0,x32,y32,v0 + mulne x32,y10,x32 + adds tmp,tmp,x32,lsl#16 + adc v0,v0,x32,lsr#16 + mul y32,x10,y32 + adds tmp,tmp,y32,lsl#16 + adc v0,v0,y32,lsr#16 + adds r5,z1,tmp + adcs r3,z2,v0 + adc r2,z3,v1,asr#31 + + teq z0,#0 + orrne r5,r5,#1 // z0 must not be lost for rounding + cmp r2,#0 + + ldmia r13!,{r0,r1,r4,r9} +#endif + + bpl CPDO_muf_norm + add r4,r4,#1 + mov pc,r14 + +CPDO_muf_norm: + adds r5,r5,r5 + adcs r3,r3,r3 + adc r2,r2,r2 + mov pc,r14 + +CPDO_muf_extra: + cmp r4,#0x7fffffff + beq CPDO_muf_1st_infnan +CPDO_muf_2nd_infnan: + orrs r5,r8,r7,lsl#1 // ignore MSB + bne CPDO_muf_2nd_nan + cmp r4,#0x80000000 + beq CPDO_muf_generate_qnan + mov r2,r7 // copy MSB + mov r3,#0 + mov r4,#0x7fffffff + eor r1,r1,r6 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_muf_1st_infnan: + cmp r11,#0x7fffffff + beq CPDO_muf_both_infnan + orrs r5,r3,r2,lsl#1 // ignore MSB + bne CPDO_muf_1st_nan + cmp r11,#0x80000000 + beq CPDO_muf_generate_qnan +// mov r4,#0x7fffffff + eor r1,r1,r6 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_muf_both_infnan: + orrs r5,r3,r2,lsl#1 // ignore MSB + beq CPDO_muf_both_infnan_1st_inf + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_muf_both_infnan_2nd_inf + tst r2,#0x40000000 + tstne r7,#0x40000000 + beq CPDO_muf_generate_qnan + mov pc,r14 + +CPDO_muf_both_infnan_1st_inf: + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_muf_both_inf + b CPDO_muf_2nd_nan + +CPDO_muf_both_infnan_2nd_inf: + b CPDO_muf_1st_nan + +CPDO_muf_both_inf: + eor r1,r1,r6 + orr r2,r2,r7 // copy both MSB + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_muf_zero: + mov r2,#0 + mov r3,#0 + mov r4,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_muf_1st_nan: + tst r2,#0x40000000 + beq CPDO_muf_generate_qnan + mov pc,r14 + +CPDO_muf_2nd_nan: + tst r7,#0x40000000 + beq CPDO_muf_generate_qnan + mov r1,r6 + mov r2,r7 + mov r3,r8 + mov r4,r11 + mov pc,r14 + +CPDO_muf_generate_qnan: + mov r1,#0x80000000 + mov r2,#0x7fffffff + mov r3,#0xffffffff + mov r4,#0x7fffffff + ldr r5,[r10,#128] + orr r5,r5,#1 + str r5,[r10,#128] + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_muf_M +CPDO_muf_M: + ldmia r2,{r6,r7,r8,r11} + ldmia r1,{r1,r2,r3,r4} + + cmp r11,#0x7fffffff + cmpne r4,#0x7fffffff + beq CPDO_muf_extra + eor r1,r1,r6 // sign + cmp r11,#0x80000000 + cmpne r4,#0x80000000 + beq CPDO_muf_zero + + add r4,r4,r11 // exponent +#if 0 + umull r11,r5,r3,r8 // r5|r11 = lo1*lo2 + teq r11,#0 + orrne r5,r5,#0x00000001 // r11 must not be lost for rounding + umull r11,r6,r8,r2 // r6|r11 = lo2*hi1 + umull r8,r2,r7,r2 // r2|r8 = hi1*hi2 + umull r12,r3,r7,r3 // r3|r12 = lo1*hi2 + adds r5,r5,r12 + adcs r3,r3,r6 + adc r2,r2,#0 + adds r5,r5,r11 + adcs r3,r3,r8 + adcs r2,r2,#0 +#else + umull r12,r11,r2,r7 + umull r2,r6,r8,r2 + umull r8,r5,r3,r8 + adds r5,r5,r2 + adcs r12,r12,r6 + adc r11,r11,#0 + umull r7,r6,r3,r7 + adds r5,r5,r7 + adcs r3,r12,r6 + adc r2,r11,#0 + teq r8,#0 + orrne r5,r5,#1 // r8 must not be lost for rounding + cmp r2,#0 +#endif + bpl CPDO_muf_norm + add r4,r4,#1 + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + +CPDO_infnan_1: + stmia r0,{r1,r3,r5,r7} + b fastfpe_next + +CPDO_infnan_2: + stmia r0,{r2,r4,r6,r8} + b fastfpe_next + +CPDO_nan_12: + orr r2,r3,r4 + b CPDO_inf_1 + +CPDO_nan: + mov r2,#0x40000000 @ create non signalling NaN + b CPDO_inf_1 + +CPDO_inf: + mov r2,#0 +CPDO_inf_1: + mov r3,#0 + mov r4,#0x7fffffff +CPDO_store_1234: + stmia r0,{r1,r2,r3,r4} + b fastfpe_next + +CPDO_zero: + mov r1,#0 +CPDO_zero_1: + mov r2,#0 + mov r3,#0 + mov r4,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next + +CPDO_muf_end: + cmp r8,#0x20000000 + bge CPDO_inf + cmp r8,#0xe0000000 + ble CPDO_zero_1 + stmia r0,{r1,r2,r7,r8} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_dvf +CPDO_dvf: + ldmia r2,{r6,r7,r8,r11} + ldmia r1,{r1,r2,r3,r4} + +CPDO_dvf_l: + cmp r11,#0x7fffffff + cmpne r4,#0x7fffffff + beq CPDO_dvf_infnan + eor r1,r1,r6 + cmp r11,#0x80000000 + cmpne r4,#0x80000000 + beq CPDO_dvf_zero + + sub r4,r4,r11 + +#define x4 r11 +#define x3 r7 +#define x2 r12 +#define x1 r8 +#define y2 r14 +#define y1 r9 +#define z3 r4 +#define z2 r5 +#define z1 r6 +#define tmp r10 + + cmp r2,r7 + cmpeq r3,r8 + bcs CPDO_dvf_no_normalize + + sub r4,r4,#1 + stmdb r13!,{r1,r4,r9,r10,r11,r14} + mov r4,r2,lsr#31 + mov r5,r2,lsl#1 + orr r5,r5,r3,lsr#31 + mov r6,r3,lsl#1 // dividend + b CPDO_dvf_normalize_back + +CPDO_dvf_no_normalize: + stmdb r13!,{r1,r4,r9,r10,r11,r14} + mov r4,#0 + mov r5,r2 + mov r6,r3 // dividend + +CPDO_dvf_normalize_back: + mov r1,#0 + sub r10,r1,r7,lsr#1 + mov r11,#0x40000000 + + .macro inv_step + adds r11,r10,r11,lsl#1 + subcc r11,r11,r10 + adc r1,r1,r1 + .endm + + .rept 17 + inv_step + .endr + + mov r1,r1,lsl#15 + adds r1,r1,#1<<15 + movcs r1,#0xffffffff // inverse + mov r1,r1,lsr#16 + + mov r2,#0 + mov r3,#0 // clear result space + + mov x4,r7,lsr#16 + bic x3,r7,x4,lsl#16 + mov x2,r8,lsr#16 + bic x1,r8,x2,lsl#16 // split divisor for 16x16=32bit mul + +CPDO_dvf_loop_entry: + mov r4,r4,lsl#16 + orrs r4,r4,r5,lsr#16 + mov r5,r5,lsl#16 + orr r5,r5,r6,lsr#16 + mov r6,r6,lsl#16 // shift dividend left by 16 + + bmi CPDO_dvf_loop_negative + mov r10,r4,lsr#16 + mul r9,r10,r1 + bic r10,r4,r10,lsl#16 + mul r10,r1,r10 + add r9,r9,r10,lsr#16 //estimate 16 bits of result in r9 + + mov r2,r2,lsl#16 + orr r2,r2,r3,lsr#16 + adds r3,r9,r3,lsl#16 // shift result left by 16 and + adc r2,r2,#0 // add in new result bits + + mov r9,r9,lsl#1 + mov y2,r9,lsr#16 + bic y1,r9,y2,lsl#16 + mul tmp,x1,y1 + subs z1,z1,tmp + mul tmp,x3,y1 + sbcs z2,z2,tmp + mul tmp,x4,y2 + sbc z3,z3,tmp + mul tmp,x2,y2 + subs z2,z2,tmp + sbc z3,z3,#0 + mul tmp,x2,y1 + subs z1,z1,tmp,lsl#16 + sbcs z2,z2,tmp,lsr#16 + sbc z3,z3,#0 + mul tmp,x1,y2 + subs z1,z1,tmp,lsl#16 + sbcs z2,z2,tmp,lsr#16 + sbc z3,z3,#0 + mul tmp,x4,y1 + subs z2,z2,tmp,lsl#16 + sbc z3,z3,tmp,lsr#16 + mul tmp,x3,y2 + subs z2,z2,tmp,lsl#16 + sbc z3,z3,tmp,lsr#16 // subtract divisor * estimated result + + tst r2,#0xff000000 + beq CPDO_dvf_loop_entry + + b CPDO_dvf_end_entry + +CPDO_dvf_loop_negative: + rsb r14,r4,#0 + mov r10,r14,lsr#16 + mul r9,r10,r1 + bic r10,r14,r10,lsl#16 + mul r10,r1,r10 + add r9,r9,r10,lsr#16 // estimate 16 bits of result in r9 + + mov r2,r2,lsl#16 + orr r2,r2,r3,lsr#16 + rsbs r3,r9,r3,lsl#16 // shift result left by 16 and + sbc r2,r2,#0 // add in new result bits + + mov r9,r9,lsl#1 + mov y2,r9,lsr#16 + bic y1,r9,y2,lsl#16 + mul tmp,x1,y1 + adds z1,z1,tmp + mul tmp,x3,y1 + adcs z2,z2,tmp + mul tmp,x4,y2 + adc z3,z3,tmp + mul tmp,x2,y2 + adds z2,z2,tmp + adc z3,z3,#0 + mul tmp,x2,y1 + adds z1,z1,tmp,lsl#16 + adcs z2,z2,tmp,lsr#16 + adc z3,z3,#0 + mul tmp,x1,y2 + adds z1,z1,tmp,lsl#16 + adcs z2,z2,tmp,lsr#16 + adc z3,z3,#0 + mul tmp,x4,y1 + adds z2,z2,tmp,lsl#16 + adc z3,z3,tmp,lsr#16 + mul tmp,x3,y2 + adds z2,z2,tmp,lsl#16 + adc z3,z3,tmp,lsr#16 // subtract divisor * estimated result + + tst r2,#0xff000000 + beq CPDO_dvf_loop_entry + +CPDO_dvf_end_entry: + movs r4,r4,asr#1 + movs r5,r5,rrx // remainder was shifted left by 1 + movs r6,r6,rrx // relative to divisor + + orr r7,x3,x4,lsl#16 + orr r8,x1,x2,lsl#16 // put the split divisor together again + + cmp r4,#0 + blt CPDO_dvf_end_negative + cmpeq r5,r7 + cmpeq r6,r8 + bcc CPDO_dvf_end + +CPDO_dvf_end_positive: + adds r3,r3,#1 + adc r2,r2,#0 + + subs r6,r6,r8 + sbcs r5,r5,r7 + sbcs r4,r4,#0 + bne CPDO_dvf_end_positive + + cmp r5,r7 + cmpeq r6,r8 + bcs CPDO_dvf_end_positive + b CPDO_dvf_end + +CPDO_dvf_end_negative: + subs r3,r3,#1 + sbc r2,r2,#0 + + adds r6,r6,r8 + adcs r5,r5,r7 + adcs r4,r4,#0 + bmi CPDO_dvf_end_negative + +CPDO_dvf_end: + orrs r9,r5,r6 + ldmia r13!,{r1,r4,r9,r10,r11,r14} + moveq pc,r14 + + adds r6,r6,r6 + adcs r5,r5,r5 + movcs r5,#0xc0000000 + movcs pc,r14 + + cmp r5,r7 + cmpeq r6,r8 + movcc r5,#0x40000000 + moveq r5,#0x80000000 + movhi r5,#0xc0000000 + mov pc,r14 + +CPDO_dvf_zero: + cmp r11,#0x80000000 + beq CPDO_dvf_by_zero + + stmia r0,{r1,r2,r3,r4} + b fastfpe_next // 0 already there +@ mov pc,r14 + +CPDO_dvf_by_zero: + cmp r4,#0x80000000 + beq CPDO_dvf_generate_qnan // first 0 too + + mov r2,#0x80000000 // set MSB + mov r3,#0 + mov r4,#0x7fffffff + ldr r5,[r10,#128] + orr r5,r5,#2 // division by zero + str r5,[r10,#128] + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_dvf_infnan: + cmp r4,#0x7fffffff + beq CPDO_dvf_1st_infnan + + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_dvf_2nd_inf + mov r1,r6 + mov r2,r7 + mov r3,r8 + mov r4,r11 + b CPDO_dvf_1st_or_2nd_nan + +CPDO_dvf_2nd_inf: + eor r1,r1,r6 + mov r2,#0 + mov r3,#0 + mov r4,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next // zero created +@ mov pc,r14 + +CPDO_dvf_1st_infnan: + cmp r11,#0x7fffffff + beq CPDO_dvf_both_infnan + + orrs r5,r3,r2,lsl#1 // 1st inf? ignore MSB + bne CPDO_dvf_1st_or_2nd_nan + + eor r1,r1,r6 // sign for inf + stmia r0,{r1,r2,r3,r4} + b fastfpe_next // inf already there +@ mov pc,r14 + +CPDO_dvf_1st_or_2nd_nan: + tst r2,#0x40000000 + beq CPDO_dvf_generate_qnan + mov pc,r14 // qnan1/2 already/copied there + +CPDO_dvf_both_infnan: + orrs r5,r3,r2,lsl#1 // ignore MSB + beq CPDO_dvf_both_infnan_1st_inf + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_dvf_both_infnan_2nd_inf + tst r2,#0x40000000 + tstne r7,#0x40000000 + beq CPDO_dvf_generate_qnan + mov pc,r14 + +CPDO_dvf_both_infnan_1st_inf: + tst r7,#0x40000000 // 2nd inf or SNaN ? + beq CPDO_dvf_generate_qnan + mov r1,r6 + mov r2,r7 + mov r3,r8 + mov r4,r11 // copy 2nd QNaN + mov pc,r14 + +CPDO_dvf_both_infnan_2nd_inf: + tst r2,#0x40000000 // 1st SNaN ? + beq CPDO_dvf_generate_qnan + mov pc,r14 + +CPDO_dvf_generate_qnan: + mov r1,#0x80000000 + mov r2,#0x7fffffff + mov r3,#0xffffffff + mov r4,#0x7fffffff + ldr r5,[r10,#128] + orr r5,r5,#1 + str r5,[r10,#128] + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_dvf_M +CPDO_dvf_M: + ldmia r2,{r6,r7,r8,r11} + ldmia r1,{r1,r2,r3,r4} + +CPDO_dvf_M_l: + cmp r11,#0x7fffffff + cmpne r4,#0x7fffffff + beq CPDO_dvf_infnan + eor r1,r1,r6 + cmp r11,#0x80000000 + cmpne r4,#0x80000000 + beq CPDO_dvf_zero + + sub r4,r4,r11 + + cmp r2,r7 + cmpeq r3,r8 + bcs CPDO_dvf_M_no_normalize + + sub r4,r4,#1 + stmdb r13!,{r1,r4,r9,r10} + mov r4,r2,lsr#31 + mov r5,r2,lsl#1 + orr r5,r5,r3,lsr#31 + mov r6,r3,lsl#1 // dividend + b CPDO_dvf_M_normalize_back + +CPDO_dvf_M_no_normalize: + stmdb r13!,{r1,r4,r9,r10} + mov r4,#0 + mov r5,r2 + mov r6,r3 // dividend + +CPDO_dvf_M_normalize_back: + mov r1,#0 + sub r10,r1,r7,lsr#1 + mov r11,#0x40000000 + + .macro inv_step + adds r11,r10,r11,lsl#1 + subcc r11,r11,r10 + adc r1,r1,r1 + .endm + + .rept 18 + inv_step + .endr + + mov r1,r1,lsl#14 + adds r1,r1,#1<<15 + movcs r1,#0xffffffff // inverse + + mov r2,#0 + mov r3,#0 // clear result space + +CPDO_dvf_M_loop_entry: + mov r4,r4,lsl#16 + orrs r4,r4,r5,lsr#16 + mov r5,r5,lsl#16 + orr r5,r5,r6,lsr#16 + mov r6,r6,lsl#16 // shift dividend left by 16 + + bmi CPDO_dvf_M_loop_negative + umull r10,r9,r4,r1 // estimate 16 bits of result in r9 + + mov r2,r2,lsl#16 + orr r2,r2,r3,lsr#16 + adds r3,r9,r3,lsl#16 // shift result left by 16 and + adc r2,r2,#0 // add in new result bits + + mov r9,r9,lsl#1 + umull r11,r10,r8,r9 // divisor lo * estimated result + subs r6,r6,r11 + sbcs r5,r5,r10 + sbc r4,r4,#0 + + umull r11,r10,r7,r9 // divisor hi * estimated result + subs r5,r5,r11 + sbc r4,r4,r10 + + tst r2,#0xff000000 + beq CPDO_dvf_M_loop_entry + + b CPDO_dvf_M_end_entry + +CPDO_dvf_M_loop_negative: + rsb r11,r4,#0 + umull r10,r9,r11,r1 // estimate 16 bits of result in r9 + + mov r2,r2,lsl#16 + orr r2,r2,r3,lsr#16 + rsbs r3,r9,r3,lsl#16 // shift result left by 16 and + sbc r2,r2,#0 // add in new result bits + + mov r9,r9,lsl#1 + umull r11,r10,r8,r9 // divisor lo * estimated result + adds r6,r6,r11 + adcs r5,r5,r10 + adc r4,r4,#0 + + umlal r5,r4,r7,r9 // divisor hi * estimated result + + tst r2,#0xff000000 + beq CPDO_dvf_M_loop_entry + +CPDO_dvf_M_end_entry: + movs r4,r4,asr#1 + movs r5,r5,rrx // remainder was shifted left by 1 + movs r6,r6,rrx // relative to divisor + + cmp r4,#0 + blt CPDO_dvf_M_end_negative + cmpeq r5,r7 + cmpeq r6,r8 + bcc CPDO_dvf_M_end + +CPDO_dvf_M_end_positive: + adds r3,r3,#1 + adc r2,r2,#0 + + subs r6,r6,r8 + sbcs r5,r5,r7 + sbcs r4,r4,#0 + + cmp r5,r7 + cmpeq r6,r8 + bcs CPDO_dvf_M_end_positive + b CPDO_dvf_M_end + +CPDO_dvf_M_end_negative: + subs r3,r3,#1 + sbc r2,r2,#0 + + adds r6,r6,r8 + adcs r5,r5,r7 + adcs r4,r4,#0 + bmi CPDO_dvf_M_end_negative + +CPDO_dvf_M_end: + orrs r9,r5,r6 + ldmia r13!,{r1,r4,r9,r10} + moveq pc,r14 + + adds r6,r6,r6 + adcs r5,r5,r5 + movcs r5,#0xc0000000 + movcs pc,r14 + + cmp r5,r7 + cmpeq r6,r8 + movcc r5,#0x40000000 + moveq r5,#0x80000000 + movhi r5,#0xc0000000 + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rdf +CPDO_rdf: + ldmia r1,{r6,r7,r8,r11} + ldmia r2,{r1,r2,r3,r4} + b CPDO_dvf_l + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rdf_M +CPDO_rdf_M: + ldmia r1,{r6,r7,r8,r11} + ldmia r2,{r1,r2,r3,r4} + b CPDO_dvf_M_l + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rmf +CPDO_rmf: + ldmia r2,{r6,r7,r8,r11} + ldmia r1,{r1,r2,r3,r4} + + cmp r11,#0x7fffffff + cmpne r4,#0x7fffffff + beq CPDO_rmf_infnan + cmp r11,#0x80000000 + cmpne r4,#0x80000000 + beq CPDO_rmf_zero + + cmp r4,r11 + bge CPDO_rmf_loop_entry + b CPDO_rmf_smaller + +CPDO_rmf_loop_0: + mov r5,#0 +CPDO_rmf_loop: + cmp r4,r11 + ble CPDO_rmf_loop_end + + sub r4,r4,#1 + + adds r3,r3,r3 + adcs r2,r2,r2 + bcs CPDO_rmf_loop_anyway + +CPDO_rmf_loop_entry: + cmp r2,r7 + cmpeq r3,r8 + bcc CPDO_rmf_loop_0 + +CPDO_rmf_loop_anyway: + subs r3,r3,r8 + sbc r2,r2,r7 + mov r5,#1 + b CPDO_rmf_loop + +CPDO_rmf_loop_end: + teq r2,#0 + teqeq r3,#0 + beq CPDO_rmf_created_zero + + //eor r1,r1,r6 // only if result not zero + + mov r6,r2,lsr#31 + mov r11,r2,lsl#1 + orr r11,r11,r3,lsr#31 + + cmp r6,#0 + cmpeq r11,r7 + rsbeqs r6,r8,r3,lsl#1 + cmpeq r5,#1 // for nearest-even + bcc CPDO_rmf_norm + + eor r1,r1,#0x80000000 + subs r3,r8,r3 + sbc r2,r7,r2 + +CPDO_rmf_norm: + teq r2,#0 // normalize 32 bit + moveq r2,r3 + moveq r3,#0 + subeq r4,r4,#32 + + cmp r2,#0x00010000 // normalize 16 bit + movcc r2,r2,lsl#16 + orrcc r2,r2,r3,lsr#16 + movcc r3,r3,lsl#16 + subcc r4,r4,#16 + + cmp r2,#0x01000000 // normalize 8 bit + movcc r2,r2,lsl#8 + orrcc r2,r2,r3,lsr#24 + movcc r3,r3,lsl#8 + subcc r4,r4,#8 + + cmp r2,#0x10000000 // normalize 4 bit + movcc r2,r2,lsl#4 + orrcc r2,r2,r3,lsr#28 + movcc r3,r3,lsl#4 + subcc r4,r4,#4 + + cmp r2,#0x40000000 // normalize 2 bit + movcc r2,r2,lsl#2 + orrcc r2,r2,r3,lsr#30 + movcc r3,r3,lsl#2 + subcc r4,r4,#2 + + cmp r2,#0x80000000 // normalize 1 bit + movcc r2,r2,lsl#1 + orrcc r2,r2,r3,lsr#31 + movcc r3,r3,lsl#1 + subcc r4,r4,#1 + + mov r5,#0 + mov pc,r14 + +CPDO_rmf_created_zero: + mov r4,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_rmf_smaller: + add r5,r4,#1 + cmp r5,r11 + blt CPDO_rmf_norm + cmp r2,r7 + cmpeq r3,r8 + bls CPDO_rmf_norm + + eor r1,r1,#0x80000000 + adds r8,r8,r8 + adc r7,r7,r7 + subs r3,r8,r3 + sbc r2,r7,r2 + b CPDO_rmf_norm + +CPDO_rmf_zero: + cmp r11,#0x80000000 + beq CPDO_rmf_generate_qnan + stmia r0,{r1,r2,r3,r4} + b fastfpe_next +@ mov pc,r14 + +CPDO_rmf_infnan: + cmp r4,#0x7fffffff + beq CPDO_rmf_1st_infnan + + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_rmf_2nd_inf + mov r1,r6 + mov r2,r7 + mov r3,r8 + mov r4,r11 + b CPDO_rmf_1st_or_2nd_nan + +CPDO_rmf_2nd_inf: + mov pc,r14 // result = 1st operand + +CPDO_rmf_1st_infnan: + cmp r11,#0x7fffffff + beq CPDO_rmf_both_infnan + + orrs r5,r3,r2,lsl#1 // 1st inf? + bne CPDO_rmf_1st_or_2nd_nan + + b CPDO_rmf_generate_qnan + +CPDO_rmf_1st_or_2nd_nan: + tst r2,#0x40000000 + beq CPDO_rmf_generate_qnan + mov pc,r14 // qnan1/2 already/copied there + +CPDO_rmf_both_infnan: + orrs r5,r3,r2,lsl#1 // ignore MSB + beq CPDO_rmf_both_infnan_1st_inf + orrs r5,r8,r7,lsl#1 // ignore MSB + beq CPDO_rmf_both_infnan_2nd_inf + tst r2,#0x40000000 + tstne r7,#0x40000000 + beq CPDO_rmf_generate_qnan + mov pc,r14 + +CPDO_rmf_both_infnan_1st_inf: + tst r7,#0x40000000 // 2nd inf or SNaN ? + beq CPDO_rmf_generate_qnan + mov r1,r6 + mov r2,r7 + mov r3,r8 + mov r4,r11 // copy 2nd QNaN + mov pc,r14 + +CPDO_rmf_both_infnan_2nd_inf: + tst r2,#0x40000000 // 1st SNaN ? + beq CPDO_rmf_generate_qnan + mov pc,r14 + +CPDO_rmf_generate_qnan: + mov r1,#0x80000000 + mov r2,#0x7fffffff + mov r3,#0xffffffff + mov r4,#0x7fffffff + ldr r5,[r10,#128] + orr r5,r5,#1 + str r5,[r10,#128] + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_mvf +CPDO_mvf: + ldmia r2,{r1,r2,r3,r4} + mov r5,#0 + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_mnf +CPDO_mnf: + ldmia r2,{r1,r2,r3,r4} + eor r1,r1,#0x80000000 + mov r5,#0 + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_abs +CPDO_abs: + ldmia r2,{r1,r2,r3,r4} + bic r1,r1,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_sqt +CPDO_sqt: + ldmia r2,{r1,r2,r3,r4} + cmp r1,#0 + bne CPDO_nan + cmp r4,#0x7fffffff + beq CPDO_store_1234 + + tst r4,r4,lsr#1 @carry=exponent bit 0 + bcc CPDO_sqt_exponenteven + adds r3,r3,r3 + adc r2,r2,r2 + cmp r2,#0x20000000 @set carry for loop +CPDO_sqt_exponenteven: + mov r4,r4,asr #1 + str r4,[r0,#12] + + mov r4,#0x80000000 + mov r5,#0 + sub r2,r2,#0x80000000 + + mov r8,#0x40000000 + mov r14,#0x80000000 + + mov r1,#1 + b CPDO_sqt_loop1_first +CPDO_sqt_loop1: + adds r3,r3,r3 + adcs r2,r2,r2 +CPDO_sqt_loop1_first: + add r6,r4,r8,lsr r1 @r7 const = r5 + bcs CPDO_sqt_loop1_1 + cmp r2,r6 + cmpeq r3,r5 @r5 for r7 + bcc CPDO_sqt_loop1_0 +CPDO_sqt_loop1_1: + orr r4,r4,r14,lsr r1 + subs r3,r3,r5 @r5 for r7 + sbc r2,r2,r6 +CPDO_sqt_loop1_0: + add r1,r1,#1 + cmp r1,#30 + ble CPDO_sqt_loop1 + + adds r3,r3,r3 + adcs r2,r2,r2 + bcs CPDO_sqt_between_1 + adds r7,r5,#0x80000000 + adc r6,r4,#0 + cmp r2,r6 + cmpeq r3,r7 + bcc CPDO_sqt_between_0 +CPDO_sqt_between_1: + orr r4,r4,#0x00000001 + subs r3,r3,r5 + sbc r2,r2,r4 + subs r3,r3,#0x80000000 + sbc r2,r2,#0 +CPDO_sqt_between_0: + mov r1,#0 + +CPDO_sqt_loop2: + adds r3,r3,r3 + adcs r2,r2,r2 + bcs CPDO_sqt_loop2_1 + adds r7,r5,r8,lsr r1 + adc r6,r4,#0 + cmp r2,r6 + cmpeq r3,r7 + bcc CPDO_sqt_loop2_0 +CPDO_sqt_loop2_1: + orr r5,r5,r14,lsr r1 + subs r3,r3,r5 + sbc r2,r2,r4 + subs r3,r3,r8,lsr r1 + sbc r2,r2,#0 +CPDO_sqt_loop2_0: + add r1,r1,#1 + cmp r1,#30 + ble CPDO_sqt_loop2 + + adds r3,r3,r3 + adcs r2,r2,r2 + bcs CPDO_sqt_after_1 + cmp r2,r6 + cmpeq r3,r7 + bcc CPDO_sqt_after_0 +CPDO_sqt_after_1: + orr r5,r5,#0x00000001 +CPDO_sqt_after_0: + + mov r1,#0 + stmia r0,{r1,r4,r5} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rnd +CPDO_rnd: + ldmia r2,{r1,r2,r3,r5} + bl CPDO_rnd_core + ldr r6,[r10,#128] + stmia r0,{r1,r2,r3,r5} + orr r6,r6,r4 + str r6,[r10,#128] + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rnd_core +CPDO_rnd_core: + and r6,r4,#0x00000060 + mov r4,#0 // for return of exception flags + cmp r5,#63 + bge CPDO_rnd_big + add pc,pc,r6,lsr#3 + mov r0,r0 + b CPDO_rnd_NE + b CPDO_rnd_P + b CPDO_rnd_M + b CPDO_rnd_Z + +CPDO_rnd_NE: + cmp r5,#0 + blt CPDO_rnd_NE_01 + + subs r6,r5,#31 + bpl CPDO_rnd_NE_2 + mov r7,#0x40000000 + mov r8,#0x7fffffff + mov r7,r7,lsr r5 + mov r8,r8,lsr r5 + teq r3,#0 + tsteq r2,r8 + orrne r4,r4,#16 // set inexact flag + adds r2,r2,r7 + bcs CPDO_rnd_overflow + teq r3,#0 + tsteq r2,r8 + beq CPDO_rnd_NE_equal + mov r3,#0 + bic r2,r2,r8 + mov pc,r14 + +CPDO_rnd_NE_2: + mov r7,#0x80000000 + mov r8,#0xffffffff + mov r7,r7,lsr r6 + mov r8,r8,lsr r6 + tst r3,r8 + orrne r4,r4,#16 // set inexact flag + adds r3,r3,r7 + adcs r2,r2,#0 + bcs CPDO_rnd_overflow + tst r3,r8 + beq CPDO_rnd_NE_equal + bic r3,r3,r8 + mov pc,r14 + +CPDO_rnd_NE_equal: + mov r7,#0x80000000 + subs r6,r5,#32 + bicpl r3,r3,r7,lsr r6 + bicmi r2,r2,r7,lsr r5 + mov pc,r14 + +CPDO_rnd_NE_01: + cmp r5,#-1 + bne CPDO_rnd_0 + cmp r2,#0x80000000 + cmpeq r3,#0 + beq CPDO_rnd_0 + + mov r2,#0x80000000 + mov r3,#0 + mov r5,#0 + orr r4,r4,#16 // set inexact flag + mov pc,r14 + +CPDO_rnd_P: + teq r1,#0 + beq CPDO_rnd_NZ + b CPDO_rnd_Z + +CPDO_rnd_M: + teq r1,#0 + beq CPDO_rnd_Z + b CPDO_rnd_NZ + +CPDO_rnd_Z: + cmp r5,#0 // smaller than 1 will be 0 + blt CPDO_rnd_0 + + rsbs r6,r5,#31 + bmi CPDO_rnd_Z_2 + cmp r3,#0 + mov r3,#0 + mov r7,r2,lsr r6 + teqeq r2,r7,lsl r6 + mov r2,r7,lsl r6 + orrne r4,r4,#16 // set inexact flag + mov pc,r14 + +CPDO_rnd_Z_2: + rsb r6,r5,#63 + mov r7,r3,lsr r6 + teq r3,r7,lsl r6 + mov r3,r7,lsl r6 + orrne r4,r4,#16 // set inexact flag + mov pc,r14 + +CPDO_rnd_0: + cmp r5,#0x80000000 + moveq pc,r14 // already 0 -> ok + + mov r2,#0 + mov r3,#0 + mov r5,#0x80000000 + orr r4,r4,#16 // set inexact flag + mov pc,r14 + +CPDO_rnd_NZ: + cmp r5,#0 // smaller than 1 will be stay 0 or become 1 + blt CPDO_rnd_NZ_01 + + mov r7,#0x7fffffff + subs r6,r5,#32 + bpl CPDO_rnd_NZ_2 + mov r7,r7,lsr r5 + teq r3,#0 + tsteq r2,r7 + orrne r4,r4,#16 // set inexact flag + adds r3,r3,#0xffffffff + adcs r2,r2,r7 + bcs CPDO_rnd_overflow + mov r3,#0 + bic r2,r2,r7 + mov pc,r14 + +CPDO_rnd_NZ_2: + mov r7,r7,lsr r6 + tst r3,r7 + orrne r4,r4,#16 // set inexact flag + adds r3,r3,r7 + adcs r2,r2,#0 + bcs CPDO_rnd_overflow + bic r3,r3,r7 + mov pc,r14 + +CPDO_rnd_NZ_01: + cmp r5,#0x80000000 + moveq pc,r14 // already 0 -> ok + + mov r2,#0x80000000 + mov r3,#0 + mov r5,#0 + orr r4,r4,#16 // set inexact flag + mov pc,r14 + +CPDO_rnd_overflow: + mov r2,#0x80000000 + mov r3,#0 + add r5,r5,#1 + mov pc,r14 + +CPDO_rnd_big: + cmp r5,#0x7fffffff + movne pc,r14 // just big + orrs r6,r3,r2,lsl#1 // ignore MSB + moveq pc,r14 // infinity + tst r2,#0x40000000 // signalling NaN ? + orreq r4,r4,#1 // set invalid operation flag + orreq r2,r2,#0x40000000 // make quiet NaN + mov pc,r14 + +/*---------------------------------------------------------------------------*/ diff -uNr linux-2.4.37.9/arch/arm/fastfpe/CPDT.S linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/CPDT.S --- linux-2.4.37.9/arch/arm/fastfpe/CPDT.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/CPDT.S Wed May 26 15:43:59 2010 @@ -0,0 +1,396 @@ +/* +The FP structure has 4 words reserved for each register, the first is used just +for the sign in bit 31, the second and third are for the mantissa (unsigned +integer, high 32 bit first) and the fourth is the exponent (signed integer). +The mantissa is always normalized. + +If the exponent is 0x80000000, that is the most negative value, the number +represented is 0 and both mantissa words are also 0. + +If the exponent is 0x7fffffff, that is the biggest positive value, the number +represented is infinity if the mantissa is 0, otherwise it is a NaN. + +Decimal and packed decimal numbers are not supported yet. +*/ + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_load_single +CPDT_load_single: + ldr r1,[r6] + + and r2,r1,#0x80000000 @ r2 = sign + + mov r5,r1,lsr#23 + bics r5,r5,#0x100 + beq CPDT_ls_e0 @ exponent = 0; zero/denormalized + teq r5,#255 + beq CPDT_ls_e255 @ exponent = 255; infinity/NaN + + sub r5,r5,#127 @ r5 = exponent, remove normalized bias + + mov r3,r1,lsl#8 + orr r3,r3,#0x80000000 + mov r4,#0 @ r3,r4 = mantissa + + stmia r0,{r2-r5} + b fastfpe_next + +CPDT_ls_e0: + movs r3,r1,lsl#9 + beq CPDT_load_zero + + mov r5,#-127 + +CPDT_ls_e0_norm: + tst r3,#0x80000000 + subeq r5,r5,#1 + moveq r3,r3,lsl#1 + beq CPDT_ls_e0_norm + + mov r4,#0 + stmia r0,{r2-r5} + b fastfpe_next + +CPDT_ls_e255: + mov r3,r1,lsl#8 + bics r3,r3,#0x80000000 + orreq r3,r3,#0x80000000 // set MSB for inf + mov r4,#0 + mov r5,#0x7fffffff + stmia r0,{r2-r5} + b fastfpe_next + +CPDT_load_zero: + mov r3,#0 + mov r4,#0 + mov r5,#0x80000000 + stmia r0,{r2-r5} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_load_double +CPDT_load_double: + ldr r1,[r6] + ldr r6,[r6,#4] + + and r2,r1,#0x80000000 @ r2 = sign + + mov r5,r1,lsr#20 + bics r5,r5,#0x800 + beq CPDT_ld_e0 @ exponent = 0; zero/denormalized + add r4,r5,#1 + teq r4,#2048 + beq CPDT_ld_e2047 @ exponent = 2047; infinity/NaN + + add r5,r5,#1 + sub r5,r5,#1024 @ r5 = exponent, remove normalized bias + + mov r3,r1,lsl#11 + orr r3,r3,#0x80000000 + orr r3,r3,r6,lsr #21 + mov r4,r6,lsl#11 @ r3,r4 = mantissa + + stmia r0,{r2-r5} + b fastfpe_next + +CPDT_ld_e0: + mov r3,r1,lsl#12 + orr r3,r3,r6,lsr#20 + movs r4,r6,lsl#12 + teqeq r3,#0 + beq CPDT_load_zero + + mov r5,#1 + sub r5,r5,#1024 + +CPDT_ld_e0_norm: + tst r3,#0x80000000 + bne CPDT_ld_e0_norm_end + sub r5,r5,#1 + movs r4,r4,lsl#1 + adc r3,r3,r3 + b CPDT_ld_e0_norm +CPDT_ld_e0_norm_end: + stmia r0,{r2-r5} + b fastfpe_next + +CPDT_ld_e2047: + mov r3,r1,lsl#11 + orr r3,r3,r6,lsr #21 + bic r3,r3,#0x80000000 + mov r4,r6,lsl#11 @ r3,r4 = mantissa + orrs r5,r3,r4 + orreq r3,r3,#0x80000000 // set MSB fo inf + mov r5,#0x7fffffff + stmia r0,{r2-r5} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_load_extended +CPDT_load_extended: + ldr r1,[r6] + ldr r3,[r6,#4] + ldr r4,[r6,#8] + + and r2,r1,#0x8000 + mov r2,r2,lsl#16 + mov r5,r1,lsl#17 + movs r5,r5,lsr#17 + beq CPDT_le_e0 + add r1,r5,#1 + teq r1,#32768 + beq CPDT_le_e32767 + + add r5,r5,#1 + sub r5,r5,#16384 + + stmia r0,{r2-r5} + b fastfpe_next + +CPDT_le_e0: + teq r3,#0 + teqeq r4,#0 + beq CPDT_load_zero + + mov r5,#2 + sub r5,r5,#16384 + b CPDT_ld_e0_norm + +CPDT_le_e32767: + mov r5,#0x7fffffff + stmia r0,{r2-r5} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_load_decimal +CPDT_load_decimal: + + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_store_single +CPDT_store_single: + ldmia r0,{r1-r4} + + cmp r4,#-127 + ble CPDT_ss_e0 + cmp r4,#128 + bge CPDT_ss_e255 + + add r4,r4,#127 + orr r1,r1,r4,lsl#23 + + bic r2,r2,#0x80000000 + orr r1,r1,r2,lsr#8 + + str r1,[r6] + b fastfpe_next + +CPDT_ss_e0: + cmp r4,#-150 + ble CPDT_ss_zero + + add r4,r4,#126 + rsb r4,r4,#0 + mov r2,r2,lsr r4 + + orr r1,r1,r2,lsr#8 + +CPDT_ss_zero: + str r1,[r6] + b fastfpe_next + +CPDT_ss_e255: + orr r1,r1,#0x7f000000 + orr r1,r1,#0x00800000 + cmp r4,#0x7fffffff + movne r2,#0 + movne r3,#0 + bic r2,r2,#0x80000000 + orrs r4,r3,r2,lsl#24 // only bits not stored in single + bne CPDT_ss_nan_special // NaN must not become Inf +CPDT_ss_nan_back: + orr r1,r1,r2,lsr#8 + str r1,[r6] + b fastfpe_next + +CPDT_ss_nan_special: + cmp r2,#1<<8 + movlt r2,#1<<8 + b CPDT_ss_nan_back + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_store_double +CPDT_store_double: + ldmia r0,{r1-r4} + + cmp r4,#1024 @ this check has to be first, or + bge CPDT_sd_e2047 @ overflow can occur on second ! + add r0,r4,#3 + cmp r0,#-1023+3 @ cmp with -1023 + ble CPDT_sd_e0 + + sub r4,r4,#1 + add r4,r4,#1024 + orr r1,r1,r4,lsl#20 + + bic r2,r2,#0x80000000 + orr r1,r1,r2,lsr#11 + + mov r2,r2,lsl#21 + orr r2,r2,r3,lsr#11 + + stmia r6,{r1,r2} + b fastfpe_next + +CPDT_sd_e0: + add r0,r4,#1075-1024 + cmp r0,#-1024 + ble CPDT_sd_zero + + add r4,r4,#1024 + sub r4,r4,#2 +CPDT_sd_unnormalize: + movs r2,r2,lsr#1 + mov r3,r3,rrx + adds r4,r4,#1 + bne CPDT_sd_unnormalize + + orr r1,r1,r2,lsr#11 + mov r2,r2,lsl#21 + orr r2,r2,r3,lsr#11 + + stmia r6,{r1,r2} + b fastfpe_next + +CPDT_sd_zero: + mov r2,#0 + stmia r6,{r1,r2} + b fastfpe_next + +CPDT_sd_e2047: + orr r1,r1,#0x7f000000 + orr r1,r1,#0x00f00000 + cmp r4,#0x7fffffff + movne r2,#0 + movne r3,#0 + movs r5,r3,lsl#21 // only bits not stored in double ! + bne CPDT_sd_nan_special +CPDT_sd_nan_back: + orr r1,r1,r2,lsr#11 + mov r2,r2,lsl#21 + orr r2,r2,r3,lsr#11 + stmia r6,{r1,r2} + b fastfpe_next + +CPDT_sd_nan_special: + bics r2,r2,#0x80000000 + bne CPDT_sd_nan_back + cmp r3,#1<<11 + movlt r3,#1<<11 + b CPDT_sd_nan_back + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_store_extended +CPDT_store_extended: + ldmia r0,{r1-r4} + + cmp r4,#16384 @ this check has to be first, or + bge CPDT_se_e32767 @ overflow can occur with second ! + add r0,r4,#63 + cmp r0,#-16383+63 + ble CPDT_se_e0 + + sub r4,r4,#1 + add r4,r4,#16384 + orr r1,r4,r1,lsr#16 + + stmia r6,{r1-r3} + b fastfpe_next + +CPDT_se_e0: + add r0,r4,#16446-16384 + cmp r0,#-16384 + ble CPDT_se_zero + + add r4,r4,#16384 + sub r4,r4,#2 +CPDT_se_unnormalize: + movs r2,r2,lsr#1 + mov r3,r3,rrx + adds r4,r4,#1 + bne CPDT_se_unnormalize + + mov r1,r1,lsr#16 + stmia r6,{r1-r3} + b fastfpe_next + +CPDT_se_zero: + mov r1,r1,lsr#16 + mov r2,#0 + mov r3,#0 + stmia r6,{r1-r3} + b fastfpe_next + +CPDT_se_e32767: + cmp r4,#0x7fffffff + movne r2,#0 + movne r3,#0 + mov r1,r1,lsr#16 + orr r1,r1,#0x00007f00 + orr r1,r1,#0x000000ff + stmia r6,{r1-r3} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_store_decimal +CPDT_store_decimal: + + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_sfm +CPDT_sfm_loop: + add r0,r0,#1<<12 + and r0,r0,#7<<12 +CPDT_sfm: + add r7,r10,r0,lsr#8 + ldmia r7,{r2-r5} + bic r3,r3,#0x80000000 + orr r3,r3,r2 + stmia r6!,{r3-r5} + + subs r1,r1,#1 + bne CPDT_sfm_loop + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_lfm +CPDT_lfm_loop: + add r0,r0,#1<<12 + and r0,r0,#7<<12 +CPDT_lfm: + add r7,r10,r0,lsr#8 + ldmia r6!,{r3-r5} + and r2,r3,#0x80000000 + cmp r5,#0x80000000 // check if the number was 0 + cmpne r5,#0x7fffffff // or inf/NaN + biceq r3,r3,#0x80000000 // yes -> clear mantissa MSB + orrne r3,r3,#0x80000000 // no -> set mantissa MSB + stmia r7,{r2-r5} + + subs r1,r1,#1 + bne CPDT_lfm_loop + b fastfpe_next + +/*---------------------------------------------------------------------------*/ diff -uNr linux-2.4.37.9/arch/arm/fastfpe/CPRT.S linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/CPRT.S --- linux-2.4.37.9/arch/arm/fastfpe/CPRT.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/CPRT.S Wed May 26 15:43:59 2010 @@ -0,0 +1,220 @@ +/* +The FP structure has 4 words reserved for each register, the first is used just +for the sign in bit 31, the second and third are for the mantissa (unsigned +integer, high 32 bit first) and the fourth is the exponent (signed integer). +The mantissa is always normalized. + +If the exponent is 0x80000000, that is the most negative value, the number +represented is 0 and both mantissa words are also 0. + +If the exponent is 0x7fffffff, that is the biggest positive value, the number +represented is infinity if the mantissa is 0, otherwise it is a NaN. + +Decimal and packed decimal numbers are not supported yet. +*/ + +/*---------------------------------------------------------------------------*/ + + .text + .globl CPRT_flt +CPRT_flt: + add r0,r13,r0,lsr#10 + ldr r2,[r0] + mov r0,r1 + mov r3,#0 + cmp r2,#0 + beq CPRT_flt_zero + + ldr r6,=round_table + and r5,r4,#0x000000e0 + and r4,r4,#0x00080000 + orr r5,r5,r4,lsr#11 + ldr r6,[r6,r5,lsr#3] // address of rounding function + + ands r1,r2,#0x80000000 + rsbne r2,r2,#0 + mov r4,#31 + + cmp r2,#0x00010000 + movcc r2,r2,lsl#16 + subcc r4,r4,#16 + + cmp r2,#0x01000000 + movcc r2,r2,lsl#8 + subcc r4,r4,#8 + + cmp r2,#0x10000000 + movcc r2,r2,lsl#4 + subcc r4,r4,#4 + + cmp r2,#0x40000000 + movcc r2,r2,lsl#2 + subcc r4,r4,#2 + + cmp r2,#0x80000000 + movcc r2,r2,lsl#1 + subcc r4,r4,#1 + + mov r5,#0 + ldr r14,=fastfpe_next + mov pc,r6 + +CPRT_flt_zero: + mov r1,#0 + mov r4,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_fix +CPRT_fix: + ldmia r2,{r1,r2,r3,r5} + bl CPDO_rnd_core + + add r0,r13,r0,lsr#10 + cmp r5,#0 + blt CPRT_fix_zero + cmp r5,#30 + bgt CPRT_fix_overflow + +CPRT_fix_no_overflow: + rsb r5,r5,#31 + mov r2,r2,lsr r5 + tst r1,#0x80000000 + rsbne r2,r2,#0 +CPRT_fix_zero_back: + str r2,[r0] + ldr r1,[r10,#128] + orr r1,r1,r4 // set flags possibly caused by rounding + str r1,[r10,#128] + b fastfpe_next + +CPRT_fix_zero: + mov r2,#0 + b CPRT_fix_zero_back + +CPRT_fix_overflow: + cmp r1,#0x80000000 // -2^31 is not exactly an overflow ... + cmpeq r2,#0x80000000 + cmpeq r5,#31 + beq CPRT_fix_no_overflow + + mov r2,#0x80000000 + tst r1,#0x80000000 + subeq r2,r2,#1 + str r2,[r0] + + ldr r1,[r10,#128] + orr r1,r1,#1 // set invalid operation flag + str r1,[r10,#128] + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_wfs +CPRT_wfs: + ldr r0,[r13,r0,lsr#10] + str r0,[r10,#128] + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_rfs +CPRT_rfs: + ldr r1,[r10,#128] + bic r1,r1,#0xff000000 + orr r1,r1,#0x02000000 @ Software Emulation, not Acorn FPE + str r1,[r13,r0,lsr#10] + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_cmf +CPRT_cmf: + ldmia r1,{r1,r3,r5,r7} + ldmia r2,{r2,r4,r6,r8} + +CPRT_cmf_e: + ldr r0,[r13,#16*4] + bic r0,r0,#0xf0000000 + + cmp r7,#0x7fffffff + beq CPRT_cmf_nan1 +CPRT_cmf_nixnan1: + cmp r8,#0x7fffffff + beq CPRT_cmf_nan2 +CPRT_cmf_nixnan2: + + cmp r1,r2 + beq CPRT_cmf_equalsign + b CPRT_cmf_signx + +CPRT_cmf_nan1: + orrs r11,r5,r3,lsl#1 // ignore MSB + beq CPRT_cmf_nixnan1 + b CPRT_cmf_unordered + +CPRT_cmf_nan2: + orrs r11,r6,r4,lsl#1 // ignore MSB + beq CPRT_cmf_nixnan2 + b CPRT_cmf_unordered + +CPRT_cmf_equalsign: + cmp r7,r8 + beq CPRT_cmf_equalexponent + bgt CPRT_cmf_sign + b CPRT_cmf_signb + +CPRT_cmf_equalexponent: + cmp r3,r4 + cmpeq r5,r6 + beq CPRT_cmf_equal + bhi CPRT_cmf_sign + b CPRT_cmf_signb + +CPRT_cmf_signx: + teq r7,#0x80000000 + teqeq r8,#0x80000000 + beq CPRT_cmf_equal +CPRT_cmf_sign: + tst r1,#0x80000000 + orreq r0,r0,#0x20000000 // PSR carry + orrne r0,r0,#0x80000000 // PSR negative + str r0,[r13,#16*4] + b fastfpe_next + +CPRT_cmf_signb: + tst r1,#0x80000000 + orrne r0,r0,#0x20000000 // PSR carry + orreq r0,r0,#0x80000000 // PSR negative + str r0,[r13,#16*4] + b fastfpe_next + +CPRT_cmf_equal: + orr r0,r0,#0x60000000 // PSR carry, zero + str r0,[r13,#16*4] + b fastfpe_next + +CPRT_cmf_unordered: + ldr r1,[r10,#128] + orr r1,r1,#1 // set invalid operation flag + str r1,[r10,#128] + + tst r0,#1<<12 // FPSR AC bit set ? + orrne r0,r0,#0x20000000 // PSR carry + orr r0,r0,#0x10000000 // PSR overflow + str r0,[r13,#16*4] + + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_cnf +CPRT_cnf: + ldmia r1,{r1,r3,r5,r7} + ldmia r2,{r2,r4,r6,r8} + eor r2,r2,#0x80000000 + b CPRT_cmf_e + +/*---------------------------------------------------------------------------*/ diff -uNr linux-2.4.37.9/arch/arm/fastfpe/Makefile linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/Makefile --- linux-2.4.37.9/arch/arm/fastfpe/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/Makefile Wed May 26 15:43:59 2010 @@ -0,0 +1,27 @@ +# +# linux/arch/arm/fastfpe/Makefile +# +# Copyright (C) Peter Teichmann +# + +O_TARGET := fast-math-emu.o + +AFLAGS_CPDO.o := -march=armv3m + +obj-y := +obj-m := +obj-n := +obj- := + +fastfpe-objs := module.o round.o CPDT.o CPRT.o CPDO.o entry.o + +list-multi := fastfpe.o + +obj-$(CONFIG_FPE_FASTFPE) += fastfpe.o + +USE_STANDARD_AS_RULE := true + +include $(TOPDIR)/Rules.make + +fastfpe.o: $(fastfpe-objs) + $(LD) -r -o $@ $(fastfpe-objs) diff -uNr linux-2.4.37.9/arch/arm/fastfpe/entry.S linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/entry.S --- linux-2.4.37.9/arch/arm/fastfpe/entry.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/entry.S Wed May 26 15:43:59 2010 @@ -0,0 +1,339 @@ +/* +At entry the registers contain the following information: + +r14 return address for undefined exception return +r9 return address for return from exception +r13 user registers on stack, offset 0 up to offset 4*15 contains + registers r0..15, then the psr +r10 FP workspace 35 words (init, reg[8][4], fpsr, fpcr) + +*/ + +#include + +/*---------------------------------------------------------------------------*/ + + .data +fp_const: + .word 0, 0x00000000, 0, 0x80000000 @ 0 + .word 0, 0x80000000, 0, 0 @ 1 + .word 0, 0x80000000, 0, 1 @ 2 + .word 0, 0xc0000000, 0, 1 @ 3 + .word 0, 0x80000000, 0, 2 @ 4 + .word 0, 0xa0000000, 0, 2 @ 5 + .word 0, 0x80000000, 0, -1 @ 0.5 + .word 0, 0xa0000000, 0, 3 @ 10 +fp_undef: + .word 0 +fp_cond: + .word 0xf0f0 @ eq + .word 0x0f0f @ ne + .word 0xcccc @ cs + .word 0x3333 @ cc + .word 0xff00 @ mi + .word 0x00ff @ pl + .word 0xaaaa @ vs + .word 0x5555 @ vc + .word 0x0c0c @ hi + .word 0xf3f3 @ ls + .word 0xaa55 @ ge + .word 0x55aa @ lt + .word 0x0a05 @ gt + .word 0xf5fa @ le + .word 0xffff @ al + .word 0x0000 @ nv + +/*---------------------------------------------------------------------------*/ + + .text + .globl fastfpe_enter +fastfpe_enter: + ldr r4,=fp_undef + str r14,[r4] @ to free one register + add r10,r10,#4 @ to make the code simpler + ldr r4,[r13,#60] @ r4=saved PC + ldr r4,[r4,#-4] @ r4=trapped instruction + and r1,r4,#0x00000f00 @ r1=coprocessor << 8 +next_enter: + cmp r1,#1<<8 @ copro 1 ? + beq copro_1 + cmp r1,#2<<8 + movne pc,r14 + +copro_2: + and r1,r4,#0x0f000000 + cmp r1,#0x0c000000 @ CPDT with post indexing + cmpne r1,#0x0d000000 @ CPDT with pre indexing + beq CPDT_M_enter + mov pc,r14 + +copro_1: + and r1,r4,#0x0f000000 + cmp r1,#0x0e000000 @ CPDO + beq CPDO_CPRT_enter + cmp r1,#0x0c000000 @ CPDT with post indexing + cmpne r1,#0x0d000000 @ CPDT with pre indexing + beq CPDT_1_enter + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + .globl fastfpe_next +fastfpe_next: + ldr r5,[r13,#60] +next_after_cond_false: +__x1: + ldrt r4,[r5],#4 + + ldr r0,=fp_cond @ check condition of next instruction + mov r2,r4,lsr#28 + cmp r2,#0xe @ "always" condition code + bne next_check_cond + +next_check_copro: + and r1,r4,#0x0f000000 @ Test for copro instruction + cmp r1,#0x0c000000 + rsbgts r0,r1,#0x0e000000 @ cmpgt #0x0e000000,r1 + movlt pc,r9 @ next is no copro instruction, return + + ands r1,r4,#0x00000f00 @ r1 = coprocessor << 8 + cmpne r1,#3<<8 + movge pc,r9 @ copro = 0 or >=3, return + + str r5,[r13,#60] @ save updated pc + cmp r1,#1<<8 @ which copro ? + beq copro_1 + b copro_2 + +next_check_cond: + ldr r1,[r13,#64] @ psr containing flags + ldr r0,[r0,r2,lsl#2] + mov r1,r1,lsr#28 + mov r0,r0,lsr r1 + tst r0,#1 + bne next_check_copro + b next_after_cond_false @ must not necessarily have been an + @ FP instruction ! + +/*---------------------------------------------------------------------------*/ + +undefined: + ldr r4,=fp_undef + ldr pc,[r4] + +/*---------------------------------------------------------------------------*/ + +CPDT_1_enter: + and r5,r4,#0x000f0000 @ r5=base register number << 16 + ldr r6,[r13,r5,lsr#14] @ r6=base address + cmp r5,#0x000f0000 @ base register = pc ? + addeq r6,r6,#4 + and r7,r4,#0x000000ff @ r7=offset value + + tst r4,#0x00800000 @ up or down? + addne r7,r6,r7,lsl#2 + subeq r7,r6,r7,lsl#2 @ r6=base address +/- offset + tst r4,#0x01000000 @ preindexing ? + movne r6,r7 + tst r4,#0x00200000 @ write back ? + cmpne r5,#0x000f0000 @ base register = pc ? + strne r7,[r13,r5,lsr#14] + + and r0,r4,#0x00007000 @ r0=fp register number << 12 + add r0,r10,r0,lsr#8 @ r0=address of fp register + + and r1,r4,#0x00008000 @ T0 + tst r4,#0x00400000 + orrne r1,r1,#0x00010000 @ T1 + tst r4,#0x00100000 + orrne r1,r1,#0x00020000 @ L/S + + ldr pc,[pc,r1,lsr#13] + .word 0 + .word CPDT_store_single @ these functions get + .word CPDT_store_double @ r0=address of fp register + .word CPDT_store_extended @ r6=address of data + .word undefined @ CPDT_store_decimal + .word CPDT_load_single + .word CPDT_load_double + .word CPDT_load_extended + .word undefined @ CPDT_load_decimal + +/*---------------------------------------------------------------------------*/ + +CPDT_M_enter: + and r5,r4,#0x000f0000 @ r5=base register number << 16 + ldr r6,[r13,r5,lsr#14] @ r6=base address + cmp r5,#0x000f0000 @ base register = pc ? + addeq r6,r6,#4 + and r7,r4,#0x000000ff @ r7=offset value + + tst r4,#0x00800000 @ up or down? + addne r7,r6,r7,lsl#2 + subeq r7,r6,r7,lsl#2 @ r7=base address +/- offset + tst r4,#0x01000000 @ preindexing ? + movne r6,r7 + tst r4,#0x00200000 @ write back ? + cmpne r5,#0x000f0000 @ base register = pc ? + strne r7,[r13,r5,lsr#14] + + and r0,r4,#0x00007000 @ r0=fp register number << 12 + and r1,r4,#0x00008000 + mov r1,r1,lsr#15 @ N0 + and r2,r4,#0x00400000 + orrs r1,r1,r2,lsr#21 @ N1 + addeq r1,r1,#4 @ r1=register count + + tst r4,#0x00100000 @ load/store + beq CPDT_sfm + b CPDT_lfm + +/*---------------------------------------------------------------------------*/ + +CPDO_CPRT_enter: + tst r4,#0x00000010 + bne CPRT_enter + + and r0,r4,#0x00007000 + add r0,r10,r0,lsr#8 @ r0=address of Fd + and r1,r4,#0x00070000 + add r1,r10,r1,lsr#12 @ r1=address of Fn + tst r4,#0x00000008 + bne CPDO_const + and r2,r4,#0x00000007 + add r2,r10,r2,lsl#4 @ r2=address of Fm + +CPDO_constback: + ldr r3,=round_table + and r5,r4,#0x000000e0 + and r6,r4,#0x00080000 + orr r5,r5,r6,lsr#11 @ r5=containing rounding mode/precision + ldr r14,[r3,r5,lsr#3] @ r14=address of rounding function + and r3,r4,#0x00f00000 + tst r4,#0x00008000 + orrne r3,r3,#0x01000000 @ r3=operation code + + ldr pc,[pc,r3,lsr#18] + .word 0 +CPDO_table: + .word CPDO_adf + .word CPDO_muf + .word CPDO_suf + .word CPDO_rsf + .word CPDO_dvf + .word CPDO_rdf + .word undefined + .word undefined + .word CPDO_rmf + .word CPDO_muf + .word CPDO_dvf + .word CPDO_rdf + .word undefined + .word undefined + .word undefined + .word undefined + .word CPDO_mvf + .word CPDO_mnf + .word CPDO_abs + .word CPDO_rnd + .word CPDO_sqt + .word undefined + .word undefined + .word undefined + .word undefined + .word undefined + .word undefined + .word undefined + .word undefined + .word undefined + .word CPDO_rnd + .word fastfpe_next + +CPDO_const: + ldr r2,=fp_const + and r3,r4,#0x00000007 + add r2,r2,r3,lsl#4 + b CPDO_constback + +/*---------------------------------------------------------------------------*/ + +CPRT_enter: + and r0,r4,#0x0000f000 @ r0=Rd<<12 + and r1,r4,#0x00070000 + add r1,r10,r1,lsr#12 @ r1=address of Fn + tst r4,#0x00000008 + bne CPRT_const + and r2,r4,#0x00000007 + add r2,r10,r2,lsl#4 @ r2=address of Fm + +CPRT_constback: + and r3,r4,#0x00f00000 + + ldr pc,[pc,r3,lsr#18] + .word 0 + .word CPRT_flt + .word CPRT_fix + .word CPRT_wfs + .word CPRT_rfs + .word undefined + .word undefined + .word undefined + .word undefined + .word undefined + .word CPRT_cmf + .word undefined + .word CPRT_cnf + .word undefined + .word CPRT_cmf + .word undefined + .word CPRT_cnf + +CPRT_const: + ldr r2,=fp_const + and r3,r4,#0x00000007 + add r2,r2,r3,lsl#4 + b CPRT_constback + +/*---------------------------------------------------------------------------*/ + + @ Test if long multiply instructions are available + + .globl fastfpe_test +fastfpe_test: + .globl elf_hwcap + ldr r0,=elf_hwcap + ldr r0,[r0] + tst r0,#HWCAP_FAST_MULT + bne fastfpe_has_long_multiply + mov r0,#0 + mov pc,r14 + +fastfpe_has_long_multiply: + adr r0,CPDO_table + ldr r1,=CPDO_muf_M + str r1,[r0,#1*4] @ muf + str r1,[r0,#9*4] @ fml + ldr r1,=CPDO_dvf_M + str r1,[r0,#4*4] @ dvf + str r1,[r0,#10*4] @ fdv + ldr r1,=CPDO_rdf_M + str r1,[r0,#5*4] @ rdf + str r1,[r0,#11*4] @ frd + mov r0,#1 + mov pc,r14 + +/*---------------------------------------------------------------------------*/ + + @ The fetch of the next instruction to emulate could fault + + .section .fixup,"ax" + .align +__f1: + mov pc,r9 + .previous + .section __ex_table,"a" + .align 3 + .long __x1,__f1 + .previous + +/*---------------------------------------------------------------------------*/ diff -uNr linux-2.4.37.9/arch/arm/fastfpe/module.c linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/module.c --- linux-2.4.37.9/arch/arm/fastfpe/module.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/module.c Wed May 26 15:43:59 2010 @@ -0,0 +1,64 @@ +/* + Fast Floating Point Emulator + (c) Peter Teichmann + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#ifndef MODULE +#define kern_fp_enter fp_enter + +extern char fpe_type[]; +#endif + +static void (*orig_fp_enter)(void); /* old kern_fp_enter value */ +extern void (*kern_fp_enter)(void); /* current FP handler */ +extern void fastfpe_enter(void); /* forward declarations */ +extern int fastfpe_test(void); /* long multiply available ? */ + +static int __init fpe_init(void) +{ + if (fpe_type[0] && strcmp(fpe_type, "fastfpe")) + return 0; + + printk("Fast Floating Point Emulator V0.94"); + if (fastfpe_test() == 1) printk("M"); + printk(" by Peter Teichmann.\n"); + + /* Save pointer to the old FP handler and then patch ourselves in */ + orig_fp_enter = kern_fp_enter; + kern_fp_enter = fastfpe_enter; + + return 0; +} + +static void __exit fpe_exit(void) +{ + /* Restore the values we saved earlier. */ + kern_fp_enter = orig_fp_enter; +} + +module_init(fpe_init); +module_exit(fpe_exit); + +MODULE_AUTHOR("Peter Teichmann "); +MODULE_DESCRIPTION("Fast floating point emulator with full precision"); diff -uNr linux-2.4.37.9/arch/arm/fastfpe/round.S linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/round.S --- linux-2.4.37.9/arch/arm/fastfpe/round.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/fastfpe/round.S Wed May 26 15:43:59 2010 @@ -0,0 +1,912 @@ + +/* +Rounds fp register r1-r4, additional mantissa bits in r5 and stores result +at address r0. Returns to fastfpe_next. +*/ + +/*------------------------------------------------------------------------*/ + + .data + .globl round_table +round_table: + .word round_single_ne + .word round_single_p + .word round_single_m + .word round_single_z + .word round_double_ne + .word round_double_p + .word round_double_m + .word round_double_z + .word round_extended_ne + .word round_extended_p + .word round_extended_m + .word round_extended_z + .word round_undef + .word round_undef + .word round_undef + .word round_undef + +/*------------------------------------------------------------------------*/ + + .text +round_single_ne: + cmp r4,#127 + bgt round_single_nz_ne_overflow + cmp r4,#-126-23-1 + blt round_single_z_ne_underflow + cmp r4,#-126 + blt round_single_ne_denormalized + + adds r6,r2,#0x80 // add 0x80.00000000.00000000 to + bcs round_single_add_ov // mantissa and additional bits + + teq r5,#0 + teqeq r3,#0 + tsteq r2,#0xff // test for inexact + + ldrne r7,[r10,#128] + orrne r7,r7,#16 // set inexact flag + strne r7,[r10,#128] + + teq r5,#0 + teqeq r3,#0 + tsteq r6,#0xff + biceq r6,r6,#0x100 // the even thingy + + mov r3,#0 // remove bits not existing in single + bic r2,r6,#0xff // remove bits not existing in single + stmia r0,{r1-r4} + b fastfpe_next + +round_single_ne_denormalized: + add r7,r4,#150 + mov r6,#0xffffffff + mov r6,r6,lsr r7 + + teq r5,#0 + teqeq r3,#0 + tsteq r2,r6 + ldrne r8,[r10,#128] + orrne r8,r8,#16+8 // set inexact, underflow flag + strne r8,[r10,#128] + + mov r8,#0x80000000 + mov r8,r8,lsr r7 + adds r2,r2,r8 + bcs round_single_ne_denormalized_ov + + teq r5,#0 + teqeq r3,#0 + tsteq r2,r6 + biceq r2,r2,r8,lsl #1 // the even thingy + + mov r3,#0 + bic r2,r2,r6 // removing bits not existing in single + stmia r0,{r1-r4} + b fastfpe_next + +round_single_ne_denormalized_ov: + cmp r4,#-150 + cmpeq r3,#0 + cmpeq r2,#0 + beq round_single_z_ne_underflow // 1.0*2^-150 to zero! + add r4,r4,#1 + cmp r4,#-126 // left denormalized range ? + cmpge r2,#0x80 // yes -> overflow also without denormalisation ? + ldrge r5,[r10,#128] + bicge r5,r5,#8 // yes -> clear underflow flag + strge r5,[r10,#128] + mov r3,#0 + mov r2,#0x80000000 + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_single_p: + teq r1,#0 + beq round_single_nz + b round_single_z + +/*------------------------------------------------------------------------*/ + +round_single_m: + teq r1,#0 + beq round_single_z + b round_single_nz + +/*------------------------------------------------------------------------*/ + +round_single_z: + cmp r4,#127 + bgt round_single_z_overflow + cmp r4,#-126-23 + blt round_single_z_ne_underflow + cmp r4,#-126 + blt round_single_z_denormalized + + teq r5,#0 + teqeq r3,#0 + tsteq r2,#0xff // testing for inexact + ldrne r5,[r10,#128] + orrne r5,r5,#16 // set inexact flag + strne r5,[r10,#128] + + mov r3,#0 + bic r2,r2,#0xff // removing bits not existing in single + stmia r0,{r1-r4} + b fastfpe_next + +round_single_z_overflow: + cmp r4,#0x7fffffff + beq round_single_infnan + + ldrne r5,[r10,#128] + orrne r5,r5,#16+4 // set inexact,overflow flag + strne r5,[r10,#128] + mov r2,#0xffffff00 + mov r3,#0 + mov r4,#127 // biggest non-infinity single + stmia r0,{r1-r4} + b fastfpe_next + +round_single_infnan: + orrs r5,r3,r2,lsl#1 // is it Inf? ignore MSB + beq round_single_infnan_store + tst r2,#0x40000000 // is it a SNaN? + beq round_single_infnan_create_qnan + mov r3,#0 // these bits can not be stored + bic r2,r2,#0xff // in single precision +round_single_infnan_store: + stmia r0,{r1-r4} + b fastfpe_next + +round_single_infnan_create_qnan: + mov r1,#0x80000000 + mov r2,#0xffffff00 + bic r2,r2,#0x80000000 // r2 = 0x7fffff00 + mov r3,#0 + ldr r5,[r10,#128] + orr r5,r5,#1 // set invalid operation flag + str r5,[r10,#128] + stmia r0,{r1-r4} + b fastfpe_next + +round_single_z_ne_underflow: + cmp r4,#0x80000000 + beq round_single_z_zero + ldrne r5,[r10,#128] + orrne r5,r5,#16+8 // set inexact, underflow flag + strne r5,[r10,#128] + mov r2,#0 + mov r3,#0 + mov r4,#0x80000000 // was by ERROR -127 +round_single_z_zero: + stmia r0,{r1-r4} + b fastfpe_next + +round_single_z_denormalized: + mov r6,#0xffffffff + add r7,r4,#150 + + teq r5,#0 + teqeq r3,#0 + tsteq r2,r6,lsr r7 // testing for tinyness + ldrne r5,[r10,#128] + orrne r5,r5,#16+8 // set inexact, undeflow flag + strne r5,[r10,#128] + + mov r3,#0 + bic r2,r2,r6,lsr r7 // removing bits not existing in single + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_single_nz: + cmp r4,#127 + bgt round_single_nz_ne_overflow + cmp r4,#-126-23 + blt round_single_nz_underflow + cmp r4,#-126 + blt round_single_nz_denormalized + + adds r5,r5,#0xffffffff + adcs r3,r3,#0xffffffff // add 0xff.ffffffff.ffffffff to + adcs r2,r2,#0xff // mantissa and additional bits + bcs round_single_add_ov + + cmp r5,#0xffffffff + cmpeq r3,#0xffffffff + andeq r5,r2,#0xff + cmpeq r5,#0xff // test for inexact + + bic r2,r2,#0xff // remove bits not existing in single + +round_single_add_ov_back: + ldrne r5,[r10,#128] + orrne r5,r5,#16 // set inexact flag + strne r5,[r10,#128] + + mov r3,#0 // remove bits not existing in single + stmia r0,{r1-r4} + b fastfpe_next + +round_single_add_ov: + add r4,r4,#1 + cmp r4,#127 + bgt round_single_nz_ne_overflow + movs r2,#0x80000000 // so that inexact flag gets set !!! + b round_single_add_ov_back + +round_single_nz_ne_overflow: + cmp r4,#0x7fffffff + beq round_single_infnan + + ldrne r5,[r10,#128] + orrne r5,r5,#16+4 // set inexact,overflow flag + strne r5,[r10,#128] + mov r2,#0x80000000 // set MSB + mov r3,#0 + mov r4,#0x7fffffff + stmia r0,{r1-r4} + b fastfpe_next + +round_single_nz_underflow: + cmp r4,#0x80000000 + beq round_single_nz_zero + + ldrne r5,[r10,#128] + orrne r5,r5,#16+8 // set inexact, underflow flag + strne r5,[r10,#128] + mov r2,#0x80000000 + mov r3,#0 + mov r4,#-149 // smallest non-zero single +round_single_nz_zero: + stmia r0,{r1-r4} + b fastfpe_next + +round_single_nz_denormalized: + mov r6,#0xffffffff + add r7,r4,#150 + mov r6,r6,lsr r7 + + teq r5,#0 + teqeq r3,#0 + tsteq r2,r6 + ldrne r8,[r10,#128] + orrne r8,r8,#16+8 // set inexact, underflow flag + strne r8,[r10,#128] + + adds r5,r5,#0xffffffff + adcs r3,r3,#0xffffffff + adcs r2,r2,r6 + bcs round_single_nz_denormalized_ov + + mov r3,#0 + bic r2,r2,r6 // removing bits not existing in single + stmia r0,{r1-r4} + b fastfpe_next + +round_single_nz_denormalized_ov: + add r4,r4,#1 + cmp r4,#-126 // left denormalized range ? + cmpge r2,#0x100 // yes -> overflow also without denormalisation ? + ldrge r5,[r10,#128] + bicge r5,r5,#8 // yes -> clear underflow flag + strge r5,[r10,#128] + mov r3,#0 + mov r2,#0x80000000 + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_double_ne: + mov r7,#0xffffffff // to generate e.g. 0x7ff + + cmp r4,#1024 + bge round_double_nz_ne_overflow + add r6,r4,#1024 + cmp r6,#-1022+1024 + blt round_double_ne_denormalized + + teq r5,#0 + tsteq r3,r7,lsr#32-11 // testing for inexact + ldrne r6,[r10,#128] + orrne r6,r6,#16 // set inexact flag + strne r6,[r10,#128] + + adds r3,r3,#0x400 // add 0x0.00000400.00000000 to + adcs r2,r2,#0 // mantissa and additional bits + bcs round_double_add_ov + + teq r5,#0 + tsteq r3,r7,lsr#32-11 + biceq r3,r3,#0x800 // the even thingy + + bic r3,r3,r7,lsr#32-11 // remove bits not existing in double + + stmia r0,{r1-r4} + b fastfpe_next + +round_double_ne_denormalized: + cmp r6,#-1022-52-1+1024 + blt round_double_z_ne_underflow + + adds r6,r6,#1022+53-32-1024 + + addmi r6,r6,#32 + movmi r6,r7,lsr r6 + + movpl r7,r7,lsr r6 + movpl r6,#0 + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 // testing for tinyness + ldrne r8,[r10,#128] + orrne r8,r8,#16+8 // set inexact, undeflow flag + strne r8,[r10,#128] + + bics r8,r6,r6,lsr#1 // generate ...0001000... + movne r11,#0 // from ...0001111... + biceq r11,r7,r7,lsr#1 // 64bit + + adds r3,r3,r11 + adcs r2,r2,r8 + bcs round_double_ne_denormalized_ov + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 + bne round_double_ne_denormalized_noeventhingy + adds r11,r11,r11 + adc r8,r8,r8 + bic r3,r3,r11 + bic r2,r2,r8 // the even thingy + +round_double_ne_denormalized_noeventhingy: + bic r3,r3,r7 // removing bits not existing in + bic r2,r2,r6 // denormalized double + stmia r0,{r1-r4} + b fastfpe_next + +round_double_ne_denormalized_ov: + add r6,r4,#1024 + cmp r6,#-1023-52+1024 + cmpeq r3,#0 + cmpeq r2,#0 + beq round_single_z_ne_underflow // 1.0*2^(-1023-52) to zero! + add r4,r4,#1 + cmp r6,#-1022-1+1024 // left denormalized range ? + cmpge r3,#0x400 // yes -> overflow also without denormalisation ? + ldrge r5,[r10,#128] + bicge r5,r5,#8 // yes -> clear underflow flag + strge r5,[r10,#128] + mov r3,#0 + mov r2,#0x80000000 + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_double_p: + teq r1,#0 + beq round_double_nz + b round_double_z + +/*------------------------------------------------------------------------*/ + +round_double_m: + teq r1,#0 + beq round_double_z + b round_double_nz + +/*------------------------------------------------------------------------*/ + +round_double_z: + mov r7,#0xffffffff + + cmp r4,#1024 + bge round_double_z_overflow + add r6,r4,#1024 + cmp r6,#-1022+1024 + blt round_double_z_denormalized + + teq r5,#0 + tsteq r3,r7,lsr#32-11 // testing for inexact + ldrne r5,[r10,#128] + orrne r5,r5,#16 // set inexact flag + strne r5,[r10,#128] + + bic r3,r3,r7,lsr#32-11 // removing bits not existing in double + stmia r0,{r1-r4} + b fastfpe_next + +round_double_z_overflow: + cmp r4,#0x7fffffff + beq round_double_infnan + + ldrne r5,[r10,#128] + orrne r5,r5,#16+4 // set inexact,overflow flag + strne r5,[r10,#128] + mov r2,#0xffffffff + mov r3,r2,lsl#11 // 0xfffff800 + mov r4,#1024 + sub r4,r4,#1 // 1023; biggest non-infinity double + stmia r0,{r1-r4} + b fastfpe_next + +round_double_infnan: + orrs r5,r3,r2,lsl#1 // is it Inf? ignore MSB + beq round_double_infnan_store + tst r2,#0x40000000 // is it a SNaN? + beq round_double_infnan_create_qnan + bic r3,r3,r7,lsr#32-11 // clear bits not in double +round_double_infnan_store: + stmia r0,{r1-r4} + b fastfpe_next + +round_double_infnan_create_qnan: + mov r1,#0x80000000 + mov r2,#0x7fffffff + mov r3,r2,lsl#11 // 0xfffff800 + ldr r5,[r10,#128] + orr r5,r5,#1 // set invalid operation flag + str r5,[r10,#128] + b round_double_infnan_store + +round_double_z_ne_underflow: + cmp r4,#0x80000000 + beq round_double_z_zero + ldr r5,[r10,#128] + orr r5,r5,#16+8 // set inexact, underflow flag + str r5,[r10,#128] + mov r2,#0 + mov r3,#0 + mov r4,#0x80000000 +round_double_z_zero: + stmia r0,{r1-r4} + b fastfpe_next + +round_double_z_denormalized: + cmp r6,#-1022-52+1024 + blt round_double_z_ne_underflow + + adds r6,r6,#1022+53-32-1024 + + addmi r6,r6,#32 + movmi r6,r7,lsr r6 + + movpl r7,r7,lsr r6 + movpl r6,#0 + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 // testing for tinyness + ldrne r5,[r10,#128] + orrne r5,r5,#16+8 // set inexact, undeflow flag + strne r5,[r10,#128] + + bic r3,r3,r7 // rmoving bits not existing in + bic r2,r2,r6 // denormalized double + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_double_nz: + mov r7,#0xffffffff // to generate e.g. 0x7ff + + cmp r4,#1024 + bge round_double_nz_ne_overflow + add r6,r4,#1024 + cmp r6,#-1022+1024 + blt round_double_nz_denormalized + + teq r5,#0 + tsteq r3,r7,lsr#32-11 // testing for inexact + ldrne r6,[r10,#128] + orrne r6,r6,#16 // set inexact flag + strne r6,[r10,#128] + + adds r5,r5,#0xffffffff + adcs r3,r3,r7,lsr#32-11 // add 0x0.000007ff.ffffffff to + adcs r2,r2,#0 // mantissa and additional bits + bcs round_double_add_ov + + bic r3,r3,r7,lsr#32-11 // remove bits not existing in double + + stmia r0,{r1-r4} + b fastfpe_next + +round_double_add_ov: + add r4,r4,#1 + cmp r4,#1024 + bge round_double_nz_ne_overflow + +// ldrne r6,[r10,#128] +// orrne r6,r6,#16 // set inexact flag +// strne r6,[r10,#128] + mov r2,#0x80000000 + mov r3,#0 + stmia r0,{r1-r4} + b fastfpe_next + +round_double_nz_ne_overflow: + cmp r4,#0x7fffffff + beq round_double_infnan + + ldrne r5,[r10,#128] + orrne r5,r5,#16+4 // set inexact,overflow flag + strne r5,[r10,#128] + mov r2,#0x80000000 // set MSB + mov r3,#0 + mov r4,#0x7fffffff + stmia r0,{r1-r4} + b fastfpe_next + +round_double_nz_underflow: + cmp r4,#0x80000000 + beq round_double_nz_zero + + ldrne r5,[r10,#128] + orrne r5,r5,#16+8 // set inexact, underflow flag + strne r5,[r10,#128] + mov r2,#0x80000000 + mov r3,#0 + mov r4,#-1074+1024 + sub r4,r4,#1024 // smallest non-zero double +round_double_nz_zero: + stmia r0,{r1-r4} + b fastfpe_next + +round_double_nz_denormalized: + cmp r6,#-1022-52+1024 + blt round_double_nz_underflow + + adds r6,r6,#1022+53-32-1024 + + addmi r6,r6,#32 + movmi r6,r7,lsr r6 + + movpl r7,r7,lsr r6 + movpl r6,#0 + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 // testing for tinyness + ldrne r8,[r10,#128] + orrne r8,r8,#16+8 // set inexact, undeflow flag + strne r8,[r10,#128] + + adds r5,r5,#0xffffffff + adcs r3,r3,r7 + adcs r2,r2,r6 + bcs round_double_nz_denormalized_ov + + bic r3,r3,r7 // rmoving bits not existing in + bic r2,r2,r6 // denormalized double + stmia r0,{r1-r4} + b fastfpe_next + +round_double_nz_denormalized_ov: + add r4,r4,#1 + add r6,r4,#1024 + cmp r6,#-1022+1024 // left denormalized range ? + cmpge r3,#0x800 // yes -> overflow also without denormalisation ? + ldrge r5,[r10,#128] + bicge r5,r5,#8 // yes -> clear underflow flag + strge r5,[r10,#128] + mov r3,#0 + mov r2,#0x80000000 + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_extended_ne: + mov r7,#0xffffffff // to generate e.g. 0x7ff + + cmp r4,#16384 + bge round_extended_nz_ne_overflow + add r6,r4,#16384 + cmp r6,#-16382+16384 + blt round_extended_ne_denormalized + + teq r5,#0 // testing for inexact + ldrne r6,[r10,#128] + orrne r6,r6,#16 // set inexact flag + strne r6,[r10,#128] + + adds r5,r5,#0x80000000 // add 0x0.00000400.00000000 to + adcs r3,r3,#0 // mantissa and additional bits + adcs r2,r2,#0 + bcs round_extended_add_ov + + teq r5,#0 + biceq r3,r3,#1 // the even thingy + + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_ne_denormalized: + cmp r6,#-16382-63-1+16384 + blt round_extended_z_ne_underflow + + adds r6,r6,#16382+64-32-16384 + + addmi r6,r6,#32 + movmi r6,r7,lsr r6 + + movpl r7,r7,lsr r6 + movpl r6,#0 + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 // testing for tinyness + ldrne r8,[r10,#128] + orrne r8,r8,#16+8 // set inexact, undeflow flag + strne r8,[r10,#128] + + bics r8,r6,r6,lsr#1 // generate ...0001000... + movne r11,#0 // from ...0001111... + biceq r11,r7,r7,lsr#1 // 64bit + + adds r3,r3,r11 + adcs r2,r2,r8 + bcs round_extended_ne_denormalized_ov + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 + bne round_extended_ne_denormalized_noeventhingy + adds r11,r11,r11 + adc r8,r8,r8 + bic r3,r3,r11 + bic r2,r2,r8 // the even thingy + +round_extended_ne_denormalized_noeventhingy: + bic r3,r3,r7 // removing bits not existing in + bic r2,r2,r6 // denormalized extended + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_ne_denormalized_ov: + add r6,r4,#16384 + cmp r6,#-16383-63+16384 + cmpeq r5,#0 + cmpeq r3,#0 + cmpeq r2,#0 + beq round_single_z_ne_underflow // 1.0*2^(-16383-63) to zero! + add r4,r4,#1 + cmp r6,#-16382-1+16384 // left denormalized range ? + blt round_extended_ne_still_denormalized + cmp r5,#0x80000000 // FIXME yes -> overflow also without denormalisation ? + ldrcs r5,[r10,#128] + biccs r5,r5,#8 // yes -> clear underflow flag + strcs r5,[r10,#128] +round_extended_ne_still_denormalized: + mov r3,#0 + mov r2,#0x80000000 + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_extended_p: + teq r1,#0 + beq round_extended_nz + b round_extended_z + +/*------------------------------------------------------------------------*/ + +round_extended_m: + teq r1,#0 + beq round_extended_z + b round_extended_nz + +/*------------------------------------------------------------------------*/ + +round_extended_z: + mov r7,#0xffffffff + + cmp r4,#16384 + bge round_extended_z_overflow + add r6,r4,#16384 + cmp r6,#-16382+16384 + blt round_extended_z_denormalized + + teq r5,#0 // testing for inexact + ldrne r5,[r10,#128] + orrne r5,r5,#16 // set inexact flag + strne r5,[r10,#128] + + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_z_overflow: + cmp r4,#0x7fffffff + beq round_extended_infnan + + ldrne r5,[r10,#128] + orrne r5,r5,#16+4 // set inexact,overflow flag + strne r5,[r10,#128] + mov r2,#0xffffffff + mov r3,#0xffffffff + mov r4,#16384 + sub r4,r4,#1 // 16383; biggest non-infinity extended + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_infnan: + orrs r5,r3,r2,lsl#1 // is it Inf? ignore MSB + beq round_extended_infnan_store + tst r2,#0x40000000 // is it a SNaN? + beq round_extended_infnan_create_qnan + bic r3,r3,r7,lsr#32-11 // clear bits not in extended +round_extended_infnan_store: + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_infnan_create_qnan: + mov r1,#0x80000000 + mov r2,#0x7fffffff + mov r3,#0xffffffff + ldr r5,[r10,#128] + orr r5,r5,#1 // set invalid operation flag + str r5,[r10,#128] + b round_extended_infnan_store + +round_extended_z_ne_underflow: + cmp r4,#0x80000000 + beq round_extended_z_zero + ldr r5,[r10,#128] + orr r5,r5,#16+8 // set inexact, underflow flag + str r5,[r10,#128] + mov r2,#0 + mov r3,#0 + mov r4,#0x80000000 +round_extended_z_zero: + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_z_denormalized: + cmp r6,#-16382-63+16384 + blt round_extended_z_ne_underflow + + adds r6,r6,#16382+64-32-16384 + + addmi r6,r6,#32 + movmi r6,r7,lsr r6 + + movpl r7,r7,lsr r6 + movpl r6,#0 + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 // testing for tinyness + ldrne r5,[r10,#128] + orrne r5,r5,#16+8 // set inexact, undeflow flag + strne r5,[r10,#128] + + bic r3,r3,r7 // removing bits not existing in + bic r2,r2,r6 // denormalized extended + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_extended_nz: + mov r7,#0xffffffff // to generate e.g. 0x7ff + + cmp r4,#16384 + bge round_extended_nz_ne_overflow + add r6,r4,#16384 + cmp r6,#-16382+16384 + blt round_extended_nz_denormalized + + teq r5,#0 // testing for inexact + ldrne r6,[r10,#128] + orrne r6,r6,#16 // set inexact flag + strne r6,[r10,#128] + + adds r5,r5,#0xffffffff + adcs r3,r3,#0 // add 0x0.0.ffffffff to + adcs r2,r2,#0 // mantissa and additional bits + bcs round_extended_add_ov + + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_add_ov: + add r4,r4,#1 + cmp r4,#16384 + bge round_extended_nz_ne_overflow + +// ldrne r6,[r10,#128] +// orrne r6,r6,#16 // set inexact flag +// strne r6,[r10,#128] + mov r2,#0x80000000 + mov r3,#0 + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_nz_ne_overflow: + cmp r4,#0x7fffffff + beq round_extended_infnan + + ldrne r5,[r10,#128] + orrne r5,r5,#16+4 // set inexact,overflow flag + strne r5,[r10,#128] + mov r2,#0x80000000 // set MSB + mov r3,#0 + mov r4,#0x7fffffff + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_nz_underflow: + cmp r4,#0x80000000 + beq round_extended_nz_zero + + ldrne r5,[r10,#128] + orrne r5,r5,#16+8 // set inexact, underflow flag + strne r5,[r10,#128] + mov r2,#0x80000000 + mov r3,#0 + mov r4,#-16445+16384 + sub r4,r4,#16384 // smallest non-zero extended +round_extended_nz_zero: + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_nz_denormalized: + cmp r6,#-16382-63+16384 + blt round_extended_nz_underflow + + adds r6,r6,#16382+64-32-16384 + + addmi r6,r6,#32 + movmi r6,r7,lsr r6 + + movpl r7,r7,lsr r6 + movpl r6,#0 + + teq r5,#0 + tsteq r3,r7 + tsteq r2,r6 // testing for tinyness + ldrne r8,[r10,#128] + orrne r8,r8,#16+8 // set inexact, undeflow flag + strne r8,[r10,#128] + + adds r5,r5,#0xffffffff + adcs r3,r3,r7 + adcs r2,r2,r6 + bcs round_extended_nz_denormalized_ov + + bic r3,r3,r7 // removing bits not existing in + bic r2,r2,r6 // denormalized extended + stmia r0,{r1-r4} + b fastfpe_next + +round_extended_nz_denormalized_ov: + add r4,r4,#1 + add r6,r4,#16384 + cmp r6,#-16382+16384 // left denormalized range ? + cmpge r3,#1 // yes -> overflow also without denormalisation ? + ldrge r5,[r10,#128] + bicge r5,r5,#8 // yes -> clear underflow flag + strge r5,[r10,#128] + mov r3,#0 + mov r2,#0x80000000 + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ + +round_undef: + stmia r0,{r1-r4} + b fastfpe_next + +/*------------------------------------------------------------------------*/ diff -uNr linux-2.4.37.9/arch/arm/kernel/Makefile linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/Makefile --- linux-2.4.37.9/arch/arm/kernel/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/Makefile Wed May 26 15:43:54 2010 @@ -45,7 +45,7 @@ $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \ $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \ $(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_OMAHA) \ - $(CONFIG_ARCH_AT91RM9200) + $(CONFIG_ARCH_AT91RM9200) $(CONFIG_ARCH_PSIONW) ifneq ($(findstring y,$(no-irq-arch)),y) obj-y += irq-arch.o @@ -54,6 +54,7 @@ obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_ARCH_RISCSTATION) += time-acorn.o +obj-$(CONFIG_ARCH_PSIONW) += fiq.o psionw_pm.o obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o obj-$(CONFIG_MODULES) += armksyms.o obj-$(CONFIG_ARTHUR) += arthur.o diff -uNr linux-2.4.37.9/arch/arm/kernel/calls.S linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/calls.S --- linux-2.4.37.9/arch/arm/kernel/calls.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/calls.S Wed May 26 15:43:54 2010 @@ -115,7 +115,7 @@ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */ .long SYMBOL_NAME(sys_statfs) /* 100 */ .long SYMBOL_NAME(sys_fstatfs) - .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 101 was sys_ioperm */ .long SYMBOL_NAME(sys_socketcall) .long SYMBOL_NAME(sys_syslog) .long SYMBOL_NAME(sys_setitimer) @@ -126,7 +126,7 @@ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */ /* 110 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_iopl */ .long SYMBOL_NAME(sys_vhangup) - .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 112 was sys_idle */ .long SYMBOL_NAME(sys_syscall) /* call a syscall */ .long SYMBOL_NAME(sys_wait4) /* 115 */ .long SYMBOL_NAME(sys_swapoff) @@ -137,7 +137,7 @@ /* 120 */ .long SYMBOL_NAME(sys_clone_wapper) .long SYMBOL_NAME(sys_setdomainname) .long SYMBOL_NAME(sys_newuname) - .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 123 was sys_modify_ldt */ .long SYMBOL_NAME(sys_adjtimex) /* 125 */ .long SYMBOL_NAME(sys_mprotect) .long SYMBOL_NAME(sys_sigprocmask) @@ -180,7 +180,7 @@ .long SYMBOL_NAME(sys_arm_mremap) .long SYMBOL_NAME(sys_setresuid16) /* 165 */ .long SYMBOL_NAME(sys_getresuid16) - .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 166 was sys_vm86 */ .long SYMBOL_NAME(sys_query_module) .long SYMBOL_NAME(sys_poll) .long SYMBOL_NAME(sys_nfsservctl) diff -uNr linux-2.4.37.9/arch/arm/kernel/debug-armv.S linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/debug-armv.S --- linux-2.4.37.9/arch/arm/kernel/debug-armv.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/debug-armv.S Wed May 26 15:43:54 2010 @@ -470,6 +470,37 @@ +#elif defined(CONFIG_ARCH_PSIONW) + +#include + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #PSIONW_PHYS_BASE + movne \rx, #PSIONW_VIRT_BASE + orr \rx, \rx, #0x0700 @ UART2 + .endm + + .macro senduart,rd,rx + str \rd, [\rx] @ UARTDR + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #0x0010] @ SYSFLGx + tst \rd, #1 << 3 @ UBUSYx + bne 1001b + .endm + + .macro busyuart,rd,rx + tst \rx, #0x0000 @ UART2 does not have CTS here + bne 1002f +1001: ldr \rd, [\rx, #0x0010] @ SYSFLGx + tst \rd, #1 << 0 @ CTS + bne 1001b +1002: + .endm + #else #error Unknown architecture #endif diff -uNr linux-2.4.37.9/arch/arm/kernel/dma-rpc.c linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/dma-rpc.c --- linux-2.4.37.9/arch/arm/kernel/dma-rpc.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/dma-rpc.c Wed May 26 15:43:54 2010 @@ -26,19 +26,6 @@ #include #include -#if 0 -typedef enum { - dma_size_8 = 1, - dma_size_16 = 2, - dma_size_32 = 4, - dma_size_128 = 16 -} dma_size_t; - -typedef struct { - dma_size_t transfersize; -} dma_t; -#endif - #define TRANSFER_SIZE 2 #define CURA (0) @@ -48,10 +35,6 @@ #define CR (IOMD_IO0CR - IOMD_IO0CURA) #define ST (IOMD_IO0ST - IOMD_IO0CURA) -#define state_prog_a 0 -#define state_wait_a 1 -#define state_wait_b 2 - static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) { unsigned long end, offset, flags = 0; @@ -65,7 +48,7 @@ if (end > PAGE_SIZE) end = PAGE_SIZE; - if (offset + (int) TRANSFER_SIZE > end) + if (offset + TRANSFER_SIZE >= end) flags |= DMA_END_L; sg->length = end - TRANSFER_SIZE; @@ -103,27 +86,31 @@ if (!(status & DMA_ST_INT)) return; - if (status & DMA_ST_OFL && !dma->sg) - break; - - iomd_get_next_sg(&dma->cur_sg, dma); + if ((dma->state ^ status) & DMA_ST_AB) + iomd_get_next_sg(&dma->cur_sg, dma); switch (status & (DMA_ST_OFL | DMA_ST_AB)) { case DMA_ST_OFL: /* OIA */ case DMA_ST_AB: /* .IB */ iomd_writel(dma->cur_sg.dma_address, base + CURA); iomd_writel(dma->cur_sg.length, base + ENDA); + dma->state = DMA_ST_AB; break; case DMA_ST_OFL | DMA_ST_AB: /* OIB */ case 0: /* .IA */ iomd_writel(dma->cur_sg.dma_address, base + CURB); iomd_writel(dma->cur_sg.length, base + ENDB); + dma->state = 0; break; } + + if (status & DMA_ST_OFL && + dma->cur_sg.length == (DMA_END_S|DMA_END_L)) + break; } while (1); - iomd_writeb(0, base + CR); + dma->state = ~DMA_ST_AB; disable_irq(irq); } @@ -158,6 +145,7 @@ } iomd_writeb(DMA_CR_C, dma_base + CR); + dma->state = DMA_ST_AB; } if (dma->dma_mode == DMA_MODE_READ) @@ -171,13 +159,11 @@ { unsigned long dma_base = dma->dma_base; unsigned long flags; - unsigned int ctrl; local_irq_save(flags); - ctrl = iomd_readb(dma_base + CR); - if (ctrl & DMA_CR_E) + if (dma->state != ~DMA_ST_AB) disable_irq(dma->dma_irq); - iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR); + iomd_writeb(0, dma_base + CR); local_irq_restore(flags); } diff -uNr linux-2.4.37.9/arch/arm/kernel/entry-armv.S linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/entry-armv.S --- linux-2.4.37.9/arch/arm/kernel/entry-armv.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/entry-armv.S Wed May 26 15:43:54 2010 @@ -566,7 +566,42 @@ .macro irq_prio_table .endm - + +#elif defined(CONFIG_ARCH_PSIONW) + +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, stat, base, mask + mov \base, #PSIONW_BASE + ldr \stat, [\base, #INTRSR] + ldr \mask, [\base, #INTENS] + mov \irqnr, #4 + mov \mask, \mask, lsl #16 + and \stat, \stat, \mask, lsr #16 + movs \stat, \stat, lsr #4 + bne 1001f + +1001: tst \stat, #255 + addeq \irqnr, \irqnr, #8 + moveq \stat, \stat, lsr #8 + tst \stat, #15 + addeq \irqnr, \irqnr, #4 + moveq \stat, \stat, lsr #4 + tst \stat, #3 + addeq \irqnr, \irqnr, #2 + moveq \stat, \stat, lsr #2 + tst \stat, #1 + addeq \irqnr, \irqnr, #1 + moveq \stat, \stat, lsr #1 + tst \stat, #1 @ bit 0 should be set + .endm + + .macro irq_prio_table + .endm + #elif defined (CONFIG_ARCH_CAMELOT) #include #undef IRQ_MODE /* same name defined in asm/proc/ptrace.h */ @@ -677,12 +712,11 @@ mrs r9, cpsr @ Enable interrupts if they were tst r3, #I_BIT biceq r9, r9, #I_BIT @ previously - mov r0, r2 @ *** remove once everyones in sync /* * This routine must not corrupt r9 */ #ifdef MULTI_CPU - ldr r4, .LCprocfns @ pass r0, r3 to + ldr r4, .LCprocfns @ pass r2, r3 to mov lr, pc @ processor code ldr pc, [r4] @ call processor specific code #else @@ -788,9 +822,8 @@ stmdb r5, {sp, lr}^ alignment_trap r7, r7, __temp_abt zero_fp - mov r0, r2 @ remove once everyones in sync #ifdef MULTI_CPU - ldr r4, .LCprocfns @ pass r0, r3 to + ldr r4, .LCprocfns @ pass r2, r3 to mov lr, pc @ processor code ldr pc, [r4] @ call processor specific code #else @@ -840,7 +873,8 @@ adrsvc al, r9, ret_from_exception @ r9 = normal FP return adrsvc al, lr, fpundefinstr @ lr = undefined instr return -call_fpe: get_current_task r10 +call_fpe: enable_irq r10 + get_current_task r10 mov r8, #1 strb r8, [r10, #TSK_USED_MATH] @ set current->used_math ldr r4, .LCfp diff -uNr linux-2.4.37.9/arch/arm/kernel/fiq.c linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/fiq.c --- linux-2.4.37.9/arch/arm/kernel/fiq.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/fiq.c Wed May 26 15:43:54 2010 @@ -122,23 +122,23 @@ register unsigned long tmp, tmp2; __asm__ volatile ( #ifdef CONFIG_CPU_26 - "mov %0, pc - bic %1, %0, #0x3 - orr %1, %1, %3 - teqp %1, #0 @ select FIQ mode - mov r0, r0 - ldmia %2, {r8 - r14} - teqp %0, #0 @ return to SVC mode - mov r0, r0" + "mov %0, pc \n" + "bic %1, %0, #0x3 \n" + "orr %1, %1, %3 \n" + "teqp %1, #0 @ select FIQ mode \n" + "mov r0, r0 \n" + "ldmia %2, {r8 - r14} \n" + "teqp %0, #0 @ return to SVC mode \n" + "mov r0, r0 \n" #endif #ifdef CONFIG_CPU_32 - "mrs %0, cpsr - mov %1, %3 - msr cpsr_c, %1 @ select FIQ mode - mov r0, r0 - ldmia %2, {r8 - r14} - msr cpsr_c, %0 @ return to SVC mode - mov r0, r0" + "mrs %0, cpsr \n" + "mov %1, %3 \n" + "msr cpsr_c, %1 @ select FIQ mode \n" + "mov r0, r0 \n" + "ldmia %2, {r8 - r14} \n" + "msr cpsr_c, %0 @ return to SVC mode \n" + "mov r0, r0 \n" #endif : "=&r" (tmp), "=&r" (tmp2) : "r" (®s->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE) @@ -154,23 +154,23 @@ register unsigned long tmp, tmp2; __asm__ volatile ( #ifdef CONFIG_CPU_26 - "mov %0, pc - bic %1, %0, #0x3 - orr %1, %1, %3 - teqp %1, #0 @ select FIQ mode - mov r0, r0 - stmia %2, {r8 - r14} - teqp %0, #0 @ return to SVC mode - mov r0, r0" + "mov %0, pc \n" + "bic %1, %0, #0x3 \n" + "orr %1, %1, %3 \n" + "teqp %1, #0 @ select FIQ mode \n" + "mov r0, r0 \n" + "stmia %2, {r8 - r14} \n" + "teqp %0, #0 @ return to SVC mode \n" + "mov r0, r0 \n" #endif #ifdef CONFIG_CPU_32 - "mrs %0, cpsr - mov %1, %3 - msr cpsr_c, %1 @ select FIQ mode - mov r0, r0 - stmia %2, {r8 - r14} - msr cpsr_c, %0 @ return to SVC mode - mov r0, r0" + "mrs %0, cpsr \n" + "mov %1, %3 \n" + "msr cpsr_c, %1 @ select FIQ mode \n" + "mov r0, r0 \n" + "stmia %2, {r8 - r14} \n" + "msr cpsr_c, %0 @ return to SVC mode \n" + "mov r0, r0 \n" #endif : "=&r" (tmp), "=&r" (tmp2) : "r" (®s->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE) diff -uNr linux-2.4.37.9/arch/arm/kernel/head-armv.S linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/head-armv.S --- linux-2.4.37.9/arch/arm/kernel/head-armv.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/head-armv.S Wed May 26 15:43:54 2010 @@ -1,7 +1,7 @@ /* * linux/arch/arm/kernel/head-armv.S * - * Copyright (C) 1994-1999 Russell King + * Copyright (C) 1994-2003 Russell King * * 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 @@ -130,7 +130,22 @@ */ mov r1, #MACH_TYPE_L7200 #endif - +#if defined(CONFIG_ARCH_PSIONW) /* PSIONW_NONSTANDARD */ + /* + * FIXME5MX Interrupts should be disabled in the boot loader. + * This will cause the kernel not to boot after early 2.4 + * kernels, as the save_and_disable_irqs assumes that fiqs + * are on. If the interrupts are not turned off, this will + * cause the system to hang. Hard to track down too, btw. + * For development, you may want to temporarily use + * mov \temp, #I_BIT | F_BIT | MODE_SVC in function + * save_and_disable_irqs if you are having trouble booting. + */ + mov r8, #0x80000000 @ physical base + mov r9, #0xff00 @ create 0xffff + add r9, r9, #0x00ff @ with two steps + str r9, [r8, #0x050c] @ write to INTENC +#endif mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode msr cpsr_c, r0 @ and all irqs disabled bl __lookup_processor_type @@ -163,10 +178,10 @@ */ .type __ret, %function __ret: ldr lr, __switch_data - mcr p15, 0, r0, c1, c0 - mrc p15, 0, r0, c1, c0, 0 @ read it back. - mov r0, r0 - mov r0, r0 + mcr p15, 0, r0, c1, c0, 0 + mrc p15, 0, r3, c0, c0, 0 + mov r3, r3 + mov r3, r3 mov pc, lr /* @@ -214,6 +229,11 @@ */ __create_page_tables: pgtbl r4, r5 @ page table address +#if defined(CONFIG_CPU_DCACHE_DISABLE) + bic r8, r8, #0x00c @ clear B, C +#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH) + bic r8, r8, #0x004 @ clear B +#endif /* * Clear the 16K level 1 swapper page table diff -uNr linux-2.4.37.9/arch/arm/kernel/irq.c linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/irq.c --- linux-2.4.37.9/arch/arm/kernel/irq.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/irq.c Wed May 26 15:43:54 2010 @@ -145,7 +145,7 @@ *p++ = '\n'; } -#ifdef CONFIG_ARCH_ACORN +#if defined(CONFIG_ARCH_ACORN) || defined(CONFIG_ARCH_PSIONW) p += get_fiq_list(p); #endif p += sprintf(p, "Err: %10lu\n", irq_err_count); @@ -549,7 +549,7 @@ kfree(action); goto out; } - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); + printk(KERN_ERR "Trying to free IRQ%d\n",irq); #ifdef CONFIG_DEBUG_ERRORS __backtrace(); #endif diff -uNr linux-2.4.37.9/arch/arm/kernel/psionw_pm.c linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/psionw_pm.c --- linux-2.4.37.9/arch/arm/kernel/psionw_pm.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/psionw_pm.c Wed May 26 15:43:54 2010 @@ -0,0 +1,116 @@ +/* + * Psion battery FIQ handler. Copyright 2002 Tony Lindgren + * + * Modeled after Russell King's dma-rpc.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +static struct fiq_handler extfiq_fh = { + name: "extfiq" +}; + +static struct fiq_handler blint_fh = { + name: "blint" +}; + +/* + * Sets up a handler for the external fiq + * NOTE: Not currently in use as Linux does not + * currently support sharing the fiq vector. + */ +static void extfiq_handler_setup(void) +{ + void *fiqhandler_start; + unsigned int fiqhandler_length; + struct pt_regs regs; + extern unsigned char extfiq_handler_start, extfiq_handler_end; + + printk("FIQ: Setting up handler for external fast interrupt\n"); + + fiqhandler_start = &extfiq_handler_start; + fiqhandler_length = &extfiq_handler_end - &extfiq_handler_start; + + if (claim_fiq(&extfiq_fh)) { + printk("FIQ: Could not claim fast interrupt\n"); + return; + } + + set_fiq_handler(fiqhandler_start, fiqhandler_length); + set_fiq_regs(®s); + + enable_fiq(IRQ_EXTFIQ); +} + +/* + * Sets up a handler for the battery low fiq + */ +static void blint_fiq_handler_setup(void) +{ + void *fiqhandler_start; + unsigned int fiqhandler_length; + struct pt_regs regs; + extern unsigned char blint_fiq_handler_start, blint_fiq_handler_end; + + printk("FIQ: Setting up handler for battery low fast interrupt\n"); + + fiqhandler_start = &blint_fiq_handler_start; + fiqhandler_length = &blint_fiq_handler_end - &blint_fiq_handler_start; + + if (claim_fiq(&blint_fh)) { + printk("FIQ: Could not claim fast interrupt\n"); + return; + } + + set_fiq_handler(fiqhandler_start, fiqhandler_length); + set_fiq_regs(®s); + psionw_writel(1, BLEOI); + enable_fiq(IRQ_BLINT); +} + +static int __init psionw_pm_init(void) +{ + printk("FIQ: Initializing Psion fast interrupts\n"); + //extfiq_handler_setup(); + blint_fiq_handler_setup(); +} + +static void __exit psionw_pm_exit(void) +{ + printk("FIQ: Disabling Psion fast interrupts\n"); + + //disable_fiq(IRQ_EXTFIQ); + //release_fiq(&extfiq_fh); + + disable_fiq(IRQ_BLINT); + release_fiq(&blint_fh); +} + + +EXPORT_NO_SYMBOLS; + +MODULE_LICENSE("GPL"); + +module_init(psionw_pm_init); +module_exit(psionw_pm_exit); diff -uNr linux-2.4.37.9/arch/arm/kernel/ptrace.c linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/ptrace.c --- linux-2.4.37.9/arch/arm/kernel/ptrace.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/ptrace.c Wed May 26 15:43:54 2010 @@ -725,11 +725,8 @@ goto out_tsk; } ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - if (child->state != TASK_STOPPED && request != PTRACE_KILL) - goto out_tsk; - if (child->p_pptr != current) + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret) goto out_tsk; ret = do_ptrace(request, child, addr, data); diff -uNr linux-2.4.37.9/arch/arm/kernel/semaphore.c linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/semaphore.c --- linux-2.4.37.9/arch/arm/kernel/semaphore.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/semaphore.c Wed May 26 15:43:54 2010 @@ -193,7 +193,7 @@ bl __down_interruptible \n\ mov ip, r0 \n\ ldmfd sp!, {r0 - r3, pc}^ \n\ - + \n\ .align 5 \n\ .globl __down_trylock_failed \n\ __down_trylock_failed: \n\ diff -uNr linux-2.4.37.9/arch/arm/kernel/signal.c linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/signal.c --- linux-2.4.37.9/arch/arm/kernel/signal.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/kernel/signal.c Wed May 26 15:43:54 2010 @@ -641,10 +641,7 @@ /* FALLTHRU */ default: - sigaddset(¤t->pending.signal, signr); - recalc_sigpending(current); - current->flags |= PF_SIGNALED; - do_exit(exit_code); + sig_exit(signr, exit_code, &info); /* NOTREACHED */ } } diff -uNr linux-2.4.37.9/arch/arm/lib/Makefile linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/Makefile --- linux-2.4.37.9/arch/arm/lib/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/Makefile Wed May 26 15:44:02 2010 @@ -15,7 +15,7 @@ strnlen_user.o strchr.o strrchr.o testchangebit.o \ testclearbit.o testsetbit.o uaccess.o getuser.o \ putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ - ucmpdi2.o udivdi3.o lib1funcs.o + ucmpdi2.o udivdi3.o lib1funcs.o div64.o obj-m := obj-n := @@ -26,6 +26,7 @@ obj-clps7500 := io-acorn.o obj-l7200 := io-acorn.o obj-shark := io-shark.o +obj-psionw := psionwfiqs.o obj-edb7211 := io-acorn.o obj-riscstation := io-acorn.o floppydma.o diff -uNr linux-2.4.37.9/arch/arm/lib/div64.S linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/div64.S --- linux-2.4.37.9/arch/arm/lib/div64.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/div64.S Wed May 26 15:44:02 2010 @@ -0,0 +1,59 @@ +#include + +#ifndef __ARMEB__ +ql .req r0 @ quotient low +qh .req r1 @ quotient high +onl .req r0 @ original dividend low +onh .req r1 @ original dividend high +nl .req r4 @ dividend low +nh .req r5 @ dividend high +res .req r4 @ result +#else +ql .req r1 +qh .req r0 +onl .req r1 +onh .req r0 +nl .req r5 +nh .req r4 +res .req r5 +#endif + +dl .req r3 @ divisor low +dh .req r2 @ divsor high + + +ENTRY(do_div64) + stmfd sp!, {r4, r5, lr} + mov nl, onl + movs nh, onh @ if high bits are zero + movne lr, #33 + moveq lr, #1 @ only divide low bits + moveq nh, onl + + tst dh, #0x80000000 + bne 2f +1: cmp nh, dh + bls 2f + add lr, lr, #1 + movs dh, dh, lsl #1 @ left justify disor + bpl 1b + +2: movs nh, onh + moveq dl, dh + moveq dh, #0 + movne dl, #0 + mov ql, #0 + mov qh, #0 +3: subs ip, nl, dl @ trial subtraction + sbcs ip, nh, dh + movcs nh, ip @ only update if successful + subcs nl, nl, dl @ (repeat the subtraction) + adcs ql, ql, ql @ C=1 if successful, shift into + adc qh, qh, qh @ quotient + movs dh, dh, lsr #1 @ shift base high part right + mov dl, dl, rrx @ shift base low part right + subs lr, lr, #1 + bne 3b + + mov r2, res + ldmfd sp!, {r4, r5, pc} diff -uNr linux-2.4.37.9/arch/arm/lib/psionwfiqs.S linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/psionwfiqs.S --- linux-2.4.37.9/arch/arm/lib/psionwfiqs.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/psionwfiqs.S Wed May 26 15:44:02 2010 @@ -0,0 +1,37 @@ +/* + * linux/arch/arm/lib/psionwblint.S + * + * Copyright (C) 2002 Tony Lindgren + * + * Modeled after Russel King's floppydma.S + * + * 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 +#include +#include + .text + + .global SYMBOL_NAME(extfiq_handler_end) +ENTRY(extfiq_handler_start) + mov r11, #0xdf000000 @ VBASE + mov r12, #'E' + strb r12, [r11, #0x700] @ UART2 + subs pc, lr, #4 @ return +SYMBOL_NAME(extfiq_handler_end): + + .global SYMBOL_NAME(blint_fiq_handler_end) +ENTRY(blint_fiq_handler_start) + mov r11, #0xdf000000 @ VBASE + str r11, [r11, #0x0410] @ write to BLEOI + + ldr r12, [r11, #0x0e08] @ load PCDR + bic r12, r12, #0x10 @ clear PCDR_LIGHT + str r12, [r11, #0x0e08] @ write PCDR + + mov r12, #'B' + strb r12, [r11, #0x700] @ UART2 + subs pc, lr, #4 @ return +SYMBOL_NAME(blint_fiq_handler_end): diff -uNr linux-2.4.37.9/arch/arm/lib/putuser.S linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/putuser.S --- linux-2.4.37.9/arch/arm/lib/putuser.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/lib/putuser.S Wed May 26 15:44:02 2010 @@ -30,11 +30,11 @@ .global __put_user_1 __put_user_1: - bic r2, sp, #0x1f00 - bic r2, r2, #0x00ff - ldr r2, [r2, #TSK_ADDR_LIMIT] - sub r2, r2, #1 - cmp r0, r2 + bic ip, sp, #0x1f00 + bic ip, ip, #0x00ff + ldr ip, [ip, #TSK_ADDR_LIMIT] + sub ip, ip, #1 + cmp r0, ip 1: strlsbt r1, [r0] movls r0, #0 movls pc, lr @@ -42,11 +42,11 @@ .global __put_user_2 __put_user_2: - bic r2, sp, #0x1f00 - bic r2, r2, #0x00ff - ldr r2, [r2, #TSK_ADDR_LIMIT] - sub r2, r2, #2 - cmp r0, r2 + bic ip, sp, #0x1f00 + bic ip, ip, #0x00ff + ldr ip, [ip, #TSK_ADDR_LIMIT] + sub ip, ip, #2 + cmp r0, ip 2: strlsbt r1, [r0], #1 movls r1, r1, lsr #8 3: strlsbt r1, [r0] @@ -56,11 +56,11 @@ .global __put_user_4 __put_user_4: - bic r2, sp, #0x1f00 - bic r2, r2, #0x00ff - ldr r2, [r2, #TSK_ADDR_LIMIT] - sub r2, r2, #4 - cmp r0, r2 + bic ip, sp, #0x1f00 + bic ip, ip, #0x00ff + ldr ip, [ip, #TSK_ADDR_LIMIT] + sub ip, ip, #4 + cmp r0, ip 4: strlst r1, [r0] movls r0, #0 movls pc, lr diff -uNr linux-2.4.37.9/arch/arm/mach-at91rm9200/Makefile linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-at91rm9200/Makefile --- linux-2.4.37.9/arch/arm/mach-at91rm9200/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-at91rm9200/Makefile Wed May 26 15:44:00 2010 @@ -18,4 +18,8 @@ export-objs := +# LEDs support +leds-$(CONFIG_ARCH_AT91RM9200DK) += dk-leds.o +obj-$(CONFIG_LEDS) += $(leds-y) + include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/arch/arm/mach-at91rm9200/dk-leds.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-at91rm9200/dk-leds.c --- linux-2.4.37.9/arch/arm/mach-at91rm9200/dk-leds.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-at91rm9200/dk-leds.c Wed May 26 15:44:00 2010 @@ -0,0 +1,97 @@ +/* + * LED driver for the Atmel AT91RM9200 Development Kit. + * + * (c) SAN People (Pty) Ltd + * + * 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 +#include +#include +#include + +#include +#include +#include +#include + + +static inline void at91_led_on(void) +{ + AT91_SYS->PIOB_CODR = AT91C_PIO_PB2; +} + +static inline void at91_led_off(void) +{ + AT91_SYS->PIOB_SODR = AT91C_PIO_PB2; +} + +static inline void at91_led_toggle(void) +{ + unsigned long curr = AT91_SYS->PIOB_ODSR; + if (curr & AT91C_PIO_PB2) + AT91_SYS->PIOB_CODR = AT91C_PIO_PB2; + else + AT91_SYS->PIOB_SODR = AT91C_PIO_PB2; +} + + +/* + * Handle LED events. + */ +static void at91rm9200dk_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch(evt) { + case led_start: /* System startup */ + at91_led_on(); + break; + + case led_stop: /* System stop / suspend */ + at91_led_off(); + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: /* Every 50 timer ticks */ + at91_led_toggle(); + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: /* Entering idle state */ + at91_led_off(); + break; + + case led_idle_end: /* Exit idle state */ + at91_led_on(); + break; +#endif + + default: + break; + } + + local_irq_restore(flags); +} + + +static int __init leds_init(void) +{ + /* Enable PIO to access the LEDs */ + AT91_SYS->PIOB_PER = AT91C_PIO_PB2; + AT91_SYS->PIOB_OER = AT91C_PIO_PB2; + + leds_event = at91rm9200dk_leds_event; + + leds_event(led_start); + return 0; +} + +__initcall(leds_init); diff -uNr linux-2.4.37.9/arch/arm/mach-integrator/pci_v3.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-integrator/pci_v3.c --- linux-2.4.37.9/arch/arm/mach-integrator/pci_v3.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-integrator/pci_v3.c Wed May 26 15:43:54 2010 @@ -21,7 +21,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include #include #include #include @@ -32,6 +31,7 @@ #include #include +#include #include #include #include @@ -447,15 +447,16 @@ #define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20) #define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24) -static int v3_fault(unsigned long addr, struct pt_regs *regs) +static int +v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { unsigned long pc = instruction_pointer(regs); unsigned long instr = *(unsigned long *)pc; #if 0 char buf[128]; - sprintf(buf, "V3 fault: address=0x%08lx, pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n", - addr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255, + sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n", + addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255, v3_readb(V3_LB_ISTAT)); printk(KERN_DEBUG "%s", buf); printascii(buf); @@ -523,8 +524,6 @@ #endif } -extern int (*external_fault)(unsigned long addr, struct pt_regs *regs); - /* * V3_LB_BASE? - local bus address * V3_LB_MAP? - pci bus address @@ -539,7 +538,10 @@ /* * Hook in our fault handler for PCI errors */ - external_fault = v3_fault; + hook_fault_code(4, v3_pci_fault, SIGBUS, "external abort on linefetch"); + hook_fault_code(6, v3_pci_fault, SIGBUS, "external abort on linefetch"); + hook_fault_code(8, v3_pci_fault, SIGBUS, "external abort on non-linefetch"); + hook_fault_code(10, v3_pci_fault, SIGBUS, "external abort on non-linefetch"); spin_lock_irqsave(&v3_lock, flags); @@ -629,7 +631,7 @@ #if 0 ret = request_irq(IRQ_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL); if (ret) - printk(KERN_ERR "PCI: unable to grab local bus timeout ". + printk(KERN_ERR "PCI: unable to grab local bus timeout " "interrupt: %d\n", ret); #endif } diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/Makefile linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/Makefile --- linux-2.4.37.9/arch/arm/mach-psionw/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/Makefile Wed May 26 15:43:59 2010 @@ -0,0 +1,27 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +USE_STANDARD_AS_RULE := true + +O_TARGET := psionw.o + +# Object file lists. + +obj-y := irq.o mm.o psionw-arch.o psionw-hardware.o +obj-m := +obj-n := +obj- := + +export-objs := psionw-time.o psionw-leds.o psionw-power.o serial-debug.o + +obj-$(CONFIG_ARCH_PSIONW) += psionw-time.o psionw-leds.o psionw-power.o serial-debug.o + +leds-$(CONFIG_ARCH_PSIONW) += psionw-leds.o +obj-$(CONFIG_LEDS) += $(leds-y) + +include $(TOPDIR)/Rules.make + diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/irq.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/irq.c --- linux-2.4.37.9/arch/arm/mach-psionw/irq.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/irq.c Wed May 26 15:43:59 2010 @@ -0,0 +1,217 @@ +/* + * linux/arch/arm/mach-psionw/irq.c + * + * Copyright (C) 2001 Yuji Shinokawa + * Copyright (C) 2001 Tony Lindgren + * + * 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 + * + */ +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +static int debug_on; +static struct irqaction *etna_action = NULL; + +#if CONFIG_PCMCIA_ETNA +extern void etna_interrupt(void); + +static struct tq_struct etna_int_task = { + routine:etna_interrupt +}; +#endif + +static void +unmask_irq_int(unsigned int irq); + +static void +mask_irq_int(unsigned int irq) +{ + u32 intmr; + intmr = (1 << irq); + psionw_writel(intmr, INTENC); +} + +#ifdef CONFIG_PCMCIA_ETNA +static void +mask_etna_irq(unsigned int irq) +{ + int etna_int, count = 0; + mask_irq_int(irq); + + etna_int = etna_readb(ETNA_INT_STATUS); + etna_action = irq_desc[irq].action; + + //printk("i0x%x ", etna_int); + + switch (etna_int) { + case (0x00): /* Card removed interrupt */ + irq_desc[irq].action = NULL; + printk("ETNA: Card removed\n"); + schedule_task(&etna_int_task); + break; + case (0x01): /* Card got hosed */ + irq_desc[irq].action = NULL; + while (etna_int == 0x01) { + count++; + schedule_task(&etna_int_task); + mdelay(500); + etna_int = etna_readb(ETNA_INT_STATUS); + if (count >= 5) { + printk("ETNA: Socket stuck, reinsert the card\n"); + break; + } + } + break; + case (0x03): + break; /* Network after nfs mount */ + case (0x05): /* Normal IDE interrupt */ + break; + case (0x07): /* Normal network interrupt */ + break; + case (0x3f): /* First write after sleep mode */ + case (0x35): /* First write after sleep mode */ + //irq_desc[IRQ_EINT1].action = NULL; + break; + default: + printk("ETNA: Unknown interrupt status: 0x%x\n", etna_int); + schedule_task(&etna_int_task); + } + + /* + * You would assume that we need to disable Etna interrupt + * until we're done? Nope, that causes delays in waking up + * the card for 16-bit writes in etna_outsw_ide. + */ + //etna_writeb(0, ETNA_INT_MASK); + + /* Clear the Etna interrupt */ + etna_writeb(ETNA_CLEAR_MASK, ETNA_INT_CLEAR); +} + +static void +unmask_etna_irq(unsigned int irq) +{ + int etna_int_mask; + + etna_int_mask = etna_readb(ETNA_INT_MASK); + while (etna_int_mask & (1 << 2)) { + printk("ETNA: Bad ETNA_INT_MASK: 0x%02x\n", + etna_readb(ETNA_INT_STATUS)); + etna_writeb(0, ETNA_INT_MASK); + etna_writeb(ETNA_CF_IRQ, ETNA_INT_CLEAR); + etna_int_mask = etna_readb(ETNA_INT_MASK); + } + + if (irq_desc[irq].action == NULL) + irq_desc[irq].action = etna_action; + + /* Let's enable the Etna interrupt again */ + etna_writeb(ETNA_CF_IRQ, ETNA_INT_MASK); + unmask_irq_int(irq); +} +#endif /* CONFIG_PCMCIA_ETNA */ + +static void +mask_ack_irq_int(unsigned int irq) +{ + switch (irq) { + case IRQ_CSINT: + psionw_writel(1, COEOI); + printk("Received and cleared CSINT irq %d\n", irq); + break; + case IRQ_EINT2: + psionw_writel(1, E2EOI); + printk("Received and cleared EINT2 irq %d\n", irq); + break; + case IRQ_TC1OI: + psionw_writel(1, TC1EOI); /* Cleared here, handled in rtc */ + break; + case IRQ_TC2OI: + psionw_writel(1, TC2EOI); /* Cleared here, handled in timer */ + break; + case IRQ_RTCMI: + psionw_writel(1, RTCEOI); /* Cleared here, handled in rtc*/ + break; + case IRQ_TINT: + psionw_writel(1, TEOI); + printk("Received and cleared TINT irq %d\n", irq); + break; + } +} + +static void +unmask_irq_int(unsigned int irq) +{ + u32 intmr; + intmr = (1 << irq); + psionw_writel(intmr, INTENS); +} + +void __init +psionw_init_irq(void) +{ + unsigned int i; + + for (i = 0; i < NR_IRQS; i++) { + if (INT1_IRQS & (1 << i)) { + irq_desc[i].valid = 1; + irq_desc[i].probe_ok = 1; + irq_desc[i].mask_ack = (INT1_ACK_IRQS & (1 << i)) ? + mask_ack_irq_int : mask_irq_int; + irq_desc[i].mask = mask_irq_int; + irq_desc[i].unmask = unmask_irq_int; + } + } + + /* + * Disable interrupts + */ + psionw_writel(~0, INTENC); + + /* + * Clear down any pending interrupts + */ + psionw_writel(0, MCEOI); + psionw_writel(0, BLEOI); + psionw_writel(0, COEOI); + psionw_writel(0, TC1EOI); + psionw_writel(0, TC2EOI); + psionw_writel(0, RTCEOI); + psionw_writel(0, TEOI); + psionw_writel(0, UMSEOI); + psionw_writel(0, SSCR0); + +#ifdef CONFIG_PCMCIA_ETNA + irq_desc[IRQ_EINT1].mask_ack = mask_etna_irq; + irq_desc[IRQ_EINT1].unmask = unmask_etna_irq; + + /* Enable the ETNA interrupts */ + __raw_writeb(ETNA_CF_IRQ, ETNA_V_BASE + ETNA_INT_MASK); +#endif + + init_FIQ(); +} diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/mm.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/mm.c --- linux-2.4.37.9/arch/arm/mach-psionw/mm.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/mm.c Wed May 26 15:43:59 2010 @@ -0,0 +1,50 @@ +/* + * linux/arch/arm/mach-psionw/mm.c + * + * Copyright (C) 2000 Tony Lindgren + * + * 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 + */ +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#define HOLE 0x000 + +/* + * Logical Physical + */ +static struct map_desc psionw_io_desc[] __initdata = { + {PSIONW_VIRT_BASE, PSIONW_PHYS_BASE, 0x10000, DOMAIN_IO, 0, 1}, + {ETNA_V_BASE, ETNA_P_BASE, ETNA_SIZE, DOMAIN_IO, 0, 1}, + {CF1_V_BASE, CF1_P_BASE, CF_SIZE, DOMAIN_IO, 0, 1}, + {PSION_V_BR, PSION_P_BR, PSION_BR_SIZE, DOMAIN_IO, 0, 1}, + {PSION_V_BF, PSION_P_BF, PSION_BF_SIZE, DOMAIN_IO, 0, 1}, + LAST_DESC +}; + +void __init +psionw_map_io(void) +{ + iotable_init(psionw_io_desc); +} diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/psionw-arch.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-arch.c --- linux-2.4.37.9/arch/arm/mach-psionw/psionw-arch.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-arch.c Wed May 26 15:43:59 2010 @@ -0,0 +1,109 @@ +/* + * linux/arch/arm/mach-psionw/psionw.c + * + * Copyright (C) 2001 Tony Lindgren + * + * Based on the mach-sa1100 code, some portions of the code + * Copyright (C) 2000 Nicolas Pitre . + * + * 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 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern void psionw_init_irq(void); +extern void psionw_map_io(void); + +#define SET_BANK(__nr,__start,__size) \ + mi->bank[__nr].start = (__start), \ + mi->bank[__nr].size = (__size), \ + mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) + +static void __init +fixup_psionw(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + +#if defined(CONFIG_PSIONW_5MX) || defined(CONFIG_PSIONW_5MXPRO16MB) + SET_BANK(0, 0xc0000000, 8 * 1024 * 1024); + SET_BANK(1, 0xc1000000, 8 * 1024 * 1024); + mi->nr_banks = 2; +#elif CONFIG_PSIONW_5MXPRO24MB + /* Chris Halls */ + SET_BANK(0, 0xc0000000, 8 * 1024 * 1024); + SET_BANK(1, 0xc1000000, 8 * 1024 * 1024); + SET_BANK(2, 0xd0000000, 4 * 1024 * 1024); + SET_BANK(3, 0xd0800000, 4 * 1024 * 1024); + mi->nr_banks = 4; +#elif CONFIG_PSIONW_5MXPRO32MB + /* Provided by Thilo Hille */ + SET_BANK(0, 0xc0000000, 8 * 1024 * 1024); + SET_BANK(1, 0xc1000000, 8 * 1024 * 1024); + SET_BANK(2, 0xd0000000, 8 * 1024 * 1024); + SET_BANK(3, 0xd1000000, 8 * 1024 * 1024); + mi->nr_banks = 4; +#elif CONFIG_PSIONW_REVO + /* This seems to be correct */ + SET_BANK(0, 0xc0000000, 4 * 1024 * 1024); + SET_BANK(1, 0xc0800000, 4 * 1024 * 1024); + mi->nr_banks = 2; +#elif CONFIG_PSIONW_REVOPLUS + /* Provided by Ilmar Kotte */ + SET_BANK(0, 0xc0000000, 4 * 1024 * 1024); + SET_BANK(1, 0xc0800000, 4 * 1024 * 1024); + SET_BANK(2, 0xd0000000, 4 * 1024 * 1024); + SET_BANK(3, 0xd0800000, 4 * 1024 * 1024); + mi->nr_banks = 4; +#else +#error Unknown machine type! +#endif + + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + + /* Merge the command line options from kernel and boot loader */ + strcat(*cmdline, " "); + strcat(*cmdline, params->commandline); + strcpy(params->commandline, *cmdline); +} + +MACHINE_START(PSIONW, "Psion Windermere NEC ARM-710T") +MAINTAINER("Tony Lindgren") +BOOT_MEM(0xc0000000, 0x80000000, 0xdf000000) + +/* + * VIDEO() does not poke a hole to bootmem. + * See arch/arm/arm/mm/init.c. + */ +VIDEO(0xc000d000, 0xc000d000 + LCD_MEM_SIZE) + +/* Must sync with TEXTADDR */ +BOOT_PARAMS(0xc0048000 - (128 * 1024)) + +FIXUP(fixup_psionw) +MAPIO(psionw_map_io) +INITIRQ(psionw_init_irq) +MACHINE_END diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/psionw-hardware.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-hardware.c --- linux-2.4.37.9/arch/arm/mach-psionw/psionw-hardware.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-hardware.c Wed May 26 15:43:59 2010 @@ -0,0 +1,45 @@ +/* + * linux/arch/arm/mach-psionw/hardware.c + * + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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 + */ +#include +#include + +#include +#include + +#include + +/* + * Shut down all unnecessary hardware + */ +static int +psionw_hw_init(void) +{ + if (psionw_readb(PCDR) & PCDR_UART1) { + psionw_writeb(psionw_readb(PCDR) & ~PCDR_UART1, PCDR); + } + + if (psionw_readb(PCDR) & PCDR_UART2) { + //psionw_writeb(psionw_readb(PCDR) & ~PCDR_UART2, PCDR); + } + + return 0; +} + +__initcall(psionw_hw_init); diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/psionw-leds.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-leds.c --- linux-2.4.37.9/arch/arm/mach-psionw/psionw-leds.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-leds.c Wed May 26 15:43:59 2010 @@ -0,0 +1,74 @@ +/* + * linux/arch/arm/mach-psionw/leds.c + * + * Psionw LED control routines + * + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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 + */ +#include +#include + +#include +#include +#include +#include +#include + +#include + +static void psionw_leds_event(led_event_t ledevt) +{ + unsigned long flags; + u32 port; + + local_irq_save(flags); + switch(ledevt) { + case led_idle_start: + /* + * Turn off red front led when entering idle. + * The led then shows the current CPU load. + */ + port = psionw_readb(PDDR); + psionw_writeb(port & ~PDDR_SLED, PDDR); + break; + + case led_idle_end: + /* Turn on red front led when not idle*/ + port = psionw_readb(PDDR); + psionw_writeb(port | PDDR_SLED, PDDR); + break; + + case led_timer: + /* FIXME5MX Blink the green top led, does not work */ + port = psionw_readb(PCDR); + //psionw_writeb(port ^ PCDR_PLED, PCDR); + break; + + default: + break; + } + + local_irq_restore(flags); +} + +static int __init leds_init(void) +{ + leds_event = psionw_leds_event; + return 0; +} + +__initcall(leds_init); diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/psionw-power.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-power.c --- linux-2.4.37.9/arch/arm/mach-psionw/psionw-power.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-power.c Wed May 26 15:43:59 2010 @@ -0,0 +1,252 @@ +/* + * arch/arm/mach-psionw/psionw-power.c - Psion power managemenent + * + * Copyright (C) 2002 Tony Lindgren + * + * Contrast restore after sleep fix (C) 2002 by Simon Howard + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void disable_irq(unsigned int irq); +extern void enable_irq(unsigned int irq); +extern void psionw_lcd_powerdown(int lock); +extern void psionw_lcd_powerup(int lock); +extern void etna_powerdown(int lock); +extern void etna_powerup(int lock); +extern void ssi5mx_powerdown(int lock); +extern void ssi5mx_powerup(int lock); +extern int psion_set_contrast(int new_contrast, int lock); +extern int psion_get_contrast(void); + + +static int psion_rtc_off; + +/* + * Stops the DC to DC converter + */ +void stop_pump(int lock) +{ + long flags = 0; + + if (lock) + save_flags_cli(flags); + + psionw_writel(PUMP_STOP_VAL,PUMPCON); + psionw_writeb(psionw_readb(PDDR) & ~PDDR_PUMP_PWR1, PDDR); + + if (lock) + restore_flags(flags); +} + +void stop_timer(int lock) +{ + unsigned int cfg; + unsigned long goto_sleep; + long flags = 0; + + if (lock) + save_flags_cli(flags); + + psion_rtc_off = xtime.tv_sec - RTCTIME; + + goto_sleep = jiffies; + do { + disable_irq(IRQ_TC2OI); + } while (time_after(jiffies, goto_sleep + HZ/50)); + cfg = psionw_readl(TC2CTRL); + cfg &= ~TC_ENABLE; + psionw_writel(cfg, TC2CTRL); + + if (lock) + restore_flags(flags); +} + +void start_timer(int lock) +{ + unsigned int cfg; + long flags = 0; + + if (lock) + save_flags_cli(flags); + + cfg = psionw_readl(TC2CTRL); + + /* These bits need to initialized to 0 */ + cfg &= ~TC_BIT2; + cfg &= ~TC_BIT4; + cfg &= ~TC_BIT5; + cfg |= TC_CLKSEL; // 512kHz mode + cfg |= TC_MODE; + cfg |= TC_ENABLE; + + psionw_writel(cfg, TC2CTRL); + psionw_writel(5119, TC2LOAD); /* 512kHz / 100Hz - 1 */ + + psionw_writel(1, TC2EOI); + enable_irq(IRQ_TC2OI); + + if (lock) + restore_flags(flags); + + /* Set the correct time from RTC */ + xtime.tv_sec = RTCTIME; + xtime.tv_sec += psion_rtc_off; +} + +/* + * Puts the Psion into sleep mode until a keyboard, serial, + * touch panel, or RTC interrupt is received. + */ +void psion_off(void) +{ + int adc_clock = 0, rfdiv = 0, rtcdiv1 = 0, rtcdiv2 = 0; + int uart1 = 0, uart2 = 0; + long flags; + + if (psionw_readl(PDDR) & PDDR_PUMP_PWR1) { + + save_flags_cli(flags); + if (psionw_readb(PCDR) & PCDR_UART1) { + uart1 = 1; + //printk("Looks like UART1 is on\n"); + psionw_writeb(psionw_readb(PCDR) & ~PCDR_UART1, PCDR); + } + + if (psionw_readb(PCDR) & PCDR_UART2) { + uart2 = 1; + //printk("Looks like UART2 is on\n"); + psionw_writeb(psionw_readb(PCDR) & ~PCDR_UART2, PCDR); + } + restore_flags(flags); + + /* First we must stop the timer */ + stop_timer(1); + + /* + * We establish a long lock for the whole sleep-wake procedure + */ + save_flags_cli(flags); + + psionw_writeb(psionw_readb(PDDR) & ~PDDR_SLED, PDDR); + psionw_writel(0, KSCAN); + ssi5mx_powerdown(0); /* SSI, saves only about 0.1mA */ + +#ifdef CONFIG_PCMCIA_ETNA + etna_powerdown(0); +#endif + + psionw_lcd_powerdown(0); + stop_pump(0); /* DC to DC, saves about 0.5mA */ + + /* Lower the DRAM refresh to 1 KHz, no real savings */ + rfdiv = psionw_readl(DRAM_CFG) & 0x7f; + psionw_writel(psionw_readl(DRAM_CFG) | 0x7f, DRAM_CFG); + + /* Disable the ADC clock, no real savings */ + adc_clock = (psionw_readl(PWRCNT) >> 8) & 0xff; + psionw_writel(psionw_readl(PWRCNT) | (0xff << 8), PWRCNT); + + cpu_cache_clean_invalidate_all(); + + rtcdiv1 = psionw_readb(PWRSR) & 0x3f; + while(rtcdiv1 == rtcdiv2) { + rtcdiv2 = psionw_readb(PWRSR) & 0x3f; + } + while(rtcdiv2 == rtcdiv1) { + rtcdiv1 = psionw_readb(PWRSR) & 0x3f; + } + + /* Now go to sleep */ + psionw_writel(1, STBY); + __asm__ __volatile__("\n" + "mov r0, r0\n" + "mov r0, r0\n" + "mov r0, r0\n" + ); + + /* We're back from sleep */ + + /* Restore the ADC clock */ + psionw_writel(psionw_readl(PWRCNT) & ~(0xff << 8), PWRCNT); + psionw_writel(psionw_readl(PWRCNT) | (adc_clock << 8), PWRCNT); + + /* Restore DRAM refresh rate */ + psionw_writel(psionw_readl(DRAM_CFG) & ~0x7f, DRAM_CFG); + psionw_writel(psionw_readl(DRAM_CFG) | rfdiv, DRAM_CFG); + + start_pump(0); + psionw_lcd_powerup(0); + + /* Restore contrast */ + psion_set_contrast(psion_get_contrast(), 1); + +#ifdef CONFIG_PCMCIA_ETNA + etna_powerup(0); +#endif + + ssi5mx_powerup(0); + + /* + * And finally we release the long lock + */ + restore_flags(flags); + start_timer(1); + + save_flags_cli(flags); + if (uart1) + psionw_writeb(psionw_readb(PCDR) | PCDR_UART1, PCDR); + + if (uart2) + psionw_writeb(psionw_readb(PCDR) | PCDR_UART2, PCDR); + restore_flags(flags); + + } else { + /* Just in case the LCD is off */ + psionw_lcd_powerup(1); + } +} + +/* + * Returns the CPU speed + */ +unsigned int psionw_get_cpu_speed(int cpu) +{ + int speed; + speed = (psionw_readl(PWRCNT) & 0x7) >> 2; + if (speed) { + return 36864000; + } else { + return 11432000; + } +} + +/* + * Changes the CPU speed + */ +void psionw_set_cpu_speed(int speed) +{ + int pwrcnt; + long flags = 0; + + save_flags_cli(flags); + cpu_cache_clean_invalidate_all(); + pwrcnt = psionw_readl(PWRCNT); + if (speed) { + pwrcnt |= (1 << 2); + printk("Setting the CPU speed to 36Mhz\n"); + psionw_writel(pwrcnt, PWRCNT); + } else { + pwrcnt &= ~(1 << 2); + printk("Setting the CPU speed to 18Mhz\n"); + psionw_writel(pwrcnt, PWRCNT); + } + restore_flags(flags); +} diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/psionw-time.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-time.c --- linux-2.4.37.9/arch/arm/mach-psionw/psionw-time.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/psionw-time.c Wed May 26 15:43:59 2010 @@ -0,0 +1,171 @@ +/* + * linux/arch/arm/mach-psionw/time.c + * + * RTC handler for Psion 5mx. + * + * Copyright (C) 2001 Yuji Shinokawa + * + * 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 + */ + +#include +#include +#include +#include +#include + +#include +#include + +#undef DEBUG_RTC + +/* + * Offset to compatible with EPOC time handling. + * In EPOC, it seems a time for rtc = 0 is "00:00:00 1 Jan 2000 UTC" + * and rtc has signed value. + * + * RTC Time & date + * 0x00000000 = 00:00:00 1 Jan 2000 (London Inner, United Kingdom) + * + * You can get this offset by following perl script; + * #!/usr/bin/perl + * require 'timelocal.pl'; + * $time = timegm (0, 0, 0, 1, 0, 2000); + * print "$time\n"; + */ +#define EPOC_RTC_OFFSET 946684800 + +extern int (*set_rtc) (void); +extern unsigned long (*gettimeoffset) (void); + +unsigned int psionw_read_rtc(void) +{ + int try_count, rtc1, rtc2; + u_int xrtc; + + try_count = 3; + do { + rtc1 = + (psionw_readl(RTCDRU) << 16) | (psionw_readl(RTCDRL) & + 0xffff); + rtc2 = + (psionw_readl(RTCDRU) << 16) | (psionw_readl(RTCDRL) & + 0xffff); + } while (rtc1 != rtc2 && --try_count); + +#if DEBUG_RTC + printk("DEBUG: (psionw_get_rtc) read rtc = %08x\n", rtc1); +#endif + + xrtc = rtc1 + EPOC_RTC_OFFSET; + + return xrtc; +} + +void psionw_write_rtc(u_int xrtc) +{ + int rtc; + + rtc = xrtc - EPOC_RTC_OFFSET; + +#if DEBUG_RTC + printk("DEBUG: (psionw_set_rtc) write rtc = %08x\n", rtc); +#endif + + /* Writing order is important. */ + psionw_writel((rtc >> 16), RTCDRU); + psionw_writel((rtc & 0xffff), RTCDRL); +} + +unsigned int psionw_read_rtc_alarm(void) +{ + int try_count, rtc1, rtc2; + u_int xrtc; + + try_count = 3; + do { + rtc1 = + (psionw_readl(RTCMRU) << 16) | (psionw_readl(RTCMRL) & + 0xffff); + rtc2 = + (psionw_readl(RTCMRU) << 16) | (psionw_readl(RTCMRL) & + 0xffff); + } while (rtc1 != rtc2 && --try_count); + +#if DEBUG_RTC + printk("DEBUG: (psionw_get_rtc_alarm) read rtc alarm = %08x\n", rtc1); +#endif + + xrtc = rtc1 + EPOC_RTC_OFFSET; + + return xrtc; +} + +void psionw_write_rtc_alarm(u_int xrtc) +{ + int rtc; + + rtc = xrtc - EPOC_RTC_OFFSET; + +#if DEBUG_RTC + printk("DEBUG: (psionw_set_rtc_alarm) write rtc alarm = %08x\n", rtc); +#endif + + /* Writing order is important. */ + psionw_writel((rtc >> 16), RTCMRU); + psionw_writel((rtc & 0xffff), RTCMRL); +} + +EXPORT_SYMBOL(psionw_read_rtc); +EXPORT_SYMBOL(psionw_write_rtc); +EXPORT_SYMBOL(psionw_read_rtc_alarm); +EXPORT_SYMBOL(psionw_write_rtc_alarm); + +static int +psionw_set_rtc(void) +{ + u_int xrtc, rtc; + + xrtc = (u_int) xtime.tv_sec; + + psionw_write_rtc(xrtc); + + rtc = psionw_read_rtc(); + if (xrtc > rtc || rtc - xrtc > 1) + return 1; /* Write failed. */ + + return 0; +} + +static unsigned long +psionw_gettimeoffset(void) +{ + return 0; +} + +static int +psionw_rtc_init(void) +{ + /* Set the initial RTC value. */ + xtime.tv_sec = (time_t) psionw_read_rtc(); + + /* Setup hook. */ + set_rtc = psionw_set_rtc; + gettimeoffset = psionw_gettimeoffset; + + return 0; +} + +__initcall(psionw_rtc_init); diff -uNr linux-2.4.37.9/arch/arm/mach-psionw/serial-debug.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/serial-debug.c --- linux-2.4.37.9/arch/arm/mach-psionw/serial-debug.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-psionw/serial-debug.c Wed May 26 15:43:59 2010 @@ -0,0 +1,35 @@ +#include +#include + +#define DEBUG 1 + +/* + * Allows printing debug information over the serial + * line even before the console is initialized. Uses + * the low level debug functions. + * To use in the code, just add: + * + * extern void serial_printf(char *fmt, ...); + * + * For debugging only, do not leave serial_printf + * statements in the code. + * + * Copied from the drivers/video/cyber2000fb.h + */ +#if defined(DEBUG) && defined(CONFIG_DEBUG_LL) +void +serial_printf(char *fmt, ...) +{ + extern void printascii(const char *); + char buffer[128]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + printascii(buffer); +} +#else +#define serial_printf(x...) do { } while (0) +#endif diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/pm.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/pm.c --- linux-2.4.37.9/arch/arm/mach-sa1100/pm.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/pm.c Wed May 26 15:44:05 2010 @@ -21,6 +21,8 @@ * * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. * Storage is local on the stack now. + * 2003-06-25: Jeff Corrall + * Saved the GPIO levels for resume after sleep. */ #include #include @@ -70,13 +72,20 @@ int pm_do_suspend(void) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; + unsigned long sleep_save_gpsr; + unsigned long sleep_save_gpcr; + unsigned long delta; cli(); leds_event(led_stop); /* preserve current time */ - RCNR = xtime.tv_sec; + delta = xtime.tv_sec - RCNR; + + /* save the current state of the GPIO output pins */ + sleep_save_gpsr = GPDR & GPLR; + sleep_save_gpcr = GPDR & ~GPLR; /* save vital registers */ SAVE(OSCR); @@ -121,6 +130,10 @@ printk(KERN_DEBUG "*** made it back from resume\n"); #endif + /* restore GPIO output state before enabling the pins */ + GPSR = sleep_save_gpsr; + GPCR = sleep_save_gpcr; + /* restore registers */ RESTORE(GPDR); RESTORE(GRER); @@ -151,7 +164,7 @@ RESTORE(ICMR); /* restore current time */ - xtime.tv_sec = RCNR; + xtime.tv_sec = RCNR + delta; leds_event(led_start); diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/sa1100_usb.h linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/sa1100_usb.h --- linux-2.4.37.9/arch/arm/mach-sa1100/sa1100_usb.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/sa1100_usb.h Wed May 26 15:44:05 2010 @@ -0,0 +1,193 @@ +/* + * sa1100_usb.h + * + * Public interface to the sa1100 USB core. For use by client modules + * like usb-eth and usb-char. + * + */ + +#ifndef _SA1100_USB_H +#define _SA1100_USB_H +#include + +typedef void (*usb_callback_t)(int flag, int size); + +/* in usb_ctl.c (see also descriptor methods at bottom of file) */ + +// Open the USB client for client and initialize data structures +// to default values, but _do not_ start UDC. +int sa1100_usb_open( const char * client_name ); + +// Start UDC running +int sa1100_usb_start( void ); + +// Immediately stop udc, fire off completion routines w/-EINTR +int sa1100_usb_stop( void ) ; + +// Disconnect client from usb core +int sa1100_usb_close( void ) ; + +// set notify callback for when core reaches configured state +// return previous pointer (if any) +typedef void (*usb_notify_t)(void); +usb_notify_t sa1100_set_configured_callback( usb_notify_t callback ); + +/* in usb_send.c */ +int sa1100_usb_xmitter_avail( void ); +int sa1100_usb_send(char *buf, int len, usb_callback_t callback); +void sa1100_usb_send_reset(void); + +/* in usb_recev.c */ +int sa1100_usb_recv(char *buf, int len, usb_callback_t callback); +void sa1100_usb_recv_reset(void); + +////////////////////////////////////////////////////////////////////////////// +// Descriptor Management +////////////////////////////////////////////////////////////////////////////// + +#define DescriptorHeader \ + __u8 bLength; \ + __u8 bDescriptorType + + +// --- Device Descriptor ------------------- + +typedef struct { + DescriptorHeader; + __u16 bcdUSB; /* USB specification revision number in BCD */ + __u8 bDeviceClass; /* USB class for entire device */ + __u8 bDeviceSubClass; /* USB subclass information for entire device */ + __u8 bDeviceProtocol; /* USB protocol information for entire device */ + __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */ + __u16 idVendor; /* USB vendor ID */ + __u16 idProduct; /* USB product ID */ + __u16 bcdDevice; /* vendor assigned device release number */ + __u8 iManufacturer; /* index of manufacturer string */ + __u8 iProduct; /* index of string that describes product */ + __u8 iSerialNumber; /* index of string containing device serial number */ + __u8 bNumConfigurations; /* number fo configurations */ +} __attribute__ ((packed)) device_desc_t; + +// --- Configuration Descriptor ------------ + +typedef struct { + DescriptorHeader; + __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */ + __u8 bNumInterfaces; /* number of interfaces in this cfg */ + __u8 bConfigurationValue; /* used to uniquely ID this cfg */ + __u8 iConfiguration; /* index of string describing configuration */ + __u8 bmAttributes; /* bitmap of attributes for ths cfg */ + __u8 MaxPower; /* power draw in 2ma units */ +} __attribute__ ((packed)) config_desc_t; + +// bmAttributes: +enum { USB_CONFIG_REMOTEWAKE=0x20, USB_CONFIG_SELFPOWERED=0x40, + USB_CONFIG_BUSPOWERED=0x80 }; +// MaxPower: +#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */ + +// --- Interface Descriptor --------------- + +typedef struct { + DescriptorHeader; + __u8 bInterfaceNumber; /* Index uniquely identfying this interface */ + __u8 bAlternateSetting; /* ids an alternate setting for this interface */ + __u8 bNumEndpoints; /* number of endpoints in this interface */ + __u8 bInterfaceClass; /* USB class info applying to this interface */ + __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */ + __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */ + __u8 iInterface; /* index of string describing interface */ +} __attribute__ ((packed)) intf_desc_t; + +// --- Endpoint Descriptor --------------- + +typedef struct { + DescriptorHeader; + __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */ + __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */ + __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */ + __u8 bInterval; /* polling interval for this ep in this cfg */ +} __attribute__ ((packed)) ep_desc_t; + +// bEndpointAddress: +enum { USB_OUT= 0, USB_IN=1 }; +#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7)) +// bmAttributes: +enum { USB_EP_CNTRL=0, USB_EP_BULK=2, USB_EP_INT=3 }; + +// --- String Descriptor ------------------- + +typedef struct { + DescriptorHeader; + __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */ +} __attribute__ ((packed)) string_desc_t; + +/*======================================================= + * Handy helpers when working with above + * + */ +// these are x86-style 16 bit "words" ... +#define make_word_c( w ) __constant_cpu_to_le16(w) +#define make_word( w ) __cpu_to_le16(w) + +// descriptor types +enum { USB_DESC_DEVICE=1, USB_DESC_CONFIG=2, USB_DESC_STRING=3, + USB_DESC_INTERFACE=4, USB_DESC_ENDPOINT=5 }; + + +/*======================================================= + * Default descriptor layout for SA-1100 and SA-1110 UDC + */ + +/* "config descriptor buffer" - that is, one config, + ..one interface and 2 endpoints */ +struct cdb { + config_desc_t cfg; + intf_desc_t intf; + ep_desc_t ep1; + ep_desc_t ep2; +} __attribute__ ((packed)); + + +/* all SA device descriptors */ +typedef struct { + device_desc_t dev; /* device descriptor */ + struct cdb b; /* bundle of descriptors for this cfg */ +} __attribute__ ((packed)) desc_t; + + +/*======================================================= + * Descriptor API + */ + +/* Get the address of the statically allocated desc_t structure + in the usb core driver. Clients can modify this between + the time they call sa1100_usb_open() and sa1100_usb_start() +*/ +desc_t * +sa1100_usb_get_descriptor_ptr( void ); + + +/* Set a pointer to the string descriptor at "index". The driver + ..has room for 8 string indicies internally. Index zero holds + ..a LANGID code and is set to US English by default. Inidices + ..1-7 are available for use in the config descriptors as client's + ..see fit. This pointer is assumed to be good as long as the + ..SA usb core is open (so statically allocate them). Returnes -EINVAL + ..if index out of range */ +int sa1100_usb_set_string_descriptor( int index, string_desc_t * p ); + +/* reverse of above */ +string_desc_t * +sa1100_usb_get_string_descriptor( int index ); + +/* kmalloc() a string descriptor and convert "p" to unicode in it */ +string_desc_t * +sa1100_usb_kmalloc_string_descriptor( const char * p ); + + + + + + +#endif /* _SA1100_USB_H */ diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/sa1111-ohci.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/sa1111-ohci.c --- linux-2.4.37.9/arch/arm/mach-sa1100/sa1111-ohci.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/sa1111-ohci.c Wed May 26 15:44:05 2010 @@ -0,0 +1,140 @@ +#include +#include +#include +#include + +#ifdef CONFIG_USB_OHCI + +/* + * The SA-1111 errata says that the DMA hardware needs to be exercised + * before the clocks are turned on to work properly. This code does + * a tiny dma transfer to prime to hardware. + * + * What DMA errata? I've checked October 1999 and February 2001, both + * of which do not mention such a bug, let alone any details of this + * work-around. + */ +static void __init sa1111_dma_setup(void) +{ + dma_addr_t dma_buf; + void * vbuf; + + /* DMA init & setup */ + + /* WARNING: The SA-1111 L3 function is used as part of this + * SA-1111 DMA errata workaround. + * + * N.B., When the L3 function is enabled, it uses GPIO_B<4:5> + * and takes precedence over the PS/2 mouse and GPIO_B + * functions. Refer to "Intel StrongARM SA-1111 Microprocessor + * Companion Chip, Sect 10.2" for details. So this "fix" may + * "break" support of either PS/2 mouse or GPIO_B if + * precautions are not taken to avoid collisions in + * configuration and use of these pins. AFAIK, no precautions + * are taken at this time. So it is likely that the action + * taken here may cause problems in PS/2 mouse and/or GPIO_B + * pin use elsewhere. + * + * But wait, there's more... What we're doing here is + * obviously altogether a bad idea. We're indiscrimanately bit + * flipping config for a few different functions here which + * are "owned" by other drivers. This needs to be handled + * better than it is being done here at this time. */ + + /* prime the dma engine with a tiny dma */ + SKPCR |= SKPCR_I2SCLKEN; + SKAUD |= SKPCR_L3CLKEN | SKPCR_SCLKEN; + + SACR0 |= 0x00003305; + SACR1 = 0x00000000; + + /* + * We need memory below 1MB. + * NOTE: consistent_alloc gives you some random virtual + * address as its return value, and the DMA address via + * the dma_addr_t pointer. + */ + vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf); + + SADTSA = (unsigned long)dma_buf; + SADTCA = 4; + + SADTCS |= 0x00000011; + SKPCR |= SKPCR_DCLKEN; + + /* wait */ + udelay(100); + + /* clear reserved but, then disable SAC */ + SACR0 &= ~(0x00000002); + SACR0 &= ~(0x00000001); + + /* toggle bit clock direction */ + SACR0 |= 0x00000004; + SACR0 &= ~(0x00000004); + + SKAUD &= ~(SKPCR_L3CLKEN | SKPCR_SCLKEN); + + SKPCR &= ~SKPCR_I2SCLKEN; + + consistent_free(vbuf, 4, dma_buf); +} + +/* + * reset the SA-1111 usb controller and turn on it's clocks + */ +int __init sa1111_ohci_hcd_init(void) +{ + unsigned int usb_reset = 0; + + if (machine_is_xp860() || + machine_has_neponset() || + machine_is_pfs168() || + machine_is_badge4()) + usb_reset = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW; + + /* + * turn on USB clocks + */ + SKPCR |= SKPCR_UCLKEN; + udelay(100); + + /* + * Force USB reset + */ + USB_RESET = USB_RESET_FORCEIFRESET; + USB_RESET |= USB_RESET_FORCEHCRESET; + udelay(100); + + /* + * Take out of reset + */ + USB_RESET = 0; + + /* + * set power sense and control lines (this from the diags code) + */ + USB_RESET = usb_reset; + + /* + * Huh? This is a _read only_ register --rmk + */ + USB_STATUS = 0; + + udelay(10); + + /* + * compensate for dma bug + */ + sa1111_dma_setup(); + + return 0; +} + +void sa1111_ohci_hcd_cleanup(void) +{ + /* turn the USB clock off */ + SKPCR &= ~SKPCR_UCLKEN; +} + +#endif /* CONFIG_USB_OHCI */ diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb-char.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb-char.c --- linux-2.4.37.9/arch/arm/mach-sa1100/usb-char.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb-char.c Wed May 26 15:44:05 2010 @@ -0,0 +1,723 @@ +/* + * (C) Copyright 2000-2001 Extenex Corporation + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * usb-char.c + * + * Miscellaneous character device interface for SA1100 USB function + * driver. + * + * Background: + * The SA1100 function driver ported from the Compaq Itsy project + * has an interface, usb-eth.c, to feed network packets over the + * usb wire and into the Linux TCP/IP stack. + * + * This file replaces that one with a simple character device + * interface that allows unstructured "byte pipe" style reads and + * writes over the USB bulk endpoints by userspace programs. + * + * A new define, CONFIG_SA1100_USB_NETLINK, has been created that, + * when set, (the default) causes the ethernet interface to be used. + * When not set, this more pedestrian character interface is linked + * in instead. + * + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. + * + * ward.willats@extenex.com + * + * To do: + * - Can't dma into ring buffer directly with pci_map/unmap usb_recv + * uses and get bytes out at the same time DMA is going on. Investigate: + * a) changing usb_recv to use alloc_consistent() at client request; or + * b) non-ring-buffer based data structures. In the meantime, I am using + * a bounce buffer. Simple, but wasteful. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "usb-char.h" +#include "sa1100_usb.h" + + + +////////////////////////////////////////////////////////////////////////////// +// Driver Options +////////////////////////////////////////////////////////////////////////////// + +#define VERSION "0.4" + + +#define VERBOSITY 1 + +#if VERBOSITY +# define PRINTK(x, a...) printk (x, ## a) +#else +# define PRINTK(x, a...) /**/ +#endif + +////////////////////////////////////////////////////////////////////////////// +// Globals - Macros - Enums - Structures +////////////////////////////////////////////////////////////////////////////// +#ifndef MIN +#define MIN( a, b ) ((a)<(b)?(a):(b)) +#endif + +typedef int bool; enum { false = 0, true = 1 }; + +static const char pszMe[] = "usbchr: "; + +static wait_queue_head_t wq_read; +static wait_queue_head_t wq_write; +static wait_queue_head_t wq_poll; + +/* Serialze multiple writers onto the transmit hardware +.. since we sleep the writer during transmit to stay in +.. sync. (Multiple writers don't make much sense, but..) */ +static DECLARE_MUTEX( xmit_sem ); + +// size of usb DATA0/1 packets. 64 is standard maximum +// for bulk transport, though most hosts seem to be able +// to handle larger. +#define TX_PACKET_SIZE 64 +#define RX_PACKET_SIZE 64 +#define RBUF_SIZE (4*PAGE_SIZE) + +static struct wcirc_buf { + char *buf; + int in; + int out; +} rx_ring = { NULL, 0, 0 }; + +static struct { + unsigned long cnt_rx_complete; + unsigned long cnt_rx_errors; + unsigned long bytes_rx; + unsigned long cnt_tx_timeouts; + unsigned long cnt_tx_errors; + unsigned long bytes_tx; +} charstats; + + +static char * tx_buf = NULL; +static char * packet_buffer = NULL; +static int sending = 0; +static int usb_ref_count = 0; +static int last_tx_result = 0; +static int last_rx_result = 0; +static int last_tx_size = 0; +static struct timer_list tx_timer; + +////////////////////////////////////////////////////////////////////////////// +// Prototypes +////////////////////////////////////////////////////////////////////////////// +static char * what_the_f( int e ); +static void free_txrx_buffers( void ); +static void twiddle_descriptors( void ); +static void free_string_descriptors( void ) ; +static int usbc_open( struct inode *pInode, struct file *pFile ); +static void rx_done_callback_packet_buffer( int flag, int size ); + +static void tx_timeout( unsigned long ); +static void tx_done_callback( int flag, int size ); + +static ssize_t usbc_read( struct file *, char *, size_t, loff_t * ); +static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * ); +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ); +static int usbc_ioctl( struct inode *pInode, struct file *pFile, + unsigned int nCmd, unsigned long argument ); +static int usbc_close( struct inode *pInode, struct file *pFile ); + +#ifdef CONFIG_SA1100_EXTENEX1 +static void extenex_configured_notify_proc( void ); +#endif +////////////////////////////////////////////////////////////////////////////// +// Private Helpers +////////////////////////////////////////////////////////////////////////////// + +static char * what_the_f( int e ) +{ + char * p; + switch( e ) { + case 0: + p = "noErr"; + break; + case -ENODEV: + p = "ENODEV - usb not in config state"; + break; + case -EBUSY: + p = "EBUSY - another request on the hardware"; + break; + case -EAGAIN: + p = "EAGAIN"; + break; + case -EINTR: + p = "EINTR - interrupted\n"; + break; + case -EPIPE: + p = "EPIPE - zero length xfer\n"; + break; + default: + p = "????"; + break; + } + return p; +} + +static void free_txrx_buffers( void ) +{ + if ( rx_ring.buf != NULL ) { + kfree( rx_ring.buf ); + rx_ring.buf = NULL; + } + if ( packet_buffer != NULL ) { + kfree( packet_buffer ); + packet_buffer = NULL; + } + if ( tx_buf != NULL ) { + kfree( tx_buf ); + tx_buf = NULL; + } +} + +/* twiddle_descriptors() + * It is between open() and start(). Setup descriptors. + */ +static void twiddle_descriptors( void ) +{ + desc_t * pDesc = sa1100_usb_get_descriptor_ptr(); + string_desc_t * pString; + + pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE ); + pDesc->b.ep1.bmAttributes = USB_EP_BULK; + pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE ); + pDesc->b.ep2.bmAttributes = USB_EP_BULK; + + if ( machine_is_extenex1() ) { +#ifdef CONFIG_SA1100_EXTENEX1 + pDesc->dev.idVendor = make_word_c( 0xC9F ); + pDesc->dev.idProduct = 1; + pDesc->dev.bcdDevice = make_word_c( 0x0001 ); + pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED; + pDesc->b.cfg.MaxPower = 0; + + pString = sa1100_usb_kmalloc_string_descriptor( "Extenex" ); + if ( pString ) { + sa1100_usb_set_string_descriptor( 1, pString ); + pDesc->dev.iManufacturer = 1; + } + + pString = sa1100_usb_kmalloc_string_descriptor( "Handheld Theater" ); + if ( pString ) { + sa1100_usb_set_string_descriptor( 2, pString ); + pDesc->dev.iProduct = 2; + } + + pString = sa1100_usb_kmalloc_string_descriptor( "00000000" ); + if ( pString ) { + sa1100_usb_set_string_descriptor( 3, pString ); + pDesc->dev.iSerialNumber = 3; + } + + pString = sa1100_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" ); + if ( pString ) { + sa1100_usb_set_string_descriptor( 4, pString ); + pDesc->b.intf.iInterface = 4; + } + sa1100_set_configured_callback( extenex_configured_notify_proc ); +#endif + } +} + +static void free_string_descriptors( void ) +{ + if ( machine_is_extenex1() ) { + string_desc_t * pString; + int i; + for( i = 1 ; i <= 4 ; i++ ) { + pString = sa1100_usb_get_string_descriptor( i ); + if ( pString ) + kfree( pString ); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// ASYNCHRONOUS +////////////////////////////////////////////////////////////////////////////// +static void kick_start_rx( void ) +{ + if ( usb_ref_count ) { + int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE ); + if ( total_space >= RX_PACKET_SIZE ) { + sa1100_usb_recv( packet_buffer, + RX_PACKET_SIZE, + rx_done_callback_packet_buffer + ); + } + } +} +/* + * rx_done_callback_packet_buffer() + * We have completed a DMA xfer into the temp packet buffer. + * Move to ring. + * + * flag values: + * on init, -EAGAIN + * on reset, -EINTR + * on RPE, -EIO + * on short packet -EPIPE + */ +static void +rx_done_callback_packet_buffer( int flag, int size ) +{ + charstats.cnt_rx_complete++; + + if ( flag == 0 || flag == -EPIPE ) { + size_t n; + + charstats.bytes_rx += size; + + n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE ); + n = MIN( n, size ); + size -= n; + + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n ); + rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1); + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size ); + rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1); + + wake_up_interruptible( &wq_read ); + wake_up_interruptible( &wq_poll ); + + last_rx_result = 0; + + kick_start_rx(); + + } else if ( flag != -EAGAIN ) { + charstats.cnt_rx_errors++; + last_rx_result = flag; + wake_up_interruptible( &wq_read ); + wake_up_interruptible( &wq_poll ); + } + else /* init, start a read */ + kick_start_rx(); +} + + +static void tx_timeout( unsigned long unused ) +{ + printk( "%stx timeout\n", pszMe ); + sa1100_usb_send_reset(); + charstats.cnt_tx_timeouts++; +} + + +// on init, -EAGAIN +// on reset, -EINTR +// on TPE, -EIO +static void tx_done_callback( int flags, int size ) +{ + if ( flags == 0 ) + charstats.bytes_tx += size; + else + charstats.cnt_tx_errors++; + last_tx_size = size; + last_tx_result = flags; + sending = 0; + wake_up_interruptible( &wq_write ); + wake_up_interruptible( &wq_poll ); +} + + +////////////////////////////////////////////////////////////////////////////// +// Workers +////////////////////////////////////////////////////////////////////////////// + +static int usbc_open( struct inode *pInode, struct file *pFile ) +{ + int retval = 0; + + PRINTK( KERN_DEBUG "%sopen()\n", pszMe ); + + /* start usb core */ + retval = sa1100_usb_open( "usb-char" ); + if ( retval ) return retval; + + /* allocate memory */ + if ( usb_ref_count == 0 ) { + tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA ); + if ( tx_buf == NULL ) { + printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe ); + goto malloc_fail; + } + rx_ring.buf = + (char*) kmalloc( RBUF_SIZE, GFP_KERNEL ); + + if ( rx_ring.buf == NULL ) { + printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe ); + goto malloc_fail; + } + + packet_buffer = + (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA ); + + if ( packet_buffer == NULL ) { + printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe ); + goto malloc_fail; + } + rx_ring.in = rx_ring.out = 0; + memset( &charstats, 0, sizeof( charstats ) ); + sending = 0; + last_tx_result = 0; + last_tx_size = 0; + } + + /* modify default descriptors */ + twiddle_descriptors(); + + retval = sa1100_usb_start(); + if ( retval ) { + printk( "%sAGHH! Could not USB core\n", pszMe ); + free_txrx_buffers(); + return retval; + } + usb_ref_count++; /* must do _before_ kick_start() */ + MOD_INC_USE_COUNT; + kick_start_rx(); + return 0; + + malloc_fail: + free_txrx_buffers(); + return -ENOMEM; +} + +/* + * Read endpoint. Note that you can issue a read to an + * unconfigured endpoint. Eventually, the host may come along + * and configure underneath this module and data will appear. + */ +static ssize_t usbc_read( struct file *pFile, char *pUserBuffer, + size_t stCount, loff_t *pPos ) +{ + ssize_t retval; + int flags; + DECLARE_WAITQUEUE( wait, current ); + + PRINTK( KERN_DEBUG "%sread()\n", pszMe ); + + local_irq_save( flags ); + if ( last_rx_result == 0 ) { + local_irq_restore( flags ); + } else { /* an error happended and receiver is paused */ + local_irq_restore( flags ); + last_rx_result = 0; + kick_start_rx(); + } + + add_wait_queue( &wq_read, &wait ); + while( 1 ) { + ssize_t bytes_avail; + ssize_t bytes_to_end; + + set_current_state( TASK_INTERRUPTIBLE ); + + /* snap ring buf state */ + local_irq_save( flags ); + bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ); + bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE ); + local_irq_restore( flags ); + + if ( bytes_avail != 0 ) { + ssize_t bytes_to_move = MIN( stCount, bytes_avail ); + retval = 0; // will be bytes transfered + if ( bytes_to_move != 0 ) { + size_t n = MIN( bytes_to_end, bytes_to_move ); + if ( copy_to_user( pUserBuffer, + &rx_ring.buf[ rx_ring.out ], + n ) ) { + retval = -EFAULT; + break; + } + bytes_to_move -= n; + retval += n; + // might go 1 char off end, so wrap + rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1); + if ( copy_to_user( pUserBuffer + n, + &rx_ring.buf[ rx_ring.out ], + bytes_to_move ) + ) { + retval = -EFAULT; + break; + } + rx_ring.out += bytes_to_move; // cannot wrap + retval += bytes_to_move; + kick_start_rx(); + } + break; + } + else if ( last_rx_result ) { + retval = last_rx_result; + break; + } + else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep + retval = -EAGAIN; + break; + } + else if ( signal_pending( current ) ) { // no data, can sleep, but signal + retval = -ERESTARTSYS; + break; + } + schedule(); // no data, can sleep + } + set_current_state( TASK_RUNNING ); + remove_wait_queue( &wq_read, &wait ); + + if ( retval < 0 ) + printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) ); + return retval; +} + +/* + * Write endpoint. This routine attempts to break the passed in buffer + * into usb DATA0/1 packet size chunks and send them to the host. + * (The lower-level driver tries to do this too, but easier for us + * to manage things here.) + * + * We are at the mercy of the host here, in that it must send an IN + * token to us to pull this data back, so hopefully some higher level + * protocol is expecting traffic to flow in that direction so the host + * is actually polling us. To guard against hangs, a 5 second timeout + * is used. + * + * This routine takes some care to only report bytes sent that have + * actually made it across the wire. Thus we try to stay in lockstep + * with the completion routine and only have one packet on the xmit + * hardware at a time. Multiple simultaneous writers will get + * "undefined" results. + * + */ +static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer, + size_t stCount, loff_t *pPos ) +{ + ssize_t retval = 0; + ssize_t stSent = 0; + + DECLARE_WAITQUEUE( wait, current ); + + PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount ); + + down( &xmit_sem ); // only one thread onto the hardware at a time + + while( stCount != 0 && retval == 0 ) { + int nThisTime = MIN( TX_PACKET_SIZE, stCount ); + copy_from_user( tx_buf, pUserBuffer, nThisTime ); + sending = nThisTime; + retval = sa1100_usb_send( tx_buf, nThisTime, tx_done_callback ); + if ( retval < 0 ) { + char * p = what_the_f( retval ); + printk( "%sCould not queue xmission. rc=%d - %s\n", + pszMe, retval, p ); + sending = 0; + break; + } + /* now have something on the diving board */ + add_wait_queue( &wq_write, &wait ); + tx_timer.expires = jiffies + ( HZ * 5 ); + add_timer( &tx_timer ); + while( 1 ) { + set_current_state( TASK_INTERRUPTIBLE ); + if ( sending == 0 ) { /* it jumped into the pool */ + del_timer( &tx_timer ); + retval = last_tx_result; + if ( retval == 0 ) { + stSent += last_tx_size; + pUserBuffer += last_tx_size; + stCount -= last_tx_size; + } + else + printk( "%sxmission error rc=%d - %s\n", + pszMe, retval, what_the_f(retval) ); + break; + } + else if ( signal_pending( current ) ) { + del_timer( &tx_timer ); + printk( "%ssignal\n", pszMe ); + retval = -ERESTARTSYS; + break; + } + schedule(); + } + set_current_state( TASK_RUNNING ); + remove_wait_queue( &wq_write, &wait ); + } + + up( &xmit_sem ); + + if ( 0 == retval ) + retval = stSent; + return retval; +} + +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ) +{ + unsigned int retval = 0; + + PRINTK( KERN_DEBUG "%poll()\n", pszMe ); + + poll_wait( pFile, &wq_poll, pWait ); + + if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) ) + retval |= POLLIN | POLLRDNORM; + if ( sa1100_usb_xmitter_avail() ) + retval |= POLLOUT | POLLWRNORM; + return retval; +} + +static int usbc_ioctl( struct inode *pInode, struct file *pFile, + unsigned int nCmd, unsigned long argument ) +{ + int retval = 0; + + switch( nCmd ) { + + case USBC_IOC_FLUSH_RECEIVER: + sa1100_usb_recv_reset(); + rx_ring.in = rx_ring.out = 0; + break; + + case USBC_IOC_FLUSH_TRANSMITTER: + sa1100_usb_send_reset(); + break; + + case USBC_IOC_FLUSH_ALL: + sa1100_usb_recv_reset(); + rx_ring.in = rx_ring.out = 0; + sa1100_usb_send_reset(); + break; + + default: + retval = -ENOIOCTLCMD; + break; + + } + return retval; +} + + +static int usbc_close( struct inode *pInode, struct file * pFile ) +{ + PRINTK( KERN_DEBUG "%sclose()\n", pszMe ); + if ( --usb_ref_count == 0 ) { + down( &xmit_sem ); + sa1100_usb_stop(); + free_txrx_buffers(); + free_string_descriptors(); + del_timer( &tx_timer ); + sa1100_usb_close(); + up( &xmit_sem ); + } + MOD_DEC_USE_COUNT; + return 0; +} + +#ifdef CONFIG_SA1100_EXTENEX1 +#include "../../../drivers/char/ex_gpio.h" +void extenex_configured_notify_proc( void ) +{ + if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN ) + printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe ); +} +#endif +////////////////////////////////////////////////////////////////////////////// +// Initialization +////////////////////////////////////////////////////////////////////////////// + +static struct file_operations usbc_fops = { + owner: THIS_MODULE, + open: usbc_open, + read: usbc_read, + write: usbc_write, + poll: usbc_poll, + ioctl: usbc_ioctl, + release: usbc_close, +}; + +static struct miscdevice usbc_misc_device = { + USBC_MINOR, "usb_char", &usbc_fops +}; + +/* + * usbc_init() + */ + +int __init usbc_init( void ) +{ + int rc; + +#if !defined( CONFIG_ARCH_SA1100 ) + return -ENODEV; +#endif + + if ( (rc = misc_register( &usbc_misc_device )) != 0 ) { + printk( KERN_WARNING "%sCould not register device 10, " + "%d. (%d)\n", pszMe, USBC_MINOR, rc ); + return -EBUSY; + } + + // initialize wait queues + init_waitqueue_head( &wq_read ); + init_waitqueue_head( &wq_write ); + init_waitqueue_head( &wq_poll ); + + // initialize tx timeout timer + init_timer( &tx_timer ); + tx_timer.function = tx_timeout; + + printk( KERN_INFO "USB Function Character Driver Interface" + " - %s, (C) 2001, Extenex Corp.\n", VERSION + ); + + return rc; +} + +void __exit usbc_exit( void ) +{ +} + +EXPORT_NO_SYMBOLS; + +module_init(usbc_init); +module_exit(usbc_exit); + + + +// end: usb-char.c + + + diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb-char.h linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb-char.h --- linux-2.4.37.9/arch/arm/mach-sa1100/usb-char.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb-char.h Wed May 26 15:44:05 2010 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2001 Extenex Corporation + * + * usb-char.h + * + * Character device emulation client for SA-1100 client usb core. + * + * + * + */ +#ifndef _USB_CHAR_H +#define _USB_CHAR_H + +#define USBC_MAJOR 10 /* miscellaneous character device */ +#define USBC_MINOR 240 /* in the "reserved for local use" range */ + +#define USBC_MAGIC 0x8E + +/* zap everything in receive ring buffer */ +#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 ) + +/* reset transmitter */ +#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 ) + +/* do both of above */ +#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 ) + + + + + + +#endif /* _USB_CHAR_H */ + diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb-eth.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb-eth.c --- linux-2.4.37.9/arch/arm/mach-sa1100/usb-eth.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb-eth.c Wed May 26 15:44:05 2010 @@ -0,0 +1,447 @@ + /* + * Ethernet driver for the SA1100 USB client function + * Copyright (c) 2001 by Nicolas Pitre + * + * This code was loosely inspired by the original initial ethernet test driver + * Copyright (c) Compaq Computer Corporation, 1999 + * + * 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. + * + * This is still work in progress... + * + * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com + * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit. + * Now, since we do not know what size of packet we are receiving + * last usb packet in sequence will always be less than max packet + * receive endpoint can accept. + * Now the only way to check correct start of frame is to compare + * MAC address. Also now we are stalling on each receive error. + * + * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte + * aligned buffer, but this breaks IP code (unaligned access). + * + * 01/04/2001 - stall endpoint operations appeared to be very unstable, so + * they are disabled now. + * + * 03/06/2001 - Readded "zerocopy" receive path (tunable). + * + */ + +// Define DMA_NO_COPY if you want data to arrive directly into the +// receive network buffers, instead of arriving into bounce buffer +// and then get copied to network buffer. +// This does not work correctly right now. +#undef DMA_NO_COPY + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sa1100_usb.h" + + +#define ETHERNET_VENDOR_ID 0x49f +#define ETHERNET_PRODUCT_ID 0x505A +#define MAX_PACKET 32768 +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +// Should be global, so that insmod can change these +int usb_rsize=64; +int usb_wsize=64; + +static struct usbe_info_t { + struct net_device *dev; + u16 packet_id; + struct net_device_stats stats; +} usbe_info; + +static char usb_eth_name[16] = "usbf"; +static struct net_device usb_eth_device; +static struct sk_buff *cur_tx_skb, *next_tx_skb; +static struct sk_buff *cur_rx_skb, *next_rx_skb; +static volatile int terminating; +#ifndef DMA_NO_COPY +static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary +#endif + +static int usb_change_mtu (struct net_device *net, int new_mtu) +{ + if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET) + return -EINVAL; + // no second zero-length packet read wanted after mtu-sized packets + if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0) + return -EDOM; + + net->mtu = new_mtu; + return 0; +} + +static struct sk_buff * +usb_new_recv_skb(void) +{ + struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC); + + if (skb) { + skb_reserve(skb, 2); + } + return skb; +} + +static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff}; +static void +usb_recv_callback(int flag, int size) +{ + struct sk_buff *skb; + + if (terminating) + return; + + skb = cur_rx_skb; + + /* flag validation */ + if (flag == 0) { + if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!! + usbe_info.stats.rx_over_errors++; + goto error; + } +#ifndef DMA_NO_COPY + memcpy(skb->tail,dmabuf,size); +#endif + skb_put(skb, size); + } else { + if (flag == -EIO) { + usbe_info.stats.rx_errors++; + } + goto error; + } + + /* validate packet length */ + if (size == usb_rsize ) { + /* packet not complete yet */ + skb = NULL; + } + + /* + * At this point skb is non null if we have a complete packet. + * If so take a fresh skb right away and restart USB receive without + * further delays, then process the packet. Otherwise resume USB + * receive on the current skb and exit. + */ + + if (skb) + cur_rx_skb = next_rx_skb; +#ifndef DMA_NO_COPY + sa1100_usb_recv(dmabuf, usb_rsize, + usb_recv_callback); +#else + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), + usb_recv_callback); +#endif + if (!skb) + return; + + next_rx_skb = usb_new_recv_skb(); + if (!next_rx_skb) { + /* + * We can't aford loosing buffer space... + * So we drop the current packet and recycle its skb. + */ + printk("%s: can't allocate new skb\n", __FUNCTION__); + usbe_info.stats.rx_dropped++; + skb_trim(skb, 0); + next_rx_skb = skb; + return; + } + if ( skb->len >= sizeof(struct ethhdr)) { + if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) { + // This frame is not for us. nor it is broadcast + usbe_info.stats.rx_frame_errors++; + kfree_skb(skb); + goto error; + } + } + + if (skb->len) { + int status; +// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ? + + skb->dev = &usb_eth_device; + skb->protocol = eth_type_trans (skb, &usb_eth_device); + usbe_info.stats.rx_packets++; + usbe_info.stats.rx_bytes += skb->len; + skb->ip_summed = CHECKSUM_NONE; + status = netif_rx (skb); + if (status != NET_RX_SUCCESS) + printk("netif_rx failed with code %d\n",status); + } else { +error: + /* + * Error due to HW addr mismatch, or IO error. + * Recycle the current skb and reset USB reception. + */ + skb_trim(cur_rx_skb, 0); +// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall +#ifndef DMA_NO_COPY + sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback); +#else + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback); +#endif + } +} + + +static void +usb_send_callback(int flag, int size) +{ + struct net_device *dev = usbe_info.dev; + struct net_device_stats *stats; + struct sk_buff *skb=cur_tx_skb; + int ret; + + if (terminating) + return; + + stats = &usbe_info.stats; + switch (flag) { + case 0: + stats->tx_packets++; + stats->tx_bytes += size; + break; + case -EIO: + stats->tx_errors++; + break; + default: + stats->tx_dropped++; + break; + } + + cur_tx_skb = next_tx_skb; + next_tx_skb = NULL; + dev_kfree_skb_irq(skb); + if (!cur_tx_skb) + return; + + dev->trans_start = jiffies; + ret = sa1100_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback); + if (ret) { + /* If the USB core can't accept the packet, we drop it. */ + dev_kfree_skb_irq(cur_tx_skb); + cur_tx_skb = NULL; + usbe_info.stats.tx_carrier_errors++; + } + netif_wake_queue(dev); +} + +static int +usb_eth_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + unsigned long flags; + + if (next_tx_skb) { + printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__); + return 1; + } + + if (skb_shared (skb)) { + struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC); + if (!skb2) { + usbe_info.stats.tx_dropped++; + dev_kfree_skb(skb); + return 1; + } + skb = skb2; + } + + if ((skb->len % usb_wsize) == 0) { + skb->len++; // other side will ignore this one, anyway. + } + + local_irq_save(flags); + if (cur_tx_skb) { + next_tx_skb = skb; + netif_stop_queue(dev); + } else { + cur_tx_skb = skb; + dev->trans_start = jiffies; + ret = sa1100_usb_send(skb->data, skb->len, usb_send_callback); + if (ret) { + /* If the USB core can't accept the packet, we drop it. */ + dev_kfree_skb(skb); + cur_tx_skb = NULL; + usbe_info.stats.tx_carrier_errors++; + } + } + local_irq_restore(flags); + return 0; +} + +static void +usb_xmit_timeout(struct net_device *dev ) +{ + sa1100_usb_send_reset(); + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + + +static int +usb_eth_open(struct net_device *dev) +{ + terminating = 0; + cur_tx_skb = next_tx_skb = NULL; + cur_rx_skb = usb_new_recv_skb(); + next_rx_skb = usb_new_recv_skb(); + if (!cur_rx_skb || !next_rx_skb) { + printk("%s: can't allocate new skb\n", __FUNCTION__); + if (cur_rx_skb) + kfree_skb(cur_rx_skb); + if (next_rx_skb) + kfree_skb(next_rx_skb); + return -ENOMEM;; + } + + MOD_INC_USE_COUNT; +#ifndef DMA_NO_COPY + sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback); +#else + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), + usb_recv_callback); +#endif + return 0; +} + +static int +usb_eth_release(struct net_device *dev) +{ + terminating = 1; + sa1100_usb_send_reset(); + sa1100_usb_recv_reset(); + if (cur_tx_skb) + kfree_skb(cur_tx_skb); + if (next_tx_skb) + kfree_skb(next_tx_skb); + if (cur_rx_skb) + kfree_skb(cur_rx_skb); + if (next_rx_skb) + kfree_skb(next_rx_skb); + MOD_DEC_USE_COUNT; + return 0; +} + +static struct net_device_stats * +usb_eth_stats(struct net_device *dev) +{ + struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv; + struct net_device_stats *stats=NULL; + + if (priv) + stats = &priv->stats; + return stats; +} + +static int +usb_eth_probe(struct net_device *dev) +{ + u8 node_id [ETH_ALEN]; + + get_random_bytes (node_id, sizeof node_id); + node_id [0] &= 0xfe; // clear multicast bit + + /* + * Assign the hardware address of the board: + * generate it randomly, as there can be many such + * devices on the bus. + */ + memcpy (dev->dev_addr, node_id, sizeof node_id); + + dev->open = usb_eth_open; + dev->change_mtu = usb_change_mtu; + dev->stop = usb_eth_release; + dev->hard_start_xmit = usb_eth_xmit; + dev->get_stats = usb_eth_stats; + dev->watchdog_timeo = 1*HZ; + dev->tx_timeout = usb_xmit_timeout; + dev->priv = &usbe_info; + + usbe_info.dev = dev; + + /* clear the statistics */ + memset(&usbe_info.stats, 0, sizeof(struct net_device_stats)); + + ether_setup(dev); + dev->flags &= ~IFF_MULTICAST; + dev->flags &= ~IFF_BROADCAST; + //dev->flags |= IFF_NOARP; + + return 0; +} + +#ifdef MODULE +MODULE_PARM(usb_rsize, "1i"); +MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to sa1100"); +MODULE_PARM(usb_wsize, "1i"); +MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from sa1100 to host"); +#endif + +static int __init +usb_eth_init(void) +{ + int rc; + +#ifndef DMA_NO_COPY + dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA ); + if (!dmabuf) + return -ENOMEM; +#endif + strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ); + usb_eth_device.init = usb_eth_probe; + if (register_netdev(&usb_eth_device) != 0) + return -EIO; + + rc = sa1100_usb_open( "usb-eth" ); + if ( rc == 0 ) { + string_desc_t * pstr; + desc_t * pd = sa1100_usb_get_descriptor_ptr(); + + pd->b.ep1.wMaxPacketSize = make_word( usb_rsize ); + pd->b.ep2.wMaxPacketSize = make_word( usb_wsize ); + pd->dev.idVendor = ETHERNET_VENDOR_ID; + pd->dev.idProduct = ETHERNET_PRODUCT_ID; + pstr = sa1100_usb_kmalloc_string_descriptor( "SA1100 USB NIC" ); + if ( pstr ) { + sa1100_usb_set_string_descriptor( 1, pstr ); + pd->dev.iProduct = 1; + } + rc = sa1100_usb_start(); + } + return rc; +} + +module_init(usb_eth_init); + +static void __exit +usb_eth_cleanup(void) +{ + string_desc_t * pstr; + sa1100_usb_stop(); + sa1100_usb_close(); + if ( (pstr = sa1100_usb_get_string_descriptor(1)) != NULL ) + kfree( pstr ); +#ifndef DMA_NO_COPY + kfree(dmabuf); +#endif + unregister_netdev(&usb_eth_device); +} + +module_exit(usb_eth_cleanup); diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb_ctl.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_ctl.c --- linux-2.4.37.9/arch/arm/mach-sa1100/usb_ctl.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_ctl.c Wed May 26 15:44:05 2010 @@ -0,0 +1,774 @@ + /* + * Copyright (C) Compaq Computer Corporation, 1998, 1999 + * Copyright (C) Extenex Corporation, 2001 + * + * usb_ctl.c + * + * SA1100 USB controller core driver. + * + * This file provides interrupt routing and overall coordination + * of the three endpoints in usb_ep0, usb_receive (1), and usb_send (2). + * + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sa1100_usb.h" +#include "usb_ctl.h" + +////////////////////////////////////////////////////////////////////////////// +// Prototypes +////////////////////////////////////////////////////////////////////////////// + +int usbctl_next_state_on_event( int event ); +static void udc_int_hndlr(int, void *, struct pt_regs *); +static void initialize_descriptors( void ); +static void soft_connect_hook( int enable ); +static void udc_disable(void); +static void udc_enable(void); + +#if CONFIG_PROC_FS +#define PROC_NODE_NAME "sausb" +static int usbctl_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); +#endif + +////////////////////////////////////////////////////////////////////////////// +// Globals +////////////////////////////////////////////////////////////////////////////// +static const char pszMe[] = "usbctl: "; +struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */ + +/* device descriptors */ +static desc_t desc; + +#define MAX_STRING_DESC 8 +static string_desc_t * string_desc_array[ MAX_STRING_DESC ]; +static string_desc_t sd_zero; /* special sd_zero holds language codes */ + +// called when configured +static usb_notify_t configured_callback = NULL; + +enum { kStateZombie = 0, kStateZombieSuspend = 1, + kStateDefault = 2, kStateDefaultSuspend = 3, + kStateAddr = 4, kStateAddrSuspend = 5, + kStateConfig = 6, kStateConfigSuspend = 7 +}; + +static int device_state_machine[8][6] = { +// suspend reset resume adddr config deconfig +/* zombie */ { kStateZombieSuspend, kStateDefault, kError, kError, kError, kError }, +/* zom sus */ { kError, kStateDefault, kStateZombie, kError, kError, kError }, +/* default */ { kStateDefaultSuspend, kError, kStateDefault, kStateAddr, kError, kError }, +/* def sus */ { kError, kStateDefault, kStateDefault, kError, kError, kError }, +/* addr */ { kStateAddrSuspend, kStateDefault, kError, kError, kStateConfig, kError }, +/* addr sus */{ kError, kStateDefault, kStateAddr, kError, kError, kError }, +/* config */ { kStateConfigSuspend, kStateDefault, kError, kError, kError, kStateAddr }, +/* cfg sus */ { kError, kStateDefault, kStateConfig, kError, kError, kError } +}; + +/* "device state" is the usb device framework state, as opposed to the + "state machine state" which is whatever the driver needs and is much + more fine grained +*/ +static int sm_state_to_device_state[8] = +// zombie zom suspend default default sus +{ USB_STATE_POWERED, USB_STATE_SUSPENDED, USB_STATE_DEFAULT, USB_STATE_SUSPENDED, +// addr addr sus config config sus + USB_STATE_ADDRESS, USB_STATE_SUSPENDED, USB_STATE_CONFIGURED, USB_STATE_SUSPENDED +}; + +static char * state_names[8] = +{ "zombie", "zombie suspended", "default", "default suspended", + "address", "address suspended", "configured", "config suspended" +}; + +static char * event_names[6] = +{ "suspend", "reset", "resume", + "address assigned", "configure", "de-configure" +}; + +static char * device_state_names[] = +{ "not attached", "attached", "powered", "default", + "address", "configured", "suspended" }; + +static int sm_state = kStateZombie; + +////////////////////////////////////////////////////////////////////////////// +// Async +////////////////////////////////////////////////////////////////////////////// +static void core_kicker(void); + +static inline void enable_resume_mask_suspend( void ); +static inline void enable_suspend_mask_resume(void); + +static void +udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs) +{ + __u32 status = Ser0UDCSR; + + /* ReSeT Interrupt Request - UDC has been reset */ + if ( status & UDCSR_RSTIR ) + { + if ( usbctl_next_state_on_event( kEvReset ) != kError ) + { + /* starting 20ms or so reset sequence now... */ + printk("%sResetting\n", pszMe); + ep0_reset(); // just set state to idle + ep1_reset(); // flush dma, clear false stall + ep2_reset(); // flush dma, clear false stall + } + // mask reset ints, they flood during sequence, enable + // suspend and resume + Ser0UDCCR |= UDCCR_REM; // mask reset + Ser0UDCCR &= ~(UDCCR_SUSIM | UDCCR_RESIM); // enable suspend and resume + UDC_flip( Ser0UDCSR, status ); // clear all pending sources + return; // <-- no reason to continue if resetting + } + // else we have done something other than reset, so be sure reset enabled + UDC_clear( Ser0UDCCR, UDCCR_REM ); + + /* RESume Interrupt Request */ + if ( status & UDCSR_RESIR ) + { + usbctl_next_state_on_event( kEvResume ); + core_kicker(); + enable_suspend_mask_resume(); + } + + /* SUSpend Interrupt Request */ + if ( status & UDCSR_SUSIR ) + { + usbctl_next_state_on_event( kEvSuspend ); + enable_resume_mask_suspend(); + } + + UDC_flip(Ser0UDCSR, status); // clear all pending sources + + if (status & UDCSR_EIR) + ep0_int_hndlr(); + + if (status & UDCSR_RIR) + ep1_int_hndlr(status); + + if (status & UDCSR_TIR) + ep2_int_hndlr(status); +} + +static inline void enable_resume_mask_suspend( void ) +{ + int i = 0; + + while( 1 ) { + Ser0UDCCR |= UDCCR_SUSIM; // mask future suspend events + udelay( i ); + if ( (Ser0UDCCR & UDCCR_SUSIM) || (Ser0UDCSR & UDCSR_RSTIR) ) + break; + if ( ++i == 50 ) { + printk( "%senable_resume(): Could not set SUSIM %8.8X\n", + pszMe, Ser0UDCCR ); + break; + } + } + + i = 0; + while( 1 ) { + Ser0UDCCR &= ~UDCCR_RESIM; + udelay( i ); + if ( ( Ser0UDCCR & UDCCR_RESIM ) == 0 + || + (Ser0UDCSR & UDCSR_RSTIR) + ) + break; + if ( ++i == 50 ) { + printk( "%senable_resume(): Could not clear RESIM %8.8X\n", + pszMe, Ser0UDCCR ); + break; + } + } +} + +static inline void enable_suspend_mask_resume(void) +{ + int i = 0; + while( 1 ) { + Ser0UDCCR |= UDCCR_RESIM; // mask future resume events + udelay( i ); + if ( Ser0UDCCR & UDCCR_RESIM || (Ser0UDCSR & UDCSR_RSTIR) ) + break; + if ( ++i == 50 ) { + printk( "%senable_suspend(): Could not set RESIM %8.8X\n", + pszMe, Ser0UDCCR ); + break; + } + } + i = 0; + while( 1 ) { + Ser0UDCCR &= ~UDCCR_SUSIM; + udelay( i ); + if ( ( Ser0UDCCR & UDCCR_SUSIM ) == 0 + || + (Ser0UDCSR & UDCSR_RSTIR) + ) + break; + if ( ++i == 50 ) { + printk( "%senable_suspend(): Could not clear SUSIM %8.8X\n", + pszMe, Ser0UDCCR ); + break; + } + } +} + + +////////////////////////////////////////////////////////////////////////////// +// Public Interface +////////////////////////////////////////////////////////////////////////////// + +/* Open SA usb core on behalf of a client, but don't start running */ + +int +sa1100_usb_open( const char * client ) +{ + if ( usbd_info.client_name != NULL ) + return -EBUSY; + + usbd_info.client_name = (char*) client; + memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t)); + memset(string_desc_array, 0, sizeof(string_desc_array)); + + /* hack to start in zombie suspended state */ + sm_state = kStateZombieSuspend; + usbd_info.state = USB_STATE_SUSPENDED; + + /* create descriptors for enumeration */ + initialize_descriptors(); + + printk( "%sOpened for %s\n", pszMe, client ); + return 0; +} + +/* Start running. Must have called usb_open (above) first */ +int +sa1100_usb_start( void ) +{ + if ( usbd_info.client_name == NULL ) { + printk( "%s%s - no client registered\n", + pszMe, __FUNCTION__ ); + return -EPERM; + } + + /* start UDC internal machinery running */ + udc_enable(); + udelay( 100 ); + + /* clear stall - receiver seems to start stalled? 19Jan01ww */ + /* also clear other stuff just to be thurough 22Feb01ww */ + UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC ); + UDC_clear(Ser0UDCCS2, UDCCS2_FST | UDCCS2_TPE | UDCCS2_TPC ); + + /* mask everything */ + Ser0UDCCR = 0xFC; + + /* flush DMA and fire through some -EAGAINs */ + ep1_init( usbd_info.dmach_rx ); + ep2_init( usbd_info.dmach_tx ); + + /* give endpoint notification we are starting */ + ep1_state_change_notify( USB_STATE_SUSPENDED ); + ep2_state_change_notify( USB_STATE_SUSPENDED ); + + /* enable any platform specific hardware */ + soft_connect_hook( 1 ); + + /* clear all top-level sources */ + Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR | + UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ; + + /* EXERIMENT - a short line in the spec says toggling this + ..bit diddles the internal state machine in the udc to + ..expect a suspend */ + Ser0UDCCR |= UDCCR_RESIM; + /* END EXPERIMENT 10Feb01ww */ + + /* enable any platform specific hardware */ + soft_connect_hook( 1 ); + + /* enable interrupts. If you are unplugged you will + immediately get a suspend interrupt. If you are plugged + and have a soft connect-circuit, you will get a reset + If you are plugged without a soft-connect, I think you + also get suspend. In short, start with suspend masked + and everything else enabled */ + UDC_write( Ser0UDCCR, UDCCR_SUSIM ); + + printk( "%sStarted for %s\n", pszMe, usbd_info.client_name ); + return 0; +} + +/* Stop USB core from running */ +int +sa1100_usb_stop( void ) +{ + if ( usbd_info.client_name == NULL ) { + printk( "%s%s - no client registered\n", + pszMe, __FUNCTION__ ); + return -EPERM; + } + /* mask everything */ + Ser0UDCCR = 0xFC; + ep1_reset(); + ep2_reset(); + udc_disable(); + printk( "%sStopped\n", pszMe ); + return 0; +} + +/* Tell SA core client is through using it */ +int +sa1100_usb_close( void ) +{ + if ( usbd_info.client_name == NULL ) { + printk( "%s%s - no client registered\n", + pszMe, __FUNCTION__ ); + return -EPERM; + } + usbd_info.client_name = NULL; + printk( "%sClosed\n", pszMe ); + return 0; +} + +/* set a proc to be called when device is configured */ +usb_notify_t sa1100_set_configured_callback( usb_notify_t func ) +{ + usb_notify_t retval = configured_callback; + configured_callback = func; + return retval; +} + +/*==================================================== + * Descriptor Manipulation. + * Use these between open() and start() above to setup + * the descriptors for your device. + * + */ + +/* get pointer to static default descriptor */ +desc_t * +sa1100_usb_get_descriptor_ptr( void ) { return &desc; } + +/* optional: set a string descriptor */ +int +sa1100_usb_set_string_descriptor( int i, string_desc_t * p ) +{ + int retval; + if ( i < MAX_STRING_DESC ) { + string_desc_array[i] = p; + retval = 0; + } else { + retval = -EINVAL; + } + return retval; +} + +/* optional: get a previously set string descriptor */ +string_desc_t * +sa1100_usb_get_string_descriptor( int i ) +{ + return ( i < MAX_STRING_DESC ) + ? string_desc_array[i] + : NULL; +} + + +/* optional: kmalloc and unicode up a string descriptor */ +string_desc_t * +sa1100_usb_kmalloc_string_descriptor( const char * p ) +{ + string_desc_t * pResult = NULL; + + if ( p ) { + int len = strlen( p ); + int uni_len = len * sizeof( __u16 ); + pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */ + if ( pResult != NULL ) { + int i; + pResult->bLength = uni_len + 2; + pResult->bDescriptorType = USB_DESC_STRING; + for( i = 0; i < len ; i++ ) { + pResult->bString[i] = make_word( (__u16) p[i] ); + } + } + } + return pResult; +} + +////////////////////////////////////////////////////////////////////////////// +// Exports to rest of driver +////////////////////////////////////////////////////////////////////////////// + +/* called by the int handler here and the two endpoint files when interesting + .."events" happen */ + +int +usbctl_next_state_on_event( int event ) +{ + int next_state = device_state_machine[ sm_state ][ event ]; + if ( next_state != kError ) + { + int next_device_state = sm_state_to_device_state[ next_state ]; + printk( "%s%s --> [%s] --> %s. Device in %s state.\n", + pszMe, state_names[ sm_state ], event_names[ event ], + state_names[ next_state ], device_state_names[ next_device_state ] ); + + sm_state = next_state; + if ( usbd_info.state != next_device_state ) + { + if ( configured_callback != NULL + && + next_device_state == USB_STATE_CONFIGURED + && + usbd_info.state != USB_STATE_SUSPENDED + ) { + configured_callback(); + } + usbd_info.state = next_device_state; + ep1_state_change_notify( next_device_state ); + ep2_state_change_notify( next_device_state ); + } + } +#if 0 + else + printk( "%s%s --> [%s] --> ??? is an error.\n", + pszMe, state_names[ sm_state ], event_names[ event ] ); +#endif + return next_state; +} + +////////////////////////////////////////////////////////////////////////////// +// Private Helpers +////////////////////////////////////////////////////////////////////////////// + +/* setup default descriptors */ + +static void +initialize_descriptors(void) +{ + desc.dev.bLength = sizeof( device_desc_t ); + desc.dev.bDescriptorType = USB_DESC_DEVICE; + desc.dev.bcdUSB = 0x100; /* 1.0 */ + desc.dev.bDeviceClass = 0xFF; /* vendor specific */ + desc.dev.bDeviceSubClass = 0; + desc.dev.bDeviceProtocol = 0; + desc.dev.bMaxPacketSize0 = 8; /* ep0 max fifo size */ + desc.dev.idVendor = 0; /* vendor ID undefined */ + desc.dev.idProduct = 0; /* product */ + desc.dev.bcdDevice = 0; /* vendor assigned device release num */ + desc.dev.iManufacturer = 0; /* index of manufacturer string */ + desc.dev.iProduct = 0; /* index of product description string */ + desc.dev.iSerialNumber = 0; /* index of string holding product s/n */ + desc.dev.bNumConfigurations = 1; + + desc.b.cfg.bLength = sizeof( config_desc_t ); + desc.b.cfg.bDescriptorType = USB_DESC_CONFIG; + desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) ); + desc.b.cfg.bNumInterfaces = 1; + desc.b.cfg.bConfigurationValue = 1; + desc.b.cfg.iConfiguration = 0; + desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED; + desc.b.cfg.MaxPower = USB_POWER( 500 ); + + desc.b.intf.bLength = sizeof( intf_desc_t ); + desc.b.intf.bDescriptorType = USB_DESC_INTERFACE; + desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/ + desc.b.intf.bAlternateSetting = 0; + desc.b.intf.bNumEndpoints = 2; + desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */ + desc.b.intf.bInterfaceSubClass = 0; + desc.b.intf.bInterfaceProtocol = 0; + desc.b.intf.iInterface = 0; + + desc.b.ep1.bLength = sizeof( ep_desc_t ); + desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT; + desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_OUT ); + desc.b.ep1.bmAttributes = USB_EP_BULK; + desc.b.ep1.wMaxPacketSize = make_word_c( 64 ); + desc.b.ep1.bInterval = 0; + + desc.b.ep2.bLength = sizeof( ep_desc_t ); + desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT; + desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_IN ); + desc.b.ep2.bmAttributes = USB_EP_BULK; + desc.b.ep2.wMaxPacketSize = make_word_c( 64 ); + desc.b.ep2.bInterval = 0; + + /* set language */ + /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */ + sd_zero.bDescriptorType = USB_DESC_STRING; + sd_zero.bLength = sizeof( string_desc_t ); + sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */ + sa1100_usb_set_string_descriptor( 0, &sd_zero ); +} + +/* soft_connect_hook() + * Some devices have platform-specific circuitry to make USB + * not seem to be plugged in, even when it is. This allows + * software to control when a device 'appears' on the USB bus + * (after Linux has booted and this driver has loaded, for + * example). If you have such a circuit, control it here. + */ +static void +soft_connect_hook( int enable ) +{ +#ifdef CONFIG_SA1100_EXTENEX1 + if (machine_is_extenex1() ) { + if ( enable ) { + PPDR |= PPC_USB_SOFT_CON; + PPSR |= PPC_USB_SOFT_CON; + } else { + PPSR &= ~PPC_USB_SOFT_CON; + PPDR &= ~PPC_USB_SOFT_CON; + } + } +#endif +} + +/* disable the UDC at the source */ +static void +udc_disable(void) +{ + soft_connect_hook( 0 ); + UDC_set( Ser0UDCCR, UDCCR_UDD ); +} + + +/* enable the udc at the source */ +static void +udc_enable(void) +{ + UDC_clear(Ser0UDCCR, UDCCR_UDD); +} + +// HACK DEBUG 3Mar01ww +// Well, maybe not, it really seems to help! 08Mar01ww +static void +core_kicker( void ) +{ + __u32 car = Ser0UDCAR; + __u32 imp = Ser0UDCIMP; + __u32 omp = Ser0UDCOMP; + + UDC_set( Ser0UDCCR, UDCCR_UDD ); + udelay( 300 ); + UDC_clear(Ser0UDCCR, UDCCR_UDD); + + Ser0UDCAR = car; + Ser0UDCIMP = imp; + Ser0UDCOMP = omp; +} + +////////////////////////////////////////////////////////////////////////////// +// Proc Filesystem Support +////////////////////////////////////////////////////////////////////////////// + +#if CONFIG_PROC_FS + +#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args ) +#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num ) +#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn ) +#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v ) + +static int usbctl_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + const char * num_fmt = "%25.25s: %8.8lX\n"; + const char * cnt_fmt = "%25.25s: %lu\n"; + const char * yn_fmt = "%25.25s: %s\n"; + const char * yes = "YES"; + const char * no = "NO"; + unsigned long v; + char * p = page; + int len; + + SAY( "SA1100 USB Controller Core\n" ); + SAY( "USB state: %s (%s) %d\n", + device_state_names[ sm_state_to_device_state[ sm_state ] ], + state_names[ sm_state ], + sm_state ); + + SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read ); + SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written ); + SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures ); + SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures ); + + SAY( "\n" ); + + v = Ser0UDCAR; + SAY( "%25.25s: 0x%8.8lX - %ld\n", "Address Register", v, v ); + v = Ser0UDCIMP; + SAY( "%25.25s: %ld (%8.8lX)\n", "IN max packet size", v+1, v ); + v = Ser0UDCOMP; + SAY( "%25.25s: %ld (%8.8lX)\n", "OUT max packet size", v+1, v ); + + v = Ser0UDCCR; + SAY( "\nUDC Mask Register\n" ); + SAYV( v ); + SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no ); + SAYC( "Suspend interrupts masked", ( v & UDCCR_SUSIM ) ? yes : no ); + SAYC( "Resume interrupts masked", ( v & UDCCR_RESIM ) ? yes : no ); + SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no ); + + v = Ser0UDCSR; + SAY( "\nUDC Interrupt Request Register\n" ); + SAYV( v ); + SAYC( "Reset pending", ( v & UDCSR_RSTIR ) ? yes : no ); + SAYC( "Suspend pending", ( v & UDCSR_SUSIR ) ? yes : no ); + SAYC( "Resume pending", ( v & UDCSR_RESIR ) ? yes : no ); + SAYC( "ep0 pending", ( v & UDCSR_EIR ) ? yes : no ); + SAYC( "receiver pending", ( v & UDCSR_RIR ) ? yes : no ); + SAYC( "tramsitter pending", ( v & UDCSR_TIR ) ? yes : no ); + +#ifdef CONFIG_SA1100_EXTENEX1 + SAYC( "\nSoft connect", (PPSR & PPC_USB_SOFT_CON) ? "Visible" : "Hidden" ); +#endif + +#if 0 + v = Ser0UDCCS0; + SAY( "\nUDC Endpoint Zero Status Register\n" ); + SAYV( v ); + SAYC( "Out Packet Ready", ( v & UDCCS0_OPR ) ? yes : no ); + SAYC( "In Packet Ready", ( v & UDCCS0_IPR ) ? yes : no ); + SAYC( "Sent Stall", ( v & UDCCS0_SST ) ? yes : no ); + SAYC( "Force Stall", ( v & UDCCS0_FST ) ? yes : no ); + SAYC( "Data End", ( v & UDCCS0_DE ) ? yes : no ); + SAYC( "Data Setup End", ( v & UDCCS0_SE ) ? yes : no ); + SAYC( "Serviced (SO)", ( v & UDCCS0_SO ) ? yes : no ); + + v = Ser0UDCCS1; + SAY( "\nUDC Receiver Status Register\n" ); + SAYV( v ); + SAYC( "Receive Packet Complete", ( v & UDCCS1_RPC ) ? yes : no ); + SAYC( "Sent Stall", ( v & UDCCS1_SST ) ? yes : no ); + SAYC( "Force Stall", ( v & UDCCS1_FST ) ? yes : no ); + SAYC( "Receive Packet Error", ( v & UDCCS1_RPE ) ? yes : no ); + SAYC( "Receive FIFO not empty", ( v & UDCCS1_RNE ) ? yes : no ); + + v = Ser0UDCCS2; + SAY( "\nUDC Transmitter Status Register\n" ); + SAYV( v ); + SAYC( "FIFO has < 8 of 16 chars", ( v & UDCCS2_TFS ) ? yes : no ); + SAYC( "Transmit Packet Complete", ( v & UDCCS2_TPC ) ? yes : no ); + SAYC( "Transmit FIFO underrun", ( v & UDCCS2_TUR ) ? yes : no ); + SAYC( "Transmit Packet Error", ( v & UDCCS2_TPE ) ? yes : no ); + SAYC( "Sent Stall", ( v & UDCCS2_SST ) ? yes : no ); + SAYC( "Force Stall", ( v & UDCCS2_FST ) ? yes : no ); +#endif + + len = ( p - page ) - off; + if ( len < 0 ) + len = 0; + *eof = ( len <=count ) ? 1 : 0; + *start = page + off; + return len; +} + +#endif /* CONFIG_PROC_FS */ + +////////////////////////////////////////////////////////////////////////////// +// Module Initialization and Shutdown +////////////////////////////////////////////////////////////////////////////// +/* + * usbctl_init() + * Module load time. Allocate dma and interrupt resources. Setup /proc fs + * entry. Leave UDC disabled. + */ +int __init usbctl_init( void ) +{ + int retval = 0; + + udc_disable(); + + memset( &usbd_info, 0, sizeof( usbd_info ) ); + +#if CONFIG_PROC_FS + create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL); +#endif + + /* setup rx dma */ + retval = sa1100_request_dma(&usbd_info.dmach_rx, "USB receive", DMA_Ser0UDCRd); + if (retval) { + printk("%sunable to register for rx dma rc=%d\n", pszMe, retval ); + goto err_rx_dma; + } + + /* setup tx dma */ + retval = sa1100_request_dma(&usbd_info.dmach_tx, "USB transmit", DMA_Ser0UDCWr); + if (retval) { + printk("%sunable to register for tx dma rc=%d\n",pszMe,retval); + goto err_tx_dma; + } + + /* now allocate the IRQ. */ + retval = request_irq(IRQ_Ser0UDC, udc_int_hndlr, SA_INTERRUPT, + "SA USB core", NULL); + if (retval) { + printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval); + goto err_irq; + } + + printk( "SA1100 USB Controller Core Initialized\n"); + return 0; + +err_irq: + sa1100_free_dma(usbd_info.dmach_tx); + usbd_info.dmach_tx = 0; +err_tx_dma: + sa1100_free_dma(usbd_info.dmach_rx); + usbd_info.dmach_rx = 0; +err_rx_dma: + return retval; +} +/* + * usbctl_exit() + * Release DMA and interrupt resources + */ +void __exit usbctl_exit( void ) +{ + printk("Unloading SA1100 USB Controller\n"); + + udc_disable(); + +#if CONFIG_PROC_FS + remove_proc_entry ( PROC_NODE_NAME, NULL); +#endif + + sa1100_free_dma(usbd_info.dmach_rx); + sa1100_free_dma(usbd_info.dmach_tx); + free_irq(IRQ_Ser0UDC, NULL); +} + +EXPORT_SYMBOL( sa1100_usb_open ); +EXPORT_SYMBOL( sa1100_usb_start ); +EXPORT_SYMBOL( sa1100_usb_stop ); +EXPORT_SYMBOL( sa1100_usb_close ); + + +EXPORT_SYMBOL( sa1100_usb_get_descriptor_ptr ); +EXPORT_SYMBOL( sa1100_usb_set_string_descriptor ); +EXPORT_SYMBOL( sa1100_usb_get_string_descriptor ); +EXPORT_SYMBOL( sa1100_usb_kmalloc_string_descriptor ); + + +module_init( usbctl_init ); +module_exit( usbctl_exit ); diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb_ctl.h linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_ctl.h --- linux-2.4.37.9/arch/arm/mach-sa1100/usb_ctl.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_ctl.h Wed May 26 15:44:05 2010 @@ -0,0 +1,123 @@ +/* + * Copyright (C) Compaq Computer Corporation, 1998, 1999 + * Copyright (C) Extenex Corporation 2001 + * + * usb_ctl.h + * + * PRIVATE interface used to share info among components of the SA-1100 USB + * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core + * should use sa1100_usb.h. + * + */ + +#ifndef _USB_CTL_H +#define _USB_CTL_H + +#include /* dmach_t */ + + +/* + * These states correspond to those in the USB specification v1.0 + * in chapter 8, Device Framework. + */ +enum { USB_STATE_NOTATTACHED=0, USB_STATE_ATTACHED=1,USB_STATE_POWERED=2, + USB_STATE_DEFAULT=3, USB_STATE_ADDRESS=4, USB_STATE_CONFIGURED=5, + USB_STATE_SUSPENDED=6}; + +struct usb_stats_t { + unsigned long ep0_fifo_write_failures; + unsigned long ep0_bytes_written; + unsigned long ep0_fifo_read_failures; + unsigned long ep0_bytes_read; +}; + +struct usb_info_t +{ + char * client_name; + dmach_t dmach_tx, dmach_rx; + int state; + unsigned char address; + struct usb_stats_t stats; +}; + +/* in usb_ctl.c */ +extern struct usb_info_t usbd_info; + +/* + * Function Prototypes + */ +enum { kError=-1, kEvSuspend=0, kEvReset=1, + kEvResume=2, kEvAddress=3, kEvConfig=4, kEvDeConfig=5 }; +int usbctl_next_state_on_event( int event ); + +/* endpoint zero */ +void ep0_reset(void); +void ep0_int_hndlr(void); + +/* receiver */ +void ep1_state_change_notify( int new_state ); +int ep1_recv(void); +int ep1_init(int chn); +void ep1_int_hndlr(int status); +void ep1_reset(void); +void ep1_stall(void); + +/* xmitter */ +void ep2_state_change_notify( int new_state ); +void ep2_reset(void); +int ep2_init(int chn); +void ep2_int_hndlr(int status); +void ep2_stall(void); + +#define UDC_write(reg, val) { \ + int i = 10000; \ + do { \ + (reg) = (val); \ + if (i-- <= 0) { \ + printk( "%s [%d]: write %#x to %p (%#x) failed\n", \ + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ + break; \ + } \ + } while((reg) != (val)); \ +} + +#define UDC_set(reg, val) { \ + int i = 10000; \ + do { \ + (reg) |= (val); \ + if (i-- <= 0) { \ + printk( "%s [%d]: set %#x of %p (%#x) failed\n", \ + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ + break; \ + } \ + } while(!((reg) & (val))); \ +} + +#define UDC_clear(reg, val) { \ + int i = 10000; \ + do { \ + (reg) &= ~(val); \ + if (i-- <= 0) { \ + printk( "%s [%d]: clear %#x of %p (%#x) failed\n", \ + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ + break; \ + } \ + } while((reg) & (val)); \ +} + +#define UDC_flip(reg, val) { \ + int i = 10000; \ + (reg) = (val); \ + do { \ + (reg) = (val); \ + if (i-- <= 0) { \ + printk( "%s [%d]: flip %#x of %p (%#x) failed\n", \ + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \ + break; \ + } \ + } while(((reg) & (val))); \ +} + + +#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}} +#endif /* _USB_CTL_H */ diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb_ep0.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_ep0.c --- linux-2.4.37.9/arch/arm/mach-sa1100/usb_ep0.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_ep0.c Wed May 26 15:44:05 2010 @@ -0,0 +1,911 @@ +/* + * Copyright (C) Extenex Corporation 2001 + * Much folklore gleaned from original code: + * Copyright (C) Compaq Computer Corporation, 1998, 1999 + * + * usb_ep0.c - SA1100 USB controller driver. + * Endpoint zero management + * + * Please see: + * linux/Documentation/arm/SA1100/SA1100_USB + * for details. (Especially since Intel docs are full of + * errors about ep0 operation.) ward.willats@extenex.com. + * + * Intel also has a "Universal Serial Bus Client Device + * Validation for the StrongARM SA-1100 Microprocessor" + * document, which has flow charts and assembler test driver, + * but be careful, since it is just for validation and not + * a "real world" solution. + * + * A summary of three types of data-returning setups: + * + * 1. Setup request <= 8 bytes. That is, requests that can + * be fullfilled in one write to the FIFO. DE is set + * with IPR in queue_and_start_write(). (I don't know + * if there really are any of these!) + * + * 2. Setup requests > 8 bytes (requiring more than one + * IN to get back to the host), and we have at least + * as much or more data than the host requested. In + * this case we pump out everything we've got, and + * when the final interrupt comes in due to the UDC + * clearing the last IPR, we just set DE. + * + * 3. Setup requests > 8 bytes, but we don't have enough + * data to satisfy the request. In this case, we send + * everything we've got, and when the final interrupt + * comes in due to the UDC clearing the last IPR + * we write nothing to the FIFO and set both IPR and DE + * so the UDC sends an empty packet and forces the host + * to perform short packet retirement instead of stalling + * out. + * + */ + +#include +#include "sa1100_usb.h" /* public interface */ +#include "usb_ctl.h" /* private stuff */ + + +// 1 == lots of trace noise, 0 = only "important' stuff +#define VERBOSITY 0 + +enum { true = 1, false = 0 }; +typedef int bool; +#ifndef MIN +#define MIN( a, b ) ((a)<(b)?(a):(b)) +#endif + +#if 1 && !defined( ASSERT ) +# define ASSERT(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n",\ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#else +# define ASSERT(expr) +#endif + +#if VERBOSITY +#define PRINTKD(fmt, args...) printk( fmt , ## args) +#else +#define PRINTKD(fmt, args...) +#endif + +/*================================================ + * USB Protocol Stuff + */ + +/* Request Codes */ +enum { GET_STATUS=0, CLEAR_FEATURE=1, SET_FEATURE=3, + SET_ADDRESS=5, GET_DESCRIPTOR=6, SET_DESCRIPTOR=7, + GET_CONFIGURATION=8, SET_CONFIGURATION=9, GET_INTERFACE=10, + SET_INTERFACE=11 }; + + +/* USB Device Requests */ +typedef struct +{ + __u8 bmRequestType; + __u8 bRequest; + __u16 wValue; + __u16 wIndex; + __u16 wLength; +} usb_dev_request_t __attribute__ ((packed)); + +/*************************************************************************** +Prototypes +***************************************************************************/ +/* "setup handlers" -- the main functions dispatched to by the + .. isr. These represent the major "modes" of endpoint 0 operaton */ +static void sh_setup_begin(void); /* setup begin (idle) */ +static void sh_write( void ); /* writing data */ +static void sh_write_with_empty_packet( void ); /* empty packet at end of xfer*/ +/* called before both sh_write routines above */ +static void common_write_preamble( void ); + +/* other subroutines */ +static __u32 queue_and_start_write( void * p, int req, int act ); +static void write_fifo( void ); +static int read_fifo( usb_dev_request_t * p ); +static void get_descriptor( usb_dev_request_t * pReq ); + +/* some voodo helpers 01Mar01ww */ +static void set_cs_bits( __u32 set_bits ); +static void set_de( void ); +static void set_ipr( void ); +static void set_ipr_and_de( void ); +static bool clear_opr( void ); + +/*************************************************************************** +Inline Helpers +***************************************************************************/ + +/* Data extraction from usb_request_t fields */ +enum { kTargetDevice=0, kTargetInterface=1, kTargetEndpoint=2 }; +static inline int request_target( __u8 b ) { return (int) ( b & 0x0F); } + +static inline int windex_to_ep_num( __u16 w ) { return (int) ( w & 0x000F); } +inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); } + +/* following is hook for self-powered flag in GET_STATUS. Some devices + .. might like to override and return real info */ +static inline bool self_powered_hook( void ) { return true; } + +/* print string descriptor */ +static inline void psdesc( string_desc_t * p ) +{ + int i; + int nchars = ( p->bLength - 2 ) / sizeof( __u16 ); + printk( "'" ); + for( i = 0 ; i < nchars ; i++ ) { + printk( "%c", (char) p->bString[i] ); + } + printk( "'\n" ); +} + + +#if VERBOSITY +/* "pcs" == "print control status" */ +static inline void pcs( void ) +{ + __u32 foo = Ser0UDCCS0; + printk( "%8.8X: %s %s %s %s\n", + foo, + foo & UDCCS0_SE ? "SE" : "", + foo & UDCCS0_OPR ? "OPR" : "", + foo & UDCCS0_IPR ? "IPR" : "", + foo & UDCCS0_SST ? "SST" : "" + ); +} +static inline void preq( usb_dev_request_t * pReq ) +{ + static char * tnames[] = { "dev", "intf", "ep", "oth" }; + static char * rnames[] = { "std", "class", "vendor", "???" }; + char * psz; + switch( pReq->bRequest ) { + case GET_STATUS: psz = "get stat"; break; + case CLEAR_FEATURE: psz = "clr feat"; break; + case SET_FEATURE: psz = "set feat"; break; + case SET_ADDRESS: psz = "set addr"; break; + case GET_DESCRIPTOR: psz = "get desc"; break; + case SET_DESCRIPTOR: psz = "set desc"; break; + case GET_CONFIGURATION: psz = "get cfg"; break; + case SET_CONFIGURATION: psz = "set cfg"; break; + case GET_INTERFACE: psz = "get intf"; break; + case SET_INTERFACE: psz = "set intf"; break; + default: psz = "unknown"; break; + } + printk( "- [%s: %s req to %s. dir=%s]\n", psz, + rnames[ (pReq->bmRequestType >> 5) & 3 ], + tnames[ pReq->bmRequestType & 3 ], + ( pReq->bmRequestType & 0x80 ) ? "in" : "out" ); +} + +#else +static inline void pcs( void ){} +static inline void preq( void ){} +#endif + +/*************************************************************************** +Globals +***************************************************************************/ +static const char pszMe[] = "usbep0: "; + +/* pointer to current setup handler */ +static void (*current_handler)(void) = sh_setup_begin; + +/* global write struct to keep write + ..state around across interrupts */ +static struct { + unsigned char *p; + int bytes_left; +} wr; + +/*************************************************************************** +Public Interface +***************************************************************************/ + +/* reset received from HUB (or controller just went nuts and reset by itself!) + so udc core has been reset, track this state here */ +void +ep0_reset(void) +{ + /* reset state machine */ + current_handler = sh_setup_begin; + wr.p = NULL; + wr.bytes_left = 0; + usbd_info.address=0; +} + +/* handle interrupt for endpoint zero */ +void +ep0_int_hndlr( void ) +{ + PRINTKD( "/\\(%d)\n", Ser0UDCAR ); + pcs(); + + /* if not in setup begin, we are returning data. + execute a common preamble to both write handlers + */ + if ( current_handler != sh_setup_begin ) + common_write_preamble(); + + (*current_handler)(); + + PRINTKD( "---\n" ); + pcs(); + PRINTKD( "\\/\n" ); +} + +/*************************************************************************** +Setup Handlers +***************************************************************************/ +/* + * sh_setup_begin() + * This setup handler is the "idle" state of endpoint zero. It looks for OPR + * (OUT packet ready) to see if a setup request has been been received from the + * host. Requests without a return data phase are immediately handled. Otherwise, + * in the case of GET_XXXX the handler may be set to one of the sh_write_xxxx + * data pumpers if more than 8 bytes need to get back to the host. + * + */ +static void +sh_setup_begin( void ) +{ + unsigned char status_buf[2]; /* returned in GET_STATUS */ + usb_dev_request_t req; + int request_type; + int n; + __u32 cs_bits; + __u32 address; + __u32 cs_reg_in = Ser0UDCCS0; + + if (cs_reg_in & UDCCS0_SST) { + PRINTKD( "%ssetup begin: sent stall. Continuing\n", pszMe ); + set_cs_bits( UDCCS0_SST ); + } + + if ( cs_reg_in & UDCCS0_SE ) { + PRINTKD( "%ssetup begin: Early term of setup. Continuing\n", pszMe ); + set_cs_bits( UDCCS0_SSE ); /* clear setup end */ + } + + /* Be sure out packet ready, otherwise something is wrong */ + if ( (cs_reg_in & UDCCS0_OPR) == 0 ) { + /* we can get here early...if so, we'll int again in a moment */ + PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe ); + goto sh_sb_end; + } + + /* read the setup request */ + n = read_fifo( &req ); + if ( n != sizeof( req ) ) { + printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. " + " Stalling out...\n", + pszMe, sizeof( req ), n ); + /* force stall, serviced out */ + set_cs_bits( UDCCS0_FST | UDCCS0_SO ); + goto sh_sb_end; + } + + /* Is it a standard request? (not vendor or class request) */ + request_type = type_code_from_request( req.bmRequestType ); + if ( request_type != 0 ) { + printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n", + pszMe, request_type ); + set_cs_bits( UDCCS0_DE | UDCCS0_SO ); + goto sh_sb_end; + } + +#if VERBOSITY + { + unsigned char * pdb = (unsigned char *) &req; + PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ", + pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7] + ); + preq( &req ); + } +#endif + + /* Handle it */ + switch( req.bRequest ) { + + /* This first bunch have no data phase */ + + case SET_ADDRESS: + address = (__u32) (req.wValue & 0x7F); + /* when SO and DE sent, UDC will enter status phase and ack, + ..propagating new address to udc core. Next control transfer + ..will be on the new address. You can't see the change in a + ..read back of CAR until then. (about 250us later, on my box). + ..The original Intel driver sets S0 and DE and code to check + ..that address has propagated here. I tried this, but it + ..would only work sometimes! The rest of the time it would + ..never propagate and we'd spin forever. So now I just set + ..it and pray... + */ + Ser0UDCAR = address; + usbd_info.address = address; + usbctl_next_state_on_event( kEvAddress ); + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */ + printk( "%sI have been assigned address: %d\n", pszMe, address ); + break; + + + case SET_CONFIGURATION: + if ( req.wValue == 1 ) { + /* configured */ + if (usbctl_next_state_on_event( kEvConfig ) != kError){ + /* (re)set the out and in max packet sizes */ + desc_t * pDesc = sa1100_usb_get_descriptor_ptr(); + __u32 out = __le16_to_cpu( pDesc->b.ep1.wMaxPacketSize ); + __u32 in = __le16_to_cpu( pDesc->b.ep2.wMaxPacketSize ); + Ser0UDCOMP = ( out - 1 ); + Ser0UDCIMP = ( in - 1 ); + printk( "%sConfigured (OMP=%8.8X IMP=%8.8X)\n", pszMe, out, in ); + } + } else if ( req.wValue == 0 ) { + /* de-configured */ + if (usbctl_next_state_on_event( kEvDeConfig ) != kError ) + printk( "%sDe-Configured\n", pszMe ); + } else { + printk( "%ssetup phase: Unknown " + "\"set configuration\" data %d\n", + pszMe, req.wValue ); + } + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */ + break; + + case CLEAR_FEATURE: + /* could check data length, direction...26Jan01ww */ + if ( req.wValue == 0 ) { /* clearing ENDPOINT_HALT/STALL */ + int ep = windex_to_ep_num( req.wIndex ); + if ( ep == 1 ) { + printk( "%sclear feature \"endpoint halt\" " + " on receiver\n", pszMe ); + ep1_reset(); + } + else if ( ep == 2 ) { + printk( "%sclear feature \"endpoint halt\" " + "on xmitter\n", pszMe ); + ep2_reset(); + } else { + printk( "%sclear feature \"endpoint halt\" " + "on unsupported ep # %d\n", + pszMe, ep ); + } + } else { + printk( "%sUnsupported feature selector (%d) " + "in clear feature. Ignored.\n" , + pszMe, req.wValue ); + } + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */ + break; + + case SET_FEATURE: + if ( req.wValue == 0 ) { /* setting ENDPOINT_HALT/STALL */ + int ep = windex_to_ep_num( req.wValue ); + if ( ep == 1 ) { + printk( "%set feature \"endpoint halt\" " + "on receiver\n", pszMe ); + ep1_stall(); + } + else if ( ep == 2 ) { + printk( "%sset feature \"endpoint halt\" " + " on xmitter\n", pszMe ); + ep2_stall(); + } else { + printk( "%sset feature \"endpoint halt\" " + "on unsupported ep # %d\n", + pszMe, ep ); + } + } + else { + printk( "%sUnsupported feature selector " + "(%d) in set feature\n", + pszMe, req.wValue ); + } + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */ + break; + + + /* The rest have a data phase that writes back to the host */ + case GET_STATUS: + /* return status bit flags */ + status_buf[0] = status_buf[1] = 0; + n = request_target(req.bmRequestType); + switch( n ) { + case kTargetDevice: + if ( self_powered_hook() ) + status_buf[0] |= 1; + break; + case kTargetInterface: + break; + case kTargetEndpoint: + /* return stalled bit */ + n = windex_to_ep_num( req.wIndex ); + if ( n == 1 ) + status_buf[0] |= (Ser0UDCCS1 & UDCCS1_FST) >> 4; + else if ( n == 2 ) + status_buf[0] |= (Ser0UDCCS2 & UDCCS2_FST) >> 5; + else { + printk( "%sUnknown endpoint (%d) " + "in GET_STATUS\n", pszMe, n ); + } + break; + default: + printk( "%sUnknown target (%d) in GET_STATUS\n", + pszMe, n ); + /* fall thru */ + break; + } + cs_bits = queue_and_start_write( status_buf, + req.wLength, + sizeof( status_buf ) ); + set_cs_bits( cs_bits ); + break; + case GET_DESCRIPTOR: + get_descriptor( &req ); + break; + + case GET_CONFIGURATION: + status_buf[0] = (usbd_info.state == USB_STATE_CONFIGURED) + ? 1 + : 0; + cs_bits = queue_and_start_write( status_buf, req.wLength, 1 ); + set_cs_bits( cs_bits ); + break; + case GET_INTERFACE: + printk( "%sfixme: get interface not supported\n", pszMe ); + cs_bits = queue_and_start_write( NULL, req.wLength, 0 ); + set_cs_bits( cs_bits ); + break; + case SET_INTERFACE: + printk( "%sfixme: set interface not supported\n", pszMe ); + set_cs_bits( UDCCS0_DE | UDCCS0_SO ); + break; + default : + printk("%sunknown request 0x%x\n", pszMe, req.bRequest); + break; + } /* switch( bRequest ) */ + +sh_sb_end: + return; + +} +/* + * common_wrtie_preamble() + * Called before execution of sh_write() or sh_write_with_empty_packet() + * Handles common abort conditions. + * + */ +static void common_write_preamble( void ) +{ + /* If "setup end" has been set, the usb controller has + ..terminated a setup transaction before we set DE. This + ..happens during enumeration with some hosts. For example, + ..the host will ask for our device descriptor and specify + ..a return of 64 bytes. When we hand back the first 8, the + ..host will know our max packet size and turn around and + ..issue a new setup immediately. This causes the UDC to auto-ack + ..the new setup and set SE. We must then "unload" (process) + ..the new setup, which is what will happen after this preamble + ..is finished executing. + */ + __u32 cs_reg_in = Ser0UDCCS0; + + if ( cs_reg_in & UDCCS0_SE ) { + PRINTKD( "%swrite_preamble(): Early termination of setup\n", pszMe ); + Ser0UDCCS0 = UDCCS0_SSE; /* clear setup end */ + current_handler = sh_setup_begin; + } + + if ( cs_reg_in & UDCCS0_SST ) { + PRINTKD( "%swrite_preamble(): UDC sent stall\n", pszMe ); + Ser0UDCCS0 = UDCCS0_SST; /* clear setup end */ + current_handler = sh_setup_begin; + } + + if ( cs_reg_in & UDCCS0_OPR ) { + PRINTKD( "%swrite_preamble(): see OPR. Stopping write to " + "handle new SETUP\n", pszMe ); + /* very rarely, you can get OPR and leftover IPR. Try to clear */ + UDC_clear( Ser0UDCCS0, UDCCS0_IPR ); + current_handler = sh_setup_begin; + } +} + +/* + * sh_write() + * This is the setup handler when we are in the data return phase of + * a setup request and have as much (or more) data than the host + * requested. If we enter this routine and bytes left is zero, the + * last data packet has gone (int is because IPR was just cleared) + * so we just set DE and reset. Otheriwse, we write another packet + * and set IPR. + */ +static void sh_write() +{ + PRINTKD( "W\n" ); + + if ( Ser0UDCCS0 & UDCCS0_IPR ) { + PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe ); + return; + } + + /* If bytes left is zero, we are coming in on the + ..interrupt after the last packet went out. And + ..we know we don't have to empty packet this transfer + ..so just set DE and we are done */ + + if ( 0 == wr.bytes_left ) { + /* that's it, so data end */ + set_de(); + wr.p = NULL; /* be anal */ + current_handler = sh_setup_begin; + } else { + /* Otherwise, more data to go */ + write_fifo(); + set_ipr(); + } +} +/* + * sh_write_with_empty_packet() + * This is the setup handler when we don't have enough data to + * satisfy the host's request. After we send everything we've got + * we must send an empty packet (by setting IPR and DE) so the + * host can perform "short packet retirement" and not stall. + * + */ +static void sh_write_with_empty_packet( void ) +{ + __u32 cs_reg_out = 0; + PRINTKD( "WE\n" ); + + if ( Ser0UDCCS0 & UDCCS0_IPR ) { + PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe ); + return; + } + + /* If bytes left is zero, we are coming in on the + ..interrupt after the last packet went out. + ..we must do short packet suff, so set DE and IPR + */ + + if ( 0 == wr.bytes_left ) { + set_ipr_and_de(); + wr.p = NULL; + current_handler = sh_setup_begin; + PRINTKD( "%ssh_write empty() Sent empty packet \n", pszMe ); + } else { + write_fifo(); /* send data */ + set_ipr(); /* flag a packet is ready */ + } + Ser0UDCCS0 = cs_reg_out; +} + +/*************************************************************************** +Other Private Subroutines +***************************************************************************/ +/* + * queue_and_start_write() + * p == data to send + * req == bytes host requested + * act == bytes we actually have + * Returns: bits to be flipped in ep0 control/status register + * + * Called from sh_setup_begin() to begin a data return phase. Sets up the + * global "wr"-ite structure and load the outbound FIFO with data. + * If can't send all the data, set appropriate handler for next interrupt. + * + */ +static __u32 queue_and_start_write( void * in, int req, int act ) +{ + __u32 cs_reg_bits = UDCCS0_IPR; + unsigned char * p = (unsigned char*) in; + + PRINTKD( "Qr=%d a=%d\n",req,act ); + + /* thou shalt not enter data phase until the serviced OUT is clear */ + if ( ! clear_opr() ) { + printk( "%sSO did not clear OPR\n", pszMe ); + return ( UDCCS0_DE | UDCCS0_SO ) ; + } + wr.p = p; + wr.bytes_left = MIN( act, req ); + + write_fifo(); + + if ( 0 == wr.bytes_left ) { + cs_reg_bits |= UDCCS0_DE; /* out in 1 so data end */ + wr.p = NULL; /* be anal */ + } + else if ( act < req ) /* we are going to short-change host */ + current_handler = sh_write_with_empty_packet; /* so need nul to not stall */ + else /* we have as much or more than requested */ + current_handler = sh_write; + + return cs_reg_bits; /* note: IPR was set uncondtionally at start of routine */ +} +/* + * write_fifo() + * Stick bytes in the 8 bytes endpoint zero FIFO. + * This version uses a variety of tricks to make sure the bytes + * are written correctly. 1. The count register is checked to + * see if the byte went in, and the write is attempted again + * if not. 2. An overall counter is used to break out so we + * don't hang in those (rare) cases where the UDC reverses + * direction of the FIFO underneath us without notification + * (in response to host aborting a setup transaction early). + * + */ +static void write_fifo( void ) +{ + int bytes_this_time = MIN( wr.bytes_left, 8 ); + int bytes_written = 0; + int i=0; + + PRINTKD( "WF=%d: ", bytes_this_time ); + + while( bytes_this_time-- ) { + PRINTKD( "%2.2X ", *wr.p ); + i = 0; + do { + Ser0UDCD0 = *wr.p; + udelay( 20 ); /* voodo 28Feb01ww */ + i++; + } while( Ser0UDCWC == bytes_written && i < 10 ); + if ( i == 50 ) { + printk( "%swrite_fifo: write failure\n", pszMe ); + usbd_info.stats.ep0_fifo_write_failures++; + } + + wr.p++; + bytes_written++; + } + wr.bytes_left -= bytes_written; + + /* following propagation voodo so maybe caller writing IPR in + ..a moment might actually get it to stick 28Feb01ww */ + udelay( 300 ); + + usbd_info.stats.ep0_bytes_written += bytes_written; + PRINTKD( "L=%d WCR=%8.8X\n", wr.bytes_left, Ser0UDCWC ); +} +/* + * read_fifo() + * Read 1-8 bytes out of FIFO and put in request. + * Called to do the initial read of setup requests + * from the host. Return number of bytes read. + * + * Like write fifo above, this driver uses multiple + * reads checked agains the count register with an + * overall timeout. + * + */ +static int +read_fifo( usb_dev_request_t * request ) +{ + int bytes_read = 0; + int fifo_count; + int i; + + unsigned char * pOut = (unsigned char*) request; + + fifo_count = ( Ser0UDCWC & 0xFF ); + + ASSERT( fifo_count <= 8 ); + PRINTKD( "RF=%d ", fifo_count ); + + while( fifo_count-- ) { + i = 0; + do { + *pOut = (unsigned char) Ser0UDCD0; + udelay( 10 ); + } while( ( Ser0UDCWC & 0xFF ) != fifo_count && i < 10 ); + if ( i == 10 ) { + printk( "%sread_fifo(): read failure\n", pszMe ); + usbd_info.stats.ep0_fifo_read_failures++; + } + pOut++; + bytes_read++; + } + + PRINTKD( "fc=%d\n", bytes_read ); + usbd_info.stats.ep0_bytes_read++; + return bytes_read; +} + +/* + * get_descriptor() + * Called from sh_setup_begin to handle data return + * for a GET_DESCRIPTOR setup request. + */ +static void get_descriptor( usb_dev_request_t * pReq ) +{ + __u32 cs_bits = 0; + string_desc_t * pString; + ep_desc_t * pEndpoint; + + desc_t * pDesc = sa1100_usb_get_descriptor_ptr(); + int type = pReq->wValue >> 8; + int idx = pReq->wValue & 0xFF; + + switch( type ) { + case USB_DESC_DEVICE: + cs_bits = + queue_and_start_write( &pDesc->dev, + pReq->wLength, + pDesc->dev.bLength ); + break; + + // return config descriptor buffer, cfg, intf, 2 ep + case USB_DESC_CONFIG: + cs_bits = + queue_and_start_write( &pDesc->b, + pReq->wLength, + sizeof( struct cdb ) ); + break; + + // not quite right, since doesn't do language code checking + case USB_DESC_STRING: + pString = sa1100_usb_get_string_descriptor( idx ); + if ( pString ) { + if ( idx != 0 ) { // if not language index + printk( "%sReturn string %d: ", pszMe, idx ); + psdesc( pString ); + } + cs_bits = + queue_and_start_write( pString, + pReq->wLength, + pString->bLength ); + } + else { + printk("%sunkown string index %d Stall.\n", pszMe, idx ); + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST ); + } + break; + + case USB_DESC_INTERFACE: + if ( idx == pDesc->b.intf.bInterfaceNumber ) { + cs_bits = + queue_and_start_write( &pDesc->b.intf, + pReq->wLength, + pDesc->b.intf.bLength ); + } + break; + + case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */ + if ( idx == 1 ) + pEndpoint = &pDesc->b.ep1; + else if ( idx == 2 ) + pEndpoint = &pDesc->b.ep2; + else + pEndpoint = NULL; + if ( pEndpoint ) { + cs_bits = + queue_and_start_write( pEndpoint, + pReq->wLength, + pEndpoint->bLength ); + } else { + printk("%sunkown endpoint index %d Stall.\n", pszMe, idx ); + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST ); + } + break; + + + default : + printk("%sunknown descriptor type %d. Stall.\n", pszMe, type ); + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST ); + break; + + } + set_cs_bits( cs_bits ); +} + + +/* some voodo I am adding, since the vanilla macros just aren't doing it 1Mar01ww */ + +#define ABORT_BITS ( UDCCS0_SST | UDCCS0_SE ) +#define OK_TO_WRITE (!( Ser0UDCCS0 & ABORT_BITS )) +#define BOTH_BITS (UDCCS0_IPR | UDCCS0_DE) + +static void set_cs_bits( __u32 bits ) +{ + if ( bits & ( UDCCS0_SO | UDCCS0_SSE | UDCCS0_FST ) ) + Ser0UDCCS0 = bits; + else if ( (bits & BOTH_BITS) == BOTH_BITS ) + set_ipr_and_de(); + else if ( bits & UDCCS0_IPR ) + set_ipr(); + else if ( bits & UDCCS0_DE ) + set_de(); +} + +static void set_de( void ) +{ + int i = 1; + while( 1 ) { + if ( OK_TO_WRITE ) { + Ser0UDCCS0 |= UDCCS0_DE; + } else { + PRINTKD( "%sQuitting set DE because SST or SE set\n", pszMe ); + break; + } + if ( Ser0UDCCS0 & UDCCS0_DE ) + break; + udelay( i ); + if ( ++i == 50 ) { + printk( "%sDangnabbbit! Cannot set DE! (DE=%8.8X CCS0=%8.8X)\n", + pszMe, UDCCS0_DE, Ser0UDCCS0 ); + break; + } + } +} + +static void set_ipr( void ) +{ + int i = 1; + while( 1 ) { + if ( OK_TO_WRITE ) { + Ser0UDCCS0 |= UDCCS0_IPR; + } else { + PRINTKD( "%sQuitting set IPR because SST or SE set\n", pszMe ); + break; + } + if ( Ser0UDCCS0 & UDCCS0_IPR ) + break; + udelay( i ); + if ( ++i == 50 ) { + printk( "%sDangnabbbit! Cannot set IPR! (IPR=%8.8X CCS0=%8.8X)\n", + pszMe, UDCCS0_IPR, Ser0UDCCS0 ); + break; + } + } +} + + + +static void set_ipr_and_de( void ) +{ + int i = 1; + while( 1 ) { + if ( OK_TO_WRITE ) { + Ser0UDCCS0 |= BOTH_BITS; + } else { + PRINTKD( "%sQuitting set IPR/DE because SST or SE set\n", pszMe ); + break; + } + if ( (Ser0UDCCS0 & BOTH_BITS) == BOTH_BITS) + break; + udelay( i ); + if ( ++i == 50 ) { + printk( "%sDangnabbbit! Cannot set DE/IPR! (DE=%8.8X IPR=%8.8X CCS0=%8.8X)\n", + pszMe, UDCCS0_DE, UDCCS0_IPR, Ser0UDCCS0 ); + break; + } + } +} + +static bool clear_opr( void ) +{ + int i = 10000; + bool is_clear; + do { + Ser0UDCCS0 = UDCCS0_SO; + is_clear = ! ( Ser0UDCCS0 & UDCCS0_OPR ); + if ( i-- <= 0 ) { + printk( "%sclear_opr(): failed\n", pszMe ); + break; + } + } while( ! is_clear ); + return is_clear; +} + + + + + +/* end usb_ep0.c */ + diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb_recv.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_recv.c --- linux-2.4.37.9/arch/arm/mach-sa1100/usb_recv.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_recv.c Wed May 26 15:44:05 2010 @@ -0,0 +1,205 @@ +/* + * Generic receive layer for the SA1100 USB client function + * Copyright (c) 2001 by Nicolas Pitre + * + * This code was loosely inspired by the original version which was + * Copyright (c) Compaq Computer Corporation, 1998-1999 + * + * 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. + * + * This is still work in progress... + * + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. + */ + +#include +#include +#include +#include +#include + +#include "sa1100_usb.h" +#include "usb_ctl.h" + + +static char *ep1_buf; +static int ep1_len; +static usb_callback_t ep1_callback; +static char *ep1_curdmabuf; +static dma_addr_t ep1_curdmapos; +static int ep1_curdmalen; +static int ep1_remain; +static int dmachn_rx; +static int rx_pktsize; + +static int naking; + +static void +ep1_start(void) +{ + sa1100_dma_flush_all(dmachn_rx); + if (!ep1_curdmalen) { + ep1_curdmalen = rx_pktsize; + if (ep1_curdmalen > ep1_remain) + ep1_curdmalen = ep1_remain; + ep1_curdmapos = pci_map_single(NULL, ep1_curdmabuf, ep1_curdmalen, + PCI_DMA_FROMDEVICE); + } + sa1100_dma_queue_buffer(dmachn_rx, NULL, ep1_curdmapos, ep1_curdmalen); + if ( naking ) { + /* turn off NAK of OUT packets, if set */ + UDC_flip( Ser0UDCCS1, UDCCS1_RPC ); + naking = 0; + } +} + +static void +ep1_done(int flag) +{ + int size = ep1_len - ep1_remain; + + if (!ep1_len) + return; + if (ep1_curdmalen) + pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen, + PCI_DMA_FROMDEVICE); + ep1_len = ep1_curdmalen = 0; + if (ep1_callback) { + ep1_callback(flag, size); + } +} + +void +ep1_state_change_notify( int new_state ) +{ + +} + +void +ep1_stall( void ) +{ + /* SET_FEATURE force stall at UDC */ + UDC_set( Ser0UDCCS1, UDCCS1_FST ); +} + +int +ep1_init(int chn) +{ + desc_t * pd = sa1100_usb_get_descriptor_ptr(); + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize ); + dmachn_rx = chn; + sa1100_dma_flush_all(dmachn_rx); + ep1_done(-EAGAIN); + return 0; +} + +void +ep1_reset(void) +{ + desc_t * pd = sa1100_usb_get_descriptor_ptr(); + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize ); + sa1100_dma_flush_all(dmachn_rx); + UDC_clear(Ser0UDCCS1, UDCCS1_FST); + ep1_done(-EINTR); +} + +void +ep1_int_hndlr(int udcsr) +{ + dma_addr_t dma_addr; + unsigned int len; + int status = Ser0UDCCS1; + + if ( naking ) printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking ); + + if (status & UDCCS1_RPC) { + + if (!ep1_curdmalen) { + printk("usb_recv: RPC for non-existent buffer\n"); + naking=1; + return; + } + + sa1100_dma_stop(dmachn_rx); + + if (status & UDCCS1_SST) { + printk("usb_recv: stall sent OMP=%d\n",Ser0UDCOMP); + UDC_flip(Ser0UDCCS1, UDCCS1_SST); + ep1_done(-EIO); // UDC aborted current transfer, so we do + return; + } + + if (status & UDCCS1_RPE) { + printk("usb_recv: RPError %x\n", status); + UDC_flip(Ser0UDCCS1, UDCCS1_RPC); + ep1_done(-EIO); + return; + } + + sa1100_dma_get_current(dmachn_rx, NULL, &dma_addr); + pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen, + PCI_DMA_FROMDEVICE); + len = dma_addr - ep1_curdmapos; + if (len < ep1_curdmalen) { + char *buf = ep1_curdmabuf + len; + while (Ser0UDCCS1 & UDCCS1_RNE) { + if (len >= ep1_curdmalen) { + printk("usb_recv: too much data in fifo\n"); + break; + } + *buf++ = Ser0UDCDR; + len++; + } + } else if (Ser0UDCCS1 & UDCCS1_RNE) { + printk("usb_recv: fifo screwed, shouldn't contain data\n"); + len = 0; + } + ep1_curdmalen = 0; /* dma unmap already done */ + ep1_remain -= len; + naking = 1; + ep1_done((len) ? 0 : -EPIPE); + } + /* else, you can get here if we are holding NAK */ +} + +int +sa1100_usb_recv(char *buf, int len, usb_callback_t callback) +{ + int flags; + + if (ep1_len) + return -EBUSY; + + local_irq_save(flags); + ep1_buf = buf; + ep1_len = len; + ep1_callback = callback; + ep1_remain = len; + ep1_curdmabuf = buf; + ep1_curdmalen = 0; + ep1_start(); + local_irq_restore(flags); + + return 0; +} + +EXPORT_SYMBOL(sa1100_usb_recv); + +void +sa1100_usb_recv_reset(void) +{ + ep1_reset(); +} + +EXPORT_SYMBOL(sa1100_usb_recv_reset); + +void +sa1100_usb_recv_stall(void) +{ + ep1_stall(); +} + +EXPORT_SYMBOL(sa1100_usb_recv_stall); + diff -uNr linux-2.4.37.9/arch/arm/mach-sa1100/usb_send.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_send.c --- linux-2.4.37.9/arch/arm/mach-sa1100/usb_send.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mach-sa1100/usb_send.c Wed May 26 15:44:05 2010 @@ -0,0 +1,205 @@ +/* + * Generic xmit layer for the SA1100 USB client function + * Copyright (c) 2001 by Nicolas Pitre + * + * This code was loosely inspired by the original version which was + * Copyright (c) Compaq Computer Corporation, 1998-1999 + * + * 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. + * + * This is still work in progress... + * + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. + * 15/03/2001 - ep2_start now sets UDCAR to overcome something that is hardware + * bug, I think. green@iXcelerator.com + */ + +#include +#include +#include +#include // for the massive_attack hack 28Feb01ww +#include +#include +#include +#include + +#include "sa1100_usb.h" +#include "usb_ctl.h" + + +static char *ep2_buf; +static int ep2_len; +static usb_callback_t ep2_callback; +static dma_addr_t ep2_dma; +static dma_addr_t ep2_curdmapos; +static int ep2_curdmalen; +static int ep2_remain; +static int dmachn_tx; +static int tx_pktsize; + +/* device state is changing, async */ +void +ep2_state_change_notify( int new_state ) +{ +} + +/* set feature stall executing, async */ +void +ep2_stall( void ) +{ + UDC_set( Ser0UDCCS2, UDCCS2_FST ); /* force stall at UDC */ +} + +static void +ep2_start(void) +{ + if (!ep2_len) + return; + + ep2_curdmalen = tx_pktsize; + if (ep2_curdmalen > ep2_remain) + ep2_curdmalen = ep2_remain; + + /* must do this _before_ queue buffer.. */ + UDC_flip( Ser0UDCCS2,UDCCS2_TPC ); /* stop NAKing IN tokens */ + UDC_write( Ser0UDCIMP, ep2_curdmalen-1 ); + + /* Remove if never seen...8Mar01ww */ + { + int massive_attack = 20; + while ( Ser0UDCIMP != ep2_curdmalen-1 && massive_attack-- ) { + printk( "usbsnd: Oh no you don't! Let me spin..." ); + udelay( 500 ); + printk( "and try again...\n" ); + UDC_write( Ser0UDCIMP, ep2_curdmalen-1 ); + } + if ( massive_attack != 20 ) { + if ( Ser0UDCIMP != ep2_curdmalen-1 ) + printk( "usbsnd: Massive attack FAILED :-( %d\n", + 20 - massive_attack ); + else + printk( "usbsnd: Massive attack WORKED :-) %d\n", + 20 - massive_attack ); + } + } + /* End remove if never seen... 8Mar01ww */ + + Ser0UDCAR = usbd_info.address; // fighting stupid silicon bug + sa1100_dma_queue_buffer(dmachn_tx, NULL, ep2_curdmapos, ep2_curdmalen); +} + +static void +ep2_done(int flag) +{ + int size = ep2_len - ep2_remain; + if (ep2_len) { + pci_unmap_single(NULL, ep2_dma, ep2_len, PCI_DMA_TODEVICE); + ep2_len = 0; + if (ep2_callback) + ep2_callback(flag, size); + } +} + +int +ep2_init(int chn) +{ + desc_t * pd = sa1100_usb_get_descriptor_ptr(); + tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize ); + dmachn_tx = chn; + sa1100_dma_flush_all(dmachn_tx); + ep2_done(-EAGAIN); + return 0; +} + +void +ep2_reset(void) +{ + desc_t * pd = sa1100_usb_get_descriptor_ptr(); + tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize ); + UDC_clear(Ser0UDCCS2, UDCCS2_FST); + sa1100_dma_flush_all(dmachn_tx); + ep2_done(-EINTR); +} + +void +ep2_int_hndlr(int udcsr) +{ + int status = Ser0UDCCS2; + + if (Ser0UDCAR != usbd_info.address) // check for stupid silicon bug. + Ser0UDCAR = usbd_info.address; + + UDC_flip(Ser0UDCCS2, UDCCS2_SST); + + if (status & UDCCS2_TPC) { + sa1100_dma_flush_all(dmachn_tx); + + if (status & (UDCCS2_TPE | UDCCS2_TUR)) { + printk("usb_send: transmit error %x\n", status); + ep2_done(-EIO); + } else { +#if 1 // 22Feb01ww/Oleg + ep2_curdmapos += ep2_curdmalen; + ep2_remain -= ep2_curdmalen; +#else + ep2_curdmapos += Ser0UDCIMP + 1; // this is workaround + ep2_remain -= Ser0UDCIMP + 1; // for case when setting of Ser0UDCIMP was failed +#endif + + if (ep2_remain != 0) { + ep2_start(); + } else { + ep2_done(0); + } + } + } else { + printk("usb_send: Not TPC: UDCCS2 = %x\n", status); + } +} + +int +sa1100_usb_send(char *buf, int len, usb_callback_t callback) +{ + int flags; + + if (usbd_info.state != USB_STATE_CONFIGURED) + return -ENODEV; + + if (ep2_len) + return -EBUSY; + + local_irq_save(flags); + ep2_buf = buf; + ep2_len = len; + ep2_dma = pci_map_single(NULL, buf, len, PCI_DMA_TODEVICE); + ep2_callback = callback; + ep2_remain = len; + ep2_curdmapos = ep2_dma; + ep2_start(); + local_irq_restore(flags); + + return 0; +} + + +void +sa1100_usb_send_reset(void) +{ + ep2_reset(); +} + +int sa1100_usb_xmitter_avail( void ) +{ + if (usbd_info.state != USB_STATE_CONFIGURED) + return -ENODEV; + if (ep2_len) + return -EBUSY; + return 0; +} + + +EXPORT_SYMBOL(sa1100_usb_xmitter_avail); +EXPORT_SYMBOL(sa1100_usb_send); +EXPORT_SYMBOL(sa1100_usb_send_reset); diff -uNr linux-2.4.37.9/arch/arm/mm/Makefile linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/Makefile --- linux-2.4.37.9/arch/arm/mm/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/Makefile Wed May 26 15:44:03 2010 @@ -39,6 +39,8 @@ p-$(CONFIG_CPU_ARM925T) += proc-arm925.o p-$(CONFIG_CPU_ARM926T) += proc-arm926.o p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o +p-$(CONFIG_CPU_ARM1020E) += proc-arm1020E.o +p-$(CONFIG_CPU_ARM1022) += proc-arm1022.o p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o p-$(CONFIG_CPU_SA110) += proc-sa110.o p-$(CONFIG_CPU_SA1100) += proc-sa110.o diff -uNr linux-2.4.37.9/arch/arm/mm/alignment.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/alignment.c --- linux-2.4.37.9/arch/arm/mm/alignment.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/alignment.c Wed May 26 15:44:03 2010 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -19,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -30,13 +28,11 @@ #include #include -extern void -do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr, - int error_code, struct pt_regs *regs); +#include "fault.h" /* * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998 - * /proc/sys/debug/alignment, modified and integrated into + * /proc/cpu/alignment, modified and integrated into * Linux 2.1 by Russell King * * Speed optimisations and better fault handling by Russell King. @@ -130,31 +126,6 @@ return count; } -/* - * This needs to be done after sysctl_init, otherwise sys/ will be - * overwritten. Actually, this shouldn't be in sys/ at all since - * it isn't a sysctl, and it doesn't contain sysctl information. - * We now locate it in /proc/cpu/alignment instead. - */ -static int __init alignment_init(void) -{ - struct proc_dir_entry *res; - - res = proc_mkdir("cpu", NULL); - if (!res) - return -ENOMEM; - - res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res); - if (!res) - return -ENOMEM; - - res->read_proc = proc_alignment_read; - res->write_proc = proc_alignment_write; - - return 0; -} - -__initcall(alignment_init); #endif /* CONFIG_PROC_FS */ union offset_union { @@ -429,7 +400,7 @@ * For alignment faults on the ARM922T/ARM920T the MMU makes * the FSR (and hence addr) equal to the updated base address * of the multiple access rather than the restored value. - * Switch this messsage off if we've got a ARM92[02], otherwise + * Switch this message off if we've got a ARM92[02], otherwise * [ls]dm alignment faults are noisy! */ #if !(defined CONFIG_CPU_ARM922T) && !(defined CONFIG_CPU_ARM920T) @@ -486,7 +457,8 @@ return TYPE_ERROR; } -int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs) +static int +do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { union offset_union offset; unsigned long instr, instrptr; @@ -541,7 +513,7 @@ case SHIFT_RORRRX: if (shiftval == 0) { offset.un >>= 1; - if (regs->ARM_cpsr & CC_C_BIT) + if (regs->ARM_cpsr & PSR_C_BIT) offset.un |= 1 << 31; } else offset.un = offset.un >> shiftval | @@ -577,7 +549,7 @@ /* * We got a fault - fix it up, or die. */ - do_bad_area(current, current->mm, addr, error_code, regs); + do_bad_area(current, current->mm, addr, fsr, regs); return 0; bad: @@ -594,8 +566,8 @@ if (ai_usermode & 1) printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%08lx " - "Address=0x%08lx Code 0x%02x\n", current->comm, - current->pid, instrptr, instr, addr, error_code); + "Address=0x%08lx FSR 0x%03x\n", current->comm, + current->pid, instrptr, instr, addr, fsr); if (ai_usermode & 2) goto fixup; @@ -607,3 +579,34 @@ return 0; } + +/* + * This needs to be done after sysctl_init, otherwise sys/ will be + * overwritten. Actually, this shouldn't be in sys/ at all since + * it isn't a sysctl, and it doesn't contain sysctl information. + * We now locate it in /proc/cpu/alignment instead. + */ +static int __init alignment_init(void) +{ +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *res; + + res = proc_mkdir("cpu", NULL); + if (!res) + return -ENOMEM; + + res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res); + if (!res) + return -ENOMEM; + + res->read_proc = proc_alignment_read; + res->write_proc = proc_alignment_write; +#endif + + hook_fault_code(1, do_alignment, SIGILL, "alignment exception"); + hook_fault_code(3, do_alignment, SIGILL, "alignment exception"); + + return 0; +} + +__initcall(alignment_init); diff -uNr linux-2.4.37.9/arch/arm/mm/fault-armv.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/fault-armv.c --- linux-2.4.37.9/arch/arm/mm/fault-armv.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/fault-armv.c Wed May 26 15:44:03 2010 @@ -2,116 +2,90 @@ * linux/arch/arm/mm/fault-armv.c * * Copyright (C) 1995 Linus Torvalds - * Modifications for ARM processor (c) 1995-2001 Russell King + * Modifications for ARM processor (c) 1995-2003 Russell King * * 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 -#include #include #include -#include -#include #include #include -#include #include -#include -#include #include #include -#include -#include #include #include +#include -extern void show_pte(struct mm_struct *mm, unsigned long addr); -extern int do_page_fault(unsigned long addr, int error_code, - struct pt_regs *regs); -extern int do_translation_fault(unsigned long addr, int error_code, - struct pt_regs *regs); -extern void do_bad_area(struct task_struct *tsk, struct mm_struct *mm, - unsigned long addr, int error_code, - struct pt_regs *regs); - -#ifdef CONFIG_ALIGNMENT_TRAP -extern int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs); -#else -#define do_alignment do_bad -#endif - +#include "fault.h" /* * Some section permission faults need to be handled gracefully. * They can happen due to a __{get,put}_user during an oops. */ static int -do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs) +do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { struct task_struct *tsk = current; - do_bad_area(tsk, tsk->active_mm, addr, error_code, regs); + do_bad_area(tsk, tsk->active_mm, addr, fsr, regs); return 0; } /* - * Hook for things that need to trap external faults. Note that - * we don't guarantee that this will be the final version of the - * interface. - */ -int (*external_fault)(unsigned long addr, struct pt_regs *regs); - -static int -do_external_fault(unsigned long addr, int error_code, struct pt_regs *regs) -{ - if (external_fault) - return external_fault(addr, regs); - return 1; -} - -/* * This abort handler always returns "fault". */ static int -do_bad(unsigned long addr, int error_code, struct pt_regs *regs) +do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { return 1; } -static const struct fsr_info { - int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs); +static struct fsr_info { + int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs); int sig; const char *name; } fsr_info[] = { { do_bad, SIGSEGV, "vector exception" }, - { do_alignment, SIGILL, "alignment exception" }, + { do_bad, SIGILL, "alignment exception" }, { do_bad, SIGKILL, "terminal exception" }, - { do_alignment, SIGILL, "alignment exception" }, - { do_external_fault, SIGBUS, "external abort on linefetch" }, + { do_bad, SIGILL, "alignment exception" }, + { do_bad, SIGBUS, "external abort on linefetch" }, { do_translation_fault, SIGSEGV, "section translation fault" }, - { do_external_fault, SIGBUS, "external abort on linefetch" }, + { do_bad, SIGBUS, "external abort on linefetch" }, { do_page_fault, SIGSEGV, "page translation fault" }, - { do_external_fault, SIGBUS, "external abort on non-linefetch" }, + { do_bad, SIGBUS, "external abort on non-linefetch" }, { do_bad, SIGSEGV, "section domain fault" }, - { do_external_fault, SIGBUS, "external abort on non-linefetch" }, + { do_bad, SIGBUS, "external abort on non-linefetch" }, { do_bad, SIGSEGV, "page domain fault" }, { do_bad, SIGBUS, "external abort on translation" }, { do_sect_fault, SIGSEGV, "section permission fault" }, { do_bad, SIGBUS, "external abort on translation" }, - { do_page_fault, SIGSEGV, "page permission fault" } + { do_page_fault, SIGSEGV, "page permission fault" }, }; +void __init +hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), + int sig, const char *name) +{ + if (nr >= 0 && nr < ARRAY_SIZE(fsr_info)) { + fsr_info[nr].fn = fn; + fsr_info[nr].sig = sig; + fsr_info[nr].name = name; + } +} + /* * Dispatch a data abort to the relevant handler. */ asmlinkage void -do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr) +do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { const struct fsr_info *inf = fsr_info + (fsr & 15); - if (!inf->fn(addr, error_code, regs)) + if (!inf->fn(addr, fsr, regs)) return; printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", @@ -127,25 +101,28 @@ do_translation_fault(addr, 0, regs); } +static unsigned long shared_pte_mask = L_PTE_CACHEABLE; + /* * We take the easy way out of this problem - we make the * PTE uncacheable. However, we leave the write buffer on. */ -static void adjust_pte(struct vm_area_struct *vma, unsigned long address) +static int adjust_pte(struct vm_area_struct *vma, unsigned long address) { pgd_t *pgd; pmd_t *pmd; pte_t *pte, entry; + int ret = 0; pgd = pgd_offset(vma->vm_mm, address); if (pgd_none(*pgd)) - return; + goto no_pgd; if (pgd_bad(*pgd)) goto bad_pgd; pmd = pmd_offset(pgd, address); if (pmd_none(*pmd)) - return; + goto no_pmd; if (pmd_bad(*pmd)) goto bad_pmd; @@ -156,33 +133,38 @@ * If this page isn't present, or is already setup to * fault (ie, is old), we can safely ignore any issues. */ - if (pte_present(entry) && pte_val(entry) & L_PTE_CACHEABLE) { + if (pte_present(entry) && pte_val(entry) & shared_pte_mask) { flush_cache_page(vma, address); - pte_val(entry) &= ~L_PTE_CACHEABLE; + pte_val(entry) &= ~shared_pte_mask; set_pte(pte, entry); flush_tlb_page(vma, address); + ret = 1; } - return; + return ret; bad_pgd: pgd_ERROR(*pgd); pgd_clear(pgd); - return; +no_pgd: + return 0; bad_pmd: pmd_ERROR(*pmd); pmd_clear(pmd); - return; +no_pmd: + return 0; } static void -make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page) +make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty) { struct vm_area_struct *mpnt; struct mm_struct *mm = vma->vm_mm; - unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT; + unsigned long pgoff; int aliases = 0; + pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT); + /* * If we have any shared mappings that are in the same mm * space, then we need to handle them specially to maintain @@ -194,7 +176,7 @@ /* * If this VMA is not in our MM, we can ignore it. - * Note that we intentionally don't mask out the VMA + * Note that we intentionally mask out the VMA * that we are fixing up. */ if (mpnt->vm_mm != mm || mpnt == vma) @@ -210,14 +192,17 @@ if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) continue; + off = mpnt->vm_start + (off << PAGE_SHIFT); + /* * Ok, it is within mpnt. Fix it up. */ - adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); - aliases ++; + aliases += adjust_pte(mpnt, off); } if (aliases) adjust_pte(vma, addr); + else if (dirty) + flush_cache_page(vma, addr); } /* @@ -242,11 +227,85 @@ return; page = pfn_to_page(pfn); if (page->mapping) { - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) { + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); + + if (dirty) { unsigned long kvirt = (unsigned long)page_address(page); cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0); } - make_coherent(vma, addr, page); + make_coherent(vma, addr, page, dirty); + } +} + +/* + * Check whether the write buffer has physical address aliasing + * issues. If it has, we need to avoid them for the case where + * we have several shared mappings of the same object in user + * space. + */ +static int __init check_writebuffer(unsigned long *p1, unsigned long *p2) +{ + register unsigned long zero = 0, one = 1, val; + + mb(); + *p1 = one; + mb(); + *p2 = zero; + mb(); + val = *p1; + mb(); + return val != zero; +} + +static inline void *map_page(struct page *page) +{ + void *map; + + map = __ioremap(page_to_phys(page), PAGE_SIZE, L_PTE_BUFFERABLE); + if (map) + get_page(page); + return map; +} + +static inline void unmap_page(void *map) +{ + iounmap(map); +} + +void __init check_writebuffer_bugs(void) +{ + struct page *page; + const char *reason; + unsigned long v = 1; + + printk(KERN_INFO "CPU: Testing write buffer: "); + + page = alloc_page(GFP_KERNEL); + if (page) { + unsigned long *p1, *p2; + + p1 = map_page(page); + p2 = map_page(page); + + if (p1 && p2) { + v = check_writebuffer(p1, p2); + reason = "enabling work-around"; + } else { + reason = "unable to map memory\n"; + } + + unmap_page(p1); + unmap_page(p2); + put_page(page); + } else { + reason = "unable to grab page\n"; + } + + if (v) { + printk("FAIL - %s\n", reason); + shared_pte_mask |= L_PTE_BUFFERABLE; + } else { + printk("pass\n"); } } diff -uNr linux-2.4.37.9/arch/arm/mm/fault-common.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/fault-common.c --- linux-2.4.37.9/arch/arm/mm/fault-common.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/fault-common.c Wed May 26 15:44:03 2010 @@ -11,21 +11,17 @@ #include #include #include -#include -#include #include -#include #include -#include #include #include -#include #include #include -#include #include -#include +#include + +#include "fault.h" #ifdef CONFIG_CPU_26 #define FAULT_CODE_WRITE 0x02 @@ -34,13 +30,11 @@ #define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE)) #else /* - * On 32-bit processors, we define "mode" to be zero when reading, - * non-zero when writing. This now ties up nicely with the polarity - * of the 26-bit machines, and also means that we avoid the horrible - * gcc code for "int val = !other_val;". + * "code" is actually the FSR register. Bit 11 set means the + * instruction was performing a write. */ -#define DO_COW(m) (m) -#define READ_FAULT(m) (!(m)) +#define DO_COW(code) ((code) & (1 << 11)) +#define READ_FAULT(code) (!DO_COW(code)) #endif /* @@ -54,16 +48,17 @@ if (!mm) mm = &init_mm; - printk(KERN_ALERT "mm = %p pgd = %p\n", mm, mm->pgd); - fs = get_fs(); set_fs(get_ds()); + do { - pgd_t pg, *pgd = pgd_offset(mm, addr); + pgd_t pg, *pgd; pmd_t pm, *pmd; pte_t pt, *pte; - printk(KERN_ALERT "*pgd = "); + printk(KERN_ALERT "pgd = %p\n", mm->pgd); + pgd = pgd_offset(mm, addr); + printk(KERN_ALERT "[%08lx] *pgd=", addr); if (__get_user(pgd_val(pg), (unsigned long *)pgd)) { printk("(faulted)"); @@ -122,7 +117,7 @@ * Oops. The kernel tried to access some page that wasn't present. */ static void -__do_kernel_fault(struct mm_struct *mm, unsigned long addr, int error_code, +__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct pt_regs *regs) { unsigned long fixup; @@ -148,7 +143,7 @@ "paging request", addr); show_pte(mm, addr); - die("Oops", regs, error_code); + die("Oops", regs, fsr); do_exit(SIGKILL); } @@ -157,20 +152,20 @@ * User mode accesses just cause a SIGSEGV */ static void -__do_user_fault(struct task_struct *tsk, unsigned long addr, int error_code, - int code, struct pt_regs *regs) +__do_user_fault(struct task_struct *tsk, unsigned long addr, + unsigned int fsr, int code, struct pt_regs *regs) { struct siginfo si; #ifdef CONFIG_DEBUG_USER printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, " "lr=0x%08lx (bad address=0x%08lx, code %d)\n", - tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, error_code); + tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, fsr); show_regs(regs); #endif tsk->thread.address = addr; - tsk->thread.error_code = error_code; + tsk->thread.error_code = fsr; tsk->thread.trap_no = 14; si.si_signo = SIGSEGV; si.si_errno = 0; @@ -181,20 +176,20 @@ void do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr, - int error_code, struct pt_regs *regs) + unsigned int fsr, struct pt_regs *regs) { /* * If we are in kernel mode at this point, we * have no context to handle this fault with. */ if (user_mode(regs)) - __do_user_fault(tsk, addr, error_code, SEGV_MAPERR, regs); + __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs); else - __do_kernel_fault(mm, addr, error_code, regs); + __do_kernel_fault(mm, addr, fsr, regs); } static int -__do_page_fault(struct mm_struct *mm, unsigned long addr, int error_code, +__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct task_struct *tsk) { struct vm_area_struct *vma; @@ -212,7 +207,7 @@ * memory access, so we can handle it. */ good_area: - if (READ_FAULT(error_code)) /* read? */ + if (READ_FAULT(fsr)) /* read? */ mask = VM_READ|VM_EXEC; else mask = VM_WRITE; @@ -227,7 +222,7 @@ * than endlessly redo the fault. */ survive: - fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(error_code)); + fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr)); /* * Handle the "normal" cases first - successful and sigbus @@ -260,7 +255,7 @@ return fault; } -int do_page_fault(unsigned long addr, int error_code, struct pt_regs *regs) +int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { struct task_struct *tsk; struct mm_struct *mm; @@ -277,7 +272,7 @@ goto no_context; down_read(&mm->mmap_sem); - fault = __do_page_fault(mm, addr, error_code, tsk); + fault = __do_page_fault(mm, addr, fsr, tsk); up_read(&mm->mmap_sem); /* @@ -308,7 +303,7 @@ printk("VM: killing process %s\n", tsk->comm); do_exit(SIGKILL); } else - __do_user_fault(tsk, addr, error_code, fault == -1 ? + __do_user_fault(tsk, addr, fsr, fault == -1 ? SEGV_ACCERR : SEGV_MAPERR, regs); return 0; @@ -323,7 +318,7 @@ * or user mode. */ tsk->thread.address = addr; - tsk->thread.error_code = error_code; + tsk->thread.error_code = fsr; tsk->thread.trap_no = 14; force_sig(SIGBUS, tsk); #ifdef CONFIG_DEBUG_USER @@ -336,7 +331,7 @@ return 0; no_context: - __do_kernel_fault(mm, addr, error_code, regs); + __do_kernel_fault(mm, addr, fsr, regs); return 0; } @@ -357,21 +352,23 @@ * interrupt or a critical region, and should only copy the information * from the master page table, nothing more. */ -int do_translation_fault(unsigned long addr, int error_code, struct pt_regs *regs) +int do_translation_fault(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) { struct task_struct *tsk; - struct mm_struct *mm; int offset; pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; if (addr < TASK_SIZE) - return do_page_fault(addr, error_code, regs); + return do_page_fault(addr, fsr, regs); offset = __pgd_offset(addr); /* * FIXME: CP15 C1 is write only on ARMv3 architectures. + * You really need to read the value in the page table + * register, not a copy. */ pgd = cpu_get_pgd() + offset; pgd_k = init_mm.pgd + offset; @@ -395,8 +392,7 @@ bad_area: tsk = current; - mm = tsk->active_mm; - do_bad_area(tsk, mm, addr, error_code, regs); + do_bad_area(tsk, tsk->active_mm, addr, fsr, regs); return 0; } diff -uNr linux-2.4.37.9/arch/arm/mm/fault.h linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/fault.h --- linux-2.4.37.9/arch/arm/mm/fault.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/fault.h Wed May 26 15:44:03 2010 @@ -0,0 +1,9 @@ +void do_bad_area(struct task_struct *tsk, struct mm_struct *mm, + unsigned long addr, unsigned int fsr, struct pt_regs *regs); + +void show_pte(struct mm_struct *mm, unsigned long addr); + +int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs); + +int do_translation_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs); + diff -uNr linux-2.4.37.9/arch/arm/mm/init.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/init.c --- linux-2.4.37.9/arch/arm/mm/init.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/init.c Wed May 26 15:44:03 2010 @@ -9,7 +9,6 @@ */ #include #include -#include #include #include #include @@ -18,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -385,6 +383,13 @@ reserve_bootmem_node(pgdat, 0xc0000000, 0x00020000); if (machine_is_p720t()) reserve_bootmem_node(pgdat, PHYS_OFFSET, 0x00014000); + +#ifdef CONFIG_ARCH_PSIONW +#include + /* Reserve the video memory area */ + reserve_bootmem_node(pgdat, LCD_MEM_START, LCD_MEM_SIZE); +#endif + #ifdef CONFIG_SA1111 /* * Because of the SA1111 DMA bug, we want to preserve diff -uNr linux-2.4.37.9/arch/arm/mm/ioremap.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/ioremap.c --- linux-2.4.37.9/arch/arm/mm/ioremap.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/ioremap.c Wed May 26 15:44:03 2010 @@ -144,7 +144,7 @@ */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; /* * Ok, go for it.. diff -uNr linux-2.4.37.9/arch/arm/mm/mm-armv.c linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/mm-armv.c --- linux-2.4.37.9/arch/arm/mm/mm-armv.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/mm-armv.c Wed May 26 15:44:03 2010 @@ -9,7 +9,6 @@ * * Page table sludge for ARM v3 and v4 processor architectures. */ -#include #include #include #include @@ -390,6 +389,9 @@ init_maps->bufferable = 0; create_mapping(init_maps); + + flush_cache_all(); + flush_tlb_all(); } /* diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm1020.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1020.S --- linux-2.4.37.9/arch/arm/mm/proc-arm1020.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1020.S Wed May 26 15:44:03 2010 @@ -65,18 +65,21 @@ * * Returns: * r0 = address of abort - * r1 != 0 if writing - * r3 = FSR + * r1 = FSR + * r3 = corrupted * r4 = corrupted */ .align 5 ENTRY(cpu_arm1020_data_abort) - mrc p15, 0, r3, c5, c0, 0 @ get FSR + mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR - ldr r1, [r2] @ read aborted instruction - and r3, r3, #255 - tst r1, r1, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 + tst r3, #PSR_T_BIT + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 mov pc, lr /* @@ -170,10 +173,10 @@ #endif subs r3, r3, #1 cmp r3, #0 - bge 2b @ entries 3F to 0 + bhs 2b @ entries 3F to 0 subs r1, r1, #1 cmp r1, #0 - bge 1b @ segments 7 to 0 + bhs 1b @ segments 7 to 0 #endif #ifndef CONFIG_CPU_ICACHE_DISABLE @@ -201,7 +204,7 @@ bic r0, r0, #DCACHELINESIZE - 1 sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE - bgt cpu_arm1020_cache_clean_invalidate_all_r2 + bhi cpu_arm1020_cache_clean_invalidate_all_r2 mcr p15, 0, r3, c7, c10, 4 #ifndef CONFIG_CPU_DCACHE_DISABLE 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry @@ -214,7 +217,7 @@ #endif add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b #endif #ifndef CONFIG_CPU_ICACHE_DISABLE @@ -302,7 +305,7 @@ #endif add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b #else /* D cache off, but still drain the write buffer */ mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer @@ -328,7 +331,7 @@ bic r0, r0, #DCACHELINESIZE - 1 sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE - bgt cpu_arm1020_cache_clean_invalidate_all_r2 + bhi cpu_arm1020_cache_clean_invalidate_all_r2 mcr p15, 0, r3, c7, c10, 4 #ifndef CONFIG_CPU_DCACHE_DISABLE 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry @@ -341,7 +344,7 @@ #endif add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b #endif #ifndef CONFIG_CPU_BPREDICT_DISABLE @@ -488,7 +491,7 @@ mov r0, r0 #endif cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -541,10 +544,10 @@ #endif subs r3, r3, #1 cmp r3, #0 - bge 2b @ entries 3F to 0 + bhs 2b @ entries 3F to 0 subs r1, r1, #1 cmp r1, #0 - bge 1b @ segments 15 to 0 + bhs 1b @ segments 15 to 0 #endif mov r1, #0 @@ -603,7 +606,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -740,12 +743,12 @@ .type cpu_arch_name, #object cpu_arch_name: - .asciz "armv4" + .asciz "armv5t" .size cpu_arch_name, . - cpu_arch_name .type cpu_elf_name, #object cpu_elf_name: - .asciz "v4" + .asciz "v5" .size cpu_elf_name, . - cpu_elf_name .align @@ -753,9 +756,9 @@ .type __arm1020_proc_info,#object __arm1020_proc_info: - .long 0x4100a200 - .long 0xff00fff0 - .long 0x00000c02 @ mmuflags + .long 0x4104a200 @ ARM 1020T (Architecture v5T) + .long 0xff0ffff0 + .long 0x00000c0e @ mmuflags b __arm1020_setup .long cpu_arch_name .long cpu_elf_name diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm1020E.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1020E.S --- linux-2.4.37.9/arch/arm/mm/proc-arm1020E.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1020E.S Wed May 26 15:44:03 2010 @@ -0,0 +1,718 @@ +/* + * linux/arch/arm/mm/proc-arm1020E.S: MMU functions for ARM1020E + * + * Copyright (C) 2000 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * + * 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 + * + * + * These are the low level assembler for performing cache and TLB + * functions on the arm1020E. + */ +#include +#include +#include +#include +#include +#include + +/* + * This is the maximum size of an area which will be invalidated + * using the single invalidate entry instructions. Anything larger + * than this, and we go for the whole cache. + * + * This value should be chosen such that we choose the cheapest + * alternative. + */ +#define MAX_AREA_SIZE 32768 + +/* + * the cache line size of the I and D cache + */ +#define DCACHELINESIZE 32 +#define ICACHELINESIZE 32 + +/* + * and the page size + */ +#define LOG2PAGESIZE 12 /* == 4096 Bytes */ +#define PAGESIZE (1 << LOG2PAGESIZE) + +/* + * create some useful conditional macro definitions + * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback) + */ +#ifdef CONFIG_CPU_DCACHE_DISABLE + #undef CONFIG_CPU_DCACHE_WRITETHROUGH + #undef CONFIG_CPU_DCACHE_WRITEBACK + #undef CONFIG_CPU_DCACHE_ENABLE +#else + #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + #undef CONFIG_CPU_DCACHE_WRITEBACK + #else + #define CONFIG_CPU_DCACHE_WRITEBACK + #endif + #define CONFIG_CPU_DCACHE_ENABLE +#endif + +#ifdef CONFIG_CPU_ICACHE_DISABLE + #undef CONFIG_CPU_ICACHE_ENABLE +#else + #define CONFIG_CPU_ICACHE_ENABLE +#endif + + .text + +/* + * cpu_arm1020E_data_abort() + * + * obtain information about current aborted instruction + * Note: we read user space. This means we might cause a data + * abort here if the I-TLB and D-TLB aren't seeing the same + * picture. Unfortunately, this does happen. We live with it. + * + * r2 = address of aborted instruction + * r3 = cpsr + * + * Returns: + * r0 = address of abort + * r1 = FSR + * r3 = corrupted + * r4 = corrupted + */ + .align 5 +ENTRY(cpu_arm1020E_data_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + tst r3, #PSR_T_BIT + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 + mov pc, lr + +/* + * cpu_arm1020E_check_bugs() + */ +ENTRY(cpu_arm1020E_check_bugs) + mrs ip, cpsr + bic ip, ip, #F_BIT + msr cpsr, ip + mov pc, lr + +/* + * cpu_arm1020E_proc_init() + */ +ENTRY(cpu_arm1020E_proc_init) + mov pc, lr + +/* + * cpu_arm1020E_proc_fin() + */ +ENTRY(cpu_arm1020E_proc_fin) + stmfd sp!, {lr} + mov ip, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, ip + bl cpu_arm1020E_cache_clean_invalidate_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + ldmfd sp!, {pc} + +/* + * cpu_arm1020E_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + */ + .align 5 +ENTRY(cpu_arm1020E_reset) + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + mov pc, r0 + +/* + * cpu_arm1020E_do_idle() + */ + .align 5 +ENTRY(cpu_arm1020E_do_idle) + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt + mov pc, lr + +/* ================================= CACHE ================================ */ + + +/* + * cpu_arm1020E_cache_clean_invalidate_all() + * + * clean and invalidate all cache lines + * + * Note: + * 1. we should preserve r0 and ip at all times + */ + .align 5 +ENTRY(cpu_arm1020E_cache_clean_invalidate_all) + mov r2, #1 +cpu_arm1020E_cache_clean_invalidate_all_r2: + +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mov r1, #0x0F << 5 @ 16 segments +1: orr r3, r1, #63 << 26 @ 64 entries +2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index + subs r3, r3, #1 << 26 + bcs 2b + subs r1, r1, #1 << 5 + bcs 1b @ segments 15 to 0 +#endif + + mov r1, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache +#endif + +#ifdef CONFIG_CPU_ICACHE_ENABLE + teq r2, #0 + mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache +#endif + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1020E_cache_clean_invalidate_range(start, end, flags) + * + * clean and invalidate all cache lines associated with this area of memory + * + * start: Area start address + * end: Area end address + * flags: nonzero for I cache as well + */ + .align 5 +ENTRY(cpu_arm1020E_cache_clean_invalidate_range) + bic r0, r0, #DCACHELINESIZE - 1 + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bhs cpu_arm1020E_cache_clean_invalidate_all_r2 +1: +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + teq r2, #0 + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b @ unsigned lower or same - must include end point (r1)! + + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1020E_flush_ram_page(page) + * + * clean and invalidate all cache lines associated with this area of memory + * + * page: page to clean and invalidate + */ + .align 5 +ENTRY(cpu_arm1020E_flush_ram_page) + mov r1, #PAGESIZE + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE +1: +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + subs r1, r1, #DCACHELINESIZE + bne 1b + + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ D-CACHE =============================== */ + +/* + * cpu_arm1020E_dcache_invalidate_range(start, end) + * + * throw away all D-cached data in specified region without an obligation + * to write them back. Note however that we must clean the D-cached entries + * around the boundaries if the start and/or end address are not cache + * aligned. + * + * start: virtual start address + * end: virtual end address + */ + .align 5 +ENTRY(cpu_arm1020E_dcache_invalidate_range) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + bic r0, r0, #DCACHELINESIZE - 1 +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + tst r0, #DCACHELINESIZE - 1 + bic r0, r0, #DCACHELINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start + tst r1, #DCACHELINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end +#endif + +1: +#ifdef CONFIG_CPU_DCACHE_ENABLE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b + + /* Even if the D cache is off still drain the write buffer */ + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer + mov pc, lr + +/* + * cpu_arm1020E_dcache_clean_range(start, end) + * + * For the specified virtual address range, ensure that all caches contain + * clean data, such that peripheral accesses to the physical RAM fetch + * correct data. + * + * start: virtual start address + * end: virtual end address + */ + .align 5 +ENTRY(cpu_arm1020E_dcache_clean_range) + + mov r2, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + bic r0, r0, #DCACHELINESIZE - 1 + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bhs cpu_arm1020E_cache_clean_invalidate_all_r2 + +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b +#endif + + mcr p15, 0, r2, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1020E_dcache_clean_page(page) + * + * Cleans a single page of dcache so that if we have any future aliased + * mappings, they will be consistent at the time that they are created. + * + * page: virtual address of page to clean from dcache + * + * Note: + * we don't invalidate the entries since when we write the page + * out to disk, the entries may get reloaded into the cache. + */ + .align 5 +ENTRY(cpu_arm1020E_dcache_clean_page) +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE + mov r1, #PAGESIZE +1: + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + subs r1, r1, #DCACHELINESIZE + bne 1b +#endif + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1020E_dcache_clean_entry(addr) + * + * Clean the specified entry of any caches such that the MMU + * translation fetches will obtain correct data. + * + * addr: cache-unaligned virtual address + */ + .align 5 +ENTRY(cpu_arm1020E_dcache_clean_entry) +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + bic r0, r0, #DCACHELINESIZE - 1 + mcr p15, 0, r0, c7, c10, 1 @ clean single D entry +#endif + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ I-CACHE =============================== */ + +/* + * cpu_arm1020E_icache_invalidate_range(start, end) + * + * invalidate a range of virtual addresses from the Icache + * + * This is a little misleading, it is not intended to clean out + * the i-cache but to make sure that any data written to the + * range is made consistent. This means that when we execute code + * in that region, everything works as we expect. + * + * This generally means writing back data in the Dcache and + * write buffer and invalidating the Icache over that region + * + * start: virtual start address + * end: virtual end address + * + * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to + * loop twice, once for i-cache, once for d-cache) + */ + .align 5 +ENTRY(cpu_arm1020E_icache_invalidate_range) + bic r0, r0, #ICACHELINESIZE - 1 + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + movhs r2, #1 + bhs cpu_arm1020E_cache_clean_invalidate_all_r2 + +1: +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c10, 1 @ Clean D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b @ unsigned lower or same - includes r1 entry + + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +ENTRY(cpu_arm1020E_icache_invalidate_page) + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE + add r1, r0, #PAGESIZE + b cpu_arm1020E_icache_invalidate_range + +/* ================================== TLB ================================= */ + +/* + * cpu_arm1020E_tlb_invalidate_all() + * + * Invalidate all TLB entries + */ + .align 5 +ENTRY(cpu_arm1020E_tlb_invalidate_all) + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs + mov pc, lr + +/* + * cpu_arm1020E_tlb_invalidate_range(start, end) + * + * invalidate TLB entries covering the specified range + * + * start: range start address + * end: range end address + */ + .align 5 +ENTRY(cpu_arm1020E_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE + bhs cpu_arm1020E_tlb_invalidate_all + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + mov r3, #PAGESIZE + sub r3, r3, #1 + bic r0, r0, r3 +1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry + add r0, r0, #PAGESIZE + cmp r0, r1 + bls 1b + mov pc, lr + +/* + * cpu_arm1020E_tlb_invalidate_page(page, flags) + * + * invalidate the TLB entries for the specified page. + * + * page: page to invalidate + * flags: non-zero if we include the I TLB + */ + .align 5 +ENTRY(cpu_arm1020E_tlb_invalidate_page) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE + teq r1, #0 + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry + mov pc, lr + +/* =============================== PageTable ============================== */ + +/* + * cpu_arm1020E_set_pgd(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_arm1020E_set_pgd) + stmfd sp!, {lr} + bl cpu_arm1020E_cache_clean_invalidate_all @ preserves r0 + mov r1, #0 + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs + ldmfd sp!, {pc} + +/* + * cpu_arm1020E_set_pmd(pmdp, pmd) + * + * Set a level 1 translation table entry, and clean it out of + * any caches such that the MMUs can load it correctly. + * + * pmdp: pointer to PMD entry + * pmd: PMD value to store + */ + .align 5 +ENTRY(cpu_arm1020E_set_pmd) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + eor r2, r1, #0x0a @ C & Section + tst r2, #0x0b + biceq r1, r1, #4 @ clear bufferable bit +#endif + str r1, [r0] +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1020E_set_pte(ptep, pte) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_arm1020E_set_pte) + str r1, [r0], #-1024 @ linux version + + eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY + + bic r2, r1, #0xff0 + bic r2, r2, #3 + orr r2, r2, #HPTE_TYPE_SMALL + + tst r1, #LPTE_USER @ User? + orrne r2, r2, #HPTE_AP_READ + + tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? + orreq r2, r2, #HPTE_AP_WRITE + + tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young? + movne r2, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + eor r3, r2, #0x0a @ C and Small Page? + tst r3, #0x0b @ if so.. + biceq r2, r2, #0x04 @ clear the bufferable bit +#endif + str r2, [r0] @ hardware version +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + + +cpu_manu_name: + .asciz "ARM" +ENTRY(cpu_arm1020E_name) + .ascii "Arm1020E" +#ifdef CONFIG_CPU_ICACHE_ENABLE + .ascii "i" +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + .ascii "d" +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + .ascii "(wt)" +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + .ascii "(wb)" +#endif +#endif +#ifndef CONFIG_CPU_BPREDICT_DISABLE + .ascii "B" +#endif +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + .ascii "RR" +#endif + .ascii "\0" + .align + + .section ".text.init", #alloc, #execinstr + +__arm1020E_setup: + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4 + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0, 0 @ load domain access register + + mrc p15, 0, r0, c1, c0, 0 @ Read current control register +/* + * The only thing worth keeping from the initial control register is the endian bit + */ + + and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others. + orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits +/* + * Turn on what we want. + */ + orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere) + orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection + orr r0, r0, #0x2000 @ ..V............. Enable high vectors + +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement +#endif + +#ifndef CONFIG_CPU_BPREDICT_DISABLE + orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction +#endif + +#ifdef CONFIG_CPU_DCACHE_ENABLE + orr r0, r0, #0x0004 @ .............C.. Enable D cache +#endif +#ifndef CONFIG_CPU_WB_DISABLE + orr r0, r0, #0x0008 @ ............W... Write Buffer enabled +#endif + +#ifdef CONFIG_CPU_ICACHE_ENABLE + orr r0, r0, #0x1000 @ ...I............ Enable I Cache +#endif + + mov pc, lr + + .text + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type arm1020E_processor_functions, #object +arm1020E_processor_functions: + .word cpu_arm1020E_data_abort + .word cpu_arm1020E_check_bugs + .word cpu_arm1020E_proc_init + .word cpu_arm1020E_proc_fin + .word cpu_arm1020E_reset + .word cpu_arm1020E_do_idle + + /* cache */ + .word cpu_arm1020E_cache_clean_invalidate_all + .word cpu_arm1020E_cache_clean_invalidate_range + .word cpu_arm1020E_flush_ram_page + + /* dcache */ + .word cpu_arm1020E_dcache_invalidate_range + .word cpu_arm1020E_dcache_clean_range + .word cpu_arm1020E_dcache_clean_page + .word cpu_arm1020E_dcache_clean_entry + + /* icache */ + .word cpu_arm1020E_icache_invalidate_range + .word cpu_arm1020E_icache_invalidate_page + + /* tlb */ + .word cpu_arm1020E_tlb_invalidate_all + .word cpu_arm1020E_tlb_invalidate_range + .word cpu_arm1020E_tlb_invalidate_page + + /* pgtable */ + .word cpu_arm1020E_set_pgd + .word cpu_arm1020E_set_pmd + .word cpu_arm1020E_set_pte + .size arm1020E_processor_functions, . - arm1020E_processor_functions + + .type cpu_arm1020E_info, #object +cpu_arm1020E_info: + .long cpu_manu_name + .long cpu_arm1020E_name + .size cpu_arm1020E_info, . - cpu_arm1020E_info + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv5te" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v5" + .size cpu_elf_name, . - cpu_elf_name + .align + + .section ".proc.info", #alloc, #execinstr + + .type __arm1020E_proc_info,#object +__arm1020E_proc_info: + .long 0x4105a200 @ ARM 1020E (Architecture v5TE) + .long 0xff0ffff0 + .long 0x00000c1e @ mmuflags + b __arm1020E_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long cpu_arm1020E_info + .long arm1020E_processor_functions + .size __arm1020E_proc_info, . - __arm1020E_proc_info + diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm1022.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1022.S --- linux-2.4.37.9/arch/arm/mm/proc-arm1022.S Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1022.S Wed May 26 15:44:03 2010 @@ -0,0 +1,716 @@ +/* + * linux/arch/arm/mm/proc-arm1022.S: MMU functions for ARM1022E + * + * Copyright (C) 2000 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * + * 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 + * + * + * These are the low level assembler for performing cache and TLB + * functions on the arm1022E. + */ +#include +#include +#include +#include +#include +#include + +/* + * This is the maximum size of an area which will be invalidated + * using the single invalidate entry instructions. Anything larger + * than this, and we go for the whole cache. + * + * This value should be chosen such that we choose the cheapest + * alternative. + */ +#define MAX_AREA_SIZE 16384 + +/* + * the cache line size of the I and D cache + */ +#define DCACHELINESIZE 32 +#define ICACHELINESIZE 32 + +/* + * and the page size + */ +#define LOG2PAGESIZE 12 /* == 4096 Bytes */ +#define PAGESIZE (1 << LOG2PAGESIZE) + +/* + * create some useful conditional macro definitions + * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback) + */ +#ifdef CONFIG_CPU_DCACHE_DISABLE + #undef CONFIG_CPU_DCACHE_WRITETHROUGH + #undef CONFIG_CPU_DCACHE_WRITEBACK + #undef CONFIG_CPU_DCACHE_ENABLE +#else + #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + #undef CONFIG_CPU_DCACHE_WRITEBACK + #else + #define CONFIG_CPU_DCACHE_WRITEBACK + #endif + #define CONFIG_CPU_DCACHE_ENABLE +#endif + +#ifdef CONFIG_CPU_ICACHE_DISABLE + #undef CONFIG_CPU_ICACHE_ENABLE +#else + #define CONFIG_CPU_ICACHE_ENABLE +#endif + + .text + +/* + * cpu_arm1022_data_abort() + * + * obtain information about current aborted instruction + * Note: we read user space. This means we might cause a data + * abort here if the I-TLB and D-TLB aren't seeing the same + * picture. Unfortunately, this does happen. We live with it. + * + * r2 = address of aborted instruction + * r3 = cpsr + * + * Returns: + * r0 = address of abort + * r1 = FSR + * r3 = corrupted + * r4 = corrupted + */ + .align 5 +ENTRY(cpu_arm1022_data_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + tst r3, #PSR_T_BIT + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 + mov pc, lr + +/* + * cpu_arm1022_check_bugs() + */ +ENTRY(cpu_arm1022_check_bugs) + mrs ip, cpsr + bic ip, ip, #F_BIT + msr cpsr, ip + mov pc, lr + +/* + * cpu_arm1022_proc_init() + */ +ENTRY(cpu_arm1022_proc_init) + mov pc, lr + +/* + * cpu_arm1022_proc_fin() + */ +ENTRY(cpu_arm1022_proc_fin) + stmfd sp!, {lr} + mov ip, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, ip + bl cpu_arm1022_cache_clean_invalidate_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + ldmfd sp!, {pc} + +/* + * cpu_arm1022_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + */ + .align 5 +ENTRY(cpu_arm1022_reset) + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + mov pc, r0 + +/* + * cpu_arm1022_do_idle() + */ + .align 5 +ENTRY(cpu_arm1022_do_idle) + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt + mov pc, lr + +/* ================================= CACHE ================================ */ + + +/* + * cpu_arm1022_cache_clean_invalidate_all() + * + * clean and invalidate all cache lines + * + * Note: + * 1. we should preserve r0 and ip at all times + */ + .align 5 +ENTRY(cpu_arm1022_cache_clean_invalidate_all) + mov r2, #1 +cpu_arm1022_cache_clean_invalidate_all_r2: + +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mov r1, #7 << 5 @ 8 segments +1: orr r3, r1, #63 << 26 @ 64 entries +2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index + subs r3, r3, #1 << 26 + bcs 2b + subs r1, r1, #1 << 5 + bcs 1b @ segments 7 to 0 +#endif + + mov r1, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache +#endif + +#ifdef CONFIG_CPU_ICACHE_ENABLE + teq r2, #0 + mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache +#endif + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1022_cache_clean_invalidate_range(start, end, flags) + * + * clean and invalidate all cache lines associated with this area of memory + * + * start: Area start address + * end: Area end address + * flags: nonzero for I cache as well + */ + .align 5 +ENTRY(cpu_arm1022_cache_clean_invalidate_range) + bic r0, r0, #DCACHELINESIZE - 1 + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bhs cpu_arm1022_cache_clean_invalidate_all_r2 +1: +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + teq r2, #0 + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b @ unsigned lower or same - must include end point (r1)! + + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1022_flush_ram_page(page) + * + * clean and invalidate all cache lines associated with this area of memory + * + * page: page to clean and invalidate + */ + .align 5 +ENTRY(cpu_arm1022_flush_ram_page) + mov r1, #PAGESIZE + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE +1: +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + subs r1, r1, #DCACHELINESIZE + bne 1b + + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ D-CACHE =============================== */ + +/* + * cpu_arm1022_dcache_invalidate_range(start, end) + * + * throw away all D-cached data in specified region without an obligation + * to write them back. Note however that we must clean the D-cached entries + * around the boundaries if the start and/or end address are not cache + * aligned. + * + * start: virtual start address + * end: virtual end address + */ + .align 5 +ENTRY(cpu_arm1022_dcache_invalidate_range) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + bic r0, r0, #DCACHELINESIZE - 1 +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + tst r0, #DCACHELINESIZE - 1 + bic r0, r0, #DCACHELINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start + tst r1, #DCACHELINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end +#endif + +1: +#ifdef CONFIG_CPU_DCACHE_ENABLE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b + + /* Even if the D cache is off still drain the write buffer */ + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer + mov pc, lr + +/* + * cpu_arm1022_dcache_clean_range(start, end) + * + * For the specified virtual address range, ensure that all caches contain + * clean data, such that peripheral accesses to the physical RAM fetch + * correct data. + * + * start: virtual start address + * end: virtual end address + */ + .align 5 +ENTRY(cpu_arm1022_dcache_clean_range) + + mov r2, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + bic r0, r0, #DCACHELINESIZE - 1 + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bhs cpu_arm1022_cache_clean_invalidate_all_r2 + +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b +#endif + + mcr p15, 0, r2, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1022_dcache_clean_page(page) + * + * Cleans a single page of dcache so that if we have any future aliased + * mappings, they will be consistent at the time that they are created. + * + * page: virtual address of page to clean from dcache + * + * Note: + * we don't invalidate the entries since when we write the page + * out to disk, the entries may get reloaded into the cache. + */ + .align 5 +ENTRY(cpu_arm1022_dcache_clean_page) +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE + mov r1, #PAGESIZE +1: + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + subs r1, r1, #DCACHELINESIZE + bne 1b +#endif + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1022_dcache_clean_entry(addr) + * + * Clean the specified entry of any caches such that the MMU + * translation fetches will obtain correct data. + * + * addr: cache-unaligned virtual address + */ + .align 5 +ENTRY(cpu_arm1022_dcache_clean_entry) +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + bic r0, r0, #DCACHELINESIZE - 1 + mcr p15, 0, r0, c7, c10, 1 @ clean single D entry +#endif + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ I-CACHE =============================== */ + +/* + * cpu_arm1022_icache_invalidate_range(start, end) + * + * invalidate a range of virtual addresses from the Icache + * + * This is a little misleading, it is not intended to clean out + * the i-cache but to make sure that any data written to the + * range is made consistent. This means that when we execute code + * in that region, everything works as we expect. + * + * This generally means writing back data in the Dcache and + * write buffer and invalidating the Icache over that region + * + * start: virtual start address + * end: virtual end address + * + * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to + * loop twice, once for i-cache, once for d-cache) + */ + .align 5 +ENTRY(cpu_arm1022_icache_invalidate_range) + bic r0, r0, #ICACHELINESIZE - 1 + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + movhs r2, #1 + bhs cpu_arm1022_cache_clean_invalidate_all_r2 +1: +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c10, 1 @ Clean D entry +#endif +#ifdef CONFIG_CPU_ICACHE_ENABLE + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry +#endif + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + bls 1b @ unsigned lower or same - includes r1 entry + + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +ENTRY(cpu_arm1022_icache_invalidate_page) + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE + add r1, r0, #PAGESIZE + b cpu_arm1022_icache_invalidate_range + +/* ================================== TLB ================================= */ + +/* + * cpu_arm1022_tlb_invalidate_all() + * + * Invalidate all TLB entries + */ + .align 5 +ENTRY(cpu_arm1022_tlb_invalidate_all) + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs + mov pc, lr + +/* + * cpu_arm1022_tlb_invalidate_range(start, end) + * + * invalidate TLB entries covering the specified range + * + * start: range start address + * end: range end address + */ + .align 5 +ENTRY(cpu_arm1022_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE + bhs cpu_arm1022_tlb_invalidate_all + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + mov r3, #PAGESIZE + sub r3, r3, #1 + bic r0, r0, r3 +1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry + add r0, r0, #PAGESIZE + cmp r0, r1 + bls 1b + mov pc, lr + +/* + * cpu_arm1022_tlb_invalidate_page(page, flags) + * + * invalidate the TLB entries for the specified page. + * + * page: page to invalidate + * flags: non-zero if we include the I TLB + */ + .align 5 +ENTRY(cpu_arm1022_tlb_invalidate_page) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page + mov r0, r0, LSL #LOG2PAGESIZE + teq r1, #0 + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry + mov pc, lr + +/* =============================== PageTable ============================== */ + +/* + * cpu_arm1022_set_pgd(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_arm1022_set_pgd) + stmfd sp!, {lr} + bl cpu_arm1022_cache_clean_invalidate_all @ preserves r0 + mov r1, #0 + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs + ldmfd sp!, {pc} + +/* + * cpu_arm1022_set_pmd(pmdp, pmd) + * + * Set a level 1 translation table entry, and clean it out of + * any caches such that the MMUs can load it correctly. + * + * pmdp: pointer to PMD entry + * pmd: PMD value to store + */ + .align 5 +ENTRY(cpu_arm1022_set_pmd) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + eor r2, r1, #0x0a @ C & Section + tst r2, #0x0b + biceq r1, r1, #4 @ clear bufferable bit +#endif + str r1, [r0] +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1022_set_pte(ptep, pte) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_arm1022_set_pte) + str r1, [r0], #-1024 @ linux version + + eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY + + bic r2, r1, #0xff0 + bic r2, r2, #3 + orr r2, r2, #HPTE_TYPE_SMALL + + tst r1, #LPTE_USER @ User? + orrne r2, r2, #HPTE_AP_READ + + tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? + orreq r2, r2, #HPTE_AP_WRITE + + tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young? + movne r2, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + eor r3, r2, #0x0a @ C and Small Page? + tst r3, #0x0b @ if so.. + biceq r2, r2, #0x04 @ clear the bufferable bit +#endif + str r2, [r0] @ hardware version +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + + +cpu_manu_name: + .asciz "ARM" +ENTRY(cpu_arm1022_name) + .ascii "Arm1022E" +#ifdef CONFIG_CPU_ICACHE_ENABLE + .ascii "i" +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + .ascii "d" +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + .ascii "(wt)" +#endif +#ifdef CONFIG_CPU_DCACHE_WRITEBACK + .ascii "(wb)" +#endif +#endif +#ifndef CONFIG_CPU_BPREDICT_DISABLE + .ascii "B" +#endif +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + .ascii "RR" +#endif + .ascii "\0" + .align + + .section ".text.init", #alloc, #execinstr + +__arm1022_setup: + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4 + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0, 0 @ load domain access register + + mrc p15, 0, r0, c1, c0, 0 @ Read current control register +/* + * The only thing worth keeping from the initial control register is the endian bit + */ + + and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others. + orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits +/* + * Turn on what we want. + */ + orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere) + orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection + orr r0, r0, #0x2000 @ ..V............. Enable high vectors + +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement +#endif + +#ifndef CONFIG_CPU_BPREDICT_DISABLE + orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction +#endif + +#ifdef CONFIG_CPU_DCACHE_ENABLE + orr r0, r0, #0x0004 @ .............C.. Enable D cache +#endif +#ifndef CONFIG_CPU_WB_DISABLE + orr r0, r0, #0x0008 @ ............W... Write Buffer enabled +#endif + +#ifdef CONFIG_CPU_ICACHE_ENABLE + orr r0, r0, #0x1000 @ ...I............ Enable I Cache +#endif + + mov pc, lr + + .text + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type arm1022_processor_functions, #object +arm1022_processor_functions: + .word cpu_arm1022_data_abort + .word cpu_arm1022_check_bugs + .word cpu_arm1022_proc_init + .word cpu_arm1022_proc_fin + .word cpu_arm1022_reset + .word cpu_arm1022_do_idle + + /* cache */ + .word cpu_arm1022_cache_clean_invalidate_all + .word cpu_arm1022_cache_clean_invalidate_range + .word cpu_arm1022_flush_ram_page + + /* dcache */ + .word cpu_arm1022_dcache_invalidate_range + .word cpu_arm1022_dcache_clean_range + .word cpu_arm1022_dcache_clean_page + .word cpu_arm1022_dcache_clean_entry + + /* icache */ + .word cpu_arm1022_icache_invalidate_range + .word cpu_arm1022_icache_invalidate_page + + /* tlb */ + .word cpu_arm1022_tlb_invalidate_all + .word cpu_arm1022_tlb_invalidate_range + .word cpu_arm1022_tlb_invalidate_page + + /* pgtable */ + .word cpu_arm1022_set_pgd + .word cpu_arm1022_set_pmd + .word cpu_arm1022_set_pte + .size arm1022_processor_functions, . - arm1022_processor_functions + + .type cpu_arm1022_info, #object +cpu_arm1022_info: + .long cpu_manu_name + .long cpu_arm1022_name + .size cpu_arm1022_info, . - cpu_arm1022_info + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv5t" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v5" + .size cpu_elf_name, . - cpu_elf_name + .align + + .section ".proc.info", #alloc, #execinstr + + .type __arm1022_proc_info,#object +__arm1022_proc_info: + .long 0x4100a220 @ ARM 1022 + .long 0xff00fff0 + .long 0x00000c1e @ mmuflags + b __arm1022_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long cpu_arm1022_info + .long arm1022_processor_functions + .size __arm1022_proc_info, . - __arm1022_proc_info diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm1026.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1026.S --- linux-2.4.37.9/arch/arm/mm/proc-arm1026.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm1026.S Wed May 26 15:44:03 2010 @@ -66,19 +66,24 @@ * * Returns: * r0 = address of abort - * r1 != 0 if writing - * r3 = FSR + * r1 = FSR, bit 11 set if writing + * r3 = corrupted * r4 = corrupted */ .align 5 ENTRY(cpu_arm1026_data_abort) - mrc p15, 0, r3, c5, c0, 0 @ get FSR - and r2, r3, #0b1101 @ Check for translation error - sub r1, r2, #0b0101 - - and r3, r3, #255 + mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR - + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + tst r3, #PSR_J_BIT @ Java? + orrne r1, r1, #1 << 11 @ always assume write + movne pc, lr + tst r3, #PSR_T_BIT + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 mov pc, lr /* @@ -254,7 +259,7 @@ */ .align 5 ENTRY(cpu_arm1026_dcache_invalidate_range) -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH tst r0, #DCACHELINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry tst r1, #DCACHELINESIZE - 1 @@ -279,7 +284,7 @@ */ .align 5 ENTRY(cpu_arm1026_dcache_clean_range) -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH bic r0, r0, #DCACHELINESIZE - 1 sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE @@ -309,7 +314,7 @@ */ .align 5 ENTRY(cpu_arm1026_dcache_clean_page) -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mov r1, #PAGESIZE 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #DCACHELINESIZE @@ -330,7 +335,7 @@ */ .align 5 ENTRY(cpu_arm1026_dcache_clean_entry) -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -473,7 +478,7 @@ biceq r1, r1, #4 @ clear bufferable bit #endif str r1, [r0] -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -494,7 +499,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -634,12 +639,12 @@ .type cpu_arch_name, #object cpu_arch_name: - .asciz "armv5EJ" + .asciz "armv5tej" .size cpu_arch_name, . - cpu_arch_name .type cpu_elf_name, #object cpu_elf_name: - .asciz "v5EJ" + .asciz "v5" .size cpu_elf_name, . - cpu_elf_name .align diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm6,7.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm6,7.S --- linux-2.4.37.9/arch/arm/mm/proc-arm6,7.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm6,7.S Wed May 26 15:44:03 2010 @@ -72,7 +72,7 @@ 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB add r0, r0, #4096 cmp r0, r1 - blt 1b + blo 1b mov pc, lr ENTRY(cpu_arm7_tlb_invalidate_range) @@ -85,7 +85,7 @@ 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB add r0, r0, #0x4000 cmp r0, r1 - blt 1b + blo 1b mov pc, lr #endif @@ -110,15 +110,13 @@ * Purpose : obtain information about current aborted instruction * * Returns : r0 = address of abort - * : r1 != 0 if writing - * : r3 = FSR + * : r1 = FSR, bit 11 set if writing + * : r3 = corrupted * : sp = pointer to registers */ ENTRY(cpu_arm6_data_abort) ldr r4, [r0] @ read instruction causing problem - tst r4, r4, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 and r2, r4, #14 << 24 teq r2, #8 << 24 @ was it ldm/stm bne Ldata_simple @@ -144,14 +142,14 @@ addeq r7, r0, r7, lsl #2 @ Do correction (signed) Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r3, c5, c0, 0 @ get FSR - and r3, r3, #255 + mrc p15, 0, r1, c5, c0, 0 @ get FSR + bic r1, r1, #1 << 11 | 1 << 10 + tst r4, #1 << 20 + orreq r1, r1, #1 << 11 mov pc, lr ENTRY(cpu_arm7_data_abort) ldr r4, [r0] @ read instruction causing problem - tst r4, r4, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 and r2, r4, #15 << 24 add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine movs pc, lr @@ -336,7 +334,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm720.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm720.S --- linux-2.4.37.9/arch/arm/mm/proc-arm720.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm720.S Wed May 26 15:44:03 2010 @@ -97,7 +97,7 @@ 1: mcr p15, 0, r0, c8, c7, 1 @ flush TLB (v4) add r0, r0, #PAGESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -124,8 +124,8 @@ * picture. Unfortunately, this does happen. We live with it. * * Returns : r0 = address of abort - * : r1 != 0 if writing - * : r3 = FSR + * : r1 = FSR, bit 11 set if writing + * : r3 = corrupted * : sp = pointer to registers */ @@ -150,16 +150,16 @@ addeq r7, r0, r7, lsl #2 @ Do correction (signed) Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r3, c5, c0, 0 @ get FSR - and r3, r3, #255 + mrc p15, 0, r1, c5, c0, 0 @ get FSR + bic r1, r1, #1 << 11 | 1 << 10 + tst r4, #1 << 20 + orreq r1, r1, #1 << 11 mov pc, lr ENTRY(cpu_arm720_data_abort) - tst r3, #T_BIT + tst r3, #PSR_T_BIT bne .data_thumb_abort - ldr r4, [r0] @ read instruction causing problem - tst r4, r4, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 + ldr r4, [r2] @ read instruction causing problem and r2, r4, #15 << 24 add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine movs pc, lr @@ -270,9 +270,9 @@ b Ldata_saver7 .data_thumb_abort: - ldrh r4, [r0] @ read instruction - tst r4, r4, lsr #12 @ C = bit 11 - sbc r1, r1, r1 @ r1 = C - 1 + ldrh r4, [r2] @ read instruction + tst r4, #1 << 11 + orrne r4, r4, #1 << 20 and r2, r4, #15 << 12 add pc, pc, r2, lsr #10 @ lookup in table nop @@ -318,8 +318,8 @@ and r0, r0, #15 @ number of regs to transfer ldr r7, [sp, #13 << 2] tst r4, #1 << 11 - addne r7, r7, r0, lsl #2 @ increment SP if PUSH - subeq r7, r7, r0, lsr #2 @ decrement SP if POP + addeq r7, r7, r0, lsl #2 @ increment SP if PUSH + subne r7, r7, r0, lsl #2 @ decrement SP if POP str r7, [sp, #13 << 2] b Ldata_simple @@ -336,7 +336,7 @@ and r0, r0, #15 @ number of regs to transfer and r5, r4, #7 << 8 ldr r7, [sp, r5, lsr #6] - sub r7, r7, r0, lsr #2 @ always decrement + sub r7, r7, r0, lsl #2 @ always decrement str r7, [sp, r5, lsr #6] b Ldata_simple @@ -418,7 +418,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -447,7 +447,7 @@ cpu_arm720_name: - .asciz "ARM720T" + .asciz "ARM720T/710T" .align .section ".text.init", #alloc, #execinstr @@ -461,7 +461,7 @@ mrc p15, 0, r0, c1, c0 @ get control register bic r0, r0, #0x0e00 @ ..V. ..RS BLDP WCAM - orr r0, r0, #0x2100 @ .... .... .111 .... (old) + orr r0, r0, #0x0100 @ .... .... .111 .... (old) orr r0, r0, #0x003d @ ..1. ..01 ..11 1101 (new) mov pc, lr @ __ret (head-armv.S) @@ -521,14 +521,16 @@ /* * See linux/include/asm-arm/procinfo.h for a definition of this structure. + * Supports both ARM720T and 710T processors. The cpu_val can be something + * like: 0x41807200 for 720T or 0x41807101 for 710T. What about 740T? */ .section ".proc.info", #alloc, #execinstr .type __arm720_proc_info, #object __arm720_proc_info: - .long 0x41807200 @ cpu_val - .long 0xffffff00 @ cpu_mask + .long 0x41807000 @ cpu_val 720T or 710T + .long 0xfffff000 @ cpu_mask .long 0x00000c1e @ section_mmu_flags b __arm720_setup @ cpu_flush .long cpu_arch_name @ arch_name diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm920.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm920.S --- linux-2.4.37.9/arch/arm/mm/proc-arm920.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm920.S Wed May 26 15:44:03 2010 @@ -71,12 +71,16 @@ */ .align 5 ENTRY(cpu_arm920_data_abort) - mrc p15, 0, r3, c5, c0, 0 @ get FSR + mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR - ldr r1, [r2] @ read aborted instruction - and r3, r3, #255 - tst r1, r1, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 + + tst r3, #PSR_T_BIT + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 mov pc, lr /* @@ -186,10 +190,9 @@ .align 5 ENTRY(cpu_arm920_cache_clean_invalidate_range) bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM - bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE - bgt cpu_arm920_cache_clean_invalidate_all_r2 + bhi cpu_arm920_cache_clean_invalidate_all_r2 1: teq r2, #0 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry @@ -207,7 +210,7 @@ add r0, r0, #DCACHELINESIZE #endif cmp r0, r1 - blt 1b + blo 1b mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr @@ -253,18 +256,17 @@ */ .align 5 ENTRY(cpu_arm920_dcache_invalidate_range) -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH tst r0, #DCACHELINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry tst r1, #DCACHELINESIZE - 1 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry #endif @ clean D entry bic r0, r0, #DCACHELINESIZE - 1 - bic r1, r1, #DCACHELINESIZE - 1 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -279,20 +281,17 @@ */ .align 5 ENTRY(cpu_arm920_dcache_clean_range) -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH bic r0, r0, #DCACHELINESIZE - 1 sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE mov r2, #0 - bgt cpu_arm920_cache_clean_invalidate_all_r2 - - bic r1, r1, #DCACHELINESIZE -1 - add r1, r1, #DCACHELINESIZE + bhi cpu_arm920_cache_clean_invalidate_all_r2 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #DCACHELINESIZE subs r1, r1, #DCACHELINESIZE - bpl 1b + bcs 1b #endif mcr p15, 0, r2, c7, c10, 4 @ drain WB mov pc, lr @@ -312,7 +311,7 @@ */ .align 5 ENTRY(cpu_arm920_dcache_clean_page) -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mov r1, #PAGESIZE 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #DCACHELINESIZE @@ -333,7 +332,7 @@ */ .align 5 ENTRY(cpu_arm920_dcache_clean_entry) -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -365,16 +364,13 @@ bic r0, r0, #ICACHELINESIZE - 1 @ Safety check sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE - bgt cpu_arm920_cache_clean_invalidate_all_r2 - - bic r1, r1, #ICACHELINESIZE - 1 - add r1, r1, #ICACHELINESIZE + bhi cpu_arm920_cache_clean_invalidate_all_r2 1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry mcr p15, 0, r0, c7, c10, 1 @ Clean D entry add r0, r0, #ICACHELINESIZE subs r1, r1, #ICACHELINESIZE - bne 1b + bcs 1b mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -418,13 +414,12 @@ mov r3, #PAGESIZE sub r3, r3, #1 bic r0, r0, r3 - bic r1, r1, r3 1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry add r0, r0, #PAGESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -457,7 +452,6 @@ ENTRY(cpu_arm920_set_pgd) mov ip, #0 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else @ && 'Clean & Invalidate whole DCache' @@ -514,7 +508,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm922.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm922.S --- linux-2.4.37.9/arch/arm/mm/proc-arm922.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm922.S Wed May 26 15:44:03 2010 @@ -62,17 +62,20 @@ * * Returns: * r0 = address of abort - * r1 != 0 if writing - * r3 = FSR + * r1 = FSR, bit 11 set if writing + * r3 = corrupted */ .align 5 ENTRY(cpu_arm922_data_abort) - ldr r1, [r0] @ read aborted instruction + mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR - tst r1, r1, lsr #21 @ C = bit 20 - mrc p15, 0, r3, c5, c0, 0 @ get FSR - sbc r1, r1, r1 @ r1 = C - 1 - and r3, r3, #255 + tst r3, #PSR_T_BIT + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 mov pc, lr /* @@ -185,7 +188,7 @@ bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE - bgt cpu_arm922_cache_clean_invalidate_all_r2 + bhi cpu_arm922_cache_clean_invalidate_all_r2 1: teq r2, #0 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry @@ -203,7 +206,7 @@ add r0, r0, #DCACHELINESIZE #endif cmp r0, r1 - blt 1b + blo 1b mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr @@ -249,7 +252,7 @@ */ .align 5 ENTRY(cpu_arm922_dcache_invalidate_range) -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH tst r0, #DCACHELINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry tst r1, #DCACHELINESIZE - 1 @@ -260,7 +263,7 @@ 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -275,12 +278,12 @@ */ .align 5 ENTRY(cpu_arm922_dcache_clean_range) -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH bic r0, r0, #DCACHELINESIZE - 1 sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE mov r2, #0 - bgt cpu_arm922_cache_clean_invalidate_all_r2 + bhi cpu_arm922_cache_clean_invalidate_all_r2 bic r1, r1, #DCACHELINESIZE -1 add r1, r1, #DCACHELINESIZE @@ -308,7 +311,7 @@ */ .align 5 ENTRY(cpu_arm922_dcache_clean_page) -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mov r1, #PAGESIZE 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #DCACHELINESIZE @@ -329,7 +332,7 @@ */ .align 5 ENTRY(cpu_arm922_dcache_clean_entry) -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -361,7 +364,7 @@ bic r0, r0, #ICACHELINESIZE - 1 @ Safety check sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE - bgt cpu_arm922_cache_clean_invalidate_all_r2 + bhi cpu_arm922_cache_clean_invalidate_all_r2 bic r1, r1, #ICACHELINESIZE - 1 add r1, r1, #ICACHELINESIZE @@ -420,7 +423,7 @@ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry add r0, r0, #PAGESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -510,7 +513,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm925.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm925.S --- linux-2.4.37.9/arch/arm/mm/proc-arm925.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm925.S Wed May 26 15:44:03 2010 @@ -69,24 +69,24 @@ * * Returns: * r0 = address of abort - * r1 != 0 if writing - * r3 = FSR + * r1 = FSR, bit 11 set if writing + * r3 = corrupted * r4 = corrupted */ .align 5 ENTRY(cpu_arm925_data_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r4, c5, c0, 0 @ get FSR - - tst r3, #1<<5 @ Check for Thumb-bit (NE -> found) - ldrneh r1, [r2] @ Read aborted Thumb instruction - tstne r1, r1, lsr #12 @ C = bit 11 - - ldreq r1, [r2] @ Read aborted ARM instruction - tsteq r1, r1, lsr #21 @ C = bit 20 - - sbc r1, r1, r1 @ r1 = C - 1 - and r3, r4, #255 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + tst r3, #PSR_J_BIT @ Java? + orrne r1, r1, #1 << 11 @ always assume write + movne pc, lr + tst r3, #PSR_T_BIT @ Thumb? + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ L = 0 -> write + orreq r1, r1, #1 << 11 @ yes. mov pc, lr /* @@ -207,7 +207,7 @@ bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE - bgt cpu_arm925_cache_clean_invalidate_all_r2 + bhi cpu_arm925_cache_clean_invalidate_all_r2 1: teq r2, #0 #ifdef CONFIG_CPU_ARM925_WRITETHROUGH mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry @@ -225,7 +225,7 @@ add r0, r0, #DCACHELINESIZE #endif cmp r0, r1 - blt 1b + blo 1b mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr @@ -282,7 +282,7 @@ 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -302,7 +302,7 @@ sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE mov r2, #0 - bgt cpu_arm925_cache_clean_invalidate_all_r2 + bhi cpu_arm925_cache_clean_invalidate_all_r2 bic r1, r1, #DCACHELINESIZE -1 add r1, r1, #DCACHELINESIZE @@ -383,7 +383,7 @@ bic r0, r0, #ICACHELINESIZE - 1 @ Safety check sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE - bgt cpu_arm925_cache_clean_invalidate_all_r2 + bhi cpu_arm925_cache_clean_invalidate_all_r2 bic r1, r1, #ICACHELINESIZE - 1 add r1, r1, #ICACHELINESIZE @@ -443,7 +443,7 @@ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry add r0, r0, #PAGESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -532,7 +532,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? diff -uNr linux-2.4.37.9/arch/arm/mm/proc-arm926.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm926.S --- linux-2.4.37.9/arch/arm/mm/proc-arm926.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-arm926.S Wed May 26 15:44:03 2010 @@ -66,28 +66,24 @@ * * Returns: * r0 = address of abort - * r1 != 0 if writing - * r3 = FSR + * r1 = FSR, bit 11 set if writing + * r3 = corrupted * r4 = corrupted */ .align 5 ENTRY(cpu_arm926_data_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r4, c5, c0, 0 @ get FSR - - tst r3, #1<<24 @ Check for Jbit (NE -> found) - movne r3, #-1 @ Mark as writing - bne 2f - - tst r3, #1<<5 @ Check for Thumb-bit (NE -> found) - ldrneh r1, [r2] @ Read aborted Thumb instruction - ldreq r1, [r2] @ Read aborted ARM instruction - movne r1, r1, lsl #(20-12) @ shift thumb bit 10 to ARM bit 20 - tsteq r1, r1, lsr #21 @ C = bit 20 - - sbc r1, r1, r1 @ r1 = C - 1 -2: - and r3, r4, #255 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + tst r3, #PSR_J_BIT @ Java? + orrne r1, r1, #1 << 11 @ always assume write + movne pc, lr + tst r3, #PSR_T_BIT @ Thumb? + ldrneh r3, [r2] @ read aborted thumb instruction + ldreq r3, [r2] @ read aborted ARM instruction + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20 + tst r3, #1 << 20 @ L = 0 -> write + orreq r1, r1, #1 << 11 @ yes. mov pc, lr /* @@ -263,7 +259,7 @@ */ .align 5 ENTRY(cpu_arm926_dcache_invalidate_range) -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH tst r0, #DCACHELINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry tst r1, #DCACHELINESIZE - 1 @@ -288,7 +284,7 @@ */ .align 5 ENTRY(cpu_arm926_dcache_clean_range) -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH bic r0, r0, #DCACHELINESIZE - 1 sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE @@ -318,7 +314,7 @@ */ .align 5 ENTRY(cpu_arm926_dcache_clean_page) -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mov r1, #PAGESIZE 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #DCACHELINESIZE @@ -339,7 +335,7 @@ */ .align 5 ENTRY(cpu_arm926_dcache_clean_entry) -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -482,7 +478,7 @@ biceq r1, r1, #4 @ clear bufferable bit #endif str r1, [r0] -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -503,7 +499,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? diff -uNr linux-2.4.37.9/arch/arm/mm/proc-sa110.S linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-sa110.S --- linux-2.4.37.9/arch/arm/mm/proc-sa110.S Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/mm/proc-sa110.S Wed May 26 15:44:03 2010 @@ -86,12 +86,12 @@ .align 5 ENTRY(cpu_sa110_data_abort) ENTRY(cpu_sa1100_data_abort) - mrc p15, 0, r3, c5, c0, 0 @ get FSR + mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR - ldr r1, [r2] @ read aborted instruction - and r3, r3, #255 - tst r1, r1, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 + ldr r3, [r2] @ read aborted instruction + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 mov pc, lr /* @@ -551,7 +551,7 @@ bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? diff -uNr linux-2.4.37.9/arch/arm/tools/mach-types linux-2.4.37.9-vrs1-5mx2/arch/arm/tools/mach-types --- linux-2.4.37.9/arch/arm/tools/mach-types Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/arm/tools/mach-types Wed May 26 15:44:00 2010 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Sat Jun 28 12:10:54 2003 +# Last update: Mon Apr 19 21:11:35 2004 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -202,7 +202,7 @@ fester SA1100_FESTER FESTER 191 gpi ARCH_GPI GPI 192 smdk2410 ARCH_SMDK2410 SMDK2410 193 -premium ARCH_PREMIUM PREMIUM 194 +i519 ARCH_I519 I519 194 nexio SA1100_NEXIO NEXIO 195 bitbox SA1100_BITBOX BITBOX 196 g200 SA1100_G200 G200 197 @@ -228,7 +228,7 @@ arnold SA1100_ARNOLD ARNOLD 217 psiboard SA1100_PSIBOARD PSIBOARD 218 jz8028 ARCH_JZ8028 JZ8028 219 -h5400 ARCH_IPAQ3 IPAQ3 220 +h5400 ARCH_H5400 H5400 220 forte SA1100_FORTE FORTE 221 acam SA1100_ACAM ACAM 222 abox SA1100_ABOX ABOX 223 @@ -259,7 +259,7 @@ stork_egg ARCH_STORK_EGG STORK_EGG 248 wismo SA1100_WISMO WISMO 249 ezlinx ARCH_EZLINX EZLINX 250 -at91rm9200 ARCH_AT91 AT91 251 +at91rm9200 ARCH_AT91RM9200 AT91RM9200 251 orion ARCH_ORION ORION 252 neptune ARCH_NEPTUNE NEPTUNE 253 hackkit SA1100_HACKKIT HACKKIT 254 @@ -295,12 +295,12 @@ adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 adsagc SA1100_ADSAGC ADSAGC 285 stp7312 ARCH_STP7312 STP7312 286 -nx_phnx ARCH_PXA255 PXA255 287 +nx_phnx MACH_NX_PHNX NX_PHNX 287 wep_ep250 ARCH_WEP_EP250 WEP_EP250 288 inhandelf3 ARCH_INHANDELF3 INHANDELF3 289 adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290 iyonix ARCH_IYONIX IYONIX 291 -damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292 +damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292 meg03 ARCH_MEG03 MEG03 293 pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294 nwsc ARCH_NWSC NWSC 295 @@ -356,3 +356,172 @@ seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345 ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346 h1940 ARCH_H1940 H1940 347 +scorpio ARCH_SCORPIO SCORPIO 348 +viva ARCH_VIVA VIVA 349 +pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350 +csb335 ARCH_CSB335 CSB335 351 +ixrd425 ARCH_IXRD425 IXRD425 352 +iq80315 ARCH_IQ80315 IQ80315 353 +nmp7312 ARCH_NMP7312 NMP7312 354 +cx861xx ARCH_CX861XX CX861XX 355 +enp2611 ARCH_ENP2611 ENP2611 356 +xda SA1100_XDA XDA 357 +csir_ims ARCH_CSIR_IMS CSIR_IMS 358 +ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359 +pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360 +toto ARCH_TOTO TOTO 361 +s3c2440 ARCH_S3C2440 S3C2440 362 +ks8695p ARCH_KS8695P KS8695P 363 +se4000 ARCH_SE4000 SE4000 364 +quadriceps ARCH_QUADRICEPS QUADRICEPS 365 +bronco ARCH_BRONCO BRONCO 366 +esl_wireless_tab ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET 367 +esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368 +s5c7375 ARCH_S5C7375 S5C7375 369 +spearhead ARCH_SPEARHEAD SPEARHEAD 370 +pantera ARCH_PANTERA PANTERA 371 +prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372 +gumstik ARCH_GUMSTIK GUMSTIK 373 +rcube ARCH_RCUBE RCUBE 374 +rea_olv ARCH_REA_OLV REA_OLV 375 +pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376 +s3c3410 ARCH_S3C3410 S3C3410 377 +espd_4510b ARCH_ESPD_4510B ESPD_4510B 378 +mp1x ARCH_MP1X MP1X 379 +at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380 +adsvgx ARCH_ADSVGX ADSVGX 381 +omap_h2 ARCH_OMAP_H2 OMAP_H2 382 +pelee ARCH_PELEE PELEE 383 +e740 MACH_E740 E740 384 +iq80331 ARCH_IQ80331 IQ80331 385 +versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387 +kev7a400 MACH_KEV7A400 KEV7A400 388 +lpd7a400 MACH_LPD7A400 LPD7A400 389 +lpd7a404 MACH_LPD7A404 LPD7A404 390 +fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391 +janus2m ARCH_JANUS2M JANUS2M 392 +embtf MACH_EMBTF EMBTF 393 +hpm MACH_HPM HPM 394 +smdk2410tk MACH_SMDK2410TK SMDK2410TK 395 +smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396 +streetracer MACH_STREETRACER STREETRACER 397 +eframe MACH_EFRAME EFRAME 398 +csb337 MACH_CSB337 CSB337 399 +pxa_lark MACH_PXA_LARK PXA_LARK 400 +pxa_pnp2110 MACH_PNP2110 PNP2110 401 +tcc72x MACH_TCC72X TCC72X 402 +altair MACH_ALTAIR ALTAIR 403 +kc3 MACH_KC3 KC3 404 +sinteftd MACH_SINTEFTD SINTEFTD 405 +mainstone MACH_MAINSTONE MAINSTONE 406 +aday4x MACH_ADAY4X ADAY4X 407 +lite300 MACH_LITE300 LITE300 408 +s5c7376 MACH_S5C7376 S5C7376 409 +mt02 MACH_MT02 MT02 410 +mport3s MACH_MPORT3S MPORT3S 411 +ra_alpha MACH_RA_ALPHA RA_ALPHA 412 +xcep MACH_XCEP XCEP 413 +arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414 +stargate MACH_STARGATE STARGATE 415 +armadilloj MACH_ARMADILLOJ ARMADILLOJ 416 +elroy_jack MACH_ELROY_JACK ELROY_JACK 417 +backend MACH_BACKEND BACKEND 418 +s5linbox MACH_S5LINBOX S5LINBOX 419 +nomadik MACH_NOMADIK NOMADIK 420 +ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421 +at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422 +corgi MACH_CORGI CORGI 423 +poodle MACH_POODLE POODLE 424 +ten MACH_TEN TEN 425 +roverp5p MACH_ROVERP5P ROVERP5P 426 +sc2700 MACH_SC2700 SC2700 427 +ex_eagle MACH_EX_EAGLE EX_EAGLE 428 +nx_pxa12 MACH_NX_PXA12 NX_PXA12 429 +nx_pxa5 MACH_NX_PXA5 NX_PXA5 430 +blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431 +i819 MACH_I819 I819 432 +ixmb995e MACH_IXMB995E IXMB995E 433 +skyrider MACH_SKYRIDER SKYRIDER 434 +skyhawk MACH_SKYHAWK SKYHAWK 435 +enterprise MACH_ENTERPRISE ENTERPRISE 436 +dep2410 MACH_DEP2410 DEP2410 437 +armcore MACH_ARMCORE ARMCORE 438 +hobbit MACH_HOBBIT HOBBIT 439 +h7210 MACH_H7210 H7210 440 +pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441 +acc MACH_ACC ACC 442 +esl_sarva MACH_ESL_SARVA ESL_SARVA 443 +xm250 MACH_XM250 XM250 444 +t6tc1xb MACH_T6TC1XB T6TC1XB 445 +ess710 MACH_ESS710 ESS710 446 +mx3ads MACH_MX3ADS MX3ADS 447 +himalaya MACH_HIMALAYA HIMALAYA 448 +bolfenk MACH_BOLFENK BOLFENK 449 +at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450 +edb9312 MACH_EDB9312 EDB9312 451 +omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452 +aximx3 MACH_AXIMX3 AXIMX3 453 +eb67xdip MACH_EB67XDIP EB67XDIP 454 +webtxs MACH_WEBTXS WEBTXS 455 +hawk MACH_HAWK HAWK 456 +ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457 +expresso MACH_EXPRESSO EXPRESSO 458 +h4000 MACH_H4000 H4000 459 +dino MACH_DINO DINO 460 +ml675k MACH_ML675K ML675K 461 +edb9301 MACH_EDB9301 EDB9301 462 +edb9315 MACH_EDB9315 EDB9315 463 +reciva_tt MACH_RECIVA_TT RECIVA_TT 464 +cstcb01 MACH_CSTCB01 CSTCB01 465 +cstcb1 MACH_CSTCB1 CSTCB1 466 +shadwell MACH_SHADWELL SHADWELL 467 +goepel263 MACH_GOEPEL263 GOEPEL263 468 +acq100 MACH_ACQ100 ACQ100 469 +mx1fs2 MACH_MX1FS2 MX1FS2 470 +hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471 +sparky MACH_SPARKY SPARKY 472 +ns9750 MACH_NS9750 NS9750 473 +phoenix MACH_PHOENIX PHOENIX 474 +vr1000 MACH_VR1000 VR1000 475 +deisterpxa MACH_DEISTERPXA DEISTERPXA 476 +bcm1160 MACH_BCM1160 BCM1160 477 +pcm022 MACH_PCM022 PCM022 478 +adsgcx MACH_ADSGCX ADSGCX 479 +dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480 +dm320 MACH_DM320 DM320 481 +markov MACH_MARKOV MARKOV 482 +cos7a400 MACH_COS7A400 COS7A400 483 +milano MACH_MILANO MILANO 484 +ue9328 MACH_UE9328 UE9328 485 +uex255 MACH_UEX255 UEX255 486 +ue2410 MACH_UE2410 UE2410 487 +a620 MACH_A620 A620 488 +ocelot MACH_OCELOT OCELOT 489 +cheetah MACH_CHEETAH CHEETAH 490 +omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491 +zvue MACH_ZVUE ZVUE 492 +roverp1 MACH_ROVERP1 ROVERP1 493 +asidial2 MACH_ASIDIAL2 ASIDIAL2 494 +s3c24a0 MACH_S3C24A0 S3C24A0 495 +e800 MACH_E800 E800 496 +e750 MACH_E750 E750 497 +s3c5500 MACH_S3C5500 S3C5500 498 +smdk5500 MACH_SMDK5500 SMDK5500 499 +signalsync MACH_SIGNALSYNC SIGNALSYNC 500 +nbc MACH_NBC NBC 501 +er4525 MACH_ER4525 ER4525 502 +netbookpro MACH_NETBOOKPRO NETBOOKPRO 503 +hw90200 MACH_HW90200 HW90200 504 +condor MACH_CONDOR CONDOR 505 +cup MACH_CUP CUP 506 +kite MACH_KITE KITE 507 +scb9328 MACH_SCB9328 SCB9328 508 +omap_h3 MACH_OMAP_H3 OMAP_H3 509 +omap_h4 MACH_OMAP_H4 OMAP_H4 510 +n10 MACH_N10 N10 511 +montajade MACH_MONTAJADE MONTAJADE 512 +sg560 MACH_SG560 SG560 513 +dp1000 MACH_DP1000 DP1000 514 +omap_osk MACH_OMAP_OSK OMAP_OSK 515 +rg100v3 MACH_RG100V3 RG100V3 516 +mx2ads MACH_MX2ADS MX2ADS 517 diff -uNr linux-2.4.37.9/arch/i386/config.in linux-2.4.37.9-vrs1-5mx2/arch/i386/config.in --- linux-2.4.37.9/arch/i386/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/i386/config.in Mon Jun 7 18:59:41 2010 @@ -9,6 +9,7 @@ define_bool CONFIG_UID16 y +define_bool CONFIG_GENERIC_ISA_DMA y mainmenu_option next_comment comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL diff -uNr linux-2.4.37.9/arch/i386/kernel/Makefile linux-2.4.37.9-vrs1-5mx2/arch/i386/kernel/Makefile --- linux-2.4.37.9/arch/i386/kernel/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/i386/kernel/Makefile Mon Jun 7 18:59:41 2010 @@ -7,8 +7,8 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -.S.o: - $(CC) $(AFLAGS) -traditional -c $< -o $*.o +USE_STANDARD_AS_RULE := true +EXTRA_AFLAGS := -traditional all: kernel.o head.o init_task.o diff -uNr linux-2.4.37.9/arch/i386/kernel/apm.c linux-2.4.37.9-vrs1-5mx2/arch/i386/kernel/apm.c --- linux-2.4.37.9/arch/i386/kernel/apm.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/i386/kernel/apm.c Mon Jun 7 18:46:10 2010 @@ -1267,6 +1267,7 @@ as->suspend_wait = 0; as->suspend_result = err; } + ignore_normal_resume = 1; wake_up_interruptible(&apm_suspend_waitqueue); return err; } @@ -1319,6 +1320,8 @@ if (ignore_bounce && ((jiffies - last_resume) > bounce_interval)) ignore_bounce = 0; + if (ignore_normal_resume && (event != APM_NORMAL_RESUME)) + ignore_normal_resume = 0; switch (event) { case APM_SYS_STANDBY: diff -uNr linux-2.4.37.9/arch/i386/lib/Makefile linux-2.4.37.9-vrs1-5mx2/arch/i386/lib/Makefile --- linux-2.4.37.9/arch/i386/lib/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/i386/lib/Makefile Wed May 26 15:45:06 2010 @@ -2,8 +2,7 @@ # Makefile for i386-specific library files.. # -.S.o: - $(CC) $(AFLAGS) -c $< -o $*.o +USE_STANDARD_AS_RULE := true L_TARGET = lib.a diff -uNr linux-2.4.37.9/arch/i386/math-emu/Makefile linux-2.4.37.9-vrs1-5mx2/arch/i386/math-emu/Makefile --- linux-2.4.37.9/arch/i386/math-emu/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/i386/math-emu/Makefile Wed May 26 15:45:08 2010 @@ -2,15 +2,15 @@ # Makefile for wm-FPU-emu # +USE_STANDARD_AS_RULE := true + O_TARGET := math.o #DEBUG = -DDEBUGGING DEBUG = PARANOID = -DPARANOID CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION) - -.S.o: - $(CC) $(AFLAGS) $(PARANOID) -c $< +EXTRA_AFLAGS := $(PARANOID) # From 'C' language sources: C_OBJS =fpu_entry.o errors.o \ diff -uNr linux-2.4.37.9/arch/ia64/config.in linux-2.4.37.9-vrs1-5mx2/arch/ia64/config.in --- linux-2.4.37.9/arch/ia64/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/ia64/config.in Wed May 26 15:45:46 2010 @@ -25,6 +25,7 @@ define_bool CONFIG_SBUS n define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y +define_bool CONFIG_GENERIC_ISA_DMA y choice 'IA-64 processor type' \ "Itanium CONFIG_ITANIUM \ diff -uNr linux-2.4.37.9/arch/m68k/config.in linux-2.4.37.9-vrs1-5mx2/arch/m68k/config.in --- linux-2.4.37.9/arch/m68k/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/m68k/config.in Mon Jun 7 19:04:33 2010 @@ -6,6 +6,7 @@ define_bool CONFIG_UID16 y define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n +define_bool CONFIG_GENERIC_ISA_DMA y mainmenu_name "Linux/68k Kernel Configuration" diff -uNr linux-2.4.37.9/arch/mips/config.in linux-2.4.37.9-vrs1-5mx2/arch/mips/config.in --- linux-2.4.37.9/arch/mips/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/mips/config.in Wed May 26 15:46:09 2010 @@ -5,5 +5,6 @@ define_bool CONFIG_MIPS y define_bool CONFIG_MIPS32 y define_bool CONFIG_MIPS64 n +define_bool CONFIG_GENERIC_ISA_DMA y source arch/mips/config-shared.in diff -uNr linux-2.4.37.9/arch/parisc/config.in linux-2.4.37.9-vrs1-5mx2/arch/parisc/config.in --- linux-2.4.37.9/arch/parisc/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/parisc/config.in Wed May 26 15:44:12 2010 @@ -9,6 +9,7 @@ define_bool CONFIG_UID16 n define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n +define_bool CONFIG_GENERIC_ISA_DMA y mainmenu_option next_comment comment 'Code maturity level options' diff -uNr linux-2.4.37.9/arch/ppc/config.in linux-2.4.37.9-vrs1-5mx2/arch/ppc/config.in --- linux-2.4.37.9/arch/ppc/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/ppc/config.in Wed May 26 15:44:37 2010 @@ -6,6 +6,7 @@ define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y define_bool CONFIG_HAVE_DEC_LOCK y +define_bool CONFIG_GENERIC_ISA_DMA y mainmenu_name "Linux/PowerPC Kernel Configuration" diff -uNr linux-2.4.37.9/arch/sh/config.in linux-2.4.37.9-vrs1-5mx2/arch/sh/config.in --- linux-2.4.37.9/arch/sh/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/sh/config.in Wed May 26 15:46:13 2010 @@ -9,6 +9,7 @@ define_bool CONFIG_UID16 y define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n +define_bool CONFIG_GENERIC_ISA_DMA y mainmenu_option next_comment comment 'Code maturity level options' diff -uNr linux-2.4.37.9/arch/sparc/config.in linux-2.4.37.9-vrs1-5mx2/arch/sparc/config.in --- linux-2.4.37.9/arch/sparc/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/sparc/config.in Wed May 26 15:45:51 2010 @@ -6,6 +6,7 @@ define_bool CONFIG_UID16 y define_bool CONFIG_HIGHMEM y +define_bool CONFIG_GENERIC_ISA_DMA y mainmenu_option next_comment comment 'Code maturity level options' diff -uNr linux-2.4.37.9/arch/sparc64/config.in linux-2.4.37.9-vrs1-5mx2/arch/sparc64/config.in --- linux-2.4.37.9/arch/sparc64/config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/arch/sparc64/config.in Wed May 26 15:44:19 2010 @@ -43,6 +43,7 @@ define_bool CONFIG_HAVE_DEC_LOCK y define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y +define_bool CONFIG_GENERIC_ISA_DMA y define_bool CONFIG_ISA n define_bool CONFIG_ISAPNP n define_bool CONFIG_EISA n diff -uNr linux-2.4.37.9/drivers/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/Makefile --- linux-2.4.37.9/drivers/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/Makefile Wed May 26 15:51:20 2010 @@ -8,9 +8,9 @@ mod-subdirs := dio hil mtd sbus video macintosh usb input telephony ide \ message/i2o message/fusion scsi md ieee1394 pnp isdn atm \ - fc4 net/hamradio i2c acpi bluetooth usb/gadget + fc4 net/hamradio i2c l3 acpi bluetooth serial usb/gadget -subdir-y := parport char block net sound misc media cdrom hotplug +subdir-y := parport serial char block net sound misc media cdrom hotplug pld subdir-m := $(subdir-y) @@ -45,8 +45,12 @@ # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch subdir-$(CONFIG_HAMRADIO) += net/hamradio subdir-$(CONFIG_I2C) += i2c +subdir-$(CONFIG_L3) += l3 subdir-$(CONFIG_ACPI_BOOT) += acpi subdir-$(CONFIG_BLUEZ) += bluetooth +subdir-$(CONFIG_SSI) += ssi + +subdir-$(CONFIG_ARCH_AT91RM9200)+= at91 include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/acorn/char/i2c.c linux-2.4.37.9-vrs1-5mx2/drivers/acorn/char/i2c.c --- linux-2.4.37.9/drivers/acorn/char/i2c.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/acorn/char/i2c.c Wed May 26 15:51:07 2010 @@ -33,9 +33,13 @@ static struct i2c_client *rtc_client; static const unsigned char days_in_mon[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static unsigned int rtc_epoch = 1900; #define CMOS_CHECKSUM (63) + +/* + * Acorn machines store the year in the static RAM at + * location 128. + */ #define CMOS_YEAR (64 + 128) static inline int rtc_command(int cmd, void *data) @@ -49,51 +53,91 @@ } /* + * Update the century + year bytes in the CMOS RAM, ensuring + * that the check byte is correctly adjusted for the change. + */ +static int rtc_update_year(unsigned int new_year) +{ + unsigned char yr[2], chk; + struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr }; + struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; + int ret; + + ret = rtc_command(MEM_READ, &cmos_check); + if (ret) + goto out; + ret = rtc_command(MEM_READ, &cmos_year); + if (ret) + goto out; + + chk -= yr[1] + yr[0]; + + yr[1] = new_year / 100; + yr[0] = new_year % 100; + + chk += yr[1] + yr[0]; + + ret = rtc_command(MEM_WRITE, &cmos_year); + if (ret == 0) + ret = rtc_command(MEM_WRITE, &cmos_check); + out: + return ret; +} + + +/* * Read the current RTC time and date, and update xtime. */ static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year) { unsigned char ctrl, yr[2]; struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr }; + int real_year, year_offset; /* * Ensure that the RTC is running. */ rtc_command(RTC_GETCTRL, &ctrl); if (ctrl & 0xc0) { - unsigned char new_ctrl; - - new_ctrl = ctrl & ~0xc0; + unsigned char new_ctrl = ctrl & ~0xc0; - printk("RTC: resetting control %02X -> %02X\n", - ctrl, new_ctrl); + printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n", + ctrl, new_ctrl); rtc_command(RTC_SETCTRL, &new_ctrl); } + if (rtc_command(RTC_GETDATETIME, rtctm) || + rtc_command(MEM_READ, &rtcmem)) + return; + + real_year = yr[0]; + /* - * Acorn machines store the year in - * the static RAM at location 192. + * The RTC year holds the LSB two bits of the current + * year, which should reflect the LSB two bits of the + * CMOS copy of the year. Any difference indicates + * that we have to correct the CMOS version. */ - if (rtc_command(MEM_READ, &rtcmem)) - return; + year_offset = rtctm->year_off - (real_year & 3); + if (year_offset < 0) + /* + * RTC year wrapped. Adjust it appropriately. + */ + year_offset += 4; - if (rtc_command(RTC_GETDATETIME, rtctm)) - return; + *year = real_year + year_offset + yr[1] * 100; - *year = yr[1] * 100 + yr[0]; } static int set_rtc_time(struct rtc_tm *rtctm, unsigned int year) { - unsigned char yr[2], leap, chk; - struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr }; - struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; + unsigned char leap; int ret; leap = (!(year % 4) && (year % 100)) || !(year % 400); - if (rtctm->mon > 12 || rtctm->mday == 0) + if (rtctm->mon > 12 || rtctm->mon == 0 || rtctm->mday == 0) return -EINVAL; if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap))) @@ -102,21 +146,16 @@ if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60) return -EINVAL; - ret = rtc_command(RTC_SETDATETIME, rtctm); - if (ret == 0) { - rtc_command(MEM_READ, &cmos_check); - rtc_command(MEM_READ, &cmos_year); - - chk -= yr[1] + yr[0]; - - yr[1] = year / 100; - yr[0] = year % 100; + /* + * The RTC's own 2-bit year must reflect the least + * significant two bits of the CMOS year. + */ + rtctm->year_off = (year % 100) & 3; - chk += yr[1] + yr[0]; + ret = rtc_command(RTC_SETDATETIME, rtctm); + if (ret == 0) + ret = rtc_update_year(year); - rtc_command(MEM_WRITE, &cmos_year); - rtc_command(MEM_WRITE, &cmos_check); - } return ret; } @@ -166,7 +205,6 @@ break; case RTC_RD_TIME: - memset(&rtctm, 0, sizeof(struct rtc_time)); get_rtc_time(&rtc_raw, &year); rtctm.tm_sec = rtc_raw.secs; rtctm.tm_min = rtc_raw.mins; @@ -188,13 +226,12 @@ rtc_raw.hours = rtctm.tm_hour; rtc_raw.mday = rtctm.tm_mday; rtc_raw.mon = rtctm.tm_mon + 1; - rtc_raw.year_off = 2; year = rtctm.tm_year + 1900; return set_rtc_time(&rtc_raw, year); break; case RTC_EPOCH_READ: - return put_user(rtc_epoch, (unsigned long *)arg); + return put_user(1900, (unsigned long *)arg); } return -EINVAL; diff -uNr linux-2.4.37.9/drivers/acorn/net/ether1.c linux-2.4.37.9-vrs1-5mx2/drivers/acorn/net/ether1.c --- linux-2.4.37.9/drivers/acorn/net/ether1.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/acorn/net/ether1.c Wed May 26 15:51:06 2010 @@ -80,7 +80,7 @@ #define BUS_16 16 #define BUS_8 8 -static const card_ids __init ether1_cids[] = { +static card_ids __initdata ether1_cids[] = { { MANU_ACORN, PROD_ACORN_ETHER1 }, { 0xffff, 0xffff } }; @@ -153,35 +153,35 @@ length -= thislen; __asm__ __volatile__( - "subs %3, %3, #2 - bmi 2f -1: ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bmi 2f - ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bmi 2f - ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bmi 2f - ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bpl 1b -2: adds %3, %3, #1 - ldreqb %0, [%1] - streqb %0, [%2]" +" subs %3, %3, #2 \n" +" bmi 2f \n" +"1: ldr %0, [%1], #2 \n" +" mov %0, %0, lsl #16 \n" +" orr %0, %0, %0, lsr #16 \n" +" str %0, [%2], #4 \n" +" subs %3, %3, #2 \n" +" bmi 2f \n" +" ldr %0, [%1], #2 \n" +" mov %0, %0, lsl #16 \n" +" orr %0, %0, %0, lsr #16 \n" +" str %0, [%2], #4 \n" +" subs %3, %3, #2 \n" +" bmi 2f \n" +" ldr %0, [%1], #2 \n" +" mov %0, %0, lsl #16 \n" +" orr %0, %0, %0, lsr #16 \n" +" str %0, [%2], #4 \n" +" subs %3, %3, #2 \n" +" bmi 2f \n" +" ldr %0, [%1], #2 \n" +" mov %0, %0, lsl #16 \n" +" orr %0, %0, %0, lsr #16 \n" +" str %0, [%2], #4 \n" +" subs %3, %3, #2 \n" +" bpl 1b \n" +"2: adds %3, %3, #1 \n" +" ldreqb %0, [%1] \n" +" streqb %0, [%2] \n" : "=&r" (used), "=&r" (data) : "r" (addr), "r" (thislen), "1" (data)); @@ -215,35 +215,35 @@ length -= thislen; __asm__ __volatile__( - "subs %3, %3, #2 - bmi 2f -1: ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bmi 2f - ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bmi 2f - ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bmi 2f - ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bpl 1b -2: adds %3, %3, #1 - ldreqb %0, [%2] - streqb %0, [%1]" +" subs %3, %3, #2 \n" +" bmi 2f \n" +"1: ldr %0, [%2], #4 \n" +" strb %0, [%1], #1 \n" +" mov %0, %0, lsr #8 \n" +" strb %0, [%1], #1 \n" +" subs %3, %3, #2 \n" +" bmi 2f \n" +" ldr %0, [%2], #4 \n" +" strb %0, [%1], #1 \n" +" mov %0, %0, lsr #8 \n" +" strb %0, [%1], #1 \n" +" subs %3, %3, #2 \n" +" bmi 2f \n" +" ldr %0, [%2], #4 \n" +" strb %0, [%1], #1 \n" +" mov %0, %0, lsr #8 \n" +" strb %0, [%1], #1 \n" +" subs %3, %3, #2 \n" +" bmi 2f \n" +" ldr %0, [%2], #4 \n" +" strb %0, [%1], #1 \n" +" mov %0, %0, lsr #8 \n" +" strb %0, [%1], #1 \n" +" subs %3, %3, #2 \n" +" bpl 1b \n" +"2: adds %3, %3, #1 \n" +" ldreqb %0, [%2] \n" +" streqb %0, [%1] \n" : "=&r" (used), "=&r" (data) : "r" (addr), "r" (thislen), "1" (data)); diff -uNr linux-2.4.37.9/drivers/acorn/net/ether3.c linux-2.4.37.9-vrs1-5mx2/drivers/acorn/net/ether3.c --- linux-2.4.37.9/drivers/acorn/net/ether3.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/acorn/net/ether3.c Wed May 26 15:51:06 2010 @@ -75,7 +75,7 @@ #include "ether3.h" static unsigned int net_debug = NET_DEBUG; -static const card_ids __init ether3_cids[] = { +static card_ids __initdata ether3_cids[] = { { MANU_ANT2, PROD_ANT_ETHER3 }, { MANU_ANT, PROD_ANT_ETHER3 }, { MANU_ANT, PROD_ANT_ETHERB }, diff -uNr linux-2.4.37.9/drivers/acorn/net/etherh.c linux-2.4.37.9-vrs1-5mx2/drivers/acorn/net/etherh.c --- linux-2.4.37.9/drivers/acorn/net/etherh.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/acorn/net/etherh.c Wed May 26 15:51:06 2010 @@ -57,7 +57,7 @@ static unsigned int net_debug = NET_DEBUG; -static const card_ids __init etherh_cids[] = { +static card_ids __initdata etherh_cids[] = { { MANU_ANT, PROD_ANT_ETHERM }, { MANU_I3, PROD_I3_ETHERLAN500 }, { MANU_I3, PROD_I3_ETHERLAN600 }, diff -uNr linux-2.4.37.9/drivers/acorn/scsi/cumana_1.c linux-2.4.37.9-vrs1-5mx2/drivers/acorn/scsi/cumana_1.c --- linux-2.4.37.9/drivers/acorn/scsi/cumana_1.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/acorn/scsi/cumana_1.c Wed May 26 15:51:06 2010 @@ -153,20 +153,20 @@ ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; outb(0x00, instance->io_port - 577); - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) { printk("scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } - if (instance->irq == IRQ_NONE) { + if (instance->irq == SCSI_IRQ_NONE) { printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no); printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no); } printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk ("s disabled"); else printk (" %d", instance->irq); @@ -185,7 +185,7 @@ { int i; - if (shpnt->irq != IRQ_NONE) + if (shpnt->irq != SCSI_IRQ_NONE) free_irq (shpnt->irq, NULL); if (shpnt->io_port) release_region (shpnt->io_port, shpnt->n_io_port); diff -uNr linux-2.4.37.9/drivers/acorn/scsi/ecoscsi.c linux-2.4.37.9-vrs1-5mx2/drivers/acorn/scsi/ecoscsi.c --- linux-2.4.37.9/drivers/acorn/scsi/ecoscsi.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/acorn/scsi/ecoscsi.c Wed May 26 15:51:06 2010 @@ -106,7 +106,7 @@ instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); instance->io_port = 0x80ce8000; instance->n_io_port = 144; - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; if (check_region (instance->io_port, instance->n_io_port)) { scsi_unregister (instance); @@ -130,20 +130,20 @@ return 0; } - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) { printk("scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } - if (instance->irq != IRQ_NONE) { + if (instance->irq != SCSI_IRQ_NONE) { printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no); printk("scsi%d: that the board had an interrupt!\n", instance->host_no); } printk("scsi%d: at port %X irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk ("s disabled"); else printk (" %d", instance->irq); @@ -157,7 +157,7 @@ int ecoscsi_release (struct Scsi_Host *shpnt) { - if (shpnt->irq != IRQ_NONE) + if (shpnt->irq != SCSI_IRQ_NONE) free_irq (shpnt->irq, NULL); if (shpnt->io_port) release_region (shpnt->io_port, shpnt->n_io_port); diff -uNr linux-2.4.37.9/drivers/acorn/scsi/oak.c linux-2.4.37.9-vrs1-5mx2/drivers/acorn/scsi/oak.c --- linux-2.4.37.9/drivers/acorn/scsi/oak.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/acorn/scsi/oak.c Wed May 26 15:51:06 2010 @@ -97,7 +97,7 @@ }; #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0)) -#define OAK_IRQ(card) (IRQ_NONE) +#define OAK_IRQ(card) (SCSI_IRQ_NONE) /* * Function : int oakscsi_detect(Scsi_Host_Template * tpnt) * @@ -136,20 +136,20 @@ instance->n_io_port = 255; request_region (instance->io_port, instance->n_io_port, "Oak SCSI"); - if (instance->irq != IRQ_NONE) + if (instance->irq != SCSI_IRQ_NONE) if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) { printk("scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = IRQ_NONE; + instance->irq = SCSI_IRQ_NONE; } - if (instance->irq != IRQ_NONE) { + if (instance->irq != SCSI_IRQ_NONE) { printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no); printk("scsi%d: that the board had an interrupt!\n", instance->host_no); } printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port); - if (instance->irq == IRQ_NONE) + if (instance->irq == SCSI_IRQ_NONE) printk ("s disabled"); else printk (" %d", instance->irq); @@ -172,7 +172,7 @@ { int i; - if (shpnt->irq != IRQ_NONE) + if (shpnt->irq != SCSI_IRQ_NONE) free_irq (shpnt->irq, NULL); if (shpnt->io_port) release_region (shpnt->io_port, shpnt->n_io_port); diff -uNr linux-2.4.37.9/drivers/at91/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/Makefile --- linux-2.4.37.9/drivers/at91/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/Makefile Wed May 26 15:51:20 2010 @@ -0,0 +1,23 @@ +# +# Makefile for the AT91RM9200-specific Linux kernel device drivers. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (not a .c file). + +O_TARGET := at91drv.o + +subdir-y := serial net watchdog rtc usb i2c spi mtd +subdir-m := $(subdir-y) + +obj-$(CONFIG_SERIAL_AT91) += serial/at91serial.o +obj-$(CONFIG_AT91_ETHER) += net/at91net.o +obj-$(CONFIG_AT91_WATCHDOG) += watchdog/at91wdt.o +obj-$(CONFIG_AT91_RTC) += rtc/at91rtc.o +obj-$(CONFIG_USB) += usb/at91usb.o +obj-$(CONFIG_I2C_AT91) += i2c/at91i2c.o +obj-$(CONFIG_AT91_SPIDEV) += spi/at91spi.o +obj-$(CONFIG_MTD_AT91_DATAFLASH) += spi/at91spi.o mtd/at91mtd.o +obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += mtd/at91mtd.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/i2c/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/i2c/Makefile --- linux-2.4.37.9/drivers/at91/i2c/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/i2c/Makefile Wed May 26 15:51:20 2010 @@ -0,0 +1,15 @@ +# File: drivers/at91/i2c/Makefile +# +# Makefile for the Atmel AT91RM9200 I2C (TWI) device drivers +# + +O_TARGET := at91i2c.o + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_I2C_AT91) += at91_i2c.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/i2c/at91_i2c.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/i2c/at91_i2c.c --- linux-2.4.37.9/drivers/at91/i2c/at91_i2c.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/i2c/at91_i2c.c Wed May 26 15:51:20 2010 @@ -0,0 +1,257 @@ +/* + i2c Support for Atmel's AT91RM9200 Two-Wire Interface + + (c) Rick Bronson + + Borrowed heavily from original work by: + Copyright (c) 2000 Philip Edelbrock + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "at91_i2c.h" + +#define DBG(x...) do {\ + if (debug > 0) \ + printk(KERN_DEBUG "i2c:" x); \ + } while(0) + +int debug = 0; + +static struct at91_i2c_local *at91_i2c_device; + +/* + * Poll the i2c status register until the specified bit is set. + * Returns 0 if timed out (100 msec) + */ +static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) { + int loop_cntr = 10000; + do { + udelay(10); + } while (!(twi->TWI_SR & bit) && (--loop_cntr > 0)); + + return (loop_cntr > 0); +} + +/* + * Generic i2c master transfer entrypoint + */ +static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct at91_i2c_local *device = (struct at91_i2c_local *) adap->data; + AT91PS_TWI twi = (AT91PS_TWI) device->base_addr; + + struct i2c_msg *pmsg; + int length; + unsigned char *buf; + + /* + * i2c_smbus_xfer_emulated() in drivers/i2c/i2c-core.c states: + * "... In the case of writing, we need to use only one message; + * when reading, we need two..." + */ + + pmsg = msgs; /* look at 1st message, it contains the address/command */ + if (num >= 1 && num <= 2) { + DBG("xfer: doing %s %d bytes to 0x%02x - %d messages\n", + pmsg->flags & I2C_M_RD ? "read" : "write", + pmsg->len, pmsg->buf[0], num); + + /* Set the TWI Master Mode Register */ + twi->TWI_MMR = (pmsg->addr << 16) | (pmsg->len << 8) + | ((pmsg + 1)->flags & I2C_M_RD ? AT91C_TWI_MREAD : 0); + + /* Set TWI Internal Address Register with first messages data field */ + if (pmsg->len == 1) + twi->TWI_IADR = pmsg->buf[0]; + else if (pmsg->len == 2) + twi->TWI_IADR = pmsg->buf[0] << 8 | pmsg->buf[1]; + else /* must be 3 */ + twi->TWI_IADR = pmsg->buf[0] << 16 | pmsg->buf[1] << 8 | pmsg->buf[2]; + + /* 1st message contains the address/command */ + if (num > 1) + pmsg++; /* go to real message */ + + length = pmsg->len; + buf = pmsg->buf; + if (length && buf) { /* sanity check */ + if (pmsg->flags & I2C_M_RD) { + twi->TWI_CR = AT91C_TWI_START; + while (length--) { + if (!length) + twi->TWI_CR = AT91C_TWI_STOP; + /* Wait until transfer is finished */ + if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) { + printk(KERN_ERR "at91_i2c: timeout 1\n"); + return 0; + } + *buf++ = twi->TWI_RHR; + } + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { + printk(KERN_ERR "at91_i2c: timeout 2\n"); + return 0; + } + } else { + twi->TWI_CR = AT91C_TWI_START; + while (length--) { + twi->TWI_THR = *buf++; + if (!length) + twi->TWI_CR = AT91C_TWI_STOP; + if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) { + printk(KERN_ERR "at91_i2c: timeout 3\n"); + return 0; + } + } + /* Wait until transfer is finished */ + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { + printk(KERN_ERR "at91_i2c: timeout 4\n"); + return 0; + } + } + } + DBG("transfer complete\n"); + return num; + } + else { + printk(KERN_ERR "at91_i2c: unexpected number of messages: %d\n", num); + return 0; + } +} + +/* + * Return list of supported functionality + */ +static u32 at91_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE + | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA + | I2C_FUNC_SMBUS_BLOCK_DATA; +} + +/* + * Open + */ +static void at91_inc(struct i2c_adapter *adapter) +{ + MOD_INC_USE_COUNT; +} + +/* + * Close + */ +static void at91_dec(struct i2c_adapter *adapter) +{ + MOD_DEC_USE_COUNT; +} + +/* For now, we only handle combined mode (smbus) */ +static struct i2c_algorithm at91_algorithm = { + name:"at91 i2c", + id:I2C_ALGO_SMBUS, + master_xfer:at91_xfer, + functionality:at91_func, +}; + +/* + * Main initialization routine + */ +static int __init i2c_at91_init(void) +{ + AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI; + struct at91_i2c_local *device; + int rc; + + AT91_CfgPIO_TWI(); + AT91_SYS->PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */ + + twi->TWI_IDR = 0x3ff; /* Disable all interrupts */ + twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */ + twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; /* Set Master mode */ + + /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */ + twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8); + + device = (struct at91_i2c_local *) kmalloc(sizeof(struct at91_i2c_local), GFP_KERNEL); + if (device == NULL) { + printk(KERN_ERR "at91_i2c: can't allocate inteface!\n"); + return -ENOMEM; + } + memset(device, 0, sizeof(struct at91_i2c_local)); + at91_i2c_device = device; + + sprintf(device->adapter.name, "AT91RM9200"); + device->adapter.data = (void *) device; + device->adapter.id = I2C_ALGO_SMBUS; + device->adapter.algo = &at91_algorithm; + device->adapter.algo_data = NULL; + device->adapter.inc_use = at91_inc; + device->adapter.dec_use = at91_dec; + device->adapter.client_register = NULL; + device->adapter.client_unregister = NULL; + device->base_addr = AT91C_VA_BASE_TWI; + + rc = i2c_add_adapter(&device->adapter); + if (rc) { + printk(KERN_ERR "at91_i2c: Adapter %s registration failed\n", device->adapter.name); + device->adapter.data = NULL; + kfree(device); + } + else + printk(KERN_INFO "Found AT91 i2c\n"); + return rc; +} + +/* + * Clean up routine + */ +static void __exit i2c_at91_cleanup(void) +{ + struct at91_i2c_local *device = at91_i2c_device; + int rc; + + rc = i2c_del_adapter(&device->adapter); + device->adapter.data = NULL; + kfree(device); + + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_TWI; /* disable peripheral clock */ + + /* We aren't that prepared to deal with this... */ + if (rc) + printk(KERN_ERR "at91_i2c: i2c_del_adapter failed (%i), that's bad!\n", rc); +} + +module_init(i2c_at91_init); +module_exit(i2c_at91_cleanup); + +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("I2C driver for Atmel AT91RM9200"); +MODULE_LICENSE("GPL"); +MODULE_PARM(debug, "i"); + +EXPORT_NO_SYMBOLS; diff -uNr linux-2.4.37.9/drivers/at91/i2c/at91_i2c.h linux-2.4.37.9-vrs1-5mx2/drivers/at91/i2c/at91_i2c.h --- linux-2.4.37.9/drivers/at91/i2c/at91_i2c.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/i2c/at91_i2c.h Wed May 26 15:51:20 2010 @@ -0,0 +1,43 @@ +/* + i2c Support for Atmel's AT91RM9200 Two-Wire Interface + + (c) Rick Bronson + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef AT91_I2C_H +#define AT91_I2C_H + +#define AT91C_TWI_CLOCK 100000 +#define AT91C_TWI_SCLOCK (10 * AT91C_MASTER_CLOCK / AT91C_TWI_CLOCK) +#define AT91C_TWI_CKDIV1 (2 << 16) /* TWI clock divider. NOTE: see Errata #22 */ + +#if (AT91C_TWI_SCLOCK % 10) >= 5 +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 5) +#else +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 6) +#endif +#define AT91C_TWI_CLDIV3 ((AT91C_TWI_CLDIV2 + (4 - AT91C_TWI_CLDIV2 % 4)) >> 2) + +#define AT91C_EEPROM_I2C_ADDRESS (0x50 << 16) + +/* Physical interface */ +struct at91_i2c_local { + struct i2c_adapter adapter; + unsigned long base_addr; +}; + +#endif diff -uNr linux-2.4.37.9/drivers/at91/mtd/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/Makefile --- linux-2.4.37.9/drivers/at91/mtd/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/Makefile Wed May 26 15:51:19 2010 @@ -0,0 +1,19 @@ +# File: drivers/at91/mtd/Makefile +# +# Makefile for the Atmel AT91RM9200 MTD devices. +# Includes: NAND flash (SmartMedia) & DataFlash +# + +O_TARGET := at91mtd.o + +export-objs := + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_MTD_AT91_DATAFLASH) += at91_dataflash.o +obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += at91_nand.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/mtd/at91_dataflash.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_dataflash.c --- linux-2.4.37.9/drivers/at91/mtd/at91_dataflash.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_dataflash.c Wed May 26 15:51:19 2010 @@ -0,0 +1,540 @@ +/* + * Atmel DataFlash driver for Atmel AT91RM9200 (Thunder) + * + * (c) SAN People (Pty) Ltd + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include "at91_dataflash.h" +#include "../spi/at91_spi.h" + +#undef DEBUG_DATAFLASH + +/* Detected DataFlash devices */ +static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES]; +static int nr_devices = 0; + +/* ......................................................................... */ + +#ifdef CONFIG_MTD_PARTITIONS + +static struct mtd_partition *mtd_parts = 0; +static int mtd_parts_nr = 0; + +#define NB_OF(x) (sizeof(x)/sizeof(x[0])) + +static struct mtd_partition static_partitions[] = +{ + { + name: "bootloader", + offset: 0, + size: 64 * 1024, /* 64 Kb */ + mask_flags: MTD_WRITEABLE /* read-only */ + }, + { + name: "kernel", + offset: MTDPART_OFS_NXTBLK, + size: 768 *1024, /* 768 Kb */ + }, + { + name: "filesystem", + offset: MTDPART_OFS_NXTBLK, + size: MTDPART_SIZ_FULL, + } +}; + +int parse_cmdline_partitions(struct mtd_info *master, + struct mtd_partition **pparts, const char *mtd_id); + +#endif + +/* ......................................................................... */ + +/* Allocate a single SPI transfer descriptor. We're assuming that if multiple + SPI transfers occur at the same time, spi_access_bus() will serialize them. + If this is not valid, then either (i) each dataflash 'priv' structure + needs it's own transfer descriptor, (ii) we lock this one, or (iii) use + another mechanism. */ +static struct spi_transfer_list* spi_transfer_desc; + +/* + * Perform a SPI transfer to access the DataFlash device. + */ +static int do_spi_transfer(int nr, char* tx, int tx_len, char* rx, int rx_len, + char* txnext, int txnext_len, char* rxnext, int rxnext_len) +{ + struct spi_transfer_list* list = spi_transfer_desc; + + list->tx[0] = tx; list->txlen[0] = tx_len; + list->rx[0] = rx; list->rxlen[0] = rx_len; + + list->tx[1] = txnext; list->txlen[1] = txnext_len; + list->rx[1] = rxnext; list->rxlen[1] = rxnext_len; + + list->nr_transfers = nr; + + return spi_transfer(list); +} + +/* ......................................................................... */ + +/* + * Poll the DataFlash device until it is READY. + */ +static void at91_dataflash_waitready(void) +{ + char* command = kmalloc(2, GFP_KERNEL); + + if (!command) + return; + + do { + command[0] = OP_READ_STATUS; + command[1] = 0; + + do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0); + } while ((command[1] & 0x80) == 0); + + kfree(command); +} + +/* + * Return the status of the DataFlash device. + */ +static unsigned short at91_dataflash_status(void) +{ + unsigned short status; + char* command = kmalloc(2, GFP_KERNEL); + + if (!command) + return 0; + + command[0] = OP_READ_STATUS; + command[1] = 0; + + do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0); + status = command[1]; + + kfree(command); + return status; +} + +/* ......................................................................... */ + +/* + * Erase blocks of flash. + */ +static int at91_dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv; + unsigned int pageaddr; + char* command; + +#ifdef DEBUG_DATAFLASH + printk("dataflash_erase: addr=%i len=%i\n", instr->addr, instr->len); +#endif + + /* Sanity checks */ + if (instr->addr + instr->len > mtd->size) + return -EINVAL; + if ((instr->len % mtd->erasesize != 0) || (instr->len % priv->page_size != 0)) + return -EINVAL; + if ((instr->addr % priv->page_size) != 0) + return -EINVAL; + + command = kmalloc(4, GFP_KERNEL); + if (!command) + return -ENOMEM; + + while (instr->len > 0) { + /* Calculate flash page address */ + pageaddr = (instr->addr / priv->page_size) << priv->page_offset; + + command[0] = OP_ERASE_PAGE; + command[1] = (pageaddr & 0x00FF0000) >> 16; + command[2] = (pageaddr & 0x0000FF00) >> 8; + command[3] = 0; +#ifdef DEBUG_DATAFLASH + printk("ERASE: (%x) %x %x %x [%i]\n", command[0], command[1], command[2], command[3], pageaddr); +#endif + + /* Send command to SPI device */ + spi_access_bus(priv->spi); + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0); + + at91_dataflash_waitready(); /* poll status until ready */ + spi_release_bus(priv->spi); + + instr->addr += priv->page_size; /* next page */ + instr->len -= priv->page_size; + } + + kfree(command); + + /* Inform MTD subsystem that erase is complete */ + instr->state = MTD_ERASE_DONE; + if (instr->callback) + instr->callback(instr); + + return 0; +} + +/* + * Read from the DataFlash device. + * from : Start offset in flash device + * len : Amount to read + * retlen : About of data actually read + * buf : Buffer containing the data + */ +static int at91_dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv; + unsigned int addr; + char* command; + +#ifdef DEBUG_DATAFLASH + printk("dataflash_read: %lli .. %lli\n", from, from+len); +#endif + + *retlen = 0; + + /* Sanity checks */ + if (!len) + return 0; + if (from + len > mtd->size) + return -EINVAL; + + /* Calculate flash page/byte address */ + addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size); + + command = kmalloc(8, GFP_KERNEL); + if (!command) + return -ENOMEM; + + command[0] = OP_READ_CONTINUOUS; + command[1] = (addr & 0x00FF0000) >> 16; + command[2] = (addr & 0x0000FF00) >> 8; + command[3] = (addr & 0x000000FF); +#ifdef DEBUG_DATAFLASH + printk("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); +#endif + + /* Send command to SPI device */ + spi_access_bus(priv->spi); + do_spi_transfer(2, command, 8, command, 8, buf, len, buf, len); + spi_release_bus(priv->spi); + + *retlen = len; + kfree(command); + return 0; +} + +/* + * Write to the DataFlash device. + * to : Start offset in flash device + * len : Amount to write + * retlen : Amount of data actually written + * buf : Buffer containing the data + */ +static int at91_dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv; + unsigned int pageaddr, addr, offset, writelen; + size_t remaining; + u_char *writebuf; + unsigned short status; + int res = 0; + char* command; + char* tmpbuf = NULL; + +#ifdef DEBUG_DATAFLASH + printk("dataflash_write: %lli .. %lli\n", to, to+len); +#endif + + *retlen = 0; + + /* Sanity checks */ + if (!len) + return 0; + if (to + len > mtd->size) + return -EINVAL; + + command = kmalloc(4, GFP_KERNEL); + if (!command) + return -ENOMEM; + + pageaddr = ((unsigned)to / priv->page_size); + offset = ((unsigned)to % priv->page_size); + if (offset + len > priv->page_size) + writelen = priv->page_size - offset; + else + writelen = len; + writebuf = buf; + remaining = len; + + /* Allocate temporary buffer */ + tmpbuf = kmalloc(priv->page_size, GFP_KERNEL); + if (!tmpbuf) { + kfree(command); + return -ENOMEM; + } + + /* Gain access to the SPI bus */ + spi_access_bus(priv->spi); + + while (remaining > 0) { +#ifdef DEBUG_DATAFLASH + printk("write @ %i:%i len=%i\n", pageaddr, offset, writelen); +#endif + + /* (1) Transfer to Buffer1 */ + if (writelen != priv->page_size) { + addr = pageaddr << priv->page_offset; + command[0] = OP_TRANSFER_BUF1; + command[1] = (addr & 0x00FF0000) >> 16; + command[2] = (addr & 0x0000FF00) >> 8; + command[3] = 0; +#ifdef DEBUG_DATAFLASH + printk("TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); +#endif + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0); + at91_dataflash_waitready(); + } + + /* (2) Program via Buffer1 */ + addr = (pageaddr << priv->page_offset) + offset; + command[0] = OP_PROGRAM_VIA_BUF1; + command[1] = (addr & 0x00FF0000) >> 16; + command[2] = (addr & 0x0000FF00) >> 8; + command[3] = (addr & 0x000000FF); +#ifdef DEBUG_DATAFLASH + printk("PROGRAM: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); +#endif + do_spi_transfer(2, command, 4, command, 4, writebuf, writelen, tmpbuf, writelen); + at91_dataflash_waitready(); + + /* (3) Compare to Buffer1 */ + addr = pageaddr << priv->page_offset; + command[0] = OP_COMPARE_BUF1; + command[1] = (addr & 0x00FF0000) >> 16; + command[2] = (addr & 0x0000FF00) >> 8; + command[3] = 0; +#ifdef DEBUG_DATAFLASH + printk("COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); +#endif + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0); + at91_dataflash_waitready(); + + /* Get result of the compare operation */ + status = at91_dataflash_status(); + if ((status & 0x40) == 1) { + printk("at91_dataflash: Write error on page %i\n", pageaddr); + remaining = 0; + res = -EIO; + } + + remaining = remaining - writelen; + pageaddr++; + offset = 0; + writebuf += writelen; + *retlen += writelen; + + if (remaining > priv->page_size) + writelen = priv->page_size; + else + writelen = remaining; + } + + /* Release SPI bus */ + spi_release_bus(priv->spi); + + kfree(tmpbuf); + kfree(command); + return res; +} + +/* ......................................................................... */ + +/* + * Initialize and register DataFlash device with MTD subsystem. + */ +static int add_dataflash(int channel, char *name, int IDsize, int nr_pages, int pagesize, int pageoffset) +{ + struct mtd_info *device; + struct dataflash_local *priv; +#ifdef CONFIG_MTD_CMDLINE_PARTS + char mtdID[14]; +#endif + + if (nr_devices >= DATAFLASH_MAX_DEVICES) { + printk(KERN_ERR "at91_dataflash: Too many devices detected\n"); + return 0; + } + + device = (struct mtd_info *) kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (!device) + return -ENOMEM; + memset(device, 0, sizeof(struct mtd_info)); + + device->name = name; + device->size = nr_pages * pagesize; + device->erasesize = pagesize; + device->module = THIS_MODULE; + device->type = MTD_NORFLASH; + device->flags = MTD_CAP_NORFLASH; + device->erase = at91_dataflash_erase; + device->read = at91_dataflash_read; + device->write = at91_dataflash_write; + + priv = (struct dataflash_local *) kmalloc(sizeof(struct dataflash_local), GFP_KERNEL); + if (!priv) { + kfree(device); + return -ENOMEM; + } + memset(priv, 0, sizeof(struct dataflash_local)); + + priv->spi = channel; + priv->page_size = pagesize; + priv->page_offset = pageoffset; + device->priv = priv; + + mtd_devices[nr_devices] = device; + nr_devices++; + printk("at91_dataflash: %s detected [spi%i] (%i bytes)\n", name, channel, device->size); + +#ifdef CONFIG_MTD_PARTITIONS +#ifdef CONFIG_MTD_CMDLINE_PARTS + sprintf(mtdID, "dataflash%i", nr_devices-1); + mtd_parts_nr = parse_cmdline_partitions(device, &mtd_parts, mtdID); +#endif + if (mtd_parts_nr <= 0) { + mtd_parts = static_partitions; + mtd_parts_nr = NB_OF(static_partitions); + } + + if (mtd_parts_nr > 0) { +#ifdef DATAFLASH_ALWAYS_ADD_DEVICE + add_mtd_device(device); +#endif + return add_mtd_partitions(device, mtd_parts, mtd_parts_nr); + } +#endif + return add_mtd_device(device); /* add whole device */ +} + +/* + * Detect and initialize DataFlash device connected to specified SPI channel. + * + * Device Density ID code Nr Pages Page Size Page offset + * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 + * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9 + * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 + * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 + * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 + * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 + * AT45DB0642 64Mbit (8M) xx1111xx (0x3c) 8192 1056 11 + * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 + */ +static int at91_dataflash_detect(int channel) +{ + int res = 0; + unsigned short status; + + spi_access_bus(channel); + status = at91_dataflash_status(); + if (status != 0xff) { /* no dataflash device there */ + switch (status & 0x3c) { + case 0x0c: /* 0 0 1 1 */ + res = add_dataflash(channel, "Atmel AT45DB011B", SZ_128K, 512, 264, 9); + break; + case 0x14: /* 0 1 0 1 */ + res = add_dataflash(channel, "Atmel AT45DB021B", SZ_256K, 1025, 264, 9); + break; + case 0x1c: /* 0 1 1 1 */ + res = add_dataflash(channel, "Atmel AT45DB041B", SZ_512K, 2048, 264, 9); + break; + case 0x24: /* 1 0 0 1 */ + res = add_dataflash(channel, "Atmel AT45DB081B", SZ_1M, 4096, 264, 9); + break; + case 0x2c: /* 1 0 1 1 */ + res = add_dataflash(channel, "Atmel AT45DB161B", SZ_2M, 4096, 528, 10); + break; + case 0x34: /* 1 1 0 1 */ + res = add_dataflash(channel, "Atmel AT45DB321B", SZ_4M, 8192, 528, 10); + break; + case 0x3c: /* 1 1 1 1 */ + res = add_dataflash(channel, "Atmel AT45DB642", SZ_8M, 8192, 1056, 11); + break; +// Currently unsupported since Atmel removed the "Main Memory Program via Buffer" commands. +// case 0x10: /* 0 1 0 0 */ +// res = add_dataflash(channel, "Atmel AT45DB1282", SZ_16M, 16384, 1056, 11); +// break; + default: + printk(KERN_ERR "at91_dataflash: Unknown device (%x)\n", status & 0x3c); + } + } + spi_release_bus(channel); + + return res; +} + +static int __init at91_dataflash_init(void) +{ + spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL); + if (!spi_transfer_desc) + return -ENOMEM; + + /* DataFlash (SPI chip select 0) */ + at91_dataflash_detect(0); + +#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD + /* DataFlash card (SPI chip select 3) */ + AT91_CfgPIO_DataFlashCard(); + at91_dataflash_detect(3); +#endif + + return 0; +} + +static void __exit at91_dataflash_exit(void) +{ + int i; + + for (i = 0; i < DATAFLASH_MAX_DEVICES; i++) { + if (mtd_devices[i]) { +#ifdef CONFIG_MTD_PARTITIONS + del_mtd_partitions(mtd_devices[i]); +#else + del_mtd_device(mtd_devices[i]); +#endif + kfree(mtd_devices[i]->priv); + kfree(mtd_devices[i]); + } + } + nr_devices = 0; + kfree(spi_transfer_desc); +} + + +EXPORT_NO_SYMBOLS; + +module_init(at91_dataflash_init); +module_exit(at91_dataflash_exit); + +MODULE_LICENSE("GPL") +MODULE_AUTHOR("Andrew Victor") +MODULE_DESCRIPTION("DataFlash driver for Atmel AT91RM9200") diff -uNr linux-2.4.37.9/drivers/at91/mtd/at91_dataflash.h linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_dataflash.h --- linux-2.4.37.9/drivers/at91/mtd/at91_dataflash.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_dataflash.h Wed May 26 15:51:19 2010 @@ -0,0 +1,43 @@ +/* + * Atmel DataFlash driver for the Atmel AT91RM9200 (Thunder) + * + * (c) SAN People (Pty) Ltd + * + * 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. + */ + +#ifndef AT91_DATAFLASH_H +#define AT91_DATAFLASH_H + +#define DATAFLASH_MAX_DEVICES 4 /* max number of dataflash devices */ +#undef DATAFLASH_ALWAYS_ADD_DEVICE /* always add whole device when using partitions? */ + +#define OP_READ_CONTINUOUS 0xE8 +#define OP_READ_PAGE 0xD2 +#define OP_READ_BUFFER1 0xD4 +#define OP_READ_BUFFER2 0xD6 +#define OP_READ_STATUS 0xD7 + +#define OP_ERASE_PAGE 0x81 +#define OP_ERASE_BLOCK 0x50 + +#define OP_TRANSFER_BUF1 0x53 +#define OP_TRANSFER_BUF2 0x55 +#define OP_COMPARE_BUF1 0x60 +#define OP_COMPARE_BUF2 0x61 + +#define OP_PROGRAM_VIA_BUF1 0x82 +#define OP_PROGRAM_VIA_BUF2 0x85 + +struct dataflash_local +{ + int spi; /* SPI chip-select number */ + + unsigned int page_size; /* number of bytes per page */ + unsigned short page_offset; /* page offset in flash address */ +}; + +#endif diff -uNr linux-2.4.37.9/drivers/at91/mtd/at91_nand.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_nand.c --- linux-2.4.37.9/drivers/at91/mtd/at91_nand.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_nand.c Wed May 26 15:51:19 2010 @@ -0,0 +1,328 @@ +/* + * drivers/at91/mtd/at91_nand.c + * + * Copyright (c) 2003 Rick Bronson + * + * Derived from drivers/mtd/nand/autcpu12.c + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) + * + * Derived from drivers/mtd/spia.c + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include "at91_nand.h" + +/* + * MTD structure for AT91 board + */ +static struct mtd_info *at91_mtd = NULL; +static struct nand_chip *my_nand_chip = NULL; + +static int at91_fio_base; + +#ifdef CONFIG_MTD_PARTITIONS + +/* + * Define partitions for flash devices + */ + +static struct mtd_partition partition_info32k[] = { + { name: "AT91 NAND partition 1, kernel", + offset: 0, + size: 1 * SZ_1M }, + { name: "AT91 NAND partition 2, filesystem", + offset: 1 * SZ_1M, + size: 16 * SZ_1M }, + { name: "AT91 NAND partition 3a, storage", + offset: (1 * SZ_1M) + (16 * SZ_1M), + size: 1 * SZ_1M }, + { name: "AT91 NAND partition 3b, storage", + offset: (2 * SZ_1M) + (16 * SZ_1M), + size: 1 * SZ_1M }, + { name: "AT91 NAND partition 3c, storage", + offset: (3 * SZ_1M) + (16 * SZ_1M), + size: 1 * SZ_1M }, + { name: "AT91 NAND partition 3d, storage", + offset: (4 * SZ_1M) + (16 * SZ_1M), + size: 1 * SZ_1M }, +}; + +static struct mtd_partition partition_info64k[] = { + { name: "AT91 NAND partition 1, kernel", + offset: 0, + size: 1 * SZ_1M }, + { name: "AT91 NAND partition 2, filesystem", + offset: 1 * SZ_1M, + size: 16 * SZ_1M }, + { name: "AT91 NAND partition 3, storage", + offset: (1 * SZ_1M) + (16 * SZ_1M), + size: 47 * SZ_1M }, +}; + +#endif + +/* + * Hardware specific access to control-lines + */ +static void at91_hwcontrol(int cmd) +{ + struct nand_chip *my_nand = my_nand_chip; + switch(cmd) + { + case NAND_CTL_SETCLE: + my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_CLE; + break; + case NAND_CTL_CLRCLE: + my_nand->IO_ADDR_W = at91_fio_base; + break; + case NAND_CTL_SETALE: + my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_ALE; + break; + case NAND_CTL_CLRALE: + my_nand->IO_ADDR_W = at91_fio_base; + break; + case NAND_CTL_SETNCE: + break; + case NAND_CTL_CLRNCE: + break; + } +} + +/* + * Send command to NAND device + */ +static void at91_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) +{ + register struct nand_chip *my_nand = mtd->priv; + + /* Begin command latch cycle */ + register unsigned long NAND_IO_ADDR = my_nand->IO_ADDR_W + AT91_SMART_MEDIA_CLE; + + /* + * Write out the command to the device. + */ + if (command != NAND_CMD_SEQIN) + writeb (command, NAND_IO_ADDR); + else { + if (mtd->oobblock == 256 && column >= 256) { + column -= 256; + writeb (NAND_CMD_RESET, NAND_IO_ADDR); + writeb (NAND_CMD_READOOB, NAND_IO_ADDR); + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); + } + else + if (mtd->oobblock == 512 && column >= 256) { + if (column < 512) { + column -= 256; + writeb (NAND_CMD_READ1, NAND_IO_ADDR); + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); + } else { + column -= 512; + writeb (NAND_CMD_READOOB, NAND_IO_ADDR); + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); + } + } else { + writeb (NAND_CMD_READ0, NAND_IO_ADDR); + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR); + } + } + + /* Set ALE and clear CLE to start address cycle */ + NAND_IO_ADDR = at91_fio_base; + + if (column != -1 || page_addr != -1) + NAND_IO_ADDR += AT91_SMART_MEDIA_ALE; + + /* Serially input address */ + if (column != -1) + writeb (column, NAND_IO_ADDR); + if (page_addr != -1) { + writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR); + writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR); + /* One more address cycle for higher density devices */ + if (mtd->size & 0x0c000000) { + writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR); + } + } + + /* wait until command is processed */ + while (!my_nand->dev_ready()) + ; +} + +/* + * Read the Device Ready pin. + */ +static int at91_device_ready(void) +{ + return AT91_PIO_SmartMedia_RDY(); +} +/* + * Main initialization routine + */ +static int __init at91_init (void) +{ + struct nand_chip *my_nand; + int err = 0; + + /* Allocate memory for MTD device structure and private data */ + at91_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); + if (!at91_mtd) { + printk ("Unable to allocate AT91 NAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + /* map physical adress */ + at91_fio_base = (unsigned long) ioremap(AT91_SMARTMEDIA_BASE, SZ_8M); + if(!at91_fio_base) { + printk("ioremap AT91 NAND failed\n"); + err = -EIO; + goto out_mtd; + } + + /* Get pointer to private data */ + my_nand_chip = my_nand = (struct nand_chip *) (&at91_mtd[1]); + + /* Initialize structures */ + memset((char *) at91_mtd, 0, sizeof(struct mtd_info)); + memset((char *) my_nand, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + at91_mtd->priv = my_nand; + + /* Set address of NAND IO lines */ + my_nand->IO_ADDR_R = at91_fio_base; + my_nand->IO_ADDR_W = at91_fio_base; + my_nand->hwcontrol = at91_hwcontrol; + my_nand->dev_ready = at91_device_ready; + my_nand->cmdfunc = at91_nand_command; /* we need our own */ + my_nand->eccmode = NAND_ECC_SOFT; /* enable ECC */ + /* 20 us command delay time */ + my_nand->chip_delay = 20; + + /* Setup Smart Media, first enable the address range of CS3 */ + AT91_SYS->EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia; + /* set the bus interface characteristics based on + tDS Data Set up Time 30 - ns + tDH Data Hold Time 20 - ns + tALS ALE Set up Time 20 - ns + 16ns at 60 MHz ~= 3 */ +#define AT91C_SM_ID_RWH (5 << 28) /* orig = 5 */ +#define AT91C_SM_RWH (1 << 28) /* orig = 1 */ +#define AT91C_SM_RWS (0 << 24) /* orig = 0 */ +#define AT91C_SM_TDF (1 << 8) /* orig = 1 */ +#define AT91C_SM_NWS (5) /* orig = 3 */ + AT91_SYS->EBI_SMC2_CSR[3] = ( AT91C_SM_RWH | AT91C_SM_RWS | + AT91C_SMC2_ACSS_STANDARD | + AT91C_SMC2_DBW_8 | AT91C_SM_TDF | + AT91C_SMC2_WSEN | AT91C_SM_NWS); + + AT91_CfgPIO_SmartMedia(); + + if (AT91_PIO_SmartMedia_CardDetect()) + printk ("No "); + printk ("SmartMedia card inserted.\n"); + + /* Scan to find existance of the device */ + if (nand_scan (at91_mtd)) { + err = -ENXIO; + goto out_ior; + } + + /* Allocate memory for internal data buffer */ + my_nand->data_buf = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL); + if (!my_nand->data_buf) { + printk ("Unable to allocate AT91 NAND data buffer.\n"); + err = -ENOMEM; + goto out_ior; + } + + /* Allocate memory for internal data buffer */ + my_nand->data_cache = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL); + if (!my_nand->data_cache) { + printk ("Unable to allocate AT91 NAND data cache.\n"); + err = -ENOMEM; + goto out_buf; + } + my_nand->cache_page = -1; + +#ifdef CONFIG_MTD_PARTITIONS + /* Register the partitions */ + switch(at91_mtd->size) + { + case SZ_32M: + err = add_mtd_partitions(at91_mtd, partition_info32k, + ARRAY_SIZE (partition_info32k)); + break; + case SZ_64M: + err = add_mtd_partitions(at91_mtd, partition_info64k, + ARRAY_SIZE (partition_info64k)); + break; + default: + printk ("Unsupported SmartMedia device\n"); + err = -ENXIO; + goto out_cac; + } +#else + err = add_mtd_device(at91_mtd); +#endif + goto out; + + out_cac: + kfree (my_nand->data_cache); + out_buf: + kfree (my_nand->data_buf); + out_ior: + iounmap((void *)at91_fio_base); + out_mtd: + kfree (at91_mtd); + out: + return err; +} + +/* + * Clean up routine + */ +static void __exit at91_cleanup (void) +{ + struct nand_chip *my_nand = (struct nand_chip *) &at91_mtd[1]; + + /* Unregister partitions */ + del_mtd_partitions(at91_mtd); + + /* Unregister the device */ + del_mtd_device (at91_mtd); + + /* Free internal data buffers */ + kfree (my_nand->data_buf); + kfree (my_nand->data_cache); + + /* unmap physical adress */ + iounmap((void *)at91_fio_base); + + /* Free the MTD device structure */ + kfree (at91_mtd); +} + +module_init(at91_init); +module_exit(at91_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("Glue layer for SmartMediaCard on ATMEL AT91RM9200"); diff -uNr linux-2.4.37.9/drivers/at91/mtd/at91_nand.h linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_nand.h --- linux-2.4.37.9/drivers/at91/mtd/at91_nand.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/mtd/at91_nand.h Wed May 26 15:51:19 2010 @@ -0,0 +1,27 @@ +/* + * AT91RM9200 specific NAND (SmartMedia) defines + * + * (c) 2003 Rick Bronson + * + * 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 + */ + +#ifndef __AT91_NAND_H +#define __AT91_NAND_H + +#define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */ +#define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */ + +#endif diff -uNr linux-2.4.37.9/drivers/at91/net/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/net/Makefile --- linux-2.4.37.9/drivers/at91/net/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/net/Makefile Wed May 26 15:51:19 2010 @@ -0,0 +1,15 @@ +# File: drivers/at91/net/Makefile +# +# Makefile for the Atmel AT91RM9200 ethernet device drivers +# + +O_TARGET := at91net.o + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_AT91_ETHER) += at91_ether.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/net/at91_ether.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/net/at91_ether.c --- linux-2.4.37.9/drivers/at91/net/at91_ether.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/net/at91_ether.c Wed May 26 15:51:19 2010 @@ -0,0 +1,875 @@ +/* + * Ethernet driver for the Atmel AT91RM9200 (Thunder) + * + * (c) SAN People (Pty) Ltd + * + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. + * Initial version by Rick Bronson 01/11/2003 + * + * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker + * (Polaroid Corporation) + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "at91_ether.h" + +static struct net_device at91_dev; + +/* ........................... PHY INTERFACE ........................... */ + +/* + * Enable the MDIO bit in MAC control register + * When not called from an interrupt-handler, access to the PHY must be + * protected by a spinlock. + */ +static void enable_mdi(AT91PS_EMAC regs) +{ + regs->EMAC_CTL |= AT91C_EMAC_MPE; /* enable management port */ +} + +/* + * Disable the MDIO bit in the MAC control register + */ +static void disable_mdi(AT91PS_EMAC regs) +{ + regs->EMAC_CTL &= ~AT91C_EMAC_MPE; /* disable management port */ +} + +/* + * Write value to the a PHY register + * Note: MDI interface is assumed to already have been enabled. + */ +static void write_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int value) +{ + regs->EMAC_MAN = (AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W + | ((phy_addr & 0x1f) << 23) | (address << 18)) + (value & 0xffff); + + /* Wait until IDLE bit in Network Status register is cleared */ + // TODO: Enforce some maximum loop-count? + while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); } +} + +/* + * Read value stored in a PHY register. + * Note: MDI interface is assumed to already have been enabled. + */ +static void read_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int *value) +{ + regs->EMAC_MAN = AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_R + | ((phy_addr & 0x1f) << 23) | (address << 18); + + /* Wait until IDLE bit in Network Status register is cleared */ + // TODO: Enforce some maximum loop-count? + while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); } + + *value = (regs->EMAC_MAN & 0x0000ffff); +} + +/* ........................... PHY MANAGEMENT .......................... */ + +/* + * Access the PHY to determine the current Link speed and Mode, and update the + * MAC accordingly. + * If no link or auto-negotiation is busy, then no changes are made. + * Returns: 0 : OK + * -1 : No link + * -2 : AutoNegotiation still in progress + */ +static int update_linkspeed(struct net_device *dev, AT91PS_EMAC regs) { + unsigned int bmsr, bmcr, lpa, mac_cfg; + unsigned int speed, duplex; + + /* Link status is latched, so read twice to get current value */ + read_phy(regs, 0, MII_BMSR, &bmsr); + read_phy(regs, 0, MII_BMSR, &bmsr); + if (!(bmsr & BMSR_LSTATUS)) return -1; /* no link */ + + read_phy(regs, 0, MII_BMCR, &bmcr); + if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ + if (!(bmsr & BMSR_ANEGCOMPLETE)) return -2; /* auto-negotitation in progress */ + + read_phy(regs, 0, MII_LPA, &lpa); + if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; + else speed = SPEED_10; + if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; + else duplex = DUPLEX_HALF; + } else { + speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; + duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; + } + + /* Update the MAC */ + mac_cfg = regs->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); + if (speed == SPEED_100) { + if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD | AT91C_EMAC_FD; + else /* 100 Half Duplex */ + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD; + } else { + if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_FD; + else /* 10 Half Duplex */ + regs->EMAC_CFG = mac_cfg; + } + + printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); + return 0; +} + +/* + * Handle interrupts from the PHY + */ +static void at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + struct at91_private *lp = (struct at91_private *) dev->priv; + AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr; + int status; + unsigned int phy; + + enable_mdi(emac); + if (lp->phy_type == MII_DM9161_ID) + read_phy(emac, 0, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */ + else if (lp->phy_type == MII_LXT971A_ID) + read_phy(emac, 0, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */ + + status = AT91_SYS->PIOC_ISR; /* acknowledge interrupt in PIO */ + + status = update_linkspeed(dev, emac); + if (status == -1) { /* link is down */ + netif_carrier_off(dev); + printk(KERN_INFO "%s: Link down.\n", dev->name); + } else if (status == -2) { /* auto-negotiation in progress */ + /* Do nothing - another interrupt generated when negotiation complete */ + } else { /* link is operational */ + netif_carrier_on(dev); + } + disable_mdi(emac); +} + +/* + * Initialize and enable the PHY interrupt when link-state changes + */ +static void enable_phyirq(struct net_device *dev, AT91PS_EMAC regs) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int dsintr, status; + + // TODO: Check error code. Really need a generic PIO (interrupt) + // layer since we're really only interested in the PC4 (DK) or PC2 (CSB337) line. + (void) request_irq(AT91C_ID_PIOC, at91ether_phy_interrupt, 0, dev->name, dev); + + status = AT91_SYS->PIOC_ISR; /* clear any pending PIO interrupts */ +#ifdef CONFIG_MACH_CSB337 + AT91_SYS->PIOC_IER = AT91C_PIO_PC2; /* Enable interrupt */ +#else + AT91_SYS->PIOC_IER = AT91C_PIO_PC4; /* Enable interrupt */ +#endif + + spin_lock_irq(&lp->lock); + enable_mdi(regs); + + if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */ + read_phy(regs, 0, MII_DSINTR_REG, &dsintr); + dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ + write_phy(regs, 0, MII_DSINTR_REG, dsintr); + } + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ + read_phy(regs, 0, MII_ISINTE_REG, &dsintr); + dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */ + write_phy(regs, 0, MII_ISINTE_REG, dsintr); + } + + disable_mdi(regs); + spin_unlock_irq(&lp->lock); +} + +/* + * Disable the PHY interrupt + */ +static void disable_phyirq(struct net_device *dev, AT91PS_EMAC regs) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int dsintr; + + spin_lock_irq(&lp->lock); + enable_mdi(regs); + + if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */ + read_phy(regs, 0, MII_DSINTR_REG, &dsintr); + dsintr = dsintr | 0xf00; /* set bits 8..11 */ + write_phy(regs, 0, MII_DSINTR_REG, dsintr); + } + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ + read_phy(regs, 0, MII_ISINTE_REG, &dsintr); + dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */ + write_phy(regs, 0, MII_ISINTE_REG, dsintr); + } + + disable_mdi(regs); + spin_unlock_irq(&lp->lock); + +#ifdef CONFIG_MACH_CSB337 + AT91_SYS->PIOC_IDR = AT91C_PIO_PC2; /* Disable interrupt */ +#else + AT91_SYS->PIOC_IDR = AT91C_PIO_PC4; /* Disable interrupt */ +#endif + free_irq(AT91C_ID_PIOC, dev); /* Free interrupt handler */ +} + +/* + * Perform a software reset of the PHY. + */ +static void reset_phy(struct net_device *dev, AT91PS_EMAC regs) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int bmcr; + + spin_lock_irq(&lp->lock); + enable_mdi(regs); + + /* Perform PHY reset */ + write_phy(regs, 0, MII_BMCR, BMCR_RESET); + + /* Wait until PHY reset is complete */ + do { + read_phy(regs, 0, MII_BMCR, &bmcr); + } while (!(bmcr && BMCR_RESET)); + + disable_mdi(regs); + spin_unlock_irq(&lp->lock); +} + + +/* ......................... ADDRESS MANAGEMENT ........................ */ + +/* + * Set the ethernet MAC address in dev->dev_addr + */ +static void get_mac_address(struct net_device *dev) { + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + char addr[6]; + unsigned int hi, lo; + + /* Check if bootloader set address in Specific-Address 1 */ + hi = regs->EMAC_SA1H; + lo = regs->EMAC_SA1L; + addr[0] = (lo & 0xff); + addr[1] = (lo & 0xff00) >> 8; + addr[2] = (lo & 0xff0000) >> 16; + addr[3] = (lo & 0xff000000) >> 24; + addr[4] = (hi & 0xff); + addr[5] = (hi & 0xff00) >> 8; + + if (is_valid_ether_addr(addr)) { + memcpy(dev->dev_addr, &addr, 6); + return; + } + + /* Check if bootloader set address in Specific-Address 2 */ + hi = regs->EMAC_SA2H; + lo = regs->EMAC_SA2L; + addr[0] = (lo & 0xff); + addr[1] = (lo & 0xff00) >> 8; + addr[2] = (lo & 0xff0000) >> 16; + addr[3] = (lo & 0xff000000) >> 24; + addr[4] = (hi & 0xff); + addr[5] = (hi & 0xff00) >> 8; + + if (is_valid_ether_addr(addr)) { + memcpy(dev->dev_addr, &addr, 6); + return; + } +} + +/* + * Program the hardware MAC address from dev->dev_addr. + */ +static void update_mac_address(struct net_device *dev) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + + regs->EMAC_SA1L = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]); + regs->EMAC_SA1H = (dev->dev_addr[5] << 8) | (dev->dev_addr[4]); +} + +/* + * Store the new hardware address in dev->dev_addr, and update the MAC. + */ +static int set_mac_address(struct net_device *dev, void* addr) +{ + struct sockaddr *address = addr; + + if (!is_valid_ether_addr(address->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, address->sa_data, dev->addr_len); + update_mac_address(dev); + + printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + + return 0; +} + +/* + * Add multicast addresses to the internal multicast-hash table. + */ +static void at91ether_sethashtable(struct net_device *dev, AT91PS_EMAC regs) +{ + struct dev_mc_list *curr; + unsigned char mc_filter[2]; + unsigned int i, bitnr; + + mc_filter[0] = mc_filter[1] = 0; + + curr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, curr = curr->next) { + if (!curr) break; /* unexpected end of list */ + + bitnr = ether_crc(ETH_ALEN, curr->dmi_addr) >> 26; + mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); + } + + regs->EMAC_HSH = mc_filter[1]; + regs->EMAC_HSL = mc_filter[0]; +} + +/* + * Enable/Disable promiscuous and multicast modes. + */ +static void at91ether_set_rx_mode(struct net_device *dev) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + + if (dev->flags & IFF_PROMISC) { /* Enable promiscuous mode */ + regs->EMAC_CFG |= AT91C_EMAC_CAF; + } else if (dev->flags & (~IFF_PROMISC)) { /* Disable promiscuous mode */ + regs->EMAC_CFG &= ~AT91C_EMAC_CAF; + } + + if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */ + regs->EMAC_HSH = -1; + regs->EMAC_HSL = -1; + regs->EMAC_CFG |= AT91C_EMAC_MTI; + } else if (dev->mc_count > 0) { /* Enable specific multicasts */ + at91ether_sethashtable(dev, regs); + regs->EMAC_CFG |= AT91C_EMAC_MTI; + } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ + regs->EMAC_HSH = 0; + regs->EMAC_HSL = 0; + regs->EMAC_CFG &= ~AT91C_EMAC_MTI; + } +} + +/* ............................... IOCTL ............................... */ + +static int mdio_read(struct net_device *dev, int phy_id, int location) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + unsigned int value; + + read_phy(regs, phy_id, location, &value); + return value; +} + +static void mdio_write(struct net_device *dev, int phy_id, int location, int value) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + + write_phy(regs, phy_id, location, value); +} + +/* + * ethtool support. + */ +static int at91ether_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + u32 ethcmd; + int res = 0; + + if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + + spin_lock_irq(&lp->lock); + enable_mdi(regs); + + switch (ethcmd) { + case ETHTOOL_GSET: { + struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + res = mii_ethtool_gset(&lp->mii, &ecmd); + if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */ + ecmd.supported = SUPPORTED_FIBRE; + ecmd.port = PORT_FIBRE; + } + if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) + res = -EFAULT; + break; + } + case ETHTOOL_SSET: { + struct ethtool_cmd ecmd; + if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) + res = -EFAULT; + else + res = mii_ethtool_sset(&lp->mii, &ecmd); + break; + } + case ETHTOOL_NWAY_RST: { + res = mii_nway_restart(&lp->mii); + break; + } + case ETHTOOL_GLINK: { + struct ethtool_value edata = { ETHTOOL_GLINK }; + edata.data = mii_link_ok(&lp->mii); + if (copy_to_user(useraddr, &edata, sizeof(edata))) + res = -EFAULT; + break; + } + default: + res = -EOPNOTSUPP; + } + + disable_mdi(regs); + spin_unlock_irq(&lp->lock); + + return res; +} + +/* + * User-space ioctl interface. + */ +static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + switch(cmd) { + case SIOCETHTOOL: + return at91ether_ethtool_ioctl(dev, (void *) rq->ifr_data); + default: + return -EOPNOTSUPP; + } +} + +/* ................................ MAC ................................ */ + +/* + * Initialize and start the Receiver and Transmit subsystems + */ +static void at91ether_start(struct net_device *dev) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + struct at91_private *lp = (struct at91_private *) dev->priv; + int i; + struct recv_desc_bufs *dlist, *dlist_phys; + + dlist = lp->dlist; + dlist_phys = lp->dlist_phys; + + for (i = 0; i < MAX_RX_DESCR; i++) { + dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0]; + dlist->descriptors[i].size = 0; + } + + /* Set the Wrap bit on the last descriptor */ + dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP; + + /* Reset buffer index */ + lp->rxBuffIndex = 0; + + /* Program address of descriptor list in Rx Buffer Queue register */ + regs->EMAC_RBQP = (AT91_REG) dlist_phys; + + /* Enable Receive and Transmit */ + regs->EMAC_CTL |= (AT91C_EMAC_RE | AT91C_EMAC_TE); +} + +/* + * Open the ethernet interface + */ +static int at91ether_open(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Re-enable Peripheral clock */ + regs->EMAC_CTL |= AT91C_EMAC_CSR; /* Clear internal statistics */ + + /* Update the MAC address (incase user has changed it) */ + update_mac_address(dev); + + /* Enable PHY interrupt */ + enable_phyirq(dev, regs); + + /* Enable MAC interrupts */ + regs->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA + | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM + | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP; + + /* Determine current link speed */ + spin_lock_irq(&lp->lock); + enable_mdi(regs); + (void) update_linkspeed(dev, regs); + disable_mdi(regs); + spin_unlock_irq(&lp->lock); + + at91ether_start(dev); + netif_start_queue(dev); + return 0; +} + +/* + * Close the interface + */ +static int at91ether_close(struct net_device *dev) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + + /* Disable Receiver and Transmitter */ + regs->EMAC_CTL &= ~(AT91C_EMAC_TE | AT91C_EMAC_RE); + + /* Disable PHY interrupt */ + disable_phyirq(dev, regs); + + /* Disable MAC interrupts */ + regs->EMAC_IDR = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA + | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM + | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP; + + netif_stop_queue(dev); + + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */ + + return 0; +} + +/* + * Transmit packet. + */ +static int at91ether_tx(struct sk_buff *skb, struct net_device *dev) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + struct at91_private *lp = (struct at91_private *) dev->priv; + + if (regs->EMAC_TSR & AT91C_EMAC_BNQ) { + netif_stop_queue(dev); + + /* Store packet information (to free when Tx completed) */ + lp->skb = skb; + lp->skb_length = skb->len; + lp->skb_physaddr = pci_map_single(NULL, skb->data, skb->len, PCI_DMA_TODEVICE); + lp->stats.tx_bytes += skb->len; + + /* Set address of the data in the Transmit Address register */ + regs->EMAC_TAR = lp->skb_physaddr; + /* Set length of the packet in the Transmit Control register */ + regs->EMAC_TCR = skb->len; + + dev->trans_start = jiffies; + } else { + printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n"); + return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) + on this skb, he also reports -ENETDOWN and printk's, so either + we free and return(0) or don't free and return 1 */ + } + + return 0; +} + +/* + * Update the current statistics from the internal statistics registers. + */ +static struct net_device_stats *at91ether_stats(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; + int ale, lenerr, seqe, lcol, ecol; + + if (netif_running(dev)) { + lp->stats.rx_packets += regs->EMAC_OK; /* Good frames received */ + ale = regs->EMAC_ALE; + lp->stats.rx_frame_errors += ale; /* Alignment errors */ + lenerr = regs->EMAC_ELR + regs->EMAC_USF; + lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */ + seqe = regs->EMAC_SEQE; + lp->stats.rx_crc_errors += seqe; /* CRC error */ + lp->stats.rx_fifo_errors += regs->EMAC_DRFC; /* Receive buffer not available */ + lp->stats.rx_errors += (ale + lenerr + seqe + regs->EMAC_CDE + regs->EMAC_RJB); + + lp->stats.tx_packets += regs->EMAC_FRA; /* Frames successfully transmitted */ + lp->stats.tx_fifo_errors += regs->EMAC_TUE; /* Transmit FIFO underruns */ + lp->stats.tx_carrier_errors += regs->EMAC_CSE; /* Carrier Sense errors */ + lp->stats.tx_heartbeat_errors += regs->EMAC_SQEE; /* Heartbeat error */ + + lcol = regs->EMAC_LCOL; + ecol = regs->EMAC_ECOL; + lp->stats.tx_window_errors += lcol; /* Late collisions */ + lp->stats.tx_aborted_errors += ecol; /* 16 collisions */ + + lp->stats.collisions += (regs->EMAC_SCOL + regs->EMAC_MCOL + lcol + ecol); + } + return &lp->stats; +} + +/* + * Extract received frame from buffer descriptors and sent to upper layers. + * (Called from interrupt context) + */ +static void at91ether_rx(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + struct recv_desc_bufs *dlist; + unsigned char *p_recv; + struct sk_buff *skb; + unsigned int pktlen; + + dlist = lp->dlist; + while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) { + p_recv = dlist->recv_buf[lp->rxBuffIndex]; + pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */ + skb = alloc_skb(pktlen + 2, GFP_ATOMIC); + if (skb != NULL) { + skb_reserve(skb, 2); + memcpy(skb_put(skb, pktlen), p_recv, pktlen); + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->len = pktlen; + dev->last_rx = jiffies; + lp->stats.rx_bytes += pktlen; + netif_rx(skb); + } + else { + lp->stats.rx_dropped += 1; + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); + } + + if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST) + lp->stats.multicast++; + + dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */ + if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */ + lp->rxBuffIndex = 0; + else + lp->rxBuffIndex++; + } +} + +/* + * MAC interrupt handler + */ +static void at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + struct at91_private *lp = (struct at91_private *) dev->priv; + AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr; + unsigned long intstatus; + + /* MAC Interrupt Status register indicates what interrupts are pending. + It is automatically cleared once read. */ + intstatus = emac->EMAC_ISR; + + if (intstatus & AT91C_EMAC_RCOM) /* Receive complete */ + at91ether_rx(dev); + + if (intstatus & AT91C_EMAC_TCOM) { /* Transmit complete */ + /* The TCOM bit is set even if the transmission failed. */ + if (intstatus & (AT91C_EMAC_TUND | AT91C_EMAC_RTRY)) + lp->stats.tx_errors += 1; + + dev_kfree_skb_irq(lp->skb); + pci_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, PCI_DMA_TODEVICE); + netif_wake_queue(dev); + } + + if (intstatus & AT91C_EMAC_RBNA) + printk("%s: RBNA error\n", dev->name); + if (intstatus & AT91C_EMAC_ROVR) + printk("%s: ROVR error\n", dev->name); +} + +/* + * Initialize the ethernet interface + */ +static int at91ether_setup(struct net_device *dev, unsigned long phy_type) +{ + struct at91_private *lp; + AT91PS_EMAC regs; + static int already_initialized = 0; + unsigned int val; + + if (already_initialized) + return 0; + + dev = init_etherdev(dev, sizeof(struct at91_private)); + dev->base_addr = AT91C_VA_BASE_EMAC; + dev->irq = AT91C_ID_EMAC; + SET_MODULE_OWNER(dev); + + /* Install the interrupt handler */ + if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) + return -EBUSY; + + /* Allocate memory for private data structure */ + lp = (struct at91_private *) kmalloc(sizeof(struct at91_private), GFP_KERNEL); + if (lp == NULL) { + free_irq(dev->irq, dev); + return -ENOMEM; + } + memset(lp, 0, sizeof(struct at91_private)); + dev->priv = lp; + + /* Allocate memory for DMA Receive descriptors */ + lp->dlist = (struct recv_desc_bufs *) consistent_alloc(GFP_DMA | GFP_KERNEL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys); + if (lp->dlist == NULL) { + kfree(dev->priv); + free_irq(dev->irq, dev); + return -ENOMEM; + } + + spin_lock_init(&lp->lock); + + ether_setup(dev); + dev->open = at91ether_open; + dev->stop = at91ether_close; + dev->hard_start_xmit = at91ether_tx; + dev->get_stats = at91ether_stats; + dev->set_multicast_list = at91ether_set_rx_mode; + dev->do_ioctl = at91ether_ioctl; + dev->set_mac_address = set_mac_address; + + get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */ + update_mac_address(dev); /* Program ethernet address into MAC */ + + regs = (AT91PS_EMAC) dev->base_addr; + regs->EMAC_CTL = 0; + +#ifdef CONFIG_AT91_ETHER_RMII + regs->EMAC_CFG = AT91C_EMAC_BIG | AT91C_EMAC_RMII; +#else + regs->EMAC_CFG = AT91C_EMAC_BIG; +#endif + if (phy_type == MII_LXT971A_ID) + regs->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; /* MDIO clock = system clock/64 */ + + if (phy_type == MII_DM9161_ID) { + spin_lock_irq(&lp->lock); + enable_mdi(regs); + + read_phy(regs, 0, MII_DSCR_REG, &val); + if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */ + lp->phy_media = PORT_FIBRE; + + disable_mdi(regs); + spin_unlock_irq(&lp->lock); + } + + lp->mii.dev = dev; /* Support for ethtool */ + lp->mii.mdio_read = mdio_read; + lp->mii.mdio_write = mdio_write; + + lp->phy_type = phy_type; /* Type of PHY connected */ + + /* Determine current link speed */ + spin_lock_irq(&lp->lock); + enable_mdi(regs); + (void) update_linkspeed(dev, regs); + disable_mdi(regs); + spin_unlock_irq(&lp->lock); + + /* Display ethernet banner */ + printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n", + dev->name, (uint) dev->base_addr, dev->irq, + regs->EMAC_CFG & AT91C_EMAC_SPD ? "100-" : "10-", + regs->EMAC_CFG & AT91C_EMAC_FD ? "FullDuplex" : "HalfDuplex", + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + if (phy_type == MII_DM9161_ID) + printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); + else if (phy_type == MII_LXT971A_ID) + printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name); + + already_initialized = 1; + return 0; +} + +/* + * Detect MAC and PHY and perform initialization + */ +static int at91ether_probe(struct net_device *dev) +{ + AT91PS_EMAC regs = (AT91PS_EMAC) AT91C_VA_BASE_EMAC; + unsigned int phyid1, phyid2; + int detected = -1; + + /* Configure the hardware - RMII vs MII mode */ +#ifdef CONFIG_AT91_ETHER_RMII + AT91_CfgPIO_EMAC_RMII(); +#else + AT91_CfgPIO_EMAC_MII(); +#endif + + AT91_CfgPIO_EMAC_PHY(); /* Configure PHY interrupt */ + AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Enable Peripheral clock */ + + /* Read the PHY ID registers */ + enable_mdi(regs); + read_phy(regs, 0, MII_PHYSID1, &phyid1); + read_phy(regs, 0, MII_PHYSID2, &phyid2); + disable_mdi(regs); + + /* Davicom 9161: PHY_ID1 = 0x181 PHY_ID2 = B881 */ + if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_DM9161_ID) { + detected = at91ether_setup(dev, MII_DM9161_ID); + } + /* Intel LXT971A: PHY_ID1 = 0x13 PHY_ID2 = 78E0 */ + else if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_LXT971A_ID) { + detected = at91ether_setup(dev, MII_LXT971A_ID); + } + + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */ + + return detected; +} + +static int __init at91ether_init(void) +{ + if (!at91ether_probe(&at91_dev)) + return register_netdev(&at91_dev); + + return -1; +} + +static void __exit at91ether_exit(void) +{ + unregister_netdev(&at91_dev); +} + +module_init(at91ether_init) +module_exit(at91ether_exit) + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); +MODULE_AUTHOR("Andrew Victor"); diff -uNr linux-2.4.37.9/drivers/at91/net/at91_ether.h linux-2.4.37.9-vrs1-5mx2/drivers/at91/net/at91_ether.h --- linux-2.4.37.9/drivers/at91/net/at91_ether.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/net/at91_ether.h Wed May 26 15:51:19 2010 @@ -0,0 +1,79 @@ +/* + * Ethernet driver for the Atmel AT91RM9200 (Thunder) + * + * (c) SAN People (Pty) Ltd + * + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. + * Initial version by Rick Bronson. + * + * 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. + */ + +#ifndef AT91_ETHERNET +#define AT91_ETHERNET + + +/* Davicom 9161 PHY */ +#define MII_DM9161_ID 0x0181b880 + +/* Davicom specific registers */ +#define MII_DSCR_REG 16 +#define MII_DSCSR_REG 17 +#define MII_DSINTR_REG 21 + +/* Intel LXT971A PHY */ +#define MII_LXT971A_ID 0x001378E0 + +/* Intel specific registers */ +#define MII_ISINTE_REG 18 +#define MII_ISINTS_REG 19 + +/* ........................................................................ */ + +#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */ +#define MAX_RX_DESCR 9 /* max number of receive buffers */ + +#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */ +#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */ + +#define EMAC_BROADCAST 0x80000000 /* broadcast address */ +#define EMAC_MULTICAST 0x40000000 /* multicast address */ +#define EMAC_UNICAST 0x20000000 /* unicast address */ + +struct rbf_t +{ + unsigned int addr; + unsigned long size; +}; + +struct recv_desc_bufs +{ + struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */ + char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */ +}; + +struct at91_private +{ + struct net_device_stats stats; + struct mii_if_info mii; /* ethtool support */ + + /* PHY */ + unsigned long phy_type; /* type of PHY (PHY_ID) */ + spinlock_t lock; /* lock for MDI interface */ + short phy_media; /* media interface type */ + + /* Transmit */ + struct sk_buff *skb; /* holds skb until xmit interrupt completes */ + dma_addr_t skb_physaddr; /* phys addr from pci_map_single */ + int skb_length; /* saved skb length for pci_unmap_single */ + + /* Receive */ + int rxBuffIndex; /* index into receive descriptor list */ + struct recv_desc_bufs *dlist; /* descriptor list address */ + struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */ +}; + +#endif diff -uNr linux-2.4.37.9/drivers/at91/rtc/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/rtc/Makefile --- linux-2.4.37.9/drivers/at91/rtc/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/rtc/Makefile Wed May 26 15:51:19 2010 @@ -0,0 +1,15 @@ +# File: drivers/at91/rtc/Makefile +# +# Makefile for the Atmel AT91RM9200 real time clock device drivers +# + +O_TARGET := at91rtc.o + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_AT91_RTC) += at91_rtc.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/rtc/at91_rtc.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/rtc/at91_rtc.c --- linux-2.4.37.9/drivers/at91/rtc/at91_rtc.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/rtc/at91_rtc.c Wed May 26 15:51:19 2010 @@ -0,0 +1,441 @@ +/* + * Real Time Clock interface for Linux on Atmel AT91RM9200 + * + * Copyright (c) 2002 Rick Bronson + * + * Based on sa1100-rtc.c by Nils Faerber + * Based on rtc.c by Paul Gortmaker + * Date/time conversion routines taken from arch/arm/kernel/time.c + * by Linus Torvalds and Russell King + * and the GNU C Library + * ( ... I love the GPL ... just take what you need! ;) + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AT91_RTC_FREQ 1 +#define EPOCH 1970 + +/* Those are the bits from a classic RTC we want to mimic */ +#define AT91_RTC_IRQF 0x80 /* any of the following 3 is active */ +#define AT91_RTC_PF 0x40 +#define AT91_RTC_AF 0x20 +#define AT91_RTC_UF 0x10 + +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +static unsigned long rtc_status = 0; +static unsigned long rtc_irq_data; +static unsigned int at91_alarm_year = EPOCH; + +static struct fasync_struct *at91_rtc_async_queue; +static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_wait); +static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_update); +static spinlock_t at91_rtc_updlock; /* some spinlocks for saving/restoring interrupt levels */ +extern spinlock_t at91_rtc_lock; + +static const unsigned char days_in_mo[] = + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +#define is_leap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) + +static const unsigned short int __mon_yday[2][13] = +{ + /* Normal years. */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + /* Leap years. */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } +}; + +/* + * Returns day since start of the year [0-365] + * (from drivers/char/efirtc.c) + */ +static inline int compute_yday(int year, int month, int day) +{ + return __mon_yday[is_leap(year)][month] + day-1; +} + +/* + * Set current time and date in RTC + */ +static void at91_rtc_settime(struct rtc_time *tval) +{ + unsigned long flags; + + /* Stop Time/Calendar from counting */ + AT91_SYS->RTC_CR |= (AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM); + + spin_lock_irqsave(&at91_rtc_updlock, flags); /* stop int's else we wakeup b4 we sleep */ + AT91_SYS->RTC_IER = AT91C_RTC_ACKUPD; + interruptible_sleep_on(&at91_rtc_update); /* wait for ACKUPD interrupt to hit */ + spin_unlock_irqrestore(&at91_rtc_updlock, flags); + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD; + + AT91_SYS->RTC_TIMR = BIN2BCD(tval->tm_sec) << 0 + | BIN2BCD(tval->tm_min) << 8 + | BIN2BCD(tval->tm_hour) << 16; + + AT91_SYS->RTC_CALR = BIN2BCD((tval->tm_year + 1900) / 100) /* century */ + | BIN2BCD(tval->tm_year % 100) << 8 /* year */ + | BIN2BCD(tval->tm_mon + 1) << 16 /* tm_mon starts at zero */ + | BIN2BCD(tval->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */ + | BIN2BCD(tval->tm_mday) << 24; + + /* Restart Time/Calendar */ + AT91_SYS->RTC_CR &= ~(AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM); +} + +/* + * Decode time/date into rtc_time structure + */ +static void at91_rtc_decodetime(AT91_REG *timereg, AT91_REG *calreg, struct rtc_time *tval) +{ + unsigned int time, date; + + do { /* must read twice in case it changes */ + time = *timereg; + date = *calreg; + } while ((time != *timereg) || (date != *calreg)); + + tval->tm_sec = BCD2BIN((time & AT91C_RTC_SEC) >> 0); + tval->tm_min = BCD2BIN((time & AT91C_RTC_MIN) >> 8); + tval->tm_hour = BCD2BIN((time & AT91C_RTC_HOUR) >> 16); + + /* The Calendar Alarm register does not have a field for + the year - so these will return an invalid value. When an + alarm is set, at91_alarm_year wille store the current year. */ + tval->tm_year = BCD2BIN(date & AT91C_RTC_CENT) * 100; /* century */ + tval->tm_year += BCD2BIN((date & AT91C_RTC_YEAR) >> 8); /* year */ + + tval->tm_wday = BCD2BIN((date & AT91C_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */ + tval->tm_mon = BCD2BIN(((date & AT91C_RTC_MONTH) >> 16) - 1); + tval->tm_mday = BCD2BIN((date & AT91C_RTC_DATE) >> 24); +} + +/* + * IRQ handler for the RTC + */ +static void at91_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int rtsr = AT91_SYS->RTC_SR & AT91_SYS->RTC_IMR; + + /* update irq data & counter */ + if (rtsr) { /* this interrupt is shared! Is it ours? */ + if (rtsr & AT91C_RTC_ALARM) + rtc_irq_data |= (AT91_RTC_AF | AT91_RTC_IRQF); + if (rtsr & AT91C_RTC_SECEV) + rtc_irq_data |= (AT91_RTC_UF | AT91_RTC_IRQF); + if (rtsr & AT91C_RTC_ACKUPD) + wake_up_interruptible(&at91_rtc_update); + rtc_irq_data += 0x100; + AT91_SYS->RTC_SCCR = rtsr; /* clear status reg */ + + /* wake up waiting process */ + wake_up_interruptible(&at91_rtc_wait); + kill_fasync(&at91_rtc_async_queue, SIGIO, POLL_IN); + } +} + +static int at91_rtc_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(1, &rtc_status)) + return -EBUSY; + rtc_irq_data = 0; + return 0; +} + +static int at91_rtc_release(struct inode *inode, struct file *file) +{ + rtc_status = 0; + return 0; +} + +static int at91_rtc_fasync(int fd, struct file *filp, int on) +{ + return fasync_helper(fd, filp, on, &at91_rtc_async_queue); +} + +static unsigned int at91_rtc_poll(struct file *file, poll_table * wait) +{ + poll_wait(file, &at91_rtc_wait, wait); + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM; +} + +static ssize_t at91_rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&at91_rtc_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + for (;;) { + spin_lock_irq(&at91_rtc_lock); + data = rtc_irq_data; + if (data != 0) { + rtc_irq_data = 0; + break; + } + spin_unlock_irq(&at91_rtc_lock); + + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + + schedule(); + } + spin_unlock_irq(&at91_rtc_lock); + + data -= 0x100; /* the first IRQ wasn't actually missed */ + retval = put_user(data, (unsigned long *) buf); + if (!retval) + retval = sizeof(unsigned long); + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&at91_rtc_wait, &wait); + return retval; +} + +/* + * Handle commands from user-space + */ +static int at91_rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct rtc_time tm, tm2; + int ret = 0; + + spin_lock_irq(&at91_rtc_lock); + switch (cmd) { + case RTC_AIE_OFF: /* alarm off */ + AT91_SYS->RTC_IDR = AT91C_RTC_ALARM; + rtc_irq_data = 0; + break; + case RTC_AIE_ON: /* alarm on */ + AT91_SYS->RTC_IER = AT91C_RTC_ALARM; + rtc_irq_data = 0; + break; + case RTC_UIE_OFF: /* update off */ + AT91_SYS->RTC_IDR = AT91C_RTC_SECEV; + rtc_irq_data = 0; + break; + case RTC_UIE_ON: /* update on */ + AT91_SYS->RTC_IER = AT91C_RTC_SECEV; + rtc_irq_data = 0; + break; + case RTC_PIE_OFF: /* periodic off */ + AT91_SYS->RTC_IDR = AT91C_RTC_SECEV; + rtc_irq_data = 0; + break; + case RTC_PIE_ON: /* periodic on */ + AT91_SYS->RTC_IER = AT91C_RTC_SECEV; + rtc_irq_data = 0; + break; + case RTC_ALM_READ: /* read alarm */ + memset(&tm, 0, sizeof(struct rtc_time)); + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm); + tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday); + tm.tm_year = at91_alarm_year - 1900; + ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0; + break; + case RTC_ALM_SET: /* set alarm */ + if (copy_from_user(&tm2, (struct rtc_time *) arg, sizeof(tm2))) + ret = -EFAULT; + else { + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm); + at91_alarm_year = tm.tm_year; + if ((unsigned) tm2.tm_hour < 24) /* do some range checking */ + tm.tm_hour = tm2.tm_hour; + if ((unsigned) tm2.tm_min < 60) + tm.tm_min = tm2.tm_min; + if ((unsigned) tm2.tm_sec < 60) + tm.tm_sec = tm2.tm_sec; + AT91_SYS->RTC_TIMALR = BIN2BCD(tm.tm_sec) << 0 + | BIN2BCD(tm.tm_min) << 8 + | BIN2BCD(tm.tm_hour) << 16 + | AT91C_RTC_HOUREN | AT91C_RTC_MINEN + | AT91C_RTC_SECEN; + AT91_SYS->RTC_CALALR = BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ + | BIN2BCD(tm.tm_mday) << 24 + | AT91C_RTC_DATEEN | AT91C_RTC_MONTHEN; + } + break; + case RTC_RD_TIME: /* read time */ + memset(&tm, 0, sizeof(struct rtc_time)); + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm); + tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday); + tm.tm_year = tm.tm_year - 1900; + ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0; + break; + case RTC_SET_TIME: /* set time */ + if (!capable(CAP_SYS_TIME)) + ret = -EACCES; + else { + if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(tm))) + ret = -EFAULT; + else { + int tm_year = tm.tm_year + 1900; + if (tm_year < EPOCH + || (unsigned) tm.tm_mon >= 12 + || tm.tm_mday < 1 + || tm.tm_mday > (days_in_mo[tm.tm_mon] + (tm.tm_mon == 1 && is_leap(tm_year))) + || (unsigned) tm.tm_hour >= 24 + || (unsigned) tm.tm_min >= 60 + || (unsigned) tm.tm_sec >= 60) + ret = -EINVAL; + else + at91_rtc_settime(&tm); + } + } + break; + case RTC_IRQP_READ: /* read periodic alarm frequency */ + ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg); + break; + case RTC_IRQP_SET: /* set periodic alarm frequency */ + if (arg != AT91_RTC_FREQ) + ret = -EINVAL; + break; + case RTC_EPOCH_READ: /* read epoch */ + ret = put_user(EPOCH, (unsigned long *) arg); + break; + default: + ret = -EINVAL; + break; + } + spin_unlock_irq(&at91_rtc_lock); + return ret; +} + +/* + * Provide RTC information in /proc/driver/rtc + */ +static int at91_rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + int len; + struct rtc_time tm; + + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm); + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, EPOCH); + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm); + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n" + "alrm_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + at91_alarm_year, tm.tm_mon + 1, tm.tm_mday); + p += sprintf(p, "alarm_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ALARM) ? "yes" : "no"); + p += sprintf(p, "update_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ACKUPD) ? "yes" : "no"); + p += sprintf(p, "periodic_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_SECEV) ? "yes" : "no"); + p += sprintf(p, "periodic_freq\t: %ld\n", (unsigned long) AT91_RTC_FREQ); + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return len; +} + +static struct file_operations at91_rtc_fops = { + owner:THIS_MODULE, + llseek:no_llseek, + read:at91_rtc_read, + poll:at91_rtc_poll, + ioctl:at91_rtc_ioctl, + open:at91_rtc_open, + release:at91_rtc_release, + fasync:at91_rtc_fasync, +}; + +static struct miscdevice at91_rtc_miscdev = { + minor:RTC_MINOR, + name:"rtc", + fops:&at91_rtc_fops, +}; + +/* + * Initialize and install RTC driver + */ +static int __init at91_rtc_init(void) +{ + int ret; + + AT91_SYS->RTC_CR = 0; + AT91_SYS->RTC_MR = 0; /* put in 24 hour format */ + /* Disable all interrupts */ + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV; + + spin_lock_init(&at91_rtc_updlock); + spin_lock_init(&at91_rtc_lock); + + misc_register(&at91_rtc_miscdev); + create_proc_read_entry("driver/rtc", 0, 0, at91_rtc_read_proc, NULL); + ret = request_irq(AT91C_ID_SYS, at91_rtc_interrupt, SA_SHIRQ, + "at91_rtc", &rtc_status); + if (ret) { + printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", AT91C_ID_SYS); + remove_proc_entry("driver/rtc", NULL); + misc_deregister(&at91_rtc_miscdev); + return ret; + } + + printk(KERN_INFO "AT91 Real Time Clock driver\n"); + return 0; +} + +/* + * Disable and remove the RTC driver + */ +static void __exit at91_rtc_exit(void) +{ + /* Disable all interrupts */ + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV; + free_irq(AT91C_ID_SYS, &rtc_status); + + rtc_status = 0; + remove_proc_entry("driver/rtc", NULL); + misc_deregister(&at91_rtc_miscdev); +} + +module_init(at91_rtc_init); +module_exit(at91_rtc_exit); + +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("AT91 Realtime Clock Driver (AT91_RTC)"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -uNr linux-2.4.37.9/drivers/at91/serial/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/serial/Makefile --- linux-2.4.37.9/drivers/at91/serial/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/serial/Makefile Wed May 26 15:51:19 2010 @@ -0,0 +1,15 @@ +# File: drivers/at91/serial/Makefile +# +# Makefile for the Atmel AT91RM9200 serial and console device drivers +# + +O_TARGET := at91serial.o + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_SERIAL_AT91) += at91_serial.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/serial/at91_serial.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/serial/at91_serial.c --- linux-2.4.37.9/drivers/at91/serial/at91_serial.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/serial/at91_serial.c Wed May 26 15:51:19 2010 @@ -0,0 +1,881 @@ +/* + * linux/drivers/char/at91_serial.c + * + * Driver for Atmel AT91RM9200 Serial ports + * + * Copyright (c) Rick Bronson + * + * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * 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 + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + +#define SERIAL_AT91_MAJOR TTY_MAJOR +#define CALLOUT_AT91_MAJOR TTYAUX_MAJOR +#define MINOR_START 64 + +#define AT91C_VA_BASE_DBGU ((unsigned long) &(AT91_SYS->DBGU_CR)) +#define AT91_ISR_PASS_LIMIT 256 + +#define UART_PUT_CR(port,v) ((AT91PS_USART)(port)->membase)->US_CR = v +#define UART_GET_MR(port) ((AT91PS_USART)(port)->membase)->US_MR +#define UART_PUT_MR(port,v) ((AT91PS_USART)(port)->membase)->US_MR = v +#define UART_PUT_IER(port,v) ((AT91PS_USART)(port)->membase)->US_IER = v +#define UART_PUT_IDR(port,v) ((AT91PS_USART)(port)->membase)->US_IDR = v +#define UART_GET_IMR(port) ((AT91PS_USART)(port)->membase)->US_IMR +#define UART_GET_CSR(port) ((AT91PS_USART)(port)->membase)->US_CSR +#define UART_GET_CHAR(port) ((AT91PS_USART)(port)->membase)->US_RHR +#define UART_PUT_CHAR(port,v) ((AT91PS_USART)(port)->membase)->US_THR = v +#define UART_GET_BRGR(port) ((AT91PS_USART)(port)->membase)->US_BRGR +#define UART_PUT_BRGR(port,v) ((AT91PS_USART)(port)->membase)->US_BRGR = v +#define UART_PUT_RTOR(port,v) ((AT91PS_USART)(port)->membase)->US_RTOR = v + +// #define UART_GET_CR(port) ((AT91PS_USART)(port)->membase)->US_CR // is write-only + + /* PDC registers */ +#define UART_PUT_PTCR(port,v) ((AT91PS_USART)(port)->membase)->US_PTCR = v +#define UART_PUT_RPR(port,v) ((AT91PS_USART)(port)->membase)->US_RPR = v +#define UART_PUT_RCR(port,v) ((AT91PS_USART)(port)->membase)->US_RCR = v +#define UART_GET_RCR(port) ((AT91PS_USART)(port)->membase)->US_RCR +#define UART_PUT_RNPR(port,v) ((AT91PS_USART)(port)->membase)->US_RNPR = v +#define UART_PUT_RNCR(port,v) ((AT91PS_USART)(port)->membase)->US_RNCR = v + +static struct tty_driver normal, callout; +static struct tty_struct *at91_table[AT91C_NR_UART]; +static struct termios *at91_termios[AT91C_NR_UART], *at91_termios_locked[AT91C_NR_UART]; + +const int at91_serialmap[AT91C_NR_UART] = AT91C_UART_MAP; + +static int (*at91_open)(struct uart_port *); +static void (*at91_close)(struct uart_port *); + +#ifdef SUPPORT_SYSRQ +static struct console at91_console; +#endif + +/* + * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. + */ +static u_int at91_tx_empty(struct uart_port *port) +{ + return UART_GET_CSR(port) & AT91C_US_TXEMPTY ? TIOCSER_TEMT : 0; +} + +/* + * Set state of the modem control output lines + */ +static void at91_set_mctrl(struct uart_port *port, u_int mctrl) +{ + unsigned int control = 0; + + /* + * Errata #39: RTS0 is not internally connected to PA21. We need to drive + * the pin manually. + */ + if (port->mapbase == AT91C_VA_BASE_US0) { + if (mctrl & TIOCM_RTS) + AT91_SYS->PIOA_CODR = AT91C_PA21_RTS0; + else + AT91_SYS->PIOA_SODR = AT91C_PA21_RTS0; + } + + if (mctrl & TIOCM_RTS) + control |= AT91C_US_RTSEN; + else + control |= AT91C_US_RTSDIS; + + if (mctrl & TIOCM_DTR) + control |= AT91C_US_DTREN; + else + control |= AT91C_US_DTRDIS; + + UART_PUT_CR(port,control); +} + +/* + * Get state of the modem control input lines + */ +static u_int at91_get_mctrl(struct uart_port *port) +{ + unsigned int status, ret = 0; + + status = UART_GET_CSR(port); + if (status & AT91C_US_DCD) + ret |= TIOCM_CD; + if (status & AT91C_US_CTS) + ret |= TIOCM_CTS; + if (status & AT91C_US_DSR) + ret |= TIOCM_DSR; + if (status & AT91C_US_RI) + ret |= TIOCM_RI; + + return ret; +} + +/* + * Stop transmitting. + */ +static void at91_stop_tx(struct uart_port *port, u_int from_tty) +{ + UART_PUT_IDR(port, AT91C_US_TXRDY); + port->read_status_mask &= ~AT91C_US_TXRDY; +} + +/* + * Start transmitting. + */ +static void at91_start_tx(struct uart_port *port, u_int from_tty) +{ + unsigned long flags; + + local_irq_save(flags); + port->read_status_mask |= AT91C_US_TXRDY; + UART_PUT_IER(port, AT91C_US_TXRDY); + local_irq_restore(flags); +} + +/* + * Stop receiving - port is in process of being closed. + */ +static void at91_stop_rx(struct uart_port *port) +{ + UART_PUT_IDR(port, AT91C_US_RXRDY); +} + +/* + * Enable modem status interrupts + */ +static void at91_enable_ms(struct uart_port *port) +{ + UART_PUT_IER(port, AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC); +} + +/* + * Control the transmission of a break signal + */ +static void at91_break_ctl(struct uart_port *port, int break_state) +{ + if (break_state != 0) + UART_PUT_CR(port, AT91C_US_STTBRK); /* start break */ + else + UART_PUT_CR(port, AT91C_US_STPBRK); /* stop break */ +} + +/* + * Characters received (called from interrupt handler) + */ +static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) +{ + struct uart_info *info = port->info; + struct tty_struct *tty = info->tty; + unsigned int status, ch, flg, ignored = 0; + + status = UART_GET_CSR(port); + while (status & (AT91C_US_RXRDY)) { + ch = UART_GET_CHAR(port); + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + port->icount.rx++; + + flg = TTY_NORMAL; + + /* + * note that the error handling code is + * out of the main execution path + */ + if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE)) + goto handle_error; + + if (uart_handle_sysrq_char(port, ch, regs)) + goto ignore_char; + + error_return: + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + ignore_char: + status = UART_GET_CSR(port); + } +out: + tty_flip_buffer_push(tty); + return; + +handle_error: + if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE)) + UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */ + if (status & (AT91C_US_PARE)) + port->icount.parity++; + else if (status & (AT91C_US_FRAME)) + port->icount.frame++; + if (status & (AT91C_US_OVRE)) + port->icount.overrun++; + + if (status & port->ignore_status_mask) { + if (++ignored > 100) + goto out; + goto ignore_char; + } + + status &= port->read_status_mask; + + UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */ + if (status & AT91C_US_PARE) + flg = TTY_PARITY; + else if (status & AT91C_US_FRAME) + flg = TTY_FRAME; + + if (status & AT91C_US_OVRE) { + /* + * overrun does *not* affect the character + * we read from the FIFO + */ + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + ch = 0; + flg = TTY_OVERRUN; + } +#ifdef SUPPORT_SYSRQ + port->sysrq = 0; +#endif + goto error_return; +} + +/* + * Transmit characters (called from interrupt handler) + */ +static void at91_tx_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (port->x_char) { + UART_PUT_CHAR(port, port->x_char); + port->icount.tx++; + port->x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + at91_stop_tx(port, 0); + return; + } + + while (UART_GET_CSR(port) & AT91C_US_TXRDY) { + UART_PUT_CHAR(port, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (uart_circ_empty(xmit)) + at91_stop_tx(port, 0); +} + +/* + * Interrupt handler + */ +static void at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + unsigned int status, pending, pass_counter = 0; + + status = UART_GET_CSR(port); + pending = status & port->read_status_mask; + if (pending) { + do { + if (pending & AT91C_US_RXRDY) + at91_rx_chars(port, regs); + + /* Clear the relevent break bits */ + if (pending & AT91C_US_RXBRK) { + UART_PUT_CR(port, AT91C_US_RSTSTA); + port->icount.brk++; +#ifdef SUPPORT_SYSRQ + if (port->line == at91_console.index && !port->sysrq) { + port->sysrq = jiffies + HZ*5; + } +#endif + } + + // TODO: All reads to CSR will clear these interrupts! + if (pending & AT91C_US_RIIC) port->icount.rng++; + if (pending & AT91C_US_DSRIC) port->icount.dsr++; + if (pending & AT91C_US_DCDIC) { + port->icount.dcd++; + uart_handle_dcd_change(port, status & AT91C_US_DCD); + } + if (pending & AT91C_US_CTSIC) { + port->icount.cts++; + uart_handle_cts_change(port, status & AT91C_US_CTS); + } + if (pending & (AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC)) + wake_up_interruptible(&port->info->delta_msr_wait); + + if (pending & AT91C_US_TXRDY) + at91_tx_chars(port); + if (pass_counter++ > AT91_ISR_PASS_LIMIT) + break; + + status = UART_GET_CSR(port); + pending = status & port->read_status_mask; + } while (pending); + } +} + +/* + * Perform initialization and enable port for reception + */ +static int at91_startup(struct uart_port *port) +{ + int retval; + + /* + * Allocate the IRQ + */ + retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port); + if (retval) { + printk("at91_serial: at91_startup - Can't get irq\n"); + return retval; + } + /* + * If there is a specific "open" function (to register + * control line interrupts) + */ + if (at91_open) { + retval = at91_open(port); + if (retval) { + free_irq(port->irq, port); + return retval; + } + } + + /* Enable peripheral clock if required */ + if (port->irq != AT91C_ID_SYS) + AT91_SYS->PMC_PCER = 1 << port->irq; + + port->read_status_mask = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE + | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK; + /* + * Finally, clear and enable interrupts + */ + UART_PUT_IDR(port, -1); + UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); /* enable xmit & rcvr */ + UART_PUT_IER(port, AT91C_US_RXRDY); /* do receive only */ + return 0; +} + +/* + * Disable the port + */ +static void at91_shutdown(struct uart_port *port) +{ + /* + * Free the interrupt + */ + free_irq(port->irq, port); + + /* + * If there is a specific "close" function (to unregister + * control line interrupts) + */ + if (at91_close) + at91_close(port); + + /* + * Disable all interrupts, port and break condition. + */ + UART_PUT_CR(port, AT91C_US_RSTSTA); + UART_PUT_IDR(port, -1); + + /* Disable peripheral clock if required */ + if (port->irq != AT91C_ID_SYS) + AT91_SYS->PMC_PCDR = 1 << port->irq; +} + +static struct uart_ops at91_pops; /* forward declaration */ + +/* + * Change the port parameters + */ +static void at91_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot) +{ + unsigned long flags; + unsigned int mode, imr; + + /* Get current mode register */ + mode = UART_GET_MR(port) & ~(AT91C_US_CHRL | AT91C_US_NBSTOP | AT91C_US_PAR); + + /* byte size */ + switch (cflag & CSIZE) { + case CS5: + mode |= AT91C_US_CHRL_5_BITS; + break; + case CS6: + mode |= AT91C_US_CHRL_6_BITS; + break; + case CS7: + mode |= AT91C_US_CHRL_7_BITS; + break; + default: + mode |= AT91C_US_CHRL_8_BITS; + break; + } + + /* stop bits */ + if (cflag & CSTOPB) + mode |= AT91C_US_NBSTOP_2_BIT; + + /* parity */ + if (cflag & PARENB) { + if (cflag & CMSPAR) { /* Mark or Space parity */ + if (cflag & PARODD) + mode |= AT91C_US_PAR_MARK; + else + mode |= AT91C_US_PAR_SPACE; + } + else if (cflag & PARODD) + mode |= AT91C_US_PAR_ODD; + else + mode |= AT91C_US_PAR_EVEN; + } + else + mode |= AT91C_US_PAR_NONE; + + port->read_status_mask |= AT91C_US_OVRE; + if (iflag & INPCK) + port->read_status_mask |= AT91C_US_FRAME | AT91C_US_PARE; + if (iflag & (BRKINT | PARMRK)) + port->read_status_mask |= AT91C_US_RXBRK; + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (iflag & IGNPAR) + port->ignore_status_mask |= (AT91C_US_FRAME | AT91C_US_PARE); + if (iflag & IGNBRK) { + port->ignore_status_mask |= AT91C_US_RXBRK; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (iflag & IGNPAR) + port->ignore_status_mask |= AT91C_US_OVRE; + } + + // TODO: Ignore all characters if CREAD is set. + + /* first, disable interrupts and drain transmitter */ + local_irq_save(flags); + imr = UART_GET_IMR(port); /* get interrupt mask */ + UART_PUT_IDR(port, -1); /* disable all interrupts */ + local_irq_restore(flags); + while (!(UART_GET_CSR(port) & AT91C_US_TXEMPTY)) { barrier(); } + + /* disable receiver and transmitter */ + UART_PUT_CR(port, AT91C_US_TXDIS | AT91C_US_RXDIS); + + /* set the parity, stop bits and data size */ + UART_PUT_MR(port, mode); + + /* set the baud rate */ + UART_PUT_BRGR(port, quot); + UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); + + /* restore interrupts */ + UART_PUT_IER(port, imr); + + /* CTS flow-control and modem-status interrupts */ + if (UART_ENABLE_MS(port, cflag)) + at91_pops.enable_ms(port); +} + +/* + * Return string describing the specified port + */ +static const char *at91_type(struct uart_port *port) +{ + return port->type == PORT_AT91RM9200 ? "AT91_SERIAL" : NULL; +} + +/* + * Release the memory region(s) being used by 'port'. + */ +static void at91_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, + port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K); +} + +/* + * Request the memory region(s) being used by 'port'. + */ +static int at91_request_port(struct uart_port *port) +{ + return request_mem_region(port->mapbase, + port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K, + "at91_serial") != NULL ? 0 : -EBUSY; + +} + +/* + * Configure/autoconfigure the port. + */ +static void at91_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + port->type = PORT_AT91RM9200; + at91_request_port(port); + } +} + +/* + * Verify the new serial_struct (for TIOCSSERIAL). + */ +static int at91_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200) + ret = -EINVAL; + if (port->irq != ser->irq) + ret = -EINVAL; + if (ser->io_type != SERIAL_IO_MEM) + ret = -EINVAL; + if (port->uartclk / 16 != ser->baud_base) + ret = -EINVAL; + if ((void *)port->mapbase != ser->iomem_base) + ret = -EINVAL; + if (port->iobase != ser->port) + ret = -EINVAL; + if (ser->hub6 != 0) + ret = -EINVAL; + return ret; +} + +static struct uart_ops at91_pops = { + tx_empty: at91_tx_empty, + set_mctrl: at91_set_mctrl, + get_mctrl: at91_get_mctrl, + stop_tx: at91_stop_tx, + start_tx: at91_start_tx, + stop_rx: at91_stop_rx, + enable_ms: at91_enable_ms, + break_ctl: at91_break_ctl, + startup: at91_startup, + shutdown: at91_shutdown, + change_speed: at91_change_speed, + type: at91_type, + release_port: at91_release_port, + request_port: at91_request_port, + config_port: at91_config_port, + verify_port: at91_verify_port, +}; + +static struct uart_port at91_ports[AT91C_NR_UART]; + +void __init at91_init_ports(void) +{ + static int first = 1; + int i; + + if (!first) + return; + first = 0; + + for (i = 0; i < AT91C_NR_UART; i++) { + at91_ports[i].iotype = SERIAL_IO_MEM; + at91_ports[i].flags = ASYNC_BOOT_AUTOCONF; + at91_ports[i].uartclk = AT91C_MASTER_CLOCK; + at91_ports[i].ops = &at91_pops; + at91_ports[i].fifosize = 1; + at91_ports[i].line = i; + } +} + +void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns) +{ + if (fns->enable_ms) + at91_pops.enable_ms = fns->enable_ms; + if (fns->get_mctrl) + at91_pops.get_mctrl = fns->get_mctrl; + if (fns->set_mctrl) + at91_pops.set_mctrl = fns->set_mctrl; + at91_open = fns->open; + at91_close = fns->close; + at91_pops.pm = fns->pm; + at91_pops.set_wake = fns->set_wake; +} + +/* + * Setup ports. + */ +void __init at91_register_uart(int idx, int port) +{ + if ((idx < 0) || (idx >= AT91C_NR_UART)) { + printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx); + return; + } + + switch (port) { + case 0: + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US0; + at91_ports[idx].mapbase = AT91C_VA_BASE_US0; + at91_ports[idx].irq = AT91C_ID_US0; + AT91_CfgPIO_USART0(); + break; + case 1: + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US1; + at91_ports[idx].mapbase = AT91C_VA_BASE_US1; + at91_ports[idx].irq = AT91C_ID_US1; + AT91_CfgPIO_USART1(); + break; + case 2: + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US2; + at91_ports[idx].mapbase = AT91C_VA_BASE_US2; + at91_ports[idx].irq = AT91C_ID_US2; + AT91_CfgPIO_USART2(); + break; + case 3: + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US3; + at91_ports[idx].mapbase = AT91C_VA_BASE_US3; + at91_ports[idx].irq = AT91C_ID_US3; + AT91_CfgPIO_USART3(); + break; + case 4: + at91_ports[idx].membase = (void *) AT91C_VA_BASE_DBGU; + at91_ports[idx].mapbase = AT91C_VA_BASE_DBGU; + at91_ports[idx].irq = AT91C_ID_SYS; + AT91_CfgPIO_DBGU(); + break; + default: + printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port); + } +} + +#ifdef CONFIG_SERIAL_AT91_CONSOLE + +/* + * Interrupts are disabled on entering + */ +static void at91_console_write(struct console *co, const char *s, u_int count) +{ + struct uart_port *port = at91_ports + co->index; + unsigned int status, i, imr; + + /* + * First, save IMR and then disable interrupts + */ + imr = UART_GET_IMR(port); /* get interrupt mask */ + UART_PUT_IDR(port, AT91C_US_RXRDY | AT91C_US_TXRDY); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + do { + status = UART_GET_CSR(port); + } while (!(status & AT91C_US_TXRDY)); + UART_PUT_CHAR(port, s[i]); + if (s[i] == '\n') { + do { + status = UART_GET_CSR(port); + } while (!(status & AT91C_US_TXRDY)); + UART_PUT_CHAR(port, '\r'); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore IMR + */ + do { + status = UART_GET_CSR(port); + } while (!(status & AT91C_US_TXRDY)); + UART_PUT_IER(port, imr); /* set interrupts back the way they were */ +} + +static kdev_t at91_console_device(struct console *co) +{ + return MKDEV(SERIAL_AT91_MAJOR, MINOR_START + co->index); +} + +/* + * If the port was already initialised (eg, by a boot loader), try to determine + * the current setup. + */ +static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) +{ + unsigned int mr, quot; + +// TODO: CR is a write-only register +// unsigned int cr; +// +// cr = UART_GET_CR(port) & (AT91C_US_RXEN | AT91C_US_TXEN); +// if (cr == (AT91C_US_RXEN | AT91C_US_TXEN)) { +// /* ok, the port was enabled */ +// +// mr = UART_GET_MR(port) & AT91C_US_PAR; +// +// *parity = 'n'; +// if (mr == AT91C_US_PAR_EVEN) +// *parity = 'e'; +// else if (mr == AT91C_US_PAR_ODD) +// *parity = 'o'; +// } + + mr = UART_GET_MR(port) & AT91C_US_CHRL; + if (mr == AT91C_US_CHRL_8_BITS) + *bits = 8; + else + *bits = 7; + + quot = UART_GET_BRGR(port); + *baud = port->uartclk / (16 * (quot)); +} + +static int __init at91_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = AT91C_CONSOLE_DEFAULT_BAUDRATE; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + port = uart_get_console(at91_ports, AT91C_NR_UART, co); + + // TODO: The console port should be initialized, and clock enabled if + // we're not relying on the bootloader to do it. + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + at91_console_get_options(port, &baud, &parity, &bits); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct console at91_console = { + name: "ttyS", + write: at91_console_write, + device: at91_console_device, + setup: at91_console_setup, + flags: CON_PRINTBUFFER, + index: AT91C_CONSOLE, +}; + +#define AT91_CONSOLE_DEVICE &at91_console + +void __init at91_console_init(void) +{ + at91_init_ports(); + register_console(&at91_console); +} + +#else +#define AT91_CONSOLE_DEVICE NULL +#endif + +static struct uart_driver at91_reg = { + owner: THIS_MODULE, + normal_major: SERIAL_AT91_MAJOR, +#ifdef CONFIG_DEVFS_FS + normal_name: "ttyS%d", + callout_name: "cua%d", +#else + normal_name: "ttyS", + callout_name: "cua", +#endif + normal_driver: &normal, + callout_major: CALLOUT_AT91_MAJOR, + callout_driver: &callout, + table: at91_table, + termios: at91_termios, + termios_locked: at91_termios_locked, + minor: MINOR_START, + nr: AT91C_NR_UART, + cons: AT91_CONSOLE_DEVICE, +}; + +static int __init at91_serial_init(void) +{ + int ret, i; + + at91_init_ports(); + + ret = uart_register_driver(&at91_reg); + if (ret) + return ret; + + for (i = 0; i < AT91C_NR_UART; i++) { + if (at91_serialmap[i] >= 0) + uart_add_one_port(&at91_reg, &at91_ports[i]); + } + + return 0; +} + +static void __exit at91_serial_exit(void) +{ + int i; + + for (i = 0; i < AT91C_NR_UART; i++) { + if (at91_serialmap[i] >= 0) + uart_remove_one_port(&at91_reg, &at91_ports[i]); + } + + uart_unregister_driver(&at91_reg); +} + +module_init(at91_serial_init); +module_exit(at91_serial_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("AT91 generic serial port driver"); +MODULE_LICENSE("GPL"); diff -uNr linux-2.4.37.9/drivers/at91/spi/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/Makefile --- linux-2.4.37.9/drivers/at91/spi/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/Makefile Wed May 26 15:51:20 2010 @@ -0,0 +1,17 @@ +# File: drivers/at91/spi/Makefile +# +# Makefile for the Atmel AT91RM9200 SPI device drivers +# + +O_TARGET := at91spi.o + +export-objs := at91_spi.o + +obj-y := at91_spi.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_AT91_SPIDEV) += at91_spidev.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/spi/at91_spi.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/at91_spi.c --- linux-2.4.37.9/drivers/at91/spi/at91_spi.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/at91_spi.c Wed May 26 15:51:20 2010 @@ -0,0 +1,275 @@ +/* + * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 (Thunder) + * + * (c) SAN People (Pty) Ltd + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include "at91_spi.h" + +#undef DEBUG_SPI + +static struct spi_local spi_dev[NR_SPI_DEVICES]; /* state of the SPI devices */ +static int spi_enabled = 0; +static struct semaphore spi_lock; /* protect access to SPI bus */ +static int current_device = -1; /* currently selected SPI device */ + +DECLARE_COMPLETION(transfer_complete); + +/* SPI controller device */ +static AT91PS_SPI controller = (AT91PS_SPI) AT91C_VA_BASE_SPI; + +/* ......................................................................... */ + +/* + * Access and enable the SPI bus. + * This MUST be called before any transfers are performed. + */ +void spi_access_bus(short device) +{ + /* Ensure that requested device is valid */ + if ((device < 0) || (device >= NR_SPI_DEVICES)) + panic("at91_spi: spi_access_bus called with invalid device"); + + if (spi_enabled == 0) { + AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Enable Peripheral clock */ + controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */ +#ifdef DEBUG_SPI + printk("SPI on\n"); +#endif + } + MOD_INC_USE_COUNT; + spi_enabled++; + + /* Lock the SPI bus */ + down(&spi_lock); + current_device = device; + + /* Enable PIO */ + if (!spi_dev[device].pio_enabled) { + switch (device) { + case 0: AT91_CfgPIO_SPI_CS0(); break; + case 1: AT91_CfgPIO_SPI_CS1(); break; + case 2: AT91_CfgPIO_SPI_CS2(); break; + case 3: AT91_CfgPIO_SPI_CS3(); break; + } + spi_dev[device].pio_enabled = 1; +#ifdef DEBUG_SPI + printk("SPI CS%i enabled\n", device); +#endif + } + + /* Configure SPI bus for device */ + controller->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (spi_dev[device].pcs << 16); +} + +/* + * Relinquish control of the SPI bus. + */ +void spi_release_bus(short device) +{ + if (device != current_device) + panic("at91_spi: spi_release called with invalid device"); + + /* Release the SPI bus */ + current_device = -1; + up(&spi_lock); + + spi_enabled--; + MOD_DEC_USE_COUNT; + if (spi_enabled == 0) { + controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */ + AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Disable Peripheral clock */ +#ifdef DEBUG_SPI + printk("SPI off\n"); +#endif + } +} + +/* + * Perform a data transfer over the SPI bus + */ +int spi_transfer(struct spi_transfer_list* list) +{ + struct spi_local *device = (struct spi_local *) &spi_dev[current_device]; + + if (!list) + panic("at91_spi: spi_transfer called with NULL transfer list"); + if (current_device == -1) + panic("at91_spi: spi_transfer called without acquiring bus"); + +#ifdef DEBUG_SPI + printk("SPI transfer start [%i]\n", list->nr_transfers); +#endif + + /* Store transfer list */ + device->xfers = list; + list->curr = 0; + + /* Assume there must be at least one transfer */ + device->tx = pci_map_single(NULL, list->tx[0], list->txlen[0], PCI_DMA_TODEVICE); + device->rx = pci_map_single(NULL, list->rx[0], list->rxlen[0], PCI_DMA_FROMDEVICE); + + /* Program PDC registers */ + controller->SPI_TPR = device->tx; + controller->SPI_RPR = device->rx; + controller->SPI_TCR = list->txlen[0]; + controller->SPI_RCR = list->rxlen[0]; + + /* Is there a second transfer? */ + if (list->nr_transfers > 1) { + device->txnext = pci_map_single(NULL, list->tx[1], list->txlen[1], PCI_DMA_TODEVICE); + device->rxnext = pci_map_single(NULL, list->rx[1], list->rxlen[1], PCI_DMA_FROMDEVICE); + + /* Program Next PDC registers */ + controller->SPI_TNPR = device->txnext; + controller->SPI_RNPR = device->rxnext; + controller->SPI_TNCR = list->txlen[1]; + controller->SPI_RNCR = list->rxlen[1]; + } + else { + device->txnext = 0; + device->rxnext = 0; + controller->SPI_TNCR = 0; + controller->SPI_RNCR = 0; + } + + // TODO: If we are doing consecutive transfers (at high speed, or + // small buffers), then it might be worth modifying the 'Delay between + // Consecutive Transfers' in the CSR registers. + // This is an issue if we cannot chain the next buffer fast enough + // in the interrupt handler. + + /* Enable transmitter and receiver */ + controller->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN; + + controller->SPI_IER = AT91C_SPI_SPENDRX; /* enable buffer complete interrupt */ + wait_for_completion(&transfer_complete); + +#ifdef DEBUG_SPI + printk("SPI transfer end\n"); +#endif + + return 0; +} + +/* ......................................................................... */ + +/* + * Handle interrupts from the SPI controller. + */ +static void spi_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int status; + struct spi_local *device = (struct spi_local *) &spi_dev[current_device]; + struct spi_transfer_list *list = device->xfers; + +#ifdef DEBUG_SPI + printk("SPI interrupt %i\n", current_device); +#endif + + if (!list) + panic("at91_spi: spi_interrupt with a NULL transfer list"); + + status = controller->SPI_SR & controller->SPI_IMR; /* read status */ + + pci_unmap_single(NULL, device->tx, list->txlen[list->curr], PCI_DMA_TODEVICE); + pci_unmap_single(NULL, device->rx, list->rxlen[list->curr], PCI_DMA_FROMDEVICE); + + device->tx = device->txnext; /* move next transfer to current transfer */ + device->rx = device->rxnext; + + list->curr = list->curr + 1; + if (list->curr == list->nr_transfers) { /* all transfers complete */ + controller->SPI_IDR = AT91C_SPI_SPENDRX; /* disable interrupt */ + + /* Disable transmitter and receiver */ + controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS; + + device->xfers = NULL; + complete(&transfer_complete); + } + else if (list->curr+1 == list->nr_transfers) { /* no more next transfers */ + device->txnext = 0; + device->rxnext = 0; + controller->SPI_TNCR = 0; + controller->SPI_RNCR = 0; + } + else { + int i = (list->curr)+1; + + device->txnext = pci_map_single(NULL, list->tx[i], list->txlen[i], PCI_DMA_TODEVICE); + device->rxnext = pci_map_single(NULL, list->rx[i], list->rxlen[i], PCI_DMA_FROMDEVICE); + controller->SPI_TNPR = device->txnext; + controller->SPI_RNPR = device->rxnext; + controller->SPI_TNCR = list->txlen[i]; + controller->SPI_RNCR = list->rxlen[i]; + } +} + +/* ......................................................................... */ + +/* + * Initialize the SPI controller + */ +static int __init at91_spi_init(void) +{ + init_MUTEX(&spi_lock); + + AT91_CfgPIO_SPI(); + + controller->SPI_CR = AT91C_SPI_SWRST; /* software reset of SPI controller */ + + /* Set Chip Select registers to good defaults */ + controller->SPI_CSR0 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8); + controller->SPI_CSR1 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8); + controller->SPI_CSR2 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8); + controller->SPI_CSR3 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8); + + controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS; + + memset(&spi_dev, 0, sizeof(spi_dev)); + spi_dev[0].pcs = 0xE; + spi_dev[1].pcs = 0xD; + spi_dev[2].pcs = 0xB; + spi_dev[3].pcs = 0x7; + + if (request_irq(AT91C_ID_SPI, spi_interrupt, 0, "spi", NULL)) + return -EBUSY; + + controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */ + + return 0; +} + +static void at91_spi_exit(void) +{ + controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */ + + free_irq(AT91C_ID_SPI, 0); +} + + +EXPORT_SYMBOL(spi_access_bus); +EXPORT_SYMBOL(spi_release_bus); +EXPORT_SYMBOL(spi_transfer); + +module_init(at91_spi_init); +module_exit(at91_spi_exit); + +MODULE_LICENSE("GPL") +MODULE_AUTHOR("Andrew Victor") +MODULE_DESCRIPTION("SPI driver for Atmel AT91RM9200") diff -uNr linux-2.4.37.9/drivers/at91/spi/at91_spi.h linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/at91_spi.h --- linux-2.4.37.9/drivers/at91/spi/at91_spi.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/at91_spi.h Wed May 26 15:51:20 2010 @@ -0,0 +1,56 @@ +/* + * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 + * + * (c) SAN People (Pty) Ltd + * + * 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. + */ + +#ifndef AT91_SPI_H +#define AT91_SPI_H + +/* Maximum number of buffers in a single SPI transfer. + * DataFlash uses maximum of 2 + * spidev interface supports up to 8. + */ +#define MAX_SPI_TRANSFERS 8 + +#define NR_SPI_DEVICES 4 /* number of devices on SPI bus */ + +#define DATAFLASH_CLK 6000000 +#define DEFAULT_SPI_BAUD AT91C_MASTER_CLOCK / (2 * DATAFLASH_CLK) + +#define SPI_MAJOR 153 /* registered device number */ + +/* + * Describes the buffers for a SPI transfer. + * A transmit & receive buffer must be specified for each transfer + */ +struct spi_transfer_list { + void* tx[MAX_SPI_TRANSFERS]; /* transmit */ + int txlen[MAX_SPI_TRANSFERS]; + void* rx[MAX_SPI_TRANSFERS]; /* receive */ + int rxlen[MAX_SPI_TRANSFERS]; + int nr_transfers; /* number of transfers */ + int curr; /* current transfer */ +}; + +struct spi_local { + unsigned int pcs; /* Peripheral Chip Select value */ + short pio_enabled; /* has PIO been enabled? */ + + struct spi_transfer_list *xfers; /* current transfer list */ + dma_addr_t tx, rx; /* DMA address for current transfer */ + dma_addr_t txnext, rxnext; /* DMA address for next transfer */ +}; + + +/* Exported functions */ +extern void spi_access_bus(short device); +extern void spi_release_bus(short device); +extern int spi_transfer(struct spi_transfer_list* list); + +#endif diff -uNr linux-2.4.37.9/drivers/at91/spi/at91_spidev.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/at91_spidev.c --- linux-2.4.37.9/drivers/at91/spi/at91_spidev.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/spi/at91_spidev.c Wed May 26 15:51:20 2010 @@ -0,0 +1,226 @@ +/* + * User-space interface to the SPI bus on Atmel AT91RM9200 + * + * (c) SAN People (Pty) Ltd + * + * Based on SPI driver by Rick Bronson + * + * 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 +#include +#include +#include +#include +#include + +#ifdef CONFIG_DEVFS_FS +#include +#endif + +#include "at91_spi.h" + +#undef DEBUG_SPIDEV + +#ifdef CONFIG_DEVFS_FS +static devfs_handle_t devfs_handle = NULL; +static devfs_handle_t devfs_spi[NR_SPI_DEVICES]; +#endif + +/* ......................................................................... */ + +/* + * Read or Write to SPI bus. + */ +static ssize_t spidev_rd_wr(struct file *file, char *buf, size_t count, loff_t *offset) +{ + unsigned int spi_device = (unsigned int) file->private_data; + struct kiobuf *iobuf; + unsigned int ofs, pagelen; + int res, i; + + struct spi_transfer_list* list = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL); + if (!list) + return -ENOMEM; + + res = alloc_kiovec(1, &iobuf); + if (res) { + kfree(list); + return res; + } + + res = map_user_kiobuf(READ, iobuf, (unsigned long) buf, count); + if (res) { + free_kiovec(1, &iobuf); + kfree(list); + return res; + } + + /* More pages than transfer slots in spi_transfer_list */ + if (iobuf->nr_pages >= MAX_SPI_TRANSFERS) { + unmap_kiobuf(iobuf); + free_kiovec(1, &iobuf); + kfree(list); + return -EFBIG; + } + +#ifdef DEBUG_SPIDEV + printk("spidev_rd_rw: %i %i\n", count, iobuf->nr_pages); +#endif + + /* Set default return value = transfer length */ + res = count; + + /* + * At this point, the virtual area buf[0] .. buf[count-1] will have + * corresponding pages mapped in the physical memory and locked until + * we unmap the kiobuf. The pages cannot be swapped out or moved + * around. + */ + ofs = iobuf->offset; + pagelen = PAGE_SIZE - iobuf->offset; + if (count < pagelen) + pagelen = count; + + for (i = 0; i < iobuf->nr_pages; i++) { + list->tx[i] = list->rx[i] = page_address(iobuf->maplist[i]) + ofs; + list->txlen[i] = list->rxlen[i] = pagelen; + +#ifdef DEBUG_SPIDEV + printk(" %i: %x (%i)\n", i, list->tx[i], list->txlen[i]); +#endif + + ofs = 0; /* all subsequent transfers start at beginning of a page */ + count = count - pagelen; + pagelen = (count < PAGE_SIZE) ? count : PAGE_SIZE; + } + list->nr_transfers = iobuf->nr_pages; + + /* Perform transfer on SPI bus */ + spi_access_bus(spi_device); + spi_transfer(list); + spi_release_bus(spi_device); + + unmap_kiobuf(iobuf); + free_kiovec(1, &iobuf); + kfree(list); + + return res; +} + +static int spidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int spi_device = MINOR(inode->i_rdev); + + if (spi_device >= NR_SPI_DEVICES) + return -ENODEV; + + // TODO: This interface can be used to configure the SPI bus. + // Configurable options could include: Speed, Clock Polarity, Clock Phase + + switch(cmd) { + default: + return -ENOIOCTLCMD; + } +} + +/* + * Open the SPI device + */ +static int spidev_open(struct inode *inode, struct file *file) +{ + unsigned int spi_device = MINOR(inode->i_rdev); + + if (spi_device >= NR_SPI_DEVICES) + return -ENODEV; + + MOD_INC_USE_COUNT; + + /* + * 'private_data' is actually a pointer, but we overload it with the + * value we want to store. + */ + (unsigned int) file->private_data = spi_device; + + return 0; +} + +/* + * Close the SPI device + */ +static int spidev_close(struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +/* ......................................................................... */ + +static struct file_operations spidev_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + read: spidev_rd_wr, + write: spidev_rd_wr, + ioctl: spidev_ioctl, + open: spidev_open, + release: spidev_close, +}; + +/* + * Install the SPI /dev interface driver + */ +static int __init at91_spidev_init(void) +{ + int i; + char name[3]; + +#ifdef CONFIG_DEVFS_FS + if (devfs_register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) { +#else + if (register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) { +#endif + printk(KERN_ERR "at91_spidev: Unable to get major %d for SPI bus\n", SPI_MAJOR); + return -EIO; + } + +#ifdef CONFIG_DEVFS_FS + devfs_handle = devfs_mk_dir(NULL, "spi", NULL); + + for (i = 0; i < NR_SPI_DEVICES; i++) { + sprintf (name, "%d", i); + devfs_spi[i] = devfs_register (devfs_handle, name, + DEVFS_FL_DEFAULT, SPI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, + &spidev_fops, NULL); + } +#endif + printk(KERN_INFO "AT91 SPI driver loaded\n"); + + return 0; +} + +/* + * Remove the SPI /dev interface driver + */ +static void __exit at91_spidev_exit(void) +{ +#ifdef CONFIG_DEVFS_FS + devfs_unregister(devfs_handle); + if (devfs_unregister_chrdev(SPI_MAJOR, "spi")) { +#else + if (unregister_chrdev(SPI_MAJOR,"spi")) { +#endif + printk(KERN_ERR "at91_spidev: Unable to release major %d for SPI bus\n", SPI_MAJOR); + return; + } +} + +module_init(at91_spidev_init); +module_exit(at91_spidev_exit); + +MODULE_LICENSE("GPL") +MODULE_AUTHOR("Andrew Victor") +MODULE_DESCRIPTION("SPI /dev interface for Atmel AT91RM9200") diff -uNr linux-2.4.37.9/drivers/at91/usb/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/usb/Makefile --- linux-2.4.37.9/drivers/at91/usb/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/usb/Makefile Wed May 26 15:51:20 2010 @@ -0,0 +1,17 @@ +# File: drivers/at91/usb/Makefile +# +# Makefile for the Atmel AT91RM9200 USB device drivers +# + +O_TARGET := at91usb.o + +export-objs := + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_USB_OHCI_AT91) += at91_usb-ohci.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/usb/at91_usb-ohci.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/usb/at91_usb-ohci.c --- linux-2.4.37.9/drivers/at91/usb/at91_usb-ohci.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/usb/at91_usb-ohci.c Wed May 26 15:51:20 2010 @@ -0,0 +1,85 @@ +/* + * linux/drivers/at91/usb/at91_usb_ohci-at91.c + * + * (c) Rick Bronson + * + * The outline of this code was taken from Brad Parkers + * original OHCI driver modifications, and reworked into a cleaner form + * by Russell King . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + NOTE: + The following is so that we don't have to include usb-ohci.h or pci.h as the + usb-ohci.c driver needs these routines even when the architecture + has no PCI bus... +*/ + +extern int __devinit hc_add_ohci(struct pci_dev *dev, int irq, void *membase, + unsigned long flags, void *ohci, const char *name, + const char *slot_name); +extern void hc_remove_ohci(void *ohci); + +static void *at91_ohci; +AT91PS_UHP ohci_regs; + +static int __init at91_ohci_init(void) +{ + int ret; + + ohci_regs = ioremap(AT91_UHP_BASE, SZ_4K); + if (!ohci_regs) { + printk(KERN_ERR "at91_usb-ohci: ioremap failed\n"); + return -EIO; + } + + /* Enable PLLB */ + AT91_SYS->CKGR_PLLBR = AT91_PLLB_INIT; + while ((AT91_SYS->PMC_SR & 4) == 0); + + /* Now, enable the USB clock */ + AT91_SYS->PMC_SCER = AT91C_PMC_UHP; /* enable system clock */ + AT91_SYS->PMC_PCER = 1 << AT91C_ID_UHP; /* enable peripheral clock */ + + /* Take Hc out of reset */ + ohci_regs->UHP_HcControl = 2 << 6; + + /* Initialise the generic OHCI driver. */ + ret = hc_add_ohci((struct pci_dev *) 1, AT91C_ID_UHP, + (void *)ohci_regs, 0, &at91_ohci, + "usb-ohci", "at91"); + if (ret) + iounmap(ohci_regs); + + return ret; +} + +static void __exit at91_ohci_exit(void) +{ + hc_remove_ohci(at91_ohci); + + /* Force UHP_Hc to reset */ + ohci_regs->UHP_HcControl = 0; + + /* Stop the USB clock. */ + AT91_SYS->PMC_SCDR = AT91C_PMC_UHP; /* disable system clock */ + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_UHP; /* disable peripheral clock */ + + iounmap(ohci_regs); +} + +module_init(at91_ohci_init); +module_exit(at91_ohci_exit); diff -uNr linux-2.4.37.9/drivers/at91/watchdog/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/at91/watchdog/Makefile --- linux-2.4.37.9/drivers/at91/watchdog/Makefile Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/watchdog/Makefile Wed May 26 15:51:19 2010 @@ -0,0 +1,15 @@ +# File: drivers/at91/watchdog/Makefile +# +# Makefile for the Atmel AT91RM9200 watchdog device driver +# + +O_TARGET := at91wdt.o + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o + +include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/at91/watchdog/at91_wdt.c linux-2.4.37.9-vrs1-5mx2/drivers/at91/watchdog/at91_wdt.c --- linux-2.4.37.9/drivers/at91/watchdog/at91_wdt.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/at91/watchdog/at91_wdt.c Wed May 26 15:51:19 2010 @@ -0,0 +1,193 @@ +/* + * Watchdog driver for Atmel AT91RM9200 (Thunder) + * + * (c) SAN People (Pty) Ltd + * + * 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 +#include +#include +#include +#include +#include + +#define WDT_DEFAULT_TIME 5 /* 5 seconds */ +#define WDT_MAX_TIME 256 /* 256 seconds */ + +static int at91wdt_time = WDT_DEFAULT_TIME; +static int at91wdt_busy; + +/* ......................................................................... */ + +/* + * Disable the watchdog. + */ +static void at91_wdt_stop(void) +{ + AT91_SYS->ST_WDMR = AT91C_ST_EXTEN; +} + +/* + * Enable and reset the watchdog. + */ +static void at91_wdt_start(void) +{ + AT91_SYS->ST_WDMR = AT91C_ST_EXTEN | AT91C_ST_RSTEN | (((65536 * at91wdt_time) >> 8) & AT91C_ST_WDV); + AT91_SYS->ST_CR = AT91C_ST_WDRST; +} + +/* ......................................................................... */ + +/* + * Watchdog device is opened, and watchdog starts running. + */ +static int at91_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(1, &at91wdt_busy)) + return -EBUSY; + MOD_INC_USE_COUNT; + + /* + * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz + * + * Since WDV is a 16-bit counter, the maximum period is + * 65536 / 0.256 = 256 seconds. + */ + + at91_wdt_start(); + return 0; +} + +/* + * Close the watchdog device. + * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also + * disabled. + */ +static int at91_wdt_close(struct inode *inode, struct file *file) +{ +#ifndef CONFIG_WATCHDOG_NOWAYOUT + /* Disable the watchdog when file is closed */ + at91_wdt_stop(); +#endif + + at91wdt_busy = 0; + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Handle commands from user-space. + */ +static int at91_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned int new_value; + static struct watchdog_info info = { + identity: "at91 watchdog", + options: WDIOF_SETTIMEOUT, + }; + + switch(cmd) { + case WDIOC_KEEPALIVE: + AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */ + return 0; + + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &info, sizeof(info)); + + case WDIOC_SETTIMEOUT: + if (get_user(new_value, (int *)arg)) + return -EFAULT; + if ((new_value <= 0) || (new_value > WDT_MAX_TIME)) + return -EINVAL; + + /* Restart watchdog with new time */ + at91wdt_time = new_value; + at91_wdt_start(); + + /* Return current value */ + return put_user(at91wdt_time, (int *)arg); + + case WDIOC_GETTIMEOUT: + return put_user(at91wdt_time, (int *)arg); + + case WDIOC_GETSTATUS: + return put_user(0, (int *)arg); + + case WDIOC_SETOPTIONS: + if (get_user(new_value, (int *)arg)) + return -EFAULT; + if (new_value & WDIOS_DISABLECARD) + at91_wdt_stop(); + if (new_value & WDIOS_ENABLECARD) + at91_wdt_start(); + return 0; + + default: + return -ENOIOCTLCMD; + } +} + +/* + * Pat the watchdog whenever device is written to. + */ +static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (len) { + AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */ + return len; + } + + return 0; +} + +/* ......................................................................... */ + +static struct file_operations at91wdt_fops = +{ + .owner = THIS_MODULE, + .ioctl = at91_wdt_ioctl, + .open = at91_wdt_open, + .release = at91_wdt_close, + .write = at91_wdt_write, +}; + +static struct miscdevice at91wdt_miscdev = +{ + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &at91wdt_fops, +}; + +static int __init at91_wdt_init(void) +{ + int res; + + res = misc_register(&at91wdt_miscdev); + if (res) + return res; + + printk("AT91 Watchdog Timer enabled (%d seconds)\n", WDT_DEFAULT_TIME); + return 0; +} + +static void __exit at91_wdt_exit(void) +{ + misc_deregister(&at91wdt_miscdev); +} + +module_init(at91_wdt_init); +module_exit(at91_wdt_exit); + +MODULE_LICENSE("GPL") +MODULE_AUTHOR("Andrew Victor") +MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200") diff -uNr linux-2.4.37.9/drivers/block/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/block/Makefile --- linux-2.4.37.9/drivers/block/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/block/Makefile Wed May 26 15:50:08 2010 @@ -27,12 +27,18 @@ obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o obj-$(CONFIG_BLK_DEV_XD) += xd.o obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o -obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o +obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o obj-$(CONFIG_BLK_DEV_UMEM) += umem.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o obj-$(CONFIG_BLK_DEV_SX8) += sx8.o subdir-$(CONFIG_PARIDE) += paride + +ifeq ($(CONFIG_ARCH_ACORN),y) +mod-subdirs += ../acorn/block +subdir-y += ../acorn/block +obj-y += ../acorn/block/acorn-block.o +endif include $(TOPDIR)/Rules.make diff -uNr linux-2.4.37.9/drivers/block/ll_rw_blk.c linux-2.4.37.9-vrs1-5mx2/drivers/block/ll_rw_blk.c --- linux-2.4.37.9/drivers/block/ll_rw_blk.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/block/ll_rw_blk.c Mon Jun 7 18:47:47 2010 @@ -32,6 +32,19 @@ #include #include +/* Maybe something to cleanup in 2.3? + * We shouldn't touch 0x3f2 on machines which don't have a PC floppy controller + * - it may contain something else which could cause a system hang. This is + * now selected by a configuration option, but maybe it ought to be in the + * floppy code itself? - rmk + */ +#if defined(__i386__) || (defined(__arm__) && defined(CONFIG_ARCH_ACORN)) +#define FLOPPY_BOOT_DISABLE +#endif +#ifdef CONFIG_BLK_DEV_FD +#undef FLOPPY_BOOT_DISABLE +#endif + /* * MAC Floppy IWM hooks */ @@ -519,7 +532,7 @@ elevator_init(&q->elevator, ELEVATOR_LINUS); blk_init_free_list(q); q->request_fn = rfn; - q->back_merge_fn = ll_back_merge_fn; + q->back_merge_fn = ll_back_merge_fn; q->front_merge_fn = ll_front_merge_fn; q->merge_requests_fn = ll_merge_requests_fn; q->make_request_fn = __make_request; @@ -1550,7 +1563,7 @@ mfm_init(); #endif #ifdef CONFIG_PARIDE - { extern void paride_init(void); paride_init(); }; + { extern void paride_init(void); paride_init(); } #endif #ifdef CONFIG_MAC_FLOPPY swim3_init(); @@ -1564,12 +1577,14 @@ #ifdef CONFIG_ATARI_FLOPPY atari_floppy_init(); #endif +#ifdef CONFIG_BLK_DEV_FD1772 + fd1772_init(); +#endif #ifdef CONFIG_BLK_DEV_FD floppy_init(); -#else -#if defined(__i386__) /* Do we even need this? */ - outb_p(0xc, 0x3f2); #endif +#ifdef FLOPPY_BOOT_DISABLE + outb_p(0xc, 0x3f2); #endif #ifdef CONFIG_CDU31A cdu31a_init(); @@ -1627,7 +1642,7 @@ jsfd_init(); #endif return 0; -}; +} EXPORT_SYMBOL(io_request_lock); EXPORT_SYMBOL(end_that_request_first); diff -uNr linux-2.4.37.9/drivers/cdrom/cdrom.c linux-2.4.37.9-vrs1-5mx2/drivers/cdrom/cdrom.c --- linux-2.4.37.9/drivers/cdrom/cdrom.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/cdrom/cdrom.c Mon Jun 7 18:47:15 2010 @@ -246,8 +246,8 @@ #define CD_DVD 0x80 /* Define this to remove _all_ the debugging messages */ -/* #define ERRLOGMASK CD_NOTHING */ -#define ERRLOGMASK (CD_WARNING) +#define ERRLOGMASK CD_NOTHING +/* #define ERRLOGMASK (CD_WARNING) */ /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */ /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */ diff -uNr linux-2.4.37.9/drivers/char/Config.in linux-2.4.37.9-vrs1-5mx2/drivers/char/Config.in --- linux-2.4.37.9/drivers/char/Config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/Config.in Mon Jun 7 19:04:33 2010 @@ -20,10 +20,10 @@ if [ "$CONFIG_IA64" = "y" ]; then bool ' Support for serial port described by EFI HCDP table' CONFIG_SERIAL_HCDP fi - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL - tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL - fi +fi +if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + dep_tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL $CONFIG_SERIAL + dep_tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL $CONFIG_SERIAL fi dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then @@ -133,19 +133,6 @@ bool ' SGI SN2 IOC4 serial port support' CONFIG_SGI_IOC4_SERIAL fi fi -fi -if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then - bool ' Enable broken drivers for Commodore cards (may randomly crash)' CONFIG_A2232_BROKEN - dep_tristate 'Commodore A2232 serial support (broken) (EXPERIMENTAL)' CONFIG_A2232 $CONFIG_A2232_BROKEN -fi -if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then - bool 'DC21285 serial port support' CONFIG_SERIAL_21285 - if [ "$CONFIG_SERIAL_21285" = "y" ]; then - if [ "$CONFIG_OBSOLETE" = "y" ]; then - bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD - fi - bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE - fi if [ "$CONFIG_PARISC" = "y" ]; then bool ' PDC software console support' CONFIG_PDC_CONSOLE fi @@ -170,6 +157,28 @@ if [ "$CONFIG_CPU_VR41XX" = "y" ]; then bool 'NEC VR4100 series Keyboard Interface Unit Support ' CONFIG_VR41XX_KIU fi +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then + tristate 'AT91RM9200 SPI device interface' CONFIG_AT91_SPIDEV +fi + +source drivers/serial/Config.in + +if [ "$CONFIG_ARCH_ANAKIN" = "y" ]; then + tristate 'Anakin touchscreen support' CONFIG_TOUCHSCREEN_ANAKIN +fi + +if [ "$CONFIG_ARCH_PSIONW" = "y" ]; then + mainmenu_option next_comment + comment 'Psion Windermere Keyboard Locale' + choice 'Psion-Windermere Keyboard Locale' \ + "Psion-UK-Keyboard CONFIG_PSION_KBD_UK \ + Psion-US-Keyboard CONFIG_PSION_KBD_US \ + Psion-DE-Keyboard CONFIG_PSION_KBD_DE \ + Psion-FR-Keyboard CONFIG_PSION_KBD_FR" CONFIG_PSION_KBD_UK + endmenu + bool '/proc/psionw support' CONFIG_PROCFS_PSION +fi + bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 @@ -192,6 +201,12 @@ source drivers/i2c/Config.in +if [ "$CONFIG_I2C" != "n" ]; then + dep_tristate ' DS1307 RTC' CONFIG_I2C_DS1307 $CONFIG_I2C +fi + +source drivers/l3/Config.in + mainmenu_option next_comment comment 'Mice' tristate 'Bus Mouse Support' CONFIG_BUSMOUSE @@ -247,11 +262,13 @@ tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG - if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then - tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG - if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then - tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG - fi + if [ "$CONFIG_ARM" = "y" ]; then + dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE + dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER + dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100 + dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT + dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA + dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200 fi tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT @@ -299,6 +316,9 @@ if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ] ; then bool 'SGI SN2 fetchop support' CONFIG_FETCHOP fi +if [ "$CONFIG_ARCH_PSIONW" = "y" ]; then + tristate 'Psion Windermere Real Time Clock' CONFIG_PSIONW_RTC +fi if [ "$CONFIG_X86" = "y" -o "$CONFIG_X86_64" = "y" ]; then dep_tristate 'AMD 768/8111 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI @@ -333,6 +353,15 @@ fi if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then tristate 'Dallas DS1742 RTC support' CONFIG_DS1742 +fi +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then + tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC +fi +if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then + tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC +fi +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then + tristate 'AT91RM9200 Real Time Clock' CONFIG_AT91_RTC fi tristate 'Double Talk PC internal speech card support' CONFIG_DTLK diff -uNr linux-2.4.37.9/drivers/char/Makefile linux-2.4.37.9-vrs1-5mx2/drivers/char/Makefile --- linux-2.4.37.9/drivers/char/Makefile Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/Makefile Mon Jun 7 18:59:41 2010 @@ -29,7 +29,7 @@ mod-subdirs := joystick ftape drm drm-4.0 pcmcia -list-multi := +list-multi := KEYMAP =defkeymap.o KEYBD =pc_keyb.o @@ -106,11 +106,39 @@ endif ifeq ($(ARCH),arm) - ifneq ($(CONFIG_PC_KEYMAP),y) - KEYMAP = + KEYMAP := + KEYBD := + ifeq ($(CONFIG_PC_KEYMAP),y) + KEYMAP := defkeymap.o endif - ifneq ($(CONFIG_PC_KEYB),y) - KEYBD = + ifeq ($(CONFIG_PC_KEYB),y) + KEYBD += pc_keyb.o + endif + ifeq ($(CONFIG_KMI_KEYB),y) + KEYBD += amba_kmi_keyb.o + endif + ifeq ($(CONFIG_SA1111),y) + KEYBD += sa1111_keyb.o + endif + ifeq ($(CONFIG_ARCH_EDB7211),y) + KEYBD += edb7211_keyb.o + endif + ifeq ($(CONFIG_ARCH_AUTCPU12),y) + KEYMAP := defkeymap.o + KEYBD += clps711x_keyb.o + endif + ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) + KEYMAP = gckeymap.o + KEYBD += gc_keyb.o + endif + ifeq ($(CONFIG_SA1100_CERF_CPLD),y) + KEYBD += cerf_keyb.o + endif + ifeq ($(CONFIG_ARCH_FORTUNET),y) + KEYMAP := defkeymap.o + endif + ifeq ($(CONFIG_ARCH_GUIDEA07),y) + KEYMAP := defkeymap.o endif endif @@ -173,11 +201,9 @@ obj-$(CONFIG_SERIAL) += $(SERIAL) obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o -obj-$(CONFIG_SERIAL_21285) += serial_21285.o -obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o -obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o obj-$(CONFIG_TS_AU1X00_ADS7846) += au1000_ts.o obj-$(CONFIG_SERIAL_DEC) += decserial.o +obj-$(CONFIG_TOUCHSCREEN_ANAKIN) += anakin_ts.o ifndef CONFIG_SUN_KEYBOARD obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD) @@ -254,6 +280,9 @@ obj-$(CONFIG_SGI_DS1286) += ds1286.o obj-$(CONFIG_MIPS_RTC) += mips_rtc.o obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o +obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o +obj-$(CONFIG_PSIONW_RTC) += psionw-rtc.o +obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o ifeq ($(CONFIG_PPC),) obj-$(CONFIG_NVRAM) += nvram.o endif @@ -293,6 +322,7 @@ obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200) += scx200.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o +obj-$(CONFIG_SA1100_CONSUS) += consusbutton.o # Only one watchdog can succeed. We probe the hardware watchdog # drivers first, then the softdog driver. This means if your hardware @@ -321,6 +351,9 @@ obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o +obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o +obj-$(CONFIG_EPXA_WATCHDOG) += epxa_wdt.o +obj-$(CONFIG_OMAHA_WATCHDOG) += omaha_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o @@ -328,16 +361,50 @@ obj-$(CONFIG_WDT_W83627) += wdt83627.o obj-$(CONFIG_W83977EF_WDT) += wdt83977.o +# I2C char devices +obj-$(CONFIG_I2C_DS1307) += ds1307.o + subdir-$(CONFIG_MWAVE) += mwave ifeq ($(CONFIG_MWAVE),y) obj-y += mwave/mwave.o endif +ifeq ($(CONFIG_ARCH_ACORN),y) +mod-subdirs += ../acorn/char +subdir-y += ../acorn/char +obj-y += ../acorn/char/acorn-char.o +endif + subdir-$(CONFIG_IPMI_HANDLER) += ipmi ifeq ($(CONFIG_IPMI_HANDLER),y) obj-y += ipmi/ipmi.o endif +ifeq ($(CONFIG_ARCH_PSIONW),y) + KEYBD =keyboard_psion.o + CONSOLE =console.o + obj-y += keyboard_psion.o + ifeq ($(CONFIG_PSION_KBD_UK),y) + KEYMAP =keymap_psion.o + obj-y += keymap_psion.o + endif + ifeq ($(CONFIG_PSION_KBD_US),y) + KEYMAP =keymap_psion_us.o + obj-y += keymap_psion_us.o + endif + ifeq ($(CONFIG_PSION_KBD_DE),y) + KEYMAP =keymap_psion_de.o + obj-y += keymap_psion_de.o + endif + ifeq ($(CONFIG_PSION_KBD_FR),y) + KEYMAP =keymap_psion_fr.o + obj-y += keymap_psion_fr.o + endif + ifeq ($(CONFIG_PROCFS_PSION),y) + obj-y += psionw_procfs.o + endif +endif + include $(TOPDIR)/Rules.make fastdep: @@ -353,7 +420,20 @@ .DELETE_ON_ERROR: defkeymap.c: defkeymap.map - set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ + set -e ; loadkeys -u --mktable $< | sed -e 's/^static *//' > $@ qtronixmap.c: qtronixmap.map - set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ + set -e ; loadkeys -u --mktable $< | sed -e 's/^static *//' > $@ + +keymap_psion.c: keymap_psion.map + set -e ; loadkeys -u --mktable $< | sed -e 's/^static *//' > $@ + +keymap_psion_us.c: keymap_psion_us.map + set -e ; loadkeys -u --mktable $< | sed -e 's/^static *//' > $@ + +keymap_psion_de.c: keymap_psion_de.map + set -e ; loadkeys -u --mktable $< | sed -e 's/^static *//' > $@ + +keymap_psion_fr.c: keymap_psion_fr.map + set -e ; loadkeys -u --mktable $< | sed -e 's/^static *//' > $@ + diff -uNr linux-2.4.37.9/drivers/char/amba_kmi_keyb.c linux-2.4.37.9-vrs1-5mx2/drivers/char/amba_kmi_keyb.c --- linux-2.4.37.9/drivers/char/amba_kmi_keyb.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/amba_kmi_keyb.c Wed May 26 15:48:46 2010 @@ -0,0 +1,999 @@ +/* + * linux/drivers/char/amba_kmi_keyb.c + * + * AMBA Keyboard and Mouse Interface Driver + * + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * + * 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 + * + * This keyboard driver drives a PS/2 keyboard and mouse connected + * to the KMI interfaces. The KMI interfaces are nothing more than + * a uart; there is no inteligence in them to do keycode translation. + * We leave all that up to the keyboard itself. + * + * FIXES: + * dirk.uffmann@nokia.com: enabled PS/2 reconnection + */ +#include +#include +#include +#include /* for in_interrupt */ +#include +#include +#include /* for udelay */ +#include /* for keyboard_tasklet */ +#include + +#include +#include +#include +#include + +//#define DEBUG(s) printk s +#define DEBUG(s) do { } while (0) + +#define CONFIG_AMBA_PS2_RECONNECT + +#define KMI_BASE (kmi->base) + +#define KMI_RESET 0x00 +#define KMI_RESET_POR 0x01 +#define KMI_RESET_DONE 0x02 + +#define KMI_NO_ACK 0xffff + +#define PS2_O_RESET 0xff +#define PS2_O_RESEND 0xfe +#define PS2_O_DISABLE 0xf5 +#define PS2_O_ENABLE 0xf4 +#define PS2_O_ECHO 0xee + +/* + * Keyboard + */ +#define PS2_O_SET_DEFAULT 0xf6 +#define PS2_O_SET_RATE_DELAY 0xf3 +#define PS2_O_SET_SCANSET 0xf0 +#define PS2_O_INDICATORS 0xed + +/* + * Mouse + */ +#define PS2_O_SET_SAMPLE 0xf3 +#define PS2_O_SET_STREAM 0xea +#define PS2_O_SET_RES 0xe8 +#define PS2_O_SET_SCALE21 0xe7 +#define PS2_O_SET_SCALE11 0xe6 +#define PS2_O_REQ_STATUS 0xe9 + +/* + * Responses + */ +#define PS2_I_RESEND 0xfe +#define PS2_I_DIAGFAIL 0xfc +#define PS2_I_ACK 0xfa +#define PS2_I_BREAK 0xf0 +#define PS2_I_ECHO 0xee +#define PS2_I_BAT_OK 0xaa + +static char *kmi_type[] = { "Keyboard", "Mouse" }; + +static struct kmi_info *kmi_keyb; +static struct kmi_info *kmi_mouse; + +static inline void __kmi_send(struct kmi_info *kmi, u_int val) +{ + u_int status; + + do { + status = __raw_readb(KMISTAT); + } while (!(status & KMISTAT_TXEMPTY)); + + kmi->resend_count += 1; + __raw_writeb(val, KMIDATA); +} + +static void kmi_send(struct kmi_info *kmi, u_int val) +{ + kmi->last_tx = val; + kmi->resend_count = -1; + __kmi_send(kmi, val); +} + +static u_int kmi_send_and_wait(struct kmi_info *kmi, u_int val, u_int timeo) +{ + DECLARE_WAITQUEUE(wait, current); + + if (kmi->present == 0) + return KMI_NO_ACK; + + kmi->res = KMI_NO_ACK; + kmi->last_tx = val; + kmi->resend_count = -1; + + if (current->pid != 0 && !in_interrupt()) { + add_wait_queue(&kmi->wait_q, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + __kmi_send(kmi, val); + schedule_timeout(timeo); + current->state = TASK_RUNNING; + remove_wait_queue(&kmi->wait_q, &wait); + } else { + int i; + + __kmi_send(kmi, val); + for (i = 0; i < 1000; i++) { + if (kmi->res != KMI_NO_ACK) + break; + udelay(100); + } + } + + return kmi->res; +} + +/* + * This lot should probably be separated into a separate file... + */ +#ifdef CONFIG_KMI_MOUSE + +#include /* for struct file_ops */ +#include /* for poll_table */ +#include /* for struct miscdev */ +#include /* for add_mouse_randomness */ +#include /* for kmalloc */ +#include /* for {un,}lock_kernel */ +#include + +#include + +#define BUF_SZ 2048 + +static spinlock_t kmi_mouse_lock; +static int kmi_mouse_count; +static struct queue { + u_int head; + u_int tail; + struct fasync_struct *fasync; + unsigned char buf[BUF_SZ]; +} *queue; + +#define queue_empty() (queue->head == queue->tail) + +static u_char get_from_queue(void) +{ + unsigned long flags; + u_char res; + + spin_lock_irqsave(&kmi_mouse_lock, flags); + res = queue->buf[queue->tail]; + queue->tail = (queue->tail + 1) & (BUF_SZ-1); + spin_unlock_irqrestore(&kmi_mouse_lock, flags); + + return res; +} + +static ssize_t +kmi_mouse_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + ssize_t i = count; + + if (queue_empty()) { + int ret; + + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + ret = wait_event_interruptible(kmi_mouse->wait_q, !queue_empty()); + if (ret) + return ret; + } + while (i > 0 && !queue_empty()) { + u_char c; + c = get_from_queue(); + put_user(c, buf++); + i--; + } + if (count - i) + file->f_dentry->d_inode->i_atime = CURRENT_TIME; + return count - i; +} + +static ssize_t +kmi_mouse_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + ssize_t retval = 0; + + if (count > 32) + count = 32; + + do { + char c; + get_user(c, buf++); + kmi_send_and_wait(kmi_mouse, c, HZ); + retval++; + } while (--count); + + if (retval) + file->f_dentry->d_inode->i_mtime = CURRENT_TIME; + + return retval; +} + +static unsigned int +kmi_mouse_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &kmi_mouse->wait_q, wait); + return (!queue_empty()) ? POLLIN | POLLRDNORM : 0; +} + +static int +kmi_mouse_release(struct inode *inode, struct file *file) +{ + lock_kernel(); + fasync_helper(-1, file, 0, &queue->fasync); + if (--kmi_mouse_count == 0) + kmi_send_and_wait(kmi_mouse, PS2_O_DISABLE, HZ); + unlock_kernel(); + return 0; +} + +static int +kmi_mouse_open(struct inode *inode, struct file *file) +{ + if (kmi_mouse_count++) + return 0; + queue->head = queue->tail = 0; + kmi_send_and_wait(kmi_mouse, PS2_O_ENABLE, HZ); + return 0; +} + +static int +kmi_mouse_fasync(int fd, struct file *filp, int on) +{ + int retval = fasync_helper(fd, filp, on, &queue->fasync); + if (retval > 0) + retval = 0; + return retval; +} + +static struct file_operations ps_fops = { + read: kmi_mouse_read, + write: kmi_mouse_write, + poll: kmi_mouse_poll, + open: kmi_mouse_open, + release: kmi_mouse_release, + fasync: kmi_mouse_fasync, +}; + +static struct miscdevice ps_mouse = { + minor: PSMOUSE_MINOR, + name: "psaux", + fops: &ps_fops, +}; + +static u_char kmi_mse_init_string[] = { + PS2_O_DISABLE, + PS2_O_SET_SAMPLE, 100, + PS2_O_SET_RES, 3, + PS2_O_SET_SCALE21 +}; + +/* + * The "normal" mouse scancode processing + */ +static void kmi_mse_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs) +{ + u_int head; + + add_mouse_randomness(val); + +#ifdef CONFIG_AMBA_PS2_RECONNECT + /* Try to detect a hot-plug event on the PS/2 mouse port */ + switch (kmi->hotplug_state) { + case 0: + /* Maybe we lost contact... */ + if (val == PS2_I_BAT_OK) { + kmi->hotplug_state++; + DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state)); + } + break; + + case 1: + /* Again, maybe (but only maybe) we lost contact... */ + if (val == 0) { + kmi->hotplug_state++; + kmi_send(kmi, PS2_O_REQ_STATUS); + DEBUG(("%s: Got 0xAA 0x00. Sent Status Request\n", kmi->name)); + } else { + kmi->hotplug_state = 0; + DEBUG(("%s: No 0x00 followed 0xAA. No reconnect.\n", kmi->name)); + } + break; + + case 2: + /* Eat up acknowledge */ + if (val == PS2_I_ACK) + kmi->hotplug_state++; + else { + kmi->hotplug_state = 0; + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val)); + } + break; + + case 3: + /* check if data reporting is still enabled, then no POR has happend */ + kmi->reconnect = !(val & 1<<5); + DEBUG(("%s: Data reporting disabled?: (%d)\n", kmi->name, kmi->reconnect)); + kmi->hotplug_state++; + DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state)); + break; + + case 4: + /* Eat up one status byte */ + kmi->hotplug_state++; + DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state)); + break; + + case 5: + /* Eat up another status byte */ + if (kmi->reconnect) { + kmi->config_num = 0; + kmi_send(kmi, kmi_mse_init_string[kmi->config_num]); + kmi->config_num++; + kmi->hotplug_state++; + DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num)); + } else { + kmi->hotplug_state = 0; + DEBUG(("%s: False Alarm...\n", kmi->name)); + } + break; + + case 6: + if (val == PS2_I_ACK && kmi->config_num < sizeof(kmi_mse_init_string)) { + kmi_send(kmi, kmi_mse_init_string[kmi->config_num]); + kmi->config_num++; + DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num)); + } else { + if (val == PS2_I_ACK) { + DEBUG(("%s: Now enable the mouse again...\n", kmi->name)); + queue->head = queue->tail = 0; + kmi_send(kmi, PS2_O_ENABLE); + kmi->hotplug_state++; + } else { + kmi->hotplug_state = 0; + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val)); + } + } + break; + + case 7: + /* Eat up last acknowledge from enable */ + if (val == PS2_I_ACK) + printk(KERN_ERR "%s: reconnected\n", kmi->name); + else + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val)); + + kmi->hotplug_state = 0; + break; + + } /* switch (kmi->hotplug_state) */ + + /* while inside hotplug mechanism, don't misinterpret values */ + if (kmi->hotplug_state > 2) + return; +#endif + + /* We are waiting for the mouse to respond to a kmi_send_and_wait() */ + if (kmi->res == KMI_NO_ACK) { + if (val == PS2_I_RESEND) { + if (kmi->resend_count < 5) + __kmi_send(kmi, kmi->last_tx); + else { + printk(KERN_ERR "%s: too many resends\n", kmi->name); + return; + } + } + + if (val == PS2_I_ACK) { + kmi->res = val; + wake_up(&kmi->wait_q); + } + return; + } + + /* The mouse autonomously send new data, so wake up mouse_read() */ + if (queue) { + head = queue->head; + queue->buf[head] = val; + head = (head + 1) & (BUF_SZ - 1); + if (head != queue->tail) { + queue->head = head; + kill_fasync(&queue->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&kmi->wait_q); + } + } +} + +static int kmi_init_mouse(struct kmi_info *kmi) +{ + u_int ret, i; + + if (kmi->present) { + kmi->rx = kmi_mse_intr; + + for (i = 0; i < sizeof(kmi_mse_init_string); i++) { + ret = kmi_send_and_wait(kmi, kmi_mse_init_string[i], HZ); + if (ret != PS2_I_ACK) + printk("%s: didn't get ack (0x%2.2x)\n", + kmi->name, ret); + } + } + + queue = kmalloc(sizeof(*queue), GFP_KERNEL); + if (queue) { + memset(queue, 0, sizeof(*queue)); + misc_register(&ps_mouse); + ret = 0; + } else + ret = -ENOMEM; + + return ret; +} +#endif /* CONFIG_KMI_MOUSE */ + +/* + * The "program" we send to the keyboard to set it up how we want it: + * - default typematic delays + * - scancode set 1 + */ +static u_char kmi_kbd_init_string[] = { + PS2_O_DISABLE, + PS2_O_SET_DEFAULT, + PS2_O_SET_SCANSET, 0x01, + PS2_O_ENABLE +}; + +static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs); + +static int __kmi_init_keyboard(struct kmi_info *kmi) +{ + u_int ret, i; + + if (!kmi->present) + return 0; + + kmi->rx = kmi_kbd_intr; + + for (i = 0; i < sizeof(kmi_kbd_init_string); i++) { + ret = kmi_send_and_wait(kmi, kmi_kbd_init_string[i], HZ); + if (ret != PS2_I_ACK) + printk("%s: didn't ack (0x%2.2x)\n", + kmi->name, ret); + } + + return 0; +} + +static void kmi_kbd_init_tasklet(unsigned long k) +{ + struct kmi_info *kmi = (struct kmi_info *)k; + __kmi_init_keyboard(kmi); +} + +static DECLARE_TASKLET_DISABLED(kmikbd_init_tasklet, kmi_kbd_init_tasklet, 0); + +/* + * The "normal" keyboard scancode processing + */ +static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs) +{ +#ifdef CONFIG_AMBA_PS2_RECONNECT + /* Try to detect a hot-plug event on the PS/2 keyboard port */ + switch (kmi->hotplug_state) { + case 0: + /* Maybe we lost contact... */ + if (val == PS2_I_BAT_OK) { + kmi_send(kmi, PS2_O_SET_SCANSET); + kmi->hotplug_state++; + DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state)); + } + break; + + case 1: + /* Eat up acknowledge */ + if (val == PS2_I_ACK) { + /* Request scan code set: '2' if POR has happend, '1' is false alarm */ + kmi_send(kmi, 0); + kmi->hotplug_state++; + } + else { + kmi->hotplug_state = 0; + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val)); + } + break; + + case 2: + /* Eat up acknowledge */ + if (val == PS2_I_ACK) + kmi->hotplug_state++; + else { + kmi->hotplug_state = 0; + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val)); + } + break; + + case 3: + kmi->hotplug_state = 0; + if (val == 2) { + DEBUG(("%s: POR detected. Scan code is: (%d)\n", kmi->name, val)); + kmi->present = 1; + tasklet_schedule(&kmikbd_init_tasklet); + printk(KERN_ERR "%s: reconnected\n", kmi->name); + return; + } + else + DEBUG(("%s: False Alarm...\n", kmi->name)); + break; + + } /* switch (kmi->hotplug_state) */ +#endif + + if (val == PS2_I_DIAGFAIL) { + printk(KERN_ERR "%s: diagnostic failed\n", kmi->name); + return; + } + + /* We are waiting for the keyboard to respond to a kmi_send_and_wait() */ + if (kmi->res == KMI_NO_ACK) { + if (val == PS2_I_RESEND) { + if (kmi->resend_count < 5) + __kmi_send(kmi, kmi->last_tx); + else { + printk(KERN_ERR "%s: too many resends\n", kmi->name); + return; + } + } + + if (val >= 0xee) { + kmi->res = val; + wake_up(&kmi->wait_q); + } + return; + } + +#ifdef CONFIG_VT + kbd_pt_regs = regs; + handle_scancode(val, !(val & 0x80)); + tasklet_schedule(&keyboard_tasklet); +#endif +} + +static void kmi_intr(int nr, void *devid, struct pt_regs *regs) +{ + struct kmi_info *kmi = devid; + u_int status = __raw_readb(KMIIR); + + if (status & KMIIR_RXINTR) { + u_int val = __raw_readb(KMIDATA); + + if (kmi->rx) + kmi->rx(kmi, val, regs); + } +} + +static int kmi_init_keyboard(struct kmi_info *kmi) +{ + kmikbd_init_tasklet.data = (unsigned long)kmi; + tasklet_enable(&kmikbd_init_tasklet); + + return __kmi_init_keyboard(kmi); +} + +/* + * Reset interrupt handler + */ +static void __init +kmi_reset_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs) +{ + if (kmi->state == KMI_RESET) { + if (val == PS2_I_ACK) + kmi->state = KMI_RESET_POR; + else { + val = KMI_NO_ACK; + goto finished; + } + } else if (kmi->state == KMI_RESET_POR) { +finished: + kmi->res = val; + kmi->state = KMI_RESET_DONE; + kmi->rx = NULL; + wake_up(&kmi->wait_q); + } +} + +/* + * Reset the device plugged into this interface + */ +static int __init kmi_reset(struct kmi_info *kmi) +{ + u_int res; + int ret = 0; + + kmi->state = KMI_RESET; + kmi->rx = kmi_reset_intr; + res = kmi_send_and_wait(kmi, PS2_O_RESET, HZ); + kmi->rx = NULL; + + if (res != PS2_I_BAT_OK) { + printk(KERN_ERR "%s: reset failed; ", kmi->name); + if (kmi->res != KMI_NO_ACK) + printk("code 0x%2.2x\n", kmi->res); + else + printk("no ack\n"); + ret = -EINVAL; + } + return ret; +} + +static int __init kmi_init_one_interface(struct kmi_info *kmi) +{ + u_int stat; + int ret = -ENODEV; + + init_waitqueue_head(&kmi->wait_q); + + printk(KERN_INFO "%s at 0x%8.8x on irq %d (%s)\n", kmi->name, + kmi->base, kmi->irq, kmi_type[kmi->type]); + + /* + * Initialise the KMI interface + */ + __raw_writeb(kmi->divisor, KMICLKDIV); + __raw_writeb(KMICR_EN, KMICR); + + /* + * Check that the data and clock lines are OK. + */ + stat = __raw_readb(KMISTAT); + if ((stat & (KMISTAT_IC|KMISTAT_ID)) != (KMISTAT_IC|KMISTAT_ID)) { + printk(KERN_ERR "%s: %s%s%sline%s stuck low\n", kmi->name, + (stat & KMISTAT_IC) ? "" : "clock ", + (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "and ", + (stat & KMISTAT_ID) ? "" : "data ", + (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "s"); + goto bad; + } + + /* + * Claim the appropriate interrupts + */ + ret = request_irq(kmi->irq, kmi_intr, 0, kmi->name, kmi); + if (ret) + goto bad; + + /* + * Enable the receive interrupt, and reset the device. + */ + __raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR); + kmi->present = 1; + kmi->present = kmi_reset(kmi) == 0; + + switch (kmi->type) { + case KMI_KEYBOARD: + ret = kmi_init_keyboard(kmi); + break; + +#ifdef CONFIG_KMI_MOUSE + case KMI_MOUSE: + ret = kmi_init_mouse(kmi); + break; +#endif + } + + return ret; + +bad: + /* + * Oh dear, the interface was bad, disable it. + */ + __raw_writeb(0, KMICR); + return ret; +} + +#ifdef CONFIG_VT +/* + * The fragment between #ifdef above and #endif * CONFIG_VT * + * is from the pc_keyb.c driver. It is not copyrighted under the + * above notice. This code is by various authors; please see + * drivers/char/pc_keyb.c for further information. + */ + +/* + * Translation of escaped scancodes to keycodes. + * This is now user-settable. + * The keycodes 1-88,96-111,119 are fairly standard, and + * should probably not be changed - changing might confuse X. + * X also interprets scancode 0x5d (KEY_Begin). + * + * For 1-88 keycode equals scancode. + */ + +#define E0_KPENTER 96 +#define E0_RCTRL 97 +#define E0_KPSLASH 98 +#define E0_PRSCR 99 +#define E0_RALT 100 +#define E0_BREAK 101 /* (control-pause) */ +#define E0_HOME 102 +#define E0_UP 103 +#define E0_PGUP 104 +#define E0_LEFT 105 +#define E0_RIGHT 106 +#define E0_END 107 +#define E0_DOWN 108 +#define E0_PGDN 109 +#define E0_INS 110 +#define E0_DEL 111 + +#define E1_PAUSE 119 + +/* BTC */ +#define E0_MACRO 112 +/* LK450 */ +#define E0_F13 113 +#define E0_F14 114 +#define E0_HELP 115 +#define E0_DO 116 +#define E0_F17 117 +#define E0_KPMINPLUS 118 +/* + * My OmniKey generates e0 4c for the "OMNI" key and the + * right alt key does nada. [kkoller@nyx10.cs.du.edu] + */ +#define E0_OK 124 +/* + * New microsoft keyboard is rumoured to have + * e0 5b (left window button), e0 5c (right window button), + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] + * [or: Windows_L, Windows_R, TaskMan] + */ +#define E0_MSLW 125 +#define E0_MSRW 126 +#define E0_MSTM 127 + +static u_char e0_keys[128] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + E0_KPENTER, E0_RCTRL, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, E0_KPSLASH, 0, E0_PRSCR, + E0_RALT, 0, 0, 0, + 0, E0_F13, E0_F14, E0_HELP, + E0_DO, E0_F17, 0, 0, + 0, 0, E0_BREAK, E0_HOME, + E0_UP, E0_PGUP, 0, E0_LEFT, + E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, + 0, 0, 0, 0, + 0, 0, 0, E0_MSLW, + E0_MSRW, E0_MSTM, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, E0_MACRO, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; + +#ifdef CONFIG_MAGIC_SYSRQ +u_char kmi_kbd_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +#endif + +int kmi_kbd_setkeycode(u_int scancode, u_int keycode) +{ + if (scancode < 128 || scancode > 255 || keycode > 127) + return -EINVAL; + e0_keys[scancode - 128] = keycode; + return 0; +} + +int kmi_kbd_getkeycode(u_int scancode) +{ + if (scancode < 128 || scancode > 255) + return -EINVAL; + return e0_keys[scancode - 128]; +} + +int kmi_kbd_translate(u_char scancode, u_char *keycode, char raw_mode) +{ + static int prev_scancode = 0; + + /* special prefix scancodes.. */ + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; + return 0; + } + + /* 0xff is sent by a few keyboards, ignore it. 0x00 is error */ + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; + return 0; + } + + scancode &= 0x7f; + + if (prev_scancode) { + int old_scancode = prev_scancode; + + prev_scancode = 0; + switch (old_scancode) { + case 0xe0: + /* + * The keyboard maintains its own internal caps lock + * and num lock status. In caps lock mode, E0 AA + * precedes make code and E0 2A follows break code. + * In numlock mode, E0 2A precedes make code, and + * E0 AA follows break code. We do our own book- + * keeping, so we will just ignore these. + * + * For my keyboard there is no caps lock mode, but + * there are both Shift-L and Shift-R modes. The + * former mode generates E0 2A / E0 AA pairs, the + * latter E0 B6 / E0 36 pairs. So, we should also + * ignore the latter. - aeb@cwi.nl + */ + if (scancode == 0x2a || scancode == 0x36) + return 0; + if (e0_keys[scancode]) + *keycode = e0_keys[scancode]; + else { + if (!raw_mode) + printk(KERN_INFO "kbd: unknown " + "scancode e0 %02x\n", + scancode); + return 0; + } + break; + + case 0xe1: + if (scancode == 0x1d) + prev_scancode = 0x100; + else { + if (!raw_mode) + printk(KERN_INFO "kbd: unknown " + "scancode e1 %02x\n", + scancode); + return 0; + } + break; + + case 0x100: + if (scancode == 0x45) + *keycode = E1_PAUSE; + else { + if (!raw_mode) + printk(KERN_INFO "kbd: unknown " + "scan code e1 1d %02x\n", + scancode); + return 0; + } + break; + } + } else + *keycode = scancode; + return 1; +} + +char kmi_kbd_unexpected_up(u_char keycode) +{ + return 0x80; +} + +void kmi_kbd_leds(u_char leds) +{ + struct kmi_info *kmi = kmi_keyb; + u_int ret; + + if (kmi) { + ret = kmi_send_and_wait(kmi, PS2_O_INDICATORS, HZ); + if (ret != KMI_NO_ACK) + ret = kmi_send_and_wait(kmi, leds, HZ); + if (ret == KMI_NO_ACK) + kmi->present = 0; + } +} + +int __init kmi_kbd_init(void) +{ + int ret = -ENODEV; + + if (kmi_keyb) { + strcpy(kmi_keyb->name, "kmikbd"); + ret = kmi_init_one_interface(kmi_keyb); + } + + if (ret == 0) { + k_setkeycode = kmi_kbd_setkeycode; + k_getkeycode = kmi_kbd_getkeycode; + k_translate = kmi_kbd_translate; + k_unexpected_up = kmi_kbd_unexpected_up; + k_leds = kmi_kbd_leds; +#ifdef CONFIG_MAGIC_SYSRQ + k_sysrq_xlate = kmi_kbd_sysrq_xlate; + k_sysrq_key = 0x54; +#endif + } + + return ret; +} + +#endif /* CONFIG_VT */ + +int register_kmi(struct kmi_info *kmi) +{ + struct kmi_info **kmip = NULL; + int ret; + + if (kmi->type == KMI_KEYBOARD) + kmip = &kmi_keyb; + else if (kmi->type == KMI_MOUSE) + kmip = &kmi_mouse; + + ret = -EINVAL; + if (kmip) { + ret = -EBUSY; + if (!*kmip) { + *kmip = kmi; + ret = 0; + } + } + + return ret; +} + +#ifdef CONFIG_KMI_MOUSE +static int __init kmi_init(void) +{ + int ret = -ENODEV; + + if (kmi_mouse) { + strcpy(kmi_mouse->name, "kmimouse"); + ret = kmi_init_one_interface(kmi_mouse); + } + + return ret; +} + +__initcall(kmi_init); +#endif diff -uNr linux-2.4.37.9/drivers/char/anakin_ts.c linux-2.4.37.9-vrs1-5mx2/drivers/char/anakin_ts.c --- linux-2.4.37.9/drivers/char/anakin_ts.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/anakin_ts.c Wed May 26 15:48:46 2010 @@ -0,0 +1,208 @@ +/* + * linux/drivers/char/anakin_ts.c + * + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V. + * + * 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. + * + * Changelog: + * 18-Apr-2001 TTC Created + * 23-Oct-2001 dwmw2 Cleanup + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * TSBUF_SIZE must be a power of two + */ +#define ANAKIN_TS_MINOR 16 +#define TSBUF_SIZE 256 +#define NEXT(index) (((index) + 1) & (TSBUF_SIZE - 1)) + +static unsigned short buffer[TSBUF_SIZE][4]; +static int head, tail; +static DECLARE_WAIT_QUEUE_HEAD(queue); +static DECLARE_MUTEX(open_sem); +static spinlock_t tailptr_lock = SPIN_LOCK_UNLOCKED; +static struct fasync_struct *fasync; + +/* + * Interrupt handler and standard file operations + */ +static void +anakin_ts_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int status = __raw_readl(IO_BASE + IO_CONTROLLER + 0x24); + + /* + * iPAQ format (u16 pressure, x, y, millisecs) + */ + switch (status >> 20 & 3) { + case 0: + return; + case 2: + buffer[head][0] = 0; + break; + default: + buffer[head][0] = 0x7f; + } + + if (unlikely((volatile int)tail == NEXT(head))) { + /* Run out of space in the buffer. Move the tail pointer */ + spin_lock(&tailptr_lock); + + if ((volatile int)tail == NEXT(head)) { + tail = NEXT(NEXT(head)); + } + spin_unlock(&tailptr_lock); + } + + buffer[head][1] = status >> 2 & 0xff; + buffer[head][2] = status >> 12 & 0xff; + buffer[head][3] = jiffies; + mb(); + head = NEXT(head); + + wake_up_interruptible(&queue); + kill_fasync(&fasync, SIGIO, POLL_IN); + +} + +static ssize_t +anakin_ts_read(struct file *filp, char *buf, size_t count, loff_t *l) +{ + unsigned short data[4]; + ssize_t written = 0; + + if (head == tail) { + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(queue, (volatile int)head != (volatile int)tail)) + return -ERESTARTSYS; + } + + while ((volatile int)head != (volatile int)tail && count >= sizeof data) { + /* Copy the data out with the spinlock held, so the + interrupt can't fill the buffer and move the tail + pointer while we're doing it */ + spin_lock_irq(&tailptr_lock); + + memcpy(data, buffer[tail], sizeof data); + tail = NEXT(tail); + + spin_unlock_irq(&tailptr_lock); + + if (copy_to_user(buf, data, sizeof data)) + return -EFAULT; + count -= sizeof data; + buf += sizeof data; + written += sizeof data; + } + return written ? written : -EINVAL; +} + +static unsigned int +anakin_ts_poll(struct file *filp, poll_table *wait) +{ + poll_wait(filp, &queue, wait); + return head != tail ? POLLIN | POLLRDNORM : 0; +} + +static int +anakin_ts_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + /* + * Future ioctl goes here + */ + return 0; +} + +static int +anakin_ts_open(struct inode *inode, struct file *filp) +{ + if (down_trylock(&open_sem)) + return -EBUSY; + return 0; +} + +static int +anakin_ts_fasync(int fd, struct file *filp, int on) +{ + return fasync_helper(fd, filp, on, &fasync); +} + +static int +anakin_ts_release(struct inode *inode, struct file *filp) +{ + anakin_ts_fasync(-1, filp, 0); + up(&open_sem); + return 0; +} + +static struct file_operations anakin_ts_fops = { + owner: THIS_MODULE, + read: anakin_ts_read, + poll: anakin_ts_poll, + ioctl: anakin_ts_ioctl, + open: anakin_ts_open, + release: anakin_ts_release, + fasync: anakin_ts_fasync, +}; + +static struct miscdevice anakin_ts_miscdev = { + ANAKIN_TS_MINOR, + "anakin_ts", + &anakin_ts_fops +}; + +/* + * Initialization and exit routines + */ +int __init +anakin_ts_init(void) +{ + int retval; + + if ((retval = request_irq(IRQ_TOUCHSCREEN, anakin_ts_handler, + SA_INTERRUPT, "anakin_ts", 0))) { + printk(KERN_WARNING "anakin_ts: failed to get IRQ\n"); + return retval; + } + __raw_writel(1, IO_BASE + IO_CONTROLLER + 8); + misc_register(&anakin_ts_miscdev); + + printk(KERN_NOTICE "Anakin touchscreen driver initialised\n"); + + return 0; +} + +void __exit +anakin_ts_exit(void) +{ + __raw_writel(0, IO_BASE + IO_CONTROLLER + 8); + free_irq(IRQ_TOUCHSCREEN, 0); + misc_deregister(&anakin_ts_miscdev); +} + +module_init(anakin_ts_init); +module_exit(anakin_ts_exit); + +MODULE_AUTHOR("Tak-Shing Chan "); +MODULE_DESCRIPTION("Anakin touchscreen driver"); +MODULE_SUPPORTED_DEVICE("touchscreen/anakin"); diff -uNr linux-2.4.37.9/drivers/char/cerf_keyb.c linux-2.4.37.9-vrs1-5mx2/drivers/char/cerf_keyb.c --- linux-2.4.37.9/drivers/char/cerf_keyb.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/cerf_keyb.c Wed May 26 15:48:46 2010 @@ -0,0 +1,380 @@ +/* + cerf_keyb.c: This is the end. Daniel is writing a device driver!!! +*/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define KBD_REPORT_UNKN + +#define KBD_REPORT_ERR /* Report keyboard errors */ +#define KBD_REPORT_UNKN /* Report unknown scan codes */ +#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */ +#define KBD_NO_DATA (-1) /* No data */ +#define KBD_REPEAT_START (0x20) +#define KBD_REPEAT_CONTINUE (0x05) +#define KBD_KEY_DOWN_MAX (0x10) +#define UINT_LEN (20) +#define SC_LIM (69) +#define KBD_ROWS (5) +#define KBD_COLUMNS (8) + +#define KBD_KEYUP (0x80) +#define KBD_MODESCAN (0x7f) +#define KBD_CAPSSCAN (0x3a) +#define KBD_SHIFTSCAN (0x2a) +#define KBD_NUMCURSCAN (0x7c) +#define KBD_CTRLSCAN (0x1d) +#define KBD_ALTSCAN (0x38) + +#define KBD_UP_OFF (0) +#define KBD_UP_ON (1) +#define KBD_DOWN (2) +#define KBD_DOWN_HOLD (3) + + + +static unsigned char handle_kbd_event(void); +static unsigned char kbd_read_input(void); +static void column_set(unsigned int column); +static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]); + +static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; +static struct timer_list kbd_timer; + +static short mode_ena = 0; +static short numcur_ena = 0; +static short shift_ena = 0; + +#define E0_KPENTER 96 +#define E0_RCTRL 97 +#define E0_KPSLASH 98 +#define E0_PRSCR 99 +#define E0_RALT 100 +#define E0_BREAK 101 /* (control-pause) */ +#define E0_HOME 102 +#define E0_UP 103 +#define E0_PGUP 104 +#define E0_LEFT 105 +#define E0_RIGHT 106 +#define E0_END 107 +#define E0_DOWN 108 +#define E0_PGDN 109 +#define E0_INS 110 +#define E0_DEL 111 +#define E1_PAUSE 119 +#define E0_MACRO 112 +#define E0_F13 113 +#define E0_F14 114 +#define E0_HELP 115 +#define E0_DO 116 +#define E0_F17 117 +#define E0_KPMINPLUS 118 +#define E0_OK 124 +#define E0_MSLW 125 +#define E0_MSRW 126 +#define E0_MSTM 127 + +static unsigned char e0_keys[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */ + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ +}; + +static unsigned char cerf_normal_map[KBD_ROWS][KBD_COLUMNS] = { + {KBD_ALTSCAN, KBD_MODESCAN, 0x1e, 0x30, 0x2e, 0x20, 0x00, 0x00}, + {0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x00}, + {0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x00}, + {0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x00}, + {0x2c, KBD_SHIFTSCAN, KBD_CTRLSCAN, 0x39, KBD_NUMCURSCAN, 0x2b, 0x1c, 0x00} +}; + +static unsigned char cerf_mode_map[KBD_ROWS][KBD_COLUMNS] = { + {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00}, + {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, // + {0x0d, 0x0c, 0x37, 0x35, 0x0d, 0x48, 0x28, 0x00}, + {0x01, 0x33, 0x34, 0x00, 0x4b, 0x27, 0x4d, 0x00}, // + {0x0f, 0x00, KBD_CAPSSCAN, 0x0e, 0x00, 0x50, 0x00, 0x00} +}; + +static unsigned char cerf_numcur_map[KBD_ROWS][KBD_COLUMNS] = { + {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00}, + {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, + {0x0d, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x4d, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00} +}; + +static void column_set(unsigned int column) +{ + if (column < 0) + { + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF); + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF); + } + else + { + if(column < 4) + { + CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_A, 1 << (column % 4), 0xFF); + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF); + } + else + { + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF); + CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_B, 1 << (column % 4), 0xFF); + } + } +} + +static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]) +{ + int i, j; + + for(i = 0; i < KBD_COLUMNS; i++) + { + column_set(i); + udelay(50); + for(j = 0; j < KBD_ROWS; j++) + { + if(mode_ena) + codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_mode_map[j][i]?cerf_mode_map[j][i]:cerf_normal_map[j][i]):0; + else if(numcur_ena) + codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_numcur_map[j][i]?cerf_numcur_map[j][i]:cerf_normal_map[j][i]):0; + else + codeval[j][i] = (GPLR & (1 << (20 + j)))?cerf_normal_map[j][i]:0; + } + } + column_set(-1); + + return 0; +} + +static unsigned char kbd_read_input(void) +{ + int i, j, k, l; + unsigned char prev; + static unsigned char count = 0; + + static unsigned char oldcodes[KBD_ROWS][KBD_COLUMNS]={{0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}}; + unsigned char inputcode[KBD_ROWS][KBD_COLUMNS]; + + memset(inputcode, 0, sizeof(unsigned char) * (KBD_ROWS * KBD_COLUMNS)); + scancodes(inputcode); + + for(i = 0; i < KBD_COLUMNS; i++) + { + for(j = 0; j < KBD_ROWS; j++) + { +// if(oldcodes[j][i] == 0xe0) +// oldcodes[j][i] = + if(oldcodes[j][i] != inputcode[j][i]) + { + // Value of the key before entering this function + prev = oldcodes[j][i]; + + // KEYUP + if(inputcode[j][i] == 0 && oldcodes[j][i] != 0 && !(oldcodes[j][i] & KBD_KEYUP)) + { + oldcodes[j][i] |= KBD_KEYUP; + + if(mode_ena == KBD_UP_ON) + mode_ena = KBD_UP_OFF; + if(prev == KBD_MODESCAN) + if(mode_ena == KBD_DOWN_HOLD) + mode_ena = KBD_UP_OFF; + else if(mode_ena == KBD_DOWN) + mode_ena = KBD_UP_ON; + if(mode_ena == KBD_DOWN) + mode_ena = KBD_DOWN_HOLD; + } + // RESET KEYUP + else if(oldcodes[j][i] & KBD_KEYUP) + oldcodes[j][i] = 0; + // KEY DOWN + else + { + oldcodes[j][i] = inputcode[j][i]; + + // Parse out mode modifiers before the keyboard interpreter can touch them + if(inputcode[j][i] == KBD_MODESCAN) + { + if(!mode_ena) + mode_ena = KBD_DOWN; + continue; + } + if(inputcode[j][i] == KBD_NUMCURSCAN) + { + numcur_ena = numcur_ena?0:1; + continue; + } + } + //printk("Modified: (%#x,%#x), ipv:%#x, To: (%#.2x), From: (%#.2x), Flags:%d,%d,%d\r\n", j, i, inputcode[j][i], oldcodes[j][i], prev, mode_ena, shift_ena, numcur_ena); + return oldcodes[j][i]; + } + } + } + + return (unsigned char)(KBD_NO_DATA); +} + +int cerf_kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + static int prev_scancode; + + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; + return 0; + } + + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; + return 0; + } + + scancode &= 0x7f; + + if (prev_scancode) { + if (prev_scancode != 0xe0) { + if (prev_scancode == 0xe1 && scancode == 0x1d) { + prev_scancode = 0x100; + return 0; + } else if (prev_scancode == 0x100 && scancode == 0x45) { + prev_scancode = 0; + } else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); +#endif + prev_scancode = 0; + return 0; + } + } else { + prev_scancode = 0; + if (scancode == 0x2a || scancode == 0x36) + return 0; + else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", + scancode); +#endif + return 0; + } + } + } else + *keycode = scancode; + return 1; +} + +static inline void handle_keyboard_event(unsigned char scancode) +{ + if(scancode != (unsigned char)(KBD_NO_DATA)) + { +#ifdef CONFIG_VT + handle_scancode(scancode, !(scancode & KBD_KEYUP)); +#endif + tasklet_schedule(&keyboard_tasklet); + } +} + +static unsigned char handle_kbd_event(void) +{ + unsigned char scancode; + + scancode = kbd_read_input(); + handle_keyboard_event(scancode); + + return 0; +} + +/* Handle the automatic interrupts handled by the timer */ +static void keyboard_interrupt(unsigned long foo) +{ + spin_lock_irq(&kbd_controller_lock); + handle_kbd_event(); + spin_unlock_irq(&kbd_controller_lock); + + kbd_timer.expires = 8 + jiffies; + kbd_timer.data = 0x00000000; + kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt; + + add_timer(&kbd_timer); +} + +void cerf_leds(unsigned char leds) +{ +} +char cerf_unexpected_up(unsigned char keycode) +{ +return 0; +} +int cerf_getkeycode(unsigned int scancode) +{ +return 0; +} +int cerf_setkeycode(unsigned int scancode, unsigned int keycode) +{ +return 0; +} + +void cerf_kbd_init_hw(void) +{ + printk("Starting Cerf PDA Keyboard Driver... "); + + k_setkeycode = cerf_setkeycode; + k_getkeycode = cerf_getkeycode; + k_translate = cerf_kbd_translate; + k_unexpected_up = cerf_unexpected_up; + k_leds = cerf_leds; + + GPDR &= ~(GPIO_GPIO(20) | GPIO_GPIO(21) | GPIO_GPIO(22) | GPIO_GPIO(23) | GPIO_GPIO(24)); + kbd_timer.expires = 40 + jiffies; + kbd_timer.data = 0x00000000; + kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt; + + add_timer(&kbd_timer); + + printk("Done\r\n"); +} diff -uNr linux-2.4.37.9/drivers/char/clps711x_keyb.c linux-2.4.37.9-vrs1-5mx2/drivers/char/clps711x_keyb.c --- linux-2.4.37.9/drivers/char/clps711x_keyb.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/clps711x_keyb.c Wed May 26 15:48:46 2010 @@ -0,0 +1,547 @@ +/* + * drivers/char/clps711x_keyb.c + * + * Copyright (C) 2001 Thomas Gleixner + * + * based on drivers/edb7211_keyb.c, which is copyright (C) 2000 Bluemug Inc. + * + * Keyboard driver for ARM Linux on EP7xxx and CS89712 processors + * + * 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. See the file COPYING + * in the main directory of this archive for more details. + * + * + * Hardware: + * + * matrix scan keyboards based on EP7209,7211,7212,7312 and CS89712 + * on chip keyboard scanner. + * Adaption for different machines is done in init function. + * + * Basic Function: + * + * Basicly the driver is interrupt driven. It sets all column drivers + * high. If any key is pressed, a interrupt occures. Now a seperate scan of + * each column is done. This scan is timer based, because we use a keyboard + * interface with decoupling capacitors (neccecary if you want to survive + * EMC compliance tests). Always one line is set high. When next timer event + * occures the scan data on port A are valid. This makes also sure, that no + * spurious keys are scanned. The kbd int on these CPU's is not deglitched! + * After scanning all columns, we switch back to int mode, if no key is + * pressed. If any is pressed we reschedule the scan within a programmable + * delay. If we would switch back to interrupt mode as long as a key is pressed, + * we come right back to the interrupt, because the int. is level triggered ! + * The timer based scan of the seperate columns can also be done in one + * timer event (set fastscan to 1). + * + * Summary: + * The design of this keyboard controller chip is stupid at all ! + * + * Matrix translation: + * The matrix translation table is based on standard XT scancodes. Maybe + * you have to adjust the KEYISPRINTABLE macro if you set other codes. + * + * HandyKey: + * + * On small matrix keyboards you don't have enough keys for operation. + * The intention was to implement a operation mode as it's used on handys. + * You can rotate trough four scancode levels and produce e.g. with a 4x3 + * matrix 4*3*4 = 48 different keycodes. That's basicly enough for editing + * filenames or things like that. The HandyKey function takes care about + * nonprintable keys like cursors, backspace, del ... + * If a key is pressed and is a printable keycode, the code is put to the + * main keyboard handler and a cursor left is applied. If you press the same + * key again, the current character is deleted and the next level character + * is applied. (e.g. 1, a, b, c, 1 ....). If you press a different key, the + * driver applies cursor right, before processing the new key. + * The autocomplete feature moves the cursor right, if you do not press a + * key within a programmable time. + * If HandyKey is off, the keyboard behaviour is that of a standard keyboard + * HandyKey can be en/disabled from userspace with the proc/keyboard entry + * + * proc/keyboard: + * + * Read access gives back the actual state of the HandyKey function + * h:0 Disabled + * h:1 Enabled + * Write access has two functions. Changing the HandyKey mode and applying + * a different scancode translation table. + * Syntax is: h:0 disable Handykey + * h:1 enabled Handykey + * t:array[256] of bytes Transfer translation table + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +void clps711x_kbd_init_hw(void); + +/* + * Values for the keyboard column scan control register. + */ +#define KBSC_HI 0x0 /* All driven high */ +#define KBSC_LO 0x1 /* All driven low */ +#define KBSC_X 0x2 /* All high impedance */ +#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */ +#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */ +#define KBSC_COL2 0xa /* Column 2 high, others high impedance */ +#define KBSC_COL3 0xb /* Column 3 high, others high impedance */ +#define KBSC_COL4 0xc /* Column 4 high, others high impedance */ +#define KBSC_COL5 0xd /* Column 5 high, others high impedance */ +#define KBSC_COL6 0xe /* Column 6 high, others high impedance */ +#define KBSC_COL7 0xf /* Column 7 high, others high impedance */ + +/* +* Keycodes for cursor left/right and delete (used by HandyKey) +*/ +#define KEYCODE_CLEFT 0x4b +#define KEYCODE_CRIGHT 0x4d +#define KEYCODE_DEL 0x53 +#define KEYISPRINTABLE(code) ( (code > 0x01 && code < 0x37 && code != 0x1c \ + && code != 0x0e) || code == 0x39) + +/* Simple translation table for the SysRq keys */ +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char clps711x_kbd_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +#endif + +/* + * This table maps row/column keyboard matrix positions to XT scancodes. + * It's a default table, which can be overriden by writing to proc/keyboard + */ +#ifdef CONFIG_ARCH_AUTCPU12 +static unsigned char autcpu12_scancode[256] = +{ +/* Column: + Row 0 1 2 3 4 5 6 7 */ +/* A0 */ 0x08, 0x09, 0x0a, 0x0e, 0x05, 0x06, 0x00, 0x00, +/* A1 */ 0x07, 0x53, 0x02, 0x03, 0x04, 0x0f, 0x00, 0x00, +/* A2 */ 0x0c, 0x0b, 0x33, 0x1c, 0xff, 0x4b, 0x00, 0x00, +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00, +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +/* A0 */ 0x1e, 0x20, 0x22, 0x0e, 0x24, 0x32, 0x00, 0x00, +/* A1 */ 0x19, 0x53, 0x1f, 0x2f, 0x15, 0x0f, 0x00, 0x00, +/* A2 */ 0x0c, 0x39, 0x34, 0x1c, 0xff, 0x4b, 0x00, 0x00, +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00, +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +/* A0 */ 0x30, 0x12, 0x23, 0x0e, 0x25, 0x31, 0x00, 0x00, +/* A1 */ 0x10, 0x53, 0x14, 0x11, 0x2c, 0x0f, 0x00, 0x00, +/* A2 */ 0x0c, 0x0b, 0x27, 0x1c, 0xff, 0x4b, 0x00, 0x00, +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00, +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +/* A0 */ 0x2e, 0x21, 0x17, 0x0e, 0x26, 0x18, 0x00, 0x00, +/* A1 */ 0x13, 0x53, 0x16, 0x2D, 0x04, 0x0f, 0x00, 0x00, +/* A2 */ 0x0c, 0x39, 0x35, 0x1c, 0xff, 0x4b, 0x00, 0x00, +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00, +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +#endif + +static int keys[8]; +static int new_keys[8]; +static int previous_keys[8]; + +static int fastscan; +static int scan_interval; +static int scan_delay; +static int last_column; +static int key_is_pressed; + +static unsigned char *act_scancode; + +static struct kbd_handy_key { + int ena; + int code; + int shift; + int autocomplete; + unsigned long expires; + unsigned long delay; + unsigned char left; + unsigned char right; + unsigned char del; +} khandy; + +static struct tq_struct kbd_process_task; +static struct timer_list clps711x_kbd_timer; +static struct timer_list clps711x_kbdhandy_timer; +static struct proc_dir_entry *clps711x_keyboard_proc_entry = NULL; + +/* + * Translate a raw keycode to an XT keyboard scancode. + */ +static int clps711x_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + *keycode = act_scancode[scancode]; + return 1; +} + +/* +* Initialize handykey structure +* clear code, clear shift +* scan scancode for cursor right/left and delete +*/ +static void clps711x_handykey_init(void) { + + int i; + + khandy.ena = 0; + khandy.code = 0; + khandy.shift = 0; + khandy.autocomplete = 0; + for(i = 0; i < 64; i++) { + switch(act_scancode[i]) { + case KEYCODE_CLEFT: khandy.left = i; break; + case KEYCODE_CRIGHT: khandy.right = i; break; + case KEYCODE_DEL: khandy.del = i; break; + } + } +} + +/* +* Check for handy key and process it +*/ +void inline clps711x_checkhandy(int col, int row) { + + int scode, down; + unsigned char kcode; + + scode = (row<<3) + col; + down = keys[col]>>row & 0x01; + kcode = act_scancode[scode]; + + if (!khandy.ena) { + if (khandy.code) { + handle_scancode(khandy.right,1); + handle_scancode(khandy.right,0); + } + khandy.code = 0; + khandy.shift = 0; + khandy.autocomplete = 0; + } + + if(!kcode) + return; + + if (!down || !khandy.ena) { + if (khandy.ena && KEYISPRINTABLE(act_scancode[scode])) + khandy.autocomplete = 1; + else + handle_scancode(scode + khandy.shift, down); + return; + } + + khandy.autocomplete = 0; + if (KEYISPRINTABLE(kcode)) { + if (khandy.code) { + if(khandy.code == (scode|0x100)) { + handle_scancode(khandy.del,1); + handle_scancode(khandy.del,0); + khandy.shift = khandy.shift < 3*64 ? khandy.shift + 64 : 0 ; + } else { + handle_scancode(khandy.right,1); + handle_scancode(khandy.right,0); + khandy.shift = 0; + } + } + handle_scancode(scode + khandy.shift, 1); + handle_scancode(scode + khandy.shift, 0); + khandy.code = scode | 0x100; + handle_scancode(khandy.left,1); + handle_scancode(khandy.left,0); + } else { + if (khandy.code) { + khandy.code = 0; + handle_scancode(khandy.right,1); + handle_scancode(khandy.right,0); + } + khandy.shift = 0; + handle_scancode(scode, down); + } +} + + +/* + * Process the new key data + */ +static void clps711x_kbd_process(void* data) +{ + int col,row,res; + + for (col = 0; col < 8; col++) { + if (( res = previous_keys[col] ^ keys[col]) == 0) + continue; + for(row = 0; row < 8; row++) { + if ( ((res >> row) & 0x01) != 0) + clps711x_checkhandy(col,row); + } + } + /* Update the state variables. */ + memcpy(previous_keys, keys, 8 * sizeof(int)); + + /* reschedule, if autocomplete pending */ + if (khandy.autocomplete) { + khandy.expires = jiffies + khandy.delay; + mod_timer(&clps711x_kbdhandy_timer,khandy.expires); + } + +} + +static char clps711x_unexpected_up(unsigned char scancode) +{ + return 0200; +} + +/* +* Handle timer event, for autocomplete function +* Reschedule keyboard process task +*/ +static void clps711x_kbdhandy_timeout(unsigned long data) +{ + if(khandy.autocomplete) { + khandy.code = 0; + khandy.shift = 0; + khandy.autocomplete = 0; + handle_scancode(khandy.right,1); + handle_scancode(khandy.right,0); + } +} + +/* +* Handle timer event, while in pollmode +*/ +static void clps711x_kbd_timeout(unsigned long data) +{ + int i; + unsigned long flags; + /* + * read bits of actual column or all columns in fastscan-mode + */ + for (i = 0; i < 8; i++) { + new_keys[last_column - KBSC_COL0] = clps_readb(PADR) & 0xff; + key_is_pressed |= new_keys[last_column - KBSC_COL0]; + last_column = last_column < KBSC_COL7 ? last_column + 1 : KBSC_COL0; + local_irq_save(flags); + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) + | last_column, SYSCON1); + local_irq_restore(flags); + /* + * For fastscan, apply a short delay to settle scanlines + * else break and wait for next timeout + */ + if (fastscan) + udelay(5); + else + break; + } + + if (key_is_pressed) + khandy.autocomplete = 0; + + /* + * switch to interupt mode, if all columns scanned and no key pressed + * else reschedule scan + */ + if (last_column == KBSC_COL0) { + if (!key_is_pressed) { + local_irq_save(flags); + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) + | KBSC_HI, SYSCON1); + local_irq_restore(flags); + clps_writel(0,KBDEOI); + enable_irq(IRQ_KBDINT); + } else { + clps711x_kbd_timer.expires = jiffies + scan_interval; + add_timer(&clps711x_kbd_timer); + } + key_is_pressed = 0; + memcpy(keys, new_keys, 8 * sizeof(int)); + for (i = 0; i < 8; i++) { + if (previous_keys[i] != keys[i]) { + queue_task(&kbd_process_task, &tq_timer); + return; + } + } + } else { + clps711x_kbd_timer.expires = jiffies + scan_delay; + add_timer(&clps711x_kbd_timer); + } +} + +/* +* Keyboard interrupt, change to scheduling mode +*/ +static void clps711x_kbd_int(int irq, void *dev_id, struct pt_regs *regs) +{ + +#ifdef CONFIG_VT + kbd_pt_regs = regs; +#endif + disable_irq(IRQ_KBDINT); + khandy.autocomplete = 0; + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) + | KBSC_COL0, SYSCON1); + clps711x_kbd_timer.expires = jiffies + scan_delay; + add_timer(&clps711x_kbd_timer); +} + + +static int clps711x_kbd_proc_keyboard_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + if (count < 2) + return -EINVAL; + + return sprintf(page,"h:%d\n",khandy.ena); +} + +static int clps711x_kbd_proc_keyboard_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char buf[260]; + + if (count < 3|| count > 258) + return -EINVAL; + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + if (buf[1] != ':') + return -EINVAL; + + if (buf[0] == 'h') { + switch (buf[2]) { + case '0': + case '1': + case '2': khandy.ena = buf[2]-'0'; return count; + } + } + + if (buf[0] == 't' && count == 258) { + memcpy(act_scancode,buf+2,256); + /* rescan cursor left/right and del */ + clps711x_handykey_init(); + return count; + } + + return -EINVAL; +} + + +/* + * Initialize the keyboard hardware. + * Set all columns high + * Install interrupt handler + * + * Machine dependent parameters: + * + * fastscan: 0 = timer based scan for each column + * 1 = full scan is done in one timer event + * scan_delay: time between column scans + * setup even if you use fastscan (leeds to timer mode) + * scan_interval: time between full scans + * handy.delay: timeout before last entry get's automatically valid + * + */ +void __init clps711x_kbd_init_hw(void) +{ + + /* + * put here machine dependent init stuff + */ + if (machine_is_autcpu12()) { + fastscan = 0; + scan_interval = 50*HZ/1000; + scan_delay = 20*HZ/1000; + khandy.delay = 750*HZ/1000; + act_scancode = autcpu12_scancode; + } else { + printk("No initialization, keyboard killed\n"); + return; + } + + last_column = KBSC_COL0; + key_is_pressed = 0; + + clps711x_handykey_init(); + + /* Register the /proc entry */ + clps711x_keyboard_proc_entry = create_proc_entry("keyboard", 0444, + &proc_root); + if (clps711x_keyboard_proc_entry == NULL) + printk("Couldn't create the /proc entry for the keyboard\n"); + else { + clps711x_keyboard_proc_entry->read_proc = + &clps711x_kbd_proc_keyboard_read; + clps711x_keyboard_proc_entry->write_proc = + &clps711x_kbd_proc_keyboard_write; + } + + /* Initialize the matrix processing task. */ + k_translate = clps711x_translate; + k_unexpected_up = clps711x_unexpected_up; + kbd_process_task.routine = clps711x_kbd_process; + kbd_process_task.data = 0; + + /* Setup the timer for keyboard polling, after kbd int */ + init_timer(&clps711x_kbd_timer); + clps711x_kbd_timer.function = clps711x_kbd_timeout; + clps711x_kbd_timer.data = 0; + init_timer(&clps711x_kbdhandy_timer); + clps711x_kbdhandy_timer.function = clps711x_kbdhandy_timeout; + clps711x_kbdhandy_timer.data = 1; + + /* Initialise scan hardware, request int */ + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) + | KBSC_HI, SYSCON1); + request_irq(IRQ_KBDINT, clps711x_kbd_int, 0,"keyboard", NULL); + + printk("clps711x keyboard init done\n"); + +} diff -uNr linux-2.4.37.9/drivers/char/console.c linux-2.4.37.9-vrs1-5mx2/drivers/char/console.c --- linux-2.4.37.9/drivers/char/console.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/console.c Wed May 26 15:48:46 2010 @@ -72,8 +72,14 @@ * * Removed console_lock, enabled interrupts across all console operations * 13 March 2001, Andrew Morton + * + * Split out con_write_ctrl_* functions from do_con_write & changed + * vc_state to function pointer + * by Russell King , July 1998 */ +#define CONSOLE_WIP + #include #include #include @@ -228,7 +234,7 @@ static inline unsigned short *screenpos(int currcons, int offset, int viewed) { unsigned short *p; - + if (!viewed) p = (unsigned short *)(origin + offset); else if (!sw->con_screen_pos) @@ -735,7 +741,7 @@ else { unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER); if (!p) { - for (i = first; i < currcons; i++) + for (i = first; i< currcons; i++) if (newscreens[i]) kfree(newscreens[i]); return -ENOMEM; @@ -853,7 +859,7 @@ /* the default colour table, for VGA+ colour systems */ int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa, 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff}; -int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa, +int default_grn[] = {0x00,0x00,0xaa,0xaa,0x00,0x00,0xaa,0xaa, 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff}; int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff}; @@ -1399,6 +1405,19 @@ need_wrap = 0; } +static int con_write_ctrl_ESnormal(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESesc(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESnonstd(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESpalette(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESsquare(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESgetpars(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESgotpars(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESpercent(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESfunckey(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_EShash(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESsetG0(int, struct tty_struct *, unsigned int); +static int con_write_ctrl_ESsetG1(int, struct tty_struct *, unsigned int); + enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd, ESpalette }; @@ -1408,7 +1427,7 @@ { top = 0; bottom = video_num_lines; - vc_state = ESnormal; + vc_state = con_write_ctrl_ESnormal; ques = 0; translate = set_translate(LAT1_MAP,currcons); G0_charset = LAT1_MAP; @@ -1506,328 +1525,426 @@ disp_ctrl = 0; return; case 24: case 26: - vc_state = ESnormal; + vc_state = con_write_ctrl_ESnormal; return; case 27: - vc_state = ESesc; + vc_state = con_write_ctrl_ESesc; return; case 127: del(currcons); return; case 128+27: - vc_state = ESsquare; + vc_state = con_write_ctrl_ESsquare; return; } - switch(vc_state) { - case ESesc: - vc_state = ESnormal; - switch (c) { - case '[': - vc_state = ESsquare; - return; - case ']': - vc_state = ESnonstd; - return; - case '%': - vc_state = ESpercent; - return; - case 'E': - cr(currcons); - lf(currcons); - return; - case 'M': - ri(currcons); - return; - case 'D': - lf(currcons); - return; - case 'H': - tab_stop[x >> 5] |= (1 << (x & 31)); - return; - case 'Z': - respond_ID(tty); - return; - case '7': - save_cur(currcons); - return; - case '8': - restore_cur(currcons); - return; - case '(': - vc_state = ESsetG0; - return; - case ')': - vc_state = ESsetG1; - return; - case '#': - vc_state = EShash; - return; - case 'c': - reset_terminal(currcons,1); - return; - case '>': /* Numeric keypad */ - clr_kbd(kbdapplic); - return; - case '=': /* Appl. keypad */ - set_kbd(kbdapplic); - return; - } - return; - case ESnonstd: - if (c=='P') { /* palette escape sequence */ - for (npar=0; npar='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) { - par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ; - if (npar==7) { - int i = par[0]*3, j = 1; - palette[i] = 16*par[j++]; - palette[i++] += par[j++]; - palette[i] = 16*par[j++]; - palette[i++] += par[j++]; - palette[i] = 16*par[j++]; - palette[i] += par[j]; - set_palette(currcons); - vc_state = ESnormal; - } - } else - vc_state = ESnormal; - return; - case ESsquare: - for(npar = 0 ; npar < NPAR ; npar++) - par[npar] = 0; - npar = 0; - vc_state = ESgetpars; - if (c == '[') { /* Function key */ - vc_state=ESfunckey; - return; + vc_state(currcons, tty, c); +} + +static int con_write_utf(int currcons, int c) +{ + unsigned int chr; + + /* Combine UTF-8 into Unicode */ + /* Incomplete characters silently ignored */ + if (c < 0x80) { + utf_count = 0; + return c; + } + + if (utf_count > 0 && (c & 0xc0) == 0x80) { + chr = (utf_char << 6) | (c & 0x3f); + utf_count--; + if (utf_count == 0) + return chr; + } else { + unsigned int count; + if ((c & 0xe0) == 0xc0) { + count = 1; + chr = (c & 0x1f); + } else if ((c & 0xf0) == 0xe0) { + count = 2; + chr = (c & 0x0f); + } else if ((c & 0xf8) == 0xf0) { + count = 3; + chr = (c & 0x07); + } else if ((c & 0xfc) == 0xf8) { + count = 4; + chr = (c & 0x03); + } else if ((c & 0xfe) == 0xfc) { + count = 5; + chr = (c & 0x01); + } else { + count = 0; + chr = 0; } - ques = (c=='?'); - if (ques) - return; - case ESgetpars: - if (c==';' && npar='0' && c<='9') { - par[npar] *= 10; - par[npar] += c-'0'; - return; - } else vc_state=ESgotpars; - case ESgotpars: - vc_state = ESnormal; - switch(c) { - case 'h': - set_mode(currcons,1); - return; - case 'l': - set_mode(currcons,0); - return; - case 'c': - if (ques) { - if (par[0]) - cursor_type = par[0] | (par[1]<<8) | (par[2]<<16); - else - cursor_type = CUR_DEFAULT; - return; - } - break; - case 'm': - if (ques) { - clear_selection(); - if (par[0]) - complement_mask = par[0]<<8 | par[1]; - else - complement_mask = s_complement_mask; - return; - } - break; - case 'n': - if (!ques) { - if (par[0] == 5) - status_report(tty); - else if (par[0] == 6) - cursor_report(currcons,tty); - } - return; + utf_count = count; + } + + utf_char = chr; + return -1; +} + +static int con_write_ctrl_ESnormal(int currcons, struct tty_struct *tty, unsigned int c) +{ + return 0; +} + +static int con_write_ctrl_ESesc(int currcons, struct tty_struct *tty, unsigned int c) +{ + vc_state = con_write_ctrl_ESnormal; + switch (c) { + case '[': + vc_state = con_write_ctrl_ESsquare; + break; + case ']': + vc_state = con_write_ctrl_ESnonstd; + break; + case '%': + vc_state = con_write_ctrl_ESpercent; + break; + case 'E': + cr(currcons); + lf(currcons); + break; + case 'M': + ri(currcons); + break; + case 'D': + lf(currcons); + break; + case 'H': + tab_stop[x >> 5] |= (1 << (x & 31)); + break; + case 'Z': + respond_ID(tty); + break; + case '7': + save_cur(currcons); + break; + case '8': + restore_cur(currcons); + return 1; + case '(': + vc_state = con_write_ctrl_ESsetG0; + break; + case ')': + vc_state = con_write_ctrl_ESsetG1; + break; + case '#': + vc_state = con_write_ctrl_EShash; + break; + case 'c': + reset_terminal(currcons,1); + return 1; + case '>': /* Numeric keypad */ + clr_kbd(kbdapplic); + break; + case '=': /* Appl. keypad */ + set_kbd(kbdapplic); + break; + } + return 0; +} + +static int con_write_ctrl_ESnonstd(int currcons, struct tty_struct *tty, unsigned int c) +{ + switch (c) { + case 'P': /* palette escape sequence */ + for (npar=0; npar='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) { + par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ; + if (npar==7) { + int i = par[0]*3, j = 1; + palette[i] = 16*par[j++]; + palette[i++] += par[j++]; + palette[i] = 16*par[j++]; + palette[i++] += par[j++]; + palette[i] = 16*par[j++]; + palette[i] += par[j]; + set_palette(currcons); + vc_state = con_write_ctrl_ESnormal; } + } else + vc_state = con_write_ctrl_ESnormal; + return 0; +} + +static int con_write_ctrl_ESsquare(int currcons, struct tty_struct *tty, unsigned int c) +{ + for(npar = 0 ; npar < NPAR ; npar++) + par[npar] = 0; + npar = 0; + vc_state = con_write_ctrl_ESgetpars; + if (c == '[') { /* Function key */ + vc_state = con_write_ctrl_ESfunckey; + return 0; + } + ques = (c=='?'); + if (ques) + return 0; + return con_write_ctrl_ESgetpars(currcons, tty, c); +} + +static int con_write_ctrl_ESgetpars(int currcons, struct tty_struct *tty, unsigned int c) +{ + if (c==';' && npar='0' && c<='9') { + par[npar] *= 10; + par[npar] += c-'0'; + return 0; + } else vc_state = con_write_ctrl_ESgotpars; + return con_write_ctrl_ESgotpars(currcons, tty, c); +} + +static int con_write_ctrl_ESgotpars(int currcons, struct tty_struct *tty, unsigned int c) +{ + vc_state = con_write_ctrl_ESnormal; + switch(c) { + case 'h': + set_mode(currcons,1); + return 0; + case 'l': + set_mode(currcons,0); + return 0; + case 'c': if (ques) { - ques = 0; - return; + if (par[0]) + cursor_type = par[0] | (par[1]<<8) | (par[2]<<16); + else + cursor_type = CUR_DEFAULT; + return 0; } - switch(c) { - case 'G': case '`': - if (par[0]) par[0]--; - gotoxy(currcons,par[0],y); - return; - case 'A': - if (!par[0]) par[0]++; - gotoxy(currcons,x,y-par[0]); - return; - case 'B': case 'e': - if (!par[0]) par[0]++; - gotoxy(currcons,x,y+par[0]); - return; - case 'C': case 'a': - if (!par[0]) par[0]++; - gotoxy(currcons,x+par[0],y); - return; - case 'D': - if (!par[0]) par[0]++; - gotoxy(currcons,x-par[0],y); - return; - case 'E': - if (!par[0]) par[0]++; - gotoxy(currcons,0,y+par[0]); - return; - case 'F': - if (!par[0]) par[0]++; - gotoxy(currcons,0,y-par[0]); - return; - case 'd': - if (par[0]) par[0]--; - gotoxay(currcons,x,par[0]); - return; - case 'H': case 'f': - if (par[0]) par[0]--; - if (par[1]) par[1]--; - gotoxay(currcons,par[1],par[0]); - return; - case 'J': - csi_J(currcons,par[0]); - return; - case 'K': - csi_K(currcons,par[0]); - return; - case 'L': - csi_L(currcons,par[0]); - return; - case 'M': - csi_M(currcons,par[0]); - return; - case 'P': - csi_P(currcons,par[0]); - return; - case 'c': - if (!par[0]) - respond_ID(tty); - return; - case 'g': - if (!par[0]) - tab_stop[x >> 5] &= ~(1 << (x & 31)); - else if (par[0] == 3) { - tab_stop[0] = - tab_stop[1] = - tab_stop[2] = - tab_stop[3] = - tab_stop[4] = 0; - } - return; - case 'm': - csi_m(currcons); - return; - case 'q': /* DECLL - but only 3 leds */ - /* map 0,1,2,3 to 0,1,2,4 */ - if (par[0] < 4) - setledstate(kbd_table + currcons, - (par[0] < 3) ? par[0] : 4); - return; - case 'r': - if (!par[0]) - par[0]++; - if (!par[1]) - par[1] = video_num_lines; - /* Minimum allowed region is 2 lines */ - if (par[0] < par[1] && - par[1] <= video_num_lines) { - top=par[0]-1; - bottom=par[1]; - gotoxay(currcons,0,0); - } - return; - case 's': - save_cur(currcons); - return; - case 'u': - restore_cur(currcons); - return; - case 'X': - csi_X(currcons, par[0]); - return; - case '@': - csi_at(currcons,par[0]); - return; - case ']': /* setterm functions */ - setterm_command(currcons); - return; + break; + case 'm': + if (ques) { + clear_selection(); + if (par[0]) + complement_mask = par[0]<<8 | par[1]; + else + complement_mask = s_complement_mask; + return 0; } - return; - case ESpercent: - vc_state = ESnormal; - switch (c) { - case '@': /* defined in ISO 2022 */ - utf = 0; - return; - case 'G': /* prelim official escape code */ - case '8': /* retained for compatibility */ - utf = 1; - return; + break; + case 'n': + if (!ques) { + if (par[0] == 5) + status_report(tty); + else if (par[0] == 6) + cursor_report(currcons,tty); } - return; - case ESfunckey: - vc_state = ESnormal; - return; - case EShash: - vc_state = ESnormal; - if (c == '8') { - /* DEC screen alignment test. kludge :-) */ - video_erase_char = - (video_erase_char & 0xff00) | 'E'; - csi_J(currcons, 2); - video_erase_char = - (video_erase_char & 0xff00) | ' '; - do_update_region(currcons, origin, screenbuf_size/2); + return 0; + } + if (ques) { + ques = 0; + return 0; + } + switch(c) { + case 'G': case '`': + if (par[0]) par[0]--; + gotoxy(currcons,par[0],y); + break; + case 'A': + if (!par[0]) par[0]++; + gotoxy(currcons,x,y-par[0]); + break; + case 'B': case 'e': + if (!par[0]) par[0]++; + gotoxy(currcons,x,y+par[0]); + break; + case 'C': case 'a': + if (!par[0]) par[0]++; + gotoxy(currcons,x+par[0],y); + break; + case 'D': + if (!par[0]) par[0]++; + gotoxy(currcons,x-par[0],y); + break; + case 'E': + if (!par[0]) par[0]++; + gotoxy(currcons,0,y+par[0]); + break; + case 'F': + if (!par[0]) par[0]++; + gotoxy(currcons,0,y-par[0]); + break; + case 'd': + if (par[0]) par[0]--; + gotoxay(currcons,x,par[0]); + break; + case 'H': case 'f': + if (par[0]) par[0]--; + if (par[1]) par[1]--; + gotoxay(currcons,par[1],par[0]); + break; + case 'J': + csi_J(currcons,par[0]); + break; + case 'K': + csi_K(currcons,par[0]); + break; + case 'L': + csi_L(currcons,par[0]); + break; + case 'M': + csi_M(currcons,par[0]); + break; + case 'P': + csi_P(currcons,par[0]); + break; + case 'c': + if (!par[0]) + respond_ID(tty); + break; + case 'g': + if (!par[0]) + tab_stop[x >> 5] &= ~(1 << (x & 31)); + else if (par[0] == 3) { + tab_stop[0] = + tab_stop[1] = + tab_stop[2] = + tab_stop[3] = + tab_stop[4] = 0; + } + break; + case 'm': + csi_m(currcons); + return 1; + case 'q': /* DECLL - but only 3 leds */ + /* map 0,1,2,3 to 0,1,2,4 */ + if (par[0] < 4) + setledstate(kbd_table + currcons, + (par[0] < 3) ? par[0] : 4); + break; + case 'r': + if (!par[0]) + par[0]++; + if (!par[1]) + par[1] = video_num_lines; + /* Minimum allowed region is 2 lines */ + if (par[0] < par[1] && + par[1] <= video_num_lines) { + top=par[0]-1; + bottom=par[1]; + gotoxay(currcons,0,0); } - return; - case ESsetG0: - if (c == '0') - G0_charset = GRAF_MAP; - else if (c == 'B') - G0_charset = LAT1_MAP; - else if (c == 'U') - G0_charset = IBMPC_MAP; - else if (c == 'K') - G0_charset = USER_MAP; - if (charset == 0) - translate = set_translate(G0_charset,currcons); - vc_state = ESnormal; - return; - case ESsetG1: - if (c == '0') - G1_charset = GRAF_MAP; - else if (c == 'B') - G1_charset = LAT1_MAP; - else if (c == 'U') - G1_charset = IBMPC_MAP; - else if (c == 'K') - G1_charset = USER_MAP; - if (charset == 1) - translate = set_translate(G1_charset,currcons); - vc_state = ESnormal; - return; - default: - vc_state = ESnormal; + break; + case 's': + save_cur(currcons); + break; + case 'u': + restore_cur(currcons); + return 1; + case 'X': + csi_X(currcons, par[0]); + break; + case '@': + csi_at(currcons,par[0]); + break; + case ']': /* setterm functions */ + setterm_command(currcons); + break; + } + return 0; +} + +static int con_write_ctrl_ESpercent(int currcons, struct tty_struct *tty, unsigned int c) +{ + vc_state = con_write_ctrl_ESnormal; + switch (c) { + case '@': /* defined in ISO 2022 */ + utf = 0; + break; + case 'G': /* prelim official escape code */ + case '8': /* retained for compatibility */ + utf = 1; + break; } + return 0; +} + +static int con_write_ctrl_ESfunckey(int currcons, struct tty_struct *tty, unsigned int c) +{ + vc_state = con_write_ctrl_ESnormal; + return 0; +} + +static int con_write_ctrl_EShash(int currcons, struct tty_struct *tty, unsigned int c) +{ + vc_state = con_write_ctrl_ESnormal; + if (c == '8') { + /* DEC screen alignment test. kludge :-) */ + video_erase_char = + (video_erase_char & 0xff00) | 'E'; + csi_J(currcons, 2); + video_erase_char = + (video_erase_char & 0xff00) | ' '; + do_update_region(currcons, origin, screenbuf_size/2); + } + return 0; +} + +static int con_write_ctrl_ESsetG0(int currcons, struct tty_struct *tty, unsigned int c) +{ + switch (c) { + case '0': + G0_charset = GRAF_MAP; + break; + case 'B': + G0_charset = LAT1_MAP; + break; + case 'U': + G0_charset = IBMPC_MAP; + break; + case 'K': + G0_charset = USER_MAP; + break; + } + if (charset == 0) { + translate = set_translate(G0_charset,currcons); + return 1; + } + vc_state = con_write_ctrl_ESnormal; + return 0; +} + +static int con_write_ctrl_ESsetG1(int currcons, struct tty_struct *tty, unsigned int c) +{ + switch (c) { + case '0': + G1_charset = GRAF_MAP; + break; + case 'B': + G1_charset = LAT1_MAP; + break; + case 'U': + G1_charset = IBMPC_MAP; + break; + case 'K': + G1_charset = USER_MAP; + break; + } + if (charset == 1) { + translate = set_translate(G1_charset,currcons); + return 1; + } + vc_state = con_write_ctrl_ESnormal; + return 0; } /* This is a temporary buffer used to prepare a tty console write @@ -1861,7 +1978,7 @@ unsigned long draw_from = 0, draw_to = 0; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; u16 himask, charmask; - const unsigned char *orig_buf = NULL; + const unsigned char *orig_buf; int orig_count; if (in_interrupt()) @@ -1919,42 +2036,12 @@ count--; if (utf) { - /* Combine UTF-8 into Unicode */ - /* Incomplete characters silently ignored */ - if(c > 0x7f) { - if (utf_count > 0 && (c & 0xc0) == 0x80) { - utf_char = (utf_char << 6) | (c & 0x3f); - utf_count--; - if (utf_count == 0) - tc = c = utf_char; - else continue; - } else { - if ((c & 0xe0) == 0xc0) { - utf_count = 1; - utf_char = (c & 0x1f); - } else if ((c & 0xf0) == 0xe0) { - utf_count = 2; - utf_char = (c & 0x0f); - } else if ((c & 0xf8) == 0xf0) { - utf_count = 3; - utf_char = (c & 0x07); - } else if ((c & 0xfc) == 0xf8) { - utf_count = 4; - utf_char = (c & 0x03); - } else if ((c & 0xfe) == 0xfc) { - utf_count = 5; - utf_char = (c & 0x01); - } else - utf_count = 0; + tc = con_write_utf(currcons, c); + if (tc < 0) continue; - } - } else { - tc = c; - utf_count = 0; - } - } else { /* no utf */ - tc = translate[toggle_meta ? (c|0x80) : c]; - } + c = tc; + } else /* no utf */ + tc = translate[toggle_meta ? (c|0x80) : c]; /* If the original code was a control character we * only allow a glyph to be displayed if the code is @@ -1972,7 +2059,7 @@ && (c != 127 || disp_ctrl) && (c != 128+27); - if (vc_state == ESnormal && ok) { + if (vc_state == con_write_ctrl_ESnormal && ok) { /* Now try to find out how to display it */ tc = conv_uni_to_pc(vc_cons[currcons].d, tc); if ( tc == -4 ) { @@ -2118,7 +2205,7 @@ if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; - /* read `x' only after setting currecons properly (otherwise + /* read `x' only after setting currcons properly (otherwise the `x' macro will read the x of the foreground console). */ myx = x; @@ -2442,7 +2529,14 @@ vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ; vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ; } + +#ifdef CONFIG_ARCH_PSIONW /* PSIONW_NONSTANDARD */ + /* setterm -foreground 9 should do, but doesn't */ + def_color = 0x0f; /* really white */ +#else def_color = 0x07; /* white */ +#endif + ulcolor = 0x0f; /* bold white */ halfcolor = 0x08; /* grey */ init_waitqueue_head(&vt_cons[currcons]->paste_wait); @@ -2481,8 +2575,8 @@ console_driver.init_termios = tty_std_termios; console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; /* Tell tty_register_driver() to skip consoles because they are - * registered before kmalloc() is ready. We'll patch them in later. - * See comments at console_init(); see also con_init_devfs(). + * registered before kmalloc() is ready. We'll patch them in later. + * See comments at console_init(); see also con_init_devfs(). */ console_driver.flags |= TTY_DRIVER_NO_DEVFS; console_driver.refcount = &console_refcount; @@ -2725,7 +2819,7 @@ if (console_blank_hook && console_blank_hook(1)) return; - if (vesa_blank_mode) + if (vesa_blank_mode) sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1); } @@ -2899,7 +2993,7 @@ if (!op->height) { /* Need to guess font height [compat] */ int h, i; u8 *charmap = op->data, tmp; - + /* If from KDFONTOP ioctl, don't allow things which can be done in userland, so that we can get rid of this soon */ if (!(op->flags & KD_FONT_FLAG_OLD)) @@ -2946,18 +3040,18 @@ op->data = old_op.data; if (!rc && !set) { int c = (op->width+7)/8 * 32 * op->charcount; - + if (op->data && op->charcount > old_op.charcount) rc = -ENOSPC; if (!(op->flags & KD_FONT_FLAG_OLD)) { - if (op->width > old_op.width || + if (op->width > old_op.width || op->height > old_op.height) rc = -ENOSPC; } else { if (op->width != 8) rc = -EIO; else if ((old_op.height && op->height > old_op.height) || - op->height > 32) + op->height > 32) rc = -ENOSPC; } if (!rc && op->data && copy_to_user(op->data, temp, c)) diff -uNr linux-2.4.37.9/drivers/char/ds1307.c linux-2.4.37.9-vrs1-5mx2/drivers/char/ds1307.c --- linux-2.4.37.9/drivers/char/ds1307.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/ds1307.c Wed May 26 15:48:46 2010 @@ -0,0 +1,604 @@ +/* + * ds1307.c + * + * Device driver for Dallas Semiconductor's Real Time Controller DS1307. + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ds1307.h" + +#define DEBUG 0 + +#if DEBUG +static unsigned int rtc_debug = DEBUG; +#else +#define rtc_debug 0 /* gcc will remove all the debug code for us */ +#endif + +static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR; + +struct i2c_driver ds1307_driver; +struct i2c_client *ds1307_i2c_client = 0; + +static unsigned short ignore[] = { I2C_CLIENT_END }; +static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END }; + +static struct i2c_client_address_data addr_data = { + normal_i2c: normal_addr, + normal_i2c_range: ignore, + probe: ignore, + probe_range: ignore, + ignore: ignore, + ignore_range: ignore, + force: ignore, +}; + +static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long); +static int ds1307_rtc_open(struct inode *inode, struct file *file); +static int ds1307_rtc_release(struct inode *inode, struct file *file); + +static struct file_operations rtc_fops = { + owner: THIS_MODULE, + ioctl: ds1307_rtc_ioctl, + open: ds1307_rtc_open, + release: ds1307_rtc_release, +}; + +static struct miscdevice ds1307_rtc_miscdev = { + RTC_MINOR, + "rtc", + &rtc_fops +}; + +static int ds1307_probe(struct i2c_adapter *adap); +static int ds1307_detach(struct i2c_client *client); +static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg); + +struct i2c_driver ds1307_driver = { + name: "DS1307", + id: I2C_DRIVERID_DS1307, + flags: I2C_DF_NOTIFY, + attach_adapter: ds1307_probe, + detach_client: ds1307_detach, + command: ds1307_command +}; + +static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED; + +#define DAT(x) ((unsigned int)((x)->data)) /* keep the control register info */ + +static int +ds1307_readram( char *buf, int len) +{ + unsigned long flags; + unsigned char ad[1] = { 0 }; + int ret; + struct i2c_msg msgs[2] = { + { ds1307_i2c_client->addr , 0, 1, ad }, + { ds1307_i2c_client->addr , I2C_M_RD, len, buf } }; + + spin_lock_irqsave(&ds1307_rtc_lock, flags); + ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2); + spin_unlock_irqrestore(&ds1307_rtc_lock,flags); + + return ret; +} + +static void +ds1307_dumpram( void) +{ + unsigned char buf[DS1307_RAM_SIZE]; + int ret; + + ret = ds1307_readram( buf, DS1307_RAM_SIZE); + + if( ret > 0) + { + int i; + for( i=0; iaddr , 0, 1, ad }, + { ds1307_i2c_client->addr , I2C_M_RD, 1, buf } + }; + unsigned char ctrl_info; + int ret; + + if( enable) + ctrl_info = SQW_ENABLE | RATE_32768HZ; + else + ctrl_info = SQW_DISABLE; + ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info); + + /* read addr 0 (Clock-Halt bit and second counter */ + ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2); + + if( enable) + buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */ + else + buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */ + buf[0] = 0; /* control register address on DS1307 */ + + ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2); +} + +static int +ds1307_attach(struct i2c_adapter *adap, int addr, unsigned short flags,int kind) +{ + struct i2c_client *c; + unsigned char buf[1], ad[1] = { 7 }; + struct i2c_msg msgs[2] = { + { addr , 0, 1, ad }, + { addr , I2C_M_RD, 1, buf } + }; + int ret; + + c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return -ENOMEM; + + strcpy(c->name, "DS1307"); + c->id = ds1307_driver.id; + c->flags = 0; + c->addr = addr; + c->adapter = adap; + c->driver = &ds1307_driver; + c->data = NULL; + + ret = i2c_transfer(c->adapter, msgs, 2); + + if ( ret == 2 ) + { + DAT(c) = buf[0]; + } + else + printk ("ds1307_attach(): i2c_transfer() returned %d.\n",ret); + + ds1307_i2c_client = c; + ds1307_enable_clock( 1); + + return i2c_attach_client(c); +} + +static int +ds1307_probe(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, ds1307_attach); +} + +static int +ds1307_detach(struct i2c_client *client) +{ + i2c_detach_client(client); + ds1307_enable_clock( 0); + + return 0; +} + +static void +ds1307_convert_to_time( struct rtc_time *dt, char *buf) +{ + dt->tm_sec = BCD_TO_BIN(buf[0]); + dt->tm_min = BCD_TO_BIN(buf[1]); + + if ( TWELVE_HOUR_MODE(buf[2]) ) + { + dt->tm_hour = HOURS_12(buf[2]); + if (HOURS_AP(buf[2])) /* PM */ + { + dt->tm_hour += 12; + } + } + else /* 24-hour-mode */ + { + dt->tm_hour = HOURS_24(buf[2]); + } + + dt->tm_mday = BCD_TO_BIN(buf[4]); + /* dt->tm_mon is zero-based */ + dt->tm_mon = BCD_TO_BIN(buf[5]) - 1; + /* year is 1900 + dt->tm_year */ + dt->tm_year = BCD_TO_BIN(buf[6]) + 100; + + if( rtc_debug > 2) + { + printk("ds1307_get_datetime: year = %d\n", dt->tm_year); + printk("ds1307_get_datetime: mon = %d\n", dt->tm_mon); + printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday); + printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour); + printk("ds1307_get_datetime: min = %d\n", dt->tm_min); + printk("ds1307_get_datetime: sec = %d\n", dt->tm_sec); + } +} + +static int +ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt) +{ + unsigned char buf[7], addr[1] = { 0 }; + struct i2c_msg msgs[2] = { + { client->addr, 0, 1, addr }, + { client->addr, I2C_M_RD, 7, buf } + }; + int ret = -EIO; + + memset(buf, 0, sizeof(buf)); + + ret = i2c_transfer(client->adapter, msgs, 2); + + if (ret == 2) { + ds1307_convert_to_time( dt, buf); + ret = 0; + } + else + printk("ds1307_get_datetime(), i2c_transfer() returned %d\n",ret); + + return ret; +} + +static int +ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo) +{ + unsigned char buf[8]; + int ret, len = 4; + + if( rtc_debug > 2) + { + printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year); + printk("ds1307_set_datetime: tm_mon = %d\n", dt->tm_mon); + printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday); + printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour); + printk("ds1307_set_datetime: tm_min = %d\n", dt->tm_min); + printk("ds1307_set_datetime: tm_sec = %d\n", dt->tm_sec); + } + + buf[0] = 0; /* register address on DS1307 */ + buf[1] = (BIN_TO_BCD(dt->tm_sec)); + buf[2] = (BIN_TO_BCD(dt->tm_min)); + buf[3] = (BIN_TO_BCD(dt->tm_hour)); + + if (datetoo) { + len = 8; + /* we skip buf[4] as we don't use day-of-week. */ + buf[5] = (BIN_TO_BCD(dt->tm_mday)); + buf[6] = (BIN_TO_BCD(dt->tm_mon + 1)); + /* The year only ranges from 0-99, we are being passed an offset from 1900, + * and the chip calulates leap years based on 2000, thus we adjust by 100. + */ + buf[7] = (BIN_TO_BCD(dt->tm_year - 100)); + } + ret = i2c_master_send(client, (char *)buf, len); + if (ret == len) + ret = 0; + else + printk("ds1307_set_datetime(), i2c_master_send() returned %d\n",ret); + + + return ret; +} + +static int +ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl) +{ + *ctrl = DAT(client); + + return 0; +} + +static int +ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo) +{ + unsigned char buf[2]; + int ret; + + + buf[0] = 7; /* control register address on DS1307 */ + buf[1] = *cinfo; + /* save the control reg info in the client data field so that get_ctrl + * function doesn't have to do an I2C transfer to get it. + */ + DAT(client) = buf[1]; + + ret = i2c_master_send(client, (char *)buf, 2); + + return ret; +} + +static int +ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem) +{ + unsigned char addr[1]; + struct i2c_msg msgs[2] = { + { client->addr, 0, 1, addr }, + { client->addr, I2C_M_RD, mem->nr, mem->data } + }; + + if ( (mem->loc < DS1307_RAM_ADDR_START) || + ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) ) + return -EINVAL; + + addr[0] = mem->loc; + + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; +} + +static int +ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem) +{ + unsigned char addr[1]; + struct i2c_msg msgs[2] = { + { client->addr, 0, 1, addr }, + { client->addr, 0, mem->nr, mem->data } + }; + + if ( (mem->loc < DS1307_RAM_ADDR_START) || + ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) ) + return -EINVAL; + + addr[0] = mem->loc; + + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; +} + +static int +ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + switch (cmd) { + case DS1307_GETDATETIME: + return ds1307_get_datetime(client, arg); + + case DS1307_SETTIME: + return ds1307_set_datetime(client, arg, 0); + + case DS1307_SETDATETIME: + return ds1307_set_datetime(client, arg, 1); + + case DS1307_GETCTRL: + return ds1307_get_ctrl(client, arg); + + case DS1307_SETCTRL: + return ds1307_set_ctrl(client, arg); + + case DS1307_MEM_READ: + return ds1307_read_mem(client, arg); + + case DS1307_MEM_WRITE: + return ds1307_write_mem(client, arg); + + default: + return -EINVAL; + } +} + +static int +ds1307_rtc_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int +ds1307_rtc_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static int +ds1307_rtc_ioctl( struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned long flags; + struct rtc_time wtime; + int status = 0; + + switch (cmd) { + default: + case RTC_UIE_ON: + case RTC_UIE_OFF: + case RTC_PIE_ON: + case RTC_PIE_OFF: + case RTC_AIE_ON: + case RTC_AIE_OFF: + case RTC_ALM_SET: + case RTC_ALM_READ: + case RTC_IRQP_READ: + case RTC_IRQP_SET: + case RTC_EPOCH_READ: + case RTC_EPOCH_SET: + case RTC_WKALM_SET: + case RTC_WKALM_RD: + status = -EINVAL; + break; + + case RTC_RD_TIME: + spin_lock_irqsave(&ds1307_rtc_lock, flags); + ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime); + spin_unlock_irqrestore(&ds1307_rtc_lock,flags); + + if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time))) + status = -EFAULT; + break; + + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + { + status = -EACCES; + break; + } + + if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) ) + { + status = -EFAULT; + break; + } + + spin_lock_irqsave(&ds1307_rtc_lock, flags); + ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime); + spin_unlock_irqrestore(&ds1307_rtc_lock,flags); + break; + } + + return status; +} + +static char * +ds1307_mon2str( unsigned int mon) +{ + char *mon2str[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + if( mon > 11) return "error"; + else return mon2str[ mon]; +} + +static int ds1307_rtc_proc_output( char *buf) +{ +#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no") + unsigned char ram[DS1307_RAM_SIZE]; + int ret; + + char *p = buf; + + ret = ds1307_readram( ram, DS1307_RAM_SIZE); + if( ret > 0) + { + int i; + struct rtc_time dt; + char text[9]; + + p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n"); + + ds1307_convert_to_time( &dt, ram); + p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n", + dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900, + dt.tm_hour, dt.tm_min, dt.tm_sec); + + p += sprintf(p, "Clock halted : %s\n", CHECK(ram[0],0x80)); + p += sprintf(p, "24h mode : %s\n", CHECK(ram[2],0x40)); + p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10)); + p += sprintf(p, "Freq : "); + + switch( ram[7] & 0x03) + { + case RATE_1HZ: + p += sprintf(p, "1Hz\n"); + break; + case RATE_4096HZ: + p += sprintf(p, "4.096kHz\n"); + break; + case RATE_8192HZ: + p += sprintf(p, "8.192kHz\n"); + break; + case RATE_32768HZ: + default: + p += sprintf(p, "32.768kHz\n"); + break; + + } + + p += sprintf(p, "RAM dump:\n"); + text[8]='\0'; + for( i=0; i126)) ram[i]='.'; + text[i%8] = ram[i]; + if( (i%8) == 7) p += sprintf(p, "%s\n",text); + } + p += sprintf(p, "\n"); + } + else + { + p += sprintf(p, "Failed to read RTC memory!\n"); + } + + return p - buf; +} + +static int ds1307_rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = ds1307_rtc_proc_output (page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + +static __init int ds1307_init(void) +{ + int retval=0; + + if( slave_address != 0xffff) + { + normal_addr[0] = slave_address; + } + + if( normal_addr[0] == 0xffff) + { + printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n", + normal_addr[0]); + return -EINVAL; + } + + retval = i2c_add_driver(&ds1307_driver); + + if (retval==0) + { + misc_register (&ds1307_rtc_miscdev); + create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL); + printk("I2C: DS1307 RTC driver successfully loaded\n"); + + if( rtc_debug) ds1307_dumpram(); + } + return retval; +} + +static __exit void ds1307_exit(void) +{ + remove_proc_entry (PROC_DS1307_NAME, NULL); + misc_deregister(&ds1307_rtc_miscdev); + i2c_del_driver(&ds1307_driver); +} + +module_init(ds1307_init); +module_exit(ds1307_exit); + +MODULE_PARM (slave_address, "i"); +MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC."); + +MODULE_AUTHOR ("Intrinsyc Software Inc."); +MODULE_LICENSE("GPL"); diff -uNr linux-2.4.37.9/drivers/char/ds1307.h linux-2.4.37.9-vrs1-5mx2/drivers/char/ds1307.h --- linux-2.4.37.9/drivers/char/ds1307.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/ds1307.h Wed May 26 15:48:46 2010 @@ -0,0 +1,58 @@ +/* + * ds1307.h + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * + * 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. + * + */ +#ifndef DS1307_H +#define DS1307_H + +#if defined(CONFIG_PXA_EMERSON_SBC) || defined(CONFIG_PXA_CERF_BOARD) || defined(CONFIG_MACH_CSB337) + #define DS1307_I2C_SLAVE_ADDR 0x68 +#else + #define DS1307_I2C_SLAVE_ADDR 0xffff +#endif + +#define DS1307_RAM_ADDR_START 0x08 +#define DS1307_RAM_ADDR_END 0x3F +#define DS1307_RAM_SIZE 0x40 + +#define PROC_DS1307_NAME "driver/ds1307" + +struct rtc_mem { + unsigned int loc; + unsigned int nr; + unsigned char *data; +}; + +#define DS1307_GETDATETIME 0 +#define DS1307_SETTIME 1 +#define DS1307_SETDATETIME 2 +#define DS1307_GETCTRL 3 +#define DS1307_SETCTRL 4 +#define DS1307_MEM_READ 5 +#define DS1307_MEM_WRITE 6 + +#define SQW_ENABLE 0x10 /* Square Wave Enable */ +#define SQW_DISABLE 0x00 /* Square Wave disable */ + +#define RATE_32768HZ 0x03 /* Rate Select 32.768KHz */ +#define RATE_8192HZ 0x02 /* Rate Select 8.192KHz */ +#define RATE_4096HZ 0x01 /* Rate Select 4.096KHz */ +#define RATE_1HZ 0x00 /* Rate Select 1Hz */ + +#define CLOCK_HALT 0x80 /* Clock Halt */ + +#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) + +#define TWELVE_HOUR_MODE(n) (((n)>>6)&1) +#define HOURS_AP(n) (((n)>>5)&1) +#define HOURS_12(n) BCD_TO_BIN((n)&0x1F) +#define HOURS_24(n) BCD_TO_BIN((n)&0x3F) + +#endif diff -uNr linux-2.4.37.9/drivers/char/edb7211_keyb.c linux-2.4.37.9-vrs1-5mx2/drivers/char/edb7211_keyb.c --- linux-2.4.37.9/drivers/char/edb7211_keyb.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/edb7211_keyb.c Wed May 26 15:48:46 2010 @@ -0,0 +1,335 @@ +/* + * drivers/char/edb7211_keyb.c + * + * Copyright (C) 2000 Blue Mug, Inc. All Rights Reserved. + * + * EDB7211 Keyboard driver for ARM Linux. + * + * The EP7211 keyboard hardware only supports generating interrupts for 64 keys. + * The EBD7211's keyboard has 84 keys. Therefore we need to poll for keys, + * instead of waiting for interrupts. + * + * In a real-world hardware situation, this would be a bad thing. It would + * kill power management. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +/* + * The number of jiffies between keyboard scans. + */ +#define KEYBOARD_SCAN_INTERVAL 5 + +/* + * Values for the keyboard column scan control register. + */ +#define KBSC_HI 0x0 /* All driven high */ +#define KBSC_LO 0x1 /* All driven low */ +#define KBSC_X 0x2 /* All high impedance */ +#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */ +#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */ +#define KBSC_COL2 0xa /* Column 2 high, others high impedance */ +#define KBSC_COL3 0xb /* Column 3 high, others high impedance */ +#define KBSC_COL4 0xc /* Column 4 high, others high impedance */ +#define KBSC_COL5 0xd /* Column 5 high, others high impedance */ +#define KBSC_COL6 0xe /* Column 6 high, others high impedance */ +#define KBSC_COL7 0xf /* Column 7 high, others high impedance */ + + +/* XXX: Figure out what these values should be... */ +/* Simple translation table for the SysRq keys */ +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char edb7211_kbd_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +#endif + +/* + * Row/column to scancode mappings. + * + * This table maps row/column keyboard matrix positions to XT scancodes. + * + * The port A rows come first, followed by the extended rows. + */ +static unsigned char colrow_2_scancode[128] = +{ +/* Column: + Row 0 1 2 3 4 5 6 7 */ +/* A0 */ 0x01, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x40, 0x41, +/* A1 */ 0x02, 0x07, 0x06, 0x05, 0x04, 0x03, 0x08, 0x09, +/* A2 */ 0x0f, 0x14, 0x13, 0x12, 0x11, 0x10, 0x15, 0x16, +/* A3 */ 0x3a, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x23, 0x24, +/* A4 */ 0x29, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x31, 0x32, +/* A5 */ 0x39, 0x35, 0x6F, 0x52, 0x00, 0x6B, 0x34, 0x33, +/* A6 */ 0x6A, 0x27, 0x28, 0x00, 0x1c, 0x6D, 0x26, 0x25, +/* A7 */ 0x67, 0x19, 0x1a, 0x1b, 0x2b, 0x68, 0x18, 0x17, +/* E0 */ 0x6C, 0x0c, 0x0d, 0x0e, 0x00, 0x66, 0x0b, 0x0a, +/* E1 */ 0x69, 0x44, 0x45, 0x37, 0x46, 0x77, 0x43, 0x42, +/* E2 */ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E3 */ 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E4 */ 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E5 */ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E6 */ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E7 */ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * A bitfield array which contains the state of the keyboard after the last + * scan. A bit set in this array corresponds to a key down. Only the lower + * 16 bits of each array element are used. + */ +static unsigned long previous_keys[8]; +static unsigned long keys[8]; + + +/* This will be set to a non-zero value if a key was found to be pressed + * in the last scan. */ +static int key_is_pressed; + +static struct tq_struct kbd_process_task; +static struct timer_list edb7211_kbd_timer; + +/* + * External methods. + */ +void edb7211_kbd_init_hw(void); + +/* + * Internal methods. + */ +static int edb7211_kbd_scan_matrix(u_long* keys); +static void edb7211_kbd_timeout(unsigned long data); +static void edb7211_kbd_process(void* data); + +/* + * Translate a raw keycode to an XT keyboard scancode. + */ +static int +edb7211_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + *keycode = colrow_2_scancode[scancode & 0x7f]; + return 1; +} + +/* + * Scan the keyboard matrix; for each key that is pressed, set the + * corresponding bit in the bitfield array. + * + * The parameter is expected to be an array of 8 32-bit values. Only the lower + * 16 bits of each value is used. Each value contains the row bits for the + * corresponding column. + */ +static int +edb7211_kbd_scan_matrix(u_long* keys) +{ + int column, row, key_pressed; + unsigned char port_a_data, ext_port_data; + + key_pressed = 0; + + /* Drive all the columns low. */ + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_LO, + SYSCON1); + + for (column = 0; column < 8; column++) { + + /* Drive the column high. */ + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | + (KBSC_COL0 + column), SYSCON1); + + /* Read port A and the extended port. */ + port_a_data = clps_readb(PADR) & 0xff; + ext_port_data = __raw_readb(EP7211_VIRT_EXTKBD) & 0xff; + + /* Drive all columns tri-state. */ + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X, + SYSCON1); + + /* Look at each column in port A. */ + for (row=0; row < 8; row++) { + /* If the row's bit is set, set the bit in the bitfield. + * Otherwise, clear it. + */ + if (port_a_data & (1 << row)) { + keys[column] |= (1 << row); + key_pressed = 1; + } else { + keys[column] &= ~(1 << row); + } + } + + /* Look at each column in the extended port. */ + for (row=0; row < 8; row++) { + /* If the row's bit is set, set the bit in the bitfield. + * Otherwise, clear it. + */ + if (ext_port_data & (1 << row)) { + keys[column] |= (1 << (row + 8)); + key_pressed = 1; + } else { + keys[column] &= ~(1 << (row + 8)); + } + } + + /* + * Short delay: The example code for the EDB7211 runs an empty + * loop 256 times. At this rate, there were some spurious keys + * generated. I doubled the delay to let the column drives + * settle some. + */ + for (row=0; row < 512; row++) { } + } + + /* If we could use interrupts, we would drive all columns high so + * that interrupts will be generated on key presses. But we can't, + * so we leave all columns floating. + */ + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X, + SYSCON1); + + return key_pressed; +} + +/* + * XXX: This is really ugly; this needs to be reworked to have less levels of + * indentation. + */ +static void +edb7211_kbd_timeout(unsigned long data) +{ + /* Schedule the next timer event. */ + edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL; + add_timer(&edb7211_kbd_timer); + + if (edb7211_kbd_scan_matrix(keys) || key_is_pressed) { + queue_task(&kbd_process_task, &tq_timer); + } else { + key_is_pressed = 0; + } +} + +/* + * Process the keys that have been pressed. + */ +static void +edb7211_kbd_process(void* data) +{ + int i; + + /* First check if any keys have been released. */ + if (key_is_pressed) { + for (i=0; i < 8; i++) { + if (previous_keys[i]) { + int row; + + for (row=0; row < 16; row++) { + if ((previous_keys[i] & (1 << row)) && + !(keys[i] & (1 << row))) { + /* Generate the up event. */ + handle_scancode( + (row<<3)+i, 0); + } + } + } + } + } + + key_is_pressed = 0; + + /* Now scan the keys and send press events. */ + for (i=0; i < 8; i++) { + if (keys[i]) { + int row; + + for (row=0; row < 16; row++) { + if (keys[i] & (1 << row)) { + if (previous_keys[i] & (1 << row)) { + /* Generate the hold event. */ + handle_scancode((row<<3)+i, 1); + } else { + /* Generate the down event. */ + handle_scancode((row<<3)+i, 1); + } + + key_is_pressed = 1; + } + } + } + } + + /* Update the state variables. */ + memcpy(previous_keys, keys, 8 * sizeof(unsigned long)); +} + +static char edb7211_unexpected_up(unsigned char scancode) +{ + return 0200; +} + +static void edb7211_leds(unsigned char leds) +{ +} + +/* + * Initialize the keyboard hardware. Set the column drives low and + * start the timer. + */ +void __init +edb7211_kbd_init_hw(void) +{ + k_translate = edb7211_translate; + k_unexpected_up = edb7211_unexpected_up; + k_leds = edb7211_leds; + + /* + * If we had the ability to use interrupts, we would want to drive all + * columns high. But we have more keys than can generate interrupts, so + * we leave them floating. + */ + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X, + SYSCON1); + + /* Initialize the matrix processing task. */ + kbd_process_task.routine = edb7211_kbd_process; + kbd_process_task.data = NULL; + + /* Setup the timer to poll the keyboard. */ + init_timer(&edb7211_kbd_timer); + edb7211_kbd_timer.function = edb7211_kbd_timeout; + edb7211_kbd_timer.data = (unsigned long)NULL; + edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL; + add_timer(&edb7211_kbd_timer); +} + + diff -uNr linux-2.4.37.9/drivers/char/epxa_wdt.c linux-2.4.37.9-vrs1-5mx2/drivers/char/epxa_wdt.c --- linux-2.4.37.9/drivers/char/epxa_wdt.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/epxa_wdt.c Wed May 26 15:48:46 2010 @@ -0,0 +1,178 @@ +/* + * Watchdog driver for the Altera Excalibur EPXA1DB + * + * (c) Copyright 2003 Krzysztof Marianski + * Based on SA11x0 Watchdog driver by Oleg Drokin + * + * 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 material is provided "AS-IS" and at no charge + * + * (c) Copyright 2003 Krzysztof Marianski + * + * 1/08/2003 Initial release + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WATCHDOG00_TYPE (volatile unsigned int*) +#include +#include + +#define TIMER_MARGIN 30 /* (secs) Default is 30 seconds */ + +static int margin = TIMER_MARGIN; /* in seconds */ +static int epxa1wdt_users; +static unsigned char last_written_byte; + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout=1; +#else +static int nowayout=0; +#endif + +#ifdef MODULE +MODULE_PARM(margin,"i"); +MODULE_PARM(nowayout, "i"); +#endif + +/* + * Allow only one person to hold it open + */ + +static int epxa1dog_open(struct inode *inode, struct file *file) +{ + if(test_and_set_bit(1,&epxa1wdt_users)) + return -EBUSY; + + /* Reset the Watchdog, just to be sure we don't set + a value close to actual value of WDOG_COUNT register */ + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1; + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2; + + /* Activate EPXA1DB Watchdog timer */ + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK; + + last_written_byte = 'V'; //in case user opens it only to ioctl + return 0; +} + +static int epxa1dog_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer and set lock bit when no special + * character 'V' was last written + */ + + if ((last_written_byte != 'V') && (nowayout)) { + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)) |= WDOG_CR_LK_MSK; + printk("No special character 'V' was written to Watchdog just before closing it\n"); + printk("WATCHDOG LOCKED - Reboot expected!!!\n"); + } else + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))=0; + + epxa1wdt_users = 0; + + return 0; +} + +static ssize_t epxa1dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* Reset Watchdog timer. */ + if(len) { + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1; + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2; + last_written_byte = *data; + return 1; + } + return 0; +} + +static int epxa1dog_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + identity: "EPXA Watchdog", + }; + + switch(cmd){ + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)); +// case WDIOC_GETSTATUS: //TODO +// return put_user(0,(int *)arg); +// case WDIOC_GETBOOTSTATUS: //TODO +// return 0; + case WDIOC_KEEPALIVE: + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1; + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2; + return 0; + case WDIOC_SETTIMEOUT: + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK; + return 0; + case WDIOC_GETTIMEOUT: + return put_user( ((*WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)))/EXC_INPUT_CLK_FREQUENCY), (int*)arg); + } +} + +static struct file_operations epxa1dog_fops = { + .owner = THIS_MODULE, + .write = epxa1dog_write, + .ioctl = epxa1dog_ioctl, + .open = epxa1dog_open, + .release = epxa1dog_release, +}; + +static struct miscdevice epxa1dog_miscdev= +{ + .minor = WATCHDOG_MINOR, + .name = "EPXA watchdog", + .fops = &epxa1dog_fops +}; + +static int __init epxa1dog_init(void) +{ + int ret; + + ret = misc_register(&epxa1dog_miscdev); + + if (ret) + return ret; + + printk("EPXA Watchdog Timer: timer margin %d sec\n", margin); + printk("EPXA Watchdog Timer: no way out is %s\n", nowayout ? "enabled" : "disabled"); + + return 0; +} + +static void __exit epxa1dog_exit(void) +{ + misc_deregister(&epxa1dog_miscdev); +} + +module_init(epxa1dog_init); +module_exit(epxa1dog_exit); + +MODULE_AUTHOR("Krzysztof Marianski "); +MODULE_DESCRIPTION("EPXA Watchdog Timer"); +MODULE_LICENSE("GPL"); diff -uNr linux-2.4.37.9/drivers/char/gc_kbmap.h linux-2.4.37.9-vrs1-5mx2/drivers/char/gc_kbmap.h --- linux-2.4.37.9/drivers/char/gc_kbmap.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/gc_kbmap.h Wed May 26 15:48:46 2010 @@ -0,0 +1,162 @@ + + +#define KK_NONE 0x7f +#define KK_ESC 0x00 +#define KK_F1 0x01 +#define KK_F2 0x02 +#define KK_F3 0x03 +#define KK_F4 0x04 +#define KK_F5 0x05 +#define KK_F6 0x06 +#define KK_F7 0x07 +#define KK_F8 0x08 +#define KK_F9 0x09 +#define KK_F10 0x0a +#define KK_F11 0x0b +#define KK_F12 0x0c +#define KK_PRNT 0x0d +#define KK_SCRL 0x0e +#define KK_BRK 0x0f +#define KK_AGR 0x10 +#define KK_1 0x11 +#define KK_2 0x12 +#define KK_3 0x13 +#define KK_4 0x14 +#define KK_5 0x15 +#define KK_6 0x16 +#define KK_7 0x17 +#define KK_8 0x18 +#define KK_9 0x19 +#define KK_0 0x1a +#define KK_MINS 0x1b +#define KK_EQLS 0x1c +#define KK_BKSP 0x1e +#define KK_INS 0x1f +#define KK_HOME 0x20 +#define KK_PGUP 0x21 +#define KK_NUML 0x22 +#define KP_SLH 0x23 +#define KP_STR 0x24 +#define KP_MNS 0x3a +#define KK_TAB 0x26 +#define KK_Q 0x27 +#define KK_W 0x28 +#define KK_E 0x29 +#define KK_R 0x2a +#define KK_T 0x2b +#define KK_Y 0x2c +#define KK_U 0x2d +#define KK_I 0x2e +#define KK_O 0x2f +#define KK_P 0x30 +#define KK_LSBK 0x31 +#define KK_RSBK 0x32 +#define KK_ENTR 0x47 +#define KK_DEL 0x34 +#define KK_END 0x35 +#define KK_PGDN 0x36 +#define KP_7 0x37 +#define KP_8 0x38 +#define KP_9 0x39 +#define KP_PLS 0x4b +#define KK_CAPS 0x5d +#define KK_A 0x3c +#define KK_S 0x3d +#define KK_D 0x3e +#define KK_F 0x3f +#define KK_G 0x40 +#define KK_H 0x41 +#define KK_J 0x42 +#define KK_K 0x43 +#define KK_L 0x44 +#define KK_SEMI 0x45 +#define KK_SQOT 0x46 +#define KK_HASH 0x1d +#define KP_4 0x48 +#define KP_5 0x49 +#define KP_6 0x4a +#define KK_LSFT 0x4c +#define KK_BSLH 0x33 +#define KK_Z 0x4e +#define KK_X 0x4f +#define KK_C 0x50 +#define KK_V 0x51 +#define KK_B 0x52 +#define KK_N 0x53 +#define KK_M 0x54 +#define KK_COMA 0x55 +#define KK_DOT 0x56 +#define KK_FSLH 0x57 +#define KK_RSFT 0x58 +#define KK_UP 0x59 +#define KP_1 0x5a +#define KP_2 0x5b +#define KP_3 0x5c +#define KP_ENT 0x67 +#define KK_LCTL 0x3b +#define KK_LALT 0x5e +#define KK_SPCE 0x5f +#define KK_RALT 0x60 +#define KK_RCTL 0x61 +#define KK_LEFT 0x62 +#define KK_DOWN 0x63 +#define KK_RGHT 0x64 +#define KP_0 0x65 +#define KP_DOT 0x66 + +static char kbmap[128] = { +KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_AGR, KK_BSLH, KK_TAB, KK_Z, KK_A, KK_X, KK_NONE, +KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_ESC, KK_DEL, KK_Q, KK_CAPS, KK_S, KK_C, KK_3, +KK_NONE, KK_1, KK_NONE, KK_W, KK_NONE, KK_D, KK_V, KK_4, +KK_NONE, KK_2, KK_T, KK_E, KK_NONE, KK_F, KK_B, KK_5, +KK_NONE, KK_9, KK_Y, KK_R, KK_K, KK_G, KK_N, KK_6, +KK_NONE, KK_0, KK_U, KK_O, KK_L, KK_H, KK_M, KK_7, +KK_NONE, KK_MINS, KK_I, KK_P, KK_SEMI, KK_J, KK_COMA, KK_8, +KK_NONE, KK_EQLS, KK_ENTR, KK_LSBK, KK_BSLH, KK_FSLH, KK_DOT, KK_NONE, +KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_BKSP, KK_DOWN, KK_RSBK, KK_UP, KK_LEFT, KK_SPCE, KK_RGHT, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE}; + +static char kbmapFN[128] = { +KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F3, +KK_NONE, KK_F1, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F4, +KK_NONE, KK_F2, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F5, +KK_NONE, KK_F9, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F6, +KK_NONE, KK_F10, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F7, +KK_NONE, KK_NUML, KK_NONE, KK_INS, KK_PRNT, KK_NONE, KK_NONE, KK_F8, +KK_NONE, KK_BRK, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_PGDN, KK_SCRL, KK_PGUP, KK_HOME, KK_NONE, KK_END, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE}; + +static char kbmapNL[128] = { +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KP_9, KK_NONE, KK_NONE, KP_2, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KP_STR, KP_4, KP_6, KP_3, KK_NONE, KP_0, KP_7, +KK_NONE, KK_NONE, KP_5, KP_MNS, KP_PLS, KP_1, KK_NONE, KP_8, +KK_NONE, KK_NONE, KP_ENT, KK_NONE, KK_NONE, KP_SLH, KP_DOT, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE}; + + + diff -uNr linux-2.4.37.9/drivers/char/gc_keyb.c linux-2.4.37.9-vrs1-5mx2/drivers/char/gc_keyb.c --- linux-2.4.37.9/drivers/char/gc_keyb.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/gc_keyb.c Wed May 26 15:48:46 2010 @@ -0,0 +1,1145 @@ +/* + * linux/arch/arm/drivers/char/gc_keyb.c + * + * Copyright 2000 Applied Data Systems + * + * Keyboard & Smartio driver for GraphicsClient ARM Linux. + * Graphics Client is SA1110 based single board computer by + * Applied Data Systems (http://www.applieddata.net) + * + * Change log: + * 7-10/6/01 Thomas Thaele + * - Added Keyboard Sniffer on /dev/sio12 + * - First implementation of PC- compatible Scancodes (thanks to pc_keyb.c) + * 3/23/01 Woojung Huh + * Power Management added + * 12/01/00 Woojung Huh + * Bug fixed + * 11/16/00 Woojung Huh [whuh@applieddata.net] + * Added smartio device driver on it + */ + +/* + * Introduced setkeycode, ketkeycode for the GC+ by Thomas Thaele + * GC+ now performs like a real PC on the keyboard. + * Warning: this code is still beta! PrntScrn and Pause keys are not + * completely tested and implemented!!! Keyboard driver can be confused + * by hacking like crazy on the keyboard. (hardware problem on serial line?) + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ADS_AVR_IRQ 63 + +#define SMARTIO_IOCTL_BASES 's' +#define SMARTIO_KPD_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 0, int) +#define SMARTIO_KPD_SETUP _IOW(SMARTIO_IOCTL_BASES, 1, short) +#define SMARTIO_BL_CONTROL _IOW(SMARTIO_IOCTL_BASES, 2, char) +#define SMARTIO_BL_CONTRAST _IOW(SMARTIO_IOCTL_BASES, 3, char) +#define SMARTIO_PORT_CONFIG _IOW(SMARTIO_IOCTL_BASES, 4, char) +#define SMARTIO_SNIFFER_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 5, long) + + +/* Simple translation table for the SysRq keys */ + +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char pckbd_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +#endif + +/* + * Translation of escaped scancodes to keycodes. + * This is now user-settable. + * The keycodes 1-88,96-111,119 are fairly standard, and + * should probably not be changed - changing might confuse X. + * X also interprets scancode 0x5d (KEY_Begin). + * + * For 1-88 keycode equals scancode. + */ + +#define E0_KPENTER 96 +#define E0_RCTRL 97 +#define E0_KPSLASH 98 +#define E0_PRSCR 99 +#define E0_RALT 100 +#define E0_BREAK 101 /* (control-pause) */ +#define E0_HOME 102 +#define E0_UP 103 +#define E0_PGUP 104 +#define E0_LEFT 105 +#define E0_RIGHT 106 +#define E0_END 107 +#define E0_DOWN 108 +#define E0_PGDN 109 +#define E0_INS 110 +#define E0_DEL 111 + +#define E1_PAUSE 119 + +/* + * The keycodes below are randomly located in 89-95,112-118,120-127. + * They could be thrown away (and all occurrences below replaced by 0), + * but that would force many users to use the `setkeycodes' utility, where + * they needed not before. It does not matter that there are duplicates, as + * long as no duplication occurs for any single keyboard. + */ +#define SC_LIM 89 + +#define FOCUS_PF1 85 /* actual code! */ +#define FOCUS_PF2 89 +#define FOCUS_PF3 90 +#define FOCUS_PF4 91 +#define FOCUS_PF5 92 +#define FOCUS_PF6 93 +#define FOCUS_PF7 94 +#define FOCUS_PF8 95 +#define FOCUS_PF9 120 +#define FOCUS_PF10 121 +#define FOCUS_PF11 122 +#define FOCUS_PF12 123 + +#define JAP_86 124 +/* tfj@olivia.ping.dk: + * The four keys are located over the numeric keypad, and are + * labelled A1-A4. It's an rc930 keyboard, from + * Regnecentralen/RC International, Now ICL. + * Scancodes: 59, 5a, 5b, 5c. + */ +#define RGN1 124 +#define RGN2 125 +#define RGN3 126 +#define RGN4 127 + +static unsigned char high_keys[128 - SC_LIM] = { + RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */ +}; + +/* BTC */ +#define E0_MACRO 112 +/* LK450 */ +#define E0_F13 113 +#define E0_F14 114 +#define E0_HELP 115 +#define E0_DO 116 +#define E0_F17 117 +#define E0_KPMINPLUS 118 +/* + * My OmniKey generates e0 4c for the "OMNI" key and the + * right alt key does nada. [kkoller@nyx10.cs.du.edu] + */ +#define E0_OK 124 +/* + * New microsoft keyboard is rumoured to have + * e0 5b (left window button), e0 5c (right window button), + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] + * [or: Windows_L, Windows_R, TaskMan] + */ +#define E0_MSLW 125 +#define E0_MSRW 126 +#define E0_MSTM 127 + +static unsigned char e0_keys[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */ + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ +}; + +int gc_kbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + if (scancode < SC_LIM || scancode > 255 || keycode > 127) + return -EINVAL; + if (scancode < 128) + high_keys[scancode - SC_LIM] = keycode; + else + e0_keys[scancode - 128] = keycode; + return 0; +} + +int gc_kbd_getkeycode(unsigned int scancode) +{ + return + (scancode < SC_LIM || scancode > 255) ? -EINVAL : + (scancode < 128) ? high_keys[scancode - SC_LIM] : + e0_keys[scancode - 128]; +} + +int gc_kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + static int prev_scancode; + + /* special prefix scancodes.. */ + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; + return 0; + } + + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */ + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; + return 0; + } + + scancode &= 0x7f; + + if (prev_scancode) { + /* + * usually it will be 0xe0, but a Pause key generates + * e1 1d 45 e1 9d c5 when pressed, and nothing when released + */ + if (prev_scancode != 0xe0) { + if (prev_scancode == 0xe1 && scancode == 0x1d) { + prev_scancode = 0x100; + return 0; + } else if (prev_scancode == 0x100 && scancode == 0x45) { + *keycode = E1_PAUSE; + prev_scancode = 0; + } else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); +#endif + prev_scancode = 0; + return 0; + } + } else { + prev_scancode = 0; + /* + * The keyboard maintains its own internal caps lock and + * num lock statuses. In caps lock mode E0 AA precedes make + * code and E0 2A follows break code. In num lock mode, + * E0 2A precedes make code and E0 AA follows break code. + * We do our own book-keeping, so we will just ignore these. + */ + /* + * For my keyboard there is no caps lock mode, but there are + * both Shift-L and Shift-R modes. The former mode generates + * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs. + * So, we should also ignore the latter. - aeb@cwi.nl + */ + if (scancode == 0x2a || scancode == 0x36) + return 0; + + if (e0_keys[scancode]) + *keycode = e0_keys[scancode]; + else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", + scancode); +#endif + return 0; + } + } + } else if (scancode >= SC_LIM) { + /* This happens with the FOCUS 9000 keyboard + Its keys PF1..PF12 are reported to generate + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f + Moreover, unless repeated, they do not generate + key-down events, so we have to zero up_flag below */ + /* Also, Japanese 86/106 keyboards are reported to + generate 0x73 and 0x7d for \ - and \ | respectively. */ + /* Also, some Brazilian keyboard is reported to produce + 0x73 and 0x7e for \ ? and KP-dot, respectively. */ + + *keycode = high_keys[scancode - SC_LIM]; + + if (!*keycode) { + if (!raw_mode) { +#ifdef KBD_REPORT_UNKN + printk(KERN_INFO "keyboard: unrecognized scancode (%02x)" + " - ignored\n", scancode); +#endif + } + return 0; + } + } else + *keycode = scancode; + return 1; +} + +// this table converts the hardware dependent codes of a MF-2 Keyboard to +// the codes normally comming out of a i8042. This table is 128 Bytes too +// big, but for stability reasons it should be kept like it is! +// There is no range checking in the code! +static int mf_two_kbdmap[256] = { + 00, 67, 65, 63, 61, 59, 60, 88, 00, 68, 66, 64, 62, 15, 41, 00, + 00, 56, 42, 00, 29, 16, 02, 00, 00, 00, 44, 31, 30, 17, 03, 00, + 00, 46, 45, 32, 18, 05, 04, 00, 00, 57, 47, 33, 20, 19, 06, 00, + 00, 49, 48, 35, 34, 21, 7, 00, 00, 00, 50, 36, 22, 8, 9, 00, + 00, 51, 37, 23, 24, 11, 10, 00, 00, 52, 53, 38, 39, 25, 12, 00, + 00, 00, 40, 00, 26, 13, 00, 00, 58, 54, 28, 27, 00, 43, 00, 00, + 00, 86, 00, 00, 00, 00, 14, 00, 00, 79, 00, 75, 71, 00, 00, 00, + 82, 83, 80, 76, 77, 72, 01, 69, 87, 78, 81, 74, 55, 73, 70, 00, + 00, 00, 00, 65, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 }; + + +// some texts displayed by the proc_file_system +static char *kbd_sniff[2] = { "off", "on" }; +static char *kbd_sniff_mode[2] = { "passive", "active" }; + +#define PASSIVE 0 +#define ACTIVE 1 + +// is the sniffer active (1) or inactive (0) +static int SNIFFER = 0; +// do we get a copy (SNIFFMODE = PASSIVE) or do we get the original data (SNIFFMODE = ACTIVE) +// and have to reinsert the data +static int SNIFFMODE = PASSIVE; + +// we allow only one process to sniff +static int sniffer_in_use = 0; + +// timeout for the keyboard sniffer -1 = blocking, otherwise timeout in msecs +static long sniffer_timeout = -1; + +// the value we sniffed from the keyboard +static int sniffed_value; + +static char *smartio_version = "1.02 MF-II compatibility patch "; +static char *smartio_date = "Aug-27-2001"; + +static int sio_reset_flag; +static int kbd_press_flag; + +static void send_SSP_msg(unchar *pBuf, int num) +{ + ushort tmp; + int i; + + for (i=0;i 7)) + return 0xFFFF; + + CONV_ADC_CMD.Opt[0] = (unchar) channel; + + lock_smartio(&flags); + send_SSP_msg((unchar *) &CONV_ADC_CMD, 3); + unlock_smartio(&flags); + + interruptible_sleep_on(&smartio_adc_queue); + + return adc_value & 0x3FF; +} + +static ushort read_sio_port(int port) +{ + unsigned long flags; + ushort ret; + + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D)) + return 0xFFFF; + + READ_PORT_CMD.Code = (unchar) port; + + lock_smartio(&flags); + send_SSP_msg((unchar *) &READ_PORT_CMD, 2); + ret = read_SSP_response(1); + unlock_smartio(&flags); + + return ret; +} + +static ushort read_sio_kpd(void) +{ + long timeout; + + // kpd_timeout is mSec order + // interrupt_sleep_on_timeout is based on 10msec timer tick + if (kpd_timeout == -1) { + interruptible_sleep_on(&smartio_kpd_queue); + } + else { + timeout = interruptible_sleep_on_timeout(&smartio_kpd_queue, + kpd_timeout/10); + if (timeout == 0) { + // timeout without keypad input + return 0xFFFF; + } + } + return kpd_value; +} + +static ushort read_sio_sniff(void) +{ + long timeout; + + // kpd_timeout is mSec order + // interrupt_sleep_on_timeout is based on 10msec timer tick + if (sniffer_timeout == -1) { + interruptible_sleep_on(&sniffer_queue); + } + else { + timeout = interruptible_sleep_on_timeout(&sniffer_queue, + sniffer_timeout/10); + if (timeout == 0) { + // timeout without keypad input + return -1; + } + } + return (ushort)sniffed_value; +} + +static struct sio_ver { + uint DevVer; + uint DevType; + uint FwLevel; +}; + +static ushort read_sio_version(struct sio_ver *ptr) +{ + unsigned long flags; + ushort ret; + + // Read Device Version + lock_smartio(&flags); + send_SSP_msg((unchar *) &READ_DEVVER_CMD, 2); + ret = read_SSP_response(1); + unlock_smartio(&flags); + ptr->DevVer = (uint)ret; + // Read Device Type + lock_smartio(&flags); + send_SSP_msg((unchar *) &READ_DEVTYPE_CMD, 2); + ret = read_SSP_response(2); + unlock_smartio(&flags); + // swap MSB & LSB + ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8); + ptr->DevType = (uint)ret; + // Read Firmware Level + lock_smartio(&flags); + send_SSP_msg((unchar *) &READ_FWLEVEL_CMD, 2); + ret = read_SSP_response(2); + unlock_smartio(&flags); + // swap MSB & LSB + ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8); + ptr->FwLevel = (uint)ret; + + return 0; +} + +static ssize_t sio_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + unsigned int minor = MINOR(inode->i_rdev); + ushort *ret = (ushort *)buf; + + switch (minor) { + case SMARTIO_ADC: + if ((*ret = read_sio_adc(buf[0])) != 0xFFFF) + return sizeof(ushort); // 2 bytes + case SMARTIO_PORT_B: + case SMARTIO_PORT_C: + case SMARTIO_PORT_D: + if ((*ret = read_sio_port(minor)) != 0xFFFF) + return sizeof(ushort); + case SMARTIO_VERSION: + if ((read_sio_version((struct sio_ver *)buf)) != 0xFFFF) + return sizeof(struct sio_ver); + case SMARTIO_KEYPAD: + if ((*ret = read_sio_kpd()) != 0xFFFF) + return sizeof(ushort); + case SMARTIO_KBD_SNIFFER: + if ((*ret = read_sio_sniff()) != (ushort)-1) + return 1; + default : + return -ENXIO; + } +} + +static SMARTIO_CMD WRITE_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } }; +static SMARTIO_CMD SELECT_OPT_CMD = { 0x80, 0x00, { 0x00, 0x00 } }; +static SMARTIO_CMD CONTROL_BL_CMD = { 0x80, 0x00, { 0x00, 0x00 } }; +static SMARTIO_CMD CONTRAST_BL_CMD = { 0x80, 0x21, { 0x00, 0x00 } }; +static SMARTIO_CMD CONTROL_KPD_CMD = { 0x80, 0x27, { 0x00, 0x00 } }; +static SMARTIO_CMD CONTROL_VEE_CMD = { 0x80, 0x22, { 0x00, 0x00 } }; + +static ushort write_sio_port(int port, unchar value) +{ + unsigned long flags; + + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D)) + return 0xFFFF; + + WRITE_PORT_CMD.Code = (unchar) port; + WRITE_PORT_CMD.Opt[0] = (unchar) value; + + lock_smartio(&flags); + send_SSP_msg((unchar *) &WRITE_PORT_CMD, 3); + unlock_smartio(&flags); + + return 0; +} + +static ushort write_sio_select(unchar select) +{ + unsigned long flags; + + if ((select < 1) || (select > 2)) + return 0xFFFF; + + SELECT_OPT_CMD.Code = (unchar) (select + 0x28); + + lock_smartio(&flags); + send_SSP_msg((unchar *) &SELECT_OPT_CMD, 2); + unlock_smartio(&flags); + + return 0; +} + +static ushort control_sio_backlite(int cmd, int value) +{ + unsigned long flags; + + if (cmd == SMARTIO_BL_CONTRAST) { + value &= 0xFF; + CONTRAST_BL_CMD.Opt[0] = (unchar) value; + + lock_smartio(&flags); + send_SSP_msg((unchar *) &CONTRAST_BL_CMD, 3); + unlock_smartio(&flags); + } + else if (cmd == SMARTIO_BL_CONTROL) { + if (value == 0x00) { + // Backlite OFF + CONTROL_BL_CMD.Code = 0x24; + } + else { + // Backlite ON + CONTROL_BL_CMD.Code = 0x23; + } + lock_smartio(&flags); + send_SSP_msg((unchar *) &CONTROL_BL_CMD, 2); + unlock_smartio(&flags); + } + else + return 0xFFFF; + + return 0; +} + +static ushort control_sio_keypad(int x, int y) +{ + unsigned long flags; + + if ( (x<1) || (x>8) || (y<1) || (y>8)) { + return 0xFFFF; + } + + CONTROL_KPD_CMD.Opt[0] = (unchar) x; + CONTROL_KPD_CMD.Opt[1] = (unchar) y; + + lock_smartio(&flags); + send_SSP_msg((unchar *) &CONTROL_KPD_CMD, 4); + unlock_smartio(&flags); + + return 0; +} + +static ushort control_sio_vee(int value) +{ + unsigned long flags; + + value &= 0xFF; + CONTROL_VEE_CMD.Opt[0] = (unchar) value; + + lock_smartio(&flags); + send_SSP_msg((unchar *) &CONTROL_VEE_CMD, 3); + unlock_smartio(&flags); + + return 0; +} + +static ssize_t sio_write(struct file *file, const char *buf, size_t cont, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode; + unsigned int minor = MINOR(inode->i_rdev); + + switch (minor) { + case SMARTIO_PORT_B: + case SMARTIO_PORT_C: + case SMARTIO_PORT_D: + if (write_sio_port(minor, buf[0]) != 0xFFFF) + return 1; + case SMARTIO_SELECT_OPTION: + if (write_sio_select(buf[0]) != 0xFFFF) + return 1; + case SMARTIO_BACKLITE: + if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) + return 1; + case SMARTIO_KEYPAD: + if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) + return 2; + case SMARTIO_VEE_PWM: + if (control_sio_vee(buf[0]) != 0xFFFF) + return 1; + case SMARTIO_KBD_SNIFFER: + // here are the scancodes injected + handle_scancode((unchar)buf[0], (buf[0] & 0x80) ? 0 : 1); + wake_up_interruptible(&keyboard_done_queue); + // give some time to process! File IO is a bit faster than manual typing ;-) + udelay(10000); + return 1; + default: + return -ENXIO; + } +} + +static unsigned int sio_poll(struct file *file, struct poll_table_struct *wait) +{ + return 0; +} + +static SMARTIO_CMD IOCTL_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } }; + +static ushort ioctl_sio_port(int port, unchar value) +{ + unsigned long flags; + + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D)) + return 0xFFFF; + + IOCTL_PORT_CMD.Code = (unchar) port + 0x04; // 0x05 ~ 0x08 + if (port == SMARTIO_PORT_B) { + // Port B has 4 bits only + IOCTL_PORT_CMD.Opt[0] = (unchar) value & 0x0F; + } + else + IOCTL_PORT_CMD.Opt[0] = (unchar) value; + + lock_smartio(&flags); + send_SSP_msg((unchar *) &IOCTL_PORT_CMD, 3); + unlock_smartio(&flags); + + return 0; +} + +static int sio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned int minor = MINOR(inode->i_rdev); + unchar *buf = (unchar *)arg; + + switch (minor) { + case SMARTIO_PORT_B: + case SMARTIO_PORT_C: + case SMARTIO_PORT_D: + if (cmd == SMARTIO_PORT_CONFIG) { + if (ioctl_sio_port(minor, buf[0]) != 0xFFFF) + return 0; + } + return -EINVAL; + case SMARTIO_SELECT_OPTION: + if (write_sio_select(buf[0]) != 0xFFFF) return 0; + return -EINVAL; + case SMARTIO_BACKLITE: + if (cmd == SMARTIO_BL_CONTROL) { + if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) return 0; + } + else if (cmd == SMARTIO_BL_CONTRAST) { + if (control_sio_backlite(SMARTIO_BL_CONTRAST, buf[0]) != 0xFFFF) return 0; + } + else return -EINVAL; + case SMARTIO_KEYPAD: + if (cmd == SMARTIO_KPD_TIMEOUT) { + kpd_timeout = *(long*)buf; + return 0; + } + else if (cmd == SMARTIO_KPD_SETUP) { + if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) return 0; + } + return -EINVAL; + case SMARTIO_VEE_PWM: + if (control_sio_vee(buf[0]) != 0xFFFF) return 0; + return -EINVAL; + case SMARTIO_KBD_SNIFFER: + if (cmd == SMARTIO_SNIFFER_TIMEOUT) { + sniffer_timeout = *(long*)buf; + if (sniffer_timeout < 0) sniffer_timeout = -1; + // the value will be devided by 10 later on + if (!sniffer_timeout) sniffer_timeout = 10; + return 0; + } + return -EINVAL; + default: + return -ENXIO; + } +} + +static int sio_open(struct inode *inode, struct file *file) +{ + unsigned int minor = MINOR(inode->i_rdev); + + // we open all by default. we only have a special handler for the kbd sniffer + switch (minor) { + case SMARTIO_KBD_SNIFFER: + if (sniffer_in_use) return -EBUSY; + sniffer_in_use = 1; + SNIFFER = 1; + // sniff in active or passive mode + if ((file->f_flags & O_RDWR) == O_RDWR) SNIFFMODE = 1; else SNIFFMODE = 0; + // do we have a blocking or non blocking sniffer? + if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK) sniffer_timeout = 100; else sniffer_timeout = -1; + break; + default: + break; + } + return 0; +} + +static int sio_close(struct inode *inode, struct file *file) +{ + unsigned int minor = MINOR(inode->i_rdev); + + switch (minor) { + case SMARTIO_KBD_SNIFFER: + SNIFFER = 0; + SNIFFMODE = 0; + sniffer_in_use = 0; + break; + default: + break; + } + return 0; +} + +static struct file_operations sio_fops = { + read: sio_read, + write: sio_write, + poll: sio_poll, + ioctl: sio_ioctl, + open: sio_open, + release: sio_close, +}; + +static struct proc_dir_entry *sio_dir, *parent_dir = NULL; + +#define SMARTIO_MAJOR 58 +#define MAJOR_NR SMARTIO_MAJOR + +#define PROC_NAME "sio" + +static int sio_read_proc(char *buf, char **start, off_t pos, int count, int *eof, void *data) +{ + char *p = buf; + + p += sprintf(p, "ADS SMARTIO Status: \n"); + p += sprintf(p, "\t Keyboard Interrupt : %lu\n", kbd_int); + p += sprintf(p, "\t Keypad Interrupt : %lu\n", kpd_int); + p += sprintf(p, "\t ADC Interrupt : %lu\n", adc_int); + p += sprintf(p, "\t Keyboard Sniffer : %s mode : %s\n", kbd_sniff[ SNIFFER ], kbd_sniff_mode [ SNIFFMODE ]); + + return (p-buf); +} + +#ifdef CONFIG_PM +static int pm_smartio_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + switch (rqst) { + case PM_RESUME: + gc_sio_init(); + break; + case PM_SUSPEND: + // 4/5/01 Woojung + // It checks Keybard received pair of press/release code. + // System can sleep before receiving release code + if (kbd_press_flag) { + interruptible_sleep_on(&keyboard_done_queue); + } + break; + } + + return 0; +} +#endif + +void __init sio_init(void) +{ + if (register_chrdev(MAJOR_NR, "sio", &sio_fops)) { + printk("smartio : unable to get major %d\n", MAJOR_NR); + return; + } + else { + printk("smartio driver initialized. version %s, date:%s\n", + smartio_version, smartio_date); + + if (sio_reset_flag != 1) { + gc_sio_init(); + if (request_irq(ADS_AVR_IRQ, gc_sio_interrupt,0,"sio",NULL) != 0){ + printk("smartio : Could not allocate IRQ!\n"); + return; + } + } + + if ((sio_dir = create_proc_entry(PROC_NAME, 0, parent_dir)) == NULL) { + printk("smartio : Unable to create /proc entry\n"); + return; + } + else { + sio_dir->read_proc = sio_read_proc; +#ifdef CONFIG_PM + pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_smartio_callback); +#endif + } + } +} diff -uNr linux-2.4.37.9/drivers/char/gckeymap.c linux-2.4.37.9-vrs1-5mx2/drivers/char/gckeymap.c --- linux-2.4.37.9/drivers/char/gckeymap.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/gckeymap.c Wed May 26 15:48:46 2010 @@ -0,0 +1,262 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, + 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c, + 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, + 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009, + 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, + 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53, + 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a, + 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, + 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c, + 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, + 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, + 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, + 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73, + 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76, + 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, + 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911, + 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b, + 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516, + 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c, + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, + 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809, + 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869, + 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873, + 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b, + 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876, + 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c, + 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907, + 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901, + 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813, + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816, + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -uNr linux-2.4.37.9/drivers/char/gckeymap.map linux-2.4.37.9-vrs1-5mx2/drivers/char/gckeymap.map --- linux-2.4.37.9/drivers/char/gckeymap.map Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/gckeymap.map Wed May 26 15:48:46 2010 @@ -0,0 +1,357 @@ +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 +# Change the above line into +# keymaps 0-2,4-6,8,12 +# in case you want the entries +# altgr control keycode 83 = Boot +# altgr control keycode 111 = Boot +# below. +# +# In fact AltGr is used very little, and one more keymap can +# be saved by mapping AltGr to Alt (and adapting a few entries): +# keycode 100 = Alt +# +keycode 1 = Escape Escape + alt keycode 1 = Meta_Escape +keycode 2 = one exclam + alt keycode 2 = Meta_one +keycode 3 = two at at + control keycode 3 = nul + shift control keycode 3 = nul + alt keycode 3 = Meta_two +keycode 4 = three numbersign + control keycode 4 = Escape + alt keycode 4 = Meta_three +keycode 5 = four dollar dollar + control keycode 5 = Control_backslash + alt keycode 5 = Meta_four +keycode 6 = five percent + control keycode 6 = Control_bracketright + alt keycode 6 = Meta_five +keycode 7 = six asciicircum + control keycode 7 = Control_asciicircum + alt keycode 7 = Meta_six +keycode 8 = seven ampersand braceleft + control keycode 8 = Control_underscore + alt keycode 8 = Meta_seven +keycode 9 = eight asterisk bracketleft + control keycode 9 = Delete + alt keycode 9 = Meta_eight +keycode 10 = nine parenleft bracketright + alt keycode 10 = Meta_nine +keycode 11 = zero parenright braceright + alt keycode 11 = Meta_zero +keycode 12 = minus underscore backslash + control keycode 12 = Control_underscore + shift control keycode 12 = Control_underscore + alt keycode 12 = Meta_minus +keycode 13 = equal plus + alt keycode 13 = Meta_equal +keycode 14 = Delete Delete + control keycode 14 = BackSpace + alt keycode 14 = Meta_Delete +keycode 15 = Tab Tab + alt keycode 15 = Meta_Tab +keycode 16 = q +keycode 17 = w +keycode 18 = e + altgr keycode 18 = Hex_E +keycode 19 = r +keycode 20 = t +keycode 21 = y +keycode 22 = u +keycode 23 = i +keycode 24 = o +keycode 25 = p +keycode 26 = bracketleft braceleft + control keycode 26 = Escape + alt keycode 26 = Meta_bracketleft +keycode 27 = bracketright braceright asciitilde + control keycode 27 = Control_bracketright + alt keycode 27 = Meta_bracketright +keycode 28 = Return + alt keycode 28 = Meta_Control_m +keycode 29 = Control +keycode 30 = a + altgr keycode 30 = Hex_A +keycode 31 = s +keycode 32 = d + altgr keycode 32 = Hex_D +keycode 33 = f + altgr keycode 33 = Hex_F +keycode 34 = g +keycode 35 = h +keycode 36 = j +keycode 37 = k +keycode 38 = l +keycode 39 = semicolon colon + alt keycode 39 = Meta_semicolon +keycode 40 = apostrophe quotedbl + control keycode 40 = Control_g + alt keycode 40 = Meta_apostrophe +keycode 41 = grave asciitilde + control keycode 41 = nul + alt keycode 41 = Meta_grave +keycode 42 = Shift +keycode 43 = backslash bar + control keycode 43 = Control_backslash + alt keycode 43 = Meta_backslash +keycode 44 = z +keycode 45 = x +keycode 46 = c + altgr keycode 46 = Hex_C +keycode 47 = v +keycode 48 = b + altgr keycode 48 = Hex_B +keycode 49 = n +keycode 50 = m +keycode 51 = comma less + alt keycode 51 = Meta_comma +keycode 52 = period greater + control keycode 52 = Compose + alt keycode 52 = Meta_period +keycode 53 = slash question + control keycode 53 = Delete + alt keycode 53 = Meta_slash +keycode 54 = Shift +keycode 55 = KP_Multiply +keycode 56 = Alt +keycode 57 = space space + control keycode 57 = nul + alt keycode 57 = Meta_space +keycode 58 = Caps_Lock +keycode 59 = F1 F11 Console_13 + control keycode 59 = F1 + alt keycode 59 = Console_1 + control alt keycode 59 = Console_1 +keycode 60 = F2 F12 Console_14 + control keycode 60 = F2 + alt keycode 60 = Console_2 + control alt keycode 60 = Console_2 +keycode 61 = F3 F13 Console_15 + control keycode 61 = F3 + alt keycode 61 = Console_3 + control alt keycode 61 = Console_3 +keycode 62 = F4 F14 Console_16 + control keycode 62 = F4 + alt keycode 62 = Console_4 + control alt keycode 62 = Console_4 +keycode 63 = F5 F15 Console_17 + control keycode 63 = F5 + alt keycode 63 = Console_5 + control alt keycode 63 = Console_5 +keycode 64 = F6 F16 Console_18 + control keycode 64 = F6 + alt keycode 64 = Console_6 + control alt keycode 64 = Console_6 +keycode 65 = F7 F17 Console_19 + control keycode 65 = F7 + alt keycode 65 = Console_7 + control alt keycode 65 = Console_7 +keycode 66 = F8 F18 Console_20 + control keycode 66 = F8 + alt keycode 66 = Console_8 + control alt keycode 66 = Console_8 +keycode 67 = F9 F19 Console_21 + control keycode 67 = F9 + alt keycode 67 = Console_9 + control alt keycode 67 = Console_9 +keycode 68 = F10 F20 Console_22 + control keycode 68 = F10 + alt keycode 68 = Console_10 + control alt keycode 68 = Console_10 +keycode 69 = Num_Lock + shift keycode 69 = Bare_Num_Lock +keycode 70 = Scroll_Lock Show_Memory Show_Registers + control keycode 70 = Show_State + alt keycode 70 = Scroll_Lock +keycode 71 = KP_7 + alt keycode 71 = Ascii_7 + altgr keycode 71 = Hex_7 +keycode 72 = KP_8 + alt keycode 72 = Ascii_8 + altgr keycode 72 = Hex_8 +keycode 73 = KP_9 + alt keycode 73 = Ascii_9 + altgr keycode 73 = Hex_9 +keycode 74 = KP_Subtract +keycode 75 = KP_4 + alt keycode 75 = Ascii_4 + altgr keycode 75 = Hex_4 +keycode 76 = KP_5 + alt keycode 76 = Ascii_5 + altgr keycode 76 = Hex_5 +keycode 77 = KP_6 + alt keycode 77 = Ascii_6 + altgr keycode 77 = Hex_6 +keycode 78 = KP_Add +keycode 79 = KP_1 + alt keycode 79 = Ascii_1 + altgr keycode 79 = Hex_1 +keycode 80 = KP_2 + alt keycode 80 = Ascii_2 + altgr keycode 80 = Hex_2 +keycode 81 = KP_3 + alt keycode 81 = Ascii_3 + altgr keycode 81 = Hex_3 +keycode 82 = KP_0 + alt keycode 82 = Ascii_0 + altgr keycode 82 = Hex_0 +keycode 83 = KP_Period +# altgr control keycode 83 = Boot + control alt keycode 83 = Boot +keycode 84 = Last_Console +keycode 85 = +keycode 86 = less greater bar + alt keycode 86 = Meta_less +keycode 87 = F11 F11 Console_23 + control keycode 87 = F11 + alt keycode 87 = Console_11 + control alt keycode 87 = Console_11 +keycode 88 = F12 F12 Console_24 + control keycode 88 = F12 + alt keycode 88 = Console_12 + control alt keycode 88 = Console_12 +keycode 89 = +keycode 90 = +keycode 91 = +keycode 92 = +keycode 93 = +keycode 94 = +keycode 95 = +keycode 96 = KP_Enter +keycode 97 = Control +keycode 98 = KP_Divide +keycode 99 = Control_backslash + control keycode 99 = Control_backslash + alt keycode 99 = Control_backslash +keycode 100 = AltGr +keycode 101 = Break +keycode 102 = Find +keycode 103 = Up +keycode 104 = Prior + shift keycode 104 = Scroll_Backward +keycode 105 = Left + alt keycode 105 = Decr_Console +keycode 106 = Right + alt keycode 106 = Incr_Console +keycode 107 = Select +keycode 108 = Down +keycode 109 = Next + shift keycode 109 = Scroll_Forward +keycode 110 = Insert +keycode 111 = Remove +# altgr control keycode 111 = Boot + control alt keycode 111 = Boot +keycode 112 = Macro +keycode 113 = F13 +keycode 114 = F14 +keycode 115 = Help +keycode 116 = Do +keycode 117 = F17 +keycode 118 = KP_MinPlus +keycode 119 = Pause +keycode 120 = +keycode 121 = +keycode 122 = +keycode 123 = +keycode 124 = +keycode 125 = +keycode 126 = +keycode 127 = +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -uNr linux-2.4.37.9/drivers/char/generic_serial.c linux-2.4.37.9-vrs1-5mx2/drivers/char/generic_serial.c --- linux-2.4.37.9/drivers/char/generic_serial.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/generic_serial.c Wed May 26 15:48:46 2010 @@ -876,6 +876,9 @@ if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n"); } + /* + * should be using tty_get_baud_rate() here -- rmk + */ baudrate = tiosp->c_cflag & CBAUD; if (baudrate & CBAUDEX) { baudrate &= ~CBAUDEX; @@ -950,6 +953,11 @@ unsigned long flags; unsigned long page; + /* + * Do we expect to allocate tmp_buf from an interrupt routine? + * If not, then save_flags() cli() and restore_flags() are + * redundant here and should be replaced by a semaphore. -- rmk + */ save_flags (flags); if (!tmp_buf) { page = get_free_page(GFP_KERNEL); @@ -969,6 +977,11 @@ if (port->flags & ASYNC_INITIALIZED) return 0; + /* + * Do we expect to allocate xmit_buf from an interrupt routine? + * If not, then save_flags() cli() and restore_flags() are + * redundant here and should be replaced by a semaphore. -- rmk + */ if (!port->xmit_buf) { /* We may sleep in get_free_page() */ unsigned long tmp; @@ -1009,7 +1022,7 @@ struct serial_struct sio; if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) - return(-EFAULT); + return -EFAULT; if (!capable(CAP_SYS_ADMIN)) { if ((sio.baud_base != port->baud_base) || diff -uNr linux-2.4.37.9/drivers/char/keyboard.c linux-2.4.37.9-vrs1-5mx2/drivers/char/keyboard.c --- linux-2.4.37.9/drivers/char/keyboard.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keyboard.c Wed May 26 15:48:46 2010 @@ -14,13 +14,17 @@ * `Sticky' modifier keys, 951006. * * 11-11-96: SAK should now work in the raw mode (Martin Mares) - * + * * Modified to provide 'generic' keyboard support by Hamish Macdonald * Merge with the m68k keyboard driver and split-off of the PC low-level * parts by Geert Uytterhoeven, May 1997 * * 27-05-97: Added support for the Magic SysRq Key (Martin Mares) * 30-07-98: Dead keys redone, aeb@cwi.nl. + * + * 04-04-1998: Added keyboard autorepeat support (some keyboards don't + * autorepeat, and some keyboard changers interfere with keyboard + * autorepeat settings). - Russell King (rmk@arm.linux.org.uk) */ #include @@ -30,6 +34,7 @@ #include #include #include +#include #include #include @@ -61,6 +66,14 @@ #define KBD_DEFLOCK 0 #endif +/* + * Default autorepeat settings. + * DEFAULT_REPEAT_TIMEOUT is the timeout from the keypress to the first repeat + * DEFAULT_REPEAT_INTERVAL is the timeout between successive repeats + */ +#define DEFAULT_REPEAT_TIMEOUT HZ*300/1000 +#define DEFAULT_REPEAT_INTERVAL HZ*30/1000 + void (*kbd_ledfunc)(unsigned int led); EXPORT_SYMBOL(handle_scancode); EXPORT_SYMBOL(kbd_ledfunc); @@ -82,21 +95,25 @@ static unsigned long key_down[256/BITS_PER_LONG]; static int dead_key_next; -/* +/* * In order to retrieve the shift_state (for the mouse server), either - * the variable must be global, or a new procedure must be created to + * the variable must be global, or a new procedure must be created to * return the value. I chose the former way. */ int shift_state; static int npadch = -1; /* -1 or number assembled on pad */ static unsigned char diacr; static char rep; /* flag telling character repeat */ +static int kbd_repeatkeycode= -1; +static int kbd_repeattimeout = DEFAULT_REPEAT_TIMEOUT; +static int kbd_repeatinterval= DEFAULT_REPEAT_INTERVAL; struct kbd_struct kbd_table[MAX_NR_CONSOLES]; static struct tty_struct **ttytab; static struct kbd_struct * kbd = kbd_table; static struct tty_struct * tty; static unsigned char prev_scancode; +static void kbd_processkeycode(unsigned char scancode, char up_flag, int autorepeat); void compute_shiftstate(void); typedef void (*k_hand)(unsigned char value, char up_flag); @@ -105,17 +122,17 @@ static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2, - do_ignore; + do_ignore, do_arch; /* PSIONW_NONSTANDARD */ static k_hand key_handler[16] = { do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2, - do_ignore, do_ignore + do_ignore, do_arch }; /* Key types processed even in raw modes */ -#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT)) +#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_CONS) | (1 << KT_SLOCK) | (1 << KT_SHIFT) | (1 << KT_ARCH1) | (1 << KT_ARCH2) | (1 << KT_ARCH3)) typedef void (*void_fnp)(void); typedef void (void_fn)(void); @@ -139,7 +156,7 @@ 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1, NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, 255, - NR_LOCK - 1, 255 + NR_LOCK - 1, 255, 0, 11 }; const int NR_TYPES = SIZE(max_vals); @@ -152,7 +169,7 @@ struct pt_regs * kbd_pt_regs; #ifdef CONFIG_MAGIC_SYSRQ -static int sysrq_pressed; +int sysrq_pressed; #endif static struct pm_dev *pm_kbd; @@ -163,7 +180,8 @@ * string, and in both cases we might assume that it is * in utf-8 already. */ -void to_utf8(ushort c) { +void to_utf8(ushort c) +{ if (c < 0x80) put_queue(c); /* 0******* */ else if (c < 0x800) { @@ -182,17 +200,23 @@ * Translation of escaped scancodes to keycodes. * This is now user-settable (for machines were it makes sense). */ - int setkeycode(unsigned int scancode, unsigned int keycode) { - return kbd_setkeycode(scancode, keycode); + return kbd_setkeycode(scancode, keycode); } int getkeycode(unsigned int scancode) { - return kbd_getkeycode(scancode); + return kbd_getkeycode(scancode); } +static void key_callback(unsigned long nr); + +static struct timer_list key_autorepeat_timer = +{ + function: key_callback +}; + void handle_scancode(unsigned char scancode, int down) { unsigned char keycode; @@ -201,6 +225,7 @@ char have_keycode; pm_access(pm_kbd); + add_keyboard_randomness(scancode | up_flag); tty = ttytab? ttytab[fg_console]: NULL; @@ -223,15 +248,15 @@ if (raw_mode) { /* * The following is a workaround for hardware - * which sometimes send the key release event twice + * which sometimes send the key release event twice */ unsigned char next_scancode = scancode|up_flag; if (have_keycode && up_flag && next_scancode==prev_scancode) { /* unexpected 2nd release event */ } else { - /* + /* * Only save previous scancode if it was a key-up - * and had a single-byte scancode. + * and had a single-byte scancode. */ if (!have_keycode) prev_scancode = 1; @@ -256,12 +281,35 @@ * return the keycode if in MEDIUMRAW mode. */ + kbd_processkeycode(keycode, up_flag, 0); + +out: + do_poke_blanked_console = 1; + schedule_console_callback(); +} + +static void +kbd_processkeycode(unsigned char keycode, char up_flag, int autorepeat) +{ + char raw_mode = (kbd->kbdmode == VC_RAW); + if (up_flag) { rep = 0; if(!test_and_clear_bit(keycode, key_down)) up_flag = kbd_unexpected_up(keycode); - } else + } else { rep = test_and_set_bit(keycode, key_down); + /* If the keyboard autorepeated for us, ignore it. + * We do our own autorepeat processing. + */ + if (rep && !autorepeat) + return; + } + + if (kbd_repeatkeycode == keycode || !up_flag || raw_mode) { + kbd_repeatkeycode = -1; + del_timer(&key_autorepeat_timer); + } #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ if (keycode == SYSRQ_KEY) { @@ -275,6 +323,23 @@ } #endif + /* + * Calculate the next time when we have to do some autorepeat + * processing. Note that we do not do autorepeat processing + * while in raw mode but we do do autorepeat processing in + * medium raw mode. + */ + if (!up_flag && !raw_mode) { + kbd_repeatkeycode = keycode; + if (vc_kbd_mode(kbd, VC_REPEAT)) { + if (rep) + key_autorepeat_timer.expires = jiffies + kbd_repeatinterval; + else + key_autorepeat_timer.expires = jiffies + kbd_repeattimeout; + add_timer(&key_autorepeat_timer); + } + } + if (kbd->kbdmode == VC_MEDIUMRAW) { /* soon keycodes will require more than one byte */ put_queue(keycode + up_flag); @@ -311,8 +376,15 @@ if (type >= 0xf0) { type -= 0xf0; - if (raw_mode && ! (TYPES_ALLOWED_IN_RAW_MODE & (1 << type))) - goto out; + +#if 0 + printk("keysym=0x%x type=0x%x 0x%x && 0x%x\n", + keysym, type, raw_mode, !(TYPES_ALLOWED_IN_RAW_MODE & (1<slockstate = 0; } else { /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */ @@ -343,9 +417,24 @@ #endif } } + rep = 0; out: - do_poke_blanked_console = 1; - schedule_console_callback(); +} + +/* + * This clears the key down arrays when the keyboard is reset. On + * keyboard reset, this must be called before any keycodes are + * received. + */ +void kbd_reset_kdown(void) +{ + int i; + + for (i = 0; i < NR_SHIFT; i++) + k_down[i] = 0; + for (i = 0; i < SIZE(key_down); i++) + key_down[i] = 0; + shift_state = 0; } void put_queue(int ch) @@ -453,7 +542,7 @@ static void decr_console(void) { int i; - + for (i = fg_console-1; i != fg_console; i--) { if (i == -1) i = MAX_NR_CONSOLES-1; @@ -531,11 +620,18 @@ { } -static void do_null() +static void do_null(void) { compute_shiftstate(); } +static void do_arch(unsigned char value, char up_flag) +{ +#ifdef kbd_arch_handler + kbd_arch_handler(value,up_flag); +#endif +} + static void do_spec(unsigned char value, char up_flag) { if (up_flag) @@ -646,8 +742,8 @@ static void do_pad(unsigned char value, char up_flag) { - static const char *pad_chars = "0123456789+-*/\015,.?()"; - static const char *app_map = "pqrstuvwxylSRQMnnmPQ"; + static const char *pad_chars = "0123456789+-*/\015,.?()#"; + static const char *app_map = "pqrstuvwxylSRQMnnmPQS"; if (up_flag) return; /* no action, if this is a key release */ @@ -748,9 +844,10 @@ } } -/* called after returning from RAW mode or when changing consoles - - recompute k_down[] and shift_state from key_down[] */ -/* maybe called when keymap is undefined, so that shiftkey release is seen */ +/* Called after returning from RAW mode or when changing consoles - + * recompute k_down[] and shift_state from key_down[] + * Maybe called when keymap is undefined so that shift key release is seen + */ void compute_shiftstate(void) { int i, j, k, sym, val; @@ -829,19 +926,22 @@ } /* - * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, - * or (ii) whatever pattern of lights people want to show using KDSETLED, - * or (iii) specified bits of specified words in kernel memory. + * The leds display either + * (i) the status of NumLock, CapsLock, ScrollLock, or + * (ii) whatever pattern of lights people want to show using KDSETLED, or + * (iii) specified bits of specified words in kernel memory. */ static unsigned char ledstate = 0xff; /* undefined */ static unsigned char ledioctl; -unsigned char getledstate(void) { +unsigned char getledstate(void) +{ return ledstate; } -void setledstate(struct kbd_struct *kbd, unsigned int led) { +void setledstate(struct kbd_struct *kbd, unsigned int led) +{ if (!(led & ~7)) { ledioctl = led; kbd->ledmode = LED_SHOW_IOCTL; @@ -857,7 +957,8 @@ } ledptrs[3]; void register_leds(int console, unsigned int led, - unsigned int *addr, unsigned int mask) { + unsigned int *addr, unsigned int mask) +{ struct kbd_struct *kbd = kbd_table + console; if (led < 3) { ledptrs[led].addr = addr; @@ -868,7 +969,8 @@ kbd->ledmode = LED_SHOW_FLAGS; } -static inline unsigned char getleds(void){ +static inline unsigned char getleds(void) +{ struct kbd_struct *kbd = kbd_table + fg_console; unsigned char leds; @@ -915,6 +1017,19 @@ { unsigned char leds = getleds(); + if (rep && kbd_repeatkeycode != -1) { + tty = ttytab? ttytab[fg_console]: NULL; + kbd = kbd_table + fg_console; + + /* This prevents the kbd_key routine from being called + * twice, once by this BH, and once by the interrupt + * routine. + */ + kbd_disable_irq(); + kbd_processkeycode(kbd_repeatkeycode, 0, 1); + kbd_enable_irq(); + } + if (leds != ledstate) { ledstate = leds; kbd_leds(leds); @@ -937,6 +1052,12 @@ tasklet_enable(&keyboard_tasklet); } +static void key_callback(unsigned long nr) +{ + rep = 1; + tasklet_schedule(&keyboard_tasklet); +} + typedef void (pm_kbd_func) (void); pm_callback pm_kbd_request_override = NULL; @@ -953,7 +1074,7 @@ kbd0.slockstate = 0; kbd0.modeflags = KBD_DEFMODE; kbd0.kbdmode = VC_XLATE; - + for (i = 0 ; i < MAX_NR_CONSOLES ; i++) kbd_table[i] = kbd0; @@ -963,7 +1084,7 @@ tasklet_enable(&keyboard_tasklet); tasklet_schedule(&keyboard_tasklet); - + pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override); return 0; diff -uNr linux-2.4.37.9/drivers/char/keyboard_psion.c linux-2.4.37.9-vrs1-5mx2/drivers/char/keyboard_psion.c --- linux-2.4.37.9/drivers/char/keyboard_psion.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keyboard_psion.c Wed May 26 15:48:46 2010 @@ -0,0 +1,337 @@ +/* + * arch/arm/drivers/char/keyboard_psion.c - Keyboard Driver for Psion + * + * Copyright (C) 1998 Roger Gammans + * Copyright (C) 2001 Tony Lindgren + * + * 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 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "keyboard_psion.h" + +/* callback function for auto sleep */ +void (*psion_sleep_set_callback)(void); + +extern void psionw_lcd_powerdown(int lock); +extern void psionw_lcd_powerup(int lock); + +unsigned int kbd_delay[] = KB_DELAY; +static int keysdown = 0; +static struct tq_struct kbdhw_task; + +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char kbdpsion_sysrq_xlate[] = + "\000" "6" "5" "4" "3" "2" "1" "\000" + "\000" "'" "\000" "0" "9" "8" "7" "\000" + "\000" "y" "t" "r" "e" "w" "q" "\000" + "\000" "\012" "l" "p" "o" "i" "u" "\000" + "\000" "g" "f" "d" "s" "a" "\011" "\000" + "\000" "\000" "." "m" "k" "j" "h" "\000" + "\000" "n" "b" "v" "c" "x" "z" "\000" + "\000" "\000" "\000" "," "\000" " " "\000"; +#endif + +void psion_cleartable(void) +{ + int key; + unsigned int t; + + for (key = 0; key < NR_KEYCODES; key++) { + if (!kbdstate[key].in) + continue; + + /* + * dont worry these ops are commutative and + * assoicative + */ + t = (jiffies - kbdstate[key].jif) & KB_JIFMASK; + if (t>KB_DEB_JIFFY) { + + /* Keboard could have changed meanwhile */ + kbdstate[key].in = 0; + keysdown--; + /* printk("Releasing key:%x\n",key); */ + handle_scancode(key, 0); + } + } +} + +static void kbd_press(int keycode) +{ + unsigned char newpress = 0; + + if (!kbdstate[keycode].in) { + keysdown++; + newpress = 1; + /* printk("Keycode: %d (0x%x)\n", keycode, keycode); */ + } + + /* + * We approximate a retriggable monostable + * action. + */ + kbdstate[keycode].in=1; + + /* We only need to ensure keysdown consistent */ + kbdstate[keycode].jif = jiffies & KB_JIFMASK; + if (newpress) { + handle_scancode(keycode, 1); + if (psion_sleep_set_callback != 0) + (*psion_sleep_set_callback)(); + } +} + +static void psion_tick(void* dummy) +{ + int col,row; + int rowd; + int count=0; + unsigned char state; + + /* + * Check if any keys are depressed + */ + for (col = 0; col < 8; col++) { + udelay(kbd_delay[8]); + state = psionw_readl(KSCAN); + state &= ~KBDSCAN; + state |= (KBSC_COL0 + col); + psionw_writel(state, KSCAN); + udelay(kbd_delay[col]); + rowd = psionw_readl(PADR) & 0xff; + if (!rowd) + continue; + for (row=0; row < KB_LASTROW; row++) { + if (rowd & KB_ROWMASK(row)) { + kbd_press(KEYCODE(row,col)); + count++; + } + } + }; + + if (count != keysdown) { + psion_cleartable(); + } + + /* + * Re-queue ourselves + */ + queue_task(&kbdhw_task,&tq_timer); +} + +void kbdpsion_hw_init(void) +{ + kbdhw_task.routine = psion_tick; + kbdhw_task.sync = 0; + queue_task(&kbdhw_task,&tq_timer); +} + +int kbdpsion_translate(unsigned char scancode, unsigned char *keycode_p) +{ + *keycode_p = scancode & ~(KBDOWN | KBUP); + return 1; +} + +#if defined(CONFIG_VT) && defined(CONFIG_MAGIC_SYSRQ) +extern int sysrq_pressed; +#endif + +void psion_arch_handler(unsigned char value, char up_flag) +{ +#if defined(CONFIG_VT) && defined(CONFIG_MAGIC_SYSRQ) + if (value == 1) { + sysrq_pressed = !up_flag; + return; + } +#endif + if (up_flag) return; + switch (value) { + +#ifdef KBD_ARCHKEY_2 + case 2: + KBD_ARCHKEY_2; + break; +#endif +#ifdef KBD_ARCHKEY_3 + case 3: + KBD_ARCHKEY_3; + break; +#endif +#ifdef KBD_ARCHKEY_4 + case 4: + KBD_ARCHKEY_4; + break; +#endif +#ifdef KBD_ARCHKEY_5 + case 5: + KBD_ARCHKEY_5; + break; +#endif +#ifdef KBD_ARCHKEY_6 + case 6: + KBD_ARCHKEY_6; + break; +#endif +#ifdef KBD_ARCHKEY_7 + case 7: + KBD_ARCHKEY_7; + break; +#endif +#ifdef KBD_ARCHKEY_8 + case 8: + KBD_ARCHKEY_8; + break; +#endif +#ifdef KBD_ARCHKEY_9 + case 9: + KBD_ARCHKEY_9; + break; +#endif +#ifdef KBD_ARCHKEY_10 + case 10: + KBD_ARCHKEY_10; + break; +#endif +#ifdef KBD_ARCHKEY_11 + case 11: + KBD_ARCHKEY_11; + break; +#endif + + default: + return; + } +} + +void psion_toggle_backlight() +{ + int pcdr; + long flags; + + if ((psionw_readl(LCDCTL) & LCDCTL_EN) == 0) + psionw_lcd_powerup(1); + + save_flags_cli(flags); + pcdr = psionw_readl(PCDR); + pcdr ^= PCDR_LIGHT; + psionw_writel(pcdr, PCDR); + restore_flags(flags); +} + +/* + * Contrast table. Upper four bits: output value, lower four bits: direction + * (0 = in = Z) + */ +#define V0 0 +#define V1 1 +#define VZ 0 +#define D0 1 +#define D1 1 +#define DZ 0 + +#define C(a,b,c,d) \ + ((V##a << 7) | (V##b << 6) | (V##c << 5) | (V##d << 4) | \ + (D##a << 3) | (D##b << 2) | (D##c << 1) | D##d) + +static __u8 contrast_table[] = { + C(1,1,1,1), C(1,1,1,Z), C(1,1,1,0), C(1,1,Z,1), /* 1- 4 */ + C(1,1,Z,Z), C(1,1,0,1), C(1,1,Z,0), C(1,Z,1,1), /* 5- 8 */ + C(1,1,0,0), C(1,Z,1,Z), C(1,Z,1,0), C(1,Z,Z,1), /* 9-12 */ + C(1,0,1,1), C(1,Z,Z,Z), C(1,Z,0,1), C(1,0,1,Z), /* 13-16 */ + C(1,0,1,0), C(1,0,Z,1), C(1,Z,0,0), C(Z,1,1,Z), /* 17-20 */ + C(1,0,Z,Z), C(1,0,0,1), C(1,0,Z,0), C(1,0,0,Z), /* 21-24 */ + C(Z,1,Z,Z), C(1,0,0,0), C(Z,1,Z,0), C(Z,1,0,Z), /* 25-28 */ + C(Z,1,0,0), C(Z,Z,1,Z), C(Z,Z,1,0), C(Z,Z,Z,1), /* 29-32 */ + C(0,1,1,0), C(0,1,Z,1), C(Z,Z,0,1), C(Z,0,1,Z), /* 33-36 */ + C(0,1,Z,Z), C(Z,Z,0,Z), C(0,1,Z,0), C(Z,Z,0,0), /* 37-40 */ + C(0,1,0,Z), C(Z,0,Z,Z), C(0,1,0,0), C(Z,0,Z,0), /* 41-44 */ + C(0,Z,1,0), C(0,Z,Z,1), C(Z,0,0,0), C(0,0,1,1), /* 45-48 */ + C(0,Z,Z,Z), C(0,Z,0,1), C(0,Z,Z,0), C(0,0,1,0), /* 49-52 */ + C(0,0,Z,1), C(0,Z,0,0), C(0,0,Z,Z), C(0,0,0,1), /* 53-56 */ + C(0,0,Z,0), C(0,0,0,Z), C(0,0,0,0) /* 57-60 */ +}; + +static int contrast = 40; + +int psion_get_contrast(void) +{ + return contrast; +} + +int psion_set_contrast(int new_contrast, int lock) +{ + long flags = 0; + + if ((new_contrast >= 0) && (new_contrast < sizeof(contrast_table))) { + contrast = new_contrast; + } + else { + printk("Bad contrast value: %i, should be between 0 - %d\n", + new_contrast, sizeof(contrast_table) - 1); + return -EINVAL; + } + + if (lock) + save_flags_cli(flags); + + psionw_writeb((psionw_readb(PBDR) & ~PBDR_VLD_MASK) | + ((contrast_table[contrast] >> 4) << PBDR_VLD_SHIFT), + PBDR); + psionw_writeb((psionw_readb(PBDDR) & ~PBDR_VLD_MASK) | + ((contrast_table[contrast] & 0xf) << PBDR_VLD_SHIFT), + PBDDR); + + if (lock) + restore_flags(flags); + + return 0; +} + +void psion_contrast(int increase) +{ + + if (increase) + if (contrast == sizeof(contrast_table)-1) return; + else contrast++; + else if (!contrast) return; + else contrast--; + + psion_set_contrast(contrast, 1); +} + +void debug_gpio(void) +{ + printk("\nPADR=0x%02x PBDR=0x%02x PCDR=0x%02x PDDR=0x%02x PEDR=0x%02x ", + psionw_readb(PADR), + psionw_readb(PBDR), + psionw_readb(PCDR), + psionw_readb(PDDR), + psionw_readb(PEDR)); + + printk("PADDR=0x%02x PBDDR=0x%02x\n", + psionw_readb(PADDR), + psionw_readb(PBDDR)); +} diff -uNr linux-2.4.37.9/drivers/char/keyboard_psion.h linux-2.4.37.9-vrs1-5mx2/drivers/char/keyboard_psion.h --- linux-2.4.37.9/drivers/char/keyboard_psion.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keyboard_psion.h Mon Jun 7 19:17:01 2010 @@ -0,0 +1,127 @@ +/* + * arch/arm/drivers/char/keyboard_psion.h + * + * Psion keyboard definitions. + * + * Copyright (C) 1998 Roger Gammans + * Copyright (C) 2000 Tony Lindgren + * + * 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 + */ + +#ifndef __ASM_ARCH_PSION_H +#define __ASM_ARCH_PSION_H + +#include + +#define KBDSCAN 0x0000000f /* Keyboard scan */ +#define KBSC_HI 0x0 /* All driven high */ +#define KBSC_LO 0x1 /* All driven low */ +#define KBSC_X 0x2 /* All high impedance */ +#define KBSC_COL0 0x8 /* Col 0 high, others high impedance */ +#define KBSC_COL1 0x9 /* Col 1 high, others high impedance */ +#define KBSC_COL2 0xa /* Col 2 high, others high impedance */ +#define KBSC_COL3 0xb /* Col 3 high, others high impedance */ +#define KBSC_COL4 0xc /* Col 4 high, others high impedance */ +#define KBSC_COL5 0xd /* Col 5 high, others high impedance */ +#define KBSC_COL6 0xe /* Col 6 high, others high impedance */ +#define KBSC_COL7 0xf /* Col 7 high, others high impedance */ + +#define KB_JIFMASK (127) + +/* + * Arm's keyboard is active high row select... + * (must try to remember) + */ +#define KB_ALLCOLS KBSC_HI +#define KB_DISCHARGE KBSC_LO +#define KB_LASTROW 7 + +#define KBUP (0x80) +#define KBDOWN (0) + +/* + * Later on we'll try a struct of + * two arrays then the existing keyboard.c can + * test our array directly but until then.... + */ +typedef struct { + int in:1; /* If the key down */ + int jif:7; /* how long has key been down for (approx) */ +} kbd_keyinfo; + +static kbd_keyinfo kbdstate[NR_KEYCODES]; + +#ifdef KB_DELAY +extern unsigned int kbd_delay[]; +#endif + +/* + * Be sure to change the if you increase the + * number of kbd rows... + */ +#define KEYCODE(r,c) ( ((c)<<3) + (r)+1) +#define KB_ROWMASK(r) (1 << (r)) + +/* + * KB_DELAY is used to allow the matrix + * to stabilize.., value is determined via + * experimentation. + */ + +#define KB_DELAY {16 ,16 ,16 ,16 ,16 ,16 ,16 ,16 ,16} + +/* + * Not sure whether this trick works yet! + * + */ +#undef KBD_SUPPORTS_WIREOR + +/* + * treat debounce monostable as 30ms + */ + +#define KB_DEB_JIFFY (30/HZ) + +extern void psion_off(void); +void psion_toggle_backlight(void); +void psion_contrast(int increase); +void psion_debug_cf(void); + +/* + * Architecture-specific keys. Value 0 is invalid. 1 is SysRq. + * Ctrl-Alt = Ctrl-Menu on Psion, For example: SysRq = Ctrl-Menu-, + */ +#define KBD_ARCHKEY_2 psion_off() /* Fn-Off */ +#define KBD_ARCHKEY_3 psion_toggle_backlight() /* Fn-Space */ +#define KBD_ARCHKEY_4 psion_contrast(0) /* Fn-- */ +#define KBD_ARCHKEY_5 psion_contrast(1) /* Fn-+ */ + +/* KBD_ARCHKEY_6 to KBD_ARCHKEY_11 reserved for debugging */ +#define KBD_ARCHKEY_6 0 /* Ctrl-Menu-z */ + +#ifdef CONFIG_PCMCIA_ETNA +extern void psion_debug_etna(void); +#define KBD_ARCHKEY_7 psion_debug_etna() /* Ctrl-Menu-x */ +#else +#define KBD_ARCHKEY_7 debug_gpio() /* Ctrl-Menu-x */ +#endif + +#define KBD_ARCHKEY_8 0 /* Ctrl-Menu-c */ +#define KBD_ARCHKEY_9 0 /* Ctrl-Menu-v */ +#define KBD_ARCHKEY_8 0 +#define KBD_ARCHKEY_9 0 + +#endif diff -uNr linux-2.4.37.9/drivers/char/keymap_psion.c linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion.c --- linux-2.4.37.9/drivers/char/keymap_psion.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion.c Wed May 26 15:48:46 2010 @@ -0,0 +1,374 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf10c, + 0xf200, 0xf027, 0xf07f, 0xf030, 0xf039, 0xf038, 0xf037, 0xf10e, + 0xf200, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf01b, + 0xf200, 0xf201, 0xfb6c, 0xfb70, 0xfb6f, 0xfb69, 0xfb75, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf009, 0xfc02, + 0xf200, 0xf600, 0xf02e, 0xfb6d, 0xfb6b, 0xfb6a, 0xfb68, 0xfc01, + 0xf200, 0xfb6e, 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf02c, 0xf603, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf05e, 0xf025, 0xf024, 0x00a3, 0xf022, 0xf021, 0xf10c, + 0xf200, 0xf07e, 0xf07f, 0xf029, 0xf028, 0xf02a, 0xf026, 0xf10e, + 0xf200, 0xfb59, 0xfb54, 0xfb52, 0xfb45, 0xfb57, 0xfb51, 0xf01b, + 0xf200, 0xf201, 0xfb4c, 0xfb50, 0xfb4f, 0xfb49, 0xfb55, 0xfc03, + 0xf200, 0xfb47, 0xfb46, 0xfb44, 0xfb53, 0xfb41, 0xf009, 0xfc02, + 0xf200, 0xf20b, 0xf03f, 0xfb4d, 0xfb4b, 0xfb4a, 0xfb48, 0xfc01, + 0xf200, 0xfb4e, 0xfb42, 0xfb56, 0xfb43, 0xfb58, 0xfb5a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf02f, 0xf20a, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf03e, 0xf03c, 0xf040, 0xf05c, 0xf023, 0xf05f, 0xf10c, + 0xf200, 0xf03a, 0xf060, 0xf07d, 0xf07b, 0xf05d, 0xf05b, 0xf10e, + 0xf200, 0xf30c, 0xf07c, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xff02, + 0xf200, 0xf201, 0xf03b, 0xf03d, 0xf02d, 0xf02b, 0xf30d, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf207, 0xfc02, + 0xf200, 0xf118, 0xff05, 0xff04, 0xfb6b, 0xfb6a, 0xfb68, 0xfc01, + 0xf200, 0xfb6e, 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xfc00, + 0xf200, 0xf117, 0xf114, 0xf200, 0xf119, 0xff03, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf01e, 0xf200, 0xf200, 0xf01c, 0xf200, 0xf01f, 0xf10c, + 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, 0xf01d, 0xf01b, 0xf10e, + 0xf200, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf00d, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf00d, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf505, 0xf504, 0xf503, 0xf502, 0xf501, 0xf500, 0xf10c, + 0xf200, 0xf200, 0xf116, 0xf509, 0xf508, 0xf507, 0xf506, 0xf10e, + 0xf200, 0xf879, 0xf874, 0xf872, 0xf865, 0xf877, 0xf871, 0xf81b, + 0xf200, 0xf201, 0xf86c, 0xf870, 0xf86f, 0xf869, 0xf875, 0xfc03, + 0xf200, 0xf867, 0xf866, 0xf864, 0xf873, 0xf861, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf86d, 0xf86b, 0xf86a, 0xf868, 0xfc01, + 0xf200, 0xf86e, 0xf862, 0xf876, 0xf863, 0xf878, 0xf87a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf200, 0xf20c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf819, 0xf814, 0xf812, 0xf805, 0xf817, 0xf811, 0xf200, + 0xf200, 0xf201, 0xf80c, 0xf810, 0xf80f, 0xf809, 0xf815, 0xfc03, + 0xf200, 0xf807, 0xf806, 0xf804, 0xf813, 0xf801, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf80d, 0xf80b, 0xf80a, 0xf808, 0xfc01, + 0xf200, 0xff0b, 0xff0a, 0xff09, 0xff08, 0xff07, 0xff06, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xff01, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -uNr linux-2.4.37.9/drivers/char/keymap_psion.map linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion.map --- linux-2.4.37.9/drivers/char/keymap_psion.map Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion.map Wed May 26 15:48:46 2010 @@ -0,0 +1,234 @@ +# arch/arm/drivers/char/keymap_psion.map - UK (default) keyboard map +# +# Written 1998,1999 by Werner Almesberger +# +# based on keymap_geo.map, string and compose def's taken from +# drivers/char/defkeymap.map +# +# Special keys: +# F13 REC F14 STOP F15 PLAY +# F16 Contrast-- F17 Contrast++ F18 Backlight + +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 + + keycode 1 = six asciicircum +alt keycode 1 = Console_6 +altgr keycode 1 = greater +control keycode 1 = Control_asciicircum + keycode 2 = five percent +alt keycode 2 = Console_5 +altgr keycode 2 = less + keycode 3 = four dollar +alt keycode 3 = Console_4 +altgr keycode 3 = at + keycode 4 = three sterling +alt keycode 4 = Console_3 +altgr keycode 4 = backslash +control keycode 4 = Control_backslash + keycode 5 = two quotedbl +alt keycode 5 = Console_2 +altgr keycode 5 = numbersign + keycode 6 = one exclam +alt keycode 6 = Console_1 +altgr keycode 6 = underscore +control keycode 6 = Control_underscore + keycode 7 = F13 # REC + + keycode 8 = VoidSymbol + keycode 9 = apostrophe asciitilde +altgr keycode 9 = colon + keycode 10 = Delete +alt keycode 10 = Remove +altgr keycode 10 = grave +control alt keycode 10 = Boot + keycode 11 = zero parenright +alt keycode 11 = Console_10 +altgr keycode 11 = braceright + keycode 12 = nine parenleft +alt keycode 12 = Console_9 +altgr keycode 12 = braceleft + keycode 13 = eight asterisk +alt keycode 13 = Console_8 +altgr keycode 13 = bracketright +control keycode 13 = Control_bracketright + keycode 14 = seven ampersand +alt keycode 14 = Console_7 +altgr keycode 14 = bracketleft +control keycode 14 = Escape + keycode 15 = F15 # PLAY + + keycode 16 = VoidSymbol + keycode 17 = y +altgr keycode 17 = KP_Multiply + keycode 18 = t +altgr keycode 18 = bar + keycode 19 = r + keycode 20 = e + keycode 21 = w + keycode 22 = q + keycode 23 = Escape Escape +alt keycode 23 = Meta_Escape +altgr keycode 23 = 0xf02 # OFF + + keycode 24 = VoidSymbol + keycode 25 = Return + keycode 26 = l +altgr keycode 26 = semicolon + keycode 27 = p +altgr keycode 27 = equal + keycode 28 = o +altgr keycode 28 = minus + keycode 29 = i +altgr keycode 29 = plus + keycode 30 = u +altgr keycode 30 = KP_Divide + keycode 31 = SAlt # Menu + + keycode 32 = VoidSymbol + keycode 33 = g + keycode 34 = f + keycode 35 = d + keycode 36 = s + keycode 37 = a + keycode 38 = Tab +altgr keycode 38 = Caps_Lock + keycode 39 = SControl + + keycode 40 = VoidSymbol + keycode 41 = Down Scroll_Backward +altgr keycode 41 = Prior + keycode 42 = period question +altgr keycode 42 = 0xf05 # Contrast++ + keycode 43 = m +altgr keycode 43 = 0xf04 # Contrast-- + keycode 44 = k + keycode 45 = j + keycode 46 = h + keycode 47 = SAltGr # Fn + + keycode 48 = VoidSymbol + keycode 49 = n +control alt keycode 49 = 0xf0b # Debug 5 + keycode 50 = b +control alt keycode 50 = 0xf0a # Debug 4 + keycode 51 = v +control alt keycode 51 = 0xf09 # Debug 3 + keycode 52 = c +control alt keycode 52 = 0xf08 # Debug 2 + keycode 53 = x +control alt keycode 53 = 0xf07 # Debug 1 + keycode 54 = z +control alt keycode 54 = 0xf06 # Debug 0 + keycode 55 = SShift + + keycode 56 = VoidSymbol + keycode 57 = Right +altgr keycode 57 = Select # End + keycode 58 = Left +altgr keycode 58 = Find # Home + keycode 59 = comma slash +control alt keycode 59 = 0xf01 # SysRq + keycode 60 = Up Scroll_Forward +altgr keycode 60 = Next + keycode 61 = space +altgr keycode 61 = 0xf03 # Backlight + keycode 62 = F14 # STOP + keycode 63 = SShift + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -uNr linux-2.4.37.9/drivers/char/keymap_psion_de.c linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_de.c --- linux-2.4.37.9/drivers/char/keymap_psion_de.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_de.c Wed May 26 15:48:46 2010 @@ -0,0 +1,374 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf10c, + 0xf200, 0xf023, 0xf07f, 0xf030, 0xf039, 0xf038, 0xf037, 0xf10e, + 0xf200, 0xfb7a, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf01b, + 0xf200, 0xf201, 0xfb6c, 0xfb70, 0xfb6f, 0xfb69, 0xfb75, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf009, 0xfc02, + 0xf200, 0xf600, 0xf02c, 0xfb6d, 0xfb6b, 0xfb6a, 0xfb68, 0xfc01, + 0xf200, 0xfb6e, 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb79, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf02e, 0xf603, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf026, 0xf025, 0xf024, 0x00a7, 0xf022, 0xf021, 0xf10c, + 0xf200, 0xf02a, 0xf07f, 0xf027, 0xf029, 0xf028, 0xf03f, 0xf10e, + 0xf200, 0xfb5a, 0xfb54, 0xfb52, 0xfb45, 0xfb57, 0xfb51, 0xf01b, + 0xf200, 0xf201, 0xfb4c, 0xfb50, 0xfb4f, 0xfb49, 0xfb55, 0xfc03, + 0xf200, 0xfb47, 0xfb46, 0xfb44, 0xfb53, 0xfb41, 0xf009, 0xfc02, + 0xf200, 0xf20b, 0xf03b, 0xfb4d, 0xfb4b, 0xfb4a, 0xfb48, 0xfc01, + 0xf200, 0xfb4e, 0xfb42, 0xfb56, 0xfb43, 0xfb58, 0xfb59, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf03a, 0xf20a, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf03e, 0xf03c, 0xf07e, 0xf05c, 0xf02f, 0xf05f, 0xf10c, + 0xf200, 0xf03d, 0xf060, 0xf07d, 0xf07b, 0xf05d, 0xf05b, 0xf10e, + 0xf200, 0xfb7a, 0xf07c, 0x00ba, 0x00a4, 0xf05e, 0xf040, 0xff02, + 0xf200, 0xf201, 0xf02d, 0x00df, 0x00f6, 0x00b5, 0x00fc, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0x00e4, 0xf207, 0xfc02, + 0xf200, 0xf119, 0xff05, 0xff04, 0xf02b, 0x00f7, 0x00d7, 0xfc01, + 0xf200, 0xfb6e, 0xf402, 0xf403, 0x00b4, 0xf060, 0x00a8, 0xfc00, + 0xf200, 0xf117, 0xf114, 0xf200, 0xf118, 0xff03, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01c, 0xf200, 0xf01f, 0xf10c, + 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, 0xf01d, 0xf01b, 0xf10e, + 0xf200, 0xf01a, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf00d, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf019, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf01a, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf00d, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf019, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf505, 0xf504, 0xf503, 0xf502, 0xf501, 0xf500, 0xf10c, + 0xf200, 0xf200, 0xf116, 0xf509, 0xf508, 0xf507, 0xf506, 0xf10e, + 0xf200, 0xf87a, 0xf874, 0xf872, 0xf865, 0xf877, 0xf871, 0xf81b, + 0xf200, 0xf201, 0xf86c, 0xf870, 0xf86f, 0xf869, 0xf875, 0xfc03, + 0xf200, 0xf867, 0xf866, 0xf864, 0xf873, 0xf861, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf86d, 0xf86b, 0xf86a, 0xf868, 0xfc01, + 0xf200, 0xf86e, 0xf862, 0xf876, 0xf863, 0xf878, 0xf879, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf200, 0xf20c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf81a, 0xf814, 0xf812, 0xf805, 0xf817, 0xf811, 0xf200, + 0xf200, 0xf201, 0xf80c, 0xf810, 0xf80f, 0xf809, 0xf815, 0xfc03, + 0xf200, 0xf807, 0xf806, 0xf804, 0xf813, 0xf801, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf80d, 0xf80b, 0xf80a, 0xf808, 0xfc01, + 0xf200, 0xff0b, 0xff0a, 0xff09, 0xff08, 0xff07, 0xff06, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xff01, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -uNr linux-2.4.37.9/drivers/char/keymap_psion_de.map linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_de.map --- linux-2.4.37.9/drivers/char/keymap_psion_de.map Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_de.map Wed May 26 15:48:46 2010 @@ -0,0 +1,321 @@ +# arch/arm/drivers/char/keymap_psion_de.map +# +# Written 1999 by Ian E. Morgan +# +# largely based on keymap_psion.map by Werner Almesberger +# for UK keyboard layout +# +# based on keymap_geo.map, string and compose def's taken from +# drivers/char/defkeymap.map +# +# Special keys: +# F13 REC F14 STOP F15 PLAY +# F16 Contrast-- F17 Contrast++ F18 Backlight + + +# IEM: This is the mapping of US keyboard to keycodes: +# +# esc 1 2 3 4 5 6 7 8 9 0 del +# 23 6 5 4 3 2 1 14 13 12 11 10 +# +# q w e r t y u i o p enter +# 22 21 20 19 18 17 30 29 28 27 25 +# +# tab a s d f g h j k l : +# 38 37 36 35 34 33 46 45 44 26 9 +# +# shift z x c v b n m . up shift +# 55 54 53 52 51 50 49 43 42 60 63 +# +# ctrl fn menu space , left down right +# 39 47 31 61 59 58 41 47 + + +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 + + keycode 1 = six ampersand +alt keycode 1 = Console_6 +altgr keycode 1 = greater + + keycode 2 = five percent +alt keycode 2 = Console_5 +altgr keycode 2 = less + + keycode 3 = four dollar +alt keycode 3 = Console_4 +altgr keycode 3 = asciitilde + + keycode 4 = three section +alt keycode 4 = Console_3 +altgr keycode 4 = backslash +control keycode 4 = Control_backslash + + keycode 5 = two quotedbl +alt keycode 5 = Console_2 +altgr keycode 5 = slash + + keycode 6 = one exclam +alt keycode 6 = Console_1 +altgr keycode 6 = underscore +control keycode 6 = Control_underscore + + keycode 7 = F13 # REC + + keycode 8 = VoidSymbol + + keycode 9 = numbersign asterisk +altgr keycode 9 = equal + + keycode 10 = Delete +alt keycode 10 = Remove +altgr keycode 10 = grave +control alt keycode 10 = Boot + + keycode 11 = zero apostrophe +alt keycode 11 = Console_10 +altgr keycode 11 = braceright + + keycode 12 = nine parenright +alt keycode 12 = Console_9 +altgr keycode 12 = braceleft + + keycode 13 = eight parenleft +alt keycode 13 = Console_8 +altgr keycode 13 = bracketright +control keycode 13 = Control_bracketright + + keycode 14 = seven question +alt keycode 14 = Console_7 +altgr keycode 14 = bracketleft +control keycode 14 = Escape + + keycode 15 = F15 # PLAY + + keycode 16 = VoidSymbol + + keycode 17 = z + + keycode 18 = t +altgr keycode 18 = bar + + keycode 19 = r +altgr keycode 19 = masculine + + keycode 20 = e +altgr keycode 20 = currency + + keycode 21 = w +altgr keycode 21 = asciicircum + + keycode 22 = q +altgr keycode 22 = at + + keycode 23 = Escape Escape +alt keycode 23 = Meta_Escape +altgr keycode 23 = 0xf02 # OFF + + keycode 24 = VoidSymbol + + keycode 25 = Return + + keycode 26 = l +altgr keycode 26 = minus + + keycode 27 = p +altgr keycode 27 = ssharp + + keycode 28 = o +altgr keycode 28 = odiaeresis + + keycode 29 = i +altgr keycode 29 = mu + + keycode 30 = u +altgr keycode 30 = udiaeresis + + keycode 31 = SAlt # Menu + + keycode 32 = VoidSymbol + + keycode 33 = g + + keycode 34 = f + + keycode 35 = d + + keycode 36 = s + + keycode 37 = a +altgr keycode 37 = adiaeresis + + keycode 38 = Tab +altgr keycode 38 = Caps_Lock + + keycode 39 = SControl + + keycode 40 = VoidSymbol + + keycode 41 = Down Scroll_Backward +altgr keycode 41 = Next + + keycode 42 = comma semicolon +altgr keycode 42 = 0xf05 # Contrast++ + + keycode 43 = m +altgr keycode 43 = 0xf04 # Contrast-- + + keycode 44 = k +altgr keycode 44 = plus + + keycode 45 = j +altgr keycode 45 = division + + keycode 46 = h +altgr keycode 46 = multiply + + keycode 47 = SAltGr # Fn + + keycode 48 = VoidSymbol + + keycode 49 = n +control alt keycode 49 = 0xf0b # Debug 5 + + keycode 50 = b +altgr keycode 50 = dead_caron +control alt keycode 50 = 0xf0a # Debug 4 + + keycode 51 = v +altgr keycode 51 = dead_breve +control alt keycode 51 = 0xf09 # Debug 3 + + keycode 52 = c +altgr keycode 52 = acute +control alt keycode 52 = 0xf08 # Debug 2 + + keycode 53 = x +altgr keycode 53 = grave +control alt keycode 53 = 0xf07 # Debug 1 + + keycode 54 = y +altgr keycode 54 = diaeresis +control alt keycode 54 = 0xf06 # Debug 0 + + keycode 55 = SShift + + keycode 56 = VoidSymbol + + keycode 57 = Right +altgr keycode 57 = Select # End + + keycode 58 = Left +altgr keycode 58 = Find # Home + + keycode 59 = period colon +control alt keycode 59 = 0xf01 # SysRq + + keycode 60 = Up Scroll_Forward +altgr keycode 60 = Prior + + keycode 61 = space +altgr keycode 61 = 0xf03 # Backlight + + keycode 62 = F14 # STOP + keycode 63 = SShift + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -uNr linux-2.4.37.9/drivers/char/keymap_psion_fr.c linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_fr.c --- linux-2.4.37.9/drivers/char/keymap_psion_fr.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_fr.c Wed May 26 15:48:46 2010 @@ -0,0 +1,374 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf029, 0xf028, 0xf027, 0xf022, 0x00e9, 0xf026, 0xf10c, + 0xf200, 0xfb6d, 0xf07f, 0x00e0, 0x00e7, 0xf05f, 0x00e9, 0xf10e, + 0xf200, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb7a, 0xfb61, 0xf01b, + 0xf200, 0xf201, 0xfb6c, 0xfb70, 0xfb6f, 0xfb69, 0xfb75, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb71, 0xf009, 0xfc02, + 0xf200, 0xf600, 0xf03b, 0xf02c, 0xfb6b, 0xfb6a, 0xfb68, 0xfc01, + 0xf200, 0xfb6e, 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb77, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf03a, 0xf603, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf10c, + 0xf200, 0xfb4d, 0xf07f, 0xf030, 0xf039, 0xf038, 0xf037, 0xf10e, + 0xf200, 0xfb59, 0xfb54, 0xfb52, 0xfb45, 0xfb5a, 0xfb41, 0xf01b, + 0xf200, 0xf201, 0xfb4c, 0xfb50, 0xfb4f, 0xfb49, 0xfb55, 0xfc03, + 0xf200, 0xfb47, 0xfb46, 0xfb44, 0xfb53, 0xfb51, 0xf009, 0xfc02, + 0xf200, 0xf20b, 0xf02e, 0xf03f, 0xfb4b, 0xfb4a, 0xfb48, 0xfc01, + 0xf200, 0xfb4e, 0xfb42, 0xfb56, 0xfb43, 0xfb58, 0xfb57, 0xfc00, + 0xf200, 0xf602, 0xf601, 0x00b5, 0xf20a, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf024, 0x00b0, 0xf403, 0xf023, 0xf025, 0xf021, 0xf10c, + 0xf200, 0xf02d, 0xf07f, 0xf040, 0xf402, 0xf05c, 0x00a3, 0xf10e, + 0xf200, 0xf07d, 0xf07b, 0xf05d, 0xf05b, 0xf03e, 0xf03c, 0xff02, + 0xf200, 0xf201, 0xf02b, 0xf03d, 0xf30c, 0xf07c, 0x00f9, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb71, 0xf207, 0xfc02, + 0xf200, 0xf119, 0xf02f, 0xf30c, 0xf30d, 0xff05, 0xff04, 0xfc01, + 0xf200, 0xfb6e, 0xf402, 0xf403, 0xf027, 0xf060, 0xf404, 0xf02f, + 0xf200, 0xf117, 0xf114, 0xf200, 0xf118, 0xff03, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf01d, 0xf200, 0xf200, 0xf01b, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf00d, 0xf07f, 0xf200, 0xf200, 0xf01c, 0xf200, 0xf10e, + 0xf200, 0xf019, 0xf014, 0xf012, 0xf005, 0xf01a, 0xf001, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf011, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf017, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf00d, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf019, 0xf014, 0xf012, 0xf005, 0xf01a, 0xf001, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf011, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf017, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf505, 0xf504, 0xf503, 0xf502, 0xf501, 0xf500, 0xf10c, + 0xf200, 0xf86d, 0xf116, 0xf509, 0xf508, 0xf507, 0xf506, 0xf10e, + 0xf200, 0xf879, 0xf874, 0xf872, 0xf865, 0xf87a, 0xf861, 0xf81b, + 0xf200, 0xf201, 0xf86c, 0xf870, 0xf86f, 0xf869, 0xf875, 0xfc03, + 0xf200, 0xf867, 0xf866, 0xf864, 0xf873, 0xf871, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf86b, 0xf86a, 0xf868, 0xfc01, + 0xf200, 0xf86e, 0xf862, 0xf876, 0xf863, 0xf878, 0xf877, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf80d, 0xf20c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf819, 0xf814, 0xf812, 0xf805, 0xf81a, 0xf801, 0xf200, + 0xf200, 0xf201, 0xf80c, 0xf810, 0xf80f, 0xf809, 0xf815, 0xfc03, + 0xf200, 0xf807, 0xf806, 0xf804, 0xf813, 0xf811, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf80b, 0xf80a, 0xf808, 0xfc01, + 0xf200, 0xff0b, 0xff0a, 0xff09, 0xff08, 0xff07, 0xff06, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xff01, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -uNr linux-2.4.37.9/drivers/char/keymap_psion_fr.map linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_fr.map --- linux-2.4.37.9/drivers/char/keymap_psion_fr.map Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_fr.map Wed May 26 15:48:46 2010 @@ -0,0 +1,274 @@ +keymaps 0-2,4-5,8,12 + + keycode 1 = parenright six dollar Control_bracketright +alt keycode 1 = Console_6 + + keycode 2 = parenleft five degree +alt keycode 2 = Console_5 + + keycode 3 = apostrophe four dead_tilde +alt keycode 3 = Console_4 + + keycode 4 = quotedbl three numbersign Escape +alt keycode 4 = Console_3 + + keycode 5 = eacute two percent +alt keycode 5 = Console_2 + + keycode 6 = ampersand one exclam +alt keycode 6 = Console_1 + + keycode 7 = F13 + + keycode 8 = VoidSymbol + + keycode 9 = m +AltGr keycode 9 = minus + + keycode 10 = Delete +alt keycode 10 = Remove +control alt keycode 10 = Boot + + keycode 11 = agrave zero at +alt keycode 11 = Console_10 + + keycode 12 = ccedilla nine dead_circumflex +alt keycode 12 = Console_9 + + keycode 13 = underscore eight backslash Control_backslash +alt keycode 13 = Console_8 + + keycode 14 = eacute seven sterling +alt keycode 14 = Console_7 + + keycode 15 = F15 + + keycode 16 = VoidSymbol + + keycode 17 = y +AltGr keycode 17 = braceright + + keycode 18 = t +AltGr keycode 18 = braceleft + + keycode 19 = r +AltGr keycode 19 = bracketright + + keycode 20 = e +AltGr keycode 20 = bracketleft + + keycode 21 = z +AltGr keycode 21 = greater + + keycode 22 = a +altgr keycode 22 = less + + keycode 23 = Escape Escape +alt keycode 23 = Meta_Escape +altgr keycode 23 = 0xf02 # OFF + + keycode 24 = VoidSymbol + + keycode 25 = Return + + keycode 26 = l +altgr keycode 26 = plus + + keycode 27 = p +altgr keycode 27 = equal + + keycode 28 = o +altgr keycode 28 = KP_Multiply + + keycode 29 = i +altgr keycode 29 = bar + + keycode 30 = u +altgr keycode 30 = ugrave + + keycode 31 = SAlt # Menu + + keycode 32 = VoidSymbol + + keycode 33 = g + + keycode 34 = f + + keycode 35 = d + + keycode 36 = s + + keycode 37 = q + + keycode 38 = Tab +altgr keycode 38 = Caps_Lock + + keycode 39 = SControl + + keycode 40 = VoidSymbol + + keycode 41 = Down Scroll_Backward +AltGr keycode 41 = Next + + keycode 42 = semicolon period +AltGr keycode 42 = slash + + keycode 43 = comma question +AltGr keycode 43 = KP_Multiply + + keycode 44 = k +AltGr keycode 44 = KP_Divide + + keycode 45 = j +altgr keycode 45 = 0xf05 # Contrast++ + + keycode 46 = h +altgr keycode 46 = 0xf04 # Contrast-- + + keycode 47 = SAltGr # Fn + + keycode 48 = VoidSymbol + + keycode 49 = n +control alt keycode 49 = 0xf0b # Debug 5 + + keycode 50 = b +AltGr keycode 50 = dead_circumflex +control alt keycode 50 = 0xf0a # Debug 4 + + keycode 51 = v +AltGr keycode 51 = dead_tilde +control alt keycode 51 = 0xf09 # Debug 3, ARCHKEY_9 + + keycode 52 = c +AltGr keycode 52 = apostrophe +control alt keycode 52 = 0xf08 # Debug 2, ARCHKEY_8 + + keycode 53 = x +AltGr keycode 53 = grave +control alt keycode 53 = 0xf07 # Debug 1, ARCHKEY_7 + + keycode 54 = w +AltGr keycode 54 = dead_diaeresis +control alt keycode 54 = 0xf06 # Debug 0, ARCHKEY_6 + + keycode 55 = SShift +altgr keycode 55 = slash + + keycode 56 = VoidSymbol + + keycode 57 = Right +altgr keycode 57 = Select + + keycode 58 = Left +altgr keycode 58 = Find + + keycode 59 = colon mu +control alt keycode 59 = 0xf01 # SysRq + + keycode 60 = Up Scroll_Forward +altgr keycode 60 = Prior + + keycode 61 = space +altgr keycode 61 = 0xf03 # Backlight + + keycode 62 = F14 + keycode 63 = SShift + + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -uNr linux-2.4.37.9/drivers/char/keymap_psion_us.c linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_us.c --- linux-2.4.37.9/drivers/char/keymap_psion_us.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_us.c Wed May 26 15:48:46 2010 @@ -0,0 +1,374 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf10c, + 0xf200, 0xf03a, 0xf07f, 0xf030, 0xf039, 0xf038, 0xf037, 0xf10e, + 0xf200, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf01b, + 0xf200, 0xf201, 0xfb6c, 0xfb70, 0xfb6f, 0xfb69, 0xfb75, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf009, 0xfc02, + 0xf200, 0xf600, 0xf02e, 0xfb6d, 0xfb6b, 0xfb6a, 0xfb68, 0xfc01, + 0xf200, 0xfb6e, 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf02c, 0xf603, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf05e, 0xf025, 0xf024, 0xf023, 0xf040, 0xf021, 0xf10c, + 0xf200, 0xf022, 0xf07f, 0xf029, 0xf028, 0xf02a, 0xf026, 0xf10e, + 0xf200, 0xfb59, 0xfb54, 0xfb52, 0xfb45, 0xfb57, 0xfb51, 0xf01b, + 0xf200, 0xf201, 0xfb4c, 0xfb50, 0xfb4f, 0xfb49, 0xfb55, 0xfc03, + 0xf200, 0xfb47, 0xfb46, 0xfb44, 0xfb53, 0xfb41, 0xf009, 0xfc02, + 0xf200, 0xf20b, 0xf027, 0xfb4d, 0xfb4b, 0xfb4a, 0xfb48, 0xfc01, + 0xf200, 0xfb4e, 0xfb42, 0xfb56, 0xfb43, 0xfb58, 0xfb5a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf03f, 0xf20a, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf03e, 0xf03c, 0xf02f, 0xf05c, 0xf07e, 0xf05f, 0xf10c, + 0xf200, 0xf03b, 0xf060, 0xf07d, 0xf07b, 0xf05d, 0xf05b, 0xf10e, + 0xf200, 0xf30c, 0xf07c, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xff02, + 0xf200, 0xf201, 0xfb6c, 0xf03d, 0xf02d, 0xf02b, 0xf30d, 0xfc03, + 0xf200, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf207, 0xfc02, + 0xf200, 0xf119, 0xff05, 0xff04, 0xfb6b, 0xfb6a, 0xfb68, 0xfc01, + 0xf200, 0xfb6e, 0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xf02f, + 0xf200, 0xf117, 0xf114, 0xf200, 0xf118, 0xff03, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf01e, 0xf200, 0xf200, 0xf01c, 0xf200, 0xf01f, 0xf10c, + 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, 0xf01d, 0xf01b, 0xf10e, + 0xf200, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf00d, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200, + 0xf200, 0xf201, 0xf00c, 0xf010, 0xf00f, 0xf009, 0xf015, 0xfc03, + 0xf200, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf00d, 0xf00b, 0xf00a, 0xf008, 0xfc01, + 0xf200, 0xf00e, 0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf505, 0xf504, 0xf503, 0xf502, 0xf501, 0xf500, 0xf10c, + 0xf200, 0xf200, 0xf116, 0xf509, 0xf508, 0xf507, 0xf506, 0xf10e, + 0xf200, 0xf879, 0xf874, 0xf872, 0xf865, 0xf877, 0xf871, 0xf81b, + 0xf200, 0xf201, 0xf86c, 0xf870, 0xf86f, 0xf869, 0xf875, 0xfc03, + 0xf200, 0xf867, 0xf866, 0xf864, 0xf873, 0xf861, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf86d, 0xf86b, 0xf86a, 0xf868, 0xfc01, + 0xf200, 0xf86e, 0xf862, 0xf876, 0xf863, 0xf878, 0xf87a, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xf200, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10c, + 0xf200, 0xf200, 0xf20c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf10e, + 0xf200, 0xf819, 0xf814, 0xf812, 0xf805, 0xf817, 0xf811, 0xf200, + 0xf200, 0xf201, 0xf80c, 0xf810, 0xf80f, 0xf809, 0xf815, 0xfc03, + 0xf200, 0xf807, 0xf806, 0xf804, 0xf813, 0xf801, 0xf009, 0xfc02, + 0xf200, 0xf200, 0xf200, 0xf80d, 0xf80b, 0xf80a, 0xf808, 0xfc01, + 0xf200, 0xff0b, 0xff0a, 0xff09, 0xff08, 0xff07, 0xff06, 0xfc00, + 0xf200, 0xf602, 0xf601, 0xff01, 0xf200, 0xf020, 0xf10d, 0xfc00, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -uNr linux-2.4.37.9/drivers/char/keymap_psion_us.map linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_us.map --- linux-2.4.37.9/drivers/char/keymap_psion_us.map Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/keymap_psion_us.map Wed May 26 15:48:46 2010 @@ -0,0 +1,311 @@ +# arch/arm/drivers/char/keymap_psion_us.map +# +# Written 1999 by Ian E. Morgan +# +# largely based on keymap_psion.map by Werner Almesberger +# for UK keyboard layout +# +# based on keymap_geo.map, string and compose def's taken from +# drivers/char/defkeymap.map +# +# Special keys: +# F13 REC F14 STOP F15 PLAY +# F16 Contrast-- F17 Contrast++ F18 Backlight + + +# IEM: This is the mapping of US keyboard to keycodes: +# +# esc 1 2 3 4 5 6 7 8 9 0 del +# 23 6 5 4 3 2 1 14 13 12 11 10 +# +# q w e r t y u i o p enter +# 22 21 20 19 18 17 30 29 28 27 25 +# +# tab a s d f g h j k l : +# 38 37 36 35 34 33 46 45 44 26 9 +# +# shift z x c v b n m . up shift +# 63 54 53 52 51 50 49 43 42 60 55 +# +# ctrl fn menu space , left down right +# 39 47 31 61 59 58 41 47 + + +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 + + keycode 1 = six asciicircum +alt keycode 1 = Console_6 +altgr keycode 1 = greater +control keycode 1 = Control_asciicircum + + keycode 2 = five percent +alt keycode 2 = Console_5 +altgr keycode 2 = less + + keycode 3 = four dollar +alt keycode 3 = Console_4 +altgr keycode 3 = slash + + keycode 4 = three numbersign +alt keycode 4 = Console_3 +altgr keycode 4 = backslash +control keycode 4 = Control_backslash + + keycode 5 = two at +alt keycode 5 = Console_2 +altgr keycode 5 = asciitilde + + keycode 6 = one exclam +alt keycode 6 = Console_1 +altgr keycode 6 = underscore +control keycode 6 = Control_underscore + + keycode 7 = F13 # REC + + keycode 8 = VoidSymbol + + keycode 9 = colon quotedbl +altgr keycode 9 = semicolon + + keycode 10 = Delete +alt keycode 10 = Remove +altgr keycode 10 = grave +control alt keycode 10 = Boot + + keycode 11 = zero parenright +alt keycode 11 = Console_10 +altgr keycode 11 = braceright + + keycode 12 = nine parenleft +alt keycode 12 = Console_9 +altgr keycode 12 = braceleft + + keycode 13 = eight asterisk +alt keycode 13 = Console_8 +altgr keycode 13 = bracketright +control keycode 13 = Control_bracketright + + keycode 14 = seven ampersand +alt keycode 14 = Console_7 +altgr keycode 14 = bracketleft +control keycode 14 = Escape + + keycode 15 = F15 # PLAY + + keycode 16 = VoidSymbol + + keycode 17 = y +altgr keycode 17 = KP_Multiply + + keycode 18 = t +altgr keycode 18 = bar + + keycode 19 = r + + keycode 20 = e + + keycode 21 = w + + keycode 22 = q + + keycode 23 = Escape Escape +alt keycode 23 = Meta_Escape +altgr keycode 23 = 0xf02 # OFF + + keycode 24 = VoidSymbol + + keycode 25 = Return + + keycode 26 = l + + keycode 27 = p +altgr keycode 27 = equal + + keycode 28 = o +altgr keycode 28 = minus + + keycode 29 = i +altgr keycode 29 = plus + + keycode 30 = u +altgr keycode 30 = KP_Divide + + keycode 31 = SAlt # Menu + + keycode 32 = VoidSymbol + + keycode 33 = g + + keycode 34 = f + + keycode 35 = d + + keycode 36 = s + + keycode 37 = a + + keycode 38 = Tab +altgr keycode 38 = Caps_Lock + + keycode 39 = SControl + + keycode 40 = VoidSymbol + + keycode 41 = Down Scroll_Backward +altgr keycode 41 = Next + + keycode 42 = period apostrophe +altgr keycode 42 = 0xf05 # Contrast++ + + keycode 43 = m +altgr keycode 43 = 0xf04 # Contrast-- + + keycode 44 = k + + keycode 45 = j + + keycode 46 = h + + keycode 47 = SAltGr # Fn + + keycode 48 = VoidSymbol + + keycode 49 = n +control alt keycode 49 = 0xf0b # Debug 5 + + keycode 50 = b +control alt keycode 50 = 0xf0a # Debug 4 + + keycode 51 = v +control alt keycode 51 = 0xf09 # Debug 3, ARCHKEY_9 + + keycode 52 = c +control alt keycode 52 = 0xf08 # Debug 2, ARCHKEY_8 + + keycode 53 = x +control alt keycode 53 = 0xf07 # Debug 1, ARCHKEY_7 + + keycode 54 = z +control alt keycode 54 = 0xf06 # Debug 0, ARCHKEY_6 + + keycode 55 = SShift +altgr keycode 55 = slash + + keycode 56 = VoidSymbol + + keycode 57 = Right +altgr keycode 57 = Select # End + + keycode 58 = Left +altgr keycode 58 = Find # Home + + keycode 59 = comma question +control alt keycode 59 = 0xf01 # SysRq + + keycode 60 = Up Scroll_Forward +altgr keycode 60 = Prior + + keycode 61 = space +altgr keycode 61 = 0xf03 # Backlight + + keycode 62 = F14 # STOP + + keycode 63 = SShift + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -uNr linux-2.4.37.9/drivers/char/mem.c linux-2.4.37.9-vrs1-5mx2/drivers/char/mem.c --- linux-2.4.37.9/drivers/char/mem.c Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/mem.c Mon Jun 7 18:47:47 2010 @@ -27,9 +27,6 @@ #include #include -#ifdef CONFIG_I2C -extern int i2c_init_all(void); -#endif #ifdef CONFIG_FB extern void fbmem_init(void); #endif @@ -741,9 +738,6 @@ printk("unable to get major %d for memory devs\n", MEM_MAJOR); memory_devfs_register(); rand_initialize(); -#ifdef CONFIG_I2C - i2c_init_all(); -#endif #if defined (CONFIG_FB) fbmem_init(); #endif diff -uNr linux-2.4.37.9/drivers/char/omaha-rtc.c linux-2.4.37.9-vrs1-5mx2/drivers/char/omaha-rtc.c --- linux-2.4.37.9/drivers/char/omaha-rtc.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/omaha-rtc.c Wed May 26 15:48:46 2010 @@ -0,0 +1,566 @@ +/* + * (C) ARM Limited 2002. + * + * Real Time Clock interface for Linux on Omaha + * + * Based on sa1100-rtc.c + * + * Copyright (c) 2000 Nils Faerber + * + * Based on rtc.c by Paul Gortmaker + * Date/time conversion routines taken from arch/arm/kernel/time.c + * by Linus Torvalds and Russell King + * and the GNU C Library + * ( ... I love the GPL ... just take what you need! ;) + * + * 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. + * + * 1.00 2001-06-08 Nicolas Pitre + * - added periodic timer capability using OSMR1 + * - flag compatibility with other RTC chips + * - permission checks for ioctls + * - major cleanup, partial rewrite + * + * 0.03 2001-03-07 CIH + * - Modify the bug setups RTC clock. + * + * 0.02 2001-02-27 Nils Faerber + * - removed mktime(), added alarm irq clear + * + * 0.01 2000-10-01 Nils Faerber + * - initial release + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "1.00" + +#define epoch 1970 + +#define TIMER_FREQ 3686400 + +#define RTC_DEF_DIVIDER 32768 - 1 +#define RTC_DEF_TRIM 0 + +/* Those are the bits from a classic RTC we want to mimic */ +#define RTC_IRQF 0x80 /* any of the following 3 is active */ +#define RTC_PF 0x40 +#define RTC_AF 0x20 +#define RTC_UF 0x10 + +// bitdefs for rtc registers +#define TICNT_ENABLE 0x80 // Enable tick interrupt +#define TICNT_PERIOD 0x7F // Divisor required for 1Hz tick +#define RTC_ENABLE 0x1 // Enable bit for RTC + +static unsigned long rtc_status; +static unsigned long rtc_irq_data; +static unsigned long rtc_freq = 1024; + +static struct fasync_struct *rtc_async_queue; +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); + +extern spinlock_t rtc_lock; + +static const unsigned char days_in_mo[] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +#define is_leap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) + +// all the alarm and rtc registers +static volatile unsigned int almsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMSEC); +static volatile unsigned int almmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMIN); +static volatile unsigned int almhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMHOUR); +static volatile unsigned int almday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMDAY); +static volatile unsigned int almmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMON); +static volatile unsigned int almyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMYEAR); + +static volatile unsigned int bcdsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDSEC); +static volatile unsigned int bcdmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMIN); +static volatile unsigned int bcdhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDHOUR); +static volatile unsigned int bcdday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDAY); +static volatile unsigned int bcddate = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDATE); +static volatile unsigned int bcdmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMON); +static volatile unsigned int bcdyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDYEAR); + +/* + * Converts seconds since 1970-01-01 00:00:00 to Gregorian date. + */ + +static void decodetime (unsigned long t, struct rtc_time *tval) +{ + long days, month, year, rem; + + days = t / 86400; + rem = t % 86400; + tval->tm_hour = rem / 3600; + rem %= 3600; + tval->tm_min = rem / 60; + tval->tm_sec = rem % 60; + tval->tm_wday = (4 + days) % 7; + +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) + + year = epoch; + while (days >= (365 + is_leap(year))) { + unsigned long yg = year + days / 365; + days -= ((yg - year) * 365 + + LEAPS_THRU_END_OF (yg - 1) + - LEAPS_THRU_END_OF (year - 1)); + year = yg; + } + tval->tm_year = year - 1900; + tval->tm_yday = days + 1; + + month = 0; + if (days >= 31) { + days -= 31; + month++; + if (days >= (28 + is_leap(year))) { + days -= (28 + is_leap(year)); + month++; + while (days >= days_in_mo[month]) { + days -= days_in_mo[month]; + month++; + } + } + } + tval->tm_mon = month; + tval->tm_mday = days + 1; +} + +// Get alarm time in seconds +static unsigned long get_alarm_time(void) +{ + int sec, min,hour,date,mon,year; + + // Read data from h/w + year = __raw_readb(almyear); + mon = __raw_readb(almmon); + date = __raw_readb(almday); + hour = __raw_readb(almhour); + min = __raw_readb(almmin); + sec = __raw_readb(almsec); + + // convert all the data into binary + year = BCD_TO_BIN(year); + mon = BCD_TO_BIN(mon); + date = BCD_TO_BIN(date); + hour = BCD_TO_BIN(hour); + min = BCD_TO_BIN(min); + sec = BCD_TO_BIN(sec); + + // convert year to 19xx or 20xx as appropriate + if (year > 69) + year += 1900; + else + year += 2000; + + // Now calculate number of seconds since time began... + return mktime(year,mon,date,hour,min,sec); +} + +// Get rtc time in seconds +static unsigned long get_rtc_time(void) +{ + int sec,min,hour,day,date,mon,year; + + // Read data from h/w + year = __raw_readb(bcdyear); + mon = __raw_readb(bcdmon); + date = __raw_readb(bcdday); + day = __raw_readb(bcddate); + hour = __raw_readb(bcdhour); + min = __raw_readb(bcdmin); + sec = __raw_readb(bcdsec); + + // convert all the data into binary + year = BCD_TO_BIN(year); + mon = BCD_TO_BIN(mon); + date = BCD_TO_BIN(date); + day = BCD_TO_BIN(day); + hour = BCD_TO_BIN(hour); + min = BCD_TO_BIN(min); + sec = BCD_TO_BIN(sec); + + // convert year to 19xx or 20xx as appropriate + if (year > 69) + year += 1900; + else + year += 2000; + + // Now calculate number of seconds since time began... + return mktime(year,mon,date,hour,min,sec); +} + +/* Sets time of alarm */ +static void set_alarm_time(struct rtc_time *tval) +{ + + int sec,min,hour,day,mon,year; + + // Convert data from binary to 8-bit bcd + sec = BIN_TO_BCD(tval->tm_sec); + min = BIN_TO_BCD(tval->tm_min); + hour = BIN_TO_BCD(tval->tm_hour); + day = BIN_TO_BCD(tval->tm_mday); + mon = BIN_TO_BCD(tval->tm_mon); + + // Year is special + year = tval->tm_year; + if(year > 1999) + year -=2000; + else + year -=1900; + + year = BIN_TO_BCD(year); + + // Write all the registers + __raw_writeb(year,almyear); + __raw_writeb(mon,almmon); + __raw_writeb(day,almday); + __raw_writeb(hour,almhour); + __raw_writeb(min,almmin); + __raw_writeb(sec,almsec); +} + +/* Sets time of alarm */ +static void set_rtc_time(struct rtc_time *tval) +{ + + int sec,min,hour,day,date,mon,year; + + // Convert data from binary to 8-bit bcd + sec = BIN_TO_BCD(tval->tm_sec); + min = BIN_TO_BCD(tval->tm_min); + hour = BIN_TO_BCD(tval->tm_hour); + day = BIN_TO_BCD(tval->tm_mday); + date = BIN_TO_BCD(tval->tm_wday); + mon = BIN_TO_BCD(tval->tm_mon); + + // Year is special + year = tval->tm_year; + if(year > 1999) + year -=2000; + else + year -=1900; + + year = BIN_TO_BCD(year); + + // Write all the registers + __raw_writeb(year,bcdyear); + __raw_writeb(mon,bcdmon); + __raw_writeb(date,bcddate); + __raw_writeb(day,bcdday); + __raw_writeb(hour,bcdhour); + __raw_writeb(min,bcdmin); + __raw_writeb(sec,bcdsec); +} + +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* update irq data & counter */ + rtc_irq_data += 0x100; + + /* wake up waiting process */ + wake_up_interruptible(&rtc_wait); + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); +} + +static int rtc_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit (1, &rtc_status)) + return -EBUSY; + MOD_INC_USE_COUNT; + rtc_irq_data = 0; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + rtc_status = 0; + MOD_DEC_USE_COUNT; + return 0; +} + +static int rtc_fasync (int fd, struct file *filp, int on) +{ + return fasync_helper (fd, filp, on, &rtc_async_queue); +} + +static unsigned int rtc_poll(struct file *file, poll_table *wait) +{ + poll_wait (file, &rtc_wait, wait); + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM; +} + +static loff_t rtc_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&rtc_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + for (;;) { + spin_lock_irq (&rtc_lock); + data = rtc_irq_data; + if (data != 0) { + rtc_irq_data = 0; + break; + } + spin_unlock_irq (&rtc_lock); + + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + + schedule(); + } + + spin_unlock_irq (&rtc_lock); + + data -= 0x100; /* the first IRQ wasn't actually missed */ + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&rtc_wait, &wait); + return retval; +} + +static int rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + volatile unsigned int rtcalm = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCALM); + volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT); + + struct rtc_time tm, tm2; + switch (cmd) { + case RTC_AIE_OFF: + spin_lock_irq(&rtc_lock); + __raw_writel(0,rtcalm); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_AIE_ON: + spin_lock_irq(&rtc_lock); + __raw_writel(0x7F,rtcalm); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_UIE_OFF: + spin_lock_irq(&rtc_lock); + __raw_writel(~TICNT_ENABLE,ticnt); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_UIE_ON: + spin_lock_irq(&rtc_lock); + __raw_writel(TICNT_ENABLE|TICNT_PERIOD,ticnt); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_PIE_OFF: + spin_lock_irq(&rtc_lock); + // Periodic int not available + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_PIE_ON: + spin_lock_irq(&rtc_lock); + // Periodic int not available + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_ALM_READ: + decodetime(get_alarm_time(),&tm); + break; + case RTC_ALM_SET: + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2))) + return -EFAULT; + decodetime(get_rtc_time(),&tm); + if ((unsigned)tm2.tm_hour < 24) + tm.tm_hour = tm2.tm_hour; + if ((unsigned)tm2.tm_min < 60) + tm.tm_min = tm2.tm_min; + if ((unsigned)tm2.tm_sec < 60) + tm.tm_sec = tm2.tm_sec; + + // Munge (as per sa1100) + tm.tm_year+=1900; + tm.tm_mon+=1; + + // Set the alarm + set_alarm_time(&tm); + return 0; + case RTC_RD_TIME: + decodetime (get_rtc_time(), &tm); + break; + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm))) + return -EFAULT; + tm.tm_year += 1900; + if (tm.tm_year < epoch || (unsigned)tm.tm_mon >= 12 || + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] + + (tm.tm_mon == 1 && is_leap(tm.tm_year))) || + (unsigned)tm.tm_hour >= 24 || + (unsigned)tm.tm_min >= 60 || + (unsigned)tm.tm_sec >= 60) + return -EINVAL; + tm.tm_mon +=1; // wierd: same as sa1100 though (gets month wrong otherwise!) + set_rtc_time(&tm); + return 0; + case RTC_IRQP_READ: + return put_user(rtc_freq, (unsigned long *)arg); + case RTC_IRQP_SET: + if (arg < 1 || arg > TIMER_FREQ) + return -EINVAL; + if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) + return -EACCES; + rtc_freq = arg; + return 0; + case RTC_EPOCH_READ: + return put_user (epoch, (unsigned long *)arg); + default: + return -EINVAL; + } + return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0; +} + +static struct file_operations rtc_fops = { + .owner = THIS_MODULE, + .llseek = rtc_llseek, + .read = rtc_read, + .poll = rtc_poll, + .ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, + .fasync = rtc_fasync, +}; + +static struct miscdevice omahartc_miscdev = { + .minor = RTC_MINOR, + .name = "rtc", + .fops = &rtc_fops, +}; + +static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + char *p = page; + int len; + struct rtc_time tm; + + decodetime (get_rtc_time(), &tm); + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); + decodetime (get_alarm_time(), &tm); + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n" + "alrm_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq); + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return len; +} + +static int __init rtc_init(void) +{ + volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT); + volatile unsigned int rtccon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCCON); + int ret; + + misc_register (&omahartc_miscdev); + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL); + + // Enable RTC + __raw_writel(RTC_ENABLE,rtccon); + + // Acquire 1Hz timer + ret = request_irq (OMAHA_INT_TICK, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL); + if (ret) { + printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_TICK); + goto IRQ_TICK_failed; + } + + // Acquire RTC (Alarm interrupt) + ret = request_irq (OMAHA_INT_RTC, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL); + if (ret) { + printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_RTC); + goto IRQ_RTC_failed; + } + + printk (KERN_INFO "Omaha Real Time Clock driver v" DRIVER_VERSION "\n"); + + // Program tick interrupt divisor to generate real 1Hz clock and enable the interrupt + __raw_writeb(TICNT_ENABLE|TICNT_PERIOD,ticnt); + + return 0; + +IRQ_TICK_failed: + free_irq (OMAHA_INT_TICK, NULL); +IRQ_RTC_failed: + free_irq(OMAHA_INT_RTC, NULL); + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&omahartc_miscdev); + return ret; +} + +static void __exit rtc_exit(void) +{ + free_irq (OMAHA_INT_TICK, NULL); + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&omahartc_miscdev); +} + +module_init(rtc_init); +module_exit(rtc_exit); + +MODULE_AUTHOR("ARM Limited "); +MODULE_DESCRIPTION("Omaha Realtime Clock Driver (RTC)"); +EXPORT_NO_SYMBOLS; diff -uNr linux-2.4.37.9/drivers/char/omaha_wdt.c linux-2.4.37.9-vrs1-5mx2/drivers/char/omaha_wdt.c --- linux-2.4.37.9/drivers/char/omaha_wdt.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/omaha_wdt.c Wed May 26 15:48:46 2010 @@ -0,0 +1,193 @@ +/* + * Watchdog driver for the Omaha + * (C) ARM Limited 2002. + * + * Based on sa1100_wdt.c + * + * (c) Copyright 2000 Oleg Drokin + * Based on SoftDog driver by Alan Cox + * + * 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. + * + * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 Oleg Drokin + * + * 27/11/2000 Initial release + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_MARGIN 8 /* (secs) Default is 1 minute */ +#define WT_TPS 7812 /* Watchdog ticks per second. */ +#define WT_ENABLE 0x21 // Enable bits for watchdog +#define WT_CLKSEL_128 0x18 // Select 1/128 divider + +static int omaha_margin = TIMER_MARGIN; /* in seconds */ +static int omahawdt_users; +static int pre_margin; +#ifdef MODULE +MODULE_PARM(omaha_margin,"i"); +#endif + +/* + * Allow only one person to hold it open + */ + +static int omahadog_open(struct inode *inode, struct file *file) +{ + volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON); + volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT); + volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT); + unsigned int tmp; + + if(test_and_set_bit(1,&omahawdt_users)) + return -EBUSY; + MOD_INC_USE_COUNT; + /* Activate omaha Watchdog timer */ + + /* Assume that uhal has set up pre-scaler according + * to the system clock frequency (don't change it!) + * + * Ie. all counting occurs at 1MHz / 128 = 7812.5Hz + * + * Since we have 16-bit counter, maximum period is + * 65536/7812.5 = 8.338608 seconds! + */ + + pre_margin = WT_TPS * omaha_margin; + + // Set count to the maximum + __raw_writel(pre_margin,wtcnt); + + // Set the clock division factor + tmp = __raw_readl(wtcon); + tmp |= WT_CLKSEL_128; + __raw_writel(tmp,wtcon); + + // Program an initial count into WTDAT + __raw_writel(0x8000,wtdat); + + // enable the watchdog + tmp = __raw_readl(wtcon); + tmp |= WT_ENABLE; + + __raw_writel(tmp,wtcon); + + return 0; +} + +static int omahadog_release(struct inode *inode, struct file *file) +{ + volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON); + unsigned int tmp; + + /* + * Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT + */ +#ifndef CONFIG_WATCHDOG_NOWAYOUT + tmp = __raw_readl(wtcon); + tmp &= ~WT_ENABLE; + __raw_writel(tmp,wtcon); +#endif + omahawdt_users = 0; + MOD_DEC_USE_COUNT; + return 0; +} + +static ssize_t omahadog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT); + + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* Refresh timer. */ + if(len) { + __raw_writel(pre_margin,wtcnt); + return 1; + } + return 0; +} + +static int omahadog_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT); + static struct watchdog_info ident = { + identity: "omaha Watchdog", + }; + + switch(cmd){ + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)); + case WDIOC_GETSTATUS: + return put_user(0,(int *)arg); + case WDIOC_GETBOOTSTATUS: + return 0; + case WDIOC_KEEPALIVE: + __raw_writel(pre_margin,wtdat); + return 0; + } +} + +static struct file_operations omahadog_fops= +{ + .owner = THIS_MODULE, + .write = omahadog_write, + .ioctl = omahadog_ioctl, + .open = omahadog_open, + .release = omahadog_release, +}; + +static struct miscdevice omahadog_miscdev= +{ + .minor = WATCHDOG_MINOR, + .name = "omaha watchdog", + .fops = &omahadog_fops +}; + +static int __init omahadog_init(void) +{ + int ret; + + ret = misc_register(&omahadog_miscdev); + + if (ret) + return ret; + + printk("Omaha Watchdog Timer: timer margin %d sec\n", omaha_margin); + + return 0; +} + +static void __exit omahadog_exit(void) +{ + misc_deregister(&omahadog_miscdev); +} + +module_init(omahadog_init); +module_exit(omahadog_exit); diff -uNr linux-2.4.37.9/drivers/char/pcmcia/Config.in linux-2.4.37.9-vrs1-5mx2/drivers/char/pcmcia/Config.in --- linux-2.4.37.9/drivers/char/pcmcia/Config.in Mon Feb 1 21:04:46 2010 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/pcmcia/Config.in Wed May 26 15:48:37 2010 @@ -5,7 +5,13 @@ mainmenu_option next_comment comment 'PCMCIA character devices' -dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_SERIAL +if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_SERIAL_8250" = "y" ]; then + dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS y +else + if [ "$CONFIG_SERIAL" = "m" -o "$CONFIG_SERIAL_8250" = "m" ]; then + dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS m + fi +fi if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" ]; then define_bool CONFIG_PCMCIA_CHRDEV y fi diff -uNr linux-2.4.37.9/drivers/char/pcmcia/memory_cs.c linux-2.4.37.9-vrs1-5mx2/drivers/char/pcmcia/memory_cs.c --- linux-2.4.37.9/drivers/char/pcmcia/memory_cs.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/pcmcia/memory_cs.c Wed May 26 15:48:37 2010 @@ -0,0 +1,214 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static dev_info_t dev_info = "memory_cs"; +static dev_link_t *dev_list; + +struct memcs_dev { + dev_link_t link; + struct map_info map; +}; + +static __u8 mem_cs_read8(struct map_info *map, unsigned long ofs) +{ + return readb(map->map_priv_1 + ofs); +} + +static __u16 mem_cs_read16(struct map_info *map, unsigned long ofs) +{ + return readw(map->map_priv_1 + ofs); +} + +static __u32 mem_cs_read32(struct map_info *map, unsigned long ofs) +{ + return readl(map->map_priv_1 + ofs); +} + +static void mem_cs_copy_from(struct map_info *map, void *to, unsigned long ofs, ssize_t size) +{ + memcpy_fromio(to, map->map_priv_1 + ofs, size); +} + +static void mem_cs_write8(struct map_info *map, __u8 val, unsigned long ofs) +{ + writeb(val, map->map_priv_1 + ofs); +} + +static void mem_cs_write16(struct map_info *map, __u16 val, unsigned long ofs) +{ + writew(val, map->map_priv_1 + ofs); +} + +static void mem_cs_write32(struct map_info *map, __u32 val, unsigned long ofs) +{ + writel(val, map->map_priv_1 + ofs); +} + +static void mem_cs_copy_to(struct map_info *map, unsigned long ofs, const void *to, ssize_t size) +{ + memcpy_toio(map->map_priv_1 + ofs, from, size); +} + +static void mem_cs_release(u_long arg); + +static void mem_cs_detach(dev_link_t *link) +{ + del_timer(&link->release); + if (link->state & DEV_CONFIG) { + mem_cs_release((u_long)link); + if (link->state & DEV_STALE_CONFIG) { + link->state |= DEV_STALE_LINK; + return; + } + } + + if (link->handle) + CardServices(DeregisterClient, link->handle); + + kfree(link); +} + +static void mem_cs_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + + link->dev = NULL; + if (link->win) { + CardServices(ReleaseWindow, link->win); + } + link->state &= ~DEV_CONFIG; + + if (link->state & DEV_STALE_LINK) + mem_cs_detach(link); +} + +static void mem_cs_config(dev_link_t *link) +{ + struct memcs_dev *dev = link->priv; + cs_status_t status; + win_req_t req; + + link->state |= DEV_CONFIG; + + req.Attributes = word_width ? WIN_DATA_WIDTH_16 : WIN_DATA_WIDTH_8; + req.Base = 0; + req.Size = 0; + req.AccessSpeed = mem_speed; + + link->win = (window_handle_t)link->handle; + + CS_CHECK(RequestWindow, &link->win, &req); + + CS_CHECK(GetStatus, link->handle, &status); + + dev->map.buswidth = word_width ? 2 : 1; + dev->map.size = req.Size; + dev->map.map_priv_1 = ioremap(req.Base, req.Size); +} + +static int +mem_cs_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) + mod_timer(&link->release, jiffies + HZ/20); + break; + + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + mem_cs_config(link); + break; + } + return 0; +} + +static dev_link_t *mem_cs_attach(void) +{ + struct memcs_dev *dev; + client_reg_t clnt; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (dev) { + memset(dev, 0, sizeof(*dev)); + + dev->map.read8 = mem_cs_read8; + dev->map.read16 = mem_cs_read16; + dev->map.read32 = mem_cs_read32; + dev->map.copy_from = mem_cs_copy_from; + dev->map.write8 = mem_cs_write8; + dev->map.write16 = mem_cs_write16; + dev->map.write32 = mem_cs_write32; + dev->map.copy_to = mem_cs_copy_to; + + dev->link.release.function = &mem_cs_release; + dev->link.release.data = (u_long)link; + dev->link.priv = dev; + + dev->link.next = dev_list; + dev_list = &dev->link; + + clnt.dev_info = &dev_info; + clnt.Attributes = INOF_IO_CLIENT | INFO_CARD_SHARE; + clnt.EventMask = + CS_EVENT_WRITE_PROTECT | CS_EVENT_CARD_INSERTION | + CS_EVENT_CARD_REMOVAL | CS_EVENT_BATTERY_DEAD | + CS_EVENT_BATTERY_LOW; + + clnt.event_handler = &mem_cs_event; + clnt.Version = 0x0210; + clnt.event_callback_args.client_data = &dev->link; + + ret = CardServices(RegisterClient, &dev->link.handle, &clnt); + if (ret != CS_SUCCESS) { + error_info_t err = { RegisterClient, ret }; + CardServices(ReportError, dev->link.handle, &err); + mem_cs_detach(&dev->link); + dev = NULL; + } + } + + return &dev->link; +} + +static int __init mem_cs_init(void) +{ + servinfo_t serv; + + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "memory_cs: Card services release " + "does not match\n"); + return -ENXIO; + } + register_pccard_driver(&dev_info, mem_cs_attach, mem_cs_detach); + return 0; +} + +static void __exit mem_cs_exit(void) +{ + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + memory_detach(dev_list); +} + +module_init(mem_cs_init); +module_exit(mem_cs_exit); + +MODULE_LICENSE("GPL"); diff -uNr linux-2.4.37.9/drivers/char/psionw-rtc.c linux-2.4.37.9-vrs1-5mx2/drivers/char/psionw-rtc.c --- linux-2.4.37.9/drivers/char/psionw-rtc.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/psionw-rtc.c Wed May 26 15:48:46 2010 @@ -0,0 +1,445 @@ +/* + * Real Time Clock interface for Psion Windermere + * + * Copyright (c) 2002 Tony Lindgren + * + * Modified from the sa1100-rtc.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "1.00" + +#define TIMER_FREQ 3686400 + +#define RTC_DEF_DIVIDER 32768 - 1 +#define RTC_DEF_TRIM 0 + +/* Those are the bits from a classic RTC we want to mimic */ +#define RTC_IRQF 0x80 /* any of the following 3 is active */ +#define RTC_PF 0x40 +#define RTC_AF 0x20 +#define RTC_UF 0x10 + +static unsigned long rtc_status; +static unsigned long rtc_irq_data; +static unsigned long rtc_freq = 1024; + +static struct fasync_struct *rtc_async_queue; +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); + +extern spinlock_t rtc_lock; + +static const unsigned char days_in_mo[] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +#define is_leap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) + +/* + * Converts seconds since 1970-01-01 00:00:00 to Gregorian date. + */ +static void decodetime (unsigned int t, struct rtc_time *tval) +{ + unsigned int days, month, year, rem; + + days = t / 86400; + rem = t % 86400; + tval->tm_hour = rem / 3600; + rem %= 3600; + tval->tm_min = rem / 60; + tval->tm_sec = rem % 60; + tval->tm_wday = (4 + days) % 7; + +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) + + year = 1970 + days / 365; + days -= ((year - 1970) * 365 + + LEAPS_THRU_END_OF (year - 1) + - LEAPS_THRU_END_OF (1970 - 1)); + if (days < 0) { + year -= 1; + days += 365 + is_leap(year); + } + tval->tm_year = year - 1900; + tval->tm_yday = days + 1; + + month = 0; + if (days >= 31) { + days -= 31; + month++; + if (days >= (28 + is_leap(year))) { + days -= (28 + is_leap(year)); + month++; + while (days >= days_in_mo[month]) { + days -= days_in_mo[month]; + month++; + } + } + } + tval->tm_mon = month; + tval->tm_mday = days + 1; +} + +static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* + * If we match for the first time, the periodic interrupt flag won't + * be set. If it is, then we did wrap around (very unlikely but + * still possible) and compute the amount of missed periods. + * The match reg is updated only when the data is actually retrieved + * to avoid unnecessary interrupts. + */ + if (rtc_irq_data & RTC_PF) { + rtc_irq_data += (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))) << 8; + } else { + rtc_irq_data += (0x100|RTC_PF|RTC_IRQF); + } + + wake_up_interruptible(&rtc_wait); + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); +} + +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* update irq data & counter */ + rtc_irq_data |= (RTC_AF|RTC_IRQF); + rtc_irq_data += 0x100; + + /* wake up waiting process */ + wake_up_interruptible(&rtc_wait); + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); +} + +static int rtc_set_timer(int frequency) { + unsigned int timer = 0; + unsigned int multiplier = 2000; + + if (frequency == 0) { + psionw_writel(0, TC1CTRL); + psionw_writel(0, TC1LOAD); + return 0; + } + + timer = psionw_readl(TC1CTRL); + timer |= TC_MODE; /* Periodic mode */ + + if (frequency > 1900) { + multiplier = 512000; + timer |= TC_CLKSEL; /* 512kHz mode */ + } else { + timer &= ~TC_CLKSEL; /* 2kHz mode */ + } + + timer |= TC_ENABLE; + psionw_writel(timer, TC1CTRL); + + psionw_writel((multiplier / frequency) - 1, TC1LOAD); + + return 0; +} + +static int rtc_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit (1, &rtc_status)) + return -EBUSY; + rtc_irq_data = 0; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + spin_lock_irq (&rtc_lock); + rtc_set_timer(0); + spin_unlock_irq (&rtc_lock); + rtc_status = 0; + return 0; +} + +static int rtc_fasync (int fd, struct file *filp, int on) +{ + return fasync_helper (fd, filp, on, &rtc_async_queue); +} + +static unsigned int rtc_poll(struct file *file, poll_table *wait) +{ + poll_wait (file, &rtc_wait, wait); + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM; +} + +static loff_t rtc_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&rtc_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + for (;;) { + spin_lock_irq (&rtc_lock); + data = rtc_irq_data; + if (data != 0) { + rtc_irq_data = 0; + break; + } + spin_unlock_irq (&rtc_lock); + + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + + schedule(); + } + +#if 0 + if (data & RTC_PF) { + /* interpolate missed periods and set match for the next one */ + unsigned long period = TIMER_FREQ/rtc_freq; + unsigned long oscr = OSCR; + unsigned long osmr1 = OSMR1; + unsigned long missed = (oscr - osmr1)/period; + data += missed << 8; + OSSR = OSSR_M1; /* clear match on timer 1 */ + OSMR1 = osmr1 + (missed + 1)*period; + /* ensure we didn't miss another match in the mean time */ + while( (signed long)((osmr1 = OSMR1) - OSCR) <= 0 ) { + data += 0x100; + OSSR = OSSR_M1; /* clear match on timer 1 */ + OSMR1 = osmr1 + period; + } + } +#endif + spin_unlock_irq (&rtc_lock); + + data -= 0x100; /* the first IRQ wasn't actually missed */ + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&rtc_wait, &wait); + return retval; +} + +static int rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct rtc_time tm, tm2; + + switch (cmd) { + case RTC_AIE_OFF: + spin_lock_irq(&rtc_lock); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_AIE_ON: + spin_lock_irq(&rtc_lock); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_UIE_OFF: + spin_lock_irq(&rtc_lock); + rtc_set_timer(0); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_UIE_ON: + spin_lock_irq(&rtc_lock); + rtc_set_timer(1); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_PIE_OFF: + spin_lock_irq(&rtc_lock); + rtc_set_timer(0); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_PIE_ON: + if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE)) + return -EACCES; + spin_lock_irq(&rtc_lock); + rtc_set_timer(rtc_freq); + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_ALM_READ: + decodetime(psionw_read_rtc_alarm(), &tm); + break; + case RTC_ALM_SET: + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2))) + return -EFAULT; + decodetime(psionw_read_rtc(), &tm); + if ((unsigned)tm2.tm_hour < 24) + tm.tm_hour = tm2.tm_hour; + if ((unsigned)tm2.tm_min < 60) + tm.tm_min = tm2.tm_min; + if ((unsigned)tm2.tm_sec < 60) + tm.tm_sec = tm2.tm_sec; + psionw_write_rtc_alarm(mktime(tm.tm_year + 1900, tm.tm_mon + 1, + tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec)); + return 0; + case RTC_RD_TIME: + decodetime(psionw_read_rtc(), &tm); + break; + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm))) + return -EFAULT; + tm.tm_year += 1900; + if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 || + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] + + (tm.tm_mon == 1 && is_leap(tm.tm_year))) || + (unsigned)tm.tm_hour >= 24 || + (unsigned)tm.tm_min >= 60 || + (unsigned)tm.tm_sec >= 60) + return -EINVAL; + psionw_write_rtc(mktime(tm.tm_year, tm.tm_mon + 1, + tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec)); + return 0; + case RTC_IRQP_READ: + return put_user(rtc_freq, (unsigned long *)arg); + case RTC_IRQP_SET: + if (arg < 1 || arg > TIMER_FREQ) + return -EINVAL; + if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) + return -EACCES; + rtc_freq = arg; + return 0; + case RTC_EPOCH_READ: + return put_user (1970, (unsigned long *)arg); + default: + return -EINVAL; + } + return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0; +} + +static struct file_operations rtc_fops = { + owner: THIS_MODULE, + llseek: rtc_llseek, + read: rtc_read, + poll: rtc_poll, + ioctl: rtc_ioctl, + open: rtc_open, + release: rtc_release, + fasync: rtc_fasync, +}; + +static struct miscdevice psionwrtc_miscdev = { + RTC_MINOR, + "rtc", + &rtc_fops +}; + +static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + char *p = page; + int len; + struct rtc_time tm; + + decodetime(psionw_read_rtc(), &tm); + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1970); + decodetime(psionw_read_rtc_alarm(), &tm); + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n" + "alrm_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + ////p += sprintf(p, "trim/divider\t: 0x%08x\n", RTTR); + ////p += sprintf(p, "alarm_IRQ\t: %s\n", (RTSR & RTSR_ALE) ? "yes" : "no" ); + ////p += sprintf(p, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no"); + ////p += sprintf(p, "periodic_IRQ\t: %s\n", (OIER & OIER_E1) ? "yes" : "no"); + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq); + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return len; +} + +static int __init rtc_init(void) +{ + int ret; + + misc_register (&psionwrtc_miscdev); + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL); + + ret = request_irq (IRQ_TC1OI, timer1_interrupt, SA_INTERRUPT, "rtc timer", NULL); + if (ret) { + printk (KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_TC1OI); + goto IRQ_TC1OI_failed; + } + + ret = request_irq (IRQ_RTCMI, rtc_interrupt, SA_INTERRUPT, "rtc alarm", NULL); + if (ret) { + printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTCMI); + goto IRQ_RTCMI_failed; + } + + rtc_set_timer(0); + + printk (KERN_INFO "Psion Windermere Real Time Clock driver v" DRIVER_VERSION "\n"); + + return 0; + +IRQ_RTCMI_failed: + free_irq (IRQ_TC1OI, NULL); +IRQ_TC1OI_failed: + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&psionwrtc_miscdev); + return ret; +} + +static void __exit rtc_exit(void) +{ + rtc_set_timer(0); + free_irq (IRQ_TC1OI, NULL); + free_irq (IRQ_RTCMI, NULL); + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&psionwrtc_miscdev); +} + +module_init(rtc_init); +module_exit(rtc_exit); + +MODULE_AUTHOR("Tony Lindgren "); +MODULE_DESCRIPTION("Psion Windermere Realtime Clock Driver (RTC)"); +EXPORT_NO_SYMBOLS; diff -uNr linux-2.4.37.9/drivers/char/psionw_procfs.c linux-2.4.37.9-vrs1-5mx2/drivers/char/psionw_procfs.c --- linux-2.4.37.9/drivers/char/psionw_procfs.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.37.9-vrs1-5mx2/drivers/char/psionw_procfs.c Wed May 26 15:48:46 2010 @@ -0,0 +1,684 @@ +/* + * linux/drivers/chars/psionw_utils.c + * + * Psion procfs entries for manipulating backlight, contrast, power off + * and auto-sleep on Psion Windermere based Computers (Psion5mx(Pro), + * Revo(Plus), Mako). + * + * Copyright (C) 2002 Thilo Hille + * Vaclav Kulakovsky + * Tony Lindgren + * Simon Howard + * + * 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 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include <../drivers/pcmcia/psion_etna.h> + +#define MODULE_VERSION "0.2" +#define MODULE_NAME "procfs_psionw" +#define MODULE_DIR_NAME "psionw" +#define COREAD 3 + +extern void psion_off(void); +extern void psionw_lcd_powerdown(int lock); +extern void psionw_lcd_powerup(int lock); + +extern int psion_get_contrast(void); +extern int psion_set_contrast(int new_contrast, int lock); +extern unsigned int psionw_get_cpu_speed(int cpu); +extern void psionw_set_cpu_speed(int speed); +/*extern int psionw_battery_proc_read(char *page, char **start, + off_t off, int count, + int *eof, void *data); */ + +/* Psion sleep variables */ + +//#define PSLEEP_DEBUG 1 +#ifdef PSLEEP_DEBUG + #define DEBUG_PSLEEP(x...) printk(x) +#else + #define DEBUG_PSLEEP(x...) do { ; } while(0) +#endif + +#define PROC_SLEEP_MAX_LEN 8 + +static struct timer_list psion_sleep_timer; +static int psionblankinterval = 0; + +struct fb_data_t { + char name[PROC_SLEEP_MAX_LEN + 1]; + char value[PROC_SLEEP_MAX_LEN + 1]; +}; + +struct fb_data_t psion_sleep_data; + +static struct proc_dir_entry *psion_sleep_file; +extern void (*psion_sleep_set_callback)(void); +void psion_sleep_set(void); + +static int psionw_proc_lcdpower_read(char *page, char **start, off_t off, + int count, int *eof, void *data); +static int psionw_proc_lcdpower_write(struct file *file, + const char *buffer, unsigned long count, void *data); + +static int psionw_proc_backlight_read(char *page, char **start, off_t off, + int count, int *eof, void *data); +static int psionw_proc_backlight_write(struct file *file, + const char *buffer, unsigned long count, void *data); +static int psionw_proc_contrast_read(char *page, char **start, off_t off, + int count, int *eof, void *data); +static int psionw_proc_contrast_write(struct file *file, + const char *buffer, unsigned long count, void *data); +static int psionw_proc_state_read(char *page, char **start, off_t off, + int count, int *eof, void *data); +static int psionw_proc_state_write(struct file *file, + const char *buffer, unsigned long count, void *data); +static int psionw_proc_uart_read(char *page, char **start, off_t off, + int count, int *eof, void *data); +static int psionw_proc_uart_write(struct file *file, + const char *buffer, unsigned long count, void *data); +static int psionw_proc_cpu_read(char *page, char **start, off_t off, + int count, int *eof, void *data); +static int psionw_proc_cpu_write(struct file *file, + const char *buffer, unsigned long count, void *data); + +static struct proc_dir_entry *psionw_proc_dir, + *psionw_lcdpower_proc_entry, + *psionw_backlight_proc_entry, + *psionw_contrast_proc_entry, + *psionw_state_proc_entry, + *psionw_uart1_proc_entry, + *psionw_uart2_proc_entry, + *psionw_mains_proc_entry, + *psionw_case_proc_entry; + + +struct uart_data_t { + short uart; +}; + +struct uart_data_t uart1_data, uart2_data; + +static int +psionw_proc_lcdpower_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + return sprintf(page, "%d\n", + (psionw_readl(LCDCTL) & LCDCTL_EN)? 1 : 0 ); +} + +static int +psionw_proc_lcdpower_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char char_value; + int value; + + if (count < 1) { + return -EINVAL; + } + + if (copy_from_user(&char_value, buffer, 1)) + return -EFAULT; + + value = char_value - '0'; + + if (value) { + psionw_lcd_powerup(1); + } else { + psionw_lcd_powerdown(1); + } + + return count; +} + +static int +psionw_proc_contrast_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + return sprintf(page, "%i\n", psion_get_contrast()); +} + +static int damn_atoi(const char *name) +{ + int val = 0; + + for (;; name++) { + switch (*name) { + case '0'...'9': + val = 10*val+(*name-'0'); + break; + default: + return val; + } + } +} + +static int +psionw_proc_contrast_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char rbuffer[COREAD + 1]; + int new_contrast; + int len; + + if (count < 1) + return -EINVAL; + + if (count > COREAD){ + len = COREAD; + } + else { + len = count; + } + + if (copy_from_user(&rbuffer, buffer, len)) + return -EFAULT; + + rbuffer[len]='\0'; + new_contrast = damn_atoi(rbuffer); + + psion_set_contrast(new_contrast, 1); + + return len; +} + + +static int +psionw_proc_backlight_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + return sprintf(page, "%d\n", + (psionw_readl(PCDR) & PCDR_LIGHT)? 1 : 0 ); +} + +static int +psionw_proc_backlight_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char char_value; + int value; + int pcdr; + long flags; + + if (count < 1) { + return -EINVAL; + } + + if (copy_from_user(&char_value, buffer, 1)) + return -EFAULT; + + value = char_value - '0'; + + save_flags_cli(flags); + pcdr = psionw_readl(PCDR); + if (value) { + pcdr |= PCDR_LIGHT; + } else { + pcdr &= ~PCDR_LIGHT; + } + psionw_writel(pcdr, PCDR); + restore_flags(flags); + + return count; +} + +static int +psionw_proc_uart_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int psionw_proc_uart_state; + struct uart_data_t *uart_data = (struct uart_data_t *)data; + int pcdr; + + if (uart_data->uart == 1) { + pcdr = PCDR_UART1; + } + else if (uart_data->uart == 2) { + pcdr = PCDR_UART2; + } + else + return -EINVAL; + + psionw_proc_uart_state = (psionw_readb(PCDR) & pcdr); + + return sprintf(page, "%i\n",(psionw_proc_uart_state) ? 1 : 0); +} + +static int +psionw_proc_uart_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct uart_data_t *uart_data = (struct uart_data_t *)data; + unsigned char char_value; + int value; + int pcdr; + long flags; + + if (copy_from_user(&char_value, buffer, 1)) + return -EFAULT; + + value = char_value - '0'; + if (count < 1) { + return -EINVAL; + } + if (uart_data->uart==1){ + pcdr=PCDR_UART1; + } + else if (uart_data->uart==2){ + pcdr=PCDR_UART2; + } + else + return -EINVAL; + + save_flags_cli(flags); + if (value) { + printk("uart%i: powerup: \n",uart_data->uart); + psionw_writeb(psionw_readb(PCDR) | pcdr, PCDR); + } + else { + printk("uart%i: powerdown: \n",uart_data->uart); + psionw_writeb(psionw_readb(PCDR) & ~pcdr, PCDR); + } + restore_flags(flags); + + return count; +} + +static int +psionw_proc_state_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ +/* + * SlothAttack! + * If i had invented the refrigerator, their lights would remain on even with their door closed . + * We should output 0 if the machine is in sleepmode. But since noone will ever be able to read it + * it always sends 1 + */ + return sprintf(page, "1\n"); + +} + +static int +psionw_proc_state_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char char_value; + int value; + int pcdr; + + if (count < 1) { + return -EINVAL; + } + + if (copy_from_user(&char_value, buffer, 1)) + return -EFAULT; + + value = char_value - '0'; + + pcdr = psionw_readl(PCDR); + if (!value){ + psion_off(); + } + + return count; +} + +static int +psionw_proc_cpu_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int speed = 0; + + speed = psionw_get_cpu_speed(0) / 100000; + return sprintf(page, "%d.%d\n", speed/10, speed%10); +} + +static int +psionw_proc_cpu_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char char_value; + int value; + int pcdr; + + if (count < 1) { + return -EINVAL; + } + + if (copy_from_user(&char_value, buffer, 1)) + return -EFAULT; + + value = char_value - '0'; + + psionw_set_cpu_speed(value); + + return count; +} + +static void psion_sleep_timer_func(unsigned long dummy) +{ + psion_off(); + psion_sleep_set(); +} + +/* Called from keyboard_psion.c on a key press */ +void psion_sleep_set(void) +{ + /* modify timer*/ + psion_sleep_timer.function = psion_sleep_timer_func; + if (psionblankinterval) { + mod_timer(&psion_sleep_timer, jiffies + psionblankinterval); + } else { + del_timer(&psion_sleep_timer); + } +} + +static int psion_sleep_proc_read(char *page, char **start, + off_t off, int count, + int *eof, void *data) +{ + int len; + struct fb_data_t *fb_data = (struct fb_data_t *)data; + + len = sprintf(page, "%s\n", fb_data->value); + return len; +} + +static int psion_sleep_proc_write(struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int len, interval; + struct fb_data_t *fb_data = (struct fb_data_t *)data; + + if (count > PROC_SLEEP_MAX_LEN) len = PROC_SLEEP_MAX_LEN; + else len = count; + + if (copy_from_user(fb_data->value, buffer, len)) { + return 0; + } + fb_data->value[len] = '\0'; + + /* read new timeout */ + sscanf( fb_data->value, "%d", &interval ); + if( interval ) + if( interval < 10 ) { + interval = 10; + printk( "Minimal sleep inerval is 10 sec.\n" ); + } + snprintf(fb_data->value, PROC_SLEEP_MAX_LEN, "%d", interval); + fb_data->value[len] = '\0'; + + psionblankinterval = interval * HZ; + psion_sleep_set(); + DEBUG_PSLEEP("Psion sleep after %d s. \n", psionblankinterval/HZ ); + + return len; +} + + +static int psionw_proc_mains_read(char *page, char **start, + off_t off, int count, + int *eof, void *data) { + return sprintf(page, "%i\n", (psionw_readb(PWRSR) & DCDET) != 0); +} + +static int psionw_proc_mains_write(struct file *file, + const char *buffer, + unsigned long count, + void *data) { + /* i cant do that */ + return 0; +} + +static int psionw_proc_case_read(char *page, char **start, + off_t off, int count, + int *eof, void *data) { + + /* Make sure the data direction is set for read */ + if (psionw_readb(PBDDR) & PBDR_OPEN) { + long flags; + save_flags_cli(flags); + psionw_writeb(psionw_readb(PBDDR) & ~PBDR_OPEN, PBDDR); + restore_flags(flags); + } + + /* 0 on PBDR_OPEN = open, 1 = closed, invert this + (seems more intuitive this way) */ + return sprintf(page, "%i\n", (psionw_readb(PBDR) & PBDR_OPEN) == 0); +} + +static int psionw_proc_case_write(struct file *file, + const char *buffer, + unsigned long count, + void *data) { + /* i cant close the case for you! */ + return 0; +} + + +int __init psionwbl_init(void) +{ + int rv = 0; + + /* Create directory */ + psionw_proc_dir = proc_mkdir(MODULE_DIR_NAME, NULL); + if(psionw_proc_dir == NULL) { + printk("Couldn't create the procfs dir for psionw \n"); + rv = -ENOMEM; + goto out; + } + psionw_proc_dir->owner = THIS_MODULE; + + /* Register the /proc/psionw/lcd entry */ + psionw_lcdpower_proc_entry = create_proc_entry("lcd", 0444, + psionw_proc_dir); + if (psionw_lcdpower_proc_entry == NULL) { + printk("Couldn't create the procfs entry for lcd. \n"); + rv = -EINVAL; + goto out; + } + psionw_lcdpower_proc_entry->read_proc = + &psionw_proc_lcdpower_read; + psionw_lcdpower_proc_entry->write_proc = + &psionw_proc_lcdpower_write; + + /* Register the /proc/psionw/backlight entry. */ + psionw_backlight_proc_entry = create_proc_entry("backlight", 0444, + psionw_proc_dir); + if (psionw_backlight_proc_entry == NULL) { + printk("Co