diff -urN orig/Documentation/Configure.help linux/Documentation/Configure.help --- orig/Documentation/Configure.help Tue Jun 24 13:57:40 2003 +++ linux/Documentation/Configure.help Tue Jun 24 11:16:15 2003 @@ -4330,6 +4330,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 @@ -9908,7 +9915,7 @@ whenever you want). If you want to compile it as a module, say M here and read . -CSZ packet scheduler +CSZ packet scheduler (experimental) CONFIG_NET_SCH_CSZ Say Y here if you want to use the Clark-Shenker-Zhang (CSZ) packet scheduling algorithm for some of your network devices. At the @@ -12265,6 +12272,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. @@ -12297,6 +12315,7 @@ The module will be called madgemc.o. If you want to compile it as a module, say M here and read . + SMC ISA/MCA Token Ring adapter support CONFIG_SMCTR This is support for the ISA and MCA SMC Token Ring cards, @@ -14088,6 +14107,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 @@ -17827,6 +17856,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. @@ -18879,6 +18922,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. @@ -20512,6 +20566,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 @@ -24099,6 +24177,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) @@ -24106,6 +24198,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 @@ -24173,6 +24273,36 @@ Say Y if you want support for the ARM920T processor. Otherwise, say N. +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 ARM922T processor. + Otherwise, say N. + +Support low power wait for interrupt +CONFIG_CPU_ARM922_CPU_IDLE + Saying Y here will allow the processor to enter a low power + mode whilst waiting for an interrupt in idle. If you're unsure + say Y. + +Enable ARM922T instruction cache +CONFIG_CPU_ARM922_I_CACHE_ON + Say Y here to enable the processor instruction cache. Unless + you have a reason not to, say Y. + +Enable ARM922T data cache +CONFIG_CPU_ARM922_D_CACHE_ON + Say Y here to enable the processor data cache. Unless + you have a reason not to, say Y. + +Use data cache in writethrough mode +CONFIG_CPU_ARM922_WRITETHROUGH + Say Y here to use the data cache in writethough mode. Unless you + specifically require this, say N. + Support ARM1020 processor CONFIG_CPU_ARM1020 The ARM1020 is the cached version of the ARM10 processor, @@ -24210,6 +24340,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 @@ -24222,6 +24357,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 @@ -24250,19 +24394,27 @@ 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 + This is an experimental much faster emulator which now also has full 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 is very simple, and approximately 3-6 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. + It should be sufficient for most programs. It may be not suitable + for scientific calculations, but you have to check this for yourself. + If you do not feel you need a faster FP emulation you should better + choose NWFPE. 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 diff -urN orig/Documentation/cpufreq/core.txt linux/Documentation/cpufreq/core.txt --- orig/Documentation/cpufreq/core.txt Thu Jan 1 01:00:00 1970 +++ linux/Documentation/cpufreq/core.txt Fri Mar 7 10:35:36 2003 @@ -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 -urN orig/Documentation/cpufreq/cpu-drivers.txt linux/Documentation/cpufreq/cpu-drivers.txt --- orig/Documentation/cpufreq/cpu-drivers.txt Thu Jan 1 01:00:00 1970 +++ linux/Documentation/cpufreq/cpu-drivers.txt Fri Mar 7 10:35:36 2003 @@ -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 -urN orig/Documentation/cpufreq/governors.txt linux/Documentation/cpufreq/governors.txt --- orig/Documentation/cpufreq/governors.txt Thu Jan 1 01:00:00 1970 +++ linux/Documentation/cpufreq/governors.txt Sat Feb 22 10:43:02 2003 @@ -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 -urN orig/Documentation/cpufreq/index.txt linux/Documentation/cpufreq/index.txt --- orig/Documentation/cpufreq/index.txt Thu Jan 1 01:00:00 1970 +++ linux/Documentation/cpufreq/index.txt Sat Feb 22 10:43:02 2003 @@ -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 -urN orig/Documentation/cpufreq/user-guide.txt linux/Documentation/cpufreq/user-guide.txt --- orig/Documentation/cpufreq/user-guide.txt Thu Jan 1 01:00:00 1970 +++ linux/Documentation/cpufreq/user-guide.txt Fri Mar 7 10:35:36 2003 @@ -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 -urN orig/Documentation/cpufreq-old linux/Documentation/cpufreq-old --- orig/Documentation/cpufreq-old Thu Jan 1 01:00:00 1970 +++ linux/Documentation/cpufreq-old Sun Jul 7 13:36:45 2002 @@ -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 -urN orig/Documentation/l3/structure linux/Documentation/l3/structure --- orig/Documentation/l3/structure Thu Jan 1 01:00:00 1970 +++ linux/Documentation/l3/structure Sun Aug 5 18:40:00 2001 @@ -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 -urN orig/Documentation/serial/driver linux/Documentation/serial/driver --- orig/Documentation/serial/driver Thu Jan 1 01:00:00 1970 +++ linux/Documentation/serial/driver Sat Nov 24 23:24:47 2001 @@ -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 -urN orig/Makefile linux/Makefile --- orig/Makefile Tue Jun 24 13:57:41 2003 +++ linux/Makefile Wed Jul 16 21:41:45 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 21 -EXTRAVERSION = +EXTRAVERSION =-rmk1 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -134,7 +134,10 @@ DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o -DRIVERS-y += drivers/char/char.o \ +DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.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 @@ -158,6 +161,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 @@ -183,13 +187,14 @@ DRIVERS-$(CONFIG_HIL) += drivers/hil/hil.o DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o -DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o DRIVERS-$(CONFIG_GSC) += drivers/gsc/gscbus.o DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o +DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o +DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o DRIVERS := $(DRIVERS-y) @@ -267,11 +272,6 @@ 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 -urN orig/Rules.make linux/Rules.make --- orig/Rules.make Mon Aug 5 13:29:42 2002 +++ linux/Rules.make Mon Aug 5 13:54:24 2002 @@ -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 -urN orig/arch/alpha/config.in linux/arch/alpha/config.in --- orig/arch/alpha/config.in Tue Jun 24 13:57:41 2003 +++ linux/arch/alpha/config.in Tue Jun 24 11:16:19 2003 @@ -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 -urN orig/arch/arm/Makefile linux/arch/arm/Makefile --- orig/arch/arm/Makefile Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/Makefile Sun Jun 15 21:43:52 2003 @@ -8,8 +8,15 @@ # Copyright (C) 1995-2001 by Russell King LINKFLAGS :=-p -X -T arch/arm/vmlinux.lds +OBJCOPYFLAGS :=-O binary -R .note -R .comment -S GZFLAGS :=-9 -CFLAGS +=-fno-common -pipe +CFLAGS +=-Uarm -fno-common -pipe + +ifeq ($(CONFIG_FRAME_POINTER),y) +CFLAGS :=$(CFLAGS:-fomit-frame-pointer=-mapcs -mno-sched-prolog) +endif + +CFLAGS :=$(CFLAGS:-O2=-Os) ifeq ($(CONFIG_DEBUG_INFO),y) CFLAGS +=-g @@ -24,10 +31,13 @@ apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 -Os # This selects which instruction set is used. +# Note that GCC is lame - it doesn't numerically define an +# architecture version macro, but instead defines a whole +# series of macros. arch-y := -arch-$(CONFIG_CPU_32v3) :=-march=armv3 -arch-$(CONFIG_CPU_32v4) :=-march=armv4 -arch-$(CONFIG_CPU_32v5) :=-march=armv5 +arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 +arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 +arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5 # This selects how we optimise for the processor. tune-y := @@ -40,12 +50,12 @@ tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 -CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float +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 ifeq ($(CONFIG_CPU_26),y) -PROCESSOR = armo +PROCESSOR := armo ifeq ($(CONFIG_ROM_KERNEL),y) DATAADDR = 0x02080000 TEXTADDR = 0x03800000 @@ -81,6 +91,10 @@ INCDIR = cl7500 endif +ifeq ($(CONFIG_ARCH_RISCSTATION),y) +MACHINE = riscstation +endif + ifeq ($(CONFIG_FOOTBRIDGE),y) MACHINE = footbridge INCDIR = ebsa285 @@ -121,12 +135,16 @@ MACHINE = integrator endif +ifeq ($(CONFIG_ARCH_AT91RM9200),y) +MACHINE = at91rm9200 +endif + ifeq ($(CONFIG_ARCH_MX1ADS),y) MACHINE = mx1ads endif ifeq ($(CONFIG_ARCH_CAMELOT),y) -MACHINE = epxa10db +MACHINE = epxa endif ifeq ($(CONFIG_ARCH_CLPS711X),y) @@ -135,19 +153,23 @@ endif ifeq ($(CONFIG_ARCH_FORTUNET),y) -TEXTADDR = 0xc0008000 +TEXTADDR = 0xc0208000 endif ifeq ($(CONFIG_ARCH_ANAKIN),y) MACHINE = anakin endif -export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT +ifeq ($(CONFIG_ARCH_OMAHA),y) +MACHINE = omaha +endif + +export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT OBJCOPYFLAGS # Only set INCDIR if its not already defined above # Grr, ?= doesn't work as all the other assignment operators do. Make bug? ifeq ($(origin INCDIR), undefined) -INCDIR := $(MACHINE) +INCDIR :=$(MACHINE) endif ifeq ($(origin DATAADDR), undefined) @@ -161,32 +183,42 @@ CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES) endif -HEAD := arch/arm/kernel/head-$(PROCESSOR).o \ - arch/arm/kernel/init_task.o -SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe -CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) -LIBS := arch/arm/lib/lib.a $(LIBS) +HEAD :=arch/arm/kernel/head-$(PROCESSOR).o \ + arch/arm/kernel/init_task.o +SUBDIRS +=arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe +CORE_FILES :=arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) +LIBS :=arch/arm/lib/lib.a $(LIBS) ifeq ($(CONFIG_FPE_NWFPE),y) -LIBS := arch/arm/nwfpe/math-emu.o $(LIBS) +LIBS :=arch/arm/nwfpe/math-emu.o $(LIBS) endif # Only include fastfpe if it is part of the kernel tree. -FASTFPE := arch/arm/fastfpe +FASTFPE :=arch/arm/fastfpe ifeq ($(FASTFPE),$(wildcard $(FASTFPE))) -SUBDIRS += $(FASTFPE) +SUBDIRS +=$(FASTFPE) ifeq ($(CONFIG_FPE_FASTFPE),y) -LIBS := arch/arm/fastfpe/fast-math-emu.o $(LIBS) +LIBS :=arch/arm/fastfpe/fast-math-emu.o $(LIBS) +endif endif + +ifeq ($(findstring y,$(CONFIG_USB_OHCI_SA1111) $(CONFIG_USB_OHCI_AT91)),y) + SUBDIRS +=arch/arm/common + CORE_FILES +=arch/arm/common/nopci.o endif ifeq ($(findstring y,$(CONFIG_ARCH_CLPS7500) $(CONFIG_ARCH_L7200)),y) -SUBDIRS += drivers/acorn/char -DRIVERS += drivers/acorn/char/acorn-char.o +SUBDIRS +=drivers/acorn/char +DRIVERS +=drivers/acorn/char/acorn-char.o +endif + +ifeq ($(CONFIG_ARCH_RISCSTATION),y) +SUBDIRS +=drivers/acorn/char +DRIVERS +=drivers/acorn/char/acorn-char.o endif -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot -MAKETOOLS = $(MAKE) -C arch/$(ARCH)/tools +MAKEBOOT =$(MAKE) -C arch/$(ARCH)/boot +MAKETOOLS =$(MAKE) -C arch/$(ARCH)/tools # The following is a hack to get 'constants.h' up # to date before starting compilation @@ -194,15 +226,44 @@ $(patsubst %,_dir_%, $(SUBDIRS)): maketools $(patsubst %,_modsubdir_%,$(MOD_DIRS)): maketools -symlinks: archsymlinks +symlinks: include/asm-arm/.arch include/asm-arm/.proc -archsymlinks: - $(RM) include/asm-arm/arch include/asm-arm/proc - (cd include/asm-arm; ln -sf arch-$(INCDIR) arch; ln -sf proc-$(PROCESSOR) proc) +# Update machine arch and proc symlinks if something which affects +# them changed. We use .arch and .proc to indicate when they were +# updated last, otherwise make uses the target directory mtime. + +include/asm-arm/.arch: $(wildcard include/config/arch/*.h) +ifneq ("$(INCDIR)","") + @echo ' Making asm-arm/arch -> asm-arm/arch-$(INCDIR) symlink' + @rm -f include/asm-arm/arch + @ln -sf arch-$(INCDIR) include/asm-arm/arch + @touch $@ +else + @echo ' No architecture defined. You may want to use a pre-packaged config. make a5k_config, ebsa110_config, footbridge_config, etc.' +endif + +include/asm-arm/.proc: $(wildcard include/config/cpu/32.h) $(wildcard include/config/cpu/26.h) +ifneq ("$(INCDIR)","") + @echo ' Making asm-arm/proc -> asm-arm/proc-$(PROCESSOR) symlink' + @rm -f include/asm-arm/proc + @ln -sf proc-$(PROCESSOR) include/asm-arm/proc + @touch $@ +else + @echo ' No architecture defined. You may want to use a pre-packaged config. make a5k_config, ebsa110_config, footbridge_config, etc.' +endif + +.PHONY: maketools +maketools: include/asm-arm/.arch include/asm-arm/.proc \ + include/asm-arm/constants.h include/linux/version.h checkbin + @$(MAKETOOLS) vmlinux: arch/arm/vmlinux.lds -arch/arm/vmlinux.lds: $(LDSCRIPT) dummy +arch/arm/vmlinux.lds: arch/arm/Makefile $(LDSCRIPT) \ + $(wildcard include/config/cpu/32.h) \ + $(wildcard include/config/cpu/26.h) \ + $(wildcard include/config/arch/*.h) + @echo ' Generating $@' @sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@ arch/arm/kernel arch/arm/mm arch/arm/lib: dummy @@ -216,39 +277,37 @@ MRPROPER_FILES += \ arch/arm/tools/constants.h* \ - include/asm-arm/arch \ - include/asm-arm/proc \ + include/asm-arm/arch include/asm-arm/.arch \ + include/asm-arm/proc include/asm-arm/.proc \ include/asm-arm/constants.h* \ include/asm-arm/mach-types.h # We use MRPROPER_FILES and CLEAN_FILES now -archmrproper: +archmrproper: FORCE @/bin/true -archclean: +archclean: FORCE @$(MAKEBOOT) clean -archdep: scripts/mkdep archsymlinks +archdep: scripts/mkdep symlinks @$(MAKETOOLS) dep @$(MAKEBOOT) dep -# we need version.h -maketools: checkbin include/linux/version.h - @$(MAKETOOLS) all - -# Ensure this is ld "2.9.4" or later +# Ensure this is ld "2.9.5" or later NEW_LINKER := $(shell $(LD) --gc-sections --version >/dev/null 2>&1; echo $$?) ifneq ($(NEW_LINKER),0) -checkbin: +checkbin: FORCE @echo '*** ${VERSION}.${PATCHLEVEL} kernels no longer build correctly with old versions of binutils.' @echo '*** Please upgrade your binutils to 2.9.5.' @false else -checkbin: +checkbin: FORCE @true endif +.PHONY: FORCE + # My testing targets (that short circuit a few dependencies) zImg:; @$(MAKEBOOT) zImage Img:; @$(MAKEBOOT) Image diff -urN orig/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile --- orig/arch/arm/boot/Makefile Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/boot/Makefile Fri Jun 13 22:19:08 2003 @@ -5,34 +5,42 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1995-2000 Russell King +# Copyright (C) 1995-2002 Russell King # SYSTEM =$(TOPDIR)/vmlinux +# Note: the following conditions must always be true: +# ZRELADDR == virt_to_phys(TEXTADDR) +# PARAMS_PHYS must be with 4MB of ZRELADDR +# INITRD_PHYS must be in RAM + ifeq ($(CONFIG_CPU_26),y) -ZTEXTADDR = 0x02080000 +ZRELADDR = 0x02080000 PARAMS_PHYS = 0x0207c000 INITRD_PHYS = 0x02180000 -INITRD_VIRT = 0x02180000 endif ifeq ($(CONFIG_ARCH_RPC),y) -ZTEXTADDR = 0x10008000 +ZRELADDR = 0x10008000 +PARAMS_PHYS = 0x10000100 +INITRD_PHYS = 0x18000000 +endif + +ifeq ($(CONFIG_ARCH_RISCSTATION),y) +ZRELADDR = 0x10008000 PARAMS_PHYS = 0x10000100 INITRD_PHYS = 0x18000000 -INITRD_VIRT = 0xc8000000 endif ifeq ($(CONFIG_ARCH_CLPS7500),y) -ZTEXTADDR = 0x10008000 +ZRELADDR = 0x10008000 endif ifeq ($(CONFIG_ARCH_EBSA110),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 PARAMS_PHYS = 0x00000400 INITRD_PHYS = 0x00800000 -INITRD_VIRT = 0xc0800000 endif ifeq ($(CONFIG_ARCH_SHARK),y) @@ -41,126 +49,114 @@ endif ifeq ($(CONFIG_FOOTBRIDGE),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 PARAMS_PHYS = 0x00000100 INITRD_PHYS = 0x00800000 -INITRD_VIRT = 0xc0800000 endif ifeq ($(CONFIG_ARCH_INTEGRATOR),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 PARAMS_PHYS = 0x00000100 INITRD_PHYS = 0x00800000 -INITRD_VIRT = 0xc0800000 +endif + +ifeq ($(CONFIG_ARCH_AT91RM9200),y) +ZRELADDR = 0x20008000 endif ifeq ($(CONFIG_ARCH_MX1ADS),y) -ZTEXTADDR = 0x08008000 +ZRELADDR = 0x08008000 endif ifeq ($(CONFIG_ARCH_CAMELOT),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 endif ifeq ($(CONFIG_ARCH_NEXUSPCI),y) -ZTEXTADDR = 0x40008000 +ZRELADDR = 0x40008000 endif ifeq ($(CONFIG_ARCH_L7200),y) -# RAM based kernel -#ZTEXTADDR = 0xf0400000 -#ZRELADDR = 0xf0008000 - -# FLASH based kernel -ZTEXTADDR = 0x00010000 ZRELADDR = 0xf0008000 -ZBSSADDR = 0xf03e0000 endif # The standard locations for stuff on CLPS711x type processors ifeq ($(CONFIG_ARCH_CLPS711X),y) -ZTEXTADDR = 0xc0028000 +ZRELADDR = 0xc0028000 PARAMS_PHYS = 0xc0000100 endif # Should probably have some agreement on these... ifeq ($(CONFIG_ARCH_P720T),y) INITRD_PHYS = 0xc0400000 -INITRD_VIRT = 0xc0400000 endif ifeq ($(CONFIG_ARCH_CDB89712),y) INITRD_PHYS = 0x00700000 -INITRD_VIRT = 0xc0300000 +endif + +ifeq ($(CONFIG_ARCH_OMAHA),y) +ZTEXTADDR = 0x0c008000 +PARAMS_PHYS = 0x0C000100 +INITRD_PHYS = 0x0C800000 +INITRD_VIRT = 0x0C800000 endif ifeq ($(CONFIG_ARCH_SA1100),y) -ZTEXTADDR = 0xc0008000 ZRELADDR = 0xc0008000 -ifeq ($(CONFIG_SA1100_VICTOR),y) - ZTEXTADDR = 0x00002000 - ZBSSADDR = 0xc0200000 -endif -ifeq ($(CONFIG_SA1100_SHERMAN),y) - ZTEXTADDR = 0x00050000 - ZBSSADDR = 0xc0200000 -endif -ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) - ZTEXTADDR = 0xC0200000 -endif -ifeq ($(CONFIG_SA1100_GRAPHICSMASTER),y) - ZTEXTADDR = 0xC0400000 -endif -ifeq ($(CONFIG_SA1100_ADSBITSY),y) - ZTEXTADDR = 0xC0400000 -endif -ifeq ($(CONFIG_SA1100_YOPY),y) - ZTEXTADDR = 0x00080000 - ZBSSADDR = 0xc0200000 -endif +# No defconfig file to move this into... +#ifeq ($(CONFIG_SA1100_YOPY),y) +# ZTEXTADDR = 0x00080000 +# ZBSSADDR = 0xc0200000 +#endif ifeq ($(CONFIG_SA1111),y) ZRELADDR = 0xc0208000 endif endif ifeq ($(CONFIG_ARCH_ANAKIN),y) -ZTEXTADDR = 0x20008000 +ZRELADDR = 0x20008000 endif # -# If you don't define ZRELADDR above, -# then it defaults to ZTEXTADDR +# We now have a PIC decompressor implementation. Decompressors running +# from RAM should not define ZTEXTADDR. Decompressors running directly +# from ROM or Flash must define ZTEXTADDR (preferably via the config) # -ifeq ($(ZRELADDR),) -ZRELADDR = $(ZTEXTADDR) +ifeq ($(CONFIG_ZBOOT_ROM),y) +ZTEXTADDR =0x$(CONFIG_ZBOOT_ROM_TEXT) +ZBSSADDR =0x$(CONFIG_ZBOOT_ROM_BSS) +else +ZTEXTADDR =0 +ZBSSADDR =ALIGN(4) endif -export SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS INITRD_VIRT PARAMS_PHYS +export SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS -Image: $(CONFIGURE) $(SYSTEM) - $(OBJCOPY) -O binary -R .note -R .comment -S $(SYSTEM) $@ +Image: $(SYSTEM) + $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ bzImage: zImage -zImage: $(CONFIGURE) compressed/vmlinux - $(OBJCOPY) -O binary -R .note -R .comment -S compressed/vmlinux $@ +zImage: compressed/vmlinux + $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ bootpImage: bootp/bootp - $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ + $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ -compressed/vmlinux: $(TOPDIR)/vmlinux dep +compressed/vmlinux: $(TOPDIR)/vmlinux FORCE @$(MAKE) -C compressed vmlinux -bootp/bootp: zImage initrd +bootp/bootp: zImage initrd FORCE @$(MAKE) -C bootp bootp initrd: - @test "$(INITRD_VIRT)" != "" || (echo This architecture does not support INITRD; exit -1) + @test "$(INITRD_PHYS)" != "" || (echo This machine does not support INITRD; exit -1) @test "$(INITRD)" != "" || (echo You must specify INITRD; exit -1) -install: $(CONFIGURE) Image +install: Image sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" -zinstall: $(CONFIGURE) zImage +zinstall: zImage sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" clean: @@ -169,3 +165,5 @@ @$(MAKE) -C bootp clean dep: + +FORCE: diff -urN orig/arch/arm/boot/bootp/Makefile linux/arch/arm/boot/bootp/Makefile --- orig/arch/arm/boot/bootp/Makefile Fri Oct 26 16:45:49 2001 +++ linux/arch/arm/boot/bootp/Makefile Thu Sep 5 22:59:42 2002 @@ -5,9 +5,7 @@ ZSYSTEM =$(TOPDIR)/arch/arm/boot/zImage ZLDFLAGS =-p -X -T bootp.lds \ --defsym initrd_addr=$(INITRD_PHYS) \ - --defsym initrd_virt=$(INITRD_VIRT) \ - --defsym params=$(PARAMS_PHYS) \ - --defsym kernel_addr=$(ZTEXTADDR) + --defsym params=$(PARAMS_PHYS) all: bootp diff -urN orig/arch/arm/boot/bootp/bootp.lds linux/arch/arm/boot/bootp/bootp.lds --- orig/arch/arm/boot/bootp/bootp.lds Tue Oct 3 20:08:18 2000 +++ linux/arch/arm/boot/bootp/bootp.lds Thu Sep 5 22:58:17 2002 @@ -1,7 +1,7 @@ /* * linux/arch/arm/boot/bootp/bootp.lds * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,13 +15,9 @@ _text = .; .text : { _stext = .; - _start = .; - init.o(.start) - kernel_start = .; + *(.start) kernel.o - kernel_len = . - kernel_start; . = ALIGN(32); - *(.text) initrd_start = .; initrd.o initrd_len = . - initrd_start; diff -urN orig/arch/arm/boot/bootp/init.S linux/arch/arm/boot/bootp/init.S --- orig/arch/arm/boot/bootp/init.S Fri Oct 26 16:45:49 2001 +++ linux/arch/arm/boot/bootp/init.S Fri Jun 13 22:13:47 2003 @@ -1,7 +1,7 @@ /* * linux/arch/arm/boot/bootp/init.S * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,8 +11,9 @@ * r0 through to r3 straight through. */ .section .start,#alloc,#execinstr - .type _entry, #function -_entry: adr r10, initdata + .type _start, #function + .globl _start +_start: adr r10, initdata ldr r11, initdata sub r11, r10, r11 @ work out exec offset b splitify @@ -22,17 +23,11 @@ initdata: .word initdata @ compiled address of this .size initdata,. - initdata - .text splitify: adr r13, data ldmia r13!, {r4-r6} @ move the initrd add r4, r4, r11 @ correction bl move - ldmia r13!, {r4-r6} @ then the kernel - mov r12, r5 - add r4, r4, r11 @ correction - bl move - /* * Setup the initrd parameters to pass to the kernel. This can either be * passed in via a param_struct or a tag list. We spot the param_struct @@ -52,17 +47,16 @@ ldr r9, [r8, #4] @ get first tag teq r9, r4 - bne taglist @ ok, we have a tag list + beq taglist @ ok, we have a tag list /* * We didn't find a valid tag list - create one. */ str r4, [r8, #4] - mov r4, #8 + mov r4, #(8 >> 2) str r4, [r8, #0] mov r4, #0 str r4, [r8, #8] - /* * find the end of the tag list, and then add an INITRD tag on the end. * If there is already an INITRD tag, then we ignore it; the last INITRD @@ -70,12 +64,12 @@ */ taglist: ldr r9, [r8, #0] @ tag length teq r9, #0 @ last tag? - addne r8, r8, r9 + addne r8, r8, r9, lsl #2 bne taglist - - mov r4, #16 @ length of initrd tag + mov r4, #(16 >> 2) @ length of initrd tag mov r9, #0 @ end of tag list terminator stmia r8, {r4, r5, r6, r7, r9} + adr r12, kernel_start mov pc, r12 @ call kernel /* @@ -83,6 +77,7 @@ */ param_struct: add r8, r8, #16*4 stmia r8, {r6,r7} @ save in param_struct + adr r12, kernel_start mov pc, r12 @ call kernel move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time @@ -97,15 +92,12 @@ .word initrd_addr .word initrd_len - .word kernel_start - .word kernel_addr - .word kernel_len - .word 0x54410001 @ r4 = ATAG_CORE - .word 0x54410005 @ r5 = ATAG_INITRD - .word initrd_virt @ r6 + .word 0x54420005 @ r5 = ATAG_INITRD + .word initrd_addr @ r6 .word initrd_len @ r7 .word params @ r8 - .type kernel_start,#object .type initrd_start,#object + +kernel_start: diff -urN orig/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile --- orig/arch/arm/boot/compressed/Makefile Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/boot/compressed/Makefile Fri Jun 13 22:19:08 2003 @@ -9,7 +9,7 @@ HEAD = head.o OBJS = misc.o -CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_BOOT) +CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_BOOT) -fpic -Uarm FONTC = $(TOPDIR)/drivers/video/font_acorn_8x8.c ZLDFLAGS = -p -X -T vmlinux.lds @@ -18,7 +18,12 @@ # ifeq ($(CONFIG_ARCH_ACORN),y) OBJS += ll_char_wr.o font.o -ZLDFLAGS += -defsym params=$(PARAMS_PHYS) +CFLAGS += -DPARAMS_PHYS=$(PARAMS_PHYS) +endif + +ifeq ($(CONFIG_ARCH_RISCSTATION),y) +OBJS += ll_char_wr.o font.o +CFLAGS += -DPARAMS_PHYS=$(PARAMS_PHYS) endif ifeq ($(CONFIG_ARCH_NETWINDER),y) @@ -33,6 +38,10 @@ OBJS += head-integrator.o endif +ifeq ($(CONFIG_ARCH_AT91RM9200),y) +OBJS += head-at91rm9200.o +endif + ifeq ($(CONFIG_ARCH_MX1ADS),y) OBJS += head-mx1ads.o endif @@ -60,18 +69,9 @@ ifeq ($(CONFIG_ARCH_SA1100),y) OBJS += head-sa1100.o -ifeq ($(CONFIG_SA1100_NANOENGINE),y) - OBJS += hw-bse.o -endif endif -SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/; - -ifneq ($(ZBSSADDR),) -SEDFLAGS += s/BSS_START/$(ZBSSADDR)/ -else -SEDFLAGS += s/BSS_START/ALIGN(4)/ -endif +SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/ LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) @@ -80,11 +80,14 @@ vmlinux: $(HEAD) $(OBJS) piggy.o vmlinux.lds $(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(LIBGCC) -o vmlinux -$(HEAD): $(HEAD:.o=.S) +$(HEAD): $(HEAD:.o=.S) \ + $(wildcard $(TOPDIR)/include/config/zboot/rom.h) \ + $(wildcard $(TOPDIR)/include/config/cpu/32.h) \ + $(wildcard $(TOPDIR)/include/config/cpu/26.h) $(CC) $(AFLAGS) -traditional -c $(HEAD:.o=.S) piggy.o: $(SYSTEM) - $(OBJCOPY) -O binary -R .note -R .comment -S $(SYSTEM) piggy + $(OBJCOPY) $(OBJCOPYFLAGS) $(SYSTEM) piggy gzip $(GZFLAGS) < piggy > piggy.gz $(LD) -r -o $@ -b binary piggy.gz rm -f piggy piggy.gz diff -urN orig/arch/arm/boot/compressed/head-at91rm9200.S linux/arch/arm/boot/compressed/head-at91rm9200.S --- orig/arch/arm/boot/compressed/head-at91rm9200.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/boot/compressed/head-at91rm9200.S Fri Jun 13 22:19:08 2003 @@ -0,0 +1,15 @@ +/* + * linux/arch/arm/boot/compressed/head-at91rm9200.S + * + * Copyright (C) 2003 SAN People + * + * 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 + + .section ".start", "ax" + mov r7, #MACH_TYPE_AT91RM9200 diff -urN orig/arch/arm/boot/compressed/head-clps7500.S linux/arch/arm/boot/compressed/head-clps7500.S --- orig/arch/arm/boot/compressed/head-clps7500.S Sat Apr 28 11:24:53 2001 +++ linux/arch/arm/boot/compressed/head-clps7500.S Sat May 18 14:11:39 2002 @@ -13,7 +13,7 @@ /* This branch is taken if the CPU memory width matches the actual device in use. The default at power on is 16 bits so we must be prepared for a mismatch. */ - .section ".start", #alloc, #execinstr + .section ".start", "ax" 2: b 1f .word 0xffff diff -urN orig/arch/arm/boot/compressed/head-epxa10db.S linux/arch/arm/boot/compressed/head-epxa10db.S --- orig/arch/arm/boot/compressed/head-epxa10db.S Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/boot/compressed/head-epxa10db.S Sat May 18 14:11:47 2002 @@ -1,5 +1,5 @@ #include #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" mov r7, #MACH_TYPE_CAMELOT diff -urN orig/arch/arm/boot/compressed/head-ftvpci.S linux/arch/arm/boot/compressed/head-ftvpci.S --- orig/arch/arm/boot/compressed/head-ftvpci.S Thu Feb 22 11:24:58 2001 +++ linux/arch/arm/boot/compressed/head-ftvpci.S Sat May 18 14:11:56 2002 @@ -13,7 +13,7 @@ * 2 of the License, or (at your option) any later version. */ - .section ".start", #alloc, #execinstr + .section ".start", "ax" ftv_start: mcr p15, 0, r0, c7, c5, 0 @ flush I cache mrc p15, 0, r0, c1, c0 diff -urN orig/arch/arm/boot/compressed/head-integrator.S linux/arch/arm/boot/compressed/head-integrator.S --- orig/arch/arm/boot/compressed/head-integrator.S Wed Jul 4 19:53:31 2001 +++ linux/arch/arm/boot/compressed/head-integrator.S Sat May 18 14:12:03 2002 @@ -1,4 +1,4 @@ #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" mov r7, #MACH_TYPE_INTEGRATOR diff -urN orig/arch/arm/boot/compressed/head-l7200.S linux/arch/arm/boot/compressed/head-l7200.S --- orig/arch/arm/boot/compressed/head-l7200.S Thu Feb 22 11:24:58 2001 +++ linux/arch/arm/boot/compressed/head-l7200.S Sat May 18 14:12:45 2002 @@ -8,12 +8,13 @@ */ #include +#include #ifndef CONFIG_ARCH_L7200 #error What am I doing here... #endif - .section ".start", #alloc, #execinstr + .section ".start", "ax" __L7200_start: mov r0, #0x00100000 @ FLASH address of initrd @@ -26,4 +27,4 @@ ble 1b mov r8, #0 @ Zero it out - mov r7, #19 @ Set architecture ID + mov r7, #MACH_TYPE_L7200 @ Set architecture ID diff -urN orig/arch/arm/boot/compressed/head-netwinder.S linux/arch/arm/boot/compressed/head-netwinder.S --- orig/arch/arm/boot/compressed/head-netwinder.S Tue Oct 3 20:08:18 2000 +++ linux/arch/arm/boot/compressed/head-netwinder.S Thu Mar 20 15:00:46 2003 @@ -1,50 +1,13 @@ /* * linux/arch/arm/boot/compressed/head-netwinder.S * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define K(a,b,c) ((a) << 24 | (b) << 12 | (c)) + .section ".start", "ax" - .section ".start", #alloc, #execinstr - - /* - * check to see if we are running from the correct address. - * If not, we move ourselves in a two stage process. Firstly, - * we copy the start of the kernel (which includes this code) - * to 0x8000, and then jump to this code to continue with the - * rest (since this code will get overwritten). - */ - adr r2, 1f - ldmdb r2, {r9, r10} - and r3, r2, #0xc000 - teq r3, #0x8000 @ correctly located? - beq 2f @ skip this code - bic r3, r2, #0xc000 - orr r3, r3, #0x8000 - mov r0, r3 @ new address if '1' - mov r4, #64 @ number of bytes to copy - sub r5, r10, r9 @ total number of bytes to copy - b 1f - - .word _start - .word __bss_start - -1: - .rept 4 - ldmia r2!, {r6, r9, r10, r11} - stmia r3!, {r6, r9, r10, r11} - .endr - subs r4, r4, #64 - bcs 1b - movs r4, r5 @ remaining length - mov r5, #0 @ no more to copy - movne pc, r0 @ jump back to 1 (in the newly copied - @ code) - mov r7, #5 @ only here to fix NeTTroms which dont - mov r8, #2 << 24 @ scheduled for removal in 2.5.xx - orr r8, r8, #5 << 12 -2: +/* mov r7, #5*/ +/* mov r8, #0*/ diff -urN orig/arch/arm/boot/compressed/head-sa1100.S linux/arch/arm/boot/compressed/head-sa1100.S --- orig/arch/arm/boot/compressed/head-sa1100.S Fri Oct 26 16:45:49 2001 +++ linux/arch/arm/boot/compressed/head-sa1100.S Sat May 18 14:12:56 2002 @@ -11,7 +11,7 @@ #include #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" __SA1100_start: diff -urN orig/arch/arm/boot/compressed/head-shark.S linux/arch/arm/boot/compressed/head-shark.S --- orig/arch/arm/boot/compressed/head-shark.S Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/boot/compressed/head-shark.S Sat May 18 14:19:55 2002 @@ -16,7 +16,7 @@ #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" b __beginning @@ -38,7 +38,7 @@ adr r1, __ofw_data add r2, r1, #4 mov lr, pc - b SYMBOL_NAME(ofw_init) + b ofw_init mov r1, #0 adr r2, __mmu_off @ calculate physical address @@ -109,7 +109,7 @@ add sp, sp, #128 adr r0, __ofw_data mov lr, pc - b SYMBOL_NAME(create_params) + b create_params mov r8, #0 mov r7, #15 diff -urN orig/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S --- orig/arch/arm/boot/compressed/head.S Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/boot/compressed/head.S Fri Jun 13 22:19:08 2003 @@ -1,7 +1,7 @@ /* * linux/arch/arm/boot/compressed/head.S * - * Copyright (C) 1996-1999 Russell King + * Copyright (C) 1996-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,6 +19,13 @@ */ #ifdef DEBUG #if defined(CONFIG_DEBUG_DC21285_PORT) + .macro loadsp, rb + mov \rb, #0x42000000 + .endm + .macro writeb, rb + str \rb, [r3, #0x160] + .endm +#elif defined(CONFIG_FOOTBRIDGE) .macro loadsp, rb mov \rb, #0x7c000000 .endm @@ -40,6 +47,15 @@ .macro writeb, rb strb \rb, [r3, #0] .endm +#elif defined(CONFIG_ARCH_AT91RM9200) + .macro loadsp, rb + mov \rb, #0xFF000000 @ BASE_DBGU (we cannot use ldr \reg, =AT91_DBGU_BASE) + add \rb, \rb, #0x00FF0000 + add \rb, \rb, #0x0000F200 + .endm + .macro writeb, rb + strb \rb, [r3, #0x1C] @ DBGU_THR (Transmitter Holding Register) + .endm #elif defined(CONFIG_ARCH_SA1100) .macro loadsp, rb mov \rb, #0x80000000 @ physical base address @@ -50,6 +66,11 @@ # endif .endm .macro writeb, rb +/* + * "The ARM peripheral bus does not support byte or half-word operations. + * All reads and writes of the UART by the CPU should be wordwide." + * - SA-1100 Developer's Manual, August 1999 + */ str \rb, [r3, #0x14] @ UTDR .endm #else @@ -144,33 +165,98 @@ */ .text -1: adr r2, LC0 - ldmia r2, {r2, r3, r4, r5, sp} + adr r0, LC0 + ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} + subs r0, r0, r1 @ calculate the delta offset + + teq r0, #0 @ if delta is zero, we're + beq not_relocated @ running at the address we + @ were linked at. - mov r0, #0 + /* + * We're running at a different address. We need to fix + * up various pointers: + * r5 - zImage base address + * r6 - GOT start + * ip - GOT end + */ + add r5, r5, r0 + add r6, r6, r0 + add ip, ip, r0 + +#ifndef CONFIG_ZBOOT_ROM + /* + * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, + * we need to fix up pointers into the BSS region. + * r2 - BSS start + * r3 - BSS end + * sp - stack pointer + */ + add r2, r2, r0 + add r3, r3, r0 + add sp, sp, r0 + + /* + * Relocate all entries in the GOT table. + */ +1: ldr r1, [r6, #0] + add r1, r1, r0 + str r1, [r6], #4 + cmp r6, ip + blo 1b +#else + + /* + * Relocate entries in the GOT table. We only relocate + * the entries that are outside the (relocated) BSS region. + */ +1: ldr r1, [r6, #0] + cmp r1, r2 @ entry < bss_start || + cmphs r3, r1 @ _end < entry + addlo r1, r1, r0 + str r1, [r6], #4 + cmp r6, ip + blo 1b + +#endif + +not_relocated: mov r0, #0 1: str r0, [r2], #4 @ clear bss str r0, [r2], #4 str r0, [r2], #4 str r0, [r2], #4 cmp r2, r3 - blt 1b + blo 1b - mrc p15, 0, r6, c0, c0 @ get processor ID + /* + * The C runtime environment should now be setup + * sufficiently. Turn the cache on, set up some + * pointers, and start decompressing. + */ bl cache_on mov r1, sp @ malloc space above stack add r2, sp, #0x10000 @ 64k max - teq r4, r5 @ will we overwrite ourselves? - moveq r5, r2 @ decompress after image - movne r5, r4 @ decompress to final location +/* + * Check to see if we will overwrite ourselves. + * r4 = final kernel address + * r5 = start of this image + * r2 = end of malloc space (and therefore this image) + * We basically want: + * r4 >= r2 -> OK + * r4 + image length <= r5 -> OK + */ + cmp r4, r2 + bhs wont_overwrite + add r0, r4, #4096*1024 @ 4MB largest kernel size + cmp r0, r5 + bls wont_overwrite + mov r5, r2 @ decompress after malloc space mov r0, r5 mov r3, r7 - bl SYMBOL_NAME(decompress_kernel) - - teq r4, r5 @ do we need to relocate - beq call_kernel @ the kernel? + bl decompress_kernel add r0, r0, #127 bic r0, r0, #127 @ align the kernel length @@ -185,23 +271,39 @@ */ add r1, r5, r0 @ end of decompressed kernel adr r2, reloc_start - adr r3, reloc_end + ldr r3, LC1 + add r3, r2, r3 1: ldmia r2!, {r8 - r13} @ copy relocation code stmia r1!, {r8 - r13} ldmia r2!, {r8 - r13} stmia r1!, {r8 - r13} cmp r2, r3 - blt 1b + blo 1b bl cache_clean_flush add pc, r5, r0 @ call relocation code +/* + * We're not in danger of overwriting ourselves. Do this the simple way. + * + * r4 = kernel execution address + * r7 = architecture ID + */ +wont_overwrite: mov r0, r4 + mov r3, r7 + bl decompress_kernel + b call_kernel + .type LC0, #object -LC0: .word __bss_start - .word _end - .word _load_addr - .word _start - .word user_stack+4096 +LC0: .word LC0 @ r1 + .word __bss_start @ r2 + .word _end @ r3 + .word _load_addr @ r4 + .word _start @ r5 + .word _got_start @ r6 + .word _got_end @ ip + .word user_stack+4096 @ sp +LC1: .word reloc_end - reloc_start .size LC0, . - LC0 /* @@ -218,22 +320,15 @@ * r7 = architecture number * r8 = run-time address of "start" * On exit, - * r0, r1, r2, r3, r8, r9 corrupted + * r1, r2, r3, r8, r9, r12 corrupted * This routine must preserve: * r4, r5, r6, r7 */ .align 5 -cache_on: ldr r1, proc_sa110_type - eor r1, r1, r6 - movs r1, r1, lsr #5 @ catch SA110 and SA1100 - beq 1f - ldr r1, proc_sa1110_type - eor r1, r1, r6 - movs r1, r1, lsr #4 -@ movne pc, lr - bne cache_off -1: - sub r3, r4, #16384 @ Page directory size +cache_on: mov r3, #8 @ cache_on function + b call_cache_fn + +__setup_mmu: sub r3, r4, #16384 @ Page directory size bic r3, r3, #0xff @ Align the pointer bic r3, r3, #0x3f00 /* @@ -248,9 +343,9 @@ orr r1, r1, #3 << 10 add r2, r3, #16384 1: cmp r1, r8 @ if virt > start of RAM - orrge r1, r1, #0x0c @ set cacheable, bufferable + orrhs r1, r1, #0x0c @ set cacheable, bufferable cmp r1, r9 @ if virt > end of RAM - bicge r1, r1, #0x0c @ clear cacheable, bufferable + bichs r1, r1, #0x0c @ clear cacheable, bufferable str r1, [r0], #4 @ 1:1 mapping add r1, r1, #1048576 teq r0, r2 @@ -269,24 +364,42 @@ str r1, [r0], #4 add r1, r1, #1048576 str r1, [r0] + mov pc, lr +__armv4_cache_on: + mov r12, lr + bl __setup_mmu mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer - mcr p15, 0, r0, c8, c7 @ flush I,D TLBs - mcr p15, 0, r3, c2, c0 @ load page table pointer + mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs + mcr p15, 0, r3, c2, c0, 0 @ load page table pointer mov r0, #-1 - mcr p15, 0, r0, c3, c0 @ load domain access register - mrc p15, 0, r0, c1, c0 + mcr p15, 0, r0, c3, c0, 0 @ load domain access register + mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #0x1000 @ I-cache enable #ifndef DEBUG orr r0, r0, #0x003d @ Write buffer, mmu #endif - mcr p15, 0, r0, c1, c0 - mov pc, lr + mcr p15, 0, r0, c1, c0, 0 + mov pc, r12 + +__arm6_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, #0x3d + mcr p15, 0, r0, c1, c0, 0 @ load control register + mov pc, r12 /* - * This code is relocatable. It is relocated by the above code to the end - * of the kernel and executed there. During this time, we have no stacks. + * All code following this line is relocatable. It is relocated by + * the above code to the end of the decompressed kernel image and + * executed there. During this time, we have no stacks. * * r0 = decompressed kernel length * r1-r3 = unused @@ -307,7 +420,7 @@ .endr cmp r5, r8 - blt 1b + blo 1b debug_reloc_end call_kernel: bl cache_clean_flush @@ -317,47 +430,117 @@ mov pc, r4 @ call kernel /* - * Here follow the relocatable cache support functions for - * the various processors. + * Here follow the relocatable cache support functions for the + * various processors. This is a generic hook for locating an + * entry and jumping to an instruction at the specified offset + * from the start of the block. Please note this is all position + * independent code. + * + * r1 = corrupted + * r2 = corrupted + * r3 = block offset + * r6 = corrupted + * r12 = corrupted */ - .type proc_sa110_type,#object -proc_sa110_type: - .word 0x4401a100 - .size proc_sa110_type, . - proc_sa110_type - - .type proc_sa1110_type,#object -proc_sa1110_type: - .word 0x6901b110 - .size proc_sa1110_type, . - proc_sa1110_type +call_cache_fn: adr r12, proc_types + mrc p15, 0, r6, c0, c0 @ get processor ID +1: ldr r1, [r12, #0] @ get value + ldr r2, [r12, #4] @ get mask + eor r1, r1, r6 @ (real ^ match) + tst r1, r2 @ & mask + addeq pc, r12, r3 @ call cache function + add r12, r12, #4*5 + b 1b + +/* + * Table for cache operations. This is basically: + * - CPU ID match + * - CPU ID mask + * - 'cache on' method instruction + * - 'cache off' method instruction + * - 'cache flush' method instruction + * + * We match an entry using: ((real_id ^ match) & mask) == 0 + * + * Writethrough caches generally only need 'on' and 'off' + * methods. Writeback caches _must_ have the flush method + * defined. + */ + .type proc_types,#object +proc_types: + .word 0x41560600 @ ARM6/610 + .word 0xffffffe0 + b __arm6_cache_off @ works, but slow + b __arm6_cache_off + mov pc, lr +@ b __arm6_cache_on @ untested +@ b __arm6_cache_off +@ b __armv3_cache_flush + + .word 0x41007000 @ ARM7/710 + .word 0xfff8fe00 + b __arm7_cache_off + b __arm7_cache_off + mov pc, lr + + .word 0x41807200 @ ARM720T (writethrough) + .word 0xffffff00 + b __armv4_cache_on + b __armv4_cache_off + mov pc, lr + + .word 0x41129200 @ ARM920T + .word 0xff00fff0 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x41029220 @ ARM922T + .word 0xff00fff0 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x4401a100 @ sa110 / sa1100 + .word 0xffffffe0 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x6901b110 @ sa1110 + .word 0xfffffff0 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x69050000 @ xscale + .word 0xffff0000 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0 @ unrecognised type + .word 0 + mov pc, lr + mov pc, lr + mov pc, lr + + .size proc_types, . - proc_types /* * Turn off the Cache and MMU. ARMv3 does not support * reading the control register, but ARMv4 does. * * On entry, r6 = processor ID - * On exit, r0, r1 corrupted + * On exit, r0, r1, r2, r3, r12 corrupted * This routine must preserve: r4, r6, r7 */ .align 5 -cache_off: -#ifdef CONFIG_CPU_ARM610 - eor r1, r6, #0x41000000 - eor r1, r1, #0x00560000 - bic r1, r1, #0x0000001f - teq r1, #0x00000600 - mov r0, #0x00000060 @ ARM6 control reg. - beq __armv3_cache_off -#endif -#ifdef CONFIG_CPU_ARM710 - eor r1, r6, #0x41000000 - bic r1, r1, #0x00070000 - bic r1, r1, #0x000000ff - teq r1, #0x00007000 @ ARM7 - teqne r1, #0x00007100 @ ARM710 - mov r0, #0x00000070 @ ARM7 control reg. - beq __armv3_cache_off -#endif +cache_off: mov r3, #12 @ cache_off function + b call_cache_fn + +__armv4_cache_off: mrc p15, 0, r0, c1, c0 bic r0, r0, #0x000d mcr p15, 0, r0, c1, c0 @ turn MMU and cache off @@ -366,11 +549,19 @@ mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 mov pc, lr +__arm6_cache_off: + mov r0, #0x00000030 @ ARM6 control reg. + b __armv3_cache_off + +__arm7_cache_off: + mov r0, #0x00000070 @ ARM7 control reg. + b __armv3_cache_off + __armv3_cache_off: - mcr p15, 0, r0, c1, c0 @ turn MMU and cache off + mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off mov r0, #0 - mcr p15, 0, r0, c7, c0 @ invalidate whole cache v3 - mcr p15, 0, r0, c5, c0 @ invalidate whole TLB v3 + mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 + mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 mov pc, lr /* @@ -379,23 +570,18 @@ * On entry, * r6 = processor ID * On exit, - * r1, r2, r12 corrupted + * r1, r2, r3, r12 corrupted * This routine must preserve: - * r4, r6, r7 + * r0, r4, r5, r6, r7 */ .align 5 cache_clean_flush: - ldr r1, proc_sa110_type - eor r1, r1, r6 - movs r1, r1, lsr #5 @ catch SA110 and SA1100 - beq 1f - ldr r1, proc_sa1110_type - eor r1, r1, r6 - movs r1, r1, lsr #4 - movne pc, lr -1: + mov r3, #16 + b call_cache_fn + +__armv4_cache_flush: bic r1, pc, #31 - add r2, r1, #32768 + add r2, r1, #65536 @ 2x the largest dcache size 1: ldr r12, [r1], #32 @ s/w flush D cache teq r1, r2 bne 1b @@ -404,6 +590,11 @@ mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr +__armv3_cache_flush: + mov r1, #0 + mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 + mov pc, lr + /* * Various debugging routines for printing hex characters and * memory, which again must be relocatable. @@ -479,5 +670,5 @@ reloc_end: .align - .section ".stack" + .section ".stack", "w" user_stack: .space 4096 diff -urN orig/arch/arm/boot/compressed/hw-bse.c linux/arch/arm/boot/compressed/hw-bse.c --- orig/arch/arm/boot/compressed/hw-bse.c Sat Aug 26 19:55:39 2000 +++ linux/arch/arm/boot/compressed/hw-bse.c Thu Jan 1 01:00:00 1970 @@ -1,74 +0,0 @@ -/* - * Bright Star Engineering Inc. - * - * code for readng parameters from the - * parameter blocks of the boot block - * flash memory - * - */ - -static int strcmp(const char *s1, const char *s2) -{ - while (*s1 != '\0' && *s1 == *s2) - { - s1++; - s2++; - } - - return (*(unsigned char *) s1) - (*(unsigned char *) s2); -} - -struct pblk_t { - char type; - unsigned short size; -}; - -static char *bse_getflashparam(char *name) { - unsigned int esize; - char *q,*r; - unsigned char *p,*e; - struct pblk_t *thepb = (struct pblk_t *) 0x00004000; - struct pblk_t *altpb = (struct pblk_t *) 0x00006000; - if (thepb->type&1) { - if (altpb->type&1) { - /* no valid param block */ - return (char*)0; - } else { - /* altpb is valid */ - struct pblk_t *tmp; - tmp = thepb; - thepb = altpb; - altpb = tmp; - } - } - p = (char*)thepb + sizeof(struct pblk_t); - e = p + thepb->size; - while (p < e) { - q = p; - esize = *p; - if (esize == 0xFF) break; - if (esize == 0) break; - if (esize > 127) { - esize = (esize&0x7F)<<8 | p[1]; - q++; - } - q++; - r=q; - if (*r && ((name == 0) || (!strcmp(name,r)))) { - while (*q++) ; - return q; - } - p+=esize; - } - return (char*)0; -} - -void bse_setup(void) { - /* extract the linux cmdline from flash */ - char *name=bse_getflashparam("linuxboot"); - char *x = (char *)0xc0000100; - if (name) { - while (*name) *x++=*name++; - } - *x=0; -} diff -urN orig/arch/arm/boot/compressed/ll_char_wr.S linux/arch/arm/boot/compressed/ll_char_wr.S --- orig/arch/arm/boot/compressed/ll_char_wr.S Sat Apr 28 11:24:53 2001 +++ linux/arch/arm/boot/compressed/ll_char_wr.S Wed Sep 11 23:17:36 2002 @@ -19,144 +19,116 @@ #include #include - .text + .text -#define BOLD 0x01 -#define ITALIC 0x02 -#define UNDERLINE 0x04 -#define FLASH 0x08 -#define INVERSE 0x10 - -LC0: .word SYMBOL_NAME(bytes_per_char_h) - .word SYMBOL_NAME(video_size_row) - .word SYMBOL_NAME(acorndata_8x8) - .word SYMBOL_NAME(con_charconvtable) +LC0: .word LC0 + .word bytes_per_char_h + .word video_size_row + .word acorndata_8x8 + .word con_charconvtable +/* + * r0 = ptr + * r1 = char + * r2 = white + */ ENTRY(ll_write_char) - stmfd sp!, {r4 - r7, lr} + stmfd sp!, {r4 - r7, lr} @ @ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc) @ - eor ip, r1, #UNDERLINE << 9 -/* - * calculate colours - */ - tst r1, #INVERSE << 9 - moveq r2, r1, lsr #16 - moveq r3, r1, lsr #24 - movne r2, r1, lsr #24 - movne r3, r1, lsr #16 - and r3, r3, #255 - and r2, r2, #255 -/* - * calculate offset into character table - */ - mov r1, r1, lsl #23 - mov r1, r1, lsr #20 -/* - * calculate offset required for each row [maybe I should make this an argument to this fn. - * Have to see what the register usage is like in the calling routines. - */ - adr r4, LC0 - ldmia r4, {r4, r5, r6, lr} - ldr r4, [r4] - ldr r5, [r5] -/* - * Go to resolution-dependent routine... - */ - cmp r4, #4 - blt Lrow1bpp - eor r2, r3, r2 @ Create eor mask to change colour from bg - orr r3, r3, r3, lsl #8 @ to fg. - orr r3, r3, r3, lsl #16 - add r0, r0, r5, lsl #3 @ Move to bottom of character - add r1, r1, #7 - ldrb r7, [r6, r1] - tst ip, #UNDERLINE << 9 - eoreq r7, r7, #255 - teq r4, #8 - beq Lrow8bpplp + /* + * calculate offset into character table + */ + mov r1, r1, lsl #3 + /* + * calculate offset required for each row. + */ + adr ip, LC0 + ldmia ip, {r3, r4, r5, r6, lr} + sub ip, ip, r3 + add r6, r6, ip + add lr, lr, ip + ldr r4, [r4, ip] + ldr r5, [r5, ip] + /* + * Go to resolution-dependent routine... + */ + cmp r4, #4 + blt Lrow1bpp + add r0, r0, r5, lsl #3 @ Move to bottom of character + orr r1, r1, #7 + ldrb r7, [r6, r1] + teq r4, #8 + beq Lrow8bpplp @ @ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) @ - orr r3, r3, r3, lsl #4 -Lrow4bpplp: ldr r7, [lr, r7, lsl #2] - mul r7, r2, r7 - tst r1, #7 @ avoid using r7 directly after - eor ip, r3, r7 - str ip, [r0, -r5]! - LOADREGS(eqfd, sp!, {r4 - r7, pc}) - sub r1, r1, #1 - ldrb r7, [r6, r1] - ldr r7, [lr, r7, lsl #2] - mul r7, r2, r7 - tst r1, #7 @ avoid using r7 directly after - eor ip, r3, r7 - str ip, [r0, -r5]! - subne r1, r1, #1 - ldrneb r7, [r6, r1] - bne Lrow4bpplp - LOADREGS(fd, sp!, {r4 - r7, pc}) +Lrow4bpplp: + ldr r7, [lr, r7, lsl #2] + mul r7, r2, r7 + sub r1, r1, #1 @ avoid using r7 directly after + str r7, [r0, -r5]! + ldrb r7, [r6, r1] + ldr r7, [lr, r7, lsl #2] + mul r7, r2, r7 + tst r1, #7 @ avoid using r7 directly after + str r7, [r0, -r5]! + subne r1, r1, #1 + ldrneb r7, [r6, r1] + bne Lrow4bpplp + LOADREGS(fd, sp!, {r4 - r7, pc}) @ @ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) @ -Lrow8bpplp: mov ip, r7, lsr #4 - ldr ip, [lr, ip, lsl #2] - mul r4, r2, ip - and ip, r7, #15 @ avoid r4 - ldr ip, [lr, ip, lsl #2] @ avoid r4 - mul ip, r2, ip @ avoid r4 - eor r4, r3, r4 @ avoid ip - tst r1, #7 @ avoid ip - sub r0, r0, r5 @ avoid ip - eor ip, r3, ip - stmia r0, {r4, ip} - LOADREGS(eqfd, sp!, {r4 - r7, pc}) - sub r1, r1, #1 - ldrb r7, [r6, r1] - mov ip, r7, lsr #4 - ldr ip, [lr, ip, lsl #2] - mul r4, r2, ip - and ip, r7, #15 @ avoid r4 - ldr ip, [lr, ip, lsl #2] @ avoid r4 - mul ip, r2, ip @ avoid r4 - eor r4, r3, r4 @ avoid ip - tst r1, #7 @ avoid ip - sub r0, r0, r5 @ avoid ip - eor ip, r3, ip - stmia r0, {r4, ip} - subne r1, r1, #1 - ldrneb r7, [r6, r1] - bne Lrow8bpplp - LOADREGS(fd, sp!, {r4 - r7, pc}) +Lrow8bpplp: + mov ip, r7, lsr #4 + ldr ip, [lr, ip, lsl #2] + mul r4, r2, ip + and ip, r7, #15 @ avoid r4 + ldr ip, [lr, ip, lsl #2] @ avoid r4 + mul ip, r2, ip @ avoid r4 + sub r1, r1, #1 @ avoid ip + sub r0, r0, r5 @ avoid ip + stmia r0, {r4, ip} + ldrb r7, [r6, r1] + mov ip, r7, lsr #4 + ldr ip, [lr, ip, lsl #2] + mul r4, r2, ip + and ip, r7, #15 @ avoid r4 + ldr ip, [lr, ip, lsl #2] @ avoid r4 + mul ip, r2, ip @ avoid r4 + tst r1, #7 @ avoid ip + sub r0, r0, r5 @ avoid ip + stmia r0, {r4, ip} + subne r1, r1, #1 + ldrneb r7, [r6, r1] + bne Lrow8bpplp + LOADREGS(fd, sp!, {r4 - r7, pc}) @ @ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc) @ -Lrow1bpp: add r6, r6, r1 - ldmia r6, {r4, r7} - tst ip, #INVERSE << 9 - mvnne r4, r4 - mvnne r7, r7 - strb r4, [r0], r5 - mov r4, r4, lsr #8 - strb r4, [r0], r5 - mov r4, r4, lsr #8 - strb r4, [r0], r5 - mov r4, r4, lsr #8 - strb r4, [r0], r5 - strb r7, [r0], r5 - mov r7, r7, lsr #8 - strb r7, [r0], r5 - mov r7, r7, lsr #8 - strb r7, [r0], r5 - mov r7, r7, lsr #8 - tst ip, #UNDERLINE << 9 - mvneq r7, r7 - strb r7, [r0], r5 - LOADREGS(fd, sp!, {r4 - r7, pc}) +Lrow1bpp: + add r6, r6, r1 + ldmia r6, {r4, r7} + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + LOADREGS(fd, sp!, {r4 - r7, pc}) - .bss + .bss ENTRY(con_charconvtable) - .space 1024 + .space 1024 diff -urN orig/arch/arm/boot/compressed/misc.c linux/arch/arm/boot/compressed/misc.c --- orig/arch/arm/boot/compressed/misc.c Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/boot/compressed/misc.c Thu Sep 5 22:57:20 2002 @@ -22,7 +22,6 @@ #include #include -#include #ifdef STANDALONE_DEBUG #define puts printf @@ -291,7 +290,6 @@ free_mem_ptr_end = free_mem_ptr_end_p; __machine_arch_type = arch_id; - proc_decomp_setup(); arch_decomp_setup(); makecrc(); @@ -315,4 +313,3 @@ return 0; } #endif - diff -urN orig/arch/arm/boot/compressed/vmlinux.lds.in linux/arch/arm/boot/compressed/vmlinux.lds.in --- orig/arch/arm/boot/compressed/vmlinux.lds.in Wed Jul 4 19:53:31 2001 +++ linux/arch/arm/boot/compressed/vmlinux.lds.in Sat May 18 14:08:17 2002 @@ -35,29 +35,26 @@ _etext = .; - .data : { - *(.data) - } - + _got_start = .; + .got : { *(.got) } + _got_end = .; + .got.plt : { *(.got.plt) } + .data : { *(.data) } _edata = .; . = BSS_START; __bss_start = .; - .bss : { - *(.bss) - } + .bss : { *(.bss) } _end = .; - .stack : { - *(.stack) - } - - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } + .stack (NOLOAD) : { *(.stack) } + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } } diff -urN orig/arch/arm/common/Makefile linux/arch/arm/common/Makefile --- orig/arch/arm/common/Makefile Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/common/Makefile Sun Jun 15 21:43:52 2003 @@ -0,0 +1,17 @@ +# +# Makefile for the linux kernel. +# + +O_TARGET := nopci.o + +export-objs := pcipool.o + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_USB_OHCI_SA1111) += pcipool.o +obj-$(CONFIG_USB_OHCI_AT91) += pcipool.o + +include $(TOPDIR)/Rules.make diff -urN orig/arch/arm/common/pcipool.c linux/arch/arm/common/pcipool.c --- orig/arch/arm/common/pcipool.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/common/pcipool.c Fri Jun 13 22:06:31 2003 @@ -0,0 +1,391 @@ +/* + NOTE: + + this code was lifted straight out of drivers/pci/pci.c; + when compiling for the Intel StrongARM SA-1110/SA-1111 the + usb-ohci.c driver needs these routines even when the architecture + has no pci bus... +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Pool allocator ... wraps the pci_alloc_consistent page allocator, so + * small blocks are easily used by drivers for bus mastering controllers. + * This should probably be sharing the guts of the slab allocator. + */ + +struct pci_pool { /* the pool */ + struct list_head page_list; + spinlock_t lock; + size_t blocks_per_page; + size_t size; + struct pci_dev *dev; + size_t allocation; + char name [32]; + wait_queue_head_t waitq; +}; + +struct pci_page { /* cacheable header for 'allocation' bytes */ + struct list_head page_list; + void *vaddr; + dma_addr_t dma; + unsigned long bitmap [0]; +}; + +#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) +#define POOL_POISON_BYTE 0xa7 + +// #define CONFIG_PCIPOOL_DEBUG + +static inline const char *slot_name(const struct pci_pool *pool) +{ + const struct pci_dev *pdev = pool->dev; + + if (pdev == 0) + return "[0]"; + + else if (dev_is_sa1111(pdev)) + return "[SA-1111]"; + else + return pdev->slot_name; +} + + +/** + * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma. + * @name: name of pool, for diagnostics + * @pdev: pci device that will be doing the DMA + * @size: size of the blocks in this pool. + * @align: alignment requirement for blocks; must be a power of two + * @allocation: returned blocks won't cross this boundary (or zero) + * @mem_flags: SLAB_* flags. + * + * Returns a pci allocation pool with the requested characteristics, or + * null if one can't be created. Given one of these pools, pci_pool_alloc() + * may be used to allocate memory. Such memory will all have "consistent" + * DMA mappings, accessible by the device and its driver without using + * cache flushing primitives. The actual size of blocks allocated may be + * larger than requested because of alignment. + * + * If allocation is nonzero, objects returned from pci_pool_alloc() won't + * cross that size boundary. This is useful for devices which have + * addressing restrictions on individual DMA transfers, such as not crossing + * boundaries of 4KBytes. + */ +struct pci_pool * +pci_pool_create (const char *name, struct pci_dev *pdev, + size_t size, size_t align, size_t allocation, int mem_flags) +{ + struct pci_pool *retval; + + if (align == 0) + align = 1; + if (size == 0) + return 0; + else if (size < align) + size = align; + else if ((size % align) != 0) { + size += align + 1; + size &= ~(align - 1); + } + + if (allocation == 0) { + if (PAGE_SIZE < size) + allocation = size; + else + allocation = PAGE_SIZE; + // FIXME: round up for less fragmentation + } else if (allocation < size) + return 0; + + if (!(retval = kmalloc (sizeof *retval, mem_flags))) + return retval; + + strncpy (retval->name, name, sizeof retval->name); + retval->name [sizeof retval->name - 1] = 0; + + retval->dev = pdev; + INIT_LIST_HEAD (&retval->page_list); + spin_lock_init (&retval->lock); + retval->size = size; + retval->allocation = allocation; + retval->blocks_per_page = allocation / size; + init_waitqueue_head (&retval->waitq); + +#ifdef CONFIG_PCIPOOL_DEBUG + printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n", + slot_name(retval), retval->name, size, + retval->blocks_per_page, allocation); +#endif + + return retval; +} + + +static struct pci_page * +pool_alloc_page (struct pci_pool *pool, int mem_flags) +{ + struct pci_page *page; + int mapsize; + + mapsize = pool->blocks_per_page; + mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG; + mapsize *= sizeof (long); + + page = (struct pci_page *) kmalloc (mapsize + sizeof *page, mem_flags); + if (!page) + return 0; + page->vaddr = pci_alloc_consistent (pool->dev, + pool->allocation, + &page->dma); + if (page->vaddr) { + memset (page->bitmap, 0xff, mapsize); // bit set == free +#ifdef CONFIG_DEBUG_SLAB + memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); +#endif + list_add (&page->page_list, &pool->page_list); + } else { + kfree (page); + page = 0; + } + return page; +} + + +static inline int +is_page_busy (int blocks, unsigned long *bitmap) +{ + while (blocks > 0) { + if (*bitmap++ != ~0UL) + return 1; + blocks -= BITS_PER_LONG; + } + return 0; +} + +static void +pool_free_page (struct pci_pool *pool, struct pci_page *page) +{ + dma_addr_t dma = page->dma; + +#ifdef CONFIG_DEBUG_SLAB + memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); +#endif + pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma); + list_del (&page->page_list); + kfree (page); +} + + +/** + * pci_pool_destroy - destroys a pool of pci memory blocks. + * @pool: pci pool that will be destroyed + * + * Caller guarantees that no more memory from the pool is in use, + * and that nothing will try to use the pool after this call. + */ +void +pci_pool_destroy (struct pci_pool *pool) +{ + unsigned long flags; + +#ifdef CONFIG_PCIPOOL_DEBUG + printk (KERN_DEBUG "pcipool destroy %s/%s\n", + slot_name(pool), pool->name); +#endif + + spin_lock_irqsave (&pool->lock, flags); + while (!list_empty (&pool->page_list)) { + struct pci_page *page; + page = list_entry (pool->page_list.next, + struct pci_page, page_list); + if (is_page_busy (pool->blocks_per_page, page->bitmap)) { + printk (KERN_ERR "pci_pool_destroy %s/%s, %p busy\n", + slot_name(pool), pool->name, page->vaddr); + /* leak the still-in-use consistent memory */ + list_del (&page->page_list); + kfree (page); + } else + pool_free_page (pool, page); + } + spin_unlock_irqrestore (&pool->lock, flags); + kfree (pool); +} + + +/** + * pci_pool_alloc - get a block of consistent memory + * @pool: pci pool that will produce the block + * @mem_flags: SLAB_KERNEL or SLAB_ATOMIC + * @handle: pointer to dma address of block + * + * This returns the kernel virtual address of a currently unused block, + * and reports its dma address through the handle. + * If such a memory block can't be allocated, null is returned. + */ +void * +pci_pool_alloc (struct pci_pool *pool, int mem_flags, dma_addr_t *handle) +{ + unsigned long flags; + struct list_head *entry; + struct pci_page *page; + int map, block; + size_t offset; + void *retval; + +restart: + spin_lock_irqsave (&pool->lock, flags); + list_for_each (entry, &pool->page_list) { + int i; + page = list_entry (entry, struct pci_page, page_list); + /* only cachable accesses here ... */ + for (map = 0, i = 0; + i < pool->blocks_per_page; + i += BITS_PER_LONG, map++) { + if (page->bitmap [map] == 0) + continue; + block = ffz (~ page->bitmap [map]); + if ((i + block) < pool->blocks_per_page) { + clear_bit (block, &page->bitmap [map]); + offset = (BITS_PER_LONG * map) + block; + offset *= pool->size; + goto ready; + } + } + } + if (!(page = pool_alloc_page (pool, mem_flags))) { + if (mem_flags == SLAB_KERNEL) { + DECLARE_WAITQUEUE (wait, current); + + current->state = TASK_INTERRUPTIBLE; + add_wait_queue (&pool->waitq, &wait); + spin_unlock_irqrestore (&pool->lock, flags); + + schedule_timeout (POOL_TIMEOUT_JIFFIES); + + current->state = TASK_RUNNING; + remove_wait_queue (&pool->waitq, &wait); + goto restart; + } + retval = 0; + goto done; + } + + clear_bit (0, &page->bitmap [0]); + offset = 0; +ready: + retval = offset + page->vaddr; + *handle = offset + page->dma; +done: + spin_unlock_irqrestore (&pool->lock, flags); + return retval; +} + + +static struct pci_page * +pool_find_page (struct pci_pool *pool, dma_addr_t dma) +{ + unsigned long flags; + struct list_head *entry; + struct pci_page *page; + + spin_lock_irqsave (&pool->lock, flags); + list_for_each (entry, &pool->page_list) { + page = list_entry (entry, struct pci_page, page_list); + if (dma < page->dma) + continue; + if (dma < (page->dma + pool->allocation)) + goto done; + } + page = 0; +done: + spin_unlock_irqrestore (&pool->lock, flags); + return page; +} + + +/** + * pci_pool_free - put block back into pci pool + * @pool: the pci pool holding the block + * @vaddr: virtual address of block + * @dma: dma address of block + * + * Caller promises neither device nor driver will again touch this block + * unless it is first re-allocated. + */ +void +pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma) +{ + struct pci_page *page; + unsigned long flags; + int map, block; + + if ((page = pool_find_page (pool, dma)) == 0) { + printk (KERN_ERR "pci_pool_free %s/%s, %p/%lx (bad dma)\n", + pool->dev ? pool->dev->slot_name : NULL, + pool->name, vaddr, (unsigned long) dma); + return; + } + + block = dma - page->dma; + block /= pool->size; + map = block / BITS_PER_LONG; + block %= BITS_PER_LONG; + +#ifdef CONFIG_DEBUG_SLAB + if (((dma - page->dma) + (void *)page->vaddr) != vaddr) { + printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n", + pool->dev ? pool->dev->slot_name : NULL, + pool->name, vaddr, (unsigned long) dma); + return; + } + if (page->bitmap [map] & (1UL << block)) { + printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n", + pool->dev ? pool->dev->slot_name : NULL, + pool->name, dma); + return; + } + memset (vaddr, POOL_POISON_BYTE, pool->size); +#endif + + spin_lock_irqsave (&pool->lock, flags); + set_bit (block, &page->bitmap [map]); + if (waitqueue_active (&pool->waitq)) + wake_up (&pool->waitq); + /* + * Resist a temptation to do + * if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page); + * it is not interrupt safe. Better have empty pages hang around. + */ + spin_unlock_irqrestore (&pool->lock, flags); +} + + +EXPORT_SYMBOL (pci_pool_create); +EXPORT_SYMBOL (pci_pool_destroy); +EXPORT_SYMBOL (pci_pool_alloc); +EXPORT_SYMBOL (pci_pool_free); + +/* **************************************** */ + +static int __init pcipool_init(void) +{ + MOD_INC_USE_COUNT; /* never unload */ + + return 0; +} +module_init(pcipool_init); + +MODULE_LICENSE("GPL"); diff -urN orig/arch/arm/config.in linux/arch/arm/config.in --- orig/arch/arm/config.in Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/config.in Tue Jun 24 11:36:31 2003 @@ -2,7 +2,7 @@ # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # -mainmenu_name "Linux Kernel Configuration" +mainmenu_name "ARM Linux Kernel Configuration" define_bool CONFIG_ARM y define_bool CONFIG_EISA n @@ -39,14 +39,17 @@ CLPS711x/EP721x-based CONFIG_ARCH_CLPS711X \ Co-EBSA285 CONFIG_ARCH_CO285 \ EBSA-110 CONFIG_ARCH_EBSA110 \ - Epxa10db CONFIG_ARCH_CAMELOT \ + Excalibur-ARM CONFIG_ARCH_CAMELOT \ FootBridge CONFIG_ARCH_FOOTBRIDGE \ Integrator CONFIG_ARCH_INTEGRATOR \ + Omaha CONFIG_ARCH_OMAHA \ LinkUp-L7200 CONFIG_ARCH_L7200 \ Motorola-MX1ADS CONFIG_ARCH_MX1ADS \ RiscPC CONFIG_ARCH_RPC \ - SA1100-based CONFIG_ARCH_SA1100 \ - Shark CONFIG_ARCH_SHARK" RiscPC + RiscStation CONFIG_ARCH_RISCSTATION \ + SA1100-based CONFIG_ARCH_SA1100 \ + Shark CONFIG_ARCH_SHARK \ + AT91RM9200-based CONFIG_ARCH_AT91RM9200 " RiscPC mainmenu_option next_comment comment 'Archimedes/A5000 Implementations' @@ -69,10 +72,14 @@ mainmenu_option next_comment comment 'SA11x0 Implementations' +dep_bool ' ACCELENT DevBoard' CONFIG_SA1100_ACCELENT $CONFIG_ARCH_SA1100 dep_bool ' Assabet' CONFIG_SA1100_ASSABET $CONFIG_ARCH_SA1100 dep_bool ' Include support for Neponset' CONFIG_ASSABET_NEPONSET $CONFIG_SA1100_ASSABET +dep_bool ' ADS Advanced Graphics Client' CONFIG_SA1100_ADSAGC $CONFIG_ARCH_SA1100 dep_bool ' ADS Bitsy' CONFIG_SA1100_ADSBITSY $CONFIG_ARCH_SA1100 +dep_bool ' ADS Bitsy Plus' CONFIG_SA1100_ADSBITSYPLUS $CONFIG_ARCH_SA1100 dep_bool ' Brutus' CONFIG_SA1100_BRUTUS $CONFIG_ARCH_SA1100 +dep_bool ' Cep' CONFIG_SA1100_CEP $CONFIG_ARCH_SA1100 dep_bool ' CerfBoard' CONFIG_SA1100_CERF $CONFIG_ARCH_SA1100 if [ "$CONFIG_SA1100_CERF" = "y" ]; then choice 'Cerf RAM available' \ @@ -94,6 +101,8 @@ else define_bool CONFIG_SA1100_H3XXX n fi +dep_tristate 'Compaq iPAQ Handheld sleeve support' CONFIG_H3600_SLEEVE $CONFIG_SA1100_H3600 +#dep_bool ' Consus' CONFIG_SA1100_CONSUS $CONFIG_ARCH_SA1100 #dep_bool ' Empeg' CONFIG_SA1100_EMPEG $CONFIG_ARCH_SA1100 dep_bool ' Extenex HandHeld Theater (Squashtail)' CONFIG_SA1100_EXTENEX1 $CONFIG_ARCH_SA1100 if [ "$CONFIG_SA1100_EXTENEX1" = "y" ]; then @@ -104,6 +113,7 @@ dep_bool ' Frodo' CONFIG_SA1100_FRODO $CONFIG_ARCH_SA1100 dep_bool ' GraphicsClient Plus' CONFIG_SA1100_GRAPHICSCLIENT $CONFIG_ARCH_SA1100 dep_bool ' GraphicsMaster' CONFIG_SA1100_GRAPHICSMASTER $CONFIG_ARCH_SA1100 +dep_bool ' HackKit Core Board' CONFIG_SA1100_HACKKIT $CONFIG_ARCH_SA1100 dep_bool ' HP Labs BadgePAD 4' CONFIG_SA1100_BADGE4 $CONFIG_ARCH_SA1100 dep_bool ' HP Jornada 720' CONFIG_SA1100_JORNADA720 $CONFIG_ARCH_SA1100 dep_bool ' HuW WebPanel' CONFIG_SA1100_HUW_WEBPANEL $CONFIG_ARCH_SA1100 @@ -117,29 +127,23 @@ dep_bool ' Shannon' CONFIG_SA1100_SHANNON $CONFIG_ARCH_SA1100 dep_bool ' Sherman' CONFIG_SA1100_SHERMAN $CONFIG_ARCH_SA1100 dep_bool ' Simpad' CONFIG_SA1100_SIMPAD $CONFIG_ARCH_SA1100 +dep_bool ' Simputer' CONFIG_SA1100_SIMPUTER $CONFIG_ARCH_SA1100 dep_bool ' Tulsa' CONFIG_SA1100_PFS168 $CONFIG_ARCH_SA1100 dep_bool ' Victor' CONFIG_SA1100_VICTOR $CONFIG_ARCH_SA1100 dep_bool ' XP860' CONFIG_SA1100_XP860 $CONFIG_ARCH_SA1100 dep_bool ' Yopy' CONFIG_SA1100_YOPY $CONFIG_ARCH_SA1100 -# Determine if SA1111 support is required -if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \ - "$CONFIG_SA1100_JORNADA720" = "y" -o \ - "$CONFIG_SA1100_PFS168" = "y" -o \ - "$CONFIG_SA1100_XP860" = "y" -o \ - "$CONFIG_SA1100_GRAPHICSMASTER" = "y" -o \ - "$CONFIG_SA1100_PT_SYSTEM3" = "y" -o \ - "$CONFIG_SA1100_ADSBITSY" = "y" -o \ - "$CONFIG_SA1100_BADGE4" = "y" ]; then - define_bool CONFIG_SA1111 y - define_int CONFIG_FORCE_MAX_ZONEORDER 9 -fi +dep_tristate 'SA1100 USB function support' CONFIG_SA1100_USB $CONFIG_ARCH_SA1100 +dep_tristate ' Support for SA11x0 USB network link function' CONFIG_SA1100_USB_NETLINK $CONFIG_SA1100_USB +dep_tristate ' Support for SA11x0 USB character device emulation' CONFIG_SA1100_USB_CHAR $CONFIG_SA1100_USB -#dep_tristate 'SA1100 USB function support' CONFIG_SA1100_USB $CONFIG_ARCH_SA1100 -#dep_tristate ' Support for SA11x0 USB network link function' CONFIG_SA1100_USB_NETLINK $CONFIG_SA1100_USB -#dep_tristate ' Support for SA11x0 USB character device emulation' CONFIG_SA1100_USB_CHAR $CONFIG_SA1100_USB +dep_tristate 'SA1100 Generic PIO SSP support' CONFIG_SA1100_SSP $CONFIG_ARCH_SA1100 -dep_tristate 'Compaq iPAQ Handheld sleeve support' CONFIG_H3600_SLEEVE $CONFIG_SA1100_H3600 +endmenu + +mainmenu_option next_comment +comment 'AT91RM9200 Implementations' +dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200 endmenu mainmenu_option next_comment @@ -148,8 +152,10 @@ dep_bool ' CDB89712' CONFIG_ARCH_CDB89712 $CONFIG_ARCH_CLPS711X dep_bool ' CLEP7312' CONFIG_ARCH_CLEP7312 $CONFIG_ARCH_CLPS711X dep_bool ' EDB7211' CONFIG_ARCH_EDB7211 $CONFIG_ARCH_CLPS711X -dep_bool ' P720T' CONFIG_ARCH_P720T $CONFIG_ARCH_CLPS711X dep_bool ' FORTUNET' CONFIG_ARCH_FORTUNET $CONFIG_ARCH_CLPS711X +dep_bool ' GUIDEA07' CONFIG_ARCH_GUIDEA07 $CONFIG_ARCH_CLPS711X +dep_bool ' P720T' CONFIG_ARCH_P720T $CONFIG_ARCH_CLPS711X + # XXX Maybe these should indicate register compatibility # instead of being mutually exclusive. @@ -168,6 +174,11 @@ "$CONFIG_ARCH_EP7212" = "y" ]; then bool ' EP72xx ROM boot' CONFIG_EP72XX_ROM_BOOT fi + +if [ "$CONFIG_ARCH_GUIDEA07" = "y" ]; then + define_bool CONFIG_ARCH_CDB89712 y +fi + endmenu # Definitions to make life easier @@ -178,7 +189,8 @@ define_bool CONFIG_ARCH_ACORN n fi -# see Documentation/arm/ConfigVars for a description of these +##################################################################### +# Footbridge support if [ "$CONFIG_ARCH_CO285" = "y" -o \ "$CONFIG_ARCH_FOOTBRIDGE" = "y" ]; then define_bool CONFIG_FOOTBRIDGE y @@ -204,6 +216,42 @@ define_bool CONFIG_ARCH_EBSA285 y fi +##################################################################### +# SA1111 support +if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \ + "$CONFIG_SA1100_ACCELENT" = "y" -o \ + "$CONFIG_SA1100_ADSAGC" = "y" -o \ + "$CONFIG_SA1100_ADSBITSY" = "y" -o \ + "$CONFIG_SA1100_ADSBITSYPLUS" = "y" -o \ + "$CONFIG_SA1100_BADGE4" = "y" -o \ + "$CONFIG_SA1100_CONSUS" = "y" -o \ + "$CONFIG_SA1100_GRAPHICSMASTER" = "y" -o \ + "$CONFIG_SA1100_JORNADA720" = "y" -o \ + "$CONFIG_SA1100_PFS168" = "y" -o \ + "$CONFIG_SA1100_PT_SYSTEM3" = "y" -o \ + "$CONFIG_SA1100_XP860" = "y" ]; then + define_bool CONFIG_SA1111 y + define_int CONFIG_FORCE_MAX_ZONEORDER 9 +fi + +if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then + choice 'EPXA system type' \ + "EPXA10DB CONFIG_EPXA10DB \ + EPXA1DB CONFIG_EPXA1DB" EPXA10DB + +if [ "$CONFIG_EPXA10DB" = "y" ]; then + choice 'EPXA10B version' \ + "SDR CONFIG_EPXA10DB_R2 \ + DDR CONFIG_EPXA10DB_R3" DDR +fi + + comment 'PLD hotswap support' + define_bool CONFIG_PLD y + dep_bool 'Support for PLD device hotplugging' CONFIG_PLD_HOTSWAP $CONFIG_EXPERIMENTAL +fi + +comment 'Processor Type' + # Figure out whether this system uses 26-bit or 32-bit CPUs. if [ "$CONFIG_ARCH_ARCA5K" = "y" ]; then define_bool CONFIG_CPU_32 n @@ -214,28 +262,9 @@ define_bool CONFIG_CPU_26 n fi -comment 'Processor Type' - -# Firstly, figure out what processor architecture version we should be using. -if [ "$CONFIG_ARCH_RPC" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then - define_bool CONFIG_CPU_32v3 y -else - define_bool CONFIG_CPU_32v3 n -fi -if [ "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_FOOTBRIDGE" = "y" -o \ - "$CONFIG_ARCH_TBOX" = "y" -o "$CONFIG_ARCH_SHARK" = "y" -o \ - "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_CLPS711X" = "y" -o \ - "$CONFIG_ARCH_INTEGRATOR" = "y" -o "$CONFIG_ARCH_SA1100" = "y" -o \ - "$CONFIG_ARCH_L7200" = "y" -o "$CONFIG_ARCH_ANAKIN" = "y" -o \ - "$CONFIG_ARCH_CAMELOT" = "y" -o "$CONFIG_ARCH_MX1ADS" = "y" ]; then - define_bool CONFIG_CPU_32v4 y -else - define_bool CONFIG_CPU_32v4 n -fi - -# Select CPU types depending on the architecture selected. -# We use this to select which CPUs are supported, and to select -# the compiler tuning options. +# Select CPU types depending on the architecture selected. This selects +# which CPUs we support in the kernel image, and the compiler instruction +# optimiser behaviour. # ARM610 if [ "$CONFIG_ARCH_RPC" = "y" ]; then @@ -245,7 +274,8 @@ fi # ARM710 -if [ "$CONFIG_ARCH_CLPS7500" = "y" ]; then +if [ "$CONFIG_ARCH_CLPS7500" = "y" -o \ + "$CONFIG_ARCH_RISCSTATION" = "y" ]; then define_bool CONFIG_CPU_ARM710 y else if [ "$CONFIG_ARCH_RPC" = "y" ]; then @@ -269,10 +299,12 @@ fi # ARM920T -if [ "$CONFIG_ARCH_MX1ADS" = "y" ]; then +if [ "$CONFIG_ARCH_MX1ADS" = "y" -o \ + "$CONFIG_ARCH_AT91RM9200" = "y" ]; then define_bool CONFIG_CPU_ARM920T y else - if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then + if [ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ + "$CONFIG_ARCH_OMAHA" = "y" ]; then bool 'Support ARM920T processor' CONFIG_CPU_ARM920T else define_bool CONFIG_CPU_ARM920T n @@ -280,28 +312,13 @@ fi -if [ "$CONFIG_CPU_ARM920T" = "y" ]; then - bool ' ARM920T CPU idle' CONFIG_CPU_ARM920_CPU_IDLE - bool ' ARM920T I-Cache on' CONFIG_CPU_ARM920_I_CACHE_ON - bool ' ARM920T D-Cache on' CONFIG_CPU_ARM920_D_CACHE_ON - if [ "$CONFIG_CPU_ARM920_D_CACHE_ON" = "y" ] ; then - bool ' Force write through caches on ARM920T' CONFIG_CPU_ARM920_WRITETHROUGH - fi -fi - # ARM922T if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then - define_bool CONFIG_CPU_ARM922T y + define_bool CONFIG_CPU_ARM922T y + define_bool CONFIG_PLD y else - define_bool CONFIG_CPU_ARM922T n -fi -if [ "$CONFIG_CPU_ARM922T" = "y" ]; then - bool ' ARM922T CPU idle' CONFIG_CPU_ARM922_CPU_IDLE - bool ' ARM922T I-Cache on' CONFIG_CPU_ARM922_I_CACHE_ON - bool ' ARM922T D-Cache on' CONFIG_CPU_ARM922_D_CACHE_ON - if [ "$CONFIG_CPU_ARM922_D_CACHE_ON" = "y" ] ; then - bool ' Force write through caches on ARM922T' CONFIG_CPU_ARM922_WRITETHROUGH - fi + define_bool CONFIG_CPU_ARM922T n + define_bool CONFIG_PLD n fi # ARM926T @@ -310,18 +327,6 @@ else define_bool CONFIG_CPU_ARM926T n fi -if [ "$CONFIG_CPU_ARM926T" = "y" ]; then - bool ' ARM926T CPU idle' CONFIG_CPU_ARM926_CPU_IDLE - bool ' ARM926T I-Cache on' CONFIG_CPU_ARM926_I_CACHE_ON - bool ' ARM926T D-Cache on' CONFIG_CPU_ARM926_D_CACHE_ON - if [ "$CONFIG_CPU_ARM926_D_CACHE_ON" = "y" ] ; then - bool ' Force write through caches on ARM926T' CONFIG_CPU_ARM926_WRITETHROUGH - fi - if [ "$CONFIG_CPU_ARM926_I_CACHE_ON" = "y" -o \ - "$CONFIG_CPU_ARM926_D_CACHE_ON" = "y" ]; then - bool ' Round robin I and D cache replacement algorithm' CONFIG_CPU_ARM926_ROUND_ROBIN - fi -fi # ARM1020 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then @@ -329,16 +334,12 @@ else define_bool CONFIG_CPU_ARM1020 n fi -if [ "$CONFIG_CPU_ARM1020" = "y" ]; then - bool ' ARM1020 I-Cache on' CONFIG_CPU_ARM1020_I_CACHE_ON - bool ' ARM10 D-Cache on' CONFIG_CPU_ARM1020_D_CACHE_ON - if [ "$CONFIG_CPU_ARM1020_D_CACHE_ON" = "y" ] ; then - bool ' Force write through caches on ARM1020' CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH - fi - if [ "$CONFIG_CPU_ARM1020_I_CACHE_ON" = "y" -o \ - "$CONFIG_CPU_ARM1020_D_CACHE_ON" = "y" ]; then - bool ' Round robin I and D cache replacement algorithm' CONFIG_CPU_ARM1020_ROUND_ROBIN - fi + +# ARM1026EJ-S +if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then + bool 'Support ARM1026EJ-S processor' CONFIG_CPU_ARM1026 +else + define_bool CONFIG_CPU_ARM1026 n fi # SA110 @@ -361,13 +362,59 @@ define_bool CONFIG_CPU_SA1100 n fi -if [ "$CONFIG_CPU_32" = "y" ]; then - dep_bool 'Support Thumb instructions (experimental)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL +# Figure out what processor architecture version we should be using. +# This defines the compiler instruction set which depends on the machine type. + +if [ "$CONFIG_ARCH_RPC" = "y" -o \ + "$CONFIG_ARCH_RISCSTATION" = "y" -o \ + "$CONFIG_ARCH_CLPS7500" = "y" ]; then + define_bool CONFIG_CPU_32v3 y +else + define_bool CONFIG_CPU_32v3 n +fi +if [ "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_FOOTBRIDGE" = "y" -o \ + "$CONFIG_ARCH_TBOX" = "y" -o "$CONFIG_ARCH_SHARK" = "y" -o \ + "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_CLPS711X" = "y" -o \ + "$CONFIG_ARCH_INTEGRATOR" = "y" -o "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_L7200" = "y" -o "$CONFIG_ARCH_ANAKIN" = "y" -o \ + "$CONFIG_ARCH_CAMELOT" = "y" -o "$CONFIG_ARCH_MX1ADS" = "y" -o \ + "$CONFIG_ARCH_OMAHA" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then + define_bool CONFIG_CPU_32v4 y +else + define_bool CONFIG_CPU_32v4 n +fi + +comment 'Processor Features' + +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 + 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_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 + 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_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 + 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_SA1100" = "y" ]; then + "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_RISCSTATION" = "y" ]; then define_bool CONFIG_DISCONTIGMEM y else define_bool CONFIG_DISCONTIGMEM n @@ -395,6 +442,7 @@ if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_CLPS7500" = "y" -o \ + "$CONFIG_ARCH_RISCSTATION" = "y" -o \ "$CONFIG_ARCH_EBSA110" = "y" -o \ "$CONFIG_ARCH_CDB89712" = "y" -o \ "$CONFIG_ARCH_EDB7211" = "y" -o \ @@ -411,6 +459,12 @@ define_bool CONFIG_ISA_DMA n fi +# Compressed boot loader in ROM. Yes, we really want to ask about +# TEXT and BSS so we preserve their values in the config files. +bool 'Compressed boot loader in ROM/flash' CONFIG_ZBOOT_ROM +hex 'Compressed ROM boot loader base address' CONFIG_ZBOOT_ROM_TEXT 0 +hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0 + if [ "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL @@ -423,13 +477,23 @@ else define_bool CONFIG_PCMCIA n fi +if [ "$CONFIG_SA1100_ACCELENT" = "y" ]; then + if [ "$CONFIG_PCMCIA" != "n" ]; then + bool ' Use second PCMCIA/CF slot (disables on-board IDE)' CONFIG_SA_PCMCIA_SLOT_1 y + fi +fi bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL comment 'At least one math emulation must be selected' tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE -dep_tristate 'FastFPE math emulation (experimental)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL +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 + dep_tristate 'FastFPE math emulation (EXPERIMENTAL)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL +fi choice 'Kernel core (/proc/kcore) format' \ "ELF CONFIG_KCORE_ELF \ A.OUT CONFIG_KCORE_AOUT" ELF @@ -438,19 +502,8 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32 +string 'Default kernel command string' CONFIG_CMDLINE "" -if [ "$CONFIG_ARCH_EBSA110" = "y" -o \ - "$CONFIG_ARCH_SA1100" = "y" -o \ - "$CONFIG_ARCH_CLPS7500" = "y" -o \ - "$CONFIG_ARCH_PERSONAL_SERVER" = "y" -o \ - "$CONFIG_ARCH_CATS" = "y" -o \ - "$CONFIG_ARCH_P720T" = "y" -o \ - "$CONFIG_ARCH_CDB89712" = "y" -o \ - "$CONFIG_ARCH_CAMELOT" = "y" -o \ - "$CONFIG_ARCH_ANAKIN" = "y" -o \ - "$CONFIG_ARCH_MX1ADS" = "y" ]; then - string 'Default kernel command string' CONFIG_CMDLINE "" -fi if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ "$CONFIG_ARCH_EBSA110" = "y" -o \ "$CONFIG_ARCH_EBSA285" = "y" -o \ @@ -460,7 +513,8 @@ "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ "$CONFIG_ARCH_CDB89712" = "y" -o \ - "$CONFIG_ARCH_P720T" = "y" ]; then + "$CONFIG_ARCH_P720T" = "y" -o \ + "$CONFIG_ARCH_OMAHA" = "y" ]; then bool 'Timer and CPU usage LEDs' CONFIG_LEDS if [ "$CONFIG_LEDS" = "y" ]; then if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ @@ -469,17 +523,24 @@ "$CONFIG_ARCH_CO285" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ - "$CONFIG_ARCH_P720T" = "y" ]; then + "$CONFIG_ARCH_P720T" = "y" -o \ + "$CONFIG_ARCH_OMAHA" = "y" ]; then bool ' Timer LED' CONFIG_LEDS_TIMER bool ' CPU usage LED' CONFIG_LEDS_CPU fi - fi - if [ "$CONFIG_ARCH_EBSA110" = "y" ]; then - define_bool CONFIG_LEDS_TIMER y + if [ "$CONFIG_ARCH_EBSA110" = "y" ]; then + define_bool CONFIG_LEDS_TIMER y + fi fi fi -if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then - bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then + define_bool CONFIG_ALIGNMENT_TRAP y +else + if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then + bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP + else + define_bool CONFIG_ALIGNMENT_TRAP n + fi fi endmenu @@ -487,6 +548,8 @@ if [ "$CONFIG_ALIGNMENT_TRAP" = "y" ]; then source drivers/mtd/Config.in +else + define_bool CONFIG_MTD n fi source drivers/pnp/Config.in @@ -515,9 +578,9 @@ fi mainmenu_option next_comment -comment 'ATA/IDE/MFM/RLL support' +comment 'ATA/ATAPI/MFM/RLL support' -tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE +tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE if [ "$CONFIG_IDE" != "n" ]; then source drivers/ide/Config.in @@ -538,7 +601,8 @@ endmenu if [ "$CONFIG_ARCH_CLPS711X" = "y" ]; then - source drivers/scsi/Config.in + # This is _meant_ to be ssi _not_ scsi. It is not a spelling error. + source drivers/ssi/Config.in fi source drivers/ieee1394/Config.in @@ -602,7 +666,7 @@ "$CONFIG_ARCH_MX1ADS" = "y" ]; then define_bool CONFIG_PC_KEYMAP y fi - if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then + if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_ARCH_RISCSTATION" != "y" ]; then bool 'VGA text console' CONFIG_VGA_CONSOLE fi source drivers/video/Config.in @@ -611,6 +675,7 @@ if [ "$CONFIG_ARCH_ACORN" = "y" -o \ "$CONFIG_ARCH_CLPS7500" = "y" -o \ + "$CONFIG_ARCH_RISCSTATION" = "y" -o \ "$CONFIG_ARCH_TBOX" = "y" -o \ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ @@ -618,7 +683,7 @@ mainmenu_option next_comment comment 'Sound' - tristate 'Sound card support' CONFIG_SOUND + tristate 'Sound support' CONFIG_SOUND if [ "$CONFIG_SOUND" != "n" ]; then source drivers/sound/Config.in fi @@ -629,7 +694,9 @@ source drivers/usb/Config.in -source net/bluetooth/Config.in +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + source net/bluetooth/Config.in +fi mainmenu_option next_comment comment 'Kernel hacking' @@ -638,7 +705,16 @@ # you know what you are doing and are willing to live without stack traces, you # can get a slightly smaller kernel by setting this option to n, but then RMK # will have to kill you ;). -define_bool CONFIG_FRAME_POINTER y +if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then + # + # Note: We want all the performance we can get, so this means + # we accept the debugging limitations of setting CONFIG_FRAME_POINTER=n + # -- ahaigh@arm.com (23 August 2002) + define_bool CONFIG_FRAME_POINTER n +else + define_bool CONFIG_FRAME_POINTER y +fi + bool 'Verbose user fault messages' CONFIG_DEBUG_USER bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO dep_bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE $CONFIG_CPU_26 @@ -650,10 +726,11 @@ dep_bool ' Wait queue debugging' CONFIG_DEBUG_WAITQ $CONFIG_DEBUG_KERNEL dep_bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE $CONFIG_DEBUG_KERNEL dep_bool ' Verbose kernel error messages' CONFIG_DEBUG_ERRORS $CONFIG_DEBUG_KERNEL -# These options are only for real kernel hackers who want to get their hands dirty. +# These options are only for real kernel hackers who want to get their hands dirty. 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 endmenu source lib/Config.in + diff -urN orig/arch/arm/def-configs/accelent_sa linux/arch/arm/def-configs/accelent_sa --- orig/arch/arm/def-configs/accelent_sa Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/accelent_sa Mon Aug 5 22:25:08 2002 @@ -0,0 +1,1099 @@ +# +# 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 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_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +CONFIG_ARCH_SA1100=y +# 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_ACCELENT=y +# 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_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_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_SA1111=y +CONFIG_FORCE_MAX_ZONEORDER=9 +CONFIG_SA1100_USB=m +CONFIG_SA1100_USB_NETLINK=m +CONFIG_SA1100_USB_CHAR=m +# 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 +# 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=y +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# 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_SA110 is not set +CONFIG_CPU_SA1100=y +# CONFIG_ARM_THUMB is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=C0400000 +CONFIG_ZBOOT_ROM_BSS=C0200000 +CONFIG_CPU_FREQ=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +CONFIG_PCMCIA_PROBE=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=m +# CONFIG_SA_PCMCIA_SLOT_1 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 is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PM=y +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=1f02" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +CONFIG_PARPORT=m +# CONFIG_PARPORT_PC is not set +CONFIG_PARPORT_IDP=m +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +# CONFIG_PARPORT_1284 is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# 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 + +# +# User Modules And Translation Layers +# +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 is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_B1 is not set +# CONFIG_MTD_CFI_B2 is not set +CONFIG_MTD_CFI_B4=y +# CONFIG_MTD_CFI_B8 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# 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 is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +CONFIG_MTD_SA1100=y +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# 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 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=y +# 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 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set +CONFIG_CS89x0=y + +# +# 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 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 + +# +# 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=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +# CONFIG_IRNET is not set +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m +CONFIG_IRPORT_SIR=m + +# +# 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 +CONFIG_SA1100_FIR=m + +# +# 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=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_SD_EXTRA_DEVS=40 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_DEBUG_QUEUES is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_PPA is not set +# CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_SCSI_PCMCIA 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=y +CONFIG_INPUT_KEYBDEV=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE 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_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=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=115200 +# 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_SA1111_PS2_KEYB=y +CONFIG_ASI_KEYBOARD=y +# CONFIG_RTC_ASI is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +CONFIG_L3=y +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set + +# +# Other L3 adapters +# +CONFIG_L3_SA1111=y +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=m +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set + +# +# Joysticks +# +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_21285_WATCHDOG is not set +# CONFIG_977_WATCHDOG is not set +CONFIG_SA1100_WATCHDOG=m +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +CONFIG_SA1100_RTC=m +# 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 +# +# CONFIG_PCMCIA_SERIAL_CS 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=m +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_CRAMFS=m +# 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_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=m +# CONFIG_SYSV_FS is not set +CONFIG_UDF_FS=m +# 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=m +CONFIG_NFS_V3=y +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +CONFIG_SUNRPC=m +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +# 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=m + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# 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_PC_KEYMAP=y +# 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_SA1100=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# 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_SA1100=y +CONFIG_SOUND_UDA1341=y +# CONFIG_SOUND_ASSABET_UDA1341 is not set +# CONFIG_SOUND_H3600_UDA1341 is not set +# CONFIG_SOUND_PANGOLIN_UDA1341 is not set +CONFIG_SOUND_SA1111_UDA1341=y +# CONFIG_SOUND_SA1100SSP is not set +# CONFIG_SOUND_SA1111_AC97 is not set +# CONFIG_SOUND_SA1111_AC97_RATE_CONVERSION is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_WAVEARTIST is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +CONFIG_MCP=y +CONFIG_MCP_SA1100=y +CONFIG_MCP_UCB1200=y +CONFIG_MCP_UCB1200_AUDIO=m +CONFIG_MCP_UCB1200_TS=m + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_LONG_TIMEOUT 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=m +CONFIG_USB_SL811HS=m + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +CONFIG_USB_STORAGE=m +# 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) +# +CONFIG_USB_HID=m +CONFIG_USB_HIDDEV=y +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_WACOM is not set + +# +# 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=m + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# 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=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_WAITQ=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/adsagc linux/arch/arm/def-configs/adsagc --- orig/arch/arm/def-configs/adsagc Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/adsagc Fri Feb 21 15:17:34 2003 @@ -0,0 +1,1101 @@ +# +# 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 is not set +# CONFIG_KMOD is not set + +# +# 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=y +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200DK 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_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +CONFIG_SA1100_ADSAGC=y +# 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_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_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 +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_SA1111=y +CONFIG_FORCE_MAX_ZONEORDER=9 + +# +# Processor Type +# +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 is not set +# 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_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +CONFIG_CPU_SA1100=y +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# +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_CPU_FREQ is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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=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 is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PM=y +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="console=ttySA0 mem=16m@0xC0000000 mem=16m@0xC8000000 rw ramdisk_size=8192 initrd=0xC0800000,3m root=/dev/ram" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +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=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +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 is not set +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_RAM is not set +# CONFIG_MTD_ROM is not set +# 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=8000000 +CONFIG_MTD_PHYSMAP_LEN=4000000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=4 +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +CONFIG_MTD_SA1100=y +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# 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 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_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +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 is not set +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 +# 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_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=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +CONFIG_SMC91111=y +# 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_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_TIGON3 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 is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set +# CONFIG_ARLAN is not set +# CONFIG_AIRONET4500 is not set +# CONFIG_AIRONET4500_NONCS is not set +# CONFIG_AIRONET4500_PROC is not set +# CONFIG_HERMES is not set + +# +# Wireless Pcmcia cards support +# +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_AIRO_CS is not set +CONFIG_NET_WIRELESS=y + +# +# 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=y +# 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 is not set + +# +# ATA/ATAPI/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_IDEDISK_STROKE 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 +# CONFIG_IDE_TASK_IOCTL 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 + +# +# 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=y +# CONFIG_INPUT_KEYBDEV is not set +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 +# 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_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=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=38400 +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_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 +CONFIG_TOUCHSCREEN_ADS784X=y +# CONFIG_UCB1200 is not set +# CONFIG_TOUCHSCREEN_UCB1200 is not set +# CONFIG_AUDIO_UCB1200 is not set +# CONFIG_ADC_UCB1200 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_ADSSIO_I2C_ALGO=y +# CONFIG_I2C_CHARDEV is not set +# CONFIG_I2C_PROC is not set +CONFIG_I2C_DS1307=y +CONFIG_I2C_DS1307_ADS=y + +# +# 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 +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set + +# +# Joysticks +# +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_SA1100_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 is not set +# 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=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_CRAMFS=y +# 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_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 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=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=y + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# 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_PC_KEYMAP=y +# 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_SA1100 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_E13806=y +CONFIG_E13806_REG_BASE=48000000 +CONFIG_E13806_FB_BASE=48200000 +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +# CONFIG_FBCON_MFB is not set +# CONFIG_FBCON_CFB2 is not set +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +# 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=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 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_SA1100=y +# CONFIG_SOUND_UDA1341 is not set +# CONFIG_SOUND_ASSABET_UDA1341 is not set +# CONFIG_SOUND_H3600_UDA1341 is not set +# CONFIG_SOUND_PANGOLIN_UDA1341 is not set +# CONFIG_SOUND_SA1111_UDA1341 is not set +CONFIG_SOUND_SA1111_AC97=y +# CONFIG_SOUND_SA1100SSP is not set +CONFIG_SOUND_OSS=y +# CONFIG_SOUND_TRACEINIT is not set +# CONFIG_SOUND_DMAP is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_ACI_MIXER is not set +# CONFIG_SOUND_CS4232 is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_SB is not set +# CONFIG_SOUND_AWE32_SYNTH is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_YMFPCI is not set +# CONFIG_SOUND_YMFPCI_LEGACY is not set +# CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_AEDSP16 is not set +# CONFIG_SOUND_VIDC 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=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_LONG_TIMEOUT is not set + +# +# USB Host Controller Drivers +# +# 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=y + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 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) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_WACOM is not set + +# +# 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_RTL8150 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 +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_BRLVGER is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/adsbitsy linux/arch/arm/def-configs/adsbitsy --- orig/arch/arm/def-configs/adsbitsy Mon Aug 5 13:29:42 2002 +++ linux/arch/arm/def-configs/adsbitsy Thu Feb 27 23:20:10 2003 @@ -1,5 +1,5 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # CONFIG_ARM=y # CONFIG_EISA is not set @@ -8,6 +8,8 @@ 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 @@ -31,16 +33,25 @@ # 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=y # CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200DK is not set # # Archimedes/A5000 Implementations # + +# +# Archimedes/A5000 Implementations (select only ONE) +# # CONFIG_ARCH_ARC is not set # CONFIG_ARCH_A5K is not set @@ -56,15 +67,27 @@ # # 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=y +# 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_BITSY 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_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 @@ -73,40 +96,61 @@ # 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_GRAPHICSMASTER is not set -CONFIG_SA1100_ADSBITSY=y -CONFIG_SA1111=y # 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 # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_SA1111=y +CONFIG_FORCE_MAX_ZONEORDER=9 + +# +# Processor Type +# CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y # CONFIG_CPU_ARM610 is not set # CONFIG_CPU_ARM710 is not set # CONFIG_CPU_ARM720T is not set # CONFIG_CPU_ARM920T is not set +# 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_ARM1026 is not set # CONFIG_CPU_SA110 is not set CONFIG_CPU_SA1100=y +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# CONFIG_DISCONTIGMEM=y -# CONFIG_CPU_BIG_ENDIAN is not set # # General setup @@ -114,6 +158,9 @@ # 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_CPU_FREQ is not set CONFIG_HOTPLUG=y @@ -121,6 +168,8 @@ # PCMCIA/CardBus support # CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=y +# CONFIG_I82092 is not set # CONFIG_I82365 is not set # CONFIG_TCIC is not set # CONFIG_PCMCIA_CLPS6700 is not set @@ -129,6 +178,10 @@ 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 @@ -136,12 +189,12 @@ # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set -# CONFIG_APM is not set +CONFIG_PM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="ip=off" -# CONFIG_PFS168_CMDLINE is not set -# CONFIG_LEDS is not set +CONFIG_CMDLINE="console=ttySA0 mem=32m@0xC0000000 rw ramdisk_size=8192 initrd=0xC0800000,3m root=/dev/ram" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU is not set CONFIG_ALIGNMENT_TRAP=y # @@ -152,7 +205,79 @@ # # Memory Technology Devices (MTD) # -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +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 is not set +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_RAM is not set +# CONFIG_MTD_ROM is not set +# 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=8000000 +CONFIG_MTD_PHYSMAP_LEN=4000000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=4 +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +CONFIG_MTD_SA1100=y +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# 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 is not set # # Plug and Play configuration @@ -168,7 +293,9 @@ # 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_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y @@ -184,6 +311,7 @@ # 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 # @@ -191,7 +319,7 @@ # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y @@ -204,13 +332,24 @@ # 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 + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -228,6 +367,11 @@ # CONFIG_NET_SCHED is not set # +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -240,19 +384,27 @@ # 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_SUNLANCE is not set # CONFIG_SUNBMAC is not set # CONFIG_SUNQE is not set -# CONFIG_SUNLANCE 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_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +CONFIG_SMC91111=y # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set @@ -262,21 +414,44 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set -# CONFIG_ACENIC_OMIT_TIGON_I 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_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_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 is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set # CONFIG_SLIP is not set # # Wireless LAN (non-hamradio) # -# CONFIG_NET_RADIO is not set +CONFIG_NET_RADIO=y +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set +# CONFIG_ARLAN is not set +# CONFIG_AIRONET4500 is not set +# CONFIG_AIRONET4500_NONCS is not set +# CONFIG_AIRONET4500_PROC is not set +# CONFIG_HERMES is not set + +# +# Wireless Pcmcia cards support +# +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_AIRO_CS is not set +CONFIG_NET_WIRELESS=y # # Token Ring devices @@ -299,6 +474,7 @@ # CONFIG_PCMCIA_3C574 is not set # CONFIG_PCMCIA_FMVJ18X is not set CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_AXNET is not set # CONFIG_PCMCIA_NMCLAN is not set # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set @@ -317,7 +493,7 @@ # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -325,10 +501,15 @@ # 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_IDEDISK_STROKE 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 @@ -343,6 +524,11 @@ # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL 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 @@ -350,6 +536,9 @@ # 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 @@ -385,35 +574,47 @@ # Character devices # CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set +CONFIG_VT_CONSOLE=y # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE 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_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=y CONFIG_SERIAL_SA1100_CONSOLE=y CONFIG_SA1100_DEFAULT_BAUDRATE=38400 +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_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 -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_TOUCHSCREEN_ADS784X is not set CONFIG_UCB1200=y CONFIG_TOUCHSCREEN_UCB1200=y CONFIG_AUDIO_UCB1200=y CONFIG_ADC_UCB1200=y -# CONFIG_TOUCHSCREEN_BITSY is not set -# CONFIG_PROFILER is not set -# CONFIG_PFS168_SPI is not set -# CONFIG_PFS168_DTMF is not set -# CONFIG_PFS168_MISC is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 # # I2C support @@ -421,6 +622,19 @@ # CONFIG_I2C is not set # +# L3 serial bus support +# +CONFIG_L3=y +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set + +# +# Other L3 adapters +# +CONFIG_L3_SA1111=y +# CONFIG_BIT_SA1100_GPIO is not set + +# # Mice # # CONFIG_BUSMOUSE is not set @@ -429,14 +643,43 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set + +# +# Joysticks +# +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set # 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_SA1100_RTC is not set @@ -468,23 +711,29 @@ # 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 is not set # 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_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 CONFIG_CRAMFS=y # 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_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set @@ -509,6 +758,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -526,6 +776,8 @@ # 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=y # # Partition Types @@ -560,6 +812,7 @@ # 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 @@ -588,11 +841,11 @@ 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_CYBER2000 is not set CONFIG_FB_SA1100=y -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_E1355 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_E13806 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB2=y @@ -610,50 +863,169 @@ # # Sound # -# CONFIG_SOUND is not set +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_SA1100=y +CONFIG_SOUND_UDA1341=y +# CONFIG_SOUND_ASSABET_UDA1341 is not set +# CONFIG_SOUND_H3600_UDA1341 is not set +# CONFIG_SOUND_PANGOLIN_UDA1341 is not set +CONFIG_SOUND_SA1111_UDA1341=y +# CONFIG_SOUND_SA1111_AC97 is not set +# CONFIG_SOUND_SA1100SSP is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC 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=y # CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_LONG_TIMEOUT is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_UHCI is not set # CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=y -CONFIG_USB_OHCI_NOPCI=y +# CONFIG_USB_OHCI is not set +CONFIG_USB_OHCI_SA1111=y + +# +# USB Device Class drivers +# # CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 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 -# CONFIG_USB_HID is not set -# CONFIG_USB_KBD is not set -CONFIG_USB_MOUSE=y + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDDEV is not set # CONFIG_USB_WACOM is not set + +# +# 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_IBMCAM is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_PLUSB 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_RTL8150 is not set +# CONFIG_USB_KAWETH is not set # CONFIG_USB_CATC is not set -# CONFIG_USB_NET1080 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 +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_BRLVGER is not set # # Bluetooth support @@ -664,11 +1036,16 @@ # Kernel hacking # CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_MAGIC_SYSRQ is not set # CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set # CONFIG_DEBUG_DC21285_PORT is not set # CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/adsbitsyplus linux/arch/arm/def-configs/adsbitsyplus --- orig/arch/arm/def-configs/adsbitsyplus Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/adsbitsyplus Fri Feb 21 15:17:33 2003 @@ -0,0 +1,1087 @@ +# +# 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 is not set +# CONFIG_KMOD is not set + +# +# 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=y +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200DK 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_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=y +# 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_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_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 +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_SA1111=y +CONFIG_FORCE_MAX_ZONEORDER=9 + +# +# Processor Type +# +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 is not set +# 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_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +CONFIG_CPU_SA1100=y +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# +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_CPU_FREQ is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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=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 is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PM=y +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="console=ttySA0 mem=32m@0xC0000000 rw ramdisk_size=8192 initrd=0xC0800000,3m root=/dev/ram" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU 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=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +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 is not set +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_RAM is not set +# CONFIG_MTD_ROM is not set +# 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=8000000 +CONFIG_MTD_PHYSMAP_LEN=4000000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=4 +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +CONFIG_MTD_SA1100=y +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# 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 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_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +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 is not set +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 +# 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_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=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +CONFIG_SMC91111=y +# 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_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_TIGON3 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 is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set +# CONFIG_ARLAN is not set +# CONFIG_AIRONET4500 is not set +# CONFIG_AIRONET4500_NONCS is not set +# CONFIG_AIRONET4500_PROC is not set +# CONFIG_HERMES is not set + +# +# Wireless Pcmcia cards support +# +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_AIRO_CS is not set +CONFIG_NET_WIRELESS=y + +# +# 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=y +# 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 is not set + +# +# ATA/ATAPI/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_IDEDISK_STROKE 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 +# CONFIG_IDE_TASK_IOCTL 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 + +# +# 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=y +# CONFIG_INPUT_KEYBDEV is not set +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 +# 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_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=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=38400 +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_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 +CONFIG_TOUCHSCREEN_ADS784X=y +# CONFIG_UCB1200 is not set +# CONFIG_TOUCHSCREEN_UCB1200 is not set +# CONFIG_AUDIO_UCB1200 is not set +# CONFIG_ADC_UCB1200 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_ADSSIO_I2C_ALGO=y +# CONFIG_I2C_CHARDEV is not set +# CONFIG_I2C_PROC is not set +CONFIG_I2C_DS1307=y +CONFIG_I2C_DS1307_ADS=y + +# +# L3 serial bus support +# +CONFIG_L3=y +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set + +# +# Other L3 adapters +# +CONFIG_L3_SA1111=y +# 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_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set + +# +# Joysticks +# +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_SA1100_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 is not set +# 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=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_CRAMFS=y +# 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_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 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=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=y + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# 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_PC_KEYMAP=y +# 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_SA1100=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_E13806 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 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_SA1100=y +# CONFIG_SOUND_UDA1341 is not set +# CONFIG_SOUND_ASSABET_UDA1341 is not set +# CONFIG_SOUND_H3600_UDA1341 is not set +# CONFIG_SOUND_PANGOLIN_UDA1341 is not set +# CONFIG_SOUND_SA1111_UDA1341 is not set +CONFIG_SOUND_SA1111_AC97=y +# CONFIG_SOUND_SA1100SSP is not set +CONFIG_SOUND_OSS=y +# CONFIG_SOUND_TRACEINIT is not set +# CONFIG_SOUND_DMAP is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_ACI_MIXER is not set +# CONFIG_SOUND_CS4232 is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_SB is not set +# CONFIG_SOUND_AWE32_SYNTH is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_YMFPCI is not set +# CONFIG_SOUND_YMFPCI_LEGACY is not set +# CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_AEDSP16 is not set +# CONFIG_SOUND_VIDC 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=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_LONG_TIMEOUT is not set + +# +# USB Host Controller Drivers +# +# 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=y + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 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) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_WACOM is not set + +# +# 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_RTL8150 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 +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_BRLVGER is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/at91rm9200dk linux/arch/arm/def-configs/at91rm9200dk --- orig/arch/arm/def-configs/at91rm9200dk Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/at91rm9200dk Sun Jun 15 21:48:36 2003 @@ -0,0 +1,773 @@ +# +# 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=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_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_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 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_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_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,115200 initrd=0x20210000,3145728 root=/dev/ram rw" +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 is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# 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_PCI 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_ECC=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_AT91_SMARTMEDIA=y + +# +# 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_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=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 is not set +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 +# 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=y +# 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_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_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_IDE_MODES 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 + +# +# 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_I2C_ALGOPCF is not set +CONFIG_I2C_AT91=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y +# CONFIG_I2C_DS1307 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 +# 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 + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_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_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_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_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 +# 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 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_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 + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set +# 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 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=y +# 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_OHCI_AT91=y +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_BLUETOOTH is not set +# 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 +# CONFIG_USB_HID is not set +# CONFIG_USB_HIDINPUT is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_WACOM is not set +# 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 +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 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 +# 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 +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_BRLVGER 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 diff -urN orig/arch/arm/def-configs/cep linux/arch/arm/def-configs/cep --- orig/arch/arm/def-configs/cep Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/cep Sun Jun 16 12:54:24 2002 @@ -0,0 +1,615 @@ +# +# 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 is not set +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# 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_RPC is not set +CONFIG_ARCH_SA1100=y +# CONFIG_ARCH_SHARK is not set + +# +# 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_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +CONFIG_SA1100_CEP=y +# 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 +# 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 +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# 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=y +# CONFIG_ARM_THUMB is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# CONFIG_ISA_DMA is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_NET=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_FPE_NWFPE=y +# 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="console=ttySA0,9600 root=/dev/ram" +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD 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=y +# 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 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 is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE 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 + +# +# 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 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_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_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 + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA 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 + +# +# 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=y +CONFIG_SERIAL_CONSOLE=y +# 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_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=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=9600 +# 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 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 +# 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 + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_SA1100_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 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 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 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 + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set +# 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 is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_PC_KEYMAP=y +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND 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 +# 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_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# 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 +# 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 +# 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 +# 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 +# CONFIG_USB_RIO500 is not set + +# +# Kernel hacking +# +# CONFIG_NO_FRAME_POINTER is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/epxa10db linux/arch/arm/def-configs/epxa10db --- orig/arch/arm/def-configs/epxa10db Mon Aug 5 13:29:43 2002 +++ linux/arch/arm/def-configs/epxa10db Fri Feb 21 15:17:33 2003 @@ -8,6 +8,8 @@ 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 @@ -34,10 +36,14 @@ CONFIG_ARCH_CAMELOT=y # 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_AT91RM9200DK is not set # # Archimedes/A5000 Implementations @@ -57,17 +63,25 @@ # # SA11x0 Implementations # +# CONFIG_SA1100_ACCELENT is not set # 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_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_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 @@ -76,42 +90,59 @@ # 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_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 # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_EPXA10DB=y +# CONFIG_EPXA1DB is not set +# CONFIG_EPXA10DB_R2 is not set +CONFIG_EPXA10DB_R3=y +CONFIG_PLD=y +# CONFIG_PLD_HOTSWAP is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y # CONFIG_CPU_ARM610 is not set # CONFIG_CPU_ARM710 is not set # CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set CONFIG_CPU_ARM922T=y -CONFIG_CPU_ARM92X_CPU_IDLE=y -CONFIG_CPU_ARM92X_I_CACHE_ON=y -CONFIG_CPU_ARM92X_D_CACHE_ON=y -# CONFIG_CPU_ARM92X_WRITETHROUGH is not set +CONFIG_PLD=y +# CONFIG_CPU_ARM926T is not set # CONFIG_CPU_ARM1020 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_DISCONTIGMEM is not set # @@ -120,6 +151,9 @@ # 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 @@ -130,7 +164,7 @@ # CONFIG_FPE_FASTFPE is not set CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y +# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set @@ -150,8 +184,9 @@ CONFIG_MTD_DEBUG=y CONFIG_MTD_DEBUG_VERBOSE=0 CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_BOOTLDR_PARTS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +# CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -171,42 +206,32 @@ # CONFIG_MTD_ROM is not set # 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 is not set -# CONFIG_MTD_SUN_UFLASH is not set # CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_TQM8XXL is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -CONFIG_MTD_EPXA10DB=y -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_SOLUTIONENGINE is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_L440GX 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=y +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set # # Self-contained MTD device drivers # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_LART is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set # CONFIG_MTD_DOC1000 is not set @@ -224,7 +249,6 @@ # # CONFIG_PNP is not set # CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set # # Block devices @@ -234,7 +258,9 @@ # 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_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 @@ -250,6 +276,7 @@ # 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 # @@ -257,7 +284,7 @@ # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y @@ -270,13 +297,20 @@ # 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 + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -294,6 +328,11 @@ # CONFIG_NET_SCHED is not set # +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -306,16 +345,18 @@ # 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_ETHER00=y # CONFIG_SUNLANCE is not set # CONFIG_SUNBMAC is not set # CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set @@ -335,6 +376,7 @@ # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN 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 @@ -343,8 +385,8 @@ # CONFIG_PPP_FILTER is not set CONFIG_PPP_ASYNC=y CONFIG_PPP_SYNC_TTY=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_BSDCOMP=y +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set # CONFIG_PPPOE is not set # CONFIG_SLIP is not set @@ -377,7 +419,7 @@ # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set # CONFIG_BLK_DEV_IDE_MODES is not set @@ -435,6 +477,8 @@ CONFIG_SERIAL_UART00_CONSOLE=y # 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_8250 is not set # CONFIG_SERIAL_8250_CONSOLE is not set # CONFIG_SERIAL_8250_EXTENDED is not set @@ -460,7 +504,6 @@ # CONFIG_L3_ALGOBIT is not set # CONFIG_L3_BIT_SA1100_GPIO is not set # CONFIG_L3_SA1111 is not set -# CONFIG_L3_DRV_UDA1341 is not set # CONFIG_BIT_SA1100_GPIO is not set # @@ -479,13 +522,11 @@ # 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 -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -513,7 +554,6 @@ # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set # CONFIG_JBD_DEBUG is not set @@ -522,16 +562,17 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 -# CONFIG_JFFS2_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set # CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_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 @@ -557,7 +598,7 @@ # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set +CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y @@ -572,6 +613,8 @@ # 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 @@ -582,66 +625,18 @@ # 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 -# 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_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# 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_JUMPSHOT 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_ACM is not set -# CONFIG_USB_PRINTER is not set -# 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 -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_PLUSB is not set -# 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 -# 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_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_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_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set # # Bluetooth support @@ -652,11 +647,16 @@ # Kernel hacking # CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_USER=y CONFIG_DEBUG_INFO=y -CONFIG_MAGIC_SYSRQ=y # CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SLAB=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_WAITQ=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_DC21285_PORT is not set # CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/epxa1db linux/arch/arm/def-configs/epxa1db --- orig/arch/arm/def-configs/epxa1db Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/epxa1db Mon Aug 5 23:25:12 2002 @@ -0,0 +1,703 @@ +# +# 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 is not set + +# +# 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=y +# 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_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# 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_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY 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_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 +# 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 +# CONFIG_EPXA10DB is not set +CONFIG_EPXA1DB=y +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +CONFIG_CPU_ARM922T=y +CONFIG_PLD=y +CONFIG_CPU_ARM922_CPU_IDLE=y +CONFIG_CPU_ARM922_I_CACHE_ON=y +CONFIG_CPU_ARM922_D_CACHE_ON=y +# CONFIG_CPU_ARM922_WRITETHROUGH 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 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_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="console=ttyUA0,38400 root=/dev/mtdblock0 rw" +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +CONFIG_MTD_DEBUG=y +CONFIG_MTD_DEBUG_VERBOSE=0 +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +# 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 is not set +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_RAM is not set +# CONFIG_MTD_ROM is not set +# 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 is not set +# 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_EPXA10DB=y +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM 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 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=8192 +# CONFIG_BLK_DEV_INITRD 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 +# 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_ETHER00 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=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +CONFIG_SMC91111=y +# 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_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=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE 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/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 + +# +# 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 is not set +# 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_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +CONFIG_SERIAL_UART00=y +CONFIG_SERIAL_UART00_CONSOLE=y +# 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 +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 +# 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 + +# +# 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 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=y +CONFIG_JFFS2_FS_DEBUG=0 +# 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=y +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 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=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 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 +# 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_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# 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 +# 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 +# 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 +# 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 +# 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=y +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SLAB=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_WAITQ=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/frodo linux/arch/arm/def-configs/frodo --- orig/arch/arm/def-configs/frodo Mon Aug 5 13:29:43 2002 +++ linux/arch/arm/def-configs/frodo Thu Oct 24 13:01:38 2002 @@ -37,6 +37,7 @@ # 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_RPC is not set CONFIG_ARCH_SA1100=y # CONFIG_ARCH_SHARK is not set @@ -59,10 +60,12 @@ # # SA11x0 Implementations # +# CONFIG_SA1100_ACCELENT is not set # 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_CEP is not set # CONFIG_SA1100_CERF is not set # CONFIG_SA1100_H3100 is not set # CONFIG_SA1100_H3600 is not set @@ -71,6 +74,7 @@ # CONFIG_SA1100_EXTENEX1 is not set # CONFIG_SA1100_FLEXANET is not set # CONFIG_SA1100_FREEBIRD is not set +CONFIG_SA1100_FRODO=y # CONFIG_SA1100_GRAPHICSCLIENT is not set # CONFIG_SA1100_GRAPHICSMASTER is not set # CONFIG_SA1100_BADGE4 is not set @@ -86,11 +90,11 @@ # 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_FRODO=y # CONFIG_SA1100_USB is not set # CONFIG_SA1100_USB_NETLINK is not set # CONFIG_SA1100_USB_CHAR is not set @@ -113,18 +117,18 @@ # CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y # CONFIG_CPU_ARM610 is not set # CONFIG_CPU_ARM710 is not set # CONFIG_CPU_ARM720T is not set # CONFIG_CPU_ARM920T is not set # 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_SA110 is not set CONFIG_CPU_SA1100=y -# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y CONFIG_DISCONTIGMEM=y # @@ -133,15 +137,28 @@ # CONFIG_PCI is not set CONFIG_ISA=y # CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 # CONFIG_CPU_FREQ is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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=y CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -# CONFIG_FPE_NWFPE is not set -CONFIG_FPE_FASTFPE=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set # CONFIG_BINFMT_AOUT is not set @@ -149,7 +166,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttySA0,9600 ramdisk_size=4096 root=/dev/ram idebus=33" +CONFIG_CMDLINE="console=ttySA0,115200 ramdisk_size=12288 root=/dev/ram idebus=33 mem=63M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -163,7 +180,68 @@ # # Memory Technology Devices (MTD) # -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# 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 is not set +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_RAM is not set +# CONFIG_MTD_ROM is not set +# 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 is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +CONFIG_MTD_SA1100=y +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM 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 is not set # # Plug and Play configuration @@ -179,11 +257,13 @@ # 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_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=4096 +CONFIG_BLK_DEV_RAM_SIZE=12288 CONFIG_BLK_DEV_INITRD=y # @@ -201,7 +281,8 @@ # # Networking options # -# CONFIG_PACKET is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y # CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set @@ -221,6 +302,11 @@ # 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 @@ -238,9 +324,98 @@ # CONFIG_NET_SCHED is not set # +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# # Network device support # -# CONFIG_NETDEVICES is not set +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_CIRRUS=y +# CONFIG_CIRRUS_DEBUG is not set +# CONFIG_CIRRUS_DUPLEX is not set +# 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 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_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_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 + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=y +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# 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 @@ -253,7 +428,7 @@ # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -265,6 +440,7 @@ # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE 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 @@ -274,11 +450,12 @@ # 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 is not set +CONFIG_BLK_DEV_IDECS=y CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_ISAPNP is not set @@ -312,11 +489,13 @@ # # Input core support # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT=y +CONFIG_INPUT_KEYBDEV=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +CONFIG_INPUT_EVDEV=y # # Character devices @@ -343,7 +522,7 @@ # CONFIG_SERIAL_UART00_CONSOLE is not set CONFIG_SERIAL_SA1100=y CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SA1100_DEFAULT_BAUDRATE=9600 +CONFIG_SA1100_DEFAULT_BAUDRATE=115200 # CONFIG_SERIAL_8250 is not set # CONFIG_SERIAL_8250_CONSOLE is not set # CONFIG_SERIAL_8250_EXTENDED is not set @@ -355,12 +534,22 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=16 +CONFIG_UNIX98_PTY_COUNT=64 # # I2C support # -# CONFIG_I2C is not set +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_PHILIPSPAR is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_VELLEMAN is not set +CONFIG_I2C_FRODO=y +# CONFIG_I2C_BIT_SA1100_GPIO is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y +CONFIG_I2C_DS1307=y # # L3 serial bus support @@ -381,16 +570,61 @@ # Joysticks # # CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set # 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_SA1100_RTC=y +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_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=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_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_DS1307_RTC=y +CONFIG_DS1307_NVRAM=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -403,9 +637,50 @@ # CONFIG_DRM is not set # +# PCMCIA character devices +# + +# # Multimedia devices # -# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_DEV=y + +# +# Video For Linux +# +# CONFIG_I2C_PARPORT is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_PMS is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIDEO_ZORAN_BUZ is not set +# CONFIG_VIDEO_ZORAN_DC10 is not set +# CONFIG_VIDEO_ZORAN_LML33 is not set +# CONFIG_VIDEO_ZR36120 is not set +# CONFIG_VIDEO_MEYE is not set +# CONFIG_VIDEO_CYBERPRO is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_RADIO_GEMTEK_PCI is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_MAESTRO is not set +# CONFIG_RADIO_MIROPCM20 is not set +# CONFIG_RADIO_MIROPCM20_RDS is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set # # File systems @@ -424,32 +699,33 @@ # 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_FAT_FS=y +CONFIG_MSDOS_FS=y # CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_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_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 # 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_RAMFS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y # 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_FS=y +CONFIG_DEVFS_MOUNT=y # 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=y +# CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set # CONFIG_UDF_FS is not set @@ -479,8 +755,8 @@ # 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 +CONFIG_ZISOFS_FS=y +CONFIG_ZLIB_FS_INFLATE=y # # Partition Types @@ -488,11 +764,54 @@ # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y # CONFIG_SMB_NLS is not set -# CONFIG_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_PC_KEYB=y CONFIG_PC_KEYMAP=y # CONFIG_VGA_CONSOLE is not set @@ -507,15 +826,32 @@ CONFIG_FB_SA1100=y # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB2=y -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y +CONFIG_FBCON_ADVANCED=y +# CONFIG_FBCON_MFB is not set +# CONFIG_FBCON_CFB2 is not set +# CONFIG_FBCON_CFB4 is not set +# CONFIG_FBCON_CFB8 is not set CONFIG_FBCON_CFB16=y +# 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 is not set -CONFIG_FONT_8x8=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set 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 @@ -534,12 +870,19 @@ # # USB support # -# CONFIG_USB is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +# 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_1161=y # CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 is not set # CONFIG_USB_BLUETOOTH is not set # CONFIG_USB_STORAGE is not set # CONFIG_USB_STORAGE_DEBUG is not set @@ -552,12 +895,25 @@ # CONFIG_USB_STORAGE_JUMPSHOT is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDDEV=y +# CONFIG_USB_WACOM is not set # 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 +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_PWC is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_DSBR is not set +# CONFIG_USB_DABUSB is not set # CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_CATC is not set # CONFIG_USB_CDCETHER is not set @@ -575,6 +931,7 @@ # 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 @@ -588,11 +945,14 @@ # 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_BRLVGER is not set # # Bluetooth support diff -urN orig/arch/arm/def-configs/graphicsclient linux/arch/arm/def-configs/graphicsclient --- orig/arch/arm/def-configs/graphicsclient Mon Aug 5 13:29:43 2002 +++ linux/arch/arm/def-configs/graphicsclient Fri Feb 21 15:17:34 2003 @@ -8,6 +8,8 @@ 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 @@ -31,12 +33,17 @@ # 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=y # CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200DK is not set # # Archimedes/A5000 Implementations @@ -60,15 +67,27 @@ # # 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_BITSY 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=y +# 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 @@ -77,43 +96,59 @@ # 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_GRAPHICSMASTER is not set -# CONFIG_SA1100_ADSBITSY 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 # 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=y +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 is not set +# 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_ARM1026 is not set # CONFIG_CPU_SA110 is not set CONFIG_CPU_SA1100=y +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# CONFIG_DISCONTIGMEM=y -# CONFIG_CPU_BIG_ENDIAN is not set # # General setup @@ -121,6 +156,9 @@ # 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_CPU_FREQ is not set CONFIG_HOTPLUG=y @@ -128,6 +166,8 @@ # PCMCIA/CardBus support # CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=y +# CONFIG_I82092 is not set # CONFIG_I82365 is not set # CONFIG_TCIC is not set # CONFIG_PCMCIA_CLPS6700 is not set @@ -136,6 +176,10 @@ 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 @@ -143,11 +187,9 @@ # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set -# CONFIG_APM is not set +CONFIG_PM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="ip=off" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="console=ttySA0 mem=16m@0xC0000000 mem=16m@0xC8000000 rw ramdisk_size=8192 initrd=0xC0800000,3m root=/dev/ram" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -164,8 +206,9 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set # CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_BOOTLDR_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set # @@ -180,53 +223,44 @@ # RAM/ROM/Flash chip drivers # CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +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_AMDSTD is not set -# CONFIG_MTD_SHARP is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set +# 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=800000 -CONFIG_MTD_PHYSMAP_LEN=1000000 +CONFIG_MTD_PHYSMAP_START=8000000 +CONFIG_MTD_PHYSMAP_LEN=2000000 CONFIG_MTD_PHYSMAP_BUSWIDTH=4 -# CONFIG_MTD_SUN_UFLASH is not set # CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_TQM8XXL is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set CONFIG_MTD_SA1100=y -# CONFIG_MTD_SA1100_REDBOOT_PARTITIONS is not set -# CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS is not set # CONFIG_MTD_DC21285 is not set # CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_SOLUTIONENGINE is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_L440GX is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set # # Self-contained MTD device drivers # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_LART is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -257,8 +291,10 @@ # 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_BLK_DEV_DAC960 is not set -CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 @@ -273,6 +309,7 @@ # 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 # @@ -280,7 +317,7 @@ # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y @@ -293,17 +330,24 @@ # 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 + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -321,6 +365,11 @@ # CONFIG_NET_SCHED is not set # +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -333,15 +382,17 @@ # 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_SUNLANCE is not set # CONFIG_SUNBMAC is not set # CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set @@ -351,6 +402,7 @@ # CONFIG_ULTRA is not set # CONFIG_ULTRA32 is not set CONFIG_SMC9194=y +# CONFIG_SMC91111 is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set @@ -360,21 +412,44 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set -# CONFIG_ACENIC_OMIT_TIGON_I 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_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_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 is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set # CONFIG_SLIP is not set # # Wireless LAN (non-hamradio) # -# CONFIG_NET_RADIO is not set +CONFIG_NET_RADIO=y +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set +# CONFIG_ARLAN is not set +# CONFIG_AIRONET4500 is not set +# CONFIG_AIRONET4500_NONCS is not set +# CONFIG_AIRONET4500_PROC is not set +# CONFIG_HERMES is not set + +# +# Wireless Pcmcia cards support +# +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_AIRO_CS is not set +CONFIG_NET_WIRELESS=y # # Token Ring devices @@ -397,6 +472,7 @@ # CONFIG_PCMCIA_3C574 is not set # CONFIG_PCMCIA_FMVJ18X is not set CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_AXNET is not set # CONFIG_PCMCIA_NMCLAN is not set # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set @@ -415,7 +491,7 @@ # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -431,6 +507,7 @@ # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE 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 @@ -445,6 +522,7 @@ # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set # # IDE chipset support/bugfixes @@ -456,6 +534,9 @@ # 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 @@ -479,46 +560,84 @@ # # Input core support # -# CONFIG_INPUT is not set +CONFIG_INPUT=y +# CONFIG_INPUT_KEYBDEV is not set +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set # # Character devices # CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set +CONFIG_VT_CONSOLE=y # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE 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_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=y CONFIG_SERIAL_SA1100_CONSOLE=y CONFIG_SA1100_DEFAULT_BAUDRATE=38400 +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_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 -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_TOUCHSCREEN_ADS784X is not set CONFIG_UCB1200=y CONFIG_TOUCHSCREEN_UCB1200=y CONFIG_AUDIO_UCB1200=y CONFIG_ADC_UCB1200=y -# CONFIG_TOUCHSCREEN_BITSY is not set -# CONFIG_PROFILER is not set -# CONFIG_PFS168_SPI is not set -# CONFIG_PFS168_DTMF is not set -# CONFIG_PFS168_MISC is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 # # I2C support # -# CONFIG_I2C is not set +CONFIG_I2C=y +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_ADSSIO_I2C_ALGO=y +# CONFIG_I2C_CHARDEV is not set +# CONFIG_I2C_PROC is not set +CONFIG_I2C_DS1307=y +CONFIG_I2C_DS1307_ADS=y + +# +# 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 @@ -529,18 +648,43 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set # -# Input core support is needed for joysticks +# Joysticks # +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set # 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_SA1100_RTC is not set @@ -572,18 +716,21 @@ # 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 is not set # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 +# CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 CONFIG_CRAMFS=y @@ -591,6 +738,7 @@ CONFIG_RAMFS=y # 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 @@ -615,6 +763,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -632,6 +781,8 @@ # 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=y # # Partition Types @@ -666,6 +817,7 @@ # 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 @@ -694,11 +846,11 @@ 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_CYBER2000 is not set CONFIG_FB_SA1100=y -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_E1355 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_E13806 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB2=y @@ -719,6 +871,15 @@ # CONFIG_SOUND 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 @@ -732,11 +893,16 @@ # Kernel hacking # CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_MAGIC_SYSRQ is not set # CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set # CONFIG_DEBUG_DC21285_PORT is not set # CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/graphicsmaster linux/arch/arm/def-configs/graphicsmaster --- orig/arch/arm/def-configs/graphicsmaster Mon Aug 5 13:29:43 2002 +++ linux/arch/arm/def-configs/graphicsmaster Thu Feb 27 23:20:10 2003 @@ -1,5 +1,5 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # CONFIG_ARM=y # CONFIG_EISA is not set @@ -8,6 +8,8 @@ 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 @@ -31,16 +33,25 @@ # 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=y # CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200DK is not set # # Archimedes/A5000 Implementations # + +# +# Archimedes/A5000 Implementations (select only ONE) +# # CONFIG_ARCH_ARC is not set # CONFIG_ARCH_A5K is not set @@ -56,15 +67,27 @@ # # 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_BITSY 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=y +# 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 @@ -73,40 +96,61 @@ # 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_GRAPHICSMASTER=y -# CONFIG_SA1100_ADSBITSY is not set -CONFIG_SA1111=y # 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 # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_SA1111=y +CONFIG_FORCE_MAX_ZONEORDER=9 + +# +# Processor Type +# CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y # CONFIG_CPU_ARM610 is not set # CONFIG_CPU_ARM710 is not set # CONFIG_CPU_ARM720T is not set # CONFIG_CPU_ARM920T is not set +# 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_ARM1026 is not set # CONFIG_CPU_SA110 is not set CONFIG_CPU_SA1100=y +# CONFIG_CPU_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# CONFIG_DISCONTIGMEM=y -# CONFIG_CPU_BIG_ENDIAN is not set # # General setup @@ -114,6 +158,9 @@ # 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_CPU_FREQ is not set CONFIG_HOTPLUG=y @@ -121,6 +168,8 @@ # PCMCIA/CardBus support # CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=y +# CONFIG_I82092 is not set # CONFIG_I82365 is not set # CONFIG_TCIC is not set # CONFIG_PCMCIA_CLPS6700 is not set @@ -129,6 +178,10 @@ 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 @@ -136,11 +189,9 @@ # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set -# CONFIG_APM is not set +CONFIG_PM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="ip=off" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="console=ttySA0 mem=16m@0xC0000000 mem=16m@0xC8000000 rw ramdisk_size=8192 initrd=0xC0800000,3m root=/dev/ram" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -157,9 +208,14 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set # CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_BOOTLDR_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set @@ -169,55 +225,50 @@ # RAM/ROM/Flash chip drivers # CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +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_AMDSTD is not set -# CONFIG_MTD_SHARP is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set +# 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=800000 -CONFIG_MTD_PHYSMAP_LEN=1000000 +CONFIG_MTD_PHYSMAP_START=8000000 +CONFIG_MTD_PHYSMAP_LEN=4000000 CONFIG_MTD_PHYSMAP_BUSWIDTH=4 -# CONFIG_MTD_SUN_UFLASH is not set # CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_TQM8XXL is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set CONFIG_MTD_SA1100=y -# CONFIG_MTD_SA1100_REDBOOT_PARTITIONS is not set -# CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS is not set # CONFIG_MTD_DC21285 is not set # CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_SOLUTIONENGINE is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_L440GX is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set # # Self-contained MTD device drivers # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_LART is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# # CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set @@ -242,8 +293,10 @@ # 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_BLK_DEV_DAC960 is not set -CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 @@ -258,6 +311,7 @@ # 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 # @@ -265,7 +319,7 @@ # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y @@ -278,13 +332,24 @@ # 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 + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -302,6 +367,11 @@ # CONFIG_NET_SCHED is not set # +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -314,15 +384,17 @@ # 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_SUNLANCE is not set # CONFIG_SUNBMAC is not set # CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set @@ -332,6 +404,7 @@ # CONFIG_ULTRA is not set # CONFIG_ULTRA32 is not set CONFIG_SMC9194=y +# CONFIG_SMC91111 is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set @@ -341,21 +414,44 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set -# CONFIG_ACENIC_OMIT_TIGON_I 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_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_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 is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set # CONFIG_SLIP is not set # # Wireless LAN (non-hamradio) # -# CONFIG_NET_RADIO is not set +CONFIG_NET_RADIO=y +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set +# CONFIG_ARLAN is not set +# CONFIG_AIRONET4500 is not set +# CONFIG_AIRONET4500_NONCS is not set +# CONFIG_AIRONET4500_PROC is not set +# CONFIG_HERMES is not set + +# +# Wireless Pcmcia cards support +# +# CONFIG_PCMCIA_HERMES is not set +# CONFIG_AIRO_CS is not set +CONFIG_NET_WIRELESS=y # # Token Ring devices @@ -378,6 +474,7 @@ # CONFIG_PCMCIA_3C574 is not set # CONFIG_PCMCIA_FMVJ18X is not set CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_AXNET is not set # CONFIG_PCMCIA_NMCLAN is not set # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set @@ -396,7 +493,7 @@ # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -404,10 +501,15 @@ # 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_IDEDISK_STROKE 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 @@ -422,6 +524,11 @@ # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL 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 @@ -429,6 +536,9 @@ # 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 @@ -464,35 +574,47 @@ # Character devices # CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set +CONFIG_VT_CONSOLE=y # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE 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_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=y CONFIG_SERIAL_SA1100_CONSOLE=y CONFIG_SA1100_DEFAULT_BAUDRATE=38400 -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# 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=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_TOUCHSCREEN_ADS784X is not set CONFIG_UCB1200=y CONFIG_TOUCHSCREEN_UCB1200=y CONFIG_AUDIO_UCB1200=y CONFIG_ADC_UCB1200=y -# CONFIG_TOUCHSCREEN_BITSY is not set -# CONFIG_PROFILER is not set -# CONFIG_PFS168_SPI is not set -# CONFIG_PFS168_DTMF is not set -# CONFIG_PFS168_MISC is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 # # I2C support @@ -500,6 +622,19 @@ # 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 @@ -508,14 +643,43 @@ # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set + +# +# Joysticks +# +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set # 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_SA1100_RTC is not set @@ -533,6 +697,7 @@ # # PCMCIA character devices # +# CONFIG_PCMCIA_SERIAL_CS is not set # # Multimedia devices @@ -547,18 +712,21 @@ # 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 is not set # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 +# CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 CONFIG_CRAMFS=y @@ -566,6 +734,7 @@ CONFIG_RAMFS=y # 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 @@ -590,6 +759,7 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y @@ -607,6 +777,8 @@ # 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=y # # Partition Types @@ -641,6 +813,7 @@ # 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 @@ -669,11 +842,11 @@ 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_CYBER2000 is not set CONFIG_FB_SA1100=y -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_E1355 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_E13806 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB2=y @@ -691,50 +864,169 @@ # # Sound # -# CONFIG_SOUND is not set +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_SA1100=y +# CONFIG_SOUND_UDA1341 is not set +# CONFIG_SOUND_ASSABET_UDA1341 is not set +# CONFIG_SOUND_H3600_UDA1341 is not set +# CONFIG_SOUND_PANGOLIN_UDA1341 is not set +# CONFIG_SOUND_SA1111_UDA1341 is not set +# CONFIG_SOUND_SA1111_AC97 is not set +# CONFIG_SOUND_SA1100SSP is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC 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=y # CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_LONG_TIMEOUT is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_UHCI is not set # CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=y -CONFIG_USB_OHCI_NOPCI=y +# CONFIG_USB_OHCI is not set +CONFIG_USB_OHCI_SA1111=y + +# +# USB Device Class drivers +# # CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 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 -# CONFIG_USB_HID is not set -# CONFIG_USB_KBD is not set -CONFIG_USB_MOUSE=y + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDDEV is not set # CONFIG_USB_WACOM is not set + +# +# 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_IBMCAM is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_PLUSB 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_RTL8150 is not set +# CONFIG_USB_KAWETH is not set # CONFIG_USB_CATC is not set -# CONFIG_USB_NET1080 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 +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_BRLVGER is not set # # Bluetooth support @@ -745,11 +1037,16 @@ # Kernel hacking # CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_MAGIC_SYSRQ is not set # CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set # CONFIG_DEBUG_DC21285_PORT is not set # CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/lusl7200 linux/arch/arm/def-configs/lusl7200 --- orig/arch/arm/def-configs/lusl7200 Wed May 31 13:12:12 2000 +++ linux/arch/arm/def-configs/lusl7200 Sat May 18 14:48:58 2002 @@ -23,6 +23,9 @@ # CONFIG_CPU_26 is not set CONFIG_CPU_32v4=y CONFIG_CPU_ARM720=y +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=0x00010000 +CONFIG_ZBOOT_ROM_BSS=0xf03e0000 # CONFIG_PCI is not set # CONFIG_ISA is not set # CONFIG_ISA_DMA is not set diff -urN orig/arch/arm/def-configs/nanoengine linux/arch/arm/def-configs/nanoengine --- orig/arch/arm/def-configs/nanoengine Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/nanoengine Fri Jun 21 14:13:59 2002 @@ -0,0 +1,775 @@ +# +# 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 is not set +# CONFIG_KMOD is not set + +# +# 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_RPC is not set +CONFIG_ARCH_SA1100=y +# 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=y +# 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 +# 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=y +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# 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=y +# CONFIG_ARM_THUMB is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# CONFIG_ISA_DMA is not set +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=11000 +CONFIG_ZBOOT_ROM_BSS=c1fc0000 +# CONFIG_CPU_FREQ is not set +# 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 + +# +# 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 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="root=/dev/ram" +# 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=y +CONFIG_MTD_DEBUG_VERBOSE=1 +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_BOOTLDR_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +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=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# 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 is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +CONFIG_MTD_SA1100=y +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_MTDRAM=y +CONFIG_MTDRAM_TOTAL_SIZE=2048 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTDRAM_ABS_POS=0 +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# 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 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=y +CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +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=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 +# 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 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_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 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/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 + +# +# 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 is not set +# 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_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=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=9600 +# 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=y +CONFIG_UNIX98_PTY_COUNT=64 + +# +# 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_SA1100_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 +# 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 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=y +CONFIG_JFFS2_FS_DEBUG=1 +# 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 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=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 is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND 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 is not set +# 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 is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/omaha linux/arch/arm/def-configs/omaha --- orig/arch/arm/def-configs/omaha Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/omaha Thu Oct 24 14:58:03 2002 @@ -0,0 +1,798 @@ +# +# 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 is not set +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# 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=y +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# 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 +# 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=y +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +CONFIG_CPU_ARM920T=y +CONFIG_CPU_ARM920_CPU_IDLE=y +CONFIG_CPU_ARM920_I_CACHE_ON=y +CONFIG_CPU_ARM920_D_CACHE_ON=y +# CONFIG_CPU_ARM920_WRITETHROUGH 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 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_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y + +# +# At least one math emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD 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=y +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD 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 is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE 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 + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +CONFIG_SMC91C111=y +# 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_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_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 + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA 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=y +# 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 is not set +# 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 + +# +# 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 is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_ARM_DCC 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_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_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_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_PHILIPSPAR is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_VELLEMAN is not set +CONFIG_I2C_OMAHA=y +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y + +# +# 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=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_21285_WATCHDOG is not set +# CONFIG_977_WATCHDOG is not set +# CONFIG_SA1100_WATCHDOG is not set +CONFIG_OMAHA_WATCHDOG=y +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +CONFIG_OMAHA_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 +# 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=y +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=y +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +CONFIG_MINIX_FS=y +# 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 + +# +# 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 + +# +# Omaha /proc drivers +# +CONFIG_OMAHA_MISC=y + +# +# 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 + +# +# Kernel hacking +# +# CONFIG_FRAME_POINTER is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/riscstation linux/arch/arm/def-configs/riscstation --- orig/arch/arm/def-configs/riscstation Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/def-configs/riscstation Fri Dec 20 17:03:01 2002 @@ -0,0 +1,766 @@ +# +# 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 is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# 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_RPC is not set +CONFIG_ARCH_RISCSTATION=y +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# 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_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 +# 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 +CONFIG_CPU_32v3=y +# CONFIG_CPU_32v4 is not set +# CONFIG_CPU_ARM610 is not set +CONFIG_CPU_ARM710=y +# CONFIG_CPU_ARM720T is not set +# 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 is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# CONFIG_ISA_DMA is not set +# 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_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="ip=dhcp" +# 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 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 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 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_ARM_ETHER1 is not set +# CONFIG_ARM_ETHER3 is not set +# CONFIG_ARM_ETHERH 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_NEW_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_NET_POCKET 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 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/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# 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 is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_IDE_RISCSTATION=y +# 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 + +# +# 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=y +CONFIG_SERIAL_CONSOLE=y +# 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_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_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 +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +# CONFIG_PSMOUSE is not set +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +CONFIG_7K5MOUSE=y +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# 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=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 +# 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=y +# 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=y +CONFIG_JBD=y +# 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=y +CONFIG_TMPFS=y +# 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=y +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 is not set +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set +# 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=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +CONFIG_ACORN_PARTITION=y +CONFIG_ACORN_PARTITION_EESOX=y +CONFIG_ACORN_PARTITION_ICS=y +CONFIG_ACORN_PARTITION_ADFS=y +CONFIG_ACORN_PARTITION_POWERTEC=y +CONFIG_ACORN_PARTITION_RISCIX=y +# 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 +# + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_ACORN=y +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_SA1100 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_FONT_ACORN_8x8=y + +# +# Sound +# +# CONFIG_SOUND 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 +# 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_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# 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 +# 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 +# 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 +# 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 +# CONFIG_USB_RIO500 is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_KERNEL is not set +# 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 is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set diff -urN orig/arch/arm/def-configs/sherman linux/arch/arm/def-configs/sherman --- orig/arch/arm/def-configs/sherman Mon Sep 3 14:14:39 2001 +++ linux/arch/arm/def-configs/sherman Sat May 18 14:49:36 2002 @@ -47,6 +47,9 @@ # # General setup # +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=0x00050000 +CONFIG_ZBOOT_ROM_BSS=0xc0200000 # CONFIG_NET is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set diff -urN orig/arch/arm/def-configs/victor linux/arch/arm/def-configs/victor --- orig/arch/arm/def-configs/victor Wed May 31 13:12:12 2000 +++ linux/arch/arm/def-configs/victor Sat May 18 14:49:52 2002 @@ -46,6 +46,9 @@ # # General setup # +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=0x00002000 +CONFIG_ZBOOT_ROM_BSS=0xc0200000 # CONFIG_NET is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set diff -urN orig/arch/arm/fastfpe/CPDO.S linux/arch/arm/fastfpe/CPDO.S --- orig/arch/arm/fastfpe/CPDO.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/fastfpe/CPDO.S Fri Dec 28 17:39:50 2001 @@ -0,0 +1,682 @@ +/* +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 high 32 mantissa bit are also 0, otherwise it is +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity. + +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 and r14. They return +to fastfpe_next, except CPDO_rnf_core which expects the return address in r14. +*/ + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_adf +CPDO_adf: + ldmia r1,{r1,r3,r5,r7} + ldmia r2,{r2,r4,r6,r8} + + cmp r7,#0x7fffffff + cmpne r8,#0x7fffffff + beq CPDO_adf_extra + + cmp r1,r2 + bne CPDO_suf_s + +CPDO_adf_s: + subs r2,r7,r8 + bge CPDO_adf_2nd + + mov r7,r8 + rsb r2,r2,#0 + cmp r2,#32 + ble CPDO_adf_1st2 + + sub r2,r2,#32 + cmp r2,#32 + movgt r2,#32 + mov r5,r3,lsr r2 + mov r3,#0 + b CPDO_adf_add + +CPDO_adf_1st2: + rsb r8,r2,#32 + mov r5,r5,lsr r2 + orr r5,r5,r3,lsl r8 + mov r3,r3,lsr r2 @ 1. op normalized + b CPDO_adf_add + +CPDO_adf_2nd: + cmp r2,#32 + ble CPDO_adf_2nd2 + + sub r2,r2,#32 + cmp r2,#32 + movgt r2,#32 + mov r6,r4,lsr r2 + mov r4,#0 + b CPDO_adf_add + +CPDO_adf_2nd2: + rsb r8,r2,#32 + mov r6,r6,lsr r2 + orr r6,r6,r4,lsl r8 + mov r4,r4,lsr r2 @ 2. op normalized + +CPDO_adf_add: + adds r5,r5,r6 + adcs r3,r3,r4 @ do addition + bcc CPDO_adf_end + + add r7,r7,#1 + movs r3,r3,rrx + mov r5,r5,rrx @ correct for overflow + +CPDO_adf_end: + cmp r7,#0x20000000 + bge CPDO_inf + + stmia r0,{r1,r3,r5,r7} + b fastfpe_next + +CPDO_adf_extra: + cmp r7,#0x7fffffff @ was it the 1st ? + bne CPDO_infnan_2 @ no it was the 2nd + cmp r8,#0x7fffffff @ if 1st, 2nd too ? + bne CPDO_infnan_1 @ no only 1st + cmp r3,#0 + cmpeq r4,#0 + bne CPDO_nan_12 + b CPDO_inf + +/*---------------------------------------------------------------------------*/ + +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 + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_suf +CPDO_suf: + ldmia r1,{r1,r3,r5,r7} + ldmia r2,{r2,r4,r6,r8} + +CPDO_suf_l: + cmp r7,#0x7fffffff + cmpne r8,#0x7fffffff + beq CPDO_suf_extra + + cmp r1,r2 + bne CPDO_adf_s + +CPDO_suf_s: + subs r2,r7,r8 @ determine greater number + bgt CPDO_suf_2nd @ first number is greater + blt CPDO_suf_1st @ second number is greater + cmp r3,r4 @ also mantissa is important + cmpeq r5,r6 + bhi CPDO_suf_2nd @ first number is greater + beq CPDO_zero + +CPDO_suf_1st: + eor r1,r1,#0x80000000 @ second number is greater, invert sign + mov r7,r8 + rsb r2,r2,#0 + cmp r2,#32 + ble CPDO_suf_1st2 + + sub r2,r2,#32 + cmp r2,#32 + movgt r2,#32 + mov r5,r3,lsr r2 + mov r3,#0 + b CPDO_suf_1st_sub + +CPDO_suf_1st2: + rsb r8,r2,#32 + mov r5,r5,lsr r2 + orr r5,r5,r3,lsl r8 + mov r3,r3,lsr r2 @ 1. op normalized + +CPDO_suf_1st_sub: + subs r5,r6,r5 @ do subtraction + sbc r3,r4,r3 + b CPDO_suf_norm + +CPDO_suf_2nd: + cmp r2,#32 + ble CPDO_suf_2nd2 + + sub r2,r2,#32 + cmp r2,#32 + movgt r2,#32 + mov r6,r4,lsr r2 + mov r4,#0 + b CPDO_suf_2nd_sub + +CPDO_suf_2nd2: + rsb r8,r2,#32 + mov r6,r6,lsr r2 + orr r6,r6,r4,lsl r8 + mov r4,r4,lsr r2 @ 2. op normalized + +CPDO_suf_2nd_sub: + subs r5,r5,r6 + sbc r3,r3,r4 @ do subtraction + +CPDO_suf_norm: + teq r3,#0 @ normalize 32bit + moveq r3,r5 + moveq r5,#0 + subeq r7,r7,#32 + + cmp r3,#0x00010000 @ 16bit + movcc r3,r3,lsl#16 + orrcc r3,r3,r5,lsr#16 + movcc r5,r5,lsl#16 + subcc r7,r7,#16 + + cmp r3,#0x01000000 @ 8bit + movcc r3,r3,lsl#8 + orrcc r3,r3,r5,lsr#24 + movcc r5,r5,lsl#8 + subcc r7,r7,#8 + + cmp r3,#0x10000000 @ 4bit + movcc r3,r3,lsl#4 + orrcc r3,r3,r5,lsr#28 + movcc r5,r5,lsl#4 + subcc r7,r7,#4 + + cmp r3,#0x40000000 @ 2bit + movcc r3,r3,lsl#2 + orrcc r3,r3,r5,lsr#30 + movcc r5,r5,lsl#2 + subcc r7,r7,#2 + + cmp r3,#0x80000000 @ 1bit + movcc r3,r3,lsl#1 + orrcc r3,r3,r5,lsr#31 + movcc r5,r5,lsl#1 + subcc r7,r7,#1 + + cmp r7,#0xe0000000 + ble CPDO_zero_1 + + stmia r0,{r1,r3,r5,r7} + b fastfpe_next + +CPDO_suf_extra: + cmp r7,#0x7fffffff @ was it the 1st ? + eorne r2,r2,#0x80000000 @ change sign, might have been INF + bne CPDO_infnan_2 @ no it was the 2nd + cmp r8,#0x7fffffff @ if 1st, 2nd too ? + bne CPDO_infnan_1 @ no only 1st + cmp r3,#0 + cmpeq r4,#0 + bne CPDO_nan_12 + b CPDO_nan @ here is difference with adf ! + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rsf +CPDO_rsf: + mov r3,r2 + ldmia r1,{r2,r4,r6,r8} + ldmia r3,{r1,r3,r5,r7} + b CPDO_suf_l + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_muf +CPDO_muf: + ldmia r1,{r1,r3,r5,r7} + ldmia r2,{r2,r4,r6,r8} + + cmp r7,#0x7fffffff + cmpne r8,#0x7fffffff + beq CPDO_muf_extra + + eor r1,r1,r2 + adds r8,r7,r8 + bvs CPDO_zero_1 + + umull r7,r2,r3,r4 + umull r14,r3,r6,r3 + adds r7,r7,r3 @ r2|r7|r14 = r2|r7|#0 + #0|r3|r14 + adc r2,r2,#0 + umull r4,r3,r5,r4 + adds r14,r14,r4 @ r2|r7|r14 += #0|r3|r4 + adcs r7,r7,r3 + adc r2,r2,#0 + umull r4,r3,r5,r6 + adds r14,r14,r3 @ r2|r7|r14 += #0|#0|r3 + adcs r7,r7,#0 + adcs r2,r2,#0 + + bpl CPDO_muf_norm + + add r8,r8,#1 + b CPDO_muf_end + +CPDO_muf_norm: + adds r14,r14,r14 + adcs r7,r7,r7 + adcs r2,r2,r2 + +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 + +CPDO_muf_extra: + cmp r7,#0x7fffffff @ was it the first? + bne CPDO_muf_extra_2nd @ no, so it was the second + cmp r8,#0x7fffffff @ yes, second too? + bne CPDO_muf_extra_1st @ no, only first + orr r3,r3,r4 @ if both inf -> inf, otherwise nan + eor r1,r1,r2 @ sign for the inf case + b CPDO_infnan_1 + +CPDO_muf_extra_1st: + cmp r3,#0 @ is it a nan? + bne CPDO_infnan_1 + cmp r8,#0x80000000 @ is the second 0? + beq CPDO_nan + eor r1,r1,r2 @ correct sign for inf + b CPDO_inf + +CPDO_muf_extra_2nd: + cmp r4,#0 @ is it a nan? + bne CPDO_infnan_2 + cmp r7,#0x80000000 @ is the first 0? + beq CPDO_nan + eor r1,r1,r2 @ correct sign for inf + b CPDO_inf + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_dvf +CPDO_dvf: + ldmia r1,{r1,r3,r5,r7} + ldmia r2,{r2,r4,r6,r8} + +CPDO_dvf_l: + cmp r7,#0x7fffffff + cmpne r8,#0x7fffffff + beq CPDO_dvf_extra + cmp r8,#0x80000000 + beq CPDO_dvf_by0 + + eor r1,r1,r2 + cmp r7,#0x80000000 + beq CPDO_zero_1 + + sub r8,r7,r8 + + mov r2,#0 + mov r7,#1 + + cmp r3,r4 + cmpeq r5,r6 + bcs CPDO_dvf_loop_ + + sub r8,r8,#1 + +CPDO_dvf_loop: + adds r5,r5,r5 + adcs r3,r3,r3 + bcs CPDO_dvf_anyway +CPDO_dvf_loop_: + subs r5,r5,r6 + sbcs r3,r3,r4 + bcs CPDO_dvf_okay + + adds r5,r5,r6 + adc r3,r3,r4 + adds r7,r7,r7 + adcs r2,r2,r2 + bcc CPDO_dvf_loop + b CPDO_dvf_end + +CPDO_dvf_anyway: + adcs r7,r7,r7 + adcs r2,r2,r2 + bcs CPDO_dvf_end + subs r5,r5,r6 + sbc r3,r3,r4 + b CPDO_dvf_loop + +CPDO_dvf_okay: + adcs r7,r7,r7 + adcs r2,r2,r2 + bcc CPDO_dvf_loop + +CPDO_dvf_end: + b CPDO_muf_end + +CPDO_dvf_by0: + cmp R7,#0x80000000 + beq CPDO_nan @ first also 0 -> nan + eor r1,r1,r2 @ otherwise calculatesign for inf + b CPDO_inf + +CPDO_dvf_extra: + cmp r7,#0x7fffffff @ was it the first? + bne CPDO_dvf_extra_2nd @ no, so it was the second + cmp r8,#0x7fffffff @ yes, second too? + bne CPDO_dvf_extra_1st @ no, only first + orrs r3,r3,r4 + beq CPDO_nan @ if both inf -> create nan + b CPDO_nan_12 @ otherwise keep nan + +CPDO_dvf_extra_1st: + eor r1,r1,r2 @ correct sign for inf + b CPDO_infnan_1 + +CPDO_dvf_extra_2nd: + cmp r4,#0 @ is it a nan? + bne CPDO_infnan_2 + eor r1,r1,r2 @ correct sign for zero + b CPDO_zero_1 + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rdf +CPDO_rdf: + mov r3,r2 + ldmia r1,{r2,r4,r6,r8} + ldmia r3,{r1,r3,r5,r7} + b CPDO_dvf_l + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rmf +CPDO_rmf: + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_mvf +CPDO_mvf: + ldmia r2,{r1,r2,r3,r4} + stmia r0,{r1,r2,r3,r4} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_mnf +CPDO_mnf: + ldmia r2,{r1,r2,r3,r4} + eor r1,r1,#0x80000000 + stmia r0,{r1,r2,r3,r4} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .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 + adcs r2,r2,r2 @carry is needed in 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 + +CPDO_rnd_store: + stmia r0,{r1,r2,r3,r5} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDO_rnd_core +CPDO_rnd_core: + and r4,r4,#0x00000060 + add pc,pc,r4,lsr#3 + mov r0,r0 + b CPDO_rnd_N + b CPDO_rnd_P + b CPDO_rnd_M + b CPDO_rnd_Z + +CPDO_rnd_N: + cmp r5,#-1 + blt CPDO_rnd_zero + cmp r5,#63 + movge pc,r14 + mov r4,#0x40000000 + cmp r5,#31 + bge CPDO_rnd_N_2 + + adds r2,r2,r4,lsr r5 + bcc CPDO_rnd_end + b CPDO_rnd_end_norm + +CPDO_rnd_N_2: +CPDO_rnd_P_2: + sub r6,r5,#32 + adds r3,r3,r4,ror r6 @ror ist needed to handle a -1 correctly + adcs r2,r2,#0 + bcc CPDO_rnd_end + b CPDO_rnd_end_norm + +CPDO_rnd_P: + tst r1,#0x80000000 + bne CPDO_rnd_M_entry +CPDO_rnd_P_entry: + cmp r5,#0 + blt CPDO_rnd_P_small + cmp r5,#63 + movge pc,r14 + mov r4,#0x7fffffff + cmp r5,#32 + bge CPDO_rnd_P_2 + + adds r3,r3,#0xffffffff + adcs r2,r2,r4,lsr r5 + bcc CPDO_rnd_end + b CPDO_rnd_end_norm + +CPDO_rnd_P_small: + cmp r5,#0x80000000 + moveq pc,r14 + b CPDO_rnd_one + +CPDO_rnd_M: + tst r1,#0x80000000 + bne CPDO_rnd_P_entry +CPDO_rnd_M_entry: + cmp r5,#0 + blt CPDO_rnd_zero + cmp r5,#63 + movge pc,r14 + + b CPDO_rnd_end + +CPDO_rnd_Z: + cmp r5,#0 + blt CPDO_rnd_zero + cmp r5,#63 + movge pc,r14 + b CPDO_rnd_end + +CPDO_rnd_end_norm: + add r5,r5,#1 + movs r2,r2,rrx + mov r3,r3,rrx +CPDO_rnd_end: + rsbs r4,r5,#31 + bmi CPDO_rnd_end_2 + mov r3,#0 + mov r2,r2,lsr r4 + mov r2,r2,lsl r4 + mov pc,r14 + +CPDO_rnd_end_2: + rsb r4,r5,#63 + mov r3,r3,lsr r4 + mov r3,r3,lsl r4 + mov pc,r14 + +CPDO_rnd_one: + mov r2,#0x80000000 + mov r3,#0 + mov r5,#0 + mov pc,r14 + +CPDO_rnd_zero: + mov r1,#0 + mov r2,#0 + mov r3,#0 + mov r5,#0x80000000 + mov pc,r14 + +/*---------------------------------------------------------------------------*/ diff -urN orig/arch/arm/fastfpe/CPDT.S linux/arch/arm/fastfpe/CPDT.S --- orig/arch/arm/fastfpe/CPDT.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/fastfpe/CPDT.S Thu Oct 24 13:58:10 2002 @@ -0,0 +1,430 @@ +/* +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 high 32 mantissa bit are also 0, otherwise it is +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity. + +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#9 + 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 + subeq r5,r5,#1 + moveqs r4,r4,lsl#1 + adceq r3,r3,r3 + beq CPDT_ld_e0_norm + + stmia r0,{r2-r5} + b fastfpe_next + +CPDT_ld_e2047: + mov r3,r1,lsl#12 + orr r3,r3,r6,lsr#1 + bic r6,r6,#0x80000000 + orr r3,r3,r6 @ to get all fraction bits ! + mov r4,#0 + 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,#0x80000000 + bics r5,r1,#0x80000000 + beq CPDT_le_e0 + add r1,r5,#1 + teq r4,#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 r3,r3,lsl#1 + orr r3,r3,r4,lsr#1 + bic r4,r4,#0x80000000 + orr r3,r3,r4 + 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 + + adds r2,r2,#1<<7 @ round to nearest + bcs CPDT_ss_rnd_ovfl @ very very seldom taken + +CPDT_ss_store: + 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_rnd_ovfl: + add r4,r4,#1 + cmp r4,#128 + bge CPDT_ss_e255 + + mov r2,#0x80000000 + mov r3,#0 + b CPDT_ss_store + +CPDT_ss_e0: + cmp r4,#-150 + ble CPDT_ss_zero + + add r4,r4,#126 +CPDT_ss_unnormalize: + mov r2,r2,lsr#1 + adds r4,r4,#1 + bne CPDT_ss_unnormalize + + orr r1,r1,r2,lsr#8 + +CPDT_ss_zero: + str r1,[r6] + b fastfpe_next + +CPDT_ss_e255: + cmp r4,#0x7fffffff + bne CPDT_ss_inf + cmp r2,#0 + beq CPDT_ss_inf + + orr r1,r1,#0x00200000 @ for safety so that it is not INF + orr r1,r1,r2,lsr#9 @ get highest bit of mantissa + +CPDT_ss_inf: + orr r1,r1,#0x7f000000 + orr r1,r1,#0x00800000 + str r1,[r6] + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .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 + + adds r3,r3,#1<<10 @ round to nearest + adcs r2,r2,#0 + bcs CPDT_sd_rnd_ovfl @ very very seldom taken + +CPDT_sd_store: + 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_rnd_ovfl: + add r4,r4,#1 + cmp r4,#1024 + bge CPDT_sd_e2047 + + mov r2,#0x80000000 + mov r3,#0 + b CPDT_sd_store + +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: + cmp r4,#0x7fffffff + bne CPDT_sd_inf + cmp r2,#0 + beq CPDT_sd_inf + + orr r1,r1,#0x00040000 @ for safety so that it is not INF + orr r1,r1,r2,lsr#12 @ get highest bit of mantissa + +CPDT_sd_inf: + orr r1,r1,#0x7f000000 + orr r1,r1,#0x00f00000 + stmia r6,{r1,r2} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .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,r1,r4 + + 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 + + stmia r6,{r1-r3} + b fastfpe_next + +CPDT_se_zero: + mov r2,#0 + mov r3,#0 + stmia r6,{r1-r3} + b fastfpe_next + +CPDT_se_e32767: + cmp r4,#0x7fffffff + bne CPDT_se_inf + cmp r2,#0 + beq CPDT_se_inf + + mov r2,r2,lsl#1 + orr r2,r2,#0x20000000 + +CPDT_se_inf: + 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: + add r2,r10,r0,lsr#8 + ldr r4,[r2,#0] + ldr r3,[r2,#4] + bic r3,r3,#0x80000000 + orr r3,r3,r4 + str r3,[r6],#4 + ldr r3,[r2,#8] + str r3,[r6],#4 + ldr r3,[r2,#12] + str r3,[r6],#4 + + add r0,r0,#1<<12 + and r0,r0,#7<<12 + subs r1,r1,#1 + bne CPDT_sfm + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPDT_lfm +CPDT_lfm: + add r2,r10,r0,lsr#8 + ldr r4,[r6],#4 + and r3,r4,#0x80000000 + str r3,[r2,#0] + ldr r3,[r6],#4 + str r3,[r2,#8] + ldr r3,[r6],#4 + str r3,[r2,#12] + + cmp r3,#0x80000000 @ does the exp indicate zero? + biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized' + beq CPDT_lfm_storer4 + cmp r3,#0x7fffffff @ does the exp indicate inf or NaN? + biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized' + beq CPDT_lfm_storer4 + orrne r4,r4,#0x80000000 @ otherwise, set normalized bit + +CPDT_lfm_storer4: + str r4,[r2,#4] + + add r0,r0,#1<<12 + and r0,r0,#7<<12 + subs r1,r1,#1 + bne CPDT_lfm + b fastfpe_next + +/*---------------------------------------------------------------------------*/ diff -urN orig/arch/arm/fastfpe/CPRT.S linux/arch/arm/fastfpe/CPRT.S --- orig/arch/arm/fastfpe/CPRT.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/fastfpe/CPRT.S Thu Oct 24 17:47:42 2002 @@ -0,0 +1,185 @@ +/* +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 high 32 mantissa bit are also 0, otherwise it +is +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity. + +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 r3,#0 + cmp r2,#0 + beq CPRT_flt_zero + + ands r0,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 + + stmia r1,{r0,r2,r3,r4} + b fastfpe_next + +CPRT_flt_zero: + mov r0,#0 + mov r4,#0x80000000 + stmia r1,{r0,r2,r3,r4} + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_fix +CPRT_fix: + ldmia r2,{r1,r2,r3,r5} + bl CPDO_rnd_core + +CPRT_back: + add r0,r13,r0,lsr#10 + cmp r5,#0 + blt CPRT_int_zero + cmp r5,#30 + bgt CPRT_overflow + + rsb r5,r5,#31 + mov r2,r2,lsr r5 + tst r1,#0x80000000 + rsbne r2,r2,#0 + + str r2,[r0] + b fastfpe_next + +CPRT_int_zero: + mov r2,#0 + str r2,[r0] + b fastfpe_next + +CPRT_overflow: + mov r2,#0x80000000 + tst r1,#0x80000000 + subeq r2,r2,#1 + str r2,[r0] + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_wfs +CPRT_wfs: + b fastfpe_next + +/*---------------------------------------------------------------------------*/ + + .globl CPRT_rfs +CPRT_rfs: + add r0,r13,r0,lsr#10 + mov r1,#0x02000000 @ Software Emulation, not Acorn FPE + str r1,[r0] + 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] + + cmp r7,#0x7fffffff + bic r0,r0,#0xf0000000 + + cmpeq r3,#0xffffffff + beq CPRT_cmf_unordered + cmp r8,#0x7fffffff + cmpeq r4,#0xffffffff + beq CPRT_cmf_unordered + + cmp r1,r2 + beq CPRT_cmf_equalsign + b CPRT_cmf_sign + +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_sign: + cmp r7,#0x80000000 @ (0.0 == -0.0)? + cmpeq r7,r8 + beq CPRT_cmf_equal + tst r1,#0x80000000 + orreq r0,r0,#0x20000000 + orrne r0,r0,#0x80000000 + str r0,[r13,#16*4] + b fastfpe_next + +CPRT_cmf_signb: + tst r1,#0x80000000 + orrne r0,r0,#0x20000000 + orreq r0,r0,#0x80000000 + str r0,[r13,#16*4] + b fastfpe_next + +CPRT_cmf_equal: + orr r0,r0,#0x60000000 + str r0,[r13,#16*4] + b fastfpe_next + +CPRT_cmf_unordered: + orr r0,r0,#0x10000000 + 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 -urN orig/arch/arm/fastfpe/Makefile linux/arch/arm/fastfpe/Makefile --- orig/arch/arm/fastfpe/Makefile Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/fastfpe/Makefile Mon Feb 11 15:42:49 2002 @@ -0,0 +1,25 @@ +# +# linux/arch/arm/fastfpe/Makefile +# +# Copyright (C) Peter Teichmann +# + +O_TARGET := fast-math-emu.o + +obj-y := +obj-m := +obj-n := +obj- := + +fastfpe-objs := module.o entry.o CPDO.o CPRT.o CPDT.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 -urN orig/arch/arm/fastfpe/entry.S linux/arch/arm/fastfpe/entry.S --- orig/arch/arm/fastfpe/entry.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/fastfpe/entry.S Fri Dec 28 17:39:51 2001 @@ -0,0 +1,295 @@ +/* +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) + +*/ + +/*---------------------------------------------------------------------------*/ + + .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: +__x1: + ldrt r4,[r5],#4 + + ldr r0,=fp_cond @ check condition of next instruction + ldr r1,[r13,#64] @ psr containing flags + mov r2,r4,lsr#28 + mov r1,r1,lsr#28 + ldr r0,[r0,r2,lsl#2] + mov r0,r0,lsr r1 + tst r0,#1 + beq next_after_cond @ must not necessarily have been an + @ FP instruction ! + 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 + b next_enter + +/*---------------------------------------------------------------------------*/ + +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 + mov r1,#0 + tst r4,#0x00008000 + orrne r1,r1,#1 @ T0 + tst r4,#0x00400000 + orrne r1,r1,#2 @ T1 + tst r4,#0x00100000 + orrne r1,r1,#4 @ L/S + + add pc,pc,r1,lsl#2 + mov r0,r0 + b CPDT_store_single @ these functions get + b CPDT_store_double @ r0=address of fp register + b CPDT_store_extended @ r6=address of data + b undefined @ CPDT_store_decimal + b CPDT_load_single + b CPDT_load_double + b CPDT_load_extended + b 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: + and r3,r4,#0x00f00000 + tst r4,#0x00008000 + orrne r3,r3,#0x01000000 + + add pc,pc,r3,lsr#18 + mov r0,r0 + b CPDO_adf + b CPDO_muf + b CPDO_suf + b CPDO_rsf + b CPDO_dvf + b CPDO_rdf + b undefined + b undefined + b undefined @ CPDO_rmf + b CPDO_muf + b CPDO_dvf + b CPDO_rdf + b undefined + b undefined + b undefined + b undefined + b CPDO_mvf + b CPDO_mnf + b CPDO_abs + b CPDO_rnd + b CPDO_sqt + b undefined + b undefined + b undefined + b undefined + b undefined + b undefined + b undefined + b undefined + b undefined + b CPDO_rnd + b 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 + + add pc,pc,r3,lsr#18 + mov r0,r0 + b CPRT_flt + b CPRT_fix + b CPRT_wfs + b CPRT_rfs + b undefined + b undefined + b undefined + b undefined + b undefined + b CPRT_cmf + b undefined + b CPRT_cnf + b undefined + b CPRT_cmf + b undefined + b CPRT_cnf + +CPRT_const: + ldr r2,=fp_const + and r3,r4,#0x00000007 + add r2,r2,r3,lsl#4 + b CPRT_constback + +/*---------------------------------------------------------------------------*/ + + @ 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 -urN orig/arch/arm/fastfpe/module.c linux/arch/arm/fastfpe/module.c --- orig/arch/arm/fastfpe/module.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/fastfpe/module.c Fri Dec 28 17:39:51 2001 @@ -0,0 +1,78 @@ +/* + 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 */ + +#ifdef MODULE +/* + * Return 0 if we can be unloaded. This can only happen if + * kern_fp_enter is still pointing at fastfpe_enter + */ +static int fpe_unload(void) +{ + return (kern_fp_enter == fastfpe_enter) ? 0 : 1; +} +#endif + +static int __init fpe_init(void) +{ +#ifdef MODULE + if (!mod_member_present(&__this_module, can_unload)) + return -EINVAL; + __this_module.can_unload = fpe_unload; +#else + if (fpe_type[0] && strcmp(fpe_type, "fastfpe")) + return 0; +#endif + + printk("Fast Floating Point Emulator V0.9 (c) 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 -urN orig/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- orig/arch/arm/kernel/Makefile Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/Makefile Fri Jun 13 22:19:08 2003 @@ -18,6 +18,7 @@ O_OBJS_rpc = dma-rpc.o O_OBJS_footbridge = dma-footbridge.o isa.o O_OBJS_l7200 = fiq.o +O_OBJS_riscstation = fiq.o dma-riscstation.o pci-ftvpci = plx90x0.o pci-footbridge = dec21285.o @@ -43,7 +44,8 @@ no-irq-arch := $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \ $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \ $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \ - $(CONFIG_ARCH_MX1ADS) + $(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_OMAHA) \ + $(CONFIG_ARCH_AT91RM9200) ifneq ($(findstring y,$(no-irq-arch)),y) obj-y += irq-arch.o @@ -51,6 +53,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_DEBUG_LL) += debug-$(PROCESSOR).o obj-$(CONFIG_MODULES) += armksyms.o obj-$(CONFIG_ARTHUR) += arthur.o diff -urN orig/arch/arm/kernel/arch.c linux/arch/arm/kernel/arch.c --- orig/arch/arm/kernel/arch.c Mon Sep 3 14:14:39 2001 +++ linux/arch/arm/kernel/arch.c Sun Sep 15 20:18:44 2002 @@ -20,7 +20,7 @@ unsigned int vram_size; -#ifdef CONFIG_ARCH_ACORN +#if defined(CONFIG_ARCH_ACORN) || defined(CONFIG_ARCH_RISCSTATION) unsigned int memc_ctrl_reg; unsigned int number_mfm_drives; @@ -49,7 +49,8 @@ __tagtable(ATAG_ACORN, parse_tag_acorn); -#ifdef CONFIG_ARCH_RPC + +#if defined(CONFIG_ARCH_RPC) || defined(CONFIG_ARCH_RISCSTATION) static void __init fixup_riscpc(struct machine_desc *desc, struct param_struct *unusd, char **cmdline, struct meminfo *mi) @@ -61,7 +62,9 @@ } extern void __init rpc_map_io(void); +extern void __init riscstation_map_io(void); +#ifdef CONFIG_ARCH_RPC MACHINE_START(RISCPC, "Acorn-RiscPC") MAINTAINER("Russell King") BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) @@ -73,6 +76,20 @@ INITIRQ(genarch_init_irq) MACHINE_END #endif + +#ifdef CONFIG_ARCH_RISCSTATION +/* TODO = check all parameters */ +MACHINE_START(RISCSTATION, "RiscStation-RS7500") + MAINTAINER("Ben Dooks, Vincent Sanders") + BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) + BOOT_PARAMS(0x10000100) + FIXUP(fixup_riscpc) + MAPIO(riscstation_map_io) + INITIRQ(genarch_init_irq) +MACHINE_END +#endif + +#endif /* CONFIG_ARCH_RPC | CONFIG_ARCH_RISCSTATION */ #ifdef CONFIG_ARCH_ARC MACHINE_START(ARCHIMEDES, "Acorn-Archimedes") MAINTAINER("Dave Gilbert") diff -urN orig/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c --- orig/arch/arm/kernel/armksyms.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/armksyms.c Wed Jun 25 10:54:49 2003 @@ -62,9 +62,11 @@ extern void __muldi3(void); extern void __ucmpdi2(void); extern void __udivdi3(void); +extern void __umoddi3(void); extern void __udivmoddi4(void); extern void __udivsi3(void); extern void __umodsi3(void); +extern void abort(void); extern void ret_from_exception(void); extern void fpundefinstr(void); @@ -106,7 +108,9 @@ /* platform dependent support */ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(udelay); +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__ndelay); +EXPORT_SYMBOL(__const_delay); #ifdef CONFIG_CPU_32 EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(__iounmap); @@ -189,6 +193,7 @@ EXPORT_SYMBOL_NOVERS(memmove); EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memscan); +EXPORT_SYMBOL_NOVERS(memchr); EXPORT_SYMBOL_NOVERS(__memzero); /* user mem (segment) */ @@ -228,6 +233,7 @@ EXPORT_SYMBOL_NOVERS(__muldi3); EXPORT_SYMBOL_NOVERS(__ucmpdi2); EXPORT_SYMBOL_NOVERS(__udivdi3); +EXPORT_SYMBOL_NOVERS(__umoddi3); EXPORT_SYMBOL_NOVERS(__udivmoddi4); EXPORT_SYMBOL_NOVERS(__udivsi3); EXPORT_SYMBOL_NOVERS(__umodsi3); diff -urN orig/arch/arm/kernel/arthur.c linux/arch/arm/kernel/arthur.c --- orig/arch/arm/kernel/arthur.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/kernel/arthur.c Sat Jun 28 23:03:43 2003 @@ -46,7 +46,7 @@ /* * Linux to Arthur signal map. */ -static unsigned long linux_to_arthur_signals[32] = { +static unsigned long arthur_invmap[32] = { [0] = 0, [SIGHUP] = -1, [SIGINT] = ARTHUR_SIGINT, @@ -97,7 +97,7 @@ .pers_low = PER_RISCOS, .pers_high = PER_RISCOS, .signal_map = arthur_to_linux_signals, - .signal_invmap = linux_to_arthur_signals, + .signal_invmap = arthur_invmap, .module = THIS_MODULE, }; diff -urN orig/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c --- orig/arch/arm/kernel/bios32.c Wed Jun 18 13:01:05 2003 +++ linux/arch/arm/kernel/bios32.c Wed Jun 18 19:29:37 2003 @@ -584,7 +584,7 @@ * pcibios_enable_device - Enable I/O and memory. * @dev: PCI device to be enabled */ -int pcibios_enable_device(struct pci_dev *dev) +int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; int idx; @@ -593,6 +593,10 @@ pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for (idx = 0; idx < 6; idx++) { + /* Only set up the requested stuff */ + if (!(mask & (1 << idx))) + continue; + r = dev->resource + idx; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available because" @@ -604,6 +608,13 @@ if (r->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } + + /* + * Bridges (eg, cardbus bridges) need to be fully enabled + */ + if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) + cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { printk("PCI: enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); diff -urN orig/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S --- orig/arch/arm/kernel/calls.S Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/calls.S Sat Feb 22 11:24:58 2003 @@ -1,7 +1,7 @@ /* - * linux/arch/arm/lib/calls.h + * linux/arch/arm/kernel/calls.S * - * Copyright (C) 1995-1998 Russell King + * Copyright (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 @@ -10,7 +10,7 @@ * This file is included twice in entry-common.S */ #ifndef NR_syscalls -#define NR_syscalls 256 +#define NR_syscalls 288 #else __syscall_start: @@ -21,13 +21,13 @@ .long SYMBOL_NAME(sys_write) /* 5 */ .long SYMBOL_NAME(sys_open) .long SYMBOL_NAME(sys_close) - .long SYMBOL_NAME(sys_waitpid) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_waitpid */ .long SYMBOL_NAME(sys_creat) .long SYMBOL_NAME(sys_link) /* 10 */ .long SYMBOL_NAME(sys_unlink) .long SYMBOL_NAME(sys_execve_wrapper) .long SYMBOL_NAME(sys_chdir) - .long SYMBOL_NAME(sys_time) + .long SYMBOL_NAME(sys_time) /* used by libc4 */ .long SYMBOL_NAME(sys_mknod) /* 15 */ .long SYMBOL_NAME(sys_chmod) .long SYMBOL_NAME(sys_lchown16) @@ -36,15 +36,15 @@ .long SYMBOL_NAME(sys_lseek) /* 20 */ .long SYMBOL_NAME(sys_getpid) .long SYMBOL_NAME(sys_mount) - .long SYMBOL_NAME(sys_oldumount) + .long SYMBOL_NAME(sys_oldumount) /* used by libc4 */ .long SYMBOL_NAME(sys_setuid16) .long SYMBOL_NAME(sys_getuid16) /* 25 */ .long SYMBOL_NAME(sys_stime) .long SYMBOL_NAME(sys_ptrace) - .long SYMBOL_NAME(sys_alarm) + .long SYMBOL_NAME(sys_alarm) /* used by libc4 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_fstat */ .long SYMBOL_NAME(sys_pause) -/* 30 */ .long SYMBOL_NAME(sys_utime) +/* 30 */ .long SYMBOL_NAME(sys_utime) /* used by libc4 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_stty */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_getty */ .long SYMBOL_NAME(sys_access) @@ -62,7 +62,7 @@ /* 45 */ .long SYMBOL_NAME(sys_brk) .long SYMBOL_NAME(sys_setgid16) .long SYMBOL_NAME(sys_getgid16) - .long SYMBOL_NAME(sys_signal) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_signal */ .long SYMBOL_NAME(sys_geteuid16) /* 50 */ .long SYMBOL_NAME(sys_getegid16) .long SYMBOL_NAME(sys_acct) @@ -82,29 +82,29 @@ /* 65 */ .long SYMBOL_NAME(sys_getpgrp) .long SYMBOL_NAME(sys_setsid) .long SYMBOL_NAME(sys_sigaction) - .long SYMBOL_NAME(sys_sgetmask) - .long SYMBOL_NAME(sys_ssetmask) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_sgetmask */ + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_ssetmask */ /* 70 */ .long SYMBOL_NAME(sys_setreuid16) .long SYMBOL_NAME(sys_setregid16) .long SYMBOL_NAME(sys_sigsuspend_wrapper) .long SYMBOL_NAME(sys_sigpending) .long SYMBOL_NAME(sys_sethostname) /* 75 */ .long SYMBOL_NAME(sys_setrlimit) - .long SYMBOL_NAME(sys_old_getrlimit) + .long SYMBOL_NAME(sys_old_getrlimit) /* used by libc4 */ .long SYMBOL_NAME(sys_getrusage) .long SYMBOL_NAME(sys_gettimeofday) .long SYMBOL_NAME(sys_settimeofday) /* 80 */ .long SYMBOL_NAME(sys_getgroups16) .long SYMBOL_NAME(sys_setgroups16) - .long SYMBOL_NAME(old_select) + .long SYMBOL_NAME(old_select) /* used by libc4 */ .long SYMBOL_NAME(sys_symlink) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_lstat */ /* 85 */ .long SYMBOL_NAME(sys_readlink) .long SYMBOL_NAME(sys_uselib) .long SYMBOL_NAME(sys_swapon) .long SYMBOL_NAME(sys_reboot) - .long SYMBOL_NAME(old_readdir) -/* 90 */ .long SYMBOL_NAME(old_mmap) + .long SYMBOL_NAME(old_readdir) /* used by libc4 */ +/* 90 */ .long SYMBOL_NAME(old_mmap) /* used by libc4 */ .long SYMBOL_NAME(sys_munmap) .long SYMBOL_NAME(sys_truncate) .long SYMBOL_NAME(sys_ftruncate) @@ -240,23 +240,37 @@ .long SYMBOL_NAME(sys_ni_syscall) /* Security */ .long SYMBOL_NAME(sys_gettid) /* 225 */ .long SYMBOL_NAME(sys_readahead) - .long SYMBOL_NAME(sys_ni_syscall) /* sys_setxattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_lsetxattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_fsetxattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_getxattr */ -/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_lgetxattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_fgetxattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_listxattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_llistxattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_flistxattr */ -/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_removexattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_lremovexattr */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_fremovexattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* setxattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* lsetxattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* fsetxattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* getxattr */ +/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* lgetxattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* fgetxattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* listxattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* llistxattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* flistxattr */ +/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* removexattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* lremovexattr */ + .long SYMBOL_NAME(sys_ni_syscall) /* fremovexattr */ .long SYMBOL_NAME(sys_tkill) - /* - * Please check 2.5 _before_ adding calls here, - * and copy changes to rmk@arm.linux.org.uk. Thanks. - */ + .long SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */ +/* 240 */ .long SYMBOL_NAME(sys_ni_syscall) /* futex */ + .long SYMBOL_NAME(sys_ni_syscall) /* sched_setaffinity */ + .long SYMBOL_NAME(sys_ni_syscall) /* sched_getaffinity */ + .long SYMBOL_NAME(sys_ni_syscall) /* io_setup */ + .long SYMBOL_NAME(sys_ni_syscall) /* io_destroy */ +/* 245 */ .long SYMBOL_NAME(sys_ni_syscall) /* io_getevents */ + .long SYMBOL_NAME(sys_ni_syscall) /* io_submit */ + .long SYMBOL_NAME(sys_ni_syscall) /* io_cancel */ + .long SYMBOL_NAME(sys_ni_syscall) /* exit_group */ + .long SYMBOL_NAME(sys_ni_syscall) /* lookup_dcookie */ +/* 250 */ .long SYMBOL_NAME(sys_ni_syscall) /* epoll_create */ + .long SYMBOL_NAME(sys_ni_syscall) /* epoll_ctl */ + .long SYMBOL_NAME(sys_ni_syscall) /* epoll_wait */ + .long SYMBOL_NAME(sys_ni_syscall) /* remap_file_pages */ + .long SYMBOL_NAME(sys_ni_syscall) /* set_thread_area */ +/* 255 */ .long SYMBOL_NAME(sys_ni_syscall) /* get_thread_area */ + .long SYMBOL_NAME(sys_ni_syscall) /* set_tid_address */ __syscall_end: .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 diff -urN orig/arch/arm/kernel/compat.c linux/arch/arm/kernel/compat.c --- orig/arch/arm/kernel/compat.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/compat.c Thu Sep 5 20:56:38 2002 @@ -33,18 +33,35 @@ return tag; } -static void __init build_tag_list(struct param_struct *params, void *taglist, int mem_init) +static void __init build_tag_list(struct param_struct *params, void *taglist) { struct tag *tag = taglist; - printk(KERN_DEBUG "Converting old-style param struct to taglist\n"); - if (params->u1.s.page_size != PAGE_SIZE) { printk(KERN_WARNING "Warning: bad configuration page, " "trying to continue\n"); return; } + printk(KERN_DEBUG "Converting old-style param struct to taglist\n"); + +#ifdef CONFIG_ARCH_NETWINDER + if (params->u1.s.nr_pages != 0x02000 && + params->u1.s.nr_pages != 0x04000 && + params->u1.s.nr_pages != 0x08000 && + params->u1.s.nr_pages != 0x10000) { + printk(KERN_WARNING "Warning: bad NeTTrom parameters " + "detected, using defaults\n"); + + params->u1.s.nr_pages = 0x1000; /* 16MB */ + params->u1.s.ramdisk_size = 0; + params->u1.s.flags = FLAG_READONLY; + params->u1.s.initrd_start = 0; + params->u1.s.initrd_size = 0; + params->u1.s.rd_start = 0; + } +#endif + tag->hdr.tag = ATAG_CORE; tag->hdr.size = tag_size(tag_core); tag->u.core.flags = params->u1.s.flags & FLAG_READONLY; @@ -76,17 +93,15 @@ tag->hdr.size = tag_size(tag_revision); tag->u.revision.rev = params->u1.s.system_rev; - if (mem_init) { #ifdef CONFIG_ARCH_ACORN - if (machine_is_riscpc()) { - int i; - for (i = 0; i < 4; i++) - tag = memtag(tag, PHYS_OFFSET + (i << 26), - params->u1.s.pages_in_bank[i] * PAGE_SIZE); - } else + if (machine_is_riscpc()) { + int i; + for (i = 0; i < 4; i++) + tag = memtag(tag, PHYS_OFFSET + (i << 26), + params->u1.s.pages_in_bank[i] * PAGE_SIZE); + } else #endif - tag = memtag(tag, PHYS_OFFSET, params->u1.s.nr_pages * PAGE_SIZE); - } + tag = memtag(tag, PHYS_OFFSET, params->u1.s.nr_pages * PAGE_SIZE); #ifdef CONFIG_FOOTBRIDGE if (params->u1.s.mem_fclk_21285) { @@ -97,6 +112,23 @@ } #endif +#ifdef CONFIG_ARCH_EBSA285 + if (machine_is_ebsa285()) { + tag = tag_next(tag); + tag->hdr.tag = ATAG_VIDEOTEXT; + tag->hdr.size = tag_size(tag_videotext); + tag->u.videotext.x = params->u1.s.video_x; + tag->u.videotext.y = params->u1.s.video_y; + tag->u.videotext.video_page = 0; + tag->u.videotext.video_mode = 0; + tag->u.videotext.video_cols = params->u1.s.video_num_cols; + tag->u.videotext.video_ega_bx = 0; + tag->u.videotext.video_lines = params->u1.s.video_num_rows; + tag->u.videotext.video_isvga = 1; + tag->u.videotext.video_points = 8; + } +#endif + #ifdef CONFIG_ARCH_ACORN tag = tag_next(tag); tag->hdr.tag = ATAG_ACORN; @@ -114,14 +146,22 @@ strcpy(tag->u.cmdline.cmdline, params->commandline); tag = tag_next(tag); - tag->hdr.tag = 0; + tag->hdr.tag = ATAG_NONE; tag->hdr.size = 0; memmove(params, taglist, ((int)tag) - ((int)taglist) + sizeof(struct tag_header)); } -void __init convert_to_tag_list(struct param_struct *params, int mem_init) +void __init convert_to_tag_list(struct tag *tags) +{ + struct param_struct *params = (struct param_struct *)tags; + build_tag_list(params, ¶ms->u2); +} + +void __init squash_mem_tags(struct tag *tag) { - build_tag_list(params, ¶ms->u2, mem_init); + for (; tag->hdr.size; tag = tag_next(tag)) + if (tag->hdr.tag == ATAG_MEM) + tag->hdr.tag = ATAG_NONE; } diff -urN orig/arch/arm/kernel/debug-armv.S linux/arch/arm/kernel/debug-armv.S --- orig/arch/arm/kernel/debug-armv.S Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/debug-armv.S Fri Jun 13 22:37:32 2003 @@ -20,9 +20,20 @@ * printk isn't working). For DEBUGGING ONLY!!! Do not leave * references to these in a production kernel! */ -#if defined(CONFIG_ARCH_RPC) +#if defined(CONFIG_ARCH_RPC) || defined(CONFIG_ARCH_RISCSTATION) .macro addruart,rx - mov \rx, #0xe0000000 + +/* note, errors can occur in the head code BEFORE the memory map has been + * setup (and therefore the mapping for the IO) so the #if statement allows + * the address of the uart to be changed to the physical address instead of + * the logical + * + * (bjd) + */ + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + movne \rx, #0xe0000000 + moveq \rx, #0x03000000 orr \rx, \rx, #0x00010000 orr \rx, \rx, #0x00000fe0 .endm @@ -66,7 +77,7 @@ tst \rd, #0x10 beq 1001b .endm - + #elif defined(CONFIG_ARCH_SHARK) .macro addruart,rx mov \rx, #0xe0000000 @@ -287,6 +298,30 @@ tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy bne 1001b .endm +#elif defined(CONFIG_ARCH_AT91RM9200) + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldreq \rx, =AT91C_BASE_SYS @ System peripherals (phys address) + ldrne \rx, =AT91C_VA_BASE_SYS @ System peripherals (virt address) + .endm + + .macro senduart,rd,rx + strb \rd, [\rx, #DBGU_THR] @ DBGU_THR + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #DBGU_CSR] @ DBGU_CSR + tst \rd, #AT91C_DBGU_TXRDY @ DBGU_TXRDY = 1 when ready to transmit + beq 1001b + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #DBGU_CSR] @ DBGU_CSR + tst \rd, #AT91C_DBGU_TXEMPTY @ DBGU_TXEMPTY = 1 when transmission complete + beq 1001b + .endm #elif defined(CONFIG_ARCH_CLPS711X) @@ -322,6 +357,21 @@ bne 1001b 1002: .endm +#elif defined(CONFIG_ARCH_OMAHA) + +#include + + .macro addruart,rx + .endm + + .macro senduart,rd,rx + .endm + + .macro waituart,rd,rx + .endm + + .macro busyuart,rd,rx + .endm #elif defined(CONFIG_ARCH_ANAKIN) @@ -365,7 +415,7 @@ tst \rx, #1 @ MMU enabled? ldr \rx, =EXC_UART00_BASE @ physical base address orrne \rx, \rx, #0xff000000 @ virtual base - orrne \rx, \rx, #0x00f00000 + orrne \rx, \rx, #0x00f00000 .endm .macro senduart,rd,rx @@ -385,6 +435,41 @@ bne 1001b .endm +#elif defined(CONFIG_ARCH_MX1ADS) + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x00000000 @ physical + movne \rx, #0xf0000000 @ virtual + orr \rx, \rx, #0x00200000 + orr \rx, \rx, #0x00006000 @ UART1 offset + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0x40] @ TXDATA + .endm + + .macro waituart,rd,rx +#if 0 +/* REVISIT: This isn't right. I believe we should be checking CTS here instead + * to see if the user has entered to pause console output. + * gdavis@mvista.com 28apr03 + */ +1001: ldr \rd, [\rx, #0x94] @ SR1 + tst \rd, #1 << 13 @ TRDY + bne 1001b @ wait until TX FIFO ready +#endif + .endm + + .macro busyuart,rd,rx +1002: ldr \rd, [\rx, #0x98] @ SR2 + tst \rd, #1 << 3 @ TXDC + beq 1002b @ wait until transmit done + .endm + + + #else #error Unknown architecture #endif diff -urN orig/arch/arm/kernel/dma-arc.c linux/arch/arm/kernel/dma-arc.c --- orig/arch/arm/kernel/dma-arc.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/kernel/dma-arc.c Sun Sep 15 12:54:03 2002 @@ -34,14 +34,14 @@ extern void fdc1772_setupdma(unsigned int count,unsigned int addr); unsigned long flags; DPRINTK("enable_dma fdc1772 data read\n"); - save_flags(flags); - clf(); + local_save_flags(flags); + __clf(); memcpy ((void *)0x1c, (void *)&fdc1772_dma_read, &fdc1772_dma_read_end - &fdc1772_dma_read); fdc1772_setupdma(dma->buf.length, dma->buf.address); /* Sets data pointer up */ enable_fiq(FIQ_FLOPPYDATA); - restore_flags(flags); + local_irq_restore(flags); } break; @@ -50,14 +50,14 @@ extern void fdc1772_setupdma(unsigned int count,unsigned int addr); unsigned long flags; DPRINTK("enable_dma fdc1772 data write\n"); - save_flags(flags); - clf(); + local_save_flags(flags); + __clf(); memcpy ((void *)0x1c, (void *)&fdc1772_dma_write, &fdc1772_dma_write_end - &fdc1772_dma_write); fdc1772_setupdma(dma->buf.length, dma->buf.address); /* Sets data pointer up */ enable_fiq(FIQ_FLOPPYDATA; - restore_flags(flags); + local_irq_restore(flags); } break; default: @@ -81,14 +81,14 @@ DPRINTK("arc_floppy_cmdend_enable_dma\n"); /*printk("enable_dma fdc1772 command end FIQ\n");*/ - save_flags(flags); - clf(); + local_save_flags(flags); + __clf(); /* B fdc1772_comendhandler */ *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); - restore_flags(flags); + local_irq_restore(flags); } static int arc_floppy_cmdend_get_dma_residue(dmach_t channel, dma_t *dma) diff -urN orig/arch/arm/kernel/dma-riscstation.c linux/arch/arm/kernel/dma-riscstation.c --- orig/arch/arm/kernel/dma-riscstation.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/kernel/dma-riscstation.c Sun Sep 15 20:18:44 2002 @@ -0,0 +1,113 @@ +/* + * linux/arch/arm/kernel/dma-riscstation.c + * + * Copyright (C) 1998 Russell King + * Copyright (C) 2002 Ben Dooks / Simtec Electronics + * + * 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. + * + * DMA functions specific to RiscStatiun architecture + * + * sliced down version of the RiscPC DMA code by RMK + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct fiq_handler fh = { + name: "floppydma" +}; + +static void floppy_enable_dma(dmach_t channel, dma_t *dma) +{ + void *fiqhandler_start; + unsigned int fiqhandler_length; + struct pt_regs regs; + + if (dma->dma_mode == DMA_MODE_READ) { + extern unsigned char floppy_fiqin_start, floppy_fiqin_end; + fiqhandler_start = &floppy_fiqin_start; + fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; + } else { + extern unsigned char floppy_fiqout_start, floppy_fiqout_end; + fiqhandler_start = &floppy_fiqout_start; + fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; + } + + regs.ARM_r9 = dma->buf.length; + regs.ARM_r10 = (unsigned long)dma->buf.address; + regs.ARM_fp = FLOPPYDMA_BASE; + + if (claim_fiq(&fh)) { + printk("floppydma: couldn't claim FIQ.\n"); + return; + } + + set_fiq_handler(fiqhandler_start, fiqhandler_length); + set_fiq_regs(®s); + enable_fiq(dma->dma_irq); +} + +static void floppy_disable_dma(dmach_t channel, dma_t *dma) +{ + disable_fiq(dma->dma_irq); + release_fiq(&fh); +} + +static int floppy_get_residue(dmach_t channel, dma_t *dma) +{ + struct pt_regs regs; + get_fiq_regs(®s); + return regs.ARM_r9; +} + +static struct dma_ops floppy_dma_ops = { + type: "FIQDMA", + enable: floppy_enable_dma, + disable: floppy_disable_dma, + residue: floppy_get_residue, +}; + +/* + * This is virtual DMA - we don't need anything here. + */ +static void sound_enable_disable_dma(dmach_t channel, dma_t *dma) +{ +} + +static struct dma_ops sound_dma_ops = { + type: "VIRTUAL", + enable: sound_enable_disable_dma, + disable: sound_enable_disable_dma, +}; + +void __init arch_dma_init(dma_t *dma) +{ +#if 0 + iomd_writeb(0, IOMD_IO0CR); + iomd_writeb(0, IOMD_IO1CR); + iomd_writeb(0, IOMD_IO2CR); + iomd_writeb(0, IOMD_IO3CR); + + iomd_writeb(0xa0, IOMD_DMATCR); +#endif + + dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA; + dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops; + dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops; +} diff -urN orig/arch/arm/kernel/dma-rpc.c linux/arch/arm/kernel/dma-rpc.c --- orig/arch/arm/kernel/dma-rpc.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/kernel/dma-rpc.c Sat Feb 22 11:40:58 2003 @@ -91,76 +91,40 @@ sg->length |= flags; } -static inline void iomd_setup_dma_a(struct scatterlist *sg, dma_t *dma) -{ - iomd_writel(sg->dma_address, dma->dma_base + CURA); - iomd_writel(sg->length, dma->dma_base + ENDA); -} - -static inline void iomd_setup_dma_b(struct scatterlist *sg, dma_t *dma) -{ - iomd_writel(sg->dma_address, dma->dma_base + CURB); - iomd_writel(sg->length, dma->dma_base + ENDB); -} - static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) { dma_t *dma = (dma_t *)dev_id; - unsigned int status = 0, no_buffer = dma->sg == NULL; + unsigned long base = dma->dma_base; do { - switch (dma->state) { - case state_prog_a: - iomd_get_next_sg(&dma->cur_sg, dma); - iomd_setup_dma_a(&dma->cur_sg, dma); - dma->state = state_wait_a; - - case state_wait_a: - status = iomd_readb(dma->dma_base + ST); - switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { - case DMA_ST_OFL|DMA_ST_INT: - iomd_get_next_sg(&dma->cur_sg, dma); - iomd_setup_dma_a(&dma->cur_sg, dma); - break; - - case DMA_ST_INT: - iomd_get_next_sg(&dma->cur_sg, dma); - iomd_setup_dma_b(&dma->cur_sg, dma); - dma->state = state_wait_b; - break; - - case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB: - iomd_setup_dma_b(&dma->cur_sg, dma); - dma->state = state_wait_b; - break; - } + unsigned int status; + + status = iomd_readb(base + ST); + if (!(status & DMA_ST_INT)) + return; + + if (status & DMA_ST_OFL && !dma->sg) + break; + + 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); break; - case state_wait_b: - status = iomd_readb(dma->dma_base + ST); - switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { - case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB: - iomd_get_next_sg(&dma->cur_sg, dma); - iomd_setup_dma_b(&dma->cur_sg, dma); - break; - - case DMA_ST_INT|DMA_ST_AB: - iomd_get_next_sg(&dma->cur_sg, dma); - iomd_setup_dma_a(&dma->cur_sg, dma); - dma->state = state_wait_a; - break; - - case DMA_ST_OFL|DMA_ST_INT: - iomd_setup_dma_a(&dma->cur_sg, dma); - dma->state = state_wait_a; - 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); break; } - } while (dma->sg && (status & DMA_ST_INT)); + } while (1); - if (no_buffer) - disable_irq(irq); + iomd_writeb(0, base + CR); + disable_irq(irq); } static int iomd_request_dma(dmach_t channel, dma_t *dma) @@ -194,7 +158,6 @@ } iomd_writeb(DMA_CR_C, dma_base + CR); - dma->state = state_prog_a; } if (dma->dma_mode == DMA_MODE_READ) @@ -207,11 +170,15 @@ static void iomd_disable_dma(dmach_t channel, dma_t *dma) { unsigned long dma_base = dma->dma_base; + unsigned long flags; unsigned int ctrl; - disable_irq(dma->dma_irq); + local_irq_save(flags); ctrl = iomd_readb(dma_base + CR); + if (ctrl & DMA_CR_E) + disable_irq(dma->dma_irq); iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR); + local_irq_restore(flags); } static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) diff -urN orig/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c --- orig/arch/arm/kernel/dma.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/dma.c Sun Sep 15 16:08:52 2002 @@ -119,6 +119,10 @@ { dma_t *dma = dma_chan + channel; + if (dma->active) + printk(KERN_ERR "dma%d: altering DMA SG while " + "DMA active\n", channel); + dma->sg = sg; dma->sgcount = nr_sg; dma->using_sg = 1; @@ -217,6 +221,14 @@ BUG(); } +/* + * Is the specified DMA channel active? + */ +int dma_channel_active(dmach_t channel) +{ + return dma_chan[channel].active; +} + void set_dma_page(dmach_t channel, char pagenr) { printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel); @@ -272,6 +284,7 @@ GLOBAL_ALIAS(set_dma_sg, get_dma_residue); GLOBAL_ALIAS(set_dma_speed, get_dma_residue); GLOBAL_ALIAS(init_dma, get_dma_residue); +GLOBAL_ALIAS(dma_channel_active, get_dma_residue); #endif @@ -286,3 +299,6 @@ EXPORT_SYMBOL(get_dma_residue); EXPORT_SYMBOL(set_dma_sg); EXPORT_SYMBOL(set_dma_speed); +EXPORT_SYMBOL(dma_channel_active); + +EXPORT_SYMBOL(dma_spin_lock); diff -urN orig/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c --- orig/arch/arm/kernel/ecard.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/kernel/ecard.c Thu Jun 26 08:40:55 2003 @@ -38,7 +38,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -55,7 +58,7 @@ enum req { req_readbytes, - req_reset_all + req_reset }; struct ecard_request { @@ -136,14 +139,11 @@ #define POD_INT_ADDR(x) ((volatile unsigned char *)\ ((BUS_ADDR((x)) - IO_BASE) + IO_START)) -static inline void ecard_task_reset(void) +static inline void ecard_task_reset(struct ecard_request *req) { - ecard_t *ec; - - for (ec = cards; ec; ec = ec->next) - if (ec->loader) - ecard_loader_reset(POD_INT_ADDR(ec->podaddr), - ec->loader); + struct expansion_card *ec = req->ec; + if (ec->loader) + ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader); } static void @@ -223,8 +223,8 @@ ecard_task_readbytes(req); break; - case req_reset_all: - ecard_task_reset(); + case req_reset: + ecard_task_reset(req); break; } } @@ -371,60 +371,6 @@ /* ======================= Mid-level card control ===================== */ -/* - * This function is responsible for resetting the expansion cards to a - * sensible state immediately prior to rebooting the system. This function - * has process state (keventd), so we can sleep. - * - * Possible "val" values here: - * SYS_RESTART - restarting system - * SYS_HALT - halting system - * SYS_POWER_OFF - powering down system - * - * We ignore all calls, unless it is a SYS_RESTART call - power down/halts - * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again. - */ -static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v) -{ - struct ecard_request req; - - if (val != SYS_RESTART) - return 0; - - /* - * Disable the expansion card interrupt - */ - disable_irq(IRQ_EXPANSIONCARD); - - /* - * If we have any expansion card loader code which will handle - * the reset for us, call it now. - */ - req.req = req_reset_all; - ecard_call(&req); - - /* - * Disable the expansion card interrupt again, just to be sure. - */ - disable_irq(IRQ_EXPANSIONCARD); - - /* - * Finally, reset the expansion card interrupt mask to - * all enable (RISC OS doesn't set this) - */ -#ifdef HAS_EXPMASK - have_expmask = ~0; - __raw_writeb(have_expmask, EXPMASK_ENABLE); -#endif - return 0; -} - -static struct notifier_block ecard_reboot_notifier = { - .notifier_call = ecard_reboot, -}; - - - static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) { @@ -628,8 +574,7 @@ ec->irqaddr, ec->irqmask, *ec->irqaddr); } -static void -ecard_check_lockup(void) +static void ecard_check_lockup(void) { static int last, lockup; ecard_t *ec; @@ -757,8 +702,7 @@ printk(KERN_WARNING "Wild interrupt from backplane (masks)\n"); } -static void __init -ecard_probeirqhw(void) +static void __init ecard_probeirqhw(void) { ecard_t *ec; int found; @@ -785,7 +729,7 @@ __raw_writeb(have_expmask, EXPMASK_ENABLE); } #else -#define ecard_probeirqhw() +#define ecard_probeirqhw() do { } while (0) #endif #ifndef IO_EC_MEMC8_BASE @@ -896,6 +840,57 @@ get_ecard_dev_info); } +#define ec_set_resource(ec,nr,st,sz,flg) \ + do { \ + (ec)->resource[nr].name = ec->name; \ + (ec)->resource[nr].start = st; \ + (ec)->resource[nr].end = (st) + (sz) - 1; \ + (ec)->resource[nr].flags = flg; \ + } while (0) + +static void __init ecard_init_resources(struct expansion_card *ec) +{ + unsigned long base = PODSLOT_IOC4_BASE; + unsigned int slot = ec->slot_no; + int i; + + if (slot < 4) { + ec_set_resource(ec, ECARD_RES_MEMC, + PODSLOT_MEMC_BASE + (slot << 14), + PODSLOT_MEMC_SIZE, IORESOURCE_MEM); + base = PODSLOT_IOC0_BASE; + } + +#ifdef CONFIG_ARCH_RPC + if (slot < 8) { + ec_set_resource(ec, ECARD_RES_EASI, + PODSLOT_EASI_BASE + (slot << 24), + PODSLOT_EASI_SIZE, IORESOURCE_MEM); + } + + if (slot == 8) { + ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, + NETSLOT_SIZE, IORESOURCE_MEM); + } else +#endif + + for (i = 0; i < ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) { + ec_set_resource(ec, i + ECARD_RES_IOCSLOW, + base + (slot << 14) + (i << 19), + PODSLOT_IOC_SIZE, IORESOURCE_MEM); + } + + for (i = 0; i < ECARD_NUM_RESOURCES; i++) { + if (ec->resource[i].start && + request_resource(&iomem_resource, &ec->resource[i])) { + printk(KERN_ERR "ecard%d: resource(s) not available\n", + ec->slot_no); + ec->resource[i].end -= ec->resource[i].start; + ec->resource[i].start = 0; + } + } +} + /* * Probe for an expansion card. * @@ -964,21 +959,26 @@ break; } - ec->irq = 32 + slot; -#ifdef IO_EC_MEMC8_BASE - if (slot == 8) - ec->irq = 11; -#endif + snprintf(ec->name, sizeof(ec->name), "ecard %04x:%04x", + ec->cid.manufacturer, ec->cid.product); + + ecard_init_resources(ec); + /* * hook the interrupt handlers */ - if (ec->irq != 0 && ec->irq >= 32) { + if (slot < 8) { + ec->irq = 32 + slot; irq_desc[ec->irq].mask_ack = ecard_disableirq; irq_desc[ec->irq].mask = ecard_disableirq; irq_desc[ec->irq].unmask = ecard_enableirq; irq_desc[ec->irq].valid = 1; } +#ifdef IO_EC_MEMC8_BASE + if (slot == 8) + ec->irq = 11; +#endif #ifdef CONFIG_ARCH_RPC /* On RiscPC, only first two slots have DMA capability */ if (slot < 2) @@ -1012,7 +1012,7 @@ finding_pos = finding_pos->next; for (; finding_pos; finding_pos = finding_pos->next) { - if (finding_pos->claimed) + if (finding_pos->claimed || finding_pos->driver) continue; if (!cids) { @@ -1062,11 +1062,6 @@ { int slot; - /* - * Register our reboot notifier - */ - register_reboot_notifier(&ecard_reboot_notifier); - #ifdef CONFIG_CPU_32 init_waitqueue_head(&ecard_wait); #endif @@ -1093,7 +1088,162 @@ ecard_proc_init(); } +/* + * ECARD driver functions + */ +static const struct ecard_id * +ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec) +{ + int i; + + for (i = 0; ids[i].manufacturer != 65535; i++) + if (ec->cid.manufacturer == ids[i].manufacturer && + ec->cid.product == ids[i].product) + return ids + i; + + return NULL; +} + +static int ecard_drv_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + struct ecard_driver *drv = ec->driver; + int ret; + + ecard_claim(ec); + ret = drv->probe(ec, id); + if (ret) + ecard_release(ec); + return ret; +} + +static int ecard_drv_remove(struct expansion_card *ec) +{ + struct ecard_driver *drv = ec->driver; + + drv->remove(ec); + ecard_release(ec); + + return 0; +} + +/* + * Before rebooting, we must make sure that the expansion card is in a + * sensible state, so it can be re-detected. This means that the first + * page of the ROM must be visible. We call the expansion cards reset + * handler, if any. + */ +static void ecard_drv_shutdown(struct expansion_card *ec) +{ + struct ecard_driver *drv = ec->driver; + struct ecard_request req; + + if (drv && drv->shutdown) + drv->shutdown(ec); + ecard_release(ec); + req.req = req_reset; + req.ec = ec; + ecard_call(&req); +} + +int ecard_register_driver(struct ecard_driver *drv) +{ + struct expansion_card *ec; + int ret, found = 0; + + for (ec = cards; ec; ec = ec->next) { + const struct ecard_id *id; + + if (ec->driver || ec->claimed) + continue; + + if (drv->id_table) { + id = ecard_match_device(drv->id_table, ec); + ret = id != NULL; + } else { + id = NULL; + ret = ec->cid.id == drv->id; + } + + if (ret) { + ec->driver = drv; + ret = ecard_drv_probe(ec, id); + if (ret) { + ec->driver = NULL; + } else { + found++; + } + } + } + + return found ? 0 : -ENODEV; +} + +void ecard_remove_driver(struct ecard_driver *drv) +{ + struct expansion_card *ec; + + for (ec = cards; ec; ec = ec->next) + if (ec->driver == drv) { + ecard_drv_remove(ec); + ec->driver = NULL; + } +} + +/* + * This function is responsible for resetting the expansion cards to a + * sensible state immediately prior to rebooting the system. This function + * has process state (keventd), so we can sleep. + * + * Possible "val" values here: + * SYS_RESTART - restarting system + * SYS_HALT - halting system + * SYS_POWER_OFF - powering down system + * + * We ignore all calls, unless it is a SYS_RESTART call - power down/halts + * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again. + */ +static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v) +{ + struct expansion_card *ec; + + if (val != SYS_RESTART) + return 0; + + for (ec = cards; ec; ec = ec->next) + if (ec->driver || ec->claimed) + ecard_drv_shutdown(ec); + + /* + * Disable the expansion card interrupt + */ + disable_irq(IRQ_EXPANSIONCARD); + + /* + * Finally, reset the expansion card interrupt mask to + * all enable (RISC OS doesn't set this) + */ +#ifdef HAS_EXPMASK + have_expmask = ~0; + __raw_writeb(have_expmask, EXPMASK_ENABLE); +#endif + return 0; +} + +static struct notifier_block ecard_reboot_notifier = { + .notifier_call = ecard_reboot, +}; + +static int ecard_bus_init(void) +{ + register_reboot_notifier(&ecard_reboot_notifier); + return 0; +} + +__initcall(ecard_bus_init); + EXPORT_SYMBOL(ecard_startfind); EXPORT_SYMBOL(ecard_find); EXPORT_SYMBOL(ecard_readchunk); EXPORT_SYMBOL(ecard_address); +EXPORT_SYMBOL(ecard_register_driver); +EXPORT_SYMBOL(ecard_remove_driver); diff -urN orig/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- orig/arch/arm/kernel/entry-armv.S Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/entry-armv.S Fri Jun 13 22:19:08 2003 @@ -187,11 +187,10 @@ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov r4, #0xe0000000 - orr r4, r4, #0x20 mov \irqstat, #0x0C - strb \irqstat, [r4] @outb(0x0C, 0x20) /* Poll command */ - ldrb \irqnr, [r4] @irq = inb(0x20) & 7 + strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */ + ldrb \irqnr, [r4, #0x20] @irq = inb(0x20) & 7 and \irqstat, \irqnr, #0x80 teq \irqstat, #0 beq 43f @@ -199,8 +198,8 @@ teq \irqnr, #2 bne 44f 43: mov \irqstat, #0x0C - strb \irqstat, [r4, #0x80] @outb(0x0C, 0xA0) /* Poll command */ - ldrb \irqnr, [r4, #0x80] @irq = (inb(0xA0) & 7) + 8 + strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */ + ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8 and \irqstat, \irqnr, #0x80 teq \irqstat, #0 beq 44f @@ -454,6 +453,23 @@ .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_AT91RM9200) +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =(AT91C_VA_BASE_SYS) @ base virtual address of SYS peripherals + ldr \irqnr, [\base, #AIC_IVR] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt) + ldr \irqstat, [\base, #AIC_ISR] @ read interrupt source number + teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt + streq \tmp, [\base, #AIC_EOICR] @ not going to be handled further, then ACK it now. + .endm + + .macro irq_prio_table + .endm + #elif defined(CONFIG_ARCH_MX1ADS) .macro disable_fiq @@ -479,6 +495,32 @@ .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_OMAHA) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + /* Read all interrupts pending... */ + ldr \irqnr, =IO_ADDRESS(PLAT_PERIPHERAL_BASE) + OMAHA_INTPND + ldr \irqstat, [\irqnr] /* INTPND */ + + /* All pending irqs are now in \irqstat */ + mov \irqnr, #0 +1001: tst \irqstat, #1 + bne 1002f + add \irqnr, \irqnr, #1 + mov \irqstat, \irqstat, lsr #1 + cmp \irqnr, #MAXIRQNUM + bcc 1001b +1002: /* EQ will be set if we reach MAXIRQNUM */ + + .endm + + .macro irq_prio_table + .endm + #elif defined(CONFIG_ARCH_CLPS711X) #include @@ -611,16 +653,6 @@ and r2, r6, #31 @ int mode b SYMBOL_NAME(bad_mode) -#if defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE - /* The FPE is always present */ - .equ fpe_not_present, 0 -#else -wfs_mask_data: .word 0x0e200110 @ WFS/RFS - .word 0x0fef0fff - .word 0x0d000100 @ LDF [sp]/STF [sp] - .word 0x0d000100 @ LDF [fp]/STF [fp] - .word 0x0f000f00 - /* We get here if an undefined instruction happens and the floating * point emulator is not present. If the offending instruction was * a WFS, we just perform a normal return as if we had emulated the @@ -628,30 +660,7 @@ * to run so that the emulator module proper can be loaded. --philb */ fpe_not_present: - adr r10, wfs_mask_data - ldmia r10, {r4, r5, r6, r7, r8} - ldr r10, [sp, #S_PC] @ Load PC - sub r10, r10, #4 - mask_pc r10, r10 - ldrt r10, [r10] @ get instruction - and r5, r10, r5 - teq r5, r4 @ Is it WFS? - moveq pc, r9 - and r5, r10, r8 - teq r5, r6 @ Is it LDF/STF on sp or fp? - teqne r5, r7 - movne pc, lr - tst r10, #0x00200000 @ Does it have WB - moveq pc, r9 - and r4, r10, #255 @ get offset - and r6, r10, #0x000f0000 - tst r10, #0x00800000 @ +/- - ldr r5, [sp, r6, lsr #14] @ Load reg - rsbeq r4, r4, #0 - add r5, r5, r4, lsl #2 - str r5, [sp, r6, lsr #14] @ Save reg - mov pc, r9 -#endif + mov pc, lr /* * SVC mode handlers @@ -703,11 +712,13 @@ @ routine called with r0 = irq number, r1 = struct pt_regs * @ adrsvc ne, lr, 1b - bne do_IRQ + bne asm_do_IRQ ldr r0, [sp, #S_PSR] @ irqs are already disabled msr spsr, r0 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + .ltorg + .align 5 __und_svc: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ save r0 - r12 @@ -807,11 +818,13 @@ @ @ routine called with r0 = irq number, r1 = struct pt_regs * @ - bne do_IRQ + bne asm_do_IRQ mov why, #0 get_current_task tsk b ret_to_user + .ltorg + .align 5 __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go stmia sp, {r0 - r12} @ Save r0 - r12 @@ -822,6 +835,8 @@ stmdb r8, {sp, lr}^ @ Save user sp, lr alignment_trap r4, r7, __temp_und zero_fp + tst r6, #T_BIT @ Thumb mode + bne fpundefinstr adrsvc al, r9, ret_from_exception @ r9 = normal FP return adrsvc al, lr, fpundefinstr @ lr = undefined instr return @@ -859,8 +874,9 @@ * This is the return code to user mode for abort handlers */ ENTRY(ret_from_exception) - get_current_task tsk + disable_irq r1 mov why, #0 + get_current_task tsk b ret_to_user .data @@ -909,7 +925,9 @@ @ @ now branch to the relevent MODE handling routine @ - mov r13, #I_BIT | MODE_SVC + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 @@ -950,7 +968,9 @@ @ @ now branch to the relevent MODE handling routine @ - mov r13, #I_BIT | MODE_SVC + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 @@ -992,7 +1012,9 @@ @ @ now branch to the relevent MODE handling routine @ - mov r13, #I_BIT | MODE_SVC + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC msr spsr_c, r13 @ switch to SVC_32 mode ands lr, lr, #15 @@ -1033,7 +1055,9 @@ @ @ now branch to the relevent MODE handling routine @ - mov r13, #I_BIT | MODE_SVC + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 diff -urN orig/arch/arm/kernel/entry-armv.S.2 linux/arch/arm/kernel/entry-armv.S.2 --- orig/arch/arm/kernel/entry-armv.S.2 Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/kernel/entry-armv.S.2 Tue Jul 8 15:23:37 2003 @@ -0,0 +1,1189 @@ +/* + * linux/arch/arm/kernel/entry-armv.S + * + * Copyright (C) 1996,1997,1998 Russell King. + * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) + * + * 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. + * + * Low-level vector interface routines + * + * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes + * it to save wrong values... Be aware! + */ +#include +#include "entry-header.S" + + +#ifdef IOC_BASE +/* IOC / IOMD based hardware */ +#include + + .equ ioc_base_high, IOC_BASE & 0xff000000 + .equ ioc_base_low, IOC_BASE & 0x00ff0000 + .macro disable_fiq + mov r12, #ioc_base_high + .if ioc_base_low + orr r12, r12, #ioc_base_low + .endif + strb r12, [r12, #0x38] @ Disable FIQ register + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov r4, #ioc_base_high @ point at IOC + .if ioc_base_low + orr r4, r4, #ioc_base_low + .endif + ldrb \irqstat, [r4, #IOMD_IRQREQB] @ get high priority first + ldr \base, =irq_prio_h + teq \irqstat, #0 +#ifdef IOMD_BASE + ldreqb \irqstat, [r4, #IOMD_DMAREQ] @ get dma + addeq \base, \base, #256 @ irq_prio_h table size + teqeq \irqstat, #0 + bne 2406f +#endif + ldreqb \irqstat, [r4, #IOMD_IRQREQA] @ get low priority + addeq \base, \base, #256 @ irq_prio_d table size + teqeq \irqstat, #0 +#ifdef IOMD_IRQREQC + ldreqb \irqstat, [r4, #IOMD_IRQREQC] + addeq \base, \base, #256 @ irq_prio_l table size + teqeq \irqstat, #0 +#endif +#ifdef IOMD_IRQREQD + ldreqb \irqstat, [r4, #IOMD_IRQREQD] + addeq \base, \base, #256 @ irq_prio_lc table size + teqeq \irqstat, #0 +#endif +2406: ldrneb \irqnr, [\base, \irqstat] @ get IRQ number + .endm + +/* + * Interrupt table (incorporates priority). Please note that we + * rely on the order of these tables (see above code). + */ + .macro irq_prio_table +irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 +#ifdef IOMD_BASE +irq_prio_d: .byte 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 +#endif +irq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +#ifdef IOMD_IRQREQC +irq_prio_lc: .byte 24,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27 + .byte 28,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27 + .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 + .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 + .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27 + .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27 + .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 + .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 + .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 +#endif +#ifdef IOMD_IRQREQD +irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43 + .byte 44,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43 + .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 + .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 + .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43 + .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43 + .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 + .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 +#endif + .endm + +#elif defined(CONFIG_ARCH_EBSA110) + +#define IRQ_STAT 0xff000000 /* read */ + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, stat, base, tmp + mov \base, #IRQ_STAT + ldrb \stat, [\base] @ get interrupts + mov \irqnr, #0 + 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_SHARK) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov r4, #0xe0000000 + + mov \irqstat, #0x0C + strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */ + ldrb \irqnr, [r4, #0x20] @irq = inb(0x20) & 7 + and \irqstat, \irqnr, #0x80 + teq \irqstat, #0 + beq 43f + and \irqnr, \irqnr, #7 + teq \irqnr, #2 + bne 44f +43: mov \irqstat, #0x0C + strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */ + ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8 + and \irqstat, \irqnr, #0x80 + teq \irqstat, #0 + beq 44f + and \irqnr, \irqnr, #7 + add \irqnr, \irqnr, #8 +44: teq \irqstat, #0 + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_FOOTBRIDGE) +#include + + .macro disable_fiq + .endm + + .equ dc21285_high, ARMCSR_BASE & 0xff000000 + .equ dc21285_low, ARMCSR_BASE & 0x00ffffff + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov r4, #dc21285_high + .if dc21285_low + orr r4, r4, #dc21285_low + .endif + ldr \irqstat, [r4, #0x180] @ get interrupts + + mov \irqnr, #IRQ_SDRAMPARITY + tst \irqstat, #IRQ_MASK_SDRAMPARITY + bne 1001f + + tst \irqstat, #IRQ_MASK_UART_RX + movne \irqnr, #IRQ_CONRX + bne 1001f + + tst \irqstat, #IRQ_MASK_DMA1 + movne \irqnr, #IRQ_DMA1 + bne 1001f + + tst \irqstat, #IRQ_MASK_DMA2 + movne \irqnr, #IRQ_DMA2 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN0 + movne \irqnr, #IRQ_IN0 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN1 + movne \irqnr, #IRQ_IN1 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN2 + movne \irqnr, #IRQ_IN2 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN3 + movne \irqnr, #IRQ_IN3 + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI + movne \irqnr, #IRQ_PCI + bne 1001f + + tst \irqstat, #IRQ_MASK_DOORBELLHOST + movne \irqnr, #IRQ_DOORBELLHOST + bne 1001f + + tst \irqstat, #IRQ_MASK_I2OINPOST + movne \irqnr, #IRQ_I2OINPOST + bne 1001f + + tst \irqstat, #IRQ_MASK_TIMER1 + movne \irqnr, #IRQ_TIMER1 + bne 1001f + + tst \irqstat, #IRQ_MASK_TIMER2 + movne \irqnr, #IRQ_TIMER2 + bne 1001f + + tst \irqstat, #IRQ_MASK_TIMER3 + movne \irqnr, #IRQ_TIMER3 + bne 1001f + + tst \irqstat, #IRQ_MASK_UART_TX + movne \irqnr, #IRQ_CONTX + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_ABORT + movne \irqnr, #IRQ_PCI_ABORT + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_SERR + movne \irqnr, #IRQ_PCI_SERR + bne 1001f + + tst \irqstat, #IRQ_MASK_DISCARD_TIMER + movne \irqnr, #IRQ_DISCARD_TIMER + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_DPERR + movne \irqnr, #IRQ_PCI_DPERR + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_PERR + movne \irqnr, #IRQ_PCI_PERR +1001: + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_NEXUSPCI) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, =INTCONT_BASE + ldr \base, =soft_irq_mask + ldr \irqstat, [\irqstat] @ get interrupts + ldr \base, [\base] + mov \irqnr, #0 + and \irqstat, \irqstat, \base @ mask out disabled ones +1001: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + tsteq \irqnr, #32 + beq 1001b + teq \irqnr, #32 + .endm + + .macro irq_prio_table + .ltorg + .bss +ENTRY(soft_irq_mask) + .word 0 + .text + .endm + +#elif defined(CONFIG_ARCH_TBOX) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, =0xffff7000 + ldr \irqstat, [\irqstat] @ get interrupts + ldr \base, =soft_irq_mask + ldr \base, [\base] + mov \irqnr, #0 + and \irqstat, \irqstat, \base @ mask out disabled ones +1001: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + tsteq \irqnr, #32 + beq 1001b + teq \irqnr, #32 + .endm + + .macro irq_prio_table + .ltorg + .bss +ENTRY(soft_irq_mask) + .word 0 + .text + .endm + +#elif defined(CONFIG_ARCH_SA1100) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov r4, #0xfa000000 @ ICIP = 0xfa050000 + add r4, r4, #0x00050000 + ldr \irqstat, [r4] @ get irqs + ldr \irqnr, [r4, #4] @ ICMR = 0xfa050004 + ands \irqstat, \irqstat, \irqnr + mov \irqnr, #0 + beq 1001f + tst \irqstat, #0xff + moveq \irqstat, \irqstat, lsr #8 + addeq \irqnr, \irqnr, #8 + tsteq \irqstat, #0xff + moveq \irqstat, \irqstat, lsr #8 + addeq \irqnr, \irqnr, #8 + tsteq \irqstat, #0xff + moveq \irqstat, \irqstat, lsr #8 + addeq \irqnr, \irqnr, #8 + tst \irqstat, #0x0f + moveq \irqstat, \irqstat, lsr #4 + addeq \irqnr, \irqnr, #4 + tst \irqstat, #0x03 + moveq \irqstat, \irqstat, lsr #2 + addeq \irqnr, \irqnr, #2 + tst \irqstat, #0x01 + addeqs \irqnr, \irqnr, #1 +1001: + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_L7200) +#include + + .equ irq_base_addr, IO_BASE_2 + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov \irqstat, #irq_base_addr @ Virt addr IRQ regs + add \irqstat, \irqstat, #0x00001000 @ Status reg + ldr \irqstat, [\irqstat, #0] @ get interrupts + mov \irqnr, #0 +1001: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + tsteq \irqnr, #32 + beq 1001b + teq \irqnr, #32 + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_INTEGRATOR) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp +/* FIXME: should not be using soo many LDRs here */ + ldr \irqnr, =IO_ADDRESS(INTEGRATOR_IC_BASE) + ldr \irqstat, [\irqnr, #IRQ_STATUS] @ get masked status + ldr \irqnr, =IO_ADDRESS(INTEGRATOR_HDR_BASE) + ldr \irqnr, [\irqnr, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)] + orr \irqstat, \irqstat, \irqnr, lsl #INTEGRATOR_CM_INT0 + + mov \irqnr, #0 +1001: tst \irqstat, #1 + bne 1002f + add \irqnr, \irqnr, #1 + mov \irqstat, \irqstat, lsr #1 + cmp \irqnr, #22 + bcc 1001b +1002: /* EQ will be set if we reach 22 */ + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_AT91RM9200) +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =(AT91C_VA_BASE_SYS) @ base virtual address of SYS peripherals + ldr \irqnr, [\base, #AIC_IVR] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt) + ldr \irqstat, [\base, #AIC_ISR] @ read interrupt source number + teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt + streq \tmp, [\base, #AIC_EOICR] @ not going to be handled further, then ACK it now. + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_MX1ADS) + + .macro disable_fiq + .endm +#define AITC_NIVECSR 0x40 + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, =IO_ADDRESS(MX1ADS_AITC_BASE) + @ Load offset & priority of the highest priority + @ interrupt pending. + ldr \irqnr, [\irqstat, #AITC_NIVECSR] + @ Shift off the priority leaving the offset or + @ "interrupt number" + mov \irqnr, \irqnr, lsr #16 + ldr \irqstat, =1 @ dummy compare + ldr \base, =0xFFFF // invalid interrupt + cmp \irqnr, \base + bne 1001f + ldr \irqstat, =0 +1001: + tst \irqstat, #1 @ to make the condition code = TRUE + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_OMAHA) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + /* Read all interrupts pending... */ + ldr \irqnr, =IO_ADDRESS(PLAT_PERIPHERAL_BASE) + OMAHA_INTPND + ldr \irqstat, [\irqnr] /* INTPND */ + + /* All pending irqs are now in \irqstat */ + mov \irqnr, #0 +1001: tst \irqstat, #1 + bne 1002f + add \irqnr, \irqnr, #1 + mov \irqstat, \irqstat, lsr #1 + cmp \irqnr, #MAXIRQNUM + bcc 1001b +1002: /* EQ will be set if we reach MAXIRQNUM */ + + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_CLPS711X) + +#include + + .macro disable_fiq + .endm + +#if (INTSR2 - INTSR1) != (INTMR2 - INTMR1) +#error INTSR stride != INTMR stride +#endif + + .macro get_irqnr_and_base, irqnr, stat, base, mask + mov \base, #CLPS7111_BASE + ldr \stat, [\base, #INTSR1] + ldr \mask, [\base, #INTMR1] + mov \irqnr, #4 + mov \mask, \mask, lsl #16 + and \stat, \stat, \mask, lsr #16 + movs \stat, \stat, lsr #4 + bne 1001f + + add \base, \base, #INTSR2 - INTSR1 + ldr \stat, [\base, #INTSR1] + ldr \mask, [\base, #INTMR1] + mov \irqnr, #16 + mov \mask, \mask, lsl #16 + and \stat, \stat, \mask, lsr #16 + +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 */ +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE)) + ldr \irqnr,[\irqstat] + cmp \irqnr,#0 + subne \irqnr,\irqnr,#1 + + + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_ANAKIN) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov \base, #IO_BASE + mov \irqstat, #INTERRUPT_CONTROLLER + ldr \tmp, =anakin_irq_mask + ldr \irqstat, [\base, \irqstat] + ldr \tmp, [\tmp] + ands \irqstat, \irqstat, \tmp + ldrne \tmp, =anakin_active_irqs + strne \irqstat, [\tmp] + movne \irqnr, #IRQ_ANAKIN + .endm + + .macro irq_prio_table + .ltorg + .bss +ENTRY(anakin_irq_mask) + .word 0 +ENTRY(anakin_active_irqs) + .space 4 + .text + .endm + +#else +#error Unknown architecture +#endif + +/* + * Invalid mode handlers + */ +__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - lr} @ Save XXX r0 - lr + ldr r4, .LCabt + mov r1, #BAD_PREFETCH + b 1f + +__dabt_invalid: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact] + ldr r4, .LCabt + mov r1, #BAD_DATA + b 1f + +__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame + stmfd sp, {r0 - lr} @ Save r0 - lr + ldr r4, .LCirq + mov r1, #BAD_IRQ + b 1f + +__und_invalid: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - lr} + ldr r4, .LCund + mov r1, #BAD_UNDEFINSTR @ int reason + +1: zero_fp + ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0 + add r4, sp, #S_PC + stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0 + mov r0, sp + and r2, r6, #31 @ int mode + b SYMBOL_NAME(bad_mode) + +/* We get here if an undefined instruction happens and the floating + * point emulator is not present. If the offending instruction was + * a WFS, we just perform a normal return as if we had emulated the + * operation. This is a hack to allow some basic userland binaries + * to run so that the emulator module proper can be loaded. --philb + */ +fpe_not_present: + mov pc, lr + +/* + * SVC mode handlers + */ + .align 5 +__dabt_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r2, .LCabt + add r0, sp, #S_FRAME_SIZE + ldmia r2, {r2 - r4} @ get pc, cpsr + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + 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 + mov lr, pc @ processor code + ldr pc, [r4] @ call processor specific code +#else + bl cpu_data_abort +#endif + msr cpsr_c, r9 + mov r2, sp + bl SYMBOL_NAME(do_DataAbort) + mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 + ldr r0, [sp, #S_PSR] + msr spsr, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + + .align 5 +__irq_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r7, .LCirq + add r5, sp, #S_FRAME_SIZE + ldmia r7, {r7 - r9} + add r4, sp, #S_SP + mov r6, lr + stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + tst sp, #0x1000 + streq sp, [sp, -sp] +1: get_irqnr_and_base r0, r6, r5, lr + movne r1, sp + @ + @ routine called with r0 = irq number, r1 = struct pt_regs * + @ + adrsvc ne, lr, 1b + bne asm_do_IRQ + ldr r0, [sp, #S_PSR] @ irqs are already disabled + msr spsr, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + + .ltorg + + .align 5 +__und_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r7, .LCund + mov r6, lr + ldmia r7, {r7 - r9} + add r5, sp, #S_FRAME_SIZE + add r4, sp, #S_SP + stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + tst sp, #0x1000 + streq sp, [sp, -sp] + + adrsvc al, r9, 1f @ r9 = normal FP return + bl call_fpe @ lr = undefined instr return + + mov r0, r5 @ unsigned long pc + mov r1, sp @ struct pt_regs *regs + bl SYMBOL_NAME(do_undefinstr) + +1: mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 + ldr lr, [sp, #S_PSR] @ Get SVC cpsr + msr spsr, lr + ldmia sp, {r0 - pc}^ @ Restore SVC registers + + .align 5 +__pabt_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r2, .LCabt + add r0, sp, #S_FRAME_SIZE + ldmia r2, {r2 - r4} @ get pc, cpsr + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + tst sp, #0x1000 + streq sp, [sp, -sp] + mrs r9, cpsr @ Enable interrupts if they were + tst r3, #I_BIT + biceq r9, r9, #I_BIT @ previously + msr cpsr_c, r9 + mov r0, r2 @ address (pc) + mov r1, sp @ regs + bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler + mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 + ldr r0, [sp, #S_PSR] + msr spsr, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + + .align 5 +.LCirq: .word __temp_irq +.LCund: .word __temp_und +.LCabt: .word __temp_abt +#ifdef MULTI_CPU +.LCprocfns: .word SYMBOL_NAME(processor) +#endif +.LCfp: .word SYMBOL_NAME(fp_enter) + + irq_prio_table + +/* + * User mode handlers + */ + .align 5 +__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r7, .LCabt + add r5, sp, #S_PC + ldmia r7, {r2 - r4} @ Get USR pc, cpsr + stmia r5, {r2 - r4} @ Save USR pc, cpsr, old_r0 + stmdb r5, {sp, lr}^ + alignment_trap r7, r7, __temp_abt + zero_fp + tst sp, #0x1000 + streq sp, [sp, -sp] + mov r0, r2 @ remove once everyones in sync +#ifdef MULTI_CPU + ldr r4, .LCprocfns @ pass r0, r3 to + mov lr, pc @ processor code + ldr pc, [r4] @ call processor specific code +#else + bl cpu_data_abort +#endif + mov r2, #MODE_SVC + msr cpsr_c, r2 @ Enable interrupts + mov r2, sp + adrsvc al, lr, ret_from_exception + b SYMBOL_NAME(do_DataAbort) + + .align 5 +__irq_usr: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r4, .LCirq + add r8, sp, #S_PC + ldmia r4, {r5 - r7} @ get saved PC, SPSR + stmia r8, {r5 - r7} @ save pc, psr, old_r0 + stmdb r8, {sp, lr}^ + alignment_trap r4, r7, __temp_irq + zero_fp + tst sp, #0x1000 + streq sp, [sp, -sp] +1: get_irqnr_and_base r0, r6, r5, lr + movne r1, sp + adrsvc ne, lr, 1b + @ + @ routine called with r0 = irq number, r1 = struct pt_regs * + @ + bne asm_do_IRQ + mov why, #0 + get_current_task tsk + b ret_to_user + + .ltorg + + .align 5 +__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ Save r0 - r12 + ldr r4, .LCund + add r8, sp, #S_PC + ldmia r4, {r5 - r7} + stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 + stmdb r8, {sp, lr}^ @ Save user sp, lr + alignment_trap r4, r7, __temp_und + zero_fp + tst sp, #0x1000 + streq sp, [sp, -sp] + tst r6, #T_BIT @ Thumb mode + bne fpundefinstr + adrsvc al, r9, ret_from_exception @ r9 = normal FP return + adrsvc al, lr, fpundefinstr @ lr = undefined instr return + +call_fpe: get_current_task r10 + mov r8, #1 + strb r8, [r10, #TSK_USED_MATH] @ set current->used_math + ldr r4, .LCfp + add r10, r10, #TSS_FPESAVE @ r10 = workspace + ldr pc, [r4] @ Call FP module USR entry point + +fpundefinstr: mov r0, #MODE_SVC + msr cpsr_c, r0 @ Enable interrupts + mov r0, lr + mov r1, sp + adrsvc al, lr, ret_from_exception + b SYMBOL_NAME(do_undefinstr) + + .align 5 +__pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ Save r0 - r12 + ldr r4, .LCabt + add r8, sp, #S_PC + ldmia r4, {r5 - r7} @ Get USR pc, cpsr + stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 + stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr + alignment_trap r4, r7, __temp_abt + zero_fp + tst sp, #0x1000 + streq sp, [sp, -sp] + mov r0, #MODE_SVC + msr cpsr_c, r0 @ Enable interrupts + mov r0, r5 @ address (pc) + mov r1, sp @ regs + bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler + /* fall through */ +/* + * This is the return code to user mode for abort handlers + */ +ENTRY(ret_from_exception) + disable_irq r1 + mov why, #0 + get_current_task tsk + b ret_to_user + + .data +ENTRY(fp_enter) + .word fpe_not_present + .text +/* + * Register switch for ARMv3 and ARMv4 processors + * r0 = previous, r1 = next, return previous. + * previous and next are guaranteed not to be the same. + */ +ENTRY(__switch_to) + stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack + mrs ip, cpsr + str ip, [sp, #-4]! @ Save cpsr_SVC + str sp, [r0, #TSS_SAVE] @ Save sp_SVC + tst sp, #0x1000 + streq sp, [sp, -sp] + ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC + tst sp, #0x1000 + streq sp, [sp, -sp] + ldr r2, [r1, #TSS_DOMAIN] + ldr ip, [sp], #4 + mcr p15, 0, r2, c3, c0 @ Set domain register + msr spsr, ip @ Save tasks CPSR into SPSR for this return + ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously + + .section ".text.init",#alloc,#execinstr +/* + * Vector stubs. NOTE that we only align 'vector_IRQ' to a cache line boundary, + * and we rely on each stub being exactly 48 (1.5 cache lines) in size. This + * means that we only ever load two cache lines for this code, or one if we're + * lucky. We also copy this code to 0x200 so that we can use branches in the + * vectors, rather than ldr's. + */ + .align 5 +__stubs_start: +/* + * Interrupt dispatcher + * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC + */ +vector_IRQ: @ + @ save mode specific registers + @ + ldr r13, .LCsirq + sub lr, lr, #4 + str lr, [r13] @ save lr_IRQ + mrs lr, spsr + str lr, [r13, #4] @ save spsr_IRQ + @ + @ now branch to the relevent MODE handling routine + @ + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode + + and lr, lr, #15 + ldr lr, [pc, lr, lsl #2] + movs pc, lr @ Changes mode and branches + +.LCtab_irq: .word __irq_usr @ 0 (USR_26 / USR_32) + .word __irq_invalid @ 1 (FIQ_26 / FIQ_32) + .word __irq_invalid @ 2 (IRQ_26 / IRQ_32) + .word __irq_svc @ 3 (SVC_26 / SVC_32) + .word __irq_invalid @ 4 + .word __irq_invalid @ 5 + .word __irq_invalid @ 6 + .word __irq_invalid @ 7 + .word __irq_invalid @ 8 + .word __irq_invalid @ 9 + .word __irq_invalid @ a + .word __irq_invalid @ b + .word __irq_invalid @ c + .word __irq_invalid @ d + .word __irq_invalid @ e + .word __irq_invalid @ f + + .align 5 + +/* + * Data abort dispatcher - dispatches it to the correct handler for the processor mode + * Enter in ABT mode, spsr = USR CPSR, lr = USR PC + */ +vector_data: @ + @ save mode specific registers + @ + ldr r13, .LCsabt + sub lr, lr, #8 + str lr, [r13] + mrs lr, spsr + str lr, [r13, #4] + @ + @ now branch to the relevent MODE handling routine + @ + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode + + and lr, lr, #15 + ldr lr, [pc, lr, lsl #2] + movs pc, lr @ Changes mode and branches + +.LCtab_dabt: .word __dabt_usr @ 0 (USR_26 / USR_32) + .word __dabt_invalid @ 1 (FIQ_26 / FIQ_32) + .word __dabt_invalid @ 2 (IRQ_26 / IRQ_32) + .word __dabt_svc @ 3 (SVC_26 / SVC_32) + .word __dabt_invalid @ 4 + .word __dabt_invalid @ 5 + .word __dabt_invalid @ 6 + .word __dabt_invalid @ 7 + .word __dabt_invalid @ 8 + .word __dabt_invalid @ 9 + .word __dabt_invalid @ a + .word __dabt_invalid @ b + .word __dabt_invalid @ c + .word __dabt_invalid @ d + .word __dabt_invalid @ e + .word __dabt_invalid @ f + + .align 5 + +/* + * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode + * Enter in ABT mode, spsr = USR CPSR, lr = USR PC + */ +vector_prefetch: + @ + @ save mode specific registers + @ + ldr r13, .LCsabt + sub lr, lr, #4 + str lr, [r13] @ save lr_ABT + mrs lr, spsr + str lr, [r13, #4] @ save spsr_ABT + @ + @ now branch to the relevent MODE handling routine + @ + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode + + ands lr, lr, #15 + ldr lr, [pc, lr, lsl #2] + movs pc, lr + +.LCtab_pabt: .word __pabt_usr @ 0 (USR_26 / USR_32) + .word __pabt_invalid @ 1 (FIQ_26 / FIQ_32) + .word __pabt_invalid @ 2 (IRQ_26 / IRQ_32) + .word __pabt_svc @ 3 (SVC_26 / SVC_32) + .word __pabt_invalid @ 4 + .word __pabt_invalid @ 5 + .word __pabt_invalid @ 6 + .word __pabt_invalid @ 7 + .word __pabt_invalid @ 8 + .word __pabt_invalid @ 9 + .word __pabt_invalid @ a + .word __pabt_invalid @ b + .word __pabt_invalid @ c + .word __pabt_invalid @ d + .word __pabt_invalid @ e + .word __pabt_invalid @ f + + .align 5 + +/* + * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode + * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC + */ +vector_undefinstr: + @ + @ save mode specific registers + @ + ldr r13, .LCsund + str lr, [r13] @ save lr_UND + mrs lr, spsr + str lr, [r13, #4] @ save spsr_UND + @ + @ now branch to the relevent MODE handling routine + @ + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode + + and lr, lr, #15 + ldr lr, [pc, lr, lsl #2] + movs pc, lr @ Changes mode and branches + +.LCtab_und: .word __und_usr @ 0 (USR_26 / USR_32) + .word __und_invalid @ 1 (FIQ_26 / FIQ_32) + .word __und_invalid @ 2 (IRQ_26 / IRQ_32) + .word __und_svc @ 3 (SVC_26 / SVC_32) + .word __und_invalid @ 4 + .word __und_invalid @ 5 + .word __und_invalid @ 6 + .word __und_invalid @ 7 + .word __und_invalid @ 8 + .word __und_invalid @ 9 + .word __und_invalid @ a + .word __und_invalid @ b + .word __und_invalid @ c + .word __und_invalid @ d + .word __und_invalid @ e + .word __und_invalid @ f + + .align 5 + +/*============================================================================= + * Undefined FIQs + *----------------------------------------------------------------------------- + * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC + * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg. + * Basically to switch modes, we *HAVE* to clobber one register... brain + * damage alert! I don't think that we can execute any code in here in any + * other mode than FIQ... Ok you can switch to another mode, but you can't + * get out of that mode without clobbering one register. + */ +vector_FIQ: disable_fiq + subs pc, lr, #4 + +/*============================================================================= + * Address exception handler + *----------------------------------------------------------------------------- + * These aren't too critical. + * (they're not supposed to happen, and won't happen in 32-bit data mode). + */ + +vector_addrexcptn: + b vector_addrexcptn + +/* + * We group all the following data together to optimise + * for CPUs with separate I & D caches. + */ + .align 5 + +.LCvswi: .word vector_swi + +.LCsirq: .word __temp_irq +.LCsund: .word __temp_und +.LCsabt: .word __temp_abt + +__stubs_end: + + .equ __real_stubs_start, .LCvectors + 0x200 + +.LCvectors: swi SYS_ERROR0 + b __real_stubs_start + (vector_undefinstr - __stubs_start) + ldr pc, __real_stubs_start + (.LCvswi - __stubs_start) + b __real_stubs_start + (vector_prefetch - __stubs_start) + b __real_stubs_start + (vector_data - __stubs_start) + b __real_stubs_start + (vector_addrexcptn - __stubs_start) + b __real_stubs_start + (vector_IRQ - __stubs_start) + b __real_stubs_start + (vector_FIQ - __stubs_start) + +ENTRY(__trap_init) + stmfd sp!, {r4 - r6, lr} + + adr r1, .LCvectors @ set up the vectors + ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr} + stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr} + + add r2, r0, #0x200 + adr r0, __stubs_start @ copy stubs to 0x200 + adr r1, __stubs_end +1: ldr r3, [r0], #4 + str r3, [r2], #4 + cmp r0, r1 + blt 1b + LOADREGS(fd, sp!, {r4 - r6, pc}) + + .data + +/* + * Do not reorder these, and do not insert extra data between... + */ + +__temp_irq: .word 0 @ saved lr_irq + .word 0 @ saved spsr_irq + .word -1 @ old_r0 +__temp_und: .word 0 @ Saved lr_und + .word 0 @ Saved spsr_und + .word -1 @ old_r0 +__temp_abt: .word 0 @ Saved lr_abt + .word 0 @ Saved spsr_abt + .word -1 @ old_r0 + + .globl SYMBOL_NAME(cr_alignment) + .globl SYMBOL_NAME(cr_no_alignment) +SYMBOL_NAME(cr_alignment): + .space 4 +SYMBOL_NAME(cr_no_alignment): + .space 4 diff -urN orig/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S --- orig/arch/arm/kernel/entry-common.S Wed Feb 27 14:24:47 2002 +++ linux/arch/arm/kernel/entry-common.S Fri Feb 21 15:36:40 2003 @@ -34,6 +34,7 @@ * stack. */ ret_fast_syscall: + disable_irq r1 @ ensure IRQs are disabled ldr r1, [tsk, #TSK_NEED_RESCHED] ldr r2, [tsk, #TSK_SIGPENDING] teq r1, #0 @ need_resched || sigpending @@ -45,28 +46,35 @@ * Ok, we need to do extra processing, enter the slow path. */ slow: str r0, [sp, #S_R0+S_OFF]! @ returned r0 - b 1f + teq r1, #0 + beq 1f /* * "slow" syscall return path. "why" tells us if this was a real syscall. */ reschedule: bl SYMBOL_NAME(schedule) +ret_disable_irq: + disable_irq r1 @ ensure IRQs are disabled ENTRY(ret_to_user) ret_slow_syscall: ldr r1, [tsk, #TSK_NEED_RESCHED] ldr r2, [tsk, #TSK_SIGPENDING] -1: teq r1, #0 @ need_resched => schedule() + teq r1, #0 @ need_resched => schedule() bne reschedule - teq r2, #0 @ sigpending => do_signal() - blne __do_signal +1: teq r2, #0 @ sigpending => do_signal() + bne __do_signal +restore: restore_user_regs __do_signal: + enable_irq r1 mov r0, #0 @ NULL 'oldset' mov r1, sp @ 'regs' mov r2, why @ 'syscall' - b SYMBOL_NAME(do_signal) @ note the bl above sets lr + bl SYMBOL_NAME(do_signal) @ note the bl above sets lr + disable_irq r1 @ ensure IRQs are disabled + b restore /* * This is how we return from a fork. __switch_to will be calling us @@ -79,11 +87,11 @@ ldr ip, [tsk, #TSK_PTRACE] @ check for syscall tracing mov why, #1 tst ip, #PT_TRACESYS @ are we tracing syscalls? - beq ret_slow_syscall + beq ret_disable_irq mov r1, sp mov r0, #1 @ trace exit [IP = 1] bl SYMBOL_NAME(syscall_trace) - b ret_slow_syscall + b ret_disable_irq #include "calls.S" @@ -130,7 +138,7 @@ ldr ip, [ip] mcr p15, 0, ip, c1, c0 @ update control register #endif - enable_irqs ip + enable_irq ip str r4, [sp, #-S_OFF]! @ push fifth arg @@ -174,7 +182,7 @@ mov r1, sp mov r0, #1 @ trace exit [IP = 1] bl SYMBOL_NAME(syscall_trace) - b ret_slow_syscall + b ret_disable_irq .align 5 #ifdef CONFIG_ALIGNMENT_TRAP diff -urN orig/arch/arm/kernel/entry-header.S linux/arch/arm/kernel/entry-header.S --- orig/arch/arm/kernel/entry-header.S Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/entry-header.S Wed Feb 12 13:10:21 2003 @@ -41,14 +41,14 @@ @ @ Stack format (ensured by USER_* and SVC_*) @ -#define S_FRAME_SIZE 72 #ifdef CONFIG_CPU_32 +#define S_FRAME_SIZE 72 #define S_OLD_R0 68 #define S_PSR 64 #else +#define S_FRAME_SIZE 68 #define S_OLD_R0 64 #define S_PSR 60 -#define S_PC 60 #endif #define S_PC 60 @@ -70,6 +70,24 @@ #define S_OFF 8 #ifdef CONFIG_CPU_32 + .macro set_cpsr_c, reg, mode +#if 1 + /* broken binutils */ + mov \reg, \mode + msr cpsr_c, \reg +#else + msr cpsr_c, \mode +#endif + .endm + + .macro disable_irq, temp + set_cpsr_c \temp, #I_BIT | MODE_SVC + .endm + + .macro enable_irq, temp + set_cpsr_c \temp, #MODE_SVC + .endm + .macro save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 @@ -81,21 +99,23 @@ str r0, [sp, #S_OLD_R0] @ Save OLD_R0 .endm +/* + * Must be called with IRQs already disabled. + */ .macro restore_user_regs - ldr r0, [sp, #S_PSR] @ Get calling cpsr - mov ip, #I_BIT | MODE_SVC - msr cpsr_c, ip @ disable IRQs - msr spsr, r0 @ save in spsr_svc - ldr lr, [sp, #S_PC] @ Get PC - ldmia sp, {r0 - lr}^ @ Get calling r0 - lr + ldr r1, [sp, #S_PSR] @ Get calling cpsr + ldr lr, [sp, #S_PC]! @ Get PC + msr spsr, r1 @ save in spsr_svc + ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr mov r0, r0 - add sp, sp, #S_FRAME_SIZE + add sp, sp, #S_FRAME_SIZE - S_PC movs pc, lr @ return & move spsr_svc into cpsr .endm +/* + * Must be called with IRQs already disabled. + */ .macro fast_restore_user_regs - mov ip, #I_BIT | MODE_SVC - msr cpsr_c, ip @ disable IRQs ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr ldr lr, [sp, #S_OFF + S_PC]! @ get pc msr spsr, r1 @ save in spsr_svc @@ -108,11 +128,6 @@ .macro mask_pc, rd, rm .endm - .macro enable_irqs, temp - mov \temp, #MODE_SVC - msr cpsr_c, \temp - .endm - .macro get_current_task, rd mov \rd, sp, lsr #13 mov \rd, \rd, lsl #13 @@ -136,9 +151,9 @@ #else .macro save_user_regs - str r0, [sp, #-4]! - str lr, [sp, #-4]! - sub sp, sp, #15*4 + sub sp, sp, #S_FRAME_SIZE + str r0, [sp, #S_OLD_R0] + str lr, [sp, #S_PC] stmia sp, {r0 - lr}^ mov r0, r0 .endm @@ -146,17 +161,16 @@ .macro restore_user_regs ldmia sp, {r0 - lr}^ mov r0, r0 - ldr lr, [sp, #15*4] - add sp, sp, #15*4+8 + ldr lr, [sp, #S_PC] + add sp, sp, #S_FRAME_SIZE movs pc, lr .endm .macro fast_restore_user_regs - add sp, sp, #S_OFF - ldmib sp, {r1 - lr}^ + add sp, sp, #S_OFF + S_PC + ldmdb sp, {r1 - lr}^ mov r0, r0 - ldr lr, [sp, #15*4] - add sp, sp, #15*4+8 + ldr lr, [sp], #S_FRAME_SIZE - S_PC movs pc, lr .endm @@ -164,7 +178,11 @@ bic \rd, \rm, #PCMASK .endm - .macro enable_irqs, temp + .macro disable_irq, temp + teqp pc, #0x08000003 + .endm + + .macro enable_irq, temp teqp pc, #0x00000003 .endm diff -urN orig/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S --- orig/arch/arm/kernel/head-armv.S Fri Oct 26 16:45:50 2001 +++ linux/arch/arm/kernel/head-armv.S Wed Sep 11 11:56:28 2002 @@ -52,17 +52,22 @@ .endm /* - * Kernel startup entry point. + * Kernel startup entry point. + * --------------------------- * - * The rules are: - * r0 - should be 0 - * r1 - unique architecture number - * MMU - off - * I-cache - on or off - * D-cache - off + * This is normally called from the decompressor code. The requirements + * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, + * r1 = machine nr. * - * See linux/arch/arm/tools/mach-types for the complete list of numbers - * for r1. + * This code is mostly position independent, so if you link the kernel at + * 0xc0008000, you call this at __pa(0xc0008000). + * + * See linux/arch/arm/tools/mach-types for the complete list of machine + * numbers for r1. + * + * We're trying to keep crap to a minimum; DO NOT add any machine specific + * crap here - that's what the boot loader (or in extreme, well justified + * circumstances, zImage) is for. */ .section ".text.init",#alloc,#execinstr .type stext, #function @@ -143,7 +148,6 @@ .type __switch_data, %object __switch_data: .long __mmap_switched - .long SYMBOL_NAME(compat) .long SYMBOL_NAME(__bss_start) .long SYMBOL_NAME(_end) .long SYMBOL_NAME(processor_id) @@ -151,28 +155,33 @@ .long SYMBOL_NAME(cr_alignment) .long SYMBOL_NAME(init_task_union)+8192 +/* + * Enable the MMU. This completely changes the structure of the visible + * memory space. You will not be able to trace execution through this. + * If you have an enquiry about this, *please* check the linux-arm-kernel + * mailing list archives BEFORE sending another post to the list. + */ .type __ret, %function __ret: ldr lr, __switch_data mcr p15, 0, r0, c1, c0 - mov r0, r0 + mrc p15, 0, r0, c1, c0, 0 @ read it back. mov r0, r0 mov r0, r0 mov pc, lr - /* - * This code follows on after the page - * table switch and jump above. - * - * r0 = processor control register - * r1 = machine ID - * r9 = processor ID - */ +/* + * The following fragment of code is executed with the MMU on, and uses + * absolute addresses; this is not position independent. + * + * r0 = processor control register + * r1 = machine ID + * r9 = processor ID + */ .align 5 __mmap_switched: adr r3, __switch_data + 4 - ldmia r3, {r2, r4, r5, r6, r7, r8, sp}@ r2 = compat + ldmia r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat @ sp = stack pointer - str r12, [r2] mov fp, #0 @ Clear BSS (and zero fp) 1: cmp r4, r5 diff -urN orig/arch/arm/kernel/irq-arch.c linux/arch/arm/kernel/irq-arch.c --- orig/arch/arm/kernel/irq-arch.c Mon Sep 3 14:14:40 2001 +++ linux/arch/arm/kernel/irq-arch.c Thu Feb 6 11:31:26 2003 @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include diff -urN orig/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c --- orig/arch/arm/kernel/irq.c Sat Jul 21 10:46:32 2001 +++ linux/arch/arm/kernel/irq.c Sun Jun 29 18:33:27 2003 @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -46,6 +48,7 @@ static volatile unsigned long irq_err_count; static spinlock_t irq_controller_lock; +static LIST_HEAD(irq_pending); struct irqdesc irq_desc[NR_IRQS]; void (*init_arch_irq)(void) __initdata = NULL; @@ -57,21 +60,32 @@ { } +/* + * No architecture-specific irq_finish function defined in arm/arch/irq.h. + */ +#ifndef irq_finish +#define irq_finish(irq) do { } while (0) +#endif + /** * disable_irq - disable an irq and wait for completion * @irq: Interrupt to disable * - * Disable the selected interrupt line. + * Disable the selected interrupt line. We do this lazily. * - * This function may be called - with care - from IRQ context. + * This function may be called from IRQ context. */ void disable_irq(unsigned int irq) { + struct irqdesc *desc = irq_desc + irq; unsigned long flags; spin_lock_irqsave(&irq_controller_lock, flags); - irq_desc[irq].enabled = 0; - irq_desc[irq].mask(irq); + if (!desc->disable_depth++) { +#ifndef CONFIG_CPU_SA1100 + desc->mask(irq); +#endif + } spin_unlock_irqrestore(&irq_controller_lock, flags); } @@ -79,19 +93,37 @@ * enable_irq - enable interrupt handling on an irq * @irq: Interrupt to enable * - * Re-enables the processing of interrupts on this IRQ line + * Re-enables the processing of interrupts on this IRQ line. + * Note that this may call the interrupt handler, so you may + * get unexpected results if you hold IRQs disabled. * * This function may be called from IRQ context. */ void enable_irq(unsigned int irq) { + struct irqdesc *desc = irq_desc + irq; unsigned long flags; spin_lock_irqsave(&irq_controller_lock, flags); - irq_desc[irq].probing = 0; - irq_desc[irq].triggered = 0; - irq_desc[irq].enabled = 1; - irq_desc[irq].unmask(irq); + if (!desc->disable_depth) { + printk("enable_irq(%u) unbalanced from %p\n", irq, + __builtin_return_address(0)); + } else if (!--desc->disable_depth) { + desc->probing = 0; + desc->unmask(irq); + + /* + * If the interrupt is waiting to be processed, + * try to re-run it. We can't directly run it + * from here since the caller might be in an + * interrupt-protected region. + */ + if (desc->pending) { + desc->pending = 0; + if (list_empty(&desc->pend)) + list_add(&desc->pend, &irq_pending); + } + } spin_unlock_irqrestore(&irq_controller_lock, flags); } @@ -128,7 +160,7 @@ * a large number if IRQs to appear in the same jiffie with the * same instruction pointer (or within 2 instructions). */ -static void check_irq_lock(struct irqdesc *desc, int irq, struct pt_regs *regs) +static int check_irq_lock(struct irqdesc *desc, int irq, struct pt_regs *regs) { unsigned long instr_ptr = instruction_pointer(regs); @@ -137,95 +169,202 @@ desc->lck_cnt += 1; if (desc->lck_cnt > MAX_IRQ_CNT) { - printk(KERN_ERR "IRQ LOCK: IRQ%d is locking the system, disabled\n", irq); - disable_irq(irq); + if (!desc->lck_warned++) + printk(KERN_ERR "IRQ LOCK: IRQ%d is locking the system, disabled\n", irq); + mod_timer(&desc->lck_timer, jiffies + 10*HZ); + return 1; } } else { desc->lck_cnt = 0; desc->lck_pc = instruction_pointer(regs); desc->lck_jif = jiffies; + if (desc->lck_warned < 0) + desc->lck_warned ++; } + return 0; +} + +static void +__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) +{ + unsigned int status; + + spin_unlock(&irq_controller_lock); + + if (!(action->flags & SA_INTERRUPT)) + local_irq_enable(); + + status = 0; + do { + status |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + + spin_lock_irq(&irq_controller_lock); } /* * do_IRQ handles all normal device IRQ's */ -asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +void do_IRQ(int irq, struct pt_regs * regs) { - struct irqdesc * desc; - struct irqaction * action; - int cpu; + struct irqdesc *desc = irq_desc + irq; - irq = fixup_irq(irq); + desc->triggered = 1; /* - * Some hardware gives randomly wrong interrupts. Rather - * than crashing, do something sensible. + * Acknowledge and clear the IRQ, but (if its + * a level-based IRQ, don't mask it) */ - if (irq >= NR_IRQS) - goto bad_irq; + desc->mask_ack(irq); - desc = irq_desc + irq; + /* + * If we're currently running this IRQ, or its disabled, + * we shouldn't process the IRQ. Instead, turn on the + * hardware masks. + */ + if (desc->running || desc->disable_depth) + goto running; - spin_lock(&irq_controller_lock); - desc->mask_ack(irq); - spin_unlock(&irq_controller_lock); + /* + * Mark the IRQ currently in progress. + */ + desc->running = 1; - cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat.irqs[cpu][irq]++; - desc->triggered = 1; + kstat.irqs[smp_processor_id()][irq]++; - /* Return with this interrupt masked if no action */ - action = desc->action; + do { + struct irqaction *action; - if (action) { - int status = 0; + action = desc->action; + if (!action) + break; - if (desc->nomask) { - spin_lock(&irq_controller_lock); + if (desc->pending && desc->disable_depth == 0) { + desc->pending = 0; desc->unmask(irq); - spin_unlock(&irq_controller_lock); } - if (!(action->flags & SA_INTERRUPT)) - __sti(); + __do_irq(irq, action, regs); + } while (desc->pending && desc->disable_depth == 0); - do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); + desc->running = 0; - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - __cli(); + /* + * If we are disabled or freed, shut down the handler. + */ + if (desc->action && !check_irq_lock(desc, irq, regs)) + desc->unmask(irq); + return; - if (!desc->nomask && desc->enabled) { - spin_lock(&irq_controller_lock); - desc->unmask(irq); - spin_unlock(&irq_controller_lock); + running: + /* + * We got another IRQ while this one was masked or + * currently running. Delay it. + */ + desc->pending = 1; +} + +static void do_pending_irqs(struct pt_regs *regs) +{ + struct list_head head, *l, *n; + + do { + struct irqdesc *desc; + + /* + * First, take the pending interrupts off the list. + * The act of calling the handlers may add some IRQs + * back onto the list. + */ + head = irq_pending; + INIT_LIST_HEAD(&irq_pending); + head.next->prev = &head; + head.prev->next = &head; + + /* + * Now run each entry. We must delete it from our + * list before calling the handler. + */ + list_for_each_safe(l, n, &head) { + desc = list_entry(l, struct irqdesc, pend); + list_del_init(&desc->pend); + do_IRQ(desc - irq_desc, regs); } - } + + /* + * The list must be empty. + */ + BUG_ON(!list_empty(&head)); + } while (!list_empty(&irq_pending)); +} + +/* + * do_IRQ handles all hardware IRQ's. Decoded IRQs should not + * come via this function. Instead, they should provide their + * own 'handler' + */ +asmlinkage void asm_do_IRQ(int irq, struct pt_regs *regs) +{ + irq = fixup_irq(irq); /* - * Debug measure - hopefully we can continue if an - * IRQ lockup problem occurs... + * Some hardware gives randomly wrong interrupts. Rather + * than crashing, do something sensible. */ - check_irq_lock(desc, irq, regs); + if (irq < NR_IRQS) { + int cpu = smp_processor_id(); - irq_exit(cpu, irq); + irq_enter(cpu, irq); + spin_lock(&irq_controller_lock); + do_IRQ(irq, regs); - if (softirq_pending(cpu)) - do_softirq(); - return; + /* + * Now re-run any pending interrupts. + */ + if (!list_empty(&irq_pending)) + do_pending_irqs(regs); + + spin_unlock(&irq_controller_lock); + irq_exit(cpu, irq); + + if (softirq_pending(cpu)) + do_softirq(); + + irq_finish(irq); + return; + } -bad_irq: irq_err_count += 1; printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); + + irq_finish(irq); return; } +static void irqlck_timeout(unsigned long _data) +{ + struct irqdesc *desc = (struct irqdesc *)_data; + + spin_lock(&irq_controller_lock); + + del_timer(&desc->lck_timer); + + desc->lck_cnt = 0; + desc->lck_pc = 0; + desc->lck_jif = 0; + desc->lck_warned = -10; + + if (desc->disable_depth == 0) + desc->unmask(desc - irq_desc); + + spin_unlock(&irq_controller_lock); +} + #ifdef CONFIG_ARCH_ACORN void do_ecard_IRQ(int irq, struct pt_regs *regs) { @@ -302,10 +441,12 @@ *p = new; if (!shared) { - desc->nomask = (new->flags & SA_IRQNOMASK) ? 1 : 0; desc->probing = 0; + desc->running = 0; + desc->pending = 0; + desc->disable_depth = 1; if (!desc->noautoenable) { - desc->enabled = 1; + desc->disable_depth = 0; desc->unmask(irq); } } @@ -383,7 +524,7 @@ * On a shared IRQ the caller must ensure the interrupt is disabled * on the card it drives before calling this function. * - * This function may be called from interrupt context. + * This function must not be called from interrupt context. */ void free_irq(unsigned int irq, void *dev_id) { @@ -408,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 @@ -416,6 +557,8 @@ spin_unlock_irqrestore(&irq_controller_lock, flags); } +static DECLARE_MUTEX(probe_sem); + /* Start the interrupt probing. Unlike other architectures, * we don't return a mask of interrupts from probe_irq_on, * but return the number of interrupts enabled for the probe. @@ -427,15 +570,15 @@ unsigned int i, irqs = 0; unsigned long delay; + down(&probe_sem); + /* * first snaffle up any unassigned but * probe-able interrupts */ spin_lock_irq(&irq_controller_lock); for (i = 0; i < NR_IRQS; i++) { - if (!irq_desc[i].valid || - !irq_desc[i].probe_ok || - irq_desc[i].action) + if (!irq_desc[i].probe_ok || irq_desc[i].action) continue; irq_desc[i].probing = 1; @@ -456,18 +599,31 @@ */ spin_lock_irq(&irq_controller_lock); for (i = 0; i < NR_IRQS; i++) { - if (irq_desc[i].probing && - irq_desc[i].triggered) { + if (irq_desc[i].probing && irq_desc[i].triggered) { irq_desc[i].probing = 0; irqs -= 1; } } spin_unlock_irq(&irq_controller_lock); - /* now filter out any obviously spurious interrupts */ return irqs; } +unsigned int probe_irq_mask(unsigned long irqs) +{ + unsigned int mask = 0, i; + + spin_lock_irq(&irq_controller_lock); + for (i = 0; i < 16 && i < NR_IRQS; i++) + if (irq_desc[i].probing && irq_desc[i].triggered) + mask |= 1 << i; + spin_unlock_irq(&irq_controller_lock); + + up(&probe_sem); + + return mask; +} + /* * Possible return values: * >= 0 - interrupt number @@ -499,6 +655,8 @@ out: spin_unlock_irq(&irq_controller_lock); + up(&probe_sem); + return irq_found; } @@ -512,12 +670,17 @@ int irq; for (irq = 0; irq < NR_IRQS; irq++) { + irq_desc[irq].disable_depth = 1; irq_desc[irq].probe_ok = 0; irq_desc[irq].valid = 0; irq_desc[irq].noautoenable = 0; irq_desc[irq].mask_ack = dummy_mask_unmask_irq; irq_desc[irq].mask = dummy_mask_unmask_irq; irq_desc[irq].unmask = dummy_mask_unmask_irq; + INIT_LIST_HEAD(&irq_desc[irq].pend); + init_timer(&irq_desc[irq].lck_timer); + irq_desc[irq].lck_timer.data = (unsigned long)&irq_desc[irq]; + irq_desc[irq].lck_timer.function = irqlck_timeout; } init_arch_irq(); diff -urN orig/arch/arm/kernel/oldlatches.c linux/arch/arm/kernel/oldlatches.c --- orig/arch/arm/kernel/oldlatches.c Mon Sep 3 14:14:40 2001 +++ linux/arch/arm/kernel/oldlatches.c Fri Sep 6 10:56:53 2002 @@ -29,10 +29,10 @@ if (machine_is_archimedes()) { unsigned long flags; - local_save_flags(flags); + local_irq_save(flags); latch_a_copy = (latch_a_copy & ~mask) | newdata; __raw_writeb(latch_a_copy, LATCHA_BASE); - local_restore_flags(flags); + local_irq_restore(flags); printk("Latch: A = 0x%02x\n", latch_a_copy); } else @@ -46,10 +46,10 @@ if (machine_is_archimedes()) { unsigned long flags; - local_save_flags(flags); + local_irq_save(flags); latch_b_copy = (latch_b_copy & ~mask) | newdata; __raw_writeb(latch_b_copy, LATCHB_BASE); - local_restore_flags(flags); + local_irq_restore(flags); printk("Latch: B = 0x%02x\n", latch_b_copy); } else diff -urN orig/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- orig/arch/arm/kernel/process.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/kernel/process.c Tue Jun 24 11:16:23 2003 @@ -24,18 +24,10 @@ #include #include -#include #include +#include #include -/* - * Values for cpu_do_idle() - */ -#define IDLE_WAIT_SLOW 0 -#define IDLE_WAIT_FAST 1 -#define IDLE_CLOCK_SLOW 2 -#define IDLE_CLOCK_FAST 3 - extern const char *processor_modes[]; extern void setup_mm_for_reboot(char mode); @@ -75,6 +67,18 @@ void (*pm_power_off)(void); /* + * This is our default idle handler. We need to disable + * interrupts here to ensure we don't miss a wakeup call. + */ +void default_idle(void) +{ + local_irq_disable(); + if (!current->need_resched && !hlt_counter) + arch_idle(); + local_irq_enable(); +} + +/* * The idle thread. We try to conserve power, while trying to keep * overall latency low. The architecture specific idle is passed * a value to indicate the level of "idleness" of the system. @@ -89,7 +93,7 @@ while (1) { void (*idle)(void) = pm_idle; if (!idle) - idle = arch_idle; + idle = default_idle; leds_event(led_idle_start); while (!current->need_resched) idle(); @@ -176,15 +180,15 @@ flags & CC_Z_BIT ? 'Z' : 'z', flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); - printk(" IRQs %s FIQs %s Mode %s%s Segment %s\n", - interrupts_enabled(regs) ? "on" : "off", - fast_interrupts_enabled(regs) ? "on" : "off", + printk(" IRQs o%s FIQs o%s Mode %s%s Segment %s\n", + interrupts_enabled(regs) ? "n" : "ff", + fast_interrupts_enabled(regs) ? "n" : "ff", processor_modes[processor_mode(regs)], thumb_mode(regs) ? " (T)" : "", get_fs() == get_ds() ? "kernel" : "user"); #if defined(CONFIG_CPU_32) { - int ctrl, transbase, dac; + unsigned int ctrl, transbase, dac; __asm__ ( " mrc p15, 0, %0, c1, c0\n" " mrc p15, 0, %1, c2, c0\n" @@ -282,12 +286,22 @@ { } +static void default_fp_init(union fp_state *fp) +{ + memset(fp, 0, sizeof(union fp_state)); +} + +void (*fp_init)(union fp_state *) = default_fp_init; + void flush_thread(void) { - memset(¤t->thread.debug, 0, sizeof(struct debug_info)); - memset(¤t->thread.fpstate, 0, sizeof(union fp_state)); - current->used_math = 0; - current->flags &= ~PF_USEDFPU; + struct task_struct *tsk = current; + + tsk->flags &= ~PF_USEDFPU; + tsk->used_math = 0; + + memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); + fp_init(&tsk->thread.fpstate); } void release_thread(struct task_struct *dead_task) @@ -296,16 +310,16 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); -int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, - unsigned long unused, - struct task_struct * p, struct pt_regs * regs) +int +copy_thread(int nr, unsigned long clone_flags, unsigned long esp, + unsigned long unused, struct task_struct * p, struct pt_regs * regs) { - struct pt_regs * childregs; + struct pt_regs *childregs; struct context_save_struct * save; atomic_set(&p->thread.refcount, 1); - childregs = ((struct pt_regs *)((unsigned long)p + 8192)) - 1; + childregs = ((struct pt_regs *)((unsigned long)p + 8192 - 8)) - 1; *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = esp; @@ -324,10 +338,12 @@ */ int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { - if (current->used_math) + int used_math = current->used_math; + + if (used_math) memcpy(fp, ¤t->thread.fpstate.soft, sizeof (*fp)); - return current->used_math; + return used_math; } /* @@ -347,8 +363,8 @@ dump->u_debugreg[0] = tsk->thread.debug.bp[0].address; dump->u_debugreg[1] = tsk->thread.debug.bp[1].address; - dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn; - dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn; + dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn.arm; + dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn.arm; dump->u_debugreg[4] = tsk->thread.debug.nsaved; if (dump->start_stack < 0x04000000) @@ -371,18 +387,18 @@ pid_t __ret; __asm__ __volatile__( - "orr r0, %1, %2 @ kernel_thread sys_clone - mov r1, #0 - "__syscall(clone)" - movs %0, r0 @ if we are the child - bne 1f - mov fp, #0 @ ensure that fp is zero - mov r0, %4 - mov lr, pc - mov pc, %3 - b sys_exit + "orr r0, %1, %2 @ kernel_thread sys_clone \n\ + mov r1, #0 \n\ + "__syscall(clone)" \n\ + movs %0, r0 @ if we are the child \n\ + bne 1f \n\ + mov fp, #0 @ ensure that fp is zero \n\ + mov r0, %4 \n\ + mov lr, pc \n\ + mov pc, %3 \n\ + b sys_exit \n\ 1: " - : "=r" (__ret) + : "=&r" (__ret) : "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg) : "r0", "r1", "lr"); return __ret; @@ -405,7 +421,7 @@ return 0; stack_page = 4096 + (unsigned long)p; - fp = get_css_fp(&p->thread); + fp = thread_saved_fp(&p->thread); do { if (fp < stack_page || fp > 4092+stack_page) return 0; diff -urN orig/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c --- orig/arch/arm/kernel/ptrace.c Mon Oct 1 23:10:02 2001 +++ linux/arch/arm/kernel/ptrace.c Fri Apr 25 14:51:49 2003 @@ -9,6 +9,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include @@ -33,18 +35,24 @@ /* * Breakpoint SWI instruction: SWI &9F0001 */ -#define BREAKINST 0xef9f0001 +#define BREAKINST_ARM 0xef9f0001 +/* fill this in later */ +#define BREAKINST_THUMB 0xdf00 /* * Get the address of the live pt_regs for the specified task. * These are saved onto the top kernel stack when the process * is not running. + * + * Note: if a user thread is execve'd from kernel space, the + * kernel stack will not be empty on entry to the kernel, so + * ptracing these tasks will fail. */ static inline struct pt_regs * get_user_regs(struct task_struct *task) { return (struct pt_regs *) - ((unsigned long)task + 8192 - sizeof(struct pt_regs)); + ((unsigned long)task + 8192 - 8 - sizeof(struct pt_regs)); } /* @@ -53,7 +61,7 @@ * this routine assumes that all the privileged stacks are in our * data space. */ -static inline long get_stack_long(struct task_struct *task, int offset) +static inline long get_user_reg(struct task_struct *task, int offset) { return get_user_regs(task)->uregs[offset]; } @@ -65,14 +73,14 @@ * data space. */ static inline int -put_stack_long(struct task_struct *task, int offset, long data) +put_user_reg(struct task_struct *task, int offset, long data) { struct pt_regs newregs, *regs = get_user_regs(task); int ret = -EINVAL; newregs = *regs; newregs.uregs[offset] = data; - + if (valid_user_regs(&newregs)) { regs->uregs[offset] = data; ret = 0; @@ -82,23 +90,32 @@ } static inline int -read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res) +read_u32(struct task_struct *task, unsigned long addr, u32 *res) { - int copied; + int ret; - copied = access_process_vm(child, addr, res, sizeof(*res), 0); + ret = access_process_vm(task, addr, res, sizeof(*res), 0); - return copied != sizeof(*res) ? -EIO : 0; + return ret == sizeof(*res) ? 0 : -EIO; } static inline int -write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val) +read_instr(struct task_struct *task, unsigned long addr, u32 *res) { - int copied; - - copied = access_process_vm(child, addr, &val, sizeof(val), 1); + int ret; - return copied != sizeof(val) ? -EIO : 0; + if (addr & 1) { + u16 val; + ret = access_process_vm(task, addr & ~1, &val, sizeof(val), 0); + ret = ret == sizeof(val) ? 0 : -EIO; + *res = val; + } else { + u32 val; + ret = access_process_vm(task, addr & ~3, &val, sizeof(val), 0); + ret = ret == sizeof(val) ? 0 : -EIO; + *res = val; + } + return ret; } /* @@ -110,7 +127,7 @@ unsigned int reg = (insn >> 16) & 15; unsigned long val; - val = get_stack_long(child, reg); + val = get_user_reg(child, reg); if (reg == 15) val = pc_pointer(val + 8); @@ -132,10 +149,10 @@ shift = (insn >> 8) & 15; type = 3; } else { - val = get_stack_long (child, insn & 15); + val = get_user_reg (child, insn & 15); if (insn & (1 << 4)) - shift = (int)get_stack_long (child, (insn >> 8) & 15); + shift = (int)get_user_reg (child, (insn >> 8) & 15); else shift = (insn >> 7) & 31; @@ -165,7 +182,7 @@ int shift; int type; - val = get_stack_long(child, insn & 15); + val = get_user_reg(child, insn & 15); shift = (insn >> 7) & 31; type = (insn >> 5) & 3; @@ -182,10 +199,24 @@ return val; } +#define OP_MASK 0x01e00000 +#define OP_AND 0x00000000 +#define OP_EOR 0x00200000 +#define OP_SUB 0x00400000 +#define OP_RSB 0x00600000 +#define OP_ADD 0x00800000 +#define OP_ADC 0x00a00000 +#define OP_SBC 0x00c00000 +#define OP_RSC 0x00e00000 +#define OP_ORR 0x01800000 +#define OP_MOV 0x01a00000 +#define OP_BIC 0x01c00000 +#define OP_MVN 0x01e00000 + static unsigned long get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn) { - unsigned long alt = 0; + u32 alt = 0; switch (insn & 0x0e000000) { case 0x00000000: @@ -200,21 +231,21 @@ aluop1 = ptrace_getrn(child, insn); aluop2 = ptrace_getaluop2(child, insn); - ccbit = get_stack_long(child, REG_PSR) & CC_C_BIT ? 1 : 0; + ccbit = get_user_reg(child, REG_PSR) & CC_C_BIT ? 1 : 0; - switch (insn & 0x01e00000) { - case 0x00000000: alt = aluop1 & aluop2; break; - case 0x00200000: alt = aluop1 ^ aluop2; break; - case 0x00400000: alt = aluop1 - aluop2; break; - case 0x00600000: alt = aluop2 - aluop1; break; - case 0x00800000: alt = aluop1 + aluop2; break; - case 0x00a00000: alt = aluop1 + aluop2 + ccbit; break; - case 0x00c00000: alt = aluop1 - aluop2 + ccbit; break; - case 0x00e00000: alt = aluop2 - aluop1 + ccbit; break; - case 0x01800000: alt = aluop1 | aluop2; break; - case 0x01a00000: alt = aluop2; break; - case 0x01c00000: alt = aluop1 & ~aluop2; break; - case 0x01e00000: alt = ~aluop2; break; + switch (insn & OP_MASK) { + case OP_AND: alt = aluop1 & aluop2; break; + case OP_EOR: alt = aluop1 ^ aluop2; break; + case OP_SUB: alt = aluop1 - aluop2; break; + case OP_RSB: alt = aluop2 - aluop1; break; + case OP_ADD: alt = aluop1 + aluop2; break; + case OP_ADC: alt = aluop1 + aluop2 + ccbit; break; + case OP_SBC: alt = aluop1 - aluop2 + ccbit; break; + case OP_RSC: alt = aluop2 - aluop1 + ccbit; break; + case OP_ORR: alt = aluop1 | aluop2; break; + case OP_MOV: alt = aluop2; break; + case OP_BIC: alt = aluop1 & ~aluop2; break; + case OP_MVN: alt = ~aluop2; break; } break; } @@ -241,7 +272,7 @@ else base -= aluop2; } - if (read_tsk_long(child, base, &alt) == 0) + if (read_u32(child, base, &alt) == 0) alt = pc_pointer(alt); } break; @@ -255,13 +286,7 @@ unsigned int nr_regs; if (insn & (1 << 23)) { - nr_regs = insn & 65535; - - nr_regs = (nr_regs & 0x5555) + ((nr_regs & 0xaaaa) >> 1); - nr_regs = (nr_regs & 0x3333) + ((nr_regs & 0xcccc) >> 2); - nr_regs = (nr_regs & 0x0707) + ((nr_regs & 0x7070) >> 4); - nr_regs = (nr_regs & 0x000f) + ((nr_regs & 0x0f00) >> 8); - nr_regs <<= 2; + nr_regs = hweight16(insn & 65535) << 2; if (!(insn & (1 << 24))) nr_regs -= 4; @@ -274,8 +299,8 @@ base = ptrace_getrn(child, insn); - if (read_tsk_long(child, base + nr_regs, &alt) == 0) - alt = pc_pointer (alt); + if (read_u32(child, base + nr_regs, &alt) == 0) + alt = pc_pointer(alt); break; } break; @@ -304,36 +329,82 @@ } static int -add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr) +swap_insn(struct task_struct *task, unsigned long addr, + void *old_insn, void *new_insn, int size) +{ + int ret; + + ret = access_process_vm(task, addr, old_insn, size, 0); + if (ret == size) + ret = access_process_vm(task, addr, new_insn, size, 1); + return ret; +} + +static void +add_breakpoint(struct task_struct *task, struct debug_info *dbg, unsigned long addr) { int nr = dbg->nsaved; - int res = -EINVAL; if (nr < 2) { - res = read_tsk_long(child, addr, &dbg->bp[nr].insn); - if (res == 0) - res = write_tsk_long(child, addr, BREAKINST); + u32 new_insn = BREAKINST_ARM; + int res; + + res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4); - if (res == 0) { + if (res == 4) { dbg->bp[nr].address = addr; dbg->nsaved += 1; } } else printk(KERN_ERR "ptrace: too many breakpoints\n"); +} + +/* + * Clear one breakpoint in the user program. We copy what the hardware + * does and use bit 0 of the address to indicate whether this is a Thumb + * breakpoint or an ARM breakpoint. + */ +static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp) +{ + unsigned long addr = bp->address; + union debug_insn old_insn; + int ret; - return res; + if (addr & 1) { + ret = swap_insn(task, addr & ~1, &old_insn.thumb, + &bp->insn.thumb, 2); + + if (ret != 2 || old_insn.thumb != BREAKINST_THUMB) + printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at " + "0x%08lx (0x%04x)\n", task->comm, task->pid, + addr, old_insn.thumb); + } else { + ret = swap_insn(task, addr & ~3, &old_insn.thumb, + &bp->insn.thumb, 4); + + if (ret != 4 || old_insn.arm != BREAKINST_ARM) + printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at " + "0x%08lx (0x%08x)\n", task->comm, task->pid, + addr, old_insn.arm); + } } -int ptrace_set_bpt(struct task_struct *child) +void ptrace_set_bpt(struct task_struct *child) { struct pt_regs *regs; - unsigned long pc, insn; + unsigned long pc; + u32 insn; int res; regs = get_user_regs(child); pc = instruction_pointer(regs); - res = read_tsk_long(child, pc, &insn); + if (thumb_mode(regs)) { + printk(KERN_WARNING "ptrace: can't handle thumb mode\n"); + return; + } + + res = read_instr(child, pc, &insn); if (!res) { struct debug_info *dbg = &child->thread.debug; unsigned long alt; @@ -342,7 +413,7 @@ alt = get_branch_address(child, pc, insn); if (alt) - res = add_breakpoint(child, dbg, alt); + add_breakpoint(child, dbg, alt); /* * Note that we ignore the result of setting the above @@ -354,10 +425,8 @@ * loose control of the thread during single stepping. */ if (!alt || predicate(insn) != PREDICATE_ALWAYS) - res = add_breakpoint(child, dbg, pc + 4); + add_breakpoint(child, dbg, pc + 4); } - - return res; } /* @@ -366,24 +435,17 @@ */ void __ptrace_cancel_bpt(struct task_struct *child) { - struct debug_info *dbg = &child->thread.debug; - int i, nsaved = dbg->nsaved; + int i, nsaved = child->thread.debug.nsaved; - dbg->nsaved = 0; + child->thread.debug.nsaved = 0; if (nsaved > 2) { printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); nsaved = 2; } - for (i = 0; i < nsaved; i++) { - unsigned long tmp; - - read_tsk_long(child, dbg->bp[i].address, &tmp); - write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn); - if (tmp != BREAKINST) - printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n"); - } + for (i = 0; i < nsaved; i++) + clear_breakpoint(child, &child->thread.debug.bp[i]); } /* @@ -396,6 +458,114 @@ __ptrace_cancel_bpt(child); } +/* + * Handle hitting a breakpoint. regs points at the instruction. + */ +void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) +{ + siginfo_t info; + + /* + * The PC is pointing at the next instruction. Fix this. + */ + regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; + + __ptrace_cancel_bpt(tsk); + + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; + info.si_addr = (void *)instruction_pointer(regs); + + force_sig_info(SIGTRAP, &info, tsk); +} + +/* + * Read the word at offset "off" into the "struct user". We + * actually access the pt_regs stored on the kernel stack. + */ +static int ptrace_read_user(struct task_struct *tsk, unsigned long off, + unsigned long *ret) +{ + unsigned long tmp; + + if (off & 3 || off >= sizeof(struct user)) + return -EIO; + + tmp = 0; + if (off < sizeof(struct pt_regs)) + tmp = get_user_reg(tsk, off >> 2); + + return put_user(tmp, ret); +} + +/* + * Write the word at offset "off" into "struct user". We + * actually access the pt_regs stored on the kernel stack. + */ +static int ptrace_write_user(struct task_struct *tsk, unsigned long off, + unsigned long val) +{ + if (off & 3 || off >= sizeof(struct user)) + return -EIO; + + if (off >= sizeof(struct pt_regs)) + return 0; + + return put_user_reg(tsk, off >> 2, val); +} + +/* + * Get all user integer registers. + */ +static int ptrace_getregs(struct task_struct *tsk, void *uregs) +{ + struct pt_regs *regs = get_user_regs(tsk); + + return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; +} + +/* + * Set all user integer registers. + */ +static int ptrace_setregs(struct task_struct *tsk, void *uregs) +{ + struct pt_regs newregs; + int ret; + + ret = -EFAULT; + if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { + struct pt_regs *regs = get_user_regs(tsk); + + ret = -EINVAL; + if (valid_user_regs(&newregs)) { + *regs = newregs; + ret = 0; + } + } + + return ret; +} + +/* + * Get the child FPU state. + */ +static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) +{ + return copy_to_user(ufp, &tsk->thread.fpstate, + sizeof(struct user_fp)) ? -EFAULT : 0; +} + +/* + * Set the child FPU state. + */ +static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) +{ + tsk->used_math = 1; + return copy_from_user(&tsk->thread.fpstate, ufp, + sizeof(struct user_fp)) ? -EFAULT : 0; +} + static int do_ptrace(int request, struct task_struct *child, long addr, long data) { unsigned long tmp; @@ -407,23 +577,16 @@ */ case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: - ret = read_tsk_long(child, addr, &tmp); - if (!ret) + ret = access_process_vm(child, addr, &tmp, + sizeof(unsigned long), 0); + if (ret == sizeof(unsigned long)) ret = put_user(tmp, (unsigned long *) data); + else + ret = -EIO; break; - /* - * read the word at location "addr" in the user registers. - */ case PTRACE_PEEKUSR: - ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) - break; - - tmp = 0; /* Default return condition */ - if (addr < sizeof(struct pt_regs)) - tmp = get_stack_long(child, (int)addr >> 2); - ret = put_user(tmp, (unsigned long *)data); + ret = ptrace_read_user(child, addr, (unsigned long *)data); break; /* @@ -431,19 +594,16 @@ */ case PTRACE_POKETEXT: case PTRACE_POKEDATA: - ret = write_tsk_long(child, addr, data); + ret = access_process_vm(child, addr, &data, + sizeof(unsigned long), 1); + if (ret == sizeof(unsigned long)) + ret = 0; + else + ret = -EIO; break; - /* - * write the word at location addr in the user registers. - */ case PTRACE_POKEUSR: - ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) - break; - - if (addr < sizeof(struct pt_regs)) - ret = put_stack_long(child, (int)addr >> 2, data); + ret = ptrace_write_user(child, addr, data); break; /* @@ -471,14 +631,12 @@ * exit. */ case PTRACE_KILL: - /* already dead */ - ret = 0; - if (child->state == TASK_ZOMBIE) - break; - child->exit_code = SIGKILL; /* make sure single-step breakpoint is gone. */ __ptrace_cancel_bpt(child); - wake_up_process(child); + if (child->state != TASK_ZOMBIE) { + child->exit_code = SIGKILL; + wake_up_process(child); + } ret = 0; break; @@ -497,71 +655,32 @@ ret = 0; break; - /* - * detach a process that was attached. - */ case PTRACE_DETACH: ret = ptrace_detach(child, data); break; - /* - * Get all gp regs from the child. - */ - case PTRACE_GETREGS: { - struct pt_regs *regs = get_user_regs(child); - - ret = 0; - if (copy_to_user((void *)data, regs, - sizeof(struct pt_regs))) - ret = -EFAULT; - + case PTRACE_GETREGS: + ret = ptrace_getregs(child, (void *)data); break; - } - /* - * Set all gp regs in the child. - */ - case PTRACE_SETREGS: { - struct pt_regs newregs; - - ret = -EFAULT; - if (copy_from_user(&newregs, (void *)data, - sizeof(struct pt_regs)) == 0) { - struct pt_regs *regs = get_user_regs(child); - - ret = -EINVAL; - if (valid_user_regs(&newregs)) { - *regs = newregs; - ret = 0; - } - } + case PTRACE_SETREGS: + ret = ptrace_setregs(child, (void *)data); break; - } - /* - * Get the child FPU state. - */ case PTRACE_GETFPREGS: - ret = -EIO; - if (!access_ok(VERIFY_WRITE, (void *)data, sizeof(struct user_fp))) - break; - - /* we should check child->used_math here */ - ret = __copy_to_user((void *)data, &child->thread.fpstate, - sizeof(struct user_fp)) ? -EFAULT : 0; + ret = ptrace_getfpregs(child, (void *)data); break; - /* - * Set the child FPU state. - */ case PTRACE_SETFPREGS: - ret = -EIO; - if (!access_ok(VERIFY_READ, (void *)data, sizeof(struct user_fp))) - break; + ret = ptrace_setfpregs(child, (void *)data); + break; - child->used_math = 1; - ret = __copy_from_user(&child->thread.fpstate, (void *)data, - sizeof(struct user_fp)) ? -EFAULT : 0; + case PTRACE_SETOPTIONS: + if (data & PTRACE_O_TRACESYSGOOD) + child->ptrace |= PT_TRACESYSGOOD; + else + child->ptrace &= ~PT_TRACESYSGOOD; + ret = 0; break; default: diff -urN orig/arch/arm/kernel/ptrace.h linux/arch/arm/kernel/ptrace.h --- orig/arch/arm/kernel/ptrace.h Tue Oct 3 20:08:18 2000 +++ linux/arch/arm/kernel/ptrace.h Fri Sep 6 20:10:01 2002 @@ -1,14 +1,15 @@ /* * linux/arch/arm/kernel/ptrace.h * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ extern void __ptrace_cancel_bpt(struct task_struct *); -extern int ptrace_set_bpt(struct task_struct *); +extern void ptrace_set_bpt(struct task_struct *); +extern void ptrace_break(struct task_struct *, struct pt_regs *); /* * Clear a breakpoint, if one exists. diff -urN orig/arch/arm/kernel/semaphore.c linux/arch/arm/kernel/semaphore.c --- orig/arch/arm/kernel/semaphore.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/semaphore.c Wed Jul 16 18:47:23 2003 @@ -177,76 +177,76 @@ * value in some cases.. */ #ifdef CONFIG_CPU_26 -asm(" .align 5 - .globl __down_failed -__down_failed: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __down - ldmfd sp!, {r0 - r3, pc}^ - - .align 5 - .globl __down_interruptible_failed -__down_interruptible_failed: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __down_interruptible - mov ip, r0 - ldmfd sp!, {r0 - r3, pc}^ - - .align 5 - .globl __down_trylock_failed -__down_trylock_failed: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __down_trylock - mov ip, r0 - ldmfd sp!, {r0 - r3, pc}^ - - .align 5 - .globl __up_wakeup -__up_wakeup: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __up - ldmfd sp!, {r0 - r3, pc}^ +asm(" .align 5 \n\ + .globl __down_failed \n\ +__down_failed: \n\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + bl __down \n\ + ldmfd sp!, {r0 - r3, pc}^ \n\ + \n\ + .align 5 \n\ + .globl __down_interruptible_failed \n\ +__down_interruptible_failed: \n\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + 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\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + bl __down_trylock \n\ + mov ip, r0 \n\ + ldmfd sp!, {r0 - r3, pc}^ \n\ + \n\ + .align 5 \n\ + .globl __up_wakeup \n\ +__up_wakeup: \n\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + bl __up \n\ + ldmfd sp!, {r0 - r3, pc}^ \n\ "); #else /* 32 bit version */ -asm(" .align 5 - .globl __down_failed -__down_failed: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __down - ldmfd sp!, {r0 - r3, pc} - - .align 5 - .globl __down_interruptible_failed -__down_interruptible_failed: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __down_interruptible - mov ip, r0 - ldmfd sp!, {r0 - r3, pc} - - .align 5 - .globl __down_trylock_failed -__down_trylock_failed: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __down_trylock - mov ip, r0 - ldmfd sp!, {r0 - r3, pc} - - .align 5 - .globl __up_wakeup -__up_wakeup: - stmfd sp!, {r0 - r3, lr} - mov r0, ip - bl __up - ldmfd sp!, {r0 - r3, pc} +asm(" .align 5 \n\ + .globl __down_failed \n\ +__down_failed: \n\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + bl __down \n\ + ldmfd sp!, {r0 - r3, pc} \n\ + \n\ + .align 5 \n\ + .globl __down_interruptible_failed \n\ +__down_interruptible_failed: \n\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + 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\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + bl __down_trylock \n\ + mov ip, r0 \n\ + ldmfd sp!, {r0 - r3, pc} \n\ + \n\ + .align 5 \n\ + .globl __up_wakeup \n\ +__up_wakeup: \n\ + stmfd sp!, {r0 - r3, lr} \n\ + mov r0, ip \n\ + bl __up \n\ + ldmfd sp!, {r0 - r3, pc} \n\ "); #endif diff -urN orig/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c --- orig/arch/arm/kernel/setup.c Fri Nov 23 10:12:06 2001 +++ linux/arch/arm/kernel/setup.c Thu Feb 6 11:31:09 2003 @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -33,10 +35,6 @@ #define MEM_SIZE (16*1024*1024) #endif -#ifndef CONFIG_CMDLINE -#define CONFIG_CMDLINE "" -#endif - #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE) char fpe_type[8]; @@ -51,14 +49,14 @@ extern unsigned int mem_fclk_21285; extern void paging_init(struct meminfo *, struct machine_desc *desc); -extern void convert_to_tag_list(struct param_struct *params, int mem_init); +extern void convert_to_tag_list(struct tag *tags); +extern void squash_mem_tags(struct tag *tag); extern void bootmem_init(struct meminfo *); extern void reboot_setup(char *str); extern int root_mountflags; extern int _stext, _text, _etext, _edata, _end; unsigned int processor_id; -unsigned int compat; unsigned int __machine_arch_type; unsigned int system_rev; unsigned int system_serial_low; @@ -72,9 +70,11 @@ unsigned char aux_device_present; char elf_platform[ELF_PLATFORM_SIZE]; char saved_command_line[COMMAND_LINE_SIZE]; +unsigned long phys_initrd_start __initdata = 0; +unsigned long phys_initrd_size __initdata = 0; static struct meminfo meminfo __initdata = { 0, }; -static struct proc_info_item proc_info; +static const char *cpu_name; static const char *machine_name; static char command_line[COMMAND_LINE_SIZE]; @@ -129,15 +129,13 @@ while (1); } - proc_info = *list->info; + cpu_name = list->info->cpu_name; #ifdef MULTI_CPU processor = *list->proc; #endif - printk("Processor: %s %s revision %d\n", - proc_info.manufacturer, proc_info.cpu_name, - (int)processor_id & 15); + printk("CPU: %s revision %d\n", cpu_name, (int)processor_id & 15); sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS); sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS); @@ -146,7 +144,7 @@ cpu_proc_init(); } -static struct machine_desc * __init setup_architecture(unsigned int nr) +static struct machine_desc * __init setup_machine(unsigned int nr) { extern struct machine_desc __arch_info_begin, __arch_info_end; struct machine_desc *list; @@ -168,12 +166,7 @@ while (1); } - printk("Architecture: %s\n", list->name); - if (compat) - printk(KERN_WARNING "Using compatibility code " - "scheduled for removal in v%d.%d.%d\n", - compat >> 24, (compat >> 12) & 0x3ff, - compat & 0x3ff); + printk("Machine: %s\n", list->name); return list; } @@ -215,6 +208,22 @@ mi->bank[mi->nr_banks].size = size; mi->bank[mi->nr_banks].node = PHYS_TO_NID(start); mi->nr_banks += 1; + } else if (c == ' ' && !memcmp(from, "initrd=", 7)) { + unsigned long start, size; + + /* + * Remove space character + */ + if (to != command_line) + to -= 1; + + start = memparse(from + 7, &from); + if (*from == ',') { + size = memparse(from + 1, &from); + + phys_initrd_start = start; + phys_initrd_size = size; + } } c = *from++; if (!c) @@ -231,7 +240,7 @@ setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) { #ifdef CONFIG_BLK_DEV_RAM - extern int rd_size; + extern int rd_size, rd_image_start, rd_prompt, rd_doload; rd_image_start = image_start; rd_prompt = prompt; @@ -250,8 +259,8 @@ #ifdef CONFIG_BLK_DEV_INITRD if (start == 0) size = 0; - initrd_start = start; - initrd_end = start + size; + phys_initrd_start = __virt_to_phys(start); + phys_initrd_size = size; #endif } @@ -351,12 +360,12 @@ #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) struct screen_info screen_info = { - orig_video_lines: 30, - orig_video_cols: 80, - orig_video_mode: 0, - orig_video_ega_bx: 0, - orig_video_isVGA: 1, - orig_video_points: 8 + .orig_video_lines = 30, + .orig_video_cols = 80, + .orig_video_mode = 0, + .orig_video_ega_bx = 0, + .orig_video_isVGA = 1, + .orig_video_points = 8 }; static int __init parse_tag_videotext(const struct tag *tag) @@ -388,12 +397,22 @@ static int __init parse_tag_initrd(const struct tag *tag) { - setup_initrd(tag->u.initrd.start, tag->u.initrd.size); + phys_initrd_start = __virt_to_phys(tag->u.initrd.start); + phys_initrd_size = tag->u.initrd.size; return 0; } __tagtable(ATAG_INITRD, parse_tag_initrd); +static int __init parse_tag_initrd2(const struct tag *tag) +{ + phys_initrd_start = tag->u.initrd.start; + phys_initrd_size = tag->u.initrd.size; + return 0; +} + +__tagtable(ATAG_INITRD2, parse_tag_initrd2); + static int __init parse_tag_serialnr(const struct tag *tag) { system_serial_low = tag->u.serialnr.low; @@ -452,16 +471,30 @@ t->hdr.tag); } +static struct init_tags { + struct tag_header hdr1; + struct tag_core core; + struct tag_header hdr2; + struct tag_mem32 mem; + struct tag_header hdr3; +} init_tags __initdata = { + { tag_size(tag_core), ATAG_CORE }, + { 1, PAGE_SIZE, 0xff }, + { tag_size(tag_mem32), ATAG_MEM }, + { MEM_SIZE, PHYS_OFFSET }, + { 0, ATAG_NONE } +}; + void __init setup_arch(char **cmdline_p) { - struct tag *tags = NULL; + struct tag *tags = (struct tag *)&init_tags; struct machine_desc *mdesc; char *from = default_command_line; ROOT_DEV = MKDEV(0, 255); setup_processor(); - mdesc = setup_architecture(machine_arch_type); + mdesc = setup_machine(machine_arch_type); machine_name = mdesc->name; if (mdesc->soft_reboot) @@ -480,14 +513,16 @@ /* * If we have the old style parameters, convert them to - * a tag list before. + * a tag list. */ - if (tags && tags->hdr.tag != ATAG_CORE) - convert_to_tag_list((struct param_struct *)tags, - meminfo.nr_banks == 0); + if (tags->hdr.tag != ATAG_CORE) + convert_to_tag_list(tags); - if (tags && tags->hdr.tag == ATAG_CORE) + if (tags->hdr.tag == ATAG_CORE) { + if (meminfo.nr_banks != 0) + squash_mem_tags(tags); parse_tags(tags); + } if (meminfo.nr_banks == 0) { meminfo.nr_banks = 1; @@ -537,9 +572,8 @@ { int i; - seq_printf(m, "Processor\t: %s %s rev %d (%s)\n", - proc_info.manufacturer, proc_info.cpu_name, - (int)processor_id & 15, elf_platform); + seq_printf(m, "Processor\t: %s rev %d (%s)\n", + cpu_name, (int)processor_id & 15, elf_platform); seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", loops_per_jiffy / (500000/HZ), @@ -578,8 +612,8 @@ } struct seq_operations cpuinfo_op = { - start: c_start, - next: c_next, - stop: c_stop, - show: c_show + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show }; diff -urN orig/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c --- orig/arch/arm/kernel/signal.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/signal.c Fri Jul 4 13:36:32 2003 @@ -405,7 +405,7 @@ regs->ARM_r0 = usig; regs->ARM_sp = (unsigned long)frame; regs->ARM_lr = retcode; - regs->ARM_pc = handler & (thumb ? ~1 : ~3); + regs->ARM_pc = handler; #ifdef CONFIG_CPU_32 regs->ARM_cpsr = cpsr; @@ -466,8 +466,8 @@ * arguments for the signal handler. * -- Peter Maydell 2000-12-06 */ - regs->ARM_r1 = (unsigned long)frame->pinfo; - regs->ARM_r2 = (unsigned long)frame->puc; + regs->ARM_r1 = (unsigned long)&frame->info; + regs->ARM_r2 = (unsigned long)&frame->uc; } return err; @@ -613,7 +613,7 @@ continue; switch (signr) { - case SIGCONT: case SIGCHLD: case SIGWINCH: + case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: @@ -621,13 +621,17 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); + single_stepping |= ptrace_cancel_bpt(current); continue; + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: @@ -637,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 -urN orig/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c --- orig/arch/arm/kernel/time.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/kernel/time.c Tue Jun 24 11:16:23 2003 @@ -203,6 +203,7 @@ static struct irqaction timer_irq = { .name = "timer", + .flags = SA_INTERRUPT, }; /* diff -urN orig/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- orig/arch/arm/kernel/traps.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/kernel/traps.c Wed Jun 18 15:44:52 2003 @@ -1,7 +1,7 @@ /* * linux/arch/arm/kernel/traps.c * - * Copyright (C) 1995, 1996 Russell King + * Copyright (C) 1995-2002 Russell King * Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds * * This program is free software; you can redistribute it and/or modify @@ -63,8 +63,17 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top) { unsigned long p = bottom & ~31; + mm_segment_t fs; int i; + /* + * We need to switch to kernel mode so that we can use __get_user + * to safely read from kernel space. Note that we now dump the + * code first, just in case the backtrace kills us. + */ + fs = get_fs(); + set_fs(KERNEL_DS); + printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); for (p = bottom & ~31; p < top;) { @@ -82,6 +91,8 @@ } printk ("\n"); } + + set_fs(fs); } static void dump_instr(struct pt_regs *regs) @@ -89,8 +100,17 @@ unsigned long addr = instruction_pointer(regs); const int thumb = thumb_mode(regs); const int width = thumb ? 4 : 8; + mm_segment_t fs; int i; + /* + * We need to switch to kernel mode so that we can use __get_user + * to safely read from kernel space. Note that we now dump the + * code first, just in case the backtrace kills us. + */ + fs = get_fs(); + set_fs(KERNEL_DS); + printk("Code: "); for (i = -4; i < 1; i++) { unsigned int val, bad; @@ -108,29 +128,36 @@ } } printk("\n"); + + set_fs(fs); } -static void dump_stack(struct task_struct *tsk, unsigned long sp) +static void I_really_mean_dump_stack_so_dont_mess_with_me(struct task_struct *tsk, unsigned long sp) { - dump_mem("Stack: ", sp - 16, 8192+(unsigned long)tsk); + dump_mem("Stack: ", sp, 8192+(unsigned long)tsk); } static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) { - unsigned int fp; + unsigned int fp = regs->ARM_fp; + char *msg = ""; int ok = 1; - printk("Backtrace: "); - fp = regs->ARM_fp; +#ifdef CONFIG_FRAME_POINTER if (!fp) { - printk("no frame pointer"); + msg = "no frame pointer"; ok = 0; } else if (verify_stack(fp)) { - printk("invalid frame pointer 0x%08x", fp); + msg = "invalid frame pointer"; ok = 0; } else if (fp < 4096+(unsigned long)tsk) - printk("frame pointer underflow"); - printk("\n"); + msg = "frame pointer underflow"; +#else + msg = "not available"; + ok = 0; +#endif + + printk("Backtrace: %s\n", msg); if (ok) c_backtrace(fp, processor_mode(regs)); @@ -143,7 +170,7 @@ void show_trace_task(struct task_struct *tsk) { if (tsk != current) { - unsigned int fp = tsk->thread.save->fp; + unsigned int fp = thread_saved_fp(&tsk->thread); c_backtrace(fp, 0x10); } } @@ -163,26 +190,13 @@ printk("Internal error: %s: %x\n", str, err); printk("CPU: %d\n", smp_processor_id()); show_regs(regs); - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, 4096+(unsigned long)tsk); + printk("Process %s (pid: %d, stack limit = 0x%p)\n", + current->comm, current->pid, tsk + 1); if (!user_mode(regs) || in_interrupt()) { - mm_segment_t fs; - - /* - * We need to switch to kernel mode so that we can - * use __get_user to safely read from kernel space. - * Note that we now dump the code first, just in case - * the backtrace kills us. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - - dump_stack(tsk, (unsigned long)(regs + 1)); + I_really_mean_dump_stack_so_dont_mess_with_me(tsk, (unsigned long)(regs + 1)); dump_backtrace(regs, tsk); dump_instr(regs); - - set_fs(fs); } spin_unlock_irq(&die_lock); @@ -270,7 +284,6 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) { unsigned int vectors = vectors_base(); - mm_segment_t fs; console_verbose(); @@ -278,24 +291,14 @@ handler[reason], processor_modes[proc_mode]); /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - - /* * Dump out the vectors and stub routines. Maybe a better solution * would be to dump them out only if we detect that they are corrupted. */ dump_mem(KERN_CRIT "Vectors: ", vectors, vectors + 0x40); dump_mem(KERN_CRIT "Stubs: ", vectors + 0x200, vectors + 0x4b8); - set_fs(fs); - die("Oops", regs, 0); - cli(); + local_irq_disable(); panic("bad mode"); } @@ -356,20 +359,7 @@ return 0; case NR(breakpoint): /* SWI BREAK_POINT */ - /* - * The PC is always left pointing at the next - * instruction. Fix this. - */ - regs->ARM_pc -= 4; - __ptrace_cancel_bpt(current); - - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - info.si_addr = (void *)instruction_pointer(regs) - - (thumb_mode(regs) ? 2 : 4); - - force_sig_info(SIGTRAP, &info, current); + ptrace_break(current, regs); return regs->ARM_r0; #ifdef CONFIG_CPU_32 @@ -522,12 +512,13 @@ void __init trap_init(void) { - extern void __trap_init(void *); + extern void __trap_init(unsigned long); + unsigned long base = vectors_base(); - __trap_init((void *)vectors_base()); - if (vectors_base() != 0) - printk(KERN_DEBUG "Relocating machine vectors to 0x%08x\n", - vectors_base()); + __trap_init(base); + if (base != 0) + printk(KERN_DEBUG "Relocating machine vectors to 0x%08lx\n", + base); #ifdef CONFIG_CPU_32 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); #endif diff -urN orig/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- orig/arch/arm/lib/Makefile Fri Oct 26 16:45:51 2001 +++ linux/arch/arm/lib/Makefile Thu Oct 24 14:33:56 2002 @@ -27,15 +27,16 @@ obj-l7200 := io-acorn.o obj-shark := io-shark.o obj-edb7211 := io-acorn.o +obj-riscstation := io-acorn.o floppydma.o obj-y += $(obj-$(MACHINE)) -ifeq ($(CONFIG_CPU_32v4),y) - v3 := n - v4 := y -else +ifeq ($(CONFIG_CPU_32v3),y) v3 := y v4 := n +else + v3 := n + v4 := y endif obj-y += io-readsb.o io-writesb.o @@ -51,4 +52,3 @@ csumpartialcopy.o: csumpartialcopygeneric.S csumpartialcopyuser.o: csumpartialcopygeneric.S - diff -urN orig/arch/arm/lib/backtrace.S linux/arch/arm/lib/backtrace.S --- orig/arch/arm/lib/backtrace.S Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/lib/backtrace.S Thu Sep 5 23:15:26 2002 @@ -52,25 +52,32 @@ 3: tst frame, mask @ Check for address exceptions... bne 1b -1001: ldmda frame, {r0, r1, r2, r3} @ fp, sp, lr, pc - mov next, r0 - +1001: ldr next, [frame, #-12] @ get fp +1002: ldr r2, [frame, #-4] @ get lr +1003: ldr r3, [frame, #0] @ get pc sub save, r3, offset @ Correct PC for prefetching bic save, save, mask +1004: ldr r1, [save, #0] @ get instruction at function + mov r1, r1, lsr #10 + ldr r3, .Ldsi+4 + teq r1, r3 + subeq save, save, #4 adr r0, .Lfe mov r1, save bic r2, r2, mask - bl SYMBOL_NAME(printk) @ print pc and link register + bl printk @ print pc and link register - sub r0, frame, #16 -1002: ldr r1, [save, #4] @ get instruction at function+4 + ldr r0, [frame, #-8] @ get sp + sub r0, r0, #4 +1005: ldr r1, [save, #4] @ get instruction at function+4 mov r3, r1, lsr #10 ldr r2, .Ldsi+4 teq r3, r2 @ Check for stmia sp!, {args} addeq save, save, #4 @ next instruction bleq .Ldumpstm -1003: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction + sub r0, frame, #16 +1006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction mov r3, r1, lsr #10 ldr r2, .Ldsi teq r3, r2 @@ -87,18 +94,21 @@ */ .section .fixup,"ax" .align 0 -1004: ldr r0, =.Lbad +1007: ldr r0, =.Lbad mov r1, frame - bl SYMBOL_NAME(printk) + bl printk LOADREGS(fd, sp!, {r4 - r8, pc}) .ltorg .previous .section __ex_table,"a" .align 3 - .long 1001b, 1004b - .long 1002b, 1004b - .long 1003b, 1004b + .long 1001b, 1007b + .long 1002b, 1007b + .long 1003b, 1007b + .long 1004b, 1007b + .long 1005b, 1007b + .long 1006b, 1007b .previous #define instr r4 @@ -121,12 +131,12 @@ ldr r2, [stack], #-4 mov r1, reg adr r0, .Lfp - bl SYMBOL_NAME(printk) + bl printk 2: subs reg, reg, #1 bpl 1b teq r7, #0 adrne r0, .Lcr - blne SYMBOL_NAME(printk) + blne printk mov r0, stack LOADREGS(fd, sp!, {instr, reg, stack, r7, pc}) diff -urN orig/arch/arm/lib/csumpartial.S linux/arch/arm/lib/csumpartial.S --- orig/arch/arm/lib/csumpartial.S Fri May 25 20:06:03 2001 +++ linux/arch/arm/lib/csumpartial.S Wed Sep 11 16:20:35 2002 @@ -49,8 +49,9 @@ /* we are now half-word aligned */ .less8_wordlp: -#ifdef __ARM_ARCH_4__ - ldrh td0, [buf], #2 +#if __LINUX_ARM_ARCH__ >= 4 + ldrh td0, [buf] + add buf, buf, #2 sub len, len, #2 #else ldrb td0, [buf], #1 @@ -79,8 +80,9 @@ adcnes sum, sum, td0, lsl #8 @ update checksum tst buf, #2 @ 32-bit aligned? -#ifdef __ARM_ARCH_4__ - ldrneh td0, [buf], #2 @ make 32-bit aligned +#if __LINUX_ARM_ARCH__ >= 4 + ldrneh td0, [buf] @ make 32-bit aligned + add buf, buf, #2 subne len, len, #2 #else ldrneb td0, [buf], #1 diff -urN orig/arch/arm/lib/delay.S linux/arch/arm/lib/delay.S --- orig/arch/arm/lib/delay.S Sat Apr 28 11:24:53 2001 +++ linux/arch/arm/lib/delay.S Wed Jun 25 10:52:17 2003 @@ -1,7 +1,7 @@ /* * linux/arch/arm/lib/delay.S * - * Copyright (C) 1995, 1996 Russell King + * Copyright (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 @@ -9,45 +9,52 @@ */ #include #include - .text +#include -LC0: .word SYMBOL_NAME(loops_per_jiffy) + .text /* - * 0 <= r0 <= 2000 + * See linux/include/asm-arm/delay.h for a description of the maths. */ -ENTRY(udelay) - mov r2, #0x6800 - orr r2, r2, #0x00db + +#if NDELAY_FACTOR > 255 +#error NDELAY_FACTOR out of range +#endif +#if UDELAY_FACTOR > 65535 +#error UDELAY_FACTOR out of range +#endif + +LC0: .word SYMBOL_NAME(loops_per_jiffy) + +ENTRY(__const_delay) + ldr r3, LC0 + mov r1, r0, lsr #11 + ldr r2, [r3, #0] + b 2f + +ENTRY(__ndelay) + mov r2, #NDELAY_FACTOR + b 1f + +ENTRY(__udelay) + mov r2, #UDELAY_FACTOR & 0xff00 + orr r2, r2, #UDELAY_FACTOR & 0x00ff +1: ldr r3, LC0 mul r1, r0, r2 - ldr r2, LC0 - ldr r2, [r2] + ldr r2, [r3, #0] mov r1, r1, lsr #11 - mov r2, r2, lsr #11 +2: mov r2, r2, lsr #12 mul r0, r1, r2 - movs r0, r0, lsr #6 + movs r0, r0, lsr #5 RETINSTR(moveq,pc,lr) /* - * loops = (r0 * 0x10c6 * 100 * loops_per_jiffie) / 2^32 + * loops = (r0 * 0x10c6 * HZ * loops_per_jiffy) / 2^32 + * + * Oh, if only we had a cycle counter... */ -@ Delay routine ENTRY(__delay) subs r0, r0, #1 - RETINSTR(movcc,pc,lr) - subs r0, r0, #1 - RETINSTR(movcc,pc,lr) - subs r0, r0, #1 - RETINSTR(movcc,pc,lr) - subs r0, r0, #1 - RETINSTR(movcc,pc,lr) - subs r0, r0, #1 - RETINSTR(movcc,pc,lr) - subs r0, r0, #1 - RETINSTR(movcc,pc,lr) - subs r0, r0, #1 - RETINSTR(movcc,pc,lr) - subs r0, r0, #1 bcs SYMBOL_NAME(__delay) RETINSTR(mov,pc,lr) diff -urN orig/arch/arm/lib/longlong.h linux/arch/arm/lib/longlong.h --- orig/arch/arm/lib/longlong.h Fri Oct 26 16:45:51 2001 +++ linux/arch/arm/lib/longlong.h Thu Sep 5 23:09:22 2002 @@ -75,7 +75,7 @@ #if defined (__arm__) #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("adds %1, %4, %5 + __asm__ ("adds %1, %4, %5 \n\ adc %0, %2, %3" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ @@ -84,7 +84,7 @@ "%r" ((USItype) (al)), \ "rI" ((USItype) (bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subs %1, %4, %5 + __asm__ ("subs %1, %4, %5 \n\ sbc %0, %2, %3" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ @@ -94,18 +94,18 @@ "rI" ((USItype) (bl))) #define umul_ppmm(xh, xl, a, b) \ {register USItype __t0, __t1, __t2; \ - __asm__ ("%@ Inlined umul_ppmm - mov %2, %5, lsr #16 - mov %0, %6, lsr #16 - bic %3, %5, %2, lsl #16 - bic %4, %6, %0, lsl #16 - mul %1, %3, %4 - mul %4, %2, %4 - mul %3, %0, %3 - mul %0, %2, %0 - adds %3, %4, %3 - addcs %0, %0, #65536 - adds %1, %1, %3, lsl #16 + __asm__ ("%@ Inlined umul_ppmm \n\ + mov %2, %5, lsr #16 \n\ + mov %0, %6, lsr #16 \n\ + bic %3, %5, %2, lsl #16 \n\ + bic %4, %6, %0, lsl #16 \n\ + mul %1, %3, %4 \n\ + mul %4, %2, %4 \n\ + mul %3, %0, %3 \n\ + mul %0, %2, %0 \n\ + adds %3, %4, %3 \n\ + addcs %0, %0, #65536 \n\ + adds %1, %1, %3, lsl #16 \n\ adc %0, %0, %3, lsr #16" \ : "=&r" ((USItype) (xh)), \ "=r" ((USItype) (xl)), \ diff -urN orig/arch/arm/lib/memchr.S linux/arch/arm/lib/memchr.S --- orig/arch/arm/lib/memchr.S Tue Oct 3 20:08:19 2000 +++ linux/arch/arm/lib/memchr.S Thu Sep 5 23:10:59 2002 @@ -15,11 +15,11 @@ .text .align 5 ENTRY(memchr) -1: ldrb r3, [r0], #1 +1: subs r2, r2, #1 + bmi 2f + ldrb r3, [r0], #1 teq r3, r1 - beq 2f - subs r2, r2, #1 - bpl 1b + bne 1b + sub r0, r0, #1 2: movne r0, #0 - subeq r0, r0, #1 RETINSTR(mov,pc,lr) diff -urN orig/arch/arm/lib/muldi3.c linux/arch/arm/lib/muldi3.c --- orig/arch/arm/lib/muldi3.c Fri Oct 26 16:45:51 2001 +++ linux/arch/arm/lib/muldi3.c Thu Sep 5 23:11:40 2002 @@ -33,18 +33,18 @@ #define umul_ppmm(xh, xl, a, b) \ {register USItype __t0, __t1, __t2; \ - __asm__ ("%@ Inlined umul_ppmm - mov %2, %5, lsr #16 - mov %0, %6, lsr #16 - bic %3, %5, %2, lsl #16 - bic %4, %6, %0, lsl #16 - mul %1, %3, %4 - mul %4, %2, %4 - mul %3, %0, %3 - mul %0, %2, %0 - adds %3, %4, %3 - addcs %0, %0, #65536 - adds %1, %1, %3, lsl #16 + __asm__ ("%@ Inlined umul_ppmm \n\ + mov %2, %5, lsr #16 \n\ + mov %0, %6, lsr #16 \n\ + bic %3, %5, %2, lsl #16 \n\ + bic %4, %6, %0, lsl #16 \n\ + mul %1, %3, %4 \n\ + mul %4, %2, %4 \n\ + mul %3, %0, %3 \n\ + mul %0, %2, %0 \n\ + adds %3, %4, %3 \n\ + addcs %0, %0, #65536 \n\ + adds %1, %1, %3, lsl #16 \n\ adc %0, %0, %3, lsr #16" \ : "=&r" ((USItype) (xh)), \ "=r" ((USItype) (xl)), \ diff -urN orig/arch/arm/lib/strchr.S linux/arch/arm/lib/strchr.S --- orig/arch/arm/lib/strchr.S Tue Oct 3 20:08:19 2000 +++ linux/arch/arm/lib/strchr.S Sat Sep 21 11:20:06 2002 @@ -15,11 +15,12 @@ .text .align 5 ENTRY(strchr) + and r1, r1, #0xff 1: ldrb r2, [r0], #1 teq r2, r1 teqne r2, #0 bne 1b - teq r2, #0 - moveq r0, #0 - subne r0, r0, #1 + teq r2, r1 + movne r0, #0 + subeq r0, r0, #1 RETINSTR(mov,pc,lr) diff -urN orig/arch/arm/lib/udivdi3.c linux/arch/arm/lib/udivdi3.c --- orig/arch/arm/lib/udivdi3.c Fri Oct 26 16:45:51 2001 +++ linux/arch/arm/lib/udivdi3.c Sat May 18 21:17:48 2002 @@ -229,3 +229,14 @@ { return __udivmoddi4 (n, d, (UDItype *) 0); } + +UDItype +__umoddi3 (UDItype u, UDItype v) +{ + UDItype w; + + (void) __udivmoddi4 (u ,v, &w); + + return w; +} + diff -urN orig/arch/arm/mach-anakin/irq.c linux/arch/arm/mach-anakin/irq.c --- orig/arch/arm/mach-anakin/irq.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-anakin/irq.c Tue Feb 4 15:08:01 2003 @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include diff -urN orig/arch/arm/mach-at91rm9200/Makefile linux/arch/arm/mach-at91rm9200/Makefile --- orig/arch/arm/mach-at91rm9200/Makefile Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-at91rm9200/Makefile Fri Jun 13 22:19:08 2003 @@ -0,0 +1,21 @@ +# +# 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 := at91rm9200.o + +# Object file lists. + +obj-y := core.o +obj-m := +obj-n := +obj- := + +export-objs := + +include $(TOPDIR)/Rules.make diff -urN orig/arch/arm/mach-at91rm9200/core.c linux/arch/arm/mach-at91rm9200/core.c --- orig/arch/arm/mach-at91rm9200/core.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-at91rm9200/core.c Fri Jun 13 22:21:22 2003 @@ -0,0 +1,183 @@ +/* + * linux/arch/arm/mach-at91rm9200/core.c + * + * Copyright (c) 2003 SAN People + * Copyright (c) 2003 ATMEL + * Copyright (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* + * System peripheral registers mapped at virtual address. + */ +AT91PS_SYS AT91_SYS = (AT91PS_SYS) AT91C_VA_BASE_SYS; + +static struct map_desc at91rm9200_io_desc[] __initdata = { + /* virtual, physical, length, domain, r, w, c, b */ + { AT91C_VA_BASE_SYS, AT91C_BASE_SYS, SZ_4K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_SPI, AT91C_BASE_SPI, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_SSC2, AT91C_BASE_SSC2, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_SSC1, AT91C_BASE_SSC1, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_SSC0, AT91C_BASE_SSC0, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_US3, AT91C_BASE_US3, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_US2, AT91C_BASE_US2, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_US1, AT91C_BASE_US1, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_US0, AT91C_BASE_US0, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_EMAC, AT91C_BASE_EMAC, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_TWI, AT91C_BASE_TWI, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_MCI, AT91C_BASE_MCI, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_UDP, AT91C_BASE_UDP, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_TCB1, AT91C_BASE_TCB1, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + { AT91C_VA_BASE_TCB0, AT91C_BASE_TCB0, SZ_16K, DOMAIN_IO, 0, 1, 0, 0}, + LAST_DESC +}; + +/* Interrupt configuration */ +static AT91_REG at91rm9200_irq_smr[] __initdata = { + (AT91_SMR_FIQ), /* FIQ */ + (AT91_SMR_SYS), /* System Peripherals */ + (AT91_SMR_PIOA), /* PIO A */ + (AT91_SMR_PIOB), /* PIO B */ + (AT91_SMR_PIOC), /* PIO C */ + (AT91_SMR_PIOD), /* PIO D */ + (AT91_SMR_US0), /* USART 0 */ + (AT91_SMR_US1), /* USART 1 */ + (AT91_SMR_US2), /* USART 2 */ + (AT91_SMR_US3), /* USART 3 */ + (AT91_SMR_MCI), /* Multimedia Card */ + (AT91_SMR_UDP), /* USB Device */ + (AT91_SMR_TWI), /* Two-wire interface */ + (AT91_SMR_SPI), /* SPI */ + (AT91_SMR_SSC0), /* Sync Serial 0 */ + (AT91_SMR_SSC1), /* Sync Serial 1 */ + (AT91_SMR_SSC2), /* Sync Serial 2 */ + (AT91_SMR_TC0), /* TC 0 */ + (AT91_SMR_TC1), /* TC 1 */ + (AT91_SMR_TC2), /* TC 2 */ + (AT91_SMR_TC3), /* TC 3 */ + (AT91_SMR_TC4), /* TC 4 */ + (AT91_SMR_TC5), /* TC 5 */ + (AT91_SMR_UHP), /* USB Host */ + (AT91_SMR_EMAC), /* Ethernet */ + (AT91_SMR_IRQ0), /* IRQ 0 */ + (AT91_SMR_IRQ1), /* IRQ 1 */ + (AT91_SMR_IRQ2), /* IRQ 2 */ + (AT91_SMR_IRQ3), /* IRQ 3 */ + (AT91_SMR_IRQ4), /* IRQ 4 */ + (AT91_SMR_IRQ5), /* IRQ 5 */ + (AT91_SMR_IRQ6) /* IRQ 6 */ +}; + +/* Architecture-specific fixups */ +static void __init at91rm9200_fixup(struct machine_desc *desc, struct param_struct *unused, + char **cmdline, struct meminfo *mi) +{ +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + setup_ramdisk(1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE); +// setup_initrd(0xc0100000, 3*1024*1024); +#endif +} + +extern void at91_register_uart(int idx, int port); + +void __init at91rm9200_map_io(void) +{ + int serial[AT91C_NR_UART] = AT91C_UART_MAP; + int i; + + iotable_init(at91rm9200_io_desc); + + /* Register UARTs */ + for (i = 0; i < AT91C_NR_UART; i++) { + if (serial[i] >= 0) + at91_register_uart(i, serial[i]); + } +} + +static void at91rm9200_mask_irq(unsigned int irq) +{ + /* Disable interrupt on AIC */ + AT91_SYS->AIC_IDCR = 1 << irq; +} + +static void at91rm9200_unmask_irq(unsigned int irq) +{ + /* Enable interrupt on AIC */ + AT91_SYS->AIC_IECR = 1 << irq; +} + +void __init at91rm9200_init_irq(void) +{ + unsigned int i; + + /* + * The IVR is used by macro get_irqnr_and_base to read and verify. + * The irq number is NR_IRQS when a spurious interrupt has occured. + */ + for (i = 0; i < NR_IRQS; i++) { + /* Put irq number in Source Vector Register: */ + AT91_SYS->AIC_SVR[i] = i; + /* Store the Source Mode Register as defined in table above */ + AT91_SYS->AIC_SMR[i] = at91rm9200_irq_smr[i]; + + irq_desc[i].valid = 1; + irq_desc[i].mask_ack = at91rm9200_mask_irq; + irq_desc[i].mask = at91rm9200_mask_irq; + irq_desc[i].unmask = at91rm9200_unmask_irq; + + /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */ + if (i < 8) + AT91_SYS->AIC_EOICR = AT91_SYS->AIC_EOICR; + } + + /* Spurious Interrupt ID in Spurious Vector Register is NR_IRQS + * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU + */ + AT91_SYS->AIC_SPU = NR_IRQS; + + /* No debugging in AIC: Debug (Protect) Control Register */ + AT91_SYS->AIC_DCR = 0; + + /* Disable and clear all interrupts initially */ + AT91_SYS->AIC_IDCR = 0xFFFFFFFF; + AT91_SYS->AIC_ICCR = 0xFFFFFFFF; +} + +MACHINE_START(AT91RM9200, "ATMEL AT91RM9200") + MAINTAINER("SAN People / ATMEL") + BOOT_MEM(AT91_SDRAM_BASE, AT91C_BASE_SYS, AT91C_VA_BASE_SYS) + BOOT_PARAMS(AT91_SDRAM_BASE + 0x100) + FIXUP(at91rm9200_fixup) + MAPIO(at91rm9200_map_io) + INITIRQ(at91rm9200_init_irq) +MACHINE_END diff -urN orig/arch/arm/mach-clps711x/Makefile linux/arch/arm/mach-clps711x/Makefile --- orig/arch/arm/mach-clps711x/Makefile Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/mach-clps711x/Makefile Thu Feb 27 23:20:10 2003 @@ -16,12 +16,13 @@ obj-n := obj- := -export-objs := leds-p720t.o +export-objs := p720t-leds.o obj-$(CONFIG_ARCH_AUTCPU12) += autcpu12.o obj-$(CONFIG_ARCH_CDB89712) += cdb89712.o obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o obj-$(CONFIG_ARCH_EDB7211) += edb7211-arch.o edb7211-mm.o +obj-$(CONFIG_ARCH_GUIDEA07) += guide-a07.o obj-$(CONFIG_ARCH_P720T) += p720t.o obj-$(CONFIG_ARCH_FORTUNET) += fortunet.o leds-$(CONFIG_ARCH_P720T) += p720t-leds.o diff -urN orig/arch/arm/mach-clps711x/fortunet.c linux/arch/arm/mach-clps711x/fortunet.c --- orig/arch/arm/mach-clps711x/fortunet.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/mach-clps711x/fortunet.c Sat May 18 21:17:48 2002 @@ -31,6 +31,10 @@ #include #include +#include +#include +#include + #include #include @@ -48,9 +52,11 @@ int extra_param_type; int extra_param_ptr; int command_line; + int extra_ram_start; + int extra_ram_size; } IMAGE_PARAMS; -#define IMAGE_PARAMS_PHYS 0xC01F0000 +#define IMAGE_PARAMS_PHYS 0xC0200000 static void __init fortunet_fixup(struct machine_desc *desc, struct param_struct *params, @@ -67,14 +73,23 @@ } #endif memmap.bank[0].size = ip->ram_size; + memmap.bank[0].node = PHYS_TO_NID(0xC0000000); + if(ip->extra_ram_size) + { + memmap.bank[1].start = ip->extra_ram_start; + memmap.bank[1].size = ip->extra_ram_size; + memmap.bank[1].node = PHYS_TO_NID(ip->extra_ram_start); + mi->nr_banks=2; + } memmap.end = ip->ram_size+0xC0000000; *mi = memmap; } MACHINE_START(FORTUNET, "ARM-FortuNet") MAINTAINER("FortuNet Inc.") - BOOT_MEM(0xc0000000, 0x80000000, 0xf0000000) + BOOT_MEM(0xc0000000, 0x80000000, 0xff000000) BOOT_PARAMS(0x00000000) + VIDEO(0xC0000000,0xC00020000) FIXUP(fortunet_fixup) MAPIO(clps711x_map_io) INITIRQ(clps711x_init_irq) diff -urN orig/arch/arm/mach-clps711x/guide-a07.c linux/arch/arm/mach-clps711x/guide-a07.c --- orig/arch/arm/mach-clps711x/guide-a07.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-clps711x/guide-a07.c Fri Jun 13 22:04:51 2003 @@ -0,0 +1,92 @@ +/* + * linux/arch/arm/mach-clps711x/guide-a07.c + * + * Copyright (C) 2003 Iders Incorporated + * Copyright (C) 2000-2001 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 +#include +#include +#include +#include +#include +#include + +extern void clps711x_init_irq(void); +extern void clps711x_map_io(void); + +#ifndef CONFIG_I2C_GUIDE +#error Config error - The Guide A07 requires I2C Guide GPIO support. Please enable it. +#endif + +/* + * Map the CS89712 Ethernet port. That should be moved to the + * ethernet driver, perhaps. + * also map the Guide FPGA and persistance locations + */ +static struct map_desc guide_a07_io_desc[] __initdata = { + { ETHER_BASE, ETHER_START, ETHER_SIZE, + DOMAIN_IO, 0, 1, 0, 0 }, + { GD_A07_FPGA_BASE, GD_A07_FPGA_START, GD_A07_FPGA_SIZE, + DOMAIN_IO, 0, 1, 0, 0 }, + { GD_A07_PERSISTANCE_BASE, GD_A07_PERSISTANCE_START, GD_A07_PERSISTANCE_SIZE, + DOMAIN_IO, 0, 1, 0, 0 }, + LAST_DESC +}; + +static void __init +fixup_guide_a07(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ +} + +static void __init guide_a07_map_io(void) +{ + clps711x_map_io(); + iotable_init(guide_a07_io_desc); +} + +MACHINE_START(GUIDEA07, "Guide A07 (cs89712 core)") + MAINTAINER("Cam Mayor") + VIDEO(0x60000000, 0x6000bfff) + BOOT_MEM(0xc0000000, 0x80000000, 0xff000000) + BOOT_PARAMS(0xc0000100) + FIXUP(fixup_guide_a07) + MAPIO(guide_a07_map_io) + INITIRQ(clps711x_init_irq) +MACHINE_END + +static int guide_a07_hw_init(void) +{ + /* in cs[1] (the FPGA), set zero wait states, clkenb, and sqaen */ + u32 memcfg1 = 0xfc << 8; + memcfg1 |= clps_readl(MEMCFG1); + clps_writel(memcfg1, MEMCFG1); + + return 0; +} + +__initcall(guide_a07_hw_init); + diff -urN orig/arch/arm/mach-clps711x/irq.c linux/arch/arm/mach-clps711x/irq.c --- orig/arch/arm/mach-clps711x/irq.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/mach-clps711x/irq.c Sun Apr 13 18:15:08 2003 @@ -18,6 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include +#include +#include #include #include diff -urN orig/arch/arm/mach-ebsa110/irq.c linux/arch/arm/mach-ebsa110/irq.c --- orig/arch/arm/mach-ebsa110/irq.c Sat Apr 28 11:24:53 2001 +++ linux/arch/arm/mach-ebsa110/irq.c Wed Mar 19 16:52:57 2003 @@ -11,6 +11,9 @@ * 22-08-1998 RMK Restructured IRQ routines */ #include +#include +#include +#include #include #include @@ -35,14 +38,14 @@ unsigned long flags; int irq; - save_flags_cli (flags); + local_irq_save(flags); __raw_writeb(0xff, IRQ_MCLR); __raw_writeb(0x55, IRQ_MSET); __raw_writeb(0x00, IRQ_MSET); if (__raw_readb(IRQ_MASK) != 0x55) while (1); __raw_writeb(0xff, IRQ_MCLR); /* clear all interrupt enables */ - restore_flags (flags); + local_irq_restore(flags); for (irq = 0; irq < NR_IRQS; irq++) { irq_desc[irq].valid = 1; diff -urN orig/arch/arm/mach-epxa/Makefile linux/arch/arm/mach-epxa/Makefile --- orig/arch/arm/mach-epxa/Makefile Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-epxa/Makefile Mon Aug 5 23:25:12 2002 @@ -0,0 +1,24 @@ +# +# 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 := epxa.o + +# Object file lists. + +obj-y := irq.o mm.o time.o +obj-m := +obj-n := +obj- := + +export-objs := + +obj-$(CONFIG_EPXA1DB) += arch-epxa1db.o +obj-$(CONFIG_EPXA10DB) += arch-epxa10db.o + +include $(TOPDIR)/Rules.make diff -urN orig/arch/arm/mach-epxa/arch-epxa10db.c linux/arch/arm/mach-epxa/arch-epxa10db.c --- orig/arch/arm/mach-epxa/arch-epxa10db.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-epxa/arch-epxa10db.c Fri Feb 21 15:17:33 2003 @@ -0,0 +1,60 @@ +/* + * linux/arch/arm/mach-epxa/arch-epxa10db.c + * + * Copyright (C) 2001 Altera 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +extern void epxa_map_io(void); +extern void epxa_init_irq(void); + + +static void __init +epxa10db_fixup(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + + mi->nr_banks = 1; + mi->bank[0].start = 0; + mi->bank[0].size = (128*1024*1024); + mi->bank[0].node = 0; + +/* + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd(0xc0200000, 6*1024*1024); +*/ +} + +MACHINE_START(CAMELOT, "Altera Epxa10db") + MAINTAINER("Altera Corporation") + BOOT_MEM(0x00000000, 0x7fffc000, 0xffffc000) + FIXUP(epxa10db_fixup) + MAPIO(epxa_map_io) + INITIRQ(epxa_init_irq) + BOOT_PARAMS(0x100) +MACHINE_END diff -urN orig/arch/arm/mach-epxa/arch-epxa1db.c linux/arch/arm/mach-epxa/arch-epxa1db.c --- orig/arch/arm/mach-epxa/arch-epxa1db.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-epxa/arch-epxa1db.c Thu Oct 24 13:35:37 2002 @@ -0,0 +1,59 @@ +/* + * linux/arch/arm/mach-epxa/arch-epxa10db.c + * + * Copyright (C) 2001 Altera 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +extern void epxa_map_io(void); +extern void epxa_init_irq(void); + +static void __init +epxa1db_fixup(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + + mi->nr_banks = 1; + mi->bank[0].start = 0; + mi->bank[0].size = (32*1024*1024); + mi->bank[0].node = 0; + +/* + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd(0xc0200000, 6*1024*1024); +*/ +} + +MACHINE_START(CAMELOT, "Altera Epxa1db") + MAINTAINER("Altera Corporation") + BOOT_MEM(0x00000000, 0x7fffc000, 0xffffc000) + FIXUP(epxa1db_fixup) + MAPIO(epxa_map_io) + INITIRQ(epxa_init_irq) + BOOT_PARAMS(0x100) +MACHINE_END diff -urN orig/arch/arm/mach-epxa/dma.c linux/arch/arm/mach-epxa/dma.c --- orig/arch/arm/mach-epxa/dma.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-epxa/dma.c Fri Nov 23 10:20:49 2001 @@ -0,0 +1,36 @@ +/* + * linux/arch/arm/mach-epxa10db/dma.c + * + * Copyright (C) 1999 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 + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +void __init arch_dma_init(dma_t *dma) +{ +} diff -urN orig/arch/arm/mach-epxa/irq.c linux/arch/arm/mach-epxa/irq.c --- orig/arch/arm/mach-epxa/irq.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-epxa/irq.c Wed Feb 12 17:14:51 2003 @@ -0,0 +1,74 @@ +/* + * linux/arch/arm/mach-epxa10db/irq.c + * + * Copyright (C) 2001 Altera 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +static void mask_irq(unsigned int irq) +{ + __raw_writel(1 << irq, INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE))); +} + +static void unmask_irq(unsigned int irq) +{ + __raw_writel(1 << irq, INT_MS(IO_ADDRESS(EXC_INT_CTRL00_BASE))); +} + +void __init epxa_init_irq(void) +{ + unsigned int i; + + /* + * This bit sets up the interrupt controller using + * the 6 PLD interrupts mode (the default) each + * irqs is assigned a priority which is the same + * as its interrupt number. This scheme is used because + * its easy, but you may want to change it depending + * on the contents of your PLD + */ + + __raw_writel(3,INT_MODE(IO_ADDRESS(EXC_INT_CTRL00_BASE))); + for (i = 0; i < NR_IRQS; i++){ + __raw_writel(i+1, INT_PRIORITY_P0(IO_ADDRESS(EXC_INT_CTRL00_BASE)) + (4*i)); + } + + + for (i = 0; i < NR_IRQS; i++) { + + irq_desc[i].valid = 1; + irq_desc[i].probe_ok = 1; + irq_desc[i].mask_ack = mask_irq; + irq_desc[i].mask = mask_irq; + irq_desc[i].unmask = unmask_irq; + } + + /* Disable all interrupt */ + __raw_writel(-1,INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE))); + +} diff -urN orig/arch/arm/mach-epxa/mm.c linux/arch/arm/mach-epxa/mm.c --- orig/arch/arm/mach-epxa/mm.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-epxa/mm.c Mon Aug 5 23:25:13 2002 @@ -0,0 +1,43 @@ +/* + * linux/arch/arm/mach-epxa10db/mm.c + * + * MM routines for Altera'a Epxa10db board + * + * Copyright (C) 2001 Altera 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* Page table mapping for I/O region */ + +static struct map_desc epxa_io_desc[] __initdata = { + { IO_ADDRESS(EXC_REGISTERS_BASE), EXC_REGISTERS_BASE, SZ_4K , DOMAIN_IO, 0, 1}, LAST_DESC +}; + +void __init epxa_map_io(void) +{ + iotable_init(epxa_io_desc); +} diff -urN orig/arch/arm/mach-epxa/time.c linux/arch/arm/mach-epxa/time.c --- orig/arch/arm/mach-epxa/time.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-epxa/time.c Fri Oct 12 14:28:54 2001 @@ -0,0 +1,33 @@ +/* + * linux/arch/arm/mach-epxa10db/time.c + * + * Copyright (C) 2000 Deep Blue Solutions + * Copyright (C) 2001 Altera Corporation + * + * 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 + + + +extern int (*set_rtc)(void); + +static int epxa10db_set_rtc(void) +{ + return 1; +} + +static int epxa10db_rtc_init(void) +{ + set_rtc = epxa10db_set_rtc; + + return 0; +} + +__initcall(epxa10db_rtc_init); diff -urN orig/arch/arm/mach-epxa10db/Makefile linux/arch/arm/mach-epxa10db/Makefile --- orig/arch/arm/mach-epxa10db/Makefile Fri Nov 16 10:09:48 2001 +++ linux/arch/arm/mach-epxa10db/Makefile Thu Jan 1 01:00:00 1970 @@ -1,22 +0,0 @@ -# -# 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 := epxa10db.o - -# Object file lists. - -obj-y := arch.o irq.o mm.o time.o -obj-m := -obj-n := -obj- := - -export-objs := - - -include $(TOPDIR)/Rules.make diff -urN orig/arch/arm/mach-epxa10db/arch.c linux/arch/arm/mach-epxa10db/arch.c --- orig/arch/arm/mach-epxa10db/arch.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/mach-epxa10db/arch.c Thu Jan 1 01:00:00 1970 @@ -1,61 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/arch.c - * - * Copyright (C) 2000 Deep Blue Solutions Ltd - * Copyright (C) 2001 Altera 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -extern void epxa10db_map_io(void); -extern void epxa10db_init_irq(void); - - -static void __init -epxa10db_fixup(struct machine_desc *desc, struct param_struct *params, - char **cmdline, struct meminfo *mi) -{ - - mi->nr_banks = 1; - mi->bank[0].start = 0; - mi->bank[0].size = (32*1024*1024); - mi->bank[0].node = 0; - -/* - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd(0xc0200000, 6*1024*1024); -*/ -} - -MACHINE_START(CAMELOT, "Altera Epxa10db") - MAINTAINER("Altera Corporation") - BOOT_MEM(0x00000000, 0x7fffc000, 0xffffc000) - FIXUP(epxa10db_fixup) - MAPIO(epxa10db_map_io) - INITIRQ(epxa10db_init_irq) - -MACHINE_END diff -urN orig/arch/arm/mach-epxa10db/dma.c linux/arch/arm/mach-epxa10db/dma.c --- orig/arch/arm/mach-epxa10db/dma.c Fri Nov 23 10:12:06 2001 +++ linux/arch/arm/mach-epxa10db/dma.c Thu Jan 1 01:00:00 1970 @@ -1,36 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/dma.c - * - * Copyright (C) 1999 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 - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -void __init arch_dma_init(dma_t *dma) -{ -} diff -urN orig/arch/arm/mach-epxa10db/irq.c linux/arch/arm/mach-epxa10db/irq.c --- orig/arch/arm/mach-epxa10db/irq.c Fri Nov 16 10:09:48 2001 +++ linux/arch/arm/mach-epxa10db/irq.c Thu Jan 1 01:00:00 1970 @@ -1,70 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/irq.c - * - * Copyright (C) 2001 Altera 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include - - -static void mask_irq(unsigned int irq) -{ - __raw_writel(1 << irq, INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE))); -} - -static void unmask_irq(unsigned int irq) -{ - __raw_writel(1 << irq, INT_MS(IO_ADDRESS(EXC_INT_CTRL00_BASE))); -} - -void __init epxa10db_init_irq(void) -{ - unsigned int i; - - /* - * This bit sets up the interrupt controller using - * the 6 PLD interrupts mode (the default) each - * irqs is assigned a priority which is the same - * as its interrupt number. This scheme is used because - * its easy, but you may want to change it depending - * on the contents of your PLD - */ - - __raw_writel(3,INT_MODE(IO_ADDRESS(EXC_INT_CTRL00_BASE))); - for (i = 0; i < NR_IRQS; i++){ - __raw_writel(i+1, INT_PRIORITY_P0(IO_ADDRESS(EXC_INT_CTRL00_BASE)) + (4*i)); - } - - - for (i = 0; i < NR_IRQS; i++) { - - irq_desc[i].valid = 1; - irq_desc[i].probe_ok = 1; - irq_desc[i].mask_ack = mask_irq; - irq_desc[i].mask = mask_irq; - irq_desc[i].unmask = unmask_irq; - } - - /* Disable all interrupt */ - __raw_writel(-1,INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE))); - -} diff -urN orig/arch/arm/mach-epxa10db/mm.c linux/arch/arm/mach-epxa10db/mm.c --- orig/arch/arm/mach-epxa10db/mm.c Mon Aug 5 13:29:44 2002 +++ linux/arch/arm/mach-epxa10db/mm.c Thu Jan 1 01:00:00 1970 @@ -1,49 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/mm.c - * - * MM routines for Altera'a Epxa10db board - * - * Copyright (C) 2001 Altera 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -/* Page table mapping for I/O region */ - -static struct map_desc epxa10db_io_desc[] __initdata = { - { IO_ADDRESS(EXC_REGISTERS_BASE), EXC_REGISTERS_BASE, SZ_16K , DOMAIN_IO, 0, 1}, -{IO_ADDRESS(EXC_PLD_BLOCK0_BASE), EXC_PLD_BLOCK0_BASE, SZ_16K , DOMAIN_IO, 0, 1}, -{IO_ADDRESS(EXC_PLD_BLOCK1_BASE), EXC_PLD_BLOCK1_BASE, SZ_16K , DOMAIN_IO, 0, 1}, -{IO_ADDRESS(EXC_PLD_BLOCK2_BASE), EXC_PLD_BLOCK2_BASE, SZ_16K , DOMAIN_IO, 0, 1}, -{IO_ADDRESS(EXC_PLD_BLOCK3_BASE), EXC_PLD_BLOCK3_BASE, SZ_16K , DOMAIN_IO, 0, 1}, -{ FLASH_VADDR(EXC_EBI_BLOCK0_BASE), EXC_EBI_BLOCK0_BASE, SZ_16M , DOMAIN_IO, 0, 1}, - LAST_DESC -}; - -void __init epxa10db_map_io(void) -{ - iotable_init(epxa10db_io_desc); -} diff -urN orig/arch/arm/mach-epxa10db/time.c linux/arch/arm/mach-epxa10db/time.c --- orig/arch/arm/mach-epxa10db/time.c Fri Nov 16 10:09:48 2001 +++ linux/arch/arm/mach-epxa10db/time.c Thu Jan 1 01:00:00 1970 @@ -1,33 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/time.c - * - * Copyright (C) 2000 Deep Blue Solutions - * Copyright (C) 2001 Altera Corporation - * - * 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 - - - -extern int (*set_rtc)(void); - -static int epxa10db_set_rtc(void) -{ - return 1; -} - -static int epxa10db_rtc_init(void) -{ - set_rtc = epxa10db_set_rtc; - - return 0; -} - -__initcall(epxa10db_rtc_init); diff -urN orig/arch/arm/mach-footbridge/arch.c linux/arch/arm/mach-footbridge/arch.c --- orig/arch/arm/mach-footbridge/arch.c Mon Sep 3 14:14:40 2001 +++ linux/arch/arm/mach-footbridge/arch.c Sun Mar 24 21:11:24 2002 @@ -41,10 +41,12 @@ fixup_ebsa285(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { +#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) ORIG_X = params->u1.s.video_x; ORIG_Y = params->u1.s.video_y; ORIG_VIDEO_COLS = params->u1.s.video_num_cols; ORIG_VIDEO_LINES = params->u1.s.video_num_rows; +#endif } MACHINE_START(EBSA285, "EBSA285") diff -urN orig/arch/arm/mach-footbridge/irq.c linux/arch/arm/mach-footbridge/irq.c --- orig/arch/arm/mach-footbridge/irq.c Sat Apr 28 11:24:53 2001 +++ linux/arch/arm/mach-footbridge/irq.c Tue Feb 4 15:08:01 2003 @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include diff -urN orig/arch/arm/mach-integrator/cpu.c linux/arch/arm/mach-integrator/cpu.c --- orig/arch/arm/mach-integrator/cpu.c Wed Jun 18 13:01:05 2003 +++ linux/arch/arm/mach-integrator/cpu.c Mon Jun 17 11:38:10 2002 @@ -3,7 +3,7 @@ * * Copyright (C) 2001 Deep Blue Solutions Ltd. * - * $Id: cpu.c,v 1.2 2001/09/22 12:11:17 rmk Exp $ + * $Id: cpu.c,v 1.2.2.1 2002/05/30 15:08:03 db Exp $ * * 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 diff -urN orig/arch/arm/mach-integrator/irq.c linux/arch/arm/mach-integrator/irq.c --- orig/arch/arm/mach-integrator/irq.c Sat Mar 31 23:47:15 2001 +++ linux/arch/arm/mach-integrator/irq.c Mon Jun 16 15:22:51 2003 @@ -18,6 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include +#include +#include #include #include diff -urN orig/arch/arm/mach-integrator/pci_v3.c linux/arch/arm/mach-integrator/pci_v3.c --- orig/arch/arm/mach-integrator/pci_v3.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-integrator/pci_v3.c Wed Jul 16 16:33:02 2003 @@ -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 -urN orig/arch/arm/mach-mx1ads/irq.c linux/arch/arm/mach-mx1ads/irq.c --- orig/arch/arm/mach-mx1ads/irq.c Mon Aug 5 13:29:45 2002 +++ linux/arch/arm/mach-mx1ads/irq.c Tue Feb 4 15:08:01 2003 @@ -19,6 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include +#include #include #include diff -urN orig/arch/arm/mach-omaha/Makefile linux/arch/arm/mach-omaha/Makefile --- orig/arch/arm/mach-omaha/Makefile Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-omaha/Makefile Thu Oct 24 14:58:03 2002 @@ -0,0 +1,21 @@ +# +# 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 := omaha.o + +# Object file lists. + +obj-y := core.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_LEDS) += leds.o + +include $(TOPDIR)/Rules.make diff -urN orig/arch/arm/mach-omaha/core.c linux/arch/arm/mach-omaha/core.c --- orig/arch/arm/mach-omaha/core.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-omaha/core.c Thu Feb 6 11:30:13 2003 @@ -0,0 +1,130 @@ +/* + * linux/arch/arm/mach-omaha/core.c + * + * Copyright (C) ARM Limited 2002. + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern void omaha_map_io(void); + +/* + * All IO addresses are mapped onto VA 0xExxx.xxxx, where x.xxxx + * is the (PA + 0xE0000000). + * + * Setup a VA for the Omaha interrupt controller. + */ + +#define VA_IC_BASE IO_ADDRESS(PLAT_PERIPHERAL_BASE) + +static void sc_mask_and_ack_irq(unsigned int irq) +{ + unsigned int tmp; + + // Mask this interrupt + tmp = __raw_readl(VA_IC_BASE + OMAHA_INTMSK); + tmp = tmp | (1 << irq); + __raw_writel(tmp, VA_IC_BASE + OMAHA_INTMSK); + + // Clear the source pending register + tmp = __raw_readl(VA_IC_BASE + OMAHA_SRCPND); + tmp = tmp | (1 << irq); + __raw_writel(tmp, VA_IC_BASE + OMAHA_SRCPND); + + // Clear the interrupt pending register + tmp = __raw_readl(VA_IC_BASE + OMAHA_INTPND); + tmp = tmp | (1 << irq); + __raw_writel(tmp, VA_IC_BASE + OMAHA_INTPND); + +} + +static void sc_mask_irq(unsigned int irq) +{ + unsigned int tmp; + + // Mask this interrupt + tmp = __raw_readl(VA_IC_BASE + OMAHA_INTMSK); + tmp = tmp | (1 << irq); + __raw_writel(tmp, VA_IC_BASE + OMAHA_INTMSK); +} + +static void sc_unmask_irq(unsigned int irq) +{ + unsigned int tmp; + + tmp = __raw_readl(VA_IC_BASE + OMAHA_INTMSK); + tmp = tmp & ~(1 << irq); + __raw_writel(tmp, VA_IC_BASE + OMAHA_INTMSK); +} + +static void __init omaha_init_irq(void) +{ + unsigned int i; + + /* bootloader disables interrupt hardware, + * so we just set up linux data structures... + */ + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].valid = 1; + irq_desc[i].probe_ok = 1; + irq_desc[i].mask_ack = sc_mask_and_ack_irq; + irq_desc[i].mask = sc_mask_irq; + irq_desc[i].unmask = sc_unmask_irq; + } +} + +/* Notes + * + * IO space has been mapped into the top of virtual memory at 0xExxx xxxx + * See IO_ACCESS macro for details. + */ + +/* Logical Physical + * Start 0xE0000000 0x00000000 + * End 0xFAFFFFFC 0x1AFFFFFC + */ + +/* Map the bottom 2Gb of IO space into the top of memory, but leave + * space for the high vector table. + */ +static struct map_desc omaha_io_desc[] __initdata = { + { IO_ADDRESS(0x00000000), 0x00000000, 0x1B000000, DOMAIN_IO, 0, 1 }, + LAST_DESC +}; + +static void __init omaha_map_io(void) +{ diff -urN orig/arch/arm/mach-omaha/leds.c linux/arch/arm/mach-omaha/leds.c --- orig/arch/arm/mach-omaha/leds.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-omaha/leds.c Thu Oct 24 14:58:03 2002 @@ -0,0 +1,89 @@ +/* + * linux/arch/arm/mach-omaha/leds.c + * + * Omaha LED control routines + * + * Copyright (C) 1999-2002 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 + */ +#include +#include + +#include +#include +#include +#include +#include + +static int saved_leds; + +static void omaha_leds_event(led_event_t ledevt) +{ + unsigned long flags; + unsigned int ctrl = IO_ADDRESS(PLAT_DBG_LEDS); + unsigned int leds; + + // yup, change the LEDs + local_irq_save(flags); + + switch(ledevt) { + case led_idle_start: + leds = __raw_readl(ctrl); + leds |= GREEN_LED; + __raw_writel(leds,ctrl); + break; + + case led_idle_end: + leds = __raw_readl(ctrl); + leds &= ~GREEN_LED; + __raw_writel(leds,ctrl); + break; + + case led_timer: + leds = __raw_readl(ctrl); + leds ^= YELLOW_LED; + __raw_writel(leds,ctrl); + break; + + case led_red_on: + leds = __raw_readl(ctrl); + leds |= RED_LED; + __raw_writel(leds,ctrl); + break; + + case led_red_off: + leds = __raw_readl(ctrl); + leds &= ~RED_LED; + __raw_writel(leds,ctrl); + break; + + default: + break; + } + + local_irq_restore(flags); +} + +static int __init leds_init(void) +{ + if (machine_is_omaha()) + leds_event = omaha_leds_event; + + return 0; +} + +__initcall(leds_init); diff -urN orig/arch/arm/mach-sa1100/Makefile linux/arch/arm/mach-sa1100/Makefile --- orig/arch/arm/mach-sa1100/Makefile Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/Makefile Fri Jun 13 22:06:31 2003 @@ -15,10 +15,10 @@ obj-n := obj- := -export-objs := assabet.o dma-sa1100.o dma-sa1111.o \ - flexanet.o freebird.o generic.o h3600.o \ - huw_webpanel.o irq.o pcipool.o sa1111.o sa1111-pcibuf.o \ - system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o +export-objs := assabet.o consus.o badge4.o dma-sa1100.o dma-sa1111.o \ + flexanet.o freebird.o frodo.o generic.o h3600.o \ + huw_webpanel.o irq.o sa1111.o sa1111-pcibuf.o \ + system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o # These aren't present yet, and prevents a plain -ac kernel building. # hwtimer.o @@ -29,22 +29,30 @@ # We link the CPU support next, so that RAM timings can be tuned. ifeq ($(CONFIG_CPU_FREQ),y) obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o +obj-$(CONFIG_SA1100_CEP) += cpu-sa1110.o +obj-$(CONFIG_SA1100_CONSUS) += cpu-sa1110.o obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o +obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o +obj-$(CONFIG_SA1100_SIMPUTER) += cpu-sa1110.o obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o endif # Next, the SA1111 stuff. obj-$(CONFIG_SA1111) += sa1111.o dma-sa1111.o -obj-$(CONFIG_USB_OHCI_SA1111) += sa1111-pcibuf.o pcipool.o +obj-$(CONFIG_USB_OHCI_SA1111) += sa1111-pcibuf.o # Specific board support +obj-$(CONFIG_SA1100_ADSAGC) += adsagc.o obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o +obj-$(CONFIG_SA1100_ADSBITSYPLUS) += adsbitsyplus.o obj-$(CONFIG_SA1100_ASSABET) += assabet.o obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o obj-$(CONFIG_SA1100_BADGE4) += badge4.o obj-$(CONFIG_SA1100_BRUTUS) += brutus.o +obj-$(CONFIG_SA1100_CEP) += cep.o obj-$(CONFIG_SA1100_CERF) += cerf.o +obj-$(CONFIG_SA1100_CONSUS) += consus.o obj-$(CONFIG_SA1100_EMPEG) += empeg.o obj-$(CONFIG_SA1100_FLEXANET) += flexanet.o obj-$(CONFIG_SA1100_FREEBIRD) += freebird.o @@ -52,6 +60,7 @@ obj-$(CONFIG_SA1100_GRAPHICSCLIENT) += graphicsclient.o obj-$(CONFIG_SA1100_GRAPHICSMASTER) += graphicsmaster.o obj-$(CONFIG_SA1100_H3600) += h3600.o +obj-$(CONFIG_SA1100_HACKKIT) += hackkit.o obj-$(CONFIG_SA1100_HUW_WEBPANEL) += huw_webpanel.o obj-$(CONFIG_SA1100_ITSY) += itsy.o obj-$(CONFIG_SA1100_JORNADA720) += jornada720.o @@ -65,20 +74,25 @@ obj-$(CONFIG_SA1100_SHANNON) += shannon.o obj-$(CONFIG_SA1100_SHERMAN) += sherman.o obj-$(CONFIG_SA1100_SIMPAD) += simpad.o +obj-$(CONFIG_SA1100_SIMPUTER) += simputer.o obj-$(CONFIG_SA1100_VICTOR) += victor.o obj-$(CONFIG_SA1100_XP860) += xp860.o obj-$(CONFIG_SA1100_YOPY) += yopy.o # LEDs support leds-y := leds.o +leds-$(CONFIG_SA1100_ADSAGC) += leds-adsagc.o leds-$(CONFIG_SA1100_ADSBITSY) += leds-adsbitsy.o +leds-$(CONFIG_SA1100_ADSBITSYPLUS) += leds-adsbitsyplus.o leds-$(CONFIG_SA1100_ASSABET) += leds-assabet.o leds-$(CONFIG_SA1100_BRUTUS) += leds-brutus.o leds-$(CONFIG_SA1100_CERF) += leds-cerf.o +leds-$(CONFIG_SA1100_CONSUS) += leds-consus.o leds-$(CONFIG_SA1100_FLEXANET) += leds-flexanet.o leds-$(CONFIG_SA1100_FRODO) += leds-frodo.o leds-$(CONFIG_SA1100_GRAPHICSCLIENT) += leds-graphicsclient.o leds-$(CONFIG_SA1100_GRAPHICSMASTER) += leds-graphicsmaster.o +leds-$(CONFIG_SA1100_HACKKIT) += leds-hackkit.o leds-$(CONFIG_SA1100_LART) += leds-lart.o leds-$(CONFIG_SA1100_PFS168) += leds-pfs168.o leds-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o @@ -95,6 +109,8 @@ # Miscelaneous functions obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_SA1100_SSP) += ssp.o + include $(TOPDIR)/Rules.make sa1100usb_core.o: $(sa1100usb_core-objs) diff -urN orig/arch/arm/mach-sa1100/adsagc.c linux/arch/arm/mach-sa1100/adsagc.c --- orig/arch/arm/mach-sa1100/adsagc.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/adsagc.c Fri Feb 21 15:17:34 2003 @@ -0,0 +1,360 @@ +/* + * linux/arch/arm/mach-sa1100/adsagc.c + * + * Pieces specific to the ADS Advanced Graphics Client board + * + * 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 "generic.h" +#include "sa1111.h" + +static int __init adsagc_init(void) +{ + int ret; + + if (!machine_is_adsagc()) + return -ENODEV; + + /* + * Ensure that the memory bus request/grant signals are setup, + * and the grant is held in its inactive state + */ + sa1110_mb_disable(); + + /* Adsagc uses GPIO pins for SPI interface to AVR + * AGC uses the standard pins instead. AGC also has controls + * SA1111 and Smartio reset with GPIO. + */ + + // Set RTS low during sleep + PGSR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19; + + // Reset SA1111 + GPDR |= GPIO_GPIO12; + GPCR = GPIO_GPIO12; + udelay(1000); + GPSR = GPIO_GPIO12; + + /* use the regular SSP pins */ + PPAR &= ~PPAR_SSPGPIO; + /* + * Probe for SA1111. + */ + ret = sa1111_probe(ADS_SA1111_BASE); + if (ret < 0) + return ret; + + /* + * We found it. Wake the chip up. + */ + sa1111_wake(); + + /* + * The SDRAM configuration of the SA1110 and the SA1111 must + * match. This is very important to ensure that SA1111 accesses + * don't corrupt the SDRAM. Note that this ungates the SA1111's + * MBGNT signal, so we must have called sa1110_mb_disable() + * beforehand. + */ + sa1111_configure_smc(1, + FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), + FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); + + /* + * Enable PWM control for LCD + */ + SKPCR |= SKPCR_PWMCLKEN; + SACR1 &= ~SACR1_L3EN; + ADS_CR3 |= ADS_CR3_BLON; // Enable the backlight + SKPWM1 = 0x7F; // Backlight PWM + SKPEN1 = 1; + SKPWM0 = 0x7F; // VEE + SKPEN0 = 1; + + /* + * We only need to turn on DCLK whenever we want to use the + * DMA. It can otherwise be held firmly in the off position. + */ + SKPCR |= SKPCR_DCLKEN; + + /* + * Enable the SA1110 memory bus request and grant signals. + */ + sa1110_mb_enable(); + + set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_RISING_EDGE); + sa1111_init_irq(IRQ_GPIO0); + + return 0; +} + +__initcall(adsagc_init); + +/* + * Handlers for Adsagc's external IRQ logic + */ + +#define ADSAGC_N_IRQ (IRQ_ADSAGC_END - IRQ_ADSAGC_START) + +static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs ) +{ + int i; + + while( (irq = ADS_INT_ST1 ) ){ + for( i = 0; i < ADSAGC_N_IRQ; i++ ) + if( irq & (1<mapbase == _Ser1UTCR0) { + Ser1SDCR0 |= SDCR0_UART; + } + else if (port->mapbase == _Ser2UTCR0) { + Ser2UTCR4 = Ser2HSCR0 = 0; + } + return ret; +} + +static u_int adsagc_get_mctrl(struct uart_port *port) +{ + u_int result = TIOCM_CD | TIOCM_DSR; + + if (port->mapbase == _Ser1UTCR0) { + if (!(GPLR & GPIO_GPIO14)) + result |= TIOCM_CTS; + } else if (port->mapbase == _Ser2UTCR0) { + if (!(GPLR & GPIO_GPIO16)) + result |= TIOCM_CTS; + } else if (port->mapbase == _Ser3UTCR0) { + if (!(GPLR & GPIO_GPIO18)) + result |= TIOCM_CTS; + } else { + result = TIOCM_CTS; + } + + return result; +} + +static void adsagc_set_mctrl(struct uart_port *port, u_int mctrl) +{ + if (port->mapbase == _Ser1UTCR0) { + if (mctrl & TIOCM_RTS) + GPCR = GPIO_GPIO15; + else + GPSR = GPIO_GPIO15; + } else if (port->mapbase == _Ser2UTCR0) { + if (mctrl & TIOCM_RTS) + GPCR = GPIO_GPIO17; + else + GPSR = GPIO_GPIO17; + } else if (port->mapbase == _Ser3UTCR0) { + if (mctrl & TIOCM_RTS) + GPCR = GPIO_GPIO19; + else + GPSR = GPIO_GPIO19; + } +} + +static void +adsagc_uart_pm(struct uart_port *port, u_int state, u_int oldstate) +{ + // state has ACPI D0-D3 + // ACPI D0 : resume from suspend + // ACPI D1-D3 : enter to a suspend state + if (port->mapbase == _Ser1UTCR0) { + if (state) { + // disable uart + Ser1UTCR3 = 0; + } + } + else if (port->mapbase == _Ser2UTCR0) { + if (state) { + // disable uart + Ser2UTCR3 = 0; + Ser2HSCR0 = 0; + } + } + else if (port->mapbase == _Ser3UTCR0) { + if (state) { + // disable uart + Ser3UTCR3 = 0; + } + } +} + +static struct sa1100_port_fns adsagc_port_fns __initdata = { + .open = adsagc_uart_open, + .get_mctrl = adsagc_get_mctrl, + .set_mctrl = adsagc_set_mctrl, + .pm = adsagc_uart_pm, +}; + +static void __init adsagc_map_io(void) +{ + sa1100_map_io(); + iotable_init(adsagc_io_desc); + + sa1100_register_uart_fns(&adsagc_port_fns); + sa1100_register_uart(0, 3); + sa1100_register_uart(1, 1); + // don't register if you want to use IRDA +#ifndef CONFIG_SA1100_FIR + sa1100_register_uart(2, 2); +#endif + + /* set GPDR now */ + GPDR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19; + GPDR &= ~(GPIO_GPIO14 | GPIO_GPIO16 | GPIO_GPIO18); +} + +MACHINE_START(ADSAGC, "ADS Advanced GraphicsClient") + BOOT_PARAMS(0xc000003c) + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + MAPIO(adsagc_map_io) + INITIRQ(adsagc_init_irq) +MACHINE_END diff -urN orig/arch/arm/mach-sa1100/adsbitsy.c linux/arch/arm/mach-sa1100/adsbitsy.c --- orig/arch/arm/mach-sa1100/adsbitsy.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-sa1100/adsbitsy.c Tue Jun 24 11:16:24 2003 @@ -14,9 +14,13 @@ #include #include #include +#include #include +#include +#include #include +#include #include #include @@ -30,6 +34,7 @@ #include "generic.h" #include "sa1111.h" + static int __init adsbitsy_init(void) { int ret; @@ -43,6 +48,13 @@ */ sa1110_mb_disable(); + /* Bitsy uses GPIO pins for SPI interface to AVR + * Bitsy Plus uses the standard pins instead. + * it also needs to reset the AVR when booting + */ + + PPAR |= PPAR_SSPGPIO; + /* * Reset SA1111 */ @@ -50,6 +62,19 @@ udelay(1000); GPSR |= GPIO_GPIO26; + +#ifndef CONFIG_LEDS_TIMER + // Set Serial port 1 RTS and DTR Low during sleep + PGSR |= GPIO_GPIO15 | GPIO_GPIO20; +#else + // only RTS (because DTR is also the LED + // which should be off during sleep); + PGSR |= GPIO_GPIO15; +#endif + + // Set Serial port 3RTS Low during sleep + PGSR |= GPIO_GPIO19; + /* * Probe for SA1111. */ @@ -74,15 +99,6 @@ FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); /* - * Enable PWM control for LCD - */ - SKPCR |= SKPCR_PWMCLKEN; - SKPWM0 = 0x7F; // VEE - SKPEN0 = 1; - SKPWM1 = 0x01; // Backlight - SKPEN1 = 1; - - /* * We only need to turn on DCLK whenever we want to use the * DMA. It can otherwise be held firmly in the off position. */ @@ -108,48 +124,135 @@ } -/* - * Initialization fixup - */ - -static void __init -fixup_adsbitsy(struct machine_desc *desc, struct param_struct *params, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -} - static struct map_desc adsbitsy_io_desc[] __initdata = { /* virtual physical length domain r w c b */ - { 0xe8000000, 0x08000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 1 */ + { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 1 */ + { 0xf0000000, 0x3C000000, 0x00004000, DOMAIN_IO, 0, 1, 0, 0 }, /* 91C1111 */ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */ LAST_DESC }; +/* Use this to see when all uarts are shutdown. Or all are closed. + * We can only turn off RS232 chip if either of these are true. + */ + +static int uart_wake_count[3] = {1, 1, 1}; + +enum {UART_SHUTDOWN, UART_WAKEUP}; + +static void update_uart_counts(int line, int state) +{ + switch (state) { + case UART_WAKEUP: + uart_wake_count[line]++; + break; + case UART_SHUTDOWN: + uart_wake_count[line]--; + break; + } +} + static int adsbitsy_uart_open(struct uart_port *port, struct uart_info *info) { if (port->mapbase == _Ser1UTCR0) { Ser1SDCR0 |= SDCR0_UART; -#error Fixme // Set RTS High (should be done in the set_mctrl fn) - GPCR = GPIO_GPIO15; } else if (port->mapbase == _Ser2UTCR0) { Ser2UTCR4 = Ser2HSCR0 = 0; -#error Fixme // Set RTS High (should be done in the set_mctrl fn) - GPCR = GPIO_GPIO17; - } else if (port->mapbase == _Ser2UTCR0) { -#error Fixme // Set RTS High (should be done in the set_mctrl fn) - GPCR = GPIO_GPIO19; } return 0; } +void adsbitsy_uart_pm(struct uart_port *port, u_int state, u_int oldstate) +{ + // state has ACPI D0-D3 + // ACPI D0 : resume from suspend + // ACPI D1-D3 : enter to a suspend state + if (port->mapbase == _Ser1UTCR0) { + if (state) { + update_uart_counts(1, UART_SHUTDOWN); + // disable uart + Ser1UTCR3 = 0; + } + else { + update_uart_counts(1, UART_WAKEUP); + } + } + else if (port->mapbase == _Ser2UTCR0) { + if (state) { + update_uart_counts(2, UART_SHUTDOWN); + // disable uart + Ser2UTCR3 = 0; + Ser2HSCR0 = 0; + } + else { + update_uart_counts(2, UART_WAKEUP); + } + } + else if (port->mapbase == _Ser3UTCR0) { + if (state) { + update_uart_counts(0, UART_SHUTDOWN); + // disable uart + Ser3UTCR3 = 0; + } + else { + update_uart_counts(0, UART_WAKEUP); + } + } +} + +static void adsbitsy_set_mctrl(struct uart_port *port, u_int mctrl) +{ + // note: only ports 1 and 3 have modem control + if (port->mapbase == _Ser1UTCR0) { + if (mctrl & TIOCM_RTS) + // Set RTS High + GPCR = GPIO_GPIO15; + else + // Set RTS LOW + GPSR = GPIO_GPIO15; + if (mctrl & TIOCM_DTR) + // Set DTR High + GPCR = GPIO_GPIO20; + else + // Set DTR Low + GPSR = GPIO_GPIO20; + } else if (port->mapbase == _Ser3UTCR0) { + if (mctrl & TIOCM_RTS) + // Set RTS High + GPCR = GPIO_GPIO19; + else + // Set RTS LOW + GPSR = GPIO_GPIO19; + } +} + +static u_int adsbitsy_get_mctrl(struct uart_port *port) +{ + u_int ret = 0; + + // note: only ports 1 and 3 have modem control + if (port->mapbase == _Ser1UTCR0) { + if (!(GPLR & GPIO_GPIO14)) + ret |= TIOCM_CTS; + if (!(GPLR & GPIO_GPIO24)) + ret |= TIOCM_DSR; + if (!(GPLR & GPIO_GPIO16)) + ret |= TIOCM_RI; + if (!(GPLR & GPIO_GPIO17)) + ret |= TIOCM_CD; + } else if (port->mapbase == _Ser3UTCR0) { + if (!(GPLR & GPIO_GPIO18)) + ret |= TIOCM_CTS; + } + + return ret; +} + static struct sa1100_port_fns adsbitsy_port_fns __initdata = { - .open = adsbitsy_uart_open, + .set_mctrl = adsbitsy_set_mctrl, + .get_mctrl = adsbitsy_get_mctrl, + .open = adsbitsy_uart_open, + .pm = adsbitsy_uart_pm, }; static void __init adsbitsy_map_io(void) @@ -160,14 +263,27 @@ sa1100_register_uart_fns(&adsbitsy_port_fns); sa1100_register_uart(0, 3); sa1100_register_uart(1, 1); + + // don't register if you want to use IRDA +#ifndef CONFIG_SA1100_FIR sa1100_register_uart(2, 2); - GPDR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19; - GPDR &= ~(GPIO_GPIO14 | GPIO_GPIO16 | GPIO_GPIO18); +#endif + + // COM1 Set RTS and DTR Output + GPDR |= GPIO_GPIO15 | GPIO_GPIO20; + // Set CTS, DSR, RI and CD Input + GPDR &= ~(GPIO_GPIO14 | GPIO_GPIO24 | GPIO_GPIO16 | GPIO_GPIO17); + + // COM3 Set RTS Output + GPDR |= GPIO_GPIO19; + // Set CTS Input + GPDR &= ~GPIO_GPIO18; } + MACHINE_START(ADSBITSY, "ADS Bitsy") + BOOT_PARAMS(0xc000003c) BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_adsbitsy) MAPIO(adsbitsy_map_io) INITIRQ(adsbitsy_init_irq) MACHINE_END diff -urN orig/arch/arm/mach-sa1100/adsbitsyplus.c linux/arch/arm/mach-sa1100/adsbitsyplus.c --- orig/arch/arm/mach-sa1100/adsbitsyplus.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/adsbitsyplus.c Fri Feb 21 15:17:33 2003 @@ -0,0 +1,395 @@ +/* + * linux/arch/arm/mach-sa1100/adsbitsyplus.c + * + * Author: Robert Whaley + * + * This file comes from adsbitsy.c of Woojung Huh + * + * Pieces specific to the ADS Bitsy Plus + * + * 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 "generic.h" +#include "sa1111.h" + +/* unfortunately, we can't detect the difference between REV 2 and REV A + connector boards. So by convention, the registers.txt file is used + to set a byte to either 0x02 or 0x0a to make this distinction. The + bootloader must detect this by default we assume rev A since most boards + will be rev A */ + +static int adsbitsyplus_connector_board_rev_number = 0xA; + +static int __init adsbitsyplus_connector_board_rev_setup(char *str) +{ + adsbitsyplus_connector_board_rev_number = simple_strtol(str,NULL,0); + return 1; +} + +int adsbitsyplus_connector_board_rev(void) +{ + static int only_once = 1; + if (only_once) { + printk(KERN_INFO "Bitsy Connector Board REV: %#x\n", adsbitsyplus_connector_board_rev_number); + only_once = 0; + } + return adsbitsyplus_connector_board_rev_number; +} + +static int __init adsbitsyplus_init(void) +{ + int ret; + + if (!machine_is_adsbitsyplus()) + return -ENODEV; + + /* + * Ensure that the memory bus request/grant signals are setup, + * and the grant is held in its inactive state + */ + sa1110_mb_disable(); + + /* Bitsy uses GPIO pins for SPI interface to AVR + * Bitsy Plus uses the standard pins instead. + * it also needs to reset the AVR when booting + */ + + PPAR &= ~PPAR_SSPGPIO; + ADS_CPLD_SUPPC |= ADS_SUPPC_AVR_WKP; + mdelay(100); + ADS_CPLD_SUPPC &= ~ADS_SUPPC_AVR_WKP; + + /* + * Reset SA1111 + */ + GPCR |= GPIO_GPIO26; + udelay(1000); + GPSR |= GPIO_GPIO26; + +#ifndef CONFIG_LEDS_TIMER + // Set Serial port 1 RTS and DTR Low during sleep + PGSR |= GPIO_GPIO15 | GPIO_GPIO20; +#else + // only RTS (because DTR is also the LED + // which should be off during sleep); + PGSR |= GPIO_GPIO15; +#endif + + // Set Serial port 3RTS Low during sleep + PGSR |= GPIO_GPIO19; + + /* + * Probe for SA1111. + */ + ret = sa1111_probe(ADSBITSYPLUS_SA1111_BASE); + if (ret < 0) + return ret; + + /* + * We found it. Wake the chip up. + */ + sa1111_wake(); + + /* + * The SDRAM configuration of the SA1110 and the SA1111 must + * match. This is very important to ensure that SA1111 accesses + * don't corrupt the SDRAM. Note that this ungates the SA1111's + * MBGNT signal, so we must have called sa1110_mb_disable() + * beforehand. + */ + sa1111_configure_smc(1, + FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), + FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); + + /* + * We only need to turn on DCLK whenever we want to use the + * DMA. It can otherwise be held firmly in the off position. + */ + SKPCR |= SKPCR_DCLKEN; + + /* + * Enable the SA1110 memory bus request and grant signals. + */ + sa1110_mb_enable(); + + set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_RISING_EDGE); + sa1111_init_irq(IRQ_GPIO0); + + return 0; +} + +__initcall(adsbitsyplus_init); + +static void __init adsbitsyplus_init_irq(void) +{ + /* First the standard SA1100 IRQs */ + sa1100_init_irq(); +} + +/* + * Resume SA1111 when system wakes up + */ +void adsbitsyplus_sa1111_wake(unsigned long pa_dwr) +{ + // Turn ON SA1111 + GPCR |= GPIO_GPIO26; + mdelay(1); + GPSR |= GPIO_GPIO26; + + GAFR |= GPIO_32_768kHz; + GPDR |= GPIO_32_768kHz; + TUCR = TUCR_3_6864MHz; + + SBI_SKCR = SKCR_PLL_BYPASS | SKCR_RDYEN | SKCR_OE_EN; + udelay(100); + SBI_SKCR = SKCR_PLL_BYPASS | SKCR_RCLKEN | SKCR_RDYEN | SKCR_OE_EN; + + GAFR |= (GPIO_MBGNT | GPIO_MBREQ); + GPDR |= GPIO_MBGNT; + GPDR &= ~GPIO_MBREQ; + TUCR |= TUCR_MR; + + sa1111_configure_smc(1, + FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), + FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); + SKPCR |= SKPCR_DCLKEN; + + // Reset PCMCIA + PCCR = 0xFF; + mdelay(100); + PA_DDR = 0x00; + // PA_DWR = GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3; + // PA_DWR = GPIO_GPIO0 | GPIO_GPIO2 | GPIO_GPIO3; + PA_DWR = pa_dwr; + PCCR = ~(PCCR_S0_RST | PCCR_S1_RST); + +#ifdef CONFIG_USB_OHCI_SA1111 + // Turn ON clock + SKPCR |= SKPCR_UCLKEN; + udelay(100); + + // force a RESET + USB_RESET = 0x01; + USB_RESET |= 0x02; + udelay(100); + + // Set Power Sense and Control Line + USB_RESET = 0; + USB_RESET = USB_RESET_PWRSENSELOW; + USB_STATUS = 0; + udelay(10); +#endif +} + + +static struct map_desc adsbitsyplus_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 1 */ + { 0xf0000000, 0x3C000000, 0x00004000, DOMAIN_IO, 0, 1, 0, 0 }, /* 91C1111 */ + { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */ + { 0xf1000000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD Controller */ + LAST_DESC +}; + +/* Use this to see when all uarts are shutdown. Or all are closed. + * We can only turn off RS232 chip if either of these are true. + */ + +static int uart_wake_count[3] = {1, 1, 1}; + +enum {UART_SHUTDOWN, UART_WAKEUP}; + +static void update_uart_counts(int line, int state) +{ + switch (state) { + case UART_WAKEUP: + uart_wake_count[line]++; + break; + case UART_SHUTDOWN: + uart_wake_count[line]--; + break; + } +} + +static int adsbitsyplus_uart_open(struct uart_port *port, struct uart_info *info) +{ + if (port->mapbase == _Ser1UTCR0) { + Ser1SDCR0 |= SDCR0_UART; + } else if (port->mapbase == _Ser2UTCR0) { + Ser2UTCR4 = Ser2HSCR0 = 0; + } + return 0; +} + +void adsbitsyplus_uart_pm(struct uart_port *port, u_int state, u_int oldstate) +{ + // state has ACPI D0-D3 + // ACPI D0 : resume from suspend + // ACPI D1-D3 : enter to a suspend state + if (port->mapbase == _Ser1UTCR0) { + if (state) { + update_uart_counts(1, UART_SHUTDOWN); + // disable uart + Ser1UTCR3 = 0; + } + else { + update_uart_counts(1, UART_WAKEUP); + } + } + else if (port->mapbase == _Ser2UTCR0) { + if (state) { + update_uart_counts(2, UART_SHUTDOWN); + // disable uart + Ser2UTCR3 = 0; + Ser2HSCR0 = 0; + } + else { + update_uart_counts(2, UART_WAKEUP); + } + } + else if (port->mapbase == _Ser3UTCR0) { + if (state) { + update_uart_counts(0, UART_SHUTDOWN); + // disable uart + Ser3UTCR3 = 0; + } + else { + update_uart_counts(0, UART_WAKEUP); + } + } + if (state == 0) { + // Turn power on if uarts are awake + if (uart_wake_count[0] + uart_wake_count[1] != 0) { + // make sure RS-232 is turned on if 1 or 3 are open + ADS_CPLD_PCON |= ADS_PCON_COM1_3_ON; + } + if (uart_wake_count[2] != 0) { + if (adsbitsyplus_connector_board_rev() >= 0x0a) + ADS_CPLD_PCON |= ADS_PCON_CONN_B_PE2; + } + } + else { + // Turn power off if uarts are asleep + if (uart_wake_count[0] + uart_wake_count[1] == 0) { + // save power if we are sleeping + ADS_CPLD_PCON &= ~ADS_PCON_COM1_3_ON; + GAFR &= ~(GPIO_GPIO15 | GPIO_GPIO19 | GPIO_GPIO20); + GPDR |= GPIO_GPIO15 | GPIO_GPIO19 | GPIO_GPIO20; + } + if (uart_wake_count[2] == 0) { + if (adsbitsyplus_connector_board_rev() >= 0x0a) + ADS_CPLD_PCON &= ~ADS_PCON_CONN_B_PE2; + } + } +} + +static void adsbitsyplus_set_mctrl(struct uart_port *port, u_int mctrl) +{ + // note: only ports 1 and 3 have modem control + if (port->mapbase == _Ser1UTCR0) { + if (mctrl & TIOCM_RTS) + // Set RTS High + GPCR = GPIO_GPIO15; + else + // Set RTS LOW + GPSR = GPIO_GPIO15; + if (mctrl & TIOCM_DTR) + // Set DTR High + GPCR = GPIO_GPIO20; + else + // Set DTR Low + GPSR = GPIO_GPIO20; + } else if (port->mapbase == _Ser3UTCR0) { + if (mctrl & TIOCM_RTS) + // Set RTS High + GPCR = GPIO_GPIO19; + else + // Set RTS LOW + GPSR = GPIO_GPIO19; + } +} + +static u_int adsbitsyplus_get_mctrl(struct uart_port *port) +{ + u_int ret = 0; + + // note: only ports 1 and 3 have modem control + if (port->mapbase == _Ser1UTCR0) { + if (!(GPLR & GPIO_GPIO14)) + ret |= TIOCM_CTS; + if (!(GPLR & GPIO_GPIO24)) + ret |= TIOCM_DSR; + if (!(GPLR & GPIO_GPIO16)) + ret |= TIOCM_RI; + if (!(GPLR & GPIO_GPIO17)) + ret |= TIOCM_CD; + } else if (port->mapbase == _Ser3UTCR0) { + if (!(GPLR & GPIO_GPIO18)) + ret |= TIOCM_CTS; + } + + return ret; +} + +static struct sa1100_port_fns adsbitsyplus_port_fns __initdata = { + .set_mctrl = adsbitsyplus_set_mctrl, + .get_mctrl = adsbitsyplus_get_mctrl, + .open = adsbitsyplus_uart_open, + .pm = adsbitsyplus_uart_pm, +}; + +static void __init adsbitsyplus_map_io(void) +{ + sa1100_map_io(); + iotable_init(adsbitsyplus_io_desc); + + sa1100_register_uart_fns(&adsbitsyplus_port_fns); + sa1100_register_uart(0, 3); + sa1100_register_uart(1, 1); + + // don't register if you want to use IRDA +#ifndef CONFIG_SA1100_FIR + sa1100_register_uart(2, 2); +#endif + + // COM1 Set RTS and DTR Output + GPDR |= GPIO_GPIO15 | GPIO_GPIO20; + // Set CTS, DSR, RI and CD Input + GPDR &= ~(GPIO_GPIO14 | GPIO_GPIO24 | GPIO_GPIO16 | GPIO_GPIO17); + + // COM3 Set RTS Output + GPDR |= GPIO_GPIO19; + // Set CTS Input + GPDR &= ~GPIO_GPIO18; +} + +__setup("adsbitsyplus_conn_board_rev=", adsbitsyplus_connector_board_rev_setup); + +MACHINE_START(ADSBITSYPLUS, "ADS Bitsy Plus") + BOOT_PARAMS(0xc000003c) + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + MAPIO(adsbitsyplus_map_io) + INITIRQ(adsbitsyplus_init_irq) +MACHINE_END diff -urN orig/arch/arm/mach-sa1100/assabet.c linux/arch/arm/mach-sa1100/assabet.c --- orig/arch/arm/mach-sa1100/assabet.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-sa1100/assabet.c Sun Sep 15 13:00:50 2002 @@ -42,7 +42,8 @@ ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \ ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \ ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \ - ASSABET_BCR_IRDA_MD0 | ASSABET_BCR_CF_RST) + ASSABET_BCR_IRDA_MD0 | ASSABET_BCR_CF_RST | \ + ASSABET_BCR_CODEC_RST ) unsigned long SCR_value = ASSABET_SCR_INIT; EXPORT_SYMBOL(SCR_value); diff -urN orig/arch/arm/mach-sa1100/cep.c linux/arch/arm/mach-sa1100/cep.c --- orig/arch/arm/mach-sa1100/cep.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/cep.c Sun Jun 16 12:54:24 2002 @@ -0,0 +1,123 @@ +/* + * linux/arch/arm/mach-sa1100/cep.c + * + * Author: Matthias Gorjup + * + * This file contains all Cep - specific tweaks. + * + * 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 "generic.h" + + +extern void convert_to_tag_list(struct param_struct *params, int mem_init); + +static void __init +fixup_cep(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + struct tag *t = (struct tag *)params; + + + /* + * Apparantly bootldr uses a param_struct. Groan. + */ + if (t->hdr.tag != ATAG_CORE) + convert_to_tag_list(params, 1); + + if (t->hdr.tag != ATAG_CORE) { + t->hdr.tag = ATAG_CORE; + t->hdr.size = tag_size(tag_core); + t->u.core.flags = 0; + t->u.core.pagesize = PAGE_SIZE; + t->u.core.rootdev = RAMDISK_MAJOR << 8 | 0; + t = tag_next(t); + + t->hdr.tag = ATAG_MEM; + t->hdr.size = tag_size(tag_mem32); + t->u.mem.start = 0xc0000000; + t->u.mem.size = 32 * 1024 * 1024; + t = tag_next(t); + + + t->hdr.tag = ATAG_RAMDISK; + t->hdr.size = tag_size(tag_ramdisk); + t->u.ramdisk.flags = 1; + t->u.ramdisk.size = 8192; + t->u.ramdisk.start = 0; + t = tag_next(t); + + t->hdr.tag = ATAG_INITRD; + t->hdr.size = tag_size(tag_initrd); + t->u.initrd.start = 0xc0800000; + t->u.initrd.size = 3 * 1024 * 1024; + t = tag_next(t); + + t->hdr.tag = ATAG_NONE; + t->hdr.size = 0; + } +} + + +static struct map_desc cep_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */ + LAST_DESC +}; + +static void __init cep_map_io(void) +{ + + sa1100_map_io(); + iotable_init(cep_io_desc); + + sa1100_register_uart(0, 1); /* com port */ + sa1100_register_uart(2, 3); /* radio module */ + + /* + * Ensure that these pins are set as outputs and are driving + * logic 0. This ensures that we won't inadvertently toggle + * the WS latch in the CPLD, and we don't float causing + * excessive power drain. --rmk + */ + GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; + GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; + + /* + * Set up registers for sleep mode. + */ + PWER = PWER_GPIO0; + PGSR = 0; + PCFR = 0; + PSDR = 0; +} + + +MACHINE_START(CEP, "Iskratel Cep") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) + FIXUP(fixup_cep) + MAPIO(cep_map_io) + INITIRQ(sa1100_init_irq) +MACHINE_END diff -urN orig/arch/arm/mach-sa1100/cpu-sa1110.c linux/arch/arm/mach-sa1100/cpu-sa1110.c --- orig/arch/arm/mach-sa1100/cpu-sa1110.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/cpu-sa1110.c Sun Sep 15 23:42:59 2002 @@ -49,33 +49,33 @@ }; static struct sdram_params tc59sm716_cl2_params __initdata = { - rows: 12, - tck: 10, - trcd: 20, - trp: 20, - twr: 10, - refresh: 64000, - cas_latency: 2, + .rows = 12, + .tck = 10, + .trcd = 20, + .trp = 20, + .twr = 10, + .refresh = 64000, + .cas_latency = 2, }; static struct sdram_params tc59sm716_cl3_params __initdata = { - rows: 12, - tck: 8, - trcd: 20, - trp: 20, - twr: 8, - refresh: 64000, - cas_latency: 3, + .rows = 12, + .tck = 8, + .trcd = 20, + .trp = 20, + .twr = 8, + .refresh = 64000, + .cas_latency = 3, }; static struct sdram_params samsung_k4s641632d_tc75 __initdata = { - rows: 14, - tck: 9, - trcd: 27, - trp: 20, - twr: 9, - refresh: 64000, - cas_latency: 3, + .rows = 14, + .tck = 9, + .trcd = 27, + .trp = 20, + .twr = 9, + .refresh = 64000, + .cas_latency = 3, }; static struct sdram_params sdram_params; @@ -235,21 +235,21 @@ * the programming. */ local_irq_save(flags); - asm("mcr p15, 0, %0, c10, c4" : : "r" (0)); + asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); udelay(10); - __asm__ __volatile__(" - b 2f - .align 5 -1: str %3, [%1, #0] @ MDCNFG - str %4, [%1, #28] @ MDREFR - str %5, [%1, #4] @ MDCAS0 - str %6, [%1, #8] @ MDCAS1 - str %7, [%1, #12] @ MDCAS2 - str %8, [%2, #0] @ PPCR - ldr %0, [%1, #0] - b 3f -2: b 1b -3: nop + __asm__ __volatile__(" \n\ + b 2f \n\ + .align 5 \n\ +1: str %3, [%1, #0] @ MDCNFG \n\ + str %4, [%1, #28] @ MDREFR \n\ + str %5, [%1, #4] @ MDCAS0 \n\ + str %6, [%1, #8] @ MDCAS1 \n\ + str %7, [%1, #12] @ MDCAS2 \n\ + str %8, [%2, #0] @ PPCR \n\ + ldr %0, [%1, #0] \n\ + b 3f \n\ +2: b 1b \n\ +3: nop \n\ nop" : "=&r" (unused) : "r" (&MDCNFG), "r" (&PPCR), "0" (sd.mdcnfg), diff -urN orig/arch/arm/mach-sa1100/dma-sa1100.c linux/arch/arm/mach-sa1100/dma-sa1100.c --- orig/arch/arm/mach-sa1100/dma-sa1100.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/dma-sa1100.c Fri Sep 6 10:52:52 2002 @@ -477,11 +477,11 @@ return sa1111_dma_resume(channel); if (dma->stopped) { - int flags; - save_flags_cli(flags); + unsigned long flags; + local_irq_save(flags); dma->stopped = 0; process_dma(dma); - restore_flags(flags); + local_irq_restore(flags); } return 0; } diff -urN orig/arch/arm/mach-sa1100/dma-sa1111.c linux/arch/arm/mach-sa1100/dma-sa1111.c --- orig/arch/arm/mach-sa1100/dma-sa1111.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/dma-sa1111.c Fri Feb 21 15:17:34 2003 @@ -305,7 +305,8 @@ * SDRAM bank 1 on Neponset). The default configuration selects * Assabet, so any address in bank 1 is necessarily invalid. */ - if((machine_is_assabet() || machine_is_pfs168()) && addr >= 0xc8000000) + if((machine_is_assabet() || machine_is_pfs168() || + machine_is_graphicsmaster() || machine_is_adsagc()) && addr >= 0xc8000000) return -1; /* The bug only applies to buffers located more than one megabyte diff -urN orig/arch/arm/mach-sa1100/flexanet.c linux/arch/arm/mach-sa1100/flexanet.c --- orig/arch/arm/mach-sa1100/flexanet.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/flexanet.c Mon Aug 5 13:41:22 2002 @@ -26,6 +26,7 @@ #include #include #include +#include #include "generic.h" @@ -145,6 +146,11 @@ static int __init flexanet_init(void) { + /* Set IRQ edges */ + set_GPIO_IRQ_edge(GPIO_GUI_IRQ, GPIO_RISING_EDGE); + + /* deassert the GUI reset */ + FLEXANET_BCR_set(FHH_BCR_GUI_NRST); return 0; } @@ -155,10 +161,6 @@ fixup_flexanet(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { - int status; - unsigned long now; - - /* fixed RAM size, by now (64MB) */ SET_BANK( 0, 0xc0000000, 64*1024*1024 ); mi->nr_banks = 1; @@ -175,7 +177,7 @@ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */ { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */ { 0xf1000000, 0x18000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Ethernet controller */ - { 0xD0000000, 0x40000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Instrument boards */ + { 0xD0000000, 0x40000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Instrument boards */ { 0xD8000000, 0x48000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* External peripherals */ LAST_DESC }; @@ -198,13 +200,6 @@ */ PCFR = PCFR_OPDE | PCFR_FP | PCFR_FS; - /* deassert the GUI reset */ - FLEXANET_BCR_set(FHH_BCR_GUI_NRST); - - /* - * Set IRQ edges - */ - set_GPIO_IRQ_edge(GPIO_GUI_IRQ, GPIO_RISING_EDGE); } diff -urN orig/arch/arm/mach-sa1100/frodo.c linux/arch/arm/mach-sa1100/frodo.c --- orig/arch/arm/mach-sa1100/frodo.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/frodo.c Thu Oct 24 13:01:38 2002 @@ -12,15 +12,22 @@ * * History: * + * 2002/05/27 Setup GPIOs for all the onboard peripherals so + * that we don't have to do it in each driver + * * 2002/01/31 Initial version */ #include #include +#include #include +#include -#include #include +#include +#include +#include #include #include @@ -28,30 +35,108 @@ #include "generic.h" -static struct map_desc frodo_io_desc[] __initdata = -{ - /* virtual physical length domain r w c b */ - { 0xe8000000, 0x00000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* flash memory */ - { 0xf0000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* 16-bit on-board devices (including CPLDs) */ - { 0xf1000000, 0x18000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* 32-bit daughter card */ - LAST_DESC +static struct map_desc frodo_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xe8000000, 0x00000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* flash memory */ + { 0xf0000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* 16-bit on-board devices (including CPLDs) */ + { 0xf1000000, 0x18000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* 32-bit daughter card */ + LAST_DESC }; +static spinlock_t frodo_cpld_lock = SPIN_LOCK_UNLOCKED; +static volatile u16 *frodo_cpld_memory = (u16 *) 0xf0000000; + static void __init frodo_map_io (void) { - sa1100_map_io (); - iotable_init (frodo_io_desc); + sa1100_map_io (); + iotable_init (frodo_io_desc); + + sa1100_register_uart (0,2); /* UART2 (serial console) */ + sa1100_register_uart (1,1); /* UART1 (big kahuna flow control serial port) */ + + /* + * Set SUS bit in SDCR0 so serial port 1 acts as a UART. + * See Intel SA-1110 Developers Manual Section 11.9.2.1 (GPCLK/UART Select) + */ + Ser1SDCR0 |= SDCR0_SUS; +} + +static int __init frodo_init_irq(void) +{ + int i,gpio[] = { + FRODO_IDE_GPIO, + FRODO_ETH_GPIO, + FRODO_USB_DC_GPIO, + FRODO_USB_HC_GPIO, + FRODO_RTC_GPIO, + FRODO_UART1_GPIO, + FRODO_UART2_GPIO, + FRODO_PCMCIA_STATUS_GPIO, + FRODO_PCMCIA_RDYBSY_GPIO + }; + + for (i = 0; i < sizeof (gpio) / sizeof (gpio[0]); i++) + set_GPIO_IRQ_edge (gpio[i],GPIO_RISING_EDGE); + + return (0); +} + +__initcall(frodo_init_irq); +#if 0 +static int __init frodo_init_cpld(void) +{ + if ((frodo_cpld_memory = ioremap (FRODO_CPLD_BASE,FRODO_CPLD_LENGTH)) == NULL) + panic ("Couldn't map CPLD memory to a virtual address. We're screwed!\n"); + + return (0); +} + +__initcall(frodo_init_cpld); +#endif +u16 frodo_cpld_read (u32 reg) +{ + unsigned long flags; + u16 value; + + spin_lock_irqsave (&frodo_cpld_lock,flags); + value = frodo_cpld_memory[reg / 2]; + spin_unlock_irqrestore (&frodo_cpld_lock,flags); + + return (value); +} + +void frodo_cpld_write (u32 reg,u16 value) +{ + unsigned long flags; - sa1100_register_uart (0,2); /* UART2 (serial console) */ - sa1100_register_uart (1,1); /* UART1 (big kahuna flow control serial port) */ + spin_lock_irqsave (&frodo_cpld_lock,flags); + frodo_cpld_memory[reg / 2] = value; + spin_unlock_irqrestore (&frodo_cpld_lock,flags); +} + +void frodo_cpld_set (u32 reg,u16 mask) +{ + unsigned long flags; + + spin_lock_irqsave (&frodo_cpld_lock,flags); + frodo_cpld_memory[reg / 2] |= mask; + spin_unlock_irqrestore (&frodo_cpld_lock,flags); +} + +void frodo_cpld_clear (u32 reg,u16 mask) +{ + unsigned long flags; - /* - * Set SUS bit in SDCR0 so serial port 1 acts as a UART. - * See Intel SA-1110 Developers Manual Section 11.9.2.1 (GPCLK/UART Select) - */ - Ser1SDCR0 |= SDCR0_SUS; + spin_lock_irqsave (&frodo_cpld_lock,flags); + frodo_cpld_memory[reg / 2] &= ~mask; + spin_unlock_irqrestore (&frodo_cpld_lock,flags); } +EXPORT_SYMBOL (frodo_cpld_read); +EXPORT_SYMBOL (frodo_cpld_write); +EXPORT_SYMBOL (frodo_cpld_set); +EXPORT_SYMBOL (frodo_cpld_clear); + MACHINE_START (FRODO,"2d3D, Inc. SA-1110 Development Board") BOOT_MEM (0xc0000000,0x80000000,0xf8000000) BOOT_PARAMS (0xc0000100) diff -urN orig/arch/arm/mach-sa1100/generic.c linux/arch/arm/mach-sa1100/generic.c --- orig/arch/arm/mach-sa1100/generic.c Wed Jun 18 13:01:05 2003 +++ linux/arch/arm/mach-sa1100/generic.c Wed Jun 18 09:56:19 2003 @@ -86,7 +86,7 @@ static int __init sa11x0_init_clock(void) { - cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100, 0, 0); + cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100, 59000, 287000); return 0; } diff -urN orig/arch/arm/mach-sa1100/graphicsclient.c linux/arch/arm/mach-sa1100/graphicsclient.c --- orig/arch/arm/mach-sa1100/graphicsclient.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/graphicsclient.c Fri Feb 21 15:17:35 2003 @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -34,55 +36,58 @@ * Handlers for GraphicsClient's external IRQ logic */ +#define GRAPHICSCLIENT_N_IRQ (IRQ_GRAPHICSCLIENT_END - IRQ_GRAPHICSCLIENT_START) +#define GRAPHICSCLIENT_FIRST_IRQ (IRQ_GRAPHICSCLIENT_CAN - IRQ_GRAPHICSCLIENT_START) + static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs ) { int i; while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){ - for( i = 0; i < 16; i++ ) + for( i = GRAPHICSCLIENT_FIRST_IRQ; i < GRAPHICSCLIENT_N_IRQ; i++ ) if( irq & (1<nr_banks = 2; - - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -} - static struct map_desc graphicsclient_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 1 */ @@ -143,120 +133,31 @@ LAST_DESC }; -static struct gc_uart_ctrl_data_t gc_uart_ctrl_data[] = { - { GPIO_GC_UART0_CTS, 0, NULL,NULL }, - { GPIO_GC_UART1_CTS, 0, NULL,NULL }, - { GPIO_GC_UART2_CTS, 0, NULL,NULL } -}; - -static void -graphicsclient_cts_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct gc_uart_ctrl_data_t * uart_data = (struct gc_uart_ctrl_data_t *)dev_id; - int cts = !(GPLR & uart_data->cts_gpio); - - /* NOTE: I supose that we will no get any interrupt - if the GPIO is not changed, so maybe - the cts_prev_state can be removed ... */ - if (cts != uart_data->cts_prev_state) { - uart_data->cts_prev_state = cts; - - uart_handle_cts_change(uart_data->info, cts); - } -} - -static int -graphicsclient_register_cts_intr(int gpio, int irq, - struct gc_uart_ctrl_data_t *uart_data) -{ - int ret = 0; - - set_GPIO_IRQ_edge(gpio, GPIO_BOTH_EDGES); - - ret = request_irq(irq, graphicsclient_cts_intr, - 0, "GC RS232 CTS", uart_data); - if (ret) { - printk(KERN_ERR "uart_open: failed to register CTS irq (%d)\n", - ret); - free_irq(irq, uart_data); - } - - return ret; -} - -static int -graphicsclient_uart_open(struct uart_port *port, struct uart_info *info) +static int graphicsclient_uart_open(struct uart_port *port, struct uart_info *info) { - int ret = 0; + int ret = 0; if (port->mapbase == _Ser1UTCR0) { Ser1SDCR0 |= SDCR0_UART; - /* Set RTS Output */ - GPSR = GPIO_GC_UART0_RTS; - - gc_uart_ctrl_data[0].cts_prev_state = 0; - gc_uart_ctrl_data[0].info = info; - gc_uart_ctrl_data[0].port = port; - - /* register uart0 CTS irq */ - ret = graphicsclient_register_cts_intr(GPIO_GC_UART0_CTS, - IRQ_GC_UART0_CTS, - &gc_uart_ctrl_data[0]); - } else if (port->mapbase == _Ser2UTCR0) { + } + else if (port->mapbase == _Ser2UTCR0) { Ser2UTCR4 = Ser2HSCR0 = 0; - /* Set RTS Output */ - GPSR = GPIO_GC_UART1_RTS; - - gc_uart_ctrl_data[1].cts_prev_state = 0; - gc_uart_ctrl_data[1].info = info; - gc_uart_ctrl_data[1].port = port; - - /* register uart1 CTS irq */ - ret = graphicsclient_register_cts_intr(GPIO_GC_UART1_CTS, - IRQ_GC_UART1_CTS, - &gc_uart_ctrl_data[1]); - } else if (port->mapbase == _Ser3UTCR0) { - /* Set RTS Output */ - GPSR = GPIO_GC_UART2_RTS; - - gc_uart_ctrl_data[2].cts_prev_state = 0; - gc_uart_ctrl_data[2].info = info; - gc_uart_ctrl_data[2].port = port; - - /* register uart2 CTS irq */ - ret = graphicsclient_register_cts_intr(GPIO_GC_UART2_CTS, - IRQ_GC_UART2_CTS, - &gc_uart_ctrl_data[2]); } return ret; } -static int -graphicsclient_uart_close(struct uart_port *port, struct uart_info *info) -{ - if (port->mapbase == _Ser1UTCR0) { - free_irq(IRQ_GC_UART0_CTS, &gc_uart_ctrl_data[0]); - } else if (port->mapbase == _Ser2UTCR0) { - free_irq(IRQ_GC_UART1_CTS, &gc_uart_ctrl_data[1]); - } else if (port->mapbase == _Ser3UTCR0) { - free_irq(IRQ_GC_UART2_CTS, &gc_uart_ctrl_data[2]); - } - - return 0; -} - static u_int graphicsclient_get_mctrl(struct uart_port *port) { u_int result = TIOCM_CD | TIOCM_DSR; if (port->mapbase == _Ser1UTCR0) { - if (!(GPLR & GPIO_GC_UART0_CTS)) + if (!(GPLR & GPIO_GPIO14)) result |= TIOCM_CTS; } else if (port->mapbase == _Ser2UTCR0) { - if (!(GPLR & GPIO_GC_UART1_CTS)) + if (!(GPLR & GPIO_GPIO16)) result |= TIOCM_CTS; } else if (port->mapbase == _Ser3UTCR0) { - if (!(GPLR & GPIO_GC_UART2_CTS)) + if (!(GPLR & GPIO_GPIO18)) result |= TIOCM_CTS; } else { result = TIOCM_CTS; @@ -269,39 +170,54 @@ { if (port->mapbase == _Ser1UTCR0) { if (mctrl & TIOCM_RTS) - GPCR = GPIO_GC_UART0_RTS; + GPCR = GPIO_GPIO15; else - GPSR = GPIO_GC_UART0_RTS; + GPSR = GPIO_GPIO15; } else if (port->mapbase == _Ser2UTCR0) { if (mctrl & TIOCM_RTS) - GPCR = GPIO_GC_UART1_RTS; + GPCR = GPIO_GPIO17; else - GPSR = GPIO_GC_UART1_RTS; + GPSR = GPIO_GPIO17; } else if (port->mapbase == _Ser3UTCR0) { if (mctrl & TIOCM_RTS) - GPCR = GPIO_GC_UART2_RTS; + GPCR = GPIO_GPIO19; else - GPSR = GPIO_GC_UART2_RTS; + GPSR = GPIO_GPIO19; } } static void graphicsclient_uart_pm(struct uart_port *port, u_int state, u_int oldstate) { - if (!state) { - /* make serial ports work ... */ - Ser2UTCR4 = 0; - Ser2HSCR0 = 0; - Ser1SDCR0 |= SDCR0_UART; + // state has ACPI D0-D3 + // ACPI D0 : resume from suspend + // ACPI D1-D3 : enter to a suspend state + if (port->mapbase == _Ser1UTCR0) { + if (state) { + // disable uart + Ser1UTCR3 = 0; + } + } + else if (port->mapbase == _Ser2UTCR0) { + if (state) { + // disable uart + Ser2UTCR3 = 0; + Ser2HSCR0 = 0; + } + } + else if (port->mapbase == _Ser3UTCR0) { + if (state) { + // disable uart + Ser3UTCR3 = 0; + } } } static struct sa1100_port_fns graphicsclient_port_fns __initdata = { - open: graphicsclient_uart_open, - close: graphicsclient_uart_close, - get_mctrl: graphicsclient_get_mctrl, - set_mctrl: graphicsclient_set_mctrl, - pm: graphicsclient_uart_pm, + .open = graphicsclient_uart_open, + .get_mctrl = graphicsclient_get_mctrl, + .set_mctrl = graphicsclient_set_mctrl, + .pm = graphicsclient_uart_pm, }; static void __init graphicsclient_map_io(void) @@ -312,14 +228,20 @@ sa1100_register_uart_fns(&graphicsclient_port_fns); sa1100_register_uart(0, 3); sa1100_register_uart(1, 1); + + // don't register if you want to use IRDA +#ifndef CONFIG_SA1100_FIR sa1100_register_uart(2, 2); - GPDR |= GPIO_GC_UART0_RTS | GPIO_GC_UART1_RTS | GPIO_GC_UART2_RTS; - GPDR &= ~(GPIO_GC_UART0_CTS | GPIO_GC_UART1_RTS | GPIO_GC_UART2_RTS); +#endif + + /* set GPDR now */ + GPDR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19; + GPDR &= ~(GPIO_GPIO14 | GPIO_GPIO16 | GPIO_GPIO18); } MACHINE_START(GRAPHICSCLIENT, "ADS GraphicsClient") + BOOT_PARAMS(0xc000003c) BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_graphicsclient) MAPIO(graphicsclient_map_io) INITIRQ(graphicsclient_init_irq) MACHINE_END diff -urN orig/arch/arm/mach-sa1100/graphicsmaster.c linux/arch/arm/mach-sa1100/graphicsmaster.c --- orig/arch/arm/mach-sa1100/graphicsmaster.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/graphicsmaster.c Thu Feb 27 23:20:10 2003 @@ -12,8 +12,13 @@ #include #include #include +#include +#include +#include +#include #include +#include #include #include @@ -40,6 +45,15 @@ */ sa1110_mb_disable(); + /* GraphicsMaster uses GPIO pins for SPI interface to AVR + */ + + /* use the alternate SSP pins */ + PPAR |= PPAR_SSPGPIO; + + // Set RTS low during sleep + PGSR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19; + /* * Probe for SA1111. */ @@ -67,9 +81,11 @@ * Enable PWM control for LCD */ SKPCR |= SKPCR_PWMCLKEN; - SKPWM0 = 0x7F; // VEE + SACR1 &= ~SACR1_L3EN; + ADS_DCR |= DCR_BACKLITE_ON; + SKPWM0 = 0x01; // Backlight SKPEN0 = 1; - SKPWM1 = 0x01; // Backlight + SKPWM1 = 0x7F; // VEE SKPEN1 = 1; /* @@ -83,7 +99,7 @@ */ sa1110_mb_enable(); - sa1111_init_irq(ADS_EXT_IRQ(0)); + sa1111_init_irq(IRQ_GRAPHICSMASTER_SA1111); return 0; } @@ -94,56 +110,58 @@ * Handlers for GraphicsMaster's external IRQ logic */ +#define GRAPHICSMASTER_N_IRQ (IRQ_GRAPHICSMASTER_END - IRQ_GRAPHICSMASTER_START) + static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs ) { int i; while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){ - for( i = 0; i < 16; i++ ) + for( i = 0; i < GRAPHICSMASTER_N_IRQ; i++ ) if( irq & (1<nr_banks = 1; - SET_BANK( 1, 0xc8000000, 16*1024*1024 ); - mi->nr_banks = 2; - - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -} - static struct map_desc graphicsmaster_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 1 */ @@ -212,17 +214,9 @@ if (port->mapbase == _Ser1UTCR0) { Ser1SDCR0 |= SDCR0_UART; - /* Set RTS Output */ - GPSR = GPIO_GPIO15; } else if (port->mapbase == _Ser2UTCR0) { Ser2UTCR4 = Ser2HSCR0 = 0; - /* Set RTS Output */ - GPSR = GPIO_GPIO17; - } - else if (port->mapbase == _Ser3UTCR0) { - /* Set RTS Output */ - GPSR = GPIO_GPIO19; } return ret; } @@ -238,7 +232,7 @@ if (!(GPLR & GPIO_GPIO16)) result |= TIOCM_CTS; } else if (port->mapbase == _Ser3UTCR0) { - if (!(GPLR & GPIO_GPIO17)) + if (!(GPLR & GPIO_GPIO18)) result |= TIOCM_CTS; } else { result = TIOCM_CTS; @@ -270,19 +264,35 @@ static void graphicsmaster_uart_pm(struct uart_port *port, u_int state, u_int oldstate) { - if (!state) { - /* make serial ports work ... */ - Ser2UTCR4 = 0; - Ser2HSCR0 = 0; - Ser1SDCR0 |= SDCR0_UART; + // state has ACPI D0-D3 + // ACPI D0 : resume from suspend + // ACPI D1-D3 : enter to a suspend state + if (port->mapbase == _Ser1UTCR0) { + if (state) { + // disable uart + Ser1UTCR3 = 0; + } + } + else if (port->mapbase == _Ser2UTCR0) { + if (state) { + // disable uart + Ser2UTCR3 = 0; + Ser2HSCR0 = 0; + } + } + else if (port->mapbase == _Ser3UTCR0) { + if (state) { + // disable uart + Ser3UTCR3 = 0; + } } } static struct sa1100_port_fns graphicsmaster_port_fns __initdata = { - open: graphicsmaster_uart_open, - get_mctrl: graphicsmaster_get_mctrl, - set_mctrl: graphicsmaster_set_mctrl, - pm: graphicsmaster_uart_pm, + .open = graphicsmaster_uart_open, + .get_mctrl = graphicsmaster_get_mctrl, + .set_mctrl = graphicsmaster_set_mctrl, + .pm = graphicsmaster_uart_pm, }; static void __init graphicsmaster_map_io(void) @@ -293,7 +303,10 @@ sa1100_register_uart_fns(&graphicsmaster_port_fns); sa1100_register_uart(0, 3); sa1100_register_uart(1, 1); + // don't register if you want to use IRDA +#ifndef CONFIG_SA1100_FIR sa1100_register_uart(2, 2); +#endif /* set GPDR now */ GPDR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19; @@ -301,8 +314,8 @@ } MACHINE_START(GRAPHICSMASTER, "ADS GraphicsMaster") + BOOT_PARAMS(0xc000003c) BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_graphicsmaster) MAPIO(graphicsmaster_map_io) INITIRQ(graphicsmaster_init_irq) MACHINE_END diff -urN orig/arch/arm/mach-sa1100/h3600.c linux/arch/arm/mach-sa1100/h3600.c --- orig/arch/arm/mach-sa1100/h3600.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-sa1100/h3600.c Sun Jun 29 17:09:04 2003 @@ -394,16 +394,16 @@ static void h3600_dcd_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct uart_info *info = dev_id; + struct uart_port *port = dev_id; /* Note: should only call this if something has changed */ - uart_handle_dcd_change(info, !(GPLR & GPIO_H3600_COM_DCD)); + uart_handle_dcd_change(port, !(GPLR & GPIO_H3600_COM_DCD)); } static void h3600_cts_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct uart_info *info = dev_id; + struct uart_port *port = dev_id; /* Note: should only call this if something has changed */ - uart_handle_cts_change(info, !(GPLR & GPIO_H3600_COM_CTS)); + uart_handle_cts_change(port, !(GPLR & GPIO_H3600_COM_CTS)); } static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate) @@ -433,7 +433,7 @@ return err; } -static int h3600_uart_open(struct uart_port *port, struct uart_info *info) +static int h3600_uart_open(struct uart_port *port) { int ret = 0; @@ -447,23 +447,23 @@ GPIO_BOTH_EDGES); ret = request_irq(IRQ_GPIO_H3600_COM_DCD, h3600_dcd_intr, - 0, "RS232 DCD", info); + 0, "RS232 DCD", port); if (ret) return ret; ret = request_irq(IRQ_GPIO_H3600_COM_CTS, h3600_cts_intr, - 0, "RS232 CTS", info); + 0, "RS232 CTS", port); if (ret) - free_irq(IRQ_GPIO_H3600_COM_DCD, info); + free_irq(IRQ_GPIO_H3600_COM_DCD, port); } return ret; } -static void h3600_uart_close(struct uart_port *port, struct uart_info *info) +static void h3600_uart_close(struct uart_port *port) { if (port->mapbase == _Ser3UTCR0) { - free_irq(IRQ_GPIO_H3600_COM_DCD, info); - free_irq(IRQ_GPIO_H3600_COM_CTS, info); + free_irq(IRQ_GPIO_H3600_COM_DCD, port); + free_irq(IRQ_GPIO_H3600_COM_CTS, port); } } diff -urN orig/arch/arm/mach-sa1100/hackkit.c linux/arch/arm/mach-sa1100/hackkit.c --- orig/arch/arm/mach-sa1100/hackkit.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/hackkit.c Thu Feb 6 11:33:12 2003 @@ -0,0 +1,221 @@ +/* + * linux/arch/arm/mach-sa1100/hackkit.c + * + * Copyright (C) 2002 Stefan Eletzhofer + * + * This file contains all HackKit tweaks. Based on original work from + * Nicolas Pitre's assabet fixes + * + * 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 + +#include + +#include + +#include "generic.h" + +#define DEBUG 1 + +#ifdef DEBUG +# define DPRINTK( x, args... ) printk( "%s: line %d: "x, __FUNCTION__, __LINE__, ## args ); +#else +# define DPRINTK( x, args... ) /* nix */ +#endif + +/********************************************************************** + * prototypes + */ + +/* init funcs */ +static void __init fixup_hackkit(struct machine_desc *desc, + struct param_struct *params, char **cmdline, struct meminfo *mi); +static void __init get_hackkit_scr(void); +static int __init hackkit_init(void); +static void __init hackkit_init_irq(void); +static void __init hackkit_map_io(void); + +static int hackkit_get_mctrl(struct uart_port *port); +static void hackkit_set_mctrl(struct uart_port *port, u_int mctrl); +static void hackkit_uart_pm(struct uart_port *port, u_int state, u_int oldstate); + +extern void convert_to_tag_list(struct param_struct *params, int mem_init); + + +/********************************************************************** + * global data + */ + +/********************************************************************** + * static data + */ + +static struct map_desc hackkit_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */ + LAST_DESC +}; + +static struct sa1100_port_fns hackkit_port_fns __initdata = { + .set_mctrl = hackkit_set_mctrl, + .get_mctrl = hackkit_get_mctrl, + .pm = hackkit_uart_pm, +}; + +/********************************************************************** + * Static functions + */ + +static void __init hackkit_map_io(void) +{ + DPRINTK( "%s\n", "START" ); + sa1100_map_io(); + iotable_init(hackkit_io_desc); + + sa1100_register_uart_fns(&hackkit_port_fns); + sa1100_register_uart(0, 1); /* com port */ + sa1100_register_uart(1, 2); + sa1100_register_uart(2, 3); /* radio module */ + + Ser1SDCR0 |= SDCR0_SUS; +} + +static void __init hackkit_init_irq(void) +{ + /* none used yet */ +} + +/** + * fixup_hackkit - fixup function for system 3 board + * @desc: machine description + * @param: kernel params + * @cmdline: kernel cmdline + * @mi: memory info struct + * + */ +static void __init fixup_hackkit(struct machine_desc *desc, + struct param_struct *params, char **cmdline, struct meminfo *mi) +{ + DPRINTK( "%s\n", "START" ); + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( 0xc0800000, 8*1024*1024 ); +} + + +/** + * hackkit_uart_pm - powermgmt callback function for system 3 UART + * @port: uart port structure + * @state: pm state + * @oldstate: old pm state + * + */ +static void hackkit_uart_pm(struct uart_port *port, u_int state, u_int oldstate) +{ + /* TODO: switch on/off uart in powersave mode */ +} + +/* + * Note! this can be called from IRQ context. + * FIXME: No modem ctrl lines yet. + */ +static void hackkit_set_mctrl(struct uart_port *port, u_int mctrl) +{ +#if 0 + if (port->mapbase == _Ser1UTCR0) { + u_int set = 0, clear = 0; + + if (mctrl & TIOCM_RTS) + set |= PT_CTRL2_RS1_RTS; + else + clear |= PT_CTRL2_RS1_RTS; + + if (mctrl & TIOCM_DTR) + set |= PT_CTRL2_RS1_DTR; + else + clear |= PT_CTRL2_RS1_DTR; + + PTCTRL2_clear(clear); + PTCTRL2_set(set); + } +#endif +} + +static int hackkit_get_mctrl(struct uart_port *port) +{ + u_int ret = 0; +#if 0 + u_int irqsr = PT_IRQSR; + + /* need 2 reads to read current value */ + irqsr = PT_IRQSR; + + /* TODO: check IRQ source register for modem/com + status lines and set them correctly. */ +#endif + + ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; + + return ret; +} + +static int __init hackkit_init(void) +{ + int ret = 0; + DPRINTK( "%s\n", "START" ); + + if ( !machine_is_hackkit() ) { + ret = -EINVAL; + goto DONE; + } + + hackkit_init_irq(); + + ret = 0; +DONE: + DPRINTK( "ret=%d\n", ret ); + return ret; +} + +/********************************************************************** + * Exported Functions + */ + +/********************************************************************** + * kernel magic macros + */ +__initcall(hackkit_init); + +MACHINE_START(HACKKIT, "HackKit Cpu Board") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) + FIXUP(fixup_hackkit) + MAPIO(hackkit_map_io) + INITIRQ(sa1100_init_irq) +MACHINE_END diff -urN orig/arch/arm/mach-sa1100/irq.c linux/arch/arm/mach-sa1100/irq.c --- orig/arch/arm/mach-sa1100/irq.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/irq.c Tue Feb 4 15:08:01 2003 @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -30,9 +32,9 @@ * This must be called *before* the appropriate IRQ is registered. * Use this instead of directly setting GRER/GFER. */ - static int GPIO_IRQ_rising_edge; static int GPIO_IRQ_falling_edge; +static int GPIO_IRQ_mask = (1 << 11) - 1; void set_GPIO_IRQ_edge(int gpio_mask, int edge) { @@ -51,6 +53,8 @@ GPIO_IRQ_rising_edge &= ~gpio_mask; GPDR &= ~gpio_mask; GAFR &= ~gpio_mask; + GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; + GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; while (gpio_mask) { if (irq == 11) irq = IRQ_GPIO11; @@ -86,8 +90,10 @@ static void sa1100_mask_and_ack_GPIO0_10_irq(unsigned int irq) { - ICMR &= ~(1 << irq); - GEDR = (1 << irq); + unsigned int mask = 1 << irq; + + ICMR &= ~mask; + GEDR = mask; } static void sa1100_mask_GPIO0_10_irq(unsigned int irq) @@ -97,16 +103,13 @@ static void sa1100_unmask_GPIO0_10_irq(unsigned int irq) { - GRER = (GRER & ~(1 << irq)) | (GPIO_IRQ_rising_edge & (1 << irq)); - GFER = (GFER & ~(1 << irq)) | (GPIO_IRQ_falling_edge & (1 << irq)); - ICMR |= (1 << irq); + ICMR |= 1 << irq; } /* * Install handler for GPIO 11-27 edge detect interrupts */ -static int GPIO_11_27_enabled; /* enabled i.e. unmasked GPIO IRQs */ static int GPIO_11_27_spurious; /* GPIOs that triggered when masked */ static void sa1100_GPIO11_27_demux(int irq, void *dev_id, @@ -124,7 +127,7 @@ * enabled at this point are considered spurious. Those * are cleared but only de-activated if they happen twice. */ - spurious = irq & ~GPIO_11_27_enabled; + spurious = irq & ~GPIO_IRQ_mask; if (spurious) { GEDR = spurious; GRER &= ~(spurious & GPIO_11_27_spurious); @@ -143,29 +146,29 @@ } static struct irqaction GPIO11_27_irq = { - name: "GPIO 11-27", - handler: sa1100_GPIO11_27_demux, - flags: SA_INTERRUPT + .name = "GPIO 11-27", + .handler = sa1100_GPIO11_27_demux, + .flags = SA_INTERRUPT }; static void sa1100_mask_and_ack_GPIO11_27_irq(unsigned int irq) { - int mask = (1 << GPIO_11_27_IRQ(irq)); + unsigned int mask = (1 << GPIO_11_27_IRQ(irq)); GPIO_11_27_spurious &= ~mask; - GPIO_11_27_enabled &= ~mask; + GPIO_IRQ_mask &= ~mask; GEDR = mask; } static void sa1100_mask_GPIO11_27_irq(unsigned int irq) { - int mask = (1 << GPIO_11_27_IRQ(irq)); + unsigned int mask = (1 << GPIO_11_27_IRQ(irq)); GPIO_11_27_spurious &= ~mask; - GPIO_11_27_enabled &= ~mask; + GPIO_IRQ_mask &= ~mask; } static void sa1100_unmask_GPIO11_27_irq(unsigned int irq) { - int mask = (1 << GPIO_11_27_IRQ(irq)); + unsigned int mask = (1 << GPIO_11_27_IRQ(irq)); if (GPIO_11_27_spurious & mask) { /* * We don't want to miss an interrupt that would have occurred @@ -185,15 +188,17 @@ return; } } - GPIO_11_27_enabled |= mask; - GRER = (GRER & ~mask) | (GPIO_IRQ_rising_edge & mask); - GFER = (GFER & ~mask) | (GPIO_IRQ_falling_edge & mask); + + GPIO_IRQ_mask |= mask; + + GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; + GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; } static struct resource irq_resource = { - name: "irqs", - start: 0x90050000, - end: 0x9005ffff, + .name = "irqs", + .start = 0x90050000, + .end = 0x9005ffff, }; void __init sa1100_init_irq(void) @@ -248,10 +253,4 @@ irq_desc[irq].unmask = sa1100_unmask_GPIO11_27_irq; } setup_arm_irq( IRQ_GPIO11_27, &GPIO11_27_irq ); - - /* - * We generally don't want the LCD IRQ being - * enabled as soon as we request it. - */ - irq_desc[IRQ_LCD].noautoenable = 1; } diff -urN orig/arch/arm/mach-sa1100/jornada720.c linux/arch/arm/mach-sa1100/jornada720.c --- orig/arch/arm/mach-sa1100/jornada720.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/jornada720.c Sun Dec 29 12:01:34 2002 @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include @@ -34,7 +36,7 @@ udelay(1); GPSR = GPIO_GPIO20; udelay(20); - SKCR = JORSKCR_INIT; /* Turn on the PLL, enable Ready and enable nOE assertion from DC */ + SBI_SKCR = JORSKCR_INIT;/* Turn on the PLL, enable Ready and enable nOE assertion from DC */ mdelay(100); SBI_SKCR = JORSKCR_RCLK;/* turn on the RCLOCK */ diff -urN orig/arch/arm/mach-sa1100/leds-adsagc.c linux/arch/arm/mach-sa1100/leds-adsagc.c --- orig/arch/arm/mach-sa1100/leds-adsagc.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/leds-adsagc.c Fri Feb 21 15:17:34 2003 @@ -0,0 +1,107 @@ +/* + * linux/arch/arm/mach-sa1100/leds-adsagc.c + * + * ADS Advanced Graphics Client LEDs support + * Robert Whaley, Feb 7, 2003 + */ +#include +#include + +#include +#include +#include + +#include "leds.h" + + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + +#define LED_TIMER ADS_LED0 /* green heartbeat */ +#define LED_USER ADS_LED1 /* amber, boots to on */ +#define LED_IDLE ADS_LED2 /* red has the idle led, if any */ + +#define LED_MASK (ADS_LED0|ADS_LED1|ADS_LED2) + +void adsagc_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = 0; /* gc leds are positive logic */ + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= LED_TIMER; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~LED_IDLE; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= LED_IDLE; + break; +#endif + + case led_green_on: + break; + + case led_green_off: + break; + + case led_amber_on: + hw_led_state |= LED_USER; + break; + + case led_amber_off: + hw_led_state &= ~LED_USER; + break; + + case led_red_on: + break; + + case led_red_off: + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) { + + unsigned char ads_cr3 = ADS_CR3; + ads_cr3 &= ~LED_MASK; + ads_cr3 |= hw_led_state; + ADS_CR3 = ads_cr3; + } + + local_irq_restore(flags); +} diff -urN orig/arch/arm/mach-sa1100/leds-adsbitsy.c linux/arch/arm/mach-sa1100/leds-adsbitsy.c --- orig/arch/arm/mach-sa1100/leds-adsbitsy.c Fri Nov 16 10:09:48 2001 +++ linux/arch/arm/mach-sa1100/leds-adsbitsy.c Fri Sep 6 10:53:47 2002 @@ -28,7 +28,7 @@ { unsigned long flags; - save_flags_cli(flags); + local_irq_save(flags); switch (evt) { case led_start: @@ -92,5 +92,5 @@ GPCR = hw_led_state ^ LED_MASK; } - restore_flags(flags); + local_irq_restore(flags); } diff -urN orig/arch/arm/mach-sa1100/leds-adsbitsyplus.c linux/arch/arm/mach-sa1100/leds-adsbitsyplus.c --- orig/arch/arm/mach-sa1100/leds-adsbitsyplus.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/leds-adsbitsyplus.c Fri Feb 21 15:17:33 2003 @@ -0,0 +1,97 @@ +/* + * linux/arch/arm/mach-sa1100/leds-adsbitsy.c + * + * ADS Bitsy LED + * 2/7/2003 Robert Whaley + * This file comes from leds-adsbitsy.c of Woojung Huh + */ +#include +#include + +#include +#include +#include + +#include "leds.h" + + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + +#define LED_TIMER GPIO_GPIO20 /* green heartbeat */ + +#define LED_MASK (LED_TIMER) + +void adsbitsyplus_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = 0; /* gc leds are positive logic */ + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= LED_TIMER; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + break; + + case led_idle_end: + break; +#endif + + case led_green_on: + break; + + case led_green_off: + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + break; + + case led_red_off: + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) { + GPSR = hw_led_state; + GPCR = hw_led_state ^ LED_MASK; + } + + local_irq_restore(flags); +} diff -urN orig/arch/arm/mach-sa1100/leds-frodo.c linux/arch/arm/mach-sa1100/leds-frodo.c --- orig/arch/arm/mach-sa1100/leds-frodo.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/leds-frodo.c Thu Oct 24 13:01:38 2002 @@ -22,22 +22,22 @@ #include "leds.h" -#define led6_on() FRODO_CPLD_GENERAL |= FRODO_LED2 -#define led6_off() FRODO_CPLD_GENERAL &= ~FRODO_LED2 -#define led6_invert() do { \ - if ((FRODO_CPLD_GENERAL & FRODO_LED2)) \ - led6_off (); \ - else \ - led6_on (); \ +#define led6_on() frodo_cpld_set (FRODO_CPLD_GENERAL,FRODO_LED2) +#define led6_off() frodo_cpld_clear (FRODO_CPLD_GENERAL,FRODO_LED2) +#define led6_invert() do { \ + if ((frodo_cpld_read (FRODO_CPLD_GENERAL) & FRODO_LED2)) \ + led6_off (); \ + else \ + led6_on (); \ } while (0) -#define led7_on() FRODO_CPLD_GENERAL |= FRODO_LED1 -#define led7_off() FRODO_CPLD_GENERAL &= ~FRODO_LED1 +#define led7_on() frodo_cpld_set (FRODO_CPLD_GENERAL,FRODO_LED1) +#define led7_off() frodo_cpld_clear (FRODO_CPLD_GENERAL,FRODO_LED1) #define led7_invert() do { \ - if ((FRODO_CPLD_GENERAL & FRODO_LED1)) \ - led7_off (); \ - else \ - led7_on (); \ + if ((frodo_cpld_read (FRODO_CPLD_GENERAL) & FRODO_LED1)) \ + led7_off (); \ + else \ + led7_on (); \ } while (0) static int claimed; diff -urN orig/arch/arm/mach-sa1100/leds-graphicsclient.c linux/arch/arm/mach-sa1100/leds-graphicsclient.c --- orig/arch/arm/mach-sa1100/leds-graphicsclient.c Mon Sep 3 14:14:40 2001 +++ linux/arch/arm/mach-sa1100/leds-graphicsclient.c Fri Sep 6 10:54:23 2002 @@ -30,7 +30,7 @@ { unsigned long flags; - save_flags_cli(flags); + local_irq_save(flags); switch (evt) { case led_start: @@ -100,5 +100,5 @@ GPCR = hw_led_state ^ LED_MASK; } - restore_flags(flags); + local_irq_restore(flags); } diff -urN orig/arch/arm/mach-sa1100/leds-graphicsmaster.c linux/arch/arm/mach-sa1100/leds-graphicsmaster.c --- orig/arch/arm/mach-sa1100/leds-graphicsmaster.c Fri Oct 26 16:45:53 2001 +++ linux/arch/arm/mach-sa1100/leds-graphicsmaster.c Fri Sep 6 10:54:23 2002 @@ -30,7 +30,7 @@ { unsigned long flags; - save_flags_cli(flags); + local_irq_save(flags); switch (evt) { case led_start: @@ -100,5 +100,5 @@ GPCR = hw_led_state ^ LED_MASK; } - restore_flags(flags); + local_irq_restore(flags); } diff -urN orig/arch/arm/mach-sa1100/leds-hackkit.c linux/arch/arm/mach-sa1100/leds-hackkit.c --- orig/arch/arm/mach-sa1100/leds-hackkit.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/leds-hackkit.c Thu Dec 12 22:37:25 2002 @@ -0,0 +1,113 @@ +/* + * linux/arch/arm/mach-sa1100/leds-hackkit.c + * + * based on leds-lart.c + * + * (C) Erik Mouw (J.A.K.Mouw@its.tudelft.nl), April 21, 2000 + * (C) Stefan Eletzhofer , 2002 + * + * The HackKit has two leds (GPIO 22/23). The red led (gpio 22) is used + * as cpu led, the green one is used as timer led. + */ +#include +#include + +#include +#include +#include + +#include "leds.h" + + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + +#define LED_GREEN GPIO_GPIO23 +#define LED_RED GPIO_GPIO22 +#define LED_MASK (LED_RED | LED_GREEN) + +void hackkit_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch(evt) { + case led_start: + /* pin 22/23 are outputs */ + GPDR |= LED_MASK; + hw_led_state = LED_MASK; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= LED_GREEN; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + /* The LART people like the LED to be off when the + system is idle... */ + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~LED_RED; + break; + + case led_idle_end: + /* ... and on if the system is not idle */ + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= LED_RED; + break; +#endif + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~LED_RED; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= LED_RED; + break; + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~LED_GREEN; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= LED_GREEN; + break; + + default: + break; + } + + /* Now set the GPIO state, or nothing will happen at all */ + if (led_state & LED_STATE_ENABLED) { + GPSR = hw_led_state; + GPCR = hw_led_state ^ LED_MASK; + } + + local_irq_restore(flags); +} diff -urN orig/arch/arm/mach-sa1100/leds.c linux/arch/arm/mach-sa1100/leds.c --- orig/arch/arm/mach-sa1100/leds.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/leds.c Fri Feb 21 15:22:51 2003 @@ -15,8 +15,12 @@ static int __init sa1100_leds_init(void) { + if (machine_is_adsagc()) + leds_event = adsagc_leds_event; if (machine_is_adsbitsy()) leds_event = adsbitsy_leds_event; + if (machine_is_adsbitsyplus()) + leds_event = adsbitsyplus_leds_event; if (machine_is_assabet()) leds_event = assabet_leds_event; if (machine_is_consus()) @@ -33,6 +37,8 @@ leds_event = graphicsclient_leds_event; if (machine_is_graphicsmaster()) leds_event = graphicsmaster_leds_event; + if (machine_is_hackkit()) + leds_event = hackkit_leds_event; if (machine_is_lart()) leds_event = lart_leds_event; if (machine_is_pfs168()) diff -urN orig/arch/arm/mach-sa1100/leds.h linux/arch/arm/mach-sa1100/leds.h --- orig/arch/arm/mach-sa1100/leds.h Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/leds.h Fri Feb 21 15:17:34 2003 @@ -1,12 +1,15 @@ +extern void adsagc_leds_event(led_event_t evt); +extern void adsbitsy_leds_event(led_event_t evt); +extern void adsbitsyplus_leds_event(led_event_t evt); extern void assabet_leds_event(led_event_t evt); extern void consus_leds_event(led_event_t evt); extern void brutus_leds_event(led_event_t evt); extern void cerf_leds_event(led_event_t evt); extern void flexanet_leds_event(led_event_t evt); +extern void frodo_leds_event(led_event_t evt); extern void graphicsclient_leds_event(led_event_t evt); +extern void graphicsmaster_leds_event(led_event_t evt); +extern void hackkit_leds_event(led_event_t evt); extern void lart_leds_event(led_event_t evt); extern void pfs168_leds_event(led_event_t evt); -extern void graphicsmaster_leds_event(led_event_t evt); -extern void adsbitsy_leds_event(led_event_t evt); extern void system3_leds_event(led_event_t evt); -extern void frodo_leds_event(led_event_t evt); diff -urN orig/arch/arm/mach-sa1100/nanoengine.c linux/arch/arm/mach-sa1100/nanoengine.c --- orig/arch/arm/mach-sa1100/nanoengine.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/nanoengine.c Fri Jun 21 14:13:59 2002 @@ -16,22 +16,6 @@ #include "generic.h" -static void __init -fixup_nanoengine(struct machine_desc *desc, struct param_struct *params, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); - - /* Get command line parameters passed from the loader (if any) */ - if( *((char*)0xc0000100) ) - *cmdline = ((char *)0xc0000100); -} - static struct map_desc nanoengine_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */ @@ -56,7 +40,7 @@ MACHINE_START(NANOENGINE, "BSE nanoEngine") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_nanoengine) + BOOT_PARAMS(0xc0000100) MAPIO(nanoengine_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -urN orig/arch/arm/mach-sa1100/neponset.c linux/arch/arm/mach-sa1100/neponset.c --- orig/arch/arm/mach-sa1100/neponset.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-sa1100/neponset.c Thu Feb 6 11:33:12 2003 @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include diff -urN orig/arch/arm/mach-sa1100/pcipool.c linux/arch/arm/mach-sa1100/pcipool.c --- orig/arch/arm/mach-sa1100/pcipool.c Mon Sep 3 14:14:40 2001 +++ linux/arch/arm/mach-sa1100/pcipool.c Thu Jan 1 01:00:00 1970 @@ -1,377 +0,0 @@ -/* - NOTE: - - this code was lifted straight out of drivers/pci/pci.c; - when compiling for the Intel StrongARM SA-1110/SA-1111 the - usb-ohci.c driver needs these routines even when the architecture - has no pci bus... -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "pcipool.h" - -/* - * Pool allocator ... wraps the pci_alloc_consistent page allocator, so - * small blocks are easily used by drivers for bus mastering controllers. - * This should probably be sharing the guts of the slab allocator. - */ - -struct pci_pool { /* the pool */ - struct list_head page_list; - spinlock_t lock; - size_t blocks_per_page; - size_t size; - int flags; - struct pci_dev *dev; - size_t allocation; - char name [32]; - wait_queue_head_t waitq; -}; - -struct pci_page { /* cacheable header for 'allocation' bytes */ - struct list_head page_list; - void *vaddr; - dma_addr_t dma; - unsigned long bitmap [0]; -}; - -#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) -#define POOL_POISON_BYTE 0xa7 - -// #define CONFIG_PCIPOOL_DEBUG - - -/** - * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma. - * @name: name of pool, for diagnostics - * @pdev: pci device that will be doing the DMA - * @size: size of the blocks in this pool. - * @align: alignment requirement for blocks; must be a power of two - * @allocation: returned blocks won't cross this boundary (or zero) - * @flags: SLAB_* flags (not all are supported). - * - * Returns a pci allocation pool with the requested characteristics, or - * null if one can't be created. Given one of these pools, pci_pool_alloc() - * may be used to allocate memory. Such memory will all have "consistent" - * DMA mappings, accessible by the device and its driver without using - * cache flushing primitives. The actual size of blocks allocated may be - * larger than requested because of alignment. - * - * If allocation is nonzero, objects returned from pci_pool_alloc() won't - * cross that size boundary. This is useful for devices which have - * addressing restrictions on individual DMA transfers, such as not crossing - * boundaries of 4KBytes. - */ -struct pci_pool * -pci_pool_create (const char *name, struct pci_dev *pdev, - size_t size, size_t align, size_t allocation, int flags) -{ - struct pci_pool *retval; - - if (align == 0) - align = 1; - if (size == 0) - return 0; - else if (size < align) - size = align; - else if ((size % align) != 0) { - size += align + 1; - size &= ~(align - 1); - } - - if (allocation == 0) { - if (PAGE_SIZE < size) - allocation = size; - else - allocation = PAGE_SIZE; - // FIXME: round up for less fragmentation - } else if (allocation < size) - return 0; - - if (!(retval = kmalloc (sizeof *retval, flags))) - return retval; - -#ifdef CONFIG_PCIPOOL_DEBUG - flags |= SLAB_POISON; -#endif - - strncpy (retval->name, name, sizeof retval->name); - retval->name [sizeof retval->name - 1] = 0; - - retval->dev = pdev; - INIT_LIST_HEAD (&retval->page_list); - spin_lock_init (&retval->lock); - retval->size = size; - retval->flags = flags; - retval->allocation = allocation; - retval->blocks_per_page = allocation / size; - init_waitqueue_head (&retval->waitq); - -#ifdef CONFIG_PCIPOOL_DEBUG - printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n", - pdev ? pdev->slot_name : NULL, retval->name, size, - retval->blocks_per_page, allocation); -#endif - - return retval; -} - - -static struct pci_page * -pool_alloc_page (struct pci_pool *pool, int mem_flags) -{ - struct pci_page *page; - int mapsize; - - mapsize = pool->blocks_per_page; - mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG; - mapsize *= sizeof (long); - - page = (struct pci_page *) kmalloc (mapsize + sizeof *page, mem_flags); - if (!page) - return 0; - page->vaddr = pci_alloc_consistent (pool->dev, - pool->allocation, &page->dma); - if (page->vaddr) { - memset (page->bitmap, 0xff, mapsize); // bit set == free - if (pool->flags & SLAB_POISON) - memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); - list_add (&page->page_list, &pool->page_list); - } else { - kfree (page); - page = 0; - } - return page; -} - - -static inline int -is_page_busy (int blocks, unsigned long *bitmap) -{ - while (blocks > 0) { - if (*bitmap++ != ~0UL) - return 1; - blocks -= BITS_PER_LONG; - } - return 0; -} - -static void -pool_free_page (struct pci_pool *pool, struct pci_page *page) -{ - dma_addr_t dma = page->dma; - - if (pool->flags & SLAB_POISON) - memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); - pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma); - list_del (&page->page_list); - kfree (page); -} - - -/** - * pci_pool_destroy - destroys a pool of pci memory blocks. - * @pool: pci pool that will be destroyed - * - * Caller guarantees that no more memory from the pool is in use, - * and that nothing will try to use the pool after this call. - */ -void -pci_pool_destroy (struct pci_pool *pool) -{ - unsigned long flags; - -#ifdef CONFIG_PCIPOOL_DEBUG - printk (KERN_DEBUG "pcipool destroy %s/%s\n", - pool->dev ? pool->dev->slot_name : NULL, - pool->name); -#endif - - spin_lock_irqsave (&pool->lock, flags); - while (!list_empty (&pool->page_list)) { - struct pci_page *page; - page = list_entry (pool->page_list.next, - struct pci_page, page_list); - if (is_page_busy (pool->blocks_per_page, page->bitmap)) { - printk (KERN_ERR "pci_pool_destroy %s/%s, %p busy\n", - pool->dev ? pool->dev->slot_name : NULL, - pool->name, page->vaddr); - /* leak the still-in-use consistent memory */ - list_del (&page->page_list); - kfree (page); - } else - pool_free_page (pool, page); - } - spin_unlock_irqrestore (&pool->lock, flags); - kfree (pool); -} - - -/** - * pci_pool_alloc - get a block of consistent memory - * @pool: pci pool that will produce the block - * @mem_flags: SLAB_KERNEL or SLAB_ATOMIC - * @handle: pointer to dma address of block - * - * This returns the kernel virtual address of a currently unused block, - * and reports its dma address through the handle. - * If such a memory block can't be allocated, null is returned. - */ -void * -pci_pool_alloc (struct pci_pool *pool, int mem_flags, dma_addr_t *handle) -{ - unsigned long flags; - struct list_head *entry; - struct pci_page *page; - int map, block; - size_t offset; - void *retval; - -restart: - spin_lock_irqsave (&pool->lock, flags); - list_for_each (entry, &pool->page_list) { - int i; - page = list_entry (entry, struct pci_page, page_list); - /* only cachable accesses here ... */ - for (map = 0, i = 0; - i < pool->blocks_per_page; - i += BITS_PER_LONG, map++) { - if (page->bitmap [map] == 0) - continue; - block = ffz (~ page->bitmap [map]); - if ((i + block) < pool->blocks_per_page) { - clear_bit (block, &page->bitmap [map]); - offset = (BITS_PER_LONG * map) + block; - offset *= pool->size; - goto ready; - } - } - } - if (!(page = pool_alloc_page (pool, mem_flags))) { - if (mem_flags == SLAB_KERNEL) { - DECLARE_WAITQUEUE (wait, current); - - current->state = TASK_INTERRUPTIBLE; - add_wait_queue (&pool->waitq, &wait); - spin_unlock_irqrestore (&pool->lock, flags); - - schedule_timeout (POOL_TIMEOUT_JIFFIES); - - current->state = TASK_RUNNING; - remove_wait_queue (&pool->waitq, &wait); - goto restart; - } - retval = 0; - goto done; - } - - clear_bit (0, &page->bitmap [0]); - offset = 0; -ready: - retval = offset + page->vaddr; - *handle = offset + page->dma; -done: - spin_unlock_irqrestore (&pool->lock, flags); - return retval; -} - - -static struct pci_page * -pool_find_page (struct pci_pool *pool, dma_addr_t dma) -{ - unsigned long flags; - struct list_head *entry; - struct pci_page *page; - - spin_lock_irqsave (&pool->lock, flags); - list_for_each (entry, &pool->page_list) { - page = list_entry (entry, struct pci_page, page_list); - if (dma < page->dma) - continue; - if (dma < (page->dma + pool->allocation)) - goto done; - } - page = 0; -done: - spin_unlock_irqrestore (&pool->lock, flags); - return page; -} - - -/** - * pci_pool_free - put block back into pci pool - * @pool: the pci pool holding the block - * @vaddr: virtual address of block - * @dma: dma address of block - * - * Caller promises neither device nor driver will again touch this block - * unless it is first re-allocated. - */ -void -pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma) -{ - struct pci_page *page; - unsigned long flags; - int map, block; - - if ((page = pool_find_page (pool, dma)) == 0) { - printk (KERN_ERR "pci_pool_free %s/%s, %p/%x (bad dma)\n", - pool->dev ? pool->dev->slot_name : NULL, - pool->name, vaddr, dma); - return; - } -#ifdef CONFIG_PCIPOOL_DEBUG - if (((dma - page->dma) + (void *)page->vaddr) != vaddr) { - printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%x\n", - pool->dev ? pool->dev->slot_name : NULL, - pool->name, vaddr, dma); - return; - } -#endif - - block = dma - page->dma; - block /= pool->size; - map = block / BITS_PER_LONG; - block %= BITS_PER_LONG; - -#ifdef CONFIG_PCIPOOL_DEBUG - if (page->bitmap [map] & (1UL << block)) { - printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n", - pool->dev ? pool->dev->slot_name : NULL, - pool->name, dma); - return; - } -#endif - if (pool->flags & SLAB_POISON) - memset (vaddr, POOL_POISON_BYTE, pool->size); - - spin_lock_irqsave (&pool->lock, flags); - set_bit (block, &page->bitmap [map]); - if (waitqueue_active (&pool->waitq)) - wake_up (&pool->waitq); - /* - * Resist a temptation to do - * if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page); - * it is not interrupt safe. Better have empty pages hang around. - */ - spin_unlock_irqrestore (&pool->lock, flags); -} - - -EXPORT_SYMBOL (pci_pool_create); -EXPORT_SYMBOL (pci_pool_destroy); -EXPORT_SYMBOL (pci_pool_alloc); -EXPORT_SYMBOL (pci_pool_free); - diff -urN orig/arch/arm/mach-sa1100/pcipool.h linux/arch/arm/mach-sa1100/pcipool.h --- orig/arch/arm/mach-sa1100/pcipool.h Mon Sep 3 14:14:40 2001 +++ linux/arch/arm/mach-sa1100/pcipool.h Thu Jan 1 01:00:00 1970 @@ -1,8 +0,0 @@ - -struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev, - size_t size, size_t align, size_t allocation, int flags); -void pci_pool_destroy (struct pci_pool *pool); - -void *pci_pool_alloc (struct pci_pool *pool, int flags, dma_addr_t *handle); -void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr); - diff -urN orig/arch/arm/mach-sa1100/pm.c linux/arch/arm/mach-sa1100/pm.c --- orig/arch/arm/mach-sa1100/pm.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/pm.c Mon Aug 5 13:41:24 2002 @@ -18,11 +18,13 @@ * 2001-08-29: Nicolas Pitre * Cleaned up, pushed platform dependent stuff * in the platform specific files. + * + * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. + * Storage is local on the stack now. */ #include #include #include -#include #include #include #include @@ -33,7 +35,6 @@ #include #include -#include "sleep.h" /* * Debug macros @@ -43,20 +44,32 @@ extern void sa1100_cpu_suspend(void); extern void sa1100_cpu_resume(void); -extern unsigned long *sleep_save; /* virtual address */ -extern unsigned long sleep_save_p; /* physical address */ - #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] +/* + * List of global SA11x0 peripheral registers to preserve. + * More ones like CP and general purpose register values are preserved + * with the stack location in sleep.S. + */ +enum { SLEEP_SAVE_START = 0, + + SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, + SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, + + SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR, + SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, + + SLEEP_SAVE_ICMR, + SLEEP_SAVE_Ser1SDCR0, + + SLEEP_SAVE_SIZE +}; + + int pm_do_suspend(void) { - /* set up pointer to sleep parameters */ - sleep_save = kmalloc(SLEEP_SAVE_SIZE*sizeof(long), GFP_ATOMIC); - if (!sleep_save) - return -ENOMEM; - - sleep_save_p = virt_to_phys(sleep_save); + unsigned long sleep_save[SLEEP_SAVE_SIZE]; cli(); @@ -144,8 +157,6 @@ sti(); - kfree (sleep_save); - /* * Restore the CPU frequency settings. */ @@ -156,6 +167,11 @@ return 0; } +unsigned long sleep_phys_sp(void *sp) +{ + return virt_to_phys(sp); +} + #ifdef CONFIG_SYSCTL /* * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than diff -urN orig/arch/arm/mach-sa1100/sa1100_usb.h linux/arch/arm/mach-sa1100/sa1100_usb.h --- orig/arch/arm/mach-sa1100/sa1100_usb.h Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/sa1100_usb.h Tue Oct 16 20:02:23 2001 @@ -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 -urN orig/arch/arm/mach-sa1100/sa1111-ohci.c linux/arch/arm/mach-sa1100/sa1111-ohci.c --- orig/arch/arm/mach-sa1100/sa1111-ohci.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/sa1111-ohci.c Wed Feb 27 11:37:49 2002 @@ -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 -urN orig/arch/arm/mach-sa1100/sa1111-pcibuf.c linux/arch/arm/mach-sa1100/sa1111-pcibuf.c --- orig/arch/arm/mach-sa1100/sa1111-pcibuf.c Mon Aug 5 13:29:46 2002 +++ linux/arch/arm/mach-sa1100/sa1111-pcibuf.c Fri Jan 24 16:20:58 2003 @@ -1,272 +1,400 @@ /* * linux/arch/arm/mach-sa1100/pci-sa1111.c * - * Special pci_map/unmap_single routines for SA-1111. These functions - * compensate for a bug in the SA-1111 hardware which don't allow DMA - * to/from addresses above 1MB. + * Special pci_{map/unmap/dma_sync}_* routines for SA-1111. * - * Brad Parker (brad@heeltoe.com) + * These functions utilize bouncer buffers to compensate for a bug in + * the SA-1111 hardware which don't allow DMA to/from addresses + * certain addresses above 1MB. * - * 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. + * Re-written by Christopher Hoover + * Original version by Brad Parker (brad@heeltoe.com) * - * 06/13/2001 - created. - */ + * Copyright (C) 2002 Hewlett Packard Company. + * + * 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 +//#define DEBUG +#ifdef DEBUG +#define DPRINTK(...) do { printk(KERN_DEBUG __VA_ARGS__); } while (0) +#else +#define DPRINTK(...) do { } while (0) +#endif + +struct safe_buffer { + struct list_head node; + + /* original request */ + void *ptr; + size_t size; + int direction; -#include "pcipool.h" + /* safe buffer info */ + struct pci_pool *pool; + void *safe; + dma_addr_t safe_dma_addr; +}; -/* - * simple buffer allocator for copying of unsafe to safe buffers - * uses __alloc/__free for actual buffers - * keeps track of safe buffers we've allocated so we can recover the - * unsafe buffers. - */ +LIST_HEAD(safe_buffers); -#define MAX_SAFE 32 #define SIZE_SMALL 1024 #define SIZE_LARGE (16*1024) -static long mapped_alloc_size; -static char *safe_buffers[MAX_SAFE][2]; - - -static struct pci_pool *small_buffer_cache, *large_buffer_cache; +static struct pci_pool *small_buffer_pool, *large_buffer_pool; -static int -init_safe_buffers(struct pci_dev *dev) +static int __init +create_safe_buffer_pools(void) { - small_buffer_cache = pci_pool_create("pci_small_buffer", - dev, + small_buffer_pool = pci_pool_create("sa1111_small_dma_buffer", + SA1111_FAKE_PCIDEV, SIZE_SMALL, 0 /* byte alignment */, 0 /* no page-crossing issues */, - GFP_KERNEL | GFP_DMA); - - if (small_buffer_cache == 0) + SLAB_KERNEL); + if (0 == small_buffer_pool) { + printk(KERN_ERR + "sa1111_pcibuf: could not allocate small pci pool\n"); return -1; + } - large_buffer_cache = pci_pool_create("pci_large_buffer", - dev, + large_buffer_pool = pci_pool_create("sa1111_large_dma_buffer", + SA1111_FAKE_PCIDEV, SIZE_LARGE, 0 /* byte alignment */, 0 /* no page-crossing issues */, - GFP_KERNEL | GFP_DMA); - if (large_buffer_cache == 0) + SLAB_KERNEL); + if (0 == large_buffer_pool) { + printk(KERN_ERR + "sa1111_pcibuf: could not allocate large pci pool\n"); + pci_pool_destroy(small_buffer_pool); + small_buffer_pool = 0; return -1; + } return 0; } +static void __exit +destroy_safe_buffer_pools(void) +{ + if (small_buffer_pool) + pci_pool_destroy(small_buffer_pool); + if (large_buffer_pool) + pci_pool_destroy(large_buffer_pool); + + small_buffer_pool = large_buffer_pool = 0; +} + + /* allocate a 'safe' buffer and keep track of it */ -static char * -alloc_safe_buffer(char *unsafe, int size, dma_addr_t *pbus) +static struct safe_buffer * +alloc_safe_buffer(void *ptr, size_t size, int direction) { - char *safe; - dma_addr_t busptr; + struct safe_buffer *buf; struct pci_pool *pool; - int i; - - if (0) printk("alloc_safe_buffer(size=%d)\n", size); + void *safe; + dma_addr_t safe_dma_addr; - if (size <= SIZE_SMALL) - pool = small_buffer_cache; - else - if (size < SIZE_LARGE) - pool = large_buffer_cache; - else - return 0; + DPRINTK("%s(ptr=%p, size=%d, direction=%d)\n", + __func__, ptr, size, direction); - safe = pci_pool_alloc(pool, SLAB_ATOMIC, &busptr); - if (safe == 0) + buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC); + if (buf == 0) { + printk(KERN_WARNING "%s: kmalloc failed\n", __func__); return 0; + } - for (i = 0; i < MAX_SAFE; i++) - if (safe_buffers[i][0] == 0) { - break; - } - - if (i == MAX_SAFE) { - panic(__FILE__ ": exceeded MAX_SAFE buffers"); + if (size <= SIZE_SMALL) { + pool = small_buffer_pool; + safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); + } else if (size <= SIZE_LARGE) { + pool = large_buffer_pool; + safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); + } else { + printk(KERN_DEBUG + "sa111_pcibuf: resorting to pci_alloc_consistent\n"); + pool = 0; + safe = pci_alloc_consistent(SA1111_FAKE_PCIDEV, size, + &safe_dma_addr); } - /* place the size index and the old buffer ptr in the first 8 bytes - * and return a ptr + 12 to caller - */ - ((int *)safe)[0] = i; - ((char **)safe)[1] = (char *)pool; - ((char **)safe)[2] = unsafe; + if (safe == 0) { + printk(KERN_WARNING + "%s: could not alloc dma memory (size=%d)\n", + __func__, size); + kfree(buf); + return 0; + } - busptr += sizeof(int) + sizeof(char *) + sizeof(char *); + BUG_ON(sa1111_check_dma_bug(safe_dma_addr)); // paranoia - safe_buffers[i][0] = (void *)busptr; - safe_buffers[i][1] = (void *)safe; + buf->ptr = ptr; + buf->size = size; + buf->direction = direction; + buf->pool = pool; + buf->safe = safe; + buf->safe_dma_addr = safe_dma_addr; - safe += sizeof(int) + sizeof(char *) + sizeof(char *); + MOD_INC_USE_COUNT; + list_add(&buf->node, &safe_buffers); - *pbus = busptr; - return safe; + return buf; } /* determine if a buffer is from our "safe" pool */ -static char * -find_safe_buffer(char *busptr, char **unsafe) +static struct safe_buffer * +find_safe_buffer(dma_addr_t safe_dma_addr) { - int i; - char *buf; + struct list_head *entry; - for (i = 0; i < MAX_SAFE; i++) { - if (safe_buffers[i][0] == busptr) { - if (0) printk("find_safe_buffer(%p) found @ %d\n", busptr, i); - buf = safe_buffers[i][1]; - *unsafe = ((char **)buf)[2]; - return buf + sizeof(int) + sizeof(char *) + sizeof(char *); + list_for_each(entry, &safe_buffers) { + struct safe_buffer *b = + list_entry(entry, struct safe_buffer, node); + + if (b->safe_dma_addr == safe_dma_addr) { + return b; } } - return (char *)0; + return 0; } static void -free_safe_buffer(char *buf) +free_safe_buffer(struct safe_buffer *buf) { - int index; - struct pci_pool *pool; - char *dma; + DPRINTK("%s(buf=%p)\n", __func__, buf); - if (0) printk("free_safe_buffer(buf=%p)\n", buf); + list_del(&buf->node); - /* retrieve the buffer size index */ - buf -= sizeof(int) + sizeof(char*) + sizeof(char*); - index = ((int *)buf)[0]; - pool = (struct pci_pool *)((char **)buf)[1]; + if (buf->pool) + pci_pool_free(buf->pool, buf->safe, buf->safe_dma_addr); + else + pci_free_consistent(SA1111_FAKE_PCIDEV, buf->size, buf->safe, + buf->safe_dma_addr); + kfree(buf); - if (0) printk("free_safe_buffer(%p) index %d\n", - buf, index); + MOD_DEC_USE_COUNT; +} - if (index < 0 || index >= MAX_SAFE) { - printk(__FILE__ ": free_safe_buffer() corrupt buffer\n"); - return; - } +static inline int +dma_range_is_safe(dma_addr_t addr, size_t size) +{ + unsigned int physaddr = SA1111_DMA_ADDR((unsigned int) addr); - dma = safe_buffers[index][0]; - safe_buffers[index][0] = 0; + /* Any address within one megabyte of the start of the target + * bank will be OK. This is an overly conservative test: + * other addresses can be OK depending on the dram + * configuration. (See sa1111.c:sa1111_check_dma_bug() * for + * details.) + * + * We take care to ensure the entire dma region is within + * the safe range. + */ - pci_pool_free(pool, buf, (u32)dma); + return ((physaddr + size - 1) < (1<<20)); } /* - NOTE: - replace pci_map/unmap_single with local routines which will - do buffer copies if buffer is above 1mb... -*/ - -/* * see if a buffer address is in an 'unsafe' range. if it is * allocate a 'safe' buffer and copy the unsafe buffer into it. * substitute the safe buffer for the unsafe one. * (basically move the buffer from an unsafe area to a safe one) - * - * we assume calls to map_single are symmetric with calls to unmap_single... */ dma_addr_t -sa1111_map_single(struct pci_dev *hwdev, void *virtptr, - size_t size, int direction) +sa1111_map_single(void *ptr, size_t size, int direction) { - dma_addr_t busptr; + unsigned long flags; + dma_addr_t dma_addr; - mapped_alloc_size += size; + DPRINTK("%s(ptr=%p,size=%d,dir=%x)\n", + __func__, ptr, size, direction); - if (0) printk("pci_map_single(hwdev=%p,ptr=%p,size=%d,dir=%x) " - "alloced=%ld\n", - hwdev, virtptr, size, direction, mapped_alloc_size); + BUG_ON(direction == PCI_DMA_NONE); - busptr = virt_to_bus(virtptr); + local_irq_save(flags); - /* we assume here that a buffer will never be >=64k */ - if ( (((unsigned long)busptr) & 0x100000) || - ((((unsigned long)busptr)+size) & 0x100000) ) - { - char *safe; + dma_addr = virt_to_bus(ptr); - safe = alloc_safe_buffer(virtptr, size, &busptr); - if (safe == 0) { - printk("unable to map unsafe buffer %p!\n", virtptr); + if (!dma_range_is_safe(dma_addr, size)) { + struct safe_buffer *buf; + + buf = alloc_safe_buffer(ptr, size, direction); + if (buf == 0) { + printk(KERN_ERR + "%s: unable to map unsafe buffer %p!\n", + __func__, ptr); + local_irq_restore(flags); return 0; } - if (0) printk("unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", - virtptr, (void *)virt_to_bus(virtptr), - safe, (void *)busptr); - - memcpy(safe, virtptr, size); - consistent_sync(safe, size, direction); + DPRINTK("%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", + __func__, + buf->ptr, (void *) virt_to_bus(buf->ptr), + buf->safe, (void *) buf->safe_dma_addr); + + if ((direction == PCI_DMA_TODEVICE) || + (direction == PCI_DMA_BIDIRECTIONAL)) { + DPRINTK("%s: copy out from unsafe %p, to safe %p, size %d\n", + __func__, ptr, buf->safe, size); + memcpy(buf->safe, ptr, size); + } + consistent_sync(buf->safe, size, direction); - return busptr; + dma_addr = buf->safe_dma_addr; + } else { + consistent_sync(ptr, size, direction); } - consistent_sync(virtptr, size, direction); - return busptr; + local_irq_restore(flags); + return dma_addr; } /* - * see if a mapped address was really a "safe" buffer and if so, - * copy the data from the safe buffer back to the unsafe buffer - * and free up the safe buffer. - * (basically return things back to the way they should be) + * see if a mapped address was really a "safe" buffer and if so, copy + * the data from the safe buffer back to the unsafe buffer and free up + * the safe buffer. (basically return things back to the way they + * should be) */ + void -sa1111_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, - size_t size, int direction) +sa1111_unmap_single(dma_addr_t dma_addr, size_t size, int direction) { - char *safe, *unsafe; - void *buf; + unsigned long flags; + struct safe_buffer *buf; - /* hack; usb-ohci.c never sends hwdev==NULL, all others do */ - if (hwdev == NULL) { - return; + DPRINTK("%s(ptr=%p,size=%d,dir=%x)\n", + __func__, (void *) dma_addr, size, direction); + + BUG_ON(direction == PCI_DMA_NONE); + + local_irq_save(flags); + + buf = find_safe_buffer(dma_addr); + if (buf) { + BUG_ON(buf->size != size); + BUG_ON(buf->direction != direction); + + DPRINTK("%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", + __func__, + buf->ptr, (void *) virt_to_bus(buf->ptr), + buf->safe, (void *) buf->safe_dma_addr); + + if ((direction == PCI_DMA_FROMDEVICE) || + (direction == PCI_DMA_BIDIRECTIONAL)) { + DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n", + __func__, buf->safe, buf->ptr, size); + memcpy(buf->ptr, buf->safe, size); + } + free_safe_buffer(buf); } - mapped_alloc_size -= size; + local_irq_restore(flags); +} + +int +sa1111_map_sg(struct scatterlist *sg, int nents, int direction) +{ + BUG(); /* Not implemented. */ + + return -1; +} + +void +sa1111_unmap_sg(struct scatterlist *sg, int nents, int direction) +{ + BUG(); /* Not implemented. */ +} + +void +sa1111_dma_sync_single(dma_addr_t dma_addr, size_t size, int direction) +{ + unsigned long flags; + struct safe_buffer *buf; + + DPRINTK("%s(ptr=%p,size=%d,dir=%x)\n", + __func__, (void *) dma_addr, size, direction); - if (0) printk("pci_unmap_single(hwdev=%p,ptr=%p,size=%d,dir=%x) " - "alloced=%ld\n", - hwdev, (void *)dma_addr, size, direction, - mapped_alloc_size); - - if ((safe = find_safe_buffer((void *)dma_addr, &unsafe))) { - if (0) printk("copyback unsafe %p, safe %p, size %d\n", - unsafe, safe, size); - - consistent_sync(safe, size, PCI_DMA_FROMDEVICE); - memcpy(unsafe, safe, size); - free_safe_buffer(safe); + local_irq_save(flags); + + buf = find_safe_buffer(dma_addr); + if (buf) { + BUG_ON(buf->size != size); + BUG_ON(buf->direction != direction); + + DPRINTK("%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", + __func__, + buf->ptr, (void *) virt_to_bus(buf->ptr), + buf->safe, (void *) buf->safe_dma_addr); + + switch (direction) { + case PCI_DMA_FROMDEVICE: + DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n", + __func__, buf->safe, buf->ptr, size); + memcpy(buf->ptr, buf->safe, size); + break; + case PCI_DMA_TODEVICE: + DPRINTK("%s: copy out from unsafe %p, to safe %p, size %d\n", + __func__,buf->ptr, buf->safe, size); + memcpy(buf->safe, buf->ptr, size); + break; + case PCI_DMA_BIDIRECTIONAL: + BUG(); /* is this allowed? what does it mean? */ + default: + BUG(); + } + consistent_sync(buf->safe, size, direction); } else { - /* assume this is normal memory */ - buf = bus_to_virt(dma_addr); - consistent_sync(buf, size, PCI_DMA_FROMDEVICE); + consistent_sync(bus_to_virt(dma_addr), size, direction); } + + local_irq_restore(flags); +} + +void +sa1111_dma_sync_sg(struct scatterlist *sg, int nelems, int direction) +{ + BUG(); /* Not implemented. */ } EXPORT_SYMBOL(sa1111_map_single); EXPORT_SYMBOL(sa1111_unmap_single); +EXPORT_SYMBOL(sa1111_map_sg); +EXPORT_SYMBOL(sa1111_unmap_sg); +EXPORT_SYMBOL(sa1111_dma_sync_single); +EXPORT_SYMBOL(sa1111_dma_sync_sg); -static int __init sa1111_init_safe_buffers(void) +/* **************************************** */ + +static int __init sa1111_pcibuf_init(void) { - printk("Initializing SA1111 buffer pool for DMA workaround\n"); - init_safe_buffers(NULL); - return 0; + int ret; + + printk(KERN_DEBUG + "sa1111_pcibuf: initializing SA-1111 DMA workaround\n"); + + ret = create_safe_buffer_pools(); + + return ret; } +module_init(sa1111_pcibuf_init); -static void free_safe_buffers(void) +static void __exit sa1111_pcibuf_exit(void) { - pci_pool_destroy(small_buffer_cache); - pci_pool_destroy(large_buffer_cache); + BUG_ON(!list_empty(&safe_buffers)); + + destroy_safe_buffer_pools(); } +module_exit(sa1111_pcibuf_exit); -module_init(sa1111_init_safe_buffers); -module_exit(free_safe_buffers); +MODULE_AUTHOR("Christopher Hoover "); +MODULE_DESCRIPTION("Special pci_{map/unmap/dma_sync}_* routines for SA-1111."); +MODULE_LICENSE("GPL"); diff -urN orig/arch/arm/mach-sa1100/sa1111.c linux/arch/arm/mach-sa1100/sa1111.c --- orig/arch/arm/mach-sa1100/sa1111.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-sa1100/sa1111.c Thu Feb 6 11:31:52 2003 @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include diff -urN orig/arch/arm/mach-sa1100/simputer.c linux/arch/arm/mach-sa1100/simputer.c --- orig/arch/arm/mach-sa1100/simputer.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/simputer.c Mon Aug 5 23:10:38 2002 @@ -0,0 +1,78 @@ +/* + * linux/arch/arm/mach-sa1100/simputer.c + * + * Author: Vivek K S (modified from Nicolas Pitre's Assabet file) + * + * This file contains all Simputer-specific tweaks. + * + * 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 "generic.h" + +static void __init +fixup_simputer(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ +} + + +static struct map_desc simputer_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */ + { 0xf2800000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Simputer Modem */ + { 0xf3800000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* USB */ + LAST_DESC +}; + +static void __init simputer_map_io(void) +{ + sa1100_map_io(); + iotable_init(simputer_io_desc); + + sa1100_register_uart(1, 2); + sa1100_register_uart(0, 1); /* com port */ + sa1100_register_uart(2, 3); /* radio module */ + + /* + * Set up registers for sleep mode. + */ + PWER = PWER_GPIO0; + PGSR = 0; + PCFR = 0; + + /* + * Clear all possible wakeup reasons. + */ + RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR; +} + + +MACHINE_START(SIMPUTER, "Picopeta-Simputer") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) + FIXUP(fixup_simputer) + MAPIO(simputer_map_io) + INITIRQ(sa1100_init_irq) +MACHINE_END diff -urN orig/arch/arm/mach-sa1100/sleep.S linux/arch/arm/mach-sa1100/sleep.S --- orig/arch/arm/mach-sa1100/sleep.S Fri Nov 16 10:09:48 2001 +++ linux/arch/arm/mach-sa1100/sleep.S Sun Jun 29 16:55:53 2003 @@ -11,12 +11,17 @@ * 2001-02-06: Cliff Brake Initial code * * 2001-08-29: Nicolas Pitre Simplified. + * + * 2002-05-27: Nicolas Pitre Revisited, more cleanup and simplification. + * Storage is on the stack now. */ #include #include #include -#include "sleep.h" + + + .text /* * sa1100_cpu_suspend() @@ -25,35 +30,25 @@ * */ - .text - -ENTRY(sleep_save) .word 0 @ virtual address of parameter array -ENTRY(sleep_save_p) .word 0 @ physical address of parameter array - ENTRY(sa1100_cpu_suspend) - @ save registers on stack - stmfd sp!, {r4 - r12, lr} - - @ load virtual address for sleep_save array - ldr r4, sleep_save + stmfd sp!, {r4 - r12, lr} @ save registers on stack - @ save stack pointer - str sp, [r4, #(SLEEP_SAVE_SP*4)] - - @ save coprocessor registers - mrc p15, 0, r1, c1, c0, 0 - str r1, [r4, #(SLEEP_SAVE_CP15_R1*4)] - mrc p15, 0, r1, c2, c0, 0 - str r1, [r4, #(SLEEP_SAVE_CP15_R2*4)] - mrc p15, 0, r1, c3, c0, 0 - str r1, [r4, #(SLEEP_SAVE_CP15_R3*4)] - mrc p15, 0, r1, c5, c0, 0 - str r1, [r4, #(SLEEP_SAVE_CP15_R5*4)] - mrc p15, 0, r1, c6, c0, 0 - str r1, [r4, #(SLEEP_SAVE_CP15_R6*4)] - mrc p15, 0, r1, c13, c0, 0 - str r1, [r4, #(SLEEP_SAVE_CP15_R13*4)] + @ get coprocessor registers + mrc p15, 0, r4, c3, c0, 0 @ domain ID + mrc p15, 0, r5, c2, c0, 0 @ translation table base addr + mrc p15, 0, r6, c13, c0, 0 @ PID + mrc p15, 0, r7, c1, c0, 0 @ control reg + + @ store them plus current virtual stack ptr on stack + mov r8, sp + stmfd sp!, {r4 - r8} + + @ preserve phys address of stack + mov r0, sp + bl sleep_phys_sp + ldr r1, =sleep_save_sp + str r0, [r1] @ clean data cache and invalidate WB bl cpu_sa1100_cache_clean_invalidate_all @@ -72,32 +67,31 @@ @ delay 90us and set CPU PLL to lowest speed @ fixes resume problem on high speed SA1110 mov r0, #90 - bl SYMBOL_NAME(udelay) + bl SYMBOL_NAME(__udelay) ldr r0, =PPCR mov r1, #0 str r1, [r0] mov r0, #90 - bl SYMBOL_NAME(udelay) + bl SYMBOL_NAME(__udelay) - -/* setup up register contents for jump to page containing SA1110 SDRAM controller bug fix suspend code - * - * r0 points to MSC0 register - * r1 points to MSC1 register - * r2 points to MSC2 register - * r3 is MSC0 value - * r4 is MSC1 value - * r5 is MSC2 value - * r6 points to MDREFR register - * r7 is first MDREFR value - * r8 is second MDREFR value - * r9 is pointer to MDCNFG register - * r10 is MDCNFG value - * r11 is third MDREFR value - * r12 is pointer to PMCR register - * r13 is PMCR value (1) - * - */ + /* + * SA1110 SDRAM controller workaround. register values: + * + * r0 = &MSC0 + * r1 = &MSC1 + * r2 = &MSC2 + * r3 = MSC0 value + * r4 = MSC1 value + * r5 = MSC2 value + * r6 = &MDREFR + * r7 = first MDREFR value + * r8 = second MDREFR value + * r9 = &MDCNFG + * r10 = MDCNFG value + * r11 = third MDREFR value + * r12 = &PMCR + * r13 = PMCR value (1) + */ ldr r0, =MSC0 ldr r1, =MSC1 @@ -170,69 +164,49 @@ * * entry point from bootloader into kernel during resume * + * Note: Yes, part of the following code is located into the .data section. + * This is to allow sleep_save_sp to be accessed with a relative load + * while we can't rely on any MMU translation. We could have put + * sleep_save_sp in the .text section as well, but some setups might + * insist on .text to be truely read-only. */ + .data .align 5 ENTRY(sa1100_cpu_resume) - - @ set SVC, irqs off - mov r0, #I_BIT | MODE_SVC + mov r0, #I_BIT | F_BIT | MODE_SVC @ set SVC, irqs off msr cpsr_c, r0 - @ load physical address of sleep_save - ldr r4, sleep_save_p - - @ restore cp15_r3, domain id - ldr r1, [r4, #(SLEEP_SAVE_CP15_R3*4)] - mcr p15, 0, r1, c3, c0 ,0 - - @ restore cp15_r2, translation table base address - ldr r1, [r4, #(SLEEP_SAVE_CP15_R2*4)] - mcr p15, 0, r1, c2, c0 ,0 + ldr r0, sleep_save_sp @ stack phys addr + ldr r2, =resume_after_mmu @ its absolute virtual address + ldmfd r0, {r4 - r7, sp} @ CP regs + virt stack ptr mov r1, #0 mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache + mcr p15, 0, r1, c9, c0, 0 @ invalidate RB + mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB - @ get saved cp15 r1 (control register) - ldr r1, [r4, #(SLEEP_SAVE_CP15_R1*4)] - - @ get address to jump to after turning on MMU - ldr r2, =resume_after_mmu - - cmp r2, #0 - - b resume_turn_on_mmu + mcr p15, 0, r4, c3, c0, 0 @ domain ID + mcr p15, 0, r5, c2, c0, 0 @ translation table base addr + mcr p15, 0, r6, c13, c0, 0 @ PID + b resume_turn_on_mmu @ cache align execution .align 5 resume_turn_on_mmu: - - @ turn on mmu - mcr p15, 0, r1, c1, c0 ,0 - - @ jump to resume_after_mmu - mov pc, r2 + mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, caches, etc. + nop + mov pc, r2 @ jump to virtual addr + nop nop nop - .align 5 -resume_after_mmu: - - @ load virtual address for sleep_save array - ldr r4, sleep_save - - @ restore the rest of CPU state - ldr r1, [r4, #(SLEEP_SAVE_CP15_R13*4)] - mcr p15, 0, r1, c13, c0, 0 - ldr r1, [r4, #(SLEEP_SAVE_CP15_R5*4)] - mcr p15, 0, r1, c5, c0 ,0 - ldr r1, [r4, #(SLEEP_SAVE_CP15_R6*4)] - mcr p15, 0, r1, c6, c0 ,0 - - @ restore stack pointer - ldr sp, [r4, #(SLEEP_SAVE_SP*4)] +sleep_save_sp: + .word 0 @ preserve stack phys ptr here - @ return to caller - ldmfd sp!, {r4 - r12, pc} + .text +resume_after_mmu: + mcr p15, 0, r1, c15, c1, 2 @ enable clock switching + ldmfd sp!, {r4 - r12, pc} @ return to caller diff -urN orig/arch/arm/mach-sa1100/sleep.h linux/arch/arm/mach-sa1100/sleep.h --- orig/arch/arm/mach-sa1100/sleep.h Fri Nov 16 10:09:48 2001 +++ linux/arch/arm/mach-sa1100/sleep.h Thu Jan 1 01:00:00 1970 @@ -1,30 +0,0 @@ -/* - * Offsets for register values preserved in RAM while in sleep mode - */ - -#define SLEEP_SAVE_OSCR 0 -#define SLEEP_SAVE_OSMR0 1 -#define SLEEP_SAVE_OSMR1 2 -#define SLEEP_SAVE_OSMR2 3 -#define SLEEP_SAVE_OSMR3 4 -#define SLEEP_SAVE_OIER 5 -#define SLEEP_SAVE_GPDR 6 -#define SLEEP_SAVE_GRER 7 -#define SLEEP_SAVE_GFER 8 -#define SLEEP_SAVE_GAFR 9 -#define SLEEP_SAVE_PPDR 10 -#define SLEEP_SAVE_PPSR 11 -#define SLEEP_SAVE_PPAR 12 -#define SLEEP_SAVE_PSDR 13 -#define SLEEP_SAVE_Ser1SDCR0 14 -#define SLEEP_SAVE_ICMR 15 -#define SLEEP_SAVE_SP 16 -#define SLEEP_SAVE_CP15_R1 17 -#define SLEEP_SAVE_CP15_R2 18 -#define SLEEP_SAVE_CP15_R3 19 -#define SLEEP_SAVE_CP15_R5 20 -#define SLEEP_SAVE_CP15_R6 21 -#define SLEEP_SAVE_CP15_R13 22 - -#define SLEEP_SAVE_SIZE 23 - diff -urN orig/arch/arm/mach-sa1100/ssp.c linux/arch/arm/mach-sa1100/ssp.c --- orig/arch/arm/mach-sa1100/ssp.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/ssp.c Wed Feb 12 13:10:07 2003 @@ -0,0 +1,208 @@ +/* + * linux/arch/arm/mach-sa1100/ssp.c + * + * Copyright (C) 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. + * + * Generic SSP driver. This provides the generic core for simple + * IO-based SSP applications. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static void ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int status = Ser4SSSR; + + if (status & SSSR_ROR) { + printk(KERN_WARNING "SSP: receiver overrun\n"); + } + + Ser4SSSR = SSSR_ROR; +} + +/** + * ssp_write_word - write a word to the SSP port + * @data: 16-bit, MSB justified data to write. + * + * Wait for a free entry in the SSP transmit FIFO, and write a data + * word to the SSP port. + * + * The caller is expected to perform the necessary locking. + * + * Returns: + * %-ETIMEDOUT timeout occurred (for future) + * 0 success + */ +int ssp_write_word(u16 data) +{ + while (!(Ser4SSSR & SSSR_TNF)) + cpu_relax(); + + Ser4SSDR = data; + + return 0; +} + +/** + * ssp_read_word - read a word from the SSP port + * + * Wait for a data word in the SSP receive FIFO, and return the + * received data. Data is LSB justified. + * + * Note: Currently, if data is not expected to be received, this + * function will wait for ever. + * + * The caller is expected to perform the necessary locking. + * + * Returns: + * %-ETIMEDOUT timeout occurred (for future) + * 16-bit data success + */ +int ssp_read_word(void) +{ + while (!(Ser4SSSR & SSSR_RNE)) + cpu_relax(); + + return Ser4SSDR; +} + +/** + * ssp_flush - flush the transmit and receive FIFOs + * + * Wait for the SSP to idle, and ensure that the receive FIFO + * is empty. + * + * The caller is expected to perform the necessary locking. + */ +void ssp_flush(void) +{ + do { + while (Ser4SSSR & SSSR_RNE) { + (void) Ser4SSDR; + } + } while (Ser4SSSR & SSSR_BSY); +} + +/** + * ssp_enable - enable the SSP port + * + * Turn on the SSP port. + */ +void ssp_enable(void) +{ + Ser4SSCR0 |= SSCR0_SSE; +} + +/** + * ssp_disable - shut down the SSP port + * + * Turn off the SSP port, optionally powering it down. + */ +void ssp_disable(void) +{ + Ser4SSCR0 &= ~SSCR0_SSE; +} + +/** + * ssp_save_state - save the SSP configuration + * @ssp: pointer to structure to save SSP configuration + * + * Save the configured SSP state for suspend. + */ +void ssp_save_state(struct ssp_state *ssp) +{ + ssp->cr0 = Ser4SSCR0; + ssp->cr1 = Ser4SSCR1; + + Ser4SSCR0 &= ~SSCR0_SSE; +} + +/** + * ssp_restore_state - restore a previously saved SSP configuration + * @ssp: pointer to configuration saved by ssp_save_state + * + * Restore the SSP configuration saved previously by ssp_save_state. + */ +void ssp_restore_state(struct ssp_state *ssp) +{ + Ser4SSSR = SSSR_ROR; + + Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE; + Ser4SSCR1 = ssp->cr1; + Ser4SSCR0 = ssp->cr0; +} + +/** + * ssp_init - setup the SSP port + * + * initialise and claim resources for the SSP port. + * + * Returns: + * %-ENODEV if the SSP port is unavailable + * %-EBUSY if the resources are already in use + * %0 on success + */ +int ssp_init(void) +{ + int ret; + + if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE)) + return -ENODEV; + + if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) { + return -EBUSY; + } + + Ser4SSSR = SSSR_ROR; + + ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL); + if (ret) + goto out_region; + + return 0; + + out_region: + release_mem_region(__PREG(Ser4SSCR0), 0x18); + return ret; +} + +/** + * ssp_exit - undo the effects of ssp_init + * + * release and free resources for the SSP port. + */ +void ssp_exit(void) +{ + Ser4SSCR0 &= ~SSCR0_SSE; + + free_irq(IRQ_Ser4SSP, NULL); + release_mem_region(__PREG(Ser4SSCR0), 0x18); +} + +MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("SA11x0 SSP PIO driver"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(ssp_write_word); +EXPORT_SYMBOL(ssp_read_word); +EXPORT_SYMBOL(ssp_flush); +EXPORT_SYMBOL(ssp_enable); +EXPORT_SYMBOL(ssp_disable); +EXPORT_SYMBOL(ssp_save_state); +EXPORT_SYMBOL(ssp_restore_state); +EXPORT_SYMBOL(ssp_init); +EXPORT_SYMBOL(ssp_exit); diff -urN orig/arch/arm/mach-sa1100/system3.c linux/arch/arm/mach-sa1100/system3.c --- orig/arch/arm/mach-sa1100/system3.c Tue Jun 24 13:57:43 2003 +++ linux/arch/arm/mach-sa1100/system3.c Thu Feb 6 11:33:12 2003 @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include diff -urN orig/arch/arm/mach-sa1100/usb-char.c linux/arch/arm/mach-sa1100/usb-char.c --- orig/arch/arm/mach-sa1100/usb-char.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb-char.c Wed Feb 27 11:38:38 2002 @@ -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 -urN orig/arch/arm/mach-sa1100/usb-char.h linux/arch/arm/mach-sa1100/usb-char.h --- orig/arch/arm/mach-sa1100/usb-char.h Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb-char.h Tue Oct 16 20:02:24 2001 @@ -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 -urN orig/arch/arm/mach-sa1100/usb-eth.c linux/arch/arm/mach-sa1100/usb-eth.c --- orig/arch/arm/mach-sa1100/usb-eth.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb-eth.c Fri Sep 6 10:53:22 2002 @@ -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 -urN orig/arch/arm/mach-sa1100/usb_ctl.c linux/arch/arm/mach-sa1100/usb_ctl.c --- orig/arch/arm/mach-sa1100/usb_ctl.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb_ctl.c Tue Feb 5 20:32:51 2002 @@ -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 -urN orig/arch/arm/mach-sa1100/usb_ctl.h linux/arch/arm/mach-sa1100/usb_ctl.h --- orig/arch/arm/mach-sa1100/usb_ctl.h Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb_ctl.h Tue Oct 16 20:02:24 2001 @@ -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 -urN orig/arch/arm/mach-sa1100/usb_ep0.c linux/arch/arm/mach-sa1100/usb_ep0.c --- orig/arch/arm/mach-sa1100/usb_ep0.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb_ep0.c Tue Oct 16 20:02:24 2001 @@ -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 -urN orig/arch/arm/mach-sa1100/usb_recv.c linux/arch/arm/mach-sa1100/usb_recv.c --- orig/arch/arm/mach-sa1100/usb_recv.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb_recv.c Tue Oct 16 20:02:24 2001 @@ -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 -urN orig/arch/arm/mach-sa1100/usb_send.c linux/arch/arm/mach-sa1100/usb_send.c --- orig/arch/arm/mach-sa1100/usb_send.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mach-sa1100/usb_send.c Tue Oct 16 20:02:24 2001 @@ -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 -urN orig/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile --- orig/arch/arm/mm/Makefile Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/Makefile Thu Dec 12 22:40:17 2002 @@ -36,8 +36,10 @@ p-$(CONFIG_CPU_ARM720T) += proc-arm720.o p-$(CONFIG_CPU_ARM920T) += proc-arm920.o p-$(CONFIG_CPU_ARM922T) += proc-arm922.o +p-$(CONFIG_CPU_ARM925T) += proc-arm925.o p-$(CONFIG_CPU_ARM926T) += proc-arm926.o p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o +p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o p-$(CONFIG_CPU_SA110) += proc-sa110.o p-$(CONFIG_CPU_SA1100) += proc-sa110.o diff -urN orig/arch/arm/mm/alignment.c linux/arch/arm/mm/alignment.c --- orig/arch/arm/mm/alignment.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/alignment.c Wed Jul 16 18:44:24 2003 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -19,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -30,9 +28,7 @@ #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 @@ -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 { @@ -426,13 +397,13 @@ eaddr += 4; /* - * For alignment faults on the ARM922T the MMU makes + * 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 ARM922, otherwise + * Switch this message off if we've got a ARM92[02], otherwise * [ls]dm alignment faults are noisy! */ -#if !(defined CONFIG_CPU_ARM922T) +#if !(defined CONFIG_CPU_ARM922T) && !(defined CONFIG_CPU_ARM920T) /* * This is a "hint" - we already have eaddr worked out by the * processor for us. @@ -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 -urN orig/arch/arm/mm/consistent.c linux/arch/arm/mm/consistent.c --- orig/arch/arm/mm/consistent.c Wed Jul 4 19:53:31 2001 +++ linux/arch/arm/mm/consistent.c Thu Dec 12 22:33:33 2002 @@ -30,14 +30,20 @@ * now, we expressly forbid it, especially as some of the stuff we do * here is not interrupt context safe. * + * We should allow this function to be called from interrupt context. + * However, we call ioremap, which needs to fiddle around with various + * things (like the vmlist_lock, and allocating page tables). These + * things aren't interrupt safe (yet). + * * Note that this does *not* zero the allocated area! */ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) { struct page *page, *end, *free; unsigned long order; - void *ret, *virt; + void *ret; + /* FIXME */ if (in_interrupt()) BUG(); @@ -48,22 +54,22 @@ if (!page) goto no_page; - /* - * We could do with a page_to_phys and page_to_bus here. - */ - virt = page_address(page); - *dma_handle = virt_to_bus(virt); - ret = __ioremap(virt_to_phys(virt), size, 0); + *dma_handle = page_to_bus(page); + ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, 0); if (!ret) goto no_remap; #if 0 /* ioremap_does_flush_cache_all */ - /* - * we need to ensure that there are no cachelines in use, or - * worse dirty in this area. Really, we don't need to do - * this since __ioremap does a flush_cache_all() anyway. --rmk - */ - invalidate_dcache_range(virt, virt + size); + { + void *virt = page_address(page); + + /* + * we need to ensure that there are no cachelines in use, or + * worse dirty in this area. Really, we don't need to do + * this since __ioremap does a flush_cache_all() anyway. --rmk + */ + invalidate_dcache_range(virt, virt + size); + } #endif /* @@ -72,7 +78,6 @@ * We also mark the pages in use as reserved so that * remap_page_range works. */ - page = virt_to_page(virt); free = page + (size >> PAGE_SHIFT); end = page + (1 << order); @@ -93,18 +98,15 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handle) { - void *__ret; - int __gfp = GFP_KERNEL; + int gfp = GFP_KERNEL; -#ifdef CONFIG_PCI - if ((hwdev) == NULL || +#if defined(CONFIG_PCI) || defined(CONFIG_SA1111) + if ((hwdev) == NULL || dev_is_sa1111(hwdev) || (hwdev)->dma_mask != 0xffffffff) #endif - __gfp |= GFP_DMA; + gfp |= GFP_DMA; - __ret = consistent_alloc(__gfp, (size), - (handle)); - return __ret; + return consistent_alloc(gfp, size, handle); } /* @@ -114,19 +116,16 @@ void consistent_free(void *vaddr, size_t size, dma_addr_t handle) { struct page *page, *end; - void *virt; if (in_interrupt()) BUG(); - virt = bus_to_virt(handle); - /* * More messing around with the MM internals. This is * sick, but then so is remap_page_range(). */ size = PAGE_ALIGN(size); - page = virt_to_page(virt); + page = virt_to_page(bus_to_virt(handle)); end = page + (size >> PAGE_SHIFT); for (; page < end; page++) diff -urN orig/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c --- orig/arch/arm/mm/fault-armv.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/fault-armv.c Wed Jul 16 16:10:17 2003 @@ -2,117 +2,89 @@ * 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 -extern void die_if_kernel(const char *str, struct pt_regs *regs, int err); -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", @@ -132,21 +104,22 @@ * 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; @@ -162,22 +135,25 @@ pte_val(entry) &= ~L_PTE_CACHEABLE; 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; @@ -211,14 +187,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); } /* @@ -236,14 +215,20 @@ */ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) { - struct page *page = pte_page(pte); + unsigned long pfn = pte_pfn(pte); + struct page *page; + + if (!pfn_valid(pfn)) + return; + page = pfn_to_page(pfn); + if (page->mapping) { + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); - if (VALID_PAGE(page) && page->mapping) { - if (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); } } diff -urN orig/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c --- orig/arch/arm/mm/fault-common.c Wed Jun 18 13:01:05 2003 +++ linux/arch/arm/mm/fault-common.c Wed Jul 16 18:47:40 2003 @@ -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,61 +30,85 @@ #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 -NORET_TYPE void die(const char *msg, struct pt_regs *regs, int err) ATTRIB_NORET; - /* * This is useful to dump out the page tables associated with * 'addr' in mm 'mm'. */ void show_pte(struct mm_struct *mm, unsigned long addr) { - pgd_t *pgd; + mm_segment_t fs; if (!mm) mm = &init_mm; - printk(KERN_ALERT "pgd = %p\n", mm->pgd); - pgd = pgd_offset(mm, addr); - printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd)); + fs = get_fs(); + set_fs(get_ds()); do { - pmd_t *pmd; - pte_t *pte; + pgd_t pg, *pgd; + pmd_t pm, *pmd; + pte_t pt, *pte; + + printk(KERN_ALERT "pgd = %p\n", mm->pgd); + pgd = pgd_offset(mm, addr); + printk(KERN_ALERT "[%08lx] *pgd=", addr); - if (pgd_none(*pgd)) + if (__get_user(pgd_val(pg), (unsigned long *)pgd)) { + printk("(faulted)"); break; + } + + printk("%08lx", pgd_val(pg)); - if (pgd_bad(*pgd)) { + if (pgd_none(pg)) + break; + + if (pgd_bad(pg)) { printk("(bad)"); break; } pmd = pmd_offset(pgd, addr); - printk(", *pmd = %08lx", pmd_val(*pmd)); - if (pmd_none(*pmd)) + printk(", *pmd = "); + + if (__get_user(pmd_val(pm), (unsigned long *)pmd)) { + printk("(faulted)"); break; + } + + printk("%08lx", pmd_val(pm)); - if (pmd_bad(*pmd)) { + if (pmd_none(pm)) + break; + + if (pmd_bad(pm)) { printk("(bad)"); break; } pte = pte_offset(pmd, addr); - printk(", *pte = %08lx", pte_val(*pte)); + + printk(", *pte = "); + + if (__get_user(pte_val(pt), (unsigned long *)pte)) { + printk("(faulted)"); + break; + } + + printk("%08lx", pte_val(pt)); #ifdef CONFIG_CPU_32 printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE])); #endif } while(0); + set_fs(fs); printk("\n"); } @@ -97,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; @@ -123,7 +143,7 @@ "paging request", addr); show_pte(mm, addr); - die("Oops", regs, error_code); + die("Oops", regs, fsr); do_exit(SIGKILL); } @@ -132,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; @@ -156,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; @@ -187,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; @@ -202,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 @@ -235,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; @@ -252,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); /* @@ -283,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; @@ -298,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 @@ -311,7 +331,7 @@ return 0; no_context: - __do_kernel_fault(mm, addr, error_code, regs); + __do_kernel_fault(mm, addr, fsr, regs); return 0; } @@ -332,19 +352,24 @@ * 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; @@ -367,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 -urN orig/arch/arm/mm/fault.h linux/arch/arm/mm/fault.h --- orig/arch/arm/mm/fault.h Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mm/fault.h Wed Jul 16 16:11:23 2003 @@ -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 -urN orig/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- orig/arch/arm/mm/init.c Fri Oct 26 16:45:58 2001 +++ linux/arch/arm/mm/init.c Wed Jul 16 16:23:25 2003 @@ -1,7 +1,7 @@ /* * linux/arch/arm/mm/init.c * - * Copyright (C) 1995-2000 Russell King + * Copyright (C) 1995-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,7 +9,6 @@ */ #include #include -#include #include #include #include @@ -18,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -46,11 +44,13 @@ #define TABLE_OFFSET 0 #endif -#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *)) +#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(pte_t)) static unsigned long totalram_pages; extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern char _stext, _text, _etext, _end, __init_begin, __init_end; +extern unsigned long phys_initrd_start; +extern unsigned long phys_initrd_size; /* * The sole use of this is to pass memory configuration @@ -292,6 +292,7 @@ * also get rid of some of the stuff above as well. */ max_low_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET); +// max_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET); mi->end = memend_pfn << PAGE_SHIFT; return bootmem_pages; @@ -302,16 +303,16 @@ int initrd_node = -2; #ifdef CONFIG_BLK_DEV_INITRD + unsigned long end = phys_initrd_start + phys_initrd_size; + /* * Make sure that the initrd is within a valid area of * memory. */ - if (initrd_start) { - unsigned long phys_initrd_start, phys_initrd_end; + if (phys_initrd_size) { unsigned int i; - phys_initrd_start = __pa(initrd_start); - phys_initrd_end = __pa(initrd_end); + initrd_node = -1; for (i = 0; i < mi->nr_banks; i++) { unsigned long bank_end; @@ -319,7 +320,7 @@ bank_end = mi->bank[i].start + mi->bank[i].size; if (mi->bank[i].start <= phys_initrd_start && - phys_initrd_end <= bank_end) + end <= bank_end) initrd_node = mi->bank[i].node; } } @@ -327,8 +328,8 @@ if (initrd_node == -1) { printk(KERN_ERR "initrd (0x%08lx - 0x%08lx) extends beyond " "physical memory - disabling initrd\n", - initrd_start, initrd_end); - initrd_start = initrd_end = 0; + phys_initrd_start, end); + phys_initrd_start = phys_initrd_size = 0; } #endif @@ -354,7 +355,7 @@ * and can only be in node 0. */ reserve_bootmem_node(pgdat, __pa(swapper_pg_dir), - PTRS_PER_PGD * sizeof(void *)); + PTRS_PER_PGD * sizeof(pgd_t)); #endif /* * And don't forget to reserve the allocator bitmap, @@ -378,7 +379,7 @@ */ if (machine_is_archimedes() || machine_is_a5k()) reserve_bootmem_node(pgdat, 0x02000000, 0x00080000); - if (machine_is_edb7211()) + if (machine_is_edb7211() || machine_is_fortunet()) reserve_bootmem_node(pgdat, 0xc0000000, 0x00020000); if (machine_is_p720t()) reserve_bootmem_node(pgdat, PHYS_OFFSET, 0x00014000); @@ -469,9 +470,12 @@ #ifdef CONFIG_BLK_DEV_INITRD - if (initrd_node >= 0) - reserve_bootmem_node(NODE_DATA(initrd_node), __pa(initrd_start), - initrd_end - initrd_start); + if (phys_initrd_size && initrd_node >= 0) { + reserve_bootmem_node(NODE_DATA(initrd_node), phys_initrd_start, + phys_initrd_size); + initrd_start = __phys_to_virt(phys_initrd_start); + initrd_end = initrd_start + phys_initrd_size; + } #endif if (map_pg != bootmap_pfn + bootmap_pages) @@ -501,6 +505,7 @@ memtable_init(mi); if (mdesc->map_io) mdesc->map_io(); + flush_cache_all(); flush_tlb_all(); /* @@ -583,7 +588,7 @@ } if (size && s) - printk("Freeing %s memory: %dK\n", s, size); + printk(KERN_INFO "Freeing %s memory: %dK\n", s, size); } /* diff -urN orig/arch/arm/mm/ioremap.c linux/arch/arm/mm/ioremap.c --- orig/arch/arm/mm/ioremap.c Sat Apr 28 11:24:54 2001 +++ linux/arch/arm/mm/ioremap.c Fri Sep 6 11:25:14 2002 @@ -8,24 +8,19 @@ * Hacked for ARM by Phil Blundell * Hacked to allow all architectures to build, and various cleanups * by Russell King - */ - -/* + * * This allows a driver to remap an arbitrary region of bus memory into * virtual space. One should *only* use readl, writel, memcpy_toio and * so on with such remapped areas. * - * Because the ARM only has a 32-bit address space we can't address the - * whole of the (physical) PCI space at once. PCI huge-mode addressing - * allows us to circumvent this restriction by splitting PCI space into - * two 2GB chunks and mapping only one at a time into processor memory. - * We use MMU protection domains to trap any attempt to access the bank - * that is not currently mapped. (This isn't fully implemented yet.) - * - * DC21285 currently has a bug in that the PCI address extension - * register affects the address of any writes waiting in the outbound - * FIFO. Unfortunately, it is not possible to tell the DC21285 to - * flush this - flushing the area causes the bus to lock. + * ioremap support tweaked to allow support for large page mappings. We + * have several issues that needs to be resolved first however: + * + * 1. We need set_pte, or something like set_pte to understand large + * page mappings. + * + * 2. we need the unmap_* functions to likewise understand large page + * mappings. */ #include #include @@ -35,8 +30,9 @@ #include #include -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, pgprot_t pgprot) +static inline void +remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, + unsigned long pfn, pgprot_t pgprot) { unsigned long end; @@ -44,22 +40,26 @@ end = address + size; if (end > PMD_SIZE) end = PMD_SIZE; - if (address >= end) - BUG(); + BUG_ON(address >= end); do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, mk_pte_phys(phys_addr, pgprot)); + if (!pte_none(*pte)) + goto bad; + + set_pte(pte, pfn_pte(pfn, pgprot)); address += PAGE_SIZE; - phys_addr += PAGE_SIZE; + pfn++; pte++; } while (address && (address < end)); + return; + + bad: + printk("remap_area_pte: page already exists\n"); + BUG(); } -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline int +remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, + unsigned long pfn, unsigned long flags) { unsigned long end; pgprot_t pgprot; @@ -70,34 +70,33 @@ if (end > PGDIR_SIZE) end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); + pfn -= address >> PAGE_SHIFT; + BUG_ON(address >= end); pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags); do { pte_t * pte = pte_alloc(&init_mm, pmd, address); if (!pte) return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, pgprot); + remap_area_pte(pte, address, end - address, pfn + (address >> PAGE_SHIFT), pgprot); address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address && (address < end)); return 0; } -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) +static int +remap_area_pages(unsigned long address, unsigned long pfn, + unsigned long size, unsigned long flags) { int error; pgd_t * dir; unsigned long end = address + size; - phys_addr -= address; + pfn -= address >> PAGE_SHIFT; dir = pgd_offset(&init_mm, address); flush_cache_all(); - if (address >= end) - BUG(); + BUG_ON(address >= end); spin_lock(&init_mm.page_table_lock); do { pmd_t *pmd; @@ -106,7 +105,7 @@ if (!pmd) break; if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) + pfn + (address >> PAGE_SHIFT), flags)) break; error = 0; address = (address + PGDIR_SIZE) & PGDIR_MASK; @@ -154,7 +153,7 @@ if (!area) return NULL; addr = area->addr; - if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) { + if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr >> PAGE_SHIFT, size, flags)) { vfree(addr); return NULL; } diff -urN orig/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c --- orig/arch/arm/mm/mm-armv.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/mm-armv.c Wed Jul 16 16:25:32 2003 @@ -9,7 +9,6 @@ * * Page table sludge for ARM v3 and v4 processor architectures. */ -#include #include #include #include @@ -200,7 +199,7 @@ } ptep = pte_offset(pmdp, virt); - set_pte(ptep, mk_pte_phys(phys, __pgprot(prot))); + set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, __pgprot(prot))); } /* @@ -390,6 +389,7 @@ create_mapping(init_maps); flush_cache_all(); + flush_tlb_all(); } /* diff -urN orig/arch/arm/mm/mm-riscstation.c linux/arch/arm/mm/mm-riscstation.c --- orig/arch/arm/mm/mm-riscstation.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mm/mm-riscstation.c Sun Sep 15 20:18:44 2002 @@ -0,0 +1,35 @@ +/* + * linux/arch/arm/mm/mm-rpc.c + * linux/arch/arm/mm/mm-riscstation.c + * + * Copyright (C) 1998-1999 Russell King + * Copyright (C) 2002 Simtec Electronics / Ben Dooks + * + * 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. + * + * Extra MM routines for RiscStation + */ +#include +#include + +#include +#include +#include +#include + +#include + +/* map the EASI space to use for the ISA slot */ + +static struct map_desc riscstation_io_desc[] __initdata = { + { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, /* IO space */ + { EASI_BASE, EASI_START, EASI_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* EASI space */ + LAST_DESC +}; + +void __init riscstation_map_io(void) +{ + iotable_init(riscstation_io_desc); +} diff -urN orig/arch/arm/mm/proc-arm1020.S linux/arch/arm/mm/proc-arm1020.S --- orig/arch/arm/mm/proc-arm1020.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/proc-arm1020.S Wed Jul 16 19:01:02 2003 @@ -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 /* @@ -135,7 +138,7 @@ .align 5 ENTRY(cpu_arm1020_do_idle) mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -156,7 +159,7 @@ ENTRY(cpu_arm1020_cache_clean_invalidate_all) mov r2, #1 cpu_arm1020_cache_clean_invalidate_all_r2: -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, ip, c7, c10, 4 mov r1, #0xf @ 16 segments @@ -165,23 +168,23 @@ orr ip, ip, r1, LSL #5 @ shift in/up index mcr p15, 0, ip, c7, c14, 2 @ Clean & Inval DCache entry mcr p15, 0, ip, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov ip, ip #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 -#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE teq r2, #0 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache #endif mcr p15, 0, ip, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov ip, ip mov ip, ip #endif @@ -201,27 +204,27 @@ 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 -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry mcr p15, 0, r3, c7, c10, 4 @ drain WB add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry mcr p15, 0, r3, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 #endif add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b #endif -#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE teq r2, #0 movne r0, #0 mcrne p15, 0, r0, c7, c5, 0 @ invalidate I cache -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -238,14 +241,14 @@ .align 5 ENTRY(cpu_arm1020_flush_ram_page) mcr p15, 0, r1, c7, c10, 4 -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE mov r1, #PAGESIZE 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -254,7 +257,7 @@ mov r0, #0 #endif -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -275,14 +278,14 @@ */ .align 5 ENTRY(cpu_arm1020_dcache_invalidate_range) -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE /* D cache are on */ tst r0, #DCACHELINESIZE - 1 bic r0, r0, #DCACHELINESIZE - 1 mcrne p15, 0, r0, c7, c10, 4 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start mcrne p15, 0, r0, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -290,23 +293,23 @@ mcrne p15, 0, r1, c7, c10, 4 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end mcrne p15, 0, r1, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r1, r1 mov r1, r1 mov r1, r1 #endif 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 #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 -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -328,23 +331,23 @@ 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 -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry mcr p15, 0, r3, c7, c10, 4 @ drain WB add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry mcr p15, 0, r3, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 #endif add r0, r0, #DCACHELINESIZE cmp r0, r1 - blt 1b + blo 1b #endif -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -367,23 +370,23 @@ ENTRY(cpu_arm1020_dcache_clean_page) mov r1, #PAGESIZE mcr p15, 0, r0, c7, c10, 4 -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) mcr p15, 0, r0, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 #endif add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 #endif add r0, r0, #DCACHELINESIZE subs r1, r1, #2 * DCACHELINESIZE bhi 1b #endif -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -401,14 +404,14 @@ ENTRY(cpu_arm1020_dcache_clean_entry) mov r1, #0 mcr p15, 0, r1, c7, c10, 4 -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, r0, c7, c10, 1 @ clean single D entry mcr p15, 0, r1, c7, c10, 4 @ drain WB #endif -#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE mcr p15, 0, r1, c7, c5, 1 @ invalidate I entry #endif -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r1, r1 mov r1, r1 #endif @@ -427,14 +430,14 @@ .align 5 ENTRY(cpu_arm1020_icache_invalidate_range) 1: mcr p15, 0, r0, c7, c10, 4 -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, r0, c7, c10, 1 @ Clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c10, 1 @ Clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB #endif -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 #endif add r0, r0, #DCACHELINESIZE @@ -442,7 +445,7 @@ blo 1b ENTRY(cpu_arm1020_icache_invalidate_page) mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -460,7 +463,7 @@ mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain WB mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -476,16 +479,19 @@ */ .align 5 ENTRY(cpu_arm1020_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE + bhi cpu_arm1020_tlb_invalidate_all mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB 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 -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 #endif cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -500,14 +506,14 @@ ENTRY(cpu_arm1020_tlb_invalidate_page) mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif 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 -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -524,7 +530,7 @@ */ .align 5 ENTRY(cpu_arm1020_set_pgd) -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, r3, c7, c10, 4 mov r1, #0xF @ 16 segments 1: mov r3, #0x3F @ 64 entries @@ -533,25 +539,25 @@ mcr p15, 0, ip, c7, c14, 2 @ Clean & Inval DCache entry mov ip, #0 mcr p15, 0, ip, c7, c10, 4 -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov ip, ip #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 -#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache #endif mcr p15, 0, r1, c7, c10, 4 @ drain WB mcr p15, 0, r0, c2, c0, 0 @ load page table pointer mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov ip, ip mov ip, ip #endif @@ -568,18 +574,18 @@ */ .align 5 ENTRY(cpu_arm1020_set_pmd) -#ifdef CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH +#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_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, r0, c7, c10, 4 mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif @@ -600,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? @@ -609,47 +615,42 @@ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young? movne r2, #0 -#ifdef CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH eor r3, r1, #0x0a @ C & small page? tst r3, #0x0b biceq r2, r2, #4 #endif str r2, [r0] @ hardware version mov r0, r0 -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, r0, c7, c10, 4 mcr p15, 0, r0, c7, c10, 1 @ clean D entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE mov r0, r0 mov r0, r0 #endif mov pc, lr -cpu_manu_name: - .asciz "ARM/VLSI" ENTRY(cpu_arm1020_name) .ascii "Arm1020" -#if defined(CONFIG_CPU_ARM1020_CPU_IDLE) - .ascii "s" -#endif -#if defined(CONFIG_CPU_ARM1020_I_CACHE_ON) +#ifndef CONFIG_CPU_ICACHE_DISABLE .ascii "i" #endif -#if defined(CONFIG_CPU_ARM1020_D_CACHE_ON) +#ifndef CONFIG_CPU_DCACHE_DISABLE .ascii "d" -#if defined(CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH .ascii "(wt)" #else .ascii "(wb)" #endif #endif -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE .ascii "B" #endif -#ifdef CONFIG_CPU_ARM1020_ROUND_ROBIN +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN .ascii "RR" #endif .ascii "\0" @@ -679,16 +680,16 @@ orr r0, r0, #0x0031 @ ..........DP...M orr r0, r0, #0x0100 @ .......S........ -#ifdef CONFIG_CPU_ARM1020_ROUND_ROBIN +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .R.............. #endif -#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION +#ifndef CONFIG_CPU_BPREDICT_DISABLE orr r0, r0, #0x0800 @ ....Z........... #endif -#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE orr r0, r0, #0x0004 @ Enable D cache #endif -#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE orr r0, r0, #0x1000 @ I Cache on #endif mov pc, lr @@ -736,7 +737,7 @@ .type cpu_arm1020_info, #object cpu_arm1020_info: - .long cpu_manu_name + .long 0 .long cpu_arm1020_name .size cpu_arm1020_info, . - cpu_arm1020_info @@ -761,7 +762,7 @@ b __arm1020_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB .long cpu_arm1020_info .long arm1020_processor_functions .size __arm1020_proc_info, . - __arm1020_proc_info diff -urN orig/arch/arm/mm/proc-arm1026.S linux/arch/arm/mm/proc-arm1026.S --- orig/arch/arm/mm/proc-arm1026.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mm/proc-arm1026.S Wed Jul 16 15:50:57 2003 @@ -0,0 +1,662 @@ +/* + * linux/arch/arm/mm/arm1026.S: MMU functions for ARM1026EJ-S + * + * Copyright (C) 2002 ARM Limited + * Copyright (C) 2002 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 arm1026. + */ +#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 PAGESIZE 4096 + + .text + +/* + * cpu_arm1026_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. + * + * Inputs: + * r2 = address of abort + * r3 = cpsr of abort + * + * Returns: + * r0 = address of abort + * r1 = FSR, bit 11 set if writing + * r3 = corrupted + * r4 = corrupted + */ + .align 5 +ENTRY(cpu_arm1026_data_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR + bic r1, r1, #1 << 11 | 1 << 10 + and r2, r1, #0b1101 @ Check for translation error + teq r1, r2, #0b1101 + orrne r1, r1, #1 << 11 @ set write bit + + and r3, r3, #255 + mrc p15, 0, r0, c6, c0, 0 @ get FAR + + mov pc, lr + +/* + * cpu_arm1026_check_bugs() + */ +ENTRY(cpu_arm1026_check_bugs) + mrs ip, cpsr + bic ip, ip, #F_BIT + msr cpsr, ip + mov pc, lr + +/* + * cpu_arm1026_proc_init() + */ +ENTRY(cpu_arm1026_proc_init) + mov pc, lr + +/* + * cpu_arm1026_proc_fin() + */ +ENTRY(cpu_arm1026_proc_fin) + stmfd sp!, {lr} + mov ip, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, ip + bl cpu_arm1026_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_arm1026_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_arm1026_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_arm1026_do_idle() + */ + .align 5 +ENTRY(cpu_arm1026_do_idle) + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt + mov pc, lr + +/* ================================= CACHE ================================ */ + + +/* + * cpu_arm1026_cache_clean_invalidate_all() + * + * clean and invalidate all cache lines + * + * Note: + * 1. we should preserve r0 at all times + */ + .align 5 +ENTRY(cpu_arm1026_cache_clean_invalidate_all) + mov r2, #1 +cpu_arm1026_cache_clean_invalidate_all_r2: + mov ip, #0 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else +1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate + bne 1b +#endif + teq r2, #0 + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1026_cache_clean_invalidate_range(start, end, flags) + * + * clean and invalidate all cache lines associated with this area of memory + * + * 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 consistant. 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 flushing the Icache over that region + * start: Area start address + * end: Area end address + * flags: nonzero for I cache as well + */ + .align 5 +ENTRY(cpu_arm1026_cache_clean_invalidate_range) + bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bhi cpu_arm1026_cache_clean_invalidate_all_r2 + +1: teq r2, #0 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE +#else + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE +#endif + + cmp r0, r1 + blo 1b + + mcr p15, 0, r1, c7, c10, 4 @ drain WB + + mov pc, lr + +/* + * cpu_arm1026_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_arm1026_flush_ram_page) + mov r1, #PAGESIZE +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #DCACHELINESIZE +#else +1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + add r0, r0, #DCACHELINESIZE +#endif + subs r1, r1, #2 * DCACHELINESIZE + bne 1b + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ D-CACHE =============================== */ + +/* + * cpu_arm1026_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_arm1026_dcache_invalidate_range) +#ifndef CONFIG_CPU_ARM1026_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 + bic r0, r0, #DCACHELINESIZE - 1 +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + blo 1b + mov pc, lr + +/* + * cpu_arm1026_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_arm1026_dcache_clean_range) +#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH + bic r0, r0, #DCACHELINESIZE - 1 + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + mov r2, #0 + bhi cpu_arm1026_cache_clean_invalidate_all_r2 + +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + blo 1b +#endif + mcr p15, 0, r2, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1026_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: + * 1. we don't need to flush the write buffer in this case. + * 2. 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_arm1026_dcache_clean_page) +#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH + mov r1, #PAGESIZE +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + subs r1, r1, #2 * DCACHELINESIZE + bne 1b +#endif + mov pc, lr + +/* + * cpu_arm1026_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_arm1026_dcache_clean_entry) +#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ I-CACHE =============================== */ + +/* + * cpu_arm1026_icache_invalidate_range(start, end) + * + * This *is not* just icache. It is to make data written to memory + * consistent such that instructions fetched from the region are what + * we expect. + * + * This is typically used after we have copied a module into kernel space, + * and we're about to start executing code from that module. + * + * start: virtual start address + * end: virtual end address + */ + .align 5 +ENTRY(cpu_arm1026_icache_invalidate_range) + bic r0, r0, #DCACHELINESIZE - 1 @ Safety check + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bhi cpu_arm1026_cache_clean_invalidate_all_r2 + +1: mcr p15, 0, r0, c7, c5, 1 @ clean I entries + add r0, r0, #DCACHELINESIZE + cmp r0, r1 + blo 1b + + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +ENTRY(cpu_arm1026_icache_invalidate_page) + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mov pc, lr + + +/* ================================== TLB ================================= */ + +/* + * cpu_arm1026_tlb_invalidate_all() + * + * Invalidate all TLB entries + */ + .align 5 +ENTRY(cpu_arm1026_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_arm1026_tlb_invalidate_range(start, end) + * + * invalidate TLB entries covering the specified range + * + * start: range start address + * end: range end address + */ + .align 5 +ENTRY(cpu_arm1026_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE @ arbitary, should be tuned + bhi cpu_arm1026_tlb_invalidate_all + + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + + bic r0, r0, #(PAGESIZE - 1) & 0x00ff + bic r0, r0, #(PAGESIZE - 1) & 0xff00 + +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 + blo 1b + mov pc, lr + +/* + * cpu_arm1026_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_arm1026_tlb_invalidate_page) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + 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_arm1026_set_pgd(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_arm1026_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' +1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate + bne 1b +#endif + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mov pc, lr + +/* + * cpu_arm1026_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_arm1026_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] +#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm1026_set_pte(ptep, pte) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_arm1026_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 & small page? + tst r3, #0x0b + biceq r2, r2, #4 +#endif + str r2, [r0] @ hardware version + mov r0, r0 +#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 + mov pc, lr + + +ENTRY(cpu_arm1026_name) + .ascii "ARM1026EJ-S" +#ifndef CONFIG_CPU_ICACHE_DISABLE + .ascii "i" +#endif +#ifndef CONFIG_CPU_DCACHE_DISABLE + .ascii "d" +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + .ascii "(wt)" +#else + .ascii "(wb)" +#endif +#ifndef CONFIG_CPU_BPREDICT_DISABLE + .ascii "B" +#endif +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + .ascii "RR" +#endif +#endif + .ascii "\0" + .align + + .section ".text.init", #alloc, #execinstr + +__arm1026_setup: + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 + mcr p15, 0, r4, c2, c0 @ load page table pointer + + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mov r0, #4 @ disable write-back on caches explicitly + mcr p15, 7, r0, c15, c0, 0 +#endif + + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mrc p15, 0, r0, c1, c0 @ get control register v4 +/* + * Clear out 'unwanted' bits (then put them in if we need them) + */ + @ VI ZFRS BLDP WCAM + bic r0, r0, #0x0e00 + bic r0, r0, #0x0002 + bic r0, r0, #0x000c + bic r0, r0, #0x1000 @ ...0 000. .... 000. +/* + * Turn on what we want + */ + orr r0, r0, #0x0031 + orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 + +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + orr r0, r0, #0x4000 @ .1.. .... .... .... +#endif +#ifndef CONFIG_CPU_BPREDICT_DISABLE + orr r0, r0, #0x0800 @ ....Z........... +#endif +#ifndef CONFIG_CPU_DCACHE_DISABLE + orr r0, r0, #0x0004 @ .... .... .... .1.. +#endif +#ifndef CONFIG_CPU_ICACHE_DISABLE + orr r0, r0, #0x1000 @ ...1 .... .... .... +#endif + mov pc, lr + + .text + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type arm1026_processor_functions, #object +arm1026_processor_functions: + .word cpu_arm1026_data_abort + .word cpu_arm1026_check_bugs + .word cpu_arm1026_proc_init + .word cpu_arm1026_proc_fin + .word cpu_arm1026_reset + .word cpu_arm1026_do_idle + + /* cache */ + .word cpu_arm1026_cache_clean_invalidate_all + .word cpu_arm1026_cache_clean_invalidate_range + .word cpu_arm1026_flush_ram_page + + /* dcache */ + .word cpu_arm1026_dcache_invalidate_range + .word cpu_arm1026_dcache_clean_range + .word cpu_arm1026_dcache_clean_page + .word cpu_arm1026_dcache_clean_entry + + /* icache */ + .word cpu_arm1026_icache_invalidate_range + .word cpu_arm1026_icache_invalidate_page + + /* tlb */ + .word cpu_arm1026_tlb_invalidate_all + .word cpu_arm1026_tlb_invalidate_range + .word cpu_arm1026_tlb_invalidate_page + + /* pgtable */ + .word cpu_arm1026_set_pgd + .word cpu_arm1026_set_pmd + .word cpu_arm1026_set_pte + .size arm1026_processor_functions, . - arm1026_processor_functions + + .type cpu_arm1026_info, #object +cpu_arm1026_info: + .long 0 + .long cpu_arm1026_name + .size cpu_arm1026_info, . - cpu_arm1026_info + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv5EJ" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v5EJ" + .size cpu_elf_name, . - cpu_elf_name + .align + + .section ".proc.info", #alloc, #execinstr + + .type __arm1026_proc_info,#object +__arm1026_proc_info: + .long 0x4100a260 + .long 0xff00fff0 + .long 0x00000c1e @ mmuflags + b __arm1026_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \ + HWCAP_FAST_MULT + .long cpu_arm1026_info + .long arm1026_processor_functions + .size __arm1026_proc_info, . - __arm1026_proc_info diff -urN orig/arch/arm/mm/proc-arm2,3.S linux/arch/arm/mm/proc-arm2,3.S --- orig/arch/arm/mm/proc-arm2,3.S Sat Mar 31 23:47:15 2001 +++ linux/arch/arm/mm/proc-arm2,3.S Thu Jan 23 20:40:31 2003 @@ -275,7 +275,6 @@ _arm2_3_check_bugs: bics pc, lr, #0x04000000 @ Clear FIQ disable bit -armvlsi_name: .asciz "ARM/VLSI" _arm2_name: .asciz "ARM 2" _arm250_name: .asciz "ARM 250" _arm3_name: .asciz "ARM 3" @@ -295,7 +294,7 @@ .word _arm2_xchg_4 cpu_arm2_info: - .long armvlsi_name + .long 0 .long _arm2_name .globl SYMBOL_NAME(arm250_processor_functions) @@ -308,7 +307,7 @@ .word _arm3_xchg_4 cpu_arm250_info: - .long armvlsi_name + .long 0 .long _arm250_name .globl SYMBOL_NAME(arm3_processor_functions) @@ -321,7 +320,7 @@ .word _arm3_xchg_4 cpu_arm3_info: - .long armvlsi_name + .long 0 .long _arm3_name arm2_arch_name: .asciz "armv1" diff -urN orig/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S --- orig/arch/arm/mm/proc-arm6,7.S Mon Sep 3 14:14:41 2001 +++ linux/arch/arm/mm/proc-arm6,7.S Wed Jul 16 18:59:54 2003 @@ -68,12 +68,26 @@ * Purpose : flush a TLB entry */ ENTRY(cpu_arm6_tlb_invalidate_range) -ENTRY(cpu_arm7_tlb_invalidate_range) -1: mcr p15, 0, r0, c6, c0, 0 @ flush TLB + @ arm 6 tbl purge reg is bits 12 - 31 +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) +#if defined(CONFIG_ARCH_RISCSTATION) + mov r0, #0 + mcr p15, 0, r0, c5, c0, 0 @ flush TLB + mov pc, lr +#else + @ arm 7 tbl purge reg is bits 14 - 31 +1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB + add r0, r0, #0x4000 + cmp r0, r1 + blo 1b mov pc, lr +#endif /* * Function: arm6_7_tlb_invalidate_page (unsigned long address, int flags) @@ -96,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 @@ -130,20 +142,20 @@ 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 b Ldata_unknown - b Ldata_unknown + b Ldata_simple @ swp b Ldata_unknown b Ldata_unknown b Ldata_lateldrpostconst @ ldr rd, [rn], #m @@ -160,7 +172,7 @@ Ldata_unknown: @ Part of jumptable mov r0, r2 mov r1, r4 - mov r2, r3 + mov r2, r5 bl baddataabort b ret_from_exception @@ -258,7 +270,6 @@ ENTRY(cpu_arm6_do_idle) ENTRY(cpu_arm7_do_idle) - mov r0, #-EINVAL mov pc, lr /* @@ -323,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? @@ -349,8 +360,6 @@ mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc mov pc, r0 -cpu_armvlsi_name: - .asciz "ARM/VLSI" cpu_arm6_name: .asciz "ARM 6" cpu_arm610_name: .asciz "ARM 610" @@ -461,25 +470,25 @@ .type cpu_arm6_info, #object cpu_arm6_info: - .long cpu_armvlsi_name + .long 0 .long cpu_arm6_name .size cpu_arm6_info, . - cpu_arm6_info .type cpu_arm610_info, #object cpu_arm610_info: - .long cpu_armvlsi_name + .long 0 .long cpu_arm610_name .size cpu_arm610_info, . - cpu_Arm610_info .type cpu_arm7_info, #object cpu_arm7_info: - .long cpu_armvlsi_name + .long 0 .long cpu_arm7_name .size cpu_arm7_info, . - cpu_arm7_info .type cpu_arm710_info, #object cpu_arm710_info: - .long cpu_armvlsi_name + .long 0 .long cpu_arm710_name .size cpu_arm710_info, . - cpu_arm710_info diff -urN orig/arch/arm/mm/proc-arm720.S linux/arch/arm/mm/proc-arm720.S --- orig/arch/arm/mm/proc-arm720.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/proc-arm720.S Wed Jul 16 19:00:09 2003 @@ -37,6 +37,11 @@ #include /* + * and the page size + */ +#define PAGESIZE 4096 + +/* * Function: arm720_cache_clean_invalidate_all (void) * : arm720_cache_clean_invalidate_page (unsigned long address, int size, * int flags) @@ -86,10 +91,13 @@ * Purpose : flush a TLB entry */ ENTRY(cpu_arm720_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE @ arbitary, should be tuned + bhi cpu_arm720_tlb_invalidate_all 1: mcr p15, 0, r0, c8, c7, 1 @ flush TLB (v4) - add r0, r0, #4096 + add r0, r0, #PAGESIZE cmp r0, r1 - blt 1b + blo 1b mov pc, lr /* @@ -116,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 */ @@ -142,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 and r2, r4, #15 << 24 add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine movs pc, lr @@ -263,8 +271,8 @@ .data_thumb_abort: ldrh r4, [r0] @ read instruction - tst r4, r4, lsr #12 @ C = bit 11 - sbc r1, r1, r1 @ r1 = C - 1 + tst r4, #1 << 11 + orrne r4, r4, #1 << 20 and r2, r4, #15 << 12 add pc, pc, r2, lsr #10 @ lookup in table nop @@ -410,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? @@ -438,8 +446,6 @@ mov pc, r0 -cpu_armvlsi_name: - .asciz "ARM" cpu_arm720_name: .asciz "ARM720T" .align @@ -500,7 +506,7 @@ .type cpu_arm720_info, #object cpu_arm720_info: - .long cpu_armvlsi_name + .long 0 .long cpu_arm720_name .size cpu_arm720_info, . - cpu_arm720_info @@ -527,7 +533,7 @@ b __arm720_setup @ cpu_flush .long cpu_arch_name @ arch_name .long cpu_elf_name @ elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_26BIT @ elf_hwcap + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB @ elf_hwcap .long cpu_arm720_info @ info .long arm720_processor_functions .size __arm720_proc_info, . - __arm720_proc_info diff -urN orig/arch/arm/mm/proc-arm920.S linux/arch/arm/mm/proc-arm920.S --- orig/arch/arm/mm/proc-arm920.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/proc-arm920.S Wed Jul 16 18:56:43 2003 @@ -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 /* @@ -134,9 +138,7 @@ */ .align 5 ENTRY(cpu_arm920_do_idle) -#if defined(CONFIG_CPU_ARM920_CPU_IDLE) mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt -#endif mov pc, lr /* ================================= CACHE ================================ */ @@ -155,7 +157,7 @@ mov r2, #1 cpu_arm920_cache_clean_invalidate_all_r2: mov ip, #0 -#ifdef CONFIG_CPU_ARM920_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else /* @@ -191,9 +193,9 @@ 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_ARM920_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry add r0, r0, #DCACHELINESIZE @@ -209,7 +211,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 @@ -224,7 +226,7 @@ .align 5 ENTRY(cpu_arm920_flush_ram_page) mov r1, #PAGESIZE -#ifdef CONFIG_CPU_ARM920_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry @@ -266,7 +268,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 /* @@ -286,7 +288,7 @@ sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE mov r2, #0 - bgt cpu_arm920_cache_clean_invalidate_all_r2 + bhi cpu_arm920_cache_clean_invalidate_all_r2 bic r1, r1, #DCACHELINESIZE -1 add r1, r1, #DCACHELINESIZE @@ -367,7 +369,7 @@ bic r0, r0, #ICACHELINESIZE - 1 @ Safety check sub r1, r1, r0 cmp r1, #MAX_AREA_SIZE - bgt cpu_arm920_cache_clean_invalidate_all_r2 + bhi cpu_arm920_cache_clean_invalidate_all_r2 bic r1, r1, #ICACHELINESIZE - 1 add r1, r1, #ICACHELINESIZE @@ -410,6 +412,10 @@ */ .align 5 ENTRY(cpu_arm920_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE @ arbitary, should be tuned + bhi cpu_arm920_tlb_invalidate_all + mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB @@ -422,7 +428,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 /* @@ -454,8 +460,7 @@ .align 5 ENTRY(cpu_arm920_set_pgd) mov ip, #0 -#ifdef CONFIG_CPU_ARM920_WRITETHROUGH - /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */ +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else @ && 'Clean & Invalidate whole DCache' @@ -487,7 +492,7 @@ */ .align 5 ENTRY(cpu_arm920_set_pmd) -#ifdef CONFIG_CPU_ARM920_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH eor r2, r1, #0x0a @ C & Section tst r2, #0x0b biceq r1, r1, #4 @ clear bufferable bit @@ -512,7 +517,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 or Exec? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -521,7 +526,7 @@ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young? movne r2, #0 -#ifdef CONFIG_CPU_ARM920_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH eor r3, r2, #0x0a @ C & small page? tst r3, #0x0b biceq r2, r2, #4 @@ -533,19 +538,14 @@ mov pc, lr -cpu_manu_name: - .asciz "ARM/CIRRUS" ENTRY(cpu_arm920_name) .ascii "Arm920T" -#if defined(CONFIG_CPU_ARM920_CPU_IDLE) - .ascii "s" -#endif -#if defined(CONFIG_CPU_ARM920_I_CACHE_ON) +#ifndef CONFIG_CPU_ICACHE_DISABLE .ascii "i" #endif -#if defined(CONFIG_CPU_ARM920_D_CACHE_ON) +#ifndef CONFIG_CPU_DCACHE_DISABLE .ascii "d" -#if defined(CONFIG_CPU_ARM920_WRITETHROUGH) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH .ascii "(wt)" #else .ascii "(wb)" @@ -579,10 +579,10 @@ orr r0, r0, #0x0031 orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 -#ifdef CONFIG_CPU_ARM920_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE orr r0, r0, #0x0004 @ .... .... .... .1.. #endif -#ifdef CONFIG_CPU_ARM920_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE orr r0, r0, #0x1000 @ ...1 .... .... .... #endif mov pc, lr @@ -630,7 +630,7 @@ .type cpu_arm920_info, #object cpu_arm920_info: - .long cpu_manu_name + .long 0 .long cpu_arm920_name .size cpu_arm920_info, . - cpu_arm920_info @@ -655,7 +655,7 @@ b __arm920_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB .long cpu_arm920_info .long arm920_processor_functions .size __arm920_proc_info, . - __arm920_proc_info diff -urN orig/arch/arm/mm/proc-arm922.S linux/arch/arm/mm/proc-arm922.S --- orig/arch/arm/mm/proc-arm922.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/proc-arm922.S Wed Jul 16 19:01:24 2003 @@ -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 /* @@ -130,9 +133,7 @@ */ .align 5 ENTRY(cpu_arm922_do_idle) -#if defined(CONFIG_CPU_ARM922_CPU_IDLE) mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt -#endif mov pc, lr /* ================================= CACHE ================================ */ @@ -151,7 +152,7 @@ mov r2, #1 cpu_arm922_cache_clean_invalidate_all_r2: mov ip, #0 -#ifdef CONFIG_CPU_ARM922_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else /* @@ -187,9 +188,9 @@ 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_ARM922_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry add r0, r0, #DCACHELINESIZE @@ -205,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 @@ -220,7 +221,7 @@ .align 5 ENTRY(cpu_arm922_flush_ram_page) mov r1, #PAGESIZE -#ifdef CONFIG_CPU_ARM922_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry @@ -262,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 /* @@ -282,7 +283,7 @@ 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 @@ -363,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 @@ -406,6 +407,10 @@ */ .align 5 ENTRY(cpu_arm922_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE @ arbitary, should be tuned + bhi cpu_arm922_tlb_invalidate_all + mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB @@ -418,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 /* @@ -450,7 +455,7 @@ .align 5 ENTRY(cpu_arm922_set_pgd) mov ip, #0 -#ifdef CONFIG_CPU_ARM922_WRITETHROUGH +#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 @@ -483,7 +488,7 @@ */ .align 5 ENTRY(cpu_arm922_set_pmd) -#ifdef CONFIG_CPU_ARM922_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH eor r2, r1, #0x0a @ C & Section tst r2, #0x0b biceq r1, r1, #4 @ clear bufferable bit @@ -508,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? @@ -517,7 +522,7 @@ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young? movne r2, #0 -#ifdef CONFIG_CPU_ARM922_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH eor r3, r2, #0x0a @ C & small page? tst r3, #0x0b biceq r2, r2, #4 @@ -529,19 +534,14 @@ mov pc, lr -cpu_manu_name: - .asciz "ARM/ALTERA" ENTRY(cpu_arm922_name) .ascii "Arm922T" -#if defined(CONFIG_CPU_ARM922_CPU_IDLE) - .ascii "s" -#endif -#if defined(CONFIG_CPU_ARM922_I_CACHE_ON) +#ifndef CONFIG_CPU_ICACHE_DISABLE .ascii "i" #endif -#if defined(CONFIG_CPU_ARM922_D_CACHE_ON) +#ifndef CONFIG_CPU_DCACHE_DISABLE .ascii "d" -#if defined(CONFIG_CPU_ARM922_WRITETHROUGH) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH .ascii "(wt)" #else .ascii "(wb)" @@ -575,10 +575,10 @@ orr r0, r0, #0x0031 orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 -#ifdef CONFIG_CPU_ARM922_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE orr r0, r0, #0x0004 @ .... .... .... .1.. #endif -#ifdef CONFIG_CPU_ARM922_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE orr r0, r0, #0x1000 @ ...1 .... .... .... #endif mov pc, lr @@ -626,7 +626,7 @@ .type cpu_arm922_info, #object cpu_arm922_info: - .long cpu_manu_name + .long 0 .long cpu_arm922_name .size cpu_arm922_info, . - cpu_arm922_info @@ -651,7 +651,7 @@ b __arm922_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB .long cpu_arm922_info .long arm922_processor_functions .size __arm922_proc_info, . - __arm922_proc_info diff -urN orig/arch/arm/mm/proc-arm925.S linux/arch/arm/mm/proc-arm925.S --- orig/arch/arm/mm/proc-arm925.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/mm/proc-arm925.S Wed Jul 16 19:01:42 2003 @@ -0,0 +1,732 @@ +/* + * linux/arch/arm/mm/arm925.S: MMU functions for ARM925 + * + * Copyright (C) 1999-2001 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * Copyright (C) 2002 RidgeRun, Inc. + * Copyright (C) 2002 MontaVista Software, Inc. + * + * 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 arm925. + */ +#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 (2 * 1024) + +/* + * the cache line size of the I and D cache + */ +#define DCACHELINESIZE 16 +#define ICACHELINESIZE 16 + +/* + * and the page size + */ +#define PAGESIZE 4096 + + .text + +/* + * cpu_arm925_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. + * + * Inputs: + * r2 = address of abort + * r3 = cpsr of abort + * + * Returns: + * r0 = address of abort + * 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 + 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 + +/* + * cpu_arm925_check_bugs() + */ +ENTRY(cpu_arm925_check_bugs) + mrs ip, cpsr + bic ip, ip, #F_BIT + msr cpsr, ip + mov pc, lr + +/* + * cpu_arm925_proc_init() + */ +ENTRY(cpu_arm925_proc_init) + mov pc, lr + +/* + * cpu_arm925_proc_fin() + */ +ENTRY(cpu_arm925_proc_fin) + stmfd sp!, {lr} + mov ip, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, ip + bl cpu_arm925_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_arm925_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_arm925_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_arm925_do_idle() + */ + .align 5 +ENTRY(cpu_arm925_do_idle) +#if defined(CONFIG_CPU_ARM925_CPU_IDLE) + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt +#endif + mov pc, lr + +/* ================================= CACHE ================================ */ + + +/* + * cpu_arm925_cache_clean_invalidate_all() + * + * clean and invalidate all cache lines + * + * Note: + * 1. we should preserve r0 at all times + */ + .align 5 +ENTRY(cpu_arm925_cache_clean_invalidate_all) + mov r2, #1 +cpu_arm925_cache_clean_invalidate_all_r2: + mov ip, #0 +#ifdef CONFIG_CPU_ARM925_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else +/* + * 'Clean & Invalidate whole DCache' + * Re-written to use Index Ops. + * NOTE: Requires TI925T Configuration Register C bit <- 0 + * for clean and invalidate of both D-Cache sets. + */ + mov r3, #255 << 4 @ 256 entries/set + @ ((NSETS - 1) << (CIR[13-12] + 3)) +2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index + subs r3, r3, #1 << 4 + bcs 2b @ entries 255 to 0 +#endif + teq r2, #0 + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm925_cache_clean_invalidate_range(start, end, flags) + * + * clean and invalidate all cache lines associated with this area of memory + * + * 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 consistant. 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 flushing the Icache over that region + * start: Area start address + * end: Area end address + * flags: nonzero for I cache as well + */ + .align 5 +ENTRY(cpu_arm925_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 + 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 + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE +#else + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #DCACHELINESIZE +#endif + cmp r0, r1 + blo 1b + + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm925_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_arm925_flush_ram_page) + mov r1, #PAGESIZE +#ifdef CONFIG_CPU_ARM925_WRITETHROUGH +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #DCACHELINESIZE +#else +1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + add r0, r0, #DCACHELINESIZE +#endif + subs r1, r1, #2 * DCACHELINESIZE + bne 1b + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ D-CACHE =============================== */ + +/* + * cpu_arm925_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_arm925_dcache_invalidate_range) +#ifndef CONFIG_CPU_ARM925_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 + 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 + blo 1b + mov pc, lr + +/* + * cpu_arm925_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_arm925_dcache_clean_range) +#ifndef CONFIG_CPU_ARM925_WRITETHROUGH + bic r0, r0, #DCACHELINESIZE - 1 + sub r1, r1, r0 + cmp r1, #MAX_AREA_SIZE + mov r2, #0 + bhi cpu_arm925_cache_clean_invalidate_all_r2 + + bic r1, r1, #DCACHELINESIZE -1 + add r1, r1, #DCACHELINESIZE + +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + subs r1, r1, #DCACHELINESIZE + bpl 1b +#endif + mcr p15, 0, r2, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm925_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: + * 1. we don't need to flush the write buffer in this case. + * 2. 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_arm925_dcache_clean_page) +#ifndef CONFIG_CPU_ARM925_WRITETHROUGH + mov r1, #PAGESIZE +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + subs r1, r1, #2 * DCACHELINESIZE + bne 1b +#endif + mov pc, lr + +/* + * cpu_arm925_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_arm925_dcache_clean_entry) +#ifndef CONFIG_CPU_ARM925_WRITETHROUGH + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* ================================ I-CACHE =============================== */ + +/* + * cpu_arm925_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 consistant. 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 flushing 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_arm925_icache_invalidate_range) + bic r0, r0, #ICACHELINESIZE - 1 @ Safety check + sub r1, r1, r0 + cmp r1, #MAX_AREA_SIZE + bhi cpu_arm925_cache_clean_invalidate_all_r2 + + bic r1, r1, #ICACHELINESIZE - 1 + add r1, r1, #ICACHELINESIZE + +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 + + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + + +ENTRY(cpu_arm925_icache_invalidate_page) + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + nop + nop + nop + nop + mov pc, lr + +/* ================================== TLB ================================= */ + +/* + * cpu_arm925_tlb_invalidate_all() + * + * Invalidate all TLB entries + */ + .align 5 +ENTRY(cpu_arm925_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_arm925_tlb_invalidate_range(start, end) + * + * invalidate TLB entries covering the specified range + * + * start: range start address + * end: range end address + */ + .align 5 +ENTRY(cpu_arm925_tlb_invalidate_range) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + + 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 + blo 1b + mov pc, lr + +/* + * cpu_arm925_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_arm925_tlb_invalidate_page) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + 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_arm925_set_pgd(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_arm925_set_pgd) + mov ip, #0 +#ifdef CONFIG_CPU_ARM925_WRITETHROUGH + mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D cache +#else +/* + * 'Clean & Invalidate whole DCache' + * Re-written to use Index Ops. + * NOTE: Requires TI925T Configuration Register C bit <- 0 + * for clean and invalidate of both D-Cache sets. + */ + mov r3, #255 << 4 @ 256 entries/set + @ ((NSETS - 1) << (CIR[13-12] + 3)) +2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index + subs r3, r3, #1 << 4 + bcs 2b @ entries 255 to 0 +#endif + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mov pc, lr + +/* + * cpu_arm925_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_arm925_set_pmd) +#ifdef CONFIG_CPU_ARM925_WRITETHROUGH + eor r2, r1, #0x0a @ C & Section + tst r2, #0x0b + biceq r1, r1, #4 @ clear bufferable bit +#endif + str r1, [r0] + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_arm925_set_pte(ptep, pte) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_arm925_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_ARM925_WRITETHROUGH + eor r3, r2, #0x0a @ C & small page? + tst r3, #0x0b + biceq r2, r2, #4 +#endif + str r2, [r0] @ hardware version + mov r0, r0 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + + +ENTRY(cpu_arm925_name) + .ascii "Arm925T" +#if defined(CONFIG_CPU_ARM925_CPU_IDLE) + .ascii "s" +#endif +#if defined(CONFIG_CPU_ARM925_I_CACHE_ON) + .ascii "i" +#endif +#if defined(CONFIG_CPU_ARM925_D_CACHE_ON) + .ascii "d" +#if defined(CONFIG_CPU_ARM925_WRITETHROUGH) + .ascii "(wt)" +#else + .ascii "(wb)" +#endif +#endif + .ascii "\0" + +ENTRY(cpu_arm915_name) + .ascii "Arm915T" +#if defined(CONFIG_CPU_ARM925_CPU_IDLE) + .ascii "s" +#endif +#if defined(CONFIG_CPU_ARM925_I_CACHE_ON) + .ascii "i" +#endif +#if defined(CONFIG_CPU_ARM925_D_CACHE_ON) + .ascii "d" +#if defined(CONFIG_CPU_ARM925_WRITETHROUGH) + .ascii "(wt)" +#else + .ascii "(wb)" +#endif +#endif + .ascii "\0" + .align + + .section ".text.init", #alloc, #execinstr + +__arm925_setup: + mov r0, #0 +#if defined(CONFIG_CPU_ARM925_NON_STREAMING_ON) + orr r0,r0,#0x80 +#endif +#if defined(CONFIG_CPU_ARM925_TRANSPARENT_ON) + orr r0,r0,#0x2 +#endif + mcr p15, 0, r0, c15, c1, 0 @ write TI config register + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mrc p15, 0, r0, c1, c0 @ get control register v4 +/* + * Clear out 'unwanted' bits (then put them in if we need them) + */ + @ VI ZFRS BLDP WCAM + bic r0, r0, #0x0e00 + bic r0, r0, #0x0002 + bic r0, r0, #0x000c + bic r0, r0, #0x1000 @ ...0 000. .... 000. +/* + * Turn on what we want + */ + orr r0, r0, #0x0031 + orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 + +#ifdef CONFIG_CPU_ARM925_WRITEBUFFER_ON + orr r0, r0, #0x0008 @ .... .... .... 1... +#endif +#ifdef CONFIG_CPU_ARM925_D_CACHE_ON + orr r0, r0, #0x0004 @ .... .... .... .1.. +#endif +#ifdef CONFIG_CPU_ARM925_I_CACHE_ON + orr r0, r0, #0x1000 @ ...1 .... .... .... +#endif + mov pc, lr + + .text + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type arm925_processor_functions, #object +arm925_processor_functions: + .word cpu_arm925_data_abort + .word cpu_arm925_check_bugs + .word cpu_arm925_proc_init + .word cpu_arm925_proc_fin + .word cpu_arm925_reset + .word cpu_arm925_do_idle + + /* cache */ + .word cpu_arm925_cache_clean_invalidate_all + .word cpu_arm925_cache_clean_invalidate_range + .word cpu_arm925_flush_ram_page + + /* dcache */ + .word cpu_arm925_dcache_invalidate_range + .word cpu_arm925_dcache_clean_range + .word cpu_arm925_dcache_clean_page + .word cpu_arm925_dcache_clean_entry + + /* icache */ + .word cpu_arm925_icache_invalidate_range + .word cpu_arm925_icache_invalidate_page + + /* tlb */ + .word cpu_arm925_tlb_invalidate_all + .word cpu_arm925_tlb_invalidate_range + .word cpu_arm925_tlb_invalidate_page + + /* pgtable */ + .word cpu_arm925_set_pgd + .word cpu_arm925_set_pmd + .word cpu_arm925_set_pte + .size arm925_processor_functions, . - arm925_processor_functions + + .type cpu_arm925_info, #object +cpu_arm925_info: + .long 0 + .long cpu_arm925_name + .size cpu_arm925_info, . - cpu_arm925_info + + .type cpu_arm915_info, #object +cpu_arm915_info: + .long cpu_manu_name + .long cpu_arm915_name + .size cpu_arm915_info, . - cpu_arm915_info + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv4" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v4" + .size cpu_elf_name, . - cpu_elf_name + .align + +#if defined(CONFIG_CPU_ARM925_WRITETHROUGH) +# define MMU_FLAGS 0x00000c1a +#else +# define MMU_FLAGS 0x00000c1e +#endif + .section ".proc.info", #alloc, #execinstr + + .type __arm925_proc_info,#object +__arm925_proc_info: + .long 0x54029252 + .long 0xffffffff + .long MMU_FLAGS + b __arm925_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long cpu_arm925_info + .long arm925_processor_functions + .size __arm925_proc_info, . - __arm925_proc_info + + .type __arm915_proc_info,#object +__arm915_proc_info: + .long 0x54029152 + .long 0xffffffff + .long MMU_FLAGS + b __arm925_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long cpu_arm915_info + .long arm925_processor_functions + .size __arm925_proc_info, . - __arm925_proc_info diff -urN orig/arch/arm/mm/proc-arm926.S linux/arch/arm/mm/proc-arm926.S --- orig/arch/arm/mm/proc-arm926.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/proc-arm926.S Wed Jul 16 15:57:10 2003 @@ -66,29 +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 - 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 -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 /* @@ -146,9 +141,7 @@ */ .align 5 ENTRY(cpu_arm926_do_idle) -#if defined(CONFIG_CPU_ARM926_CPU_IDLE) mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt -#endif mov pc, lr /* ================================= CACHE ================================ */ @@ -167,7 +160,7 @@ mov r2, #1 cpu_arm926_cache_clean_invalidate_all_r2: mov ip, #0 -#ifdef CONFIG_CPU_ARM926_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else 1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate @@ -202,7 +195,7 @@ bhi cpu_arm926_cache_clean_invalidate_all_r2 1: teq r2, #0 -#ifdef CONFIG_CPU_ARM926_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry add r0, r0, #DCACHELINESIZE @@ -235,7 +228,7 @@ .align 5 ENTRY(cpu_arm926_flush_ram_page) mov r1, #PAGESIZE -#ifdef CONFIG_CPU_ARM926_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #DCACHELINESIZE mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry @@ -408,6 +401,10 @@ */ .align 5 ENTRY(cpu_arm926_tlb_invalidate_range) + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE @ arbitary, should be tuned + bhi cpu_arm926_tlb_invalidate_all + mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB @@ -450,7 +447,7 @@ .align 5 ENTRY(cpu_arm926_set_pgd) mov ip, #0 -#ifdef CONFIG_CPU_ARM926_WRITETHROUGH +#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 @@ -475,7 +472,7 @@ */ .align 5 ENTRY(cpu_arm926_set_pmd) -#ifdef CONFIG_CPU_ARM926_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH eor r2, r1, #0x0a @ C & Section tst r2, #0x0b biceq r1, r1, #4 @ clear bufferable bit @@ -502,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? @@ -511,38 +508,33 @@ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young? movne r2, #0 -#ifdef CONFIG_CPU_ARM926_WRITETHROUGH +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH eor r3, r2, #0x0a @ C & small page? tst r3, #0x0b biceq r2, r2, #4 #endif str r2, [r0] @ hardware version mov r0, 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 mov pc, lr -cpu_manu_name: - .asciz "ARM" ENTRY(cpu_arm926_name) .ascii "ARM926EJ-S" -#if defined(CONFIG_CPU_ARM926_CPU_IDLE) - .ascii "s" -#endif -#if defined(CONFIG_CPU_ARM926_I_CACHE_ON) +#ifndef CONFIG_CPU_ICACHE_DISABLE .ascii "i" #endif -#if defined(CONFIG_CPU_ARM926_D_CACHE_ON) +#ifndef CONFIG_CPU_DCACHE_DISABLE .ascii "d" -#if defined(CONFIG_CPU_ARM926_WRITETHROUGH) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH .ascii "(wt)" #else .ascii "(wb)" #endif -#ifdef CONFIG_CPU_ARM926_ROUND_ROBIN +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN .ascii "RR" #endif #endif @@ -559,7 +551,7 @@ mcr p15, 0, r4, c2, c0 @ load page table pointer -#if defined(CONFIG_CPU_ARM926_WRITETHROUGH) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mov r0, #4 @ disable write-back on caches explicitly mcr p15, 7, r0, c15, c0, 0 #endif @@ -581,13 +573,13 @@ orr r0, r0, #0x0031 orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 -#ifdef CONFIG_CPU_ARM926_ROUND_ROBIN +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .1.. .... .... .... #endif -#ifdef CONFIG_CPU_ARM926_D_CACHE_ON +#ifndef CONFIG_CPU_DCACHE_DISABLE orr r0, r0, #0x0004 @ .... .... .... .1.. #endif -#ifdef CONFIG_CPU_ARM926_I_CACHE_ON +#ifndef CONFIG_CPU_ICACHE_DISABLE orr r0, r0, #0x1000 @ ...1 .... .... .... #endif mov pc, lr @@ -635,7 +627,7 @@ .type cpu_arm926_info, #object cpu_arm926_info: - .long cpu_manu_name + .long 0 .long cpu_arm926_name .size cpu_arm926_info, . - cpu_arm926_info @@ -660,7 +652,8 @@ b __arm926_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \ + HWCAP_FAST_MULT .long cpu_arm926_info .long arm926_processor_functions .size __arm926_proc_info, . - __arm926_proc_info diff -urN orig/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S --- orig/arch/arm/mm/proc-sa110.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/mm/proc-sa110.S Wed Jul 16 15:43:54 2003 @@ -159,43 +159,12 @@ mov pc, r0 /* - * cpu_sa110_do_idle(type) + * cpu_sa110_do_idle() * * Cause the processor to idle - * - * type: call type: - * 0 = slow idle - * 1 = fast idle - * 2 = switch to slow processor clock - * 3 = switch to fast processor clock */ .align 5 -idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt, cache aligned - mov r0, r0 @ safety - mov pc, lr - ENTRY(cpu_sa110_do_idle) - mov ip, #0 - cmp r0, #4 - addcc pc, pc, r0, lsl #2 - mov pc, lr - - b idle - b idle - b slow_clock - b fast_clock - -fast_clock: - mcr p15, 0, ip, c15, c1, 2 @ enable clock switching - mov pc, lr - -slow_clock: - mcr p15, 0, ip, c15, c2, 2 @ disable clock switching - ldr r1, =UNCACHEABLE_ADDR @ load from uncacheable loc - ldr r1, [r1, #0] @ force switch to MCLK - mov pc, lr - - .align 5 ENTRY(cpu_sa1100_do_idle) mov r0, r0 @ 4 nop padding mov r0, r0 @@ -468,6 +437,9 @@ ENTRY(cpu_sa1100_tlb_invalidate_range) bic r0, r0, #0x0ff bic r0, r0, #0xf00 + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE @ arbitary, should be tuned + bhi cpu_sa110_tlb_invalidate_all mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB 1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry @@ -579,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? @@ -595,8 +567,6 @@ mov pc, lr -cpu_manu_name: - .asciz "Intel" cpu_sa110_name: .asciz "StrongARM-110" cpu_sa1100_name: @@ -676,7 +646,7 @@ .type cpu_sa110_info, #object cpu_sa110_info: - .long cpu_manu_name + .long 0 .long cpu_sa110_name .size cpu_sa110_info, . - cpu_sa110_info @@ -720,12 +690,12 @@ .size sa1100_processor_functions, . - sa1100_processor_functions cpu_sa1100_info: - .long cpu_manu_name + .long 0 .long cpu_sa1100_name .size cpu_sa1100_info, . - cpu_sa1100_info cpu_sa1110_info: - .long cpu_manu_name + .long 0 .long cpu_sa1110_name .size cpu_sa1110_info, . - cpu_sa1110_info diff -urN orig/arch/arm/mm/small_page.c linux/arch/arm/mm/small_page.c --- orig/arch/arm/mm/small_page.c Sat Apr 28 11:24:54 2001 +++ linux/arch/arm/mm/small_page.c Fri Sep 6 11:33:02 2002 @@ -150,8 +150,8 @@ unsigned long flags; struct page *page; - page = virt_to_page(spage); - if (VALID_PAGE(page)) { + if (virt_addr_valid(spage)) { + page = virt_to_page(spage); /* * The container-page must be marked Reserved diff -urN orig/arch/arm/nwfpe/ChangeLog linux/arch/arm/nwfpe/ChangeLog --- orig/arch/arm/nwfpe/ChangeLog Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/ChangeLog Sat Mar 29 20:30:19 2003 @@ -1,3 +1,11 @@ +2003-03-22 Ralph Siemsen + * Reformat all but softfloat files to get a consistent coding style. + Used "indent -kr -i8 -ts8 -sob -l132 -ss" and a few manual fixups. + * Removed dead code and fixed function protypes to match definitions. + * Consolidated use of (opcode && MASK_ARITHMETIC_OPCODE) >> 20. + * Make 80-bit precision a compile-time option. (1%) + * Only initialize FPE state once in repeat-FP situations. (6%) + 2002-01-19 Russell King * fpa11.h - Add documentation diff -urN orig/arch/arm/nwfpe/Makefile linux/arch/arm/nwfpe/Makefile --- orig/arch/arm/nwfpe/Makefile Sat Apr 28 11:24:54 2001 +++ linux/arch/arm/nwfpe/Makefile Sat Mar 29 19:35:46 2003 @@ -18,7 +18,11 @@ nwfpe-objs := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \ fpmodule.o fpopcode.o softfloat.o \ - single_cpdo.o double_cpdo.o extended_cpdo.o + single_cpdo.o double_cpdo.o + +ifeq ($(CONFIG_FPE_NWFPE_XP),y) +nwfpe-objs += extended_cpdo.o +endif ifeq ($(CONFIG_CPU_26),y) nwfpe-objs += entry26.o diff -urN orig/arch/arm/nwfpe/double_cpdo.c linux/arch/arm/nwfpe/double_cpdo.c --- orig/arch/arm/nwfpe/double_cpdo.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/double_cpdo.c Sat Mar 29 18:54:42 2003 @@ -23,6 +23,11 @@ #include "softfloat.h" #include "fpopcode.h" +union float64_components { + float64 f64; + unsigned int i[2]; +}; + float64 float64_exp(float64 Fm); float64 float64_ln(float64 Fm); float64 float64_sin(float64 rFm); @@ -32,257 +37,123 @@ float64 float64_log(float64 rFm); float64 float64_tan(float64 rFm); float64 float64_arccos(float64 rFm); -float64 float64_pow(float64 rFn,float64 rFm); -float64 float64_pol(float64 rFn,float64 rFm); +float64 float64_pow(float64 rFn, float64 rFm); +float64 float64_pol(float64 rFn, float64 rFm); -unsigned int DoubleCPDO(const unsigned int opcode) +static float64 float64_rsf(float64 rFn, float64 rFm) { - FPA11 *fpa11 = GET_FPA11(); - float64 rFm, rFn; - unsigned int Fd, Fm, Fn, nRc = 1; - - //printk("DoubleCPDO(0x%08x)\n",opcode); - - Fm = getFm(opcode); - if (CONSTANT_FM(opcode)) - { - rFm = getDoubleConstant(Fm); - } - else - { - switch (fpa11->fType[Fm]) - { - case typeSingle: - rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); - break; - - case typeDouble: - rFm = fpa11->fpreg[Fm].fDouble; - break; - - case typeExtended: - // !! patb - //printk("not implemented! why not?\n"); - //!! ScottB - // should never get here, if extended involved - // then other operand should be promoted then - // ExtendedCPDO called. - break; - - default: return 0; - } - } - - if (!MONADIC_INSTRUCTION(opcode)) - { - Fn = getFn(opcode); - switch (fpa11->fType[Fn]) - { - case typeSingle: - rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - rFn = fpa11->fpreg[Fn].fDouble; - break; - - default: return 0; - } - } - - Fd = getFd(opcode); - /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */ - switch (opcode & MASK_ARITHMETIC_OPCODE) - { - /* dyadic opcodes */ - case ADF_CODE: - fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm); - break; - - case MUF_CODE: - case FML_CODE: - fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm); - break; - - case SUF_CODE: - fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm); - break; - - case RSF_CODE: - fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn); - break; - - case DVF_CODE: - case FDV_CODE: - fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm); - break; - - case RDF_CODE: - case FRD_CODE: - fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn); - break; - -#if 0 - case POW_CODE: - fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm); - break; - - case RPW_CODE: - fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn); - break; -#endif - - case RMF_CODE: - fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm); - break; - -#if 0 - case POL_CODE: - fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm); - break; -#endif - - /* monadic opcodes */ - case MVF_CODE: - fpa11->fpreg[Fd].fDouble = rFm; - break; - - case MNF_CODE: - { - unsigned int *p = (unsigned int*)&rFm; - p[1] ^= 0x80000000; - fpa11->fpreg[Fd].fDouble = rFm; - } - break; - - case ABS_CODE: - { - unsigned int *p = (unsigned int*)&rFm; - p[1] &= 0x7fffffff; - fpa11->fpreg[Fd].fDouble = rFm; - } - break; - - case RND_CODE: - case URD_CODE: - fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm); - break; - - case SQT_CODE: - fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm); - break; - -#if 0 - case LOG_CODE: - fpa11->fpreg[Fd].fDouble = float64_log(rFm); - break; - - case LGN_CODE: - fpa11->fpreg[Fd].fDouble = float64_ln(rFm); - break; - - case EXP_CODE: - fpa11->fpreg[Fd].fDouble = float64_exp(rFm); - break; - - case SIN_CODE: - fpa11->fpreg[Fd].fDouble = float64_sin(rFm); - break; - - case COS_CODE: - fpa11->fpreg[Fd].fDouble = float64_cos(rFm); - break; - - case TAN_CODE: - fpa11->fpreg[Fd].fDouble = float64_tan(rFm); - break; - - case ASN_CODE: - fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); - break; - - case ACS_CODE: - fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); - break; - - case ATN_CODE: - fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); - break; -#endif - - case NRM_CODE: - break; - - default: - { - nRc = 0; - } - } - - if (0 != nRc) fpa11->fType[Fd] = typeDouble; - return nRc; + return float64_sub(rFm, rFn); } -#if 0 -float64 float64_exp(float64 rFm) +static float64 float64_rdv(float64 rFn, float64 rFm) { - return rFm; -//series + return float64_div(rFm, rFn); } -float64 float64_ln(float64 rFm) -{ - return rFm; -//series -} +static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { + [ADF_CODE >> 20] = float64_add, + [MUF_CODE >> 20] = float64_mul, + [SUF_CODE >> 20] = float64_sub, + [RSF_CODE >> 20] = float64_rsf, + [DVF_CODE >> 20] = float64_div, + [RDF_CODE >> 20] = float64_rdv, + [RMF_CODE >> 20] = float64_rem, -float64 float64_sin(float64 rFm) -{ - return rFm; -//series -} + /* strictly, these opcodes should not be implemented */ + [FML_CODE >> 20] = float64_mul, + [FDV_CODE >> 20] = float64_div, + [FRD_CODE >> 20] = float64_rdv, +}; -float64 float64_cos(float64 rFm) +static float64 float64_mvf(float64 rFm) { - return rFm; - //series + return rFm; } -#if 0 -float64 float64_arcsin(float64 rFm) +static float64 float64_mnf(float64 rFm) { -//series -} + union float64_components u; -float64 float64_arctan(float64 rFm) -{ - //series -} -#endif + u.f64 = rFm; + u.i[1] ^= 0x80000000; -float64 float64_log(float64 rFm) -{ - return float64_div(float64_ln(rFm),getDoubleConstant(7)); + return u.f64; } -float64 float64_tan(float64 rFm) +static float64 float64_abs(float64 rFm) { - return float64_div(float64_sin(rFm),float64_cos(rFm)); -} + union float64_components u; -float64 float64_arccos(float64 rFm) -{ -return rFm; - //return float64_sub(halfPi,float64_arcsin(rFm)); -} + u.f64 = rFm; + u.i[1] &= 0x7fffffff; -float64 float64_pow(float64 rFn,float64 rFm) -{ - return float64_exp(float64_mul(rFm,float64_ln(rFn))); + return u.f64; } -float64 float64_pol(float64 rFn,float64 rFm) +static float64 (*const monadic_double[16])(float64 rFm) = { + [MVF_CODE >> 20] = float64_mvf, + [MNF_CODE >> 20] = float64_mnf, + [ABS_CODE >> 20] = float64_abs, + [RND_CODE >> 20] = float64_round_to_int, + [URD_CODE >> 20] = float64_round_to_int, + [SQT_CODE >> 20] = float64_sqrt, + [NRM_CODE >> 20] = float64_mvf, +}; + +unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) { - return float64_arctan(float64_div(rFn,rFm)); + FPA11 *fpa11 = GET_FPA11(); + float64 rFm; + unsigned int Fm, opc_mask_shift; + + Fm = getFm(opcode); + if (CONSTANT_FM(opcode)) { + rFm = getDoubleConstant(Fm); + } else { + switch (fpa11->fType[Fm]) { + case typeSingle: + rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); + break; + + case typeDouble: + rFm = fpa11->fpreg[Fm].fDouble; + break; + + default: + return 0; + } + } + + opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + if (!MONADIC_INSTRUCTION(opcode)) { + unsigned int Fn = getFn(opcode); + float64 rFn; + + switch (fpa11->fType[Fn]) { + case typeSingle: + rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + rFn = fpa11->fpreg[Fn].fDouble; + break; + + default: + return 0; + } + + if (dyadic_double[opc_mask_shift]) { + rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm); + } else { + return 0; + } + } else { + if (monadic_double[opc_mask_shift]) { + rFd->fDouble = monadic_double[opc_mask_shift](rFm); + } else { + return 0; + } + } + + return 1; } -#endif diff -urN orig/arch/arm/nwfpe/entry.S linux/arch/arm/nwfpe/entry.S --- orig/arch/arm/nwfpe/entry.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/entry.S Tue Apr 22 00:58:25 2003 @@ -70,39 +70,42 @@ .globl nwfpe_enter nwfpe_enter: - mov r4, lr @ save the failure-return addresses - mov sl, sp @ we access the registers via 'sl' - - ldr r5, [sp, #60] @ get contents of PC; - sub r8, r5, #4 -.Lx2: ldrt r0, [r8] @ get actual instruction into r0 + mov r4, lr @ save the failure-return addresses + ldr ip, [r10, #112] @ get init_flag + mov sl, sp @ we access the registers via 'sl' + + ldr r5, [sp, #60] @ get contents of PC; + cmp ip, #0 + bleq nwfpe_init_fpa + sub r8, r5, #4 +.Lx1: ldrt r0, [r8] @ get actual instruction into r0 emulate: - bl EmulateAll @ emulate the instruction - cmp r0, #0 @ was emulation successful - moveq pc, r4 @ no, return failure + bl EmulateAll @ emulate the instruction + cmp r0, #0 @ was emulation successful + moveq pc, r4 @ no, return failure next: -.Lx1: ldrt r6, [r5], #4 @ get the next instruction and +.Lx2: ldrt r6, [r5], #4 @ get the next instruction and @ increment PC - and r2, r6, #0x0F000000 @ test for FP insns - teq r2, #0x0C000000 - teqne r2, #0x0D000000 - teqne r2, #0x0E000000 - movne pc, r9 @ return ok if not a fp insn - - str r5, [sp, #60] @ update PC copy in regs - - mov r0, r6 @ save a copy - ldr r1, [sp, #64] @ fetch the condition codes - bl checkCondition @ check the condition - cmp r0, #0 @ r0 = 0 ==> condition failed - - @ if condition code failed to match, next insn - beq next @ get the next instruction; - - mov r0, r6 @ prepare for EmulateAll() - b emulate @ if r0 != 0, goto EmulateAll + and r2, r6, #0x0F000000 @ test for FP insns + teq r2, #0x0C000000 + teqne r2, #0x0D000000 + teqne r2, #0x0E000000 + movne pc, r9 @ return ok if not a fp insn + + str r5, [sp, #60] @ update PC copy in regs + + mov r0, r6 @ save a copy + ldr r1, [sp, #64] @ fetch the condition codes + bl checkCondition @ check the condition + cmp r0, #0 @ r0 = 0 ==> condition failed + + @ if condition code failed to match, next insn + beq next @ get the next instruction; + + mov r0, r6 @ prepare for EmulateAll() + b emulate @ if r0 != 0, goto EmulateAll @ We need to be prepared for the instructions at .Lx1 and .Lx2 @ to fault. Emit the appropriate exception gunk to fix things up. diff -urN orig/arch/arm/nwfpe/entry26.S linux/arch/arm/nwfpe/entry26.S --- orig/arch/arm/nwfpe/entry26.S Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/entry26.S Sat Mar 29 21:26:59 2003 @@ -95,7 +95,7 @@ @ if condition code failed to match, next insn beq next @ get the next instruction; - + mov r0, r6 @ prepare for EmulateAll() adr lr, 1b orr lr, lr, #3 diff -urN orig/arch/arm/nwfpe/extended_cpdo.c linux/arch/arm/nwfpe/extended_cpdo.c --- orig/arch/arm/nwfpe/extended_cpdo.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/extended_cpdo.c Sat Mar 29 18:54:42 2003 @@ -32,242 +32,123 @@ floatx80 floatx80_log(floatx80 rFm); floatx80 floatx80_tan(floatx80 rFm); floatx80 floatx80_arccos(floatx80 rFm); -floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm); -floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm); +floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); +floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); -unsigned int ExtendedCPDO(const unsigned int opcode) +static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm) { - FPA11 *fpa11 = GET_FPA11(); - floatx80 rFm, rFn; - unsigned int Fd, Fm, Fn, nRc = 1; - - //printk("ExtendedCPDO(0x%08x)\n",opcode); - - Fm = getFm(opcode); - if (CONSTANT_FM(opcode)) - { - rFm = getExtendedConstant(Fm); - } - else - { - switch (fpa11->fType[Fm]) - { - case typeSingle: - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); - break; - - case typeDouble: - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); - break; - - case typeExtended: - rFm = fpa11->fpreg[Fm].fExtended; - break; - - default: return 0; - } - } - - if (!MONADIC_INSTRUCTION(opcode)) - { - Fn = getFn(opcode); - switch (fpa11->fType[Fn]) - { - case typeSingle: - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); - break; - - case typeExtended: - rFn = fpa11->fpreg[Fn].fExtended; - break; - - default: return 0; - } - } - - Fd = getFd(opcode); - switch (opcode & MASK_ARITHMETIC_OPCODE) - { - /* dyadic opcodes */ - case ADF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm); - break; - - case MUF_CODE: - case FML_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm); - break; - - case SUF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm); - break; - - case RSF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn); - break; - - case DVF_CODE: - case FDV_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm); - break; - - case RDF_CODE: - case FRD_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn); - break; - -#if 0 - case POW_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm); - break; - - case RPW_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn); - break; -#endif - - case RMF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm); - break; - -#if 0 - case POL_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm); - break; -#endif - - /* monadic opcodes */ - case MVF_CODE: - fpa11->fpreg[Fd].fExtended = rFm; - break; - - case MNF_CODE: - rFm.high ^= 0x8000; - fpa11->fpreg[Fd].fExtended = rFm; - break; - - case ABS_CODE: - rFm.high &= 0x7fff; - fpa11->fpreg[Fd].fExtended = rFm; - break; - - case RND_CODE: - case URD_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm); - break; - - case SQT_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm); - break; - -#if 0 - case LOG_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_log(rFm); - break; - - case LGN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm); - break; - - case EXP_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm); - break; - - case SIN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm); - break; - - case COS_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm); - break; - - case TAN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm); - break; - - case ASN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm); - break; - - case ACS_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm); - break; - - case ATN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm); - break; -#endif - - case NRM_CODE: - break; - - default: - { - nRc = 0; - } - } - - if (0 != nRc) fpa11->fType[Fd] = typeExtended; - return nRc; + return floatx80_sub(rFm, rFn); } -#if 0 -floatx80 floatx80_exp(floatx80 Fm) +static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm) { -//series + return floatx80_div(rFm, rFn); } -floatx80 floatx80_ln(floatx80 Fm) -{ -//series -} +static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { + [ADF_CODE >> 20] = floatx80_add, + [MUF_CODE >> 20] = floatx80_mul, + [SUF_CODE >> 20] = floatx80_sub, + [RSF_CODE >> 20] = floatx80_rsf, + [DVF_CODE >> 20] = floatx80_div, + [RDF_CODE >> 20] = floatx80_rdv, + [RMF_CODE >> 20] = floatx80_rem, -floatx80 floatx80_sin(floatx80 rFm) -{ -//series -} + /* strictly, these opcodes should not be implemented */ + [FML_CODE >> 20] = floatx80_mul, + [FDV_CODE >> 20] = floatx80_div, + [FRD_CODE >> 20] = floatx80_rdv, +}; -floatx80 floatx80_cos(floatx80 rFm) +static floatx80 floatx80_mvf(floatx80 rFm) { -//series + return rFm; } -floatx80 floatx80_arcsin(floatx80 rFm) +static floatx80 floatx80_mnf(floatx80 rFm) { -//series + rFm.high ^= 0x8000; + return rFm; } -floatx80 floatx80_arctan(floatx80 rFm) +static floatx80 floatx80_abs(floatx80 rFm) { - //series + rFm.high &= 0x7fff; + return rFm; } -floatx80 floatx80_log(floatx80 rFm) -{ - return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7)); -} +static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { + [MVF_CODE >> 20] = floatx80_mvf, + [MNF_CODE >> 20] = floatx80_mnf, + [ABS_CODE >> 20] = floatx80_abs, + [RND_CODE >> 20] = floatx80_round_to_int, + [URD_CODE >> 20] = floatx80_round_to_int, + [SQT_CODE >> 20] = floatx80_sqrt, + [NRM_CODE >> 20] = floatx80_mvf, +}; -floatx80 floatx80_tan(floatx80 rFm) +unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) { - return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm)); -} + FPA11 *fpa11 = GET_FPA11(); + floatx80 rFm; + unsigned int Fm, opc_mask_shift; -floatx80 floatx80_arccos(floatx80 rFm) -{ - //return floatx80_sub(halfPi,floatx80_arcsin(rFm)); -} + Fm = getFm(opcode); + if (CONSTANT_FM(opcode)) { + rFm = getExtendedConstant(Fm); + } else { + switch (fpa11->fType[Fm]) { + case typeSingle: + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); + break; -floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm) -{ - return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn))); -} + case typeDouble: + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); + break; -floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm) -{ - return floatx80_arctan(floatx80_div(rFn,rFm)); + case typeExtended: + rFm = fpa11->fpreg[Fm].fExtended; + break; + + default: + return 0; + } + } + + opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + if (!MONADIC_INSTRUCTION(opcode)) { + unsigned int Fn = getFn(opcode); + floatx80 rFn; + + switch (fpa11->fType[Fn]) { + case typeSingle: + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); + break; + + case typeExtended: + rFn = fpa11->fpreg[Fn].fExtended; + break; + + default: + return 0; + } + + if (dyadic_extended[opc_mask_shift]) { + rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm); + } else { + return 0; + } + } else { + if (monadic_extended[opc_mask_shift]) { + rFd->fExtended = monadic_extended[opc_mask_shift](rFm); + } else { + return 0; + } + } + + return 1; } -#endif diff -urN orig/arch/arm/nwfpe/fpa11.c linux/arch/arm/nwfpe/fpa11.c --- orig/arch/arm/nwfpe/fpa11.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/fpa11.c Sat Mar 29 21:32:46 2003 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -20,7 +21,6 @@ */ #include "fpa11.h" - #include "fpopcode.h" #include "fpmodule.h" @@ -36,180 +36,96 @@ /* Reset the FPA11 chip. Called to initialize and reset the emulator. */ void resetFPA11(void) { - int i; - FPA11 *fpa11 = GET_FPA11(); - - /* initialize the register type array */ - for (i=0;i<=7;i++) - { - fpa11->fType[i] = typeNone; - } - - /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */ - fpa11->fpsr = FP_EMULATOR | BIT_AC; - - /* FPCR: set SB, AB and DA bits, clear all others */ -#if MAINTAIN_FPCR - fpa11->fpcr = MASK_RESET; -#endif + int i; + FPA11 *fpa11 = GET_FPA11(); + + /* initialize the register type array */ + for (i = 0; i <= 7; i++) { + fpa11->fType[i] = typeNone; + } + + /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */ + fpa11->fpsr = FP_EMULATOR | BIT_AC; } void SetRoundingMode(const unsigned int opcode) { -#if MAINTAIN_FPCR - FPA11 *fpa11 = GET_FPA11(); - fpa11->fpcr &= ~MASK_ROUNDING_MODE; -#endif - switch (opcode & MASK_ROUNDING_MODE) - { - default: - case ROUND_TO_NEAREST: - float_rounding_mode = float_round_nearest_even; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_NEAREST; -#endif - break; - - case ROUND_TO_PLUS_INFINITY: - float_rounding_mode = float_round_up; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_PLUS_INFINITY; -#endif - break; - - case ROUND_TO_MINUS_INFINITY: - float_rounding_mode = float_round_down; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_MINUS_INFINITY; -#endif - break; - - case ROUND_TO_ZERO: - float_rounding_mode = float_round_to_zero; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_ZERO; -#endif - break; - } + switch (opcode & MASK_ROUNDING_MODE) { + default: + case ROUND_TO_NEAREST: + float_rounding_mode = float_round_nearest_even; + break; + + case ROUND_TO_PLUS_INFINITY: + float_rounding_mode = float_round_up; + break; + + case ROUND_TO_MINUS_INFINITY: + float_rounding_mode = float_round_down; + break; + + case ROUND_TO_ZERO: + float_rounding_mode = float_round_to_zero; + break; + } } void SetRoundingPrecision(const unsigned int opcode) { -#if MAINTAIN_FPCR - FPA11 *fpa11 = GET_FPA11(); - fpa11->fpcr &= ~MASK_ROUNDING_PRECISION; -#endif - switch (opcode & MASK_ROUNDING_PRECISION) - { - case ROUND_SINGLE: - floatx80_rounding_precision = 32; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_SINGLE; -#endif - break; - - case ROUND_DOUBLE: - floatx80_rounding_precision = 64; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_DOUBLE; -#endif - break; - - case ROUND_EXTENDED: - floatx80_rounding_precision = 80; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_EXTENDED; -#endif - break; - - default: floatx80_rounding_precision = 80; - } +#ifdef CONFIG_FPE_NWFPE_XP + switch (opcode & MASK_ROUNDING_PRECISION) { + case ROUND_SINGLE: + floatx80_rounding_precision = 32; + break; + + case ROUND_DOUBLE: + floatx80_rounding_precision = 64; + break; + + case ROUND_EXTENDED: + floatx80_rounding_precision = 80; + break; + + default: + floatx80_rounding_precision = 80; + } +#endif } -/* Emulate the instruction in the opcode. */ -unsigned int EmulateAll(unsigned int opcode) +void nwfpe_init_fpa(void) { - unsigned int nRc = 0; - unsigned long flags; - FPA11 *fpa11; - save_flags(flags); sti(); - - fpa11 = GET_FPA11(); - - if (fpa11->initflag == 0) /* good place for __builtin_expect */ - { - resetFPA11(); - SetRoundingMode(ROUND_TO_NEAREST); - SetRoundingPrecision(ROUND_EXTENDED); - fpa11->initflag = 1; - } - - if (TEST_OPCODE(opcode,MASK_CPRT)) - { - /* Emulate conversion opcodes. */ - /* Emulate register transfer opcodes. */ - /* Emulate comparison opcodes. */ - nRc = EmulateCPRT(opcode); - } - else if (TEST_OPCODE(opcode,MASK_CPDO)) - { - /* Emulate monadic arithmetic opcodes. */ - /* Emulate dyadic arithmetic opcodes. */ - nRc = EmulateCPDO(opcode); - } - else if (TEST_OPCODE(opcode,MASK_CPDT)) - { - /* Emulate load/store opcodes. */ - /* Emulate load/store multiple opcodes. */ - nRc = EmulateCPDT(opcode); - } - else - { - /* Invalid instruction detected. Return FALSE. */ - nRc = 0; - } - - restore_flags(flags); - - return(nRc); + FPA11 *fpa11 = GET_FPA11(); +#ifdef NWFPE_DEBUG + printk("NWFPE: setting up state.\n"); +#endif + resetFPA11(); + SetRoundingMode(ROUND_TO_NEAREST); + SetRoundingPrecision(ROUND_EXTENDED); + fpa11->initflag = 1; } -#if 0 -unsigned int EmulateAll1(unsigned int opcode) +/* Emulate the instruction in the opcode. */ +unsigned int EmulateAll(const unsigned int opcode) { - switch ((opcode >> 24) & 0xf) - { - case 0xc: - case 0xd: - if ((opcode >> 20) & 0x1) - { - switch ((opcode >> 8) & 0xf) - { - case 0x1: return PerformLDF(opcode); break; - case 0x2: return PerformLFM(opcode); break; - default: return 0; - } - } - else - { - switch ((opcode >> 8) & 0xf) - { - case 0x1: return PerformSTF(opcode); break; - case 0x2: return PerformSFM(opcode); break; - default: return 0; - } - } - break; - - case 0xe: - if (opcode & 0x10) - return EmulateCPDO(opcode); - else - return EmulateCPRT(opcode); - break; - - default: return 0; - } -} +#ifdef NWFPE_DEBUG + printk("NWFPE: emulating opcode %08x\n", opcode); #endif + if (TEST_OPCODE(opcode, MASK_CPRT)) { + /* Emulate conversion opcodes. */ + /* Emulate register transfer opcodes. */ + /* Emulate comparison opcodes. */ + return EmulateCPRT(opcode); + } else if (TEST_OPCODE(opcode, MASK_CPDO)) { + /* Emulate monadic arithmetic opcodes. */ + /* Emulate dyadic arithmetic opcodes. */ + return EmulateCPDO(opcode); + } else if (TEST_OPCODE(opcode, MASK_CPDT)) { + /* Emulate load/store opcodes. */ + /* Emulate load/store multiple opcodes. */ + return EmulateCPDT(opcode); + } + + /* Invalid instruction detected. Return FALSE. */ + return 0; +} diff -urN orig/arch/arm/nwfpe/fpa11.h linux/arch/arm/nwfpe/fpa11.h --- orig/arch/arm/nwfpe/fpa11.h Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/fpa11.h Tue Apr 22 00:45:21 2003 @@ -38,6 +38,7 @@ /* includes */ #include "fpsr.h" /* FP control and status register definitions */ +#include "milieu.h" #include "softfloat.h" #define typeNone 0x00 @@ -49,9 +50,13 @@ * This must be no more and no less than 12 bytes. */ typedef union tagFPREG { - floatx80 fExtended; - float64 fDouble; - float32 fSingle; + float32 fSingle; + float64 fDouble; +#ifdef CONFIG_FPE_NWFPE_XP + floatx80 fExtended; +#else + int padding[3]; +#endif } FPREG; /* @@ -68,17 +73,17 @@ * not initialise. */ typedef struct tagFPA11 { -/* 0 */ FPREG fpreg[8]; /* 8 floating point registers */ -/* 96 */ FPSR fpsr; /* floating point status register */ -/* 100 */ FPCR fpcr; /* floating point control register */ -/* 104 */ unsigned char fType[8]; /* type of floating point value held in - floating point registers. One of none - single, double or extended. */ -/* 112 */ int initflag; /* this is special. The kernel guarantees - to set it to 0 when a thread is launched, - so we can use it to detect whether this - instance of the emulator needs to be - initialised. */ +/* 0 */ FPREG fpreg[8]; /* 8 floating point registers */ +/* 96 */ FPSR fpsr; /* floating point status register */ +/* 100 */ FPCR fpcr; /* floating point control register */ +/* 104 */ unsigned char fType[8]; /* type of floating point value held in + floating point registers. One of + none, single, double or extended. */ +/* 112 */ int initflag; /* this is special. The kernel guarantees + to set it to 0 when a thread is launched, + so we can use it to detect whether this + instance of the emulator needs to be + initialised. */ } FPA11; extern void resetFPA11(void); diff -urN orig/arch/arm/nwfpe/fpa11.inl linux/arch/arm/nwfpe/fpa11.inl --- orig/arch/arm/nwfpe/fpa11.inl Mon Sep 3 14:14:41 2001 +++ linux/arch/arm/nwfpe/fpa11.inl Sat Mar 29 18:42:58 2003 @@ -24,28 +24,28 @@ /* Read and write floating point status register */ extern __inline__ unsigned int readFPSR(void) { - FPA11 *fpa11 = GET_FPA11(); - return(fpa11->fpsr); + FPA11 *fpa11 = GET_FPA11(); + return (fpa11->fpsr); } extern __inline__ void writeFPSR(FPSR reg) { - FPA11 *fpa11 = GET_FPA11(); - /* the sysid byte in the status register is readonly */ - fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID); + FPA11 *fpa11 = GET_FPA11(); + /* the sysid byte in the status register is readonly */ + fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID); } /* Read and write floating point control register */ extern __inline__ FPCR readFPCR(void) { - FPA11 *fpa11 = GET_FPA11(); - /* clear SB, AB and DA bits before returning FPCR */ - return(fpa11->fpcr & ~MASK_RFC); + FPA11 *fpa11 = GET_FPA11(); + /* clear SB, AB and DA bits before returning FPCR */ + return (fpa11->fpcr & ~MASK_RFC); } extern __inline__ void writeFPCR(FPCR reg) { - FPA11 *fpa11 = GET_FPA11(); - fpa11->fpcr &= ~MASK_WFC; /* clear SB, AB and DA bits */ - fpa11->fpcr |= (reg & MASK_WFC); /* write SB, AB and DA bits */ + FPA11 *fpa11 = GET_FPA11(); + fpa11->fpcr &= ~MASK_WFC; /* clear SB, AB and DA bits */ + fpa11->fpcr |= (reg & MASK_WFC); /* write SB, AB and DA bits */ } diff -urN orig/arch/arm/nwfpe/fpa11_cpdo.c linux/arch/arm/nwfpe/fpa11_cpdo.c --- orig/arch/arm/nwfpe/fpa11_cpdo.c Mon Sep 3 14:14:41 2001 +++ linux/arch/arm/nwfpe/fpa11_cpdo.c Sat Mar 29 19:35:46 2003 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -22,96 +23,109 @@ #include "fpa11.h" #include "fpopcode.h" -unsigned int SingleCPDO(const unsigned int opcode); -unsigned int DoubleCPDO(const unsigned int opcode); -unsigned int ExtendedCPDO(const unsigned int opcode); +unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd); +unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd); +unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd); unsigned int EmulateCPDO(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - unsigned int Fd, nType, nDest, nRc = 1; - - //printk("EmulateCPDO(0x%08x)\n",opcode); - - /* Get the destination size. If not valid let Linux perform - an invalid instruction trap. */ - nDest = getDestinationSize(opcode); - if (typeNone == nDest) return 0; - - SetRoundingMode(opcode); - - /* Compare the size of the operands in Fn and Fm. - Choose the largest size and perform operations in that size, - in order to make use of all the precision of the operands. - If Fm is a constant, we just grab a constant of a size - matching the size of the operand in Fn. */ - if (MONADIC_INSTRUCTION(opcode)) - nType = nDest; - else - nType = fpa11->fType[getFn(opcode)]; - - if (!CONSTANT_FM(opcode)) - { - register unsigned int Fm = getFm(opcode); - if (nType < fpa11->fType[Fm]) - { - nType = fpa11->fType[Fm]; - } - } - - switch (nType) - { - case typeSingle : nRc = SingleCPDO(opcode); break; - case typeDouble : nRc = DoubleCPDO(opcode); break; - case typeExtended : nRc = ExtendedCPDO(opcode); break; - default : nRc = 0; - } - - /* If the operation succeeded, check to see if the result in the - destination register is the correct size. If not force it - to be. */ - Fd = getFd(opcode); - nType = fpa11->fType[Fd]; - if ((0 != nRc) && (nDest != nType)) - { - switch (nDest) - { - case typeSingle: - { - if (typeDouble == nType) - fpa11->fpreg[Fd].fSingle = - float64_to_float32(fpa11->fpreg[Fd].fDouble); - else - fpa11->fpreg[Fd].fSingle = - floatx80_to_float32(fpa11->fpreg[Fd].fExtended); - } - break; - - case typeDouble: - { - if (typeSingle == nType) - fpa11->fpreg[Fd].fDouble = - float32_to_float64(fpa11->fpreg[Fd].fSingle); - else - fpa11->fpreg[Fd].fDouble = - floatx80_to_float64(fpa11->fpreg[Fd].fExtended); - } - break; - - case typeExtended: - { - if (typeSingle == nType) - fpa11->fpreg[Fd].fExtended = - float32_to_floatx80(fpa11->fpreg[Fd].fSingle); - else - fpa11->fpreg[Fd].fExtended = - float64_to_floatx80(fpa11->fpreg[Fd].fDouble); - } - break; - } - - fpa11->fType[Fd] = nDest; - } - - return nRc; + FPA11 *fpa11 = GET_FPA11(); + FPREG *rFd; + unsigned int nType, nDest, nRc; + + /* Get the destination size. If not valid let Linux perform + an invalid instruction trap. */ + nDest = getDestinationSize(opcode); + if (typeNone == nDest) + return 0; + + SetRoundingMode(opcode); + + /* Compare the size of the operands in Fn and Fm. + Choose the largest size and perform operations in that size, + in order to make use of all the precision of the operands. + If Fm is a constant, we just grab a constant of a size + matching the size of the operand in Fn. */ + if (MONADIC_INSTRUCTION(opcode)) + nType = nDest; + else + nType = fpa11->fType[getFn(opcode)]; + + if (!CONSTANT_FM(opcode)) { + register unsigned int Fm = getFm(opcode); + if (nType < fpa11->fType[Fm]) { + nType = fpa11->fType[Fm]; + } + } + + rFd = &fpa11->fpreg[getFd(opcode)]; + + switch (nType) { + case typeSingle: + nRc = SingleCPDO(opcode, rFd); + break; + case typeDouble: + nRc = DoubleCPDO(opcode, rFd); + break; +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + nRc = ExtendedCPDO(opcode, rFd); + break; +#endif + default: + nRc = 0; + } + + /* The CPDO functions used to always set the destination type + to be the same as their working size. */ + + if (nRc != 0) { + /* If the operation succeeded, check to see if the result in the + destination register is the correct size. If not force it + to be. */ + + fpa11->fType[getFd(opcode)] = nDest; + +#ifdef CONFIG_FPE_NWFPE_XP + if (nDest != nType) { + switch (nDest) { + case typeSingle: + { + if (typeDouble == nType) + rFd->fSingle = float64_to_float32(rFd->fDouble); + else + rFd->fSingle = floatx80_to_float32(rFd->fExtended); + } + break; + + case typeDouble: + { + if (typeSingle == nType) + rFd->fDouble = float32_to_float64(rFd->fSingle); + else + rFd->fDouble = floatx80_to_float64(rFd->fExtended); + } + break; + + case typeExtended: + { + if (typeSingle == nType) + rFd->fExtended = float32_to_floatx80(rFd->fSingle); + else + rFd->fExtended = float64_to_floatx80(rFd->fDouble); + } + break; + } + } +#else + if (nDest != nType) { + if (nDest == typeSingle) + rFd->fSingle = float64_to_float32(rFd->fDouble); + else + rFd->fDouble = float32_to_float64(rFd->fSingle); + } +#endif + } + + return nRc; } diff -urN orig/arch/arm/nwfpe/fpa11_cpdt.c linux/arch/arm/nwfpe/fpa11_cpdt.c --- orig/arch/arm/nwfpe/fpa11_cpdt.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/fpa11_cpdt.c Sat Mar 29 19:35:46 2003 @@ -1,7 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.com, 1998-1999 - (c) Philip Blundell, 1998 + (c) Philip Blundell, 1998, 2001 Direct questions, comments to Scott Bambrough @@ -28,331 +28,347 @@ #include -static inline -void loadSingle(const unsigned int Fn,const unsigned int *pMem) +static inline void loadSingle(const unsigned int Fn, const unsigned int *pMem) { - FPA11 *fpa11 = GET_FPA11(); - fpa11->fType[Fn] = typeSingle; - get_user(fpa11->fpreg[Fn].fSingle, pMem); -} - -static inline -void loadDouble(const unsigned int Fn,const unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; - fpa11->fType[Fn] = typeDouble; - get_user(p[0], &pMem[1]); - get_user(p[1], &pMem[0]); /* sign & exponent */ -} - -static inline -void loadExtended(const unsigned int Fn,const unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; - fpa11->fType[Fn] = typeExtended; - get_user(p[0], &pMem[0]); /* sign & exponent */ - get_user(p[1], &pMem[2]); /* ls bits */ - get_user(p[2], &pMem[1]); /* ms bits */ -} - -static inline -void loadMultiple(const unsigned int Fn,const unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - register unsigned int *p; - unsigned long x; - - p = (unsigned int*)&(fpa11->fpreg[Fn]); - get_user(x, &pMem[0]); - fpa11->fType[Fn] = (x >> 14) & 0x00000003; - - switch (fpa11->fType[Fn]) - { - case typeSingle: - case typeDouble: - { - get_user(p[0], &pMem[2]); /* Single */ - get_user(p[1], &pMem[1]); /* double msw */ - p[2] = 0; /* empty */ - } - break; - - case typeExtended: - { - get_user(p[1], &pMem[2]); - get_user(p[2], &pMem[1]); /* msw */ - p[0] = (x & 0x80003fff); - } - break; - } -} - -static inline -void storeSingle(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - float32 val; - register unsigned int *p = (unsigned int*)&val; - - switch (fpa11->fType[Fn]) - { - case typeDouble: - val = float64_to_float32(fpa11->fpreg[Fn].fDouble); - break; - - case typeExtended: - val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); - break; - - default: val = fpa11->fpreg[Fn].fSingle; - } - - put_user(p[0], pMem); -} - -static inline -void storeDouble(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - float64 val; - register unsigned int *p = (unsigned int*)&val; - - switch (fpa11->fType[Fn]) - { - case typeSingle: - val = float32_to_float64(fpa11->fpreg[Fn].fSingle); - break; - - case typeExtended: - val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); - break; - - default: val = fpa11->fpreg[Fn].fDouble; - } - put_user(p[1], &pMem[0]); /* msw */ - put_user(p[0], &pMem[1]); /* lsw */ -} - -static inline -void storeExtended(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - floatx80 val; - register unsigned int *p = (unsigned int*)&val; - - switch (fpa11->fType[Fn]) - { - case typeSingle: - val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); - break; - - default: val = fpa11->fpreg[Fn].fExtended; - } - - put_user(p[0], &pMem[0]); /* sign & exp */ - put_user(p[1], &pMem[2]); - put_user(p[2], &pMem[1]); /* msw */ -} - -static inline -void storeMultiple(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - register unsigned int nType, *p; - - p = (unsigned int*)&(fpa11->fpreg[Fn]); - nType = fpa11->fType[Fn]; - - switch (nType) - { - case typeSingle: - case typeDouble: - { - put_user(p[0], &pMem[2]); /* single */ - put_user(p[1], &pMem[1]); /* double msw */ - put_user(nType << 14, &pMem[0]); - } - break; - - case typeExtended: - { - put_user(p[2], &pMem[1]); /* msw */ - put_user(p[1], &pMem[2]); - put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]); - } - break; - } + FPA11 *fpa11 = GET_FPA11(); + fpa11->fType[Fn] = typeSingle; + get_user(fpa11->fpreg[Fn].fSingle, pMem); } -unsigned int PerformLDF(const unsigned int opcode) +static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + unsigned int *p; + p = (unsigned int *) &fpa11->fpreg[Fn].fDouble; + fpa11->fType[Fn] = typeDouble; + get_user(p[0], &pMem[1]); + get_user(p[1], &pMem[0]); /* sign & exponent */ +} + +#ifdef CONFIG_FPE_NWFPE_XP +static inline void loadExtended(const unsigned int Fn, const unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + unsigned int *p; + p = (unsigned int *) &fpa11->fpreg[Fn].fExtended; + fpa11->fType[Fn] = typeExtended; + get_user(p[0], &pMem[0]); /* sign & exponent */ + get_user(p[1], &pMem[2]); /* ls bits */ + get_user(p[2], &pMem[1]); /* ms bits */ +} +#endif + +static inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + register unsigned int *p; + unsigned long x; + + p = (unsigned int *) &(fpa11->fpreg[Fn]); + get_user(x, &pMem[0]); + fpa11->fType[Fn] = (x >> 14) & 0x00000003; + + switch (fpa11->fType[Fn]) { + case typeSingle: + case typeDouble: + { + get_user(p[0], &pMem[2]); /* Single */ + get_user(p[1], &pMem[1]); /* double msw */ + p[2] = 0; /* empty */ + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + { + get_user(p[1], &pMem[2]); + get_user(p[2], &pMem[1]); /* msw */ + p[0] = (x & 0x80003fff); + } + break; +#endif + } +} + +static inline void storeSingle(const unsigned int Fn, unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + float32 val; + register unsigned int *p = (unsigned int *) &val; + + switch (fpa11->fType[Fn]) { + case typeDouble: + val = float64_to_float32(fpa11->fpreg[Fn].fDouble); + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); + break; +#endif + + default: + val = fpa11->fpreg[Fn].fSingle; + } + + put_user(p[0], pMem); +} + +static inline void storeDouble(const unsigned int Fn, unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + float64 val; + register unsigned int *p = (unsigned int *) &val; + + switch (fpa11->fType[Fn]) { + case typeSingle: + val = float32_to_float64(fpa11->fpreg[Fn].fSingle); + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); + break; +#endif + + default: + val = fpa11->fpreg[Fn].fDouble; + } + put_user(p[1], &pMem[0]); /* msw */ + put_user(p[0], &pMem[1]); /* lsw */ +} + +#ifdef CONFIG_FPE_NWFPE_XP +static inline void storeExtended(const unsigned int Fn, unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + floatx80 val; + register unsigned int *p = (unsigned int *) &val; + + switch (fpa11->fType[Fn]) { + case typeSingle: + val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); + break; + + default: + val = fpa11->fpreg[Fn].fExtended; + } + + put_user(p[0], &pMem[0]); /* sign & exp */ + put_user(p[1], &pMem[2]); + put_user(p[2], &pMem[1]); /* msw */ +} +#endif + +static inline void storeMultiple(const unsigned int Fn, unsigned int *pMem) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1, - write_back = WRITE_BACK(opcode); + FPA11 *fpa11 = GET_FPA11(); + register unsigned int nType, *p; + + p = (unsigned int *) &(fpa11->fpreg[Fn]); + nType = fpa11->fType[Fn]; + + switch (nType) { + case typeSingle: + case typeDouble: + { + put_user(p[0], &pMem[2]); /* single */ + put_user(p[1], &pMem[1]); /* double msw */ + put_user(nType << 14, &pMem[0]); + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + { + put_user(p[2], &pMem[1]); /* msw */ + put_user(p[1], &pMem[2]); + put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]); + } + break; +#endif + } +} - //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); +unsigned int PerformLDF(const unsigned int opcode) +{ + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - switch (opcode & MASK_TRANSFER_LENGTH) - { - case TRANSFER_SINGLE : loadSingle(getFd(opcode),pAddress); break; - case TRANSFER_DOUBLE : loadDouble(getFd(opcode),pAddress); break; - case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break; - default: nRc = 0; - } - - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return nRc; + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + switch (opcode & MASK_TRANSFER_LENGTH) { + case TRANSFER_SINGLE: + loadSingle(getFd(opcode), pAddress); + break; + case TRANSFER_DOUBLE: + loadDouble(getFd(opcode), pAddress); + break; +#ifdef CONFIG_FPE_NWFPE_XP + case TRANSFER_EXTENDED: + loadExtended(getFd(opcode), pAddress); + break; +#endif + default: + nRc = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return nRc; } unsigned int PerformSTF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1, - write_back = WRITE_BACK(opcode); - - //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); - SetRoundingMode(ROUND_TO_NEAREST); - - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - switch (opcode & MASK_TRANSFER_LENGTH) - { - case TRANSFER_SINGLE : storeSingle(getFd(opcode),pAddress); break; - case TRANSFER_DOUBLE : storeDouble(getFd(opcode),pAddress); break; - case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break; - default: nRc = 0; - } - - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return nRc; + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); + + SetRoundingMode(ROUND_TO_NEAREST); + + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + switch (opcode & MASK_TRANSFER_LENGTH) { + case TRANSFER_SINGLE: + storeSingle(getFd(opcode), pAddress); + break; + case TRANSFER_DOUBLE: + storeDouble(getFd(opcode), pAddress); + break; +#ifdef CONFIG_FPE_NWFPE_XP + case TRANSFER_EXTENDED: + storeExtended(getFd(opcode), pAddress); + break; +#endif + default: + nRc = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return nRc; } unsigned int PerformLFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal, - write_back = WRITE_BACK(opcode); - - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - Fd = getFd(opcode); - for (i=getRegisterCount(opcode);i>0;i--) - { - loadMultiple(Fd,pAddress); - pAddress += 3; Fd++; - if (Fd == 8) Fd = 0; - } + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return 1; + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + Fd = getFd(opcode); + for (i = getRegisterCount(opcode); i > 0; i--) { + loadMultiple(Fd, pAddress); + pAddress += 3; + Fd++; + if (Fd == 8) + Fd = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return 1; } unsigned int PerformSFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal, - write_back = WRITE_BACK(opcode); - - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - Fd = getFd(opcode); - for (i=getRegisterCount(opcode);i>0;i--) - { - storeMultiple(Fd,pAddress); - pAddress += 3; Fd++; - if (Fd == 8) Fd = 0; - } + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return 1; + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + Fd = getFd(opcode); + for (i = getRegisterCount(opcode); i > 0; i--) { + storeMultiple(Fd, pAddress); + pAddress += 3; + Fd++; + if (Fd == 8) + Fd = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return 1; } -#if 1 unsigned int EmulateCPDT(const unsigned int opcode) { - unsigned int nRc = 0; + unsigned int nRc = 0; - //printk("EmulateCPDT(0x%08x)\n",opcode); - - if (LDF_OP(opcode)) - { - nRc = PerformLDF(opcode); - } - else if (LFM_OP(opcode)) - { - nRc = PerformLFM(opcode); - } - else if (STF_OP(opcode)) - { - nRc = PerformSTF(opcode); - } - else if (SFM_OP(opcode)) - { - nRc = PerformSFM(opcode); - } - else - { - nRc = 0; - } - - return nRc; + if (LDF_OP(opcode)) { + nRc = PerformLDF(opcode); + } else if (LFM_OP(opcode)) { + nRc = PerformLFM(opcode); + } else if (STF_OP(opcode)) { + nRc = PerformSTF(opcode); + } else if (SFM_OP(opcode)) { + nRc = PerformSFM(opcode); + } else { + nRc = 0; + } + + return nRc; } -#endif diff -urN orig/arch/arm/nwfpe/fpa11_cprt.c linux/arch/arm/nwfpe/fpa11_cprt.c --- orig/arch/arm/nwfpe/fpa11_cprt.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/fpa11_cprt.c Sat Mar 29 19:35:46 2003 @@ -1,7 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 - (c) Philip Blundell, 1999 + (c) Philip Blundell, 1999, 2001 Direct questions, comments to Scott Bambrough @@ -21,269 +21,348 @@ */ #include "fpa11.h" -#include "milieu.h" -#include "softfloat.h" #include "fpopcode.h" #include "fpa11.inl" #include "fpmodule.h" #include "fpmodule.inl" +#ifdef CONFIG_FPE_NWFPE_XP extern flag floatx80_is_nan(floatx80); -extern flag float64_is_nan( float64); -extern flag float32_is_nan( float32); +#endif +extern flag float64_is_nan(float64); +extern flag float32_is_nan(float32); void SetRoundingMode(const unsigned int opcode); unsigned int PerformFLT(const unsigned int opcode); unsigned int PerformFIX(const unsigned int opcode); -static unsigned int -PerformComparison(const unsigned int opcode); +static unsigned int PerformComparison(const unsigned int opcode); unsigned int EmulateCPRT(const unsigned int opcode) { - unsigned int nRc = 1; - - //printk("EmulateCPRT(0x%08x)\n",opcode); - if (opcode & 0x800000) - { - /* This is some variant of a comparison (PerformComparison will - sort out which one). Since most of the other CPRT - instructions are oddball cases of some sort or other it makes - sense to pull this out into a fast path. */ - return PerformComparison(opcode); - } - - /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ - switch ((opcode & 0x700000) >> 20) - { - case FLT_CODE >> 20: nRc = PerformFLT(opcode); break; - case FIX_CODE >> 20: nRc = PerformFIX(opcode); break; - - case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break; - case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break; - -#if 0 /* We currently have no use for the FPCR, so there's no point - in emulating it. */ - case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode))); - case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break; -#endif + if (opcode & 0x800000) { + /* This is some variant of a comparison (PerformComparison + will sort out which one). Since most of the other CPRT + instructions are oddball cases of some sort or other it + makes sense to pull this out into a fast path. */ + return PerformComparison(opcode); + } + + /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ + switch ((opcode & 0x700000) >> 20) { + case FLT_CODE >> 20: + return PerformFLT(opcode); + break; + case FIX_CODE >> 20: + return PerformFIX(opcode); + break; + + case WFS_CODE >> 20: + writeFPSR(readRegister(getRd(opcode))); + break; + case RFS_CODE >> 20: + writeRegister(getRd(opcode), readFPSR()); + break; + + default: + return 0; + } - default: nRc = 0; - } - - return nRc; + return 1; } unsigned int PerformFLT(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - - unsigned int nRc = 1; - SetRoundingMode(opcode); - - switch (opcode & MASK_ROUNDING_PRECISION) - { - case ROUND_SINGLE: - { - fpa11->fType[getFn(opcode)] = typeSingle; - fpa11->fpreg[getFn(opcode)].fSingle = - int32_to_float32(readRegister(getRd(opcode))); - } - break; - - case ROUND_DOUBLE: - { - fpa11->fType[getFn(opcode)] = typeDouble; - fpa11->fpreg[getFn(opcode)].fDouble = - int32_to_float64(readRegister(getRd(opcode))); - } - break; - - case ROUND_EXTENDED: - { - fpa11->fType[getFn(opcode)] = typeExtended; - fpa11->fpreg[getFn(opcode)].fExtended = - int32_to_floatx80(readRegister(getRd(opcode))); - } - break; - - default: nRc = 0; - } - - return nRc; + FPA11 *fpa11 = GET_FPA11(); + SetRoundingMode(opcode); + SetRoundingPrecision(opcode); + + switch (opcode & MASK_ROUNDING_PRECISION) { + case ROUND_SINGLE: + { + fpa11->fType[getFn(opcode)] = typeSingle; + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); + } + break; + + case ROUND_DOUBLE: + { + fpa11->fType[getFn(opcode)] = typeDouble; + fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode))); + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case ROUND_EXTENDED: + { + fpa11->fType[getFn(opcode)] = typeExtended; + fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode))); + } + break; +#endif + + default: + return 0; + } + + return 1; } unsigned int PerformFIX(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - unsigned int nRc = 1; - unsigned int Fn = getFm(opcode); - - SetRoundingMode(opcode); - - switch (fpa11->fType[Fn]) - { - case typeSingle: - { - writeRegister(getRd(opcode), - float32_to_int32(fpa11->fpreg[Fn].fSingle)); - } - break; - - case typeDouble: - { - writeRegister(getRd(opcode), - float64_to_int32(fpa11->fpreg[Fn].fDouble)); - } - break; - - case typeExtended: - { - writeRegister(getRd(opcode), - floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); - } - break; - - default: nRc = 0; - } - - return nRc; -} + FPA11 *fpa11 = GET_FPA11(); + unsigned int Fn = getFm(opcode); - -static unsigned int __inline__ -PerformComparisonOperation(floatx80 Fn, floatx80 Fm) -{ - unsigned int flags = 0; + SetRoundingMode(opcode); - /* test for less than condition */ - if (floatx80_lt(Fn,Fm)) - { - flags |= CC_NEGATIVE; - } - - /* test for equal condition */ - if (floatx80_eq(Fn,Fm)) - { - flags |= CC_ZERO; - } - - /* test for greater than or equal condition */ - if (floatx80_lt(Fm,Fn)) - { - flags |= CC_CARRY; - } - - writeConditionCodes(flags); - return 1; + switch (fpa11->fType[Fn]) { + case typeSingle: + { + writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle)); + } + break; + + case typeDouble: + { + writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble)); + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + { + writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); + } + break; +#endif + + default: + return 0; + } + + return 1; } /* This instruction sets the flags N, Z, C, V in the FPSR. */ - static unsigned int PerformComparison(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - unsigned int Fn, Fm; - floatx80 rFn, rFm; - int e_flag = opcode & 0x400000; /* 1 if CxFE */ - int n_flag = opcode & 0x200000; /* 1 if CNxx */ - unsigned int flags = 0; - - //printk("PerformComparison(0x%08x)\n",opcode); - - Fn = getFn(opcode); - Fm = getFm(opcode); - - /* Check for unordered condition and convert all operands to 80-bit - format. - ?? Might be some mileage in avoiding this conversion if possible. - Eg, if both operands are 32-bit, detect this and do a 32-bit - comparison (cheaper than an 80-bit one). */ - switch (fpa11->fType[Fn]) - { - case typeSingle: - //printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fn].fSingle)) - goto unordered; - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - //printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fn].fDouble)) - goto unordered; - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); - break; - - case typeExtended: - //printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended)) - goto unordered; - rFn = fpa11->fpreg[Fn].fExtended; - break; - - default: return 0; - } - - if (CONSTANT_FM(opcode)) - { - //printk("Fm is a constant: #%d.\n",Fm); - rFm = getExtendedConstant(Fm); - if (floatx80_is_nan(rFm)) - goto unordered; - } - else - { - //printk("Fm = r%d which contains a ",Fm); - switch (fpa11->fType[Fm]) - { - case typeSingle: - //printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fm].fSingle)) - goto unordered; - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); - break; - - case typeDouble: - //printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fm].fDouble)) - goto unordered; - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); - break; - - case typeExtended: - //printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended)) - goto unordered; - rFm = fpa11->fpreg[Fm].fExtended; - break; - - default: return 0; - } - } - - if (n_flag) - { - rFm.high ^= 0x8000; - } - - return PerformComparisonOperation(rFn,rFm); - - unordered: - /* ?? The FPA data sheet is pretty vague about this, in particular - about whether the non-E comparisons can ever raise exceptions. - This implementation is based on a combination of what it says in - the data sheet, observation of how the Acorn emulator actually - behaves (and how programs expect it to) and guesswork. */ - flags |= CC_OVERFLOW; - flags &= ~(CC_ZERO | CC_NEGATIVE); + FPA11 *fpa11 = GET_FPA11(); + unsigned int Fn = getFn(opcode), Fm = getFm(opcode); + int e_flag = opcode & 0x400000; /* 1 if CxFE */ + int n_flag = opcode & 0x200000; /* 1 if CNxx */ + unsigned int flags = 0; + +#ifdef CONFIG_FPE_NWFPE_XP + floatx80 rFn, rFm; + + /* Check for unordered condition and convert all operands to 80-bit + format. + ?? Might be some mileage in avoiding this conversion if possible. + Eg, if both operands are 32-bit, detect this and do a 32-bit + comparison (cheaper than an 80-bit one). */ + switch (fpa11->fType[Fn]) { + case typeSingle: + //printk("single.\n"); + if (float32_is_nan(fpa11->fpreg[Fn].fSingle)) + goto unordered; + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + //printk("double.\n"); + if (float64_is_nan(fpa11->fpreg[Fn].fDouble)) + goto unordered; + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); + break; + + case typeExtended: + //printk("extended.\n"); + if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended)) + goto unordered; + rFn = fpa11->fpreg[Fn].fExtended; + break; + + default: + return 0; + } + + if (CONSTANT_FM(opcode)) { + //printk("Fm is a constant: #%d.\n",Fm); + rFm = getExtendedConstant(Fm); + if (floatx80_is_nan(rFm)) + goto unordered; + } else { + //printk("Fm = r%d which contains a ",Fm); + switch (fpa11->fType[Fm]) { + case typeSingle: + //printk("single.\n"); + if (float32_is_nan(fpa11->fpreg[Fm].fSingle)) + goto unordered; + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); + break; + + case typeDouble: + //printk("double.\n"); + if (float64_is_nan(fpa11->fpreg[Fm].fDouble)) + goto unordered; + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); + break; + + case typeExtended: + //printk("extended.\n"); + if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended)) + goto unordered; + rFm = fpa11->fpreg[Fm].fExtended; + break; + + default: + return 0; + } + } + + if (n_flag) + rFm.high ^= 0x8000; + + /* test for less than condition */ + if (floatx80_lt(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (floatx80_eq(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (floatx80_lt(rFm, rFn)) + flags |= CC_CARRY; + +#else + if (CONSTANT_FM(opcode)) { + /* Fm is a constant. Do the comparison in whatever precision + Fn happens to be stored in. */ + if (fpa11->fType[Fn] == typeSingle) { + float32 rFm = getSingleConstant(Fm); + float32 rFn = fpa11->fpreg[Fn].fSingle; + + if (float32_is_nan(rFn)) + goto unordered; + + if (n_flag) + rFm ^= 0x80000000; + + /* test for less than condition */ + if (float32_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float32_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float32_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } else { + float64 rFm = getDoubleConstant(Fm); + float64 rFn = fpa11->fpreg[Fn].fDouble; + + if (float64_is_nan(rFn)) + goto unordered; + + if (n_flag) + rFm ^= 0x8000000000000000ULL; + + /* test for less than condition */ + if (float64_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float64_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float64_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } + } else { + /* Both operands are in registers. */ + if (fpa11->fType[Fn] == typeSingle + && fpa11->fType[Fm] == typeSingle) { + float32 rFm = fpa11->fpreg[Fm].fSingle; + float32 rFn = fpa11->fpreg[Fn].fSingle; + + if (float32_is_nan(rFn) + || float32_is_nan(rFm)) + goto unordered; + + if (n_flag) + rFm ^= 0x80000000; + + /* test for less than condition */ + if (float32_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float32_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float32_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } else { + /* Promote 32-bit operand to 64 bits. */ + float64 rFm, rFn; + + rFm = (fpa11->fType[Fm] == typeSingle) ? + float32_to_float64(fpa11->fpreg[Fm].fSingle) + : fpa11->fpreg[Fm].fDouble; + + rFn = (fpa11->fType[Fn] == typeSingle) ? + float32_to_float64(fpa11->fpreg[Fn].fSingle) + : fpa11->fpreg[Fn].fDouble; + + if (float64_is_nan(rFn) + || float64_is_nan(rFm)) + goto unordered; + + if (n_flag) + rFm ^= 0x8000000000000000ULL; + + /* test for less than condition */ + if (float64_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float64_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float64_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } + } + +#endif + + writeConditionCodes(flags); + + return 1; + + unordered: + /* ?? The FPA data sheet is pretty vague about this, in particular + about whether the non-E comparisons can ever raise exceptions. + This implementation is based on a combination of what it says in + the data sheet, observation of how the Acorn emulator actually + behaves (and how programs expect it to) and guesswork. */ + flags |= CC_OVERFLOW; + flags &= ~(CC_ZERO | CC_NEGATIVE); - if (BIT_AC & readFPSR()) flags |= CC_CARRY; + if (BIT_AC & readFPSR()) + flags |= CC_CARRY; - if (e_flag) float_raise(float_flag_invalid); + if (e_flag) + float_raise(float_flag_invalid); - writeConditionCodes(flags); - return 1; + writeConditionCodes(flags); + return 1; } diff -urN orig/arch/arm/nwfpe/fpmodule.c linux/arch/arm/nwfpe/fpmodule.c --- orig/arch/arm/nwfpe/fpmodule.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/fpmodule.c Sat Mar 29 19:35:46 2003 @@ -41,13 +41,19 @@ #include "fpa11.inl" /* kernel symbols required for signal handling */ -typedef struct task_struct* PTASK; +typedef struct task_struct *PTASK; + +#ifdef CONFIG_FPE_NWFPE_XP +#define NWFPE_BITS "extended" +#else +#define NWFPE_BITS "double" +#endif #ifdef MODULE void fp_send_sig(unsigned long sig, PTASK p, int priv); #if LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Scott Bambrough "); -MODULE_DESCRIPTION("NWFPE floating point emulator"); +MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)"); #endif #else @@ -63,7 +69,7 @@ /* external declarations for saved kernel symbols */ extern void (*kern_fp_enter)(void); -/* Original value of fp_enter from kernel before patched by fpe_init. */ +/* Original value of fp_enter from kernel before patched by fpe_init. */ static void (*orig_fp_enter)(void); /* forward declarations */ @@ -76,46 +82,45 @@ */ static int fpe_unload(void) { - return (kern_fp_enter == nwfpe_enter) ? 0 : 1; + return (kern_fp_enter == nwfpe_enter) ? 0 : 1; } #endif static int __init fpe_init(void) { - if (sizeof(FPA11) > sizeof(union fp_state)) { - printk(KERN_ERR "nwfpe: bad structure size\n"); - return -EINVAL; - } - - if (sizeof(FPREG) != 12) { - printk(KERN_ERR "nwfpe: bad register size\n"); - return -EINVAL; - } - + if (sizeof(FPA11) > sizeof(union fp_state)) { + printk(KERN_ERR "nwfpe: bad structure size\n"); + return -EINVAL; + } + + if (sizeof(FPREG) != 12) { + printk(KERN_ERR "nwfpe: bad register size\n"); + return -EINVAL; + } #ifdef MODULE - if (!mod_member_present(&__this_module, can_unload)) - return -EINVAL; - __this_module.can_unload = fpe_unload; + if (!mod_member_present(&__this_module, can_unload)) + return -EINVAL; + __this_module.can_unload = fpe_unload; #else - if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) - return 0; + if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) + return 0; #endif - /* Display title, version and copyright information. */ - printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 " - "(c) 1998-1999 Rebel.com\n"); - - /* Save pointer to the old FP handler and then patch ourselves in */ - orig_fp_enter = kern_fp_enter; - kern_fp_enter = nwfpe_enter; + /* Display title, version and copyright information. */ + printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 (" + NWFPE_BITS " precision)\n"); + + /* Save pointer to the old FP handler and then patch ourselves in */ + orig_fp_enter = kern_fp_enter; + kern_fp_enter = nwfpe_enter; - return 0; + return 0; } static void __exit fpe_exit(void) { - /* Restore the values we saved earlier. */ - kern_fp_enter = orig_fp_enter; + /* Restore the values we saved earlier. */ + kern_fp_enter = orig_fp_enter; } /* @@ -140,41 +145,42 @@ void float_raise(signed char flags) { - register unsigned int fpsr, cumulativeTraps; - + register unsigned int fpsr, cumulativeTraps; + #ifdef CONFIG_DEBUG_USER - printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", - current->comm, current->pid, flags, - __builtin_return_address(0), GET_USERREG()[15]); -#endif - - /* Keep SoftFloat exception flags up to date. */ - float_exception_flags |= flags; - - /* Read fpsr and initialize the cumulativeTraps. */ - fpsr = readFPSR(); - cumulativeTraps = 0; - - /* For each type of exception, the cumulative trap exception bit is only - set if the corresponding trap enable bit is not set. */ - if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC)) - cumulativeTraps |= BIT_IXC; - if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC)) - cumulativeTraps |= BIT_UFC; - if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC)) - cumulativeTraps |= BIT_OFC; - if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC)) - cumulativeTraps |= BIT_DZC; - if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC)) - cumulativeTraps |= BIT_IOC; - - /* Set the cumulative exceptions flags. */ - if (cumulativeTraps) - writeFPSR(fpsr | cumulativeTraps); - - /* Raise an exception if necessary. */ - if (fpsr & (flags << 16)) - fp_send_sig(SIGFPE, current, 1); + printk(KERN_DEBUG + "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", + current->comm, current->pid, flags, + __builtin_return_address(0), GET_USERREG()[15]); +#endif + + /* Keep SoftFloat exception flags up to date. */ + float_exception_flags |= flags; + + /* Read fpsr and initialize the cumulativeTraps. */ + fpsr = readFPSR(); + cumulativeTraps = 0; + + /* For each type of exception, the cumulative trap exception bit is only + set if the corresponding trap enable bit is not set. */ + if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC)) + cumulativeTraps |= BIT_IXC; + if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC)) + cumulativeTraps |= BIT_UFC; + if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC)) + cumulativeTraps |= BIT_OFC; + if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC)) + cumulativeTraps |= BIT_DZC; + if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC)) + cumulativeTraps |= BIT_IOC; + + /* Set the cumulative exceptions flags. */ + if (cumulativeTraps) + writeFPSR(fpsr | cumulativeTraps); + + /* Raise an exception if necessary. */ + if (fpsr & (flags << 16)) + fp_send_sig(SIGFPE, current, 1); } module_init(fpe_init); diff -urN orig/arch/arm/nwfpe/fpmodule.inl linux/arch/arm/nwfpe/fpmodule.inl --- orig/arch/arm/nwfpe/fpmodule.inl Mon Sep 3 14:14:41 2001 +++ linux/arch/arm/nwfpe/fpmodule.inl Sat Mar 29 18:42:59 2003 @@ -22,63 +22,64 @@ extern __inline__ unsigned int readRegister(const unsigned int nReg) { - /* Note: The CPU thinks it has dealt with the current instruction. As - a result the program counter has been advanced to the next - instruction, and points 4 bytes beyond the actual instruction - that caused the invalid instruction trap to occur. We adjust - for this in this routine. LDF/STF instructions with Rn = PC - depend on the PC being correct, as they use PC+8 in their - address calculations. */ - unsigned int *userRegisters = GET_USERREG(); - unsigned int val = userRegisters[nReg]; - if (REG_PC == nReg) val -= 4; - return val; + /* Note: The CPU thinks it has dealt with the current instruction. + As a result the program counter has been advanced to the next + instruction, and points 4 bytes beyond the actual instruction + that caused the invalid instruction trap to occur. We adjust + for this in this routine. LDF/STF instructions with Rn = PC + depend on the PC being correct, as they use PC+8 in their + address calculations. */ + unsigned int *userRegisters = GET_USERREG(); + unsigned int val = userRegisters[nReg]; + if (REG_PC == nReg) + val -= 4; + return val; } extern __inline__ void writeRegister(const unsigned int nReg, const unsigned int val) { - unsigned int *userRegisters = GET_USERREG(); - userRegisters[nReg] = val; + unsigned int *userRegisters = GET_USERREG(); + userRegisters[nReg] = val; } extern __inline__ unsigned int readCPSR(void) { - return(readRegister(REG_CPSR)); + return (readRegister(REG_CPSR)); } extern __inline__ void writeCPSR(const unsigned int val) { - writeRegister(REG_CPSR,val); + writeRegister(REG_CPSR, val); } extern __inline__ unsigned int readConditionCodes(void) { #ifdef __FPEM_TEST__ - return(0); + return (0); #else - return(readCPSR() & CC_MASK); + return (readCPSR() & CC_MASK); #endif } extern __inline__ void writeConditionCodes(const unsigned int val) { - unsigned int *userRegisters = GET_USERREG(); - unsigned int rval; - /* - * Operate directly on userRegisters since - * the CPSR may be the PC register itself. - */ - rval = userRegisters[REG_CPSR] & ~CC_MASK; - userRegisters[REG_CPSR] = rval | (val & CC_MASK); + unsigned int *userRegisters = GET_USERREG(); + unsigned int rval; + /* + * Operate directly on userRegisters since + * the CPSR may be the PC register itself. + */ + rval = userRegisters[REG_CPSR] & ~CC_MASK; + userRegisters[REG_CPSR] = rval | (val & CC_MASK); } extern __inline__ unsigned int readMemoryInt(unsigned int *pMem) { - return *pMem; + return *pMem; } diff -urN orig/arch/arm/nwfpe/fpopcode.c linux/arch/arm/nwfpe/fpopcode.c --- orig/arch/arm/nwfpe/fpopcode.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/fpopcode.c Sat Mar 29 20:30:11 2003 @@ -26,123 +26,64 @@ #include "fpmodule.h" #include "fpmodule.inl" +#ifdef CONFIG_FPE_NWFPE_XP const floatx80 floatx80Constant[] = { - { 0x0000, 0x0000000000000000ULL}, /* extended 0.0 */ - { 0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */ - { 0x4000, 0x8000000000000000ULL}, /* extended 2.0 */ - { 0x4000, 0xc000000000000000ULL}, /* extended 3.0 */ - { 0x4001, 0x8000000000000000ULL}, /* extended 4.0 */ - { 0x4001, 0xa000000000000000ULL}, /* extended 5.0 */ - { 0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */ - { 0x4002, 0xa000000000000000ULL} /* extended 10.0 */ -}; + {0x0000, 0x0000000000000000ULL}, /* extended 0.0 */ + {0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */ + {0x4000, 0x8000000000000000ULL}, /* extended 2.0 */ + {0x4000, 0xc000000000000000ULL}, /* extended 3.0 */ + {0x4001, 0x8000000000000000ULL}, /* extended 4.0 */ + {0x4001, 0xa000000000000000ULL}, /* extended 5.0 */ + {0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */ + {0x4002, 0xa000000000000000ULL} /* extended 10.0 */ +}; +#endif const float64 float64Constant[] = { - 0x0000000000000000ULL, /* double 0.0 */ - 0x3ff0000000000000ULL, /* double 1.0 */ - 0x4000000000000000ULL, /* double 2.0 */ - 0x4008000000000000ULL, /* double 3.0 */ - 0x4010000000000000ULL, /* double 4.0 */ - 0x4014000000000000ULL, /* double 5.0 */ - 0x3fe0000000000000ULL, /* double 0.5 */ - 0x4024000000000000ULL /* double 10.0 */ -}; + 0x0000000000000000ULL, /* double 0.0 */ + 0x3ff0000000000000ULL, /* double 1.0 */ + 0x4000000000000000ULL, /* double 2.0 */ + 0x4008000000000000ULL, /* double 3.0 */ + 0x4010000000000000ULL, /* double 4.0 */ + 0x4014000000000000ULL, /* double 5.0 */ + 0x3fe0000000000000ULL, /* double 0.5 */ + 0x4024000000000000ULL /* double 10.0 */ +}; const float32 float32Constant[] = { - 0x00000000, /* single 0.0 */ - 0x3f800000, /* single 1.0 */ - 0x40000000, /* single 2.0 */ - 0x40400000, /* single 3.0 */ - 0x40800000, /* single 4.0 */ - 0x40a00000, /* single 5.0 */ - 0x3f000000, /* single 0.5 */ - 0x41200000 /* single 10.0 */ -}; - -unsigned int getTransferLength(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_TRANSFER_LENGTH) - { - case 0x00000000: nRc = 1; break; /* single precision */ - case 0x00008000: nRc = 2; break; /* double precision */ - case 0x00400000: nRc = 3; break; /* extended precision */ - default: nRc = 0; - } - - return(nRc); -} - -unsigned int getRegisterCount(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_REGISTER_COUNT) - { - case 0x00000000: nRc = 4; break; - case 0x00008000: nRc = 1; break; - case 0x00400000: nRc = 2; break; - case 0x00408000: nRc = 3; break; - default: nRc = 0; - } - - return(nRc); -} - -unsigned int getRoundingPrecision(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_ROUNDING_PRECISION) - { - case 0x00000000: nRc = 1; break; - case 0x00000080: nRc = 2; break; - case 0x00080000: nRc = 3; break; - default: nRc = 0; - } - - return(nRc); -} - -unsigned int getDestinationSize(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_DESTINATION_SIZE) - { - case 0x00000000: nRc = typeSingle; break; - case 0x00000080: nRc = typeDouble; break; - case 0x00080000: nRc = typeExtended; break; - default: nRc = typeNone; - } - - return(nRc); -} + 0x00000000, /* single 0.0 */ + 0x3f800000, /* single 1.0 */ + 0x40000000, /* single 2.0 */ + 0x40400000, /* single 3.0 */ + 0x40800000, /* single 4.0 */ + 0x40a00000, /* single 5.0 */ + 0x3f000000, /* single 0.5 */ + 0x41200000 /* single 10.0 */ +}; /* condition code lookup table index into the table is test code: EQ, NE, ... LT, GT, AL, NV bit position in short is condition code: NZCV */ static const unsigned short aCC[16] = { - 0xF0F0, // EQ == Z set - 0x0F0F, // NE - 0xCCCC, // CS == C set - 0x3333, // CC - 0xFF00, // MI == N set - 0x00FF, // PL - 0xAAAA, // VS == V set - 0x5555, // VC - 0x0C0C, // HI == C set && Z clear - 0xF3F3, // LS == C clear || Z set - 0xAA55, // GE == (N==V) - 0x55AA, // LT == (N!=V) - 0x0A05, // GT == (!Z && (N==V)) - 0xF5FA, // LE == (Z || (N!=V)) - 0xFFFF, // AL always - 0 // NV + 0xF0F0, // EQ == Z set + 0x0F0F, // NE + 0xCCCC, // CS == C set + 0x3333, // CC + 0xFF00, // MI == N set + 0x00FF, // PL + 0xAAAA, // VS == V set + 0x5555, // VC + 0x0C0C, // HI == C set && Z clear + 0xF3F3, // LS == C clear || Z set + 0xAA55, // GE == (N==V) + 0x55AA, // LT == (N!=V) + 0x0A05, // GT == (!Z && (N==V)) + 0xF5FA, // LE == (Z || (N!=V)) + 0xFFFF, // AL always + 0 // NV }; unsigned int checkCondition(const unsigned int opcode, const unsigned int ccodes) { - return (aCC[opcode>>28] >> (ccodes>>28)) & 1; + return (aCC[opcode >> 28] >> (ccodes >> 28)) & 1; } diff -urN orig/arch/arm/nwfpe/fpopcode.h linux/arch/arm/nwfpe/fpopcode.h --- orig/arch/arm/nwfpe/fpopcode.h Sat Apr 28 11:24:54 2001 +++ linux/arch/arm/nwfpe/fpopcode.h Sat Mar 29 20:30:11 2003 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -26,7 +27,7 @@ ARM Floating Point Instruction Classes | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT -|c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|0|1| o f f s e t | CPDT +|c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT @@ -34,7 +35,7 @@ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | CPDT data transfer instructions - LDF, STF, LFM, SFM + LDF, STF, LFM (copro 2), SFM (copro 2) CPDO dyadic arithmetic instructions ADF, MUF, SUF, RSF, DVF, RDF, @@ -186,7 +187,7 @@ #define BIT_LOAD 0x00100000 /* masks for load/store */ -#define MASK_CPDT 0x0c000000 /* data processing opcode */ +#define MASK_CPDT 0x0c000000 /* data processing opcode */ #define MASK_OFFSET 0x000000ff #define MASK_TRANSFER_LENGTH 0x00408000 #define MASK_REGISTER_COUNT MASK_TRANSFER_LENGTH @@ -236,7 +237,7 @@ #define MONADIC_INSTRUCTION(opcode) ((opcode & BIT_MONADIC) != 0) /* instruction identification masks */ -#define MASK_CPDO 0x0e000000 /* arithmetic opcode */ +#define MASK_CPDO 0x0e000000 /* arithmetic opcode */ #define MASK_ARITHMETIC_OPCODE 0x00f08000 #define MASK_DESTINATION_SIZE 0x00080080 @@ -282,7 +283,7 @@ === */ -#define MASK_CPRT 0x0e000010 /* register transfer opcode */ +#define MASK_CPRT 0x0e000010 /* register transfer opcode */ #define MASK_CPRT_CODE 0x00f00000 #define FLT_CODE 0x00000000 #define FIX_CODE 0x00100000 @@ -366,25 +367,111 @@ /* Get the rounding mode from the opcode. */ #define getRoundingMode(opcode) ((opcode & MASK_ROUNDING_MODE) >> 5) +#ifdef CONFIG_FPE_NWFPE_XP static inline const floatx80 getExtendedConstant(const unsigned int nIndex) { - extern const floatx80 floatx80Constant[]; - return floatx80Constant[nIndex]; -} + extern const floatx80 floatx80Constant[]; + return floatx80Constant[nIndex]; +} +#endif static inline const float64 getDoubleConstant(const unsigned int nIndex) { - extern const float64 float64Constant[]; - return float64Constant[nIndex]; -} + extern const float64 float64Constant[]; + return float64Constant[nIndex]; +} static inline const float32 getSingleConstant(const unsigned int nIndex) { - extern const float32 float32Constant[]; - return float32Constant[nIndex]; -} + extern const float32 float32Constant[]; + return float32Constant[nIndex]; +} + +static inline unsigned int getTransferLength(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_TRANSFER_LENGTH) { + case 0x00000000: + nRc = 1; + break; /* single precision */ + case 0x00008000: + nRc = 2; + break; /* double precision */ + case 0x00400000: + nRc = 3; + break; /* extended precision */ + default: + nRc = 0; + } + + return (nRc); +} + +static inline unsigned int getRegisterCount(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_REGISTER_COUNT) { + case 0x00000000: + nRc = 4; + break; + case 0x00008000: + nRc = 1; + break; + case 0x00400000: + nRc = 2; + break; + case 0x00408000: + nRc = 3; + break; + default: + nRc = 0; + } + + return (nRc); +} + +static inline unsigned int getRoundingPrecision(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_ROUNDING_PRECISION) { + case 0x00000000: + nRc = 1; + break; + case 0x00000080: + nRc = 2; + break; + case 0x00080000: + nRc = 3; + break; + default: + nRc = 0; + } + + return (nRc); +} + +static inline unsigned int getDestinationSize(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_DESTINATION_SIZE) { + case 0x00000000: + nRc = typeSingle; + break; + case 0x00000080: + nRc = typeDouble; + break; + case 0x00080000: + nRc = typeExtended; + break; + default: + nRc = typeNone; + } -extern unsigned int getRegisterCount(const unsigned int opcode); -extern unsigned int getDestinationSize(const unsigned int opcode); + return (nRc); +} #endif diff -urN orig/arch/arm/nwfpe/fpsr.h linux/arch/arm/nwfpe/fpsr.h --- orig/arch/arm/nwfpe/fpsr.h Tue Feb 15 00:12:16 2000 +++ linux/arch/arm/nwfpe/fpsr.h Sat Mar 29 18:42:59 2003 @@ -38,12 +38,12 @@ ------------ Note: the system id byte is read only */ -typedef unsigned int FPSR; /* type for floating point status register */ -typedef unsigned int FPCR; /* type for floating point control register */ +typedef unsigned int FPSR; /* type for floating point status register */ +typedef unsigned int FPCR; /* type for floating point control register */ #define MASK_SYSID 0xff000000 #define BIT_HARDWARE 0x80000000 -#define FP_EMULATOR 0x01000000 /* System ID for emulator */ +#define FP_EMULATOR 0x01000000 /* System ID for emulator */ #define FP_ACCELERATOR 0x81000000 /* System ID for FPA11 */ /* EXCEPTION TRAP ENABLE BYTE @@ -51,11 +51,11 @@ #define MASK_TRAP_ENABLE 0x00ff0000 #define MASK_TRAP_ENABLE_STRICT 0x001f0000 -#define BIT_IXE 0x00100000 /* inexact exception enable */ -#define BIT_UFE 0x00080000 /* underflow exception enable */ -#define BIT_OFE 0x00040000 /* overflow exception enable */ -#define BIT_DZE 0x00020000 /* divide by zero exception enable */ -#define BIT_IOE 0x00010000 /* invalid operation exception enable */ +#define BIT_IXE 0x00100000 /* inexact exception enable */ +#define BIT_UFE 0x00080000 /* underflow exception enable */ +#define BIT_OFE 0x00040000 /* overflow exception enable */ +#define BIT_DZE 0x00020000 /* divide by zero exception enable */ +#define BIT_IOE 0x00010000 /* invalid operation exception enable */ /* SYSTEM CONTROL BYTE ---------------------- */ diff -urN orig/arch/arm/nwfpe/single_cpdo.c linux/arch/arm/nwfpe/single_cpdo.c --- orig/arch/arm/nwfpe/single_cpdo.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/single_cpdo.c Sat Mar 29 18:54:42 2003 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -32,224 +33,92 @@ float32 float32_log(float32 rFm); float32 float32_tan(float32 rFm); float32 float32_arccos(float32 rFm); -float32 float32_pow(float32 rFn,float32 rFm); -float32 float32_pol(float32 rFn,float32 rFm); +float32 float32_pow(float32 rFn, float32 rFm); +float32 float32_pol(float32 rFn, float32 rFm); -unsigned int SingleCPDO(const unsigned int opcode) +static float32 float32_rsf(float32 rFn, float32 rFm) { - FPA11 *fpa11 = GET_FPA11(); - float32 rFm, rFn; - unsigned int Fd, Fm, Fn, nRc = 1; - - Fm = getFm(opcode); - if (CONSTANT_FM(opcode)) - { - rFm = getSingleConstant(Fm); - } - else - { - switch (fpa11->fType[Fm]) - { - case typeSingle: - rFm = fpa11->fpreg[Fm].fSingle; - break; - - default: return 0; - } - } - - if (!MONADIC_INSTRUCTION(opcode)) - { - Fn = getFn(opcode); - switch (fpa11->fType[Fn]) - { - case typeSingle: - rFn = fpa11->fpreg[Fn].fSingle; - break; - - default: return 0; - } - } - - Fd = getFd(opcode); - switch (opcode & MASK_ARITHMETIC_OPCODE) - { - /* dyadic opcodes */ - case ADF_CODE: - fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm); - break; - - case MUF_CODE: - case FML_CODE: - fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm); - break; - - case SUF_CODE: - fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm); - break; - - case RSF_CODE: - fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn); - break; - - case DVF_CODE: - case FDV_CODE: - fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm); - break; - - case RDF_CODE: - case FRD_CODE: - fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn); - break; - -#if 0 - case POW_CODE: - fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm); - break; - - case RPW_CODE: - fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn); - break; -#endif - - case RMF_CODE: - fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm); - break; - -#if 0 - case POL_CODE: - fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm); - break; -#endif - - /* monadic opcodes */ - case MVF_CODE: - fpa11->fpreg[Fd].fSingle = rFm; - break; - - case MNF_CODE: - rFm ^= 0x80000000; - fpa11->fpreg[Fd].fSingle = rFm; - break; - - case ABS_CODE: - rFm &= 0x7fffffff; - fpa11->fpreg[Fd].fSingle = rFm; - break; - - case RND_CODE: - case URD_CODE: - fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm); - break; - - case SQT_CODE: - fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm); - break; - -#if 0 - case LOG_CODE: - fpa11->fpreg[Fd].fSingle = float32_log(rFm); - break; - - case LGN_CODE: - fpa11->fpreg[Fd].fSingle = float32_ln(rFm); - break; - - case EXP_CODE: - fpa11->fpreg[Fd].fSingle = float32_exp(rFm); - break; - - case SIN_CODE: - fpa11->fpreg[Fd].fSingle = float32_sin(rFm); - break; - - case COS_CODE: - fpa11->fpreg[Fd].fSingle = float32_cos(rFm); - break; - - case TAN_CODE: - fpa11->fpreg[Fd].fSingle = float32_tan(rFm); - break; - - case ASN_CODE: - fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm); - break; - - case ACS_CODE: - fpa11->fpreg[Fd].fSingle = float32_arccos(rFm); - break; - - case ATN_CODE: - fpa11->fpreg[Fd].fSingle = float32_arctan(rFm); - break; -#endif - - case NRM_CODE: - break; - - default: - { - nRc = 0; - } - } - - if (0 != nRc) fpa11->fType[Fd] = typeSingle; - return nRc; + return float32_sub(rFm, rFn); } -#if 0 -float32 float32_exp(float32 Fm) +static float32 float32_rdv(float32 rFn, float32 rFm) { -//series + return float32_div(rFm, rFn); } -float32 float32_ln(float32 Fm) -{ -//series -} +static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { + [ADF_CODE >> 20] = float32_add, + [MUF_CODE >> 20] = float32_mul, + [SUF_CODE >> 20] = float32_sub, + [RSF_CODE >> 20] = float32_rsf, + [DVF_CODE >> 20] = float32_div, + [RDF_CODE >> 20] = float32_rdv, + [RMF_CODE >> 20] = float32_rem, -float32 float32_sin(float32 rFm) -{ -//series -} + [FML_CODE >> 20] = float32_mul, + [FDV_CODE >> 20] = float32_div, + [FRD_CODE >> 20] = float32_rdv, +}; -float32 float32_cos(float32 rFm) +static float32 float32_mvf(float32 rFm) { -//series + return rFm; } -float32 float32_arcsin(float32 rFm) +static float32 float32_mnf(float32 rFm) { -//series + return rFm ^ 0x80000000; } -float32 float32_arctan(float32 rFm) +static float32 float32_abs(float32 rFm) { - //series + return rFm & 0x7fffffff; } -float32 float32_arccos(float32 rFm) -{ - //return float32_sub(halfPi,float32_arcsin(rFm)); -} +static float32 (*const monadic_single[16])(float32 rFm) = { + [MVF_CODE >> 20] = float32_mvf, + [MNF_CODE >> 20] = float32_mnf, + [ABS_CODE >> 20] = float32_abs, + [RND_CODE >> 20] = float32_round_to_int, + [URD_CODE >> 20] = float32_round_to_int, + [SQT_CODE >> 20] = float32_sqrt, + [NRM_CODE >> 20] = float32_mvf, +}; -float32 float32_log(float32 rFm) +unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) { - return float32_div(float32_ln(rFm),getSingleConstant(7)); -} + FPA11 *fpa11 = GET_FPA11(); + float32 rFm; + unsigned int Fm, opc_mask_shift; -float32 float32_tan(float32 rFm) -{ - return float32_div(float32_sin(rFm),float32_cos(rFm)); -} + Fm = getFm(opcode); + if (CONSTANT_FM(opcode)) { + rFm = getSingleConstant(Fm); + } else if (fpa11->fType[Fm] == typeSingle) { + rFm = fpa11->fpreg[Fm].fSingle; + } else { + return 0; + } -float32 float32_pow(float32 rFn,float32 rFm) -{ - return float32_exp(float32_mul(rFm,float32_ln(rFn))); -} + opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + if (!MONADIC_INSTRUCTION(opcode)) { + unsigned int Fn = getFn(opcode); + float32 rFn; -float32 float32_pol(float32 rFn,float32 rFm) -{ - return float32_arctan(float32_div(rFn,rFm)); + if (fpa11->fType[Fn] == typeSingle && + dyadic_single[opc_mask_shift]) { + rFn = fpa11->fpreg[Fn].fSingle; + rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm); + } else { + return 0; + } + } else { + if (monadic_single[opc_mask_shift]) { + rFd->fSingle = monadic_single[opc_mask_shift](rFm); + } else { + return 0; + } + } + + return 1; } -#endif diff -urN orig/arch/arm/nwfpe/softfloat.c linux/arch/arm/nwfpe/softfloat.c --- orig/arch/arm/nwfpe/softfloat.c Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/softfloat.c Sat Mar 29 19:35:47 2003 @@ -29,8 +29,8 @@ */ #include "fpa11.h" -#include "milieu.h" -#include "softfloat.h" +//#include "milieu.h" +//#include "softfloat.h" /* ------------------------------------------------------------------------------- @@ -142,12 +142,14 @@ Returns the sign bit of the single-precision floating-point value `a'. ------------------------------------------------------------------------------- */ +#if 0 /* in softfloat.h */ INLINE flag extractFloat32Sign( float32 a ) { return a>>31; } +#endif /* ------------------------------------------------------------------------------- @@ -184,9 +186,9 @@ { #if 0 float32 f; - __asm__("@ packFloat32; - mov %0, %1, asl #31; - orr %0, %2, asl #23; + __asm__("@ packFloat32 \n\ + mov %0, %1, asl #31 \n\ + orr %0, %2, asl #23 \n\ orr %0, %3" : /* no outputs */ : "g" (f), "g" (zSign), "g" (zExp), "g" (zSig) @@ -321,12 +323,14 @@ Returns the sign bit of the double-precision floating-point value `a'. ------------------------------------------------------------------------------- */ +#if 0 /* in softfloat.h */ INLINE flag extractFloat64Sign( float64 a ) { return a>>63; } +#endif /* ------------------------------------------------------------------------------- diff -urN orig/arch/arm/nwfpe/softfloat.h linux/arch/arm/nwfpe/softfloat.h --- orig/arch/arm/nwfpe/softfloat.h Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/nwfpe/softfloat.h Sat Mar 29 19:35:47 2003 @@ -40,7 +40,9 @@ input or output the `floatx80' type will be defined. ------------------------------------------------------------------------------- */ +#ifdef CONFIG_FPE_NWFPE_XP #define FLOATX80 +#endif /* ------------------------------------------------------------------------------- @@ -229,4 +231,46 @@ #endif +static inline flag extractFloat32Sign(float32 a) +{ + return a >> 31; +} + +static inline flag float32_eq_nocheck(float32 a, float32 b) +{ + return (a == b) || ((bits32) ((a | b) << 1) == 0); +} + +static inline flag float32_lt_nocheck(float32 a, float32 b) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign(a); + bSign = extractFloat32Sign(b); + if (aSign != bSign) + return aSign && ((bits32) ((a | b) << 1) != 0); + return (a != b) && (aSign ^ (a < b)); +} + +static inline flag extractFloat64Sign(float64 a) +{ + return a >> 63; +} + +static inline flag float64_eq_nocheck(float64 a, float64 b) +{ + return (a == b) || ((bits64) ((a | b) << 1) == 0); +} + +static inline flag float64_lt_nocheck(float64 a, float64 b) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign(a); + bSign = extractFloat64Sign(b); + if (aSign != bSign) + return aSign && ((bits64) ((a | b) << 1) != 0); + return (a != b) && (aSign ^ (a < b)); +} + #endif diff -urN orig/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types --- orig/arch/arm/tools/mach-types Mon Aug 5 13:29:47 2002 +++ linux/arch/arm/tools/mach-types Wed Jul 16 16:34:01 2003 @@ -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 Mar 16 15:56:27 2002 +# Last update: Wed Jul 16 16:34:00 2003 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -71,7 +71,7 @@ jupiter SA1100_JUPITER JUPITER 59 psionw ARCH_PSIONW PSIONW 60 aln SA1100_ALN ALN 61 -epxa10db ARCH_CAMELOT CAMELOT 62 +epxa ARCH_CAMELOT CAMELOT 62 gds2200 SA1100_GDS2200 GDS2200 63 psion_series7 SA1100_PSION_SERIES7 PSION_SERIES7 64 xfile SA1100_XFILE XFILE 65 @@ -149,12 +149,12 @@ blue_v1 ARCH_BLUE_V1 BLUE_V1 138 pxa_cerf ARCH_PXA_CERF PXA_CERF 139 arm7tevb ARCH_ARM7TEVB ARM7TEVB 140 -d7400 ARCH_D7400 D7400 141 +d7400 SA1100_D7400 D7400 141 piranha ARCH_PIRANHA PIRANHA 142 sbcamelot SA1100_SBCAMELOT SBCAMELOT 143 kings SA1100_KINGS KINGS 144 smdk2400 ARCH_SMDK2400 SMDK2400 145 -collie ARCH_COLLIE COLLIE 146 +collie SA1100_COLLIE COLLIE 146 idr ARCH_IDR IDR 147 badge4 SA1100_BADGE4 BADGE4 148 webnet ARCH_WEBNET WEBNET 149 @@ -175,6 +175,191 @@ iam SA1100_IAM IAM 164 tt530 SA1100_TT530 TT530 165 sam2400 ARCH_SAM2400 SAM2400 166 -jornada56x ARCH_JORNADA56X JORNADA56X 167 +jornada56x SA1100_JORNADA56X JORNADA56X 167 active SA1100_ACTIVE ACTIVE 168 iq80321 ARCH_IQ80321 IQ80321 169 +wid SA1100_WID WID 170 +sabinal ARCH_SABINAL SABINAL 171 +ixp425_matacumbe ARCH_IXP425_MATACUMBE IXP425_MATACUMBE 172 +miniprint SA1100_MINIPRINT MINIPRINT 173 +adm510x ARCH_ADM510X ADM510X 174 +svs200 SA1100_SVS200 SVS200 175 +atg_tcu ARCH_ATG_TCU ATG_TCU 176 +jornada820 SA1100_JORNADA820 JORNADA820 177 +s3c44b0 ARCH_S3C44B0 S3C44B0 178 +margis2 ARCH_MARGIS2 MARGIS2 179 +ks8695 ARCH_KS8695 KS8695 180 +brh ARCH_BRH BRH 181 +s3c2410 ARCH_S3C2410 S3C2410 182 +possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183 +s3c2800 ARCH_S3C2800 S3C2800 184 +fleetwood SA1100_FLEETWOOD FLEETWOOD 185 +omaha ARCH_OMAHA OMAHA 186 +ta7 ARCH_TA7 TA7 187 +nova SA1100_NOVA NOVA 188 +hmk ARCH_HMK HMK 189 +karo ARCH_KARO KARO 190 +fester SA1100_FESTER FESTER 191 +gpi ARCH_GPI GPI 192 +smdk2410 ARCH_SMDK2410 SMDK2410 193 +premium ARCH_PREMIUM PREMIUM 194 +nexio SA1100_NEXIO NEXIO 195 +bitbox SA1100_BITBOX BITBOX 196 +g200 SA1100_G200 G200 197 +gill SA1100_GILL GILL 198 +pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199 +ceiva ARCH_CEIVA CEIVA 200 +fret SA1100_FRET FRET 201 +emailphone SA1100_EMAILPHONE EMAILPHONE 202 +h3900 ARCH_H3900 H3900 203 +pxa1 ARCH_PXA1 PXA1 204 +koan369 SA1100_KOAN369 KOAN369 205 +cogent ARCH_COGENT COGENT 206 +esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207 +esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208 +esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209 +hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210 +he500 ARCH_HE500 HE500 211 +inhandelf2 SA1100_INHANDELF2 INHANDELF2 212 +inhandftip SA1100_INHANDFTIP INHANDFTIP 213 +dnp1110 SA1100_DNP1110 DNP1110 214 +pnp1110 SA1100_PNP1110 PNP1110 215 +csb226 ARCH_CSB226 CSB226 216 +arnold SA1100_ARNOLD ARNOLD 217 +psiboard SA1100_PSIBOARD PSIBOARD 218 +jz8028 ARCH_JZ8028 JZ8028 219 +h5400 ARCH_IPAQ3 IPAQ3 220 +forte SA1100_FORTE FORTE 221 +acam SA1100_ACAM ACAM 222 +abox SA1100_ABOX ABOX 223 +atmel ARCH_ATMEL ATMEL 224 +sitsang ARCH_SITSANG SITSANG 225 +cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226 +mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227 +opus_a1 ARCH_OPUS_A1 OPUS_A1 228 +daytona ARCH_DAYTONA DAYTONA 229 +killbear SA1100_KILLBEAR KILLBEAR 230 +yoho ARCH_YOHO YOHO 231 +jasper ARCH_JASPER JASPER 232 +dsc25 ARCH_DSC25 DSC25 233 +innovator ARCH_INNOVATOR INNOVATOR 234 +ramses ARCH_RAMSES RAMSES 235 +s28x ARCH_S28X S28X 236 +mport3 ARCH_MPORT3 MPORT3 237 +pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 +pdb ARCH_PDB PDB 239 +blue_2g SA1100_BLUE_2G BLUE_2G 240 +bluearch SA1100_BLUEARCH BLUEARCH 241 +ixdp2400 ARCH_IXMB2400 IXMB2400 242 +ixdp2800 ARCH_IXMB2800 IXMB2800 243 +explorer SA1100_EXPLORER EXPLORER 244 +ixdp425 ARCH_IXDP425 IXDP425 245 +chimp ARCH_CHIMP CHIMP 246 +stork_nest ARCH_STORK_NEST STORK_NEST 247 +stork_egg ARCH_STORK_EGG STORK_EGG 248 +wismo SA1100_WISMO WISMO 249 +ezlinx ARCH_EZLINX EZLINX 250 +at91rm9200 ARCH_AT91 AT91 251 +orion ARCH_ORION ORION 252 +neptune ARCH_NEPTUNE NEPTUNE 253 +hackkit SA1100_HACKKIT HACKKIT 254 +pxa_wins30 ARCH_PXA_WINS30 PXA_WINS30 255 +lavinna SA1100_LAVINNA LAVINNA 256 +pxa_uengine ARCH_PXA_UENGINE PXA_UENGINE 257 +innokom ARCH_INNOKOM INNOKOM 258 +bms ARCH_BMS BMS 259 +ixcdp1100 ARCH_IXCDP1100 IXCDP1100 260 +prpmc1100 ARCH_PRPMC1100 PRPMC1100 261 +at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262 +armstick ARCH_ARMSTICK ARMSTICK 263 +armonie ARCH_ARMONIE ARMONIE 264 +mport1 ARCH_MPORT1 MPORT1 265 +s3c5410 ARCH_S3C5410 S3C5410 266 +zcp320a ARCH_ZCP320A ZCP320A 267 +i_box ARCH_I_BOX I_BOX 268 +stlc1502 ARCH_STLC1502 STLC1502 269 +siren ARCH_SIREN SIREN 270 +greenlake ARCH_GREENLAKE GREENLAKE 271 +argus ARCH_ARGUS ARGUS 272 +combadge SA1100_COMBADGE COMBADGE 273 +rokepxa ARCH_ROKEPXA ROKEPXA 274 +cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275 +guidea07 ARCH_GUIDEA07 GUIDEA07 276 +tat257 ARCH_TAT257 TAT257 277 +igp2425 ARCH_IGP2425 IGP2425 278 +bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279 +ipod ARCH_IPOD IPOD 280 +adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281 +trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282 +viper ARCH_VIPER VIPER 283 +adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 +adsagc SA1100_ADSAGC ADSAGC 285 +stp7312 ARCH_STP7312 STP7312 286 +nx_phnx ARCH_PXA255 PXA255 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 +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 +nwlarm ARCH_NWLARM NWLARM 296 +ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297 +pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298 +ixdp2401 ARCH_IXDP2401 IXDP2401 299 +ixdp2801 ARCH_IXDP2801 IXDP2801 300 +zodiac ARCH_ZODIAC ZODIAC 301 +armmodul ARCH_ARMMODUL ARMMODUL 302 +ketop SA1100_KETOP KETOP 303 +av7200 ARCH_AV7200 AV7200 304 +arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305 +acq200 ARCH_ACQ200 ACQ200 306 +pt_dafit SA1100_PT_DAFIT PT_DAFIT 307 +ihba ARCH_IHBA IHBA 308 +quinque ARCH_QUINQUE QUINQUE 309 +nimbraone ARCH_NIMBRAONE NIMBRAONE 310 +nimbra29x ARCH_NIMBRA29X NIMBRA29X 311 +nimbra210 ARCH_NIMBRA210 NIMBRA210 312 +hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313 +labarm ARCH_LABARM LABARM 314 +m825xx ARCH_M825XX M825XX 315 +m7100 SA1100_M7100 M7100 316 +nipc2 ARCH_NIPC2 NIPC2 317 +fu7202 ARCH_FU7202 FU7202 318 +adsagx ARCH_ADSAGX ADSAGX 319 +pxa_pooh ARCH_PXA_POOH PXA_POOH 320 +bandon ARCH_BANDON BANDON 321 +pcm7210 ARCH_PCM7210 PCM7210 322 +nms9200 ARCH_NMS9200 NMS9200 323 +logodl ARCH_LOGODL LOGODL 324 +m7140 SA1100_M7140 M7140 325 +korebot ARCH_KOREBOT KOREBOT 326 +iq31244 ARCH_IQ31244 IQ31244 327 +koan393 SA1100_KOAN393 KOAN393 328 +inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329 +gonzo ARCH_GONZO GONZO 330 +bast ARCH_BAST BAST 331 +scanpass ARCH_SCANPASS SCANPASS 332 +ep7312_pooh ARCH_EP7312_POOH EP7312_POOH 333 +ta7s ARCH_TA7S TA7S 334 +ta7v ARCH_TA7V TA7V 335 +icarus SA1100_ICARUS ICARUS 336 +h1900 ARCH_H1900 H1900 337 +gemini SA1100_GEMINI GEMINI 338 +axim ARCH_AXIM AXIM 339 +audiotron ARCH_AUDIOTRON AUDIOTRON 340 +h2200 ARCH_H2200 H2200 341 +loox600 ARCH_LOOX600 LOOX600 342 +niop ARCH_NIOP NIOP 343 +dm310 ARCH_DM310 DM310 344 +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 diff -urN orig/arch/i386/config.in linux/arch/i386/config.in --- orig/arch/i386/config.in Tue Jun 24 13:57:45 2003 +++ linux/arch/i386/config.in Tue Jun 24 11:16:27 2003 @@ -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 -urN orig/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- orig/arch/i386/kernel/Makefile Wed Jun 18 13:01:06 2003 +++ linux/arch/i386/kernel/Makefile Wed Jun 18 09:56:32 2003 @@ -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 -urN orig/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- orig/arch/i386/kernel/apm.c Tue Jun 24 13:57:45 2003 +++ linux/arch/i386/kernel/apm.c Tue Jun 24 11:16:27 2003 @@ -1265,6 +1265,7 @@ as->suspend_wait = 0; as->suspend_result = err; } + ignore_normal_resume = 1; wake_up_interruptible(&apm_suspend_waitqueue); return err; } @@ -1317,6 +1318,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 -urN orig/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile --- orig/arch/i386/lib/Makefile Mon Oct 1 23:10:05 2001 +++ linux/arch/i386/lib/Makefile Sun Aug 12 17:52:40 2001 @@ -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 -urN orig/arch/i386/math-emu/Makefile linux/arch/i386/math-emu/Makefile --- orig/arch/i386/math-emu/Makefile Sun Dec 31 22:12:08 2000 +++ linux/arch/i386/math-emu/Makefile Sun Dec 17 22:31:38 2000 @@ -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 -urN orig/arch/ia64/config.in linux/arch/ia64/config.in --- orig/arch/ia64/config.in Tue Jun 24 13:57:46 2003 +++ linux/arch/ia64/config.in Tue Jun 24 11:16:28 2003 @@ -25,6 +25,7 @@ define_bool CONFIG_SBUS n define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n +define_bool CONFIG_GENERIC_ISA_DMA y choice 'IA-64 processor type' \ "Itanium CONFIG_ITANIUM \ diff -urN orig/arch/m68k/config.in linux/arch/m68k/config.in --- orig/arch/m68k/config.in Tue Jun 24 13:57:53 2003 +++ linux/arch/m68k/config.in Tue Jun 24 11:16:41 2003 @@ -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 -urN orig/arch/mips/config.in linux/arch/mips/config.in --- orig/arch/mips/config.in Wed Jun 18 13:01:12 2003 +++ linux/arch/mips/config.in Wed Jun 18 10:15:05 2003 @@ -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 -urN orig/arch/parisc/config.in linux/arch/parisc/config.in --- orig/arch/parisc/config.in Wed Jun 18 13:01:22 2003 +++ linux/arch/parisc/config.in Wed Jun 18 09:57:12 2003 @@ -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 -urN orig/arch/ppc/config.in linux/arch/ppc/config.in --- orig/arch/ppc/config.in Tue Jun 24 13:57:58 2003 +++ linux/arch/ppc/config.in Tue Jun 24 11:16:52 2003 @@ -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 -urN orig/arch/sh/config.in linux/arch/sh/config.in --- orig/arch/sh/config.in Tue Jun 24 13:58:07 2003 +++ linux/arch/sh/config.in Tue Jun 24 11:17:14 2003 @@ -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 -urN orig/arch/sparc/config.in linux/arch/sparc/config.in --- orig/arch/sparc/config.in Tue Jun 24 13:58:07 2003 +++ linux/arch/sparc/config.in Tue Jun 24 11:17:14 2003 @@ -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 -urN orig/arch/sparc64/config.in linux/arch/sparc64/config.in --- orig/arch/sparc64/config.in Wed Jun 18 13:01:37 2003 +++ linux/arch/sparc64/config.in Wed Jun 18 09:57:50 2003 @@ -37,6 +37,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 -urN orig/drivers/Makefile linux/drivers/Makefile --- orig/drivers/Makefile Wed Jun 18 13:01:45 2003 +++ linux/drivers/Makefile Wed Jun 18 10:09:41 2003 @@ -8,9 +8,9 @@ mod-subdirs := dio hil mtd sbus video macintosh usb input telephony sgi ide \ message/i2o message/fusion scsi md ieee1394 pnp isdn atm \ - fc4 net/hamradio i2c acpi bluetooth + fc4 net/hamradio i2c l3 acpi bluetooth serial -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) += acpi subdir-$(CONFIG_BLUEZ) += bluetooth +subdir-$(CONFIG_SSI) += ssi + +subdir-$(CONFIG_ARCH_AT91RM9200)+= at91 include $(TOPDIR)/Rules.make diff -urN orig/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c --- orig/drivers/acorn/block/fd1772.c Wed Jun 18 13:01:45 2003 +++ linux/drivers/acorn/block/fd1772.c Wed Jun 18 10:22:15 2003 @@ -1567,26 +1567,26 @@ int fd1772_init(void) { - int err; - int i; + int i, err; if (!machine_is_archimedes()) return 0; - if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { + err = register_blkdev(MAJOR_NR, "fd", &floppy_fops); + if (err) { printk("Unable to get major %d for floppy\n", MAJOR_NR); - return 1; + goto err_out; } + err = -EBUSY; if (request_dma(FLOPPY_DMA, "fd1772")) { printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA); - return 1; + goto err_blkdev; }; if (request_dma(FIQ_FD1772, "fd1772 end")) { printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772); - err = 1; /* XXX */ - goto cleanup_dma; + goto err_dma1; }; /* initialize variables */ @@ -1596,16 +1596,15 @@ BufferDrive = BufferSide = BufferTrack = -1; /* Atari uses 512 - I want to eventually cope with 1K sectors */ DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL); - if (DMABuffer == NULL) - goto cleanup_dma; TrackBuffer = DMABuffer + 512; #else /* Allocate memory for the DMAbuffer - on the Atari this takes it out of some special memory... */ DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */ - if (DMABuffer == NULL) - goto cleanup_dma; #endif + if (DMABuffer == NULL) + goto err_dma2; + enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */ for (i = 0; i < FD_MAX_UNITS; i++) { unit[i].track = -1; @@ -1624,7 +1623,13 @@ config_types(); return 0; -cleanup_dma: + + err_dma2: + free_dma(FIQ_FD1772); + err_dma1: free_dma(FLOPPY_DMA); + err_blkdev: + unregister_blkdev(MAJOR_NR, &floppy_fops); + err_out: return err; } diff -urN orig/drivers/acorn/char/Makefile linux/drivers/acorn/char/Makefile --- orig/drivers/acorn/char/Makefile Mon Sep 3 14:14:43 2001 +++ linux/drivers/acorn/char/Makefile Fri Dec 20 17:03:01 2002 @@ -24,7 +24,9 @@ obj-arc := keyb_arc.o obj-rpc := keyb_ps2.o obj-clps7500 := keyb_ps2.o defkeymap-acorn.o +obj-riscstation := keyb_ps2.o defkeymap-acorn.o +obj-$(CONFIG_7K5MOUSE) += mouse_ps2.o obj-$(CONFIG_RPCMOUSE) += mouse_rpc.o obj-$(CONFIG_ATOMWIDE_SERIAL) += serial-atomwide.o obj-$(CONFIG_DUALSP_SERIAL) += serial-dualsp.o diff -urN orig/drivers/acorn/char/i2c.c linux/drivers/acorn/char/i2c.c --- orig/drivers/acorn/char/i2c.c Sat Mar 31 23:47:19 2001 +++ linux/drivers/acorn/char/i2c.c Thu Jan 3 10:29:48 2002 @@ -14,6 +14,9 @@ */ #include #include +#include +#include +#include #include #include @@ -21,15 +24,19 @@ #include #include #include +#include #include "pcf8583.h" -extern unsigned long -mktime(unsigned int year, unsigned int mon, unsigned int day, - unsigned int hour, unsigned int min, unsigned int sec); extern int (*set_rtc)(void); 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) +#define CMOS_YEAR (64 + 128) static inline int rtc_command(int cmd, void *data) { @@ -44,12 +51,10 @@ /* * Read the current RTC time and date, and update xtime. */ -static void get_rtc_time(void) +static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year) { - unsigned char ctrl; - unsigned char year; - struct rtc_tm rtctm; - struct mem rtcmem = { 0xc0, 1, &year }; + unsigned char ctrl, yr[2]; + struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr }; /* * Ensure that the RTC is running. @@ -73,22 +78,53 @@ if (rtc_command(MEM_READ, &rtcmem)) return; - if (rtc_command(RTC_GETDATETIME, &rtctm)) + if (rtc_command(RTC_GETDATETIME, rtctm)) return; - if (year < 70) - year += 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 }; + int ret; + + leap = (!(year % 4) && (year % 100)) || !(year % 400); + + if (rtctm->mon > 12 || rtctm->mday == 0) + return -EINVAL; + + if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap))) + return -EINVAL; + + if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60) + return -EINVAL; - xtime.tv_usec = rtctm.cs * 10000; - xtime.tv_sec = mktime(1900 + year, rtctm.mon, rtctm.mday, - rtctm.hours, rtctm.mins, rtctm.secs); + 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; + + chk += yr[1] + yr[0]; + + rtc_command(MEM_WRITE, &cmos_year); + rtc_command(MEM_WRITE, &cmos_check); + } + return ret; } /* * Set the RTC time only. Note that * we do not touch the date. */ -static int set_rtc_time(void) +static int k_set_rtc_time(void) { struct rtc_tm new_rtctm, old_rtctm; unsigned long nowtime = xtime.tv_sec; @@ -110,13 +146,70 @@ * [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00, * rtc gets set to 1/1/2000 00:01:00 ] */ - if ((old_rtctm.hours == 23 && old_rtctm.mins == 59) || - (new_rtctm.hours == 23 && new_rtctm.mins == 59)) + if ((old_rtctm.hours == 23 && old_rtctm.mins == 59) || + (new_rtctm.hours == 23 && new_rtctm.mins == 59)) return 1; return rtc_command(RTC_SETTIME, &new_rtctm); } +static int rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned int year; + struct rtc_time rtctm; + struct rtc_tm rtc_raw; + + switch (cmd) { + case RTC_ALM_READ: + case RTC_ALM_SET: + break; + + case RTC_RD_TIME: + get_rtc_time(&rtc_raw, &year); + rtctm.tm_sec = rtc_raw.secs; + rtctm.tm_min = rtc_raw.mins; + rtctm.tm_hour = rtc_raw.hours; + rtctm.tm_mday = rtc_raw.mday; + rtctm.tm_mon = rtc_raw.mon - 1; /* month starts at 0 */ + rtctm.tm_year = year - 1900; /* starts at 1900 */ + return copy_to_user((void *)arg, &rtctm, sizeof(rtctm)) + ? -EFAULT : 0; + + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtctm, (void *)arg, sizeof(rtctm))) + return -EFAULT; + rtc_raw.secs = rtctm.tm_sec; + rtc_raw.mins = rtctm.tm_min; + 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 -EINVAL; +} + +static struct file_operations rtc_fops = { + ioctl: rtc_ioctl, +}; + +static struct miscdevice rtc_dev = { + minor: RTC_MINOR, + name: "rtc", + fops: &rtc_fops, +}; + +/* IOC / IOMD i2c driver */ #define FORCE_ONES 0xdc #define SCL 0x02 @@ -184,9 +277,16 @@ { if (client->id == I2C_DRIVERID_PCF8583 && client->addr == 0x50) { + struct rtc_tm rtctm; + unsigned int year; + rtc_client = client; - get_rtc_time(); - set_rtc = set_rtc_time; + get_rtc_time(&rtctm, &year); + + xtime.tv_usec = rtctm.cs * 10000; + xtime.tv_sec = mktime(year, rtctm.mon, rtctm.mday, + rtctm.hours, rtctm.mins, rtctm.secs); + set_rtc = k_set_rtc_time; } return 0; @@ -212,9 +312,16 @@ static int __init i2c_ioc_init(void) { + int ret; + force_ones = FORCE_ONES | SCL | SDA; - return i2c_bit_add_bus(&ioc_ops); + ret = i2c_bit_add_bus(&ioc_ops); + + if (ret >= 0) + misc_register(&rtc_dev); + + return ret; } __initcall(i2c_ioc_init); diff -urN orig/drivers/acorn/char/keyb_arc.c linux/drivers/acorn/char/keyb_arc.c --- orig/drivers/acorn/char/keyb_arc.c Mon Sep 3 14:14:43 2001 +++ linux/drivers/acorn/char/keyb_arc.c Mon Aug 27 18:06:17 2001 @@ -419,12 +419,51 @@ disable_irq(irq); } +static int a5kkbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + return -EINVAL; +} + +static int a5kkbd_getkeycode(unsigned int scancode) +{ + return -EINVAL; +} + +static int a5kkbd_translate(unsigned char scancode, unsigned char *keycode, char rawmode) +{ + *keycode = scancode; + return 1; +} + +static char a5kkbd_unexpected_up(unsigned char keycode) +{ + return 0200; +} + +static int a5kkbd_rate(struct kbd_repeat *rep) +{ + return -EINVAL; +} + #ifdef CONFIG_KBDMOUSE static struct busmouse a5kkbd_mouse = { 6, "kbdmouse", NULL, NULL, NULL, 7 }; #endif +struct kbd_ops_struct a5k_kbd_ops = { + k_setkeycode: a5kkbd_setkeycode, + k_getkeycode: a5kkbd_getkeycode, + k_translate: a5kkbd_translate, + k_unexpected_up: a5kkbd_unexpected_up, + k_leds: a5kkbd_leds, + k_rate: a5kkbd_rate, +#ifdef CONFIG_MAGIC_SYSRQ + k_sysrq_xlate: a5kkbd_sysrq_xlate, + k_sysrq_key: 13, +#endif +}; + void __init a5kkbd_init_hw (void) { if (request_irq (IRQ_KEYBOARDTX, a5kkbd_tx, 0, "keyboard", NULL) != 0) diff -urN orig/drivers/acorn/char/mouse_ps2.c linux/drivers/acorn/char/mouse_ps2.c --- orig/drivers/acorn/char/mouse_ps2.c Wed Jun 18 13:01:45 2003 +++ linux/drivers/acorn/char/mouse_ps2.c Wed Jun 18 09:58:01 2003 @@ -1,8 +1,6 @@ /* * Driver for PS/2 mouse on IOMD interface */ - -#include #include #include #include @@ -294,3 +292,6 @@ return 0; } + +module_init(psaux_init); + diff -urN orig/drivers/acorn/char/serial-atomwide.c linux/drivers/acorn/char/serial-atomwide.c --- orig/drivers/acorn/char/serial-atomwide.c Tue Oct 3 20:08:24 2000 +++ linux/drivers/acorn/char/serial-atomwide.c Wed Jun 25 16:17:56 2003 @@ -12,15 +12,28 @@ * 07-05-1996 RMK Altered for greater number of cards. * 30-07-1996 RMK Now uses generic card code. */ -#define MY_CARD_LIST { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL } -#define MY_NUMPORTS 3 -#define MY_BAUD_BASE (7372800 / 16) -#define MY_BASE_ADDRESS(ec) \ - ecard_address ((ec), ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2) -#define MY_PORT_ADDRESS(port,cardaddr) \ - ((cardaddr) + 0x200 - (port) * 0x100) +#include +#include -#define INIT serial_card_atomwide_init -#define EXIT serial_card_atomwide_exit +#define MAX_PORTS 3 + +struct serial_card_type { + unsigned int num_ports; + unsigned int baud_base; + unsigned int type; + unsigned int offset[MAX_PORTS]; +}; + +static struct serial_card_type atomwide_type = { + .num_ports = 3, + .baud_base = 7372800 / 16, + .type = ECARD_RES_IOCSLOW, + .offset = { 0x2800, 0x2400, 0x2000 }, +}; + +static const struct ecard_id serial_cids[] = { + { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, &atomwide_type }, + { 0xffff, 0xffff } +}; #include "serial-card.c" diff -urN orig/drivers/acorn/char/serial-card.c linux/drivers/acorn/char/serial-card.c --- orig/drivers/acorn/char/serial-card.c Mon Oct 1 23:10:27 2001 +++ linux/drivers/acorn/char/serial-card.c Wed Jun 25 16:17:18 2003 @@ -27,106 +27,110 @@ */ #include #include -#include +#include +#include #include +#include +#include #include +#include #include #include -#ifndef NUM_SERIALS -#define NUM_SERIALS MY_NUMPORTS * MAX_ECARDS -#endif - -#ifdef MODULE -static int __serial_ports[NUM_SERIALS]; -static int __serial_pcount; -static int __serial_addr[NUM_SERIALS]; -static struct expansion_card *expcard[MAX_ECARDS]; -#define ADD_ECARD(ec,card) expcard[(card)] = (ec) -#define ADD_PORT(port,addr) \ - do { \ - __serial_ports[__serial_pcount] = (port); \ - __serial_addr[__serial_pcount] = (addr); \ - __serial_pcount += 1; \ - } while (0) -#else -#define ADD_ECARD(ec,card) -#define ADD_PORT(port,addr) -#endif +struct serial_card_info { + unsigned int num_ports; + int ports[MAX_PORTS]; +}; -static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } }; - -static inline int serial_register_onedev (unsigned long port, int irq) +static inline int +serial_register_onedev(unsigned long baddr, void *vaddr, int irq, unsigned int baud_base) { - struct serial_struct req; + struct serial_struct req; - memset(&req, 0, sizeof(req)); - req.baud_base = MY_BAUD_BASE; - req.irq = irq; - req.port = port; - req.flags = 0; + memset(&req, 0, sizeof(req)); + req.irq = irq; + req.flags = UPF_AUTOPROBE | UPF_RESOURCES | + UPF_SHARE_IRQ; + req.baud_base = baud_base; + req.io_type = UPIO_MEM; + req.iomem_base = vaddr; + req.iomem_reg_shift = 2; + req.iomap_base = baddr; - return register_serial(&req); + return register_serial(&req); } -static int __init INIT (void) +static int __devinit +serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) { - int card = 0; - - ecard_startfind (); + struct serial_card_info *info; + struct serial_card_type *type = id->data; + unsigned long bus_addr; + unsigned char *virt_addr; + unsigned int port; + + info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + memset(info, 0, sizeof(struct serial_card_info)); + info->num_ports = type->num_ports; + + ecard_set_drvdata(ec, info); + + bus_addr = ec->resource[type->type].start; + virt_addr = ioremap(bus_addr, ec->resource[type->type].end - bus_addr + 1); + if (!virt_addr) { + kfree(info); + return -ENOMEM; + } - do { - struct expansion_card *ec; - unsigned long cardaddr; - int port; + for (port = 0; port < info->num_ports; port ++) { + unsigned long baddr = bus_addr + type->offset[port]; + unsigned char *vaddr = virt_addr + type->offset[port]; - ec = ecard_find (0, serial_cids); - if (!ec) - break; + info->ports[port] = serial_register_onedev(baddr, vaddr, + ec->irq, type->baud_base); + } - cardaddr = MY_BASE_ADDRESS(ec); + return 0; +} - for (port = 0; port < MY_NUMPORTS; port ++) { - unsigned long address; - int line; +static void __devexit serial_card_remove(struct expansion_card *ec) +{ + struct serial_card_info *info = ecard_get_drvdata(ec); + int i; - address = MY_PORT_ADDRESS(port, cardaddr); + ecard_set_drvdata(ec, NULL); - line = serial_register_onedev (address, ec->irq); - if (line < 0) - break; - ADD_PORT(line, address); - } + for (i = 0; i < info->num_ports; i++) + if (info->ports[i] > 0) + unregister_serial(info->ports[i]); - if (port) { - ecard_claim (ec); - ADD_ECARD(ec, card); - } else - break; - } while (++card < MAX_ECARDS); - return card ? 0 : -ENODEV; + kfree(info); } -static void __exit EXIT (void) +static struct ecard_driver serial_card_driver = { + .probe = serial_card_probe, + .remove = __devexit_p(serial_card_remove), + .id_table = serial_cids, +}; + +static int __init serial_card_init(void) { -#ifdef MODULE - int i; + return ecard_register_driver(&serial_card_driver); +} - for (i = 0; i < __serial_pcount; i++) { - unregister_serial(__serial_ports[i]); - release_region(__serial_addr[i], 8); - } - - for (i = 0; i < MAX_ECARDS; i++) - if (expcard[i]) - ecard_release (expcard[i]); -#endif +static void __exit serial_card_exit(void) +{ + ecard_remove_driver(&serial_card_driver); } EXPORT_NO_SYMBOLS; +MODULE_AUTHOR("Russell King"); MODULE_LICENSE("GPL"); -module_init(INIT); -module_exit(EXIT); +module_init(serial_card_init); +module_exit(serial_card_exit); diff -urN orig/drivers/acorn/char/serial-dualsp.c linux/drivers/acorn/char/serial-dualsp.c --- orig/drivers/acorn/char/serial-dualsp.c Tue Oct 3 20:08:24 2000 +++ linux/drivers/acorn/char/serial-dualsp.c Wed Jun 25 16:17:56 2003 @@ -10,15 +10,28 @@ * Changelog: * 30-07-1996 RMK Created */ -#define MY_CARD_LIST { MANU_SERPORT, PROD_SERPORT_DSPORT } -#define MY_NUMPORTS 2 -#define MY_BAUD_BASE (3686400 / 16) -#define MY_BASE_ADDRESS(ec) \ - ecard_address (ec, ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2) -#define MY_PORT_ADDRESS(port,cardaddress) \ - ((cardaddress) + (port) * 8) +#include +#include -#define INIT serial_card_dualsp_init -#define EXIT serial_card_dualsp_exit +#define MAX_PORTS 3 + +struct serial_card_type { + unsigned int num_ports; + unsigned int baud_base; + unsigned int type; + unsigned int offset[MAX_PORTS]; +}; + +static struct serial_card_type serport_type = { + .num_ports = 2, + .baud_base = 3686400 / 16, + .type = ECARD_RES_IOCSLOW, + .offset = { 0x2000, 0x2020 }, +}; + +static const struct ecard_id serial_cids[] = { + { MANU_SERPORT, PROD_SERPORT_DSPORT, &serport_type }, + { 0xffff, 0xffff } +}; #include "serial-card.c" diff -urN orig/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c --- orig/drivers/acorn/net/ether1.c Mon Oct 1 23:10:27 2001 +++ linux/drivers/acorn/net/ether1.c Wed Jul 16 10:05:22 2003 @@ -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 } }; @@ -647,6 +647,11 @@ { struct ether1_priv *priv = (struct ether1_priv *)dev->priv; + if (!is_valid_ether_addr(dev->dev_addr)) { + printk("%s: invalid ethernet MAC address\n", dev->name); + return -EINVAL; + } + if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev)) return -EAGAIN; @@ -684,7 +689,6 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) { struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - int len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr; unsigned long flags; tx_t tx; @@ -702,19 +706,25 @@ priv->restart = 0; } + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (!skb) + goto out; + } + /* * insert packet followed by a nop */ txaddr = ether1_txalloc (dev, TX_SIZE); tbdaddr = ether1_txalloc (dev, TBD_SIZE); - dataddr = ether1_txalloc (dev, len); + dataddr = ether1_txalloc (dev, skb->len); nopaddr = ether1_txalloc (dev, NOP_SIZE); tx.tx_status = 0; tx.tx_command = CMD_TX | CMD_INTR; tx.tx_link = nopaddr; tx.tx_tbdoffset = tbdaddr; - tbd.tbd_opts = TBD_EOL | len; + tbd.tbd_opts = TBD_EOL | skb->len; tbd.tbd_link = I82586_NULL; tbd.tbd_bufl = dataddr; tbd.tbd_bufh = 0; @@ -725,7 +735,7 @@ save_flags_cli(flags); ether1_writebuffer (dev, &tx, txaddr, TX_SIZE); ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE); - ether1_writebuffer (dev, skb->data, dataddr, len); + ether1_writebuffer (dev, skb->data, dataddr, skb->len); ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE); tmp = priv->tx_link; priv->tx_link = nopaddr; @@ -747,6 +757,7 @@ if (tst == -1) netif_stop_queue(dev); + out: return 0; } @@ -971,6 +982,23 @@ return &priv->stats; } +static int +ether1_set_mac_address(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + + if (netif_running(dev)) + return -EBUSY; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + /* + * We'll set the MAC address on the chip when we open it. + */ + + return 0; +} + /* * Set or clear the multicast filter for this adaptor. * num_addrs == -1 Promiscuous mode, receive all packets. @@ -1038,6 +1066,7 @@ dev->hard_start_xmit = ether1_sendpacket; dev->get_stats = ether1_getstats; dev->set_multicast_list = ether1_setmulticastlist; + dev->set_mac_address = ether1_set_mac_address; dev->tx_timeout = ether1_timeout; dev->watchdog_timeo = 5 * HZ / 100; return 0; diff -urN orig/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c --- orig/drivers/acorn/net/ether3.c Mon Oct 1 23:10:27 2001 +++ linux/drivers/acorn/net/ether3.c Wed Jul 16 10:05:22 2003 @@ -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 }, @@ -417,6 +417,9 @@ static int ether3_open(struct net_device *dev) { + if (!is_valid_ether_addr(dev->dev_addr)) + return -EINVAL; + if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) return -EAGAIN; @@ -460,6 +463,23 @@ return &priv->stats; } +static int +ether3_set_mac_address(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + + if (netif_running(dev)) + return -EBUSY; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + /* + * We'll set the MAC address on the chip when we open it. + */ + + return 0; +} + /* * Set or clear promiscuous/multicast mode filter for this adaptor. * @@ -531,6 +551,12 @@ return 0; } + if (skb->len != length) { + skb = skb_padto(skb, length); + if (!skb) + goto out; + } + next_ptr = (priv->tx_head + 1) & 15; save_flags_cli(flags); @@ -572,6 +598,7 @@ if (priv->tx_tail == next_ptr) netif_stop_queue(dev); + out: return 0; } @@ -718,7 +745,7 @@ /* * Don't print this message too many times... */ - if (jiffies - last_warned > 30 * HZ) { + if (time_after(jiffies, last_warned + 10 * HZ)) { last_warned = jiffies; printk("%s: memory squeeze, dropping packet.\n", dev->name); } @@ -875,6 +902,7 @@ dev->hard_start_xmit = ether3_sendpacket; dev->get_stats = ether3_getstats; dev->set_multicast_list = ether3_setmulticastlist; + dev->set_mac_address = ether3_set_mac_address; dev->tx_timeout = ether3_timeout; dev->watchdog_timeo = 5 * HZ / 100; return 0; diff -urN orig/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c --- orig/drivers/acorn/net/etherh.c Mon Aug 5 13:30:41 2002 +++ linux/drivers/acorn/net/etherh.c Wed Jul 16 10:05:22 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/acorn/net/etherh.c * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,6 +23,7 @@ * 12-10-1999 CK/TEW EtherM driver first release * 21-12-2000 TTC EtherH/EtherM integration * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver. + * 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot. */ #include @@ -56,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 }, @@ -64,13 +65,18 @@ { 0xffff, 0xffff } }; +struct etherh_priv { + unsigned int id; + unsigned int ctrl_port; + unsigned int ctrl; +}; MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("EtherH/EtherM driver"); MODULE_LICENSE("GPL"); static char version[] __initdata = - "EtherH/EtherM Driver (c) 2000 Russell King v1.08\n"; + "EtherH/EtherM Driver (c) 2002 Russell King v1.09\n"; #define ETHERH500_DATAPORT 0x200 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */ @@ -97,18 +103,61 @@ #define ETHERM_TX_START_PAGE 64 #define ETHERM_STOP_PAGE 127 -/* --------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ + +static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask) +{ + eh->ctrl |= mask; + outb(eh->ctrl, eh->ctrl_port); +} + +static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask) +{ + eh->ctrl &= ~mask; + outb(eh->ctrl, eh->ctrl_port); +} + +static inline unsigned int etherh_get_stat(struct etherh_priv *eh) +{ + return inb(eh->ctrl_port); +} + + + + +static void etherh_irq_enable(ecard_t *ec, int irqnr) +{ + struct etherh_priv *eh = ec->irq_data; + + etherh_set_ctrl(eh, ETHERH_CP_IE); +} + +static void etherh_irq_disable(ecard_t *ec, int irqnr) +{ + struct etherh_priv *eh = ec->irq_data; + + etherh_clr_ctrl(eh, ETHERH_CP_IE); +} + +static expansioncard_ops_t etherh_ops = { + irqenable: etherh_irq_enable, + irqdisable: etherh_irq_disable, +}; + + + static void etherh_setif(struct net_device *dev) { struct ei_device *ei_local = (struct ei_device *) dev->priv; + struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start; unsigned long addr, flags; save_flags_cli(flags); /* set the interface type */ - switch (dev->mem_end) { + switch (eh->id) { case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: addr = dev->base_addr + EN0_RCNTHI; @@ -124,14 +173,13 @@ break; case PROD_I3_ETHERLAN500: - addr = dev->rmem_start; - switch (dev->if_port) { case IF_PORT_10BASE2: - outb(inb(addr) & ~ETHERH_CP_IF, addr); + etherh_clr_ctrl(eh, ETHERH_CP_IF); break; + case IF_PORT_10BASET: - outb(inb(addr) | ETHERH_CP_IF, addr); + etherh_set_ctrl(eh, ETHERH_CP_IF); break; } break; @@ -147,9 +195,10 @@ etherh_getifstat(struct net_device *dev) { struct ei_device *ei_local = (struct ei_device *) dev->priv; + struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start; int stat = 0; - switch (dev->mem_end) { + switch (eh->id) { case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: switch (dev->if_port) { @@ -168,7 +217,7 @@ stat = 1; break; case IF_PORT_10BASET: - stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT; + stat = etherh_get_stat(eh) & ETHERH_CP_HEARTBEAT; break; } break; @@ -251,7 +300,13 @@ return; } - ei_local->dmaing |= 1; + /* + * Make sure we have a round number of bytes if we're in word mode. + */ + if (count & 1 && ei_local->word16) + count++; + + ei_local->dmaing = 1; addr = dev->base_addr; dma_addr = dev->mem_start; @@ -291,7 +346,7 @@ } outb (ENISR_RDC, addr + EN0_ISR); - ei_local->dmaing &= ~1; + ei_local->dmaing = 0; } /* @@ -311,7 +366,7 @@ return; } - ei_local->dmaing |= 1; + ei_local->dmaing = 1; addr = dev->base_addr; dma_addr = dev->mem_start; @@ -332,7 +387,7 @@ insb (dma_addr, buf, count); outb (ENISR_RDC, addr + EN0_ISR); - ei_local->dmaing &= ~1; + ei_local->dmaing = 0; } /* @@ -351,7 +406,7 @@ return; } - ei_local->dmaing |= 1; + ei_local->dmaing = 1; addr = dev->base_addr; dma_addr = dev->mem_start; @@ -369,7 +424,7 @@ insb (dma_addr, hdr, sizeof (*hdr)); outb (ENISR_RDC, addr + EN0_ISR); - ei_local->dmaing &= ~1; + ei_local->dmaing = 0; } /* @@ -385,6 +440,12 @@ { struct ei_device *ei_local = (struct ei_device *) dev->priv; + if (!is_valid_ether_addr(dev->dev_addr)) { + printk(KERN_WARNING "%s: invalid ethernet address\n", + dev->name); + return -EINVAL; + } + if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)) return -EAGAIN; @@ -427,22 +488,22 @@ return 0; } -static void etherh_irq_enable(ecard_t *ec, int irqnr) +static int +etherh_set_mac_address(struct net_device *dev, void *p) { - unsigned int ctrl_addr = (unsigned int)ec->irq_data; - outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr); -} + struct sockaddr *addr = p; -static void etherh_irq_disable(ecard_t *ec, int irqnr) -{ - unsigned int ctrl_addr = (unsigned int)ec->irq_data; - outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr); -} + if (netif_running(dev)) + return -EBUSY; -static expansioncard_ops_t etherh_ops = { - irqenable: etherh_irq_enable, - irqdisable: etherh_irq_disable, -}; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + /* + * We'll set the MAC address on the chip when we open it. + */ + + return 0; +} /* * Initialisation @@ -460,11 +521,13 @@ * Read the ethernet address string from the on board rom. * This is an ascii string... */ -static int __init etherh_addr(char *addr, struct expansion_card *ec) +static void __init etherh_addr(char *addr, struct expansion_card *ec) { struct in_chunk_dir cd; char *s; + memset(addr, 0, 6); + if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { int i; for (i = 0; i < 6; i++) { @@ -472,31 +535,25 @@ if (*s != (i == 5? ')' : ':')) break; } - if (i == 6) - return 0; } - return -ENODEV; } /* * Create an ethernet address from the system serial number. */ -static int __init etherm_addr(char *addr) +static void __init etherm_addr(char *addr) { unsigned int serial; - if (system_serial_low == 0 && system_serial_high == 0) - return -ENODEV; - serial = system_serial_low | system_serial_high; - - addr[0] = 0; - addr[1] = 0; - addr[2] = 0xa4; - addr[3] = 0x10 + (serial >> 24); - addr[4] = serial >> 16; - addr[5] = serial >> 8; - return 0; + if (serial != 0) { + addr[0] = 0; + addr[1] = 0; + addr[2] = 0xa4; + addr[3] = 0x10 + (serial >> 24); + addr[4] = serial >> 16; + addr[5] = serial >> 8; + } } static u32 etherh_regoffsets[16]; @@ -506,6 +563,7 @@ { struct ei_device *ei_local; struct net_device *dev; + struct etherh_priv *eh; const char *dev_type; int i, size; @@ -517,42 +575,50 @@ if (!dev) goto out; + eh = kmalloc(sizeof(struct etherh_priv), GFP_KERNEL); + if (!eh) + goto out_nopriv; + SET_MODULE_OWNER(dev); - dev->open = etherh_open; - dev->stop = etherh_close; - dev->set_config = etherh_set_config; - dev->irq = ec->irq; - dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); - dev->mem_end = ec->cid.product; + dev->open = etherh_open; + dev->stop = etherh_close; + dev->set_mac_address = etherh_set_mac_address; + dev->set_config = etherh_set_config; + dev->irq = ec->irq; + dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); + dev->rmem_start = (unsigned long)eh; + + /* + * IRQ and control port handling + */ ec->ops = ðerh_ops; + ec->irq_data = eh; + eh->ctrl = 0; + eh->id = ec->cid.product; switch (ec->cid.product) { case PROD_ANT_ETHERM: - if (etherm_addr(dev->dev_addr)) - goto free; + etherm_addr(dev->dev_addr); dev->base_addr += ETHERM_NS8390; dev->mem_start = dev->base_addr + ETHERM_DATAPORT; - ec->irq_data = (void *)(dev->base_addr + ETHERM_CTRLPORT); + eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT; break; case PROD_I3_ETHERLAN500: - if (etherh_addr(dev->dev_addr, ec)) - goto free; + etherh_addr(dev->dev_addr, ec); dev->base_addr += ETHERH500_NS8390; dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; - dev->rmem_start = (unsigned long) - ec->irq_data = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST) + eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ETHERH500_CTRLPORT; break; case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: - if (etherh_addr(dev->dev_addr, ec)) - goto free; + etherh_addr(dev->dev_addr, ec); dev->base_addr += ETHERH600_NS8390; - dev->mem_start = dev->base_addr + ETHERH600_DATAPORT; - ec->irq_data = (void *)(dev->base_addr + ETHERH600_CTRLPORT); + dev->mem_start = dev->base_addr + ETHERH600_DATAPORT; + eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT; break; default: @@ -572,6 +638,12 @@ goto release; /* + * If we're in the NIC slot, make sure the IRQ is enabled + */ + if (dev->irq == 11) + etherh_set_ctrl(eh, ETHERH_CP_IE); + + /* * Unfortunately, ethdev_init eventually calls * ether_setup, which re-writes dev->flags. */ @@ -636,6 +708,8 @@ release: release_region(dev->base_addr, 16); free: + kfree(eh); +out_nopriv: unregister_netdev(dev); kfree(dev); out: @@ -696,6 +770,7 @@ } if (e_card[i]) { e_card[i]->ops = NULL; + kfree(e_card[i]->irq_data); ecard_release(e_card[i]); e_card[i] = NULL; } diff -urN orig/drivers/acorn/scsi/arxescsi.c linux/drivers/acorn/scsi/arxescsi.c --- orig/drivers/acorn/scsi/arxescsi.c Fri Oct 26 16:46:02 2001 +++ linux/drivers/acorn/scsi/arxescsi.c Thu Jan 23 12:57:02 2003 @@ -37,16 +37,22 @@ #include "../../scsi/sd.h" #include "../../scsi/hosts.h" -#include "arxescsi.h" +#include #include "fas216.h" +#include "scsi.h" -/* Hmm - this should go somewhere else */ -#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) +struct arxescsi_info { + FAS216_Info info; + struct expansion_card *ec; + unsigned int dmaarea; /* Pseudo DMA area */ +}; -/* Configuration */ -#define ARXESCSI_XTALFREQ 24 -#define ARXESCSI_ASYNC_PERIOD 200 -#define ARXESCSI_SYNC_DEPTH 0 +#define DMADATA_OFFSET (0x200/4) + +#define DMASTAT_OFFSET (0x600/4) +#define DMASTAT_DRQ (1 << 0) + +#define CSTATUS_IRQ (1 << 0) /* * List of devices that the driver will recognise @@ -56,11 +62,7 @@ /* * Version */ -#define VER_MAJOR 0 -#define VER_MINOR 1 -#define VER_PATCH 1 - -static struct expansion_card *ecs[MAX_ECARDS]; +#define VERSION "1.10 (22/01/2003 2.4.19-rmk5)" /* * Function: int arxescsi_dma_setup(host, SCpnt, direction, min_type) @@ -157,7 +159,7 @@ void arxescsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer) { - ARXEScsi_Info *info = (ARXEScsi_Info *)host->hostdata; + struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata; unsigned int length, io, error=0; unsigned char *addr; @@ -182,7 +184,7 @@ if (getb(io, 4) & STAT_INT) break; - if (!(getb(io, 48) & CSTATUS_IRQ)) + if (!(getb(io, 48) & DMASTAT_DRQ)) continue; word = *addr | *(addr + 1) << 8; @@ -205,7 +207,7 @@ break; } - if (!(getb(io, 48) & CSTATUS_IRQ)) + if (!(getb(io, 48) & DMASTAT_DRQ)) continue; insw(info->dmaarea, addr, 256 >> 1); @@ -221,7 +223,7 @@ if (getb(io, 4) & STAT_INT) break; - if (!(getb(io, 48) & CSTATUS_IRQ)) + if (!(getb(io, 48) & DMASTAT_DRQ)) continue; word = getw(io, 16); @@ -248,96 +250,6 @@ } /* - * Function: int arxescsi_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises ARXE SCSI driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int arxescsi_detect(Scsi_Host_Template *tpnt) -{ - static const card_ids arxescsi_cids[] = { ARXESCSI_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "arxescsi"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); - - while (1) { - ARXEScsi_Info *info; - - ecs[count] = ecard_find(0, arxescsi_cids); - if (!ecs[count]) - break; - - ecard_claim(ecs[count]); - - host = scsi_register(tpnt, sizeof (ARXEScsi_Info)); - if (!host) { - ecard_release(ecs[count]); - break; - } - - host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0) + 0x0800; - host->irq = NO_IRQ; - host->dma_channel = NO_DMA; - host->can_queue = 0; /* no command queueing */ - info = (ARXEScsi_Info *)host->hostdata; - - info->info.scsi.io_port = host->io_port; - info->info.scsi.irq = host->irq; - info->info.scsi.io_shift = 3; - info->info.ifcfg.clockrate = ARXESCSI_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = ARXESCSI_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = ARXESCSI_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 0; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = arxescsi_dma_setup; - info->info.dma.pseudo = arxescsi_dma_pseudo; - info->info.dma.stop = arxescsi_dma_stop; - info->dmaarea = host->io_port + 128; - info->cstatus = host->io_port + 384; - - ecs[count]->irqaddr = (unsigned char *)BUS_ADDR(host->io_port); - ecs[count]->irqmask = CSTATUS_IRQ; - - request_region(host->io_port , 120, "arxescsi-fas"); - request_region(host->io_port + 128, 384, "arxescsi-dma"); - - printk("scsi%d: Has no interrupts - using polling mode\n", - host->host_no); - - fas216_init(host); - ++count; - } - return count; -} - -/* - * Function: int arxescsi_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - * Returns : nothing - */ -int arxescsi_release(struct Scsi_Host *host) -{ - int i; - - fas216_release(host); - - release_region(host->io_port, 120); - release_region(host->io_port + 128, 384); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && host->io_port == (ecard_address(ecs[i], ECARD_MEMC, 0) + 0x0800)) - ecard_release(ecs[i]); - return 0; -} - -/* * Function: const char *arxescsi_info(struct Scsi_Host * host) * Purpose : returns a descriptive string about this interface, * Params : host - driver host structure to return info for. @@ -345,13 +257,12 @@ */ const char *arxescsi_info(struct Scsi_Host *host) { - ARXEScsi_Info *info = (ARXEScsi_Info *)host->hostdata; - static char string[100], *p; + struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata; + static char string[150]; - p = string; - p += sprintf(p, "%s ", host->hostt->name); - p += fas216_info(&info->info, p); - p += sprintf(p, "v%d.%d.%d", VER_MAJOR, VER_MINOR, VER_PATCH); + sprintf(string, "%s (%s) in slot %d v%s", + host->hostt->name, info->info.scsi.type, info->ec->slot_no, + VERSION); return string; } @@ -374,26 +285,20 @@ int length, int host_no, int inout) { int pos, begin; - struct Scsi_Host *host = scsi_hostlist; - ARXEScsi_Info *info; + struct Scsi_Host *host; + struct arxescsi_info *info; Scsi_Device *scd; - while (host) { - if (host->host_no == host_no) - break; - host = host->next; - } + host = scsi_host_hn_get(host_no); if (!host) return 0; - info = (ARXEScsi_Info *)host->hostdata; + info = (struct arxescsi_info *)host->hostdata; if (inout == 1) return -EINVAL; begin = 0; - pos = sprintf(buffer, - "ARXE 16-bit SCSI driver version %d.%d.%d\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + pos = sprintf(buffer, "ARXE 16-bit SCSI driver v%s\n", VERSION); pos += fas216_print_host(&info->info, buffer + pos); pos += fas216_print_stats(&info->info, buffer + pos); @@ -418,11 +323,156 @@ return pos; } -static Scsi_Host_Template arxescsi_template = ARXEScsi; +static int arxescsi_probe(struct expansion_card *ec); + +/* + * Function: int arxescsi_detect(Scsi_Host_Template * tpnt) + * Purpose : initialises ARXE SCSI driver + * Params : tpnt - template for this SCSI adapter + * Returns : >0 if host found, 0 otherwise. + */ +static int arxescsi_detect(Scsi_Host_Template *tpnt) +{ + static const card_ids arxescsi_cids[] = { ARXESCSI_LIST, { 0xffff, 0xffff} }; + int count = 0, ret; + + ecard_startfind(); + + while (1) { + struct expansion_card *ec; + ec = ecard_find(0, arxescsi_cids); + if (!ec) + break; + + ecard_claim(ec); + ret = arxescsi_probe(ec); + if (ret) { + ecard_release(ec); + break; + } + ++count; + } + return count; +} + +static void arxescsi_remove(struct Scsi_Host *host); + +/* + * Function: int arxescsi_release(struct Scsi_Host * host) + * Purpose : releases all resources used by this adapter + * Params : host - driver host structure to return info for. + * Returns : nothing + */ +static int arxescsi_release(struct Scsi_Host *host) +{ + arxescsi_remove(host); + return 0; +} + +static Scsi_Host_Template arxescsi_template = { + .module = THIS_MODULE, + .proc_info = arxescsi_proc_info, + .name = "ARXE SCSI card", + .detect = arxescsi_detect, + .release = arxescsi_release, + .info = arxescsi_info, + .bios_param = scsicam_bios_param, + .command = fas216_command, + .queuecommand = fas216_queue_command, + .eh_host_reset_handler = fas216_eh_host_reset, + .eh_bus_reset_handler = fas216_eh_bus_reset, + .eh_device_reset_handler = fas216_eh_device_reset, + .eh_abort_handler = fas216_eh_abort, + .use_new_eh_code = 1, + + .can_queue = 0, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "arxescsi", +}; + +static int +arxescsi_probe(struct expansion_card *ec) +{ + struct Scsi_Host *host; + struct arxescsi_info *info; + unsigned long base; + int ret; + + base = ecard_address(ec, ECARD_MEMC, 0) + 0x0800; + + if (!request_region(base, 512, "arxescsi")) { + ret = -EBUSY; + goto out; + } + + host = scsi_register(&arxescsi_template, sizeof(struct arxescsi_info)); + if (!host) { + ret = -ENOMEM; + goto out_region; + } + + host->io_port = base; + host->irq = NO_IRQ; + host->dma_channel = NO_DMA; + + info = (struct arxescsi_info *)host->hostdata; + info->ec = ec; + info->dmaarea = base + DMADATA_OFFSET; + + info->info.scsi.io_port = host->io_port; + info->info.scsi.irq = NO_IRQ; + info->info.scsi.io_shift = 3; + info->info.ifcfg.clockrate = 24; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 0; + info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 0; + info->info.ifcfg.wide_max_size = 0; + info->info.ifcfg.capabilities = FASCAP_PSEUDODMA; + info->info.dma.setup = arxescsi_dma_setup; + info->info.dma.pseudo = arxescsi_dma_pseudo; + info->info.dma.stop = arxescsi_dma_stop; + + ec->irqaddr = (unsigned char *)ioaddr(base); + ec->irqmask = CSTATUS_IRQ; + + ret = fas216_init(host); + if (ret) + goto out_unregister; + + ret = fas216_add(host); + if (ret == 0) + goto out; + + fas216_release(host); + out_unregister: + scsi_unregister(host); + out_region: + release_region(base, 512); + out: + return ret; +} + +static void arxescsi_remove(struct Scsi_Host *host) +{ + struct arxescsi_info *info; + + info = (struct arxescsi_info *)host->hostdata; + + fas216_remove(host); + + release_region(host->io_port, 512); + + ecard_release(info->ec); + fas216_release(host); +} static int __init init_arxe_scsi_driver(void) { - arxescsi_template.module = THIS_MODULE; scsi_register_module(MODULE_SCSI_HA, &arxescsi_template); if (arxescsi_template.present) return 0; diff -urN orig/drivers/acorn/scsi/arxescsi.h linux/drivers/acorn/scsi/arxescsi.h --- orig/drivers/acorn/scsi/arxescsi.h Sat May 13 01:01:39 2000 +++ linux/drivers/acorn/scsi/arxescsi.h Thu Jan 1 01:00:00 1970 @@ -1,82 +0,0 @@ -/* - * ARXE SCSI card driver - * - * Copyright (C) 1997-2000 Russell King - * - * Changes to support ARXE 16-bit SCSI card by Stefan Hanske - */ -#ifndef ARXE_SCSI_H -#define ARXE_SCSI_H - -#define MANU_ARXE 0x0041 -#define PROD_ARXE_SCSI 0x00be - -extern int arxescsi_detect (Scsi_Host_Template *); -extern int arxescsi_release (struct Scsi_Host *); -extern const char *arxescsi_info (struct Scsi_Host *); -extern int arxescsi_proc_info (char *buffer, char **start, off_t offset, - int length, int hostno, int inout); - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#ifndef CAN_QUEUE -/* - * Default queue size - */ -#define CAN_QUEUE 1 -#endif - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 1 -#endif - -#ifndef SCSI_ID -/* - * Default SCSI host ID - */ -#define SCSI_ID 7 -#endif - -#include - -#include "fas216.h" - -#define ARXEScsi { \ -proc_info: arxescsi_proc_info, \ -name: "ARXE SCSI card", \ -detect: arxescsi_detect, \ -release: arxescsi_release, \ -info: arxescsi_info, \ -bios_param: scsicam_bios_param, \ -can_queue: CAN_QUEUE, \ -this_id: SCSI_ID, \ -sg_tablesize: SG_ALL, \ -cmd_per_lun: CMD_PER_LUN, \ -use_clustering: DISABLE_CLUSTERING, \ -command: fas216_command, \ -queuecommand: fas216_queue_command, \ -eh_host_reset_handler: fas216_eh_host_reset, \ -eh_bus_reset_handler: fas216_eh_bus_reset, \ -eh_device_reset_handler: fas216_eh_device_reset, \ -eh_abort_handler: fas216_eh_abort, \ -use_new_eh_code: 1 \ - } - -#ifndef HOSTS_C - -typedef struct { - FAS216_Info info; - - /* other info... */ - unsigned int cstatus; /* card status register */ - unsigned int dmaarea; /* Pseudo DMA area */ -} ARXEScsi_Info; - -#define CSTATUS_IRQ (1 << 0) -#define CSTATUS_DRQ (1 << 0) - -#endif /* HOSTS_C */ - -#endif /* ARXE_SCSI_H */ diff -urN orig/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c --- orig/drivers/acorn/scsi/cumana_2.c Fri Nov 16 10:09:50 2001 +++ linux/drivers/acorn/scsi/cumana_2.c Wed Jun 25 11:55:31 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/acorn/scsi/cumana_2.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,8 +23,6 @@ #include #include #include -#include -#include #include #include #include @@ -38,14 +36,10 @@ #include "../../scsi/sd.h" #include "../../scsi/hosts.h" #include "fas216.h" +#include "scsi.h" #include -/* Configuration */ -#define CUMANASCSI2_XTALFREQ 40 -#define CUMANASCSI2_ASYNC_PERIOD 200 -#define CUMANASCSI2_SYNC_DEPTH 7 - /* * List of devices that the driver will recognise */ @@ -76,11 +70,7 @@ /* * Version */ -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 4 - -static struct expansion_card *ecs[MAX_ECARDS]; +#define VERSION "1.00 (13/11/2002 2.4.19-rmk5)" /* * Use term=0,1,0,0,0 to turn terminators on/off @@ -89,16 +79,16 @@ #define NR_SG 256 -typedef struct { - FAS216_Info info; - - /* other info... */ - unsigned int status; /* card status register */ - unsigned int alatch; /* Control register */ - unsigned int terms; /* Terminator state */ - unsigned int dmaarea; /* Pseudo DMA area */ - struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -} CumanaScsi2_Info; +struct cumanascsi2_info { + FAS216_Info info; + struct expansion_card *ec; + + unsigned int status; /* card status register */ + unsigned int alatch; /* Control register */ + unsigned int terms; /* Terminator state */ + unsigned int dmaarea; /* Pseudo DMA area */ + struct scatterlist sg[NR_SG]; /* Scatter DMA list */ +}; #define CSTATUS_IRQ (1 << 0) #define CSTATUS_DRQ (1 << 1) @@ -128,12 +118,8 @@ } static const expansioncard_ops_t cumanascsi_2_ops = { - cumanascsi_2_irqenable, - cumanascsi_2_irqdisable, - NULL, - NULL, - NULL, - NULL + .irqenable = cumanascsi_2_irqenable, + .irqdisable = cumanascsi_2_irqdisable, }; /* Prototype: void cumanascsi_2_terminator_ctl(host, on_off) @@ -144,7 +130,7 @@ static void cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; if (on_off) { info->terms = 1; @@ -164,9 +150,7 @@ static void cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct Scsi_Host *host = (struct Scsi_Host *)dev_id; - - fas216_intr(host); + fas216_intr(dev_id); } /* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type) @@ -181,36 +165,30 @@ cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_type) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; int dmach = host->dma_channel; outb(ALATCH_DIS_DMA, info->alatch); if (dmach != NO_DMA && (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs = SCp->buffers_residual; - int pci_dir, dma_dir, alatch_dir; + int bufs, map_dir, dma_dir, alatch_dir; - if (bufs) - memcpy(info->sg + 1, SCp->buffer + 1, - sizeof(struct scatterlist) * bufs); - info->sg[0].address = SCp->ptr; - info->sg[0].page = NULL; - info->sg[0].length = SCp->this_residual; + bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); if (direction == DMA_OUT) - pci_dir = PCI_DMA_TODEVICE, + map_dir = PCI_DMA_TODEVICE, dma_dir = DMA_MODE_WRITE, alatch_dir = ALATCH_DMA_OUT; else - pci_dir = PCI_DMA_FROMDEVICE, + map_dir = PCI_DMA_FROMDEVICE, dma_dir = DMA_MODE_READ, alatch_dir = ALATCH_DMA_IN; - pci_map_sg(NULL, info->sg, bufs + 1, pci_dir); + pci_map_sg(NULL, info->sg, bufs, map_dir); disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); + set_dma_sg(dmach, info->sg, bufs); outb(alatch_dir, info->alatch); set_dma_mode(dmach, dma_dir); enable_dma(dmach); @@ -238,7 +216,7 @@ cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; unsigned int length; unsigned char *addr; @@ -271,7 +249,7 @@ unsigned int status = inb(info->status); if (status & STATUS_INT) - goto end; + return; if (!(status & STATUS_DRQ)) continue; @@ -287,7 +265,7 @@ unsigned int status = inb(info->status); if (status & STATUS_INT) - goto end; + return; if (!(status & STATUS_DRQ)) continue; @@ -300,8 +278,6 @@ } } } - -end: } /* Prototype: int cumanascsi_2_dma_stop(host, SCpnt) @@ -312,124 +288,13 @@ static void cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; if (host->dma_channel != NO_DMA) { outb(ALATCH_DIS_DMA, info->alatch); disable_dma(host->dma_channel); } } -/* Prototype: int cumanascsi_2_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises Cumana SCSI 2 driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int -cumanascsi_2_detect(Scsi_Host_Template *tpnt) -{ - static const card_ids cumanascsi_2_cids[] = - { CUMANASCSI2_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "cumanascs2"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); - - while (1) { - CumanaScsi2_Info *info; - - ecs[count] = ecard_find(0, cumanascsi_2_cids); - if (!ecs[count]) - break; - - ecard_claim(ecs[count]); - - host = scsi_register(tpnt, sizeof (CumanaScsi2_Info)); - if (!host) { - ecard_release(ecs[count]); - break; - } - - host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0); - host->irq = ecs[count]->irq; - host->dma_channel = ecs[count]->dma; - info = (CumanaScsi2_Info *)host->hostdata; - - info->terms = term[count] ? 1 : 0; - cumanascsi_2_terminator_ctl(host, info->terms); - - info->info.scsi.io_port = host->io_port + CUMANASCSI2_FAS216_OFFSET; - info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = CUMANASCSI2_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = CUMANASCSI2_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = CUMANASCSI2_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = cumanascsi_2_dma_setup; - info->info.dma.pseudo = cumanascsi_2_dma_pseudo; - info->info.dma.stop = cumanascsi_2_dma_stop; - info->dmaarea = host->io_port + CUMANASCSI2_PSEUDODMA; - info->status = host->io_port + CUMANASCSI2_STATUS; - info->alatch = host->io_port + CUMANASCSI2_ALATCH; - - ecs[count]->irqaddr = (unsigned char *)ioaddr(info->status); - ecs[count]->irqmask = STATUS_INT; - ecs[count]->irq_data = (void *)info->alatch; - ecs[count]->ops = (expansioncard_ops_t *)&cumanascsi_2_ops; - - request_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, - 16 << CUMANASCSI2_FAS216_SHIFT, "cumanascsi2-fas"); - - if (host->irq != NO_IRQ && - request_irq(host->irq, cumanascsi_2_intr, - SA_INTERRUPT, "cumanascsi2", host)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - host->host_no, host->irq); - host->irq = NO_IRQ; - info->info.scsi.irq = NO_IRQ; - } - - if (host->dma_channel != NO_DMA && - request_dma(host->dma_channel, "cumanascsi2")) { - printk("scsi%d: DMA%d not free, DMA disabled\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } - - fas216_init(host); - ++count; - } - return count; -} - -/* Prototype: int cumanascsi_2_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - */ -int cumanascsi_2_release(struct Scsi_Host *host) -{ - int i; - - fas216_release(host); - - if (host->irq != NO_IRQ) - free_irq(host->irq, host); - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, - 16 << CUMANASCSI2_FAS216_SHIFT); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && host->io_port == ecard_address (ecs[i], ECARD_MEMC, 0)) - ecard_release (ecs[i]); - return 0; -} - /* Prototype: const char *cumanascsi_2_info(struct Scsi_Host * host) * Purpose : returns a descriptive string about this interface, * Params : host - driver host structure to return info for. @@ -437,15 +302,12 @@ */ const char *cumanascsi_2_info(struct Scsi_Host *host) { - CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata; - static char string[100], *p; + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; + static char string[150]; - p = string; - p += sprintf(p, "%s ", host->hostt->name); - p += fas216_info(&info->info, p); - p += sprintf(p, "v%d.%d.%d terminators o%s", - VER_MAJOR, VER_MINOR, VER_PATCH, - info->terms ? "n" : "ff"); + sprintf(string, "%s (%s) in slot %d v%s terminators o%s", + host->hostt->name, info->info.scsi.type, info->ec->slot_no, + VERSION, info->terms ? "n" : "ff"); return string; } @@ -498,28 +360,21 @@ int length, int host_no, int inout) { int pos, begin; - struct Scsi_Host *host = scsi_hostlist; - CumanaScsi2_Info *info; + struct Scsi_Host *host; + struct cumanascsi2_info *info; Scsi_Device *scd; - while (host) { - if (host->host_no == host_no) - break; - host = host->next; - } + host = scsi_host_hn_get(host_no); if (!host) return 0; if (inout == 1) return cumanascsi_2_set_proc_info(host, buffer, length); - info = (CumanaScsi2_Info *)host->hostdata; + info = (struct cumanascsi2_info *)host->hostdata; begin = 0; - pos = sprintf(buffer, - "Cumana SCSI II driver version %d.%d.%d\n", - VER_MAJOR, VER_MINOR, VER_PATCH); - + pos = sprintf(buffer, "Cumana SCSI II driver v%s\n", VERSION); pos += fas216_print_host(&info->info, buffer + pos); pos += sprintf(buffer + pos, "Term : o%s\n", info->terms ? "n" : "ff"); @@ -556,28 +411,194 @@ return pos; } +static int cumanascsi2_probe(struct expansion_card *ec); + +/* Prototype: int cumanascsi_2_detect(Scsi_Host_Template * tpnt) + * Purpose : initialises Cumana SCSI 2 driver + * Params : tpnt - template for this SCSI adapter + * Returns : >0 if host found, 0 otherwise. + */ +static int +cumanascsi_2_detect(Scsi_Host_Template *tpnt) +{ + static const card_ids cumanascsi_2_cids[] = + { CUMANASCSI2_LIST, { 0xffff, 0xffff} }; + int count = 0, ret; + + ecard_startfind(); + + while (1) { + struct expansion_card *ec; + + ec = ecard_find(0, cumanascsi_2_cids); + if (!ec) + break; + + ecard_claim(ec); + ret = cumanascsi2_probe(ec); + if (ret) { + ecard_release(ec); + break; + } + + ++count; + } + return count; +} + +static void cumanascsi2_remove(struct Scsi_Host *host); + +/* Prototype: int cumanascsi_2_release(struct Scsi_Host * host) + * Purpose : releases all resources used by this adapter + * Params : host - driver host structure to return info for. + */ +static int cumanascsi_2_release(struct Scsi_Host *host) +{ + cumanascsi2_remove(host); + return 0; +} + static Scsi_Host_Template cumanascsi2_template = { - module: THIS_MODULE, - proc_info: cumanascsi_2_proc_info, - name: "Cumana SCSI II", - detect: cumanascsi_2_detect, - release: cumanascsi_2_release, - info: cumanascsi_2_info, - bios_param: scsicam_bios_param, - can_queue: 1, - this_id: 7, - sg_tablesize: SG_ALL, - cmd_per_lun: 1, - use_clustering: DISABLE_CLUSTERING, - command: fas216_command, - queuecommand: fas216_queue_command, - eh_host_reset_handler: fas216_eh_host_reset, - eh_bus_reset_handler: fas216_eh_bus_reset, - eh_device_reset_handler: fas216_eh_device_reset, - eh_abort_handler: fas216_eh_abort, - use_new_eh_code: 1 + .module = THIS_MODULE, + .proc_info = cumanascsi_2_proc_info, + .name = "Cumana SCSI II", + .detect = cumanascsi_2_detect, + .release = cumanascsi_2_release, + .info = cumanascsi_2_info, + .bios_param = scsicam_bios_param, + .command = fas216_command, + .queuecommand = fas216_queue_command, + .eh_host_reset_handler = fas216_eh_host_reset, + .eh_bus_reset_handler = fas216_eh_bus_reset, + .eh_device_reset_handler = fas216_eh_device_reset, + .eh_abort_handler = fas216_eh_abort, + .use_new_eh_code = 1, + + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "cumanascsi2", }; +static int +cumanascsi2_probe(struct expansion_card *ec) +{ + struct Scsi_Host *host; + struct cumanascsi2_info *info; + unsigned long base; + int ret; + + base = ecard_address(ec, ECARD_MEMC, 0); + + if (request_region(base + CUMANASCSI2_FAS216_OFFSET, + 16 << CUMANASCSI2_FAS216_SHIFT, "cumanascsi2-fas")) { + ret = -EBUSY; + goto out; + } + + host = scsi_register(&cumanascsi2_template, + sizeof(struct cumanascsi2_info)); + if (!host) { + ret = -ENOMEM; + goto out_region; + } + + host->io_port = base; + host->irq = ec->irq; + host->dma_channel = ec->dma; + + info = (struct cumanascsi2_info *)host->hostdata; + info->ec = ec; + info->dmaarea = base + CUMANASCSI2_PSEUDODMA; + info->status = base + CUMANASCSI2_STATUS; + info->alatch = base + CUMANASCSI2_ALATCH; + + ec->irqaddr = (unsigned char *)ioaddr(info->status); + ec->irqmask = STATUS_INT; + ec->irq_data = (void *)base + CUMANASCSI2_ALATCH; + ec->ops = (expansioncard_ops_t *)&cumanascsi_2_ops; + + cumanascsi_2_terminator_ctl(host, term[ec->slot_no]); + + info->info.scsi.io_port = base + CUMANASCSI2_FAS216_OFFSET; + info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = 40; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 7; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; + info->info.ifcfg.capabilities = 0; + info->info.dma.setup = cumanascsi_2_dma_setup; + info->info.dma.pseudo = cumanascsi_2_dma_pseudo; + info->info.dma.stop = cumanascsi_2_dma_stop; + + ret = fas216_init(host); + if (ret) + goto out_free; + + ret = request_irq(host->irq, cumanascsi_2_intr, + SA_INTERRUPT, "cumanascsi2", &info->info); + if (ret) { + printk("scsi%d: IRQ%d not free: %d\n", + host->host_no, host->irq, ret); + goto out_release; + } + + if (host->dma_channel != NO_DMA) { + if (request_dma(host->dma_channel, "cumanascsi2")) { + printk("scsi%d: DMA%d not free, using PIO\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } else { + set_dma_speed(host->dma_channel, 180); + info->info.ifcfg.capabilities |= FASCAP_DMA; + } + } + + ret = fas216_add(host); + if (ret == 0) + goto out; + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + + out_release: + fas216_release(host); + + out_free: + scsi_unregister(host); + + out_region: + release_region(base + CUMANASCSI2_FAS216_OFFSET, + 16 << CUMANASCSI2_FAS216_SHIFT); + + out: + return ret; +} + +static void cumanascsi2_remove(struct Scsi_Host *host) +{ + struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; + + fas216_remove(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + + release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET, + 16 << CUMANASCSI2_FAS216_SHIFT); + + fas216_release(host); + ecard_release(info->ec); +} + static int __init cumanascsi2_init(void) { scsi_register_module(MODULE_SCSI_HA, &cumanascsi2_template); diff -urN orig/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c --- orig/drivers/acorn/scsi/eesox.c Fri Nov 16 10:09:50 2001 +++ linux/drivers/acorn/scsi/eesox.c Wed Jun 25 11:55:41 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/acorn/scsi/eesox.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-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 @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include #include #include @@ -44,14 +42,10 @@ #include "../../scsi/sd.h" #include "../../scsi/hosts.h" #include "fas216.h" +#include "scsi.h" #include -/* Configuration */ -#define EESOX_XTALFREQ 40 -#define EESOX_ASYNC_PERIOD 200 -#define EESOX_SYNC_DEPTH 7 - /* * List of devices that the driver will recognise */ @@ -60,7 +54,7 @@ #define EESOX_FAS216_OFFSET 0xc00 #define EESOX_FAS216_SHIFT 3 -#define EESOX_STATUS 0xa00 +#define EESOX_DMASTAT 0xa00 #define EESOX_STAT_INTR 0x01 #define EESOX_STAT_DMA 0x02 @@ -69,16 +63,12 @@ #define EESOX_TERM_ENABLE 0x02 #define EESOX_RESET 0x01 -#define EESOX_DMA_OFFSET 0xe00 +#define EESOX_DMADATA 0xe00 /* * Version */ -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 3 - -static struct expansion_card *ecs[MAX_ECARDS]; +#define VERSION "1.10 (22/01/2003 2.4.19-rmk5)" /* * Use term=0,1,0,0,0 to turn terminators on/off @@ -87,20 +77,15 @@ #define NR_SG 256 -struct control { - unsigned int io_port; - unsigned int control; +struct eesoxscsi_info { + FAS216_Info info; + struct expansion_card *ec; + + unsigned int ctl_port; + unsigned int control; + struct scatterlist sg[NR_SG]; /* Scatter DMA list */ }; -typedef struct { - FAS216_Info info; - - struct control control; - - unsigned int dmaarea; /* Pseudo DMA area */ - struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -} EESOXScsi_Info; - /* Prototype: void eesoxscsi_irqenable(ec, irqnr) * Purpose : Enable interrupts on EESOX SCSI card * Params : ec - expansion card structure @@ -109,11 +94,11 @@ static void eesoxscsi_irqenable(struct expansion_card *ec, int irqnr) { - struct control *control = (struct control *)ec->irq_data; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data; - control->control |= EESOX_INTR_ENABLE; + info->control |= EESOX_INTR_ENABLE; - outb(control->control, control->io_port); + outb(info->control, info->ctl_port); } /* Prototype: void eesoxscsi_irqdisable(ec, irqnr) @@ -124,20 +109,16 @@ static void eesoxscsi_irqdisable(struct expansion_card *ec, int irqnr) { - struct control *control = (struct control *)ec->irq_data; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data; - control->control &= ~EESOX_INTR_ENABLE; + info->control &= ~EESOX_INTR_ENABLE; - outb(control->control, control->io_port); + outb(info->control, info->ctl_port); } static const expansioncard_ops_t eesoxscsi_ops = { - eesoxscsi_irqenable, - eesoxscsi_irqdisable, - NULL, - NULL, - NULL, - NULL + .irqenable = eesoxscsi_irqenable, + .irqdisable = eesoxscsi_irqdisable, }; /* Prototype: void eesoxscsi_terminator_ctl(*host, on_off) @@ -148,17 +129,17 @@ static void eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; unsigned long flags; save_flags_cli(flags); if (on_off) - info->control.control |= EESOX_TERM_ENABLE; + info->control |= EESOX_TERM_ENABLE; else - info->control.control &= ~EESOX_TERM_ENABLE; - restore_flags(flags); + info->control &= ~EESOX_TERM_ENABLE; - outb(info->control.control, info->control.io_port); + outb(info->control, info->ctl_port); + restore_flags(flags); } /* Prototype: void eesoxscsi_intr(irq, *dev_id, *regs) @@ -170,9 +151,7 @@ static void eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct Scsi_Host *host = (struct Scsi_Host *)dev_id; - - fas216_intr(host); + fas216_intr(dev_id); } /* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type) @@ -187,32 +166,26 @@ eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_type) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; int dmach = host->dma_channel; if (dmach != NO_DMA && (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs = SCp->buffers_residual; - int pci_dir, dma_dir; + int bufs, map_dir, dma_dir; - if (bufs) - memcpy(info->sg + 1, SCp->buffer + 1, - sizeof(struct scatterlist) * bufs); - info->sg[0].address = SCp->ptr; - info->sg[0].page = NULL; - info->sg[0].length = SCp->this_residual; + bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); if (direction == DMA_OUT) - pci_dir = PCI_DMA_TODEVICE, + map_dir = PCI_DMA_TODEVICE, dma_dir = DMA_MODE_WRITE; else - pci_dir = PCI_DMA_FROMDEVICE, + map_dir = PCI_DMA_FROMDEVICE, dma_dir = DMA_MODE_READ; - pci_map_sg(NULL, info->sg, bufs + 1, pci_dir); + pci_map_sg(NULL, info->sg, bufs, map_dir); disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); + set_dma_sg(dmach, info->sg, bufs); set_dma_mode(dmach, dma_dir); enable_dma(dmach); return fasdma_real_all; @@ -225,215 +198,174 @@ return fasdma_pseudo; } -static void -eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t dir, int transfer_size) +static void eesoxscsi_buffer_in(void *buf, int length, unsigned long base) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; - unsigned int status; - unsigned int length = SCp->this_residual; - union { - unsigned char *c; - unsigned short *s; - unsigned long *l; - } buffer; + const unsigned long reg_fas = base + EESOX_FAS216_OFFSET; + const unsigned long reg_dmastat = base + EESOX_DMASTAT; + const unsigned long reg_dmadata = base + EESOX_DMADATA; + + do { + unsigned int status; + + /* + * Interrupt request? + */ + status = inb(reg_fas + (REG_STAT << EESOX_FAS216_SHIFT)); + if (status & STAT_INT) + break; - buffer.c = SCp->ptr; + /* + * DMA request active? + */ + status = inb(reg_dmastat); + if (!(status & EESOX_STAT_DMA)) + continue; + + /* + * Get number of bytes in FIFO + */ + status = inb(reg_fas + (REG_CFIS << EESOX_FAS216_SHIFT)) & CFIS_CF; + if (status > 16) + status = 16; + if (status > length) + status = length; + + /* + * Align buffer. + */ + if (((u32)buf) & 2 && status >= 2) { + *((u16 *)buf)++ = inw(reg_dmadata); + status -= 2; + length -= 2; + } - status = inb(host->io_port + EESOX_STATUS); - if (dir == DMA_IN) { - while (length > 8) { - if (status & EESOX_STAT_DMA) { - unsigned long l1, l2; - - l1 = inw(info->dmaarea); - l1 |= inw(info->dmaarea) << 16; - l2 = inw(info->dmaarea); - l2 |= inw(info->dmaarea) << 16; - *buffer.l++ = l1; - *buffer.l++ = l2; - length -= 8; - } else if (status & EESOX_STAT_INTR) - goto end; - status = inb(host->io_port + EESOX_STATUS); - } - - while (length > 1) { - if (status & EESOX_STAT_DMA) { - *buffer.s++ = inw(info->dmaarea); - length -= 2; - } else if (status & EESOX_STAT_INTR) - goto end; - status = inb(host->io_port + EESOX_STATUS); - } - - while (length > 0) { - if (status & EESOX_STAT_DMA) { - *buffer.c++ = inw(info->dmaarea); - length -= 1; - } else if (status & EESOX_STAT_INTR) - goto end; - status = inb(host->io_port + EESOX_STATUS); + if (status >= 8) { + unsigned long l1, l2; + + l1 = inw(reg_dmadata); + l1 |= inw(reg_dmadata) << 16; + l2 = inw(reg_dmadata); + l2 |= inw(reg_dmadata) << 16; + *((u32 *)buf)++ = l1; + *((u32 *)buf)++ = l2; + length -= 8; + continue; } - } else { - while (length > 8) { - if (status & EESOX_STAT_DMA) { - unsigned long l1, l2; - - l1 = *buffer.l++; - l2 = *buffer.l++; - - outw(l1, info->dmaarea); - outw(l1 >> 16, info->dmaarea); - outw(l2, info->dmaarea); - outw(l2 >> 16, info->dmaarea); - length -= 8; - } else if (status & EESOX_STAT_INTR) - goto end; - status = inb(host->io_port + EESOX_STATUS); - } - - while (length > 1) { - if (status & EESOX_STAT_DMA) { - outw(*buffer.s++, info->dmaarea); - length -= 2; - } else if (status & EESOX_STAT_INTR) - goto end; - status = inb(host->io_port + EESOX_STATUS); - } - - while (length > 0) { - if (status & EESOX_STAT_DMA) { - outw(*buffer.c++, info->dmaarea); - length -= 1; - } else if (status & EESOX_STAT_INTR) - goto end; - status = inb(host->io_port + EESOX_STATUS); + + if (status >= 4) { + unsigned long l1; + + l1 = inw(reg_dmadata); + l1 |= inw(reg_dmadata) << 16; + *((u32 *)buf)++ = l1; + length -= 4; + continue; } - } -end: -} -/* Prototype: int eesoxscsi_dma_stop(host, SCpnt) - * Purpose : stops DMA/PIO - * Params : host - host - * SCpnt - command - */ -static void -eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) -{ - if (host->dma_channel != NO_DMA) - disable_dma(host->dma_channel); + if (status >= 2) { + *((u16 *)buf)++ = inw(reg_dmadata); + length -= 2; + } + } while (length); } -/* Prototype: int eesoxscsi_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises EESOX SCSI driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int -eesoxscsi_detect(Scsi_Host_Template *tpnt) +static void eesoxscsi_buffer_out(void *buf, int length, unsigned long base) { - static const card_ids eesoxscsi_cids[] = - { EESOXSCSI_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "eesox"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); + const unsigned long reg_fas = base + EESOX_FAS216_OFFSET; + const unsigned long reg_dmastat = base + EESOX_DMASTAT; + const unsigned long reg_dmadata = base + EESOX_DMADATA; - while(1) { - EESOXScsi_Info *info; + do { + unsigned int status; - ecs[count] = ecard_find(0, eesoxscsi_cids); - if (!ecs[count]) + /* + * Interrupt request? + */ + status = inb(reg_fas + (REG_STAT << EESOX_FAS216_SHIFT)); + if (status & STAT_INT) break; - ecard_claim(ecs[count]); + /* + * DMA request active? + */ + status = inb(reg_dmastat); + if (!(status & EESOX_STAT_DMA)) + continue; + + /* + * Get number of bytes in FIFO + */ + status = inb(reg_fas + (REG_CFIS << EESOX_FAS216_SHIFT)) & CFIS_CF; + if (status > 16) + status = 16; + status = 16 - status; + if (status > length) + status = length; + + /* + * Align buffer. + */ + if (((u32)buf) & 2 && status >= 2) { + outw(*((u16 *)buf)++, reg_dmadata); + status -= 2; + length -= 2; + } - host = scsi_register(tpnt, sizeof (EESOXScsi_Info)); - if (!host) { - ecard_release(ecs[count]); - break; + if (status >= 8) { + unsigned long l1, l2; + + l1 = *((u32 *)buf)++; + l2 = *((u32 *)buf)++; + + outw(l1, reg_dmadata); + outw(l1 >> 16, reg_dmadata); + outw(l2, reg_dmadata); + outw(l2 >> 16, reg_dmadata); + status -= 8; + length -= 8; + continue; } - host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST); - host->irq = ecs[count]->irq; - host->dma_channel = ecs[count]->dma; - info = (EESOXScsi_Info *)host->hostdata; - - info->control.io_port = host->io_port + EESOX_CONTROL; - info->control.control = term[count] ? EESOX_TERM_ENABLE : 0; - outb(info->control.control, info->control.io_port); - - ecs[count]->irqaddr = (unsigned char *) - ioaddr(host->io_port + EESOX_STATUS); - ecs[count]->irqmask = EESOX_STAT_INTR; - ecs[count]->irq_data = &info->control; - ecs[count]->ops = (expansioncard_ops_t *)&eesoxscsi_ops; - - info->info.scsi.io_port = host->io_port + EESOX_FAS216_OFFSET; - info->info.scsi.io_shift = EESOX_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = EESOX_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = EESOX_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = EESOX_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = eesoxscsi_dma_setup; - info->info.dma.pseudo = eesoxscsi_dma_pseudo; - info->info.dma.stop = eesoxscsi_dma_stop; - info->dmaarea = host->io_port + EESOX_DMA_OFFSET; - - request_region(host->io_port + EESOX_FAS216_OFFSET, - 16 << EESOX_FAS216_SHIFT, "eesox2-fas"); - - if (host->irq != NO_IRQ && - request_irq(host->irq, eesoxscsi_intr, - SA_INTERRUPT, "eesox", host)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - host->host_no, host->irq); - host->irq = NO_IRQ; + if (status >= 4) { + unsigned long l1; + + l1 = *((u32 *)buf)++; + outw(l1, reg_dmadata); + outw(l1 >> 16, reg_dmadata); + status -= 4; + length -= 4; + continue; } - if (host->dma_channel != NO_DMA && - request_dma(host->dma_channel, "eesox")) { - printk("scsi%d: DMA%d not free, DMA disabled\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; + if (status >= 2) { + outw(*((u16 *)buf)++, reg_dmadata); + length -= 2; } + } while (length); +} - fas216_init(host); - ++count; +static void +eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, + fasdmadir_t dir, int transfer_size) +{ + unsigned int base = host->io_port; + if (dir == DMA_IN) { + eesoxscsi_buffer_in(SCp->ptr, SCp->this_residual, base); + } else { + eesoxscsi_buffer_out(SCp->ptr, SCp->this_residual, base); } - return count; } -/* Prototype: int eesoxscsi_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. +/* Prototype: int eesoxscsi_dma_stop(host, SCpnt) + * Purpose : stops DMA/PIO + * Params : host - host + * SCpnt - command */ -int eesoxscsi_release(struct Scsi_Host *host) +static void +eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) { - int i; - - fas216_release(host); - - if (host->irq != NO_IRQ) - free_irq(host->irq, host); if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - release_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && - host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST)) - ecard_release(ecs[i]); - return 0; + disable_dma(host->dma_channel); } /* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host) @@ -443,15 +375,12 @@ */ const char *eesoxscsi_info(struct Scsi_Host *host) { - EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata; - static char string[100], *p; + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; + static char string[150]; - p = string; - p += sprintf(p, "%s ", host->hostt->name); - p += fas216_info(&info->info, p); - p += sprintf(p, "v%d.%d.%d terminators o%s", - VER_MAJOR, VER_MINOR, VER_PATCH, - info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); + sprintf(string, "%s (%s) in slot %d v%s terminators o%s", + host->hostt->name, info->info.scsi.type, info->ec->slot_no, + VERSION, info->control & EESOX_TERM_ENABLE ? "n" : "ff"); return string; } @@ -504,43 +433,37 @@ int length, int host_no, int inout) { int pos, begin; - struct Scsi_Host *host = scsi_hostlist; - EESOXScsi_Info *info; + struct Scsi_Host *host; + struct eesoxscsi_info *info; Scsi_Device *scd; - while (host) { - if (host->host_no == host_no) - break; - host = host->next; - } + host = scsi_host_hn_get(host_no); if (!host) return 0; if (inout == 1) return eesoxscsi_set_proc_info(host, buffer, length); - info = (EESOXScsi_Info *)host->hostdata; + info = (struct eesoxscsi_info *)host->hostdata; begin = 0; - pos = sprintf(buffer, - "EESOX SCSI driver version %d.%d.%d\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + pos = sprintf(buffer, "EESOX SCSI driver v%s\n", VERSION); pos += fas216_print_host(&info->info, buffer + pos); pos += sprintf(buffer + pos, "Term : o%s\n", - info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); + info->control & EESOX_TERM_ENABLE ? "n" : "ff"); pos += fas216_print_stats(&info->info, buffer + pos); - pos += sprintf (buffer+pos, "\nAttached devices:\n"); + pos += sprintf(buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { int len; - proc_print_scsidevice (scd, buffer, &len, pos); + proc_print_scsidevice(scd, buffer, &len, pos); pos += len; - pos += sprintf (buffer+pos, "Extensions: "); + pos += sprintf(buffer+pos, "Extensions: "); if (scd->tagged_supported) - pos += sprintf (buffer+pos, "TAG %sabled [%d] ", + pos += sprintf(buffer+pos, "TAG %sabled [%d] ", scd->tagged_queue ? "en" : "dis", scd->current_tag); pos += sprintf (buffer+pos, "\n"); @@ -558,28 +481,188 @@ return pos; } +static int eesoxscsi_probe(struct expansion_card *ec); + +/* Prototype: int eesoxscsi_detect(Scsi_Host_Template * tpnt) + * Purpose : initialises EESOX SCSI driver + * Params : tpnt - template for this SCSI adapter + * Returns : >0 if host found, 0 otherwise. + */ +static int eesoxscsi_detect(Scsi_Host_Template *tpnt) +{ + static const card_ids eesoxscsi_cids[] = + { EESOXSCSI_LIST, { 0xffff, 0xffff} }; + struct expansion_card *ec; + int count = 0, ret; + + ecard_startfind(); + + while(1) { + ec = ecard_find(0, eesoxscsi_cids); + if (!ec) + break; + + ecard_claim(ec); + + ret = eesoxscsi_probe(ec); + if (ret) { + ecard_release(ec); + break; + } + ++count; + } + return count; +} + +static void eesoxscsi_remove(struct Scsi_Host *host); + +/* Prototype: int eesoxscsi_release(struct Scsi_Host * host) + * Purpose : releases all resources used by this adapter + * Params : host - driver host structure to return info for. + */ +static int eesoxscsi_release(struct Scsi_Host *host) +{ + eesoxscsi_remove(host); + return 0; +} + static Scsi_Host_Template eesox_template = { - module: THIS_MODULE, - proc_info: eesoxscsi_proc_info, - name: "EESOX SCSI", - detect: eesoxscsi_detect, - release: eesoxscsi_release, - info: eesoxscsi_info, - bios_param: scsicam_bios_param, - can_queue: 1, - this_id: 7, - sg_tablesize: SG_ALL, - cmd_per_lun: 1, - use_clustering: DISABLE_CLUSTERING, - command: fas216_command, - queuecommand: fas216_queue_command, - eh_host_reset_handler: fas216_eh_host_reset, - eh_bus_reset_handler: fas216_eh_bus_reset, - eh_device_reset_handler: fas216_eh_device_reset, - eh_abort_handler: fas216_eh_abort, - use_new_eh_code: 1 + .module = THIS_MODULE, + .proc_info = eesoxscsi_proc_info, + .name = "EESOX SCSI", + .detect = eesoxscsi_detect, + .release = eesoxscsi_release, + .info = eesoxscsi_info, + .bios_param = scsicam_bios_param, + .command = fas216_command, + .queuecommand = fas216_queue_command, + .eh_host_reset_handler = fas216_eh_host_reset, + .eh_bus_reset_handler = fas216_eh_bus_reset, + .eh_device_reset_handler = fas216_eh_device_reset, + .eh_abort_handler = fas216_eh_abort, + .use_new_eh_code = 1, + + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "eesox", }; +static int +eesoxscsi_probe(struct expansion_card *ec) +{ + struct Scsi_Host *host; + struct eesoxscsi_info *info; + unsigned long base; + int ret; + + base = ecard_address(ec, ECARD_IOC, ECARD_FAST); + + if (!request_region(base + EESOX_FAS216_OFFSET, + 16 << EESOX_FAS216_SHIFT, "eesox2-fas")) { + ret = -EBUSY; + goto out; + } + + host = scsi_register(&eesox_template, + sizeof(struct eesoxscsi_info)); + if (!host) { + ret = -ENOMEM; + goto out_region; + } + + host->io_port = base; + host->irq = ec->irq; + host->dma_channel = ec->dma; + + info = (struct eesoxscsi_info *)host->hostdata; + info->ec = ec; + info->ctl_port = base + EESOX_CONTROL; + info->control = term[ec->slot_no] ? EESOX_TERM_ENABLE : 0; + outb(info->control, info->ctl_port); + + ec->irqaddr = (unsigned char *)ioaddr(base + EESOX_DMASTAT); + ec->irqmask = EESOX_STAT_INTR; + ec->irq_data = info; + ec->ops = (expansioncard_ops_t *)&eesoxscsi_ops; + + info->info.scsi.io_port = base + EESOX_FAS216_OFFSET; + info->info.scsi.io_shift = EESOX_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = 40; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 7; + info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; + info->info.ifcfg.capabilities = FASCAP_PSEUDODMA; + info->info.dma.setup = eesoxscsi_dma_setup; + info->info.dma.pseudo = eesoxscsi_dma_pseudo; + info->info.dma.stop = eesoxscsi_dma_stop; + + ret = fas216_init(host); + if (ret) + goto out_free; + + ret = request_irq(host->irq, eesoxscsi_intr, 0, "eesox", &info->info); + if (ret) { + printk("scsi%d: IRQ%d not free: %d\n", + host->host_no, host->irq, ret); + goto out_remove; + } + + if (host->dma_channel != NO_DMA) { + if (request_dma(host->dma_channel, "eesox")) { + printk("scsi%d: DMA%d not free, DMA disabled\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } else { + set_dma_speed(host->dma_channel, 180); + info->info.ifcfg.capabilities |= FASCAP_DMA; + info->info.ifcfg.cntl3 |= CNTL3_BS8; + } + } + + ret = fas216_add(host); + if (ret == 0) + goto out; + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + + out_remove: + fas216_remove(host); + + out_free: + scsi_unregister(host); + + out_region: + release_region(base + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT); + + out: + return ret; +} + +static void eesoxscsi_remove(struct Scsi_Host *host) +{ + struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; + + fas216_remove(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + + release_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT); + + fas216_release(host); + ecard_release(info->ec); +} + static int __init eesox_init(void) { scsi_register_module(MODULE_SCSI_HA, &eesox_template); diff -urN orig/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c --- orig/drivers/acorn/scsi/fas216.c Fri Oct 26 16:46:02 2001 +++ linux/drivers/acorn/scsi/fas216.c Sun Jun 29 18:24:21 2003 @@ -1,7 +1,7 @@ /* - * linux/arch/arm/drivers/scsi/fas216.c + * linux/drivers/acorn/scsi/fas216.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-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 @@ -10,7 +10,7 @@ * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and * other sources, including: * the AMD Am53CF94 data sheet - * the AMD Am53C94 data sheet + * the AMD Am53C94 data sheet * * This is a generic driver. To use it, have a look at cumana_2.c. You * should define your own structure that overlays FAS216_Info, eg: @@ -33,9 +33,6 @@ * 02-04-2000 RMK Converted to use the new error handling, and * automatically request sense data upon check * condition status from targets. - * - * Todo: - * - allow individual devices to enable sync xfers. */ #include #include @@ -44,25 +41,20 @@ #include #include #include -#include -#include #include +#include #include +#include #include #include #include #include -#define FAS216_C - #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" #include "fas216.h" - -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 5 +#include "scsi.h" /* NOTE: SCSI2 Synchronous transfers *require* DMA according to * the data sheet. This restriction is crazy, especially when @@ -88,35 +80,68 @@ * I was thinking that this was a good chip until I found this restriction ;( */ #define SCSI2_SYNC -#undef SCSI2_WIDE #undef SCSI2_TAG #undef DEBUG_CONNECT -#undef DEBUG_BUSSERVICE -#undef DEBUG_FUNCTIONDONE #undef DEBUG_MESSAGES #undef CHECK_STRUCTURE -static struct { int stat, ssr, isr, ph; } list[8]; -static int ptr; +#ifndef ABORT_TAG +#define ABORT_TAG 0x0d +#endif + +#define LOG_CONNECT (1 << 0) +#define LOG_BUSSERVICE (1 << 1) +#define LOG_FUNCTIONDONE (1 << 2) +#define LOG_MESSAGES (1 << 3) +#define LOG_BUFFER (1 << 4) +#define LOG_ERROR (1 << 8) + +static int level_mask = LOG_ERROR; + +MODULE_PARM(level_mask, "i"); + +static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg) +{ + unsigned int off = reg << info->scsi.io_shift; + + return inb(info->scsi.io_port + off); +} + +static inline void fas216_writeb(FAS216_Info *info, unsigned int reg, unsigned int val) +{ + unsigned int off = reg << info->scsi.io_shift; + + outb(val, info->scsi.io_port + off); +} static void fas216_dumpstate(FAS216_Info *info) { unsigned char is, stat, inst; - is = inb(REG_IS(info)); - stat = inb(REG_STAT(info)); - inst = inb(REG_INST(info)); + is = fas216_readb(info, REG_IS); + stat = fas216_readb(info, REG_STAT); + inst = fas216_readb(info, REG_INST); printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X" " INST=%02X IS=%02X CFIS=%02X", - inb(REG_CTCL(info)), inb(REG_CTCM(info)), - inb(REG_CMD(info)), stat, inst, is, - inb(REG_CFIS(info))); + fas216_readb(info, REG_CTCL), + fas216_readb(info, REG_CTCM), + fas216_readb(info, REG_CMD), stat, inst, is, + fas216_readb(info, REG_CFIS)); printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n", - inb(REG_CNTL1(info)), inb(REG_CNTL2(info)), - inb(REG_CNTL3(info)), inb(REG_CTCH(info))); + fas216_readb(info, REG_CNTL1), + fas216_readb(info, REG_CNTL2), + fas216_readb(info, REG_CNTL3), + fas216_readb(info, REG_CTCH)); +} + +static void print_SCp(Scsi_Pointer *SCp, const char *prefix, const char *suffix) +{ + printk("%sptr %p this_residual 0x%x buffer %p buffers_residual 0x%x%s", + prefix, SCp->ptr, SCp->this_residual, SCp->buffer, + SCp->buffers_residual, suffix); } static void fas216_dumpinfo(FAS216_Info *info) @@ -135,13 +160,9 @@ info->scsi.io_port, info->scsi.io_shift, info->scsi.irq, info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2], info->scsi.cfg[3]); - printk(" type=%p phase=%X reconnected={ target=%d lun=%d tag=%d }\n", - info->scsi.type, info->scsi.phase, - info->scsi.reconnected.target, - info->scsi.reconnected.lun, info->scsi.reconnected.tag); - printk(" SCp={ ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual, - info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual); + printk(" type=%p phase=%X\n", + info->scsi.type, info->scsi.phase); + print_SCp(&info->scsi.SCp, " SCp={ ", " }\n"); printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n", info->scsi.async_stp, info->scsi.disconnectable, info->scsi.aborting); @@ -155,7 +176,7 @@ info->ifcfg.clockrate, info->ifcfg.select_timeout, info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth); for (i = 0; i < 8; i++) { - printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n", + printk(" busyluns[%d]=%02x dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n", i, info->busyluns[i], i, info->device[i].disconnect_ok, info->device[i].stp, info->device[i].sof, info->device[i].sync_state); @@ -203,21 +224,24 @@ static const char *fas216_drv_phase(FAS216_Info *info) { - switch (info->scsi.phase) { - case PHASE_IDLE: return "idle"; - case PHASE_SELECTION: return "selection"; - case PHASE_COMMAND: return "command"; - case PHASE_RECONNECTED: return "reconnected"; - case PHASE_DATAOUT: return "data out"; - case PHASE_DATAIN: return "data in"; - case PHASE_MSGIN: return "message in"; - case PHASE_MSGIN_DISCONNECT: return "disconnect"; - case PHASE_MSGOUT_EXPECT: return "expect message out"; - case PHASE_MSGOUT: return "message out"; - case PHASE_STATUS: return "status"; - case PHASE_DONE: return "done"; - default: return "???"; - } + static const char *phases[] = { + [PHASE_IDLE] = "idle", + [PHASE_SELECTION] = "selection", + [PHASE_COMMAND] = "command", + [PHASE_DATAOUT] = "data out", + [PHASE_DATAIN] = "data in", + [PHASE_MSGIN] = "message in", + [PHASE_MSGIN_DISCONNECT]= "disconnect", + [PHASE_MSGOUT_EXPECT] = "expect message out", + [PHASE_MSGOUT] = "message out", + [PHASE_STATUS] = "status", + [PHASE_DONE] = "done", + }; + + if (info->scsi.phase < ARRAY_SIZE(phases) && + phases[info->scsi.phase]) + return phases[info->scsi.phase]; + return "???"; } static char fas216_target(FAS216_Info *info) @@ -228,56 +252,128 @@ return 'H'; } +static void +fas216_do_log(FAS216_Info *info, char target, char *fmt, va_list ap) +{ + static char buf[1024]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + printk("scsi%d.%c: %s", info->host->host_no, target, buf); +} + +static void +fas216_log_command(FAS216_Info *info, int level, Scsi_Cmnd *SCpnt, char *fmt, ...) +{ + va_list args; + + if (level != 0 && !(level & level_mask)) + return; + + va_start(args, fmt); + fas216_do_log(info, '0' + SCpnt->target, fmt, args); + va_end(args); + + printk("CDB: "); + print_command(SCpnt->cmnd); +} + +static void +fas216_log_target(FAS216_Info *info, int level, int target, char *fmt, ...) +{ + va_list args; + + if (level != 0 && !(level & level_mask)) + return; + + if (target < 0) + target = 'H'; + else + target += '0'; + + va_start(args, fmt); + fas216_do_log(info, target, fmt, args); + va_end(args); + + printk("\n"); +} + +static void fas216_log(FAS216_Info *info, int level, char *fmt, ...) +{ + va_list args; + + if (level != 0 && !(level & level_mask)) + return; + + va_start(args, fmt); + fas216_do_log(info, fas216_target(info), fmt, args); + va_end(args); + + printk("\n"); +} + +#define PH_SIZE 32 + +static struct { int stat, ssr, isr, ph; } ph_list[PH_SIZE]; +static int ph_ptr; + static void add_debug_list(int stat, int ssr, int isr, int ph) { - list[ptr].stat = stat; - list[ptr].ssr = ssr; - list[ptr].isr = isr; - list[ptr].ph = ph; + ph_list[ph_ptr].stat = stat; + ph_list[ph_ptr].ssr = ssr; + ph_list[ph_ptr].isr = isr; + ph_list[ph_ptr].ph = ph; + + ph_ptr = (ph_ptr + 1) & (PH_SIZE-1); +} + +static struct { int command; void *from; } cmd_list[8]; +static int cmd_ptr; + +static void fas216_cmd(FAS216_Info *info, unsigned int command) +{ + cmd_list[cmd_ptr].command = command; + cmd_list[cmd_ptr].from = __builtin_return_address(0); + + cmd_ptr = (cmd_ptr + 1) & 7; - ptr = (ptr + 1) & 7; + fas216_writeb(info, REG_CMD, command); } static void print_debug_list(void) { int i; - i = ptr; + i = ph_ptr; - printk(KERN_ERR "SCSI IRQ trail: "); + printk(KERN_ERR "SCSI IRQ trail\n"); do { - printk("%02X:%02X:%02X:%1X ", - list[i].stat, list[i].ssr, - list[i].isr, list[i].ph); + printk(" %02x:%02x:%02x:%1x", + ph_list[i].stat, ph_list[i].ssr, + ph_list[i].isr, ph_list[i].ph); + i = (i + 1) & (PH_SIZE - 1); + if (((i ^ ph_ptr) & 7) == 0) + printk("\n"); + } while (i != ph_ptr); + if ((i ^ ph_ptr) & 7) + printk("\n"); + + i = cmd_ptr; + printk(KERN_ERR "FAS216 commands: "); + do { + printk("%02x:%p ", cmd_list[i].command, cmd_list[i].from); i = (i + 1) & 7; - } while (i != ptr); + } while (i != cmd_ptr); printk("\n"); } static void fas216_done(FAS216_Info *info, unsigned int result); -/* Function: int fas216_clockrate(unsigned int clock) - * Purpose : calculate correct value to be written into clock conversion - * factor register. - * Params : clock - clock speed in MHz - * Returns : CLKF_ value - */ -static int fas216_clockrate(int clock) -{ - if (clock <= 10 || clock > 40) { - printk(KERN_CRIT - "fas216: invalid clock rate: check your driver!\n"); - clock = -1; - } else - clock = ((clock - 1) / 5 + 1) & 7; - - return clock; -} - -/* Function: unsigned short fas216_get_last_msg(FAS216_Info *info, int pos) - * Purpose : retrieve a last message from the list, using position in fifo - * Params : info - interface to search - * : pos - current fifo position +/** + * fas216_get_last_msg - retrive last message from the list + * @info: interface to search + * @pos: current fifo position + * + * Retrieve a last message from the list, using position in fifo. */ static inline unsigned short fas216_get_last_msg(FAS216_Info *info, int pos) @@ -298,22 +394,21 @@ packed_msg = msg->msg[0]; } -#ifdef DEBUG_MESSAGES - printk("Message: %04X found at position %02X\n", - packed_msg, pos); -#endif + fas216_log(info, LOG_MESSAGES, + "Message: %04x found at position %02x\n", packed_msg, pos); + return packed_msg; } -/* Function: int fas216_syncperiod(FAS216_Info *info, int ns) - * Purpose : Calculate value to be loaded into the STP register - * for a given period in ns - * Params : info - state structure for interface connected to device - * : ns - period in ns (between subsequent bytes) - * Returns : Value suitable for REG_STP +/** + * fas216_syncperiod - calculate STP register value + * @info: state structure for interface connected to device + * @ns: period in ns (between subsequent bytes) + * + * Calculate value to be loaded into the STP register for a given period + * in ns. Returns a value suitable for REG_STP. */ -static int -fas216_syncperiod(FAS216_Info *info, int ns) +static int fas216_syncperiod(FAS216_Info *info, int ns) { int value = (info->ifcfg.clockrate * ns) / 1000; @@ -327,23 +422,28 @@ return value & 31; } -/* Function: void fas216_set_sync(FAS216_Info *info, int target) - * Purpose : Correctly setup FAS216 chip for specified transfer period. - * Params : info - state structure for interface - * : target - target +/** + * fas216_set_sync - setup FAS216 chip for specified transfer period. + * @info: state structure for interface connected to device + * @target: target + * + * Correctly setup FAS216 chip for specified transfer period. * Notes : we need to switch the chip out of FASTSCSI mode if we have * a transfer period >= 200ns - otherwise the chip will violate * the SCSI timings. */ -static void -fas216_set_sync(FAS216_Info *info, int target) +static void fas216_set_sync(FAS216_Info *info, int target) { - outb(info->device[target].sof, REG_SOF(info)); - outb(info->device[target].stp, REG_STP(info)); + unsigned int cntl3; + + fas216_writeb(info, REG_SOF, info->device[target].sof); + fas216_writeb(info, REG_STP, info->device[target].stp); + + cntl3 = info->scsi.cfg[2]; if (info->device[target].period >= (200 / 4)) - outb(info->scsi.cfg[2] & ~CNTL3_FASTSCSI, REG_CNTL3(info)); - else - outb(info->scsi.cfg[2], REG_CNTL3(info)); + cntl3 = cntl3 & ~CNTL3_FASTSCSI; + + fas216_writeb(info, REG_CNTL3, cntl3); } /* Synchronous transfer support @@ -364,19 +464,20 @@ * Using the correct method assures compatibility with wide data * transfers and future enhancements. * - * We will always initiate a synchronous transfer negociation request on + * We will always initiate a synchronous transfer negotiation request on * every INQUIRY or REQUEST SENSE message, unless the target itself has - * at some point performed a synchronous transfer negociation request, or + * at some point performed a synchronous transfer negotiation request, or * we have synchronous transfers disabled for this device. */ -/* Function: void fas216_handlesync(FAS216_Info *info, char *msg) - * Purpose : Handle a synchronous transfer message from the target - * Params : info - state structure for interface - * : msg - message from target +/** + * fas216_handlesync - Handle a synchronous transfer message + * @info: state structure for interface + * @msg: message from target + * + * Handle a synchronous transfer message from the target */ -static void -fas216_handlesync(FAS216_Info *info, char *msg) +static void fas216_handlesync(FAS216_Info *info, char *msg) { struct fas216_device *dev = &info->device[info->SCpnt->target]; enum { sync, async, none, reject } res = none; @@ -392,7 +493,7 @@ * message with a MESSAGE REJECT message. * * Hence, if we get this condition, we disable - * negociation for this device. + * negotiation for this device. */ if (dev->sync_state == neg_inprogress) { dev->sync_state = neg_invalid; @@ -410,14 +511,14 @@ res = reject; break; - /* We were not negociating a synchronous transfer, - * but the device sent us a negociation request. + /* We were not negotiating a synchronous transfer, + * but the device sent us a negotiation request. * Honour the request by sending back a SDTR * message containing our capability, limited by * the targets capability. */ default: - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); if (msg[4] > info->ifcfg.sync_max_depth) msg[4] = info->ifcfg.sync_max_depth; if (msg[3] < 1000 / info->ifcfg.clockrate) @@ -436,7 +537,7 @@ res = sync; break; - /* We initiated the synchronous transfer negociation, + /* We initiated the synchronous transfer negotiation, * and have successfully received a response from the * target. The synchronous transfer agreement has been * reached. Note: if the values returned are out of our @@ -465,7 +566,7 @@ break; case reject: - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; @@ -482,332 +583,277 @@ } } -/* Function: void fas216_handlewide(FAS216_Info *info, char *msg) - * Purpose : Handle a wide transfer message from the target - * Params : info - state structure for interface - * : msg - message from target +/** + * fas216_updateptrs - update data pointers after transfer suspended/paused + * @info: interface's local pointer to update + * @bytes_transferred: number of bytes transferred + * + * Update data pointers after transfer suspended/paused */ -static void -fas216_handlewide(FAS216_Info *info, char *msg) +static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred) { - struct fas216_device *dev = &info->device[info->SCpnt->target]; - enum { wide, bit8, none, reject } res = none; + Scsi_Pointer *SCp = &info->scsi.SCp; -#ifdef SCSI2_WIDE - switch (msg[0]) { - case MESSAGE_REJECT: - /* Wide transfer request failed. - * Note: SCSI II r10: - * - * SCSI devices that are capable of wide - * data transfers shall not respond to a - * WDTR message with a MESSAGE REJECT message. - * - * Hence, if we get this condition, we never - * reattempt negociation for this device. - */ - if (dev->wide_state == neg_inprogress) { - dev->wide_state = neg_invalid; - res = bit8; - } - break; + fas216_checkmagic(info); - case EXTENDED_MESSAGE: - switch (dev->wide_state) { - /* We don't accept wide data transfer requests. - * Respond with a MESSAGE REJECT to prevent a - * wide data transfer agreement from being reached. - */ - case neg_invalid: - res = reject; - break; + BUG_ON(bytes_transferred < 0); - /* We were not negociating a wide data transfer, - * but the device sent is a negociation request. - * Honour the request by sending back a WDTR - * message containing our capability, limited by - * the targets capability. - */ - default: - outb(CMD_SETATN, REG_CMD(info)); - if (msg[3] > info->ifcfg.wide_max_size) - msg[3] = info->ifcfg.wide_max_size; + info->SCpnt->request_bufflen -= bytes_transferred; - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - msg[3]); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - res = wide; + while (bytes_transferred != 0) { + if (SCp->this_residual > bytes_transferred) break; - - /* We initiated the wide data transfer negociation, - * and have successfully received a response from the - * target. The synchronous transfer agreement has been - * reached. Note: if the values returned are out of our - * bounds, we must reject the message. + /* + * We have used up this buffer. Move on to the + * next buffer. */ - case neg_inprogress: - res = reject; - if (msg[3] <= info->ifcfg.wide_max_size) { - dev->wide_state = neg_complete; - res = wide; - } - break; + bytes_transferred -= SCp->this_residual; + if (!next_SCp(SCp) && bytes_transferred) { + printk(KERN_WARNING "scsi%d.%c: out of buffers\n", + info->host->host_no, '0' + info->SCpnt->target); + return; } } -#else - res = reject; -#endif - - switch (res) { - case wide: - dev->wide_xfer = msg[3]; - break; - - case reject: - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - - case bit8: - dev->wide_xfer = 0; - break; - case none: - break; - } + SCp->this_residual -= bytes_transferred; + if (SCp->this_residual) + SCp->ptr += bytes_transferred; + else + SCp->ptr = NULL; } -/* Function: void fas216_updateptrs(FAS216_Info *info, int bytes_transferred) - * Purpose : update data pointers after transfer suspended/paused - * Params : info - interface's local pointer to update - * bytes_transferred - number of bytes transferred +/** + * fas216_pio - transfer data off of/on to card using programmed IO + * @info: interface to transfer data to/from + * @direction: direction to transfer data (DMA_OUT/DMA_IN) + * + * Transfer data off of/on to card using programmed IO. + * Notes: this is incredibly slow. */ -static void -fas216_updateptrs(FAS216_Info *info, int bytes_transferred) +static void fas216_pio(FAS216_Info *info, fasdmadir_t direction) { - unsigned char *ptr; - unsigned int residual; + Scsi_Pointer *SCp = &info->scsi.SCp; fas216_checkmagic(info); - ptr = info->scsi.SCp.ptr; - residual = info->scsi.SCp.this_residual; - - info->SCpnt->request_bufflen -= bytes_transferred; - - while (residual <= bytes_transferred && bytes_transferred) { - /* We have used up this buffer */ - bytes_transferred -= residual; - if (info->scsi.SCp.buffers_residual) { - info->scsi.SCp.buffer++; - info->scsi.SCp.buffers_residual--; - ptr = (unsigned char *)info->scsi.SCp.buffer->address; - residual = info->scsi.SCp.buffer->length; - } else { - ptr = NULL; - residual = 0; - } - } + if (direction == DMA_OUT) + fas216_writeb(info, REG_FF, get_next_SCp_byte(SCp)); + else + put_next_SCp_byte(SCp, fas216_readb(info, REG_FF)); - residual -= bytes_transferred; - ptr += bytes_transferred; + if (SCp->this_residual == 0) + next_SCp(SCp); +} - if (residual == 0) - ptr = NULL; +static void fas216_set_stc(FAS216_Info *info, unsigned int length) +{ + fas216_writeb(info, REG_STCL, length); + fas216_writeb(info, REG_STCM, length >> 8); + fas216_writeb(info, REG_STCH, length >> 16); +} - info->scsi.SCp.ptr = ptr; - info->scsi.SCp.this_residual = residual; +static unsigned int fas216_get_ctc(FAS216_Info *info) +{ + return fas216_readb(info, REG_CTCL) + + (fas216_readb(info, REG_CTCM) << 8) + + (fas216_readb(info, REG_CTCH) << 16); } -/* Function: void fas216_pio(FAS216_Info *info, fasdmadir_t direction) - * Purpose : transfer data off of/on to card using programmed IO - * Params : info - interface to transfer data to/from - * direction - direction to transfer data (DMA_OUT/DMA_IN) - * Notes : this is incredibly slow +/** + * fas216_cleanuptransfer - clean up after a transfer has completed. + * @info: interface to clean up + * + * Update the data pointers according to the number of bytes transferred + * on the SCSI bus. */ -static void -fas216_pio(FAS216_Info *info, fasdmadir_t direction) +static void fas216_cleanuptransfer(FAS216_Info *info) { - unsigned int residual; - char *ptr; + unsigned long total, residual, fifo; + fasdmatype_t dmatype = info->dma.transfer_type; - fas216_checkmagic(info); + info->dma.transfer_type = fasdma_none; - residual = info->scsi.SCp.this_residual; - ptr = info->scsi.SCp.ptr; + /* + * PIO transfers do not need to be cleaned up. + */ + if (dmatype == fasdma_pio || dmatype == fasdma_none) + return; - if (direction == DMA_OUT) - outb(*ptr++, REG_FF(info)); + if (dmatype == fasdma_real_all) + total = info->SCpnt->request_bufflen; else - *ptr++ = inb(REG_FF(info)); + total = info->scsi.SCp.this_residual; - residual -= 1; + residual = fas216_get_ctc(info); - if (residual == 0) { - if (info->scsi.SCp.buffers_residual) { - info->scsi.SCp.buffer++; - info->scsi.SCp.buffers_residual--; - ptr = (unsigned char *)info->scsi.SCp.buffer->address; - residual = info->scsi.SCp.buffer->length; - } else { - ptr = NULL; - residual = 0; - } - } + fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; - info->scsi.SCp.ptr = ptr; - info->scsi.SCp.this_residual = residual; + fas216_log(info, LOG_BUFFER, "cleaning up from previous " + "transfer: length 0x%06x, residual 0x%x, fifo %d", + total, residual, fifo); + + /* + * If we were performing Data-Out, the transfer counter + * counts down each time a byte is transferred by the + * host to the FIFO. This means we must include the + * bytes left in the FIFO from the transfer counter. + */ + if (info->scsi.phase == PHASE_DATAOUT) + residual += fifo; + + fas216_updateptrs(info, total - residual); } -/* Function: void fas216_starttransfer(FAS216_Info *info, - * fasdmadir_t direction) - * Purpose : Start a DMA/PIO transfer off of/on to card - * Params : info - interface from which device disconnected from - * direction - transfer direction (DMA_OUT/DMA_IN) +/** + * fas216_transfer - Perform a DMA/PIO transfer off of/on to card + * @info: interface from which device disconnected from + * + * Start a DMA/PIO transfer off of/on to card */ -static void -fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo) +static void fas216_transfer(FAS216_Info *info) { + fasdmadir_t direction; fasdmatype_t dmatype; - fas216_checkmagic(info); - - info->scsi.phase = (direction == DMA_OUT) ? - PHASE_DATAOUT : PHASE_DATAIN; - - if (info->dma.transfer_type != fasdma_none && - info->dma.transfer_type != fasdma_pio) { - unsigned long total, residual; - - if (info->dma.transfer_type == fasdma_real_all) - total = info->SCpnt->request_bufflen; - else - total = info->scsi.SCp.this_residual; - - residual = (inb(REG_CFIS(info)) & CFIS_CF) + - inb(REG_CTCL(info)) + - (inb(REG_CTCM(info)) << 8) + - (inb(REG_CTCH(info)) << 16); - fas216_updateptrs(info, total - residual); - } - info->dma.transfer_type = fasdma_none; + fas216_log(info, LOG_BUFFER, + "starttransfer: buffer %p length 0x%06x reqlen 0x%06x", + info->scsi.SCp.ptr, info->scsi.SCp.this_residual, + info->SCpnt->request_bufflen); if (!info->scsi.SCp.ptr) { - printk("scsi%d.%c: null buffer passed to " - "fas216_starttransfer\n", info->host->host_no, - fas216_target(info)); + fas216_log(info, LOG_ERROR, "null buffer passed to " + "fas216_starttransfer"); + print_SCp(&info->scsi.SCp, "SCp: ", "\n"); + print_SCp(&info->SCpnt->SCp, "Cmnd SCp: ", "\n"); return; } - /* flush FIFO */ - if (flush_fifo) - outb(CMD_FLUSHFIFO, REG_CMD(info)); - /* - * Default to PIO mode or DMA mode if we have a synchronous - * transfer agreement. + * If we have a synchronous transfer agreement in effect, we must + * use DMA mode. If we are using asynchronous transfers, we may + * use DMA mode or PIO mode. */ - if (info->device[info->SCpnt->target].sof && info->dma.setup) + if (info->device[info->SCpnt->target].sof) dmatype = fasdma_real_all; else dmatype = fasdma_pio; + if (info->scsi.phase == PHASE_DATAOUT) + direction = DMA_OUT; + else + direction = DMA_IN; + if (info->dma.setup) dmatype = info->dma.setup(info->host, &info->scsi.SCp, direction, dmatype); info->dma.transfer_type = dmatype; + if (dmatype == fasdma_real_all) + fas216_set_stc(info, info->SCpnt->request_bufflen); + else + fas216_set_stc(info, info->scsi.SCp.this_residual); + switch (dmatype) { case fasdma_pio: - outb(0, REG_SOF(info)); - outb(info->scsi.async_stp, REG_STP(info)); - outb(info->scsi.SCp.this_residual, REG_STCL(info)); - outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); - outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_log(info, LOG_BUFFER, "PIO transfer"); + fas216_writeb(info, REG_SOF, 0); + fas216_writeb(info, REG_STP, info->scsi.async_stp); + fas216_cmd(info, CMD_TRANSFERINFO); fas216_pio(info, direction); break; case fasdma_pseudo: - outb(info->scsi.SCp.this_residual, REG_STCL(info)); - outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); - outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); + fas216_log(info, LOG_BUFFER, "pseudo transfer"); + fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); info->dma.pseudo(info->host, &info->scsi.SCp, direction, info->SCpnt->transfersize); break; case fasdma_real_block: - outb(info->scsi.SCp.this_residual, REG_STCL(info)); - outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info)); - outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); + fas216_log(info, LOG_BUFFER, "block dma transfer"); + fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); break; case fasdma_real_all: - outb(info->SCpnt->request_bufflen, REG_STCL(info)); - outb(info->SCpnt->request_bufflen >> 8, REG_STCM(info)); - outb(info->SCpnt->request_bufflen >> 16, REG_STCH(info)); - outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info)); + fas216_log(info, LOG_BUFFER, "total dma transfer"); + fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); break; default: - printk(KERN_ERR "scsi%d.%d: invalid FAS216 DMA type\n", - info->host->host_no, fas216_target(info)); + fas216_log(info, LOG_BUFFER | LOG_ERROR, + "invalid FAS216 DMA type"); break; } } -/* Function: void fas216_stoptransfer(FAS216_Info *info) - * Purpose : Stop a DMA transfer onto / off of the card - * Params : info - interface from which device disconnected from +/** + * fas216_stoptransfer - Stop a DMA transfer onto / off of the card + * @info: interface from which device disconnected from + * + * Called when we switch away from DATA IN or DATA OUT phases. */ -static void -fas216_stoptransfer(FAS216_Info *info) +static void fas216_stoptransfer(FAS216_Info *info) { fas216_checkmagic(info); - if (info->dma.transfer_type != fasdma_none && - info->dma.transfer_type != fasdma_pio) { - unsigned long total, residual; + if (info->dma.transfer_type == fasdma_real_all || + info->dma.transfer_type == fasdma_real_block) + info->dma.stop(info->host, &info->scsi.SCp); - if ((info->dma.transfer_type == fasdma_real_all || - info->dma.transfer_type == fasdma_real_block) && - info->dma.stop) - info->dma.stop(info->host, &info->scsi.SCp); + fas216_cleanuptransfer(info); - if (info->dma.transfer_type == fasdma_real_all) - total = info->SCpnt->request_bufflen; - else - total = info->scsi.SCp.this_residual; + if (info->scsi.phase == PHASE_DATAIN) { + unsigned int fifo; - residual = (inb(REG_CFIS(info)) & CFIS_CF) + - inb(REG_CTCL(info)) + - (inb(REG_CTCM(info)) << 8) + - (inb(REG_CTCH(info)) << 16); - fas216_updateptrs(info, total - residual); - info->dma.transfer_type = fasdma_none; + /* + * If we were performing Data-In, then the FIFO counter + * contains the number of bytes not transferred via DMA + * from the on-board FIFO. Read them manually. + */ + fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; + while (fifo && info->scsi.SCp.ptr) { + *info->scsi.SCp.ptr = fas216_readb(info, REG_FF); + fas216_updateptrs(info, 1); + fifo--; + } + } else { + /* + * After a Data-Out phase, there may be unsent + * bytes left in the FIFO. Flush them out. + */ + fas216_cmd(info, CMD_FLUSHFIFO); } - if (info->scsi.phase == PHASE_DATAOUT) - outb(CMD_FLUSHFIFO, REG_CMD(info)); } -/* Function: void fas216_disconnected_intr(FAS216_Info *info) - * Purpose : handle device disconnection - * Params : info - interface from which device disconnected from +static void fas216_aborttransfer(FAS216_Info *info) +{ + fas216_checkmagic(info); + + if (info->dma.transfer_type == fasdma_real_all || + info->dma.transfer_type == fasdma_real_block) + info->dma.stop(info->host, &info->scsi.SCp); + + info->dma.transfer_type = fasdma_none; + fas216_cmd(info, CMD_FLUSHFIFO); +} + +static void fas216_kick(FAS216_Info *info); + +/** + * fas216_disconnected_intr - handle device disconnection + * @info: interface from which device disconnected from + * + * Handle device disconnection */ -static void -fas216_disconnect_intr(FAS216_Info *info) +static void fas216_disconnect_intr(FAS216_Info *info) { + unsigned long flags; + fas216_checkmagic(info); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no, - fas216_target(info), info->scsi.phase); -#endif + fas216_log(info, LOG_CONNECT, "disconnect phase=%02x", + info->scsi.phase); + msgqueue_flush(&info->scsi.msgs); switch (info->scsi.phase) { @@ -817,11 +863,13 @@ break; case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */ - outb(CMD_ENABLESEL, REG_CMD(info)); info->scsi.disconnectable = 1; - info->scsi.reconnected.tag = 0; info->scsi.phase = PHASE_IDLE; info->stats.disconnects += 1; + spin_lock_irqsave(&info->host_lock, flags); + if (info->scsi.phase == PHASE_IDLE) + fas216_kick(info); + spin_unlock_irqrestore(&info->host_lock, flags); break; case PHASE_DONE: /* at end of command - complete */ @@ -845,295 +893,131 @@ } } -/* Function: void fas216_reselected_intr(FAS216_Info *info) - * Purpose : Start reconnection of a device - * Params : info - interface which was reselected +/** + * fas216_reselected_intr - start reconnection of a device + * @info: interface which was reselected + * + * Start reconnection of a device */ static void fas216_reselected_intr(FAS216_Info *info) { - unsigned char target, identify_msg, ok; + unsigned int cfis, i; + unsigned char msg[4]; + unsigned char target, lun, tag; fas216_checkmagic(info); - if ((info->scsi.phase == PHASE_SELECTION || - info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) { - Scsi_Cmnd *SCpnt = info->SCpnt; + if (info->scsi.phase == PHASE_SELECTION || + info->scsi.phase == PHASE_SELSTEPS) { + fas216_log(info, LOG_ERROR, "wrong phase in reselected_intr\n"); + return; + } - info->origSCpnt = SCpnt; - info->SCpnt = NULL; + cfis = fas216_readb(info, REG_CFIS); - if (info->device[SCpnt->target].wide_state == neg_inprogress) - info->device[SCpnt->target].wide_state = neg_wait; - if (info->device[SCpnt->target].sync_state == neg_inprogress) - info->device[SCpnt->target].sync_state = neg_wait; - } + fas216_log(info, LOG_CONNECT, "reconnect phase=%02x cfis=%02x", + info->scsi.phase, cfis); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: reconnect phase=%02X\n", info->host->host_no, - fas216_target(info), info->scsi.phase); -#endif + cfis &= CFIS_CF; - if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) { + if (cfis < 2 || cfis > 4) { printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n", info->host->host_no); - outb(CMD_SETATN, REG_CMD(info)); - outb(CMD_MSGACCEPTED, REG_CMD(info)); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - return; - } - - target = inb(REG_FF(info)); - identify_msg = inb(REG_FF(info)); - - ok = 1; - if (!(target & (1 << info->host->this_id))) { - printk(KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no); - ok = 0; + goto bad_message; } - if (!(identify_msg & 0x80)) { - printk(KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n", - info->host->host_no, identify_msg); - ok = 0; - } + for (i = 0; i < cfis; i++) + msg[i] = fas216_readb(info, REG_FF); - if (!ok) { - /* - * Something went wrong - send an initiator error to - * the target. - */ - outb(CMD_SETATN, REG_CMD(info)); - outb(CMD_MSGACCEPTED, REG_CMD(info)); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - return; - } + if (!(msg[0] & (1 << info->host->this_id)) || + !(msg[1] & 0x80)) + goto initiator_error; - target &= ~(1 << info->host->this_id); - switch (target) { - case 1: target = 0; break; - case 2: target = 1; break; - case 4: target = 2; break; - case 8: target = 3; break; - case 16: target = 4; break; - case 32: target = 5; break; - case 64: target = 6; break; - case 128: target = 7; break; - default: target = info->host->this_id; break; - } - - identify_msg &= 7; - info->scsi.reconnected.target = target; - info->scsi.reconnected.lun = identify_msg; - info->scsi.reconnected.tag = 0; - - ok = 0; - if (info->scsi.disconnectable && info->SCpnt && - info->SCpnt->target == target && info->SCpnt->lun == identify_msg) - ok = 1; + target = msg[0] & ~(1 << info->host->this_id); + target = ffs(target) - 1; + lun = msg[1] & 7; + tag = 0; - if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg)) - ok = 1; + if (cfis >= 3) { + if (msg[2] != SIMPLE_QUEUE_TAG) + goto initiator_error; - msgqueue_flush(&info->scsi.msgs); - if (ok) { - info->scsi.phase = PHASE_RECONNECTED; - outb(target, REG_SDID(info)); - } else { - /* - * Our command structure not found - abort the - * command on the target. Since we have no - * record of this command, we can't send - * an INITIATOR DETECTED ERROR message. - */ - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; + tag = msg[3]; } - outb(CMD_MSGACCEPTED, REG_CMD(info)); -} - -/* Function: void fas216_finish_reconnect(FAS216_Info *info) - * Purpose : finish reconnection sequence for device - * Params : info - interface which caused function done interrupt - */ -static void -fas216_finish_reconnect(FAS216_Info *info) -{ - fas216_checkmagic(info); + /* set up for synchronous transfers */ + fas216_writeb(info, REG_SDID, target); + fas216_set_sync(info, target); + msgqueue_flush(&info->scsi.msgs); -#ifdef DEBUG_CONNECT - printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n", - info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag, - info->scsi.reconnected.target, info->scsi.reconnected.lun, - info->scsi.reconnected.tag); -#endif + fas216_log(info, LOG_CONNECT, "Reconnected: target %1x lun %1x tag %02x", + target, lun, tag); if (info->scsi.disconnectable && info->SCpnt) { info->scsi.disconnectable = 0; - if (info->SCpnt->target == info->scsi.reconnected.target && - info->SCpnt->lun == info->scsi.reconnected.lun && - info->SCpnt->tag == info->scsi.reconnected.tag) { -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: reconnected", - info->host->host_no, fas216_target(info)); -#endif + if (info->SCpnt->target == target && + info->SCpnt->lun == lun && + info->SCpnt->tag == tag) { + fas216_log(info, LOG_CONNECT, "reconnected previously connected command"); } else { queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: had to move command to disconnected queue\n", - info->host->host_no, fas216_target(info)); -#endif + fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue"); info->SCpnt = NULL; } } if (!info->SCpnt) { info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected, - info->scsi.reconnected.target, - info->scsi.reconnected.lun, - info->scsi.reconnected.tag); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: had to get command", - info->host->host_no, fas216_target(info)); -#endif + target, lun, tag); + fas216_log(info, LOG_CONNECT, "had to get command"); } - if (!info->SCpnt) { - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_flush(&info->scsi.msgs); -#if 0 - if (info->scsi.reconnected.tag) - msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag); - else -#endif - msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - info->scsi.aborting = 1; - } else { + + if (info->SCpnt) { /* * Restore data pointer from SAVED data pointer */ info->scsi.SCp = info->SCpnt->SCp; -#ifdef DEBUG_CONNECT - printk(", data pointers: [%p, %X]", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif - } -#ifdef DEBUG_CONNECT - printk("\n"); -#endif -} -static int fas216_wait_cmd(FAS216_Info *info, int cmd) -{ - int tout; - int stat; - - outb(cmd, REG_CMD(info)); + fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]", + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + info->scsi.phase = PHASE_MSGIN; + } else { + /* + * Our command structure not found - abort the + * command on the target. Since we have no + * record of this command, we can't send + * an INITIATOR DETECTED ERROR message. + */ + fas216_cmd(info, CMD_SETATN); - for (tout = 1000; tout; tout -= 1) { - stat = inb(REG_STAT(info)); - if (stat & STAT_INT) - break; - udelay(1); + if (tag) + msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, tag); + else + msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + info->scsi.aborting = 1; } - return stat; -} - -static int fas216_get_msg_byte(FAS216_Info *info) -{ - int stat; - - stat = fas216_wait_cmd(info, CMD_MSGACCEPTED); - - if ((stat & STAT_INT) == 0) - goto timedout; - - if ((stat & STAT_BUSMASK) != STAT_MESGIN) - goto unexpected_phase_change; - - inb(REG_INST(info)); - - stat = fas216_wait_cmd(info, CMD_TRANSFERINFO); - - if ((stat & STAT_INT) == 0) - goto timedout; - - if ((stat & STAT_BUSMASK) != STAT_MESGIN) - goto unexpected_phase_change; - - inb(REG_INST(info)); - - return inb(REG_FF(info)); - -timedout: - printk("scsi%d.%c: timed out waiting for message byte\n", - info->host->host_no, fas216_target(info)); - return -1; - -unexpected_phase_change: - printk("scsi%d.%c: unexpected phase change: status = %02X\n", - info->host->host_no, fas216_target(info), stat); + fas216_cmd(info, CMD_MSGACCEPTED); + return; - return -2; + initiator_error: + printk(KERN_ERR "scsi%d.H: error during reselection: bytes", + info->host->host_no); + for (i = 0; i < cfis; i++) + printk(" %02x", msg[i]); + printk("\n"); + bad_message: + fas216_cmd(info, CMD_SETATN); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + fas216_cmd(info, CMD_MSGACCEPTED); } -/* Function: void fas216_message(FAS216_Info *info) - * Purpose : handle a function done interrupt from FAS216 chip - * Params : info - interface which caused function done interrupt - */ -static void fas216_message(FAS216_Info *info) +static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen) { - unsigned char *message = info->scsi.message; - unsigned int msglen = 1, i; - int msgbyte = 0; - - fas216_checkmagic(info); - - message[0] = inb(REG_FF(info)); - - if (message[0] == EXTENDED_MESSAGE) { - msgbyte = fas216_get_msg_byte(info); - - if (msgbyte >= 0) { - message[1] = msgbyte; - - for (msglen = 2; msglen < message[1] + 2; msglen++) { - msgbyte = fas216_get_msg_byte(info); - - if (msgbyte >= 0) - message[msglen] = msgbyte; - else - break; - } - } - } - - info->scsi.msglen = msglen; - -#ifdef DEBUG_MESSAGES - { - int i; - - printk("scsi%d.%c: message in: ", - info->host->host_no, fas216_target(info)); - for (i = 0; i < msglen; i++) - printk("%02X ", message[i]); - printk("\n"); - } -#endif - - if (info->scsi.phase == PHASE_RECONNECTED) { - if (message[0] == SIMPLE_QUEUE_TAG) - info->scsi.reconnected.tag = message[1]; - fas216_finish_reconnect(info); - info->scsi.phase = PHASE_MSGIN; - } + int i; switch (message[0]) { case COMMAND_COMPLETE: @@ -1159,11 +1043,9 @@ */ info->SCpnt->SCp = info->scsi.SCp; info->SCpnt->SCp.sent_command = 0; -#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT) - printk("scsi%d.%c: save data pointers: [%p, %X]\n", - info->host->host_no, fas216_target(info), + fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER, + "save data pointers: [%p, %X]", info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif break; case RESTORE_POINTERS: @@ -1174,11 +1056,9 @@ * Restore current data pointer from SAVED data pointer */ info->scsi.SCp = info->SCpnt->SCp; -#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT) - printk("scsi%d.%c: restore data pointers: [%p, %X]\n", - info->host->host_no, fas216_target(info), + fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER, + "restore data pointers: [%p, 0x%x]", info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif break; case DISCONNECT: @@ -1197,13 +1077,8 @@ fas216_handlesync(info, message); break; - case EXTENDED_MESSAGE | EXTENDED_WDTR << 8: - fas216_handlewide(info, message); - break; - default: - printk("scsi%d.%c: reject, last message %04X\n", - info->host->host_no, fas216_target(info), + fas216_log(info, 0, "reject, last message 0x%04x", fas216_get_last_msg(info, info->scsi.msgin_fifo)); } break; @@ -1211,29 +1086,15 @@ case NOP: break; - case SIMPLE_QUEUE_TAG: - if (msglen < 2) - goto unrecognised; - - /* handled above - print a warning since this is untested */ - printk("scsi%d.%c: reconnect queue tag %02X\n", - info->host->host_no, fas216_target(info), - message[1]); - break; - case EXTENDED_MESSAGE: if (msglen < 3) goto unrecognised; switch (message[2]) { - case EXTENDED_SDTR: /* Sync transfer negociation request/reply */ + case EXTENDED_SDTR: /* Sync transfer negotiation request/reply */ fas216_handlesync(info, message); break; - case EXTENDED_WDTR: /* Wide transfer negociation request/reply */ - fas216_handlewide(info, message); - break; - default: goto unrecognised; } @@ -1242,12 +1103,10 @@ default: goto unrecognised; } - outb(CMD_MSGACCEPTED, REG_CMD(info)); return; unrecognised: - printk("scsi%d.%c: unrecognised message, rejecting\n", - info->host->host_no, fas216_target(info)); + fas216_log(info, 0, "unrecognised message, rejecting"); printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info)); for (i = 0; i < msglen; i++) printk("%s%02X", i & 31 ? " " : "\n ", message[i]); @@ -1258,19 +1117,138 @@ * I can't use SETATN since the chip gives me an * invalid command interrupt when I do. Weird. */ -outb(CMD_NOP, REG_CMD(info)); +fas216_cmd(info, CMD_NOP); fas216_dumpstate(info); - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; fas216_dumpstate(info); - outb(CMD_MSGACCEPTED, REG_CMD(info)); } -/* Function: void fas216_send_command(FAS216_Info *info) - * Purpose : send a command to a target after all message bytes have been sent - * Params : info - interface which caused bus service +static int fas216_wait_cmd(FAS216_Info *info, int cmd) +{ + int tout; + int stat; + + fas216_cmd(info, cmd); + + for (tout = 1000; tout; tout -= 1) { + stat = fas216_readb(info, REG_STAT); + if (stat & (STAT_INT|STAT_PARITYERROR)) + break; + udelay(1); + } + + return stat; +} + +static int fas216_get_msg_byte(FAS216_Info *info) +{ + unsigned int stat = fas216_wait_cmd(info, CMD_MSGACCEPTED); + + if ((stat & STAT_INT) == 0) + goto timedout; + + if ((stat & STAT_BUSMASK) != STAT_MESGIN) + goto unexpected_phase_change; + + fas216_readb(info, REG_INST); + + stat = fas216_wait_cmd(info, CMD_TRANSFERINFO); + + if ((stat & STAT_INT) == 0) + goto timedout; + + if (stat & STAT_PARITYERROR) + goto parity_error; + + if ((stat & STAT_BUSMASK) != STAT_MESGIN) + goto unexpected_phase_change; + + fas216_readb(info, REG_INST); + + return fas216_readb(info, REG_FF); + +timedout: + fas216_log(info, LOG_ERROR, "timed out waiting for message byte"); + return -1; + +unexpected_phase_change: + fas216_log(info, LOG_ERROR, "unexpected phase change: status = %02x", stat); + return -2; + +parity_error: + fas216_log(info, LOG_ERROR, "parity error during message in phase"); + return -3; +} + +/** + * fas216_message - handle a function done interrupt from FAS216 chip + * @info: interface which caused function done interrupt + * + * Handle a function done interrupt from FAS216 chip + */ +static void fas216_message(FAS216_Info *info) +{ + unsigned char *message = info->scsi.message; + unsigned int msglen = 1; + int msgbyte = 0; + + fas216_checkmagic(info); + + message[0] = fas216_readb(info, REG_FF); + + if (message[0] == EXTENDED_MESSAGE) { + msgbyte = fas216_get_msg_byte(info); + + if (msgbyte >= 0) { + message[1] = msgbyte; + + for (msglen = 2; msglen < message[1] + 2; msglen++) { + msgbyte = fas216_get_msg_byte(info); + + if (msgbyte >= 0) + message[msglen] = msgbyte; + else + break; + } + } + } + + if (msgbyte == -3) + goto parity_error; + +#ifdef DEBUG_MESSAGES + { + int i; + + printk("scsi%d.%c: message in: ", + info->host->host_no, fas216_target(info)); + for (i = 0; i < msglen; i++) + printk("%02X ", message[i]); + printk("\n"); + } +#endif + + fas216_parse_message(info, message, msglen); + fas216_cmd(info, CMD_MSGACCEPTED); + return; + +parity_error: + fas216_cmd(info, CMD_SETATN); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, MSG_PARITY_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + fas216_cmd(info, CMD_MSGACCEPTED); + return; +} + +/** + * fas216_send_command - send command after all message bytes have been sent + * @info: interface which caused bus service + * + * Send a command to a target after all message bytes have been sent */ static void fas216_send_command(FAS216_Info *info) { @@ -1278,22 +1256,24 @@ fas216_checkmagic(info); - outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info)); - outb(CMD_FLUSHFIFO, REG_CMD(info)); + fas216_cmd(info, CMD_NOP|CMD_WITHDMA); + fas216_cmd(info, CMD_FLUSHFIFO); /* load command */ for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++) - outb(info->SCpnt->cmnd[i], REG_FF(info)); + fas216_writeb(info, REG_FF, info->SCpnt->cmnd[i]); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO); info->scsi.phase = PHASE_COMMAND; } -/* Function: void fas216_send_messageout(FAS216_Info *info, int start) - * Purpose : handle bus service to send a message - * Params : info - interface which caused bus service - * Note : We do not allow the device to change the data direction! +/** + * fas216_send_messageout - handle bus service to send a message + * @info: interface which caused bus service + * + * Handle bus service to send a message. + * Note: We do not allow the device to change the data direction! */ static void fas216_send_messageout(FAS216_Info *info, int start) { @@ -1301,7 +1281,7 @@ fas216_checkmagic(info); - outb(CMD_FLUSHFIFO, REG_CMD(info)); + fas216_cmd(info, CMD_FLUSHFIFO); if (tot_msglen) { struct message *msg; @@ -1311,42 +1291,43 @@ int i; for (i = start; i < msg->length; i++) - outb(msg->msg[i], REG_FF(info)); + fas216_writeb(info, REG_FF, msg->msg[i]); - msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); + msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF); start = 0; } } else - outb(NOP, REG_FF(info)); + fas216_writeb(info, REG_FF, NOP); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO); info->scsi.phase = PHASE_MSGOUT; } -/* Function: void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) - * Purpose : handle a bus service interrupt from FAS216 chip - * Params : info - interface which caused bus service interrupt - * stat - Status register contents - * ssr - SCSI Status register contents +/** + * fas216_busservice_intr - handle bus service interrupt from FAS216 chip + * @info: interface which caused bus service interrupt + * @stat: Status register contents + * @is: SCSI Status register contents + * + * Handle a bus service interrupt from FAS216 chip */ -static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) +static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int is) { fas216_checkmagic(info); -#ifdef DEBUG_BUSSERVICE - printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n", - info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); -#endif + fas216_log(info, LOG_BUSSERVICE, + "bus service: stat=%02x is=%02x phase=%02x", + stat, is, info->scsi.phase); switch (info->scsi.phase) { case PHASE_SELECTION: - if ((ssr & IS_BITS) != 1) + if ((is & IS_BITS) != IS_MSGBYTESENT) goto bad_is; break; case PHASE_SELSTEPS: - switch (ssr & IS_BITS) { + switch (is & IS_BITS) { case IS_SELARB: case IS_MSGBYTESENT: goto bad_is; @@ -1365,42 +1346,36 @@ break; } - outb(CMD_NOP, REG_CMD(info)); + fas216_cmd(info, CMD_NOP); #define STATE(st,ph) ((ph) << 3 | (st)) /* This table describes the legal SCSI state transitions, * as described by the SCSI II spec. */ switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) { - /* Reselmsgin -> Data In */ - case STATE(STAT_DATAIN, PHASE_RECONNECTED): - fas216_finish_reconnect(info); case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */ - case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */ case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */ case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */ - fas216_starttransfer(info, DMA_IN, 0); + info->scsi.phase = PHASE_DATAIN; + fas216_transfer(info); return; + case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */ case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */ - fas216_starttransfer(info, DMA_OUT, 0); + fas216_cleanuptransfer(info); + fas216_transfer(info); return; - /* Reselmsgin -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_RECONNECTED): - fas216_finish_reconnect(info); case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */ case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */ case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */ - fas216_starttransfer(info, DMA_OUT, 1); + fas216_cmd(info, CMD_FLUSHFIFO); + info->scsi.phase = PHASE_DATAOUT; + fas216_transfer(info); return; - /* Reselmsgin -> Status */ - case STATE(STAT_STATUS, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - goto status; case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ fas216_stoptransfer(info); @@ -1408,8 +1383,7 @@ case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ - status: - outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); + fas216_cmd(info, CMD_INITCMDCOMPLETE); info->scsi.phase = PHASE_STATUS; return; @@ -1419,32 +1393,59 @@ case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */ case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */ - info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; - outb(CMD_FLUSHFIFO, REG_CMD(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; + fas216_cmd(info, CMD_FLUSHFIFO); + fas216_cmd(info, CMD_TRANSFERINFO); info->scsi.phase = PHASE_MSGIN; return; - /* Reselmsgin -> Message In */ - case STATE(STAT_MESGIN, PHASE_RECONNECTED): case STATE(STAT_MESGIN, PHASE_MSGIN): - info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; - outb(CMD_TRANSFERINFO, REG_CMD(info)); + info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; + fas216_cmd(info, CMD_TRANSFERINFO); return; - /* Reselmsgin -> Command */ - case STATE(STAT_COMMAND, PHASE_RECONNECTED): - fas216_finish_reconnect(info); case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */ case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */ fas216_send_command(info); info->scsi.phase = PHASE_COMMAND; return; - /* Selection -> Message Out */ + + + /* + * Selection -> Message Out + */ case STATE(STAT_MESGOUT, PHASE_SELECTION): fas216_send_messageout(info, 1); return; - /* Any -> Message Out */ + + /* + * Message Out -> Message Out + */ + case STATE(STAT_MESGOUT, PHASE_SELSTEPS): + case STATE(STAT_MESGOUT, PHASE_MSGOUT): + /* + * If we get another message out phase, this usually + * means some parity error occurred. Resend complete + * set of messages. If we have more than one byte to + * send, we need to assert ATN again. + */ + if (info->device[info->SCpnt->target].parity_check) { + /* + * We were testing... good, the device + * supports parity checking. + */ + info->device[info->SCpnt->target].parity_check = 0; + info->device[info->SCpnt->target].parity_enabled = 1; + fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); + } + + if (msgqueue_msglength(&info->scsi.msgs) > 1) + fas216_cmd(info, CMD_SETATN); + /*FALLTHROUGH*/ + + /* + * Any -> Message Out + */ case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT): fas216_send_messageout(info, 0); return; @@ -1463,30 +1464,13 @@ printk(KERN_ERR "scsi%d.%c: " "target trying to receive more command bytes\n", info->host->host_no, fas216_target(info)); - outb(CMD_SETATN, REG_CMD(info)); - outb(15, REG_STCL(info)); - outb(0, REG_STCM(info)); - outb(0, REG_STCH(info)); - outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); + fas216_set_stc(info, 15); + fas216_cmd(info, CMD_PADBYTES | CMD_WITHDMA); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); info->scsi.phase = PHASE_MSGOUT_EXPECT; return; - - /* Selection -> Message Out */ - case STATE(STAT_MESGOUT, PHASE_SELSTEPS): - case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out -> Message Out */ - /* If we get another message out phase, this - * usually means some parity error occurred. - * Resend complete set of messages. If we have - * more than 1 byte to send, we need to assert - * ATN again. - */ - if (msgqueue_msglength(&info->scsi.msgs) > 1) - outb(CMD_SETATN, REG_CMD(info)); - - fas216_send_messageout(info, 0); - return; } if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) { @@ -1494,11 +1478,11 @@ info->host->host_no, fas216_target(info), fas216_bus_phase(stat)); msgqueue_flush(&info->scsi.msgs); - outb(CMD_SETATN, REG_CMD(info)); + fas216_cmd(info, CMD_SETATN); msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); info->scsi.phase = PHASE_MSGOUT_EXPECT; info->scsi.aborting = 1; - outb(CMD_TRANSFERINFO, REG_CMD(info)); + fas216_cmd(info, CMD_TRANSFERINFO); return; } printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n", @@ -1509,191 +1493,245 @@ return; bad_is: - printk("scsi%d.%c: bus service at step %d?\n", - info->host->host_no, fas216_target(info), - ssr & IS_BITS); + fas216_log(info, 0, "bus service at step %d?", is & IS_BITS); + fas216_dumpstate(info); print_debug_list(); fas216_done(info, DID_ERROR); } -/* Function: void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) - * Purpose : handle a function done interrupt from FAS216 chip - * Params : info - interface which caused function done interrupt - * stat - Status register contents - * ssr - SCSI Status register contents +/** + * fas216_funcdone_intr - handle a function done interrupt from FAS216 chip + * @info: interface which caused function done interrupt + * @stat: Status register contents + * @is: SCSI Status register contents + * + * Handle a function done interrupt from FAS216 chip */ -static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) +static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int is) { - int status, message; + unsigned int fifo_len = fas216_readb(info, REG_CFIS) & CFIS_CF; fas216_checkmagic(info); -#ifdef DEBUG_FUNCTIONDONE - printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n", - info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); -#endif + fas216_log(info, LOG_FUNCTIONDONE, + "function done: stat=%02x is=%02x phase=%02x", + stat, is, info->scsi.phase); + switch (info->scsi.phase) { case PHASE_STATUS: /* status phase - read status and msg */ - status = inb(REG_FF(info)); - message = inb(REG_FF(info)); - info->scsi.SCp.Message = message; - info->scsi.SCp.Status = status; + if (fifo_len != 2) { + fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len); + } + /* + * Read status then message byte. + */ + info->scsi.SCp.Status = fas216_readb(info, REG_FF); + info->scsi.SCp.Message = fas216_readb(info, REG_FF); info->scsi.phase = PHASE_DONE; - outb(CMD_MSGACCEPTED, REG_CMD(info)); + fas216_cmd(info, CMD_MSGACCEPTED); + break; + + case PHASE_IDLE: + case PHASE_SELECTION: + case PHASE_SELSTEPS: break; - case PHASE_IDLE: /* reselected? */ case PHASE_MSGIN: /* message in phase */ - case PHASE_RECONNECTED: /* reconnected command */ if ((stat & STAT_BUSMASK) == STAT_MESGIN) { - info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; + info->scsi.msgin_fifo = fifo_len; fas216_message(info); break; } default: - printk("scsi%d.%c: internal phase %s for function done?" - " What do I do with this?\n", - info->host->host_no, fas216_target(info), + fas216_log(info, 0, "internal phase %s for function done?" + " What do I do with this?", fas216_drv_phase(info)); } } -/* Function: void fas216_intr(struct Scsi_Host *instance) - * Purpose : handle interrupts from the interface to progress a command - * Params : instance - interface to service +static void fas216_bus_reset(FAS216_Info *info) +{ + neg_t sync_state; + int i; + + msgqueue_flush(&info->scsi.msgs); + + sync_state = neg_invalid; + +#ifdef SCSI2_SYNC + if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA)) + sync_state = neg_wait; +#endif + + info->scsi.phase = PHASE_IDLE; + info->SCpnt = NULL; /* bug! */ + memset(&info->scsi.SCp, 0, sizeof(info->scsi.SCp)); + + for (i = 0; i < 8; i++) { + info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; + info->device[i].sync_state = sync_state; + info->device[i].period = info->ifcfg.asyncperiod / 4; + info->device[i].stp = info->scsi.async_stp; + info->device[i].sof = 0; + info->device[i].wide_xfer = 0; + } + + info->rst_bus_status = 1; + wake_up(&info->eh_wait); +} + +/** + * fas216_intr - handle interrupts to progress a command + * @info: interface to service + * + * Handle interrupts from the interface to progress a command */ -void fas216_intr(struct Scsi_Host *instance) +void fas216_intr(FAS216_Info *info) { - FAS216_Info *info = (FAS216_Info *)instance->hostdata; - unsigned char isr, ssr, stat; + unsigned char inst, is, stat; fas216_checkmagic(info); - stat = inb(REG_STAT(info)); - ssr = inb(REG_IS(info)); - isr = inb(REG_INST(info)); + stat = fas216_readb(info, REG_STAT); + is = fas216_readb(info, REG_IS); + inst = fas216_readb(info, REG_INST); - add_debug_list(stat, ssr, isr, info->scsi.phase); + add_debug_list(stat, is, inst, info->scsi.phase); if (stat & STAT_INT) { - if (isr & INST_BUSRESET) { - printk(KERN_DEBUG "scsi%d.H: bus reset detected\n", instance->host_no); - scsi_report_bus_reset(instance, 0); - } else if (isr & INST_ILLEGALCMD) { - printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no); + if (inst & INST_BUSRESET) { + fas216_log(info, 0, "bus reset detected"); + fas216_bus_reset(info); + scsi_report_bus_reset(info->host, 0); + } else if (inst & INST_ILLEGALCMD) { + fas216_log(info, LOG_ERROR, "illegal command given\n"); fas216_dumpstate(info); - } else if (isr & INST_DISCONNECT) + print_debug_list(); + } else if (inst & INST_DISCONNECT) fas216_disconnect_intr(info); - else if (isr & INST_RESELECTED) /* reselected */ + else if (inst & INST_RESELECTED) /* reselected */ fas216_reselected_intr(info); - else if (isr & INST_BUSSERVICE) /* bus service request */ - fas216_busservice_intr(info, stat, ssr); - else if (isr & INST_FUNCDONE) /* function done */ - fas216_funcdone_intr(info, stat, ssr); + else if (inst & INST_BUSSERVICE) /* bus service request */ + fas216_busservice_intr(info, stat, is); + else if (inst & INST_FUNCDONE) /* function done */ + fas216_funcdone_intr(info, stat, is); else - printk("scsi%d.%c: unknown interrupt received:" - " phase %s isr %02X ssr %02X stat %02X\n", - instance->host_no, fas216_target(info), - fas216_drv_phase(info), isr, ssr, stat); + fas216_log(info, 0, "unknown interrupt received:" + " phase %s inst %02X is %02X stat %02X", + fas216_drv_phase(info), inst, is, stat); } } -/* Function: void fas216_kick(FAS216_Info *info) - * Purpose : kick a command to the interface - interface should be idle - * Params : info - our host interface to kick - * Notes : Interrupts are always disabled! - */ -static void fas216_kick(FAS216_Info *info) +static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) { - Scsi_Cmnd *SCpnt = NULL; - int tot_msglen, from_queue = 0, disconnect_ok; + int tot_msglen; - fas216_checkmagic(info); + /* following what the ESP driver says */ + fas216_set_stc(info, 0); + fas216_cmd(info, CMD_NOP | CMD_WITHDMA); - /* - * Obtain the next command to process. - */ - do { - if (info->reqSCpnt) { - SCpnt = info->reqSCpnt; - info->reqSCpnt = NULL; - break; - } + /* flush FIFO */ + fas216_cmd(info, CMD_FLUSHFIFO); - if (info->origSCpnt) { - SCpnt = info->origSCpnt; - info->origSCpnt = NULL; - break; + /* load bus-id and timeout */ + fas216_writeb(info, REG_SDID, BUSID(SCpnt->target)); + fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); + + /* synchronous transfers */ + fas216_set_sync(info, SCpnt->target); + + tot_msglen = msgqueue_msglength(&info->scsi.msgs); + +#ifdef DEBUG_MESSAGES + { + struct message *msg; + int msgnr = 0, i; + + printk("scsi%d.%c: message out: ", + info->host->host_no, '0' + SCpnt->target); + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + printk("{ "); + for (i = 0; i < msg->length; i++) + printk("%02x ", msg->msg[i]); + printk("} "); } + printk("\n"); + } +#endif - /* retrieve next command */ - if (!SCpnt) { - SCpnt = queue_remove_exclude(&info->queues.issue, - info->busyluns); - from_queue = 1; - break; + if (tot_msglen == 1 || tot_msglen == 3) { + /* + * We have an easy message length to send... + */ + struct message *msg; + int msgnr = 0, i; + + info->scsi.phase = PHASE_SELSTEPS; + + /* load message bytes */ + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + for (i = 0; i < msg->length; i++) + fas216_writeb(info, REG_FF, msg->msg[i]); + msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF); } - } while (0); - if (!SCpnt) /* no command pending - just exit */ - return; + /* load command */ + for (i = 0; i < SCpnt->cmd_len; i++) + fas216_writeb(info, REG_FF, SCpnt->cmnd[i]); - if (info->scsi.disconnectable && info->SCpnt) { - queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); - info->scsi.disconnectable = 0; - info->SCpnt = NULL; - printk("scsi%d.%c: moved command to disconnected queue\n", - info->host->host_no, fas216_target(info)); + if (tot_msglen == 1) + fas216_cmd(info, CMD_SELECTATN); + else + fas216_cmd(info, CMD_SELECTATN3); + } else { + /* + * We have an unusual number of message bytes to send. + * Load first byte into fifo, and issue SELECT with ATN and + * stop steps. + */ + struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0); + + fas216_writeb(info, REG_FF, msg->msg[0]); + msg->fifo = 1; + + fas216_cmd(info, CMD_SELECTATNSTOP); } +} + +/* + * Decide whether we need to perform a parity test on this device. + * Can also be used to force parity error conditions during initial + * information transfer phase (message out) for test purposes. + */ +static int parity_test(FAS216_Info *info, int target) +{ +#if 0 + if (target == 3) { + info->device[target].parity_check = 0; + return 1; + } +#endif + return info->device[target].parity_check; +} + +static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) +{ + int disconnect_ok; /* * claim host busy */ info->scsi.phase = PHASE_SELECTION; - info->SCpnt = SCpnt; info->scsi.SCp = SCpnt->SCp; + info->SCpnt = SCpnt; info->dma.transfer_type = fasdma_none; -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: starting cmd %02X", - info->host->host_no, '0' + SCpnt->target, - SCpnt->cmnd[0]); -#endif - - if (from_queue) { -#ifdef SCSI2_TAG - /* - * tagged queuing - allocate a new tag to this command - */ - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && - SCpnt->cmnd[0] != INQUIRY) { - SCpnt->device->current_tag += 1; - if (SCpnt->device->current_tag == 0) - SCpnt->device->current_tag = 1; - SCpnt->tag = SCpnt->device->current_tag; - } else -#endif - set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); - - info->stats.removes += 1; - switch (SCpnt->cmnd[0]) { - case WRITE_6: - case WRITE_10: - case WRITE_12: - info->stats.writes += 1; - break; - case READ_6: - case READ_10: - case READ_12: - info->stats.reads += 1; - break; - default: - info->stats.miscs += 1; - break; - } - } + if (parity_test(info, SCpnt->target)) + fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_PTE); + else + fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); /* * Don't allow request sense commands to disconnect. @@ -1714,15 +1752,6 @@ msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag); do { -#ifdef SCSI2_WIDE - if (info->device[SCpnt->target].wide_state == neg_wait) { - info->device[SCpnt->target].wide_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - info->ifcfg.wide_max_size); - break; - } -#endif #ifdef SCSI2_SYNC if ((info->device[SCpnt->target].sync_state == neg_wait || info->device[SCpnt->target].sync_state == neg_complete) && @@ -1738,100 +1767,202 @@ #endif } while (0); + __fas216_start_command(info, SCpnt); +} + +static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt) +{ +#ifdef SCSI2_TAG + /* + * tagged queuing - allocate a new tag to this command + */ + if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && + SCpnt->cmnd[0] != INQUIRY) { + SCpnt->device->current_tag += 1; + if (SCpnt->device->current_tag == 0) + SCpnt->device->current_tag = 1; + SCpnt->tag = SCpnt->device->current_tag; + } else +#endif + set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + + info->stats.removes += 1; + switch (SCpnt->cmnd[0]) { + case WRITE_6: + case WRITE_10: + case WRITE_12: + info->stats.writes += 1; + break; + case READ_6: + case READ_10: + case READ_12: + info->stats.reads += 1; + break; + default: + info->stats.miscs += 1; + break; + } +} + +static void fas216_do_bus_device_reset(FAS216_Info *info, Scsi_Cmnd *SCpnt) +{ + struct message *msg; + + /* + * claim host busy + */ + info->scsi.phase = PHASE_SELECTION; + info->scsi.SCp = SCpnt->SCp; + info->SCpnt = SCpnt; + info->dma.transfer_type = fasdma_none; + + fas216_log(info, LOG_ERROR, "sending bus device reset"); + + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, BUS_DEVICE_RESET); + /* following what the ESP driver says */ - outb(0, REG_STCL(info)); - outb(0, REG_STCM(info)); - outb(0, REG_STCH(info)); - outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info)); + fas216_set_stc(info, 0); + fas216_cmd(info, CMD_NOP | CMD_WITHDMA); /* flush FIFO */ - outb(CMD_FLUSHFIFO, REG_CMD(info)); + fas216_cmd(info, CMD_FLUSHFIFO); /* load bus-id and timeout */ - outb(BUSID(SCpnt->target), REG_SDID(info)); - outb(info->ifcfg.select_timeout, REG_STIM(info)); + fas216_writeb(info, REG_SDID, BUSID(SCpnt->target)); + fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); /* synchronous transfers */ fas216_set_sync(info, SCpnt->target); - tot_msglen = msgqueue_msglength(&info->scsi.msgs); + msg = msgqueue_getmsg(&info->scsi.msgs, 0); -#ifdef DEBUG_MESSAGES - { - struct message *msg; - int msgnr = 0, i; + fas216_writeb(info, REG_FF, BUS_DEVICE_RESET); + msg->fifo = 1; - printk("scsi%d.%c: message out: ", - info->host->host_no, '0' + SCpnt->target); - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - printk("{ "); - for (i = 0; i < msg->length; i++) - printk("%02x ", msg->msg[i]); - printk("} "); + fas216_cmd(info, CMD_SELECTATNSTOP); +} + +/** + * fas216_kick - kick a command to the interface + * @info: our host interface to kick + * + * Kick a command to the interface, interface should be idle. + * Notes: Interrupts are always disabled! + */ +static void fas216_kick(FAS216_Info *info) +{ + Scsi_Cmnd *SCpnt = NULL; +#define TYPE_OTHER 0 +#define TYPE_RESET 1 +#define TYPE_QUEUE 2 + int where_from = TYPE_OTHER; + + fas216_checkmagic(info); + + /* + * Obtain the next command to process. + */ + do { + if (info->rstSCpnt) { + SCpnt = info->rstSCpnt; + /* don't remove it */ + where_from = TYPE_RESET; + break; } - printk("\n"); - } -#endif - if (tot_msglen == 1 || tot_msglen == 3) { - /* - * We have an easy message length to send... - */ - struct message *msg; - int msgnr = 0, i; + if (info->reqSCpnt) { + SCpnt = info->reqSCpnt; + info->reqSCpnt = NULL; + break; + } - info->scsi.phase = PHASE_SELSTEPS; + if (info->origSCpnt) { + SCpnt = info->origSCpnt; + info->origSCpnt = NULL; + break; + } - /* load message bytes */ - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - for (i = 0; i < msg->length; i++) - outb(msg->msg[i], REG_FF(info)); - msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); + /* retrieve next command */ + if (!SCpnt) { + SCpnt = queue_remove_exclude(&info->queues.issue, + info->busyluns); + where_from = TYPE_QUEUE; + break; } + } while (0); - /* load command */ - for (i = 0; i < SCpnt->cmd_len; i++) - outb(SCpnt->cmnd[i], REG_FF(info)); - - if (tot_msglen == 1) - outb(CMD_SELECTATN, REG_CMD(info)); - else - outb(CMD_SELECTATN3, REG_CMD(info)); - } else { + if (!SCpnt) { /* - * We have an unusual number of message bytes to send. - * Load first byte into fifo, and issue SELECT with ATN and - * stop steps. + * no command pending, so enable reselection. */ - struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0); + fas216_cmd(info, CMD_ENABLESEL); + return; + } - outb(msg->msg[0], REG_FF(info)); - msg->fifo = 1; + /* + * We're going to start a command, so disable reselection + */ + fas216_cmd(info, CMD_DISABLESEL); + + if (info->scsi.disconnectable && info->SCpnt) { + fas216_log(info, LOG_CONNECT, + "moved command for %d to disconnected queue", + info->SCpnt->target); + queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); + info->scsi.disconnectable = 0; + info->SCpnt = NULL; + } - outb(CMD_SELECTATNSTOP, REG_CMD(info)); + fas216_log_command(info, LOG_CONNECT | LOG_MESSAGES, SCpnt, "starting "); + + switch (where_from) { + case TYPE_QUEUE: + fas216_allocate_tag(info, SCpnt); + case TYPE_OTHER: + fas216_start_command(info, SCpnt); + break; + case TYPE_RESET: + fas216_do_bus_device_reset(info, SCpnt); + break; } -#ifdef DEBUG_CONNECT - printk(", data pointers [%p, %X]\n", + fas216_log(info, LOG_CONNECT, "select: data pointers [%p, %X]", info->scsi.SCp.ptr, info->scsi.SCp.this_residual); -#endif - /* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */ + + /* + * should now get either DISCONNECT or + * (FUNCTION DONE with BUS SERVICE) interrupt + */ +} + +/* + * Clean up from issuing a BUS DEVICE RESET message to a device. + */ +static void +fas216_devicereset_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) +{ + fas216_log(info, LOG_ERROR, "fas216 device reset complete"); + + info->rstSCpnt = NULL; + info->rst_dev_status = 1; + wake_up(&info->eh_wait); } -/* Function: void fas216_rq_sns_done(info, SCpnt, result) - * Purpose : Finish processing automatic request sense command - * Params : info - interface that completed - * SCpnt - command that completed - * result - driver byte of result +/** + * fas216_rq_sns_done - Finish processing automatic request sense command + * @info: interface that completed + * @SCpnt: command that completed + * @result: driver byte of result + * + * Finish processing automatic request sense command */ static void fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) { -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: request sense complete, result=%04X%02X%02X\n", - info->host->host_no, '0' + SCpnt->target, result, - SCpnt->SCp.Message, SCpnt->SCp.Status); -#endif + fas216_log_target(info, LOG_CONNECT, SCpnt->target, + "request sense complete, result=0x%04x%02x%02x", + result, SCpnt->SCp.Message, SCpnt->SCp.Status); if (result != DID_OK || SCpnt->SCp.Status != GOOD) /* @@ -1840,7 +1971,8 @@ * confuse the higher levels. */ memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - +//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->target); +//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); } /* * Note that we don't set SCpnt->result, since that should * reflect the status of the command that we were asked by @@ -1850,11 +1982,13 @@ SCpnt->scsi_done(SCpnt); } -/* Function: void fas216_std_done(info, SCpnt, result) - * Purpose : Finish processing of standard command - * Params : info - interface that completed - * SCpnt - command that completed - * result - driver byte of result +/** + * fas216_std_done - finish processing of standard command + * @info: interface that completed + * @SCpnt: command that completed + * @result: driver byte of result + * + * Finish processing of standard command */ static void fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) @@ -1864,31 +1998,29 @@ SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | info->scsi.SCp.Status; -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: command complete, result=%08X, command=", - info->host->host_no, '0' + SCpnt->target, SCpnt->result); - print_command(SCpnt->cmnd); -#endif + fas216_log_command(info, LOG_CONNECT, SCpnt, + "command complete, result=0x%08x ", SCpnt->result); /* - * If the driver detected an error, or the command - * was request sense, then we're all done. + * If the driver detected an error, we're all done. */ - if (result != DID_OK || SCpnt->cmnd[0] == REQUEST_SENSE) + if (host_byte(SCpnt->result) != DID_OK || + msg_byte(SCpnt->result) != COMMAND_COMPLETE) goto done; /* - * If the command returned CHECK_CONDITION status, - * request the sense information. + * If the command returned CHECK_CONDITION or COMMAND_TERMINATED + * status, request the sense information. */ - if (info->scsi.SCp.Status == CHECK_CONDITION) + if (status_byte(SCpnt->result) == CHECK_CONDITION || + status_byte(SCpnt->result) == COMMAND_TERMINATED) goto request_sense; /* * If the command did not complete with GOOD status, * we are all done here. */ - if (info->scsi.SCp.Status != GOOD) + if (status_byte(SCpnt->result) != GOOD) goto done; /* @@ -1902,24 +2034,38 @@ switch (SCpnt->cmnd[0]) { case INQUIRY: case START_STOP: -// case READ_CAPACITY: case MODE_SENSE: break; default: printk(KERN_ERR "scsi%d.%c: incomplete data transfer " - "detected: res=%08X ptr=%p len=%X command=", + "detected: res=%08X ptr=%p len=%X CDB: ", info->host->host_no, '0' + SCpnt->target, SCpnt->result, info->scsi.SCp.ptr, info->scsi.SCp.this_residual); print_command(SCpnt->cmnd); + SCpnt->result &= ~(255 << 16); + SCpnt->result |= DID_BAD_TARGET << 16; + goto request_sense; } } -done: SCpnt->scsi_done(SCpnt); - return; +done: + if (SCpnt->scsi_done) { + SCpnt->scsi_done(SCpnt); + return; + } + + panic("scsi%d.H: null scsi_done function in fas216_done", + info->host->host_no); + request_sense: + if (SCpnt->cmnd[0] == REQUEST_SENSE) + goto done; + + fas216_log_target(info, LOG_CONNECT, SCpnt->target, + "requesting sense"); memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd)); SCpnt->cmnd[0] = REQUEST_SENSE; SCpnt->cmnd[1] = SCpnt->lun << 5; @@ -1931,6 +2077,7 @@ SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer); SCpnt->SCp.Message = 0; SCpnt->SCp.Status = 0; + SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer); SCpnt->sc_data_direction = SCSI_DATA_READ; SCpnt->use_sg = 0; SCpnt->tag = 0; @@ -1947,15 +2094,18 @@ info->reqSCpnt = SCpnt; } -/* Function: void fas216_done(FAS216_Info *info, unsigned int result) - * Purpose : complete processing for current command - * Params : info - interface that completed - * result - driver byte of result +/** + * fas216_done - complete processing for current command + * @info: interface that completed + * @result: driver byte of result + * + * Complete processing for current command */ static void fas216_done(FAS216_Info *info, unsigned int result) { void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int); Scsi_Cmnd *SCpnt; + unsigned long flags; fas216_checkmagic(info); @@ -1966,12 +2116,8 @@ info->SCpnt = NULL; info->scsi.phase = PHASE_IDLE; - if (!SCpnt->scsi_done) - goto no_done; - if (info->scsi.aborting) { - printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n", - info->host->host_no, fas216_target(info)); + fas216_log(info, 0, "uncaught abort - returning DID_ABORT"); result = DID_ABORT; info->scsi.aborting = 0; } @@ -1982,7 +2128,7 @@ */ if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) { printk("scsi%d.%c: zero bytes left to transfer, but " - "buffer pointer still valid: ptr=%p len=%08x command=", + "buffer pointer still valid: ptr=%p len=%08x CDB: ", info->host->host_no, '0' + SCpnt->target, info->scsi.SCp.ptr, info->scsi.SCp.this_residual); info->scsi.SCp.ptr = NULL; @@ -1994,29 +2140,33 @@ * the sense information, fas216_kick will re-assert the busy * status. */ + info->device[SCpnt->target].parity_check = 0; clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble; fn(info, SCpnt, result); - if (info->scsi.irq != NO_IRQ) - fas216_kick(info); + if (info->scsi.irq != NO_IRQ) { + spin_lock_irqsave(&info->host_lock, flags); + if (info->scsi.phase == PHASE_IDLE) + fas216_kick(info); + spin_unlock_irqrestore(&info->host_lock, flags); + } return; no_command: panic("scsi%d.H: null command in fas216_done", info->host->host_no); -no_done: - panic("scsi%d.H: null scsi_done function in fas216_done", - info->host->host_no); } -/* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) - * Purpose : queue a command for adapter to process. - * Params : SCpnt - Command to queue - * done - done function to call once command is complete - * Returns : 0 - success, else error - * Notes : io_request_lock is held, interrupts are disabled. +/** + * fas216_queue_command - queue a command for adapter to process. + * @SCpnt: Command to queue + * @done: done function to call once command is complete + * + * Queue a command for adapter to process. + * Returns: 0 on success, else error. + * Notes: io_request_lock is held, interrupts are disabled. */ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { @@ -2025,61 +2175,20 @@ fas216_checkmagic(info); -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: received queuable command (%p) %02X\n", - SCpnt->host->host_no, '0' + SCpnt->target, - SCpnt, SCpnt->cmnd[0]); -#endif + fas216_log_command(info, LOG_CONNECT, SCpnt, + "received command (%p) ", SCpnt); SCpnt->scsi_done = done; SCpnt->host_scribble = (void *)fas216_std_done; SCpnt->result = 0; - SCpnt->SCp.Message = 0; - SCpnt->SCp.Status = 0; - - if (SCpnt->use_sg) { - unsigned long len = 0; - int buf; - - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer; - SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; - SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address; - SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - /* - * Calculate correct buffer length. Some commands - * come in with the wrong request_bufflen. - */ - for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) - len += SCpnt->SCp.buffer[buf].length; - - if (SCpnt->request_bufflen != len) - printk(KERN_WARNING "scsi%d.%c: bad request buffer " - "length %d, should be %ld\n", info->host->host_no, - '0' + SCpnt->target, SCpnt->request_bufflen, len); - SCpnt->request_bufflen = len; - } else { - SCpnt->SCp.buffer = NULL; - SCpnt->SCp.buffers_residual = 0; - SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; - } - /* - * If the upper SCSI layers pass a buffer, but zero length, - * we aren't interested in the buffer pointer. - */ - if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { -#if 0 - printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " - "command ", info->host->host_no, '0' + SCpnt->target); - print_command(SCpnt->cmnd); -#endif - SCpnt->SCp.ptr = NULL; - } + init_SCp(SCpnt); info->stats.queues += 1; SCpnt->tag = 0; + spin_lock(&info->host_lock); + /* * Add command into execute queue and let it complete under * whatever scheme we're using. @@ -2090,15 +2199,21 @@ * If we successfully added the command, * kick the interface to get it moving. */ - if (result == 0 && (!info->SCpnt || info->scsi.disconnectable)) + if (result == 0 && info->scsi.phase == PHASE_IDLE) fas216_kick(info); + spin_unlock(&info->host_lock); + + fas216_log_target(info, LOG_CONNECT, -1, "queue %s", + result ? "failure" : "success"); return result; } -/* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt) - * Purpose : trigger restart of a waiting thread in fas216_command - * Params : SCpnt - Command to wake +/** + * fas216_internal_done - trigger restart of a waiting thread in fas216_command + * @SCpnt: Command to wake + * + * Trigger restart of a waiting thread in fas216_command */ static void fas216_internal_done(Scsi_Cmnd *SCpnt) { @@ -2109,11 +2224,13 @@ info->internal_done = 1; } -/* Function: int fas216_command(Scsi_Cmnd *SCpnt) - * Purpose : queue a command for adapter to process. - * Params : SCpnt - Command to queue - * Returns : scsi result code - * Notes : io_request_lock is held, interrupts are disabled. +/** + * fas216_command - queue a command for adapter to process. + * @SCpnt: Command to queue + * + * Queue a command for adapter to process. + * Returns: scsi result code. + * Notes: io_request_lock is held, interrupts are disabled. */ int fas216_command(Scsi_Cmnd *SCpnt) { @@ -2125,8 +2242,7 @@ * We should only be using this if we don't have an interrupt. * Provide some "incentive" to use the queueing code. */ - if (info->scsi.irq != NO_IRQ) - BUG(); + BUG_ON(info->scsi.irq != NO_IRQ); info->internal_done = 0; fas216_queue_command(SCpnt, fas216_internal_done); @@ -2148,9 +2264,9 @@ * and go to sleep if we know that the device is going * to be some time (eg, disconnected). */ - if (inb(REG_STAT(info)) & STAT_INT) { + if (fas216_readb(info, REG_STAT) & STAT_INT) { spin_lock_irq(&io_request_lock); - fas216_intr(info->host); + fas216_intr(info); spin_unlock_irq(&io_request_lock); } } @@ -2160,23 +2276,42 @@ return SCpnt->result; } -enum res_abort { - res_failed, /* unable to abort */ +/* + * Error handler timeout function. Indicate that we timed out, + * and wake up any error handler process so it can continue. + */ +static void fas216_eh_timer(unsigned long data) +{ + FAS216_Info *info = (FAS216_Info *)data; + + fas216_log(info, LOG_ERROR, "error handling timed out\n"); + + del_timer(&info->eh_timer); + + if (info->rst_bus_status == 0) + info->rst_bus_status = -1; + if (info->rst_dev_status == 0) + info->rst_dev_status = -1; + + wake_up(&info->eh_wait); +} + +enum res_find { + res_failed, /* not found */ res_success, /* command on issue queue */ - res_success_clear, /* command marked tgt/lun busy */ res_hw_abort /* command on disconnected dev */ }; -/* - * Prototype: enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) - * Purpose : decide how to abort a command - * Params : SCpnt - command to abort - * Returns : abort status +/** + * fas216_do_abort - decide how to abort a command + * @SCpnt: command to abort + * + * Decide how to abort a command. + * Returns: abort status */ -static enum res_abort -fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) +static enum res_find fas216_find_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) { - enum res_abort res = res_failed; + enum res_find res = res_failed; if (queue_remove_cmd(&info->queues.issue, SCpnt)) { /* @@ -2224,19 +2359,22 @@ * been set. */ info->origSCpnt = NULL; + clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); printk("waiting for execution "); - res = res_success_clear; + res = res_success; } else printk("unknown "); return res; } -/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort this command - * Params : SCpnt - command to abort - * Returns : FAILED if unable to abort - * Notes : io_request_lock is taken, and irqs are disabled +/** + * fas216_eh_abort - abort this command + * @SCpnt: command to abort + * + * Abort this command. + * Returns: FAILED if unable to abort + * Notes: io_request_lock is taken, and irqs are disabled */ int fas216_eh_abort(Scsi_Cmnd *SCpnt) { @@ -2247,22 +2385,15 @@ info->stats.aborts += 1; + printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no); + print_command(SCpnt->data_cmnd); + print_debug_list(); fas216_dumpstate(info); - fas216_dumpinfo(info); - printk(KERN_WARNING "scsi%d: abort ", info->host->host_no); - - switch (fas216_do_abort(info, SCpnt)) { - /* - * We managed to find the command and cleared it out. - * We do not expect the command to be executing on the - * target, but we have set the busylun bit. - */ - case res_success_clear: - printk("clear "); - clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + printk(KERN_WARNING "scsi%d: abort %p ", info->host->host_no, SCpnt); + switch (fas216_find_command(info, SCpnt)) { /* * We found the command, and cleared it out. Either * the command is still known to be executing on the @@ -2293,155 +2424,195 @@ return result; } -/* Function: void fas216_reset_state(FAS216_Info *info) - * Purpose : Initialise driver internal state - * Params : info - state to initialise +/** + * fas216_eh_device_reset - Reset the device associated with this command + * @SCpnt: command specifing device to reset + * + * Reset the device associated with this command. + * Returns: FAILED if unable to reset. + * Notes: We won't be re-entered, so we'll only have one device + * reset on the go at one time. */ -static void fas216_reset_state(FAS216_Info *info) +int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) { - neg_t sync_state, wide_state; - int i; + FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + unsigned long flags; + int i, res = FAILED, target = SCpnt->target; - fas216_checkmagic(info); + fas216_log(info, LOG_ERROR, "device reset for target %d", target); - /* - * Clear out all stale info in our state structure - */ - memset(info->busyluns, 0, sizeof(info->busyluns)); - msgqueue_flush(&info->scsi.msgs); - info->scsi.reconnected.target = 0; - info->scsi.reconnected.lun = 0; - info->scsi.reconnected.tag = 0; - info->scsi.disconnectable = 0; - info->scsi.aborting = 0; - info->scsi.phase = PHASE_IDLE; - info->scsi.async_stp = - fas216_syncperiod(info, info->ifcfg.asyncperiod); + spin_lock_irqsave(&info->host_lock, flags); - if (info->ifcfg.wide_max_size == 0) - wide_state = neg_invalid; - else -#ifdef SCSI2_WIDE - wide_state = neg_wait; -#else - wide_state = neg_invalid; -#endif + do { + /* + * If we are currently connected to a device, and + * it is the device we want to reset, there is + * nothing we can do here. Chances are it is stuck, + * and we need a bus reset. + */ + if (info->SCpnt && !info->scsi.disconnectable && + info->SCpnt->target == SCpnt->target) + break; - if (info->host->dma_channel == NO_DMA || !info->dma.setup) - sync_state = neg_invalid; - else -#ifdef SCSI2_SYNC - sync_state = neg_wait; -#else - sync_state = neg_invalid; -#endif + /* + * We're going to be resetting this device. Remove + * all pending commands from the driver. By doing + * so, we guarantee that we won't touch the command + * structures except to process the reset request. + */ + queue_remove_all_target(&info->queues.issue, target); + queue_remove_all_target(&info->queues.disconnected, target); + if (info->origSCpnt && info->origSCpnt->target == target) + info->origSCpnt = NULL; + if (info->reqSCpnt && info->reqSCpnt->target == target) + info->reqSCpnt = NULL; + for (i = 0; i < 8; i++) + clear_bit(target * 8 + i, info->busyluns); - for (i = 0; i < 8; i++) { - info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; - info->device[i].sync_state = sync_state; - info->device[i].wide_state = wide_state; - info->device[i].period = info->ifcfg.asyncperiod / 4; - info->device[i].stp = info->scsi.async_stp; - info->device[i].sof = 0; - info->device[i].wide_xfer = 0; - } + /* + * Hijack this SCSI command structure to send + * a bus device reset message to this device. + */ + SCpnt->host_scribble = (void *)fas216_devicereset_done; - /* - * Drain all commands on disconnected queue - */ - while (queue_remove(&info->queues.disconnected) != NULL); + info->rst_dev_status = 0; + info->rstSCpnt = SCpnt; - /* - * Remove executing commands. - */ - info->SCpnt = NULL; - info->reqSCpnt = NULL; - info->origSCpnt = NULL; -} + if (info->scsi.phase == PHASE_IDLE) + fas216_kick(info); -/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the device associated with this command - * Params : SCpnt - command specifing device to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + mod_timer(&info->eh_timer, 30 * HZ); + spin_unlock_irqrestore(&info->host_lock, flags); + + /* + * Wait up to 30 seconds for the reset to complete. + */ + wait_event(info->eh_wait, info->rst_dev_status); + + del_timer_sync(&info->eh_timer); + spin_lock_irqsave(&info->host_lock, flags); + info->rstSCpnt = NULL; + + if (info->rst_dev_status == 1) + res = SUCCESS; + } while (0); + + SCpnt->host_scribble = NULL; + spin_unlock_irqrestore(&info->host_lock, flags); + + fas216_log(info, LOG_ERROR, "device reset complete: %s\n", + res == SUCCESS ? "success" : "failed"); - printk("scsi%d.%c: "__FUNCTION__": called\n", - info->host->host_no, '0' + SCpnt->target); - return FAILED; + return res; } -/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the bus associated with the command - * Params : SCpnt - command specifing bus to reset - * Returns : FAILED if unable to reset - * Notes : io_request_lock is taken, and irqs are disabled +/** + * fas216_eh_bus_reset - Reset the bus associated with the command + * @SCpnt: command specifing bus to reset + * + * Reset the bus associated with the command. + * Returns: FAILED if unable to reset. + * Notes: Further commands are blocked. */ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - int result = FAILED; + unsigned long flags; + Scsi_Device *SDpnt; fas216_checkmagic(info); + fas216_log(info, LOG_ERROR, "resetting bus"); info->stats.bus_resets += 1; - printk("scsi%d.%c: "__FUNCTION__": resetting bus\n", - info->host->host_no, '0' + SCpnt->target); + spin_lock_irqsave(&info->host_lock, flags); /* - * Attempt to stop all activity on this interface. + * Stop all activity on this interface. */ - outb(info->scsi.cfg[2], REG_CNTL3(info)); - fas216_stoptransfer(info); + fas216_aborttransfer(info); + fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]); /* - * Clear any pending interrupts + * Clear any pending interrupts. */ - while (inb(REG_STAT(info)) & STAT_INT) - inb(REG_INST(info)); + while (fas216_readb(info, REG_STAT) & STAT_INT) + fas216_readb(info, REG_INST); + + info->rst_bus_status = 0; /* - * Reset the SCSI bus + * For each attached hard-reset device, clear out + * all command structures. Leave the running + * command in place. */ - outb(CMD_RESETSCSI, REG_CMD(info)); - udelay(5); + for (SDpnt = info->host->host_queue; SDpnt; SDpnt = SDpnt->next) { + int i; + + if (SDpnt->soft_reset) + continue; + + queue_remove_all_target(&info->queues.issue, SDpnt->id); + queue_remove_all_target(&info->queues.disconnected, SDpnt->id); + if (info->origSCpnt && info->origSCpnt->target == SDpnt->id) + info->origSCpnt = NULL; + if (info->reqSCpnt && info->reqSCpnt->target == SDpnt->id) + info->reqSCpnt = NULL; + info->SCpnt = NULL; + + for (i = 0; i < 8; i++) + clear_bit(SDpnt->id * 8 + i, info->busyluns); + } + + info->scsi.phase = PHASE_IDLE; /* - * Clear reset interrupt + * Reset the SCSI bus. Device cleanup happens in + * the interrupt handler. */ - if (inb(REG_STAT(info)) & STAT_INT && - inb(REG_INST(info)) & INST_BUSRESET) - result = SUCCESS; + fas216_cmd(info, CMD_RESETSCSI); - fas216_reset_state(info); + mod_timer(&info->eh_timer, jiffies + HZ); + spin_unlock_irqrestore(&info->host_lock, flags); - return result; + /* + * Wait one second for the interrupt. + */ + wait_event(info->eh_wait, info->rst_bus_status); + del_timer_sync(&info->eh_timer); + + fas216_log(info, LOG_ERROR, "bus reset complete: %s\n", + info->rst_bus_status == 1 ? "success" : "failed"); + + return info->rst_bus_status == 1 ? SUCCESS : FAILED; } -/* Function: void fas216_init_chip(FAS216_Info *info) - * Purpose : Initialise FAS216 state after reset - * Params : info - state structure for interface +/** + * fas216_init_chip - Initialise FAS216 state after reset + * @info: state structure for interface + * + * Initialise FAS216 state after reset */ static void fas216_init_chip(FAS216_Info *info) { - outb(fas216_clockrate(info->ifcfg.clockrate), REG_CLKF(info)); - outb(info->scsi.cfg[0], REG_CNTL1(info)); - outb(info->scsi.cfg[1], REG_CNTL2(info)); - outb(info->scsi.cfg[2], REG_CNTL3(info)); - outb(info->ifcfg.select_timeout, REG_STIM(info)); - outb(0, REG_SOF(info)); - outb(info->scsi.async_stp, REG_STP(info)); - outb(info->scsi.cfg[0], REG_CNTL1(info)); + unsigned int clock = ((info->ifcfg.clockrate - 1) / 5 + 1) & 7; + fas216_writeb(info, REG_CLKF, clock); + fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); + fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]); + fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]); + fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); + fas216_writeb(info, REG_SOF, 0); + fas216_writeb(info, REG_STP, info->scsi.async_stp); + fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); } -/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the host associated with this command - * Params : SCpnt - command specifing host to reset - * Returns : FAILED if unable to reset - * Notes : io_request_lock is taken, and irqs are disabled +/** + * fas216_eh_host_reset - Reset the host associated with this command + * @SCpnt: command specifing host to reset + * + * Reset the host associated with this command. + * Returns: FAILED if unable to reset. + * Notes: io_request_lock is taken, and irqs are disabled */ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) { @@ -2449,13 +2620,13 @@ fas216_checkmagic(info); - printk("scsi%d.%c: "__FUNCTION__": resetting host\n", - info->host->host_no, '0' + SCpnt->target); + printk("scsi%d.%c: %s: resetting host\n", + info->host->host_no, '0' + SCpnt->target, __FUNCTION__); /* * Reset the SCSI chip. */ - outb(CMD_RESETCHIP, REG_CMD(info)); + fas216_cmd(info, CMD_RESETCHIP); /* * Ugly ugly ugly! @@ -2464,13 +2635,13 @@ * IRQs after the sleep. */ spin_unlock_irq(&io_request_lock); - scsi_sleep(25*HZ/100); + scsi_sleep(50 * HZ/100); spin_lock_irq(&io_request_lock); /* * Release the SCSI reset. */ - outb(CMD_NOP, REG_CMD(info)); + fas216_cmd(info, CMD_NOP); fas216_init_chip(info); @@ -2502,56 +2673,56 @@ /* * Reset the chip. */ - outb(CMD_RESETCHIP, REG_CMD(info)); + fas216_writeb(info, REG_CMD, CMD_RESETCHIP); udelay(50); - outb(CMD_NOP, REG_CMD(info)); + fas216_writeb(info, REG_CMD, CMD_NOP); /* * Check to see if control reg 2 is present. */ - outb(0, REG_CNTL3(info)); - outb(CNTL2_S2FE, REG_CNTL2(info)); + fas216_writeb(info, REG_CNTL3, 0); + fas216_writeb(info, REG_CNTL2, CNTL2_S2FE); /* * If we are unable to read back control reg 2 * correctly, it is not present, and we have a * NCR53C90. */ - if ((inb(REG_CNTL2(info)) & (~0xe0)) != CNTL2_S2FE) + if ((fas216_readb(info, REG_CNTL2) & (~0xe0)) != CNTL2_S2FE) return TYPE_NCR53C90; /* * Now, check control register 3 */ - outb(0, REG_CNTL2(info)); - outb(0, REG_CNTL3(info)); - outb(5, REG_CNTL3(info)); + fas216_writeb(info, REG_CNTL2, 0); + fas216_writeb(info, REG_CNTL3, 0); + fas216_writeb(info, REG_CNTL3, 5); /* * If we are unable to read the register back * correctly, we have a NCR53C90A */ - if (inb(REG_CNTL3(info)) != 5) + if (fas216_readb(info, REG_CNTL3) != 5) return TYPE_NCR53C90A; /* * Now read the ID from the chip. */ - outb(0, REG_CNTL3(info)); + fas216_writeb(info, REG_CNTL3, 0); - outb(CNTL3_ADIDCHK, REG_CNTL3(info)); - outb(0, REG_CNTL3(info)); + fas216_writeb(info, REG_CNTL3, CNTL3_ADIDCHK); + fas216_writeb(info, REG_CNTL3, 0); - outb(CMD_RESETCHIP, REG_CMD(info)); - udelay(5); - outb(CMD_WITHDMA | CMD_NOP, REG_CMD(info)); + fas216_writeb(info, REG_CMD, CMD_RESETCHIP); + udelay(50); + fas216_writeb(info, REG_CMD, CMD_WITHDMA | CMD_NOP); - outb(CNTL2_ENF, REG_CNTL2(info)); - outb(CMD_RESETCHIP, REG_CMD(info)); - udelay(5); - outb(CMD_NOP, REG_CMD(info)); + fas216_writeb(info, REG_CNTL2, CNTL2_ENF); + fas216_writeb(info, REG_CMD, CMD_RESETCHIP); + udelay(50); + fas216_writeb(info, REG_CMD, CMD_NOP); - rev = inb(REG1_ID(info)); + rev = fas216_readb(info, REG_ID); family = rev >> 3; rev &= 7; @@ -2577,33 +2748,106 @@ return TYPE_NCR53C9x; } -/* Function: int fas216_init(struct Scsi_Host *instance) - * Purpose : initialise FAS/NCR/AMD SCSI ic. - * Params : instance - a driver-specific filled-out structure - * Returns : 0 on success +/** + * fas216_reset_state - Initialise driver internal state + * @info: state to initialise + * + * Initialise driver internal state */ -int fas216_init(struct Scsi_Host *instance) +static void fas216_reset_state(FAS216_Info *info) { - FAS216_Info *info = (FAS216_Info *)instance->hostdata; - int type; + int i; + + fas216_checkmagic(info); + + fas216_bus_reset(info); - info->magic_start = MAGIC; - info->magic_end = MAGIC; - info->host = instance; - info->scsi.cfg[0] = instance->this_id; - info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; - info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB; + /* + * Clear out all stale info in our state structure + */ + memset(info->busyluns, 0, sizeof(info->busyluns)); + info->scsi.disconnectable = 0; + info->scsi.aborting = 0; + + for (i = 0; i < 8; i++) { + info->device[i].parity_enabled = 0; + info->device[i].parity_check = 1; + } + + /* + * Drain all commands on disconnected queue + */ + while (queue_remove(&info->queues.disconnected) != NULL); + + /* + * Remove executing commands. + */ + info->SCpnt = NULL; + info->reqSCpnt = NULL; + info->rstSCpnt = NULL; + info->origSCpnt = NULL; +} + +/** + * fas216_init - initialise FAS/NCR/AMD SCSI structures. + * @host: a driver-specific filled-out structure + * + * Initialise FAS/NCR/AMD SCSI structures. + * Returns: 0 on success + */ +int fas216_init(struct Scsi_Host *host) +{ + FAS216_Info *info = (FAS216_Info *)host->hostdata; + + info->magic_start = MAGIC; + info->magic_end = MAGIC; + info->host = host; + info->scsi.cfg[0] = host->this_id | CNTL1_PERE; + info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; + info->scsi.cfg[2] = info->ifcfg.cntl3 | + CNTL3_ADIDCHK | CNTL3_QTAG | CNTL3_G2CB | CNTL3_LBTM; + info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod); + + info->rst_dev_status = -1; + info->rst_bus_status = -1; + init_waitqueue_head(&info->eh_wait); + init_timer(&info->eh_timer); + info->eh_timer.data = (unsigned long)info; + info->eh_timer.function = fas216_eh_timer; + + spin_lock_init(&info->host_lock); memset(&info->stats, 0, sizeof(info->stats)); msgqueue_initialise(&info->scsi.msgs); if (!queue_initialise(&info->queues.issue)) - return 1; + return -ENOMEM; if (!queue_initialise(&info->queues.disconnected)) { queue_free(&info->queues.issue); - return 1; + return -ENOMEM; + } + + return 0; +} + +/** + * fas216_add - initialise FAS/NCR/AMD SCSI ic. + * @host: a driver-specific filled-out structure + * + * Initialise FAS/NCR/AMD SCSI ic. + * Returns: 0 on success + */ +int fas216_add(struct Scsi_Host *host) +{ + FAS216_Info *info = (FAS216_Info *)host->hostdata; + int type; + + if (info->ifcfg.clockrate <= 10 || info->ifcfg.clockrate > 40) { + printk(KERN_CRIT "fas216: invalid clock rate %u MHz\n", + info->ifcfg.clockrate); + return -EINVAL; } fas216_reset_state(info); @@ -2622,78 +2866,53 @@ * the resulting reset interrupt, so mask it * out. */ - outb(info->scsi.cfg[0] | CNTL1_DISR, REG_CNTL1(info)); - outb(CMD_RESETSCSI, REG_CMD(info)); + fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_DISR); + fas216_writeb(info, REG_CMD, CMD_RESETSCSI); /* * scsi standard says wait 250ms */ spin_unlock_irq(&io_request_lock); - scsi_sleep(25*HZ/100); + scsi_sleep(100*HZ/100); spin_lock_irq(&io_request_lock); - outb(info->scsi.cfg[0], REG_CNTL1(info)); - inb(REG_INST(info)); + fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); + fas216_readb(info, REG_INST); fas216_checkmagic(info); return 0; } -/* Function: int fas216_release(struct Scsi_Host *instance) - * Purpose : release all resources and put everything to bed for - * FAS/NCR/AMD SCSI ic. - * Params : instance - a driver-specific filled-out structure - * Returns : 0 on success - */ -int fas216_release(struct Scsi_Host *instance) +void fas216_remove(struct Scsi_Host *host) { - FAS216_Info *info = (FAS216_Info *)instance->hostdata; + FAS216_Info *info = (FAS216_Info *)host->hostdata; fas216_checkmagic(info); - outb(CMD_RESETCHIP, REG_CMD(info)); - queue_free(&info->queues.disconnected); - queue_free(&info->queues.issue); - - return 0; + fas216_writeb(info, REG_CMD, CMD_RESETCHIP); } -/* - * Function: int fas216_info(FAS216_Info *info, char *buffer) - * Purpose : generate a string containing information about this - * host. - * Params : info - FAS216 host information - * buffer - string buffer to build string - * Returns : size of built string +/** + * fas216_release - release all resources for FAS/NCR/AMD SCSI ic. + * @host: a driver-specific filled-out structure + * + * release all resources and put everything to bed for FAS/NCR/AMD SCSI ic. */ -int fas216_info(FAS216_Info *info, char *buffer) +void fas216_release(struct Scsi_Host *host) { - char *p = buffer; + FAS216_Info *info = (FAS216_Info *)host->hostdata; - p += sprintf(p, "(%s) at port 0x%08lX ", - info->scsi.type, info->host->io_port); - - if (info->host->irq != NO_IRQ) - p += sprintf(p, "irq %d ", info->host->irq); - else - p += sprintf(p, "no irq "); - - if (info->host->dma_channel != NO_DMA) - p += sprintf(p, "dma %d ", info->host->dma_channel); - else - p += sprintf(p, "no dma "); - - return p - buffer; + queue_free(&info->queues.disconnected); + queue_free(&info->queues.issue); } int fas216_print_host(FAS216_Info *info, char *buffer) { - return sprintf(buffer, "\n" "Chip : %s\n" - " Address: 0x%08lX\n" + " Address: 0x%08lx\n" " IRQ : %d\n" " DMA : %d\n", info->scsi.type, info->host->io_port, @@ -2702,8 +2921,9 @@ int fas216_print_stats(FAS216_Info *info, char *buffer) { - return sprintf(buffer, - "\n" + char *p = buffer; + + p += sprintf(p, "\n" "Command Statistics:\n" " Queued : %u\n" " Issued : %u\n" @@ -2720,6 +2940,8 @@ info->stats.writes, info->stats.miscs, info->stats.disconnects, info->stats.aborts, info->stats.bus_resets, info->stats.host_resets); + + return p - buffer; } int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) @@ -2738,7 +2960,9 @@ scd->tagged_queue ? "en" : "dis", scd->current_tag); - p += sprintf(p, "\n Transfers : %d-bit ", + p += sprintf(p, "%s\n", dev->parity_enabled ? "parity" : ""); + + p += sprintf(p, " Transfers : %d-bit ", 8 << dev->wide_xfer); if (dev->sof) @@ -2750,11 +2974,12 @@ return p - buffer; } -EXPORT_SYMBOL(fas216_info); EXPORT_SYMBOL(fas216_init); +EXPORT_SYMBOL(fas216_add); EXPORT_SYMBOL(fas216_queue_command); EXPORT_SYMBOL(fas216_command); EXPORT_SYMBOL(fas216_intr); +EXPORT_SYMBOL(fas216_remove); EXPORT_SYMBOL(fas216_release); EXPORT_SYMBOL(fas216_eh_abort); EXPORT_SYMBOL(fas216_eh_device_reset); diff -urN orig/drivers/acorn/scsi/fas216.h linux/drivers/acorn/scsi/fas216.h --- orig/drivers/acorn/scsi/fas216.h Tue Oct 3 20:08:24 2000 +++ linux/drivers/acorn/scsi/fas216.h Wed Jun 25 11:54:29 2003 @@ -22,18 +22,18 @@ /* FAS register definitions */ /* transfer count low */ -#define REG_CTCL(x) ((x)->scsi.io_port) -#define REG_STCL(x) ((x)->scsi.io_port) +#define REG_CTCL (0) +#define REG_STCL (0) /* transfer count medium */ -#define REG_CTCM(x) ((x)->scsi.io_port + (1 << (x)->scsi.io_shift)) -#define REG_STCM(x) ((x)->scsi.io_port + (1 << (x)->scsi.io_shift)) +#define REG_CTCM (1) +#define REG_STCM (1) /* fifo data */ -#define REG_FF(x) ((x)->scsi.io_port + (2 << (x)->scsi.io_shift)) +#define REG_FF (2) /* command */ -#define REG_CMD(x) ((x)->scsi.io_port + (3 << (x)->scsi.io_shift)) +#define REG_CMD (3) #define CMD_NOP 0x00 #define CMD_FLUSHFIFO 0x01 #define CMD_RESETCHIP 0x02 @@ -57,7 +57,7 @@ #define CMD_WITHDMA 0x80 /* status register (read) */ -#define REG_STAT(x) ((x)->scsi.io_port + (4 << (x)->scsi.io_shift)) +#define REG_STAT (4) #define STAT_IO (1 << 0) /* IO phase */ #define STAT_CD (1 << 1) /* CD phase */ #define STAT_MSG (1 << 2) /* MSG phase */ @@ -76,11 +76,11 @@ #define STAT_MESGIN (STAT_MSG|STAT_CD|STAT_IO) /* Message In */ /* bus ID for select / reselect */ -#define REG_SDID(x) ((x)->scsi.io_port + (4 << (x)->scsi.io_shift)) +#define REG_SDID (4) #define BUSID(target) ((target) & 7) /* Interrupt status register (read) */ -#define REG_INST(x) ((x)->scsi.io_port + (5 << (x)->scsi.io_shift)) +#define REG_INST (5) #define INST_SELWOATN (1 << 0) /* Select w/o ATN */ #define INST_SELATN (1 << 1) /* Select w/ATN */ #define INST_RESELECTED (1 << 2) /* Reselected */ @@ -91,10 +91,10 @@ #define INST_BUSRESET (1 << 7) /* SCSI Bus reset */ /* Timeout register (write) */ -#define REG_STIM(x) ((x)->scsi.io_port + (5 << (x)->scsi.io_shift)) +#define REG_STIM (5) /* Sequence step register (read) */ -#define REG_IS(x) ((x)->scsi.io_port + (6 << (x)->scsi.io_shift)) +#define REG_IS (6) #define IS_BITS 0x07 #define IS_SELARB 0x00 /* Select & Arb ok */ #define IS_MSGBYTESENT 0x01 /* One byte message sent*/ @@ -104,18 +104,18 @@ #define IS_SOF 0x08 /* Sync off flag */ /* Transfer period step (write) */ -#define REG_STP(x) ((x)->scsi.io_port + (6 << (x)->scsi.io_shift)) +#define REG_STP (6) /* Synchronous Offset (write) */ -#define REG_SOF(x) ((x)->scsi.io_port + (7 << (x)->scsi.io_shift)) +#define REG_SOF (7) /* Fifo state register (read) */ -#define REG_CFIS(x) ((x)->scsi.io_port + (7 << (x)->scsi.io_shift)) +#define REG_CFIS (7) #define CFIS_CF 0x1f /* Num bytes in FIFO */ #define CFIS_IS 0xe0 /* Step */ /* config register 1 */ -#define REG_CNTL1(x) ((x)->scsi.io_port + (8 << (x)->scsi.io_shift)) +#define REG_CNTL1 (8) #define CNTL1_CID (7 << 0) /* Chip ID */ #define CNTL1_STE (1 << 3) /* Self test enable */ #define CNTL1_PERE (1 << 4) /* Parity enable reporting en. */ @@ -124,7 +124,7 @@ #define CNTL1_ETM (1 << 7) /* Extended Timing Mode */ /* Clock conversion factor (read) */ -#define REG_CLKF(x) ((x)->scsi.io_port + (9 << (x)->scsi.io_shift)) +#define REG_CLKF (9) #define CLKF_F37MHZ 0x00 /* 35.01 - 40 MHz */ #define CLKF_F10MHZ 0x02 /* 10 MHz */ #define CLKF_F12MHZ 0x03 /* 10.01 - 15 MHz */ @@ -134,13 +134,13 @@ #define CLKF_F32MHZ 0x07 /* 30.01 - 35 MHz */ /* Chip test register (write) */ -#define REG0_FTM(x) ((x)->scsi.io_port + (10 << (x)->scsi.io_shift)) +#define REG_FTM (10) #define TEST_FTM 0x01 /* Force target mode */ #define TEST_FIM 0x02 /* Force initiator mode */ #define TEST_FHI 0x04 /* Force high impedance mode */ /* Configuration register 2 (read/write) */ -#define REG_CNTL2(x) ((x)->scsi.io_port + (11 << (x)->scsi.io_shift)) +#define REG_CNTL2 (11) #define CNTL2_PGDP (1 << 0) /* Pass Th/Generate Data Parity */ #define CNTL2_PGRP (1 << 1) /* Pass Th/Generate Reg Parity */ #define CNTL2_ACDPE (1 << 2) /* Abort on Cmd/Data Parity Err */ @@ -151,7 +151,7 @@ #define CNTL2_DAE (1 << 7) /* Data Alignment Enable */ /* Configuration register 3 (read/write) */ -#define REG_CNTL3(x) ((x)->scsi.io_port + (12 << (x)->scsi.io_shift)) +#define REG_CNTL3 (12) #define CNTL3_BS8 (1 << 0) /* Burst size 8 */ #define CNTL3_MDM (1 << 1) /* Modify DMA mode */ #define CNTL3_LBTM (1 << 2) /* Last Byte Transfer mode */ @@ -162,14 +162,14 @@ #define CNTL3_ADIDCHK (1 << 7) /* Additional ID check */ /* High transfer count (read/write) */ -#define REG_CTCH(x) ((x)->scsi.io_port + (14 << (x)->scsi.io_shift)) -#define REG_STCH(x) ((x)->scsi.io_port + (14 << (x)->scsi.io_shift)) +#define REG_CTCH (14) +#define REG_STCH (14) -/* ID reigster (read only) */ -#define REG1_ID(x) ((x)->scsi.io_port + (14 << (x)->scsi.io_shift)) +/* ID register (read only) */ +#define REG_ID (14) /* Data alignment */ -#define REG0_DAL(x) ((x)->scsi.io_port + (15 << (x)->scsi.io_shift)) +#define REG_DAL (15) typedef enum { PHASE_IDLE, /* we're not planning on doing anything */ @@ -177,7 +177,6 @@ PHASE_SELSTEPS, /* selection with command steps */ PHASE_COMMAND, /* command sent */ PHASE_MESSAGESENT, /* selected, and we're sending cmd */ - PHASE_RECONNECTED, /* reconnected */ PHASE_DATAOUT, /* data out to device */ PHASE_DATAIN, /* data in from device */ PHASE_MSGIN, /* message in from device */ @@ -212,27 +211,36 @@ #define MAGIC 0x441296bdUL #define NR_MSGS 8 +#define FASCAP_DMA (1 << 0) +#define FASCAP_PSEUDODMA (1 << 1) + typedef struct { unsigned long magic_start; + spinlock_t host_lock; struct Scsi_Host *host; /* host */ Scsi_Cmnd *SCpnt; /* currently processing command */ Scsi_Cmnd *origSCpnt; /* original connecting command */ Scsi_Cmnd *reqSCpnt; /* request sense command */ + Scsi_Cmnd *rstSCpnt; /* reset command */ + Scsi_Cmnd *pending_SCpnt[8]; /* per-device pending commands */ + int next_pending; /* next pending device */ + + /* + * Error recovery + */ + wait_queue_head_t eh_wait; + struct timer_list eh_timer; + unsigned int rst_dev_status; + unsigned int rst_bus_status; /* driver information */ struct { + phase_t phase; /* current phase */ unsigned int io_port; /* base address of FAS216 */ unsigned int io_shift; /* shift to adjust reg offsets by */ - unsigned int irq; /* interrupt */ unsigned char cfg[4]; /* configuration registers */ const char *type; /* chip type */ - phase_t phase; /* current phase */ - - struct { - unsigned char target; /* reconnected target */ - unsigned char lun; /* reconnected lun */ - unsigned char tag; /* reconnected tag */ - } reconnected; + unsigned int irq; /* interrupt */ Scsi_Pointer SCp; /* current commands data pointer */ @@ -241,7 +249,6 @@ unsigned int async_stp; /* Async transfer STP value */ unsigned char msgin_fifo; /* bytes in fifo at time of message in */ unsigned char message[256]; /* last message received from device */ - unsigned int msglen; /* length of last message received */ unsigned char disconnectable:1; /* this command can be disconnected */ unsigned char aborting:1; /* aborting command */ @@ -269,6 +276,7 @@ unsigned char wide_max_size; /* Maximum wide transfer size */ unsigned char cntl3; /* Control Reg 3 */ unsigned int asyncperiod; /* Async transfer period (ns) */ + unsigned int capabilities; /* driver capabilities */ unsigned int disconnect_ok:1; /* Disconnects allowed? */ } ifcfg; @@ -281,6 +289,8 @@ /* per-device info */ struct fas216_device { unsigned char disconnect_ok:1; /* device can disconnect */ + unsigned char parity_enabled:1; /* parity checking enabled */ + unsigned char parity_check:1; /* need to check parity checking */ unsigned char period; /* sync xfer period in (*4ns) */ unsigned char stp; /* synchronous transfer period */ unsigned char sof; /* synchronous offset register */ @@ -300,31 +310,22 @@ /* miscellaneous */ int internal_done; /* flag to indicate request done */ - unsigned long magic_end; } FAS216_Info; /* Function: int fas216_init (struct Scsi_Host *instance) - * Purpose : initialise FAS/NCR/AMD SCSI ic. + * Purpose : initialise FAS/NCR/AMD SCSI structures. * Params : instance - a driver-specific filled-out structure * Returns : 0 on success */ extern int fas216_init (struct Scsi_Host *instance); -/* Function: int fas216_abort (Scsi_Cmnd *SCpnt) - * Purpose : abort a command if something horrible happens. - * Params : SCpnt - Command that is believed to be causing a problem. - * Returns : one of SCSI_ABORT_ macros. - */ -extern int fas216_abort (Scsi_Cmnd *); - -/* Function: int fas216_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) - * Purpose : resets the adapter if something horrible happens. - * Params : SCpnt - Command that is believed to be causing a problem. - * reset_flags - flags indicating reset type that is believed to be required. - * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET macros. +/* Function: int fas216_add (struct Scsi_Host *instance) + * Purpose : initialise FAS/NCR/AMD SCSI ic. + * Params : instance - a driver-specific filled-out structure + * Returns : 0 on success */ -extern int fas216_reset (Scsi_Cmnd *, unsigned int); +extern int fas216_add (struct Scsi_Host *instance); /* Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) * Purpose : queue a command for adapter to process. @@ -341,20 +342,21 @@ */ extern int fas216_command (Scsi_Cmnd *); -/* Function: void fas216_intr (struct Scsi_Host *instance) +/* Function: void fas216_intr (FAS216_Info *info) * Purpose : handle interrupts from the interface to progress a command - * Params : instance - interface to service + * Params : info - interface to service */ -extern void fas216_intr (struct Scsi_Host *instance); +extern void fas216_intr (FAS216_Info *info); + +extern void fas216_remove (struct Scsi_Host *instance); /* Function: int fas216_release (struct Scsi_Host *instance) * Purpose : release all resources and put everything to bed for FAS/NCR/AMD SCSI ic. * Params : instance - a driver-specific filled-out structure * Returns : 0 on success */ -extern int fas216_release (struct Scsi_Host *instance); +extern void fas216_release (struct Scsi_Host *instance); -extern int fas216_info(FAS216_Info *info, char *buffer); extern int fas216_print_host(FAS216_Info *info, char *buffer); extern int fas216_print_stats(FAS216_Info *info, char *buffer); extern int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer); diff -urN orig/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c --- orig/drivers/acorn/scsi/powertec.c Fri Nov 16 10:09:50 2001 +++ linux/drivers/acorn/scsi/powertec.c Sun Jun 29 18:33:46 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/acorn/scsi/powertec.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-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 @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -41,14 +39,10 @@ #include "../../scsi/sd.h" #include "../../scsi/hosts.h" #include "fas216.h" +#include "scsi.h" #include -/* Configuration */ -#define POWERTEC_XTALFREQ 40 -#define POWERTEC_ASYNC_PERIOD 200 -#define POWERTEC_SYNC_DEPTH 7 - /* * List of devices that the driver will recognise */ @@ -70,33 +64,23 @@ #define POWERTEC_INTR_ENABLE 1 #define POWERTEC_INTR_DISABLE 0 -/* - * Version - */ -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 5 - -static struct expansion_card *ecs[MAX_ECARDS]; +#define VERSION "1.10 (22/01/2003 2.4.19-rmk5)" /* - * Use term=0,1,0,0,0 to turn terminators on/off + * Use term=0,1,0,0,0 to turn terminators on/off. + * One entry per slot. */ static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; #define NR_SG 256 -typedef struct { +struct powertec_info { FAS216_Info info; - - struct { - unsigned int term_port; - unsigned int terms; - } control; - - /* other info... */ - struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -} PowerTecScsi_Info; + struct expansion_card *ec; + unsigned int term_port; + unsigned int term_ctl; + struct scatterlist sg[NR_SG]; +}; /* Prototype: void powertecscsi_irqenable(ec, irqnr) * Purpose : Enable interrupts on Powertec SCSI card @@ -123,12 +107,8 @@ } static const expansioncard_ops_t powertecscsi_ops = { - powertecscsi_irqenable, - powertecscsi_irqdisable, - NULL, - NULL, - NULL, - NULL + .irqenable = powertecscsi_irqenable, + .irqdisable = powertecscsi_irqdisable, }; /* Prototype: void powertecscsi_terminator_ctl(host, on_off) @@ -139,14 +119,10 @@ static void powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off) { - PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; - - if (on_off) - info->control.terms = POWERTEC_TERM_ENABLE; - else - info->control.terms = 0; + struct powertec_info *info = (struct powertec_info *)host->hostdata; - outb(info->control.terms, info->control.term_port); + info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0; + outb(info->term_ctl, info->term_port); } /* Prototype: void powertecscsi_intr(irq, *dev_id, *regs) @@ -158,9 +134,7 @@ static void powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs) { - struct Scsi_Host *host = (struct Scsi_Host *)dev_id; - - fas216_intr(host); + fas216_intr(dev_id); } /* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type) @@ -175,32 +149,26 @@ powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_type) { - PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; + struct powertec_info *info = (struct powertec_info *)host->hostdata; int dmach = host->dma_channel; - if (dmach != NO_DMA && - (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs = SCp->buffers_residual; - int pci_dir, dma_dir; - - if (bufs) - memcpy(info->sg + 1, SCp->buffer + 1, - sizeof(struct scatterlist) * bufs); - info->sg[0].address = SCp->ptr; - info->sg[0].page = NULL; - info->sg[0].length = SCp->this_residual; + if (info->info.ifcfg.capabilities & FASCAP_DMA && + min_type == fasdma_real_all) { + int bufs, map_dir, dma_dir; + + bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); if (direction == DMA_OUT) - pci_dir = PCI_DMA_TODEVICE, + map_dir = PCI_DMA_TODEVICE, dma_dir = DMA_MODE_WRITE; else - pci_dir = PCI_DMA_FROMDEVICE, + map_dir = PCI_DMA_FROMDEVICE, dma_dir = DMA_MODE_READ; - pci_map_sg(NULL, info->sg, bufs + 1, pci_dir); + pci_map_sg(NULL, info->sg, bufs, map_dir); disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); + set_dma_sg(dmach, info->sg, bufs); set_dma_mode(dmach, dma_dir); enable_dma(dmach); return fasdma_real_all; @@ -225,122 +193,6 @@ disable_dma(host->dma_channel); } -/* Prototype: int powertecscsi_detect(Scsi_Host_Template * tpnt) - * Purpose : initialises PowerTec SCSI driver - * Params : tpnt - template for this SCSI adapter - * Returns : >0 if host found, 0 otherwise. - */ -int -powertecscsi_detect(Scsi_Host_Template *tpnt) -{ - static const card_ids powertecscsi_cids[] = - { POWERTECSCSI_LIST, { 0xffff, 0xffff} }; - int count = 0; - struct Scsi_Host *host; - - tpnt->proc_name = "powertec"; - memset(ecs, 0, sizeof (ecs)); - - ecard_startfind(); - - while (1) { - PowerTecScsi_Info *info; - - ecs[count] = ecard_find(0, powertecscsi_cids); - if (!ecs[count]) - break; - - ecard_claim(ecs[count]); - - host = scsi_register(tpnt, sizeof (PowerTecScsi_Info)); - if (!host) { - ecard_release(ecs[count]); - break; - } - - host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST); - host->irq = ecs[count]->irq; - host->dma_channel = ecs[count]->dma; - info = (PowerTecScsi_Info *)host->hostdata; - - if (host->dma_channel != NO_DMA) - set_dma_speed(host->dma_channel, 180); - - info->control.term_port = host->io_port + POWERTEC_TERM_CONTROL; - info->control.terms = term[count] ? POWERTEC_TERM_ENABLE : 0; - powertecscsi_terminator_ctl(host, info->control.terms); - - info->info.scsi.io_port = - host->io_port + POWERTEC_FAS216_OFFSET; - info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = POWERTEC_XTALFREQ; - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = POWERTEC_ASYNC_PERIOD; - info->info.ifcfg.sync_max_depth = POWERTEC_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.dma.setup = powertecscsi_dma_setup; - info->info.dma.pseudo = NULL; - info->info.dma.stop = powertecscsi_dma_stop; - - ecs[count]->irqaddr = (unsigned char *) - ioaddr(host->io_port + POWERTEC_INTR_STATUS); - ecs[count]->irqmask = POWERTEC_INTR_BIT; - ecs[count]->irq_data = (void *) - (host->io_port + POWERTEC_INTR_CONTROL); - ecs[count]->ops = (expansioncard_ops_t *)&powertecscsi_ops; - - request_region(host->io_port + POWERTEC_FAS216_OFFSET, - 16 << POWERTEC_FAS216_SHIFT, "powertec2-fas"); - - if (host->irq != NO_IRQ && - request_irq(host->irq, powertecscsi_intr, - SA_INTERRUPT, "powertec", host)) { - printk("scsi%d: IRQ%d not free, interrupts disabled\n", - host->host_no, host->irq); - host->irq = NO_IRQ; - info->info.scsi.irq = NO_IRQ; - } - - if (host->dma_channel != NO_DMA && - request_dma(host->dma_channel, "powertec")) { - printk("scsi%d: DMA%d not free, DMA disabled\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } - - fas216_init(host); - ++count; - } - return count; -} - -/* Prototype: int powertecscsi_release(struct Scsi_Host * host) - * Purpose : releases all resources used by this adapter - * Params : host - driver host structure to return info for. - */ -int powertecscsi_release(struct Scsi_Host *host) -{ - int i; - - fas216_release(host); - - if (host->irq != NO_IRQ) - free_irq(host->irq, host); - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - release_region(host->io_port + POWERTEC_FAS216_OFFSET, - 16 << POWERTEC_FAS216_SHIFT); - - for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && - host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST)) - ecard_release(ecs[i]); - return 0; -} - /* Prototype: const char *powertecscsi_info(struct Scsi_Host * host) * Purpose : returns a descriptive string about this interface, * Params : host - driver host structure to return info for. @@ -348,15 +200,12 @@ */ const char *powertecscsi_info(struct Scsi_Host *host) { - PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata; - static char string[100], *p; + struct powertec_info *info = (struct powertec_info *)host->hostdata; + static char string[150]; - p = string; - p += sprintf(p, "%s ", host->hostt->name); - p += fas216_info(&info->info, p); - p += sprintf(p, "v%d.%d.%d terminators o%s", - VER_MAJOR, VER_MINOR, VER_PATCH, - info->control.terms ? "n" : "ff"); + sprintf(string, "%s (%s) in slot %d v%s terminators o%s", + host->hostt->name, info->info.scsi.type, info->ec->slot_no, + VERSION, info->term_ctl ? "n" : "ff"); return string; } @@ -409,31 +258,25 @@ int length, int host_no, int inout) { int pos, begin; - struct Scsi_Host *host = scsi_hostlist; - PowerTecScsi_Info *info; + struct Scsi_Host *host; + struct powertec_info *info; Scsi_Device *scd; - while (host) { - if (host->host_no == host_no) - break; - host = host->next; - } + host = scsi_host_hn_get(host_no); if (!host) return 0; if (inout == 1) return powertecscsi_set_proc_info(host, buffer, length); - info = (PowerTecScsi_Info *)host->hostdata; + info = (struct powertec_info *)host->hostdata; begin = 0; - pos = sprintf(buffer, - "PowerTec SCSI driver version %d.%d.%d\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + pos = sprintf(buffer, "PowerTec SCSI driver v%s\n", VERSION); pos += fas216_print_host(&info->info, buffer + pos); pos += sprintf(buffer + pos, "Term : o%s\n", - info->control.terms ? "n" : "ff"); + info->term_ctl ? "n" : "ff"); pos += fas216_print_stats(&info->info, buffer + pos); @@ -458,28 +301,186 @@ return pos; } +static int powertecscsi_probe(struct expansion_card *ec); + +/* Prototype: int powertecscsi_detect(Scsi_Host_Template * tpnt) + * Purpose : initialises PowerTec SCSI driver + * Params : tpnt - template for this SCSI adapter + * Returns : >0 if host found, 0 otherwise. + */ +static int powertecscsi_detect(Scsi_Host_Template *tpnt) +{ + static const card_ids powertecscsi_cids[] = + { POWERTECSCSI_LIST, { 0xffff, 0xffff} }; + struct expansion_card *ec; + int count = 0, ret; + + ecard_startfind(); + + while (1) { + ec = ecard_find(0, powertecscsi_cids); + if (!ec) + break; + + ecard_claim(ec); + + ret = powertecscsi_probe(ec); + if (ret) { + ecard_release(ec); + break; + } + ++count; + } + return count; +} + +static void powertecscsi_remove(struct Scsi_Host *host); + +/* Prototype: int powertecscsi_release(struct Scsi_Host * host) + * Purpose : releases all resources used by this adapter + * Params : host - driver host structure to return info for. + */ +static int powertecscsi_release(struct Scsi_Host *host) +{ + powertecscsi_remove(host); + return 0; +} + static Scsi_Host_Template powertecscsi_template = { - module: THIS_MODULE, - proc_info: powertecscsi_proc_info, - name: "PowerTec SCSI", - detect: powertecscsi_detect, - release: powertecscsi_release, - info: powertecscsi_info, - bios_param: scsicam_bios_param, - can_queue: 1, - this_id: 7, - sg_tablesize: SG_ALL, - cmd_per_lun: 1, - use_clustering: ENABLE_CLUSTERING, - command: fas216_command, - queuecommand: fas216_queue_command, - eh_host_reset_handler: fas216_eh_host_reset, - eh_bus_reset_handler: fas216_eh_bus_reset, - eh_device_reset_handler: fas216_eh_device_reset, - eh_abort_handler: fas216_eh_abort, - use_new_eh_code: 1 + .module = THIS_MODULE, + .proc_info = powertecscsi_proc_info, + .name = "PowerTec SCSI", + .detect = powertecscsi_detect, + .release = powertecscsi_release, + .info = powertecscsi_info, + .bios_param = scsicam_bios_param, + .command = fas216_command, + .queuecommand = fas216_queue_command, + .eh_host_reset_handler = fas216_eh_host_reset, + .eh_bus_reset_handler = fas216_eh_bus_reset, + .eh_device_reset_handler = fas216_eh_device_reset, + .eh_abort_handler = fas216_eh_abort, + .use_new_eh_code = 1, + + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, + .proc_name = "powertec", }; +static int +powertecscsi_probe(struct expansion_card *ec) +{ + struct Scsi_Host *host; + struct powertec_info *info; + unsigned long base; + int ret; + + base = ecard_address(ec, ECARD_IOC, ECARD_FAST); + + request_region(base + POWERTEC_FAS216_OFFSET, + 16 << POWERTEC_FAS216_SHIFT, "powertec2-fas"); + + host = scsi_register(&powertecscsi_template, + sizeof (struct powertec_info)); + if (!host) { + ret = -ENOMEM; + goto out_region; + } + + host->io_port = base; + host->irq = ec->irq; + host->dma_channel = ec->dma; + + ec->irqaddr = (unsigned char *)ioaddr(base + POWERTEC_INTR_STATUS); + ec->irqmask = POWERTEC_INTR_BIT; + ec->irq_data = (void *)(base + POWERTEC_INTR_CONTROL); + ec->ops = (expansioncard_ops_t *)&powertecscsi_ops; + + info = (struct powertec_info *)host->hostdata; + info->ec = ec; + info->term_port = base + POWERTEC_TERM_CONTROL; + powertecscsi_terminator_ctl(host, term[ec->slot_no]); + + info->info.scsi.io_port = host->io_port + POWERTEC_FAS216_OFFSET; + info->info.scsi.io_shift = POWERTEC_FAS216_SHIFT; + info->info.scsi.irq = host->irq; + info->info.ifcfg.clockrate = 40; /* MHz */ + info->info.ifcfg.select_timeout = 255; + info->info.ifcfg.asyncperiod = 200; /* ns */ + info->info.ifcfg.sync_max_depth = 7; + info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; + info->info.ifcfg.capabilities = 0; + info->info.dma.setup = powertecscsi_dma_setup; + info->info.dma.pseudo = NULL; + info->info.dma.stop = powertecscsi_dma_stop; + + ret = fas216_init(host); + if (ret) + goto out_free; + + ret = request_irq(host->irq, powertecscsi_intr, + SA_INTERRUPT, "powertec", &info->info); + if (ret) { + printk("scsi%d: IRQ%d not free: %d\n", + host->host_no, host->irq, ret); + goto out_release; + } + + if (host->dma_channel != NO_DMA) { + if (request_dma(host->dma_channel, "powertec")) { + printk("scsi%d: DMA%d not free, using PIO\n", + host->host_no, host->dma_channel); + host->dma_channel = NO_DMA; + } else { + set_dma_speed(host->dma_channel, 180); + info->info.ifcfg.capabilities |= FASCAP_DMA; + } + } + + ret = fas216_add(host); + if (ret == 0) + goto out; + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, host); + + out_release: + fas216_release(host); + + out_free: + scsi_unregister(host); + + out_region: + release_region(base + POWERTEC_FAS216_OFFSET, + 16 << POWERTEC_FAS216_SHIFT); + + out: + return ret; +} + +static void powertecscsi_remove(struct Scsi_Host *host) +{ + struct powertec_info *info = (struct powertec_info *)host->hostdata; + + fas216_remove(host); + + if (host->dma_channel != NO_DMA) + free_dma(host->dma_channel); + free_irq(host->irq, info); + + release_region(host->io_port + POWERTEC_FAS216_OFFSET, + 16 << POWERTEC_FAS216_SHIFT); + + fas216_release(host); + ecard_release(info->ec); +} + static int __init powertecscsi_init(void) { scsi_register_module(MODULE_SCSI_HA, &powertecscsi_template); diff -urN orig/drivers/acorn/scsi/queue.c linux/drivers/acorn/scsi/queue.c --- orig/drivers/acorn/scsi/queue.c Fri Oct 26 16:46:02 2001 +++ linux/drivers/acorn/scsi/queue.c Wed Nov 13 14:09:51 2002 @@ -229,6 +229,27 @@ } /* + * Function: queue_remove_all_target(queue, target) + * Purpose : remove all SCSI commands from the queue for a specified target + * Params : queue - queue to remove command from + * target - target device id + * Returns : nothing + */ +void queue_remove_all_target(Queue_t *queue, int target) +{ + unsigned long flags; + struct list_head *l; + + spin_lock_irqsave(&queue->queue_lock, flags); + list_for_each(l, &queue->head) { + QE_t *q = list_entry(l, QE_t, list); + if (q->SCpnt->target == target) + __queue_remove(queue, l); + } + spin_unlock_irqrestore(&queue->queue_lock, flags); +} + +/* * Function: int queue_probetgtlun (queue, target, lun) * Purpose : check to see if we have a command in the queue for the specified * target/lun. @@ -290,6 +311,7 @@ EXPORT_SYMBOL(queue_remove_exclude); EXPORT_SYMBOL(queue_remove_tgtluntag); EXPORT_SYMBOL(queue_remove_cmd); +EXPORT_SYMBOL(queue_remove_all_target); EXPORT_SYMBOL(queue_probetgtlun); MODULE_AUTHOR("Russell King"); diff -urN orig/drivers/acorn/scsi/queue.h linux/drivers/acorn/scsi/queue.h --- orig/drivers/acorn/scsi/queue.h Tue Oct 3 20:08:24 2000 +++ linux/drivers/acorn/scsi/queue.h Wed Nov 13 14:09:51 2002 @@ -74,6 +74,15 @@ extern Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag); /* + * Function: queue_remove_all_target(queue, target) + * Purpose : remove all SCSI commands from the queue for a specified target + * Params : queue - queue to remove command from + * target - target device id + * Returns : nothing + */ +extern void queue_remove_all_target(Queue_t *queue, int target); + +/* * Function: int queue_probetgtlun (queue, target, lun) * Purpose : check to see if we have a command in the queue for the specified * target/lun. diff -urN orig/drivers/acorn/scsi/scsi.h linux/drivers/acorn/scsi/scsi.h --- orig/drivers/acorn/scsi/scsi.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/acorn/scsi/scsi.h Fri Feb 21 16:51:30 2003 @@ -0,0 +1,123 @@ +/* + * linux/drivers/acorn/scsi/scsi.h + * + * Copyright (C) 2002 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Commonly used scsi driver functions. + */ + +#define BELT_AND_BRACES + +/* + * The scatter-gather list handling. This contains all + * the yucky stuff that needs to be fixed properly. + */ +static inline int copy_SCp_to_sg(struct scatterlist *sg, Scsi_Pointer *SCp, int max) +{ + int bufs = SCp->buffers_residual; + + BUG_ON(bufs + 1 > max); + + sg->address = SCp->ptr; + sg->length = SCp->this_residual; + + if (bufs) + memcpy(sg + 1, SCp->buffer + 1, + sizeof(struct scatterlist) * bufs); + return bufs + 1; +} + +static inline int next_SCp(Scsi_Pointer *SCp) +{ + int ret = SCp->buffers_residual; + if (ret) { + SCp->buffer++; + SCp->buffers_residual--; + SCp->ptr = (unsigned char *)SCp->buffer->address; + SCp->this_residual = SCp->buffer->length; + } else { + SCp->ptr = NULL; + SCp->this_residual = 0; + } + return ret; +} + +static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp) +{ + char c = *SCp->ptr; + + SCp->ptr += 1; + SCp->this_residual -= 1; + + return c; +} + +static inline void put_next_SCp_byte(Scsi_Pointer *SCp, unsigned char c) +{ + *SCp->ptr = c; + SCp->ptr += 1; + SCp->this_residual -= 1; +} + +static inline void init_SCp(Scsi_Cmnd *SCpnt) +{ + memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); + + if (SCpnt->use_sg) { + unsigned long len = 0; + int buf; + + SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer; + SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; + SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address; + SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; + +#ifdef BELT_AND_BRACES + /* + * Calculate correct buffer length. Some commands + * come in with the wrong request_bufflen. + */ + for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) + len += SCpnt->SCp.buffer[buf].length; + + if (SCpnt->request_bufflen != len) + printk(KERN_WARNING "scsi%d.%c: bad request buffer " + "length %d, should be %ld\n", SCpnt->host->host_no, + '0' + SCpnt->target, SCpnt->request_bufflen, len); + SCpnt->request_bufflen = len; +#endif + } else { + SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; + SCpnt->SCp.this_residual = SCpnt->request_bufflen; + } + + /* + * If the upper SCSI layers pass a buffer, but zero length, + * we aren't interested in the buffer pointer. + */ + if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { +#if 0 //def BELT_AND_BRACES + printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " + "command ", SCpnt->host->host_no, '0' + SCpnt->target); + print_command(SCpnt->cmnd); +#endif + SCpnt->SCp.ptr = NULL; + } +} + +static inline struct Scsi_Host *scsi_host_hn_get(int host_no) +{ + struct Scsi_Host *host = scsi_hostlist; + + while (host) { + if (host->host_no == host_no) + break; + host = host->next; + } + + return host; +} diff -urN orig/drivers/at91/Makefile linux/drivers/at91/Makefile --- orig/drivers/at91/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/Makefile Sun Jun 15 21:48:36 2003 @@ -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 -urN orig/drivers/at91/i2c/Makefile linux/drivers/at91/i2c/Makefile --- orig/drivers/at91/i2c/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/i2c/Makefile Sun Jun 15 21:45:20 2003 @@ -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 -urN orig/drivers/at91/i2c/at91_i2c.c linux/drivers/at91/i2c/at91_i2c.c --- orig/drivers/at91/i2c/at91_i2c.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/i2c/at91_i2c.c Sun Jun 15 21:45:20 2003 @@ -0,0 +1,294 @@ +/* + 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; + +/* + * SMBUS-type transfer entrypoint + */ +static s32 at91_smbus_xfer(struct i2c_adapter *adap, + u16 addr, + unsigned short flags, + char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ +#if 0 + struct at91_i2c_local *device = (struct at91_i2c_local *) adap->data; + int len; + u8 *buffer; + u16 cur_word; + int rc = 0; + + /* Prepare datas & select mode */ + switch (size) { + case I2C_SMBUS_QUICK: + len = 0; + buffer = NULL; + break; + case I2C_SMBUS_BYTE: + len = 1; + buffer = &data->byte; + break; + case I2C_SMBUS_BYTE_DATA: + len = 1; + buffer = &data->byte; + break; + case I2C_SMBUS_WORD_DATA: + len = 2; + cur_word = cpu_to_le16(data->word); + buffer = (u8 *) & cur_word; + break; + case I2C_SMBUS_BLOCK_DATA: + len = data->block[0]; + buffer = &data->block[1]; + break; + default: + return -1; + } + + /* Original driver had this limitation */ + if (len > 32) + len = 32; + + DBG("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n", + device->chan_no, addr, len, read_write == I2C_SMBUS_READ); + + /* Set up address and r/w bit */ + write_reg(reg_addr, (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); + + /* Set up the sub address */ + + /* Start sending address & enable interrupt */ + write_reg(reg_control, read_reg(reg_control) | KW_I2C_CTL_XADDR); + write_reg(reg_ier, KW_I2C_IRQ_MASK); + + DBG("transfer done\n"); + + if (size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ) + data->word = le16_to_cpu(cur_word); +#endif + return 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 completed = 0, length; + unsigned char *buf; + + pmsg = msgs; /* look at 1st message, it contains the address/command */ + if (num == 2 && pmsg->len >= 1 && pmsg->len <= 3) { + 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]; + + 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 */ + do + udelay(10); + while (!(twi->TWI_SR & AT91C_TWI_RXRDY)); + *buf++ = twi->TWI_RHR; + } + do { + udelay(10); + } while (!(twi->TWI_SR & AT91C_TWI_TXCOMP)); + } else { + twi->TWI_CR = AT91C_TWI_START; + while (length--) { + twi->TWI_THR = *buf++; + if (!length) + twi->TWI_CR = AT91C_TWI_STOP; + do { + udelay(10); + } while (!(twi->TWI_SR & AT91C_TWI_TXRDY)); + } + /* Wait until transfer is finished */ + do { + udelay(10); + } while (!(twi->TWI_SR & AT91C_TWI_TXCOMP)); + } + } + } + DBG("transfer done\n"); + return completed++; +} + +/* + * 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; + AT91_SYS->PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */ +} + +/* + * Close + */ +static void at91_dec(struct i2c_adapter *adapter) +{ + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_TWI; /* disable peripheral clock */ + 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, + smbus_xfer:at91_smbus_xfer, + 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(); + + 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); + + /* 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 -urN orig/drivers/at91/i2c/at91_i2c.h linux/drivers/at91/i2c/at91_i2c.h --- orig/drivers/at91/i2c/at91_i2c.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/i2c/at91_i2c.h Sun Jun 15 21:45:20 2003 @@ -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 (1 << 16) /* TWI clock divider */ + +#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 -urN orig/drivers/at91/mtd/Makefile linux/drivers/at91/mtd/Makefile --- orig/drivers/at91/mtd/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/mtd/Makefile Sun Jun 15 21:48:36 2003 @@ -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 -urN orig/drivers/at91/mtd/at91_dataflash.c linux/drivers/at91/mtd/at91_dataflash.c --- orig/drivers/at91/mtd/at91_dataflash.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/mtd/at91_dataflash.c Sun Jun 15 21:48:36 2003 @@ -0,0 +1,495 @@ +/* + * 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 "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. */ +struct spi_transfer_list* spi_transfer_desc; + +/* + * Perform a SPI transfer to access the DataFlash device. + */ +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. + */ +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. + */ +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 a block of flash. + */ +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) || (instr->len != priv->page_size)) + return -EINVAL; + if ((instr->addr % priv->page_size) != 0) + return -EINVAL; + + command = kmalloc(4, GFP_KERNEL); + if (!command) + return -ENOMEM; + + /* 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); + + 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 + */ +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 + */ +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; + char *writebuf; + unsigned short status; + int res = 0; + char* command; + +#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; + + /* 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, writebuf, 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(command); + return res; +} + +/* ......................................................................... */ + +/* + * Initialize and register DataFlash device with MTD subsystem. + */ +int add_dataflash(int channel, char *name, int size, 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 = size; + 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, 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); + } + + return add_mtd_partitions(device, mtd_parts, mtd_parts_nr); +#else + return add_mtd_device(device); +#endif +} + +/* + * Detect and initialize DataFlash device connected to specified SPI channel. + */ +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 0x2c: /* 1 0 1 1 */ + res = add_dataflash(channel, "Atmel AT45DB161B", 4096*528, 528, 10); + break; + case 0x34: /* 1 1 0 1 */ + res = add_dataflash(channel, "Atmel AT45DB321B", 8192*528, 528, 10); + break; + case 0x3c: /* 1 1 1 1 */ + res = add_dataflash(channel, "Atmel AT45DB642", 8192*1056, 1056, 11); + break; + default: + printk(KERN_ERR "at91_dataflash: Unknown device (%x)\n", status & 0x3c); + } + } + spi_release_bus(channel); + + return res; +} + +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; +} + +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 -urN orig/drivers/at91/mtd/at91_dataflash.h linux/drivers/at91/mtd/at91_dataflash.h --- orig/drivers/at91/mtd/at91_dataflash.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/mtd/at91_dataflash.h Sun Jun 15 21:48:36 2003 @@ -0,0 +1,42 @@ +/* + * 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 */ + +#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 -urN orig/drivers/at91/mtd/at91_nand.c linux/drivers/at91/mtd/at91_nand.c --- orig/drivers/at91/mtd/at91_nand.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/mtd/at91_nand.c Sun Jun 15 21:48:08 2003 @@ -0,0 +1,327 @@ +/* + * 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; + +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 + */ +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. + */ +int at91_device_ready(void) +{ + return AT91_PIO_SmartMedia_RDY(); +} +/* + * Main initialization routine + */ +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 */ + /* 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) /* debug only 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 (3) /* 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 -urN orig/drivers/at91/mtd/at91_nand.h linux/drivers/at91/mtd/at91_nand.h --- orig/drivers/at91/mtd/at91_nand.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/mtd/at91_nand.h Sun Jun 15 21:48:08 2003 @@ -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 -urN orig/drivers/at91/net/Makefile linux/drivers/at91/net/Makefile --- orig/drivers/at91/net/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/net/Makefile Fri Jun 13 22:22:15 2003 @@ -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 -urN orig/drivers/at91/net/at91_ether.c linux/drivers/at91/net/at91_ether.c --- orig/drivers/at91/net/at91_ether.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/net/at91_ether.c Fri Jun 13 22:22:15 2003 @@ -0,0 +1,800 @@ +/* + * 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 + * + * 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 address, unsigned int value) +{ + regs->EMAC_MAN = (AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W + | (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 address, unsigned int *value) +{ + regs->EMAC_MAN = AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_R + | (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, MII_BMSR, &bmsr); + read_phy(regs, MII_BMSR, &bmsr); + if (!(bmsr & BMSR_LSTATUS)) return -1; /* no link */ + + read_phy(regs, MII_BMCR, &bmcr); + if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ + if (!(bmsr & BMSR_ANEGCOMPLETE)) return -2; /* auto-negotitation in progress */ + + read_phy(regs, 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 + */ +void at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr; + int status; + unsigned int phy; + + enable_mdi(emac); + + read_phy(emac, MII_DSINTR_REG, &phy); /* acknowledge interrupt in 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 + */ +void enable_phyirq(struct net_device *dev, AT91PS_EMAC regs) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int dsintr, status; + + static int first_init = 0; + + if (first_init == 0) { + // TODO: Check error code. Really need a generic PIO (interrupt) + // layer since we're really only interested in the PC4 line. + (void) request_irq(4, at91ether_phy_interrupt, 0, dev->name, dev); + + AT91_SYS->PIOC_ODR = AT91C_PIO_PC4; /* Configure as input */ + + first_init = 1; + } + else { + status = AT91_SYS->PIOC_ISR; /* clear any pending PIO interrupts */ + AT91_SYS->PIOC_IER = AT91C_PIO_PC4; /* Enable interrupt */ + + spin_lock_irq(&lp->lock); + enable_mdi(regs); + read_phy(regs, MII_DSINTR_REG, &dsintr); + dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ + write_phy(regs, MII_DSINTR_REG, dsintr); + disable_mdi(regs); + spin_unlock_irq(&lp->lock); + } +} + +/* + * Disable the PHY interrupt + */ +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); + read_phy(regs, MII_DSINTR_REG, &dsintr); + dsintr = dsintr | 0xf00; /* set bits 8..11 */ + write_phy(regs, MII_DSINTR_REG, dsintr); + disable_mdi(regs); + spin_unlock_irq(&lp->lock); + + AT91_SYS->PIOC_IDR = AT91C_PIO_PC4; /* Disable interrupt */ +} + +/* ......................... ADDRESS MANAGEMENT ........................ */ + +/* + * Set the ethernet MAC address in dev->dev_addr + */ +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]); +} + +#ifdef AT91_ETHER_ADDR_CONFIGURABLE +/* + * 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; +} +#endif + +/* + * 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, 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, 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 (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 */ + + /* 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) +{ + struct at91_private *lp; + AT91PS_EMAC regs; + static int already_initialized = 0; + + 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; + +#ifdef AT91_ETHER_ADDR_CONFIGURABLE + dev->set_mac_address = set_mac_address; +#endif + + 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_RMII; +#else + regs->EMAC_CFG = 0; +#endif + + lp->mii.dev = dev; /* Support for ethtool */ + lp->mii.mdio_read = mdio_read; + lp->mii.mdio_write = mdio_write; + + enable_phyirq(dev, regs); + + /* 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]); + + already_initialized = 1; + return 0; +} + +/* + * Detect MAC and PHY and perform initialization + */ +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_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Enable Peripheral clock */ + + /* Read the PHY ID registers */ + enable_mdi(regs); + read_phy(regs, MII_PHYSID1, &phyid1); + read_phy(regs, 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); + } + + 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 -urN orig/drivers/at91/net/at91_ether.h linux/drivers/at91/net/at91_ether.h --- orig/drivers/at91/net/at91_ether.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/net/at91_ether.h Fri Jun 13 22:22:15 2003 @@ -0,0 +1,71 @@ +/* + * 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 + +#undef AT91_ETHER_ADDR_CONFIGURABLE /* MAC address can be changed? */ + + +/* Davicom 9161 PHY */ +#define MII_DM9161_ID 0x0181b880 + +/* Davicom specific registers */ +#define MII_DSCSR_REG 17 +#define MII_DSINTR_REG 21 + +/* ........................................................................ */ + +#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 */ + spinlock_t lock; /* lock for MDI interface */ + + /* 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 -urN orig/drivers/at91/rtc/Makefile linux/drivers/at91/rtc/Makefile --- orig/drivers/at91/rtc/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/rtc/Makefile Fri Jun 13 22:58:44 2003 @@ -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 -urN orig/drivers/at91/rtc/at91_rtc.c linux/drivers/at91/rtc/at91_rtc.c --- orig/drivers/at91/rtc/at91_rtc.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/rtc/at91_rtc.c Fri Jun 13 22:58:44 2003 @@ -0,0 +1,440 @@ +/* + * 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 / 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; +} + +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); + remove_wait_queue(&at91_rtc_update, &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 */ + 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 */ + 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 -urN orig/drivers/at91/serial/Makefile linux/drivers/at91/serial/Makefile --- orig/drivers/at91/serial/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/serial/Makefile Fri Jun 13 22:21:22 2003 @@ -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 -urN orig/drivers/at91/serial/at91_serial.c linux/drivers/at91/serial/at91_serial.c --- orig/drivers/at91/serial/at91_serial.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/serial/at91_serial.c Fri Jun 13 22:21:22 2003 @@ -0,0 +1,834 @@ +/* + * 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 + +/* + * This is a temporary structure for registering these + * functions; it is intended to be discarded after boot. + */ +struct uart_port; +struct uart_info; +struct at91_port_fns { + void (*set_mctrl)(struct uart_port *, u_int); + u_int (*get_mctrl)(struct uart_port *); + void (*enable_ms)(struct uart_port *); + void (*pm)(struct uart_port *, u_int, u_int); + int (*set_wake)(struct uart_port *, u_int); + int (*open)(struct uart_port *, struct uart_info *); + void (*close)(struct uart_port *, struct uart_info *); +}; + +#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_GET_CR(port) ((AT91PS_USART)(port)->membase)->US_CR // is write-only + +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]; +static int (*at91_open)(struct uart_port *, struct uart_info *); +static void (*at91_close)(struct uart_port *, struct uart_info *); + +#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; + + 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 nonempty, u_int from_tty) +{ + if (nonempty) { + 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_info *info, struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + struct uart_port *port = info->port; + 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(info, 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 + info->sysrq = 0; +#endif + goto error_return; +} + +/* + * Transmit characters (called from interrupt handler) + */ +static void at91_tx_chars(struct uart_info *info) +{ + struct uart_port *port = info->port; + + if (port->x_char) { + UART_PUT_CHAR(port, port->x_char); + port->icount.tx++; + port->x_char = 0; + return; + } + if (info->xmit.head == info->xmit.tail + || info->tty->stopped + || info->tty->hw_stopped) { + at91_stop_tx(info->port, 0); + return; + } + + while (UART_GET_CSR(port) & AT91C_US_TXRDY) { + UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]); + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (info->xmit.head == info->xmit.tail) + break; + } + + if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) < WAKEUP_CHARS) + uart_event(info, EVT_WRITE_WAKEUP); + + if (info->xmit.head == info->xmit.tail) + at91_stop_tx(info->port, 0); +} + +/* + * Interrupt handler + */ +static void at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_info *info = dev_id; + struct uart_port *port = info->port; + 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(info, 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 && !info->sysrq) { + info->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(info, status & AT91C_US_DCD); + } + if (pending & AT91C_US_CTSIC) { + port->icount.cts++; + uart_handle_cts_change(info, status & AT91C_US_CTS); + } + if (pending & (AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC)) + wake_up_interruptible(&info->delta_msr_wait); + + if (pending & AT91C_US_TXRDY) + at91_tx_chars(info); + 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, struct uart_info *info) +{ + int retval; + + /* + * Allocate the IRQ + */ + retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", info); + 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, info); + if (retval) { + free_irq(port->irq, info); + 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, struct uart_info *info) +{ + /* + * Free the interrupt + */ + free_irq(port->irq, info); + + /* + * If there is a specific "close" function (to unregister + * control line interrupts) + */ + if (at91_close) + at91_close(port, info); + + /* + * 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; +} + +/* + * 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 & 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); +} + +/* + * 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_register_uart_fns(struct at91_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; + } + + at91_ports[idx].iotype = SERIAL_IO_MEM; + at91_ports[idx].flags = ASYNC_BOOT_AUTOCONF; + at91_ports[idx].uartclk = AT91C_MASTER_CLOCK; + at91_ports[idx].ops = &at91_pops; + at91_ports[idx].fifosize = 0; + + 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 + +#ifndef CONFIG_AT91_DEFAULT_BAUDRATE +#define CONFIG_AT91_DEFAULT_BAUDRATE 115200 +#endif + +/* + * 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 cr, mr, quot; + +// TODO: CR is a write-only register +// 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 = CONFIG_AT91_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) +{ + 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, + port: at91_ports, + cons: AT91_CONSOLE_DEVICE, +}; + +static int __init at91_serial_init(void) +{ + return uart_register_driver(&at91_reg); +} + +static void __exit at91_serial_exit(void) +{ + 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 -urN orig/drivers/at91/spi/Makefile linux/drivers/at91/spi/Makefile --- orig/drivers/at91/spi/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/spi/Makefile Sun Jun 15 21:46:43 2003 @@ -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 -urN orig/drivers/at91/spi/at91_spi.c linux/drivers/at91/spi/at91_spi.c --- orig/drivers/at91/spi/at91_spi.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/spi/at91_spi.c Sun Jun 15 21:46:43 2003 @@ -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 */ +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(); + case 1: AT91_CfgPIO_SPI_CS1(); + case 2: AT91_CfgPIO_SPI_CS2(); + case 3: AT91_CfgPIO_SPI_CS3(); + } + 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. + */ +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 -urN orig/drivers/at91/spi/at91_spi.h linux/drivers/at91/spi/at91_spi.h --- orig/drivers/at91/spi/at91_spi.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/spi/at91_spi.h Sun Jun 15 21:46:43 2003 @@ -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 -urN orig/drivers/at91/spi/at91_spidev.c linux/drivers/at91/spi/at91_spidev.c --- orig/drivers/at91/spi/at91_spidev.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/spi/at91_spidev.c Sun Jun 15 21:46:43 2003 @@ -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; +} + +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 + */ +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 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 -urN orig/drivers/at91/usb/Makefile linux/drivers/at91/usb/Makefile --- orig/drivers/at91/usb/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/usb/Makefile Sun Jun 15 21:43:52 2003 @@ -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 -urN orig/drivers/at91/usb/at91_usb-ohci.c linux/drivers/at91/usb/at91_usb-ohci.c --- orig/drivers/at91/usb/at91_usb-ohci.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/usb/at91_usb-ohci.c Sun Jun 15 21:43:52 2003 @@ -0,0 +1,81 @@ +/* + * 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; + } + + /* 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 -urN orig/drivers/at91/watchdog/Makefile linux/drivers/at91/watchdog/Makefile --- orig/drivers/at91/watchdog/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/watchdog/Makefile Fri Jun 13 22:38:41 2003 @@ -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 -urN orig/drivers/at91/watchdog/at91_wdt.c linux/drivers/at91/watchdog/at91_wdt.c --- orig/drivers/at91/watchdog/at91_wdt.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/at91/watchdog/at91_wdt.c Fri Jun 13 22:38:41 2003 @@ -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. + */ +void at91_wdt_stop(void) +{ + AT91_SYS->ST_WDMR = AT91C_ST_EXTEN; +} + +/* + * Enable and reset the watchdog. + */ +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 -urN orig/drivers/block/Makefile linux/drivers/block/Makefile --- orig/drivers/block/Makefile Tue Jun 24 13:58:13 2003 +++ linux/drivers/block/Makefile Tue Jun 24 11:17:29 2003 @@ -27,11 +27,17 @@ 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 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 -urN orig/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- orig/drivers/block/ll_rw_blk.c Tue Jun 24 13:58:13 2003 +++ linux/drivers/block/ll_rw_blk.c Tue Jun 24 11:17:31 2003 @@ -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 */ @@ -483,7 +496,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; @@ -1422,7 +1435,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(); @@ -1436,12 +1449,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(); @@ -1499,7 +1514,7 @@ jsfd_init(); #endif return 0; -}; +} EXPORT_SYMBOL(io_request_lock); EXPORT_SYMBOL(end_that_request_first); diff -urN orig/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c --- orig/drivers/cdrom/cdrom.c Wed Jun 18 13:01:47 2003 +++ linux/drivers/cdrom/cdrom.c Wed Jun 18 09:58:09 2003 @@ -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 -urN orig/drivers/char/Config.in linux/drivers/char/Config.in --- orig/drivers/char/Config.in Tue Jun 24 13:58:16 2003 +++ linux/drivers/char/Config.in Tue Jun 24 11:17:32 2003 @@ -20,10 +20,10 @@ if [ "$CONFIG_IA64" = "y" ]; then bool 'Support for serial console 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 @@ -103,18 +103,6 @@ bool ' Leave port 1 alone (for kgdb or audio)' CONFIG_SIBYTE_SB1250_DUART_NO_PORT_1 fi fi - fi -fi -if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then - tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232 -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_MIPS" = "y" ]; then bool ' TMPTX3912/PR31700 serial port support' CONFIG_SERIAL_TX3912 @@ -145,6 +133,16 @@ fi bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 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 + 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 @@ -164,6 +162,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 @@ -216,11 +220,12 @@ 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 ' 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 @@ -273,6 +278,15 @@ if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then bool 'Tadpole ANA H8 Support (OBSOLETE)' CONFIG_H8 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 tristate 'Siemens R3964 line discipline' CONFIG_R3964 diff -urN orig/drivers/char/Makefile linux/drivers/char/Makefile --- orig/drivers/char/Makefile Tue Jun 24 13:58:16 2003 +++ linux/drivers/char/Makefile Tue Jun 24 12:10:33 2003 @@ -101,11 +101,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 @@ -168,10 +196,8 @@ obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o obj-$(CONFIG_SERIAL) += $(SERIAL) 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_AU1000_ADS7846) += au1000_ts.o +obj-$(CONFIG_TOUCHSCREEN_ANAKIN) += anakin_ts.o ifndef CONFIG_SUN_KEYBOARD obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD) @@ -239,6 +265,8 @@ obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o +obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o +obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o ifeq ($(CONFIG_PPC),) obj-$(CONFIG_NVRAM) += nvram.o endif @@ -271,6 +299,7 @@ obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o scx200.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 @@ -299,14 +328,25 @@ 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_OMAHA_WATCHDOG) += omaha_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.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 diff -urN orig/drivers/char/amba_kmi_keyb.c linux/drivers/char/amba_kmi_keyb.c --- orig/drivers/char/amba_kmi_keyb.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/amba_kmi_keyb.c Wed Feb 27 11:50:07 2002 @@ -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 -urN orig/drivers/char/anakin_ts.c linux/drivers/char/anakin_ts.c --- orig/drivers/char/anakin_ts.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/anakin_ts.c Tue Oct 23 17:06:03 2001 @@ -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 -urN orig/drivers/char/cerf_keyb.c linux/drivers/char/cerf_keyb.c --- orig/drivers/char/cerf_keyb.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/cerf_keyb.c Wed Oct 17 16:13:27 2001 @@ -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 -urN orig/drivers/char/clps711x_keyb.c linux/drivers/char/clps711x_keyb.c --- orig/drivers/char/clps711x_keyb.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/clps711x_keyb.c Thu Nov 29 20:14:55 2001 @@ -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 -urN orig/drivers/char/console.c linux/drivers/char/console.c --- orig/drivers/char/console.c Wed Jun 18 13:01:47 2003 +++ linux/drivers/char/console.c Wed Jun 18 09:58:13 2003 @@ -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 @@ -226,7 +232,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) @@ -720,7 +726,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; @@ -838,7 +844,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}; @@ -1384,6 +1390,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 }; @@ -1393,7 +1412,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; @@ -1491,328 +1510,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 @@ -1846,7 +1963,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()) @@ -1904,42 +2021,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 @@ -1957,7 +2044,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 ) { @@ -2100,7 +2187,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; @@ -2463,8 +2550,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; @@ -2707,7 +2794,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); } @@ -2875,7 +2962,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)) @@ -2922,18 +3009,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 -urN orig/drivers/char/ds1307.c linux/drivers/char/ds1307.c --- orig/drivers/char/ds1307.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/ds1307.c Mon Aug 5 23:06:51 2002 @@ -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 -urN orig/drivers/char/ds1307.h linux/drivers/char/ds1307.h --- orig/drivers/char/ds1307.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/ds1307.h Mon Aug 5 22:25:06 2002 @@ -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) + #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 -urN orig/drivers/char/edb7211_keyb.c linux/drivers/char/edb7211_keyb.c --- orig/drivers/char/edb7211_keyb.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/edb7211_keyb.c Mon Sep 10 14:36:18 2001 @@ -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 -urN orig/drivers/char/gc_kbmap.h linux/drivers/char/gc_kbmap.h --- orig/drivers/char/gc_kbmap.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/gc_kbmap.h Tue Aug 28 20:26:52 2001 @@ -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 -urN orig/drivers/char/gc_keyb.c linux/drivers/char/gc_keyb.c --- orig/drivers/char/gc_keyb.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/gc_keyb.c Mon Sep 24 18:13:47 2001 @@ -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 -urN orig/drivers/char/gckeymap.c linux/drivers/char/gckeymap.c --- orig/drivers/char/gckeymap.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/gckeymap.c Tue Aug 28 20:26:52 2001 @@ -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 -urN orig/drivers/char/gckeymap.map linux/drivers/char/gckeymap.map --- orig/drivers/char/gckeymap.map Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/gckeymap.map Tue Aug 28 20:26:52 2001 @@ -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 -urN orig/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c --- orig/drivers/char/generic_serial.c Wed Jun 18 13:01:51 2003 +++ linux/drivers/char/generic_serial.c Wed Jun 18 09:58:19 2003 @@ -883,6 +883,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; @@ -957,6 +960,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); @@ -976,6 +984,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; @@ -1016,7 +1029,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 -urN orig/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- orig/drivers/char/keyboard.c Tue Jun 24 13:58:17 2003 +++ linux/drivers/char/keyboard.c Tue Jun 24 12:11:33 2003 @@ -21,6 +21,10 @@ * * 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); @@ -91,12 +104,16 @@ 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); @@ -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; @@ -200,6 +224,7 @@ char raw_mode; pm_access(pm_kbd); + add_keyboard_randomness(scancode | up_flag); tty = ttytab? ttytab[fg_console]: NULL; @@ -244,12 +269,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) { @@ -263,6 +311,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); @@ -331,9 +396,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; } #ifdef CONFIG_FORWARD_KEYBOARD @@ -535,7 +615,7 @@ { } -static void do_null() +static void do_null(void) { compute_shiftstate(); } @@ -650,8 +730,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 */ @@ -752,9 +832,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; @@ -833,19 +914,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; @@ -861,7 +945,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; @@ -872,7 +957,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; @@ -919,6 +1005,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); @@ -941,6 +1040,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; @@ -967,7 +1072,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 -urN orig/drivers/char/mem.c linux/drivers/char/mem.c --- orig/drivers/char/mem.c Tue Jun 24 13:58:17 2003 +++ linux/drivers/char/mem.c Tue Jun 24 11:17:36 2003 @@ -26,9 +26,6 @@ #include #include -#ifdef CONFIG_I2C -extern int i2c_init_all(void); -#endif #ifdef CONFIG_FB extern void fbmem_init(void); #endif @@ -732,9 +729,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 -urN orig/drivers/char/omaha-rtc.c linux/drivers/char/omaha-rtc.c --- orig/drivers/char/omaha-rtc.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/omaha-rtc.c Thu Oct 24 14:58:03 2002 @@ -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 -urN orig/drivers/char/omaha_wdt.c linux/drivers/char/omaha_wdt.c --- orig/drivers/char/omaha_wdt.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/omaha_wdt.c Thu Oct 24 14:58:03 2002 @@ -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 -urN orig/drivers/char/pcmcia/Config.in linux/drivers/char/pcmcia/Config.in --- orig/drivers/char/pcmcia/Config.in Wed Jun 18 13:01:51 2003 +++ linux/drivers/char/pcmcia/Config.in Wed Jun 18 09:58:21 2003 @@ -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 -urN orig/drivers/char/pcmcia/memory_cs.c linux/drivers/char/pcmcia/memory_cs.c --- orig/drivers/char/pcmcia/memory_cs.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/pcmcia/memory_cs.c Thu Sep 13 13:31:26 2001 @@ -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 -urN orig/drivers/char/sa1100-rtc.c linux/drivers/char/sa1100-rtc.c --- orig/drivers/char/sa1100-rtc.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/sa1100-rtc.c Thu Jan 3 22:06:31 2002 @@ -0,0 +1,474 @@ +/* + * Real Time Clock interface for Linux on StrongARM SA1100 + * + * 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 Russel 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 + +#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 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 = 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 rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int rtsr = RTSR; + + /* clear interrupt sources */ + RTSR = 0; + RTSR = (RTSR_AL|RTSR_HZ); + + /* clear alarm interrupt if it has occurred */ + if (rtsr & RTSR_AL) + rtsr &= ~RTSR_ALE; + RTSR = rtsr & (RTSR_ALE|RTSR_HZE); + + /* update irq data & counter */ + if (rtsr & RTSR_AL) + rtc_irq_data |= (RTC_AF|RTC_IRQF); + if (rtsr & RTSR_HZ) + rtc_irq_data |= (RTC_UF|RTC_IRQF); + rtc_irq_data += 0x100; + + /* wake up waiting process */ + wake_up_interruptible(&rtc_wait); + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); +} + +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. + */ + OSSR = OSSR_M1; /* clear match on timer1 */ + 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 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); + RTSR = 0; + RTSR = (RTSR_AL|RTSR_HZ); + OIER &= ~OIER_E1; + OSSR = OSSR_M1; + 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 (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; + } + } + 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); + RTSR &= ~RTSR_ALE; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_AIE_ON: + spin_lock_irq(&rtc_lock); + RTSR |= RTSR_ALE; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_UIE_OFF: + spin_lock_irq(&rtc_lock); + RTSR &= ~RTSR_HZE; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_UIE_ON: + spin_lock_irq(&rtc_lock); + RTSR |= RTSR_HZE; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_PIE_OFF: + spin_lock_irq(&rtc_lock); + OIER &= ~OIER_E1; + 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); + OSMR1 = TIMER_FREQ/rtc_freq + OSCR; + OIER |= OIER_E1; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_ALM_READ: + decodetime (RTAR, &tm); + break; + case RTC_ALM_SET: + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2))) + return -EFAULT; + decodetime (RCNR, &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; + RTAR = 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 (RCNR, &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; + RCNR = 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 sa1100rtc_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 (RCNR, &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 (RTAR, &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 (&sa1100rtc_miscdev); + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL); + ret = request_irq (IRQ_RTC1Hz, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL); + if (ret) { + printk (KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTC1Hz); + goto IRQ_RTC1Hz_failed; + } + ret = request_irq (IRQ_RTCAlrm, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL); + if (ret) { + printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTCAlrm); + goto IRQ_RTCAlrm_failed; + } + ret = request_irq (IRQ_OST1, timer1_interrupt, SA_INTERRUPT, "rtc timer", NULL); + if (ret) { + printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_OST1); + goto IRQ_OST1_failed; + } + + printk (KERN_INFO "SA1100 Real Time Clock driver v" DRIVER_VERSION "\n"); + + /* + * According to the manual we should be able to let RTTR be zero + * and then a default diviser for a 32.768KHz clock is used. + * Apparently this doesn't work, at least for my SA1110 rev 5. + * If the clock divider is uninitialized then reset it to the + * default value to get the 1Hz clock. + */ + if (RTTR == 0) { + RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); + printk (KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n"); + /* The current RTC value probably doesn't make sense either */ + RCNR = 0; + } + + return 0; + +IRQ_OST1_failed: + free_irq (IRQ_RTCAlrm, NULL); +IRQ_RTCAlrm_failed: + free_irq (IRQ_RTC1Hz, NULL); +IRQ_RTC1Hz_failed: + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&sa1100rtc_miscdev); + return ret; +} + +static void __exit rtc_exit(void) +{ + free_irq (IRQ_OST1, NULL); + free_irq (IRQ_RTCAlrm, NULL); + free_irq (IRQ_RTC1Hz, NULL); + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&sa1100rtc_miscdev); +} + +module_init(rtc_init); +module_exit(rtc_exit); + +MODULE_AUTHOR("Nils Faerber "); +MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)"); +EXPORT_NO_SYMBOLS; diff -urN orig/drivers/char/sa1100_wdt.c linux/drivers/char/sa1100_wdt.c --- orig/drivers/char/sa1100_wdt.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/sa1100_wdt.c Sat Jun 23 11:37:42 2001 @@ -0,0 +1,150 @@ +/* + * Watchdog driver for the SA11x0 + * + * (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 + +#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ + +static int sa1100_margin = TIMER_MARGIN; /* in seconds */ +static int sa1100wdt_users; +static int pre_margin; +#ifdef MODULE +MODULE_PARM(sa1100_margin,"i"); +#endif + +/* + * Allow only one person to hold it open + */ + +static int sa1100dog_open(struct inode *inode, struct file *file) +{ + if(test_and_set_bit(1,&sa1100wdt_users)) + return -EBUSY; + MOD_INC_USE_COUNT; + /* Activate SA1100 Watchdog timer */ + pre_margin=3686400 * sa1100_margin; + OSMR3 = OSCR + pre_margin; + OSSR = OSSR_M3; + OWER = OWER_WME; + OIER |= OIER_E3; + return 0; +} + +static int sa1100dog_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT + */ + OSMR3 = OSCR + pre_margin; +#ifndef CONFIG_WATCHDOG_NOWAYOUT + OIER &= ~OIER_E3; +#endif + sa1100wdt_users = 0; + MOD_DEC_USE_COUNT; + return 0; +} + +static ssize_t sa1100dog_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; + + /* Refresh OSMR3 timer. */ + if(len) { + OSMR3 = OSCR + pre_margin; + return 1; + } + return 0; +} + +static int sa1100dog_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + identity: "SA1100 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 put_user((RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0, (int *)arg); + case WDIOC_KEEPALIVE: + OSMR3 = OSCR + pre_margin; + return 0; + } +} + +static struct file_operations sa1100dog_fops= +{ + owner: THIS_MODULE, + write: sa1100dog_write, + ioctl: sa1100dog_ioctl, + open: sa1100dog_open, + release: sa1100dog_release, +}; + +static struct miscdevice sa1100dog_miscdev= +{ + WATCHDOG_MINOR, + "SA1100 watchdog", + &sa1100dog_fops +}; + +static int __init sa1100dog_init(void) +{ + int ret; + + ret = misc_register(&sa1100dog_miscdev); + + if (ret) + return ret; + + printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin); + + return 0; +} + +static void __exit sa1100dog_exit(void) +{ + misc_deregister(&sa1100dog_miscdev); +} + +module_init(sa1100dog_init); +module_exit(sa1100dog_exit); diff -urN orig/drivers/char/sa1111_keyb.c linux/drivers/char/sa1111_keyb.c --- orig/drivers/char/sa1111_keyb.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/char/sa1111_keyb.c Thu Jan 24 10:50:20 2002 @@ -0,0 +1,1153 @@ +/* + * SA1111 PS/2 keyboard/mouse driver + * + * 2000 by VASARA RESEARCH INC. + * + * Changelog: + * Jun.xx,2000: Kunihiko IMAI + * Port to 2.4.0test1-ac19-rmk1-np1 + * Apr.17,2000: Takafumi Kawana + * Internal Release for XP860 + * + * + * This driver is based on linux/drivers/char/pc_keyb.c + * Original declaration follows: + + * + * linux/drivers/char/pc_keyb.c + * + * Separation of the PC low-level part by Geert Uytterhoeven, May 1997 + * See keyboard.c for the whole history. + * + * Major cleanup by Martin Mares, May 1997 + * + * Combined the keyboard and PS/2 mouse handling into one file, + * because they share the same hardware. + * Johan Myreen 1998-10-08. + * + * Code fixes to handle mouse ACKs properly. + * C. Scott Ananian 1999-01-29. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* Some configuration switches are present in the include file... */ + +#include +#include +#include + +#define KBD_STAT_RXB (1<<4) +#define KBD_STAT_RXF (1<<5) +#define KBD_STAT_TXB (1<<6) +#define KBD_STAT_TXE (1<<7) +#define KBD_STAT_STP (1<<8) + +#define MSE_STAT_RXB (1<<4) +#define MSE_STAT_RXF (1<<5) +#define MSE_STAT_TXB (1<<6) +#define MSE_STAT_TXE (1<<7) +#define MSE_STAT_STP (1<<8) + +/* Simple translation table for the SysRq keys */ + +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char sa1111_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 + +// static void kbd_write_command_w(int data); +static void kbd_write_output_w(int data); + +spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; +static void handle_kbd_event(void); + +/* used only by send_data - set by keyboard_interrupt */ +static volatile unsigned char reply_expected = 0; +static volatile unsigned char acknowledge = 0; +static volatile unsigned char resend = 0; + + +#if defined CONFIG_PSMOUSE +/* + * PS/2 Auxiliary Device + */ + +static int __init psaux_init(void); + +static struct aux_queue *queue; /* Mouse data buffer. */ +static int aux_count = 0; +/* used when we send commands to the mouse that expect an ACK. */ +static unsigned char mouse_reply_expected = 0; + +#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT) +#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT) + +#define MAX_RETRIES 60 /* some aux operations take long time */ +#endif /* CONFIG_PSMOUSE */ + +/* + * Wait for keyboard controller input buffer to drain. + * + * Don't use 'jiffies' so that we don't depend on + * interrupts.. + * + * Quote from PS/2 System Reference Manual: + * + * "Address hex 0060 and address hex 0064 should be written only when + * the input-buffer-full bit and output-buffer-full bit in the + * Controller Status register are set 0." + */ + +static void kb_wait(void) +{ + unsigned long timeout = KBC_TIMEOUT; + + do { + /* + * "handle_kbd_event()" will handle any incoming events + * while we wait - keypresses or mouse movement. + */ + handle_kbd_event(); + if (KBDSTAT & KBD_STAT_TXE) + return; + mdelay(1); + timeout--; + } + while (timeout); +#ifdef KBD_REPORT_TIMEOUTS + printk(KERN_WARNING "Keyboard timed out[1]\n"); +#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 + +/* for USB 106 keyboard */ +#define E0_YEN 124 +#define E0_BACKSLASH 89 + + +#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, E0_BACKSLASH, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, E0_YEN, 0, 0, 0, 0 /* 0x78-0x7f */ +}; + +int sa1111_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 sa1111_getkeycode(unsigned int scancode) +{ + return + (scancode < SC_LIM || scancode > 255) ? -EINVAL : + (scancode < + 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128]; +} + +static int do_acknowledge(unsigned char scancode) +{ + if (reply_expected) { + /* Unfortunately, we must recognise these codes only if we know they + * are known to be valid (i.e., after sending a command), because there + * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have + * keys with such codes :( + */ + if (scancode == KBD_REPLY_ACK) { + acknowledge = 1; + reply_expected = 0; + return 0; + } else if (scancode == KBD_REPLY_RESEND) { + resend = 1; + reply_expected = 0; + return 0; + } + /* Should not happen... */ +#if 0 + printk(KERN_DEBUG "keyboard reply expected - got %02x\n", + scancode); +#endif + } + return 1; +} + +int +sa1111_translate(unsigned char scancode, unsigned 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) { + /* + * 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; +} + +char sa1111_unexpected_up(unsigned char keycode) +{ + /* unexpected, but this can happen: maybe this was a key release for a + FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ + if (keycode >= SC_LIM || keycode == 85) + return 0; + else + return 0200; +} + +static unsigned char kbd_exists = 1; + +static inline void handle_keyboard_event(unsigned char scancode) +{ +#ifdef CONFIG_VT + kbd_exists = 1; + if (do_acknowledge(scancode)) + handle_scancode(scancode, !(scancode & 0x80)); +#endif + tasklet_schedule(&keyboard_tasklet); +} + +/* + * This reads the keyboard status port, and does the + * appropriate action. + * + * It requires that we hold the keyboard controller + * spinlock. + */ +static void handle_kbd_event(void) +{ + unsigned int status = KBDSTAT; + unsigned int work = 10000; + unsigned char scancode; + + while (status & KBD_STAT_RXF) { + while (status & KBD_STAT_RXF) { + scancode = KBDDATA & 0xff; + if (!(status & KBD_STAT_STP)) + handle_keyboard_event(scancode); + if (!--work) { + printk(KERN_ERR + "pc_keyb: keyboard controller jammed (0x%02X).\n", + status); + return; + } + status = KBDSTAT; + } + work = 10000; + } + + if (status & KBD_STAT_STP) + KBDSTAT = KBD_STAT_STP; +} + +static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + +#ifdef CONFIG_VT + kbd_pt_regs = regs; +#endif + spin_lock_irqsave(&kbd_controller_lock, flags); + handle_kbd_event(); + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} + +/* + * send_data sends a character to the keyboard and waits + * for an acknowledge, possibly retrying if asked to. Returns + * the success status. + * + * Don't use 'jiffies', so that we don't depend on interrupts + */ +static int send_data(unsigned char data) +{ + int retries = 3; + + do { + unsigned long timeout = KBD_TIMEOUT; + + acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */ + resend = 0; + reply_expected = 1; + kbd_write_output_w(data); + for (;;) { + if (acknowledge) + return 1; + if (resend) + break; + mdelay(1); + if (!--timeout) { +#ifdef KBD_REPORT_TIMEOUTS + printk(KERN_WARNING + "keyboard: Timeout - AT keyboard not present?\n"); +#endif + return 0; + } + } + } + while (retries-- > 0); +#ifdef KBD_REPORT_TIMEOUTS + printk(KERN_WARNING + "keyboard: Too many NACKs -- noisy kbd cable?\n"); +#endif + return 0; +} + +void sa1111_leds(unsigned char leds) +{ + if (kbd_exists + && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) { + send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */ + kbd_exists = 0; + } +} + +#define KBD_NO_DATA (-1) /* No data */ +#define KBD_BAD_DATA (-2) /* Parity or other error */ + +static int __init kbd_read_data(void) +{ + int retval = KBD_NO_DATA; + unsigned int status; + + status = KBDSTAT; + if (status & KBD_STAT_RXF) { + unsigned char data = KBDDATA; + + retval = data; + if (status & KBD_STAT_STP) + retval = KBD_BAD_DATA; + } + return retval; +} + +static void __init kbd_clear_input(void) +{ + int maxread = 100; /* Random number */ + + do { + if (kbd_read_data() == KBD_NO_DATA) + break; + } + while (--maxread); +} + +static int __init kbd_wait_for_input(void) +{ + long timeout = KBD_INIT_TIMEOUT; + + do { + int retval = kbd_read_data(); + if (retval >= 0) + return retval; + mdelay(1); + } + while (--timeout); + return -1; +} + +#if 0 +static void kbd_write_command_w(int data) +{ + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + kb_wait(); + kbd_write_command(data); + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} +#endif + +static void kbd_write_output_w(int data) +{ + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + kb_wait(); + KBDDATA = data & 0xff; + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} + +/* + * Test the keyboard interface. We basically check to make sure that + * we can drive each line to the keyboard independently of each other. + */ +static int kbdif_test(void) +{ + int ret = 0; + + KBDCR = KBDCR_ENA | KBDCR_FKC; + udelay(2); + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBD) { + printk("Keyboard interface test failed[1]: %02x\n", + KBDSTAT); + ret = -ENODEV; + } + + KBDCR = KBDCR_ENA; + udelay(2); + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != (KBDSTAT_KBC | KBDSTAT_KBD)) { + printk("Keyboard interface test failed[2]: %02x\n", + KBDSTAT); + ret = -ENODEV; + } + + KBDCR = KBDCR_ENA | KBDCR_FKD; + udelay(2); + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBC) { + printk("Keyboard interface test failed[3]: %02x\n", + KBDSTAT); + ret = -ENODEV; + } + + return ret; +} + +static char *__init initialize_kbd(void) +{ + int status; + + /* + * Test the keyboard interface. + */ + kbdif_test(); + + /* + * Ok, drop the force low bits, and wait a while, + * and clear the stop bit error flag. + */ + KBDCR = KBDCR_ENA; + udelay(4); + KBDSTAT = KBD_STAT_STP; + + /* + * Ok, we're now ready to talk to the keyboard. Reset + * it, just to make sure we're starting in a sane state. + * + * Set up to try again if the keyboard asks for RESEND. + */ + do { + KBDDATA = KBD_CMD_RESET; + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + break; + if (status != KBD_REPLY_RESEND) + return "Keyboard reset failed, no ACK"; + } while (1); + + if (kbd_wait_for_input() != KBD_REPLY_POR) + return "Keyboard reset failed, no POR"; + + /* + * Set keyboard controller mode. During this, the keyboard should be + * in the disabled state. + * + * Set up to try again if the keyboard asks for RESEND. + */ + do { + kbd_write_output_w(KBD_CMD_DISABLE); + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + break; + if (status != KBD_REPLY_RESEND) + return "Disable keyboard: no ACK"; + } while (1); + +#if 0 /*@@@ */ + kbd_write_command_w(KBD_CCMD_WRITE_MODE); + kbd_write_output_w(KBD_MODE_KBD_INT + | KBD_MODE_SYS | KBD_MODE_DISABLE_MOUSE | + KBD_MODE_KCC); + + /* ibm powerpc portables need this to use scan-code set 1 -- Cort */ + kbd_write_command_w(KBD_CCMD_READ_MODE); + if (!(kbd_wait_for_input() & KBD_MODE_KCC)) { + /* + * If the controller does not support conversion, + * Set the keyboard to scan-code set 1. + */ + kbd_write_output_w(0xF0); + kbd_wait_for_input(); + kbd_write_output_w(0x01); + kbd_wait_for_input(); + } +#else + kbd_write_output_w(0xf0); + kbd_wait_for_input(); + kbd_write_output_w(0x01); + kbd_wait_for_input(); +#endif + + + kbd_write_output_w(KBD_CMD_ENABLE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Enable keyboard: no ACK"; + + /* + * Finally, set the typematic rate to maximum. + */ + kbd_write_output_w(KBD_CMD_SET_RATE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Set rate: no ACK"; + kbd_write_output_w(0x00); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Set rate: no ACK"; + + return NULL; +} + +int __init sa1111_kbd_init_hw(void) +{ + char *msg; + int ret; + + if (!request_mem_region(_KBDCR, 512, "keyboard")) + return -EBUSY; + + SKPCR |= SKPCR_PTCLKEN; + KBDCLKDIV = 0; + KBDPRECNT = 127; + + /* Flush any pending input. */ + kbd_clear_input(); + + msg = initialize_kbd(); + if (msg) + printk(KERN_WARNING "initialize_kbd: %s\n", msg); + +#if defined CONFIG_PSMOUSE + psaux_init(); +#endif + + k_setkeycode = sa1111_setkeycode; + k_getkeycode = sa1111_getkeycode; + k_translate = sa1111_translate; + k_unexpected_up = sa1111_unexpected_up; + k_leds = sa1111_leds; +#ifdef CONFIG_MAGIC_SYSRQ + k_sysrq_xlate = sa1111_sysrq_xlate; + k_sysrq_key = 0x54; +#endif + + /* Ok, finally allocate the IRQ, and off we go.. */ + ret = request_irq(IRQ_TPRXINT, keyboard_interrupt, 0, "keyboard", NULL); + if (ret) + release_mem_region(_KBDCR, 512); + + return ret; +} + +#if defined CONFIG_PSMOUSE + +static inline void handle_mouse_event(unsigned char scancode) +{ + if (mouse_reply_expected) { + if (scancode == AUX_ACK) { + mouse_reply_expected--; + return; + } + mouse_reply_expected = 0; + } + + add_mouse_randomness(scancode); + if (aux_count) { + int head = queue->head; + + queue->buf[head] = scancode; + head = (head + 1) & (AUX_BUF_SIZE - 1); + if (head != queue->tail) { + queue->head = head; + if (queue->fasync) + kill_fasync(&queue->fasync, SIGIO, + POLL_IN); + wake_up_interruptible(&queue->proc_list); + } + } +} + +static void handle_mse_event(void) +{ + unsigned int msests = MSESTAT; + unsigned int work = 10000; + unsigned char scancode; + + while (msests & MSE_STAT_RXF) { + while (msests & MSE_STAT_RXF) { + scancode = MSEDATA & 0xff; + if (!(msests & MSE_STAT_STP)) + handle_mouse_event(scancode); + if (!--work) { + printk(KERN_ERR + "pc_keyb: mouse controller jammed (0x%02X).\n", + msests); + return; + /*XXX*/} + msests = MSESTAT; + } + work = 10000; + } +} + +static void ms_wait(void) +{ + unsigned long timeout = KBC_TIMEOUT; + + do { + /* + * "handle_kbd_event()" will handle any incoming events + * while we wait - keypresses or mouse movement. + */ + handle_mse_event(); + if (MSESTAT & MSE_STAT_TXE) + return; + mdelay(1); + timeout--; + } + while (timeout); +#ifdef KBD_REPORT_TIMEOUTS + printk(KERN_WARNING "Mouse timed out[1]\n"); +#endif +} + +static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + handle_mse_event(); + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} + +/* + * Check if this is a dual port controller. + */ +static int __init detect_auxiliary_port(void) +{ + unsigned long flags; + int loops = 10; + int retval = 0; + + /* Check if the BIOS detected a device on the auxiliary port. */ + if (aux_device_present == 0xaa) + return 1; + + spin_lock_irqsave(&kbd_controller_lock, flags); + + /* Put the value 0x5A in the output buffer using the "Write + * Auxiliary Device Output Buffer" command (0xD3). Poll the + * Status Register for a while to see if the value really + * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF + * bit is also set to 1 in the Status Register, we assume this + * controller has an Auxiliary Port (a.k.a. Mouse Port). + */ + // kb_wait(); + // kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF); + + SKPCR |= SKPCR_PMCLKEN; + + MSECLKDIV = 0; + MSEPRECNT = 127; + MSECR = MSECR_ENA; + mdelay(50); + MSEDATA = 0xf4; + mdelay(50); + + do { + unsigned int msests = MSESTAT; + + if (msests & MSE_STAT_RXF) { + do { + msests = MSEDATA; /* dummy read */ + mdelay(50); + msests = MSESTAT; + } + while (msests & MSE_STAT_RXF); + printk(KERN_INFO "Detected PS/2 Mouse Port.\n"); + retval = 1; + break; + } + mdelay(1); + } + while (--loops); + spin_unlock_irqrestore(&kbd_controller_lock, flags); + + return retval; +} + +/* + * Send a byte to the mouse. + */ +static void aux_write_dev(int val) +{ + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + // kb_wait(); + // kbd_write_command(KBD_CCMD_WRITE_MOUSE); + ms_wait(); + MSEDATA = val; + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} + +/* + * Send a byte to the mouse & handle returned ack + */ +static void aux_write_ack(int val) +{ + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + // kb_wait(); + // kbd_write_command(KBD_CCMD_WRITE_MOUSE); + ms_wait(); + MSEDATA = val; + /* we expect an ACK in response. */ + mouse_reply_expected++; + ms_wait(); + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} + +static unsigned char get_from_queue(void) +{ + unsigned char result; + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + result = queue->buf[queue->tail]; + queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE - 1); + spin_unlock_irqrestore(&kbd_controller_lock, flags); + return result; +} + + +static inline int queue_empty(void) +{ + return queue->head == queue->tail; +} + +static int fasync_aux(int fd, struct file *filp, int on) +{ + int retval; + + retval = fasync_helper(fd, filp, on, &queue->fasync); + if (retval < 0) + return retval; + return 0; +} + + +/* + * Random magic cookie for the aux device + */ +#define AUX_DEV ((void *)queue) + +static int release_aux(struct inode *inode, struct file *file) +{ + fasync_aux(-1, file, 0); + if (--aux_count) + return 0; + // kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */ + // kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE); + aux_write_ack(AUX_DISABLE_DEV); /* Disable aux device */ + MSECR &= ~MSECR_ENA; + free_irq(IRQ_MSRXINT, AUX_DEV); + return 0; +} + +/* + * Install interrupt handler. + * Enable auxiliary device. + */ + +static int open_aux(struct inode *inode, struct file *file) +{ + if (aux_count++) { + return 0; + } + queue->head = queue->tail = 0; /* Flush input queue */ + /* Don't enable the mouse controller until we've registered IRQ handler */ + if (request_irq(IRQ_MSRXINT, mouse_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) { + aux_count--; + return -EBUSY; + } + MSECLKDIV = 0; + MSEPRECNT = 127; + MSECR &= ~MSECR_ENA; + mdelay(50); + MSECR = MSECR_ENA; + mdelay(50); + MSEDATA = 0xf4; + mdelay(50); + if (MSESTAT & 0x0100) { + MSESTAT = 0x0100; /* clear IRQ status */ + } +/* kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); *//* Enable the + auxiliary port on + controller. */ + aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ + // kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */ + + // send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */ + + return 0; +} + +/* + * Put bytes from input queue to buffer. + */ + +static ssize_t +read_aux(struct file *file, char *buffer, size_t count, loff_t * ppos) +{ + DECLARE_WAITQUEUE(wait, current); + ssize_t i = count; + unsigned char c; + + if (queue_empty()) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + add_wait_queue(&queue->proc_list, &wait); + repeat: + set_current_state(TASK_INTERRUPTIBLE); + if (queue_empty() && !signal_pending(current)) { + schedule(); + goto repeat; + } + current->state = TASK_RUNNING; + remove_wait_queue(&queue->proc_list, &wait); + } + while (i > 0 && !queue_empty()) { + c = get_from_queue(); + put_user(c, buffer++); + i--; + } + if (count - i) { + file->f_dentry->d_inode->i_atime = CURRENT_TIME; + return count - i; + } + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +/* + * Write to the aux device. + */ + +static ssize_t +write_aux(struct file *file, const char *buffer, size_t count, + loff_t * ppos) +{ + ssize_t retval = 0; + + if (count) { + ssize_t written = 0; + + if (count > 32) + count = 32; /* Limit to 32 bytes. */ + do { + char c; + get_user(c, buffer++); + aux_write_dev(c); + written++; + } + while (--count); + retval = -EIO; + if (written) { + retval = written; + file->f_dentry->d_inode->i_mtime = CURRENT_TIME; + } + } + + return retval; +} + +static unsigned int aux_poll(struct file *file, poll_table * wait) +{ + poll_wait(file, &queue->proc_list, wait); + if (!queue_empty()) + return POLLIN | POLLRDNORM; + return 0; +} + +struct file_operations psaux_fops = { + read: read_aux, + write: write_aux, + poll: aux_poll, + open: open_aux, + release: release_aux, + fasync: fasync_aux, +}; + +/* + * Initialize driver. + */ +static struct miscdevice psaux_mouse = { + PSMOUSE_MINOR, "psaux", &psaux_fops +}; + + +static int __init psaux_init(void) +{ + int ret; + + if (!request_mem_region(_MSECR, 512, "psaux")) + return -EBUSY; + + if (!detect_auxiliary_port()) { + ret = -EIO; + goto out; + } + + misc_register(&psaux_mouse); + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); + memset(queue, 0, sizeof(*queue)); + queue->head = queue->tail = 0; + init_waitqueue_head(&queue->proc_list); + +#ifdef CONFIG_PSMOUSE + aux_write_ack(AUX_SET_SAMPLE); + aux_write_ack(100); /* 100 samples/sec */ + aux_write_ack(AUX_SET_RES); + aux_write_ack(3); /* 8 counts per mm */ + aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */ +#endif + ret = 0; + + out: + if (ret) + release_mem_region(_MSECR, 512); + return ret; +} + +#endif /* CONFIG_PSMOUSE */ diff -urN orig/drivers/char/serial.c linux/drivers/char/serial.c --- orig/drivers/char/serial.c Tue Jun 24 13:58:18 2003 +++ linux/drivers/char/serial.c Tue Jun 24 11:17:37 2003 @@ -4512,6 +4512,14 @@ } /* + * If there is exactly one port of 8 bytes, use it. + */ + if (num_port == 1 && pci_resource_len(dev, first_port) == 8) { + board->flags = first_port; + return 0; + } + + /* * If there is 1 or 0 iomem regions, and exactly one port, use * it. */ diff -urN orig/drivers/char/serial_21285.c linux/drivers/char/serial_21285.c --- orig/drivers/char/serial_21285.c Mon Aug 5 13:30:47 2002 +++ linux/drivers/char/serial_21285.c Thu Jan 1 01:00:00 1970 @@ -1,498 +0,0 @@ -/* - * linux/drivers/char/serial_21285.c - * - * Driver for the serial port on the 21285 StrongArm-110 core logic chip. - * - * Based on drivers/char/serial.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define BAUD_BASE (mem_fclk_21285/64) - -#define SERIAL_21285_NAME "ttyFB" -#define SERIAL_21285_MAJOR 204 -#define SERIAL_21285_MINOR 4 - -#define SERIAL_21285_AUXNAME "cuafb" -#define SERIAL_21285_AUXMAJOR 205 -#define SERIAL_21285_AUXMINOR 4 - -static struct tty_driver rs285_driver, callout_driver; -static int rs285_refcount; -static struct tty_struct *rs285_table[1]; - -static struct termios *rs285_termios[1]; -static struct termios *rs285_termios_locked[1]; - -static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char; -static struct tty_struct *rs285_tty; -static int rs285_use_count; - -static int rs285_write_room(struct tty_struct *tty) -{ - return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1); -} - -static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs) -{ - if (!rs285_tty) { - disable_irq(IRQ_CONRX); - return; - } - while (!(*CSR_UARTFLG & 0x10)) { - int ch, flag; - ch = *CSR_UARTDR; - flag = *CSR_RXSTAT; - if (flag & 4) - tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN); - if (flag & 2) - flag = TTY_PARITY; - else if (flag & 1) - flag = TTY_FRAME; - tty_insert_flip_char(rs285_tty, ch, flag); - } - tty_flip_buffer_push(rs285_tty); -} - -static void rs285_send_xchar(struct tty_struct *tty, char ch) -{ - x_char = ch; - enable_irq(IRQ_CONTX); -} - -static void rs285_throttle(struct tty_struct *tty) -{ - if (I_IXOFF(tty)) - rs285_send_xchar(tty, STOP_CHAR(tty)); -} - -static void rs285_unthrottle(struct tty_struct *tty) -{ - if (I_IXOFF(tty)) { - if (x_char) - x_char = 0; - else - rs285_send_xchar(tty, START_CHAR(tty)); - } -} - -static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs) -{ - while (!(*CSR_UARTFLG & 0x20)) { - if (x_char) { - *CSR_UARTDR = x_char; - x_char = 0; - continue; - } - if (putp == getp) { - disable_irq(IRQ_CONTX); - break; - } - *CSR_UARTDR = *getp; - if (++getp >= wbuf + sizeof(wbuf)) - getp = wbuf; - } - if (rs285_tty) - wake_up_interruptible(&rs285_tty->write_wait); -} - -static inline int rs285_xmit(int ch) -{ - if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf)) - return 0; - *putp = ch; - if (++putp >= wbuf + sizeof(wbuf)) - putp = wbuf; - enable_irq(IRQ_CONTX); - return 1; -} - -static int rs285_write(struct tty_struct *tty, int from_user, - const u_char * buf, int count) -{ - int i; - - if (from_user && verify_area(VERIFY_READ, buf, count)) - return -EINVAL; - - for (i = 0; i < count; i++) { - char ch; - if (from_user) - __get_user(ch, buf + i); - else - ch = buf[i]; - if (!rs285_xmit(ch)) - break; - } - return i; -} - -static void rs285_put_char(struct tty_struct *tty, u_char ch) -{ - rs285_xmit(ch); -} - -static int rs285_chars_in_buffer(struct tty_struct *tty) -{ - return sizeof(wbuf) - rs285_write_room(tty); -} - -static void rs285_flush_buffer(struct tty_struct *tty) -{ - disable_irq(IRQ_CONTX); - putp = getp = wbuf; - if (x_char) - enable_irq(IRQ_CONTX); -} - -static inline void rs285_set_cflag(int cflag) -{ - int h_lcr, baud, quot; - - switch (cflag & CSIZE) { - case CS5: - h_lcr = 0x10; - break; - case CS6: - h_lcr = 0x30; - break; - case CS7: - h_lcr = 0x50; - break; - default: /* CS8 */ - h_lcr = 0x70; - break; - - } - if (cflag & CSTOPB) - h_lcr |= 0x08; - if (cflag & PARENB) - h_lcr |= 0x02; - if (!(cflag & PARODD)) - h_lcr |= 0x04; - - switch (cflag & CBAUD) { - case B200: baud = 200; break; - case B300: baud = 300; break; - case B1200: baud = 1200; break; - case B1800: baud = 1800; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - default: - case B9600: baud = 9600; break; - case B19200: baud = 19200; break; - case B38400: baud = 38400; break; - case B57600: baud = 57600; break; - case B115200: baud = 115200; break; - } - - /* - * The documented expression for selecting the divisor is: - * BAUD_BASE / baud - 1 - * However, typically BAUD_BASE is not divisible by baud, so - * we want to select the divisor that gives us the minimum - * error. Therefore, we want: - * int(BAUD_BASE / baud - 0.5) -> - * int(BAUD_BASE / baud - (baud >> 1) / baud) -> - * int((BAUD_BASE - (baud >> 1)) / baud) - */ - quot = (BAUD_BASE - (baud >> 1)) / baud; - - *CSR_UARTCON = 0; - *CSR_L_UBRLCR = quot & 0xff; - *CSR_M_UBRLCR = (quot >> 8) & 0x0f; - *CSR_H_UBRLCR = h_lcr; - *CSR_UARTCON = 1; -} - -static void rs285_set_termios(struct tty_struct *tty, struct termios *old) -{ - if (old && tty->termios->c_cflag == old->c_cflag) - return; - rs285_set_cflag(tty->termios->c_cflag); -} - - -static void rs285_stop(struct tty_struct *tty) -{ - disable_irq(IRQ_CONTX); -} - -static void rs285_start(struct tty_struct *tty) -{ - enable_irq(IRQ_CONTX); -} - -static void rs285_wait_until_sent(struct tty_struct *tty, int timeout) -{ - int orig_jiffies = jiffies; - while (*CSR_UARTFLG & 8) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - current->state = TASK_RUNNING; -} - -static int rs285_open(struct tty_struct *tty, struct file *filp) -{ - int line; - - MOD_INC_USE_COUNT; - line = MINOR(tty->device) - tty->driver.minor_start; - if (line) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - - tty->driver_data = NULL; - if (!rs285_tty) - rs285_tty = tty; - - enable_irq(IRQ_CONRX); - rs285_use_count++; - return 0; -} - -static void rs285_close(struct tty_struct *tty, struct file *filp) -{ - if (!--rs285_use_count) { - rs285_wait_until_sent(tty, 0); - disable_irq(IRQ_CONRX); - disable_irq(IRQ_CONTX); - rs285_tty = NULL; - } - MOD_DEC_USE_COUNT; -} - -static int __init rs285_init(void) -{ - int baud = B9600; - - if (machine_is_personal_server()) - baud = B57600; - - rs285_driver.magic = TTY_DRIVER_MAGIC; - rs285_driver.driver_name = "serial_21285"; - rs285_driver.name = SERIAL_21285_NAME; - rs285_driver.major = SERIAL_21285_MAJOR; - rs285_driver.minor_start = SERIAL_21285_MINOR; - rs285_driver.num = 1; - rs285_driver.type = TTY_DRIVER_TYPE_SERIAL; - rs285_driver.subtype = SERIAL_TYPE_NORMAL; - rs285_driver.init_termios = tty_std_termios; - rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL; - rs285_driver.flags = TTY_DRIVER_REAL_RAW; - rs285_driver.refcount = &rs285_refcount; - rs285_driver.table = rs285_table; - rs285_driver.termios = rs285_termios; - rs285_driver.termios_locked = rs285_termios_locked; - - rs285_driver.open = rs285_open; - rs285_driver.close = rs285_close; - rs285_driver.write = rs285_write; - rs285_driver.put_char = rs285_put_char; - rs285_driver.write_room = rs285_write_room; - rs285_driver.chars_in_buffer = rs285_chars_in_buffer; - rs285_driver.flush_buffer = rs285_flush_buffer; - rs285_driver.throttle = rs285_throttle; - rs285_driver.unthrottle = rs285_unthrottle; - rs285_driver.send_xchar = rs285_send_xchar; - rs285_driver.set_termios = rs285_set_termios; - rs285_driver.stop = rs285_stop; - rs285_driver.start = rs285_start; - rs285_driver.wait_until_sent = rs285_wait_until_sent; - - callout_driver = rs285_driver; - callout_driver.name = SERIAL_21285_AUXNAME; - callout_driver.major = SERIAL_21285_AUXMAJOR; - callout_driver.subtype = SERIAL_TYPE_CALLOUT; - - if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL)) - panic("Couldn't get rx irq for rs285"); - - if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL)) - panic("Couldn't get tx irq for rs285"); - - if (tty_register_driver(&rs285_driver)) - printk(KERN_ERR "Couldn't register 21285 serial driver\n"); - if (tty_register_driver(&callout_driver)) - printk(KERN_ERR "Couldn't register 21285 callout driver\n"); - - return 0; -} - -static void __exit rs285_fini(void) -{ - unsigned long flags; - int ret; - - save_flags(flags); - cli(); - ret = tty_unregister_driver(&callout_driver); - if (ret) - printk(KERN_ERR "Unable to unregister 21285 callout driver " - "(%d)\n", ret); - ret = tty_unregister_driver(&rs285_driver); - if (ret) - printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n", - ret); - free_irq(IRQ_CONTX, NULL); - free_irq(IRQ_CONRX, NULL); - restore_flags(flags); -} - -module_init(rs285_init); -module_exit(rs285_fini); - -#ifdef CONFIG_SERIAL_21285_CONSOLE -/************** console driver *****************/ - -static void rs285_console_write(struct console *co, const char *s, u_int count) -{ - int i; - - disable_irq(IRQ_CONTX); - for (i = 0; i < count; i++) { - while (*CSR_UARTFLG & 0x20); - *CSR_UARTDR = s[i]; - if (s[i] == '\n') { - while (*CSR_UARTFLG & 0x20); - *CSR_UARTDR = '\r'; - } - } - enable_irq(IRQ_CONTX); -} - -static kdev_t rs285_console_device(struct console *c) -{ - return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR); -} - -static int __init rs285_console_setup(struct console *co, char *options) -{ - int baud = 9600; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - - if (machine_is_personal_server()) - baud = 57600; - - if (options) { - char *s = options; - baud = simple_strtoul(options, NULL, 10); - while (*s >= '0' && *s <= '9') - s++; - if (*s) - parity = *s++; - if (*s) - bits = *s - '0'; - } - - /* - * Now construct a cflag setting. - */ - switch (baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 9600: - cflag |= B9600; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - default: - cflag |= B9600; - break; - } - switch (bits) { - case 7: - cflag |= CS7; - break; - default: - cflag |= CS8; - break; - } - switch (parity) { - case 'o': - case 'O': - cflag |= PARODD; - break; - case 'e': - case 'E': - cflag |= PARENB; - break; - } - co->cflag = cflag; - rs285_set_cflag(cflag); - rs285_console_write(NULL, "\e[2J\e[Hboot ", 12); - if (options) - rs285_console_write(NULL, options, strlen(options)); - else - rs285_console_write(NULL, "no options", 10); - rs285_console_write(NULL, "\n", 1); - - return 0; -} - -static struct console rs285_cons = -{ - name: SERIAL_21285_NAME, - write: rs285_console_write, - device: rs285_console_device, - setup: rs285_console_setup, - flags: CON_PRINTBUFFER, - index: -1, -}; - -void __init rs285_console_init(void) -{ - register_console(&rs285_cons); -} - -#endif /* CONFIG_SERIAL_21285_CONSOLE */ - -MODULE_LICENSE("GPL"); -EXPORT_NO_SYMBOLS; diff -urN orig/drivers/char/serial_amba.c linux/drivers/char/serial_amba.c --- orig/drivers/char/serial_amba.c Mon Aug 5 13:30:47 2002 +++ linux/drivers/char/serial_amba.c Thu Jan 1 01:00:00 1970 @@ -1,2015 +0,0 @@ -/* - * linux/drivers/char/serial_amba.c - * - * Driver for AMBA serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * - * Copyright 1999 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 - * - * - * This is a generic driver for ARM AMBA-type serial ports. They - * have a lot of 16550-like features, but are not register compatable. - * Note that although they do have CTS, DCD and DSR inputs, they do - * not have an RI input, nor do they have DTR or RTS outputs. If - * required, these have to be supplied via some other means (eg, GPIO) - * and hooked into this driver. - * - * This could very easily become a generic serial driver for dumb UARTs - * (eg, {82,16x}50, 21285, SA1100). - */ - -#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 - -#include - -#define SERIAL_AMBA_NAME "ttyAM" -#define SERIAL_AMBA_MAJOR 204 -#define SERIAL_AMBA_MINOR 16 -#define SERIAL_AMBA_NR 2 - -#define CALLOUT_AMBA_NAME "cuaam" -#define CALLOUT_AMBA_MAJOR 205 -#define CALLOUT_AMBA_MINOR 16 -#define CALLOUT_AMBA_NR SERIAL_AMBA_NR - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define DEBUG 0 -#define DEBUG_LEDS 0 - -#if DEBUG_LEDS -extern int get_leds(void); -extern int set_leds(int); -#endif - -/* - * Access routines for the AMBA UARTs - */ -#define UART_GET_INT_STATUS(p) IO_READ((p)->uart_base + AMBA_UARTIIR) -#define UART_GET_FR(p) IO_READ((p)->uart_base + AMBA_UARTFR) -#define UART_GET_CHAR(p) IO_READ((p)->uart_base + AMBA_UARTDR) -#define UART_PUT_CHAR(p, c) IO_WRITE((p)->uart_base + AMBA_UARTDR, (c)) -#define UART_GET_RSR(p) IO_READ((p)->uart_base + AMBA_UARTRSR) -#define UART_GET_CR(p) IO_READ((p)->uart_base + AMBA_UARTCR) -#define UART_PUT_CR(p,c) IO_WRITE((p)->uart_base + AMBA_UARTCR, (c)) -#define UART_GET_LCRL(p) IO_READ((p)->uart_base + AMBA_UARTLCR_L) -#define UART_PUT_LCRL(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c)) -#define UART_GET_LCRM(p) IO_READ((p)->uart_base + AMBA_UARTLCR_M) -#define UART_PUT_LCRM(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c)) -#define UART_GET_LCRH(p) IO_READ((p)->uart_base + AMBA_UARTLCR_H) -#define UART_PUT_LCRH(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c)) -#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0) -#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0) -#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0) - -#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE) -#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS) - -/* - * Things needed by tty driver - */ -static struct tty_driver ambanormal_driver, ambacallout_driver; -static int ambauart_refcount; -static struct tty_struct *ambauart_table[SERIAL_AMBA_NR]; -static struct termios *ambauart_termios[SERIAL_AMBA_NR]; -static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR]; - -#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -/* - * Things needed internally to this driver - */ - -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static u_char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); - -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 -#define AMBA_ISR_PASS_LIMIT 256 - -#define EVT_WRITE_WAKEUP 0 - -struct amba_icount { - __u32 cts; - __u32 dsr; - __u32 rng; - __u32 dcd; - __u32 rx; - __u32 tx; - __u32 frame; - __u32 overrun; - __u32 parity; - __u32 brk; - __u32 buf_overrun; -}; - -/* - * Static information about the port - */ -struct amba_port { - unsigned int uart_base; - unsigned int irq; - unsigned int uartclk; - unsigned int fifosize; - unsigned int tiocm_support; - void (*set_mctrl)(struct amba_port *, u_int mctrl); -}; - -/* - * This is the state information which is persistent across opens - */ -struct amba_state { - struct amba_icount icount; - unsigned int line; - unsigned int close_delay; - unsigned int closing_wait; - unsigned int custom_divisor; - unsigned int flags; - struct termios normal_termios; - struct termios callout_termios; - - int count; - struct amba_info *info; -}; - -#define AMBA_XMIT_SIZE 1024 -/* - * This is the state information which is only valid when the port is open. - */ -struct amba_info { - struct amba_port *port; - struct amba_state *state; - struct tty_struct *tty; - unsigned char x_char; - unsigned char old_status; - unsigned char read_status_mask; - unsigned char ignore_status_mask; - struct circ_buf xmit; - unsigned int flags; -#ifdef SUPPORT_SYSRQ - unsigned long sysrq; -#endif - - unsigned int event; - unsigned int timeout; - unsigned int lcr_h; - unsigned int mctrl; - int blocked_open; - pid_t session; - pid_t pgrp; - - struct tasklet_struct tlet; - - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - wait_queue_head_t delta_msr_wait; -}; - -#ifdef CONFIG_SERIAL_AMBA_CONSOLE -static struct console ambauart_cons; -#endif -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios); -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout); - -#if 1 //def CONFIG_SERIAL_INTEGRATOR -static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl) -{ -} - -static struct amba_port amba_ports[SERIAL_AMBA_NR] = { - { - uart_base: IO_ADDRESS(INTEGRATOR_UART0_BASE), - irq: IRQ_UARTINT0, - uartclk: 14745600, - fifosize: 8, - set_mctrl: amba_set_mctrl_null, - }, - { - uart_base: IO_ADDRESS(INTEGRATOR_UART1_BASE), - irq: IRQ_UARTINT1, - uartclk: 14745600, - fifosize: 8, - set_mctrl: amba_set_mctrl_null, - } -}; -#endif - -static struct amba_state amba_state[SERIAL_AMBA_NR]; - -static void ambauart_enable_rx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE; - UART_PUT_CR(info->port, cr); -} - -static void ambauart_disable_rx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE); - UART_PUT_CR(info->port, cr); -} - -static void ambauart_enable_tx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr |= AMBA_UARTCR_TIE; - UART_PUT_CR(info->port, cr); -} - -static void ambauart_disable_tx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr &= ~AMBA_UARTCR_TIE; - UART_PUT_CR(info->port, cr); -} - -static void ambauart_stop(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - save_flags(flags); cli(); - ambauart_disable_tx_interrupt(info); - restore_flags(flags); -} - -static void ambauart_start(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - save_flags(flags); cli(); - if (info->xmit.head != info->xmit.tail - && info->xmit.buf) - ambauart_enable_tx_interrupt(info); - restore_flags(flags); -} - - -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static void ambauart_event(struct amba_info *info, int event) -{ - info->event |= 1 << event; - tasklet_schedule(&info->tlet); -} - -static void -#ifdef SUPPORT_SYSRQ -ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs) -#else -ambauart_rx_chars(struct amba_info *info) -#endif -{ - struct tty_struct *tty = info->tty; - unsigned int status, ch, rsr, flg, ignored = 0; - struct amba_icount *icount = &info->state->icount; - struct amba_port *port = info->port; - - status = UART_GET_FR(port); - while (UART_RX_DATA(status)) { - ch = UART_GET_CHAR(port); - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; - icount->rx++; - - flg = TTY_NORMAL; - - /* - * Note that the error handling code is - * out of the main execution path - */ - rsr = UART_GET_RSR(port); - if (rsr & AMBA_UARTRSR_ANY) - goto handle_error; -#ifdef SUPPORT_SYSRQ - if (info->sysrq) { - if (ch && time_before(jiffies, info->sysrq)) { - handle_sysrq(ch, regs, NULL, NULL); - info->sysrq = 0; - goto ignore_char; - } - info->sysrq = 0; - } -#endif - error_return: - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - ignore_char: - status = UART_GET_FR(port); - } -out: - tty_flip_buffer_push(tty); - return; - -handle_error: - if (rsr & AMBA_UARTRSR_BE) { - rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE); - icount->brk++; - -#ifdef SUPPORT_SYSRQ - if (info->state->line == ambauart_cons.index) { - if (!info->sysrq) { - info->sysrq = jiffies + HZ*5; - goto ignore_char; - } - } -#endif - } else if (rsr & AMBA_UARTRSR_PE) - icount->parity++; - else if (rsr & AMBA_UARTRSR_FE) - icount->frame++; - if (rsr & AMBA_UARTRSR_OE) - icount->overrun++; - - if (rsr & info->ignore_status_mask) { - if (++ignored > 100) - goto out; - goto ignore_char; - } - rsr &= info->read_status_mask; - - if (rsr & AMBA_UARTRSR_BE) - flg = TTY_BREAK; - else if (rsr & AMBA_UARTRSR_PE) - flg = TTY_PARITY; - else if (rsr & AMBA_UARTRSR_FE) - flg = TTY_FRAME; - - if (rsr & AMBA_UARTRSR_OE) { - /* - * CHECK: does overrun affect the current character? - * ASSUMPTION: it does not. - */ - *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 - info->sysrq = 0; -#endif - goto error_return; -} - -static void ambauart_tx_chars(struct amba_info *info) -{ - struct amba_port *port = info->port; - int count; - - if (info->x_char) { - UART_PUT_CHAR(port, info->x_char); - info->state->icount.tx++; - info->x_char = 0; - return; - } - if (info->xmit.head == info->xmit.tail - || info->tty->stopped - || info->tty->hw_stopped) { - ambauart_disable_tx_interrupt(info); - return; - } - - count = port->fifosize; - do { - UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]); - info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1); - info->state->icount.tx++; - if (info->xmit.head == info->xmit.tail) - break; - } while (--count > 0); - - if (CIRC_CNT(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE) < WAKEUP_CHARS) - ambauart_event(info, EVT_WRITE_WAKEUP); - - if (info->xmit.head == info->xmit.tail) { - ambauart_disable_tx_interrupt(info); - } -} - -static void ambauart_modem_status(struct amba_info *info) -{ - unsigned int status, delta; - struct amba_icount *icount = &info->state->icount; - - status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY; - - delta = status ^ info->old_status; - info->old_status = status; - - if (!delta) - return; - - if (delta & AMBA_UARTFR_DCD) { - icount->dcd++; -#ifdef CONFIG_HARD_PPS - if ((info->flags & ASYNC_HARDPPS_CD) && - (status & AMBA_UARTFR_DCD) - hardpps(); -#endif - if (info->flags & ASYNC_CHECK_CD) { - if (status & AMBA_UARTFR_DCD) - wake_up_interruptible(&info->open_wait); - else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_CALLOUT_NOHUP))) { - if (info->tty) - tty_hangup(info->tty); - } - } - } - - if (delta & AMBA_UARTFR_DSR) - icount->dsr++; - - if (delta & AMBA_UARTFR_CTS) { - icount->cts++; - - if (info->flags & ASYNC_CTS_FLOW) { - status &= AMBA_UARTFR_CTS; - - if (info->tty->hw_stopped) { - if (status) { - info->tty->hw_stopped = 0; - ambauart_enable_tx_interrupt(info); - ambauart_event(info, EVT_WRITE_WAKEUP); - } - } else { - if (!status) { - info->tty->hw_stopped = 1; - ambauart_disable_tx_interrupt(info); - } - } - } - } - wake_up_interruptible(&info->delta_msr_wait); - -} - -static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs) -{ - struct amba_info *info = dev_id; - unsigned int status, pass_counter = 0; - -#if DEBUG_LEDS - // tell the world - set_leds(get_leds() | RED_LED); -#endif - - status = UART_GET_INT_STATUS(info->port); - do { - /* - * FIXME: what about clearing the interrupts? - */ - - if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS)) -#ifdef SUPPORT_SYSRQ - ambauart_rx_chars(info, regs); -#else - ambauart_rx_chars(info); -#endif - if (status & AMBA_UARTIIR_TIS) - ambauart_tx_chars(info); - if (status & AMBA_UARTIIR_MIS) - ambauart_modem_status(info); - if (pass_counter++ > AMBA_ISR_PASS_LIMIT) - break; - - status = UART_GET_INT_STATUS(info->port); - } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS)); - -#if DEBUG_LEDS - // tell the world - set_leds(get_leds() & ~RED_LED); -#endif -} - -static void ambauart_tasklet_action(unsigned long data) -{ - struct amba_info *info = (struct amba_info *)data; - struct tty_struct *tty; - - tty = info->tty; - if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event)) - return; - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); -} - -static int ambauart_startup(struct amba_info *info) -{ - unsigned long flags; - unsigned long page; - int retval = 0; - - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - save_flags(flags); cli(); - - if (info->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - - if (info->xmit.buf) - free_page(page); - else - info->xmit.buf = (unsigned char *) page; - - /* - * Allocate the IRQ - */ - retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info); - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - retval = 0; - } - goto errout; - } - - info->mctrl = 0; - if (info->tty->termios->c_cflag & CBAUD) - info->mctrl = TIOCM_RTS | TIOCM_DTR; - info->port->set_mctrl(info->port, info->mctrl); - - /* - * initialise the old status of the modem signals - */ - info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY; - - /* - * Finally, enable interrupts - */ - ambauart_enable_rx_interrupt(info); - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit.head = info->xmit.tail = 0; - - /* - * Set up the tty->alt_speed kludge - */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } - - /* - * and set the speed of the serial port - */ - ambauart_change_speed(info, 0); - - info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); - return 0; - -errout: - restore_flags(flags); - return retval; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void ambauart_shutdown(struct amba_info *info) -{ - unsigned long flags; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - - save_flags(flags); cli(); /* Disable interrupts */ - - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq - * here so the queue might never be woken up - */ - wake_up_interruptible(&info->delta_msr_wait); - - /* - * Free the IRQ - */ - free_irq(info->port->irq, info); - - if (info->xmit.buf) { - unsigned long pg = (unsigned long) info->xmit.buf; - info->xmit.buf = NULL; - free_page(pg); - } - - /* - * disable all interrupts, disable the port - */ - UART_PUT_CR(info->port, 0); - - /* disable break condition and fifos */ - UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) & - ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN)); - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS); - info->port->set_mctrl(info->port, info->mctrl); - - /* kill off our tasklet */ - tasklet_kill(&info->tlet); - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); -} - -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios) -{ - unsigned int lcr_h, baud, quot, cflag, old_cr, bits; - unsigned long flags; - - if (!info->tty || !info->tty->termios) - return; - - cflag = info->tty->termios->c_cflag; - -#if DEBUG - printk("ambauart_set_cflag(0x%x) called\n", cflag); -#endif - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7; break; - case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8; break; - case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9; break; - default: lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8 - } - if (cflag & CSTOPB) { - lcr_h |= AMBA_UARTLCR_H_STP2; - bits ++; - } - if (cflag & PARENB) { - lcr_h |= AMBA_UARTLCR_H_PEN; - bits++; - if (!(cflag & PARODD)) - lcr_h |= AMBA_UARTLCR_H_EPS; - } - if (info->port->fifosize > 1) - lcr_h |= AMBA_UARTLCR_H_FEN; - - do { - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; - - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else - quot = (info->port->uartclk / (16 * baud)) - 1; - - if (!quot && old_termios) { - info->tty->termios->c_cflag &= ~CBAUD; - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); - old_termios = NULL; - } - } while (quot == 0 && old_termios); - - /* As a last resort, if the quotient is zero, default to 9600 bps */ - if (!quot) - quot = (info->port->uartclk / (16 * 9600)) - 1; - - info->timeout = (info->port->fifosize * HZ * bits * quot) / - (info->port->uartclk / 16); - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - if (cflag & CRTSCTS) - info->flags |= ASYNC_CTS_FLOW; - else - info->flags &= ~ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; - - /* - * Set up parity check flag - */ -#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - - info->read_status_mask = AMBA_UARTRSR_OE; - if (I_INPCK(info->tty)) - info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) - info->read_status_mask |= AMBA_UARTRSR_BE; - - /* - * Characters to ignore - */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; - if (I_IGNBRK(info->tty)) { - info->ignore_status_mask |= AMBA_UARTRSR_BE; - /* - * If we're ignoring parity and break indicators, - * ignore overruns to (for real raw support). - */ - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= AMBA_UARTRSR_OE; - } - - /* first, disable everything */ - save_flags(flags); cli(); - old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE; - - if ((info->flags & ASYNC_HARDPPS_CD) || - (cflag & CRTSCTS) || - !(cflag & CLOCAL)) - old_cr |= AMBA_UARTCR_MSIE; - - UART_PUT_CR(info->port, 0); - restore_flags(flags); - - /* Set baud rate */ - UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8)); - UART_PUT_LCRL(info->port, (quot & 0xff)); - - /* - * ----------v----------v----------v----------v----- - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L - * ----------^----------^----------^----------^----- - */ - UART_PUT_LCRH(info->port, lcr_h); - UART_PUT_CR(info->port, old_cr); -} - -static void ambauart_put_char(struct tty_struct *tty, u_char ch) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - if (!tty || !info->xmit.buf) - return; - - save_flags(flags); cli(); - if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) { - info->xmit.buf[info->xmit.head] = ch; - info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1); - } - restore_flags(flags); -} - -static void ambauart_flush_chars(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - if (info->xmit.head == info->xmit.tail - || tty->stopped - || tty->hw_stopped - || !info->xmit.buf) - return; - - save_flags(flags); cli(); - ambauart_enable_tx_interrupt(info); - restore_flags(flags); -} - -static int ambauart_write(struct tty_struct *tty, int from_user, - const u_char * buf, int count) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - int c, ret = 0; - - if (!tty || !info->xmit.buf || !tmp_buf) - return 0; - - save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = (info->xmit.head + c) & - (AMBA_XMIT_SIZE - 1); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = (info->xmit.head + c) & - (AMBA_XMIT_SIZE - 1); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); - } - if (info->xmit.head != info->xmit.tail - && !tty->stopped - && !tty->hw_stopped) - ambauart_enable_tx_interrupt(info); - return ret; -} - -static int ambauart_write_room(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - - return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE); -} - -static int ambauart_chars_in_buffer(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - - return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE); -} - -static void ambauart_flush_buffer(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - -#if DEBUG - printk("ambauart_flush_buffer(%d) called\n", - MINOR(tty->device) - tty->driver.minor_start); -#endif - save_flags(flags); cli(); - info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void ambauart_send_xchar(struct tty_struct *tty, char ch) -{ - struct amba_info *info = tty->driver_data; - - info->x_char = ch; - if (ch) - ambauart_enable_tx_interrupt(info); -} - -static void ambauart_throttle(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - if (I_IXOFF(tty)) - ambauart_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) { - save_flags(flags); cli(); - info->mctrl &= ~TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } -} - -static void ambauart_unthrottle(struct tty_struct *tty) -{ - struct amba_info *info = (struct amba_info *) tty->driver_data; - unsigned long flags; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - ambauart_send_xchar(tty, START_CHAR(tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) { - save_flags(flags); cli(); - info->mctrl |= TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } -} - -static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo) -{ - struct amba_state *state = info->state; - struct amba_port *port = info->port; - struct serial_struct tmp; - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = 0; - tmp.line = state->line; - tmp.port = port->uart_base; - if (HIGH_BITS_OFFSET) - tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET; - tmp.irq = port->irq; - tmp.flags = 0; - tmp.xmit_fifo_size = port->fifosize; - tmp.baud_base = port->uartclk / 16; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int set_serial_info(struct amba_info *info, - struct serial_struct *newinfo) -{ - struct serial_struct new_serial; - struct amba_state *state, old_state; - struct amba_port *port; - unsigned long new_port; - unsigned int i, change_irq, change_port; - int retval = 0; - - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) - return -EFAULT; - - state = info->state; - old_state = *state; - port = info->port; - - new_port = new_serial.port; - if (HIGH_BITS_OFFSET) - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; - - change_irq = new_serial.irq != port->irq; - change_port = new_port != port->uart_base; - - if (!capable(CAP_SYS_ADMIN)) { - if (change_irq || change_port || - (new_serial.baud_base != port->uartclk / 16) || - (new_serial.close_delay != state->close_delay) || - (new_serial.xmit_fifo_size != port->fifosize) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (state->flags & ~ASYNC_USR_MASK))) - return -EPERM; - state->flags = ((state->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - state->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || - (new_serial.baud_base < 9600)) - return -EINVAL; - - if (new_serial.type && change_port) { - for (i = 0; i < SERIAL_AMBA_NR; i++) - if ((port != amba_ports + i) && - amba_ports[i].uart_base != new_port) - return -EADDRINUSE; - } - - if ((change_port || change_irq) && (state->count > 1)) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - port->uartclk = new_serial.baud_base * 16; - state->flags = ((state->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | - (info->flags & ASYNC_INTERNAL_FLAGS)); - state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ / 100; - state->closing_wait = new_serial.closing_wait * HZ / 100; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - port->fifosize = new_serial.xmit_fifo_size; - - if (change_port || change_irq) { - /* - * We need to shutdown the serial port at the old - * port/irq combination. - */ - ambauart_shutdown(info); - port->irq = new_serial.irq; - port->uart_base = new_port; - } - -check_and_exit: - if (!port->uart_base) - return 0; - if (info->flags & ASYNC_INITIALIZED) { - if ((old_state.flags & ASYNC_SPD_MASK) != - (state->flags & ASYNC_SPD_MASK) || - (old_state.custom_divisor != state->custom_divisor)) { - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - ambauart_change_speed(info, NULL); - } - } else - retval = ambauart_startup(info); - return retval; -} - - -/* - * get_lsr_info - get line status register info - */ -static int get_lsr_info(struct amba_info *info, unsigned int *value) -{ - unsigned int result, status; - unsigned long flags; - - save_flags(flags); cli(); - status = UART_GET_FR(info->port); - restore_flags(flags); - result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0; - - /* - * If we're about to load something into the transmit - * register, we'll pretend the transmitter isn't empty to - * avoid a race condition (depending on when the transmit - * interrupt happens). - */ - if (info->x_char || - ((CIRC_CNT(info->xmit.head, info->xmit.tail, - AMBA_XMIT_SIZE) > 0) && - !info->tty->stopped && !info->tty->hw_stopped)) - result &= TIOCSER_TEMT; - - return put_user(result, value); -} - -static int get_modem_info(struct amba_info *info, unsigned int *value) -{ - unsigned int result = info->mctrl; - unsigned int status; - - status = UART_GET_FR(info->port); - if (status & AMBA_UARTFR_DCD) - result |= TIOCM_CAR; - if (status & AMBA_UARTFR_DSR) - result |= TIOCM_DSR; - if (status & AMBA_UARTFR_CTS) - result |= TIOCM_CTS; - - return put_user(result, value); -} - -static int set_modem_info(struct amba_info *info, unsigned int cmd, - unsigned int *value) -{ - unsigned int arg, old; - unsigned long flags; - - if (get_user(arg, value)) - return -EFAULT; - - old = info->mctrl; - switch (cmd) { - case TIOCMBIS: - info->mctrl |= arg; - break; - - case TIOCMBIC: - info->mctrl &= ~arg; - break; - - case TIOCMSET: - info->mctrl = arg; - break; - - default: - return -EINVAL; - } - save_flags(flags); cli(); - if (old != info->mctrl) - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - return 0; -} - -static void ambauart_break_ctl(struct tty_struct *tty, int break_state) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - unsigned int lcr_h; - - save_flags(flags); cli(); - lcr_h = UART_GET_LCRH(info->port); - if (break_state == -1) - lcr_h |= AMBA_UARTLCR_H_BRK; - else - lcr_h &= ~AMBA_UARTLCR_H_BRK; - UART_PUT_LCRH(info->port, lcr_h); - restore_flags(flags); -} - -static int ambauart_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct amba_info *info = tty->driver_data; - struct amba_icount cprev, cnow; - struct serial_icounter_struct icount; - unsigned long flags; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *)arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *)arg); - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *)arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *)arg); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *)arg); - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - save_flags(flags); cli(); - /* note the counters on entry */ - cprev = info->state->icount; - /* Force modem status interrupts on */ - UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE); - restore_flags(flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - save_flags(flags); cli(); - cnow = info->state->icount; /* atomic copy */ - restore_flags(flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - save_flags(flags); cli(); - cnow = info->state->icount; - restore_flags(flags); - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - return copy_to_user((void *)arg, &icount, sizeof(icount)) - ? -EFAULT : 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - unsigned int cflag = tty->termios->c_cflag; - - if ((cflag ^ old_termios->c_cflag) == 0 && - RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) - return; - - ambauart_change_speed(info, old_termios); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { - save_flags(flags); cli(); - info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR); - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { - save_flags(flags); cli(); - info->mctrl |= TIOCM_DTR; - if (!(cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) - info->mctrl |= TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(cflag & CRTSCTS)) { - tty->hw_stopped = 0; - ambauart_start(tty); - } - -#if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); -#endif -} - -static void ambauart_close(struct tty_struct *tty, struct file *filp) -{ - struct amba_info *info = tty->driver_data; - struct amba_state *state; - unsigned long flags; - - if (!info) - return; - - state = info->state; - -#if DEBUG - printk("ambauart_close() called\n"); -#endif - - save_flags(flags); cli(); - - if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("ambauart_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - printk("rs_close: bad serial port count for %s%d: %d\n", - tty->driver.name, info->state->line, state->count); - state->count = 0; - } - if (state->count) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - info->flags |= ASYNC_CLOSING; - restore_flags(flags); - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & ASYNC_NORMAL_ACTIVE) - info->state->normal_termios = *tty->termios; - if (info->flags & ASYNC_CALLOUT_ACTIVE) - info->state->callout_termios = *tty->termios; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->state->closing_wait); - /* - * At this point, we stop accepting input. To do this, we - * disable the receive line status interrupts. - */ - if (info->flags & ASYNC_INITIALIZED) { - ambauart_disable_rx_interrupt(info); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - ambauart_wait_until_sent(tty, info->timeout); - } - ambauart_shutdown(info); - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - info->event = 0; - info->tty = NULL; - if (info->blocked_open) { - if (info->state->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->state->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| - ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; -} - -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct amba_info *info = (struct amba_info *) tty->driver_data; - unsigned long char_time, expire; - unsigned int status; - - if (info->port->fifosize == 0) - return; - - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->port->fifosize; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout && timeout < char_time) - char_time = timeout; - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2 * info->timeout) - timeout = 2 * info->timeout; - - expire = jiffies + timeout; -#if DEBUG - printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n", - MINOR(tty->device) - tty->driver.minor_start, jiffies, - expire); -#endif - while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, expire)) - break; - status = UART_GET_FR(info->port); - } - set_current_state(TASK_RUNNING); -} - -static void ambauart_hangup(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - struct amba_state *state = info->state; - - ambauart_flush_buffer(tty); - if (info->flags & ASYNC_CLOSING) - return; - ambauart_shutdown(info); - info->event = 0; - state->count = 0; - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); - info->tty = NULL; - wake_up_interruptible(&info->open_wait); -} - -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct amba_info *info) -{ - DECLARE_WAITQUEUE(wait, current); - struct amba_state *state = info->state; - unsigned long flags; - int do_clocal = 0, extra_count = 0, retval; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - return (info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS; - } - - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { - if (info->flags & ASYNC_NORMAL_ACTIVE) - return -EBUSY; - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_SESSION_LOCKOUT) && - (info->session != current->session)) - return -EBUSY; - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_PGRP_LOCKOUT) && - (info->pgrp != current->pgrp)) - return -EBUSY; - info->flags |= ASYNC_CALLOUT_ACTIVE; - return 0; - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - if (info->flags & ASYNC_CALLOUT_ACTIVE) - return -EBUSY; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (info->flags & ASYNC_CALLOUT_ACTIVE) { - if (state->normal_termios.c_cflag & CLOCAL) - do_clocal = 1; - } else { - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - } - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, state->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); - save_flags(flags); cli(); - if (!tty_hung_up_p(filp)) { - extra_count = 1; - state->count--; - } - restore_flags(flags); - info->blocked_open++; - while (1) { - save_flags(flags); cli(); - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && - (tty->termios->c_cflag & CBAUD)) { - info->mctrl = TIOCM_DTR | TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - } - restore_flags(flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && - !(info->flags & ASYNC_CLOSING) && - (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD))) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); - if (extra_count) - state->count++; - info->blocked_open--; - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -static struct amba_info *ambauart_get(int line) -{ - struct amba_info *info; - struct amba_state *state = amba_state + line; - - state->count++; - if (state->info) - return state->info; - info = kmalloc(sizeof(struct amba_info), GFP_KERNEL); - if (info) { - memset(info, 0, sizeof(struct amba_info)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); - info->flags = state->flags; - info->state = state; - info->port = amba_ports + line; - tasklet_init(&info->tlet, ambauart_tasklet_action, - (unsigned long)info); - } - if (state->info) { - kfree(info); - return state->info; - } - state->info = info; - return info; -} - -static int ambauart_open(struct tty_struct *tty, struct file *filp) -{ - struct amba_info *info; - int retval, line = MINOR(tty->device) - tty->driver.minor_start; - -#if DEBUG - printk("ambauart_open(%d) called\n", line); -#endif - - // is this a line that we've got? - MOD_INC_USE_COUNT; - if (line >= SERIAL_AMBA_NR) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - - info = ambauart_get(line); - if (!info) - return -ENOMEM; - - tty->driver_data = info; - info->tty = tty; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - /* - * Make sure we have the temporary buffer allocated - */ - if (!tmp_buf) { - unsigned long page = get_zeroed_page(GFP_KERNEL); - if (tmp_buf) - free_page(page); - else if (!page) { - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - tmp_buf = (u_char *)page; - } - - /* - * If the port is in the middle of closing, bail out now. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - MOD_DEC_USE_COUNT; - return -EAGAIN; - } - - /* - * Start up the serial port - */ - retval = ambauart_startup(info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - - if ((info->state->count == 1) && - (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->state->normal_termios; - else - *tty->termios = info->state->callout_termios; - } -#ifdef CONFIG_SERIAL_AMBA_CONSOLE - if (ambauart_cons.cflag && ambauart_cons.index == line) { - tty->termios->c_cflag = ambauart_cons.cflag; - ambauart_cons.cflag = 0; - } -#endif - ambauart_change_speed(info, NULL); - info->session = current->session; - info->pgrp = current->pgrp; - return 0; -} - -int __init ambauart_init(void) -{ - int i; - - ambanormal_driver.magic = TTY_DRIVER_MAGIC; - ambanormal_driver.driver_name = "serial_amba"; - ambanormal_driver.name = SERIAL_AMBA_NAME; - ambanormal_driver.major = SERIAL_AMBA_MAJOR; - ambanormal_driver.minor_start = SERIAL_AMBA_MINOR; - ambanormal_driver.num = SERIAL_AMBA_NR; - ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL; - ambanormal_driver.subtype = SERIAL_TYPE_NORMAL; - ambanormal_driver.init_termios = tty_std_termios; - ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; - ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - ambanormal_driver.refcount = &ambauart_refcount; - ambanormal_driver.table = ambauart_table; - ambanormal_driver.termios = ambauart_termios; - ambanormal_driver.termios_locked = ambauart_termios_locked; - - ambanormal_driver.open = ambauart_open; - ambanormal_driver.close = ambauart_close; - ambanormal_driver.write = ambauart_write; - ambanormal_driver.put_char = ambauart_put_char; - ambanormal_driver.flush_chars = ambauart_flush_chars; - ambanormal_driver.write_room = ambauart_write_room; - ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer; - ambanormal_driver.flush_buffer = ambauart_flush_buffer; - ambanormal_driver.ioctl = ambauart_ioctl; - ambanormal_driver.throttle = ambauart_throttle; - ambanormal_driver.unthrottle = ambauart_unthrottle; - ambanormal_driver.send_xchar = ambauart_send_xchar; - ambanormal_driver.set_termios = ambauart_set_termios; - ambanormal_driver.stop = ambauart_stop; - ambanormal_driver.start = ambauart_start; - ambanormal_driver.hangup = ambauart_hangup; - ambanormal_driver.break_ctl = ambauart_break_ctl; - ambanormal_driver.wait_until_sent = ambauart_wait_until_sent; - ambanormal_driver.read_proc = NULL; - - /* - * The callout device is just like the normal device except for - * the major number and the subtype code. - */ - ambacallout_driver = ambanormal_driver; - ambacallout_driver.name = CALLOUT_AMBA_NAME; - ambacallout_driver.major = CALLOUT_AMBA_MAJOR; - ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT; - ambacallout_driver.read_proc = NULL; - ambacallout_driver.proc_entry = NULL; - - if (tty_register_driver(&ambanormal_driver)) - panic("Couldn't register AMBA serial driver\n"); - if (tty_register_driver(&ambacallout_driver)) - panic("Couldn't register AMBA callout driver\n"); - - for (i = 0; i < SERIAL_AMBA_NR; i++) { - struct amba_state *state = amba_state + i; - state->line = i; - state->close_delay = 5 * HZ / 10; - state->closing_wait = 30 * HZ; - state->callout_termios = ambacallout_driver.init_termios; - state->normal_termios = ambanormal_driver.init_termios; - } - - return 0; -} - -__initcall(ambauart_init); - -#ifdef CONFIG_SERIAL_AMBA_CONSOLE -/************** console driver *****************/ - -/* - * This code is currently never used; console->read is never called. - * Therefore, although we have an implementation, we don't use it. - * FIXME: the "const char *s" should be fixed to "char *s" some day. - * (when the definition in include/linux/console.h is also fixed) - */ -#ifdef used_and_not_const_char_pointer -static int ambauart_console_read(struct console *co, const char *s, u_int count) -{ - struct amba_port *port = &amba_ports[co->index]; - unsigned int status; - char *w; - int c; -#if DEBUG - printk("ambauart_console_read() called\n"); -#endif - - c = 0; - w = s; - while (c < count) { - status = UART_GET_FR(port); - if (UART_RX_DATA(status)) { - *w++ = UART_GET_CHAR(port); - c++; - } else { - // nothing more to get, return - return c; - } - } - // return the count - return c; -} -#endif - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console must be locked when we get here. - */ -static void ambauart_console_write(struct console *co, const char *s, u_int count) -{ - struct amba_port *port = &amba_ports[co->index]; - unsigned int status, old_cr; - int i; - - /* - * First save the CR then disable the interrupts - */ - old_cr = UART_GET_CR(port); - UART_PUT_CR(port, AMBA_UARTCR_UARTEN); - - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, '\r'); - } - } - - /* - * Finally, wait for transmitter to become empty - * and restore the TCR - */ - do { - status = UART_GET_FR(port); - } while (status & AMBA_UARTFR_BUSY); - UART_PUT_CR(port, old_cr); -} - -static kdev_t ambauart_console_device(struct console *c) -{ - return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index); -} - -static int __init ambauart_console_setup(struct console *co, char *options) -{ - struct amba_port *port; - int baud = 38400; - int bits = 8; - int parity = 'n'; - u_int cflag = CREAD | HUPCL | CLOCAL; - u_int lcr_h, quot; - - if (co->index >= SERIAL_AMBA_NR) - co->index = 0; - - port = &amba_ports[co->index]; - - if (options) { - char *s = options; - baud = simple_strtoul(s, NULL, 10); - while (*s >= '0' && *s <= '9') - s++; - if (*s) parity = *s++; - if (*s) bits = *s - '0'; - } - - /* - * Now construct a cflag setting. - */ - switch (baud) { - case 1200: cflag |= B1200; break; - case 2400: cflag |= B2400; break; - case 4800: cflag |= B4800; break; - default: cflag |= B9600; baud = 9600; break; - case 19200: cflag |= B19200; break; - case 38400: cflag |= B38400; break; - case 57600: cflag |= B57600; break; - case 115200: cflag |= B115200; break; - } - switch (bits) { - case 7: cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7; break; - default: cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8; break; - } - switch (parity) { - case 'o': - case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break; - case 'e': - case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN | - AMBA_UARTLCR_H_EPS; break; - } - - co->cflag = cflag; - - if (port->fifosize > 1) - lcr_h |= AMBA_UARTLCR_H_FEN; - - quot = (port->uartclk / (16 * baud)) - 1; - - UART_PUT_LCRL(port, (quot & 0xff)); - UART_PUT_LCRM(port, (quot >> 8)); - UART_PUT_LCRH(port, lcr_h); - - /* we will enable the port as we need it */ - UART_PUT_CR(port, 0); - - return 0; -} - -static struct console ambauart_cons = -{ - name: SERIAL_AMBA_NAME, - write: ambauart_console_write, -#ifdef used_and_not_const_char_pointer - read: ambauart_console_read, -#endif - device: ambauart_console_device, - setup: ambauart_console_setup, - flags: CON_PRINTBUFFER, - index: -1, -}; - -void __init ambauart_console_init(void) -{ - register_console(&ambauart_cons); -} - -#endif /* CONFIG_SERIAL_AMBA_CONSOLE */ - -MODULE_LICENSE("GPL"); -EXPORT_NO_SYMBOLS; diff -urN orig/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- orig/drivers/char/tty_io.c Tue Jun 24 13:58:18 2003 +++ linux/drivers/char/tty_io.c Tue Jun 24 11:17:38 2003 @@ -150,14 +150,14 @@ extern void tty3215_init(void); extern void tub3270_con_init(void); extern void tub3270_init(void); -extern void rs285_console_init(void); -extern void sa1100_rs_console_init(void); +extern void uart_console_init(void); extern void sgi_serial_console_init(void); extern void sci_console_init(void); extern void tx3912_console_init(void); extern void tx3912_rs_init(void); extern void txx927_console_init(void); extern void sb1250_serial_console_init(void); +extern void rs285_console_init(void); #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -2278,18 +2278,12 @@ #ifdef CONFIG_STDIO_CONSOLE stdio_console_init(); #endif -#ifdef CONFIG_SERIAL_21285_CONSOLE - rs285_console_init(); -#endif -#ifdef CONFIG_SERIAL_SA1100_CONSOLE - sa1100_rs_console_init(); +#ifdef CONFIG_SERIAL_CORE_CONSOLE + uart_console_init(); #endif #ifdef CONFIG_ARC_CONSOLE arc_console_init(); #endif -#ifdef CONFIG_SERIAL_AMBA_CONSOLE - ambauart_console_init(); -#endif #ifdef CONFIG_SERIAL_TX3912_CONSOLE tx3912_console_init(); #endif @@ -2299,6 +2293,9 @@ #ifdef CONFIG_SIBYTE_SB1250_DUART_CONSOLE sb1250_serial_console_init(); #endif +#ifdef CONFIG_SERIAL_21285_CONSOLE + rs285_console_init(); +#endif } static struct tty_driver dev_tty_driver, dev_syscons_driver; diff -urN orig/drivers/char/wdt285.c linux/drivers/char/wdt285.c --- orig/drivers/char/wdt285.c Tue Jun 24 13:58:18 2003 +++ linux/drivers/char/wdt285.c Tue Jun 24 11:17:38 2003 @@ -151,7 +151,7 @@ if (get_user(new_margin, (int *)arg)) return -EFAULT; /* Arbitrary, can't find the card's limits */ - if ((new_marg < 0) || (new_margin > 60)) + if ((new_margin < 0) || (new_margin > 60)) return -EINVAL; soft_margin = new_margin; watchdog_ping(); diff -urN orig/drivers/cpufreq/Kconfig linux/drivers/cpufreq/Kconfig --- orig/drivers/cpufreq/Kconfig Thu Jan 1 01:00:00 1970 +++ linux/drivers/cpufreq/Kconfig Sat Feb 22 10:23:47 2003 @@ -0,0 +1,38 @@ +config CPU_FREQ_PROC_INTF + tristate "/proc/cpufreq interface (deprecated)" + depends on CPU_FREQ && PROC_FS + help + This enables the /proc/cpufreq interface for controlling + CPUFreq. Please note that it is recommended to use the sysfs + interface instead (which is built automatically). + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +config CPU_FREQ_GOV_USERSPACE + tristate "'userspace' governor for userspace frequency scaling" + depends on CPU_FREQ + help + Enable this cpufreq governor when you either want to set the + CPU frequency manually or when an userspace programm shall + be able to set the CPU dynamically, like on LART + ( http://www.lart.tudelft.nl/ ) + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say Y. + +config CPU_FREQ_24_API + bool "/proc/sys/cpu/ interface (2.4. / OLD)" + depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE + help + This enables the /proc/sys/cpu/ sysctl interface for controlling + the CPUFreq,"userspace" governor. This is the same interface + as known from the.4.-kernel patches for CPUFreq, and offers + the same functionality as long as "userspace" is the + selected governor for the specified CPU. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. diff -urN orig/drivers/cpufreq/Makefile linux/drivers/cpufreq/Makefile --- orig/drivers/cpufreq/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/cpufreq/Makefile Sat Feb 22 10:23:47 2003 @@ -0,0 +1,4 @@ +#CPUfreq governors and cross-arch helpers +obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o +obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o +obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o diff -urN orig/drivers/cpufreq/freq_table.c linux/drivers/cpufreq/freq_table.c --- orig/drivers/cpufreq/freq_table.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/cpufreq/freq_table.c Fri Mar 7 10:31:56 2003 @@ -0,0 +1,203 @@ +/* + * linux/drivers/cpufreq/freq_table.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski + */ + +#include +#include +#include +#include + +/********************************************************************* + * FREQUENCY TABLE HELPERS * + *********************************************************************/ + +int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table) +{ + unsigned int min_freq = ~0; + unsigned int max_freq = 0; + unsigned int i = 0; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + if (freq < min_freq) + min_freq = freq; + if (freq > max_freq) + max_freq = freq; + } + + policy->min = policy->cpuinfo.min_freq = min_freq; + policy->max = policy->cpuinfo.max_freq = max_freq; + + if (policy->min == ~0) + return -EINVAL; + else + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo); + + +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table) +{ + unsigned int next_larger = ~0; + unsigned int i = 0; + unsigned int count = 0; + + if (!cpu_online(policy->cpu)) + return -EINVAL; + + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + if ((freq >= policy->min) && (freq <= policy->max)) + count++; + else if ((next_larger > freq) && (freq > policy->max)) + next_larger = freq; + } + + if (!count) + policy->max = next_larger; + + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); + + +int cpufreq_frequency_table_target(struct cpufreq_policy *policy, + struct cpufreq_frequency_table *table, + unsigned int target_freq, + unsigned int relation, + unsigned int *index) +{ + struct cpufreq_frequency_table optimal = { .index = ~0, }; + struct cpufreq_frequency_table suboptimal = { .index = ~0, }; + unsigned int i; + + switch (relation) { + case CPUFREQ_RELATION_H: + optimal.frequency = 0; + suboptimal.frequency = ~0; + break; + case CPUFREQ_RELATION_L: + optimal.frequency = ~0; + suboptimal.frequency = 0; + break; + } + + if (!cpu_online(policy->cpu)) + return -EINVAL; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + if ((freq < policy->min) || (freq > policy->max)) + continue; + switch(relation) { + case CPUFREQ_RELATION_H: + if (freq <= target_freq) { + if (freq >= optimal.frequency) { + optimal.frequency = freq; + optimal.index = i; + } + } else { + if (freq <= suboptimal.frequency) { + suboptimal.frequency = freq; + suboptimal.index = i; + } + } + break; + case CPUFREQ_RELATION_L: + if (freq >= target_freq) { + if (freq <= optimal.frequency) { + optimal.frequency = freq; + optimal.index = i; + } + } else { + if (freq >= suboptimal.frequency) { + suboptimal.frequency = freq; + suboptimal.index = i; + } + } + break; + } + } + if (optimal.index > i) { + if (suboptimal.index > i) + return -EINVAL; + *index = suboptimal.index; + } else + *index = optimal.index; + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); + +static struct cpufreq_frequency_table *show_table[NR_CPUS]; +/** + * show_scaling_governor - show the current policy for the specified CPU + */ +static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) +{ + unsigned int i = 0; + unsigned int cpu = policy->cpu; + ssize_t count = 0; + struct cpufreq_frequency_table *table; + + if (!show_table[cpu]) + return -ENODEV; + + table = show_table[cpu]; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + if (table[i].frequency == CPUFREQ_ENTRY_INVALID) + continue; + count += sprintf(&buf[count], "%d ", table[i].frequency); + } + count += sprintf(&buf[count], "\n"); + + return count; + +} + +struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { + .attr = { .name = "scaling_available_frequencies", .mode = 0444 }, + .show = show_available_freqs, +}; +EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); + +/* + * if you use these, you must assure that the frequency table is valid + * all the time between get_attr and put_attr! + */ +void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, + unsigned int cpu) +{ + show_table[cpu] = table; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr); + +void cpufreq_frequency_table_put_attr(unsigned int cpu) +{ + show_table[cpu] = NULL; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); + + +MODULE_AUTHOR ("Dominik Brodowski "); +MODULE_DESCRIPTION ("CPUfreq frequency table helpers"); +MODULE_LICENSE ("GPL"); diff -urN orig/drivers/cpufreq/proc_intf.c linux/drivers/cpufreq/proc_intf.c --- orig/drivers/cpufreq/proc_intf.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/cpufreq/proc_intf.c Thu Feb 20 18:07:31 2003 @@ -0,0 +1,244 @@ +/* + * linux/drivers/cpufreq/proc_intf.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski + */ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * cpufreq_parse_policy - parse a policy string + * @input_string: the string to parse. + * @policy: the policy written inside input_string + * + * This function parses a "policy string" - something the user echo'es into + * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy. + * If there are invalid/missing entries, they are replaced with current + * cpufreq policy. + */ +static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy) +{ + unsigned int min = 0; + unsigned int max = 0; + unsigned int cpu = 0; + char str_governor[16]; + struct cpufreq_policy current_policy; + unsigned int result = -EFAULT; + + if (!policy) + return -EINVAL; + + policy->min = 0; + policy->max = 0; + policy->policy = 0; + policy->cpu = CPUFREQ_ALL_CPUS; + + if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4) + { + policy->min = min; + policy->max = max; + policy->cpu = cpu; + result = 0; + goto scan_policy; + } + if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4) + { + if (!cpufreq_get_policy(¤t_policy, cpu)) { + policy->min = (min * current_policy.cpuinfo.max_freq) / 100; + policy->max = (max * current_policy.cpuinfo.max_freq) / 100; + policy->cpu = cpu; + result = 0; + goto scan_policy; + } + } + + if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3) + { + policy->min = min; + policy->max = max; + result = 0; + goto scan_policy; + } + + if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3) + { + if (!cpufreq_get_policy(¤t_policy, cpu)) { + policy->min = (min * current_policy.cpuinfo.max_freq) / 100; + policy->max = (max * current_policy.cpuinfo.max_freq) / 100; + result = 0; + goto scan_policy; + } + } + + return -EINVAL; + +scan_policy: + result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor); + + return result; +} + +/** + * cpufreq_proc_read - read /proc/cpufreq + * + * This function prints out the current cpufreq policy. + */ +static int cpufreq_proc_read ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + char *p = page; + int len = 0; + struct cpufreq_policy policy; + unsigned int min_pctg = 0; + unsigned int max_pctg = 0; + unsigned int i = 0; + + if (off != 0) + goto end; + + p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n"); + for (i=0;iname); + break; + default: + p += sprintf(p, "INVALID\n"); + break; + } + } +end: + len = (p - page); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len>count) + len = count; + if (len<0) + len = 0; + + return len; +} + + +/** + * cpufreq_proc_write - handles writing into /proc/cpufreq + * + * This function calls the parsing script and then sets the policy + * accordingly. + */ +static int cpufreq_proc_write ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + char proc_string[42] = {'\0'}; + struct cpufreq_policy policy; + unsigned int i = 0; + + + if ((count > sizeof(proc_string) - 1)) + return -EINVAL; + + if (copy_from_user(proc_string, buffer, count)) + return -EFAULT; + + proc_string[count] = '\0'; + + result = cpufreq_parse_policy(proc_string, &policy); + if (result) + return -EFAULT; + + if (policy.cpu == CPUFREQ_ALL_CPUS) + { + for (i=0; iread_proc = cpufreq_proc_read; + entry->write_proc = cpufreq_proc_write; + } + + return 0; +} + + +/** + * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory. + * + * This function removes "cpufreq" from the /proc root directory. + */ +static void __exit cpufreq_proc_exit (void) +{ + remove_proc_entry("cpufreq", &proc_root); + return; +} + +MODULE_AUTHOR ("Dominik Brodowski "); +MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface"); +MODULE_LICENSE ("GPL"); + +module_init(cpufreq_proc_init); +module_exit(cpufreq_proc_exit); diff -urN orig/drivers/cpufreq/userspace.c linux/drivers/cpufreq/userspace.c --- orig/drivers/cpufreq/userspace.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/cpufreq/userspace.c Fri Mar 7 10:30:20 2003 @@ -0,0 +1,591 @@ +/* + * drivers/cpufreq/userspace.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 - 2003 Dominik Brodowski + * + * $Id: userspace.c,v 1.4 2003/03/07 10:30:20 db Exp $ + * + * 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 + +#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \ + .ctl_name = CPU_NR_FREQ_MAX, \ + .data = &cpu_max_freq[cpunr], \ + .procname = "speed-max", \ + .maxlen = sizeof(cpu_max_freq[cpunr]),\ + .mode = 0444, \ + .proc_handler = proc_dointvec, } + +#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \ + .ctl_name = CPU_NR_FREQ_MIN, \ + .data = &cpu_min_freq[cpunr], \ + .procname = "speed-min", \ + .maxlen = sizeof(cpu_min_freq[cpunr]),\ + .mode = 0444, \ + .proc_handler = proc_dointvec, } + +#define CTL_CPU_VARS_SPEED(cpunr) { \ + .ctl_name = CPU_NR_FREQ, \ + .procname = "speed", \ + .mode = 0644, \ + .proc_handler = cpufreq_procctl, \ + .strategy = cpufreq_sysctl, \ + .extra1 = (void*) (cpunr), } + +#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\ + CTL_CPU_VARS_SPEED_MAX(cpunr), \ + CTL_CPU_VARS_SPEED_MIN(cpunr), \ + CTL_CPU_VARS_SPEED(cpunr), \ + { .ctl_name = 0, }, } + +/* the ctl_table entry for each CPU */ +#define CPU_ENUM(s) { \ + .ctl_name = (CPU_NR + s), \ + .procname = #s, \ + .mode = 0555, \ + .child = ctl_cpu_vars_##s } + +/** + * A few values needed by the userspace governor + */ +static unsigned int cpu_max_freq[NR_CPUS]; +static unsigned int cpu_min_freq[NR_CPUS]; +static unsigned int cpu_cur_freq[NR_CPUS]; +static unsigned int cpu_is_managed[NR_CPUS]; +static struct cpufreq_policy current_policy[NR_CPUS]; + +static DECLARE_MUTEX (userspace_sem); + + +/* keep track of frequency transitions */ +static int +userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + + cpu_cur_freq[freq->cpu] = freq->new; + + return 0; +} + +static struct notifier_block userspace_cpufreq_notifier_block = { + .notifier_call = userspace_cpufreq_notifier +}; + + +/** + * cpufreq_set - set the CPU frequency + * @freq: target frequency in kHz + * @cpu: CPU for which the frequency is to be set + * + * Sets the CPU frequency to freq. + */ +int cpufreq_set(unsigned int freq, unsigned int cpu) +{ + int ret = -EINVAL; + + down(&userspace_sem); + if (!cpu_is_managed[cpu]) + goto err; + + if (freq < cpu_min_freq[cpu]) + freq = cpu_min_freq[cpu]; + if (freq > cpu_max_freq[cpu]) + freq = cpu_max_freq[cpu]; + + ret = cpufreq_driver_target(¤t_policy[cpu], freq, + CPUFREQ_RELATION_L); + + err: + up(&userspace_sem); + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_set); + + +/** + * cpufreq_setmax - set the CPU to the maximum frequency + * @cpu - affected cpu; + * + * Sets the CPU frequency to the maximum frequency supported by + * this CPU. + */ +int cpufreq_setmax(unsigned int cpu) +{ + if (!cpu_is_managed[cpu] || !cpu_online(cpu)) + return -EINVAL; + return cpufreq_set(cpu_max_freq[cpu], cpu); +} +EXPORT_SYMBOL_GPL(cpufreq_setmax); + + +/** + * cpufreq_get - get the current CPU frequency (in kHz) + * @cpu: CPU number + * + * Get the CPU current (static) CPU frequency + */ +unsigned int cpufreq_get(unsigned int cpu) +{ + return cpu_cur_freq[cpu]; +} +EXPORT_SYMBOL(cpufreq_get); + + +#ifdef CONFIG_CPU_FREQ_24_API + + +/*********************** cpufreq_sysctl interface ********************/ +static int +cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + char buf[16], *p; + int cpu = (int) ctl->extra1; + int len, left = *lenp; + + if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) { + *lenp = 0; + return 0; + } + + if (write) { + unsigned int freq; + + len = left; + if (left > sizeof(buf)) + left = sizeof(buf); + if (copy_from_user(buf, buffer, left)) + return -EFAULT; + buf[sizeof(buf) - 1] = '\0'; + + freq = simple_strtoul(buf, &p, 0); + cpufreq_set(freq, cpu); + } else { + len = sprintf(buf, "%d\n", cpufreq_get(cpu)); + if (len > left) + len = left; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + } + + *lenp = len; + filp->f_pos += len; + return 0; +} + +static int +cpufreq_sysctl(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + int cpu = (int) table->extra1; + + if (!cpu_online(cpu)) + return -EINVAL; + + if (oldval && oldlenp) { + size_t oldlen; + + if (get_user(oldlen, oldlenp)) + return -EFAULT; + + if (oldlen != sizeof(unsigned int)) + return -EINVAL; + + if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) || + put_user(sizeof(unsigned int), oldlenp)) + return -EFAULT; + } + if (newval && newlen) { + unsigned int freq; + + if (newlen != sizeof(unsigned int)) + return -EINVAL; + + if (get_user(freq, (unsigned int *)newval)) + return -EFAULT; + + cpufreq_set(freq, cpu); + } + return 1; +} + +/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */ +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */ + CTL_TABLE_CPU_VARS(0); +#if NR_CPUS > 1 + CTL_TABLE_CPU_VARS(1); +#endif +#if NR_CPUS > 2 + CTL_TABLE_CPU_VARS(2); +#endif +#if NR_CPUS > 3 + CTL_TABLE_CPU_VARS(3); +#endif +#if NR_CPUS > 4 + CTL_TABLE_CPU_VARS(4); +#endif +#if NR_CPUS > 5 + CTL_TABLE_CPU_VARS(5); +#endif +#if NR_CPUS > 6 + CTL_TABLE_CPU_VARS(6); +#endif +#if NR_CPUS > 7 + CTL_TABLE_CPU_VARS(7); +#endif +#if NR_CPUS > 8 + CTL_TABLE_CPU_VARS(8); +#endif +#if NR_CPUS > 9 + CTL_TABLE_CPU_VARS(9); +#endif +#if NR_CPUS > 10 + CTL_TABLE_CPU_VARS(10); +#endif +#if NR_CPUS > 11 + CTL_TABLE_CPU_VARS(11); +#endif +#if NR_CPUS > 12 + CTL_TABLE_CPU_VARS(12); +#endif +#if NR_CPUS > 13 + CTL_TABLE_CPU_VARS(13); +#endif +#if NR_CPUS > 14 + CTL_TABLE_CPU_VARS(14); +#endif +#if NR_CPUS > 15 + CTL_TABLE_CPU_VARS(15); +#endif +#if NR_CPUS > 16 + CTL_TABLE_CPU_VARS(16); +#endif +#if NR_CPUS > 17 + CTL_TABLE_CPU_VARS(17); +#endif +#if NR_CPUS > 18 + CTL_TABLE_CPU_VARS(18); +#endif +#if NR_CPUS > 19 + CTL_TABLE_CPU_VARS(19); +#endif +#if NR_CPUS > 20 + CTL_TABLE_CPU_VARS(20); +#endif +#if NR_CPUS > 21 + CTL_TABLE_CPU_VARS(21); +#endif +#if NR_CPUS > 22 + CTL_TABLE_CPU_VARS(22); +#endif +#if NR_CPUS > 23 + CTL_TABLE_CPU_VARS(23); +#endif +#if NR_CPUS > 24 + CTL_TABLE_CPU_VARS(24); +#endif +#if NR_CPUS > 25 + CTL_TABLE_CPU_VARS(25); +#endif +#if NR_CPUS > 26 + CTL_TABLE_CPU_VARS(26); +#endif +#if NR_CPUS > 27 + CTL_TABLE_CPU_VARS(27); +#endif +#if NR_CPUS > 28 + CTL_TABLE_CPU_VARS(28); +#endif +#if NR_CPUS > 29 + CTL_TABLE_CPU_VARS(29); +#endif +#if NR_CPUS > 30 + CTL_TABLE_CPU_VARS(30); +#endif +#if NR_CPUS > 31 + CTL_TABLE_CPU_VARS(31); +#endif +#if NR_CPUS > 32 +#error please extend CPU enumeration +#endif + +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */ +static ctl_table ctl_cpu_table[NR_CPUS + 1] = { + CPU_ENUM(0), +#if NR_CPUS > 1 + CPU_ENUM(1), +#endif +#if NR_CPUS > 2 + CPU_ENUM(2), +#endif +#if NR_CPUS > 3 + CPU_ENUM(3), +#endif +#if NR_CPUS > 4 + CPU_ENUM(4), +#endif +#if NR_CPUS > 5 + CPU_ENUM(5), +#endif +#if NR_CPUS > 6 + CPU_ENUM(6), +#endif +#if NR_CPUS > 7 + CPU_ENUM(7), +#endif +#if NR_CPUS > 8 + CPU_ENUM(8), +#endif +#if NR_CPUS > 9 + CPU_ENUM(9), +#endif +#if NR_CPUS > 10 + CPU_ENUM(10), +#endif +#if NR_CPUS > 11 + CPU_ENUM(11), +#endif +#if NR_CPUS > 12 + CPU_ENUM(12), +#endif +#if NR_CPUS > 13 + CPU_ENUM(13), +#endif +#if NR_CPUS > 14 + CPU_ENUM(14), +#endif +#if NR_CPUS > 15 + CPU_ENUM(15), +#endif +#if NR_CPUS > 16 + CPU_ENUM(16), +#endif +#if NR_CPUS > 17 + CPU_ENUM(17), +#endif +#if NR_CPUS > 18 + CPU_ENUM(18), +#endif +#if NR_CPUS > 19 + CPU_ENUM(19), +#endif +#if NR_CPUS > 20 + CPU_ENUM(20), +#endif +#if NR_CPUS > 21 + CPU_ENUM(21), +#endif +#if NR_CPUS > 22 + CPU_ENUM(22), +#endif +#if NR_CPUS > 23 + CPU_ENUM(23), +#endif +#if NR_CPUS > 24 + CPU_ENUM(24), +#endif +#if NR_CPUS > 25 + CPU_ENUM(25), +#endif +#if NR_CPUS > 26 + CPU_ENUM(26), +#endif +#if NR_CPUS > 27 + CPU_ENUM(27), +#endif +#if NR_CPUS > 28 + CPU_ENUM(28), +#endif +#if NR_CPUS > 29 + CPU_ENUM(29), +#endif +#if NR_CPUS > 30 + CPU_ENUM(30), +#endif +#if NR_CPUS > 31 + CPU_ENUM(31), +#endif +#if NR_CPUS > 32 +#error please extend CPU enumeration +#endif + { + .ctl_name = 0, + } +}; + +static ctl_table ctl_cpu[2] = { + { + .ctl_name = CTL_CPU, + .procname = "cpu", + .mode = 0555, + .child = ctl_cpu_table, + }, + { + .ctl_name = 0, + } +}; + +struct ctl_table_header *cpufreq_sysctl_table; + +static inline void cpufreq_sysctl_init(void) +{ + cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0); +} + +static inline void cpufreq_sysctl_exit(void) +{ + unregister_sysctl_table(cpufreq_sysctl_table); +} + +#else +#define cpufreq_sysctl_init() do {} while(0) +#define cpufreq_sysctl_exit() do {} while(0) +#endif /* CONFIG_CPU_FREQ_24API */ + + +/************************** sysfs interface ************************/ +static ssize_t show_speed (struct cpufreq_policy *policy, char *buf) +{ + return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]); +} + +static ssize_t +store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) +{ + unsigned int freq = 0; + unsigned int ret; + + ret = sscanf (buf, "%u", &freq); + if (ret != 1) + return -EINVAL; + + cpufreq_set(freq, policy->cpu); + + return count; +} + +static struct freq_attr freq_attr_scaling_setspeed = { + .attr = { .name = "scaling_setspeed", .mode = 0644 }, + .show = show_speed, + .store = store_speed, +}; + +static int cpufreq_governor_userspace(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int cpu = policy->cpu; + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) || + !policy->cur) + return -EINVAL; + down(&userspace_sem); + cpu_is_managed[cpu] = 1; + cpu_min_freq[cpu] = policy->min; + cpu_max_freq[cpu] = policy->max; + cpu_cur_freq[cpu] = policy->cur; + sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); + memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); + up(&userspace_sem); + break; + case CPUFREQ_GOV_STOP: + down(&userspace_sem); + cpu_is_managed[cpu] = 0; + cpu_min_freq[cpu] = 0; + cpu_max_freq[cpu] = 0; + sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); + up(&userspace_sem); + module_put(THIS_MODULE); + break; + case CPUFREQ_GOV_LIMITS: + down(&userspace_sem); + cpu_min_freq[cpu] = policy->min; + cpu_max_freq[cpu] = policy->max; + if (policy->max < cpu_cur_freq[cpu]) + cpufreq_driver_target(¤t_policy[cpu], policy->max, + CPUFREQ_RELATION_H); + else if (policy->min > cpu_cur_freq[cpu]) + cpufreq_driver_target(¤t_policy[cpu], policy->min, + CPUFREQ_RELATION_L); + memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); + up(&userspace_sem); + break; + } + return 0; +} + +/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because + * of this, cpu_cur_freq[] needs to be set early. + */ +#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100) +extern unsigned int sa11x0_getspeed(void); + +static void cpufreq_sa11x0_compat(void) +{ + cpu_cur_freq[0] = sa11x0_getspeed(); +} +#else +#define cpufreq_sa11x0_compat() do {} while(0) +#endif + + +static struct cpufreq_governor cpufreq_gov_userspace = { + .name = "userspace", + .governor = cpufreq_governor_userspace, + .owner = THIS_MODULE, +}; +EXPORT_SYMBOL(cpufreq_gov_userspace); + +static int already_init = 0; + +int cpufreq_gov_userspace_init(void) +{ + if (!already_init) { + down(&userspace_sem); + cpufreq_sa11x0_compat(); + cpufreq_sysctl_init(); + cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + already_init = 1; + up(&userspace_sem); + } + return cpufreq_register_governor(&cpufreq_gov_userspace); +} +EXPORT_SYMBOL(cpufreq_gov_userspace_init); + + +static void __exit cpufreq_gov_userspace_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_userspace); + cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + cpufreq_sysctl_exit(); +} + + +MODULE_AUTHOR ("Dominik Brodowski , Russell King "); +MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'"); +MODULE_LICENSE ("GPL"); + +module_init(cpufreq_gov_userspace_init); +module_exit(cpufreq_gov_userspace_exit); diff -urN orig/drivers/i2c/Config.in linux/drivers/i2c/Config.in --- orig/drivers/i2c/Config.in Tue Jun 24 13:58:21 2003 +++ linux/drivers/i2c/Config.in Tue Jun 24 12:09:11 2003 @@ -19,6 +19,14 @@ int ' GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13 fi dep_tristate ' NatSemi SCx200 ACCESS.bus' CONFIG_SCx200_ACB $CONFIG_I2C + dep_tristate ' Guide GPIO adapter' CONFIG_I2C_GUIDE $CONFIG_I2C_ALGOBIT + if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then + dep_tristate ' Omaha I2C interface' CONFIG_I2C_OMAHA $CONFIG_I2C + fi + if [ "$CONFIG_ARCH_SA1100" = "y" ]; then + dep_tristate ' Frodo I2C adapter' CONFIG_I2C_FRODO $CONFIG_I2C_ALGOBIT + dep_tristate ' SA1100 I2C GPIO adapter' CONFIG_I2C_BIT_SA1100_GPIO $CONFIG_I2C_ALGOBIT + fi fi dep_tristate 'I2C PCF 8584 interfaces' CONFIG_I2C_ALGOPCF $CONFIG_I2C @@ -49,6 +57,10 @@ dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C fi + if [ "$CONFIG_ARCH_AT91RM9200" = "y" ] ; then + dep_tristate 'Atmel AT91RM9200 I2C Two-Wire interface (TWI)' CONFIG_I2C_AT91 $CONFIG_I2C + fi + # This is needed for automatic patch generation: sensors code starts here # This is needed for automatic patch generation: sensors code ends here diff -urN orig/drivers/i2c/Makefile linux/drivers/i2c/Makefile --- orig/drivers/i2c/Makefile Tue Jun 24 13:58:21 2003 +++ linux/drivers/i2c/Makefile Tue Jun 24 12:08:22 2003 @@ -7,12 +7,21 @@ export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \ i2c-algo-ite.o i2c-proc.o +# Init order: core, chardev, bit adapters, pcf adapters + obj-$(CONFIG_I2C) += i2c-core.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o + +# Bit adapters obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o obj-$(CONFIG_I2C_ELV) += i2c-elv.o obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o +obj-$(CONFIG_I2C_GUIDE) += i2c-guide.o +obj-$(CONFIG_I2C_FRODO) += i2c-frodo.o +obj-$(CONFIG_I2C_OMAHA) += i2c-omaha.o + +# PCF adapters obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o @@ -22,6 +31,7 @@ obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o + # This is needed for automatic patch generation: sensors code starts here # This is needed for automatic patch generation: sensors code ends here diff -urN orig/drivers/i2c/i2c-algo-bit.c linux/drivers/i2c/i2c-algo-bit.c --- orig/drivers/i2c/i2c-algo-bit.c Mon Aug 5 13:30:49 2002 +++ linux/drivers/i2c/i2c-algo-bit.c Thu Feb 27 23:20:12 2003 @@ -170,7 +170,14 @@ * 1 if the device acknowledged * 0 if the device did not ack * -ETIMEDOUT if an error occurred (while raising the scl line) - */ + + * tsong@iders.ca: an instruction to disable any timeconsuming interrupt + here except the heart beat of timer2 should be added before setsda(adap, sb). + because when interrupt occurs during + scl is set high, the interrupt service routine is served and may take long, + after the interrupt returns, sda could be sampled by the device(slave) + more than once, and this cause error problem. +*/ static int i2c_outb(struct i2c_adapter *i2c_adap, char c) { int i; @@ -583,9 +590,7 @@ printk("\n"); } -#ifdef MODULE MOD_INC_USE_COUNT; -#endif i2c_add_adapter(adap); return 0; @@ -601,15 +606,13 @@ DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name)); -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif return 0; } -int __init i2c_algo_bit_init (void) +static int __init i2c_algo_bit_init (void) { - printk("i2c-algo-bit.o: i2c bit algorithm module\n"); + printk(KERN_DEBUG "i2c-algo-bit.o: i2c bit algorithm module\n"); return 0; } @@ -618,7 +621,6 @@ EXPORT_SYMBOL(i2c_bit_add_bus); EXPORT_SYMBOL(i2c_bit_del_bus); -#ifdef MODULE MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); MODULE_LICENSE("GPL"); @@ -632,12 +634,4 @@ MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol"); -int init_module(void) -{ - return i2c_algo_bit_init(); -} - -void cleanup_module(void) -{ -} -#endif +module_init(i2c_algo_bit_init); diff -urN orig/drivers/i2c/i2c-algo-pcf.c linux/drivers/i2c/i2c-algo-pcf.c --- orig/drivers/i2c/i2c-algo-pcf.c Fri Oct 26 16:46:10 2001 +++ linux/drivers/i2c/i2c-algo-pcf.c Fri Oct 5 17:42:36 2001 @@ -476,9 +476,7 @@ return i; } -#ifdef MODULE MOD_INC_USE_COUNT; -#endif i2c_add_adapter(adap); @@ -516,13 +514,11 @@ return res; DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name)); -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif return 0; } -int __init i2c_algo_pcf_init (void) +static int __init i2c_algo_pcf_init (void) { printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n"); return 0; @@ -532,7 +528,6 @@ EXPORT_SYMBOL(i2c_pcf_add_bus); EXPORT_SYMBOL(i2c_pcf_del_bus); -#ifdef MODULE MODULE_AUTHOR("Hans Berglund "); MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); MODULE_LICENSE("GPL"); @@ -544,13 +539,4 @@ MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); - -int init_module(void) -{ - return i2c_algo_pcf_init(); -} - -void cleanup_module(void) -{ -} -#endif +module_init(i2c_algo_pcf_init); diff -urN orig/drivers/i2c/i2c-core.c linux/drivers/i2c/i2c-core.c --- orig/drivers/i2c/i2c-core.c Wed Jun 18 13:01:56 2003 +++ linux/drivers/i2c/i2c-core.c Wed Jun 18 09:58:31 2003 @@ -72,7 +72,7 @@ static int driver_count; /**** debug level */ -static int i2c_debug=1; +static int i2c_debug = 0; /* --------------------------------------------------- * /proc entry declarations @@ -82,7 +82,7 @@ #ifdef CONFIG_PROC_FS static int i2cproc_init(void); -static int i2cproc_cleanup(void); +static void i2cproc_cleanup(void); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27)) static void monitor_bus_i2c(struct inode *inode, int fill); @@ -741,14 +741,13 @@ return 0; } -int i2cproc_cleanup(void) +static void i2cproc_cleanup(void) { if (i2cproc_initialized >= 1) { remove_proc_entry("i2c",proc_bus); i2cproc_initialized -= 2; } - return 0; } @@ -1264,7 +1263,7 @@ static int __init i2c_init(void) { - printk("i2c-core.o: i2c core module\n"); + printk(KERN_DEBUG "i2c-core.o: i2c core module\n"); memset(adapters,0,sizeof(adapters)); memset(drivers,0,sizeof(drivers)); adap_count=0; @@ -1278,98 +1277,6 @@ return 0; } -#ifndef MODULE -#ifdef CONFIG_I2C_CHARDEV - extern int i2c_dev_init(void); -#endif -#ifdef CONFIG_I2C_ALGOBIT - extern int i2c_algo_bit_init(void); -#endif -#ifdef CONFIG_I2C_PHILIPSPAR - extern int i2c_bitlp_init(void); -#endif -#ifdef CONFIG_I2C_ELV - extern int i2c_bitelv_init(void); -#endif -#ifdef CONFIG_I2C_VELLEMAN - extern int i2c_bitvelle_init(void); -#endif -#ifdef CONFIG_I2C_BITVIA - extern int i2c_bitvia_init(void); -#endif - -#ifdef CONFIG_I2C_ALGOPCF - extern int i2c_algo_pcf_init(void); -#endif -#ifdef CONFIG_I2C_ELEKTOR - extern int i2c_pcfisa_init(void); -#endif - -#ifdef CONFIG_I2C_ALGO8XX - extern int i2c_algo_8xx_init(void); -#endif -#ifdef CONFIG_I2C_RPXLITE - extern int i2c_rpx_init(void); -#endif -#ifdef CONFIG_I2C_PROC - extern int sensors_init(void); -#endif - -/* This is needed for automatic patch generation: sensors code starts here */ -/* This is needed for automatic patch generation: sensors code ends here */ - -int __init i2c_init_all(void) -{ - /* --------------------- global ----- */ - i2c_init(); - -#ifdef CONFIG_I2C_CHARDEV - i2c_dev_init(); -#endif - /* --------------------- bit -------- */ -#ifdef CONFIG_I2C_ALGOBIT - i2c_algo_bit_init(); -#endif -#ifdef CONFIG_I2C_PHILIPSPAR - i2c_bitlp_init(); -#endif -#ifdef CONFIG_I2C_ELV - i2c_bitelv_init(); -#endif -#ifdef CONFIG_I2C_VELLEMAN - i2c_bitvelle_init(); -#endif - - /* --------------------- pcf -------- */ -#ifdef CONFIG_I2C_ALGOPCF - i2c_algo_pcf_init(); -#endif -#ifdef CONFIG_I2C_ELEKTOR - i2c_pcfisa_init(); -#endif - - /* --------------------- 8xx -------- */ -#ifdef CONFIG_I2C_ALGO8XX - i2c_algo_8xx_init(); -#endif -#ifdef CONFIG_I2C_RPXLITE - i2c_rpx_init(); -#endif - - /* -------------- proc interface ---- */ -#ifdef CONFIG_I2C_PROC - sensors_init(); -#endif -/* This is needed for automatic patch generation: sensors code starts here */ -/* This is needed for automatic patch generation: sensors code ends here */ - - return 0; -} - -#endif - - - EXPORT_SYMBOL(i2c_add_adapter); EXPORT_SYMBOL(i2c_del_adapter); EXPORT_SYMBOL(i2c_add_driver); @@ -1406,20 +1313,11 @@ EXPORT_SYMBOL(i2c_get_functionality); EXPORT_SYMBOL(i2c_check_functionality); -#ifdef MODULE MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus main module"); MODULE_PARM(i2c_debug, "i"); MODULE_PARM_DESC(i2c_debug,"debug level"); MODULE_LICENSE("GPL"); -int init_module(void) -{ - return i2c_init(); -} - -void cleanup_module(void) -{ - i2cproc_cleanup(); -} -#endif +module_init(i2c_init); +module_exit(i2cproc_cleanup); diff -urN orig/drivers/i2c/i2c-dev.c linux/drivers/i2c/i2c-dev.c --- orig/drivers/i2c/i2c-dev.c Tue Jun 24 13:58:21 2003 +++ linux/drivers/i2c/i2c-dev.c Tue Jun 24 11:17:41 2003 @@ -53,11 +53,6 @@ #include #include -#ifdef MODULE -extern int init_module(void); -extern int cleanup_module(void); -#endif /* def MODULE */ - /* struct file_operations changed too often in the 2.1 series for nice code */ #if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,9) @@ -79,13 +74,8 @@ static int i2cdev_command(struct i2c_client *client, unsigned int cmd, void *arg); -#ifdef MODULE -static -#else -extern -#endif - int __init i2c_dev_init(void); -static int i2cdev_cleanup(void); +static int __init i2c_dev_init(void); +static void i2cdev_cleanup(void); static struct file_operations i2cdev_fops = { #if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) @@ -505,11 +495,11 @@ return -1; } -int __init i2c_dev_init(void) +static int __init i2c_dev_init(void) { int res; - printk("i2c-dev.o: i2c /dev entries driver module\n"); + printk(KERN_DEBUG "i2c-dev.o: i2c /dev entries driver module\n"); i2cdev_initialized = 0; #ifdef CONFIG_DEVFS_FS @@ -535,7 +525,7 @@ return 0; } -int i2cdev_cleanup(void) +static void i2cdev_cleanup(void) { int res; @@ -543,9 +533,9 @@ if ((res = i2c_del_driver(&i2cdev_driver))) { printk("i2c-dev.o: Driver deregistration failed, " "module not removed.\n"); - return res; + return; } - i2cdev_initialized --; + i2cdev_initialized --; } if (i2cdev_initialized >= 1) { @@ -557,30 +547,18 @@ #endif printk("i2c-dev.o: unable to release major %d for i2c bus\n", I2C_MAJOR); - return res; + return; } i2cdev_initialized --; } - return 0; } EXPORT_NO_SYMBOLS; -#ifdef MODULE - MODULE_AUTHOR("Frodo Looijaard and Simon G. Vogl "); MODULE_DESCRIPTION("I2C /dev entries driver"); MODULE_LICENSE("GPL"); -int init_module(void) -{ - return i2c_dev_init(); -} - -int cleanup_module(void) -{ - return i2cdev_cleanup(); -} - -#endif /* def MODULE */ +module_init(i2c_dev_init); +module_exit(i2cdev_cleanup); diff -urN orig/drivers/i2c/i2c-elektor.c linux/drivers/i2c/i2c-elektor.c --- orig/drivers/i2c/i2c-elektor.c Fri Oct 26 16:46:10 2001 +++ linux/drivers/i2c/i2c-elektor.c Mon Oct 8 23:55:48 2001 @@ -184,16 +184,12 @@ static void pcf_isa_inc_use(struct i2c_adapter *adap) { -#ifdef MODULE MOD_INC_USE_COUNT; -#endif } static void pcf_isa_dec_use(struct i2c_adapter *adap) { -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif } @@ -222,7 +218,7 @@ pcf_isa_unreg, }; -int __init i2c_pcfisa_init(void) +static int __init i2c_pcfisa_init(void) { #ifdef __alpha__ /* check to see we have memory mapped PCF8584 connected to the @@ -294,10 +290,14 @@ return 0; } +static void i2c_pcfisa_exit(void) +{ + i2c_pcf_del_bus(&pcf_isa_ops); + pcf_isa_exit(); +} EXPORT_NO_SYMBOLS; -#ifdef MODULE MODULE_AUTHOR("Hans Berglund "); MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter"); MODULE_LICENSE("GPL"); @@ -309,15 +309,5 @@ MODULE_PARM(mmapped, "i"); MODULE_PARM(i2c_debug, "i"); -int init_module(void) -{ - return i2c_pcfisa_init(); -} - -void cleanup_module(void) -{ - i2c_pcf_del_bus(&pcf_isa_ops); - pcf_isa_exit(); -} - -#endif +module_init(i2c_pcfisa_init); +module_exit(i2c_pcfisa_exit); diff -urN orig/drivers/i2c/i2c-elv.c linux/drivers/i2c/i2c-elv.c --- orig/drivers/i2c/i2c-elv.c Fri Oct 26 16:46:10 2001 +++ linux/drivers/i2c/i2c-elv.c Mon Oct 8 23:55:49 2001 @@ -132,16 +132,12 @@ static void bit_elv_inc_use(struct i2c_adapter *adap) { -#ifdef MODULE MOD_INC_USE_COUNT; -#endif } static void bit_elv_dec_use(struct i2c_adapter *adap) { -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif } /* ------------------------------------------------------------------------ @@ -168,7 +164,7 @@ bit_elv_unreg, }; -int __init i2c_bitelv_init(void) +static int __init i2c_bitelv_init(void) { printk("i2c-elv.o: i2c ELV parallel port adapter module\n"); if (base==0) { @@ -195,9 +191,14 @@ } +static void __exit i2c_bitelv_exit(void) +{ + i2c_bit_del_bus(&bit_elv_ops); + bit_elv_exit(); +} + EXPORT_NO_SYMBOLS; -#ifdef MODULE MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter"); MODULE_LICENSE("GPL"); @@ -205,15 +206,5 @@ MODULE_PARM(base, "i"); -int init_module(void) -{ - return i2c_bitelv_init(); -} - -void cleanup_module(void) -{ - i2c_bit_del_bus(&bit_elv_ops); - bit_elv_exit(); -} - -#endif +module_init(i2c_bitelv_init); +module_exit(i2c_bitelv_exit); diff -urN orig/drivers/i2c/i2c-frodo.c linux/drivers/i2c/i2c-frodo.c --- orig/drivers/i2c/i2c-frodo.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/i2c/i2c-frodo.c Thu Oct 24 13:01:38 2002 @@ -0,0 +1,114 @@ + +/* + * linux/drivers/i2c/i2c-frodo.c + * + * Author: Abraham van der Merwe + * + * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 + * Development board (Frodo). + * + * This source code 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 + +static void frodo_setsda (void *data,int state) +{ + if (state) + frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT); + else + frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT); +} + +static void frodo_setscl (void *data,int state) +{ + if (state) + frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT); + else + frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT); +} + +static int frodo_getsda (void *data) +{ + return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SDA_IN) != 0); +} + +static int frodo_getscl (void *data) +{ + return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SCL_IN) != 0); +} + +static struct i2c_algo_bit_data bit_frodo_data = { + setsda: frodo_setsda, + setscl: frodo_setscl, + getsda: frodo_getsda, + getscl: frodo_getscl, + udelay: 80, + mdelay: 80, + timeout: 100 +}; + +static int frodo_client_register (struct i2c_client *client) +{ + return (0); +} + +static int frodo_client_unregister (struct i2c_client *client) +{ + return (0); +} + +static void frodo_inc_use (struct i2c_adapter *adapter) +{ + MOD_INC_USE_COUNT; +} + +static void frodo_dec_use (struct i2c_adapter *adapter) +{ + MOD_DEC_USE_COUNT; +} + +static struct i2c_adapter frodo_ops = { + name: "Frodo adapter driver", + id: I2C_HW_B_FRODO, + algo: NULL, + algo_data: &bit_frodo_data, + inc_use: frodo_inc_use, + dec_use: frodo_dec_use, + client_register: frodo_client_register, + client_unregister: frodo_client_unregister +}; + +static int __init i2c_frodo_init (void) +{ + return (i2c_bit_add_bus (&frodo_ops)); +} + +EXPORT_NO_SYMBOLS; + +static void __exit i2c_frodo_exit (void) +{ + i2c_bit_del_bus (&frodo_ops); +} + +MODULE_AUTHOR ("Abraham van der Merwe "); +MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); +MODULE_LICENSE ("GPL"); +EXPORT_NO_SYMBOLS; + +module_init (i2c_frodo_init); +module_exit (i2c_frodo_exit); + diff -urN orig/drivers/i2c/i2c-guide.c linux/drivers/i2c/i2c-guide.c --- orig/drivers/i2c/i2c-guide.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/i2c/i2c-guide.c Thu Feb 27 23:20:12 2003 @@ -0,0 +1,199 @@ +/************************************************************************************\ +Copyright : Copyright (C) 1995-2000 Simon G. Vogl + Copyright 2002 IDERs Incorporated +File Name : i2c-guide.c +Description : this i2c driver uses the GPIO port B pin 0 and pin 1 on the cs89712. +Notes : To change the bit rate, change the structure i2c_algo_bit_data + : to 10 10 100 +Contact : tsong@iders.ca +License : This source code 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 /* for 2.0 kernels to get NULL */ +#include /* for 2.0 kernels to get ENODEV */ +#include + +#include // io operation ep_writel() +#include // io operation clps_writel() +#include // io operation clps_writel() + +#include +#include + +/* ----- global defines ----------------------------------------------- */ + +#define DEB(x) /* should be reasonable open, close &c. */ +#define DEB2(x) /* low level debugging - very slow */ +#define DEBE(x) x /* error messages */ + /* Pin Port Inverted name */ +#define I2C_SDA 0x08 /* port B ctrl pin 3 (inv) */ +#define I2C_SCL 0x04 /* port B ctrl pin 2 (inv) */ + +#define I2C_SDAIN 0x08 /* use the same pin with output */ +#define I2C_SCLIN 0x04 /* use the same pin with output */ + +#define I2C_DMASK 0xf7 /* inverse of I2C_SDA */ +#define I2C_CMASK 0xfb /* inverse of I2c_SCL */ + +#define PORTB_PIN0_SDA_OUTPUT 0x08 /* pin 3 direction of port B output */ +#define PORTB_PIN0_SDA_INPUT 0xf7 /* pin 3 direction of port B input */ + +#define PORTB_PIN1_SCL_OUTPUT 0x04 /* pin 2 direction of port B output */ +#define PORTB_PIN1_SCL_INPUT 0xfb /* pin 2 direction of port B input */ + +int base = 0; +#define DEFAULT_BASE PBDR + +/* ----- local functions --------------------------------------------------- */ + +static void bit_guide_setscl(void* data, int state) +{ + if (state) { + // set port B pin2 input + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN1_SCL_INPUT, PBDDR); + } + else { + // clear + clps_writeb((clps_readb(PBDR)) & I2C_CMASK, PBDR); + // set port B pin2 output + clps_writeb((clps_readb(PBDDR)) | PORTB_PIN1_SCL_OUTPUT, PBDDR); + } +} + +static void bit_guide_setsda(void* data, int state) +{ + if (state) { + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR); + // float pin 0 (actually drive high by pull up resistor) + // clps_writeb((clps_readb(PBDR)) | I2C_SDA, PBDR); // set Jan4 ori: eff + // printk("set sda high, state=%i\n",state); + } + else { + // clear + clps_writeb((clps_readb(PBDR)) & I2C_DMASK, PBDR); + // set port B pin 0 output + clps_writeb((clps_readb(PBDDR)) | PORTB_PIN0_SDA_OUTPUT, PBDDR); + } +} + +static int bit_guide_getscl(void *data) +{ + return ( 0 != ( (clps_readb(PBDR)) & I2C_SCLIN ) ); +} + +static int bit_guide_getsda(void *data) +{ + // set port B pin 0 input Jan4 ori eff + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR); + return ( 0 != ( (clps_readb(PBDR) ) & I2C_SDAIN ) ); +} + +static int bit_guide_init(void) +{ + bit_guide_setsda((void*)base,1); + bit_guide_setscl((void*)base,1); + return 0; +} + +static int bit_guide_reg(struct i2c_client *client) +{ + return 0; +} + +static int bit_guide_unreg(struct i2c_client *client) +{ + return 0; +} + +static void bit_guide_inc_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + +static void bit_guide_dec_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ + +/* last line (us, ms, timout) + * us dominates the bit rate: 10us means: 100Kbit/sec(25 means 40kbps) + * 10ms not known + * 100ms timeout + */ +static struct i2c_algo_bit_data bit_guide_data = { + NULL, + bit_guide_setsda, + bit_guide_setscl, + bit_guide_getsda, + bit_guide_getscl, + 50, 10, 100, /* orginal (non-guide) value 10, 10, 100 */ +}; + +static struct i2c_adapter bit_guide_ops = { + "Guide Port B: PIN2-SCL/PIN3-SDA", + I2C_HW_B_GUIDE, + NULL, + &bit_guide_data, + bit_guide_inc_use, + bit_guide_dec_use, + bit_guide_reg, + bit_guide_unreg, +}; + +static int __init i2c_bitguide_init(void) +{ + printk("i2c-guide.o: Guide i2c port B adapter module.\n"); + clps_writeb((clps_readb(PBDDR)) & 0xfd, PBDDR); // set service reuest pb1 as input + if (base==0) { + /* probe some values */ + base=DEFAULT_BASE; + bit_guide_data.data=(void*)DEFAULT_BASE; + if (bit_guide_init()==0) { + if(i2c_bit_add_bus(&bit_guide_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } else { + bit_guide_data.data=(void*)base; + if (bit_guide_init()==0) { + if(i2c_bit_add_bus(&bit_guide_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } + printk("i2c-guide.o: found device at %#x.\n",base); + return 0; +} + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("T. C. Song "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for Guide (cs89712) GPIO port B"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(base, "i"); + +module_init(i2c_bitguide_init); +/* for completeness, we should have a module_exit() function, but the + GUIDE requires this to always be loaded. If it is unloaded, the + operation of the GUIDE is undefined. + Nobody has written the i2c_bitguide_exit() routine yet, so it is not included. +module_exit(i2c_bitguide_exit); +*/ diff -urN orig/drivers/i2c/i2c-omaha.c linux/drivers/i2c/i2c-omaha.c --- orig/drivers/i2c/i2c-omaha.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/i2c/i2c-omaha.c Thu Oct 24 14:58:03 2002 @@ -0,0 +1,276 @@ +/* ------------------------------------------------------------------------- * + Copyright ARM Limited 2002. All rights reserved. + + i2c driver for Omaha + + Notes:Based on i2c-elv.c + + The S3C2400X01 has better support for I2C, but bit oriented operations + are directly supported by the other I2C layers, so we use that method + of performing I2C operations. + + Copyright (C) 1995-2000 Simon G. Vogl + + 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 + +#include +#include + +#include +#include + +/* ----- global defines ----------------------------------------------- */ +#define DEB(x) if (i2c_debug>=1) x; +#define DEB2(x) if (i2c_debug>=2) x; +#define DEB3(x) if (i2c_debug>=3) x +#define DEBE(x) x // error messages +#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/ +#define DEBPROTO(x) if (i2c_debug>=9) { x; } + /* debug the protocol by showing transferred bits */ + +/* Register and bitdefs for Omaha */ + +// Port G control registers +static volatile unsigned int pgcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON); +static volatile unsigned int pgdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGDAT); + +static volatile unsigned int opencr = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_OPENCR); + +static int base = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON); + +// Open drain control registers +#define OPC_CMD BIT2 +#define OPC_DAT BIT3 + +// data bits in GPIO Port G data register +#define OMAHA_SDA BIT5 +#define OMAHA_SCL BIT6 +#define IIC_WP BIT3 // Write Protect for EEPROM + +// input/out select bits in GPIO G control register +#define IIC_BITS (BIT12|BIT10|BIT6); + + +/* ----- local functions ---------------------------------------------- */ + + +static void bit_omaha_setscl(void *data, int state) +{ + unsigned int tmp; + + if (state) + { + tmp = __raw_readl(pgdat); + tmp |= OMAHA_SCL; + __raw_writel(tmp,pgdat); + } + else + { + tmp = __raw_readl(pgdat); + tmp &= ~OMAHA_SCL; + __raw_writel(tmp,pgdat); + } +} + +static void bit_omaha_setsda(void *data, int state) +{ + unsigned int tmp; + + // ensure that sda is an output at the moment + tmp = __raw_readl(pgcon); + tmp = tmp | BIT10; + __raw_writel(tmp,pgcon); + + if (state) + { + tmp = __raw_readl(pgdat); + tmp |= OMAHA_SDA; + __raw_writel(tmp,pgdat); + } + else + { + tmp = __raw_readl(pgdat); + tmp &= ~OMAHA_SDA; + __raw_writel(tmp,pgdat); + } +} + +static int bit_omaha_getscl(void *data) +{ + if (__raw_readl(pgdat) & OMAHA_SCL) + return 1; + else + return 0; +} + +static int bit_omaha_getsda(void *data) +{ + unsigned int tmp; + + // ensure that sda is an output at the moment + tmp = __raw_readl(pgcon); + tmp = tmp & ~BIT10; + __raw_writel(tmp,pgcon); + + if (__raw_readl(pgdat) & OMAHA_SDA) + return 1; + else + return 0; +} + +static int bit_omaha_init(void) +{ + // Have we got some mmapped space? + if (request_region(base, 0x100, "i2c (omaha bus adapter)") < 0 ) + { + printk("i2c-omaha.o: requested I/O region (0x%08x) is in use.\n", base); + return -ENODEV; + } + + return 0; +} + + +static int bit_omaha_reg(struct i2c_client *client) +{ + return 0; +} + + +static int bit_omaha_unreg(struct i2c_client *client) +{ + return 0; +} + +static void bit_omaha_inc_use(struct i2c_adapter *adap) +{ + MOD_INC_USE_COUNT; +} + +static void bit_omaha_dec_use(struct i2c_adapter *adap) +{ + MOD_DEC_USE_COUNT; +} + + + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_bit_data bit_omaha_data = { + NULL, + bit_omaha_setsda, + bit_omaha_setscl, + bit_omaha_getsda, + bit_omaha_getscl, + 10, 10, 20, /* waits, timeout */ +}; + +static struct i2c_adapter bit_omaha_ops = { + "BIT-Type Omaha I2C adapter", + I2C_HW_B_OMAHA, + NULL, + &bit_omaha_data, + bit_omaha_inc_use, + bit_omaha_dec_use, + bit_omaha_reg, + bit_omaha_unreg, +}; + +static int __init i2c_omaha_init (void) +{ + unsigned int tmp; + + printk("i2c-omaha.o: i2c omaha adapter module\n"); + + if (bit_omaha_init() == 0) { + if(i2c_bit_add_bus(&bit_omaha_ops) < 0) + { + printk("Could not add bus!\n"); + return -ENODEV; + } + } else { + printk("Could not pcf_omaha_init\n"); + return -ENODEV; + } + + // Program Port G bits to output function + tmp = __raw_readl(pgcon); + tmp |= IIC_BITS; + __raw_writel(tmp,pgcon); + + // Ensure SDA and SCL are open-drain + tmp = __raw_readl(opencr); + tmp = tmp | OPC_CMD | OPC_DAT; + __raw_writel(tmp,opencr); + + bit_omaha_setsda((void*)base,1); + bit_omaha_setscl((void*)base,1); + + // Disable WP + tmp = __raw_readl(pgdat); + tmp = tmp & ~IIC_WP; + __raw_writel(tmp,pgdat); + + return 0; +} + +static void bit_omaha_exit(void) +{ + release_region(base , 2); +} + +static void i2c_omaha_exit(void) +{ + + i2c_bit_del_bus(&bit_omaha_ops); + + bit_omaha_exit(); + +} + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("ARM Limited "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for Omaha"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(base, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(clock, "i"); +MODULE_PARM(own, "i"); +MODULE_PARM(mmapped, "i"); +MODULE_PARM(i2c_debug, "i"); + + +module_init(i2c_omaha_init); +module_exit(i2c_omaha_exit); + + diff -urN orig/drivers/i2c/i2c-philips-par.c linux/drivers/i2c/i2c-philips-par.c --- orig/drivers/i2c/i2c-philips-par.c Sun Oct 14 20:53:01 2001 +++ linux/drivers/i2c/i2c-philips-par.c Fri Sep 28 21:40:51 2001 @@ -259,7 +259,7 @@ }; #endif -int __init i2c_bitlp_init(void) +static int __init i2c_bitlp_init(void) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,4) struct parport *port; @@ -276,7 +276,7 @@ return 0; } -void __exit i2c_bitlp_exit(void) +static void __exit i2c_bitlp_exit(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4) parport_unregister_driver(&i2c_driver); @@ -295,14 +295,5 @@ MODULE_PARM(type, "i"); -#ifdef MODULE -int init_module(void) -{ - return i2c_bitlp_init(); -} - -void cleanup_module(void) -{ - i2c_bitlp_exit(); -} -#endif +module_init(i2c_bitlp_init); +module_exit(i2c_bitlp_exit); diff -urN orig/drivers/i2c/i2c-velleman.c linux/drivers/i2c/i2c-velleman.c --- orig/drivers/i2c/i2c-velleman.c Fri Oct 26 16:46:10 2001 +++ linux/drivers/i2c/i2c-velleman.c Mon Oct 8 23:55:49 2001 @@ -121,16 +121,12 @@ static void bit_velle_inc_use(struct i2c_adapter *adap) { -#ifdef MODULE MOD_INC_USE_COUNT; -#endif } static void bit_velle_dec_use(struct i2c_adapter *adap) { -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif } /* ------------------------------------------------------------------------ @@ -158,7 +154,7 @@ bit_velle_unreg, }; -int __init i2c_bitvelle_init(void) +static int __init i2c_bitvelle_init(void) { printk("i2c-velleman.o: i2c Velleman K8000 adapter module\n"); if (base==0) { @@ -184,24 +180,19 @@ return 0; } +static void __exit i2c_bitvelle_exit(void) +{ + i2c_bit_del_bus(&bit_velle_ops); + bit_velle_exit(); +} + EXPORT_NO_SYMBOLS; -#ifdef MODULE MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter"); MODULE_LICENSE("GPL"); MODULE_PARM(base, "i"); -int init_module(void) -{ - return i2c_bitvelle_init(); -} - -void cleanup_module(void) -{ - i2c_bit_del_bus(&bit_velle_ops); - bit_velle_exit(); -} - -#endif +module_init(i2c_bitvelle_init); +module_exit(i2c_bitvelle_exit); diff -urN orig/drivers/ide/Config.in linux/drivers/ide/Config.in --- orig/drivers/ide/Config.in Tue Jun 24 13:58:21 2003 +++ linux/drivers/ide/Config.in Tue Jun 24 11:17:42 2003 @@ -103,6 +103,9 @@ define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN fi + if [ "$CONFIG_ARCH_RISCSTATION" = "y" ]; then + dep_bool ' RiscStation IDE' CONFIG_BLK_DEV_IDE_RISCSTATION $CONFIG_ARCH_RISCSTATION + fi if [ "$CONFIG_AMIGA" = "y" ]; then dep_bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL diff -urN orig/drivers/ide/arm/Makefile linux/drivers/ide/arm/Makefile --- orig/drivers/ide/arm/Makefile Tue Jun 24 13:58:21 2003 +++ linux/drivers/ide/arm/Makefile Tue Jun 24 13:43:51 2003 @@ -6,6 +6,7 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o +obj-$(CONFIG_BLK_DEV_IDE_RISCSTATION) += rstation-ide.o EXTRA_CFLAGS := -I../ diff -urN orig/drivers/ide/arm/icside.c linux/drivers/ide/arm/icside.c --- orig/drivers/ide/arm/icside.c Tue Jun 24 13:58:21 2003 +++ linux/drivers/ide/arm/icside.c Sat Jul 12 17:35:21 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/ide/arm/icside.c * - * Copyright (c) 1996,1997 Russell King. + * Copyright (c) 1996-2003 Russell King. * * Changelog: * 08-Jun-1996 RMK Created @@ -26,24 +26,6 @@ #include #include -#include "ide-noise.h" - -/* - * FIXME: We want to drop the the MACRO CRAP! - * - * ec->iops->in{b/w/l} - * ec->iops->in{b/w/l}_p - * ec->iops->out{b/w/l} - * ec->iops->out{b/w/l}_p - * - * the new core supports clean MMIO calls and other goodies - */ - -/* - * Maximum number of interfaces per card - */ -#define MAX_IFS 2 - #define ICS_IDENT_OFFSET 0x8a0 #define ICS_ARCIN_V5_INTRSTAT 0x000 @@ -86,17 +68,20 @@ ICS_ARCIN_V6_IDESTEPPING }; -static const card_ids icside_cids[] = { - { MANU_ICS, PROD_ICS_IDE }, - { MANU_ICS2, PROD_ICS2_IDE }, - { 0xffff, 0xffff } +struct icside_state { + unsigned int channel; + unsigned int enabled; + unsigned long irq_port; + unsigned long slot_port; + unsigned int type; + ide_hwif_t *hwif[2]; }; -typedef enum { - ics_if_unknown, - ics_if_arcin_v5, - ics_if_arcin_v6 -} iftype_t; +#define ICS_TYPE_A3IN 0 +#define ICS_TYPE_A3USER 1 +#define ICS_TYPE_V6 3 +#define ICS_TYPE_V5 15 +#define ICS_TYPE_NOTYPE ((unsigned int)-1) /* ---------------- Version 5 PCB Support Functions --------------------- */ /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) @@ -104,8 +89,10 @@ */ static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) { - unsigned int memc_port = (unsigned int)ec->irq_data; - outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET); + struct icside_state *state = ec->irq_data; + unsigned int base = state->irq_port; + + outb(0, base + ICS_ARCIN_V5_INTROFFSET); } /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) @@ -113,17 +100,15 @@ */ static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) { - unsigned int memc_port = (unsigned int)ec->irq_data; - inb(memc_port + ICS_ARCIN_V5_INTROFFSET); + struct icside_state *state = ec->irq_data; + unsigned int base = state->irq_port; + + inb(base + ICS_ARCIN_V5_INTROFFSET); } static const expansioncard_ops_t icside_ops_arcin_v5 = { - icside_irqenable_arcin_v5, - icside_irqdisable_arcin_v5, - NULL, - NULL, - NULL, - NULL + .irqenable = icside_irqenable_arcin_v5, + .irqdisable = icside_irqdisable_arcin_v5, }; @@ -133,10 +118,21 @@ */ static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) { - unsigned int ide_base_port = (unsigned int)ec->irq_data; + struct icside_state *state = ec->irq_data; + unsigned int base = state->irq_port; + + state->enabled = 1; - outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); + switch (state->channel) { + case 0: + outb(0, base + ICS_ARCIN_V6_INTROFFSET_1); + inb(base + ICS_ARCIN_V6_INTROFFSET_2); + break; + case 1: + outb(0, base + ICS_ARCIN_V6_INTROFFSET_2); + inb(base + ICS_ARCIN_V6_INTROFFSET_1); + break; + } } /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) @@ -144,10 +140,12 @@ */ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) { - unsigned int ide_base_port = (unsigned int)ec->irq_data; + struct icside_state *state = ec->irq_data; + + state->enabled = 0; - inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); + inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); } /* Prototype: icside_irqprobe(struct expansion_card *ec) @@ -155,70 +153,49 @@ */ static int icside_irqpending_arcin_v6(struct expansion_card *ec) { - unsigned int ide_base_port = (unsigned int)ec->irq_data; + struct icside_state *state = ec->irq_data; - return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || - inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; + return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; } static const expansioncard_ops_t icside_ops_arcin_v6 = { - icside_irqenable_arcin_v6, - icside_irqdisable_arcin_v6, - icside_irqpending_arcin_v6, - NULL, - NULL, - NULL + .irqenable = icside_irqenable_arcin_v6, + .irqdisable = icside_irqdisable_arcin_v6, + .irqpending = icside_irqpending_arcin_v6, }; -/* Prototype: icside_identifyif (struct expansion_card *ec) - * Purpose : identify IDE interface type - * Notes : checks the description string +/* + * Handle routing of interrupts. This is called before + * we write the command to the drive. */ -static iftype_t __init icside_identifyif (struct expansion_card *ec) +static void icside_maskproc(ide_drive_t *drive, int mask) { - unsigned int addr; - iftype_t iftype; - int id = 0; - - iftype = ics_if_unknown; - - addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; - - id = inb(addr) & 1; - id |= (inb(addr + 1) & 1) << 1; - id |= (inb(addr + 2) & 1) << 2; - id |= (inb(addr + 3) & 1) << 3; - - switch (id) { - case 0: /* A3IN */ - printk("icside: A3IN unsupported\n"); - break; - - case 1: /* A3USER */ - printk("icside: A3USER unsupported\n"); - break; + ide_hwif_t *hwif = HWIF(drive); + struct icside_state *state = hwif->hwif_data; + unsigned long flags; - case 3: /* ARCIN V6 */ - printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v6; - break; + local_irq_save(flags); - case 15:/* ARCIN V5 (no id) */ - printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v5; - break; + state->channel = hwif->channel; - default:/* we don't know - complain very loudly */ - printk("icside: ***********************************\n"); - printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); - printk("icside: ***********************************\n"); - printk("icside: please report this to linux@arm.linux.org.uk\n"); - printk("icside: defaulting to ARCIN V5\n"); - iftype = ics_if_arcin_v5; - break; + if (state->enabled && !mask) { + switch (hwif->channel) { + case 0: + outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + break; + case 1: + outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + break; + } + } else { + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); } - return iftype; + local_irq_restore(flags); } #ifdef CONFIG_BLK_DEV_IDEDMA_ICS @@ -234,125 +211,138 @@ #define NR_ENTRIES 256 #define TABLE_SIZE (NR_ENTRIES * 8) -static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq) +static void ide_build_sglist(ide_drive_t *drive, struct request *rq) { - struct buffer_head *bh; + ide_hwif_t *hwif = HWIF(drive); struct scatterlist *sg = hwif->sg_table; + struct buffer_head *bh; int nents = 0; - if (rq->cmd == READ) - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - hwif->sg_dma_direction = PCI_DMA_TODEVICE; - bh = rq->bh; - do { - unsigned char *virt_addr = bh->b_data; - unsigned int size = bh->b_size; - - while ((bh = bh->b_reqnext) != NULL) { - if ((virt_addr + size) != (unsigned char *)bh->b_data) - break; - size += bh->b_size; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_addr; - sg[nents].length = size; - nents++; - } while (bh != NULL); + BUG_ON(hwif->sg_dma_active); - return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction); -} + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; -static int -icside_build_dmatable(ide_drive_t *drive, int ddir) -{ - return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq, ddir); -} + if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; + else + hwif->sg_dma_direction = PCI_DMA_TODEVICE; + + memset(sg, 0, sizeof(*sg)); + sg->address = rq->buffer; + sg->length = rq->nr_sectors * SECTOR_SIZE; + nents = 1; + } else { + if (rq->cmd == READ) + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; + else + hwif->sg_dma_direction = PCI_DMA_TODEVICE; + + bh = rq->bh; + do { + unsigned long lastend; + + memset(sg, 0, sizeof(*sg)); + sg->page = bh->b_page; + lastend = bh_phys(bh); + + do { + lastend += bh->b_size; + sg->length += bh->b_size; + + bh = bh->b_reqnext; + if (bh == NULL) + break; + } while (lastend == bh_phys(bh)); + + sg++; + nents++; + } while (bh != NULL); + } -/* Teardown mappings after DMA has completed. */ -static void icside_destroy_dmatable(ide_drive_t *drive) -{ - struct scatterlist *sg = HWIF(drive)->sg_table; - int nents = HWIF(drive)->sg_nents; + nents = pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction); - pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction); + hwif->sg_nents = nents; } -static int -icside_config_if(ide_drive_t *drive, int xfer_mode) + +/* + * Configure the IOMD to give the appropriate timings for the transfer + * mode being requested. We take the advice of the ATA standards, and + * calculate the cycle time based on the transfer mode, and the EIDE + * MW DMA specs that the drive provides in the IDENTIFY command. + * + * We have the following IOMD DMA modes to choose from: + * + * Type Active Recovery Cycle + * A 250 (250) 312 (550) 562 (800) + * B 187 250 437 + * C 125 (125) 125 (375) 250 (500) + * D 62 125 187 + * + * (figures in brackets are actual measured timings) + * + * However, we also need to take care of the read/write active and + * recovery timings: + * + * Read Write + * Mode Active -- Recovery -- Cycle IOMD type + * MW0 215 50 215 480 A + * MW1 80 50 50 150 C + * MW2 70 25 25 120 C + */ +static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode) { - int func = ide_dma_off; + int on = 0, cycle_time = 0, use_dma_info = 0; + + /* + * Limit the transfer speed to MW_DMA_2. + */ + if (xfer_mode > XFER_MW_DMA_2) + xfer_mode = XFER_MW_DMA_2; switch (xfer_mode) { case XFER_MW_DMA_2: - /* - * The cycle time is limited to 250ns by the r/w - * pulse width (90ns), however we should still - * have a maximum burst transfer rate of 8MB/s. - */ - drive->drive_data = 250; + cycle_time = 250; + use_dma_info = 1; break; case XFER_MW_DMA_1: - drive->drive_data = 250; + cycle_time = 250; + use_dma_info = 1; break; case XFER_MW_DMA_0: - drive->drive_data = 480; + cycle_time = 480; break; - default: - drive->drive_data = 0; + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + cycle_time = 480; break; } - if (!drive->init_speed) - drive->init_speed = (u8) xfer_mode; + /* + * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should + * take care to note the values in the ID... + */ + if (use_dma_info && drive->id->eide_dma_time > cycle_time) + cycle_time = drive->id->eide_dma_time; + + drive->drive_data = cycle_time; - if (drive->drive_data && - ide_config_drive_speed(drive, (u8) xfer_mode) == 0) - func = ide_dma_on; + if (cycle_time && ide_config_drive_speed(drive, xfer_mode) == 0) + on = 1; else drive->drive_data = 480; printk("%s: %s selected (peak %dMB/s)\n", drive->name, ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); - drive->current_speed = (u8) xfer_mode; - - return func; -} - -static int -icside_set_speed(ide_drive_t *drive, u8 speed) -{ - return icside_config_if(drive, speed); -} - -/* - * dma_intr() is the handler for disk read/write DMA interrupts - */ -static ide_startstop_t icside_dmaintr(ide_drive_t *drive) -{ - u8 dma_stat = HWIF(drive)->ide_dma_end(drive); - /* get drive status */ - u8 stat = HWIF(drive)->INB(IDE_STATUS_REG); - int i; + drive->current_speed = xfer_mode; - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { - if (!dma_stat) { - struct request *rq = HWGROUP(drive)->rq; - rq = HWGROUP(drive)->rq; - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - DRIVER(drive)->end_request(drive, 1); - } - return ide_stopped; - } - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - return DRIVER(drive)->error(drive, "dma_intr", stat); + return on; } /* @@ -361,19 +351,19 @@ * This should be defined in one place only. */ struct drive_list_entry { - char * id_model; - char * id_firmware; + const char * id_model; + const char * id_firmware; }; -static struct drive_list_entry drive_whitelist [] = { +static const struct drive_list_entry drive_whitelist [] = { { "Micropolis 2112A", "ALL" }, { "CONNER CTMA 4000", "ALL" }, { "CONNER CTT8000-A", "ALL" }, { "ST34342A", "ALL" }, - { NULL, 0 } + { NULL, NULL } }; -static struct drive_list_entry drive_blacklist [] = { +static const struct drive_list_entry drive_blacklist [] = { { "WDC AC11000H", "ALL" }, { "WDC AC22100H", "ALL" }, { "WDC AC32500H", "ALL" }, @@ -407,10 +397,11 @@ { "PLEXTOR CD-R PX-W8432T", "ALL" }, { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, { "_NEC DV5800A", "ALL" }, - { NULL, 0 } + { NULL, NULL } }; -static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) +static int +in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table) { for ( ; drive_table->id_model ; drive_table++) if ((!strcmp(drive_table->id_model, id->model)) && @@ -420,41 +411,52 @@ return 0; } -/* - * For both Blacklisted and Whitelisted drives. - * This is setup to be called as an extern for future support - * to other special driver code. - */ -int check_drive_good_lists (ide_drive_t *drive) +static int icside_dma_host_off(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - return in_drive_list(id, drive_whitelist); + return 0; } -int check_drive_bad_lists (ide_drive_t *drive) +static int icside_dma_off_quietly(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - int blacklist = in_drive_list(id, drive_blacklist); - if (blacklist) - printk("%s: Disabling DMA for %s\n", drive->name, id->model); - return(blacklist); + drive->using_dma = 0; + return icside_dma_host_off(drive); +} + +static int icside_dma_off(ide_drive_t *drive) +{ + printk("%s: DMA disabled\n", drive->name); + return icside_dma_off_quietly(drive); +} + +static int icside_dma_host_on(ide_drive_t *drive) +{ + return 0; } -int icside_dma_check(ide_drive_t *drive) +static int icside_dma_on(ide_drive_t *drive) +{ + drive->using_dma = 1; + return icside_dma_host_on(drive); +} + +static int icside_dma_check(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); - int autodma = hwif->autodma; int xfer_mode = XFER_PIO_2; + int on; - if (!id || !(id->capability & 1) || !autodma) - return hwif->ide_dma_off_quietly(drive); + if (!id || !(id->capability & 1) || !hwif->autodma) + goto out; /* * Consult the list of known "bad" drives */ - if (check_drive_bad_lists(drive)) - return hwif->ide_dma_off(drive); + if (in_drive_list(id, drive_blacklist)) { + printk("%s: Disabling DMA for %s (blacklisted)\n", + drive->name, id->model); + goto out; + } /* * Enable DMA on any drive that has multiword DMA @@ -473,192 +475,241 @@ /* * Consult the list of known "good" drives */ - if (check_drive_good_lists(drive)) { + if (in_drive_list(id, drive_whitelist)) { if (id->eide_dma_time > 150) goto out; xfer_mode = XFER_MW_DMA_1; } out: - if (icside_config_if(drive, xfer_mode)) - return hwif->ide_dma_on(drive); - return hwif->ide_dma_off(drive); -} + on = icside_set_speed(drive, xfer_mode); -int icside_dma_verbose(ide_drive_t *drive) -{ - printk(", DMA"); - return 1; + if (on) + return icside_dma_on(drive); + else + return icside_dma_off(drive); } -int icside_dma_test_irq(ide_drive_t *drive) +static int icside_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - return inb((unsigned long)hwif->hw.priv) & 1; -} -int icside_dma_host_off(ide_drive_t *drive) -{ - return 0; -} + drive->waiting_for_dma = 0; -int icside_dma_off_quietly(ide_drive_t *drive) -{ - drive->using_dma = 0; - return icside_dma_host_off(drive); -} + disable_dma(hwif->hw.dma); -int icside_dma_off(ide_drive_t *drive) -{ - printk("%s: DMA disabled\n", drive->name); - return icside_dma_off_quietly(drive); -} + /* Teardown mappings after DMA has completed. */ + pci_unmap_sg(NULL, hwif->sg_table, hwif->sg_nents, + hwif->sg_dma_direction); -int icside_dma_host_on(ide_drive_t *drive) -{ - return 0; -} + hwif->sg_dma_active = 0; -int icside_dma_on(ide_drive_t *drive) -{ - drive->using_dma = 1; - return icside_dma_host_on(drive); + return get_dma_residue(hwif->hw.dma) != 0; } -int icside_dma_begin(ide_drive_t *drive) +static int icside_dma_begin(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + /* We can not enable DMA on both channels simultaneously. */ + BUG_ON(dma_channel_active(hwif->hw.dma)); enable_dma(hwif->hw.dma); return 0; } -int icside_dma_end(ide_drive_t *drive) +static int icside_dma_count(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - - drive->waiting_for_dma = 0; - disable_dma(hwif->hw.dma); - icside_destroy_dmatable(drive); - return get_dma_residue(hwif->hw.dma) != 0; + return icside_dma_begin(drive); } -int icside_dma_count (ide_drive_t *drive) +/* + * dma_intr() is the handler for disk read/write DMA interrupts + */ +static ide_startstop_t icside_dmaintr(ide_drive_t *drive) { - return icside_dma_begin(drive); + unsigned int stat; + int dma_stat; + + dma_stat = icside_dma_end(drive); + stat = HWIF(drive)->INB(IDE_STATUS_REG); + if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { + if (!dma_stat) { + struct request *rq = HWGROUP(drive)->rq; + int i; + + for (i = rq->nr_sectors; i > 0; ) { + i -= rq->current_nr_sectors; + DRIVER(drive)->end_request(drive, 1); + } + + return ide_stopped; + } + printk(KERN_ERR "%s: bad DMA status (dma_stat=%x)\n", + drive->name, dma_stat); + } + + return DRIVER(drive)->error(drive, __FUNCTION__, stat); } -int icside_dma_read(ide_drive_t *drive) +static int +icside_dma_common(ide_drive_t *drive, struct request *rq, + unsigned int dma_mode) { - ide_hwif_t *hwif = HWIF(drive); -// ide_task_t *args = HWGROUP(drive)->rq->special; - int count = 0; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; + ide_hwif_t *hwif = HWIF(drive); - count = icside_build_dmatable(drive, PCI_DMA_FROMDEVICE); - if (!count) - return 1; - disable_dma(hwif->hw.dma); + /* + * We can not enable DMA on both channels. + */ + BUG_ON(hwif->sg_dma_active); + BUG_ON(dma_channel_active(hwif->hw.dma)); + + ide_build_sglist(drive, rq); - /* Route the DMA signals to - * to the correct interface. + /* + * Ensure that we have the right interrupt routed. */ - HWIF(drive)->OUTB(hwif->select_data, hwif->config_data); + icside_maskproc(drive, 0); - /* Select the correct timing - * for this drive + /* + * Route the DMA signals to the correct interface. + */ + outb(hwif->select_data, hwif->config_data); + + /* + * Select the correct timing for this drive. */ set_dma_speed(hwif->hw.dma, drive->drive_data); - set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count); - set_dma_mode(hwif->hw.dma, DMA_MODE_READ); + /* + * Tell the DMA engine about the SG table and + * data direction. + */ + set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents); + set_dma_mode(hwif->hw.dma, dma_mode); + + return 0; +} + +static int icside_dma_read(ide_drive_t *drive) +{ + struct request *rq = HWGROUP(drive)->rq; + task_ioreg_t cmd; + + if (icside_dma_common(drive, rq, DMA_MODE_READ)) + return 1; drive->waiting_for_dma = 1; + if (drive->media != ide_disk) return 0; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); /* * FIX ME to use only ACB ide_task_t args Struct */ #if 0 { - ide_task_t *args = HWGROUP(drive)->rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + ide_task_t *args = rq->special; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; } #else - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = HWGROUP(drive)->rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; + } else if (drive->addressing == 1) { + cmd = WIN_READDMA_EXT; + } else { + cmd = WIN_READDMA; } #endif - /* issue cmd to drive */ - HWIF(drive)->OUTB(command, IDE_COMMAND_REG); - return icside_dma_count(drive); + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); + + return icside_dma_begin(drive); } -int icside_dma_write(ide_drive_t *drive) +static int icside_dma_write(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); -// ide_task_t *args = HWGROUP(drive)->rq->special; - int count = 0; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; + struct request *rq = HWGROUP(drive)->rq; + task_ioreg_t cmd; - count = icside_build_dmatable(drive, PCI_DMA_TODEVICE); - if (!count) + if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) return 1; - disable_dma(hwif->hw.dma); - - /* Route the DMA signals to - * to the correct interface. - */ - HWIF(drive)->OUTB(hwif->select_data, hwif->config_data); - - /* Select the correct timing - * for this drive - */ - set_dma_speed(hwif->hw.dma, drive->drive_data); - - set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count); - set_dma_mode(hwif->hw.dma, DMA_MODE_WRITE); drive->waiting_for_dma = 1; + if (drive->media != ide_disk) return 0; - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); /* * FIX ME to use only ACB ide_task_t args Struct */ #if 0 { - ide_task_t *args = HWGROUP(drive)->rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + ide_task_t *args = rq->special; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; } #else - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = HWGROUP(drive)->rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + if (rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; + } else if (drive->addressing == 1) { + cmd = WIN_WRITEDMA_EXT; + } else { + cmd = WIN_WRITEDMA; } #endif - /* issue cmd to drive */ - HWIF(drive)->OUTB(command, IDE_COMMAND_REG); - return icside_dma_count(drive); + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); + + return icside_dma_begin(drive); } -static int -icside_setup_dma(ide_hwif_t *hwif, int autodma) +static int icside_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct icside_state *state = hwif->hwif_data; + + return inb(state->irq_port + + (hwif->channel ? + ICS_ARCIN_V6_INTRSTAT_2 : + ICS_ARCIN_V6_INTRSTAT_1)) & 1; +} + +static int icside_dma_verbose(ide_drive_t *drive) +{ + printk(", %s (peak %dMB/s)", + ide_xfer_verbose(drive->current_speed), + 2000 / drive->drive_data); + return 1; +} + +static int icside_dma_timeout(ide_drive_t *drive) +{ + printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); + + if (icside_dma_test_irq(drive)) + return 0; + + ide_dump_status(drive, "DMA timeout", + HWIF(drive)->INB(IDE_STATUS_REG)); + + return icside_dma_end(drive); +} + +static int icside_dma_lostirq(ide_drive_t *drive) +{ + printk(KERN_ERR "%s: IRQ lost\n", drive->name); + return 1; +} + +static int icside_dma_init(ide_hwif_t *hwif) { + int autodma = 0; + +#ifdef CONFIG_IDEDMA_ICS_AUTO + autodma = 1; +#endif + printk(" %s: SG-DMA", hwif->name); hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, @@ -666,40 +717,53 @@ if (!hwif->sg_table) goto failed; - hwif->dmatable_cpu = NULL; - hwif->dmatable_dma = 0; - hwif->speedproc = icside_set_speed; - hwif->autodma = autodma; + hwif->atapi_dma = 1; + hwif->mwdma_mask = 7; /* MW0..2 */ + hwif->swdma_mask = 7; /* SW0..2 */ + + hwif->dmatable_cpu = NULL; + hwif->dmatable_dma = 0; + hwif->speedproc = icside_set_speed; + hwif->autodma = autodma; - hwif->ide_dma_check = icside_dma_check; - hwif->ide_dma_host_off = icside_dma_host_off; + hwif->ide_dma_check = icside_dma_check; + hwif->ide_dma_host_off = icside_dma_host_off; hwif->ide_dma_off_quietly = icside_dma_off_quietly; - hwif->ide_dma_off = icside_dma_off; - hwif->ide_dma_host_on = icside_dma_host_on; - hwif->ide_dma_on = icside_dma_on; - hwif->ide_dma_read = icside_dma_read; - hwif->ide_dma_write = icside_dma_write; - hwif->ide_dma_count = icside_dma_count; - hwif->ide_dma_begin = icside_dma_begin; - hwif->ide_dma_end = icside_dma_end; - hwif->ide_dma_verbose = icside_dma_verbose; - hwif->ide_dma_bad_drive = check_drive_bad_lists; - hwif->ide_dma_good_drive = check_drive_good_lists; - hwif->ide_dma_test_irq = icside_dma_test_irq; + hwif->ide_dma_off = icside_dma_off; + hwif->ide_dma_host_on = icside_dma_host_on; + hwif->ide_dma_on = icside_dma_on; + hwif->ide_dma_read = icside_dma_read; + hwif->ide_dma_write = icside_dma_write; + hwif->ide_dma_count = icside_dma_count; + hwif->ide_dma_begin = icside_dma_begin; + hwif->ide_dma_end = icside_dma_end; + hwif->ide_dma_test_irq = icside_dma_test_irq; + hwif->ide_dma_verbose = icside_dma_verbose; + hwif->ide_dma_timeout = icside_dma_timeout; + hwif->ide_dma_lostirq = icside_dma_lostirq; - printk(" capable%s\n", autodma ? - ", auto-enable" : ""); + printk(" capable%s\n", hwif->autodma ? ", auto-enable" : ""); return 1; failed: - printk(" -- ERROR, unable to allocate DMA table\n"); + printk(" disabled, unable to allocate DMA table\n"); return 0; } + +static void icside_dma_exit(ide_hwif_t *hwif) +{ + if (hwif->sg_table) { + kfree(hwif->sg_table); + hwif->sg_table = NULL; + } +} +#else +#define icside_dma_init(hwif) (0) +#define icside_dma_exit(hwif) do { } while (0) #endif -static ide_hwif_t * -icside_find_hwif(unsigned long dataport) +static ide_hwif_t *icside_find_hwif(unsigned long dataport) { ide_hwif_t *hwif; int index; @@ -716,13 +780,13 @@ goto found; } - return NULL; + hwif = NULL; found: return hwif; } static ide_hwif_t * -icside_setup(unsigned long base, struct cardinfo *info, int irq) +icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec) { unsigned long port = base + info->dataoffset; ide_hwif_t *hwif; @@ -740,8 +804,8 @@ } hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - hwif->hw.irq = irq; - hwif->irq = irq; + hwif->hw.irq = ec->irq; + hwif->irq = ec->irq; hwif->hw.dma = NO_DMA; hwif->noprobe = 0; hwif->chipset = ide_acorn; @@ -750,33 +814,39 @@ return hwif; } -static int __init icside_register_v5(struct expansion_card *ec, int autodma) +static int __init +icside_register_v5(struct icside_state *state, struct expansion_card *ec) { unsigned long slot_port; ide_hwif_t *hwif; slot_port = ecard_address(ec, ECARD_MEMC, 0); + state->irq_port = slot_port; + ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); ec->irqmask = 1; - ec->irq_data = (void *)slot_port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; + ec->irq_data = state; + ec->ops = &icside_ops_arcin_v5; /* * Be on the safe side - disable interrupts */ inb(slot_port + ICS_ARCIN_V5_INTROFFSET); - hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); + hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec); - return hwif ? 0 : -1; + state->hwif[0] = hwif; + + return hwif ? 0 : -ENODEV; } -static int __init icside_register_v6(struct expansion_card *ec, int autodma) +static int __init +icside_register_v6(struct icside_state *state, struct expansion_card *ec) { unsigned long slot_port, port; ide_hwif_t *hwif, *mate; - int sel = 0; + unsigned int sel = 0; slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); port = ecard_address(ec, ECARD_EASI, ECARD_FAST); @@ -788,88 +858,185 @@ outb(sel, slot_port); - ec->irq_data = (void *)port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; - /* * Be on the safe side - disable interrupts */ inb(port + ICS_ARCIN_V6_INTROFFSET_1); inb(port + ICS_ARCIN_V6_INTROFFSET_2); - hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); - mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); + /* + * Find and register the interfaces. + */ + hwif = icside_setup(port, &icside_cardinfo_v6_1, ec); + mate = icside_setup(port, &icside_cardinfo_v6_2, ec); + + if (!hwif || !mate) + return -ENODEV; -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS - if (ec->dma != NO_DMA) { - if (request_dma(ec->dma, hwif->name)) - goto no_dma; - - if (hwif) { - hwif->config_data = slot_port; - hwif->select_data = sel; - hwif->hw.dma = ec->dma; - hwif->hw.priv = (void *) - (port + ICS_ARCIN_V6_INTRSTAT_1); - hwif->channel = 0; - icside_setup_dma(hwif, autodma); - hwif->drives[0].autodma = autodma; - hwif->drives[1].autodma = autodma; - } - if (mate) { - mate->config_data = slot_port; - mate->select_data = sel | 1; - mate->hw.dma = ec->dma; - mate->hw.priv = (void *) - (port + ICS_ARCIN_V6_INTRSTAT_2); - mate->channel = 1; - icside_setup_dma(mate, autodma); - mate->drives[0].autodma = autodma; - mate->drives[1].autodma = autodma; - } + state->irq_port = port; + state->slot_port = slot_port; + state->hwif[0] = hwif; + state->hwif[1] = mate; + + ec->irq_data = state; + ec->ops = &icside_ops_arcin_v6; + + hwif->maskproc = icside_maskproc; + hwif->channel = 0; + hwif->hwif_data = state; + hwif->mate = mate; + hwif->serialized = 1; + hwif->config_data = slot_port; + hwif->select_data = sel; + hwif->hw.dma = ec->dma; + + mate->maskproc = icside_maskproc; + mate->channel = 1; + mate->hwif_data = state; + mate->mate = hwif; + mate->serialized = 1; + mate->config_data = slot_port; + mate->select_data = sel | 1; + mate->hw.dma = ec->dma; + + if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { + icside_dma_init(hwif); + icside_dma_init(mate); } -no_dma: -#endif - return hwif || mate ? 0 : -1; + return 0; } -int __init icside_init(void) +static int __init icside_probe(struct expansion_card *ec, const struct ecard_id *id) { - int autodma = 0; + struct icside_state *state; + int ret; -#ifdef CONFIG_IDEDMA_ICS_AUTO - autodma = 1; -#endif + state = kmalloc(sizeof(struct icside_state), GFP_KERNEL); + if (!state) { + ret = -ENOMEM; + goto out; + } - ecard_startfind (); + memset(state, 0, sizeof(struct icside_state)); + state->type = ICS_TYPE_NOTYPE; - do { - struct expansion_card *ec; - int result; + { + unsigned int addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; + unsigned int type; - ec = ecard_find(0, icside_cids); - if (ec == NULL) - break; + type = inb(addr) & 1; + type |= (inb(addr + 1) & 1) << 1; + type |= (inb(addr + 2) & 1) << 2; + type |= (inb(addr + 3) & 1) << 3; - ecard_claim(ec); + state->type = type; + } - switch (icside_identifyif(ec)) { - case ics_if_arcin_v5: - result = icside_register_v5(ec, autodma); - break; + switch (state->type) { + case ICS_TYPE_A3IN: + printk(KERN_WARNING "icside: A3IN unsupported\n"); + ret = -ENODEV; + break; - case ics_if_arcin_v6: - result = icside_register_v6(ec, autodma); - break; + case ICS_TYPE_A3USER: + printk(KERN_WARNING "icside: A3USER unsupported\n"); + ret = -ENODEV; + break; - default: - result = -1; - break; - } + case ICS_TYPE_V5: + ret = icside_register_v5(state, ec); + break; - if (result) - ecard_release(ec); - } while (1); + case ICS_TYPE_V6: + ret = icside_register_v6(state, ec); + break; - return 0; + default: + printk(KERN_WARNING "icside: unknown interface type\n"); + ret = -ENODEV; + break; + } + + if (ret == 0) { + ecard_set_drvdata(ec, state); + } else { + kfree(state); + } + out: + return ret; +} + +static void __devexit icside_remove(struct expansion_card *ec) +{ + struct icside_state *state = ecard_get_drvdata(ec); + + switch (state->type) { + case ICS_TYPE_V5: + /* FIXME: tell IDE to stop using the interface */ + + /* Disable interrupts */ + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET); + break; + + case ICS_TYPE_V6: + /* FIXME: tell IDE to stop using the interface */ + icside_dma_exit(state->hwif[1]); + icside_dma_exit(state->hwif[0]); + + if (ec->dma != NO_DMA) + free_dma(ec->dma); + + /* Disable interrupts */ + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + + /* Reset the ROM pointer/EASI selection */ + outb(0, state->slot_port); + break; + } + + ecard_set_drvdata(ec, NULL); + ec->ops = NULL; + ec->irq_data = NULL; + + kfree(state); +} + +static void icside_shutdown(struct expansion_card *ec) +{ + struct icside_state *state = ecard_get_drvdata(ec); + + switch (state->type) { + case ICS_TYPE_V5: + /* Disable interrupts */ + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET); + break; + + case ICS_TYPE_V6: + /* Disable interrupts */ + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + + /* Reset the ROM pointer/EASI selection */ + outb(0, state->slot_port); + break; + } +} + +static const struct ecard_id icside_ids[] = { + { MANU_ICS, PROD_ICS_IDE }, + { MANU_ICS2, PROD_ICS2_IDE }, + { 0xffff, 0xffff } +}; + +static struct ecard_driver icside_driver = { + .probe = icside_probe, + .remove = __devexit_p(icside_remove), + .shutdown = icside_shutdown, + .id_table = icside_ids, +}; + +int __init icside_init(void) +{ + return ecard_register_driver(&icside_driver); } diff -urN orig/drivers/ide/arm/rstation-ide.c linux/drivers/ide/arm/rstation-ide.c --- orig/drivers/ide/arm/rstation-ide.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/ide/arm/rstation-ide.c Tue Jan 21 23:21:47 2003 @@ -0,0 +1,78 @@ +/* + * linux/drivers/ide/rs-ide.c + * + * Copyright (c) 2002 Ben Dooks + * Copyright (c) 2002 Simtec Electronics + * + * Simple RiscStation IDE support +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef CONFIG_ARCH_RISCSTATION +#error "compiling this code for non-riscstation hardware is dangerous!" +#endif + +#define DRV_PREFIX "ide-rs" + +#define IRQ_PRI (40+3) +#define IRQ_SEC (40+4) + +#define PORT_BASE ((0x2b800 - 0x10000) >> 2) +#define SEC_OFF (0x400 >> 2) + +int __init rside_reg(unsigned long base, unsigned int irq); + +int __init rside_init(void) +{ + int iotcr; + + if (!machine_is_riscstation()) { + printk(DRV_PREFIX ": hardware is not a RiscStation!\n"); + return 0; + } + + /* select correct area cycle time */ + + iotcr = inb(IOMD_IOTCR); + outb((iotcr & ~3) | 1, IOMD_IOTCR); + + /* register h/w */ + + rside_reg(PORT_BASE, IRQ_PRI); + rside_reg(PORT_BASE + SEC_OFF, IRQ_SEC); + + return 0; +} + + +int __init rside_reg(unsigned long port, unsigned int irq) +{ + unsigned long addr, i; + hw_regs_t hw; + + hw.irq = irq; + + addr = port; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw.io_ports[i] = (ide_ioreg_t)addr; + addr += 0x40 >> 2; + } + + hw.io_ports[IDE_CONTROL_OFFSET] = port + ((0xb80 - 0x800) >> 2); + + printk(DRV_PREFIX ": registering channel at %08lx, %08lx, irq %d\n", + port, hw.io_ports[IDE_CONTROL_OFFSET], irq); + + return ide_register_hw(&hw, NULL); +} diff -urN orig/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c --- orig/drivers/ide/ide-probe.c Tue Jun 24 13:58:23 2003 +++ linux/drivers/ide/ide-probe.c Wed Jun 25 15:24:58 2003 @@ -1286,11 +1286,11 @@ hwif->name, hwif->major); return (hwif->present = 0); } - + if (init_irq(hwif)) { int i = hwif->irq; /* - * It failed to initialise. Find the default IRQ for + * It failed to initialise. Find the default IRQ for * this port and try that. */ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { @@ -1308,7 +1308,7 @@ printk("%s: probed IRQ %d failed, using default.\n", hwif->name, hwif->irq); } - + init_gendisk(hwif); blk_dev[hwif->major].data = hwif; blk_dev[hwif->major].queue = ide_get_queue; diff -urN orig/drivers/ide/ide-proc.c linux/drivers/ide/ide-proc.c --- orig/drivers/ide/ide-proc.c Tue Jun 24 13:58:23 2003 +++ linux/drivers/ide/ide-proc.c Tue Jun 24 13:40:09 2003 @@ -425,6 +425,7 @@ case ide_cy82c693: name = "cy82c693"; break; case ide_4drives: name = "4drives"; break; case ide_pmac: name = "pmac"; break; + case ide_acorn: name = "acorn"; break; default: name = "(unknown)"; break; } len = sprintf(page, "%s\n", name); diff -urN orig/drivers/ide/ide.c linux/drivers/ide/ide.c --- orig/drivers/ide/ide.c Tue Jun 24 13:58:24 2003 +++ linux/drivers/ide/ide.c Tue Jun 24 15:30:10 2003 @@ -218,23 +218,14 @@ static void init_hwif_data (unsigned int index) { unsigned int unit; - hw_regs_t hw; ide_hwif_t *hwif = &ide_hwifs[index]; /* bulk initialize hwif & drive info with zeros */ memset(hwif, 0, sizeof(ide_hwif_t)); - memset(&hw, 0, sizeof(hw_regs_t)); /* fill in any non-zero initial values */ hwif->index = index; - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq); - memcpy(&hwif->hw, &hw, sizeof(hw)); - memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; -#ifdef CONFIG_BLK_DEV_HD - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) - hwif->noprobe = 1; /* may be overridden by ide_setup() */ -#endif /* CONFIG_BLK_DEV_HD */ + hwif->noprobe = 1; hwif->major = ide_hwif_to_major[index]; hwif->name[0] = 'i'; hwif->name[1] = 'd'; @@ -275,6 +266,28 @@ } /* + * Old compatability function - initialise ports using ide_default_io_base + */ +static void ide_old_init_default_hwifs(void) +{ + unsigned int index; + ide_ioreg_t base; + ide_hwif_t *hwif; + + for (index = 0; index < MAX_HWIFS; index++) { + hwif = &ide_hwifs[index]; + + base = ide_default_io_base(index); + + if (base) { + ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->hw.irq); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); + hwif->noprobe = 0; + } + } +} + +/* * init_ide_data() sets reasonable default values into all fields * of all instances of the hwifs and drives, but only on the first call. * Subsequent calls have no effect (they don't wipe out anything). @@ -306,6 +319,7 @@ init_hwif_data(index); /* Add default hw interfaces */ + ide_old_init_default_hwifs(); ide_init_default_hwifs(); idebus_parameter = 0; @@ -2263,6 +2277,12 @@ rapide_init(); } #endif /* CONFIG_BLK_DEV_IDE_RAPIDE */ +#ifdef CONFIG_BLK_DEV_IDE_RISCSTATION + { + extern void rside_init(void); + rside_init(); + } +#endif /* CONFIG_BLK_DEV_IDE_RISCSTATION */ #ifdef CONFIG_BLK_DEV_GAYLE { extern void gayle_init(void); diff -urN orig/drivers/ide/pci/Makefile linux/drivers/ide/pci/Makefile --- orig/drivers/ide/pci/Makefile Tue Jun 24 13:58:25 2003 +++ linux/drivers/ide/pci/Makefile Tue Jun 24 20:17:49 2003 @@ -15,7 +15,6 @@ obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o -obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o diff -urN orig/drivers/ide/pci/sl82c105.c linux/drivers/ide/pci/sl82c105.c --- orig/drivers/ide/pci/sl82c105.c Tue Jun 24 13:58:26 2003 +++ linux/drivers/ide/pci/sl82c105.c Sat Jun 28 12:39:33 2003 @@ -37,7 +37,7 @@ #ifdef DEBUG #define DBG(arg) printk arg #else -#define DBG(fmt,...) +#define DBG(fmt...) #endif /* * SL82C105 PCI config register 0x40 bits. diff -urN orig/drivers/ide/pci/sl82c105.c.2419 linux/drivers/ide/pci/sl82c105.c.2419 --- orig/drivers/ide/pci/sl82c105.c.2419 Thu Jan 1 01:00:00 1970 +++ linux/drivers/ide/pci/sl82c105.c.2419 Sat Mar 30 19:19:18 2002 @@ -0,0 +1,380 @@ +/* + * linux/drivers/ide/sl82c105.c + * + * SL82C105/Winbond 553 IDE driver + * + * Maintainer unknown. + * + * Changelog: + * + * 15/11/1998 RMK Drive tuning added from Rebel.com's kernel + * sources + * 30/03/2002 RMK Add fixes specified in W83C553F errata. + * (with special thanks to Todd Inglett) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" + +extern char *ide_xfer_verbose (byte xfer_rate); + +/* + * SL82C105 PCI config register 0x40 bits. + */ +#define CTRL_IDE_IRQB (1 << 30) +#define CTRL_IDE_IRQA (1 << 28) +#define CTRL_LEGIRQ (1 << 11) +#define CTRL_P1F16 (1 << 5) +#define CTRL_P1EN (1 << 4) +#define CTRL_P0F16 (1 << 1) +#define CTRL_P0EN (1 << 0) + +/* + * Convert a PIO mode and cycle time to the required on/off + * times for the interface. This has protection against run-away + * timings. + */ +static unsigned int get_timing_sl82c105(ide_pio_data_t *p) +{ + unsigned int cmd_on; + unsigned int cmd_off; + + cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30; + cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30; + + if (cmd_on > 32) + cmd_on = 32; + if (cmd_on == 0) + cmd_on = 1; + + if (cmd_off > 32) + cmd_off = 32; + if (cmd_off == 0) + cmd_off = 1; + + return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00); +} + +/* + * Configure the drive and chipset for PIO + */ +static void config_for_pio(ide_drive_t *drive, int pio, int report) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + ide_pio_data_t p; + unsigned short drv_ctrl = 0x909; + unsigned int xfer_mode, reg; + + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); + + pio = ide_get_best_pio_mode(drive, pio, 5, &p); + + switch (pio) { + default: + case 0: xfer_mode = XFER_PIO_0; break; + case 1: xfer_mode = XFER_PIO_1; break; + case 2: xfer_mode = XFER_PIO_2; break; + case 3: xfer_mode = XFER_PIO_3; break; + case 4: xfer_mode = XFER_PIO_4; break; + } + + if (ide_config_drive_speed(drive, xfer_mode) == 0) + drv_ctrl = get_timing_sl82c105(&p); + + if (drive->using_dma == 0) { + /* + * If we are actually using MW DMA, then we can not + * reprogram the interface drive control register. + */ + pci_write_config_word(dev, reg, drv_ctrl); + pci_read_config_word(dev, reg, &drv_ctrl); + + if (report) { + printk("%s: selected %s (%dns) (%04X)\n", drive->name, + ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl); + } + } +} + +/* + * Configure the drive and the chipset for DMA + */ +static int config_for_dma(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + unsigned short drv_ctrl = 0x909; + unsigned int reg; + + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); + + if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0) + drv_ctrl = 0x0240; + + pci_write_config_word(dev, reg, drv_ctrl); + + return 0; +} + + +/* + * Check to see if the drive and + * chipset is capable of DMA mode + */ +static int sl82c105_check_drive(ide_drive_t *drive) +{ + ide_dma_action_t dma_func = ide_dma_off_quietly; + + do { + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + + if (!hwif->autodma) + break; + + if (!id || !(id->capability & 1)) + break; + + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + break; + } + + if (id->field_valid & 2) { + if (id->dma_mword & 7 || id->dma_1word & 7) + dma_func = ide_dma_on; + break; + } + + if (ide_dmaproc(ide_dma_good_drive, drive)) { + dma_func = ide_dma_on; + break; + } + } while (0); + + return HWIF(drive)->dmaproc(dma_func, drive); +} + +/* + * The SL82C105 holds off all IDE interrupts while in DMA mode until + * all DMA activity is completed. Sometimes this causes problems (eg, + * when the drive wants to report an error condition). + * + * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller + * state machine. We need to kick this to work around various bugs. + */ +static inline void sl82c105_reset_host(struct pci_dev *dev) +{ + u16 val; + + pci_read_config_word(dev, 0x7e, &val); + pci_write_config_word(dev, 0x7e, val | (1 << 2)); + pci_write_config_word(dev, 0x7e, val & ~(1 << 2)); +} + +/* + * If we get an IRQ timeout, it might be that the DMA state machine + * got confused. Fix from Todd Inglett. Details from Winbond. + * + * This function is called when the IDE timer expires, the drive + * indicates that it is READY, and we were waiting for DMA to complete. + */ +static int sl82c105_lostirq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; + unsigned long dma_base = hwif->dma_base; + + printk("sl82c105: lost IRQ: resetting host\n"); + + /* + * Check the raw interrupt from the drive. + */ + pci_read_config_dword(dev, 0x40, &val); + if (val & mask) + printk("sl82c105: drive was requesting IRQ, but host lost it\n"); + + /* + * Was DMA enabled? If so, disable it - we're resetting the + * host. The IDE layer will be handling the drive for us. + */ + val = inb(dma_base); + if (val & 1) { + outb(val & ~1, dma_base); + printk("sl82c105: DMA was enabled\n"); + } + + sl82c105_reset_host(dev); + + /* ide_dmaproc would return 1, so we do as well */ + return 1; +} + +/* + * ATAPI devices can cause the SL82C105 DMA state machine to go gaga. + * Winbond recommend that the DMA state machine is reset prior to + * setting the bus master DMA enable bit. + * + * The generic IDE core will have disabled the BMEN bit before this + * function is called. + */ +static void sl82c105_before_bm_enable(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + sl82c105_reset_host(dev); +} + +/* + * Our very own dmaproc. We need to intercept various calls + * to fix up the SL82C105 specific behaviour. + */ +static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + return sl82c105_check_drive(drive); + + case ide_dma_on: + if (config_for_dma(drive)) + func = ide_dma_off; + /* fall through */ + + case ide_dma_off_quietly: + case ide_dma_off: + config_for_pio(drive, 4, 0); + break; + + case ide_dma_read: + case ide_dma_write: + case ide_dma_begin: + case ide_dma_timeout: + sl82c105_before_bm_enable(drive); + break; + + case ide_dma_lostirq: + return sl82c105_lostirq(drive); + + default: + break; + } + return ide_dmaproc(func, drive); +} + +/* + * We only deal with PIO mode here - DMA mode 'using_dma' is not + * initialised at the point that this function is called. + */ +static void tune_sl82c105(ide_drive_t *drive, byte pio) +{ + config_for_pio(drive, pio, 1); + + /* + * We support 32-bit I/O on this interface, and it + * doesn't have problems with interrupts. + */ + drive->io_32bit = 1; + drive->unmask = 1; +} + +/* + * Return the revision of the Winbond bridge + * which this function is part of. + */ +static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) +{ + struct pci_dev *bridge; + unsigned char rev; + + /* + * The bridge should be part of the same device, but function 0. + */ + bridge = pci_find_slot(dev->bus->number, + PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); + if (!bridge) + return -1; + + /* + * Make sure it is a Winbond 553 and is an ISA bridge. + */ + if (bridge->vendor != PCI_VENDOR_ID_WINBOND || + bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || + bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) + return -1; + + /* + * We need to find function 0's revision, not function 1 + */ + pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); + + return rev; +} + +/* + * Enable the PCI device + */ +unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg) +{ + u32 val; + + pci_read_config_dword(dev, 0x40, &val); + val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1EN | CTRL_P1F16; + pci_write_config_dword(dev, 0x40, val); + + return dev->irq; +} + +void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) +{ + unsigned int bridge_rev; + byte dma_state; + + dma_state = inb(dma_base + 2); + bridge_rev = sl82c105_bridge_revision(hwif->pci_dev); + if (bridge_rev <= 5) { + hwif->autodma = 0; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", + hwif->name, bridge_rev); + dma_state &= ~0x60; + } else { + dma_state |= 0x60; + hwif->autodma = 1; + } + outb(dma_state, dma_base + 2); + + ide_setup_dma(hwif, dma_base, 8); + + if (bridge_rev <= 5) + hwif->dmaproc = NULL; + else + hwif->dmaproc = sl82c105_dmaproc; +} + +/* + * Initialise the chip + */ +void __init ide_init_sl82c105(ide_hwif_t *hwif) +{ + hwif->tuneproc = tune_sl82c105; +} + diff -urN orig/drivers/input/Config.in linux/drivers/input/Config.in --- orig/drivers/input/Config.in Mon Oct 1 23:10:45 2001 +++ linux/drivers/input/Config.in Fri Jun 13 22:35:16 2003 @@ -14,5 +14,6 @@ fi dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT +dep_tristate ' MX1 touchscreen support' CONFIG_INPUT_MX1TS $CONFIG_INPUT_MOUSEDEV $CONFIG_ARCH_MX1ADS endmenu diff -urN orig/drivers/input/Makefile linux/drivers/input/Makefile --- orig/drivers/input/Makefile Sun Dec 31 22:12:23 2000 +++ linux/drivers/input/Makefile Fri Jun 13 22:35:16 2003 @@ -24,6 +24,7 @@ obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o obj-$(CONFIG_INPUT_JOYDEV) += joydev.o obj-$(CONFIG_INPUT_EVDEV) += evdev.o +obj-$(CONFIG_INPUT_MX1TS) += mx1ts.o # The global Rules.make. diff -urN orig/drivers/input/mx1ts.c linux/drivers/input/mx1ts.c --- orig/drivers/input/mx1ts.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/input/mx1ts.c Fri Jun 13 22:35:16 2003 @@ -0,0 +1,508 @@ +/* + * linux/drivers/misc/mx1ts.c + * + * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc. + * + * Cloned from ucb1x00_ts.c + * + * 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 "mx1ts.h" + +#define DEV_IRQ_ID "mx1-ts" + +struct mx1_ts { + struct input_dev idev; +#ifdef CONFIG_PM + struct pm_dev *pmdev; +#endif + + wait_queue_head_t irq_wait; + struct completion init_exit; + int use_count; + u16 x_res; + u16 y_res; + + int restart:1; +}; + +static struct mx1_ts mx1ts; +static u8 mx1_performing_auto_calibration = 0; +static u16 mx1_cal_auto_zero = 0; +static u16 mx1_cal_range_x = 0; +static u16 mx1_cal_range_y = 0; + +static int mx1_ts_startup(struct mx1_ts *ts); +static void mx1_ts_shutdown(struct mx1_ts *ts); + +static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs); +static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs); +static void mx1_ts_compare_int(int irq, void *dev_id, struct pt_regs *regs); + +static void mx1_ts_enable_pen_touch_interrupt(void); +static void mx1_ts_disable_pen_touch_interrupt(void); +static void mx1_ts_enable_pen_up_interrupt(void); +static void mx1_ts_disable_pen_up_interrupt(void); +static void mx1_ts_enable_auto_sample(void); +static void mx1_ts_disable_auto_sample(void); +static void mx1_ts_start_auto_calibration(void); + +static inline void mx1_reg_write(unsigned int reg, unsigned int val) +{ + *((volatile unsigned int *)reg) = val; +} + +static inline unsigned int mx1_reg_read(unsigned int reg) +{ + return *((volatile unsigned int *)reg); +} + +static inline void mx1_reg_clear_bit(unsigned int reg, unsigned int bit) +{ + *((volatile unsigned int *)reg) &= ~bit; +} + +static inline void mx1_reg_set_bit(unsigned int reg, unsigned int bit) +{ + *((volatile unsigned int *)reg) |= bit; +} + +static inline void mx1_ts_evt_add(struct mx1_ts *ts, u16 pressure, u16 x, u16 y) +{ + input_report_abs(&ts->idev, ABS_X, (int)x - 32768); + input_report_abs(&ts->idev, ABS_Y, (int)y - 32768); + input_report_abs(&ts->idev, ABS_PRESSURE, (int)pressure); +} + +static inline void mx1_ts_flush_fifo(void) +{ + int i; + for (i = 0; i < 12; i++) + if (mx1_reg_read(ASP_ISTATR) & (ASP_PFF | ASP_PDR)) + mx1_reg_read(ASP_PADFIFO); +} + +static int mx1_ts_open(struct input_dev *idev) +{ + struct mx1_ts *ts = (struct mx1_ts *)idev; + + mx1_performing_auto_calibration = 0; + return mx1_ts_startup(ts); +} + +static void mx1_ts_close(struct input_dev *idev) +{ + struct mx1_ts *ts = (struct mx1_ts *)idev; + + mx1_ts_shutdown(ts); +} + +static inline int mx1_ts_enable_irqs(void) +{ + int result; + + result = request_irq(ASP_PENDATA_IRQ, + mx1_ts_pendata_int, + SA_INTERRUPT, + DEV_IRQ_ID, + DEV_IRQ_ID); + if (result) { + printk("Couldn't request pen data IRQ.\n"); + return result; + } + + result = request_irq(ASP_TOUCH_IRQ, + mx1_ts_touch_int, + SA_INTERRUPT, + DEV_IRQ_ID, + DEV_IRQ_ID); + if (result) { + printk("Couldn't request pen touch IRQ.\n"); + free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID); + return result; + } + + return result; +} + +static inline int mx1_ts_disable_irqs(void) +{ + free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID); + free_irq(ASP_TOUCH_IRQ, DEV_IRQ_ID); + + return 0; +} + +static inline int mx1_ts_register(struct mx1_ts *ts) +{ + ts->idev.name = "Touchscreen panel"; + ts->idev.open = mx1_ts_open; + ts->idev.close = mx1_ts_close; + + __set_bit(EV_ABS, ts->idev.evbit); + __set_bit(ABS_X, ts->idev.absbit); + __set_bit(ABS_Y, ts->idev.absbit); + __set_bit(ABS_PRESSURE, ts->idev.absbit); + + ts->idev.absmin[ABS_X] = 0; + ts->idev.absmax[ABS_X] = (u32)0x0000FFFF; + ts->idev.absfuzz[ABS_X] = 50; + ts->idev.absflat[ABS_X] = 0; + + ts->idev.absmin[ABS_Y] = 0; + ts->idev.absmax[ABS_Y] = (u32)0x0000FFFF; + ts->idev.absfuzz[ABS_Y] = 50; + ts->idev.absflat[ABS_Y] = 0; + + input_register_device(&ts->idev); + + return 0; +} + +static inline void mx1_ts_deregister(struct mx1_ts *ts) +{ + input_unregister_device(&ts->idev); +} + +/* + * Handle the touch interrupt, generated when the pen is pressed/ + * released. + */ +static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs) +{ + /* Clear the interrupt. */ + mx1_reg_set_bit(ASP_ISTATR, ASP_PEN); + + mx1_ts_disable_pen_touch_interrupt(); + mx1_ts_start_auto_calibration(); + mx1_ts_enable_pen_up_interrupt(); +} + +/* + * Handle the pen data ready interrupt, generated when pen data is + * in the FIFO. + */ +static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs) +{ + static unsigned int auto_zero, pen_x, pen_y, pen_u; + + if (mx1_reg_read(ASP_ISTATR) & 0x400) { + mx1_reg_set_bit(ASP_ISTATR, 0x400); + + mx1_ts_disable_auto_sample(); + mx1_ts_disable_pen_up_interrupt(); + mx1_ts_enable_pen_touch_interrupt(); + + mx1_ts_evt_add(&mx1ts, 0, pen_x, pen_y); + + mx1_ts_flush_fifo(); + + return; + } + + if (mx1_performing_auto_calibration) { + unsigned int value; + + mx1_cal_auto_zero = mx1_reg_read(ASP_PADFIFO) & 0xFFFF; + mx1_cal_range_x = mx1_reg_read(ASP_PADFIFO) & 0xFFFF; + mx1_cal_range_y = mx1_reg_read(ASP_PADFIFO) & 0xFFFF; + + if ((mx1_cal_auto_zero >= mx1_cal_range_x) || + (mx1_cal_auto_zero >= mx1_cal_range_y)) { + /* Invalid data. */ + mx1_ts_start_auto_calibration(); + return; + } + + mx1_cal_range_x -= mx1_cal_auto_zero; + mx1_cal_range_y -= mx1_cal_auto_zero; + + value = mx1_reg_read(ASP_ACNTLCR); + value &= ~0x04000000; /* XXX Undocumented. */ + mx1_reg_write(ASP_ACNTLCR, value); + + mx1_performing_auto_calibration = 0; + + mx1_ts_enable_auto_sample(); + } else { + /* There could be more than one sample in the FIFO, but we're + * only going to read one per call. The interrupt will be + * generated as long as there is data in the FIFO. */ + + if ((mx1_reg_read(ASP_ISTATR) & ASP_PDR) != ASP_PDR) { + return; + } + + auto_zero = mx1_reg_read(ASP_PADFIFO); + if (auto_zero > (mx1_cal_auto_zero + 0x200)) { + return; + } + + pen_x = mx1_reg_read(ASP_PADFIFO); + pen_y = mx1_reg_read(ASP_PADFIFO); + pen_u = mx1_reg_read(ASP_PADFIFO); + + pen_x = (u32)(((pen_x - mx1_cal_auto_zero) << 16) / + mx1_cal_range_x); + pen_y = (u32)(((pen_y - mx1_cal_auto_zero) << 16) / + mx1_cal_range_y); + + mx1_ts_evt_add(&mx1ts, pen_u, pen_x, pen_y); + } +} + +static void mx1_ts_reset_asp(void) +{ + unsigned int value; + + mx1_ts_flush_fifo(); + + /* Soft reset the ASP module */ + mx1_reg_write(ASP_ACNTLCR, ASP_SWRST); + + /* Read back the reset value of the control register */ + value = mx1_reg_read(ASP_ACNTLCR); + + /* Enable the clock and wait for a short while */ + value |= ASP_CLKEN; + mx1_reg_write(ASP_ACNTLCR, value); + udelay(100); + + /* Set the value of the conrtol register. */ + value = ASP_CLKEN | ASP_NM | ASP_SW6 | ASP_BGE; + mx1_reg_write(ASP_ACNTLCR, value); + + /* Set the clock divide ratio to 2. */ + mx1_reg_write(ASP_CLKDIV, 0x01); + + /* Set the sample rate control register. These values should yield + * about 150 samples per second, which seems to give good smooth + * lines. */ + value = (0x2 << ASP_DMCNT_SCALE) | /* Decimation ratio is 3 */ + (0x1 << ASP_IDLECNT_SCALE) | /* Idle count is 1 clock */ + (0x2 << ASP_DSCNT_SCALE); /* Data setup is 2 clocks */ + mx1_reg_write(ASP_PSMPLRG, value); + + /* Disable the compare function. */ + mx1_reg_write(ASP_CMPCNTL, 0); +} + +static void mx1_ts_enable_auto_sample(void) +{ + unsigned int value; + + mx1_ts_flush_fifo(); + + value = mx1_reg_read(ASP_ACNTLCR); + + /* Set the mode to X then Y */ + value &= ~ASP_MODE_MASK; + value |= ASP_MODE_ONLY_Y; + + /* Enable auto zero. */ + value |= ASP_AZE; + + /* Enable auto sample. */ + value |= ASP_AUTO; + + /* Enable pen A/D. */ + value |= ASP_PADE; + mx1_reg_write(ASP_ACNTLCR, value); + + /* Enable pen data ready and full interrupt. */ + value = mx1_reg_read(ASP_ICNTLR); + value |= ASP_PFFE | ASP_PDRE; + mx1_reg_write(ASP_ICNTLR, value); +} + +static void mx1_ts_disable_auto_sample(void) +{ + unsigned int value; + + value = mx1_reg_read(ASP_ACNTLCR); + + /* Set the mode to none */ + value &= ~ASP_MODE_MASK; + + /* Disable auto zero. */ + value &= ~ASP_AZE; + + /* Disable auto sample. */ + value &= ~ASP_AUTO; + + /* Disable pen A/D. */ + value &= ~ASP_PADE; + mx1_reg_write(ASP_ACNTLCR, value); + + /* Disable pen data ready and full interrupt. */ + value = mx1_reg_read(ASP_ICNTLR); + value &= ~(ASP_PFFE | ASP_PDRE); + mx1_reg_write(ASP_ICNTLR, value); +} + +static void mx1_ts_enable_pen_touch_interrupt(void) +{ + unsigned int value; + + /* Enable pen touch interrupt. */ + value = mx1_reg_read(ASP_ICNTLR); + value |= ASP_EDGE | ASP_PIRQE; + mx1_reg_write(ASP_ICNTLR, value); +} + +static void mx1_ts_disable_pen_touch_interrupt(void) +{ + unsigned int value; + + /* Enable pen touch interrupt. */ + value = mx1_reg_read(ASP_ICNTLR); + value &= ~ASP_PIRQE; + mx1_reg_write(ASP_ICNTLR, value); +} + +static void mx1_ts_enable_pen_up_interrupt(void) +{ + unsigned int value; + + /* Enable pen up interrupt. XXX: This feature is undocumented. */ + value = mx1_reg_read(ASP_ICNTLR); + value |= ASP_PUPE; + mx1_reg_write(ASP_ICNTLR, value); +} + +static void mx1_ts_disable_pen_up_interrupt(void) +{ + unsigned int value; + + /* Enable pen up interrupt. XXX: This feature is undocumented. */ + value = mx1_reg_read(ASP_ICNTLR); + value &= ~ASP_PUPE; + mx1_reg_write(ASP_ICNTLR, value); +} + +static void mx1_ts_start_auto_calibration(void) +{ + unsigned int value; + + mx1_performing_auto_calibration = 1; + + value = mx1_reg_read(ASP_ACNTLCR); + + /* Set the mode to X then Y */ + value &= ~ASP_MODE_MASK; + value |= ASP_MODE_ONLY_X; + + /* Enable auto zero. */ + value |= ASP_AZE; + + /* Enable auto calibrate. XXX: Undocumented bitfield. */ + value |= 0x04000000; + + /* Enable auto sample. */ + value |= ASP_AUTO; + + /* Enable pen A/D. */ + value |= ASP_PADE; + mx1_reg_write(ASP_ACNTLCR, value); + + /* Enable pen data ready and full interrupt. */ + value = mx1_reg_read(ASP_ICNTLR); + value |= ASP_PFFE | ASP_PDRE | ASP_PUPE; + mx1_reg_write(ASP_ICNTLR, value); +} + +static int mx1_ts_startup(struct mx1_ts *ts) +{ + int ret = 0; + + if (ts->use_count++ != 0) + goto out; + + /* + * Reset the ASP. + */ + mx1_ts_reset_asp(); + + + /* + * XXX: Figure out if we need this... + * If we do this at all, we should allow the user to + * measure and read the X and Y resistance at any time. + */ + //ts->x_res = mx1_ts_read_xres(ts); + //ts->y_res = mx1_ts_read_yres(ts); + + mx1_ts_enable_pen_touch_interrupt(); + + out: + if (ret) + ts->use_count--; + return ret; +} + +/* + * Release touchscreen resources. Disable IRQs. + */ +static void mx1_ts_shutdown(struct mx1_ts *ts) +{ + if (--ts->use_count == 0) { + unsigned int value; + + /* Turn off the ADC and associated circuitry. */ + value = mx1_reg_read(ASP_ACNTLCR); + value &= !(ASP_CLKEN | ASP_PADE | ASP_BGE); + mx1_reg_write(ASP_ACNTLCR, value); + } +} + +/* + * Initialization. + */ +static int __init mx1_ts_init(void) +{ + int ret = 0; + struct mx1_ts *ts = &mx1ts; + + mx1_ts_reset_asp(); + + /* + * Enable the IRQ's + */ + if ((ret = mx1_ts_enable_irqs())) + return ret; + + return mx1_ts_register(ts); +} + +static void __exit mx1_ts_exit(void) +{ + struct mx1_ts *ts = &mx1ts; + + mx1_ts_disable_irqs(); + mx1_ts_deregister(ts); +} + +module_init(mx1_ts_init); +module_exit(mx1_ts_exit); + +MODULE_AUTHOR("Jon McClintock "); +MODULE_DESCRIPTION("MX1 touchscreen driver"); +MODULE_LICENSE("GPL"); diff -urN orig/drivers/input/mx1ts.h linux/drivers/input/mx1ts.h --- orig/drivers/input/mx1ts.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/input/mx1ts.h Fri Jun 13 22:35:16 2003 @@ -0,0 +1,108 @@ +/* + * linux/drivers/misc/mx1ts.h + * + * Copyright (C) 2003 Blue Mug, Inc. for Motorola, 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. + * + */ + +/* Interrupt numbers */ +#define ASP_COMPARE_IRQ 5 +#define ASP_PENDATA_IRQ 33 +#define ASP_TOUCH_IRQ 46 + +/* Analog signal processor (ASP) control registers */ +#define ASP_ACNTLCR 0xF0215010 /* Control register */ +#define ASP_PSMPLRG 0xF0215014 /* Pen A/D sampe rate control */ +#define ASP_CMPCNTL 0xF0215030 /* Compare control register */ +#define ASP_ICNTLR 0xF0215018 /* Interrupt control register */ +#define ASP_ISTATR 0xF021501C /* Interrupt status register */ +#define ASP_PADFIFO 0xF0215000 /* Pen sample FIFO */ +#define ASP_CLKDIV 0xF021502C /* Clock divide register */ + +/* ASP control register bits */ +#define ASP_CLKEN (1 << 25) /* Clock enable */ +#define ASP_SWRST (1 << 23) /* Software reset */ +#define ASP_U_SEL (1 << 21) /* U-channel resistor select */ +#define ASP_AZ_SEL (1 << 20) /* Auto-zero position select */ +#define ASP_LVM (1 << 19) /* Low voltage output */ +#define ASP_NM (1 << 18) /* Normal voltage output */ +#define ASP_HPM (1 << 17) /* High voltage output */ +#define ASP_GLO (1 << 16) /* Low gain enable */ +#define ASP_AZE (1 << 15) /* Auto-zero enable */ +#define ASP_AUTO (1 << 14) /* Auto sampling */ +#define ASP_SW8 (1 << 11) /* Switch control 8 */ +#define ASP_SW7 (1 << 10) +#define ASP_SW6 (1 << 9) +#define ASP_SW5 (1 << 8) +#define ASP_SW4 (1 << 7) +#define ASP_SW3 (1 << 6) +#define ASP_SW2 (1 << 5) +#define ASP_SW1 (1 << 4) /* Switch control 1 */ +#define ASP_VDAE (1 << 3) /* Voice D/A enable */ +#define ASP_VADE (1 << 2) /* Voice A/D enable */ +#define ASP_PADE (1 << 1) /* Pen A/D enable */ +#define ASP_BGE (1 << 0) /* Bandgap enable */ + +#define ASP_MODE_MASK 0x00003000 +#define ASP_MODE_NONE 0x00000000 +#define ASP_MODE_ONLY_X 0x00001000 +#define ASP_MODE_ONLY_Y 0x00002000 +#define ASP_MODE_ONLY_U 0x00003000 + +/* ASP Pen A/D sample rate control register */ +#define ASP_DMCNT_MASK (0x00007000) /* Decimation ratio count */ +#define ASP_DMCNT_SCALE (12) +#define ASP_BIT_SELECT_MASK (0x00000C00) /* Bit select */ +#define ASP_BIT_SELECT_SCALE (10) +#define ASP_IDLECNT_MASK (0x000003F0) /* Idle count */ +#define ASP_IDLECNT_SCALE (4) +#define ASP_DSCNT_MASK (0x0000000F) /* Data setup count */ +#define ASP_DSCNT_SCALE (0) + +/* ASP compare control register */ +#define ASP_INT (1 << 19) /* Interrupt status */ +#define ASP_CC (1 << 18) /* Trigger on greater than */ +#define ASP_INSEL_MASK (0x00030000) +#define ASP_INSEL_DISABLE (0x00000000) +#define ASP_INSEL_X (0x00010000) +#define ASP_INSEL_Y (0x00020000) +#define ASP_INSEL_U (0x00030000) +#define ASP_COMPARE_VAL_MASK (0x0000FFFF) +#define ASP_COMPARE_VAL_SCALE (0) + +/* ASP interrupt control register bits */ +#define ASP_PUPE (1 << 10) /* Pen up XXX undocumented */ +#define ASP_VDDMAE (1 << 8) /* VDAC FIFO empty DMA */ +#define ASP_VADMAE (1 << 7) /* VADC FIFO full DMA */ +#define ASP_POL (1 << 6) /* Pen interrupt polarity */ +#define ASP_EDGE (1 << 5) /* Edge trigger enable */ +#define ASP_PIRQE (1 << 4) /* Pen interrupt enable */ +#define ASP_VDAFEE (1 << 3) /* VDAC FIFO empty interrupt */ +#define ASP_VADFFE (1 << 2) /* VADC FIFO full interrupt */ +#define ASP_PFFE (1 << 1) /* Pen FIFO full interrupt */ +#define ASP_PDRE (1 << 0) /* Pen data ready interrupt */ + +/* ASP interrupt/error status register bits */ +#define ASP_PUP (1 << 10) /* Pen up XXX undocumented */ +#define ASP_BGR (1 << 9) /* Bandgap ready */ +#define ASP_VOV (1 << 8) /* Voice sample data overflow */ +#define ASP_POV (1 << 7) /* Pen sample data overflow */ +#define ASP_PEN (1 << 6) /* Pen interrupt */ +#define ASP_VDAFF (1 << 5) /* VDAC FIFO full */ +#define ASP_VDAFE (1 << 4) /* VDAC FIFO empty */ +#define ASP_VADFF (1 << 3) /* VADC FIFO full */ +#define ASP_VADDR (1 << 2) /* VADC data ready */ +#define ASP_PFF (1 << 1) /* Pen sample FIFO full */ +#define ASP_PDR (1 << 0) /* Pen data ready */ + +/* ASP Clock divide register */ +#define ASP_PADC_CLK_MASK (0x0000001F) +#define ASP_PADC_CLK_SCALE (0) +#define ASP_VADC_CLK_MASK (0x000003E0) +#define ASP_VADC_CLK_SCALE (5) +#define ASP_VDAC_CLK_MASK (0x00003C00) +#define ASP_VDAC_CLK_SCALE (10) diff -urN orig/drivers/l3/Config.in linux/drivers/l3/Config.in --- orig/drivers/l3/Config.in Thu Jan 1 01:00:00 1970 +++ linux/drivers/l3/Config.in Sun Sep 23 20:40:19 2001 @@ -0,0 +1,21 @@ +# +# L3 bus configuration +# +mainmenu_option next_comment +comment 'L3 serial bus support' + +tristate 'L3 support' CONFIG_L3 +dep_bool ' L3 bit-banging interfaces' CONFIG_L3_ALGOBIT $CONFIG_L3 +dep_bool ' SA11x0 GPIO adapter' CONFIG_L3_BIT_SA1100_GPIO $CONFIG_L3_ALGOBIT $CONFIG_ARCH_SA1100 + +comment 'Other L3 adapters' +dep_bool ' SA1111 adapter' CONFIG_L3_SA1111 $CONFIG_L3 +endmenu + +# i2c must come before this +if [ "$CONFIG_L3_BIT_SA1100_GPIO" = "y" -o \ + "$CONFIG_I2C_BIT_SA1100_GPIO" = "y" ]; then + define_bool CONFIG_BIT_SA1100_GPIO y +else + define_bool CONFIG_BIT_SA1100_GPIO n +fi diff -urN orig/drivers/l3/Makefile linux/drivers/l3/Makefile --- orig/drivers/l3/Makefile Thu Jan 1 01:00:00 1970 +++ linux/drivers/l3/Makefile Sun Sep 23 20:33:51 2001 @@ -0,0 +1,23 @@ +# +# Makefile for the L3 bus driver. +# + +O_TARGET := l3.o + +export-objs := l3-core.o l3-algo-bit.o +l3-y := +l3-n := +l3-drv-y := +l3-drv-n := + +# Link order: +# (core, adapters, algorithms, drivers) then clients + +l3-$(CONFIG_L3_ALGOBIT) += l3-algo-bit.o +l3-$(CONFIG_BIT_SA1100_GPIO) += l3-bit-sa1100.o +l3-$(CONFIG_L3_SA1111) += l3-sa1111.o + +obj-$(CONFIG_L3) += l3-core.o $(l3-y) $(l3-drv-y) + +include $(TOPDIR)/Rules.make + diff -urN orig/drivers/l3/l3-algo-bit.c linux/drivers/l3/l3-algo-bit.c --- orig/drivers/l3/l3-algo-bit.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/l3/l3-algo-bit.c Tue Oct 23 20:15:55 2001 @@ -0,0 +1,175 @@ +/* + * L3 bus algorithm module. + * + * Copyright (C) 2001 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Note that L3 buses can share the same pins as I2C buses, so we must + * _not_ generate an I2C start condition. An I2C start condition is + * defined as a high-to-low transition of the data line while the clock + * is high. Therefore, we must only change the data line while the + * clock is low. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define setdat(adap,val) adap->setdat(adap->data, val) +#define setclk(adap,val) adap->setclk(adap->data, val) +#define setmode(adap,val) adap->setmode(adap->data, val) +#define setdatin(adap) adap->setdir(adap->data, 1) +#define setdatout(adap) adap->setdir(adap->data, 0) +#define getdat(adap) adap->getdat(adap->data) + +/* + * Send one byte of data to the chip. Data is latched into the chip on + * the rising edge of the clock. + */ +static void sendbyte(struct l3_algo_bit_data *adap, unsigned int byte) +{ + int i; + + for (i = 0; i < 8; i++) { + setclk(adap, 0); + udelay(adap->data_hold); + setdat(adap, byte & 1); + udelay(adap->data_setup); + setclk(adap, 1); + udelay(adap->clock_high); + byte >>= 1; + } +} + +/* + * Send a set of bytes to the chip. We need to pulse the MODE line + * between each byte, but never at the start nor at the end of the + * transfer. + */ +static void sendbytes(struct l3_algo_bit_data *adap, const char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i) { + udelay(adap->mode_hold); + setmode(adap, 0); + udelay(adap->mode); + } + setmode(adap, 1); + udelay(adap->mode_setup); + sendbyte(adap, buf[i]); + } +} + +/* + * Read one byte of data from the chip. Data is latched into the chip on + * the rising edge of the clock. + */ +static unsigned int readbyte(struct l3_algo_bit_data *adap) +{ + unsigned int byte = 0; + int i; + + for (i = 0; i < 8; i++) { + setclk(adap, 0); + udelay(adap->data_hold + adap->data_setup); + setclk(adap, 1); + if (getdat(adap)) + byte |= 1 << i; + udelay(adap->clock_high); + } + + return byte; +} + +/* + * Read a set of bytes from the chip. We need to pulse the MODE line + * between each byte, but never at the start nor at the end of the + * transfer. + */ +static void readbytes(struct l3_algo_bit_data *adap, char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i) { + udelay(adap->mode_hold); + setmode(adap, 0); + } + setmode(adap, 1); + udelay(adap->mode_setup); + buf[i] = readbyte(adap); + } +} + +static int l3_xfer(struct l3_adapter *l3_adap, struct l3_msg msgs[], int num) +{ + struct l3_algo_bit_data *adap = l3_adap->algo_data; + int i; + + /* + * If we share an I2C bus, ensure that it is in STOP mode + */ + setclk(adap, 1); + setdat(adap, 1); + setmode(adap, 1); + setdatout(adap); + udelay(adap->mode); + + for (i = 0; i < num; i++) { + struct l3_msg *pmsg = &msgs[i]; + + if (!(pmsg->flags & L3_M_NOADDR)) { + setmode(adap, 0); + udelay(adap->mode_setup); + sendbyte(adap, pmsg->addr); + udelay(adap->mode_hold); + } + + if (pmsg->flags & L3_M_RD) { + setdatin(adap); + readbytes(adap, pmsg->buf, pmsg->len); + } else { + setdatout(adap); + sendbytes(adap, pmsg->buf, pmsg->len); + } + } + + /* + * Ensure that we leave the bus in I2C stop mode. + */ + setclk(adap, 1); + setdat(adap, 1); + setmode(adap, 0); + setdatin(adap); + + return num; +} + +static struct l3_algorithm l3_bit_algo = { + name: "L3 bit-shift algorithm", + xfer: l3_xfer, +}; + +int l3_bit_add_bus(struct l3_adapter *adap) +{ + adap->algo = &l3_bit_algo; + return l3_add_adapter(adap); +} + +int l3_bit_del_bus(struct l3_adapter *adap) +{ + return l3_del_adapter(adap); +} + +EXPORT_SYMBOL(l3_bit_add_bus); +EXPORT_SYMBOL(l3_bit_del_bus); diff -urN orig/drivers/l3/l3-bit-sa1100.c linux/drivers/l3/l3-bit-sa1100.c --- orig/drivers/l3/l3-bit-sa1100.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/l3/l3-bit-sa1100.c Fri Oct 25 20:29:57 2002 @@ -0,0 +1,277 @@ +/* + * linux/drivers/l3/l3-bit-sa1100.c + * + * Copyright (C) 2001 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. + * + * This is a combined I2C and L3 bus driver. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define NAME "l3-bit-sa1100-gpio" + +struct bit_data { + unsigned int sda; + unsigned int scl; + unsigned int l3_mode; +}; + +static int getsda(void *data) +{ + struct bit_data *bits = data; + + return GPLR & bits->sda; +} + +#ifdef CONFIG_I2C_BIT_SA1100_GPIO +static void i2c_setsda(void *data, int state) +{ + struct bit_data *bits = data; + unsigned long flags; + + local_irq_save(flags); + if (state) + GPDR &= ~bits->sda; + else { + GPCR = bits->sda; + GPDR |= bits->sda; + } + local_irq_restore(flags); +} + +static void i2c_setscl(void *data, int state) +{ + struct bit_data *bits = data; + unsigned long flags; + + local_irq_save(flags); + if (state) + GPDR &= ~bits->scl; + else { + GPCR = bits->scl; + GPDR |= bits->scl; + } + local_irq_restore(flags); +} + +static int i2c_getscl(void *data) +{ + struct bit_data *bits = data; + + return GPLR & bits->scl; +} + +static struct i2c_algo_bit_data i2c_bit_data = { + setsda: i2c_setsda, + setscl: i2c_setscl, + getsda: getsda, + getscl: i2c_getscl, + udelay: 10, + mdelay: 10, + timeout: 100, +}; + +static struct i2c_adapter i2c_adapter = { + name: NAME, + algo_data: &i2c_bit_data, +// inc_use: i2c_inc_use, +// dec_use: i2c_dec_use, +}; + +#define LOCK &i2c_adapter.lock + +static int __init i2c_init(struct bit_data *bits) +{ + i2c_bit_data.data = bits; + return i2c_bit_add_bus(&i2c_adapter); +} + +static void i2c_exit(void) +{ + i2c_bit_del_bus(&i2c_adapter); +} + +#else +static DECLARE_MUTEX(l3_lock); +#define LOCK &l3_lock +#define i2c_init(bits) (0) +#define i2c_exit() do { } while (0) +#endif + +#ifdef CONFIG_L3_BIT_SA1100_GPIO +/* + * iPAQs need the clock line driven hard high and low. + */ +static void l3_setscl(void *data, int state) +{ + struct bit_data *bits = data; + unsigned long flags; + + local_irq_save(flags); + if (state) + GPSR = bits->scl; + else + GPCR = bits->scl; + GPDR |= bits->scl; + local_irq_restore(flags); +} + +static void l3_setsda(void *data, int state) +{ + struct bit_data *bits = data; + + if (state) + GPSR = bits->sda; + else + GPCR = bits->sda; +} + +static void l3_setdir(void *data, int in) +{ + struct bit_data *bits = data; + unsigned long flags; + + local_irq_save(flags); + if (in) + GPDR &= ~bits->sda; + else + GPDR |= bits->sda; + local_irq_restore(flags); +} + +static void l3_setmode(void *data, int state) +{ + struct bit_data *bits = data; + + if (state) + GPSR = bits->l3_mode; + else + GPCR = bits->l3_mode; +} + +static struct l3_algo_bit_data l3_bit_data = { + data: NULL, + setdat: l3_setsda, + setclk: l3_setscl, + setmode: l3_setmode, + setdir: l3_setdir, + getdat: getsda, + data_hold: 1, + data_setup: 1, + clock_high: 1, + mode_hold: 1, + mode_setup: 1, +}; + +static struct l3_adapter l3_adapter = { + owner: THIS_MODULE, + name: NAME, + algo_data: &l3_bit_data, + lock: LOCK, +}; + +static int __init l3_init(struct bit_data *bits) +{ + l3_bit_data.data = bits; + return l3_bit_add_bus(&l3_adapter); +} + +static void __exit l3_exit(void) +{ + l3_bit_del_bus(&l3_adapter); +} +#else +#define l3_init(bits) (0) +#define l3_exit() do { } while (0) +#endif + +static struct bit_data bit_data; + +static int __init bus_init(void) +{ + struct bit_data *bit = &bit_data; + unsigned long flags; + int ret; + + if (machine_is_assabet() || machine_is_pangolin()) { + bit->sda = GPIO_GPIO15; + bit->scl = GPIO_GPIO18; + bit->l3_mode = GPIO_GPIO17; + } + +#if defined(CONFIG_SA1100_H3600) || defined(CONFIG_SA1100_H3100) + if (machine_is_h3600() || machine_is_h3100()) { + bit->sda = GPIO_H3600_L3_DATA; + bit->scl = GPIO_H3600_L3_CLOCK; + bit->l3_mode = GPIO_H3600_L3_MODE; + } +#endif + +#ifdef CONFIG_SA1100_STORK + if (machine_is_stork()) { + bit->sda = GPIO_STORK_L3_I2C_SDA; + bit->scl = GPIO_STORK_L3_I2C_SCL; + bit->l3_mode = GPIO_STORK_L3_MODE; + } +#endif + + if (!bit->sda) + return -ENODEV; + + /* + * Default level for L3 mode is low. + * We set SCL and SDA high (i2c idle state). + */ + local_irq_save(flags); + GPDR &= ~(bit->scl | bit->sda); + GPCR = bit->l3_mode | bit->scl | bit->sda; + GPDR |= bit->l3_mode; + local_irq_restore(flags); + + if (machine_is_assabet()) { + /* + * Release reset on UCB1300, ADI7171 and UDA1341. We + * need to do this here so that we can communicate on + * the I2C/L3 buses. + */ + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); + mdelay(1); + ASSABET_BCR_clear(ASSABET_BCR_CODEC_RST); + mdelay(1); + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); + } + + ret = i2c_init(bit); + if (ret == 0 && bit->l3_mode) { + ret = l3_init(bit); + if (ret) + i2c_exit(); + } + + return ret; +} + +static void __exit bus_exit(void) +{ + l3_exit(); + i2c_exit(); +} + +module_init(bus_init); +module_exit(bus_exit); diff -urN orig/drivers/l3/l3-core.c linux/drivers/l3/l3-core.c --- orig/drivers/l3/l3-core.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/l3/l3-core.c Wed Jul 16 18:45:19 2003 @@ -0,0 +1,377 @@ +/* + * linux/drivers/l3/l3-core.c + * + * Copyright (C) 2001 Russell King + * + * General structure taken from i2c-core.c by Simon G. Vogl + * + * 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. + * + * See linux/Documentation/l3 for further documentation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DECLARE_MUTEX(adapter_lock); +static LIST_HEAD(adapter_list); + +static DECLARE_MUTEX(driver_lock); +static LIST_HEAD(driver_list); + +/** + * l3_add_adapter - register a new L3 bus adapter + * @adap: l3_adapter structure for the registering adapter + * + * Make the adapter available for use by clients using name adap->name. + * The adap->adapters list is initialised by this function. + * + * Returns 0; + */ +int l3_add_adapter(struct l3_adapter *adap) +{ + INIT_LIST_HEAD(&adap->clients); + down(&adapter_lock); + list_add(&adap->adapters, &adapter_list); + up(&adapter_lock); + return 0; +} + +/** + * l3_del_adapter - unregister a L3 bus adapter + * @adap: l3_adapter structure to unregister + * + * Remove an adapter from the list of available L3 Bus adapters. + * + * Returns 0; + */ +int l3_del_adapter(struct l3_adapter *adap) +{ + down(&adapter_lock); + list_del(&adap->adapters); + up(&adapter_lock); + return 0; +} + +static struct l3_adapter *__l3_get_adapter(const char *name) +{ + struct list_head *l; + + list_for_each(l, &adapter_list) { + struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters); + + if (strcmp(adap->name, name) == 0) + return adap; + } + + return NULL; +} + +/** + * l3_get_adapter - get a reference to an adapter + * @name: driver name + * + * Obtain a l3_adapter structure for the specified adapter. If the adapter + * is not currently load, then load it. The adapter will be locked in core + * until all references are released via l3_put_adapter. + */ +struct l3_adapter *l3_get_adapter(const char *name) +{ + struct l3_adapter *adap; + int try; + + for (try = 0; try < 2; try ++) { + down(&adapter_lock); + adap = __l3_get_adapter(name); + if (adap && !try_inc_mod_count(adap->owner)) + adap = NULL; + up(&adapter_lock); + + if (adap) + break; + + if (try == 0) + request_module(name); + } + + return adap; +} + +/** + * l3_put_adapter - release a reference to an adapter + * @adap: driver to release reference + * + * Indicate to the L3 core that you no longer require the adapter reference. + * The adapter module may be unloaded when there are no references to its + * data structure. + * + * You must not use the reference after calling this function. + */ +void l3_put_adapter(struct l3_adapter *adap) +{ + if (adap && adap->owner) + __MOD_DEC_USE_COUNT(adap->owner); +} + +/** + * l3_add_driver - register a new L3 device driver + * @driver - driver structure to make available + * + * Make the driver available for use by clients using name driver->name. + * The driver->drivers list is initialised by this function. + * + * Returns 0; + */ +int l3_add_driver(struct l3_driver *driver) +{ + down(&driver_lock); + list_add(&driver->drivers, &driver_list); + up(&driver_lock); + return 0; +} + +/** + * l3_del_driver - unregister a L3 device driver + * @driver: driver to remove + * + * Remove an driver from the list of available L3 Bus device drivers. + * + * Returns 0; + */ +int l3_del_driver(struct l3_driver *driver) +{ + down(&driver_lock); + list_del(&driver->drivers); + up(&driver_lock); + return 0; +} + +static struct l3_driver *__l3_get_driver(const char *name) +{ + struct list_head *l; + + list_for_each(l, &driver_list) { + struct l3_driver *drv = list_entry(l, struct l3_driver, drivers); + + if (strcmp(drv->name, name) == 0) + return drv; + } + + return NULL; +} + +/** + * l3_get_driver - get a reference to a driver + * @name: driver name + * + * Obtain a l3_driver structure for the specified driver. If the driver is + * not currently load, then load it. The driver will be locked in core + * until all references are released via l3_put_driver. + */ +struct l3_driver *l3_get_driver(const char *name) +{ + struct l3_driver *drv; + int try; + + for (try = 0; try < 2; try ++) { + down(&adapter_lock); + drv = __l3_get_driver(name); + if (drv && !try_inc_mod_count(drv->owner)) + drv = NULL; + up(&adapter_lock); + + if (drv) + break; + + if (try == 0) + request_module(name); + } + + return drv; +} + +/** + * l3_put_driver - release a reference to a driver + * @drv: driver to release reference + * + * Indicate to the L3 core that you no longer require the driver reference. + * The driver module may be unloaded when there are no references to its + * data structure. + * + * You must not use the reference after calling this function. + */ +void l3_put_driver(struct l3_driver *drv) +{ + if (drv && drv->owner) + __MOD_DEC_USE_COUNT(drv->owner); +} + +/** + * l3_attach_client - attach a client to an adapter and driver + * @client: client structure to attach + * @adap: adapter (module) name + * @drv: driver (module) name + * + * Attempt to attach a client (a user of a device driver) to a particular + * driver and adapter. If the specified driver or adapter aren't registered, + * request_module is used to load the relevant modules. + * + * Returns 0 on success, or negative error code. + */ +int l3_attach_client(struct l3_client *client, const char *adap, const char *drv) +{ + struct l3_adapter *adapter = l3_get_adapter(adap); + struct l3_driver *driver = l3_get_driver(drv); + int ret = -ENOENT; + + if (!adapter) + printk(KERN_ERR "%s: unable to get adapter: %s\n", + __FUNCTION__, adap); + if (!driver) + printk(KERN_ERR "%s: unable to get driver: %s\n", + __FUNCTION__, drv); + + if (adapter && driver) { + ret = 0; + + client->adapter = adapter; + client->driver = driver; + + list_add(&client->__adap, &adapter->clients); + + if (driver->attach_client) + ret = driver->attach_client(client); + } + + if (ret) { + l3_put_driver(driver); + l3_put_adapter(adapter); + } + return ret; +} + +/** + * l3_detach_client - detach a client from an adapter and driver + * @client: client structure to detach + * + * Detach the client from the adapter and driver. + */ +int l3_detach_client(struct l3_client *client) +{ + struct l3_adapter *adapter = client->adapter; + struct l3_driver *driver = client->driver; + + driver->detach_client(client); + + client->adapter = NULL; + client->driver = NULL; + + l3_put_driver(driver); + l3_put_adapter(adapter); + + list_del(&client->__adap); + + return 0; +} + +/** + * l3_transfer - transfer information on an L3 bus + * @adap: adapter structure to perform transfer on + * @msgs: array of l3_msg structures describing transfer + * @num: number of l3_msg structures + * + * Transfer the specified messages to/from a device on the L3 bus. + * + * Returns number of messages successfully transferred, otherwise negative + * error code. + */ +int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num) +{ + int ret = -ENOSYS; + + if (adap->algo->xfer) { + down(adap->lock); + ret = adap->algo->xfer(adap, msgs, num); + up(adap->lock); + } + return ret; +} + +/** + * l3_write - send data to a device on an L3 bus + * @client: registered client structure + * @addr: L3 bus address + * @buf: buffer for bytes to send + * @len: number of bytes to send + * + * Send len bytes pointed to by buf to device address addr on the L3 bus + * described by client. + * + * Returns the number of bytes transferred, or negative error code. + */ +int l3_write(struct l3_client *client, int addr, const char *buf, int len) +{ + struct l3_adapter *adap = client->adapter; + struct l3_msg msg; + int ret; + + msg.addr = addr; + msg.flags = 0; + msg.buf = (char *)buf; + msg.len = len; + + ret = l3_transfer(adap, &msg, 1); + return ret == 1 ? len : ret; +} + +/** + * l3_read - receive data from a device on an L3 bus + * @client: registered client structure + * @addr: L3 bus address + * @buf: buffer for bytes to receive + * @len: number of bytes to receive + * + * Receive len bytes from device address addr on the L3 bus described by + * client to a buffer pointed to by buf. + * + * Returns the number of bytes transferred, or negative error code. + */ +int l3_read(struct l3_client *client, int addr, char *buf, int len) +{ + struct l3_adapter *adap = client->adapter; + struct l3_msg msg; + int ret; + + msg.addr = addr; + msg.flags = L3_M_RD; + msg.buf = buf; + msg.len = len; + + ret = l3_transfer(adap, &msg, 1); + return ret == 1 ? len : ret; +} + +EXPORT_SYMBOL(l3_add_adapter); +EXPORT_SYMBOL(l3_del_adapter); +EXPORT_SYMBOL(l3_get_adapter); +EXPORT_SYMBOL(l3_put_adapter); + +EXPORT_SYMBOL(l3_add_driver); +EXPORT_SYMBOL(l3_del_driver); +EXPORT_SYMBOL(l3_get_driver); +EXPORT_SYMBOL(l3_put_driver); + +EXPORT_SYMBOL(l3_attach_client); +EXPORT_SYMBOL(l3_detach_client); + +EXPORT_SYMBOL(l3_transfer); +EXPORT_SYMBOL(l3_write); +EXPORT_SYMBOL(l3_read); diff -urN orig/drivers/l3/l3-sa1111.c linux/drivers/l3/l3-sa1111.c --- orig/drivers/l3/l3-sa1111.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/l3/l3-sa1111.c Mon Aug 5 22:25:08 2002 @@ -0,0 +1,118 @@ +/* + * L3 SA1111 algorithm/adapter module. + * + * By Russell King, + * gratuitously ripped from sa1111-uda1341.c by John Dorsey. + * + * 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 + +static inline unsigned char l3_sa1111_recv_byte(unsigned char addr) +{ + unsigned char dat; + + L3_CAR = addr; + while ((SASR0 & SASR0_L3RD) == 0) + mdelay(1); + dat = L3_CDR; + SASCR = SASCR_RDD; + return dat; +} + +static void l3_sa1111_recv_msg(struct l3_msg *msg) +{ + int len = msg->len; + char *p = msg->buf; + + if (len > 1) { + SACR1 |= SACR1_L3MB; + while ((len--) > 1) + *p++ = l3_sa1111_recv_byte(msg->addr); + } + SACR1 &= ~SACR1_L3MB; + *p = l3_sa1111_recv_byte(msg->addr); +} + +static inline void l3_sa1111_send_byte(unsigned char addr, unsigned char dat) +{ + L3_CAR = addr; + L3_CDR = dat; + while ((SASR0 & SASR0_L3WD) == 0) + mdelay(1); + SASCR = SASCR_DTS; +} + +static void l3_sa1111_send_msg(struct l3_msg *msg) +{ + int len = msg->len; + char *p = msg->buf; + + if (len > 1) { + SACR1 |= SACR1_L3MB; + while ((len--) > 1) + l3_sa1111_send_byte(msg->addr, *p++); + } + SACR1 &= ~SACR1_L3MB; + l3_sa1111_send_byte(msg->addr, *p); +} + +static int l3_sa1111_xfer(struct l3_adapter *adap, struct l3_msg msgs[], int num) +{ + int i; + + for (i = 0; i < num; i++) { + struct l3_msg *pmsg = &msgs[i]; + + if (pmsg->flags & L3_M_RD) + l3_sa1111_recv_msg(pmsg); + else + l3_sa1111_send_msg(pmsg); + } + + return num; +} + +static struct l3_algorithm l3_sa1111_algo = { + name: "L3 SA1111 algorithm", + xfer: l3_sa1111_xfer, +}; + +static DECLARE_MUTEX(sa1111_lock); + +static struct l3_adapter l3_sa1111_adapter = { + owner: THIS_MODULE, + name: "l3-sa1111", + algo: &l3_sa1111_algo, + lock: &sa1111_lock, +}; + +static int __init l3_sa1111_init(void) +{ + int ret = -ENODEV; + if ((machine_is_assabet() && machine_has_neponset()) || + machine_is_jornada720() || machine_is_accelent_sa() || + machine_is_badge4()) + ret = l3_add_adapter(&l3_sa1111_adapter); + return ret; +} + +static void __exit l3_sa1111_exit(void) +{ + l3_del_adapter(&l3_sa1111_adapter); +} + +module_init(l3_sa1111_init); +module_exit(l3_sa1111_exit); diff -urN orig/drivers/media/video/Config.in linux/drivers/media/video/Config.in --- orig/drivers/media/video/Config.in Tue Jun 24 13:58:32 2003 +++ linux/drivers/media/video/Config.in Tue Jun 24 12:02:51 2003 @@ -49,5 +49,8 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI fi +# unfortunately, this depends on having CONFIG_FB_CYBER2000 +# set as well - we hook off of the VGA driver +dep_tristate ' NetWinder Video for Linux (EXPERIMENTAL)' CONFIG_VIDEO_CYBERPRO $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL $CONFIG_ARCH_NETWINDER endmenu diff -urN orig/drivers/media/video/Makefile linux/drivers/media/video/Makefile --- orig/drivers/media/video/Makefile Tue Jun 24 13:58:32 2003 +++ linux/drivers/media/video/Makefile Tue Jun 24 11:18:06 2003 @@ -48,6 +48,7 @@ obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o +obj-$(CONFIG_VIDEO_CYBERPRO) += cyberpro.o i2c-old.o saa7111.o obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o obj-$(CONFIG_VIDEO_PMS) += pms.o obj-$(CONFIG_VIDEO_PLANB) += planb.o diff -urN orig/drivers/media/video/cyberpro.c linux/drivers/media/video/cyberpro.c --- orig/drivers/media/video/cyberpro.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/media/video/cyberpro.c Thu Jun 20 23:22:21 2002 @@ -0,0 +1,2091 @@ +/* + * CyberPro 2000 video capture driver for the Rebel.com NetWinder + * + * (C) 1999-2000 Russell King + * + * Re-written from Rebel.com's vidcap driver. + * + * Architecture + * ------------ + * The NetWinder video capture consists of a SAA7111 video decoder chip + * connected to the CyberPro feature bus. The video data is captured to + * the VGA memory, where the CyberPro can overlay (by chromakeying) the + * data onto the VGA display. + * + * The CyberPro also has some nifty features, including a second overlay + * and picture in picture mode. We do not currently use these features. + * + * Power Saving + * ------------ + * Please note that rev.5 NetWinders have the ability to hold the SAA7111 + * decoder chip into reset, which saves power. The only time at which + * this is done is when the driver is unloaded, which implies that this + * is compiled as a module. + * + * In this case, you will want the kernel to automatically load this + * driver when required. Place the following line in /etc/modules.conf + * to enable this: + * + * alias char-major-81-0 cyberpro + * + * The relevant modules will be automatically loaded by modprobe on a + * as and when needed basis. + * + * Capture resolution + * ------------------ + * The maximum useful capture resolution is: + * 625-line UK: 716x576 + * 525-line US: ? + * + * Bugs + * ---- + * 1. The CyberPro chip seems to be prone to randomly scribbling over VGA + * memory [hopefully fixed with new capture enable/freeze stuff] + * 2. read()ing pauses video capture, and sometimes triggers bug 1. + * 3. mmap() is not supported (requires BM-DMA - see bug 4) + * 4. Really, we want to do scatter BM-DMA. Is the CyberPro capable of this? + * The Cyberpro seems to randomly scribble to various PCI addresses if you + * transfer >16 words. + * 5. We shouldn't ignore O_NONBLOCK when reading a frame. + * 6. The incoming stream on the NetWinder is CCIR656, which is YUV422. + * CyberPro docs also call the format we capture and overlay "YUV422", + * but we actually seem to have Y, U, Y, V bytes (is this YUYV format?) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("CyberPro v4l video grabber"); +MODULE_LICENSE("GPL"); + +#include "../../video/cyber2000fb.h" + +/* + * These enable various experimental features. Most of these + * are just plain broken or just don't work at the moment. + */ +/* + * Enable this if you want mmap() access. (see bug 4) + */ +#undef USE_MMAP + +/* + * Enable this if you want mmio access. (slow) + */ +#define USE_MMIO + +/* + * The V4L API is unclear whether VIDIOCSCAPTURE call is allowed while + * capture is running. The default is to disallow the call. + * + * Define this if you do want to allow the call while capture is active. + */ +#undef ALLOW_SCAPTURE_WHILE_CAP + +/* + * We capture two frames + */ +#define NR_FRAMES 2 + +/* + * One frame of video is 202 pages, assuming YUV422 format, 716x576 + */ +#define NR_PAGES 202 + +struct src_info { + unsigned int offset; /* offset of source data */ + unsigned int x; /* source x */ + unsigned int y; /* source y */ + unsigned int width; /* source width */ + unsigned int height; /* source height */ + unsigned int format; /* source format */ +}; + +struct dst_info { + unsigned int x; /* destination x */ + unsigned int y; /* destination y */ + unsigned int width; /* destination width */ + unsigned int height; /* destination height */ + unsigned int chromakey; /* chromakey */ + unsigned int flags; /* flags (eg, chromakey enable) */ +}; + +struct cyberpro_vidinfo; + +struct win_info { + void (*init)(struct cyberpro_vidinfo *dp, struct win_info *wi); + void (*set_src)(struct cyberpro_vidinfo *dp, struct win_info *wi); + void (*set_win)(struct cyberpro_vidinfo *dp, struct win_info *wi); + void (*ctl)(struct cyberpro_vidinfo *dp, struct win_info *wi, int on_off); + + /* public */ + struct src_info src; + struct dst_info dst; + + /* private */ + unsigned short vid_fifo_ctl; + unsigned char vid_fmt; + unsigned char vid_disp_ctl1; + unsigned char vid_fifo_ctl1; + unsigned char vid_misc_ctl1; +}; + +struct framebuf { + unsigned int offset; /* mmap offset for this frame */ + unsigned int status; +#define FRAME_FREE 0 +#define FRAME_DONE 1 +#define FRAME_WAITING 2 +#define FRAME_GRABBING 3 + + /* + * Bus-Master DMA stuff. Note that we should + * probably use the kiovec stuff instead. + */ + unsigned long bus_addr[NR_PAGES]; /* list of pages */ + struct page *pages[NR_PAGES]; + void *buffer; + int dbg; +}; + +struct cyberpro_vidinfo { + struct video_device *dev; + struct i2c_bus *bus; + struct cyberpro_info info; /* host information */ + unsigned char *regs; + unsigned int irq; /* PCI interrupt number */ + + /* hardware configuration */ + unsigned int stream_fmt; /* format of stream from decoder*/ + + /* software settings */ + unsigned int decoder:1; /* decoder loaded */ + unsigned int interlace:1; /* interlace */ + unsigned int buf_set:1; /* VIDIOCSFBUF has been issued */ + unsigned int win_set:1; /* VIDIOCSWIN has been issued */ + unsigned int cap_active:1; /* capture is active */ + unsigned int ovl_active:1; /* overlay is active */ + unsigned int mmaped:1; /* buffer is mmap()d */ + unsigned int unused:25; + + unsigned int users; /* number of users */ + unsigned long cap_mem_offset; /* capture framebuffer offset */ + void * buffer; /* kernel capture buffer */ + unsigned int norm; /* video standard */ + + struct video_capability cap; /* capabilities */ + struct video_picture pic; /* current picture settings */ + struct video_buffer buf; /* display parameters */ + struct video_capture capt; /* video capture params */ + + struct win_info *ovl; /* overlay window set */ + struct win_info ext; /* "Extended" window info */ + struct win_info v2; /* "V2" window info */ + struct win_info x2; /* "X2" window info */ + + unsigned int bm_offset; /* Cap memory bus master offset */ + unsigned int bm_index; /* Cap page index */ + +#ifdef USE_MMAP + unsigned int frame_idx; /* currently grabbing frame */ + unsigned int frame_size; + struct framebuf frame[NR_FRAMES]; + wait_queue_head_t frame_wait; +#endif + + wait_queue_head_t vbl_wait; + + /* + * cyberpro registers + */ + unsigned char cap_mode1; + unsigned char cap_mode2; + unsigned char cap_miscctl; + unsigned char vfac1; + unsigned char vfac3; +}; + +/* + * Our access methods. + */ +#define cyberpro_writel(val,reg,dp) writel(val, (dp)->regs + (reg)) +#define cyberpro_writew(val,reg,dp) writew(val, (dp)->regs + (reg)) +#define cyberpro_writeb(val,reg,dp) writeb(val, (dp)->regs + (reg)) + +#define cyberpro_readb(reg,dp) readb((dp)->regs + (reg)) + +static inline void +cyberpro_grphw(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp) +{ + cyberpro_writew((reg & 255) | val << 8, 0x3ce, dp); +} + +static void cyberpro_grphw8(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp) +{ + cyberpro_grphw(reg, val, dp); +} + +static unsigned char cyberpro_grphr8(int reg, struct cyberpro_vidinfo *dp) +{ + cyberpro_writeb(reg, 0x3ce, dp); + return cyberpro_readb(0x3cf, dp); +} + +static void cyberpro_grphw16(int reg, unsigned int val, struct cyberpro_vidinfo *dp) +{ + cyberpro_grphw(reg, val, dp); + cyberpro_grphw(reg + 1, val >> 8, dp); +} + +static void cyberpro_grphw24(int reg, unsigned int val, struct cyberpro_vidinfo *dp) +{ + cyberpro_grphw(reg, val, dp); + cyberpro_grphw(reg + 1, val >> 8, dp); + cyberpro_grphw(reg + 2, val >> 16, dp); +} + +#if 0 +static void +cyberpro_dbg_dump(void) +{ + int i; + unsigned char idx[] = + { 0x30, 0x3e, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad }; + printk(KERN_DEBUG); + for (i = 0; i < sizeof(idx); i++) + printk("%02x ", idx[i]); + printk("\n" KERN_DEBUG); + for (i = 0; i < sizeof(idx); i++) + printk("%02x ", cyberpro_grphr8(idx[i])); + printk("\n"); +} +#endif + +/* + * On the NetWinder, we can put the SAA7111 to sleep by holding + * it in reset. + * + * Note: once we have initialised the SAA7111, we can't put it back to + * sleep and expect it to keep its settings. Maybe a better solution + * is to register/de-register the i2c bus in open/release? + */ +static void +decoder_sleep(int sleep) +{ +#ifdef CONFIG_ARCH_NETWINDER + extern spinlock_t gpio_lock; + + spin_lock_irq(&gpio_lock); + cpld_modify(CPLD_7111_DISABLE, sleep ? CPLD_7111_DISABLE : 0); + spin_unlock_irq(&gpio_lock); + + if (!sleep) { + /* + * wait 20ms for device to wake up + */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 50); + } +#endif +} + +/* -------------------------------- I2C support ---------------------------- */ + +#define I2C_DELAY 100 + +static void +cyberpro_i2c_setlines(struct i2c_bus *bus, int ctrl, int data) +{ + struct cyberpro_vidinfo *dp = bus->data; + int v; + + v = (ctrl ? EXT_LATCH2_I2C_CLKEN : 0x00) | (data ? EXT_LATCH2_I2C_DATEN : 0x00); + cyberpro_grphw8(EXT_LATCH2, v, dp); + + udelay(I2C_DELAY); +} + +static int +cyberpro_i2c_getdataline(struct i2c_bus *bus) +{ + struct cyberpro_vidinfo *dp = bus->data; + unsigned long flags; + int v; + + save_flags(flags); + cli(); + + v = cyberpro_grphr8(EXT_LATCH2, dp); + + restore_flags(flags); + + return v & EXT_LATCH2_I2C_DAT ? 1 : 0; +} + +static void +cyberpro_i2c_attach(struct i2c_bus *bus, int id) +{ + struct cyberpro_vidinfo *dp = bus->data; + int zero = 0; + + if (id == I2C_DRIVERID_VIDEODECODER) { + __u16 norm = dp->norm; + i2c_control_device(bus, id, DECODER_SET_NORM, &norm); + i2c_control_device(bus, id, DECODER_SET_PICTURE, &dp->pic); + i2c_control_device(bus, id, DECODER_ENABLE_OUTPUT, &zero); + + dp->decoder = 1; + } +} + +static void +cyberpro_i2c_detach(struct i2c_bus *bus, int id) +{ + struct cyberpro_vidinfo *dp = bus->data; + + if (id == I2C_DRIVERID_VIDEODECODER) + dp->decoder = 0; +} + +static struct i2c_bus cyberpro_i2c_bus = { + name: "", + id: I2C_BUSID_CYBER2000, + bus_lock: SPIN_LOCK_UNLOCKED, + attach_inform: cyberpro_i2c_attach, + detach_inform: cyberpro_i2c_detach, + i2c_setlines: cyberpro_i2c_setlines, + i2c_getdataline: cyberpro_i2c_getdataline, +}; + +/*------------------------- Extended Overlay Window ------------------------- + * Initialise 1st overlay window (works) + */ +static void +cyberpro_ext_init(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + wi->vid_fifo_ctl = 0xf87c; + wi->vid_fmt = EXT_VID_FMT_YUV422; + wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF | + EXT_VID_DISP_CTL1_NOCLIP; + wi->vid_fifo_ctl1 = EXT_VID_FIFO_CTL1_INTERLEAVE | + EXT_VID_FIFO_CTL1_OE_HIGH; + wi->vid_misc_ctl1 = 0; + + cyberpro_grphw8 (EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp); + cyberpro_grphw16(EXT_DDA_X_INIT, 0x0800, dp); + cyberpro_grphw16(EXT_DDA_Y_INIT, 0x0800, dp); + cyberpro_grphw16(EXT_VID_FIFO_CTL, wi->vid_fifo_ctl, dp); + cyberpro_grphw8 (EXT_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp); +} + +/* + * Set the source parameters for the extended window + */ +static void +cyberpro_ext_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + unsigned int phase, pitch; + + pitch = (wi->src.width >> 2) & 0x0fff; + phase = (wi->src.width + 3) >> 2; + + wi->vid_fmt &= ~7; + switch (wi->src.format) { + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break; + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break; + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break; + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break; + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break; + } + + cyberpro_grphw24(EXT_MEM_START, wi->src.offset, dp); + cyberpro_grphw16(EXT_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp); + cyberpro_grphw8 (EXT_SRC_WIN_WIDTH, phase, dp); + cyberpro_grphw8 (EXT_VID_FMT, wi->vid_fmt, dp); +} + +/* + * Set overlay1 window + */ +static void +cyberpro_ext_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + unsigned int xscale, yscale; + unsigned int xoff, yoff; + + /* + * Note: the offset does not appear to be influenced by + * hardware scrolling. + */ + xoff = yoff = 0; + + xoff += wi->dst.x; + yoff += wi->dst.y; + + xscale = wi->src.width; + + if (wi->dst.width >= wi->src.width * 2) { + wi->vid_fmt |= EXT_VID_FMT_DBL_H_PIX; + xscale *= 2; + } else { + wi->vid_fmt &= ~EXT_VID_FMT_DBL_H_PIX; + } + + xscale = ((xscale - /*2*/0) * 4096) / wi->dst.width; + yscale = ((wi->src.height - /*2*/0) * 4096) / wi->dst.height; + + cyberpro_grphw16(EXT_X_START, xoff, dp); + cyberpro_grphw16(EXT_X_END, xoff + wi->dst.width, dp); + cyberpro_grphw16(EXT_Y_START, yoff, dp); + cyberpro_grphw16(EXT_Y_END, yoff + wi->dst.height, dp); + cyberpro_grphw24(EXT_COLOUR_COMPARE, wi->dst.chromakey, dp); + cyberpro_grphw16(EXT_DDA_X_INC, xscale, dp); + cyberpro_grphw16(EXT_DDA_Y_INC, yscale, dp); + cyberpro_grphw8(EXT_VID_FMT, wi->vid_fmt, dp); + + if (wi->dst.flags & VIDEO_WINDOW_CHROMAKEY) + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_IGNORE_CCOMP; + else + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_IGNORE_CCOMP; +} + +/* + * Enable or disable the 1st overlay window. Note that for anything + * useful to be displayed, we must have capture enabled. + */ +static void +cyberpro_ext_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on) +{ + if (on) + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW; + else + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW; + + cyberpro_grphw8(EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp); +} + +/*------------------------------- V2 Overlay Window ------------------------- + * Initialise 2nd overlay window (guesswork) + */ +static void +cyberpro_v2_init(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + wi->vid_fifo_ctl = 0xf87c; + wi->vid_fmt = EXT_VID_FMT_YUV422; + wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF | + EXT_VID_DISP_CTL1_NOCLIP; + wi->vid_fifo_ctl1 = 0x06; + wi->vid_misc_ctl1 = 0; + + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); + cyberpro_grphw8 (Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp); + /* No DDA init values */ + cyberpro_grphw16(Y_V2_VID_FIFO_CTL, wi->vid_fifo_ctl, dp); + cyberpro_grphw8 (Y_V2_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp); +} + +/* + * Set the source parameters for the v2 window + */ +static void +cyberpro_v2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + unsigned int phase, pitch; + + pitch = (wi->src.width >> 2) & 0x0fff; + phase = (wi->src.width + 3) >> 2; + + wi->vid_fmt &= ~7; + switch (wi->src.format) { + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break; + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break; + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break; + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break; + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break; + } + + cyberpro_grphw8(REG_BANK, REG_BANK_X, dp); + cyberpro_grphw24(X_V2_VID_MEM_START, wi->src.offset, dp); + cyberpro_grphw16(X_V2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp); + cyberpro_grphw8 (X_V2_VID_SRC_WIN_WIDTH, phase, dp); + + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); + cyberpro_grphw8(Y_V2_VID_FMT, wi->vid_fmt, dp); +} + +/* + * Set v2 window + */ +static void +cyberpro_v2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + unsigned int xscale, yscale; + unsigned int xoff, yoff; + + /* + * Note: the offset does not appear to be influenced by + * hardware scrolling. + */ + xoff = yoff = 0; + + xoff += wi->dst.x; + yoff += wi->dst.y; + + xscale = (wi->src.width * 4096) / wi->dst.width; + yscale = (wi->src.height * 4096) / wi->dst.height; + + cyberpro_grphw8(REG_BANK, REG_BANK_X, dp); + cyberpro_grphw16(X_V2_X_START, xoff, dp); + cyberpro_grphw16(X_V2_X_END, xoff + wi->dst.width, dp); + cyberpro_grphw16(X_V2_Y_START, yoff, dp); + cyberpro_grphw16(X_V2_Y_END, yoff + wi->dst.height, dp); + + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); + cyberpro_grphw16(Y_V2_DDA_X_INC, xscale, dp); + cyberpro_grphw16(Y_V2_DDA_Y_INC, yscale, dp); +} + +/* + * Enable or disable the 2nd overlay window. Note that for anything + * useful to be displayed, we must have capture enabled. + */ +static void +cyberpro_v2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on) +{ + if (on) + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW; + else + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW; + + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); + cyberpro_grphw8(Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp); +} + +/*--------------------------- X2 Overlay Window ----------------------------- + * Initialise 3rd overlay window (guesswork) + */ +static void +cyberpro_x2_init(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + wi->vid_fmt = EXT_VID_FMT_YUV422; + wi->vid_disp_ctl1 = 0x40; + wi->vid_misc_ctl1 = 0; + + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); + cyberpro_grphw8 (K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp); + cyberpro_grphw16(K_X2_DDA_X_INIT, 0x0800, dp); + cyberpro_grphw16(K_X2_DDA_Y_INIT, 0x0800, dp); +} + +/* + * Set the source parameters for the x2 window + */ +static void +cyberpro_x2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + unsigned int phase, pitch; + + pitch = (wi->src.width >> 2) & 0x0fff; + phase = (wi->src.width + 3) >> 2; + + wi->vid_fmt &= ~7; + switch (wi->src.format) { + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break; + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break; + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break; + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break; + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break; + } + + cyberpro_grphw8(REG_BANK, REG_BANK_J, dp); + cyberpro_grphw24(J_X2_VID_MEM_START, wi->src.offset, dp); + cyberpro_grphw16(J_X2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp); + cyberpro_grphw8 (J_X2_VID_SRC_WIN_WIDTH, phase, dp); + + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); + cyberpro_grphw8(K_X2_VID_FMT, wi->vid_fmt, dp); +} + +/* + * Set x2 window + */ +static void +cyberpro_x2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi) +{ + unsigned int xscale, yscale; + unsigned int xoff, yoff; + + /* + * Note: the offset does not appear to be influenced by + * hardware scrolling. + */ + xoff = yoff = 0; + + xoff += wi->dst.x; + yoff += wi->dst.y; + + xscale = (wi->src.width * 4096) / wi->dst.width; + yscale = (wi->src.height * 4096) / wi->dst.height; + + cyberpro_grphw8(REG_BANK, REG_BANK_J, dp); + cyberpro_grphw16(J_X2_X_START, xoff, dp); + cyberpro_grphw16(J_X2_X_END, xoff + wi->dst.width, dp); + cyberpro_grphw16(J_X2_Y_START, yoff, dp); + cyberpro_grphw16(J_X2_Y_END, yoff + wi->dst.height, dp); + + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); + cyberpro_grphw16(K_X2_DDA_X_INC, xscale, dp); + cyberpro_grphw16(K_X2_DDA_Y_INC, yscale, dp); +} + +/* + * Enable or disable the 3rd overlay window. Note that for anything + * useful to be displayed, we must have capture enabled. + */ +static void +cyberpro_x2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on) +{ + if (on) + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW; + else + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW; + + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); + cyberpro_grphw8(K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp); +} + +/* ------------------------------------------------------------------------- */ + +#if 0 +static void reset_seq(struct cyberpro_vidinfo *dp) +{ + unsigned char ext_mem_ctl = cyberpro_grphr8(0x70, dp); + + cyberpro_grphw8(ext_mem_ctl | 0x80, 0x70, dp); + cyberpro_grphw8(ext_mem_ctl, 0x70, dp); +} +#endif + +#ifdef USE_MMAP +/* + * Buffer support + */ +static int +cyberpro_alloc_frame_buffer(struct cyberpro_vidinfo *dp, + struct framebuf *frame) +{ + unsigned long addr; + void *buffer; + int pgidx; + + if (frame->buffer) + return 0; + + /* + * Allocate frame buffer + */ + buffer = vmalloc(NR_PAGES * PAGE_SIZE); + + if (frame->buffer) { + vfree(buffer); + return 0; + } + + if (!buffer) + return -ENOMEM; + + printk("Buffer allocated @ %p [", buffer); + + frame->buffer = buffer; + frame->dbg = 1; + + /* + * Don't leak information from the kernel. + */ + memset(buffer, 0x5a, NR_PAGES * PAGE_SIZE); + + /* + * Now, reserve all the pages, and calculate + * each pages' bus address. + */ + addr = (unsigned long)buffer; + for (pgidx = 0; pgidx < NR_PAGES; pgidx++, addr += PAGE_SIZE) { + struct page *page; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + /* + * The page should be present. If not, + * vmalloc has gone nuts. + */ + pgd = pgd_offset_k(addr); + if (pgd_none(*pgd)) + BUG(); + pmd = pmd_offset(pgd, addr); + if (pmd_none(*pmd)) + BUG(); + pte = pte_offset(pmd, addr); + if (!pte_present(*pte)) + BUG(); + + page = pte_page(*pte); + + frame->bus_addr[pgidx] = virt_to_bus((void *)page_address(page)); + frame->pages[pgidx] = page; + SetPageReserved(page); + + printk("%08lx (%08lx) ", page_address(page), frame->bus_addr[pgidx]); + } + printk("\n"); + + return 0; +} + +static void +cyberpro_frames_free_one(struct cyberpro_vidinfo *dp, struct framebuf *frame) +{ + void *buffer; + int pgidx; + + frame->status = FRAME_FREE; + buffer = frame->buffer; + frame->buffer = NULL; + + if (buffer) { + for (pgidx = 0; pgidx < NR_PAGES; pgidx++) { + frame->bus_addr[pgidx] = 0; + ClearPageReserved(frame->pages[pgidx]); + frame->pages[pgidx] = NULL; + } + vfree(buffer); + } +} + +static void +cyberpro_busmaster_frame(struct cyberpro_vidinfo *dp, struct framebuf *frame) +{ + unsigned long bus_addr; + + bus_addr = frame->bus_addr[dp->bm_index]; + + if (frame->dbg) { + printk("Frame%d: %06x -> %08lx\n", + dp->frame_idx, + dp->bm_offset, + bus_addr); + } + + cyber2000_outw(dp->bm_offset, BM_VID_ADDR_LOW); + cyber2000_outw(dp->bm_offset >> 16, BM_VID_ADDR_HIGH); + + cyber2000_outw(bus_addr, BM_ADDRESS_LOW); + cyber2000_outw(bus_addr >> 16, BM_ADDRESS_HIGH); + + /* + * One page-full only + */ + cyber2000_outw(1023, BM_LENGTH); + + /* + * Load length + */ + cyber2000_outw(BM_CONTROL_INIT, BM_CONTROL); + + /* + * Enable transfer + */ + cyber2000_outw(BM_CONTROL_ENABLE|BM_CONTROL_IRQEN, BM_CONTROL); + + dp->bm_offset += 1024; + dp->bm_index += 1; +} + +static void cyberpro_busmaster_interrupt(struct cyberpro_vidinfo *dp) +{ + struct framebuf *frame = dp->frame + dp->frame_idx; + + /* + * Disable Busmaster operations + */ + cyber2000_outw(0, BM_CONTROL); + + if (frame->status == FRAME_GRABBING) { + /* + * We are still grabbing this frame to system + * memory. Transfer next page if there are + * more, or else flag this frame as complete. + */ + if (dp->bm_index < NR_PAGES) + cyberpro_busmaster_frame(dp); + else { + unsigned int idx; + + frame->status = FRAME_DONE; + frame->dbg = 0; + + idx = dp->frame_idx + 1; + if (idx >= NR_FRAMES) + idx = 0; + + dp->frame_idx = idx; + + wake_up(&dp->frame_wait); + } + } +} + +static void cyberpro_frames_vbl(struct cyberpro_vidinfo *dp, unsigned int stat) +{ + struct framebuf *frame = dp->frame + dp->frame_idx; + + /* + * No point capturing frames if the grabber isn't active. + */ + if (stat & EXT_ROM_UCB4GH_FREEZE) + return; + + /* + * If the next buffer is ready for grabbing, + * set up the bus master registers for the + * transfer. + */ + if (frame->status == FRAME_WAITING) { + frame->status = FRAME_GRABBING; + + dp->bm_offset = dp->cap_mem_offset; + dp->bm_index = 0; + + cyberpro_busmaster_frame(dp, frame); + } +} + +static void __init cyberpro_frames_init(struct cyberpro_vidinfo *dp) +{ + unsigned int offset, maxsize; + int i; + + init_waitqueue_head(&dp->frame_wait); + + maxsize = 2 * dp->cap.maxwidth * dp->cap.maxheight; + dp->frame_size = PAGE_ALIGN(maxsize); + dp->frame_idx = 0; + + for (i = offset = 0; i < NR_FRAMES; i++) { + dp->frame[i].offset = offset; + dp->frame[i].status = FRAME_FREE; + offset += dp->frame_size; + } +} + +static void cyberpro_frames_free(struct cyberpro_vidinfo *dp) +{ + int i; + + dp->mmaped = 0; + + /* + * Free all frame buffers + */ + for (i = 0; i < NR_FRAMES; i++) + cyberpro_frames_free_one(dp, dp->frame + i); +} + +#else +#define cyberpro_frames_vbl(dp,stat) do { } while (0) +#define cyberpro_frames_init(dp) do { } while (0) +#define cyberpro_frames_free(dp) do { } while (0) +#endif + +/* + * CyberPro Interrupts + * ------------------- + * + * We don't really know how to signal an IRQ clear to the chip. However, + * disabling and re-enabling the capture interrupt enable seems to do what + * we want. + */ +static void cyberpro_interrupt(int nr, void *dev_id, struct pt_regs *regs) +{ + struct cyberpro_vidinfo *dp = dev_id; + unsigned char old_grphidx; + unsigned int status; + + /* + * Save old graphics index register + */ + old_grphidx = cyberpro_readb(0x3ce, dp); + + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); + + /* + * Was it due to the Capture VSYNC? + */ + if (status & EXT_ROM_UCB4GH_INTSTAT) { + /* + * Frob the IRQ enable bit to drop the request. + */ + cyberpro_grphw8(VFAC_CTL3, dp->vfac3 & ~VFAC_CTL3_CAP_IRQ, dp); + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp); + + cyberpro_frames_vbl(dp, status); + wake_up(&dp->vbl_wait); + } + + /* + * Restore graphics controller index + */ + cyberpro_writeb(old_grphidx, 0x3ce, dp); + +#ifdef USE_MMAP + /* + * Do Bus-Master IRQ stuff + */ + if (cyber2000_inb(BM_CONTROL) & (1 << 7)) + cyberpro_busmaster_interrupt(dp); +#endif +} + +static void cyberpro_capture(struct cyberpro_vidinfo *dp, int on) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned int status; + + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); + + add_wait_queue(&dp->vbl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + + if (!!on ^ !(status & EXT_ROM_UCB4GH_FREEZE)) { + if (on) { + schedule_timeout(40 * HZ / 1000); + dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC); + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); + + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); + } else { + dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC; + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); + + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); + if (!(status & EXT_ROM_UCB4GH_FREEZE)) + schedule_timeout(40 * HZ / 1000); + } + } + + current->state = TASK_RUNNING; + remove_wait_queue(&dp->vbl_wait, &wait); +} + +static void cyberpro_capture_one(struct cyberpro_vidinfo *dp) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + unsigned int status; + unsigned long policy, rt_priority; + + policy = tsk->policy; + rt_priority = tsk->rt_priority; + + tsk->policy = SCHED_FIFO; + tsk->rt_priority = 1; + + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); + + add_wait_queue(&dp->vbl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + + schedule_timeout(40 * HZ / 1000); + dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC); + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); + + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(40 * HZ / 1000); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(40 * HZ / 1000); + + dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC; + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); + + set_current_state(TASK_UNINTERRUPTIBLE); + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); + + current->state = TASK_RUNNING; + remove_wait_queue(&dp->vbl_wait, &wait); + + tsk->policy = policy; + tsk->rt_priority = rt_priority; +} + +static void cyberpro_capture_set_win(struct cyberpro_vidinfo *dp) +{ + unsigned int xstart, xend, ystart, yend; + + xstart = 4 + dp->capt.x; + xend = xstart + dp->capt.width; + + if (dp->cap_mode1 & EXT_CAP_MODE1_8BIT) { + /* 8-bit capture */ + xstart *= 2; + xend *= 2; + } + + xstart -= 1; + xend -= 1; + + ystart = 18 + dp->capt.y; + yend = ystart + dp->capt.height / 2; + + cyberpro_grphw16(CAP_X_START, xstart, dp); + cyberpro_grphw16(CAP_X_END, xend + 1, dp); + cyberpro_grphw16(CAP_Y_START, ystart, dp); + cyberpro_grphw16(CAP_Y_END, yend + 2, dp); + + /* + * This should take account of capt.decimation + */ + cyberpro_grphw16(CAP_DDA_X_INIT, 0x0800, dp); + cyberpro_grphw16(CAP_DDA_X_INC, 0x1000, dp); + cyberpro_grphw16(CAP_DDA_Y_INIT, 0x0800, dp); + cyberpro_grphw16(CAP_DDA_Y_INC, 0x1000, dp); + + cyberpro_grphw8(CAP_PITCH, dp->capt.width >> 2, dp); +} + +static void cyberpro_set_interlace(struct cyberpro_vidinfo *dp) +{ + /* + * set interlace mode + */ + if (dp->interlace) { + dp->vfac3 |= VFAC_CTL3_CAP_INTERLACE; + dp->cap_miscctl &= ~CAP_CTL_MISC_ODDEVEN; + dp->ovl->src.height = dp->capt.height; + } else { + dp->vfac3 &= ~VFAC_CTL3_CAP_INTERLACE; + dp->cap_miscctl |= CAP_CTL_MISC_ODDEVEN; + dp->ovl->src.height = dp->capt.height / 2; + } + + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp); + cyberpro_grphw8(CAP_CTL_MISC, dp->cap_miscctl, dp); + + dp->ovl->set_src(dp, dp->ovl); + + if (dp->win_set) + dp->ovl->set_win(dp, dp->ovl); +} + +/* + * Calculate and set the address of the capture buffer. Note we + * also update the extended memory buffer for the overlay window. + * + * base: phys base address of display + * width: pixel width of display + * height: height of display + * depth: depth of display (8/16/24) + * bytesperline: number of bytes on a line + * + * We place the capture buffer 16K after the screen. + */ +static int +cyberpro_set_buffer(struct cyberpro_vidinfo *dp, struct video_buffer *b) +{ + unsigned long screensize, maxbufsz; + + if (b->height <= 0 || b->width <= 0 || b->bytesperline <= 0) + return -EINVAL; + + maxbufsz = dp->cap.maxwidth * dp->cap.maxheight * 2; + screensize = b->height * b->bytesperline + 16384; + + if ((screensize + maxbufsz) >= dp->info.fb_size) + return -EINVAL; + + dp->buf.base = b->base; + dp->buf.width = b->width; + dp->buf.height = b->height; + dp->buf.depth = b->depth; + dp->buf.bytesperline = b->bytesperline; + dp->cap_mem_offset = screensize >> 2; + + cyberpro_grphw24(CAP_MEM_START, dp->cap_mem_offset, dp); + + /* + * Setup the overlay source information. + */ + dp->ovl->src.offset = dp->cap_mem_offset; + dp->ovl->set_src(dp, dp->ovl); + + return 0; +} + +static void cyberpro_hw_init(struct cyberpro_vidinfo *dp) +{ + unsigned char old; + + /* + * Enable access to bus-master registers + */ + dp->info.enable_extregs(dp->info.info); + + dp->vfac1 = VFAC_CTL1_PHILIPS | + VFAC_CTL1_FREEZE_CAPTURE | + VFAC_CTL1_FREEZE_CAPTURE_SYNC; + dp->vfac3 = VFAC_CTL3_CAP_IRQ; + + dp->cap_miscctl = CAP_CTL_MISC_DISPUSED | + CAP_CTL_MISC_SYNCTZOR | + CAP_CTL_MISC_SYNCTZHIGH; + + /* + * Setup bus-master mode + */ + cyberpro_grphw8(BM_CTRL1, 0x88, dp); + cyberpro_grphw8(PCI_BM_CTL, PCI_BM_CTL_ENABLE, dp); + cyberpro_grphw8(BM_CTRL0, 0x44, dp); + cyberpro_grphw8(BM_CTRL1, 0x84, dp); + + cyberpro_grphw24(CAP_MEM_START, 0, dp); + + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp); + cyberpro_grphw8(VFAC_CTL2, 0, dp); + + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); + cyberpro_grphw8(EXT_TV_CTL, 0x80, dp); + + cyberpro_grphw8(EXT_CAP_CTL1, 0x3f, dp); /* disable PIP */ + cyberpro_grphw8(EXT_CAP_CTL2, 0xc0 | EXT_CAP_CTL2_ODDFRAMEIRQ, dp); + + /* + * Configure capture mode to match the + * external video processor format + */ + cyberpro_grphw8(EXT_CAP_MODE1, dp->cap_mode1, dp); + cyberpro_grphw8(EXT_CAP_MODE2, dp->cap_mode2, dp); + + /* setup overlay */ + cyberpro_grphw16(EXT_FIFO_CTL, 0x1010, dp); +// cyberpro_grphw16(EXT_FIFO_CTL, 0x1b0f, dp); + + /* + * Always reset the capture parameters on each open. + */ + dp->capt.x = 0; + dp->capt.y = 0; + dp->capt.width = dp->cap.maxwidth; + dp->capt.height = dp->cap.maxheight; + dp->capt.decimation = 0; + dp->capt.flags = 0; + + cyberpro_capture_set_win(dp); + + /* + * Enable VAFC + */ + old = cyberpro_grphr8(EXT_LATCH1, dp); + cyberpro_grphw8(EXT_LATCH1, old | EXT_LATCH1_VAFC_EN, dp); + + /* + * Enable capture (we hope that VSYNC=1) + */ + dp->vfac1 |= VFAC_CTL1_CAPTURE; + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); + + /* + * The overlay source format is always the + * same as the capture stream format. + */ + dp->ovl->src.width = dp->capt.width; + dp->ovl->src.height = dp->capt.height; + dp->ovl->src.format = dp->stream_fmt; + + /* + * Initialise the overlay windows + */ + dp->ext.init(dp, &dp->ext); + dp->v2.init(dp, &dp->v2); + dp->x2.init(dp, &dp->x2); +} + +static void cyberpro_deinit(struct cyberpro_vidinfo *dp) +{ + unsigned char old; + + /* + * Stop any bus-master activity + */ + cyberpro_writew(0, BM_CONTROL, dp); + + /* + * Shut down overlay + */ + if (dp->ovl_active) + dp->ovl->ctl(dp, dp->ovl, 0); + dp->ovl_active = 0; + + /* + * Shut down capture + */ + if (dp->cap_active) + cyberpro_capture(dp, 0); + dp->cap_active = 0; + + /* + * Disable all capture + */ + cyberpro_grphw8(VFAC_CTL1, 0, dp); + + /* + * Disable VAFC + */ + old = cyberpro_grphr8(EXT_LATCH1, dp); + cyberpro_grphw8(EXT_LATCH1, old & ~EXT_LATCH1_VAFC_EN, dp); + + /* + * Disable interrupt (this allows it to float) + */ + dp->vfac3 &= ~VFAC_CTL3_CAP_IRQ; + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp); + + /* + * Switch off bus-master mode + */ + cyberpro_grphw8(PCI_BM_CTL, 0, dp); + + /* + * Disable access to bus-master registers + */ + dp->info.disable_extregs(dp->info.info); +} + +static int cyberpro_grabber_open(struct video_device *dev, int flags) +{ + struct cyberpro_vidinfo *dp = dev->priv; + int ret, one = 1; + + MOD_INC_USE_COUNT; + + ret = -EBUSY; + if (flags || dp->users) + goto out; + + dp->users += 1; + + if (dp->users == 1) { + ret = request_irq(dp->irq, cyberpro_interrupt, SA_SHIRQ, + dp->info.dev_name, dp); + + if (ret) { + dp->users -= 1; + goto out; + } + + /* + * Initialise the VGA chip + */ + cyberpro_hw_init(dp); + + /* + * Enable the IRQ. This allows the IRQ to work as expected + * even if the IRQ line is missing the pull-up resistor. + */ + enable_irq(dp->irq); + + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER, + DECODER_ENABLE_OUTPUT, &one); + } + + ret = 0; +out: + if (ret) + MOD_DEC_USE_COUNT; + return ret; +} + +static void cyberpro_grabber_close(struct video_device *dev) +{ + struct cyberpro_vidinfo *dp = dev->priv; + + if (dp->users == 1) { + int zero = 0; + + /* + * Disable the IRQ. This prevents problems with missing + * pull-up resistors on the PCI interrupt line. + */ + disable_irq(dp->irq); + + cyberpro_frames_free(dp); + + /* + * Turn off the SAA7111 decoder + */ + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER, + DECODER_ENABLE_OUTPUT, &zero); + + /* + * Disable grabber + */ + cyberpro_deinit(dp); + + free_irq(dp->irq, dp); + } + + dp->users -= 1; + + MOD_DEC_USE_COUNT; +} + +/* + * Our general plan here is: + * 1. Set the CyberPro to perform a BM-DMA of one frame to this memory + * 2. Copy the frame to the userspace + * + * However, BM-DMA seems to be unreliable at the moment, especially on + * rev. 4 NetWinders. + */ +static long +cyberpro_grabber_read(struct video_device *dev, char *buf, + unsigned long count, int noblock) +{ + struct cyberpro_vidinfo *dp = dev->priv; + int ret = -EINVAL; + +#ifdef USE_MMIO + unsigned long maxbufsz = dp->capt.width * dp->capt.height * 2; + char *disp = dp->info.fb + (dp->cap_mem_offset << 2); + + /* + * If the buffer is mmap()'d, we shouldn't be using read() + */ + if (dp->mmaped) + return -EINVAL; + + if (count > maxbufsz) + count = maxbufsz; + + if (dp->cap_active) + cyberpro_capture(dp, 0); + else + cyberpro_capture_one(dp); + + ret = (int)count; + if (copy_to_user(buf, disp, count)) + ret = -EFAULT; + + /* + * unfreeze capture + */ + if (dp->cap_active) + cyberpro_capture(dp, 1); +#endif + + return ret; +} + +/* + * We don't support writing to the grabber + * (In theory, we could allow writing to a separate region of VGA memory, + * and display this using the second overlay window. This would allow us + * to do video conferencing for example). + */ +static long +cyberpro_grabber_write(struct video_device *dev, const char *buf, + unsigned long count, int noblock) +{ + return -EINVAL; +} + +static int +cyberpro_grabber_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct cyberpro_vidinfo *dp = dev->priv; + + switch (cmd) { + case VIDIOCGCAP: + return copy_to_user(arg, &dp->cap, sizeof(dp->cap)) + ? -EFAULT : 0; + + case VIDIOCGCHAN: + { + struct video_channel chan; + + chan.channel = 0; + strcpy(chan.name, "Composite"); + chan.tuners = 0; + chan.flags = 0; + chan.type = VIDEO_TYPE_CAMERA; + chan.norm = dp->norm; + + return copy_to_user(arg, &chan, sizeof(chan)) ? -EFAULT : 0; + } + + case VIDIOCGPICT: + return copy_to_user(arg, &dp->pic, sizeof(dp->pic)) + ? -EINVAL : 0; + + case VIDIOCGWIN: + { + struct video_window win; + + win.x = dp->ovl->dst.x; + win.y = dp->ovl->dst.y; + win.width = dp->ovl->dst.width; + win.height = dp->ovl->dst.height; + win.chromakey = dp->ovl->dst.chromakey; + win.flags = VIDEO_WINDOW_CHROMAKEY | + (dp->interlace ? VIDEO_WINDOW_INTERLACE : 0); + win.clips = NULL; + win.clipcount = 0; + + return copy_to_user(arg, &win, sizeof(win)) + ? -EINVAL : 0; + } + + case VIDIOCGFBUF: + return copy_to_user(arg, &dp->buf, sizeof(dp->buf)) + ? -EINVAL : 0; + + case VIDIOCGUNIT: + { + struct video_unit unit; + + unit.video = dev->minor; + unit.vbi = VIDEO_NO_UNIT; + unit.radio = VIDEO_NO_UNIT; + unit.audio = VIDEO_NO_UNIT; + unit.teletext = VIDEO_NO_UNIT; + + return copy_to_user(arg, &unit, sizeof(unit)) + ? -EINVAL : 0; + } + + case VIDIOCGCAPTURE: + return copy_to_user(arg, &dp->capt, sizeof(dp->capt)) + ? -EFAULT : 0; + + case VIDIOCSCHAN: + { + struct video_decoder_capability vdc; + struct video_channel v; + int ok; + + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + + if (v.channel != 0) + return -EINVAL; + + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER, + DECODER_GET_CAPABILITIES, &vdc); + + switch (v.norm) { + case VIDEO_MODE_PAL: + ok = vdc.flags & VIDEO_DECODER_PAL; + break; + case VIDEO_MODE_NTSC: + ok = vdc.flags & VIDEO_DECODER_NTSC; + break; + case VIDEO_MODE_AUTO: + ok = vdc.flags & VIDEO_DECODER_AUTO; + break; + default: + ok = 0; + } + if (!ok) + return -EINVAL; + + dp->norm = v.norm; + + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER, + DECODER_SET_NORM, &v.norm); + + return 0; + } + + case VIDIOCSPICT: + { + struct video_picture p; + + if (copy_from_user(&p, arg, sizeof(p))) + return -EFAULT; + + if (p.palette != dp->stream_fmt || + p.depth != 8) + return -EINVAL; + + dp->pic = p; + + /* p.depth sets the capture depth */ + /* p.palette sets the capture palette */ + + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER, + DECODER_SET_PICTURE, &p); + + return 0; + } + + case VIDIOCSWIN: /* set the size & position of the overlay window */ + { + struct video_window w; + int diff; + + if (!dp->buf_set) + return -EINVAL; + + if (copy_from_user(&w, arg, sizeof(w))) + return -EFAULT; + + if (w.clipcount) + return -EINVAL; + + /* + * Bound the overlay window by the size of the screen + */ + if (w.x < 0) + w.x = 0; + if (w.y < 0) + w.y = 0; + + if (w.x > dp->buf.width) + w.x = dp->buf.width; + if (w.y > dp->buf.height) + w.y = dp->buf.height; + + if (w.width < dp->capt.width) + w.width = dp->capt.width; + if (w.height < dp->capt.height) + w.height = dp->capt.height; + + if (w.x + w.width > dp->buf.width) + w.width = dp->buf.width - w.x; + if (w.y + w.height > dp->buf.height) + w.height = dp->buf.height - w.y; + + /* + * We've tried to make the values fit, but + * they just won't. + */ + if (w.width < dp->capt.width || w.height < dp->capt.height) + return -EINVAL; + + diff = dp->ovl->dst.x != w.x || + dp->ovl->dst.y != w.y || + dp->ovl->dst.width != w.width || + dp->ovl->dst.height != w.height || + dp->ovl->dst.chromakey != w.chromakey || + dp->ovl->dst.flags != w.flags; + + if (!dp->win_set || diff) { + dp->ovl->dst.x = w.x; + dp->ovl->dst.y = w.y; + dp->ovl->dst.width = w.width; + dp->ovl->dst.height = w.height; + dp->ovl->dst.chromakey = w.chromakey; + dp->ovl->dst.flags = w.flags; + + if (dp->ovl_active) + dp->ovl->ctl(dp, dp->ovl, 0); + + dp->ovl->set_win(dp, dp->ovl); + + if (dp->ovl_active) + dp->ovl->ctl(dp, dp->ovl, 1); + + diff = w.flags & VIDEO_WINDOW_INTERLACE ? 1 : 0; + if (!dp->win_set || dp->interlace != diff) { + dp->interlace = diff; + cyberpro_set_interlace(dp); + } + } + + dp->win_set = 1; + + return 0; + } + + case VIDIOCSFBUF: /* set frame buffer info */ + { + struct video_buffer b; + int ret; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EPERM; + + if (dp->cap_active) + return -EINVAL; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + ret = cyberpro_set_buffer(dp, &b); + if (ret == 0) { + dp->buf_set = 1; + dp->win_set = 0; + } + + return ret; + } + + case VIDIOCCAPTURE: + { + int on; + + if (get_user(on, (int *)arg)) + return -EFAULT; + + if (( on && dp->ovl_active) || + (!on && !dp->ovl_active)) + return 0; + + if (on && (!dp->buf_set || !dp->win_set)) + return -EINVAL; + + cyberpro_capture(dp, on); + dp->cap_active = on; + dp->ovl->ctl(dp, dp->ovl, on); + dp->ovl_active = on; + + return 0; + } + +#ifdef USE_MMAP + case VIDIOCSYNC: + { + DECLARE_WAITQUEUE(wait, current); + int buf; + + /* + * The buffer must have been mmaped + * for this call to work. + */ + if (!dp->mmaped) + return -EINVAL; + + if (get_user(buf, (int *)arg)) + return -EFAULT; + + if (buf < 0 || buf >= NR_FRAMES) + return -EINVAL; + + switch (dp->frame[buf].status) { + case FRAME_FREE: + return -EINVAL; + + case FRAME_WAITING: + case FRAME_GRABBING: + add_wait_queue(&dp->frame_wait, &wait); + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) + break; + if (dp->frame[buf].status == FRAME_DONE) + break; + schedule(); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&dp->frame_wait, &wait); + if (signal_pending(current)) + return -EINTR; + /*FALLTHROUGH*/ + case FRAME_DONE: + dp->frame[buf].status = FRAME_FREE; + break; + } + return 0; + } + + case VIDIOCMCAPTURE: + { + struct video_mmap vmap; + + /* + * The buffer must have been mmaped + * for this call to work. + */ + if (!dp->mmaped) + return -EINVAL; + + if (copy_from_user(&vmap, arg, sizeof(vmap))) + return -EFAULT; + + /* + * We can only capture in our source format/size. + */ + if (vmap.frame >= NR_FRAMES || + vmap.format != dp->stream_fmt || + vmap.width != dp->capt.width || + vmap.height != dp->capt.height) + return -EINVAL; + + if (dp->frame[vmap.frame].status == FRAME_WAITING || + dp->frame[vmap.frame].status == FRAME_GRABBING) + return -EBUSY; + + dp->frame[vmap.frame].status = FRAME_WAITING; + return 0; + } + + case VIDIOCGMBUF: + { + struct video_mbuf vmb; + unsigned int i; + + vmb.frames = NR_FRAMES; + vmb.size = dp->frame_size * NR_FRAMES; + + for (i = 0; i < NR_FRAMES; i++) + vmb.offsets[i] = dp->frame[i].offset; + + return copy_to_user(arg, &vmb, sizeof(vmb)) ? -EFAULT : 0; + } +#endif + + case VIDIOCSCAPTURE: + { + struct video_capture capt; + +#ifndef ALLOW_SCAPTURE_WHILE_CAP + if (dp->cap_active) + return -EINVAL; +#endif + + if (copy_from_user(&capt, arg, sizeof(capt))) + return -EFAULT; + + if (capt.x < 0 || capt.width < 0 || + capt.y < 0 || capt.height < 0 || + capt.x + capt.width > dp->cap.maxwidth || + capt.y + capt.height > dp->cap.maxheight) + return -EINVAL; + + /* + * The capture width must be a multiple of 4 + */ + if (dp->capt.width & 3) + return -EINVAL; + + dp->capt.x = capt.x; + dp->capt.y = capt.y; + dp->capt.width = capt.width; + dp->capt.height = capt.height; +#ifdef ALLOW_SCAPTURE_WHILE_CAP + if (dp->ovl_active) + dp->ovl->ctl(dp, dp->ovl, 0); + if (dp->cap_active) + cyberpro_capture(dp, 0); +#endif + cyberpro_capture_set_win(dp); + + /* + * Update the overlay window information + */ + dp->ovl->src.width = capt.width; + dp->ovl->src.height = capt.height; + + dp->ovl->set_src(dp, dp->ovl); + if (dp->win_set) + dp->ovl->set_win(dp, dp->ovl); + +#ifdef ALLOW_SCAPTURE_WHILE_CAP + if (dp->cap_active) + cyberpro_capture(dp, 1); + if (dp->ovl_active) + dp->ovl->ctl(dp, dp->ovl, 1); +#endif + return 0; + } + + case VIDIOCGTUNER: /* no tuner */ + case VIDIOCSTUNER: + return -EINVAL; + } + + return -EINVAL; +} + +#ifdef USE_MMAP +static int +cyberpro_grabber_mmap(struct video_device *dev, const char *addr, unsigned long size) +{ + struct cyberpro_vidinfo *dp = dev->priv; + unsigned long vaddr = (unsigned long)addr; + pgprot_t prot; + int frame_idx, ret = -EINVAL; + +#if defined(__arm__) + prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_USER | L_PTE_WRITE | L_PTE_DIRTY); +#elif defined(__i386__) + prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED); + if (boot_cpu_data.x86 > 3) + pgprot_val(prot) |= _PAGE_PCD; +#else +#error "Unsupported architecture" +#endif + + /* + * The mmap() request must have the correct size. + */ + if (size != NR_FRAMES * dp->frame_size) + goto out; + + /* + * If it's already mapped, don't re-do + */ + if (dp->mmaped) + goto out; + dp->mmaped = 1; + + /* + * Map in each frame + */ + for (frame_idx = 0; frame_idx < NR_FRAMES; frame_idx++) { + struct framebuf *frame; + int pgidx; + + frame = dp->frame + frame_idx; + + ret = cyberpro_alloc_frame_buffer(dp, frame); + + /* + * If an error occurs, we can be lazy and leave what we've + * been able to do. Our release function will free any + * allocated buffers, and do_mmap_pgoff() will zap any + * inserted mappings. + */ + if (ret) + goto out2; + + /* + * Map in each page on a page by page basis. This is just + * a little on the inefficient side, but it's only run once. + */ + for (pgidx = 0; pgidx < NR_PAGES; pgidx++) { + unsigned long virt; + + virt = page_address(frame->pages[pgidx]); + + ret = remap_page_range(vaddr, virt_to_phys((void *)virt), + PAGE_SIZE, prot); + + if (ret) + goto out2; + + vaddr += PAGE_SIZE; + } + } + + out2: + if (ret) + dp->mmaped = 0; + out: + return ret; +} +#endif + +static int __init cyberpro_grabber_init_done(struct video_device *dev) +{ + struct cyberpro_vidinfo *dp; + struct cyberpro_info *info = dev->priv; + int ret; + + dp = kmalloc(sizeof(*dp), GFP_KERNEL); + if (!dp) + return -ENOMEM; + + memset(dp, 0, sizeof(*dp)); + + dev->priv = dp; + dp->info = *info; + dp->dev = dev; + dp->bus = &cyberpro_i2c_bus; + dp->regs = info->regs; + dp->irq = info->dev->irq; + + strcpy(dp->cap.name, dev->name); + dp->cap.type = dev->type; + dp->cap.channels = 1; + dp->cap.audios = 0; + dp->cap.minwidth = 32; + dp->cap.maxwidth = 716; + dp->cap.minheight = 32; + dp->cap.maxheight = 576; + + dp->pic.brightness = 32768; + dp->pic.hue = 32768; + dp->pic.colour = 32768; + dp->pic.contrast = 32768; + dp->pic.whiteness = 0; + dp->pic.depth = 8; + dp->pic.palette = VIDEO_PALETTE_YUV422; + + /* dp->buf is setup by the user */ + /* dp->cap_mem_offset setup by dp->buf */ + + dp->norm = VIDEO_MODE_AUTO; + + /* + * The extended overlay window + */ + dp->ext.init = cyberpro_ext_init; + dp->ext.set_src = cyberpro_ext_set_src; + dp->ext.set_win = cyberpro_ext_set_win; + dp->ext.ctl = cyberpro_ext_ctl; + + /* + * The V2 overlay window + */ + dp->v2.init = cyberpro_v2_init; + dp->v2.set_src = cyberpro_v2_set_src; + dp->v2.set_win = cyberpro_v2_set_win; + dp->v2.ctl = cyberpro_v2_ctl; + + /* + * The X2 overlay window + */ + dp->x2.init = cyberpro_x2_init; + dp->x2.set_src = cyberpro_x2_set_src; + dp->x2.set_win = cyberpro_x2_set_win; + dp->x2.ctl = cyberpro_x2_ctl; + + /* + * Set the overlay window which we shall be using + */ + dp->ovl = &dp->ext; + + dp->cap_mode1 = EXT_CAP_MODE1_ALTFIFO; + + /* + * Initialise hardware specific values. + * - CCIR656 8bit mode (YUV422 data) + * - Ignore Hgood signal + * - Invert Odd/Even field signal + */ + dp->cap_mode1 |= EXT_CAP_MODE1_CCIR656 | EXT_CAP_MODE1_8BIT; + dp->cap_mode2 = EXT_CAP_MODE2_FIXSONY | EXT_CAP_MODE2_DATEND | + EXT_CAP_MODE2_CCIRINVOE; + dp->stream_fmt = VIDEO_PALETTE_YUV422; + + + init_waitqueue_head(&dp->vbl_wait); + cyberpro_frames_init(dp); + + /* + * wake up the decoder + */ + decoder_sleep(0); + + dp->bus->data = dp; + strncpy(dp->bus->name, dev->name, sizeof(dp->bus->name)); + + pci_set_master(dp->info.dev); + + ret = i2c_register_bus(dp->bus); + + /* + * If we successfully registered the bus, but didn't initialise + * the decoder (because its driver is not present), request + * that it is loaded. + */ + if (ret == 0 && !dp->decoder) + request_module("saa7111"); + + /* + * If that didn't work, then we're out of luck. + */ + if (ret == 0 && !dp->decoder) { + i2c_unregister_bus(dp->bus); + ret = -ENXIO; + } + + if (ret) { + kfree(dp); + + /* + * put the decoder back to sleep + */ + decoder_sleep(1); + } + + return ret; +} + +static struct video_device cyberpro_grabber = { + name: "", + type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | + VID_TYPE_CHROMAKEY | VID_TYPE_SCALES | + VID_TYPE_SUBCAPTURE, + hardware: 0, + open: cyberpro_grabber_open, + close: cyberpro_grabber_close, + read: cyberpro_grabber_read, + write: cyberpro_grabber_write, + ioctl: cyberpro_grabber_ioctl, +#ifdef USE_MMAP + mmap: cyberpro_grabber_mmap, +#endif + initialize: cyberpro_grabber_init_done, +}; + +int init_cyber2000fb_viddev(void) +{ + struct cyberpro_info info; + + if (!cyber2000fb_attach(&info, 0)) + return -ENXIO; + + strncpy(cyberpro_grabber.name, info.dev_name, sizeof(cyberpro_grabber.name)); + + cyberpro_grabber.priv = &info; + + return video_register_device(&cyberpro_grabber, VFL_TYPE_GRABBER, -1); +} + +/* + * This can be cleaned up when the SAA7111 code is fixed. + */ +#ifdef MODULE +static int __init cyberpro_init(void) +{ + disable_irq(35); + return init_cyber2000fb_viddev(); +} + +static void __exit cyberpro_exit(void) +{ + video_unregister_device(&cyberpro_grabber); + kfree(cyberpro_grabber.priv); + i2c_unregister_bus(&cyberpro_i2c_bus); + + /* + * put the decoder back to sleep + */ + decoder_sleep(1); + + cyber2000fb_detach(0); +} + +module_init(cyberpro_init); +module_exit(cyberpro_exit); +#endif diff -urN orig/drivers/media/video/i2c-old.c linux/drivers/media/video/i2c-old.c --- orig/drivers/media/video/i2c-old.c Sun Oct 14 20:53:08 2001 +++ linux/drivers/media/video/i2c-old.c Fri Sep 28 21:43:57 2001 @@ -36,22 +36,20 @@ static struct i2c_driver *drivers[I2C_DRIVER_MAX]; static int bus_count = 0, driver_count = 0; -#ifdef CONFIG_VIDEO_BUZ extern int saa7111_init(void); extern int saa7185_init(void); -#endif -#ifdef CONFIG_VIDEO_LML33 extern int bt819_init(void); extern int bt856_init(void); -#endif int i2c_init(void) { printk(KERN_INFO "i2c: initialized%s\n", scan ? " (i2c bus scan enabled)" : ""); /* anything to do here ? */ -#ifdef CONFIG_VIDEO_BUZ +#if defined(CONFIG_VIDEO_BUZ) || defined(CONFIG_VIDEO_CYBERPRO) saa7111_init(); +#endif +#ifdef CONFIG_VIDEO_BUZ saa7185_init(); #endif #ifdef CONFIG_VIDEO_LML33 diff -urN orig/drivers/media/video/saa7111.c linux/drivers/media/video/saa7111.c --- orig/drivers/media/video/saa7111.c Sun Oct 14 20:53:08 2001 +++ linux/drivers/media/video/saa7111.c Thu Jun 20 23:22:47 2002 @@ -20,9 +20,9 @@ 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 @@ -149,7 +149,11 @@ 0x0d, 0x00, /* 0d - HUE=0 */ 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ 0x0f, 0x00, /* 0f - reserved */ +#ifndef CONFIG_ARCH_NETWINDER 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */ +#else + 0x10, 0xc8, /* 10 - OFTS=YUV-CCIR656, HDEL=0, VLRN=1, YDEL=0 */ +#endif 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ 0x12, 0x00, /* 12 - output control 2 */ 0x13, 0x00, /* 13 - output control 3 */ diff -urN orig/drivers/message/i2o/i2o_core.c linux/drivers/message/i2o/i2o_core.c --- orig/drivers/message/i2o/i2o_core.c Tue Jun 24 13:58:36 2003 +++ linux/drivers/message/i2o/i2o_core.c Tue Jun 24 11:18:15 2003 @@ -1665,14 +1665,14 @@ } memset(status, 0, 4); - msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; - msg[2]=core_context; - msg[3]=0; - msg[4]=0; - msg[5]=0; - msg[6]=virt_to_bus(status); - msg[7]=0; /* 64bit host FIXME */ + writel(EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0); + writel(I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1); + writel(core_context, msg + 2); + writel(0, msg + 3); + writel(0, msg + 4); + writel(0, msg + 5); + writel(virt_to_bus(status), msg + 6); + writel(0, msg + 7); /* 64bit host FIXME */ i2o_post_message(c,m); @@ -1781,15 +1781,15 @@ return -ETIMEDOUT; msg=(u32 *)(c->mem_offset+m); - msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID; - msg[2]=core_context; - msg[3]=0; - msg[4]=0; - msg[5]=0; - msg[6]=virt_to_bus(c->status_block); - msg[7]=0; /* 64bit host FIXME */ - msg[8]=sizeof(i2o_status_block); /* always 88 bytes */ + writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0); + writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1); + writel(core_context, msg + 2); + writel(0, msg + 3); + writel(0, msg + 4); + writel(0, msg + 5); + writel(virt_to_bus(c->status_block), msg + 6); + writel(0, msg + 7); /* 64bit host FIXME */ + writel(sizeof(i2o_status_block), msg + 8); /* always 88 bytes */ i2o_post_message(c,m); @@ -2193,15 +2193,15 @@ } memset(status, 0, 4); - msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6; - msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2]= core_context; - msg[3]= 0x0106; /* Transaction context */ - msg[4]= 4096; /* Host page frame size */ + writel(EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6, msg + 0); + writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, msg + 1); + writel(core_context, msg + 2); + writel(0x0106, msg + 3); /* Transaction context */ + writel(PAGE_SIZE, msg + 4); /* Host page frame size */ /* Frame size is in words. 256 bytes a frame for now */ - msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size in words and Initcode */ - msg[6]= 0xD0000004; /* Simple SG LE, EOB */ - msg[7]= virt_to_bus(status); + writel(MSG_FRAME_SIZE<<16|0x80, msg + 5);/* Outbound msg frame size in words and Initcode */ + writel(0xD0000004, msg + 6); /* Simple SG LE, EOB */ + writel(virt_to_bus(status), msg + 7); i2o_post_message(c,m); diff -urN orig/drivers/message/i2o/i2o_pci.c linux/drivers/message/i2o/i2o_pci.c --- orig/drivers/message/i2o/i2o_pci.c Wed Jun 18 13:02:02 2003 +++ linux/drivers/message/i2o/i2o_pci.c Wed Jun 18 09:58:59 2003 @@ -390,4 +390,4 @@ MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o"); module_init(i2o_pci_core_attach); module_exit(i2o_pci_core_detach); - \ No newline at end of file + diff -urN orig/drivers/misc/Config.in linux/drivers/misc/Config.in --- orig/drivers/misc/Config.in Wed Dec 29 22:27:08 1999 +++ linux/drivers/misc/Config.in Wed Oct 3 14:57:35 2001 @@ -1,7 +1,17 @@ # -# Misc strange devices +# MCP drivers # mainmenu_option next_comment -comment 'Misc devices' +comment 'Multimedia Capabilities Port drivers' + +bool 'Multimedia drivers' CONFIG_MCP + +# Interface drivers +dep_bool 'Support SA1100 MCP interface' CONFIG_MCP_SA1100 $CONFIG_MCP $CONFIG_ARCH_SA1100 + +# Chip drivers +dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP +dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND +dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200 endmenu diff -urN orig/drivers/misc/Makefile linux/drivers/misc/Makefile --- orig/drivers/misc/Makefile Sun Dec 31 22:12:25 2000 +++ linux/drivers/misc/Makefile Sat Sep 22 23:30:40 2001 @@ -11,6 +11,14 @@ O_TARGET := misc.o +export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o + +obj-$(CONFIG_MCP) += mcp-core.o +obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o +obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o +obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o +obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o + include $(TOPDIR)/Rules.make fastdep: diff -urN orig/drivers/misc/mcp-core.c linux/drivers/misc/mcp-core.c --- orig/drivers/misc/mcp-core.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/misc/mcp-core.c Mon Feb 11 09:39:42 2002 @@ -0,0 +1,155 @@ +/* + * linux/drivers/misc/mcp-core.c + * + * Copyright (C) 2001 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * Generic MCP (Multimedia Communications Port) layer. All MCP locking + * is solely held within this file. + */ +#include +#include +#include +#include + +#include +#include + +#include "mcp.h" + +/** + * mcp_set_telecom_divisor - set the telecom divisor + * @mcp: MCP interface structure + * @div: SIB clock divisor + * + * Set the telecom divisor on the MCP interface. The resulting + * sample rate is SIBCLOCK/div. + */ +void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div) +{ + spin_lock_irq(&mcp->lock); + mcp->set_telecom_divisor(mcp, div); + spin_unlock_irq(&mcp->lock); +} + +/** + * mcp_set_audio_divisor - set the audio divisor + * @mcp: MCP interface structure + * @div: SIB clock divisor + * + * Set the audio divisor on the MCP interface. + */ +void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div) +{ + spin_lock_irq(&mcp->lock); + mcp->set_audio_divisor(mcp, div); + spin_unlock_irq(&mcp->lock); +} + +/** + * mcp_reg_write - write a device register + * @mcp: MCP interface structure + * @reg: 4-bit register index + * @val: 16-bit data value + * + * Write a device register. The MCP interface must be enabled + * to prevent this function hanging. + */ +void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) +{ + unsigned long flags; + + spin_lock_irqsave(&mcp->lock, flags); + mcp->reg_write(mcp, reg, val); + spin_unlock_irqrestore(&mcp->lock, flags); +} + +/** + * mcp_reg_read - read a device register + * @mcp: MCP interface structure + * @reg: 4-bit register index + * + * Read a device register and return its value. The MCP interface + * must be enabled to prevent this function hanging. + */ +unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&mcp->lock, flags); + val = mcp->reg_read(mcp, reg); + spin_unlock_irqrestore(&mcp->lock, flags); + + return val; +} + +/** + * mcp_enable - enable the MCP interface + * @mcp: MCP interface to enable + * + * Enable the MCP interface. Each call to mcp_enable will need + * a corresponding call to mcp_disable to disable the interface. + */ +void mcp_enable(struct mcp *mcp) +{ + spin_lock_irq(&mcp->lock); + if (mcp->use_count++ == 0) + mcp->enable(mcp); + spin_unlock_irq(&mcp->lock); +} + +/** + * mcp_disable - disable the MCP interface + * @mcp: MCP interface to disable + * + * Disable the MCP interface. The MCP interface will only be + * disabled once the number of calls to mcp_enable matches the + * number of calls to mcp_disable. + */ +void mcp_disable(struct mcp *mcp) +{ + unsigned long flags; + + spin_lock_irqsave(&mcp->lock, flags); + if (--mcp->use_count == 0) + mcp->disable(mcp); + spin_unlock_irqrestore(&mcp->lock, flags); +} + + +/* + * This needs re-working + */ +static struct mcp *mcp_if; + +struct mcp *mcp_get(void) +{ + return mcp_if; +} + +int mcp_register(struct mcp *mcp) +{ + if (mcp_if) + return -EBUSY; + if (mcp->owner) + __MOD_INC_USE_COUNT(mcp->owner); + mcp_if = mcp; + return 0; +} + +EXPORT_SYMBOL(mcp_set_telecom_divisor); +EXPORT_SYMBOL(mcp_set_audio_divisor); +EXPORT_SYMBOL(mcp_reg_write); +EXPORT_SYMBOL(mcp_reg_read); +EXPORT_SYMBOL(mcp_enable); +EXPORT_SYMBOL(mcp_disable); +EXPORT_SYMBOL(mcp_get); +EXPORT_SYMBOL(mcp_register); + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("Core multimedia communications port driver"); +MODULE_LICENSE("GPL"); diff -urN orig/drivers/misc/mcp-sa1100.c linux/drivers/misc/mcp-sa1100.c --- orig/drivers/misc/mcp-sa1100.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/misc/mcp-sa1100.c Fri Dec 20 17:17:15 2002 @@ -0,0 +1,180 @@ +/* + * linux/drivers/misc/mcp-sa1100.c + * + * Copyright (C) 2001 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * SA1100 MCP (Multimedia Communications Port) driver. + * + * MCP read/write timeouts from Jordi Colomer, rehacked by rmk. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mcp.h" + +static void +mcp_sa1100_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) +{ + unsigned int mccr0; + + divisor /= 32; + + mccr0 = Ser4MCCR0 & ~0x00007f00; + mccr0 |= divisor << 8; + Ser4MCCR0 = mccr0; +} + +static void +mcp_sa1100_set_audio_divisor(struct mcp *mcp, unsigned int divisor) +{ + unsigned int mccr0; + + divisor /= 32; + + mccr0 = Ser4MCCR0 & ~0x0000007f; + mccr0 |= divisor; + Ser4MCCR0 = mccr0; +} + +/* + * Write data to the device. The bit should be set after 3 subframe + * times (each frame is 64 clocks). We wait a maximum of 6 subframes. + * We really should try doing something more productive while we + * wait. + */ +static void +mcp_sa1100_write(struct mcp *mcp, unsigned int reg, unsigned int val) +{ + int ret = -ETIME; + int i; + + Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); + + for (i = 0; i < 2; i++) { + udelay(mcp->rw_timeout); + if (Ser4MCSR & MCSR_CWC) { + ret = 0; + break; + } + } + + if (ret < 0) + printk(KERN_WARNING "mcp: write timed out\n"); +} + +/* + * Read data from the device. The bit should be set after 3 subframe + * times (each frame is 64 clocks). We wait a maximum of 6 subframes. + * We really should try doing something more productive while we + * wait. + */ +static unsigned int +mcp_sa1100_read(struct mcp *mcp, unsigned int reg) +{ + int ret = -ETIME; + int i; + + Ser4MCDR2 = reg << 17 | MCDR2_Rd; + + for (i = 0; i < 2; i++) { + udelay(mcp->rw_timeout); + if (Ser4MCSR & MCSR_CRC) { + ret = Ser4MCDR2 & 0xffff; + break; + } + } + + if (ret < 0) + printk(KERN_WARNING "mcp: read timed out\n"); + + return ret; +} + +static void mcp_sa1100_enable(struct mcp *mcp) +{ + Ser4MCSR = -1; + Ser4MCCR0 |= MCCR0_MCE; +} + +static void mcp_sa1100_disable(struct mcp *mcp) +{ + Ser4MCCR0 &= ~MCCR0_MCE; +} + +struct mcp mcp_sa1100 = { + owner: THIS_MODULE, + lock: SPIN_LOCK_UNLOCKED, + sclk_rate: 11981000, + dma_audio_rd: DMA_Ser4MCP0Rd, + dma_audio_wr: DMA_Ser4MCP0Wr, + dma_telco_rd: DMA_Ser4MCP1Rd, + dma_telco_wr: DMA_Ser4MCP1Wr, + set_telecom_divisor: mcp_sa1100_set_telecom_divisor, + set_audio_divisor: mcp_sa1100_set_audio_divisor, + reg_write: mcp_sa1100_write, + reg_read: mcp_sa1100_read, + enable: mcp_sa1100_enable, + disable: mcp_sa1100_disable, +}; + +/* + * This needs re-working + */ +static int mcp_sa1100_init(void) +{ + struct mcp *mcp = &mcp_sa1100; + int ret = -ENODEV; + + if (machine_is_accelent_sa() || + machine_is_adsbitsy() || machine_is_assabet() || + machine_is_cerf() || machine_is_flexanet() || + machine_is_freebird() || machine_is_graphicsclient() || + machine_is_graphicsmaster() || machine_is_lart() || + machine_is_omnimeter() || machine_is_pfs168() || + machine_is_shannon() || machine_is_simpad() || + machine_is_simputer() || machine_is_yopy()) { + /* + * Setup the PPC unit correctly. + */ + PPDR &= ~PPC_RXD4; + PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; + PSDR |= PPC_RXD4; + PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + + Ser4MCSR = -1; + Ser4MCCR1 = 0; + Ser4MCCR0 = 0x00007f7f | MCCR0_ADM; + + /* + * Calculate the read/write timeout (us) from the bit clock + * rate. This is the period for 3 64-bit frames. Always + * round this time up. + */ + mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / + mcp->sclk_rate; + + ret = mcp_register(mcp); + } + + return ret; +} + +module_init(mcp_sa1100_init); +EXPORT_SYMBOL(mcp_sa1100_init); + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); +MODULE_LICENSE("GPL"); diff -urN orig/drivers/misc/mcp.h linux/drivers/misc/mcp.h --- orig/drivers/misc/mcp.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/misc/mcp.h Sun Jan 27 22:51:28 2002 @@ -0,0 +1,44 @@ +/* + * linux/drivers/misc/mcp.h + * + * Copyright (C) 2001 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + */ +#ifndef MCP_H +#define MCP_H + +struct mcp { + struct module *owner; + spinlock_t lock; + int use_count; + unsigned int sclk_rate; + unsigned int rw_timeout; + dma_device_t dma_audio_rd; + dma_device_t dma_audio_wr; + dma_device_t dma_telco_rd; + dma_device_t dma_telco_wr; + void (*set_telecom_divisor)(struct mcp *, unsigned int); + void (*set_audio_divisor)(struct mcp *, unsigned int); + void (*reg_write)(struct mcp *, unsigned int, unsigned int); + unsigned int (*reg_read)(struct mcp *, unsigned int); + void (*enable)(struct mcp *); + void (*disable)(struct mcp *); +}; + +void mcp_set_telecom_divisor(struct mcp *, unsigned int); +void mcp_set_audio_divisor(struct mcp *, unsigned int); +void mcp_reg_write(struct mcp *, unsigned int, unsigned int); +unsigned int mcp_reg_read(struct mcp *, unsigned int); +void mcp_enable(struct mcp *); +void mcp_disable(struct mcp *); + +/* noddy implementation alert! */ +struct mcp *mcp_get(void); +int mcp_register(struct mcp *); + +#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) + +#endif diff -urN orig/drivers/misc/ucb1x00-audio.c linux/drivers/misc/ucb1x00-audio.c --- orig/drivers/misc/ucb1x00-audio.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/misc/ucb1x00-audio.c Mon Aug 5 22:46:24 2002 @@ -0,0 +1,378 @@ +/* + * linux/drivers/misc/ucb1x00-audio.c + * + * Copyright (C) 2001 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ucb1x00.h" + +#include "../drivers/sound/sa1100-audio.h" + +#define MAGIC 0x41544154 + +struct ucb1x00_audio { + struct file_operations fops; + struct file_operations mops; + struct ucb1x00 *ucb; + audio_stream_t output_stream; + audio_stream_t input_stream; + audio_state_t state; + unsigned int rate; + int dev_id; + int mix_id; + unsigned int daa_oh_bit; + unsigned int telecom; + unsigned int magic; + unsigned int ctrl_a; + unsigned int ctrl_b; + + /* mixer info */ + unsigned int mod_cnt; + unsigned short output_level; + unsigned short input_level; +}; + +#define REC_MASK (SOUND_MASK_VOLUME | SOUND_MASK_MIC) +#define DEV_MASK REC_MASK + +static int +ucb1x00_mixer_ioctl(struct inode *ino, struct file *filp, uint cmd, ulong arg) +{ + struct ucb1x00_audio *ucba; + unsigned int val, gain; + int ret = 0; + + ucba = list_entry(filp->f_op, struct ucb1x00_audio, mops); + + if (_IOC_TYPE(cmd) != 'M') + return -EINVAL; + + if (cmd == SOUND_MIXER_INFO) { + struct mixer_info mi; + + strncpy(mi.id, "UCB1x00", sizeof(mi.id)); + strncpy(mi.name, "Philips UCB1x00", sizeof(mi.name)); + mi.modify_counter = ucba->mod_cnt; + return copy_to_user((void *)arg, &mi, sizeof(mi)) ? -EFAULT : 0; + } + + if (_IOC_DIR(cmd) & _IOC_WRITE) { + unsigned int left, right; + + ret = get_user(val, (unsigned int *)arg); + if (ret) + goto out; + + left = val & 255; + right = val >> 8; + + if (left > 100) + left = 100; + if (right > 100) + right = 100; + + gain = (left + right) / 2; + + ret = -EINVAL; + if (!ucba->telecom) { + switch(_IOC_NR(cmd)) { + case SOUND_MIXER_VOLUME: + ucba->output_level = gain | gain << 8; + ucba->mod_cnt++; + ucba->ctrl_b = (ucba->ctrl_b & 0xff00) | + ((gain * 31) / 100); + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, + ucba->ctrl_b); + ret = 0; + break; + + case SOUND_MIXER_MIC: + ucba->input_level = gain | gain << 8; + ucba->mod_cnt++; + ucba->ctrl_a = (ucba->ctrl_a & 0x7f) | + (((gain * 31) / 100) << 7); + ucb1x00_reg_write(ucba->ucb, UCB_AC_A, + ucba->ctrl_a); + ret = 0; + break; + } + } + } + + if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) { + switch (_IOC_NR(cmd)) { + case SOUND_MIXER_VOLUME: + val = ucba->output_level; + break; + + case SOUND_MIXER_MIC: + val = ucba->input_level; + break; + + case SOUND_MIXER_RECSRC: + case SOUND_MIXER_RECMASK: + val = ucba->telecom ? 0 : REC_MASK; + break; + + case SOUND_MIXER_DEVMASK: + val = ucba->telecom ? 0 : DEV_MASK; + break; + + case SOUND_MIXER_CAPS: + case SOUND_MIXER_STEREODEVS: + val = 0; + break; + + default: + val = 0; + ret = -EINVAL; + break; + } + + if (ret == 0) + ret = put_user(val, (int *)arg); + } + out: + return ret; +} + +static int ucb1x00_audio_setrate(struct ucb1x00_audio *ucba, int rate) +{ + unsigned int div_rate = ucb1x00_clkrate(ucba->ucb) / 32; + unsigned int div; + + div = (div_rate + (rate / 2)) / rate; + if (div < 6) + div = 6; + if (div > 127) + div = 127; + + ucba->ctrl_a = (ucba->ctrl_a & ~0x7f) | div; + + if (ucba->telecom) { + ucb1x00_reg_write(ucba->ucb, UCB_TC_B, 0); + ucb1x00_set_telecom_divisor(ucba->ucb, div * 32); + ucb1x00_reg_write(ucba->ucb, UCB_TC_A, ucba->ctrl_a); + ucb1x00_reg_write(ucba->ucb, UCB_TC_B, ucba->ctrl_b); + } else { + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, 0); + ucb1x00_set_audio_divisor(ucba->ucb, div * 32); + ucb1x00_reg_write(ucba->ucb, UCB_AC_A, ucba->ctrl_a); + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, ucba->ctrl_b); + } + + ucba->rate = div_rate / div; + + return ucba->rate; +} + +static int ucb1x00_audio_getrate(struct ucb1x00_audio *ucba) +{ + return ucba->rate; +} + +static void ucb1x00_audio_startup(void *data) +{ + struct ucb1x00_audio *ucba = data; + + ucb1x00_enable(ucba->ucb); + ucb1x00_audio_setrate(ucba, ucba->rate); + + ucb1x00_reg_write(ucba->ucb, UCB_MODE, UCB_MODE_DYN_VFLAG_ENA); + + /* + * Take off-hook + */ + if (ucba->daa_oh_bit) + ucb1x00_io_write(ucba->ucb, 0, ucba->daa_oh_bit); +} + +static void ucb1x00_audio_shutdown(void *data) +{ + struct ucb1x00_audio *ucba = data; + + /* + * Place on-hook + */ + if (ucba->daa_oh_bit) + ucb1x00_io_write(ucba->ucb, ucba->daa_oh_bit, 0); + + ucb1x00_reg_write(ucba->ucb, ucba->telecom ? UCB_TC_B : UCB_AC_B, 0); + ucb1x00_disable(ucba->ucb); +} + +static int +ucb1x00_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) +{ + struct ucb1x00_audio *ucba; + int val, ret = 0; + + ucba = list_entry(file->f_op, struct ucb1x00_audio, fops); + + /* + * Make sure we have our magic number + */ + if (ucba->magic != MAGIC) + return -ENODEV; + + switch (cmd) { + case SNDCTL_DSP_STEREO: + ret = get_user(val, (int *)arg); + if (ret) + return ret; + if (val != 0) + return -EINVAL; + val = 0; + break; + + case SNDCTL_DSP_CHANNELS: + case SOUND_PCM_READ_CHANNELS: + val = 1; + break; + + case SNDCTL_DSP_SPEED: + ret = get_user(val, (int *)arg); + if (ret) + return ret; + val = ucb1x00_audio_setrate(ucba, val); + break; + + case SOUND_PCM_READ_RATE: + val = ucb1x00_audio_getrate(ucba); + break; + + case SNDCTL_DSP_SETFMT: + case SNDCTL_DSP_GETFMTS: + val = AFMT_S16_LE; + break; + + default: + return ucb1x00_mixer_ioctl(inode, file, cmd, arg); + } + + return put_user(val, (int *)arg); +} + +static int ucb1x00_audio_open(struct inode *inode, struct file *file) +{ + struct ucb1x00_audio *ucba; + + ucba = list_entry(file->f_op, struct ucb1x00_audio, fops); + + return sa1100_audio_attach(inode, file, &ucba->state); +} + +static struct ucb1x00_audio *ucb1x00_audio_alloc(struct ucb1x00 *ucb) +{ + struct ucb1x00_audio *ucba; + + ucba = kmalloc(sizeof(*ucba), GFP_KERNEL); + if (ucba) { + memset(ucba, 0, sizeof(*ucba)); + + ucba->magic = MAGIC; + ucba->ucb = ucb; + ucba->fops.owner = THIS_MODULE; + ucba->fops.open = ucb1x00_audio_open; + ucba->mops.owner = THIS_MODULE; + ucba->mops.ioctl = ucb1x00_mixer_ioctl; + ucba->state.output_stream = &ucba->output_stream; + ucba->state.input_stream = &ucba->input_stream; + ucba->state.data = ucba; + ucba->state.hw_init = ucb1x00_audio_startup; + ucba->state.hw_shutdown = ucb1x00_audio_shutdown; + ucba->state.client_ioctl = ucb1x00_audio_ioctl; + + /* There is a bug in the StrongARM causes corrupt MCP data to be sent to + * the codec when the FIFOs are empty and writes are made to the OS timer + * match register 0. To avoid this we must make sure that data is always + * sent to the codec. + */ + ucba->state.need_tx_for_rx = 1; + + init_MUTEX(&ucba->state.sem); + ucba->rate = 8000; + } + return ucba; +} + +static struct ucb1x00_audio *audio, *telecom; + +static int __init ucb1x00_audio_init(void) +{ + struct ucb1x00 *ucb = ucb1x00_get(); + struct ucb1x00_audio *a; + + if (!ucb) + return -ENODEV; + + a = ucb1x00_audio_alloc(ucb); + if (a) { + a->state.input_dma = ucb->mcp->dma_audio_rd; + a->state.input_id = "UCB1x00 audio in"; + a->state.output_dma = ucb->mcp->dma_audio_wr; + a->state.output_id = "UCB1x00 audio out"; + a->dev_id = register_sound_dsp(&a->fops, -1); + a->mix_id = register_sound_mixer(&a->mops, -1); + a->ctrl_a = 0; + a->ctrl_b = UCB_AC_B_IN_ENA|UCB_AC_B_OUT_ENA; + audio = a; + } + + a = ucb1x00_audio_alloc(ucb); + if (a) { +#if 0 + a->daa_oh_bit = UCB_IO_8; + + ucb1x00_enable(ucb); + ucb1x00_io_write(ucb, a->daa_oh_bit, 0); + ucb1x00_io_set_dir(ucb, UCB_IO_7 | UCB_IO_6, a->daa_oh_bit); + ucb1x00_disable(ucb); +#endif + + a->telecom = 1; + a->state.input_dma = ucb->mcp->dma_telco_rd; + a->state.input_id = "UCB1x00 telco in"; + a->state.output_dma = ucb->mcp->dma_telco_wr; + a->state.output_id = "UCB1x00 telco out"; + a->dev_id = register_sound_dsp(&a->fops, -1); + a->mix_id = register_sound_mixer(&a->mops, -1); + a->ctrl_a = 0; + a->ctrl_b = UCB_TC_B_IN_ENA|UCB_TC_B_OUT_ENA; + telecom = a; + } + + return 0; +} + +static void __exit ucb1x00_audio_exit(void) +{ + unregister_sound_dsp(telecom->dev_id); + unregister_sound_dsp(audio->dev_id); + unregister_sound_mixer(telecom->mix_id); + unregister_sound_mixer(audio->mix_id); +} + +module_init(ucb1x00_audio_init); +module_exit(ucb1x00_audio_exit); + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("UCB1x00 telecom/audio driver"); +MODULE_LICENSE("GPL"); diff -urN orig/drivers/misc/ucb1x00-core.c linux/drivers/misc/ucb1x00-core.c --- orig/drivers/misc/ucb1x00-core.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/misc/ucb1x00-core.c Sun Jun 29 17:07:42 2003 @@ -0,0 +1,647 @@ +/* + * linux/drivers/misc/ucb1x00-core.c + * + * Copyright (C) 2001 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * The UCB1x00 core driver provides basic services for handling IO, + * the ADC, interrupts, and accessing registers. It is designed + * such that everything goes through this layer, thereby providing + * a consistent locking methodology, as well as allowing the drivers + * to be used on other non-MCP-enabled hardware platforms. + * + * Note that all locks are private to this file. Nothing else may + * touch them. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ucb1x00.h" + +/** + * ucb1x00_io_set_dir - set IO direction + * @ucb: UCB1x00 structure describing chip + * @in: bitfield of IO pins to be set as inputs + * @out: bitfield of IO pins to be set as outputs + * + * Set the IO direction of the ten general purpose IO pins on + * the UCB1x00 chip. The @in bitfield has priority over the + * @out bitfield, in that if you specify a pin as both input + * and output, it will end up as an input. + * + * ucb1x00_enable must have been called to enable the comms + * before using this function. + * + * This function takes a spinlock, disabling interrupts. + */ +void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out) +{ + unsigned long flags; + + spin_lock_irqsave(&ucb->io_lock, flags); + ucb->io_dir |= out; + ucb->io_dir &= ~in; + + ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); + spin_unlock_irqrestore(&ucb->io_lock, flags); +} + +/** + * ucb1x00_io_write - set or clear IO outputs + * @ucb: UCB1x00 structure describing chip + * @set: bitfield of IO pins to set to logic '1' + * @clear: bitfield of IO pins to set to logic '0' + * + * Set the IO output state of the specified IO pins. The value + * is retained if the pins are subsequently configured as inputs. + * The @clear bitfield has priority over the @set bitfield - + * outputs will be cleared. + * + * ucb1x00_enable must have been called to enable the comms + * before using this function. + * + * This function takes a spinlock, disabling interrupts. + */ +void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear) +{ + unsigned long flags; + + spin_lock_irqsave(&ucb->io_lock, flags); + ucb->io_out |= set; + ucb->io_out &= ~clear; + + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); + spin_unlock_irqrestore(&ucb->io_lock, flags); +} + +/** + * ucb1x00_io_read - read the current state of the IO pins + * @ucb: UCB1x00 structure describing chip + * + * Return a bitfield describing the logic state of the ten + * general purpose IO pins. + * + * ucb1x00_enable must have been called to enable the comms + * before using this function. + * + * This function does not take any semaphores or spinlocks. + */ +unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) +{ + return ucb1x00_reg_read(ucb, UCB_IO_DATA); +} + +/* + * UCB1300 data sheet says we must: + * 1. enable ADC => 5us (including reference startup time) + * 2. select input => 51*tsibclk => 4.3us + * 3. start conversion => 102*tsibclk => 8.5us + * (tsibclk = 1/11981000) + * Period between SIB 128-bit frames = 10.7us + */ + +/** + * ucb1x00_adc_enable - enable the ADC converter + * @ucb: UCB1x00 structure describing chip + * + * Enable the ucb1x00 and ADC converter on the UCB1x00 for use. + * Any code wishing to use the ADC converter must call this + * function prior to using it. + * + * This function takes the ADC semaphore to prevent two or more + * concurrent uses, and therefore may sleep. As a result, it + * can only be called from process context, not interrupt + * context. + * + * You should release the ADC as soon as possible using + * ucb1x00_adc_disable. + */ +void ucb1x00_adc_enable(struct ucb1x00 *ucb) +{ + down(&ucb->adc_sem); + + ucb->adc_cr |= UCB_ADC_ENA; + + ucb1x00_enable(ucb); + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); +} + +/** + * ucb1x00_adc_read - read the specified ADC channel + * @ucb: UCB1x00 structure describing chip + * @adc_channel: ADC channel mask + * @sync: wait for syncronisation pulse. + * + * Start an ADC conversion and wait for the result. Note that + * synchronised ADC conversions (via the ADCSYNC pin) must wait + * until the trigger is asserted and the conversion is finished. + * + * This function currently spins waiting for the conversion to + * complete (2 frames max without sync). + * + * If called for a synchronised ADC conversion, it may sleep + * with the ADC semaphore held. + */ +unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) +{ + unsigned int val; + + if (sync) + adc_channel |= UCB_ADC_SYNC_ENA; + + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel); + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START); + + for (;;) { + val = ucb1x00_reg_read(ucb, UCB_ADC_DATA); + if (val & UCB_ADC_DAT_VAL) + break; + /* yield to other processes */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + return UCB_ADC_DAT(val); +} + +/** + * ucb1x00_adc_disable - disable the ADC converter + * @ucb: UCB1x00 structure describing chip + * + * Disable the ADC converter and release the ADC semaphore. + */ +void ucb1x00_adc_disable(struct ucb1x00 *ucb) +{ + ucb->adc_cr &= ~UCB_ADC_ENA; + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); + ucb1x00_disable(ucb); + + up(&ucb->adc_sem); +} + +#ifdef CONFIG_PM +static int ucb1x00_pm (struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct ucb1x00 *ucb = (struct ucb1x00 *)dev->data; + unsigned int isr; + + if (rqst == PM_RESUME) { + ucb1x00_enable(ucb); + isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + ucb1x00_disable(ucb); + } + + return 0; +} +#endif + +/* + * UCB1x00 Interrupt handling. + * + * The UCB1x00 can generate interrupts when the SIBCLK is stopped. + * Since we need to read an internal register, we must re-enable + * SIBCLK to talk to the chip. We leave the clock running until + * we have finished processing all interrupts from the chip. + */ +static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs) +{ + struct ucb1x00 *ucb = devid; + struct ucb1x00_irq *irq; + unsigned int isr, i; + + ucb1x00_enable(ucb); + isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + + for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++) + if (isr & 1 && irq->fn) + irq->fn(i, irq->devid); + ucb1x00_disable(ucb); +} + +/** + * ucb1x00_hook_irq - hook a UCB1x00 interrupt + * @ucb: UCB1x00 structure describing chip + * @idx: interrupt index + * @fn: function to call when interrupt is triggered + * @devid: device id to pass to interrupt handler + * + * Hook the specified interrupt. You can only register one handler + * for each interrupt source. The interrupt source is not enabled + * by this function; use ucb1x00_enable_irq instead. + * + * Interrupt handlers will be called with other interrupts enabled. + * + * Returns zero on success, or one of the following errors: + * -EINVAL if the interrupt index is invalid + * -EBUSY if the interrupt has already been hooked + */ +int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid) +{ + struct ucb1x00_irq *irq; + int ret = -EINVAL; + + if (idx < 16) { + irq = ucb->irq_handler + idx; + ret = -EBUSY; + + spin_lock_irq(&ucb->lock); + if (irq->fn == NULL) { + irq->devid = devid; + irq->fn = fn; + ret = 0; + } + spin_unlock_irq(&ucb->lock); + } + return ret; +} + +/** + * ucb1x00_enable_irq - enable an UCB1x00 interrupt source + * @ucb: UCB1x00 structure describing chip + * @idx: interrupt index + * @edges: interrupt edges to enable + * + * Enable the specified interrupt to trigger on %UCB_RISING, + * %UCB_FALLING or both edges. The interrupt should have been + * hooked by ucb1x00_hook_irq. + */ +void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) +{ + unsigned long flags; + + if (idx < 16) { + spin_lock_irqsave(&ucb->lock, flags); + + ucb1x00_enable(ucb); + if (edges & UCB_RISING) { + ucb->irq_ris_enbl |= 1 << idx; + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); + } + if (edges & UCB_FALLING) { + ucb->irq_fal_enbl |= 1 << idx; + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); + } + ucb1x00_disable(ucb); + spin_unlock_irqrestore(&ucb->lock, flags); + } +} + +/** + * ucb1x00_disable_irq - disable an UCB1x00 interrupt source + * @ucb: UCB1x00 structure describing chip + * @edges: interrupt edges to disable + * + * Disable the specified interrupt triggering on the specified + * (%UCB_RISING, %UCB_FALLING or both) edges. + */ +void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) +{ + unsigned long flags; + + if (idx < 16) { + spin_lock_irqsave(&ucb->lock, flags); + + ucb1x00_enable(ucb); + if (edges & UCB_RISING) { + ucb->irq_ris_enbl &= ~(1 << idx); + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); + } + if (edges & UCB_FALLING) { + ucb->irq_fal_enbl &= ~(1 << idx); + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); + } + ucb1x00_disable(ucb); + spin_unlock_irqrestore(&ucb->lock, flags); + } +} + +/** + * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt + * @ucb: UCB1x00 structure describing chip + * @idx: interrupt index + * @devid: device id. + * + * Disable the interrupt source and remove the handler. devid must + * match the devid passed when hooking the interrupt. + * + * Returns zero on success, or one of the following errors: + * -EINVAL if the interrupt index is invalid + * -ENOENT if devid does not match + */ +int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid) +{ + struct ucb1x00_irq *irq; + int ret; + + if (idx >= 16) + goto bad; + + irq = ucb->irq_handler + idx; + ret = -ENOENT; + + spin_lock_irq(&ucb->lock); + if (irq->devid == devid) { + ucb->irq_ris_enbl &= ~(1 << idx); + ucb->irq_fal_enbl &= ~(1 << idx); + + ucb1x00_enable(ucb); + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); + ucb1x00_disable(ucb); + + irq->fn = NULL; + irq->devid = NULL; + ret = 0; + } + spin_unlock_irq(&ucb->lock); + return ret; + +bad: + printk(KERN_ERR "%s: freeing bad irq %d\n", __FUNCTION__, idx); + return -EINVAL; +} + +/* + * Try to probe our interrupt, rather than relying on lots of + * hard-coded machine dependencies. For reference, the expected + * IRQ mappings are: + * + * Machine Default IRQ + * adsbitsy IRQ_GPCIN4 + * cerf IRQ_GPIO_UCB1200_IRQ + * flexanet IRQ_GPIO_GUI + * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ + * graphicsclient ADS_EXT_IRQ(8) + * graphicsmaster ADS_EXT_IRQ(8) + * lart LART_IRQ_UCB1200 + * omnimeter IRQ_GPIO23 + * pfs168 IRQ_GPIO_UCB1300_IRQ + * simpad IRQ_GPIO_UCB1300_IRQ + * shannon SHANNON_IRQ_GPIO_IRQ_CODEC + * yopy IRQ_GPIO_UCB1200_IRQ + */ +static int __init ucb1x00_detect_irq(struct ucb1x00 *ucb) +{ + unsigned long mask; + + mask = probe_irq_on(); + if (!mask) + return NO_IRQ; + + /* + * Enable the ADC interrupt. + */ + ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC); + ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + + /* + * Cause an ADC interrupt. + */ + ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); + ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START); + + /* + * Wait for the conversion to complete. + */ + while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0); + ucb1x00_reg_write(ucb, UCB_ADC_CR, 0); + + /* + * Disable and clear interrupt. + */ + ucb1x00_reg_write(ucb, UCB_IE_RIS, 0); + ucb1x00_reg_write(ucb, UCB_IE_FAL, 0); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + + /* + * Read triggered interrupt. + */ + return probe_irq_off(mask); +} + +/* + * This configures the UCB1x00 layer depending on the machine type + * we're running on. The UCB1x00 drivers should not contain any + * machine dependencies. + * + * We can get rid of some of these dependencies by using existing + * facilities provided by the kernel - namely IRQ probing. The + * machine specific files are expected to setup the IRQ levels on + * initialisation. With any luck, we'll get rid of all the + * machine dependencies here. + */ +static int __init ucb1x00_configure(struct ucb1x00 *ucb) +{ + unsigned int irq_gpio_pin = 0; + int irq, default_irq = NO_IRQ; + + if (machine_is_adsbitsy()) + default_irq = IRQ_GPCIN4; + +// if (machine_is_assabet()) +// default_irq = IRQ_GPIO23; + +#ifdef CONFIG_SA1100_CERF + if (machine_is_cerf()) + default_irq = IRQ_GPIO_UCB1200_IRQ; +#endif +#ifdef CONFIG_SA1100_FREEBIRD + if (machine_is_freebird()) + default_irq = IRQ_GPIO_FREEBIRD_UCB1300_IRQ; +#endif +#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || defined(CONFIG_SA1100_GRAPICSMASTER) + if (machine_is_graphicsclient() || machine_is_graphicsmaster()) + default_irq = ADS_EXT_IRQ(8); +#endif +#ifdef CONFIG_SA1100_LART + if (machine_is_lart()) { + default_irq = LART_IRQ_UCB1200; + irq_gpio_pin = LART_GPIO_UCB1200; + } +#endif + if (machine_is_omnimeter()) + default_irq = IRQ_GPIO23; + +#ifdef CONFIG_SA1100_PFS168 + if (machine_is_pfs168()) + default_irq = IRQ_GPIO_UCB1300_IRQ; +#endif +#ifdef CONFIG_SA1100_SIMPAD + if (machine_is_simpad()) + default_irq = IRQ_GPIO_UCB1300_IRQ; +#endif +#ifdef CONFIG_SA1100_SIMPUTER + if (machine_is_simputer()) { + default_irq = IRQ_GPIO_UCB1300_IRQ; + irq_gpio_pin = GPIO_UCB1300_IRQ; + } +#endif + if (machine_is_shannon()) + default_irq = SHANNON_IRQ_GPIO_IRQ_CODEC; +#ifdef CONFIG_SA1100_YOPY + if (machine_is_yopy()) + default_irq = IRQ_GPIO_UCB1200_IRQ; +#endif +#ifdef CONFIG_SA1100_ACCELENT + if (machine_is_accelent_sa()) { + ucb->irq = IRQ_GPIO_UCB1200_IRQ; + irq_gpio_pin = GPIO_UCB1200_IRQ; + } +#endif + + /* + * Eventually, this will disappear. + */ + if (irq_gpio_pin) + set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE); + + irq = ucb1x00_detect_irq(ucb); + if (irq != NO_IRQ) { + if (default_irq != NO_IRQ && irq != default_irq) + printk(KERN_ERR "UCB1x00: probed IRQ%d != default IRQ%d\n", + irq, default_irq); + if (irq == default_irq) + printk(KERN_ERR "UCB1x00: probed IRQ%d correctly. " + "Please remove machine dependencies from " + "ucb1x00-core.c\n", irq); + ucb->irq = irq; + } else { + printk(KERN_ERR "UCB1x00: IRQ probe failed, using IRQ%d\n", + default_irq); + ucb->irq = default_irq; + } + + return ucb->irq == NO_IRQ ? -ENODEV : 0; +} + +struct ucb1x00 *my_ucb; + +/** + * ucb1x00_get - get the UCB1x00 structure describing a chip + * @ucb: UCB1x00 structure describing chip + * + * Return the UCB1x00 structure describing a chip. + * + * FIXME: Currently very noddy indeed, which currently doesn't + * matter since we only support one chip. + */ +struct ucb1x00 *ucb1x00_get(void) +{ + return my_ucb; +} + +static int __init ucb1x00_init(void) +{ + struct mcp *mcp; + unsigned int id; + int ret = -ENODEV; + + mcp = mcp_get(); + if (!mcp) + goto no_mcp; + + mcp_enable(mcp); + id = mcp_reg_read(mcp, UCB_ID); + + if (id != UCB_ID_1200 && id != UCB_ID_1300) { + printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); + goto out; + } + + my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL); + ret = -ENOMEM; + if (!my_ucb) + goto out; + + if (machine_is_shannon()) { + /* reset the codec */ + GPDR |= SHANNON_GPIO_CODEC_RESET; + GPCR = SHANNON_GPIO_CODEC_RESET; + GPSR = SHANNON_GPIO_CODEC_RESET; + + } + + memset(my_ucb, 0, sizeof(struct ucb1x00)); + + spin_lock_init(&my_ucb->lock); + spin_lock_init(&my_ucb->io_lock); + sema_init(&my_ucb->adc_sem, 1); + + my_ucb->id = id; + my_ucb->mcp = mcp; + + ret = ucb1x00_configure(my_ucb); + if (ret) + goto out; + + ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb); + if (ret) { + printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", + my_ucb->irq, ret); + kfree(my_ucb); + my_ucb = NULL; + goto out; + } + +#ifdef CONFIG_PM + my_ucb->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_pm); + if (my_ucb->pmdev == NULL) + printk("ucb1x00: unable to register in PM.\n"); + else + my_ucb->pmdev->data = my_ucb; +#endif + +out: + mcp_disable(mcp); +no_mcp: + return ret; +} + +static void __exit ucb1x00_exit(void) +{ + free_irq(my_ucb->irq, my_ucb); + kfree(my_ucb); +} + +module_init(ucb1x00_init); +module_exit(ucb1x00_exit); + +EXPORT_SYMBOL(ucb1x00_get); + +EXPORT_SYMBOL(ucb1x00_io_set_dir); +EXPORT_SYMBOL(ucb1x00_io_write); +EXPORT_SYMBOL(ucb1x00_io_read); + +EXPORT_SYMBOL(ucb1x00_adc_enable); +EXPORT_SYMBOL(ucb1x00_adc_read); +EXPORT_SYMBOL(ucb1x00_adc_disable); + +EXPORT_SYMBOL(ucb1x00_hook_irq); +EXPORT_SYMBOL(ucb1x00_free_irq); +EXPORT_SYMBOL(ucb1x00_enable_irq); +EXPORT_SYMBOL(ucb1x00_disable_irq); + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("UCB1x00 core driver"); +MODULE_LICENSE("GPL"); diff -urN orig/drivers/misc/ucb1x00-ts.c linux/drivers/misc/ucb1x00-ts.c --- orig/drivers/misc/ucb1x00-ts.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/misc/ucb1x00-ts.c Fri Jun 21 15:49:47 2002 @@ -0,0 +1,664 @@ +/* + * linux/drivers/misc/ucb1x00-ts.c + * + * Copyright (C) 2001 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 21-Jan-2002 : + * + * Added support for synchronous A/D mode. This mode is useful to + * avoid noise induced in the touchpanel by the LCD, provided that + * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin. + * It is important to note that the signal connected to the ADCSYNC + * pin should provide pulses even when the LCD is blanked, otherwise + * a pen touch needed to unblank the LCD will never be read. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ucb1x00.h" + +/* + * Define this if you want the UCB1x00 stuff to talk to the input layer + */ +#undef USE_INPUT + +#ifndef USE_INPUT + +#include +#include +#include + +/* + * This structure is nonsense - millisecs is not very useful + * since the field size is too small. Also, we SHOULD NOT + * be exposing jiffies to user space directly. + */ +struct ts_event { + u16 pressure; + u16 x; + u16 y; + u16 pad; + struct timeval stamp; +}; + +#define NR_EVENTS 16 + +#else + +#include + +#endif + +struct ucb1x00_ts { +#ifdef USE_INPUT + struct input_dev idev; +#endif + struct ucb1x00 *ucb; +#ifdef CONFIG_PM + struct pm_dev *pmdev; +#endif + + wait_queue_head_t irq_wait; + struct semaphore sem; + struct completion init_exit; + struct task_struct *rtask; + int use_count; + u16 x_res; + u16 y_res; + +#ifndef USE_INPUT + struct fasync_struct *fasync; + wait_queue_head_t read_wait; + u8 evt_head; + u8 evt_tail; + struct ts_event events[NR_EVENTS]; +#endif + int restart:1; + int adcsync:1; +}; + +static struct ucb1x00_ts ucbts; +static int adcsync = UCB_NOSYNC; + +static int ucb1x00_ts_startup(struct ucb1x00_ts *ts); +static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts); + +#ifndef USE_INPUT + +#define ucb1x00_ts_evt_pending(ts) ((volatile u8)(ts)->evt_head != (ts)->evt_tail) +#define ucb1x00_ts_evt_get(ts) ((ts)->events + (ts)->evt_tail) +#define ucb1x00_ts_evt_pull(ts) ((ts)->evt_tail = ((ts)->evt_tail + 1) & (NR_EVENTS - 1)) +#define ucb1x00_ts_evt_clear(ts) ((ts)->evt_head = (ts)->evt_tail = 0) + +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) +{ + int next_head; + + next_head = (ts->evt_head + 1) & (NR_EVENTS - 1); + if (next_head != ts->evt_tail) { + ts->events[ts->evt_head].pressure = pressure; + ts->events[ts->evt_head].x = x; + ts->events[ts->evt_head].y = y; + do_gettimeofday(&ts->events[ts->evt_head].stamp); + ts->evt_head = next_head; + + if (ts->fasync) + kill_fasync(&ts->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&ts->read_wait); + } +} + +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) +{ + ucb1x00_ts_evt_add(ts, 0, 0, 0); +} + +/* + * User space driver interface. + */ +static ssize_t +ucb1x00_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + struct ucb1x00_ts *ts = filp->private_data; + char *ptr = buffer; + int err = 0; + + add_wait_queue(&ts->read_wait, &wait); + while (count >= sizeof(struct ts_event)) { + err = -ERESTARTSYS; + if (signal_pending(current)) + break; + + if (ucb1x00_ts_evt_pending(ts)) { + struct ts_event *evt = ucb1x00_ts_evt_get(ts); + + err = copy_to_user(ptr, evt, sizeof(struct ts_event)); + ucb1x00_ts_evt_pull(ts); + + if (err) + break; + + ptr += sizeof(struct ts_event); + count -= sizeof(struct ts_event); + continue; + } + + set_current_state(TASK_INTERRUPTIBLE); + err = -EAGAIN; + if (filp->f_flags & O_NONBLOCK) + break; + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&ts->read_wait, &wait); + + return ptr == buffer ? err : ptr - buffer; +} + +static unsigned int ucb1x00_ts_poll(struct file *filp, poll_table *wait) +{ + struct ucb1x00_ts *ts = filp->private_data; + int ret = 0; + + poll_wait(filp, &ts->read_wait, wait); + if (ucb1x00_ts_evt_pending(ts)) + ret = POLLIN | POLLRDNORM; + + return ret; +} + +static int ucb1x00_ts_fasync(int fd, struct file *filp, int on) +{ + struct ucb1x00_ts *ts = filp->private_data; + + return fasync_helper(fd, filp, on, &ts->fasync); +} + +static int ucb1x00_ts_open(struct inode *inode, struct file *filp) +{ + struct ucb1x00_ts *ts = &ucbts; + int ret = 0; + + ret = ucb1x00_ts_startup(ts); + if (ret == 0) + filp->private_data = ts; + + return ret; +} + +/* + * Release touchscreen resources. Disable IRQs. + */ +static int ucb1x00_ts_release(struct inode *inode, struct file *filp) +{ + struct ucb1x00_ts *ts = filp->private_data; + + down(&ts->sem); + ucb1x00_ts_fasync(-1, filp, 0); + ucb1x00_ts_shutdown(ts); + up(&ts->sem); + + return 0; +} + +static struct file_operations ucb1x00_fops = { + owner: THIS_MODULE, + read: ucb1x00_ts_read, + poll: ucb1x00_ts_poll, + open: ucb1x00_ts_open, + release: ucb1x00_ts_release, + fasync: ucb1x00_ts_fasync, +}; + +/* + * The official UCB1x00 touchscreen is a miscdevice: + * 10 char Non-serial mice, misc features + * 14 = /dev/touchscreen/ucb1x00 UCB 1x00 touchscreen + */ +static struct miscdevice ucb1x00_ts_dev = { + minor: 14, + name: "touchscreen/ucb1x00", + fops: &ucb1x00_fops, +}; + +static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts) +{ + init_waitqueue_head(&ts->read_wait); + return misc_register(&ucb1x00_ts_dev); +} + +static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts) +{ + misc_deregister(&ucb1x00_ts_dev); +} + +#else + +#define ucb1x00_ts_evt_clear(ts) do { } while (0) + +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) +{ + input_report_abs(&ts->idev, ABS_X, x); + input_report_abs(&ts->idev, ABS_Y, y); + input_report_abs(&ts->idev, ABS_PRESSURE, pressure); +} + +static int ucb1x00_ts_open(struct input_dev *idev) +{ + struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev; + + return ucb1x00_ts_startup(ts); +} + +static void ucb1x00_ts_close(struct input_dev *idev) +{ + struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev; + + down(&ts->sem); + ucb1x00_ts_shutdown(ts); + up(&ts->sem); +} + +static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts) +{ + ts->idev.name = "Touchscreen panel"; + ts->idev.idproduct = ts->ucb->id; + ts->idev.open = ucb1x00_ts_open; + ts->idev.close = ucb1x00_ts_close; + + __set_bit(EV_ABS, ts->idev.evbit); + __set_bit(ABS_X, ts->idev.absbit); + __set_bit(ABS_Y, ts->idev.absbit); + __set_bit(ABS_PRESSURE, ts->idev.absbit); + + input_register_device(&ts->idev); + + return 0; +} + +static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts) +{ + input_unregister_device(&ts->idev); +} + +#endif + +/* + * Switch to interrupt mode. + */ +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts) +{ + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_INT); +} + +/* + * Switch to pressure mode, and read pressure. We don't need to wait + * here, since both plates are being driven. + */ +static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) +{ + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); +} + +/* + * Switch to X position mode and measure Y plate. We switch the plate + * configuration in pressure mode, then switch to position mode. This + * gives a faster response time. Even so, we need to wait about 55us + * for things to stabilise. + */ +static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) +{ + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); + + udelay(55); + + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); +} + +/* + * Switch to Y position mode and measure X plate. We switch the plate + * configuration in pressure mode, then switch to position mode. This + * gives a faster response time. Even so, we need to wait about 55us + * for things to stabilise. + */ +static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) +{ + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); + + udelay(55); + + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync); +} + +/* + * Switch to X plate resistance mode. Set MX to ground, PX to + * supply. Measure current. + */ +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts) +{ + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); +} + +/* + * Switch to Y plate resistance mode. Set MY to ground, PY to + * supply. Measure current. + */ +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts) +{ + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); +} + +/* + * This is a RT kernel thread that handles the ADC accesses + * (mainly so we can use semaphores in the UCB1200 core code + * to serialise accesses to the ADC). + */ +static int ucb1x00_thread(void *_ts) +{ + struct ucb1x00_ts *ts = _ts; + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + int valid; + + ts->rtask = tsk; + + daemonize(); + reparent_to_init(); + strcpy(tsk->comm, "ktsd"); + tsk->tty = NULL; + /* + * We could run as a real-time thread. However, thus far + * this doesn't seem to be necessary. + */ +// tsk->policy = SCHED_FIFO; +// tsk->rt_priority = 1; + + /* only want to receive SIGKILL */ + spin_lock_irq(&tsk->sigmask_lock); + siginitsetinv(&tsk->blocked, sigmask(SIGKILL)); + recalc_sigpending(tsk); + spin_unlock_irq(&tsk->sigmask_lock); + + complete(&ts->init_exit); + + valid = 0; + + add_wait_queue(&ts->irq_wait, &wait); + for (;;) { + unsigned int x, y, p, val; + signed long timeout; + + ts->restart = 0; + + ucb1x00_adc_enable(ts->ucb); + + x = ucb1x00_ts_read_xpos(ts); + y = ucb1x00_ts_read_ypos(ts); + p = ucb1x00_ts_read_pressure(ts); + + /* + * Switch back to interrupt mode. + */ + ucb1x00_ts_mode_int(ts); + ucb1x00_adc_disable(ts->ucb); + + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 100); + if (signal_pending(tsk)) + break; + + ucb1x00_enable(ts->ucb); + val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR); + + if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) { + set_task_state(tsk, TASK_INTERRUPTIBLE); + + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); + ucb1x00_disable(ts->ucb); + + /* + * If we spat out a valid sample set last time, + * spit out a "pen off" sample here. + */ + if (valid) { + ucb1x00_ts_event_release(ts); + valid = 0; + } + + timeout = MAX_SCHEDULE_TIMEOUT; + } else { + ucb1x00_disable(ts->ucb); + + /* + * Filtering is policy. Policy belongs in user + * space. We therefore leave it to user space + * to do any filtering they please. + */ + if (!ts->restart) { + ucb1x00_ts_evt_add(ts, p, x, y); + valid = 1; + } + + set_task_state(tsk, TASK_INTERRUPTIBLE); + timeout = HZ / 100; + } + + schedule_timeout(timeout); + if (signal_pending(tsk)) + break; + } + + remove_wait_queue(&ts->irq_wait, &wait); + + ts->rtask = NULL; + ucb1x00_ts_evt_clear(ts); + complete_and_exit(&ts->init_exit, 0); +} + +/* + * We only detect touch screen _touches_ with this interrupt + * handler, and even then we just schedule our task. + */ +static void ucb1x00_ts_irq(int idx, void *id) +{ + struct ucb1x00_ts *ts = id; + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); + wake_up(&ts->irq_wait); +} + +static int ucb1x00_ts_startup(struct ucb1x00_ts *ts) +{ + int ret = 0; + + if (down_interruptible(&ts->sem)) + return -EINTR; + + if (ts->use_count++ != 0) + goto out; + + if (ts->rtask) + panic("ucb1x00: rtask running?"); + + init_waitqueue_head(&ts->irq_wait); + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); + if (ret < 0) + goto out; + + /* + * If we do this at all, we should allow the user to + * measure and read the X and Y resistance at any time. + */ + ucb1x00_adc_enable(ts->ucb); + ts->x_res = ucb1x00_ts_read_xres(ts); + ts->y_res = ucb1x00_ts_read_yres(ts); + ucb1x00_adc_disable(ts->ucb); + + init_completion(&ts->init_exit); + ret = kernel_thread(ucb1x00_thread, ts, 0); + if (ret >= 0) { + wait_for_completion(&ts->init_exit); + ret = 0; + } else { + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); + } + + out: + if (ret) + ts->use_count--; + up(&ts->sem); + return ret; +} + +/* + * Release touchscreen resources. Disable IRQs. + */ +static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts) +{ + if (--ts->use_count == 0) { + if (ts->rtask) { + send_sig(SIGKILL, ts->rtask, 1); + wait_for_completion(&ts->init_exit); + } + + ucb1x00_enable(ts->ucb); + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); + ucb1x00_disable(ts->ucb); + } +} + +#ifdef CONFIG_PM +static int ucb1x00_ts_pm (struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct ucb1x00_ts *ts = (struct ucb1x00_ts *) (dev->data); + + if (rqst == PM_RESUME && ts->rtask != NULL) { + /* + * Restart the TS thread to ensure the + * TS interrupt mode is set up again + * after sleep. + */ + ts->restart = 1; + wake_up(&ts->irq_wait); + } + return 0; +} +#endif + + +/* + * Initialisation. + */ +static int __init ucb1x00_ts_init(void) +{ + struct ucb1x00_ts *ts = &ucbts; + + ts->ucb = ucb1x00_get(); + if (!ts->ucb) + return -ENODEV; + + ts->adcsync = adcsync; + init_MUTEX(&ts->sem); + +#ifdef CONFIG_PM + ts->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_ts_pm); + if (ts->pmdev == NULL) + printk("ucb1x00_ts: unable to register in PM.\n"); + else + ts->pmdev->data = ts; +#endif + return ucb1x00_ts_register(ts); +} + +static void __exit ucb1x00_ts_exit(void) +{ + struct ucb1x00_ts *ts = &ucbts; + + ucb1x00_ts_deregister(ts); + +#ifdef CONFIG_PM + if (ts->pmdev) + pm_unregister(ts->pmdev); +#endif +} + +#ifndef MODULE + +/* + * Parse kernel command-line options. + * + * syntax : ucbts=[sync|nosync],... + */ +static int __init ucb1x00_ts_setup(char *str) +{ + char *p; + + while ((p = strsep(&str, ",")) != NULL) { + if (strcmp(p, "sync") == 0) + adcsync = UCB_SYNC; + } + + return 1; +} + +__setup("ucbts=", ucb1x00_ts_setup); + +#else + +MODULE_PARM(adcsync, "i"); +MODULE_PARM_DESC(adcsync, "Enable use of ADCSYNC signal"); + +#endif + +module_init(ucb1x00_ts_init); +module_exit(ucb1x00_ts_exit); + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("UCB1x00 touchscreen driver"); +MODULE_LICENSE("GPL"); diff -urN orig/drivers/misc/ucb1x00.h linux/drivers/misc/ucb1x00.h --- orig/drivers/misc/ucb1x00.h Thu Jan 1 01:00:00 1970 +++ linux/drivers/misc/ucb1x00.h Thu Oct 24 15:24:52 2002 @@ -0,0 +1,232 @@ +/* + * linux/drivers/misc/ucb1x00.h + * + * Copyright (C) 2001 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + */ +#ifndef UCB1200_H +#define UCB1200_H + +#define UCB_IO_DATA 0x00 +#define UCB_IO_DIR 0x01 + +#define UCB_IO_0 (1 << 0) +#define UCB_IO_1 (1 << 1) +#define UCB_IO_2 (1 << 2) +#define UCB_IO_3 (1 << 3) +#define UCB_IO_4 (1 << 4) +#define UCB_IO_5 (1 << 5) +#define UCB_IO_6 (1 << 6) +#define UCB_IO_7 (1 << 7) +#define UCB_IO_8 (1 << 8) +#define UCB_IO_9 (1 << 9) + +#define UCB_IE_RIS 0x02 +#define UCB_IE_FAL 0x03 +#define UCB_IE_STATUS 0x04 +#define UCB_IE_CLEAR 0x04 +#define UCB_IE_ADC (1 << 11) +#define UCB_IE_TSPX (1 << 12) +#define UCB_IE_TSMX (1 << 13) +#define UCB_IE_TCLIP (1 << 14) +#define UCB_IE_ACLIP (1 << 15) + +#define UCB_IRQ_TSPX 12 + +#define UCB_TC_A 0x05 +#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */ +#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */ + +#define UCB_TC_B 0x06 +#define UCB_TC_B_VOICE_ENA (1 << 3) +#define UCB_TC_B_CLIP (1 << 4) +#define UCB_TC_B_ATT (1 << 6) +#define UCB_TC_B_SIDE_ENA (1 << 11) +#define UCB_TC_B_MUTE (1 << 13) +#define UCB_TC_B_IN_ENA (1 << 14) +#define UCB_TC_B_OUT_ENA (1 << 15) + +#define UCB_AC_A 0x07 +#define UCB_AC_B 0x08 +#define UCB_AC_B_LOOP (1 << 8) +#define UCB_AC_B_MUTE (1 << 13) +#define UCB_AC_B_IN_ENA (1 << 14) +#define UCB_AC_B_OUT_ENA (1 << 15) + +#define UCB_TS_CR 0x09 +#define UCB_TS_CR_TSMX_POW (1 << 0) +#define UCB_TS_CR_TSPX_POW (1 << 1) +#define UCB_TS_CR_TSMY_POW (1 << 2) +#define UCB_TS_CR_TSPY_POW (1 << 3) +#define UCB_TS_CR_TSMX_GND (1 << 4) +#define UCB_TS_CR_TSPX_GND (1 << 5) +#define UCB_TS_CR_TSMY_GND (1 << 6) +#define UCB_TS_CR_TSPY_GND (1 << 7) +#define UCB_TS_CR_MODE_INT (0 << 8) +#define UCB_TS_CR_MODE_PRES (1 << 8) +#define UCB_TS_CR_MODE_POS (2 << 8) +#define UCB_TS_CR_BIAS_ENA (1 << 11) +#define UCB_TS_CR_TSPX_LOW (1 << 12) +#define UCB_TS_CR_TSMX_LOW (1 << 13) + +#define UCB_ADC_CR 0x0a +#define UCB_ADC_SYNC_ENA (1 << 0) +#define UCB_ADC_VREFBYP_CON (1 << 1) +#define UCB_ADC_INP_TSPX (0 << 2) +#define UCB_ADC_INP_TSMX (1 << 2) +#define UCB_ADC_INP_TSPY (2 << 2) +#define UCB_ADC_INP_TSMY (3 << 2) +#define UCB_ADC_INP_AD0 (4 << 2) +#define UCB_ADC_INP_AD1 (5 << 2) +#define UCB_ADC_INP_AD2 (6 << 2) +#define UCB_ADC_INP_AD3 (7 << 2) +#define UCB_ADC_EXT_REF (1 << 5) +#define UCB_ADC_START (1 << 7) +#define UCB_ADC_ENA (1 << 15) + +#define UCB_ADC_DATA 0x0b +#define UCB_ADC_DAT_VAL (1 << 15) +#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5) + +#define UCB_ID 0x0c +#define UCB_ID_1200 0x1004 +#define UCB_ID_1300 0x1005 + +#define UCB_MODE 0x0d +#define UCB_MODE_DYN_VFLAG_ENA (1 << 12) +#define UCB_MODE_AUD_OFF_CAN (1 << 13) + +#include "mcp.h" + +struct ucb1x00; + +struct ucb1x00_irq { + void *devid; + void (*fn)(int, void *); +}; + +struct ucb1x00 { + spinlock_t lock; + struct mcp *mcp; + struct pm_dev *pmdev; + unsigned int irq; + struct semaphore adc_sem; + spinlock_t io_lock; + u16 id; + u16 io_dir; + u16 io_out; + u16 adc_cr; + u16 irq_fal_enbl; + u16 irq_ris_enbl; + struct ucb1x00_irq irq_handler[16]; +}; + +/** + * ucb1x00_clkrate - return the UCB1x00 SIB clock rate + * @ucb: UCB1x00 structure describing chip + * + * Return the SIB clock rate in Hz. + */ +static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb) +{ + return mcp_get_sclk_rate(ucb->mcp); +} + +/** + * ucb1x00_enable - enable the UCB1x00 SIB clock + * @ucb: UCB1x00 structure describing chip + * + * Enable the SIB clock. This can be called multiple times. + */ +static inline void ucb1x00_enable(struct ucb1x00 *ucb) +{ + mcp_enable(ucb->mcp); +} + +/** + * ucb1x00_disable - disable the UCB1x00 SIB clock + * @ucb: UCB1x00 structure describing chip + * + * Disable the SIB clock. The SIB clock will only be disabled + * when the number of ucb1x00_enable calls match the number of + * ucb1x00_disable calls. + */ +static inline void ucb1x00_disable(struct ucb1x00 *ucb) +{ + mcp_disable(ucb->mcp); +} + +/** + * ucb1x00_reg_write - write a UCB1x00 register + * @ucb: UCB1x00 structure describing chip + * @reg: UCB1x00 4-bit register index to write + * @val: UCB1x00 16-bit value to write + * + * Write the UCB1x00 register @reg with value @val. The SIB + * clock must be running for this function to return. + */ +static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val) +{ + mcp_reg_write(ucb->mcp, reg, val); +} + +/** + * ucb1x00_reg_read - read a UCB1x00 register + * @ucb: UCB1x00 structure describing chip + * @reg: UCB1x00 4-bit register index to write + * + * Read the UCB1x00 register @reg and return its value. The SIB + * clock must be running for this function to return. + */ +static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg) +{ + return mcp_reg_read(ucb->mcp, reg); +} +/** + * ucb1x00_set_audio_divisor - + * @ucb: UCB1x00 structure describing chip + * @div: SIB clock divisor + */ +static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div) +{ + mcp_set_audio_divisor(ucb->mcp, div); +} + +/** + * ucb1x00_set_telecom_divisor - + * @ucb: UCB1x00 structure describing chip + * @div: SIB clock divisor + */ +static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div) +{ + mcp_set_telecom_divisor(ucb->mcp, div); +} + +struct ucb1x00 *ucb1x00_get(void); + +void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int); +void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int); +unsigned int ucb1x00_io_read(struct ucb1x00 *ucb); + +#define UCB_NOSYNC (0) +#define UCB_SYNC (1) + +unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync); +void ucb1x00_adc_enable(struct ucb1x00 *ucb); +void ucb1x00_adc_disable(struct ucb1x00 *ucb); + +/* + * Which edges of the IRQ do you want to control today? + */ +#define UCB_RISING (1 << 0) +#define UCB_FALLING (1 << 1) + +int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid); +void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); +void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges); +int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid); + +#endif diff -urN orig/drivers/mtd/chips/cfi_probe.c linux/drivers/mtd/chips/cfi_probe.c --- orig/drivers/mtd/chips/cfi_probe.c Tue Jun 24 13:58:36 2003 +++ linux/drivers/mtd/chips/cfi_probe.c Fri Feb 21 15:17:33 2003 @@ -65,6 +65,10 @@ return 0; } cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + + /* some devices don't respond to 0xF0, so send 0xFF to be sure */ + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); if (!qry_present(map,base,cfi)) @@ -84,6 +88,8 @@ /* Eep. This chip also had the QRY marker. * Is it an alias for the new one? */ cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL); + /* some devices don't respond to 0xF0, so send 0xFF to be sure */ + cfi_send_gen_cmd(0xFF, 0, chips[i].start, map, cfi, cfi->device_type, NULL); /* If the QRY marker goes away, it's an alias */ if (!qry_present(map, chips[i].start, cfi)) { @@ -96,7 +102,8 @@ * too and if it's the same, assume it's an alias. */ /* FIXME: Use other modes to do a proper check */ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); - + /* some devices don't respond to 0xF0, so send 0xFF to be sure */ + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); if (qry_present(map, base, cfi)) { printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", map->name, base, chips[i].start); @@ -119,6 +126,10 @@ /* Put it back into Read Mode */ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + /* some devices don't respond to 0xF0, so send 0xFF to be sure */ + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); + + printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n", map->name, cfi->interleave, cfi->device_type*8, base, map->buswidth*8); @@ -165,6 +176,20 @@ cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc); cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize); + /* + * ST screwed up the CFI interface for buffer writes on their parts, + * so this needs to be fixed up by hand here. + * + * A possible enhancment is that instead of just reverting back + * to word write (as this does), we could use the ST specific double + * word write instead. + */ + + if (cfi_read_query(map,base) == 0x20){ + cfi->cfiq->BufWriteTimeoutTyp = 0; + cfi->cfiq->BufWriteTimeoutMax = 0; + } + #ifdef DEBUG_CFI /* Dump the information therein */ print_cfi_ident(cfi->cfiq); @@ -182,6 +207,9 @@ /* Put it back into Read Mode */ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + /* some devices don't respond to 0xF0, so send 0xFF to be sure */ + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); + return 1; } diff -urN orig/drivers/mtd/devices/Config.in linux/drivers/mtd/devices/Config.in --- orig/drivers/mtd/devices/Config.in Tue Jun 24 13:58:37 2003 +++ linux/drivers/mtd/devices/Config.in Tue Jun 24 14:02:49 2003 @@ -17,6 +17,15 @@ if [ "$CONFIG_SA1100_LART" = "y" ]; then dep_tristate ' 28F160xx flash driver for LART' CONFIG_MTD_LART $CONFIG_MTD fi +if [ "$CONFIG_ARCH_MX1ADS" = "y" ]; then + dep_tristate ' SyncFlash driver for MX1ADS' CONFIG_MTD_SYNCFLASH $CONFIG_MTD +fi +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then + dep_tristate ' AT91RM9200 DataFlash support' CONFIG_MTD_AT91_DATAFLASH $CONFIG_MTD + if [ "$CONFIG_MTD_AT91_DATAFLASH" = "y" -o "$CONFIG_MTD_AT91_DATAFLASH" = "m" ]; then + bool ' Enable DataFlash card? ' CONFIG_MTD_AT91_DATAFLASH_CARD + fi +fi dep_tristate ' Test driver using RAM' CONFIG_MTD_MTDRAM $CONFIG_MTD if [ "$CONFIG_MTD_MTDRAM" = "y" -o "$CONFIG_MTD_MTDRAM" = "m" ]; then int 'MTDRAM device size in KiB' CONFIG_MTDRAM_TOTAL_SIZE 4096 diff -urN orig/drivers/mtd/devices/Makefile linux/drivers/mtd/devices/Makefile --- orig/drivers/mtd/devices/Makefile Wed Jun 18 13:02:03 2003 +++ linux/drivers/mtd/devices/Makefile Tue Jun 24 14:02:59 2003 @@ -21,6 +21,7 @@ obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o obj-$(CONFIG_MTD_MTDRAM) += mtdram.o obj-$(CONFIG_MTD_LART) += lart.o +obj-$(CONFIG_MTD_SYNCFLASH) += syncflash.o obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o include $(TOPDIR)/Rules.make diff -urN orig/drivers/mtd/devices/syncflash.c linux/drivers/mtd/devices/syncflash.c --- orig/drivers/mtd/devices/syncflash.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/mtd/devices/syncflash.c Fri Jun 13 22:34:08 2003 @@ -0,0 +1,615 @@ +/* + * MTD driver for Micron SyncFlash flash memory. + * + * Author: Jon McClintock + * + * Based loosely upon the LART flash driver, authored by Abraham vd Merwe + * . + * + * Copyright 2003, Blue Mug, Inc. for Motorola, Inc. + * + * This code 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. + * + * References: + * + * [1] Micron SyncFlash homepage + * - http://www.syncflash.com/ + * + * [2] MT28S4M16LC -- 4Mx16 SyncFlash memory datasheet + * - http://syncflash.com/pdfs/datasheets/mt28s4m16lc_6.pdf + * + * [3] MTD internal API documentation + * - http://www.linux-mtd.infradead.org/tech/ + * + * Limitations: + * + * Even though this driver is written for Micron SyncFlash, it is quite + * specific to the Motorola MX1 ADS development board. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* partition support */ +#define HAVE_PARTITIONS +#ifdef HAVE_PARTITIONS +#include +#endif + +#ifndef CONFIG_ARCH_MX1ADS +#error The SyncFlash driver currently only supports the MX1 ADS platform. +#endif + +/* + * General flash configuration parameters. + */ +#define BUSWIDTH 4 +#define FLASH_BLOCKSIZE (256 * 1024 * BUSWIDTH) +#define FLASH_NUMBLOCKS 16 + +#define BUSWIDTH 4 +#define FLASH_ADDRESS IO_ADDRESS(MX1ADS_FLASH_BASE) + +#define FLASH_MANUFACTURER 0x002C002C +#define FLASH_DEVICE_ID 0x00D300D3 + +/* + * The size and extent of the bootloader in flash. + */ +#define NUM_BOOTLOADER_BLOCKS 1 +#define BOOTLOADER_START 0x00000000 +#define BOOTLOADER_LEN (NUM_BOOTLOADER_BLOCKS * FLASH_BLOCKSIZE) + +/* + * The size and extent of the kernel in flash. + */ +#define NUM_KERNEL_BLOCKS 1 +#define KERNEL_START (BOOTLOADER_START + BOOTLOADER_LEN) +#define KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE) + +/* File system */ +#define NUM_FILESYSTEM_BLOCKS 14 +#define FILESYSTEM_START (KERNEL_START + KERNEL_LEN) +#define FILESYSTEM_LEN (NUM_FILESYSTEM_BLOCKS * FLASH_BLOCKSIZE) + + +/* + * SDRAM controller register location and values. These are very specific + * to the MX1. + */ +#define SDRAMC_REGISTER IO_ADDRESS(0x00221004) + +/* + * This the mask we use to get the start of a block from a given address. + */ +#define BLOCK_MASK (0xFFF00000) + +/* + * This is the A10 address line of the SyncFlash; it's used to initiate + * a precharge command. + */ +#define SYNCFLASH_A10 (0x00100000) + +/* + * SDRAM controller MODE settings. + */ +#define CMD_NORMAL (0x81020300) /* Normal Mode */ +#define CMD_PREC (CMD_NORMAL + 0x10000000) /* Precharge command */ +#define CMD_AUTO (CMD_NORMAL + 0x20000000) /* Auto refresh */ +#define CMD_LMR (CMD_NORMAL + 0x30000000) /* Load Mode Register */ +#define CMD_LCR (CMD_NORMAL + 0x60000000) /* LCR Command */ +#define CMD_PROGRAM (CMD_NORMAL + 0x70000000) /* SyncFlash Program */ + +/* + * SyncFlash LCR Commands adjusted for the DBMX1 AHB internal address bus . + */ +#define LCR_READ_STATUS (0x0001C000) /* 0x70 */ +#define LCR_READ_CONFIG (0x00024000) /* 0x90 */ +#define LCR_ERASE_CONFIRM (0x00008000) /* 0x20 */ +#define LCR_ERASE_NVMODE (0x0000C000) /* 0x30 */ +#define LCR_PROG_NVMODE (0x00028000) /* 0xA0 */ +#define LCR_SR_CLEAR (0x00014000) /* 0x50 */ + +/* + * Status register bits + */ +#define SR_VPS_ERROR (1 << 8) /* Power-Up status error */ +#define SR_ISM_READY (1 << 7) /* State machine isn't busy */ +#define SR_ERASE_ERROR (1 << 5) /* Erase/Unprotect error */ +#define SR_PROGRAM_ERROR (1 << 4) /* Program/Protect error */ +#define SR_DEVICE_PROTECTED (1 << 3) /* Device is protected */ +#define SR_ISM_STATUS_H (1 << 2) /* Bank ISM status, high bit */ +#define SR_ISM_STATUS_L (1 << 1) /* Bank ISM status, low bit */ +#define SR_DEVICE_ISM_STATUS (1 << 0) /* ISM is device-level */ + +#define SR_ERROR (SR_VPS_ERROR|SR_ERASE_ERROR|SR_PROGRAM_ERROR|SR_DEVICE_PROTECTED) + +#define STATUS_VALUE(a) ((a) | ((a) << 16)) + +/* + * Device configuration register offsets + */ +#define DC_MANUFACTURER (0 * BUSWIDTH) +#define DC_DEVICE_ID (1 * BUSWIDTH) +#define DC_BLOCK_PROTECT (2 * BUSWIDTH) +#define DC_DEVICE_PROTECT (3 * BUSWIDTH) + +#define FL_WORD(addr) (*(volatile unsigned long*)(addr)) + +static char module_name[] = "syncflash"; + +inline __u8 read8 (__u32 offset) +{ + return *(volatile __u8 *) (FLASH_ADDRESS + offset); +} + +inline __u32 read32 (__u32 offset) +{ + return *(volatile __u32 *) (FLASH_ADDRESS + offset); +} + +inline void write32 (__u32 x,__u32 offset) +{ + *(volatile __u32 *) (FLASH_ADDRESS + offset) = x; +} + +static __u32 read_device_configuration_register(__u32 reg_number) +{ + __u32 tmp; + + /* Setup the SDRAM controller to issue an LCR command. */ + FL_WORD(SDRAMC_REGISTER) = CMD_LCR; + + /* Perform a read to issue the Read Device Configuration Command. */ + tmp = read32(LCR_READ_CONFIG); + + /* Return the SDRAM controller to normal mode. */ + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL; + + /* Return the value of the specified register. */ + tmp = read32(reg_number); + + return tmp; +} + +/* + * Get the status of the flash devices. + */ +static __u32 flash_read_status() +{ + __u32 status, tmp; + + /* Enter the SyncFlash Program READ/WRITE mode. */ + FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM; + + /* Read the status register. */ + status = read32(LCR_READ_STATUS); + + /* Clear the status register. */ + FL_WORD(SDRAMC_REGISTER) = CMD_LCR; + tmp = read32(LCR_SR_CLEAR); + + /* Return to Normal mode. */ + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL; + + return status; +} + +/* + * Loop until both write state machines are ready. + */ +static __u32 flash_status_wait() +{ + __u32 status; + do { + status = flash_read_status(); + } while ((status & STATUS_VALUE(SR_ISM_READY)) != + STATUS_VALUE(SR_ISM_READY)); + return status; +} + +/* + * Loop until the Write State machine is ready, then do a full error + * check. Clear status and leave the flash in Read Array mode; return + * 0 for no error, -1 for error. + */ +static int flash_status_full_check() +{ + __u32 status; + + status = flash_status_wait() & STATUS_VALUE(SR_ERROR); + return status ? -EIO : 0; +} + +/* + * Return the flash to the normal mode. + */ +static void flash_normal_mode() +{ + __u32 tmp; + + /* First issue a precharge all command. */ + FL_WORD(SDRAMC_REGISTER) = CMD_PREC; + tmp = read32(SYNCFLASH_A10); + + /* Now place the SDRAM controller in Normal mode. */ + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL; +} + +/* + * Probe for SyncFlash memory on MX1ADS board. + * + * Returns 1 if we found SyncFlash memory, 0 otherwise. + */ +static int flash_probe (void) +{ + __u32 manufacturer, device_id; + + /* For some reason, the first read doesn't work, so we do it + * twice. */ + manufacturer = read_device_configuration_register(DC_MANUFACTURER); + manufacturer = read_device_configuration_register(DC_MANUFACTURER); + device_id = read_device_configuration_register(DC_DEVICE_ID); + + printk("SyncFlash probe: manufacturer 0x%08lx, device_id 0x%08lx\n", + manufacturer, device_id); + return (manufacturer == FLASH_MANUFACTURER && + device_id == FLASH_DEVICE_ID); +} + +/* + * Erase one block of flash memory at offset ``offset'' which is any + * address within the block which should be erased. + * + * Returns 0 if successful, -1 otherwise. + */ +static inline int erase_block (__u32 offset) +{ + __u32 tmp; + + /* Mask off the lower bits of the address to get the first address + * in the flash block. */ + offset &= (__u32)BLOCK_MASK; + + /* Perform a read and precharge of the bank before the LCR|ACT|WRIT + * sequence to avoid the inadvertent precharge command occurring + * during the LCR_ACT_WRIT sequence. */ + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL; + tmp = read32(offset); + FL_WORD(SDRAMC_REGISTER) = CMD_PREC; + tmp = read32(offset); + + /* Now start the actual erase. */ + + /* LCR|ACT|WRIT sequence */ + FL_WORD(SDRAMC_REGISTER) = CMD_LCR; + write32(0, offset + LCR_ERASE_CONFIRM); + + /* Return to normal mode to issue the erase confirm. */ + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL; + write32(0xD0D0D0D0, offset); + + if (flash_status_full_check()) { + printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n", + module_name, offset); + return (-1); + } + + flash_normal_mode(); + + return 0; +} + +static int flash_erase (struct mtd_info *mtd,struct erase_info *instr) +{ + __u32 addr,len; + int i,first; + + /* sanity checks */ + if (instr->addr + instr->len > mtd->size) return (-EINVAL); + + /* + * check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + * + * skip all erase regions which are ended before the start of + * the requested erase. Actually, to save on the calculations, + * we skip to the first erase region which starts after the + * start of the requested erase, and then go back one. + */ + for (i = 0; (i < mtd->numeraseregions) && + (instr->addr >= mtd->eraseregions[i].offset); i++) ; + i--; + + /* + * ok, now i is pointing at the erase region in which this + * erase request starts. Check the start of the requested + * erase range is aligned with the erase size which is in + * effect here. + */ + if (instr->addr & (mtd->eraseregions[i].erasesize - 1)) + return (-EINVAL); + + /* Remember the erase region we start on */ + first = i; + + /* + * next, check that the end of the requested erase is aligned + * with the erase region at that address. + * + * as before, drop back one to point at the region in which + * the address actually falls + */ + for (; + (i < mtd->numeraseregions) && + ((instr->addr + instr->len) >= mtd->eraseregions[i].offset) ; + i++) ; + i--; + + /* is the end aligned on a block boundary? */ + if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1)) + return (-EINVAL); + + addr = instr->addr; + len = instr->len; + + i = first; + + /* now erase those blocks */ + while (len) + { + if (erase_block (addr)) + { + instr->state = MTD_ERASE_FAILED; + return (-EIO); + } + + addr += mtd->eraseregions[i].erasesize; + len -= mtd->eraseregions[i].erasesize; + + if (addr == (mtd->eraseregions[i].offset + + (mtd->eraseregions[i].erasesize * + mtd->eraseregions[i].numblocks))) + i++; + } + + instr->state = MTD_ERASE_DONE; + if (instr->callback) instr->callback (instr); + + return (0); +} + +static int flash_read (struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + /* Sanity checks. */ + if (!len) return (0); + if (from + len > mtd->size) return (-EINVAL); + + /* Ensure that we are in normal mode. */ + flash_normal_mode(); + + /* We always read len bytes. */ + *retlen = len; + + /* first, we read bytes until we reach a dword boundary */ + if (from & (BUSWIDTH - 1)) + { + int gap = BUSWIDTH - (from & (BUSWIDTH - 1)); + while (len && gap--) *buf++ = read8(from++), len--; + } + + /* now we read dwords until we reach a non-dword boundary */ + while (len >= BUSWIDTH) + { + *((__u32 *) buf) = read32(from); + + buf += BUSWIDTH; + from += BUSWIDTH; + len -= BUSWIDTH; + } + + /* top up the last unaligned bytes */ + if (len & (BUSWIDTH - 1)) + while (len--) *buf++ = read8(from++); + + return (0); +} + +/* + * Write one dword ``x'' to flash memory at offset ``offset''. ``offset'' + * must be 32 bits, i.e. it must be on a dword boundary. + * + * Returns 0 if successful, -1 otherwise. + */ +static int flash_write_dword(__u32 offset, __u32 x) +{ + __u32 tmp; + + /* First issue a precharge all command. */ + FL_WORD(SDRAMC_REGISTER) = CMD_PREC; + tmp = read32(SYNCFLASH_A10); + + /* Enter the SyncFlash programming mode. */ + FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM; + write32(x, offset); + + /* Wait for the write to complete. */ + flash_status_wait(); + + /* Return to normal mode. */ + flash_normal_mode(); + + return 0; +} + +static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf) +{ + __u8 tmp[4]; + int i,n; + + *retlen = 0; + + /* Sanity checks */ + if (!len) return (0); + if (to + len > mtd->size) return (-EINVAL); + + /* First, we write a 0xFF.... padded byte until we reach a + * dword boundary. */ + if (to & (BUSWIDTH - 1)) + { + __u32 aligned = to & ~(BUSWIDTH - 1); + int gap = to - aligned; + + i = n = 0; + + while (gap--) tmp[i++] = 0xFF; + while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--; + while (i < BUSWIDTH) tmp[i++] = 0xFF; + + if (flash_write_dword(aligned, *((__u32 *) tmp))) + return (-EIO); + + to += n; + buf += n; + *retlen += n; + } + + /* Now we write dwords until we reach a non-dword boundary. */ + while (len >= BUSWIDTH) + { + if (flash_write_dword (to,*((__u32 *) buf))) return (-EIO); + + to += BUSWIDTH; + buf += BUSWIDTH; + *retlen += BUSWIDTH; + len -= BUSWIDTH; + } + + /* Top up the last unaligned bytes, padded with 0xFF.... */ + if (len & (BUSWIDTH - 1)) + { + i = n = 0; + + while (len--) tmp[i++] = buf[n++]; + while (i < BUSWIDTH) tmp[i++] = 0xFF; + + if (flash_write_dword (to,*((__u32 *) tmp))) return (-EIO); + + *retlen += n; + } + + return flash_status_full_check(); +} + + + +#define NB_OF(x) (sizeof (x) / sizeof (x[0])) + +static struct mtd_info mtd; + +static struct mtd_erase_region_info erase_regions[] = +{ + /* flash blocks */ + { + offset: 0x00000000, + erasesize: FLASH_BLOCKSIZE, + numblocks: FLASH_NUMBLOCKS + }, +}; + +#ifdef HAVE_PARTITIONS +static struct mtd_partition syncflash_partitions[] = +{ + /* bootloader */ + { + name: "bootloader", + offset: BOOTLOADER_START, + size: BOOTLOADER_LEN, + mask_flags: 0 + }, + /* Kernel */ + { + name: "kernel", + offset: KERNEL_START, /* MTDPART_OFS_APPEND */ + size: KERNEL_LEN, + mask_flags: 0 + }, + /* file system */ + { + name: "file system", + offset: FILESYSTEM_START, /* MTDPART_OFS_APPEND */ + size: FILESYSTEM_LEN, /* MTDPART_SIZ_FULL */ + mask_flags: 0 + } +}; +#endif + +int __init syncflash_init (void) +{ + int result; + + memset (&mtd,0,sizeof (mtd)); + + printk ("MTD driver for Micron SyncFlash.\n"); + printk ("%s: Probing for SyncFlash on MX1ADS...\n",module_name); + + if (!flash_probe ()) + { + printk (KERN_WARNING "%s: Found no SyncFlash devices\n", + module_name); + return (-ENXIO); + } + + printk ("%s: Found a SyncFlash device.\n",module_name); + + mtd.name = module_name; + mtd.type = MTD_NORFLASH; + mtd.flags = MTD_CAP_NORFLASH; + mtd.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS; + + mtd.erasesize = FLASH_BLOCKSIZE; + mtd.numeraseregions = NB_OF(erase_regions); + mtd.eraseregions = erase_regions; + + mtd.module = THIS_MODULE; + + mtd.erase = flash_erase; + mtd.read = flash_read; + mtd.write = flash_write; + +#ifndef HAVE_PARTITIONS + result = add_mtd_device(&mtd); +#else + result = add_mtd_partitions(&mtd, + syncflash_partitions, + NB_OF(syncflash_partitions)); +#endif + + return (result); +} + +void __exit syncflash_exit (void) +{ +#ifndef HAVE_PARTITIONS + del_mtd_device (&mtd); +#else + del_mtd_partitions (&mtd); +#endif +} + +module_init (syncflash_init); +module_exit (syncflash_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jon McClintock "); +MODULE_DESCRIPTION("MTD driver for Micron MT28S4M16LC SyncFlash on MX1ADS board"); + + diff -urN orig/drivers/mtd/maps/Config.in linux/drivers/mtd/maps/Config.in --- orig/drivers/mtd/maps/Config.in Tue Jun 24 13:58:37 2003 +++ linux/drivers/mtd/maps/Config.in Tue Jun 24 14:18:40 2003 @@ -81,10 +81,10 @@ dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310 - dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT - dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET + dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_FORTUNET + dep_tristate ' CFI Flash device mapped on Epxa' CONFIG_MTD_EPXA $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12 - dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI + dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_ARCH_EDB7212 $CONFIG_MTD_CFI dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA fi diff -urN orig/drivers/mtd/maps/Makefile linux/drivers/mtd/maps/Makefile --- orig/drivers/mtd/maps/Makefile Tue Jun 24 13:58:37 2003 +++ linux/drivers/mtd/maps/Makefile Tue Jun 24 14:26:02 2003 @@ -3,11 +3,7 @@ # # $Id: Makefile,v 1.37 2003/01/24 14:26:38 dwmw2 Exp $ -BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/) - -ifeq ($(BELOW25),y) O_TARGET := mapslink.o -endif # Chip mappings obj-$(CONFIG_MTD_CDB89712) += cdb89712.o @@ -17,7 +13,7 @@ obj-$(CONFIG_MTD_DC21285) += dc21285.o obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o -obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o +obj-$(CONFIG_MTD_EPXA) += ep