libdmx: Add fso-specs to DEPENDS
[openembedded.git] / recipes / linux / opensimpad-2.4.25-vrs2-pxa1-jpm1 / 2.4.25-vrs2.patch
blob7f8a7f9a31bfde06ce075eebf1fb7ee231e20a11
3 # Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
6 --- linux-2.4.25/Documentation/Configure.help~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
7 +++ linux-2.4.25/Documentation/Configure.help 2004-03-31 17:15:08.000000000 +0200
8 @@ -4837,6 +4837,13 @@
9 Say Y to enable support for Permedia2 AGP frame buffer card from
10 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus.
12 +Permedia3 support (EXPERIMENTAL)
13 +CONFIG_FB_PM3
14 + This is the frame buffer device driver for the 3DLabs Permedia3
15 + chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
16 + similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
17 + and maybe other boards.
19 Phase5 CVisionPPC/BVisionPPC support
20 CONFIG_FB_PM2_CVPPC
21 Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC
22 @@ -13125,6 +13132,17 @@
23 The module will be called tmspci.o. If you want to compile it
24 as a module, say M here and read <file:Documentation/modules.txt>.
26 +Altera ether00 support
27 +CONFIG_ETHER00
28 + This is the driver for Altera's ether00 ethernet mac IP core. Say
29 + Y here if you want to build support for this into the kernel. It
30 + is also available as a module (say M here) that can be inserted/
31 + removed from the kernel at the same time as the PLD is configured.
32 + If this driver is running on an epxa10 development board then it
33 + will generate a suitable hw address based on the board serial
34 + number (MTD support is required for this). Otherwise you will
35 + need to set a suitable hw address using ifconfig.
37 Generic TMS380 ISA support
38 CONFIG_TMSISA
39 This tms380 module supports generic TMS380-based ISA cards.
40 @@ -15069,6 +15087,16 @@
41 support" be compiled as a module for this driver to be used
42 properly.
44 +Altera's uart00 serial driver
45 +CONFIG_SERIAL_UART00
46 + Say Y here if you want to use the hard logic uart on Excalibur. This
47 + driver also supports soft logic implentations of this uart core.
49 +Serial console on uart00
50 +CONFIG_SERIAL_UART00_CONSOLE
51 + Say Y here if you want to support a serial console on an Excalibur
52 + hard logic uart or uart00 IP core.
54 USB ConnectTech WhiteHEAT Serial Driver
55 CONFIG_USB_SERIAL_WHITEHEAT
56 Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
57 @@ -19085,6 +19113,20 @@
58 <file:Documentation/modules.txt>.
59 The module will be called i2c-velleman.o.
61 +Guide GPIO adapter
62 +CONFIG_I2C_GUIDE
63 + This supports the Iders GUIDE I2C bit-bashing adapter. If you have
64 + selected the GUIDE A07 as your ARM system type, you cannot deselect
65 + this option, as it is required for proper operation of the GUIDE.
67 + This interface uses /dev/i2c-0 (major 89, minor 0).
69 + Say Y if you own such an adapter.
71 + This driver is also available as a module. If you want to compile
72 + it as a module, say M here and read Documentation/modules.txt. The
73 + module will be called i2c-guide.o.
75 I2C PCF 8584 interfaces
76 CONFIG_I2C_ALGOPCF
77 This allows you to use a range of I2C adapters called PCF adapters.
78 @@ -20230,6 +20272,17 @@
79 <file:Documentation/modules.txt>. The module will be called
80 softdog.o.
82 +SA1100 Internal Watchdog
83 +CONFIG_SA1100_WATCHDOG
84 + Watchdog timer embedded into SA11x0 chips. This will reboot your
85 + system when timeout is reached.
86 + NOTE, that once enabled, this timer cannot be disabled.
88 + This driver is also available as a module ( = code which can be
89 + inserted in and removed from the running kernel whenever you want).
90 + If you want to compile it as a module, say M here and read
91 + Documentation/modules.txt. The module will be called sa1100_wdt.o.
93 Berkshire Products PC Watchdog
94 CONFIG_PCWATCHDOG
95 This is the driver for the Berkshire Products PC Watchdog card.
96 @@ -21891,6 +21944,30 @@
97 from RME. If you want to acess advanced features of the card, read
98 Documentation/sound/rme96xx.
100 +Assabet audio (UDA1341) support
101 +CONFIG_SOUND_ASSABET_UDA1341
102 + Say Y or M if you have an Intel Assabet evaluation board and want to
103 + use the Philips UDA 1341 audio chip (the one that drives the stereo
104 + audio output) on the SA1100 SSP port.
106 +Compaq iPAQ audio support
107 +CONFIG_SOUND_H3600_UDA1341
108 + Say Y or M if you have a Compaq iPaq handheld computer and want to
109 + use its Philips UDA 1341 audio chip.
111 +Audio support for SA1111/UDA1341
112 +CONFIG_SOUND_SA1111_UDA1341
113 + Say Y or M if you have an SA11x0 system with a Philips UDA 1341
114 + connected to the SA11x1. An example of such a system is the Intel
115 + Assabet evaluation board connected to a Neponset expansion board.
117 +Generic DAC on the SA11x0 SSP port
118 +CONFIG_SOUND_SA1100SSP
119 + Say Y or M if you have an SA-11x0 system with a DAC on the SSP port.
120 + The LART has an Burr-Brown PCM 1710 digital to analog convertor on
121 + the SSP port, so you want to say Y or M for the LART. It might work
122 + on other SA-1100 platforms, too, but this is not tested.
124 Are you using a crosscompiler
125 CONFIG_CROSSCOMPILE
126 Say Y here if you are compiling the kernel on a different
127 @@ -25594,6 +25671,20 @@
128 Say Y if configuring for a Pangolin.
129 Say N otherwise.
131 +Shannon
132 +CONFIG_SA1100_SHANNON
133 + The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
134 + limited edition webphone produced by Philips. The Shannon is a SA1100
135 + platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots,
136 + and a telco interface.
138 +Simputer
139 +CONFIG_SA1100_SIMPUTER
140 + Say Y here if you are using an Intel(R) StrongARM(R) SA-1110
141 + based Simputer. See http://www.simputer.org/ for information
142 + on the Simputer. The Simputer software is actively maintained
143 + by PicoPeta Simputers Pvt. Ltd. (http://www.picopeta.com)
145 Victor
146 CONFIG_SA1100_VICTOR
147 Say Y here if you are using a Visu Aide Intel(R) StrongARM(R)
148 @@ -25601,6 +25692,14 @@
149 <http://www.visuaide.com/pagevictor.en.html> for information on
150 this system.
152 +Radisys Corp. Tulsa
153 +CONFIG_SA1100_PFS168
154 + The Radisys Corp. PFS-168 (aka Tulsa) is an IntelĀ® StrongArmĀ® SA-1110 based
155 + computer which includes the SA-1111 Microprocessor Companion Chip and other
156 + custom I/O designed to add connectivity and multimedia features for vending
157 + and business machine applications. Say Y here if you require support for
158 + this target.
160 # Choice: cerf_ram
161 Cerf on-board RAM size
162 CONFIG_SA1100_CERF_8MB
163 @@ -25668,37 +25767,65 @@
164 Say Y if you want support for the ARM920T processor.
165 Otherwise, say N.
167 -Support ARM1020 processor
168 -CONFIG_CPU_ARM1020
169 - The ARM1020 is the cached version of the ARM10 processor,
170 - with an addition of a floating-point unit.
171 +Support ARM922T processor
172 +CONFIG_CPU_ARM922T
173 + The ARM922T is a version of the ARM920T, but with smaller
174 + instruction and data caches. It is used in Altera's
175 + Excalibur XA device family.
177 - Say Y if you want support for the ARM1020 processor.
178 + Say Y if you want support for the ARM922T processor.
179 Otherwise, say N.
181 -Disable I-Cache
182 +Disable instruction cache
183 CONFIG_CPU_ICACHE_DISABLE
184 - Say Y here to disable the processor instruction cache. Unless
185 - you have a reason not to or are unsure, say N.
186 + Say Y here to disable the processor instruction cache. Unless
187 + you have a reason to do this, say N.
189 -Disable D-Cache
190 +Disable data cache
191 CONFIG_CPU_DCACHE_DISABLE
192 - Say Y here to disable the processor data cache. Unless
193 - you have a reason not to or are unsure, say N.
194 + Say Y here to disable the processor data cache. Unless
195 + you have a reason to do this, say N.
197 -Force write through D-cache
198 +Use data cache in writethrough mode
199 CONFIG_CPU_DCACHE_WRITETHROUGH
200 - Say Y here to use the data cache in write-through mode. Unless you
201 - specifically require this or are unsure, say N.
202 + Say Y here to use the data cache in writethough mode. Unless you
203 + specifically require this, say N.
205 -Round robin I and D cache replacement algorithm
206 +Support ARM1020 processor
207 +CONFIG_CPU_ARM1020
208 + The ARM1020 is the 32K cached version of the ARM10 processor,
209 + with an addition of a floating-point unit.
211 + Say Y if you want support for the ARM1020 processor.
212 + Otherwise, say N.
214 +Support ARM1022 processor
215 +CONFIG_CPU_ARM1022
216 + The ARM1022E is the 16K cached version of the ARM10 processor,
217 + with an addition of a floating-point unit.
219 + Say Y if you want support for the ARM1022 processor.
220 + Otherwise, say N.
222 +Force round-robin cache line replacement
223 CONFIG_CPU_CACHE_ROUND_ROBIN
224 - Say Y here to use the predictable round-robin cache replacement
225 - policy. Unless you specifically require this or are unsure, say N.
226 + Say Y here to force the caches to use a round-robin
227 + algorithm when picking a cache line to evict. Unless you
228 + specifically require this, say N.
230 +Disable the write buffer
231 +CONFIG_CPU_WB_DISABLE
232 + Say Y here to turn off the write buffer (if possible)
233 + Unless you specifically require this, say N. Note that
234 + not all ARM processors allow the write buffer to be
235 + disabled.
237 Disable branch prediction
238 CONFIG_CPU_BPREDICT_DISABLE
239 - Say Y here to disable branch prediction. If unsure, say N.
240 + The ARM10 family of processors support branch prediction,
241 + which can significantly speed up execution of loops.
242 + Say Y here to disable branch prediction. Unless you
243 + specifically require this, say N.
245 Compressed boot loader in ROM/flash
246 CONFIG_ZBOOT_ROM
247 @@ -25745,6 +25872,11 @@
248 Say Y here if you are using the inhand electronics OmniMeter. See
249 <http://www.inhandelectronics.com/html/omni1.html> for details.
251 +HP Laboratories BadgePAD 4
252 +CONFIG_SA1100_BADGE4
253 + Say Y here if you want to build a kernel for the HP Laboratories
254 + BadgePAD 4.
256 Load kernel using Angel Debug Monitor
257 CONFIG_ANGELBOOT
258 Say Y if you plan to load the kernel using Angel, ARM Ltd's target
259 @@ -25757,6 +25889,15 @@
260 board includes 2 serial ports, Ethernet, IRDA, and expansion headers.
261 It comes with 16 MB SDRAM and 8 MB flash ROM.
263 +GUIDEA07
264 +CONFIG_ARCH_GUIDEA07
265 + Say Y if you are using a GUIDE (A07) board.
267 + This board is based on the cs89712 processor and shares much common
268 + hardware with the CDB89712 configuration. When you select this
269 + option and the CDB89712 becomes enabled also, don't worry. It's
270 + supposed to be that way.
272 CLPS-711X internal ROM bootstrap
273 CONFIG_EP72XX_ROM_BOOT
274 If you say Y here, your CLPS711x-based kernel will use the bootstrap
275 @@ -25785,19 +25926,27 @@
276 You may say N here if you are going to load the Acorn FPEmulator
277 early in the bootup.
279 +Math emulation 80-bit support
280 +CONFIG_FPE_NWFPE_XP
281 + Say Y to include 80-bit support in the kernel floating-point
282 + emulator. Otherwise, only 32 and 64-bit support is compiled in.
283 + Note that gcc does not generate 80-bit operations by default,
284 + so in most cases this option only enlarges the size of the
285 + floating point emulator without any good reason.
287 + You almost surely want to say N here.
289 FastFPE math emulation
290 CONFIG_FPE_FASTFPE
291 Say Y here to include the FAST floating point emulator in the kernel.
292 - This is an experimental much faster emulator which has only 32 bit
293 + This is an experimental much faster emulator which now also has full
294 precision for the mantissa. It does not support any exceptions.
295 - This makes it very simple, it is approximately 4-8 times faster than
296 - NWFPE.
297 + It is very simple, and approximately 3-6 times faster than NWFPE.
299 - It should be sufficient for most programs. It is definitely not
300 - suitable if you do scientific calculations that need double
301 - precision for iteration formulas that sum up lots of very small
302 - numbers. If you do not feel you need a faster FP emulation you
303 - should better choose NWFPE.
304 + It should be sufficient for most programs. It may be not suitable
305 + for scientific calculations, but you have to check this for yourself.
306 + If you do not feel you need a faster FP emulation you should better
307 + choose NWFPE.
309 It is also possible to say M to build the emulator as a module
310 (fastfpe.o). But keep in mind that you should only load the FP
311 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
312 +++ linux-2.4.25/Documentation/arm/Porting 2004-03-31 17:15:08.000000000 +0200
313 @@ -0,0 +1,135 @@
314 +Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html
316 +Initial definitions
317 +-------------------
319 +The following symbol definitions rely on you knowing the translation that
320 +__virt_to_phys() does for your machine. This macro converts the passed
321 +virtual address to a physical address. Normally, it is simply:
323 + phys = virt - PAGE_OFFSET + PHYS_OFFSET
326 +Decompressor Symbols
327 +--------------------
329 +ZTEXTADDR
330 + Start address of decompressor. There's no point in talking about
331 + virtual or physical addresses here, since the MMU will be off at
332 + the time when you call the decompressor code. You normally call
333 + the kernel at this address to start it booting. This doesn't have
334 + to be located in RAM, it can be in flash or other read-only or
335 + read-write addressable medium.
337 +ZBSSADDR
338 + Start address of zero-initialised work area for the decompressor.
339 + This must be pointing at RAM. The decompressor will zero initialise
340 + this for you. Again, the MMU will be off.
342 +ZRELADDR
343 + This is the address where the decompressed kernel will be written,
344 + and eventually executed. The following constraint must be valid:
346 + __virt_to_phys(TEXTADDR) == ZRELADDR
348 + The initial part of the kernel is carefully coded to be position
349 + independent.
351 +INITRD_PHYS
352 + Physical address to place the initial RAM disk. Only relevant if
353 + you are using the bootpImage stuff (which only works on the old
354 + struct param_struct).
356 +INITRD_VIRT
357 + Virtual address of the initial RAM disk. The following constraint
358 + must be valid:
360 + __virt_to_phys(INITRD_VIRT) == INITRD_PHYS
362 +PARAMS_PHYS
363 + Physical address of the struct param_struct or tag list, giving the
364 + kernel various parameters about its execution environment.
367 +Kernel Symbols
368 +--------------
370 +PHYS_OFFSET
371 + Physical start address of the first bank of RAM.
373 +PAGE_OFFSET
374 + Virtual start address of the first bank of RAM. During the kernel
375 + boot phase, virtual address PAGE_OFFSET will be mapped to physical
376 + address PHYS_OFFSET, along with any other mappings you supply.
377 + This should be the same value as TASK_SIZE.
379 +TASK_SIZE
380 + The maximum size of a user process in bytes. Since user space
381 + always starts at zero, this is the maximum address that a user
382 + process can access+1. The user space stack grows down from this
383 + address.
385 + Any virtual address below TASK_SIZE is deemed to be user process
386 + area, and therefore managed dynamically on a process by process
387 + basis by the kernel. I'll call this the user segment.
389 + Anything above TASK_SIZE is common to all processes. I'll call
390 + this the kernel segment.
392 + (In other words, you can't put IO mappings below TASK_SIZE, and
393 + hence PAGE_OFFSET).
395 +TEXTADDR
396 + Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.
397 + This is where the kernel image ends up. With the latest kernels,
398 + it must be located at 32768 bytes into a 128MB region. Previous
399 + kernels placed a restriction of 256MB here.
401 +DATAADDR
402 + Virtual address for the kernel data segment. Must not be defined
403 + when using the decompressor.
405 +VMALLOC_START
406 +VMALLOC_END
407 + Virtual addresses bounding the vmalloc() area. There must not be
408 + any static mappings in this area; vmalloc will overwrite them.
409 + The addresses must also be in the kernel segment (see above).
410 + Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the
411 + last virtual RAM address (found using variable high_memory).
413 +VMALLOC_OFFSET
414 + Offset normally incorporated into VMALLOC_START to provide a hole
415 + between virtual RAM and the vmalloc area. We do this to allow
416 + out of bounds memory accesses (eg, something writing off the end
417 + of the mapped memory map) to be caught. Normally set to 8MB.
419 +Architecture Specific Macros
420 +----------------------------
422 +BOOT_MEM(pram,pio,vio)
423 + `pram' specifies the physical start address of RAM. Must always
424 + be present, and should be the same as PHYS_OFFSET.
426 + `pio' is the physical address of an 8MB region containing IO for
427 + use with the debugging macros in arch/arm/kernel/debug-armv.S.
429 + `vio' is the virtual address of the 8MB debugging region.
431 + It is expected that the debugging region will be re-initialised
432 + by the architecture specific code later in the code (via the
433 + MAPIO function).
435 +BOOT_PARAMS
436 + Same as, and see PARAMS_PHYS.
438 +FIXUP(func)
439 + Machine specific fixups, run before memory subsystems have been
440 + initialised.
442 +MAPIO(func)
443 + Machine specific function to map IO areas (including the debug
444 + region above).
446 +INITIRQ(func)
447 + Machine specific function to initialise interrupts.
449 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
450 +++ linux-2.4.25/Documentation/arm/mem_alignment 2004-03-31 17:15:08.000000000 +0200
451 @@ -0,0 +1,58 @@
452 +Too many problems poped up because of unnoticed misaligned memory access in
453 +kernel code lately. Therefore the alignment fixup is now unconditionally
454 +configured in for SA11x0 based targets. According to Alan Cox, this is a
455 +bad idea to configure it out, but Russell King has some good reasons for
456 +doing so on some f***ed up ARM architectures like the EBSA110. However
457 +this is not the case on many design I'm aware of, like all SA11x0 based
458 +ones.
460 +Of course this is a bad idea to rely on the alignment trap to perform
461 +unaligned memory access in general. If those access are predictable, you
462 +are better to use the macros provided by include/asm/unaligned.h. The
463 +alignment trap can fixup misaligned access for the exception cases, but at
464 +a high performance cost. It better be rare.
466 +Now for user space applications, it is possible to configure the alignment
467 +trap to SIGBUS any code performing unaligned access (good for debugging bad
468 +code), or even fixup the access by software like for kernel code. The later
469 +mode isn't recommended for performance reasons (just think about the
470 +floating point emulation that works about the same way). Fix your code
471 +instead!
473 +Please note that randomly changing the behaviour without good thought is
474 +real bad - it changes the behaviour of all unaligned instructions in user
475 +space, and might cause programs to fail unexpectedly.
477 +To change the alignment trap behavior, simply echo a number into
478 +/proc/sys/debug/alignment. The number is made up from various bits:
480 +bit behavior when set
481 +--- -----------------
483 +0 A user process performing an unaligned memory access
484 + will cause the kernel to print a message indicating
485 + process name, pid, pc, instruction, address, and the
486 + fault code.
488 +1 The kernel will attempt to fix up the user process
489 + performing the unaligned access. This is of course
490 + slow (think about the floating point emulator) and
491 + not recommended for production use.
493 +2 The kernel will send a SIGBUS signal to the user process
494 + performing the unaligned access.
496 +Note that not all combinations are supported - only values 0 through 5.
497 +(6 and 7 don't make sense).
499 +For example, the following will turn on the warnings, but without
500 +fixing up or sending SIGBUS signals:
502 + echo 1 > /proc/sys/debug/alignment
504 +You can also read the content of the same file to get statistical
505 +information on unaligned access occurrences plus the current mode of
506 +operation for user space code.
509 +Nicolas Pitre, Mar 13, 2001. Modified Russell King, Nov 30, 2001.
510 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
511 +++ linux-2.4.25/Documentation/arm/memory.txt 2004-03-31 17:15:08.000000000 +0200
512 @@ -0,0 +1,74 @@
513 + Kernel Memory Layout on ARM Linux
515 + Russell King <rmk@arm.linux.org.uk>
516 + April 27, 2003 (2.5.68)
518 +This document describes the virtual memory layout which the Linux
519 +kernel uses for ARM processors. It indicates which regions are
520 +free for platforms to use, and which are used by generic code.
522 +The ARM CPU is capable of addressing a maximum of 4GB virtual memory
523 +space, and this must be shared between user space processes, the
524 +kernel, and hardware devices.
526 +As the ARM architecture matures, it becomes necessary to reserve
527 +certain regions of VM space for use for new facilities; therefore
528 +this document may reserve more VM space over time.
530 +Start End Use
531 +--------------------------------------------------------------------------
532 +ffff8000 ffffffff copy_user_page / clear_user_page use.
533 + For SA11xx and Xscale, this is used to
534 + setup a minicache mapping.
536 +ffff1000 ffff7fff Reserved.
537 + Platforms must not use this address range.
539 +ffff0000 ffff0fff CPU vector page.
540 + The CPU vectors are mapped here if the
541 + CPU supports vector relocation (control
542 + register V bit.)
544 +ffe00000 fffeffff Free for platform use, not recommended.
546 +ffc00000 ffdfffff 2MB consistent memory mapping.
547 + Memory returned by the consistent_alloc
548 + low level function will be dynamically
549 + mapped here.
551 +ff000000 ffbfffff Free for platform use, not recommended.
553 +VMALLOC_END ff000000 Free for platform use, recommended.
555 +VMALLOC_START VMALLOC_END vmalloc() / ioremap() space.
556 + Memory returned by vmalloc/ioremap will
557 + be dynamically placed in this region.
558 + VMALLOC_START may be based upon the value
559 + of the high_memory variable.
561 +PAGE_OFFSET high_memory Kernel direct-mapped RAM region.
562 + This maps the platforms RAM, and typically
563 + maps all platform RAM in a 1:1 relationship.
565 +TASK_SIZE PAGE_OFFSET Kernel module space
566 + Kernel modules inserted via insmod are
567 + placed here using dynamic mappings.
569 +00001000 TASK_SIZE User space mappings
570 + Per-thread mappings are placed here via
571 + the mmap() system call.
573 +00000000 00000fff CPU vector page / null pointer trap
574 + CPUs which do not support vector remapping
575 + place their vector page here. NULL pointer
576 + dereferences by both the kernel and user
577 + space are also caught via this mapping.
579 +Please note that mappings which collide with the above areas may result
580 +in a non-bootable kernel, or may cause the kernel to (eventually) panic
581 +at run time.
583 +Since future CPUs may impact the kernel mapping layout, user programs
584 +must not access any memory which is not mapped inside their 0x0001000
585 +to TASK_SIZE address range. If they wish to access these areas, they
586 +must set up their own mappings using open() and mmap().
587 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
588 +++ linux-2.4.25/Documentation/cpufreq/core.txt 2004-03-31 17:15:08.000000000 +0200
589 @@ -0,0 +1,94 @@
590 + CPU frequency and voltage scaling code in the Linux(TM) kernel
593 + L i n u x C P U F r e q
595 + C P U F r e q C o r e
598 + Dominik Brodowski <linux@brodo.de>
599 + David Kimdon <dwhedon@debian.org>
603 + Clock scaling allows you to change the clock speed of the CPUs on the
604 + fly. This is a nice method to save battery power, because the lower
605 + the clock speed, the less power the CPU consumes.
608 +Contents:
609 +---------
610 +1. CPUFreq core and interfaces
611 +2. CPUFreq notifiers
613 +1. General Information
614 +=======================
616 +The CPUFreq core code is located in linux/kernel/cpufreq.c. This
617 +cpufreq code offers a standardized interface for the CPUFreq
618 +architecture drivers (those pieces of code that do actual
619 +frequency transitions), as well as to "notifiers". These are device
620 +drivers or other part of the kernel that need to be informed of
621 +policy changes (ex. thermal modules like ACPI) or of all
622 +frequency changes (ex. timing code) or even need to force certain
623 +speed limits (like LCD drivers on ARM architecture). Additionally, the
624 +kernel "constant" loops_per_jiffy is updated on frequency changes
625 +here.
627 +Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
628 +which make sure that the cpufreq processor driver is correctly
629 +registered with the core, and will not be unloaded until
630 +cpufreq_put_cpu is called.
632 +2. CPUFreq notifiers
633 +====================
635 +CPUFreq notifiers conform to the standard kernel notifier interface.
636 +See linux/include/linux/notifier.h for details on notifiers.
638 +There are two different CPUFreq notifiers - policy notifiers and
639 +transition notifiers.
642 +2.1 CPUFreq policy notifiers
643 +----------------------------
645 +These are notified when a new policy is intended to be set. Each
646 +CPUFreq policy notifier is called three times for a policy transition:
648 +1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if
649 + they see a need for this - may it be thermal considerations or
650 + hardware limitations.
652 +2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid
653 + hardware failure.
655 +3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy
656 + - if two hardware drivers failed to agree on a new policy before this
657 + stage, the incompatible hardware shall be shut down, and the user
658 + informed of this.
660 +The phase is specified in the second argument to the notifier.
662 +The third argument, a void *pointer, points to a struct cpufreq_policy
663 +consisting of five values: cpu, min, max, policy and max_cpu_freq. min
664 +and max are the lower and upper frequencies (in kHz) of the new
665 +policy, policy the new policy, cpu the number of the affected CPU or
666 +CPUFREQ_ALL_CPUS for all CPUs; and max_cpu_freq the maximum supported
667 +CPU frequency. This value is given for informational purposes only.
670 +2.2 CPUFreq transition notifiers
671 +--------------------------------
673 +These are notified twice when the CPUfreq driver switches the CPU core
674 +frequency and this change has any external implications.
676 +The second argument specifies the phase - CPUFREQ_PRECHANGE or
677 +CPUFREQ_POSTCHANGE.
679 +The third argument is a struct cpufreq_freqs with the following
680 +values:
681 +cpu - number of the affected CPU or CPUFREQ_ALL_CPUS
682 +old - old frequency
683 +new - new frequency
684 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
685 +++ linux-2.4.25/Documentation/cpufreq/cpu-drivers.txt 2004-03-31 17:15:08.000000000 +0200
686 @@ -0,0 +1,210 @@
687 + CPU frequency and voltage scaling code in the Linux(TM) kernel
690 + L i n u x C P U F r e q
692 + C P U D r i v e r s
694 + - information for developers -
697 + Dominik Brodowski <linux@brodo.de>
701 + Clock scaling allows you to change the clock speed of the CPUs on the
702 + fly. This is a nice method to save battery power, because the lower
703 + the clock speed, the less power the CPU consumes.
706 +Contents:
707 +---------
708 +1. What To Do?
709 +1.1 Initialization
710 +1.2 Per-CPU Initialization
711 +1.3 verify
712 +1.4 target or setpolicy?
713 +1.5 target
714 +1.6 setpolicy
715 +2. Frequency Table Helpers
719 +1. What To Do?
720 +==============
722 +So, you just got a brand-new CPU / chipset with datasheets and want to
723 +add cpufreq support for this CPU / chipset? Great. Here are some hints
724 +on what is neccessary:
727 +1.1 Initialization
728 +------------------
730 +First of all, in an __initcall level 7 or later (preferrably
731 +module_init() so that your driver is modularized) function check
732 +whether this kernel runs on the right CPU and the right chipset. If
733 +so, register a struct cpufreq_driver with the CPUfreq core using
734 +cpufreq_register_driver()
736 +What shall this struct cpufreq_driver contain?
738 +cpufreq_driver.name - The name of this driver.
740 +cpufreq_driver.init - A pointer to the per-CPU initialization
741 + function.
743 +cpufreq_driver.verify - A pointer to a "verfication" funciton.
745 +cpufreq_driver.setpolicy _or_
746 +cpufreq_driver.target - See below on the differences.
748 +And optionally
750 +cpufreq_driver.exit - A pointer to a per-CPU cleanup function.
752 +cpufreq_driver.attr - A pointer to a NULL-terminated list of
753 + "struct freq_attr" which allow to
754 + export values to sysfs.
757 +1.2 Per-CPU Initialization
758 +--------------------------
760 +Whenever a new CPU is registered with the device model, or after the
761 +cpufreq driver registers itself, the per-CPU initialization fucntion
762 +cpufreq_driver.init is called. It takes a struct cpufreq_policy
763 +*policy as argument. What to do now?
765 +If necessary, activate the CPUfreq support on your CPU (unlock that
766 +register etc.).
768 +Then, the driver must fill in the following values:
770 +policy->cpuinfo.min_freq _and_
771 +policy->cpuinfo.max_freq - the minimum and maximum frequency
772 + (in kHz) which is supported by
773 + this CPU
774 +policy->cpuinfo.transition_latency the time it takes on this CPU to
775 + switch between two frequencies (if
776 + appropriate, else specify
777 + CPUFREQ_ETERNAL)
779 +policy->cur The current operating frequency of
780 + this CPU (if appropriate)
781 +policy->min,
782 +policy->max,
783 +policy->policy and, if neccessary,
784 +policy->governor must contain the "default policy" for
785 + this CPU. A few moments later,
786 + cpufreq_driver.verify and either
787 + cpufreq_driver.setpolicy or
788 + cpufreq_driver.target is called with
789 + these values.
791 +For setting some of these values, the frequency table helpers might be
792 +helpful. See the section 2 for more information on them.
795 +1.3 verify
796 +------------
798 +When the user decides a new policy (consisting of
799 +"policy,governor,min,max") shall be set, this policy must be validated
800 +so that incompatible values can be corrected. For verifying these
801 +values, a frequency table helper and/or the
802 +cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned
803 +int min_freq, unsigned int max_freq) function might be helpful. See
804 +section 2 for details on frequency table helpers.
806 +You need to make sure that at least one valid frequency (or operating
807 +range) is within policy->min and policy->max. If necessary, increase
808 +policy->max fist, and only if this is no solution, decreas policy->min.
811 +1.4 target or setpolicy?
812 +----------------------------
814 +Most cpufreq drivers or even most cpu frequency scaling algorithms
815 +only allow the CPU to be set to one frequency. For these, you use the
816 +->target call.
818 +Some cpufreq-capable processors switch the frequency between certain
819 +limits on their own. These shall use the ->setpolicy call
822 +1.4. target
823 +-------------
825 +The target call has three arguments: struct cpufreq_policy *policy,
826 +unsigned int target_frequency, unsigned int relation.
828 +The CPUfreq driver must set the new frequency when called here. The
829 +actual frequency must be determined using the following rules:
831 +- keep close to "target_freq"
832 +- policy->min <= new_freq <= policy->max (THIS MUST BE VALID!!!)
833 +- if relation==CPUFREQ_REL_L, try to select a new_freq higher than or equal
834 + target_freq. ("L for lowest, but no lower than")
835 +- if relation==CPUFREQ_REL_H, try to select a new_freq lower than or equal
836 + target_freq. ("H for highest, but no higher than")
838 +Here again the frequency table helper might assist you - see section 3
839 +for details.
842 +1.5 setpolicy
843 +---------------
845 +The setpolicy call only takes a struct cpufreq_policy *policy as
846 +argument. You need to set the lower limit of the in-processor or
847 +in-chipset dynamic frequency switching to policy->min, the upper limit
848 +to policy->max, and -if supported- select a performance-oriented
849 +setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a
850 +powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check
851 +the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c
855 +2. Frequency Table Helpers
856 +==========================
858 +As most cpufreq processors only allow for being set to a few specific
859 +frequencies, a "frequency table" with some functions might assist in
860 +some work of the processor driver. Such a "frequency table" consists
861 +of an array of struct cpufreq_freq_table entries, with any value in
862 +"index" you want to use, and the corresponding frequency in
863 +"frequency". At the end of the table, you need to add a
864 +cpufreq_freq_table entry with frequency set to CPUFREQ_TABLE_END. And
865 +if you want to skip one entry in the table, set the frequency to
866 +CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
867 +order.
869 +By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
870 + struct cpufreq_frequency_table *table);
871 +the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and
872 +policy->min and policy->max are set to the same values. This is
873 +helpful for the per-CPU initialization stage.
875 +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
876 + struct cpufreq_frequency_table *table);
877 +assures that at least one valid frequency is within policy->min and
878 +policy->max, and all other criteria are met. This is helpful for the
879 +->verify call.
881 +int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
882 + struct cpufreq_frequency_table *table,
883 + unsigned int target_freq,
884 + unsigned int relation,
885 + unsigned int *index);
887 +is the corresponding frequency table helper for the ->target
888 +stage. Just pass the values to this function, and the unsigned int
889 +index returns the number of the frequency table entry which contains
890 +the frequency the CPU shall be set to. PLEASE NOTE: This is not the
891 +"index" which is in this cpufreq_table_entry.index, but instead
892 +cpufreq_table[index]. So, the new frequency is
893 +cpufreq_table[index].frequency, and the value you stored into the
894 +frequency table "index" field is
895 +cpufreq_table[index].index.
897 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
898 +++ linux-2.4.25/Documentation/cpufreq/governors.txt 2004-03-31 17:15:08.000000000 +0200
899 @@ -0,0 +1,155 @@
900 + CPU frequency and voltage scaling code in the Linux(TM) kernel
903 + L i n u x C P U F r e q
905 + C P U F r e q G o v e r n o r s
907 + - information for users and developers -
910 + Dominik Brodowski <linux@brodo.de>
914 + Clock scaling allows you to change the clock speed of the CPUs on the
915 + fly. This is a nice method to save battery power, because the lower
916 + the clock speed, the less power the CPU consumes.
919 +Contents:
920 +---------
921 +1. What is a CPUFreq Governor?
923 +2. Governors In the Linux Kernel
924 +2.1 Performance
925 +2.2 Powersave
926 +2.3 Userspace
928 +3. The Governor Interface in the CPUfreq Core
932 +1. What Is A CPUFreq Governor?
933 +==============================
935 +Most cpufreq drivers (in fact, all except one, longrun) or even most
936 +cpu frequency scaling algorithms only offer the CPU to be set to one
937 +frequency. In order to offer dynamic frequency scaling, the cpufreq
938 +core must be able to tell these drivers of a "target frequency". So
939 +these specific drivers will be transformed to offer a "->target"
940 +call instead of the existing "->setpolicy" call. For "longrun", all
941 +stays the same, though.
943 +How to decide what frequency within the CPUfreq policy should be used?
944 +That's done using "cpufreq governors". Two are already in this patch
945 +-- they're the already existing "powersave" and "performance" which
946 +set the frequency statically to the lowest or highest frequency,
947 +respectively. At least two more such governors will be ready for
948 +addition in the near future, but likely many more as there are various
949 +different theories and models about dynamic frequency scaling
950 +around. Using such a generic interface as cpufreq offers to scaling
951 +governors, these can be tested extensively, and the best one can be
952 +selected for each specific use.
954 +Basically, it's the following flow graph:
956 +CPU can be set to switch independetly | CPU can only be set
957 + within specific "limits" | to specific frequencies
959 + "CPUfreq policy"
960 + consists of frequency limits (policy->{min,max})
961 + and CPUfreq governor to be used
962 + / \
963 + / \
964 + / the cpufreq governor decides
965 + / (dynamically or statically)
966 + / what target_freq to set within
967 + / the limits of policy->{min,max}
968 + / \
969 + / \
970 + Using the ->setpolicy call, Using the ->target call,
971 + the limits and the the frequency closest
972 + "policy" is set. to target_freq is set.
973 + It is assured that it
974 + is within policy->{min,max}
977 +2. Governors In the Linux Kernel
978 +================================
980 +2.1 Performance
981 +---------------
983 +The CPUfreq governor "performance" sets the CPU statically to the
984 +highest frequency within the borders of scaling_min_freq and
985 +scaling_max_freq.
988 +2.1 Powersave
989 +-------------
991 +The CPUfreq governor "powersave" sets the CPU statically to the
992 +lowest frequency within the borders of scaling_min_freq and
993 +scaling_max_freq.
996 +2.2 Userspace
997 +-------------
999 +The CPUfreq governor "userspace" allows the user, or any userspace
1000 +program running with UID "root", to set the CPU to a specifc frequency
1001 +by making a sysfs file "scaling_setspeed" available in the CPU-device
1002 +directory.
1006 +3. The Governor Interface in the CPUfreq Core
1007 +=============================================
1009 +A new governor must register itself with the CPUfreq core using
1010 +"cpufreq_register_governor". The struct cpufreq_governor, which has to
1011 +be passed to that function, must contain the following values:
1013 +governor->name - A unique name for this governor
1014 +governor->governor - The governor callback function
1015 +governor->owner - .THIS_MODULE for the governor module (if
1016 + appropriate)
1018 +The governor->governor callback is called with the current (or to-be-set)
1019 +cpufreq_policy struct for that CPU, and an unsigned int event. The
1020 +following events are currently defined:
1022 +CPUFREQ_GOV_START: This governor shall start its duty for the CPU
1023 + policy->cpu
1024 +CPUFREQ_GOV_STOP: This governor shall end its duty for the CPU
1025 + policy->cpu
1026 +CPUFREQ_GOV_LIMITS: The limits for CPU policy->cpu have changed to
1027 + policy->min and policy->max.
1029 +If you need other "events" externally of your driver, _only_ use the
1030 +cpufreq_governor_l(unsigned int cpu, unsigned int event) call to the
1031 +CPUfreq core to ensure proper locking.
1034 +The CPUfreq governor may call the CPU processor driver using one of
1035 +these two functions:
1037 +inline int cpufreq_driver_target(struct cpufreq_policy *policy,
1038 + unsigned int target_freq,
1039 + unsigned int relation);
1041 +inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
1042 + unsigned int target_freq,
1043 + unsigned int relation);
1045 +target_freq must be within policy->min and policy->max, of course.
1046 +What's the difference between these two functions? When your governor
1047 +still is in a direct code path of a call to governor->governor, the
1048 +cpufreq_driver_sem lock is still held in the cpufreq core, and there's
1049 +no need to lock it again (in fact, this would cause a deadlock). So
1050 +use cpufreq_driver_target only in these cases. In all other cases (for
1051 +example, when there's a "daemonized" function that wakes up every
1052 +second), use cpufreq_driver_target_l to lock the cpufreq_driver_sem
1053 +before the command is passed to the cpufreq processor driver.
1055 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
1056 +++ linux-2.4.25/Documentation/cpufreq/index.txt 2004-03-31 17:15:08.000000000 +0200
1057 @@ -0,0 +1,56 @@
1058 + CPU frequency and voltage scaling code in the Linux(TM) kernel
1061 + L i n u x C P U F r e q
1066 + Dominik Brodowski <linux@brodo.de>
1070 + Clock scaling allows you to change the clock speed of the CPUs on the
1071 + fly. This is a nice method to save battery power, because the lower
1072 + the clock speed, the less power the CPU consumes.
1076 +Documents in this directory:
1077 +----------------------------
1078 +core.txt - General description of the CPUFreq core and
1079 + of CPUFreq notifiers
1081 +cpu-drivers.txt - How to implement a new cpufreq processor driver
1083 +governors.txt - What are cpufreq governors and how to
1084 + implement them?
1086 +index.txt - File index, Mailing list and Links (this document)
1088 +user-guide.txt - User Guide to CPUFreq
1091 +Mailing List
1092 +------------
1093 +There is a CPU frequency changing CVS commit and general list where
1094 +you can report bugs, problems or submit patches. To post a message,
1095 +send an email to cpufreq@www.linux.org.uk, to subscribe go to
1096 +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
1097 +mailing list are available to subscribers at
1098 +http://www.linux.org.uk/mailman/private/cpufreq/.
1101 +Links
1102 +-----
1103 +the FTP archives:
1104 +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
1106 +how to access the CVS repository:
1107 +* http://cvs.arm.linux.org.uk/
1109 +the CPUFreq Mailing list:
1110 +* http://www.linux.org.uk/mailman/listinfo/cpufreq
1112 +Clock and voltage scaling for the SA-1100:
1113 +* http://www.lart.tudelft.nl/projects/scaling
1114 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
1115 +++ linux-2.4.25/Documentation/cpufreq/user-guide.txt 2004-03-31 17:15:08.000000000 +0200
1116 @@ -0,0 +1,166 @@
1117 + CPU frequency and voltage scaling code in the Linux(TM) kernel
1120 + L i n u x C P U F r e q
1122 + U S E R G U I D E
1125 + Dominik Brodowski <linux@brodo.de>
1129 + Clock scaling allows you to change the clock speed of the CPUs on the
1130 + fly. This is a nice method to save battery power, because the lower
1131 + the clock speed, the less power the CPU consumes.
1134 +Contents:
1135 +---------
1136 +1. Supported Architectures and Processors
1137 +1.1 ARM
1138 +1.2 x86
1139 +1.3 sparc64
1141 +2. "Policy" / "Governor"?
1142 +2.1 Policy
1143 +2.2 Governor
1145 +3. How to change the CPU cpufreq policy and/or speed
1146 +3.1 Preferred interface: sysfs
1147 +3.2 Deprecated interfaces
1151 +1. Supported Architectures and Processors
1152 +=========================================
1154 +1.1 ARM
1155 +-------
1157 +The following ARM processors are supported by cpufreq:
1159 +ARM Integrator
1160 +ARM-SA1100
1161 +ARM-SA1110
1164 +1.2 x86
1165 +-------
1167 +The following processors for the x86 architecture are supported by cpufreq:
1169 +AMD Elan - SC400, SC410
1170 +AMD mobile K6-2+
1171 +AMD mobile K6-3+
1172 +Cyrix Media GXm
1173 +Intel mobile PIII [*] and Intel mobile PIII-M on certain chipsets
1174 +Intel Pentium 4, Intel Xeon
1175 +National Semiconductors Geode GX
1176 +Transmeta Crusoe
1177 +varios processors on some ACPI 2.0-compatible systems [**]
1179 +[*] only certain Intel mobile PIII processors are supported. If you
1180 +know that you own a speedstep-capable processor, pass the option
1181 +"speedstep_coppermine=1" to the module speedstep.o
1183 +[**] Only if "ACPI Processor Performance States" are available
1184 +to the ACPI<->BIOS interface.
1187 +1.3 sparc64
1188 +-----------
1190 +The following processors for the sparc64 architecture are supported by
1191 +cpufreq:
1193 +UltraSPARC-III
1197 +2. "Policy" / "Governor" ?
1198 +==========================
1200 +Some CPU frequency scaling-capable processor switch between varios
1201 +frequencies and operating voltages "on the fly" without any kernel or
1202 +user involvement. This guarantuees very fast switching to a frequency
1203 +which is high enough to serve the user's needs, but low enough to save
1204 +power.
1207 +2.1 Policy
1208 +----------
1210 +On these systems, all you can do is select the lower and upper
1211 +frequency limit as well as whether you want more aggressive
1212 +power-saving or more instantly avaialble processing power.
1215 +2.2 Governor
1216 +------------
1218 +On all other cpufreq implementations, these boundaries still need to
1219 +be set. Then, a "governor" must be selected. Such a "governor" decides
1220 +what speed the processor shall run within the boundaries. One such
1221 +"governor" is the "userspace" governor. This one allows the user - or
1222 +a yet-to-implement userspace program - to decide what specific speed
1223 +the processor shall run at.
1226 +3. How to change the CPU cpufreq policy and/or speed
1227 +====================================================
1229 +3.1 Preferred Interface: sysfs
1230 +------------------------------
1232 +The preferred interface is located in the sysfs filesystem. If you
1233 +mounted it at /sys, the cpufreq interface is located in a subdirectory
1234 +"cpufreq" within the cpu-device directory
1235 +(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
1237 +cpuinfo_min_freq : this file shows the minimum operating
1238 + frequency the processor can run at(in kHz)
1239 +cpuinfo_max_freq : this file shows the maximum operating
1240 + frequency the processor can run at(in kHz)
1241 +scaling_driver : this file shows what cpufreq driver is
1242 + used to set the frequency on this CPU
1244 +scaling_available_governors : this file shows the CPUfreq governors
1245 + available in this kernel. You can see the
1246 + currently activated governor in
1248 +scaling_governor, and by "echoing" the name of another
1249 + governor you can change it. Please note
1250 + that some governors won't load - they only
1251 + work on some specific architectures or
1252 + processors.
1253 +scaling_min_freq and
1254 +scaling_max_freq show the current "policy limits" (in
1255 + kHz). By echoing new values into these
1256 + files, you can change these limits.
1259 +If you have selected the "userspace" governor which allows you to
1260 +set the CPU operating frequency to a specific value, you can read out
1261 +the current frequency in
1263 +scaling_setspeed. By "echoing" a new frequency into this
1264 + you can change the speed of the CPU,
1265 + but only within the limits of
1266 + scaling_min_freq and scaling_max_freq.
1269 +3.2 Deprecated Interfaces
1270 +-------------------------
1272 +Depending on your kernel configuration, you might find the following
1273 +cpufreq-related files:
1274 +/proc/cpufreq
1275 +/proc/sys/cpu/*/speed
1276 +/proc/sys/cpu/*/speed-min
1277 +/proc/sys/cpu/*/speed-max
1279 +These are files for deprecated interfaces to cpufreq, which offer far
1280 +less functionality. Because of this, these interfaces aren't described
1281 +here.
1283 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
1284 +++ linux-2.4.25/Documentation/cpufreq-old 2004-03-31 17:15:08.000000000 +0200
1285 @@ -0,0 +1,332 @@
1286 + CPU frequency and voltage scaling code in the Linux(TM) kernel
1289 + L i n u x C P U F r e q
1294 + Dominik Brodowski <devel@brodo.de>
1298 + Clock scaling allows you to change the clock speed of the CPUs on the
1299 + fly. This is a nice method to save battery power, because the lower
1300 + the clock speed, the less power the CPU consumes.
1304 +Contents:
1305 +---------
1306 +1. Supported architectures
1307 +2. User interface
1308 +2.1 Sample script for command line interface
1309 +3. CPUFreq core and interfaces
1310 +3.1 General information
1311 +3.2 CPUFreq notifiers
1312 +3.3 CPUFreq architecture drivers
1313 +4. Mailing list and Links
1317 +1. Supported architectures
1318 +==========================
1320 +Some architectures detect the lowest and highest possible speed
1321 +settings, while others rely on user information on this. For the
1322 +latter, a boot parameter is required, for the former, you can specify
1323 +one to set the limits between speed settings may occur.
1324 +The boot parameter has the following syntax:
1326 + cpufreq=minspeed-maxspeed
1328 +with both minspeed and maxspeed being given in kHz. To set the lower
1329 +limit to 59 MHz and the upper limit to 221 MHz, specify:
1331 + cpufreq=59000-221000
1333 +Check the "Speed Limits Detection" information below on whether
1334 +the driver detects the lowest and highest allowed speed setting
1335 +automatically.
1338 +ARM Integrator:
1339 + SA 1100, SA1110
1340 +--------------------------------
1341 + Speed Limits Detection: On Integrators, the minimum speed is set
1342 + and the maximum speed has to be specified using the boot
1343 + parameter. On SA11x0s, the frequencies are fixed (59 - 287 MHz)
1346 +AMD Elan:
1347 + SC400, SC410
1348 +--------------------------------
1349 + Speed Limits Detection: Not implemented. You need to specify the
1350 + minimum and maximum frequency in the boot parameter (see above).
1353 +VIA Cyrix Longhaul:
1354 + VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3,
1355 + VIA Cyrix Ezra, VIA Cyrix Ezra-T
1356 +--------------------------------
1357 + Speed Limits Detection: working. No need for boot parameters.
1358 + NOTE: Support for certain processors is currently disabled,
1359 + waiting on updated docs from VIA.
1362 +Intel SpeedStep:
1363 + certain mobile Intel Pentium III (Coppermine), and all mobile
1364 + Intel Pentium III-M (Tulatin) and mobile Intel Pentium 4 P4-Ms.
1365 +--------------------------------
1366 + Speed Limits Detection: working. No need for boot parameters.
1367 + NOTE:
1368 + 1.) mobile Intel Pentium III (Coppermine):
1369 + The SpeedStep interface may only be used on SpeedStep
1370 + capable processors. Unforunately, due to lack of documentation,
1371 + such detection is not yet possible on mobile Intel PIII
1372 + (Coppermine) processors. In order to activate SpeedStep on such a
1373 + processor, you have to remove one line manually in
1374 + linux/drivers/arch/i386/speedstep.c
1377 +P4 CPU Clock Modulation:
1378 + Intel Pentium 4 Xeon processors
1379 +--------------------------------
1380 + Speed Limits Detection: Not implemented. You need to specify the
1381 + minimum and maximum frequency in the boot parameter (see above).
1385 +2. User Interface
1386 +=================
1388 +CPUFreq uses a "sysctl" interface which is located in
1389 + /proc/sys/cpu/0/ on UP (uniprocessor) kernels, or
1390 + /proc/sys/cpu/any/ on SMP (symmetric multiprocessoring) kernels.
1393 +In this directory, you will find three files of importance for
1394 +CPUFreq: speed-max, speed-min, and speed:
1396 +speed shows the current CPU frequency in kHz,
1397 +speed-min the minimal supported CPU frequency, and
1398 +speed-max the maximal supported CPU frequency.
1400 +Please note that you might have to specify these limits as a boot
1401 +parameter depending on the architecture (see above).
1404 +To change the CPU frequency, "echo" the desired CPU frequency (in kHz)
1405 +to speed. For example, to set the CPU speed to the lowest/highest
1406 +allowed frequency do:
1408 +root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed
1409 +root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed
1412 +2.1 Sample script for command line interface
1413 +**********************************************
1416 +Michael Ossmann <mike@ossmann.com> has written a small command line
1417 +interface for the infinitely lazy.
1419 +#!/bin/bash
1421 +# /usr/local/bin/freq
1422 +# simple command line interface to cpufreq
1424 +[ -n "$1" ] && case "$1" in
1425 + "min" )
1426 + # set frequency to minimum
1427 + cat /proc/sys/cpu/0/speed-min >/proc/sys/cpu/0/speed
1428 + ;;
1429 + "max" )
1430 + # set frequency to maximum
1431 + cat /proc/sys/cpu/0/speed-max >/proc/sys/cpu/0/speed
1432 + ;;
1433 + * )
1434 + echo "Usage: $0 [min|max]"
1435 + echo " min: set frequency to minimum and display new frequency"
1436 + echo " max: set frequency to maximum and display new frequency"
1437 + echo " no options: display current frequency"
1438 + exit 1
1439 + ;;
1440 +esac
1442 +# display current frequency
1443 +cat /proc/sys/cpu/0/speed
1444 +exit 0
1448 +3. CPUFreq core and interfaces
1449 +===============================
1451 +3.1 General information
1452 +*************************
1454 +The CPUFreq core code is located in linux/kernel/cpufreq.c. This
1455 +cpufreq code offers a standardized interface for the CPUFreq
1456 +architecture drivers (those pieces of code that do the actual
1457 +frequency transition), as well as to "notifiers". These are device
1458 +drivers or other part of the kernel that need to be informed of
1459 +frequency changes (like timing code) or even need to force certain
1460 +speed limits (like LCD drivers on ARM architecture). Aditionally, the
1461 +kernel "constant" loops_per_jiffy is updated on frequency changes
1462 +here.
1465 +3.2 CPUFreq notifiers
1466 +***********************
1468 +CPUFreq notifiers are kernel code that need to be called to either
1469 +a) define certain minimum or maximum speed settings,
1470 +b) be informed of frequency changes in advance of the transition, or
1471 +c) be informed of frequency changes directly after the transition.
1473 +A standard kernel notifier interface is offered for this. See
1474 +linux/include/linux/notifier.h for details on notifiers.
1477 +Data and value passed to CPUFreq notifiers
1478 +------------------------------------------
1479 +The second argument passed to any notifier is an unsigned int stating
1480 +the phase of the transition:
1481 +CPUFREQ_MINMAX during the process of determing a valid new CPU
1482 + frequency,
1483 +CPUFREQ_PRECHANGE right before the transition, and
1484 +CPUFREQ_POSTCHANGE right after the transition.
1486 +The third argument, a void *pointer, points to a struct
1487 +cpufreq_freqs. This consists of four values: min, max, cur and new.
1489 +min and max are the current speed limits. Please note: Never update
1490 +these values directly, use cpufreq_updateminmax(struct cpufreq_freqs
1491 +*freqs, unsigned int min, unsigned int max) instead. cur is the
1492 +current/old speed, and new is the new speed, but might only be valid
1493 +on CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE.
1495 +Each notifier gets called all three times on any transition:
1497 +CPUFREQ_MINMAX
1498 +Here the notifier is supposed to update the min and max values to the
1499 +limits the protected device / kernel code needs. As stated above,
1500 +always use cpufreq_updateminmax for this.
1502 +CPUFREQ_PRECHANGE
1503 +CPUFREQ_POSTCHANGE
1504 +Here the notifier is supposed to update all internal (e.g. device
1505 +driver) code which is dependend on the CPU frequency.
1508 +3.3 CPUFreq architecture drivers
1509 +**********************************
1511 +CPUFreq architecture drivers are the pieces of kernel code that
1512 +actually perform CPU frequency transitions. These need to be
1513 +initialised seperately (seperate initcalls), and may be
1514 +modularized. They interact with the CPUFreq core in the following way:
1517 +cpufreq_register()
1518 +------------------
1519 +cpufreq_register registers an arch driver to the CPUFreq core. Please
1520 +note that only one arch driver may be registered at any time, -EBUSY
1521 +is returned when an arch driver is already registered. The argument to
1522 +cpufreq_register, cpufreq_driver_t driver, is described later.
1525 +cpufreq_unregister()
1526 +--------------------
1527 +cpufreq_unregister unregisters an arch driver, e.g. on module
1528 +unloading. Please note that there is no check done that this is called
1529 +from the driver which actually registered itself to the core, so
1530 +please only call this function when you are sure the arch driver got
1531 +registered correctly before.
1534 +struct cpufreq_driver
1535 +----------------
1536 +On initialisation, the arch driver is supposed to pass the following
1537 +entries in struct cpufreq_driver cpufreq_driver:
1539 +cpufreq_verify_t validate: This is a pointer to a function with the
1540 +following definition:
1541 + unsigned int validating_function (unsigned int kHz).
1542 +It is called right before a transition occurs. The proposed new
1543 +speed setting is passed as an argument in kHz; the validating code
1544 +should verify this is a valid speed setting which is currently
1545 +supported by the CPU. It shall return the closest valid CPU frequency
1546 +in kHz.
1548 +cpufreq_setspeed_t setspeed: This is a pointer to a function with the
1549 +following definition:
1550 + void setspeed_function (unsigned int kHz).
1551 +This function shall perform the transition to the new CPU frequency
1552 +given as argument in kHz. Note that this argument is exactly the same
1553 +as the one returned by cpufreq_verify_t validate.
1556 +unsigned int freq.cur: The current CPU core frequency. Note that this
1557 +is a requirement while the next two entries are optional.
1560 +unsigned int freq.min (optional): The minimal CPU core frequency this
1561 +CPU supports. This value may be limited further by the
1562 +cpufreq_verify_t validate function, and so this value should be the
1563 +minimal core frequency allowed "theoretically" on this system in this
1564 +configuration.
1567 +unsigned int freq.max (optional): The maximum CPU core frequency this
1568 +CPU supports. This value may be limited further by the
1569 +cpufreq_verify_t validate function, and so this value should be the
1570 +maximum core frequency allowed "theoretically" on this system in this
1571 +configuration.
1574 +Some Requirements to CPUFreq architecture drivers
1575 +-------------------------------------------------
1576 +* Only call cpufreq_register() when the ability to switch CPU
1577 + frequencies is _verified_ or can't be missing
1578 +* cpufreq_unregister() may only be called if cpufreq_register() has
1579 + been successfully(!) called before
1580 +* All CPUs have to be set to the same speed whenever setspeed() is
1581 + called
1582 +* Be aware that there is currently no error management in the
1583 + setspeed() code in the CPUFreq core. So only call yourself a
1584 + cpufreq_driver if you are really a working cpufreq_driver!
1588 +4. Mailing list and Links
1589 +**************************
1592 +Mailing List
1593 +------------
1594 +There is a CPU frequency changing CVS commit and general list where
1595 +you can report bugs, problems or submit patches. To post a message,
1596 +send an email to cpufreq@www.linux.org.uk, to subscribe go to
1597 +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
1598 +mailing list are available to subscribers at
1599 +http://www.linux.org.uk/mailman/private/cpufreq/.
1602 +Links
1603 +-----
1604 +the FTP archives:
1605 +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
1607 +how to access the CVS repository:
1608 +* http://www.arm.linux.org.uk/cvs/
1610 +the CPUFreq Mailing list:
1611 +* http://www.linux.org.uk/mailman/listinfo/cpufreq
1613 +Clock and voltage scaling for the SA-1100:
1614 +* http://www.lart.tudelft.nl/projects/scaling
1616 +CPUFreq project homepage
1617 +* http://www.brodo.de/cpufreq/
1618 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
1619 +++ linux-2.4.25/Documentation/l3/structure 2004-03-31 17:15:08.000000000 +0200
1620 @@ -0,0 +1,36 @@
1621 +L3 Bus Driver
1622 +-------------
1624 +The structure of the driver is as follows:
1626 + +----------+ +----------+ +----------+
1627 + | client 1 | | client 2 | | client 3 |
1628 + +-----^----+ +----^-----+ +----^-----+
1629 + | | |
1630 + +-----v--------------v---------------v-----+
1631 + | |
1632 + +-----^-------+ +-------^-----+
1633 + | | core | |
1634 + +-----v----+ | | +----v-----+
1635 + | device | | | | device |
1636 + | driver 1 | | | | driver 2 |
1637 + +-----^----+ | | +----^-----+
1638 + | | services | |
1639 + +-----v-------+ +-------v-----+
1640 + | |
1641 + +-----------------^----^-------------------+
1642 + | |
1643 + | +-v---------+
1644 + | | algorithm |
1645 + | | driver |
1646 + | +-v---------+
1647 + | |
1648 + +-v----v-+
1649 + | bus |
1650 + | driver |
1651 + +--------+
1653 +Clients talk to the core to attach device drivers and bus adapters, and
1654 +to instruct device drivers to perform actions. Device drivers then talk
1655 +to the core to perform L3 bus transactions via the algorithm driver and
1656 +ultimately bus driver.
1657 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
1658 +++ linux-2.4.25/Documentation/serial/driver 2004-03-31 17:15:08.000000000 +0200
1659 @@ -0,0 +1,208 @@
1661 + Low Level Serial API
1662 + --------------------
1665 + $Id: driver,v 1.3 2001/11/24 23:24:47 rmk Exp $
1668 +This document is meant as a brief overview of some aspects of the new serial
1669 +driver. It is not complete, any questions you have should be directed to
1670 +<rmk@arm.linux.org.uk>
1672 +The reference implementation is contained within serial_amba.c.
1676 +Low Level Serial Hardware Driver
1677 +--------------------------------
1679 +The low level serial hardware driver is responsible for supplying port
1680 +information (defined by uart_port) and a set of control methods (defined
1681 +by uart_ops) to the core serial driver. The low level driver is also
1682 +responsible for handling interrupts for the port, and providing any
1683 +console support.
1686 +Console Support
1687 +---------------
1689 +The serial core provides a few helper functions. This includes identifing
1690 +the correct port structure (via uart_get_console) and decoding command line
1691 +arguments (uart_parse_options).
1694 +Locking
1695 +-------
1697 +Generally, all locking is done by the core driver, except for the interrupt
1698 +functions. It is the responsibility of the low level hardware driver to
1699 +perform the necessary locking there using info->lock. (since it is running
1700 +in an interrupt, you only need to use spin_lock() and spin_unlock() from
1701 +the interrupt handler).
1704 +uart_ops
1705 +--------
1707 +The uart_ops structure is the main interface between serial_core and the
1708 +hardware specific driver. It contains all the methods to control the
1709 +hardware.
1711 + tx_empty(port)
1712 + This function tests whether the transmitter fifo and shifter
1713 + for the port described by 'port' is empty. If it is empty,
1714 + this function should return TIOCSER_TEMT, otherwise return 0.
1715 + If the port does not support this operation, then it should
1716 + return TIOCSER_TEMT.
1718 + set_mctrl(port, mctrl)
1719 + This function sets the modem control lines for port described
1720 + by 'port' to the state described by mctrl. The relevant bits
1721 + of mctrl are:
1722 + - TIOCM_RTS RTS signal.
1723 + - TIOCM_DTR DTR signal.
1724 + - TIOCM_OUT1 OUT1 signal.
1725 + - TIOCM_OUT2 OUT2 signal.
1726 + If the appropriate bit is set, the signal should be driven
1727 + active. If the bit is clear, the signal should be driven
1728 + inactive.
1730 + get_mctrl(port)
1731 + Returns the current state of modem control inputs. The state
1732 + of the outputs should not be returned, since the core keeps
1733 + track of their state. The state information should include:
1734 + - TIOCM_DCD state of DCD signal
1735 + - TIOCM_CTS state of CTS signal
1736 + - TIOCM_DSR state of DSR signal
1737 + - TIOCM_RI state of RI signal
1738 + The bit is set if the signal is currently driven active. If
1739 + the port does not support CTS, DCD or DSR, the driver should
1740 + indicate that the signal is permanently active. If RI is
1741 + not available, the signal should not be indicated as active.
1743 + stop_tx(port,from_tty)
1744 + Stop transmitting characters. This might be due to the CTS
1745 + line becoming inactive or the tty layer indicating we want
1746 + to stop transmission.
1748 + start_tx(port,nonempty,from_tty)
1749 + start transmitting characters. (incidentally, nonempty will
1750 + always be nonzero, and shouldn't be used - it will be dropped).
1752 + stop_rx(port)
1753 + Stop receiving characters; the port is in the process of
1754 + being closed.
1756 + enable_ms(port)
1757 + Enable the modem status interrupts.
1759 + break_ctl(port,ctl)
1760 + Control the transmission of a break signal. If ctl is
1761 + nonzero, the break signal should be transmitted. The signal
1762 + should be terminated when another call is made with a zero
1763 + ctl.
1765 + startup(port,info)
1766 + Grab any interrupt resources and initialise any low level driver
1767 + state. Enable the port for reception. It should not activate
1768 + RTS nor DTR; this will be done via a separate call to set_mctrl.
1770 + shutdown(port,info)
1771 + Disable the port, disable any break condition that may be in
1772 + effect, and free any interrupt resources. It should not disable
1773 + RTS nor DTR; this will have already been done via a separate
1774 + call to set_mctrl.
1776 + change_speed(port,cflag,iflag,quot)
1777 + Change the port parameters, including word length, parity, stop
1778 + bits. Update read_status_mask and ignore_status_mask to indicate
1779 + the types of events we are interested in receiving. Relevant
1780 + cflag bits are:
1781 + CSIZE - word size
1782 + CSTOPB - 2 stop bits
1783 + PARENB - parity enable
1784 + PARODD - odd parity (when PARENB is in force)
1785 + CREAD - enable reception of characters (if not set,
1786 + still receive characters from the port, but
1787 + throw them away.
1788 + CRTSCTS - if set, enable CTS status change reporting
1789 + CLOCAL - if not set, enable modem status change
1790 + reporting.
1791 + Relevant iflag bits are:
1792 + INPCK - enable frame and parity error events to be
1793 + passed to the TTY layer.
1794 + BRKINT
1795 + PARMRK - both of these enable break events to be
1796 + passed to the TTY layer.
1798 + IGNPAR - ignore parity and framing errors
1799 + IGNBRK - ignore break errors, If IGNPAR is also
1800 + set, ignore overrun errors as well.
1801 + The interaction of the iflag bits is as follows (parity error
1802 + given as an example):
1803 + Parity error INPCK IGNPAR
1804 + None n/a n/a character received
1805 + Yes n/a 0 character discarded
1806 + Yes 0 1 character received, marked as
1807 + TTY_NORMAL
1808 + Yes 1 1 character received, marked as
1809 + TTY_PARITY
1811 + pm(port,state,oldstate)
1812 + perform any power management related activities on the specified
1813 + port. state indicates the new state (defined by ACPI D0-D3),
1814 + oldstate indicates the previous state. Essentially, D0 means
1815 + fully on, D3 means powered down.
1817 + This function should not be used to grab any resources.
1819 + type(port)
1820 + Return a pointer to a string constant describing the specified
1821 + port, or return NULL, in which case the string 'unknown' is
1822 + substituted.
1824 + release_port(port)
1825 + Release any memory and IO region resources currently in use by
1826 + the port.
1828 + request_port(port)
1829 + Request any memory and IO region resources required by the port.
1830 + If any fail, no resources should be registered when this function
1831 + returns, and it should return -EBUSY on failure.
1833 + config_port(port,type)
1834 + Perform any autoconfiguration steps required for the port. `type`
1835 + contains a bit mask of the required configuration. UART_CONFIG_TYPE
1836 + indicates that the port requires detection and identification.
1837 + port->type should be set to the type found, or PORT_UNKNOWN if
1838 + no port was detected.
1840 + UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal,
1841 + which should be probed using standard kernel autoprobing techniques.
1842 + This is not necessary on platforms where ports have interrupts
1843 + internally hard wired (eg, system on a chip implementations).
1845 + verify_port(port,serinfo)
1846 + Verify the new serial port information contained within serinfo is
1847 + suitable for this port type.
1849 + ioctl(port,cmd,arg)
1850 + Perform any port specific IOCTLs. IOCTL commands must be defined
1851 + using the standard numbering system found in <asm/ioctl.h>
1854 +Other notes
1855 +-----------
1857 +It is intended some day to drop the 'unused' entries from uart_port, and
1858 +allow low level drivers to register their own individual uart_port's with
1859 +the core. This will allow drivers to use uart_port as a pointer to a
1860 +structure containing both the uart_port entry with their own extensions,
1861 +thus:
1863 + struct my_port {
1864 + struct uart_port port;
1865 + int my_stuff;
1866 + };
1868 --- linux-2.4.25/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
1869 +++ linux-2.4.25/Makefile 2004-03-31 17:15:08.000000000 +0200
1870 @@ -1,7 +1,7 @@
1871 VERSION = 2
1872 PATCHLEVEL = 4
1873 SUBLEVEL = 25
1874 -EXTRAVERSION =
1875 +EXTRAVERSION =-vrs2
1877 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
1879 @@ -137,7 +137,10 @@
1881 DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o
1882 DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
1883 -DRIVERS-y += drivers/char/char.o \
1884 +DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
1885 +DRIVERS-$(CONFIG_L3) += drivers/l3/l3.o
1886 +DRIVERS-y += drivers/serial/serial.o \
1887 + drivers/char/char.o \
1888 drivers/block/block.o \
1889 drivers/misc/misc.o \
1890 drivers/net/net.o
1891 @@ -161,6 +164,7 @@
1892 DRIVERS-y += drivers/cdrom/driver.o
1893 endif
1895 +DRIVERS-$(CONFIG_SSI) += drivers/ssi/ssi.o
1896 DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o
1897 DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
1898 DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
1899 @@ -186,7 +190,6 @@
1900 DRIVERS-$(CONFIG_HIL) += drivers/hil/hil.o
1901 DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o
1902 DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
1903 -DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
1904 DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
1905 DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
1906 DRIVERS-$(CONFIG_GSC) += drivers/gsc/gscbus.o
1907 @@ -194,6 +197,8 @@
1908 DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
1909 DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
1910 DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o
1911 +DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o
1912 +DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o
1914 DRIVERS := $(DRIVERS-y)
1916 @@ -273,11 +278,6 @@
1918 export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
1920 -.S.s:
1921 - $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $<
1922 -.S.o:
1923 - $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -c -o $*.o $<
1925 Version: dummy
1926 @rm -f include/linux/compile.h
1928 --- linux-2.4.25/Rules.make~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
1929 +++ linux-2.4.25/Rules.make 2004-03-31 17:15:08.000000000 +0200
1930 @@ -51,15 +51,15 @@
1933 %.s: %.c
1934 - $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
1935 + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o $@
1937 %.i: %.c
1938 - $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
1939 + $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) $< > $@
1941 %.o: %.c
1942 - $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
1943 + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -c -o $@ $<
1944 @ ( \
1945 - echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@))))' ; \
1946 + echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$(*F)) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$(*F)) $$(CFLAGS_$@))))' ; \
1947 echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
1948 echo 'endif' \
1949 ) > $(dir $@)/.$(notdir $@).flags
1950 @@ -272,7 +272,8 @@
1951 endif # CONFIG_MODVERSIONS
1953 ifneq "$(strip $(export-objs))" ""
1954 -$(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h
1955 +$(export-objs): $(TOPDIR)/include/linux/modversions.h
1956 +$(export-objs): %.o: %.c
1957 $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
1958 @ ( \
1959 echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \
1960 --- linux-2.4.25/arch/alpha/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
1961 +++ linux-2.4.25/arch/alpha/config.in 2004-03-31 17:15:08.000000000 +0200
1962 @@ -7,6 +7,7 @@
1963 define_bool CONFIG_UID16 n
1964 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
1965 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
1966 +define_bool CONFIG_GENERIC_ISA_DMA y
1968 mainmenu_name "Kernel configuration of Linux for Alpha machines"
1970 --- linux-2.4.25/arch/arm/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
1971 +++ linux-2.4.25/arch/arm/Makefile 2004-03-31 17:15:08.000000000 +0200
1972 @@ -52,7 +52,7 @@
1974 CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
1975 CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
1976 -AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
1977 +AFLAGS +=$(apcs-y) $(arch-y) -msoft-float
1979 ifeq ($(CONFIG_CPU_26),y)
1980 PROCESSOR := armo
1981 --- linux-2.4.25/arch/arm/boot/compressed/head.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
1982 +++ linux-2.4.25/arch/arm/boot/compressed/head.S 2004-03-31 17:15:08.000000000 +0200
1983 @@ -40,6 +40,14 @@
1984 .macro writeb, rb
1985 strb \rb, [r3, #0x3f8 << 2]
1986 .endm
1987 +#elif defined(CONFIG_ARCH_RISCSTATION)
1988 + .macro loadsp, rb
1989 + mov \rb, #0x03000000
1990 + orr \rb, \rb, #0x00010000
1991 + .endm
1992 + .macro writeb, rb
1993 + strb \rb, [r3, #0x3f8 << 2]
1994 + .endm
1995 #elif defined(CONFIG_ARCH_INTEGRATOR)
1996 .macro loadsp, rb
1997 mov \rb, #0x16000000
1998 @@ -396,6 +404,20 @@
1999 mcr p15, 0, r0, c1, c0, 0 @ load control register
2000 mov pc, r12
2002 +__arm7_cache_on:
2003 + mov r12, lr
2004 + bl __setup_mmu
2005 + mov r0, #0
2006 + mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
2007 + mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
2008 + mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
2009 + mov r0, #-1
2010 + mcr p15, 0, r0, c3, c0, 0 @ load domain access control
2011 + mov r0, #0x7d
2012 + mcr p15, 0, r0, c1, c0, 0 @ load control register
2013 + mov pc, r12
2017 * All code following this line is relocatable. It is relocated by
2018 * the above code to the end of the decompressed kernel image and
2019 @@ -480,9 +502,9 @@
2021 .word 0x41007000 @ ARM7/710
2022 .word 0xfff8fe00
2023 + b __arm7_cache_on
2024 b __arm7_cache_off
2025 - b __arm7_cache_off
2026 - mov pc, lr
2027 + b __armv3_cache_flush
2029 .word 0x41807200 @ ARM720T (writethrough)
2030 .word 0xffffff00
2031 @@ -490,14 +512,14 @@
2032 b __armv4_cache_off
2033 mov pc, lr
2035 - .word 0x41129200 @ ARM920T
2036 - .word 0xff00fff0
2037 + .word 0x41009200 @ ARM920T, ARM922T, ARM926TEJ-S
2038 + .word 0xff00ff90
2039 b __armv4_cache_on
2040 b __armv4_cache_off
2041 b __armv4_cache_flush
2043 - .word 0x41029220 @ ARM922T
2044 - .word 0xff00fff0
2045 + .word 0x4100a200 @ ARM1020T/E, ARM1022E, ARM1026TEJ-S
2046 + .word 0xff00ff90
2047 b __armv4_cache_on
2048 b __armv4_cache_off
2049 b __armv4_cache_flush
2050 --- linux-2.4.25/arch/arm/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
2051 +++ linux-2.4.25/arch/arm/config.in 2004-03-31 17:15:08.000000000 +0200
2052 @@ -144,6 +144,7 @@
2053 mainmenu_option next_comment
2054 comment 'AT91RM9200 Implementations'
2055 dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200
2056 +dep_bool ' Cogent CSB337' CONFIG_MACH_CSB337 $CONFIG_ARCH_AT91RM9200
2057 endmenu
2059 mainmenu_option next_comment
2060 @@ -189,6 +190,12 @@
2061 define_bool CONFIG_ARCH_ACORN n
2064 +if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
2065 + define_bool CONFIG_PLD y
2066 +else
2067 + define_bool CONFIG_PLD n
2070 #####################################################################
2071 # Footbridge support
2072 if [ "$CONFIG_ARCH_CO285" = "y" -o \
2073 @@ -315,26 +322,42 @@
2074 # ARM922T
2075 if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
2076 define_bool CONFIG_CPU_ARM922T y
2077 - define_bool CONFIG_PLD y
2078 else
2079 - define_bool CONFIG_CPU_ARM922T n
2080 - define_bool CONFIG_PLD n
2081 + if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
2082 + bool 'Support ARM922T(Excalibur) processor' CONFIG_ARM922T
2083 + else
2084 + define_bool CONFIG_CPU_ARM922T n
2085 + fi
2088 # ARM926T
2089 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
2090 - bool 'Support ARM926T processor' CONFIG_CPU_ARM926T
2091 + bool 'Support ARM926TEJ-S processor' CONFIG_CPU_ARM926T
2092 else
2093 define_bool CONFIG_CPU_ARM926T n
2096 # ARM1020
2097 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
2098 - bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020
2099 + bool 'Support ARM1020T (Rev0) processor' CONFIG_CPU_ARM1020
2100 else
2101 define_bool CONFIG_CPU_ARM1020 n
2104 +# ARM1020E
2105 +if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
2106 + bool 'Support ARM1020E (Rev1) processor' CONFIG_CPU_ARM1020E
2107 +else
2108 + define_bool CONFIG_CPU_ARM1020E n
2111 +# ARM1022
2112 +if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
2113 + bool 'Support ARM1022 processor' CONFIG_CPU_ARM1020E
2114 +else
2115 + define_bool CONFIG_CPU_ARM1022 n
2118 # ARM1026EJ-S
2119 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
2120 bool 'Support ARM1026EJ-S processor' CONFIG_CPU_ARM1026
2121 @@ -388,25 +411,29 @@
2123 if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \
2124 "$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \
2125 - "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
2126 + "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
2127 + "$CONFIG_CPU_ARM1022" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
2128 dep_bool 'Support Thumb instructions (EXPERIMENTAL)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
2130 if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \
2131 "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
2132 + "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
2133 "$CONFIG_CPU_ARM1026" = "y" ]; then
2134 bool 'Disable I-Cache' CONFIG_CPU_ICACHE_DISABLE
2135 bool 'Disable D-Cache' CONFIG_CPU_DCACHE_DISABLE
2136 - if [ "$CONFIG_CPU_DISABLE_DCACHE" = "n" ]; then
2137 + if [ "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
2138 bool 'Force write through D-cache' CONFIG_CPU_DCACHE_WRITETHROUGH
2141 if [ "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
2142 + "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
2143 "$CONFIG_CPU_ARM1026" = "y" ]; then
2144 if [ "$CONFIG_CPU_ICACHE_DISABLE" = "n" -o "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
2145 bool 'Round robin I and D cache replacement algorithm' CONFIG_CPU_CACHE_ROUND_ROBIN
2148 -if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
2149 +if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
2150 + "$CONFIG_CPU_ARM1026" = "y" -o "$CONFIG_CPU_ARM1022" = "y" ]; then
2151 bool 'Disable branch prediction' CONFIG_CPU_BPREDICT_DISABLE
2154 @@ -729,10 +756,7 @@
2155 dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
2156 dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
2157 dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
2159 -int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
2161 endmenu
2163 -source crypto/Config.in
2164 source lib/Config.in
2166 --- linux-2.4.25/arch/arm/def-configs/at91rm9200dk~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
2167 +++ linux-2.4.25/arch/arm/def-configs/at91rm9200dk 2004-03-31 17:15:08.000000000 +0200
2168 @@ -111,6 +111,7 @@
2169 # AT91RM9200 Implementations
2171 CONFIG_ARCH_AT91RM9200DK=y
2172 +# CONFIG_MACH_CSB337 is not set
2175 # CLPS711X/EP721X Implementations
2176 @@ -125,6 +126,7 @@
2177 # CONFIG_ARCH_EP7211 is not set
2178 # CONFIG_ARCH_EP7212 is not set
2179 # CONFIG_ARCH_ACORN is not set
2180 +# CONFIG_PLD is not set
2181 # CONFIG_FOOTBRIDGE is not set
2182 # CONFIG_FOOTBRIDGE_HOST is not set
2183 # CONFIG_FOOTBRIDGE_ADDIN is not set
2184 @@ -135,9 +137,10 @@
2185 # CONFIG_CPU_ARM720T is not set
2186 CONFIG_CPU_ARM920T=y
2187 # CONFIG_CPU_ARM922T is not set
2188 -# CONFIG_PLD is not set
2189 # CONFIG_CPU_ARM926T is not set
2190 # CONFIG_CPU_ARM1020 is not set
2191 +# CONFIG_CPU_ARM1020E is not set
2192 +# CONFIG_CPU_ARM1022 is not set
2193 # CONFIG_CPU_ARM1026 is not set
2194 # CONFIG_CPU_SA110 is not set
2195 # CONFIG_CPU_SA1100 is not set
2196 @@ -146,6 +149,7 @@
2197 # CONFIG_ARM_THUMB is not set
2198 # CONFIG_CPU_ICACHE_DISABLE is not set
2199 # CONFIG_CPU_DCACHE_DISABLE is not set
2200 +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
2201 # CONFIG_DISCONTIGMEM is not set
2204 @@ -164,6 +168,7 @@
2205 # CONFIG_BSD_PROCESS_ACCT is not set
2206 CONFIG_SYSCTL=y
2207 CONFIG_FPE_NWFPE=y
2208 +# CONFIG_FPE_NWFPE_XP is not set
2209 # CONFIG_FPE_FASTFPE is not set
2210 CONFIG_KCORE_ELF=y
2211 # CONFIG_KCORE_AOUT is not set
2212 @@ -173,6 +178,9 @@
2213 # CONFIG_PM is not set
2214 # CONFIG_ARTHUR is not set
2215 CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20210000,3145728 root=/dev/ram rw"
2216 +CONFIG_LEDS=y
2217 +CONFIG_LEDS_TIMER=y
2218 +# CONFIG_LEDS_CPU is not set
2219 CONFIG_ALIGNMENT_TRAP=y
2222 @@ -204,6 +212,7 @@
2223 # CONFIG_MTD_CFI_ADV_OPTIONS is not set
2224 # CONFIG_MTD_CFI_INTELEXT is not set
2225 CONFIG_MTD_CFI_AMDSTD=y
2226 +# CONFIG_MTD_CFI_STAA is not set
2227 # CONFIG_MTD_RAM is not set
2228 # CONFIG_MTD_ROM is not set
2229 # CONFIG_MTD_ABSENT is not set
2230 @@ -230,7 +239,9 @@
2231 # CONFIG_MTD_AUTCPU12 is not set
2232 # CONFIG_MTD_EDB7312 is not set
2233 # CONFIG_MTD_IMPA7 is not set
2234 +# CONFIG_MTD_CEIVA is not set
2235 # CONFIG_MTD_PCI is not set
2236 +# CONFIG_MTD_PCMCIA is not set
2239 # Self-contained MTD device drivers
2240 @@ -250,9 +261,9 @@
2241 # NAND Flash Device Drivers
2243 CONFIG_MTD_NAND=y
2244 -CONFIG_MTD_NAND_ECC=y
2245 # CONFIG_MTD_NAND_VERIFY_WRITE is not set
2246 -CONFIG_MTD_AT91_SMARTMEDIA=y
2247 +CONFIG_MTD_NAND_IDS=y
2248 +# CONFIG_MTD_AT91_SMARTMEDIA is not set
2251 # Plug and Play configuration
2252 @@ -269,6 +280,7 @@
2253 # CONFIG_BLK_CPQ_DA is not set
2254 # CONFIG_BLK_CPQ_CISS_DA is not set
2255 # CONFIG_CISS_SCSI_TAPE is not set
2256 +# CONFIG_CISS_MONITOR_THREAD is not set
2257 # CONFIG_BLK_DEV_DAC960 is not set
2258 # CONFIG_BLK_DEV_UMEM is not set
2259 # CONFIG_BLK_DEV_LOOP is not set
2260 @@ -276,6 +288,7 @@
2261 CONFIG_BLK_DEV_RAM=y
2262 CONFIG_BLK_DEV_RAM_SIZE=8192
2263 CONFIG_BLK_DEV_INITRD=y
2264 +# CONFIG_BLK_STATS is not set
2267 # Multi-device support (RAID and LVM)
2268 @@ -312,6 +325,12 @@
2269 # CONFIG_SYN_COOKIES is not set
2270 # CONFIG_IPV6 is not set
2271 # CONFIG_KHTTPD is not set
2274 +# SCTP Configuration (EXPERIMENTAL)
2276 +CONFIG_IPV6_SCTP__=y
2277 +# CONFIG_IP_SCTP is not set
2278 # CONFIG_ATM is not set
2279 # CONFIG_VLAN_8021Q is not set
2280 # CONFIG_IPX is not set
2281 @@ -382,10 +401,12 @@
2283 # CONFIG_ACENIC is not set
2284 # CONFIG_DL2K is not set
2285 +# CONFIG_E1000 is not set
2286 # CONFIG_MYRI_SBUS is not set
2287 # CONFIG_NS83820 is not set
2288 # CONFIG_HAMACHI is not set
2289 # CONFIG_YELLOWFIN is not set
2290 +# CONFIG_R8169 is not set
2291 # CONFIG_SK98LIN is not set
2292 # CONFIG_TIGON3 is not set
2293 # CONFIG_FDDI is not set
2294 @@ -455,6 +476,8 @@
2295 # CONFIG_INPUT_MOUSEDEV is not set
2296 # CONFIG_INPUT_JOYDEV is not set
2297 # CONFIG_INPUT_EVDEV is not set
2298 +# CONFIG_INPUT_UINPUT is not set
2299 +# CONFIG_INPUT_MX1TS is not set
2302 # Character devices
2303 @@ -502,6 +525,7 @@
2305 CONFIG_I2C=y
2306 # CONFIG_I2C_ALGOBIT is not set
2307 +# CONFIG_SCx200_ACB is not set
2308 # CONFIG_I2C_ALGOPCF is not set
2309 CONFIG_I2C_AT91=y
2310 CONFIG_I2C_CHARDEV=y
2311 @@ -528,6 +552,11 @@
2313 # CONFIG_INPUT_GAMEPORT is not set
2314 # CONFIG_QIC02_TAPE is not set
2315 +# CONFIG_IPMI_HANDLER is not set
2316 +# CONFIG_IPMI_PANIC_EVENT is not set
2317 +# CONFIG_IPMI_DEVICE_INTERFACE is not set
2318 +# CONFIG_IPMI_KCS is not set
2319 +# CONFIG_IPMI_WATCHDOG is not set
2322 # Watchdog Cards
2323 @@ -536,12 +565,14 @@
2324 CONFIG_WATCHDOG_NOWAYOUT=y
2325 # CONFIG_ACQUIRE_WDT is not set
2326 # CONFIG_ADVANTECH_WDT is not set
2327 +# CONFIG_ALIM1535_WDT is not set
2328 # CONFIG_ALIM7101_WDT is not set
2329 # CONFIG_SC520_WDT is not set
2330 # CONFIG_PCWATCHDOG is not set
2331 # CONFIG_21285_WATCHDOG is not set
2332 # CONFIG_977_WATCHDOG is not set
2333 # CONFIG_SA1100_WATCHDOG is not set
2334 +# CONFIG_EPXA_WATCHDOG is not set
2335 # CONFIG_OMAHA_WATCHDOG is not set
2336 CONFIG_AT91_WATCHDOG=y
2337 # CONFIG_EUROTECH_WDT is not set
2338 @@ -551,11 +582,16 @@
2339 # CONFIG_MIXCOMWD is not set
2340 # CONFIG_60XX_WDT is not set
2341 # CONFIG_SC1200_WDT is not set
2342 +# CONFIG_SCx200_WDT is not set
2343 # CONFIG_SOFT_WATCHDOG is not set
2344 # CONFIG_W83877F_WDT is not set
2345 # CONFIG_WDT is not set
2346 # CONFIG_WDTPCI is not set
2347 # CONFIG_MACHZ_WDT is not set
2348 +# CONFIG_AMD7XX_TCO is not set
2349 +# CONFIG_SCx200 is not set
2350 +# CONFIG_SCx200_GPIO is not set
2351 +# CONFIG_AMD_PM768 is not set
2352 # CONFIG_NVRAM is not set
2353 # CONFIG_RTC is not set
2354 CONFIG_AT91_RTC=y
2355 @@ -568,6 +604,10 @@
2357 # CONFIG_FTAPE is not set
2358 # CONFIG_AGP is not set
2361 +# Direct Rendering Manager (XFree86 DRI support)
2363 # CONFIG_DRM is not set
2366 @@ -579,6 +619,7 @@
2367 # File systems
2369 # CONFIG_QUOTA is not set
2370 +# CONFIG_QFMT_V2 is not set
2371 # CONFIG_AUTOFS_FS is not set
2372 # CONFIG_AUTOFS4_FS is not set
2373 # CONFIG_REISERFS_FS is not set
2374 @@ -588,6 +629,9 @@
2375 # CONFIG_ADFS_FS_RW is not set
2376 # CONFIG_AFFS_FS is not set
2377 # CONFIG_HFS_FS is not set
2378 +# CONFIG_HFSPLUS_FS is not set
2379 +# CONFIG_BEFS_FS is not set
2380 +# CONFIG_BEFS_DEBUG is not set
2381 # CONFIG_BFS_FS is not set
2382 # CONFIG_EXT3_FS is not set
2383 # CONFIG_JBD is not set
2384 @@ -605,6 +649,9 @@
2385 # CONFIG_ISO9660_FS is not set
2386 # CONFIG_JOLIET is not set
2387 # CONFIG_ZISOFS is not set
2388 +# CONFIG_JFS_FS is not set
2389 +# CONFIG_JFS_DEBUG is not set
2390 +# CONFIG_JFS_STATISTICS is not set
2391 # CONFIG_MINIX_FS is not set
2392 # CONFIG_VXFS_FS is not set
2393 # CONFIG_NTFS_FS is not set
2394 @@ -624,6 +671,11 @@
2395 # CONFIG_UDF_RW is not set
2396 # CONFIG_UFS_FS is not set
2397 # CONFIG_UFS_FS_WRITE is not set
2398 +# CONFIG_XFS_FS is not set
2399 +# CONFIG_XFS_QUOTA is not set
2400 +# CONFIG_XFS_RT is not set
2401 +# CONFIG_XFS_TRACE is not set
2402 +# CONFIG_XFS_DEBUG is not set
2405 # Network File Systems
2406 @@ -632,9 +684,11 @@
2407 # CONFIG_INTERMEZZO_FS is not set
2408 # CONFIG_NFS_FS is not set
2409 # CONFIG_NFS_V3 is not set
2410 +# CONFIG_NFS_DIRECTIO is not set
2411 # CONFIG_ROOT_NFS is not set
2412 # CONFIG_NFSD is not set
2413 # CONFIG_NFSD_V3 is not set
2414 +# CONFIG_NFSD_TCP is not set
2415 # CONFIG_SUNRPC is not set
2416 # CONFIG_LOCKD is not set
2417 # CONFIG_SMB_FS is not set
2418 @@ -648,7 +702,6 @@
2419 # CONFIG_NCPFS_NLS is not set
2420 # CONFIG_NCPFS_EXTRAS is not set
2421 # CONFIG_ZISOFS_FS is not set
2422 -# CONFIG_ZLIB_FS_INFLATE is not set
2425 # Partition Types
2426 @@ -674,16 +727,18 @@
2427 # CONFIG_USB_DEBUG is not set
2428 # CONFIG_USB_DEVICEFS is not set
2429 # CONFIG_USB_BANDWIDTH is not set
2430 -# CONFIG_USB_LONG_TIMEOUT is not set
2431 # CONFIG_USB_EHCI_HCD is not set
2432 # CONFIG_USB_UHCI is not set
2433 # CONFIG_USB_UHCI_ALT is not set
2434 # CONFIG_USB_OHCI is not set
2435 # CONFIG_USB_OHCI_SA1111 is not set
2436 +# CONFIG_USB_SL811HS_ALT is not set
2437 +# CONFIG_USB_SL811HS is not set
2438 CONFIG_USB_OHCI_AT91=y
2439 # CONFIG_USB_AUDIO is not set
2440 # CONFIG_USB_EMI26 is not set
2441 # CONFIG_USB_BLUETOOTH is not set
2442 +# CONFIG_USB_MIDI is not set
2443 # CONFIG_USB_STORAGE is not set
2444 # CONFIG_USB_STORAGE_DEBUG is not set
2445 # CONFIG_USB_STORAGE_DATAFAB is not set
2446 @@ -692,6 +747,7 @@
2447 # CONFIG_USB_STORAGE_DPCM is not set
2448 # CONFIG_USB_STORAGE_HP8200e is not set
2449 # CONFIG_USB_STORAGE_SDDR09 is not set
2450 +# CONFIG_USB_STORAGE_SDDR55 is not set
2451 # CONFIG_USB_STORAGE_JUMPSHOT is not set
2452 # CONFIG_USB_ACM is not set
2453 # CONFIG_USB_PRINTER is not set
2454 @@ -700,7 +756,10 @@
2455 # CONFIG_USB_HIDDEV is not set
2456 # CONFIG_USB_KBD is not set
2457 # CONFIG_USB_MOUSE is not set
2458 +# CONFIG_USB_AIPTEK is not set
2459 # CONFIG_USB_WACOM is not set
2460 +# CONFIG_USB_KBTAB is not set
2461 +# CONFIG_USB_POWERMATE is not set
2462 # CONFIG_USB_DC2XX is not set
2463 # CONFIG_USB_MDC800 is not set
2464 # CONFIG_USB_SCANNER is not set
2465 @@ -718,35 +777,16 @@
2466 # USB Serial Converter support
2468 # CONFIG_USB_SERIAL is not set
2469 -# CONFIG_USB_SERIAL_GENERIC is not set
2470 -# CONFIG_USB_SERIAL_BELKIN is not set
2471 -# CONFIG_USB_SERIAL_WHITEHEAT is not set
2472 -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
2473 -# CONFIG_USB_SERIAL_EMPEG is not set
2474 -# CONFIG_USB_SERIAL_FTDI_SIO is not set
2475 -# CONFIG_USB_SERIAL_VISOR is not set
2476 -# CONFIG_USB_SERIAL_IPAQ is not set
2477 -# CONFIG_USB_SERIAL_IR is not set
2478 -# CONFIG_USB_SERIAL_EDGEPORT is not set
2479 -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
2480 -# CONFIG_USB_SERIAL_KEYSPAN is not set
2481 -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
2482 -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
2483 -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
2484 -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
2485 -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
2486 -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
2487 -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
2488 -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
2489 -# CONFIG_USB_SERIAL_MCT_U232 is not set
2490 -# CONFIG_USB_SERIAL_KLSI is not set
2491 -# CONFIG_USB_SERIAL_PL2303 is not set
2492 -# CONFIG_USB_SERIAL_CYBERJACK is not set
2493 -# CONFIG_USB_SERIAL_XIRCOM is not set
2494 -# CONFIG_USB_SERIAL_OMNINET is not set
2495 # CONFIG_USB_RIO500 is not set
2496 # CONFIG_USB_AUERSWALD is not set
2497 +# CONFIG_USB_TIGL is not set
2498 # CONFIG_USB_BRLVGER is not set
2499 +# CONFIG_USB_LCD is not set
2502 +# Support for USB gadgets
2504 +# CONFIG_USB_GADGET is not set
2507 # Bluetooth support
2508 @@ -770,3 +810,10 @@
2509 CONFIG_DEBUG_LL=y
2510 # CONFIG_DEBUG_DC21285_PORT is not set
2511 # CONFIG_DEBUG_CLPS711X_UART2 is not set
2514 +# Library routines
2516 +CONFIG_CRC32=y
2517 +# CONFIG_ZLIB_INFLATE is not set
2518 +# CONFIG_ZLIB_DEFLATE is not set
2519 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
2520 +++ linux-2.4.25/arch/arm/def-configs/csb337 2004-03-31 17:15:08.000000000 +0200
2521 @@ -0,0 +1,760 @@
2523 +# Automatically generated by make menuconfig: don't edit
2525 +CONFIG_ARM=y
2526 +# CONFIG_EISA is not set
2527 +# CONFIG_SBUS is not set
2528 +# CONFIG_MCA is not set
2529 +CONFIG_UID16=y
2530 +CONFIG_RWSEM_GENERIC_SPINLOCK=y
2531 +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
2532 +# CONFIG_GENERIC_BUST_SPINLOCK is not set
2533 +# CONFIG_GENERIC_ISA_DMA is not set
2536 +# Code maturity level options
2538 +CONFIG_EXPERIMENTAL=y
2539 +# CONFIG_OBSOLETE is not set
2542 +# Loadable module support
2544 +CONFIG_MODULES=y
2545 +# CONFIG_MODVERSIONS is not set
2546 +CONFIG_KMOD=y
2549 +# System Type
2551 +# CONFIG_ARCH_ANAKIN is not set
2552 +# CONFIG_ARCH_ARCA5K is not set
2553 +# CONFIG_ARCH_CLPS7500 is not set
2554 +# CONFIG_ARCH_CLPS711X is not set
2555 +# CONFIG_ARCH_CO285 is not set
2556 +# CONFIG_ARCH_EBSA110 is not set
2557 +# CONFIG_ARCH_CAMELOT is not set
2558 +# CONFIG_ARCH_FOOTBRIDGE is not set
2559 +# CONFIG_ARCH_INTEGRATOR is not set
2560 +# CONFIG_ARCH_OMAHA is not set
2561 +# CONFIG_ARCH_L7200 is not set
2562 +# CONFIG_ARCH_MX1ADS is not set
2563 +# CONFIG_ARCH_RPC is not set
2564 +# CONFIG_ARCH_RISCSTATION is not set
2565 +# CONFIG_ARCH_SA1100 is not set
2566 +# CONFIG_ARCH_SHARK is not set
2567 +CONFIG_ARCH_AT91RM9200=y
2570 +# Archimedes/A5000 Implementations
2572 +# CONFIG_ARCH_ARC is not set
2573 +# CONFIG_ARCH_A5K is not set
2576 +# Footbridge Implementations
2578 +# CONFIG_ARCH_CATS is not set
2579 +# CONFIG_ARCH_PERSONAL_SERVER is not set
2580 +# CONFIG_ARCH_EBSA285_ADDIN is not set
2581 +# CONFIG_ARCH_EBSA285_HOST is not set
2582 +# CONFIG_ARCH_NETWINDER is not set
2585 +# SA11x0 Implementations
2587 +# CONFIG_SA1100_ACCELENT is not set
2588 +# CONFIG_SA1100_ASSABET is not set
2589 +# CONFIG_ASSABET_NEPONSET is not set
2590 +# CONFIG_SA1100_ADSAGC is not set
2591 +# CONFIG_SA1100_ADSBITSY is not set
2592 +# CONFIG_SA1100_ADSBITSYPLUS is not set
2593 +# CONFIG_SA1100_BRUTUS is not set
2594 +# CONFIG_SA1100_CEP is not set
2595 +# CONFIG_SA1100_CERF is not set
2596 +# CONFIG_SA1100_H3100 is not set
2597 +# CONFIG_SA1100_H3600 is not set
2598 +# CONFIG_SA1100_H3800 is not set
2599 +# CONFIG_SA1100_H3XXX is not set
2600 +# CONFIG_H3600_SLEEVE is not set
2601 +# CONFIG_SA1100_EXTENEX1 is not set
2602 +# CONFIG_SA1100_FLEXANET is not set
2603 +# CONFIG_SA1100_FREEBIRD is not set
2604 +# CONFIG_SA1100_FRODO is not set
2605 +# CONFIG_SA1100_GRAPHICSCLIENT is not set
2606 +# CONFIG_SA1100_GRAPHICSMASTER is not set
2607 +# CONFIG_SA1100_HACKKIT is not set
2608 +# CONFIG_SA1100_BADGE4 is not set
2609 +# CONFIG_SA1100_JORNADA720 is not set
2610 +# CONFIG_SA1100_HUW_WEBPANEL is not set
2611 +# CONFIG_SA1100_ITSY is not set
2612 +# CONFIG_SA1100_LART is not set
2613 +# CONFIG_SA1100_NANOENGINE is not set
2614 +# CONFIG_SA1100_OMNIMETER is not set
2615 +# CONFIG_SA1100_PANGOLIN is not set
2616 +# CONFIG_SA1100_PLEB is not set
2617 +# CONFIG_SA1100_PT_SYSTEM3 is not set
2618 +# CONFIG_SA1100_SHANNON is not set
2619 +# CONFIG_SA1100_SHERMAN is not set
2620 +# CONFIG_SA1100_SIMPAD is not set
2621 +# CONFIG_SA1100_SIMPUTER is not set
2622 +# CONFIG_SA1100_PFS168 is not set
2623 +# CONFIG_SA1100_VICTOR is not set
2624 +# CONFIG_SA1100_XP860 is not set
2625 +# CONFIG_SA1100_YOPY is not set
2626 +# CONFIG_SA1100_USB is not set
2627 +# CONFIG_SA1100_USB_NETLINK is not set
2628 +# CONFIG_SA1100_USB_CHAR is not set
2629 +# CONFIG_SA1100_SSP is not set
2632 +# AT91RM9200 Implementations
2634 +# CONFIG_ARCH_AT91RM9200DK is not set
2635 +CONFIG_MACH_CSB337=y
2638 +# CLPS711X/EP721X Implementations
2640 +# CONFIG_ARCH_AUTCPU12 is not set
2641 +# CONFIG_ARCH_CDB89712 is not set
2642 +# CONFIG_ARCH_CLEP7312 is not set
2643 +# CONFIG_ARCH_EDB7211 is not set
2644 +# CONFIG_ARCH_FORTUNET is not set
2645 +# CONFIG_ARCH_GUIDEA07 is not set
2646 +# CONFIG_ARCH_P720T is not set
2647 +# CONFIG_ARCH_EP7211 is not set
2648 +# CONFIG_ARCH_EP7212 is not set
2649 +# CONFIG_ARCH_ACORN is not set
2650 +# CONFIG_PLD is not set
2651 +# CONFIG_FOOTBRIDGE is not set
2652 +# CONFIG_FOOTBRIDGE_HOST is not set
2653 +# CONFIG_FOOTBRIDGE_ADDIN is not set
2654 +CONFIG_CPU_32=y
2655 +# CONFIG_CPU_26 is not set
2656 +# CONFIG_CPU_ARM610 is not set
2657 +# CONFIG_CPU_ARM710 is not set
2658 +# CONFIG_CPU_ARM720T is not set
2659 +CONFIG_CPU_ARM920T=y
2660 +# CONFIG_CPU_ARM922T is not set
2661 +# CONFIG_CPU_ARM926T is not set
2662 +# CONFIG_CPU_ARM1020 is not set
2663 +# CONFIG_CPU_ARM1020E is not set
2664 +# CONFIG_CPU_ARM1022 is not set
2665 +# CONFIG_CPU_ARM1026 is not set
2666 +# CONFIG_CPU_SA110 is not set
2667 +# CONFIG_CPU_SA1100 is not set
2668 +# CONFIG_CPU_32v3 is not set
2669 +CONFIG_CPU_32v4=y
2670 +# CONFIG_ARM_THUMB is not set
2671 +# CONFIG_CPU_ICACHE_DISABLE is not set
2672 +# CONFIG_CPU_DCACHE_DISABLE is not set
2673 +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
2674 +# CONFIG_DISCONTIGMEM is not set
2677 +# General setup
2679 +# CONFIG_PCI is not set
2680 +# CONFIG_ISA is not set
2681 +# CONFIG_ISA_DMA is not set
2682 +# CONFIG_ZBOOT_ROM is not set
2683 +CONFIG_ZBOOT_ROM_TEXT=0
2684 +CONFIG_ZBOOT_ROM_BSS=0
2685 +# CONFIG_HOTPLUG is not set
2686 +# CONFIG_PCMCIA is not set
2687 +CONFIG_NET=y
2688 +CONFIG_SYSVIPC=y
2689 +# CONFIG_BSD_PROCESS_ACCT is not set
2690 +CONFIG_SYSCTL=y
2691 +CONFIG_FPE_NWFPE=y
2692 +# CONFIG_FPE_NWFPE_XP is not set
2693 +# CONFIG_FPE_FASTFPE is not set
2694 +CONFIG_KCORE_ELF=y
2695 +# CONFIG_KCORE_AOUT is not set
2696 +# CONFIG_BINFMT_AOUT is not set
2697 +CONFIG_BINFMT_ELF=y
2698 +# CONFIG_BINFMT_MISC is not set
2699 +# CONFIG_PM is not set
2700 +# CONFIG_ARTHUR is not set
2701 +CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20210000,3145728 root=/dev/ram rw"
2702 +# CONFIG_LEDS is not set
2703 +CONFIG_ALIGNMENT_TRAP=y
2706 +# Parallel port support
2708 +# CONFIG_PARPORT is not set
2711 +# Memory Technology Devices (MTD)
2713 +CONFIG_MTD=y
2714 +# CONFIG_MTD_DEBUG is not set
2715 +# CONFIG_MTD_PARTITIONS is not set
2716 +# CONFIG_MTD_CONCAT is not set
2717 +# CONFIG_MTD_REDBOOT_PARTS is not set
2718 +# CONFIG_MTD_CMDLINE_PARTS is not set
2719 +# CONFIG_MTD_AFS_PARTS is not set
2720 +CONFIG_MTD_CHAR=y
2721 +CONFIG_MTD_BLOCK=y
2722 +# CONFIG_FTL is not set
2723 +# CONFIG_NFTL is not set
2726 +# RAM/ROM/Flash chip drivers
2728 +CONFIG_MTD_CFI=y
2729 +CONFIG_MTD_JEDECPROBE=y
2730 +CONFIG_MTD_GEN_PROBE=y
2731 +# CONFIG_MTD_CFI_ADV_OPTIONS is not set
2732 +CONFIG_MTD_CFI_INTELEXT=y
2733 +# CONFIG_MTD_CFI_AMDSTD is not set
2734 +# CONFIG_MTD_CFI_STAA is not set
2735 +# CONFIG_MTD_RAM is not set
2736 +CONFIG_MTD_ROM=y
2737 +# CONFIG_MTD_ABSENT is not set
2738 +# CONFIG_MTD_OBSOLETE_CHIPS is not set
2739 +# CONFIG_MTD_AMDSTD is not set
2740 +# CONFIG_MTD_SHARP is not set
2741 +# CONFIG_MTD_JEDEC is not set
2744 +# Mapping drivers for chip access
2746 +CONFIG_MTD_PHYSMAP=y
2747 +CONFIG_MTD_PHYSMAP_START=10000000
2748 +CONFIG_MTD_PHYSMAP_LEN=200000
2749 +CONFIG_MTD_PHYSMAP_BUSWIDTH=2
2750 +# CONFIG_MTD_NORA is not set
2751 +# CONFIG_MTD_ARM_INTEGRATOR is not set
2752 +# CONFIG_MTD_CDB89712 is not set
2753 +# CONFIG_MTD_SA1100 is not set
2754 +# CONFIG_MTD_DC21285 is not set
2755 +# CONFIG_MTD_IQ80310 is not set
2756 +# CONFIG_MTD_FORTUNET is not set
2757 +# CONFIG_MTD_EPXA is not set
2758 +# CONFIG_MTD_AUTCPU12 is not set
2759 +# CONFIG_MTD_EDB7312 is not set
2760 +# CONFIG_MTD_IMPA7 is not set
2761 +# CONFIG_MTD_CEIVA is not set
2762 +# CONFIG_MTD_PCI is not set
2763 +# CONFIG_MTD_PCMCIA is not set
2766 +# Self-contained MTD device drivers
2768 +# CONFIG_MTD_PMC551 is not set
2769 +# CONFIG_MTD_SLRAM is not set
2770 +CONFIG_MTD_AT91_DATAFLASH=y
2771 +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
2772 +# CONFIG_MTD_MTDRAM is not set
2773 +# CONFIG_MTD_BLKMTD is not set
2774 +# CONFIG_MTD_DOC1000 is not set
2775 +# CONFIG_MTD_DOC2000 is not set
2776 +# CONFIG_MTD_DOC2001 is not set
2777 +# CONFIG_MTD_DOCPROBE is not set
2780 +# NAND Flash Device Drivers
2782 +CONFIG_MTD_NAND=y
2783 +# CONFIG_MTD_NAND_VERIFY_WRITE is not set
2784 +CONFIG_MTD_NAND_IDS=y
2785 +# CONFIG_MTD_AT91_SMARTMEDIA is not set
2788 +# Plug and Play configuration
2790 +# CONFIG_PNP is not set
2791 +# CONFIG_ISAPNP is not set
2794 +# Block devices
2796 +# CONFIG_BLK_DEV_FD is not set
2797 +# CONFIG_BLK_DEV_XD is not set
2798 +# CONFIG_PARIDE is not set
2799 +# CONFIG_BLK_CPQ_DA is not set
2800 +# CONFIG_BLK_CPQ_CISS_DA is not set
2801 +# CONFIG_CISS_SCSI_TAPE is not set
2802 +# CONFIG_CISS_MONITOR_THREAD is not set
2803 +# CONFIG_BLK_DEV_DAC960 is not set
2804 +# CONFIG_BLK_DEV_UMEM is not set
2805 +# CONFIG_BLK_DEV_LOOP is not set
2806 +# CONFIG_BLK_DEV_NBD is not set
2807 +CONFIG_BLK_DEV_RAM=y
2808 +CONFIG_BLK_DEV_RAM_SIZE=8192
2809 +# CONFIG_BLK_DEV_INITRD is not set
2810 +# CONFIG_BLK_STATS is not set
2813 +# Multi-device support (RAID and LVM)
2815 +# CONFIG_MD is not set
2816 +# CONFIG_BLK_DEV_MD is not set
2817 +# CONFIG_MD_LINEAR is not set
2818 +# CONFIG_MD_RAID0 is not set
2819 +# CONFIG_MD_RAID1 is not set
2820 +# CONFIG_MD_RAID5 is not set
2821 +# CONFIG_MD_MULTIPATH is not set
2822 +# CONFIG_BLK_DEV_LVM is not set
2825 +# Networking options
2827 +CONFIG_PACKET=y
2828 +# CONFIG_PACKET_MMAP is not set
2829 +# CONFIG_NETLINK_DEV is not set
2830 +# CONFIG_NETFILTER is not set
2831 +# CONFIG_FILTER is not set
2832 +CONFIG_UNIX=y
2833 +CONFIG_INET=y
2834 +# CONFIG_IP_MULTICAST is not set
2835 +# CONFIG_IP_ADVANCED_ROUTER is not set
2836 +CONFIG_IP_PNP=y
2837 +CONFIG_IP_PNP_DHCP=y
2838 +CONFIG_IP_PNP_BOOTP=y
2839 +# CONFIG_IP_PNP_RARP is not set
2840 +# CONFIG_NET_IPIP is not set
2841 +# CONFIG_NET_IPGRE is not set
2842 +# CONFIG_ARPD is not set
2843 +# CONFIG_INET_ECN is not set
2844 +# CONFIG_SYN_COOKIES is not set
2845 +# CONFIG_IPV6 is not set
2846 +# CONFIG_KHTTPD is not set
2849 +# SCTP Configuration (EXPERIMENTAL)
2851 +CONFIG_IPV6_SCTP__=y
2852 +# CONFIG_IP_SCTP is not set
2853 +# CONFIG_ATM is not set
2854 +# CONFIG_VLAN_8021Q is not set
2855 +# CONFIG_IPX is not set
2856 +# CONFIG_ATALK is not set
2859 +# Appletalk devices
2861 +# CONFIG_DEV_APPLETALK is not set
2862 +# CONFIG_DECNET is not set
2863 +# CONFIG_BRIDGE is not set
2864 +# CONFIG_X25 is not set
2865 +# CONFIG_LAPB is not set
2866 +# CONFIG_LLC is not set
2867 +# CONFIG_NET_DIVERT is not set
2868 +# CONFIG_ECONET is not set
2869 +# CONFIG_WAN_ROUTER is not set
2870 +# CONFIG_NET_FASTROUTE is not set
2871 +# CONFIG_NET_HW_FLOWCONTROL is not set
2874 +# QoS and/or fair queueing
2876 +# CONFIG_NET_SCHED is not set
2879 +# Network testing
2881 +# CONFIG_NET_PKTGEN is not set
2884 +# Network device support
2886 +CONFIG_NETDEVICES=y
2889 +# ARCnet devices
2891 +# CONFIG_ARCNET is not set
2892 +# CONFIG_DUMMY is not set
2893 +# CONFIG_BONDING is not set
2894 +# CONFIG_EQUALIZER is not set
2895 +# CONFIG_TUN is not set
2896 +# CONFIG_ETHERTAP is not set
2899 +# Ethernet (10 or 100Mbit)
2901 +CONFIG_NET_ETHERNET=y
2902 +# CONFIG_ARM_AM79C961A is not set
2903 +# CONFIG_ARM_CIRRUS is not set
2904 +CONFIG_AT91_ETHER=y
2905 +# CONFIG_AT91_ETHER_RMII is not set
2906 +# CONFIG_SUNLANCE is not set
2907 +# CONFIG_SUNBMAC is not set
2908 +# CONFIG_SUNQE is not set
2909 +# CONFIG_SUNGEM is not set
2910 +# CONFIG_NET_VENDOR_3COM is not set
2911 +# CONFIG_LANCE is not set
2912 +# CONFIG_NET_VENDOR_SMC is not set
2913 +# CONFIG_NET_VENDOR_RACAL is not set
2914 +# CONFIG_NET_ISA is not set
2915 +# CONFIG_NET_PCI is not set
2916 +# CONFIG_NET_POCKET is not set
2919 +# Ethernet (1000 Mbit)
2921 +# CONFIG_ACENIC is not set
2922 +# CONFIG_DL2K is not set
2923 +# CONFIG_E1000 is not set
2924 +# CONFIG_MYRI_SBUS is not set
2925 +# CONFIG_NS83820 is not set
2926 +# CONFIG_HAMACHI is not set
2927 +# CONFIG_YELLOWFIN is not set
2928 +# CONFIG_R8169 is not set
2929 +# CONFIG_SK98LIN is not set
2930 +# CONFIG_TIGON3 is not set
2931 +# CONFIG_FDDI is not set
2932 +# CONFIG_HIPPI is not set
2933 +# CONFIG_PLIP is not set
2934 +# CONFIG_PPP is not set
2935 +# CONFIG_SLIP is not set
2938 +# Wireless LAN (non-hamradio)
2940 +# CONFIG_NET_RADIO is not set
2943 +# Token Ring devices
2945 +# CONFIG_TR is not set
2946 +# CONFIG_NET_FC is not set
2947 +# CONFIG_RCPCI is not set
2948 +# CONFIG_SHAPER is not set
2951 +# Wan interfaces
2953 +# CONFIG_WAN is not set
2956 +# Amateur Radio support
2958 +# CONFIG_HAMRADIO is not set
2961 +# IrDA (infrared) support
2963 +# CONFIG_IRDA is not set
2966 +# ATA/ATAPI/MFM/RLL support
2968 +# CONFIG_IDE is not set
2969 +# CONFIG_BLK_DEV_HD is not set
2972 +# SCSI support
2974 +# CONFIG_SCSI is not set
2977 +# I2O device support
2979 +# CONFIG_I2O is not set
2980 +# CONFIG_I2O_BLOCK is not set
2981 +# CONFIG_I2O_LAN is not set
2982 +# CONFIG_I2O_SCSI is not set
2983 +# CONFIG_I2O_PROC is not set
2986 +# ISDN subsystem
2988 +# CONFIG_ISDN is not set
2991 +# Input core support
2993 +# CONFIG_INPUT is not set
2994 +# CONFIG_INPUT_KEYBDEV is not set
2995 +# CONFIG_INPUT_MOUSEDEV is not set
2996 +# CONFIG_INPUT_JOYDEV is not set
2997 +# CONFIG_INPUT_EVDEV is not set
2998 +# CONFIG_INPUT_UINPUT is not set
2999 +# CONFIG_INPUT_MX1TS is not set
3002 +# Character devices
3004 +# CONFIG_VT is not set
3005 +# CONFIG_SERIAL is not set
3006 +# CONFIG_SERIAL_EXTENDED is not set
3007 +# CONFIG_SERIAL_NONSTANDARD is not set
3008 +CONFIG_AT91_SPIDEV=y
3011 +# Serial drivers
3013 +# CONFIG_SERIAL_ANAKIN is not set
3014 +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
3015 +# CONFIG_SERIAL_AMBA is not set
3016 +# CONFIG_SERIAL_AMBA_CONSOLE is not set
3017 +# CONFIG_SERIAL_CLPS711X is not set
3018 +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
3019 +# CONFIG_SERIAL_21285 is not set
3020 +# CONFIG_SERIAL_21285_OLD is not set
3021 +# CONFIG_SERIAL_21285_CONSOLE is not set
3022 +# CONFIG_SERIAL_UART00 is not set
3023 +# CONFIG_SERIAL_UART00_CONSOLE is not set
3024 +# CONFIG_SERIAL_SA1100 is not set
3025 +# CONFIG_SERIAL_SA1100_CONSOLE is not set
3026 +# CONFIG_SERIAL_OMAHA is not set
3027 +# CONFIG_SERIAL_OMAHA_CONSOLE is not set
3028 +CONFIG_SERIAL_AT91=y
3029 +CONFIG_SERIAL_AT91_CONSOLE=y
3030 +# CONFIG_SERIAL_8250 is not set
3031 +# CONFIG_SERIAL_8250_CONSOLE is not set
3032 +# CONFIG_SERIAL_8250_EXTENDED is not set
3033 +# CONFIG_SERIAL_8250_MANY_PORTS is not set
3034 +# CONFIG_SERIAL_8250_SHARE_IRQ is not set
3035 +# CONFIG_SERIAL_8250_DETECT_IRQ is not set
3036 +# CONFIG_SERIAL_8250_MULTIPORT is not set
3037 +# CONFIG_SERIAL_8250_HUB6 is not set
3038 +CONFIG_SERIAL_CORE=y
3039 +CONFIG_SERIAL_CORE_CONSOLE=y
3040 +# CONFIG_UNIX98_PTYS is not set
3043 +# I2C support
3045 +CONFIG_I2C=y
3046 +# CONFIG_I2C_ALGOBIT is not set
3047 +# CONFIG_SCx200_ACB is not set
3048 +# CONFIG_I2C_ALGOPCF is not set
3049 +CONFIG_I2C_AT91=y
3050 +CONFIG_I2C_CHARDEV=y
3051 +CONFIG_I2C_PROC=y
3052 +CONFIG_I2C_DS1307=y
3055 +# L3 serial bus support
3057 +# CONFIG_L3 is not set
3058 +# CONFIG_L3_ALGOBIT is not set
3059 +# CONFIG_L3_BIT_SA1100_GPIO is not set
3060 +# CONFIG_L3_SA1111 is not set
3061 +# CONFIG_BIT_SA1100_GPIO is not set
3064 +# Mice
3066 +# CONFIG_BUSMOUSE is not set
3067 +# CONFIG_MOUSE is not set
3070 +# Joysticks
3072 +# CONFIG_INPUT_GAMEPORT is not set
3073 +# CONFIG_QIC02_TAPE is not set
3074 +# CONFIG_IPMI_HANDLER is not set
3075 +# CONFIG_IPMI_PANIC_EVENT is not set
3076 +# CONFIG_IPMI_DEVICE_INTERFACE is not set
3077 +# CONFIG_IPMI_KCS is not set
3078 +# CONFIG_IPMI_WATCHDOG is not set
3081 +# Watchdog Cards
3083 +CONFIG_WATCHDOG=y
3084 +CONFIG_WATCHDOG_NOWAYOUT=y
3085 +# CONFIG_ACQUIRE_WDT is not set
3086 +# CONFIG_ADVANTECH_WDT is not set
3087 +# CONFIG_ALIM1535_WDT is not set
3088 +# CONFIG_ALIM7101_WDT is not set
3089 +# CONFIG_SC520_WDT is not set
3090 +# CONFIG_PCWATCHDOG is not set
3091 +# CONFIG_21285_WATCHDOG is not set
3092 +# CONFIG_977_WATCHDOG is not set
3093 +# CONFIG_SA1100_WATCHDOG is not set
3094 +# CONFIG_EPXA_WATCHDOG is not set
3095 +# CONFIG_OMAHA_WATCHDOG is not set
3096 +CONFIG_AT91_WATCHDOG=y
3097 +# CONFIG_EUROTECH_WDT is not set
3098 +# CONFIG_IB700_WDT is not set
3099 +# CONFIG_WAFER_WDT is not set
3100 +# CONFIG_I810_TCO is not set
3101 +# CONFIG_MIXCOMWD is not set
3102 +# CONFIG_60XX_WDT is not set
3103 +# CONFIG_SC1200_WDT is not set
3104 +# CONFIG_SCx200_WDT is not set
3105 +# CONFIG_SOFT_WATCHDOG is not set
3106 +# CONFIG_W83877F_WDT is not set
3107 +# CONFIG_WDT is not set
3108 +# CONFIG_WDTPCI is not set
3109 +# CONFIG_MACHZ_WDT is not set
3110 +# CONFIG_AMD7XX_TCO is not set
3111 +# CONFIG_SCx200 is not set
3112 +# CONFIG_SCx200_GPIO is not set
3113 +# CONFIG_AMD_PM768 is not set
3114 +# CONFIG_NVRAM is not set
3115 +# CONFIG_RTC is not set
3116 +CONFIG_AT91_RTC=y
3117 +# CONFIG_DTLK is not set
3118 +# CONFIG_R3964 is not set
3119 +# CONFIG_APPLICOM is not set
3122 +# Ftape, the floppy tape device driver
3124 +# CONFIG_FTAPE is not set
3125 +# CONFIG_AGP is not set
3128 +# Direct Rendering Manager (XFree86 DRI support)
3130 +# CONFIG_DRM is not set
3133 +# Multimedia devices
3135 +# CONFIG_VIDEO_DEV is not set
3138 +# File systems
3140 +# CONFIG_QUOTA is not set
3141 +# CONFIG_QFMT_V2 is not set
3142 +# CONFIG_AUTOFS_FS is not set
3143 +# CONFIG_AUTOFS4_FS is not set
3144 +# CONFIG_REISERFS_FS is not set
3145 +# CONFIG_REISERFS_CHECK is not set
3146 +# CONFIG_REISERFS_PROC_INFO is not set
3147 +# CONFIG_ADFS_FS is not set
3148 +# CONFIG_ADFS_FS_RW is not set
3149 +# CONFIG_AFFS_FS is not set
3150 +# CONFIG_HFS_FS is not set
3151 +# CONFIG_HFSPLUS_FS is not set
3152 +# CONFIG_BEFS_FS is not set
3153 +# CONFIG_BEFS_DEBUG is not set
3154 +# CONFIG_BFS_FS is not set
3155 +# CONFIG_EXT3_FS is not set
3156 +# CONFIG_JBD is not set
3157 +# CONFIG_JBD_DEBUG is not set
3158 +# CONFIG_FAT_FS is not set
3159 +# CONFIG_MSDOS_FS is not set
3160 +# CONFIG_UMSDOS_FS is not set
3161 +# CONFIG_VFAT_FS is not set
3162 +# CONFIG_EFS_FS is not set
3163 +# CONFIG_JFFS_FS is not set
3164 +# CONFIG_JFFS2_FS is not set
3165 +# CONFIG_CRAMFS is not set
3166 +# CONFIG_TMPFS is not set
3167 +CONFIG_RAMFS=y
3168 +# CONFIG_ISO9660_FS is not set
3169 +# CONFIG_JOLIET is not set
3170 +# CONFIG_ZISOFS is not set
3171 +# CONFIG_JFS_FS is not set
3172 +# CONFIG_JFS_DEBUG is not set
3173 +# CONFIG_JFS_STATISTICS is not set
3174 +# CONFIG_MINIX_FS is not set
3175 +# CONFIG_VXFS_FS is not set
3176 +# CONFIG_NTFS_FS is not set
3177 +# CONFIG_NTFS_RW is not set
3178 +# CONFIG_HPFS_FS is not set
3179 +CONFIG_PROC_FS=y
3180 +CONFIG_DEVFS_FS=y
3181 +CONFIG_DEVFS_MOUNT=y
3182 +# CONFIG_DEVFS_DEBUG is not set
3183 +# CONFIG_DEVPTS_FS is not set
3184 +# CONFIG_QNX4FS_FS is not set
3185 +# CONFIG_QNX4FS_RW is not set
3186 +# CONFIG_ROMFS_FS is not set
3187 +CONFIG_EXT2_FS=y
3188 +# CONFIG_SYSV_FS is not set
3189 +# CONFIG_UDF_FS is not set
3190 +# CONFIG_UDF_RW is not set
3191 +# CONFIG_UFS_FS is not set
3192 +# CONFIG_UFS_FS_WRITE is not set
3193 +# CONFIG_XFS_FS is not set
3194 +# CONFIG_XFS_QUOTA is not set
3195 +# CONFIG_XFS_RT is not set
3196 +# CONFIG_XFS_TRACE is not set
3197 +# CONFIG_XFS_DEBUG is not set
3200 +# Network File Systems
3202 +# CONFIG_CODA_FS is not set
3203 +# CONFIG_INTERMEZZO_FS is not set
3204 +CONFIG_NFS_FS=y
3205 +CONFIG_NFS_V3=y
3206 +# CONFIG_NFS_DIRECTIO is not set
3207 +CONFIG_ROOT_NFS=y
3208 +# CONFIG_NFSD is not set
3209 +# CONFIG_NFSD_V3 is not set
3210 +# CONFIG_NFSD_TCP is not set
3211 +CONFIG_SUNRPC=y
3212 +CONFIG_LOCKD=y
3213 +CONFIG_LOCKD_V4=y
3214 +# CONFIG_SMB_FS is not set
3215 +# CONFIG_NCP_FS is not set
3216 +# CONFIG_NCPFS_PACKET_SIGNING is not set
3217 +# CONFIG_NCPFS_IOCTL_LOCKING is not set
3218 +# CONFIG_NCPFS_STRONG is not set
3219 +# CONFIG_NCPFS_NFS_NS is not set
3220 +# CONFIG_NCPFS_OS2_NS is not set
3221 +# CONFIG_NCPFS_SMALLDOS is not set
3222 +# CONFIG_NCPFS_NLS is not set
3223 +# CONFIG_NCPFS_EXTRAS is not set
3224 +# CONFIG_ZISOFS_FS is not set
3227 +# Partition Types
3229 +# CONFIG_PARTITION_ADVANCED is not set
3230 +CONFIG_MSDOS_PARTITION=y
3231 +# CONFIG_SMB_NLS is not set
3232 +# CONFIG_NLS is not set
3235 +# Multimedia Capabilities Port drivers
3237 +# CONFIG_MCP is not set
3238 +# CONFIG_MCP_SA1100 is not set
3239 +# CONFIG_MCP_UCB1200 is not set
3240 +# CONFIG_MCP_UCB1200_AUDIO is not set
3241 +# CONFIG_MCP_UCB1200_TS is not set
3244 +# USB support
3246 +# CONFIG_USB is not set
3249 +# Support for USB gadgets
3251 +# CONFIG_USB_GADGET is not set
3254 +# Bluetooth support
3256 +# CONFIG_BLUEZ is not set
3259 +# Kernel hacking
3261 +CONFIG_FRAME_POINTER=y
3262 +CONFIG_DEBUG_USER=y
3263 +# CONFIG_DEBUG_INFO is not set
3264 +# CONFIG_NO_PGT_CACHE is not set
3265 +CONFIG_DEBUG_KERNEL=y
3266 +# CONFIG_DEBUG_SLAB is not set
3267 +# CONFIG_MAGIC_SYSRQ is not set
3268 +# CONFIG_DEBUG_SPINLOCK is not set
3269 +# CONFIG_DEBUG_WAITQ is not set
3270 +# CONFIG_DEBUG_BUGVERBOSE is not set
3271 +# CONFIG_DEBUG_ERRORS is not set
3272 +CONFIG_DEBUG_LL=y
3273 +# CONFIG_DEBUG_DC21285_PORT is not set
3274 +# CONFIG_DEBUG_CLPS711X_UART2 is not set
3277 +# Library routines
3279 +CONFIG_CRC32=y
3280 +# CONFIG_ZLIB_INFLATE is not set
3281 +# CONFIG_ZLIB_DEFLATE is not set
3282 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
3283 +++ linux-2.4.25/arch/arm/fastfpe/CPDO.S 2004-03-31 17:15:08.000000000 +0200
3284 @@ -0,0 +1,682 @@
3286 +The FP structure has 4 words reserved for each register, the first is used just
3287 +for the sign in bit 31, the second and third are for the mantissa (unsigned
3288 +integer, high 32 bit first) and the fourth is the exponent (signed integer).
3289 +The mantissa is always normalized.
3291 +If the exponent is 0x80000000, that is the most negative value, the number
3292 +represented is 0 and both mantissa words are also 0.
3294 +If the exponent is 0x7fffffff, that is the biggest positive value, the number
3295 +represented is infinity if the high 32 mantissa bit are also 0, otherwise it is
3296 +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
3298 +Decimal and packed decimal numbers are not supported yet.
3300 +The parameters to these functions are r0=destination pointer, r1 and r2
3301 +source pointers. r4 is the instruction. They may use r0-r8 and r14. They return
3302 +to fastfpe_next, except CPDO_rnf_core which expects the return address in r14.
3305 +/*---------------------------------------------------------------------------*/
3307 + .globl CPDO_adf
3308 +CPDO_adf:
3309 + ldmia r1,{r1,r3,r5,r7}
3310 + ldmia r2,{r2,r4,r6,r8}
3312 + cmp r7,#0x7fffffff
3313 + cmpne r8,#0x7fffffff
3314 + beq CPDO_adf_extra
3316 + cmp r1,r2
3317 + bne CPDO_suf_s
3319 +CPDO_adf_s:
3320 + subs r2,r7,r8
3321 + bge CPDO_adf_2nd
3323 + mov r7,r8
3324 + rsb r2,r2,#0
3325 + cmp r2,#32
3326 + ble CPDO_adf_1st2
3328 + sub r2,r2,#32
3329 + cmp r2,#32
3330 + movgt r2,#32
3331 + mov r5,r3,lsr r2
3332 + mov r3,#0
3333 + b CPDO_adf_add
3335 +CPDO_adf_1st2:
3336 + rsb r8,r2,#32
3337 + mov r5,r5,lsr r2
3338 + orr r5,r5,r3,lsl r8
3339 + mov r3,r3,lsr r2 @ 1. op normalized
3340 + b CPDO_adf_add
3342 +CPDO_adf_2nd:
3343 + cmp r2,#32
3344 + ble CPDO_adf_2nd2
3346 + sub r2,r2,#32
3347 + cmp r2,#32
3348 + movgt r2,#32
3349 + mov r6,r4,lsr r2
3350 + mov r4,#0
3351 + b CPDO_adf_add
3353 +CPDO_adf_2nd2:
3354 + rsb r8,r2,#32
3355 + mov r6,r6,lsr r2
3356 + orr r6,r6,r4,lsl r8
3357 + mov r4,r4,lsr r2 @ 2. op normalized
3359 +CPDO_adf_add:
3360 + adds r5,r5,r6
3361 + adcs r3,r3,r4 @ do addition
3362 + bcc CPDO_adf_end
3364 + add r7,r7,#1
3365 + movs r3,r3,rrx
3366 + mov r5,r5,rrx @ correct for overflow
3368 +CPDO_adf_end:
3369 + cmp r7,#0x20000000
3370 + bge CPDO_inf
3372 + stmia r0,{r1,r3,r5,r7}
3373 + b fastfpe_next
3375 +CPDO_adf_extra:
3376 + cmp r7,#0x7fffffff @ was it the 1st ?
3377 + bne CPDO_infnan_2 @ no it was the 2nd
3378 + cmp r8,#0x7fffffff @ if 1st, 2nd too ?
3379 + bne CPDO_infnan_1 @ no only 1st
3380 + cmp r3,#0
3381 + cmpeq r4,#0
3382 + bne CPDO_nan_12
3383 + b CPDO_inf
3385 +/*---------------------------------------------------------------------------*/
3387 +CPDO_infnan_1:
3388 + stmia r0,{r1,r3,r5,r7}
3389 + b fastfpe_next
3391 +CPDO_infnan_2:
3392 + stmia r0,{r2,r4,r6,r8}
3393 + b fastfpe_next
3395 +CPDO_nan_12:
3396 + orr r2,r3,r4
3397 + b CPDO_inf_1
3399 +CPDO_nan:
3400 + mov r2,#0x40000000 @ create non signalling NaN
3401 + b CPDO_inf_1
3403 +CPDO_inf:
3404 + mov r2,#0
3405 +CPDO_inf_1:
3406 + mov r3,#0
3407 + mov r4,#0x7fffffff
3408 +CPDO_store_1234:
3409 + stmia r0,{r1,r2,r3,r4}
3410 + b fastfpe_next
3412 +CPDO_zero:
3413 + mov r1,#0
3414 +CPDO_zero_1:
3415 + mov r2,#0
3416 + mov r3,#0
3417 + mov r4,#0x80000000
3418 + stmia r0,{r1,r2,r3,r4}
3419 + b fastfpe_next
3421 +/*---------------------------------------------------------------------------*/
3423 + .globl CPDO_suf
3424 +CPDO_suf:
3425 + ldmia r1,{r1,r3,r5,r7}
3426 + ldmia r2,{r2,r4,r6,r8}
3428 +CPDO_suf_l:
3429 + cmp r7,#0x7fffffff
3430 + cmpne r8,#0x7fffffff
3431 + beq CPDO_suf_extra
3433 + cmp r1,r2
3434 + bne CPDO_adf_s
3436 +CPDO_suf_s:
3437 + subs r2,r7,r8 @ determine greater number
3438 + bgt CPDO_suf_2nd @ first number is greater
3439 + blt CPDO_suf_1st @ second number is greater
3440 + cmp r3,r4 @ also mantissa is important
3441 + cmpeq r5,r6
3442 + bhi CPDO_suf_2nd @ first number is greater
3443 + beq CPDO_zero
3445 +CPDO_suf_1st:
3446 + eor r1,r1,#0x80000000 @ second number is greater, invert sign
3447 + mov r7,r8
3448 + rsb r2,r2,#0
3449 + cmp r2,#32
3450 + ble CPDO_suf_1st2
3452 + sub r2,r2,#32
3453 + cmp r2,#32
3454 + movgt r2,#32
3455 + mov r5,r3,lsr r2
3456 + mov r3,#0
3457 + b CPDO_suf_1st_sub
3459 +CPDO_suf_1st2:
3460 + rsb r8,r2,#32
3461 + mov r5,r5,lsr r2
3462 + orr r5,r5,r3,lsl r8
3463 + mov r3,r3,lsr r2 @ 1. op normalized
3465 +CPDO_suf_1st_sub:
3466 + subs r5,r6,r5 @ do subtraction
3467 + sbc r3,r4,r3
3468 + b CPDO_suf_norm
3470 +CPDO_suf_2nd:
3471 + cmp r2,#32
3472 + ble CPDO_suf_2nd2
3474 + sub r2,r2,#32
3475 + cmp r2,#32
3476 + movgt r2,#32
3477 + mov r6,r4,lsr r2
3478 + mov r4,#0
3479 + b CPDO_suf_2nd_sub
3481 +CPDO_suf_2nd2:
3482 + rsb r8,r2,#32
3483 + mov r6,r6,lsr r2
3484 + orr r6,r6,r4,lsl r8
3485 + mov r4,r4,lsr r2 @ 2. op normalized
3487 +CPDO_suf_2nd_sub:
3488 + subs r5,r5,r6
3489 + sbc r3,r3,r4 @ do subtraction
3491 +CPDO_suf_norm:
3492 + teq r3,#0 @ normalize 32bit
3493 + moveq r3,r5
3494 + moveq r5,#0
3495 + subeq r7,r7,#32
3497 + cmp r3,#0x00010000 @ 16bit
3498 + movcc r3,r3,lsl#16
3499 + orrcc r3,r3,r5,lsr#16
3500 + movcc r5,r5,lsl#16
3501 + subcc r7,r7,#16
3503 + cmp r3,#0x01000000 @ 8bit
3504 + movcc r3,r3,lsl#8
3505 + orrcc r3,r3,r5,lsr#24
3506 + movcc r5,r5,lsl#8
3507 + subcc r7,r7,#8
3509 + cmp r3,#0x10000000 @ 4bit
3510 + movcc r3,r3,lsl#4
3511 + orrcc r3,r3,r5,lsr#28
3512 + movcc r5,r5,lsl#4
3513 + subcc r7,r7,#4
3515 + cmp r3,#0x40000000 @ 2bit
3516 + movcc r3,r3,lsl#2
3517 + orrcc r3,r3,r5,lsr#30
3518 + movcc r5,r5,lsl#2
3519 + subcc r7,r7,#2
3521 + cmp r3,#0x80000000 @ 1bit
3522 + movcc r3,r3,lsl#1
3523 + orrcc r3,r3,r5,lsr#31
3524 + movcc r5,r5,lsl#1
3525 + subcc r7,r7,#1
3527 + cmp r7,#0xe0000000
3528 + ble CPDO_zero_1
3530 + stmia r0,{r1,r3,r5,r7}
3531 + b fastfpe_next
3533 +CPDO_suf_extra:
3534 + cmp r7,#0x7fffffff @ was it the 1st ?
3535 + eorne r2,r2,#0x80000000 @ change sign, might have been INF
3536 + bne CPDO_infnan_2 @ no it was the 2nd
3537 + cmp r8,#0x7fffffff @ if 1st, 2nd too ?
3538 + bne CPDO_infnan_1 @ no only 1st
3539 + cmp r3,#0
3540 + cmpeq r4,#0
3541 + bne CPDO_nan_12
3542 + b CPDO_nan @ here is difference with adf !
3544 +/*---------------------------------------------------------------------------*/
3546 + .globl CPDO_rsf
3547 +CPDO_rsf:
3548 + mov r3,r2
3549 + ldmia r1,{r2,r4,r6,r8}
3550 + ldmia r3,{r1,r3,r5,r7}
3551 + b CPDO_suf_l
3553 +/*---------------------------------------------------------------------------*/
3555 + .globl CPDO_muf
3556 +CPDO_muf:
3557 + ldmia r1,{r1,r3,r5,r7}
3558 + ldmia r2,{r2,r4,r6,r8}
3560 + cmp r7,#0x7fffffff
3561 + cmpne r8,#0x7fffffff
3562 + beq CPDO_muf_extra
3564 + eor r1,r1,r2
3565 + adds r8,r7,r8
3566 + bvs CPDO_zero_1
3568 + umull r7,r2,r3,r4
3569 + umull r14,r3,r6,r3
3570 + adds r7,r7,r3 @ r2|r7|r14 = r2|r7|#0 + #0|r3|r14
3571 + adc r2,r2,#0
3572 + umull r4,r3,r5,r4
3573 + adds r14,r14,r4 @ r2|r7|r14 += #0|r3|r4
3574 + adcs r7,r7,r3
3575 + adc r2,r2,#0
3576 + umull r4,r3,r5,r6
3577 + adds r14,r14,r3 @ r2|r7|r14 += #0|#0|r3
3578 + adcs r7,r7,#0
3579 + adcs r2,r2,#0
3581 + bpl CPDO_muf_norm
3583 + add r8,r8,#1
3584 + b CPDO_muf_end
3586 +CPDO_muf_norm:
3587 + adds r14,r14,r14
3588 + adcs r7,r7,r7
3589 + adcs r2,r2,r2
3591 +CPDO_muf_end:
3592 + cmp r8,#0x20000000
3593 + bge CPDO_inf
3594 + cmp r8,#0xe0000000
3595 + ble CPDO_zero_1
3596 + stmia r0,{r1,r2,r7,r8}
3597 + b fastfpe_next
3599 +CPDO_muf_extra:
3600 + cmp r7,#0x7fffffff @ was it the first?
3601 + bne CPDO_muf_extra_2nd @ no, so it was the second
3602 + cmp r8,#0x7fffffff @ yes, second too?
3603 + bne CPDO_muf_extra_1st @ no, only first
3604 + orr r3,r3,r4 @ if both inf -> inf, otherwise nan
3605 + eor r1,r1,r2 @ sign for the inf case
3606 + b CPDO_infnan_1
3608 +CPDO_muf_extra_1st:
3609 + cmp r3,#0 @ is it a nan?
3610 + bne CPDO_infnan_1
3611 + cmp r8,#0x80000000 @ is the second 0?
3612 + beq CPDO_nan
3613 + eor r1,r1,r2 @ correct sign for inf
3614 + b CPDO_inf
3616 +CPDO_muf_extra_2nd:
3617 + cmp r4,#0 @ is it a nan?
3618 + bne CPDO_infnan_2
3619 + cmp r7,#0x80000000 @ is the first 0?
3620 + beq CPDO_nan
3621 + eor r1,r1,r2 @ correct sign for inf
3622 + b CPDO_inf
3624 +/*---------------------------------------------------------------------------*/
3626 + .globl CPDO_dvf
3627 +CPDO_dvf:
3628 + ldmia r1,{r1,r3,r5,r7}
3629 + ldmia r2,{r2,r4,r6,r8}
3631 +CPDO_dvf_l:
3632 + cmp r7,#0x7fffffff
3633 + cmpne r8,#0x7fffffff
3634 + beq CPDO_dvf_extra
3635 + cmp r8,#0x80000000
3636 + beq CPDO_dvf_by0
3638 + eor r1,r1,r2
3639 + cmp r7,#0x80000000
3640 + beq CPDO_zero_1
3642 + sub r8,r7,r8
3644 + mov r2,#0
3645 + mov r7,#1
3647 + cmp r3,r4
3648 + cmpeq r5,r6
3649 + bcs CPDO_dvf_loop_
3651 + sub r8,r8,#1
3653 +CPDO_dvf_loop:
3654 + adds r5,r5,r5
3655 + adcs r3,r3,r3
3656 + bcs CPDO_dvf_anyway
3657 +CPDO_dvf_loop_:
3658 + subs r5,r5,r6
3659 + sbcs r3,r3,r4
3660 + bcs CPDO_dvf_okay
3662 + adds r5,r5,r6
3663 + adc r3,r3,r4
3664 + adds r7,r7,r7
3665 + adcs r2,r2,r2
3666 + bcc CPDO_dvf_loop
3667 + b CPDO_dvf_end
3669 +CPDO_dvf_anyway:
3670 + adcs r7,r7,r7
3671 + adcs r2,r2,r2
3672 + bcs CPDO_dvf_end
3673 + subs r5,r5,r6
3674 + sbc r3,r3,r4
3675 + b CPDO_dvf_loop
3677 +CPDO_dvf_okay:
3678 + adcs r7,r7,r7
3679 + adcs r2,r2,r2
3680 + bcc CPDO_dvf_loop
3682 +CPDO_dvf_end:
3683 + b CPDO_muf_end
3685 +CPDO_dvf_by0:
3686 + cmp R7,#0x80000000
3687 + beq CPDO_nan @ first also 0 -> nan
3688 + eor r1,r1,r2 @ otherwise calculatesign for inf
3689 + b CPDO_inf
3691 +CPDO_dvf_extra:
3692 + cmp r7,#0x7fffffff @ was it the first?
3693 + bne CPDO_dvf_extra_2nd @ no, so it was the second
3694 + cmp r8,#0x7fffffff @ yes, second too?
3695 + bne CPDO_dvf_extra_1st @ no, only first
3696 + orrs r3,r3,r4
3697 + beq CPDO_nan @ if both inf -> create nan
3698 + b CPDO_nan_12 @ otherwise keep nan
3700 +CPDO_dvf_extra_1st:
3701 + eor r1,r1,r2 @ correct sign for inf
3702 + b CPDO_infnan_1
3704 +CPDO_dvf_extra_2nd:
3705 + cmp r4,#0 @ is it a nan?
3706 + bne CPDO_infnan_2
3707 + eor r1,r1,r2 @ correct sign for zero
3708 + b CPDO_zero_1
3710 +/*---------------------------------------------------------------------------*/
3712 + .globl CPDO_rdf
3713 +CPDO_rdf:
3714 + mov r3,r2
3715 + ldmia r1,{r2,r4,r6,r8}
3716 + ldmia r3,{r1,r3,r5,r7}
3717 + b CPDO_dvf_l
3719 +/*---------------------------------------------------------------------------*/
3721 + .globl CPDO_rmf
3722 +CPDO_rmf:
3723 + b fastfpe_next
3725 +/*---------------------------------------------------------------------------*/
3729 +/*---------------------------------------------------------------------------*/
3731 + .globl CPDO_mvf
3732 +CPDO_mvf:
3733 + ldmia r2,{r1,r2,r3,r4}
3734 + stmia r0,{r1,r2,r3,r4}
3735 + b fastfpe_next
3737 +/*---------------------------------------------------------------------------*/
3739 + .globl CPDO_mnf
3740 +CPDO_mnf:
3741 + ldmia r2,{r1,r2,r3,r4}
3742 + eor r1,r1,#0x80000000
3743 + stmia r0,{r1,r2,r3,r4}
3744 + b fastfpe_next
3746 +/*---------------------------------------------------------------------------*/
3748 + .globl CPDO_abs
3749 +CPDO_abs:
3750 + ldmia r2,{r1,r2,r3,r4}
3751 + bic r1,r1,#0x80000000
3752 + stmia r0,{r1,r2,r3,r4}
3753 + b fastfpe_next
3755 +/*---------------------------------------------------------------------------*/
3757 + .globl CPDO_sqt
3758 +CPDO_sqt:
3759 + ldmia r2,{r1,r2,r3,r4}
3760 + cmp r1,#0
3761 + bne CPDO_nan
3762 + cmp r4,#0x7fffffff
3763 + beq CPDO_store_1234
3765 + tst r4,r4,lsr#1 @carry=exponent bit 0
3766 + bcc CPDO_sqt_exponenteven
3767 + adds r3,r3,r3
3768 + adcs r2,r2,r2 @carry is needed in loop!
3769 +CPDO_sqt_exponenteven:
3770 + mov r4,r4,asr #1
3771 + str r4,[r0,#12]
3773 + mov r4,#0x80000000
3774 + mov r5,#0
3775 + sub r2,r2,#0x80000000
3777 + mov r8,#0x40000000
3778 + mov r14,#0x80000000
3780 + mov r1,#1
3781 + b CPDO_sqt_loop1_first
3782 +CPDO_sqt_loop1:
3783 + adds r3,r3,r3
3784 + adcs r2,r2,r2
3785 +CPDO_sqt_loop1_first:
3786 + add r6,r4,r8,lsr r1 @r7 const = r5
3787 + bcs CPDO_sqt_loop1_1
3788 + cmp r2,r6
3789 + cmpeq r3,r5 @r5 for r7
3790 + bcc CPDO_sqt_loop1_0
3791 +CPDO_sqt_loop1_1:
3792 + orr r4,r4,r14,lsr r1
3793 + subs r3,r3,r5 @r5 for r7
3794 + sbc r2,r2,r6
3795 +CPDO_sqt_loop1_0:
3796 + add r1,r1,#1
3797 + cmp r1,#30
3798 + ble CPDO_sqt_loop1
3800 + adds r3,r3,r3
3801 + adcs r2,r2,r2
3802 + bcs CPDO_sqt_between_1
3803 + adds r7,r5,#0x80000000
3804 + adc r6,r4,#0
3805 + cmp r2,r6
3806 + cmpeq r3,r7
3807 + bcc CPDO_sqt_between_0
3808 +CPDO_sqt_between_1:
3809 + orr r4,r4,#0x00000001
3810 + subs r3,r3,r5
3811 + sbc r2,r2,r4
3812 + subs r3,r3,#0x80000000
3813 + sbc r2,r2,#0
3814 +CPDO_sqt_between_0:
3815 + mov r1,#0
3817 +CPDO_sqt_loop2:
3818 + adds r3,r3,r3
3819 + adcs r2,r2,r2
3820 + bcs CPDO_sqt_loop2_1
3821 + adds r7,r5,r8,lsr r1
3822 + adc r6,r4,#0
3823 + cmp r2,r6
3824 + cmpeq r3,r7
3825 + bcc CPDO_sqt_loop2_0
3826 +CPDO_sqt_loop2_1:
3827 + orr r5,r5,r14,lsr r1
3828 + subs r3,r3,r5
3829 + sbc r2,r2,r4
3830 + subs r3,r3,r8,lsr r1
3831 + sbc r2,r2,#0
3832 +CPDO_sqt_loop2_0:
3833 + add r1,r1,#1
3834 + cmp r1,#30
3835 + ble CPDO_sqt_loop2
3837 + adds r3,r3,r3
3838 + adcs r2,r2,r2
3839 + bcs CPDO_sqt_after_1
3840 + cmp r2,r6
3841 + cmpeq r3,r7
3842 + bcc CPDO_sqt_after_0
3843 +CPDO_sqt_after_1:
3844 + orr r5,r5,#0x00000001
3845 +CPDO_sqt_after_0:
3847 + mov r1,#0
3848 + stmia r0,{r1,r4,r5}
3849 + b fastfpe_next
3851 +/*---------------------------------------------------------------------------*/
3853 + .globl CPDO_rnd
3854 +CPDO_rnd:
3855 + ldmia r2,{r1,r2,r3,r5}
3856 + bl CPDO_rnd_core
3858 +CPDO_rnd_store:
3859 + stmia r0,{r1,r2,r3,r5}
3860 + b fastfpe_next
3862 +/*---------------------------------------------------------------------------*/
3864 + .globl CPDO_rnd_core
3865 +CPDO_rnd_core:
3866 + and r4,r4,#0x00000060
3867 + add pc,pc,r4,lsr#3
3868 + mov r0,r0
3869 + b CPDO_rnd_N
3870 + b CPDO_rnd_P
3871 + b CPDO_rnd_M
3872 + b CPDO_rnd_Z
3874 +CPDO_rnd_N:
3875 + cmp r5,#-1
3876 + blt CPDO_rnd_zero
3877 + cmp r5,#63
3878 + movge pc,r14
3879 + mov r4,#0x40000000
3880 + cmp r5,#31
3881 + bge CPDO_rnd_N_2
3883 + adds r2,r2,r4,lsr r5
3884 + bcc CPDO_rnd_end
3885 + b CPDO_rnd_end_norm
3887 +CPDO_rnd_N_2:
3888 +CPDO_rnd_P_2:
3889 + sub r6,r5,#32
3890 + adds r3,r3,r4,ror r6 @ror ist needed to handle a -1 correctly
3891 + adcs r2,r2,#0
3892 + bcc CPDO_rnd_end
3893 + b CPDO_rnd_end_norm
3895 +CPDO_rnd_P:
3896 + tst r1,#0x80000000
3897 + bne CPDO_rnd_M_entry
3898 +CPDO_rnd_P_entry:
3899 + cmp r5,#0
3900 + blt CPDO_rnd_P_small
3901 + cmp r5,#63
3902 + movge pc,r14
3903 + mov r4,#0x7fffffff
3904 + cmp r5,#32
3905 + bge CPDO_rnd_P_2
3907 + adds r3,r3,#0xffffffff
3908 + adcs r2,r2,r4,lsr r5
3909 + bcc CPDO_rnd_end
3910 + b CPDO_rnd_end_norm
3912 +CPDO_rnd_P_small:
3913 + cmp r5,#0x80000000
3914 + moveq pc,r14
3915 + b CPDO_rnd_one
3917 +CPDO_rnd_M:
3918 + tst r1,#0x80000000
3919 + bne CPDO_rnd_P_entry
3920 +CPDO_rnd_M_entry:
3921 + cmp r5,#0
3922 + blt CPDO_rnd_zero
3923 + cmp r5,#63
3924 + movge pc,r14
3926 + b CPDO_rnd_end
3928 +CPDO_rnd_Z:
3929 + cmp r5,#0
3930 + blt CPDO_rnd_zero
3931 + cmp r5,#63
3932 + movge pc,r14
3933 + b CPDO_rnd_end
3935 +CPDO_rnd_end_norm:
3936 + add r5,r5,#1
3937 + movs r2,r2,rrx
3938 + mov r3,r3,rrx
3939 +CPDO_rnd_end:
3940 + rsbs r4,r5,#31
3941 + bmi CPDO_rnd_end_2
3942 + mov r3,#0
3943 + mov r2,r2,lsr r4
3944 + mov r2,r2,lsl r4
3945 + mov pc,r14
3947 +CPDO_rnd_end_2:
3948 + rsb r4,r5,#63
3949 + mov r3,r3,lsr r4
3950 + mov r3,r3,lsl r4
3951 + mov pc,r14
3953 +CPDO_rnd_one:
3954 + mov r2,#0x80000000
3955 + mov r3,#0
3956 + mov r5,#0
3957 + mov pc,r14
3959 +CPDO_rnd_zero:
3960 + mov r1,#0
3961 + mov r2,#0
3962 + mov r3,#0
3963 + mov r5,#0x80000000
3964 + mov pc,r14
3966 +/*---------------------------------------------------------------------------*/
3967 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
3968 +++ linux-2.4.25/arch/arm/fastfpe/CPDT.S 2004-03-31 17:15:08.000000000 +0200
3969 @@ -0,0 +1,430 @@
3971 +The FP structure has 4 words reserved for each register, the first is used just
3972 +for the sign in bit 31, the second and third are for the mantissa (unsigned
3973 +integer, high 32 bit first) and the fourth is the exponent (signed integer).
3974 +The mantissa is always normalized.
3976 +If the exponent is 0x80000000, that is the most negative value, the number
3977 +represented is 0 and both mantissa words are also 0.
3979 +If the exponent is 0x7fffffff, that is the biggest positive value, the number
3980 +represented is infinity if the high 32 mantissa bit are also 0, otherwise it is
3981 +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
3983 +Decimal and packed decimal numbers are not supported yet.
3986 +/*---------------------------------------------------------------------------*/
3988 + .globl CPDT_load_single
3989 +CPDT_load_single:
3990 + ldr r1,[r6]
3992 + and r2,r1,#0x80000000 @ r2 = sign
3994 + mov r5,r1,lsr#23
3995 + bics r5,r5,#0x100
3996 + beq CPDT_ls_e0 @ exponent = 0; zero/denormalized
3997 + teq r5,#255
3998 + beq CPDT_ls_e255 @ exponent = 255; infinity/NaN
4000 + sub r5,r5,#127 @ r5 = exponent, remove normalized bias
4002 + mov r3,r1,lsl#8
4003 + orr r3,r3,#0x80000000
4004 + mov r4,#0 @ r3,r4 = mantissa
4006 + stmia r0,{r2-r5}
4007 + b fastfpe_next
4009 +CPDT_ls_e0:
4010 + movs r3,r1,lsl#9
4011 + beq CPDT_load_zero
4013 + mov r5,#-127
4015 +CPDT_ls_e0_norm:
4016 + tst r3,#0x80000000
4017 + subeq r5,r5,#1
4018 + moveq r3,r3,lsl#1
4019 + beq CPDT_ls_e0_norm
4021 + mov r4,#0
4022 + stmia r0,{r2-r5}
4023 + b fastfpe_next
4025 +CPDT_ls_e255:
4026 + mov r3,r1,lsl#9
4027 + mov r4,#0
4028 + mov r5,#0x7fffffff
4029 + stmia r0,{r2-r5}
4030 + b fastfpe_next
4032 +CPDT_load_zero:
4033 + mov r3,#0
4034 + mov r4,#0
4035 + mov r5,#0x80000000
4036 + stmia r0,{r2-r5}
4037 + b fastfpe_next
4039 +/*---------------------------------------------------------------------------*/
4041 + .globl CPDT_load_double
4042 +CPDT_load_double:
4043 + ldr r1,[r6]
4044 + ldr r6,[r6,#4]
4046 + and r2,r1,#0x80000000 @ r2 = sign
4048 + mov r5,r1,lsr#20
4049 + bics r5,r5,#0x800
4050 + beq CPDT_ld_e0 @ exponent = 0; zero/denormalized
4051 + add r4,r5,#1
4052 + teq r4,#2048
4053 + beq CPDT_ld_e2047 @ exponent = 2047; infinity/NaN
4055 + add r5,r5,#1
4056 + sub r5,r5,#1024 @ r5 = exponent, remove normalized bias
4058 + mov r3,r1,lsl#11
4059 + orr r3,r3,#0x80000000
4060 + orr r3,r3,r6,lsr #21
4061 + mov r4,r6,lsl#11 @ r3,r4 = mantissa
4063 + stmia r0,{r2-r5}
4064 + b fastfpe_next
4066 +CPDT_ld_e0:
4067 + mov r3,r1,lsl#12
4068 + orr r3,r3,r6,lsr#20
4069 + movs r4,r6,lsl#12
4070 + teqeq r3,#0
4071 + beq CPDT_load_zero
4073 + mov r5,#1
4074 + sub r5,r5,#1024
4076 +CPDT_ld_e0_norm:
4077 + tst r3,#0x80000000
4078 + subeq r5,r5,#1
4079 + moveqs r4,r4,lsl#1
4080 + adceq r3,r3,r3
4081 + beq CPDT_ld_e0_norm
4083 + stmia r0,{r2-r5}
4084 + b fastfpe_next
4086 +CPDT_ld_e2047:
4087 + mov r3,r1,lsl#12
4088 + orr r3,r3,r6,lsr#1
4089 + bic r6,r6,#0x80000000
4090 + orr r3,r3,r6 @ to get all fraction bits !
4091 + mov r4,#0
4092 + mov r5,#0x7fffffff
4093 + stmia r0,{r2-r5}
4094 + b fastfpe_next
4096 +/*---------------------------------------------------------------------------*/
4098 + .globl CPDT_load_extended
4099 +CPDT_load_extended:
4100 + ldr r1,[r6]
4101 + ldr r3,[r6,#4]
4102 + ldr r4,[r6,#8]
4104 + and r2,r1,#0x80000000
4105 + bics r5,r1,#0x80000000
4106 + beq CPDT_le_e0
4107 + add r1,r5,#1
4108 + teq r4,#32768
4109 + beq CPDT_le_e32767
4111 + add r5,r5,#1
4112 + sub r5,r5,#16384
4114 + stmia r0,{r2-r5}
4115 + b fastfpe_next
4117 +CPDT_le_e0:
4118 + teq r3,#0
4119 + teqeq r4,#0
4120 + beq CPDT_load_zero
4122 + mov r5,#2
4123 + sub r5,r5,#16384
4124 + b CPDT_ld_e0_norm
4126 +CPDT_le_e32767:
4127 + mov r3,r3,lsl#1
4128 + orr r3,r3,r4,lsr#1
4129 + bic r4,r4,#0x80000000
4130 + orr r3,r3,r4
4131 + mov r5,#0x7fffffff
4132 + stmia r0,{r2-r5}
4133 + b fastfpe_next
4135 +/*---------------------------------------------------------------------------*/
4137 + .globl CPDT_load_decimal
4138 +CPDT_load_decimal:
4140 + b fastfpe_next
4142 +/*---------------------------------------------------------------------------*/
4144 + .globl CPDT_store_single
4145 +CPDT_store_single:
4146 + ldmia r0,{r1-r4}
4148 + cmp r4,#-127
4149 + ble CPDT_ss_e0
4150 + cmp r4,#128
4151 + bge CPDT_ss_e255
4153 + adds r2,r2,#1<<7 @ round to nearest
4154 + bcs CPDT_ss_rnd_ovfl @ very very seldom taken
4156 +CPDT_ss_store:
4157 + add r4,r4,#127
4158 + orr r1,r1,r4,lsl#23
4160 + bic r2,r2,#0x80000000
4161 + orr r1,r1,r2,lsr#8
4163 + str r1,[r6]
4164 + b fastfpe_next
4166 +CPDT_ss_rnd_ovfl:
4167 + add r4,r4,#1
4168 + cmp r4,#128
4169 + bge CPDT_ss_e255
4171 + mov r2,#0x80000000
4172 + mov r3,#0
4173 + b CPDT_ss_store
4175 +CPDT_ss_e0:
4176 + cmp r4,#-150
4177 + ble CPDT_ss_zero
4179 + add r4,r4,#126
4180 +CPDT_ss_unnormalize:
4181 + mov r2,r2,lsr#1
4182 + adds r4,r4,#1
4183 + bne CPDT_ss_unnormalize
4185 + orr r1,r1,r2,lsr#8
4187 +CPDT_ss_zero:
4188 + str r1,[r6]
4189 + b fastfpe_next
4191 +CPDT_ss_e255:
4192 + cmp r4,#0x7fffffff
4193 + bne CPDT_ss_inf
4194 + cmp r2,#0
4195 + beq CPDT_ss_inf
4197 + orr r1,r1,#0x00200000 @ for safety so that it is not INF
4198 + orr r1,r1,r2,lsr#9 @ get highest bit of mantissa
4200 +CPDT_ss_inf:
4201 + orr r1,r1,#0x7f000000
4202 + orr r1,r1,#0x00800000
4203 + str r1,[r6]
4204 + b fastfpe_next
4206 +/*---------------------------------------------------------------------------*/
4208 + .globl CPDT_store_double
4209 +CPDT_store_double:
4210 + ldmia r0,{r1-r4}
4212 + cmp r4,#1024 @ this check has to be first, or
4213 + bge CPDT_sd_e2047 @ overflow can occur on second !
4214 + add r0,r4,#3
4215 + cmp r0,#-1023+3 @ cmp with -1023
4216 + ble CPDT_sd_e0
4218 + adds r3,r3,#1<<10 @ round to nearest
4219 + adcs r2,r2,#0
4220 + bcs CPDT_sd_rnd_ovfl @ very very seldom taken
4222 +CPDT_sd_store:
4223 + sub r4,r4,#1
4224 + add r4,r4,#1024
4225 + orr r1,r1,r4,lsl#20
4227 + bic r2,r2,#0x80000000
4228 + orr r1,r1,r2,lsr#11
4230 + mov r2,r2,lsl#21
4231 + orr r2,r2,r3,lsr#11
4233 + stmia r6,{r1,r2}
4234 + b fastfpe_next
4236 +CPDT_sd_rnd_ovfl:
4237 + add r4,r4,#1
4238 + cmp r4,#1024
4239 + bge CPDT_sd_e2047
4241 + mov r2,#0x80000000
4242 + mov r3,#0
4243 + b CPDT_sd_store
4245 +CPDT_sd_e0:
4246 + add r0,r4,#1075-1024
4247 + cmp r0,#-1024
4248 + ble CPDT_sd_zero
4250 + add r4,r4,#1024
4251 + sub r4,r4,#2
4252 +CPDT_sd_unnormalize:
4253 + movs r2,r2,lsr#1
4254 + mov r3,r3,rrx
4255 + adds r4,r4,#1
4256 + bne CPDT_sd_unnormalize
4258 + orr r1,r1,r2,lsr#11
4259 + mov r2,r2,lsl#21
4260 + orr r2,r2,r3,lsr#11
4262 + stmia r6,{r1,r2}
4263 + b fastfpe_next
4265 +CPDT_sd_zero:
4266 + mov r2,#0
4267 + stmia r6,{r1,r2}
4268 + b fastfpe_next
4270 +CPDT_sd_e2047:
4271 + cmp r4,#0x7fffffff
4272 + bne CPDT_sd_inf
4273 + cmp r2,#0
4274 + beq CPDT_sd_inf
4276 + orr r1,r1,#0x00040000 @ for safety so that it is not INF
4277 + orr r1,r1,r2,lsr#12 @ get highest bit of mantissa
4279 +CPDT_sd_inf:
4280 + orr r1,r1,#0x7f000000
4281 + orr r1,r1,#0x00f00000
4282 + stmia r6,{r1,r2}
4283 + b fastfpe_next
4285 +/*---------------------------------------------------------------------------*/
4287 + .globl CPDT_store_extended
4288 +CPDT_store_extended:
4289 + ldmia r0,{r1-r4}
4291 + cmp r4,#16384 @ this check has to be first, or
4292 + bge CPDT_se_e32767 @ overflow can occur with second !
4293 + add r0,r4,#63
4294 + cmp r0,#-16383+63
4295 + ble CPDT_se_e0
4297 + sub r4,r4,#1
4298 + add r4,r4,#16384
4299 + orr r1,r1,r4
4301 + stmia r6,{r1-r3}
4302 + b fastfpe_next
4304 +CPDT_se_e0:
4305 + add r0,r4,#16446-16384
4306 + cmp r0,#-16384
4307 + ble CPDT_se_zero
4309 + add r4,r4,#16384
4310 + sub r4,r4,#2
4311 +CPDT_se_unnormalize:
4312 + movs r2,r2,lsr#1
4313 + mov r3,r3,rrx
4314 + adds r4,r4,#1
4315 + bne CPDT_se_unnormalize
4317 + stmia r6,{r1-r3}
4318 + b fastfpe_next
4320 +CPDT_se_zero:
4321 + mov r2,#0
4322 + mov r3,#0
4323 + stmia r6,{r1-r3}
4324 + b fastfpe_next
4326 +CPDT_se_e32767:
4327 + cmp r4,#0x7fffffff
4328 + bne CPDT_se_inf
4329 + cmp r2,#0
4330 + beq CPDT_se_inf
4332 + mov r2,r2,lsl#1
4333 + orr r2,r2,#0x20000000
4335 +CPDT_se_inf:
4336 + orr r1,r1,#0x00007f00
4337 + orr r1,r1,#0x000000ff
4338 + stmia r6,{r1-r3}
4339 + b fastfpe_next
4341 +/*---------------------------------------------------------------------------*/
4343 + .globl CPDT_store_decimal
4344 +CPDT_store_decimal:
4346 + b fastfpe_next
4348 +/*---------------------------------------------------------------------------*/
4350 + .globl CPDT_sfm
4351 +CPDT_sfm:
4352 + add r2,r10,r0,lsr#8
4353 + ldr r4,[r2,#0]
4354 + ldr r3,[r2,#4]
4355 + bic r3,r3,#0x80000000
4356 + orr r3,r3,r4
4357 + str r3,[r6],#4
4358 + ldr r3,[r2,#8]
4359 + str r3,[r6],#4
4360 + ldr r3,[r2,#12]
4361 + str r3,[r6],#4
4363 + add r0,r0,#1<<12
4364 + and r0,r0,#7<<12
4365 + subs r1,r1,#1
4366 + bne CPDT_sfm
4367 + b fastfpe_next
4369 +/*---------------------------------------------------------------------------*/
4371 + .globl CPDT_lfm
4372 +CPDT_lfm:
4373 + add r2,r10,r0,lsr#8
4374 + ldr r4,[r6],#4
4375 + and r3,r4,#0x80000000
4376 + str r3,[r2,#0]
4377 + ldr r3,[r6],#4
4378 + str r3,[r2,#8]
4379 + ldr r3,[r6],#4
4380 + str r3,[r2,#12]
4382 + cmp r3,#0x80000000 @ does the exp indicate zero?
4383 + biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized'
4384 + beq CPDT_lfm_storer4
4385 + cmp r3,#0x7fffffff @ does the exp indicate inf or NaN?
4386 + biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized'
4387 + beq CPDT_lfm_storer4
4388 + orrne r4,r4,#0x80000000 @ otherwise, set normalized bit
4390 +CPDT_lfm_storer4:
4391 + str r4,[r2,#4]
4393 + add r0,r0,#1<<12
4394 + and r0,r0,#7<<12
4395 + subs r1,r1,#1
4396 + bne CPDT_lfm
4397 + b fastfpe_next
4399 +/*---------------------------------------------------------------------------*/
4400 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
4401 +++ linux-2.4.25/arch/arm/fastfpe/CPRT.S 2004-03-31 17:15:08.000000000 +0200
4402 @@ -0,0 +1,185 @@
4404 +The FP structure has 4 words reserved for each register, the first is used
4405 +just
4406 +for the sign in bit 31, the second and third are for the mantissa (unsigned
4407 +integer, high 32 bit first) and the fourth is the exponent (signed integer).
4408 +The mantissa is always normalized.
4410 +If the exponent is 0x80000000, that is the most negative value, the number
4411 +represented is 0 and both mantissa words are also 0.
4413 +If the exponent is 0x7fffffff, that is the biggest positive value, the
4414 +number
4415 +represented is infinity if the high 32 mantissa bit are also 0, otherwise it
4417 +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
4419 +Decimal and packed decimal numbers are not supported yet.
4422 +/*---------------------------------------------------------------------------*/
4424 + .text
4425 + .globl CPRT_flt
4426 +CPRT_flt:
4427 + add r0,r13,r0,lsr#10
4428 + ldr r2,[r0]
4429 + mov r3,#0
4430 + cmp r2,#0
4431 + beq CPRT_flt_zero
4433 + ands r0,r2,#0x80000000
4434 + rsbne r2,r2,#0
4435 + mov r4,#31
4437 + cmp r2,#0x00010000
4438 + movcc r2,r2,lsl#16
4439 + subcc r4,r4,#16
4441 + cmp r2,#0x01000000
4442 + movcc r2,r2,lsl#8
4443 + subcc r4,r4,#8
4445 + cmp r2,#0x10000000
4446 + movcc r2,r2,lsl#4
4447 + subcc r4,r4,#4
4449 + cmp r2,#0x40000000
4450 + movcc r2,r2,lsl#2
4451 + subcc r4,r4,#2
4453 + cmp r2,#0x80000000
4454 + movcc r2,r2,lsl#1
4455 + subcc r4,r4,#1
4457 + stmia r1,{r0,r2,r3,r4}
4458 + b fastfpe_next
4460 +CPRT_flt_zero:
4461 + mov r0,#0
4462 + mov r4,#0x80000000
4463 + stmia r1,{r0,r2,r3,r4}
4464 + b fastfpe_next
4466 +/*---------------------------------------------------------------------------*/
4468 + .globl CPRT_fix
4469 +CPRT_fix:
4470 + ldmia r2,{r1,r2,r3,r5}
4471 + bl CPDO_rnd_core
4473 +CPRT_back:
4474 + add r0,r13,r0,lsr#10
4475 + cmp r5,#0
4476 + blt CPRT_int_zero
4477 + cmp r5,#30
4478 + bgt CPRT_overflow
4480 + rsb r5,r5,#31
4481 + mov r2,r2,lsr r5
4482 + tst r1,#0x80000000
4483 + rsbne r2,r2,#0
4485 + str r2,[r0]
4486 + b fastfpe_next
4488 +CPRT_int_zero:
4489 + mov r2,#0
4490 + str r2,[r0]
4491 + b fastfpe_next
4493 +CPRT_overflow:
4494 + mov r2,#0x80000000
4495 + tst r1,#0x80000000
4496 + subeq r2,r2,#1
4497 + str r2,[r0]
4498 + b fastfpe_next
4500 +/*---------------------------------------------------------------------------*/
4502 + .globl CPRT_wfs
4503 +CPRT_wfs:
4504 + b fastfpe_next
4506 +/*---------------------------------------------------------------------------*/
4508 + .globl CPRT_rfs
4509 +CPRT_rfs:
4510 + add r0,r13,r0,lsr#10
4511 + mov r1,#0x02000000 @ Software Emulation, not Acorn FPE
4512 + str r1,[r0]
4513 + b fastfpe_next
4515 +/*---------------------------------------------------------------------------*/
4517 + .globl CPRT_cmf
4518 +CPRT_cmf:
4519 + ldmia r1,{r1,r3,r5,r7}
4520 + ldmia r2,{r2,r4,r6,r8}
4522 +CPRT_cmf_e:
4523 + ldr r0,[r13,#16*4]
4525 + cmp r7,#0x7fffffff
4526 + bic r0,r0,#0xf0000000
4528 + cmpeq r3,#0xffffffff
4529 + beq CPRT_cmf_unordered
4530 + cmp r8,#0x7fffffff
4531 + cmpeq r4,#0xffffffff
4532 + beq CPRT_cmf_unordered
4534 + cmp r1,r2
4535 + beq CPRT_cmf_equalsign
4536 + b CPRT_cmf_sign
4538 +CPRT_cmf_equalsign:
4539 + cmp r7,r8
4540 + beq CPRT_cmf_equalexponent
4541 + bgt CPRT_cmf_sign
4542 + b CPRT_cmf_signb
4544 +CPRT_cmf_equalexponent:
4545 + cmp r3,r4
4546 + cmpeq r5,r6
4547 + beq CPRT_cmf_equal
4548 + bhi CPRT_cmf_sign
4549 + b CPRT_cmf_signb
4551 +CPRT_cmf_sign:
4552 + cmp r7,#0x80000000 @ (0.0 == -0.0)?
4553 + cmpeq r7,r8
4554 + beq CPRT_cmf_equal
4555 + tst r1,#0x80000000
4556 + orreq r0,r0,#0x20000000
4557 + orrne r0,r0,#0x80000000
4558 + str r0,[r13,#16*4]
4559 + b fastfpe_next
4561 +CPRT_cmf_signb:
4562 + tst r1,#0x80000000
4563 + orrne r0,r0,#0x20000000
4564 + orreq r0,r0,#0x80000000
4565 + str r0,[r13,#16*4]
4566 + b fastfpe_next
4568 +CPRT_cmf_equal:
4569 + orr r0,r0,#0x60000000
4570 + str r0,[r13,#16*4]
4571 + b fastfpe_next
4573 +CPRT_cmf_unordered:
4574 + orr r0,r0,#0x10000000
4575 + str r0,[r13,#16*4]
4576 + b fastfpe_next
4578 +/*---------------------------------------------------------------------------*/
4580 + .globl CPRT_cnf
4581 +CPRT_cnf:
4582 + ldmia r1,{r1,r3,r5,r7}
4583 + ldmia r2,{r2,r4,r6,r8}
4584 + eor r2,r2,#0x80000000
4585 + b CPRT_cmf_e
4587 +/*---------------------------------------------------------------------------*/
4588 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
4589 +++ linux-2.4.25/arch/arm/fastfpe/Makefile 2004-03-31 17:15:08.000000000 +0200
4590 @@ -0,0 +1,25 @@
4592 +# linux/arch/arm/fastfpe/Makefile
4594 +# Copyright (C) Peter Teichmann
4597 +O_TARGET := fast-math-emu.o
4599 +obj-y :=
4600 +obj-m :=
4601 +obj-n :=
4602 +obj- :=
4604 +fastfpe-objs := module.o entry.o CPDO.o CPRT.o CPDT.o
4606 +list-multi := fastfpe.o
4608 +obj-$(CONFIG_FPE_FASTFPE) += fastfpe.o
4610 +USE_STANDARD_AS_RULE := true
4612 +include $(TOPDIR)/Rules.make
4614 +fastfpe.o: $(fastfpe-objs)
4615 + $(LD) -r -o $@ $(fastfpe-objs)
4616 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
4617 +++ linux-2.4.25/arch/arm/fastfpe/entry.S 2004-03-31 17:15:08.000000000 +0200
4618 @@ -0,0 +1,295 @@
4620 +At entry the registers contain the following information:
4622 +r14 return address for undefined exception return
4623 +r9 return address for return from exception
4624 +r13 user registers on stack, offset 0 up to offset 4*15 contains
4625 + registers r0..15, then the psr
4626 +r10 FP workspace 35 words (init, reg[8][4], fpsr, fpcr)
4630 +/*---------------------------------------------------------------------------*/
4632 + .data
4633 +fp_const:
4634 + .word 0, 0x00000000, 0, 0x80000000 @ 0
4635 + .word 0, 0x80000000, 0, 0 @ 1
4636 + .word 0, 0x80000000, 0, 1 @ 2
4637 + .word 0, 0xc0000000, 0, 1 @ 3
4638 + .word 0, 0x80000000, 0, 2 @ 4
4639 + .word 0, 0xa0000000, 0, 2 @ 5
4640 + .word 0, 0x80000000, 0, -1 @ 0.5
4641 + .word 0, 0xa0000000, 0, 3 @ 10
4642 +fp_undef:
4643 + .word 0
4644 +fp_cond:
4645 + .word 0xf0f0 @ eq
4646 + .word 0x0f0f @ ne
4647 + .word 0xcccc @ cs
4648 + .word 0x3333 @ cc
4649 + .word 0xff00 @ mi
4650 + .word 0x00ff @ pl
4651 + .word 0xaaaa @ vs
4652 + .word 0x5555 @ vc
4653 + .word 0x0c0c @ hi
4654 + .word 0xf3f3 @ ls
4655 + .word 0xaa55 @ ge
4656 + .word 0x55aa @ lt
4657 + .word 0x0a05 @ gt
4658 + .word 0xf5fa @ le
4659 + .word 0xffff @ al
4660 + .word 0x0000 @ nv
4662 +/*---------------------------------------------------------------------------*/
4664 + .text
4665 + .globl fastfpe_enter
4666 +fastfpe_enter:
4667 + ldr r4,=fp_undef
4668 + str r14,[r4] @ to free one register
4669 + add r10,r10,#4 @ to make the code simpler
4670 + ldr r4,[r13,#60] @ r4=saved PC
4671 + ldr r4,[r4,#-4] @ r4=trapped instruction
4672 + and r1,r4,#0x00000f00 @ r1=coprocessor << 8
4673 +next_enter:
4674 + cmp r1,#1<<8 @ copro 1 ?
4675 + beq copro_1
4676 + cmp r1,#2<<8
4677 + movne pc,r14
4679 +copro_2:
4680 + and r1,r4,#0x0f000000
4681 + cmp r1,#0x0c000000 @ CPDT with post indexing
4682 + cmpne r1,#0x0d000000 @ CPDT with pre indexing
4683 + beq CPDT_M_enter
4684 + mov pc,r14
4686 +copro_1:
4687 + and r1,r4,#0x0f000000
4688 + cmp r1,#0x0e000000 @ CPDO
4689 + beq CPDO_CPRT_enter
4690 + cmp r1,#0x0c000000 @ CPDT with post indexing
4691 + cmpne r1,#0x0d000000 @ CPDT with pre indexing
4692 + beq CPDT_1_enter
4693 + mov pc,r14
4695 +/*---------------------------------------------------------------------------*/
4697 + .globl fastfpe_next
4698 +fastfpe_next:
4699 + ldr r5,[r13,#60]
4700 +next_after_cond:
4701 +__x1:
4702 + ldrt r4,[r5],#4
4704 + ldr r0,=fp_cond @ check condition of next instruction
4705 + ldr r1,[r13,#64] @ psr containing flags
4706 + mov r2,r4,lsr#28
4707 + mov r1,r1,lsr#28
4708 + ldr r0,[r0,r2,lsl#2]
4709 + mov r0,r0,lsr r1
4710 + tst r0,#1
4711 + beq next_after_cond @ must not necessarily have been an
4712 + @ FP instruction !
4713 + and r1,r4,#0x0f000000 @ Test for copro instruction
4714 + cmp r1,#0x0c000000
4715 + rsbgts r0,r1,#0x0e000000 @ cmpgt #0x0e000000,r1
4716 + movlt pc,r9 @ next is no copro instruction, return
4718 + ands r1,r4,#0x00000f00 @ r1 = coprocessor << 8
4719 + cmpne r1,#3<<8
4720 + movge pc,r9 @ copro = 0 or >=3, return
4722 + str r5,[r13,#60] @ save updated pc
4723 + b next_enter
4725 +/*---------------------------------------------------------------------------*/
4727 +undefined:
4728 + ldr r4,=fp_undef
4729 + ldr pc,[r4]
4731 +/*---------------------------------------------------------------------------*/
4733 +CPDT_1_enter:
4734 + and r5,r4,#0x000f0000 @ r5=base register number << 16
4735 + ldr r6,[r13,r5,lsr#14] @ r6=base address
4736 + cmp r5,#0x000f0000 @ base register = pc ?
4737 + addeq r6,r6,#4
4738 + and r7,r4,#0x000000ff @ r7=offset value
4740 + tst r4,#0x00800000 @ up or down?
4741 + addne r7,r6,r7,lsl#2
4742 + subeq r7,r6,r7,lsl#2 @ r6=base address +/- offset
4743 + tst r4,#0x01000000 @ preindexing ?
4744 + movne r6,r7
4745 + tst r4,#0x00200000 @ write back ?
4746 + cmpne r5,#0x000f0000 @ base register = pc ?
4747 + strne r7,[r13,r5,lsr#14]
4749 + and r0,r4,#0x00007000 @ r0=fp register number << 12
4750 + add r0,r10,r0,lsr#8 @ r0=address of fp register
4751 + mov r1,#0
4752 + tst r4,#0x00008000
4753 + orrne r1,r1,#1 @ T0
4754 + tst r4,#0x00400000
4755 + orrne r1,r1,#2 @ T1
4756 + tst r4,#0x00100000
4757 + orrne r1,r1,#4 @ L/S
4759 + add pc,pc,r1,lsl#2
4760 + mov r0,r0
4761 + b CPDT_store_single @ these functions get
4762 + b CPDT_store_double @ r0=address of fp register
4763 + b CPDT_store_extended @ r6=address of data
4764 + b undefined @ CPDT_store_decimal
4765 + b CPDT_load_single
4766 + b CPDT_load_double
4767 + b CPDT_load_extended
4768 + b undefined @ CPDT_load_decimal
4770 +/*---------------------------------------------------------------------------*/
4772 +CPDT_M_enter:
4773 + and r5,r4,#0x000f0000 @ r5=base register number << 16
4774 + ldr r6,[r13,r5,lsr#14] @ r6=base address
4775 + cmp r5,#0x000f0000 @ base register = pc ?
4776 + addeq r6,r6,#4
4777 + and r7,r4,#0x000000ff @ r7=offset value
4779 + tst r4,#0x00800000 @ up or down?
4780 + addne r7,r6,r7,lsl#2
4781 + subeq r7,r6,r7,lsl#2 @ r7=base address +/- offset
4782 + tst r4,#0x01000000 @ preindexing ?
4783 + movne r6,r7
4784 + tst r4,#0x00200000 @ write back ?
4785 + cmpne r5,#0x000f0000 @ base register = pc ?
4786 + strne r7,[r13,r5,lsr#14]
4788 + and r0,r4,#0x00007000 @ r0=fp register number << 12
4789 + and r1,r4,#0x00008000
4790 + mov r1,r1,lsr#15 @ N0
4791 + and r2,r4,#0x00400000
4792 + orrs r1,r1,r2,lsr#21 @ N1
4793 + addeq r1,r1,#4 @ r1=register count
4795 + tst r4,#0x00100000 @ load/store
4796 + beq CPDT_sfm
4797 + b CPDT_lfm
4799 +/*---------------------------------------------------------------------------*/
4801 +CPDO_CPRT_enter:
4802 + tst r4,#0x00000010
4803 + bne CPRT_enter
4805 + and r0,r4,#0x00007000
4806 + add r0,r10,r0,lsr#8 @ r0=address of Fd
4807 + and r1,r4,#0x00070000
4808 + add r1,r10,r1,lsr#12 @ r1=address of Fn
4809 + tst r4,#0x00000008
4810 + bne CPDO_const
4811 + and r2,r4,#0x00000007
4812 + add r2,r10,r2,lsl#4 @ r2=address of Fm
4814 +CPDO_constback:
4815 + and r3,r4,#0x00f00000
4816 + tst r4,#0x00008000
4817 + orrne r3,r3,#0x01000000
4819 + add pc,pc,r3,lsr#18
4820 + mov r0,r0
4821 + b CPDO_adf
4822 + b CPDO_muf
4823 + b CPDO_suf
4824 + b CPDO_rsf
4825 + b CPDO_dvf
4826 + b CPDO_rdf
4827 + b undefined
4828 + b undefined
4829 + b undefined @ CPDO_rmf
4830 + b CPDO_muf
4831 + b CPDO_dvf
4832 + b CPDO_rdf
4833 + b undefined
4834 + b undefined
4835 + b undefined
4836 + b undefined
4837 + b CPDO_mvf
4838 + b CPDO_mnf
4839 + b CPDO_abs
4840 + b CPDO_rnd
4841 + b CPDO_sqt
4842 + b undefined
4843 + b undefined
4844 + b undefined
4845 + b undefined
4846 + b undefined
4847 + b undefined
4848 + b undefined
4849 + b undefined
4850 + b undefined
4851 + b CPDO_rnd
4852 + b fastfpe_next
4854 +CPDO_const:
4855 + ldr r2,=fp_const
4856 + and r3,r4,#0x00000007
4857 + add r2,r2,r3,lsl#4
4858 + b CPDO_constback
4860 +/*---------------------------------------------------------------------------*/
4862 +CPRT_enter:
4863 + and r0,r4,#0x0000f000 @ r0=Rd<<12
4864 + and r1,r4,#0x00070000
4865 + add r1,r10,r1,lsr#12 @ r1=address of Fn
4866 + tst r4,#0x00000008
4867 + bne CPRT_const
4868 + and r2,r4,#0x00000007
4869 + add r2,r10,r2,lsl#4 @ r2=address of Fm
4871 +CPRT_constback:
4872 + and r3,r4,#0x00f00000
4874 + add pc,pc,r3,lsr#18
4875 + mov r0,r0
4876 + b CPRT_flt
4877 + b CPRT_fix
4878 + b CPRT_wfs
4879 + b CPRT_rfs
4880 + b undefined
4881 + b undefined
4882 + b undefined
4883 + b undefined
4884 + b undefined
4885 + b CPRT_cmf
4886 + b undefined
4887 + b CPRT_cnf
4888 + b undefined
4889 + b CPRT_cmf
4890 + b undefined
4891 + b CPRT_cnf
4893 +CPRT_const:
4894 + ldr r2,=fp_const
4895 + and r3,r4,#0x00000007
4896 + add r2,r2,r3,lsl#4
4897 + b CPRT_constback
4899 +/*---------------------------------------------------------------------------*/
4901 + @ The fetch of the next instruction to emulate could fault
4903 + .section .fixup,"ax"
4904 + .align
4905 +__f1:
4906 + mov pc,r9
4907 + .previous
4908 + .section __ex_table,"a"
4909 + .align 3
4910 + .long __x1,__f1
4911 + .previous
4913 +/*---------------------------------------------------------------------------*/
4914 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
4915 +++ linux-2.4.25/arch/arm/fastfpe/module.c 2004-03-31 17:15:08.000000000 +0200
4916 @@ -0,0 +1,78 @@
4918 + Fast Floating Point Emulator
4919 + (c) Peter Teichmann <mail@peter-teichmann.de>
4921 + This program is free software; you can redistribute it and/or modify
4922 + it under the terms of the GNU General Public License as published by
4923 + the Free Software Foundation; either version 2 of the License, or
4924 + (at your option) any later version.
4926 + This program is distributed in the hope that it will be useful,
4927 + but WITHOUT ANY WARRANTY; without even the implied warranty of
4928 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4929 + GNU General Public License for more details.
4931 + You should have received a copy of the GNU General Public License
4932 + along with this program; if not, write to the Free Software
4933 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4936 +#include <linux/module.h>
4937 +#include <linux/types.h>
4938 +#include <linux/kernel.h>
4939 +#include <linux/signal.h>
4940 +#include <linux/sched.h>
4941 +#include <linux/init.h>
4943 +#ifndef MODULE
4944 +#define kern_fp_enter fp_enter
4946 +extern char fpe_type[];
4947 +#endif
4949 +static void (*orig_fp_enter)(void); /* old kern_fp_enter value */
4950 +extern void (*kern_fp_enter)(void); /* current FP handler */
4951 +extern void fastfpe_enter(void); /* forward declarations */
4953 +#ifdef MODULE
4955 + * Return 0 if we can be unloaded. This can only happen if
4956 + * kern_fp_enter is still pointing at fastfpe_enter
4957 + */
4958 +static int fpe_unload(void)
4960 + return (kern_fp_enter == fastfpe_enter) ? 0 : 1;
4962 +#endif
4964 +static int __init fpe_init(void)
4966 +#ifdef MODULE
4967 + if (!mod_member_present(&__this_module, can_unload))
4968 + return -EINVAL;
4969 + __this_module.can_unload = fpe_unload;
4970 +#else
4971 + if (fpe_type[0] && strcmp(fpe_type, "fastfpe"))
4972 + return 0;
4973 +#endif
4975 + printk("Fast Floating Point Emulator V0.9 (c) Peter Teichmann.\n");
4977 + /* Save pointer to the old FP handler and then patch ourselves in */
4978 + orig_fp_enter = kern_fp_enter;
4979 + kern_fp_enter = fastfpe_enter;
4981 + return 0;
4984 +static void __exit fpe_exit(void)
4986 + /* Restore the values we saved earlier. */
4987 + kern_fp_enter = orig_fp_enter;
4990 +module_init(fpe_init);
4991 +module_exit(fpe_exit);
4993 +MODULE_AUTHOR("Peter Teichmann <mail@peter-teichmann.de>");
4994 +MODULE_DESCRIPTION("Fast floating point emulator with full precision");
4995 --- linux-2.4.25/arch/arm/kernel/calls.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
4996 +++ linux-2.4.25/arch/arm/kernel/calls.S 2004-03-31 17:15:08.000000000 +0200
4997 @@ -115,7 +115,7 @@
4998 .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */
4999 .long SYMBOL_NAME(sys_statfs)
5000 /* 100 */ .long SYMBOL_NAME(sys_fstatfs)
5001 - .long SYMBOL_NAME(sys_ni_syscall)
5002 + .long SYMBOL_NAME(sys_ni_syscall) /* 101 was sys_ioperm */
5003 .long SYMBOL_NAME(sys_socketcall)
5004 .long SYMBOL_NAME(sys_syslog)
5005 .long SYMBOL_NAME(sys_setitimer)
5006 @@ -126,7 +126,7 @@
5007 .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */
5008 /* 110 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_iopl */
5009 .long SYMBOL_NAME(sys_vhangup)
5010 - .long SYMBOL_NAME(sys_ni_syscall)
5011 + .long SYMBOL_NAME(sys_ni_syscall) /* 112 was sys_idle */
5012 .long SYMBOL_NAME(sys_syscall) /* call a syscall */
5013 .long SYMBOL_NAME(sys_wait4)
5014 /* 115 */ .long SYMBOL_NAME(sys_swapoff)
5015 @@ -137,7 +137,7 @@
5016 /* 120 */ .long SYMBOL_NAME(sys_clone_wapper)
5017 .long SYMBOL_NAME(sys_setdomainname)
5018 .long SYMBOL_NAME(sys_newuname)
5019 - .long SYMBOL_NAME(sys_ni_syscall)
5020 + .long SYMBOL_NAME(sys_ni_syscall) /* 123 was sys_modify_ldt */
5021 .long SYMBOL_NAME(sys_adjtimex)
5022 /* 125 */ .long SYMBOL_NAME(sys_mprotect)
5023 .long SYMBOL_NAME(sys_sigprocmask)
5024 @@ -180,7 +180,7 @@
5025 .long SYMBOL_NAME(sys_arm_mremap)
5026 .long SYMBOL_NAME(sys_setresuid16)
5027 /* 165 */ .long SYMBOL_NAME(sys_getresuid16)
5028 - .long SYMBOL_NAME(sys_ni_syscall)
5029 + .long SYMBOL_NAME(sys_ni_syscall) /* 166 was sys_vm86 */
5030 .long SYMBOL_NAME(sys_query_module)
5031 .long SYMBOL_NAME(sys_poll)
5032 .long SYMBOL_NAME(sys_nfsservctl)
5033 --- linux-2.4.25/arch/arm/kernel/dma-rpc.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5034 +++ linux-2.4.25/arch/arm/kernel/dma-rpc.c 2004-03-31 17:15:08.000000000 +0200
5035 @@ -26,19 +26,6 @@
5036 #include <asm/mach/dma.h>
5037 #include <asm/hardware/iomd.h>
5039 -#if 0
5040 -typedef enum {
5041 - dma_size_8 = 1,
5042 - dma_size_16 = 2,
5043 - dma_size_32 = 4,
5044 - dma_size_128 = 16
5045 -} dma_size_t;
5047 -typedef struct {
5048 - dma_size_t transfersize;
5049 -} dma_t;
5050 -#endif
5052 #define TRANSFER_SIZE 2
5054 #define CURA (0)
5055 @@ -48,10 +35,6 @@
5056 #define CR (IOMD_IO0CR - IOMD_IO0CURA)
5057 #define ST (IOMD_IO0ST - IOMD_IO0CURA)
5059 -#define state_prog_a 0
5060 -#define state_wait_a 1
5061 -#define state_wait_b 2
5063 static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
5065 unsigned long end, offset, flags = 0;
5066 @@ -65,7 +48,7 @@
5067 if (end > PAGE_SIZE)
5068 end = PAGE_SIZE;
5070 - if (offset + (int) TRANSFER_SIZE > end)
5071 + if (offset + TRANSFER_SIZE >= end)
5072 flags |= DMA_END_L;
5074 sg->length = end - TRANSFER_SIZE;
5075 @@ -103,27 +86,31 @@
5076 if (!(status & DMA_ST_INT))
5077 return;
5079 - if (status & DMA_ST_OFL && !dma->sg)
5080 - break;
5082 - iomd_get_next_sg(&dma->cur_sg, dma);
5083 + if ((dma->state ^ status) & DMA_ST_AB)
5084 + iomd_get_next_sg(&dma->cur_sg, dma);
5086 switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
5087 case DMA_ST_OFL: /* OIA */
5088 case DMA_ST_AB: /* .IB */
5089 iomd_writel(dma->cur_sg.dma_address, base + CURA);
5090 iomd_writel(dma->cur_sg.length, base + ENDA);
5091 + dma->state = DMA_ST_AB;
5092 break;
5094 case DMA_ST_OFL | DMA_ST_AB: /* OIB */
5095 case 0: /* .IA */
5096 iomd_writel(dma->cur_sg.dma_address, base + CURB);
5097 iomd_writel(dma->cur_sg.length, base + ENDB);
5098 + dma->state = 0;
5099 break;
5102 + if (status & DMA_ST_OFL &&
5103 + dma->cur_sg.length == (DMA_END_S|DMA_END_L))
5104 + break;
5105 } while (1);
5107 - iomd_writeb(0, base + CR);
5108 + dma->state = ~DMA_ST_AB;
5109 disable_irq(irq);
5112 @@ -158,6 +145,7 @@
5115 iomd_writeb(DMA_CR_C, dma_base + CR);
5116 + dma->state = DMA_ST_AB;
5119 if (dma->dma_mode == DMA_MODE_READ)
5120 @@ -171,13 +159,11 @@
5122 unsigned long dma_base = dma->dma_base;
5123 unsigned long flags;
5124 - unsigned int ctrl;
5126 local_irq_save(flags);
5127 - ctrl = iomd_readb(dma_base + CR);
5128 - if (ctrl & DMA_CR_E)
5129 + if (dma->state != ~DMA_ST_AB)
5130 disable_irq(dma->dma_irq);
5131 - iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR);
5132 + iomd_writeb(0, dma_base + CR);
5133 local_irq_restore(flags);
5136 --- linux-2.4.25/arch/arm/kernel/entry-armv.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5137 +++ linux-2.4.25/arch/arm/kernel/entry-armv.S 2004-03-31 17:15:08.000000000 +0200
5138 @@ -677,12 +677,11 @@
5139 mrs r9, cpsr @ Enable interrupts if they were
5140 tst r3, #I_BIT
5141 biceq r9, r9, #I_BIT @ previously
5142 - mov r0, r2 @ *** remove once everyones in sync
5144 * This routine must not corrupt r9
5146 #ifdef MULTI_CPU
5147 - ldr r4, .LCprocfns @ pass r0, r3 to
5148 + ldr r4, .LCprocfns @ pass r2, r3 to
5149 mov lr, pc @ processor code
5150 ldr pc, [r4] @ call processor specific code
5151 #else
5152 @@ -788,9 +787,8 @@
5153 stmdb r5, {sp, lr}^
5154 alignment_trap r7, r7, __temp_abt
5155 zero_fp
5156 - mov r0, r2 @ remove once everyones in sync
5157 #ifdef MULTI_CPU
5158 - ldr r4, .LCprocfns @ pass r0, r3 to
5159 + ldr r4, .LCprocfns @ pass r2, r3 to
5160 mov lr, pc @ processor code
5161 ldr pc, [r4] @ call processor specific code
5162 #else
5163 @@ -840,7 +838,8 @@
5164 adrsvc al, r9, ret_from_exception @ r9 = normal FP return
5165 adrsvc al, lr, fpundefinstr @ lr = undefined instr return
5167 -call_fpe: get_current_task r10
5168 +call_fpe: enable_irq r10
5169 + get_current_task r10
5170 mov r8, #1
5171 strb r8, [r10, #TSK_USED_MATH] @ set current->used_math
5172 ldr r4, .LCfp
5173 --- linux-2.4.25/arch/arm/kernel/head-armv.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5174 +++ linux-2.4.25/arch/arm/kernel/head-armv.S 2004-03-31 17:15:08.000000000 +0200
5175 @@ -1,7 +1,7 @@
5177 * linux/arch/arm/kernel/head-armv.S
5179 - * Copyright (C) 1994-1999 Russell King
5180 + * Copyright (C) 1994-2003 Russell King
5182 * This program is free software; you can redistribute it and/or modify
5183 * it under the terms of the GNU General Public License version 2 as
5184 @@ -163,10 +163,10 @@
5186 .type __ret, %function
5187 __ret: ldr lr, __switch_data
5188 - mcr p15, 0, r0, c1, c0
5189 - mrc p15, 0, r0, c1, c0, 0 @ read it back.
5190 - mov r0, r0
5191 - mov r0, r0
5192 + mcr p15, 0, r0, c1, c0, 0
5193 + mrc p15, 0, r3, c0, c0, 0
5194 + mov r3, r3
5195 + mov r3, r3
5196 mov pc, lr
5199 @@ -214,6 +214,11 @@
5201 __create_page_tables:
5202 pgtbl r4, r5 @ page table address
5203 +#if defined(CONFIG_CPU_DCACHE_DISABLE)
5204 + bic r8, r8, #0x00c @ clear B, C
5205 +#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
5206 + bic r8, r8, #0x004 @ clear B
5207 +#endif
5210 * Clear the 16K level 1 swapper page table
5211 --- linux-2.4.25/arch/arm/kernel/irq.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5212 +++ linux-2.4.25/arch/arm/kernel/irq.c 2004-03-31 17:15:08.000000000 +0200
5213 @@ -549,7 +549,7 @@
5214 kfree(action);
5215 goto out;
5217 - printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
5218 + printk(KERN_ERR "Trying to free IRQ%d\n",irq);
5219 #ifdef CONFIG_DEBUG_ERRORS
5220 __backtrace();
5221 #endif
5222 --- linux-2.4.25/arch/arm/kernel/ptrace.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5223 +++ linux-2.4.25/arch/arm/kernel/ptrace.c 2004-03-31 17:15:08.000000000 +0200
5224 @@ -725,11 +725,8 @@
5225 goto out_tsk;
5227 ret = -ESRCH;
5228 - if (!(child->ptrace & PT_PTRACED))
5229 - goto out_tsk;
5230 - if (child->state != TASK_STOPPED && request != PTRACE_KILL)
5231 - goto out_tsk;
5232 - if (child->p_pptr != current)
5233 + ret = ptrace_check_attach(child, request == PTRACE_KILL);
5234 + if (ret)
5235 goto out_tsk;
5237 ret = do_ptrace(request, child, addr, data);
5238 --- linux-2.4.25/arch/arm/kernel/semaphore.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5239 +++ linux-2.4.25/arch/arm/kernel/semaphore.c 2004-03-31 17:15:08.000000000 +0200
5240 @@ -193,7 +193,7 @@
5241 bl __down_interruptible \n\
5242 mov ip, r0 \n\
5243 ldmfd sp!, {r0 - r3, pc}^ \n\
5245 + \n\
5246 .align 5 \n\
5247 .globl __down_trylock_failed \n\
5248 __down_trylock_failed: \n\
5249 --- linux-2.4.25/arch/arm/kernel/signal.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5250 +++ linux-2.4.25/arch/arm/kernel/signal.c 2004-03-31 17:15:08.000000000 +0200
5251 @@ -641,10 +641,7 @@
5252 /* FALLTHRU */
5254 default:
5255 - sigaddset(&current->pending.signal, signr);
5256 - recalc_sigpending(current);
5257 - current->flags |= PF_SIGNALED;
5258 - do_exit(exit_code);
5259 + sig_exit(signr, exit_code, &info);
5260 /* NOTREACHED */
5263 --- linux-2.4.25/arch/arm/lib/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5264 +++ linux-2.4.25/arch/arm/lib/Makefile 2004-03-31 17:15:08.000000000 +0200
5265 @@ -15,7 +15,7 @@
5266 strnlen_user.o strchr.o strrchr.o testchangebit.o \
5267 testclearbit.o testsetbit.o uaccess.o getuser.o \
5268 putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
5269 - ucmpdi2.o udivdi3.o lib1funcs.o
5270 + ucmpdi2.o udivdi3.o lib1funcs.o div64.o
5271 obj-m :=
5272 obj-n :=
5274 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
5275 +++ linux-2.4.25/arch/arm/lib/div64.S 2004-03-31 17:15:08.000000000 +0200
5276 @@ -0,0 +1,59 @@
5277 +#include <linux/linkage.h>
5279 +#ifndef __ARMEB__
5280 +ql .req r0 @ quotient low
5281 +qh .req r1 @ quotient high
5282 +onl .req r0 @ original dividend low
5283 +onh .req r1 @ original dividend high
5284 +nl .req r4 @ dividend low
5285 +nh .req r5 @ dividend high
5286 +res .req r4 @ result
5287 +#else
5288 +ql .req r1
5289 +qh .req r0
5290 +onl .req r1
5291 +onh .req r0
5292 +nl .req r5
5293 +nh .req r4
5294 +res .req r5
5295 +#endif
5297 +dl .req r3 @ divisor low
5298 +dh .req r2 @ divsor high
5301 +ENTRY(do_div64)
5302 + stmfd sp!, {r4, r5, lr}
5303 + mov nl, onl
5304 + movs nh, onh @ if high bits are zero
5305 + movne lr, #33
5306 + moveq lr, #1 @ only divide low bits
5307 + moveq nh, onl
5309 + tst dh, #0x80000000
5310 + bne 2f
5311 +1: cmp nh, dh
5312 + bls 2f
5313 + add lr, lr, #1
5314 + movs dh, dh, lsl #1 @ left justify disor
5315 + bpl 1b
5317 +2: movs nh, onh
5318 + moveq dl, dh
5319 + moveq dh, #0
5320 + movne dl, #0
5321 + mov ql, #0
5322 + mov qh, #0
5323 +3: subs ip, nl, dl @ trial subtraction
5324 + sbcs ip, nh, dh
5325 + movcs nh, ip @ only update if successful
5326 + subcs nl, nl, dl @ (repeat the subtraction)
5327 + adcs ql, ql, ql @ C=1 if successful, shift into
5328 + adc qh, qh, qh @ quotient
5329 + movs dh, dh, lsr #1 @ shift base high part right
5330 + mov dl, dl, rrx @ shift base low part right
5331 + subs lr, lr, #1
5332 + bne 3b
5334 + mov r2, res
5335 + ldmfd sp!, {r4, r5, pc}
5336 --- linux-2.4.25/arch/arm/lib/putuser.S~2.4.25-vrs2.patch 2001-10-11 18:04:57.000000000 +0200
5337 +++ linux-2.4.25/arch/arm/lib/putuser.S 2004-03-31 17:15:09.000000000 +0200
5338 @@ -30,11 +30,11 @@
5340 .global __put_user_1
5341 __put_user_1:
5342 - bic r2, sp, #0x1f00
5343 - bic r2, r2, #0x00ff
5344 - ldr r2, [r2, #TSK_ADDR_LIMIT]
5345 - sub r2, r2, #1
5346 - cmp r0, r2
5347 + bic ip, sp, #0x1f00
5348 + bic ip, ip, #0x00ff
5349 + ldr ip, [ip, #TSK_ADDR_LIMIT]
5350 + sub ip, ip, #1
5351 + cmp r0, ip
5352 1: strlsbt r1, [r0]
5353 movls r0, #0
5354 movls pc, lr
5355 @@ -42,11 +42,11 @@
5357 .global __put_user_2
5358 __put_user_2:
5359 - bic r2, sp, #0x1f00
5360 - bic r2, r2, #0x00ff
5361 - ldr r2, [r2, #TSK_ADDR_LIMIT]
5362 - sub r2, r2, #2
5363 - cmp r0, r2
5364 + bic ip, sp, #0x1f00
5365 + bic ip, ip, #0x00ff
5366 + ldr ip, [ip, #TSK_ADDR_LIMIT]
5367 + sub ip, ip, #2
5368 + cmp r0, ip
5369 2: strlsbt r1, [r0], #1
5370 movls r1, r1, lsr #8
5371 3: strlsbt r1, [r0]
5372 @@ -56,11 +56,11 @@
5374 .global __put_user_4
5375 __put_user_4:
5376 - bic r2, sp, #0x1f00
5377 - bic r2, r2, #0x00ff
5378 - ldr r2, [r2, #TSK_ADDR_LIMIT]
5379 - sub r2, r2, #4
5380 - cmp r0, r2
5381 + bic ip, sp, #0x1f00
5382 + bic ip, ip, #0x00ff
5383 + ldr ip, [ip, #TSK_ADDR_LIMIT]
5384 + sub ip, ip, #4
5385 + cmp r0, ip
5386 4: strlst r1, [r0]
5387 movls r0, #0
5388 movls pc, lr
5389 --- linux-2.4.25/arch/arm/mach-integrator/pci_v3.c~2.4.25-vrs2.patch 2003-06-13 16:51:29.000000000 +0200
5390 +++ linux-2.4.25/arch/arm/mach-integrator/pci_v3.c 2004-03-31 17:15:09.000000000 +0200
5391 @@ -21,7 +21,6 @@
5392 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5394 #include <linux/config.h>
5395 -#include <linux/sched.h>
5396 #include <linux/kernel.h>
5397 #include <linux/pci.h>
5398 #include <linux/ptrace.h>
5399 @@ -32,6 +31,7 @@
5400 #include <linux/init.h>
5402 #include <asm/hardware.h>
5403 +#include <asm/io.h>
5404 #include <asm/irq.h>
5405 #include <asm/system.h>
5406 #include <asm/mach/pci.h>
5407 @@ -447,15 +447,16 @@
5408 #define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20)
5409 #define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24)
5411 -static int v3_fault(unsigned long addr, struct pt_regs *regs)
5412 +static int
5413 +v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
5415 unsigned long pc = instruction_pointer(regs);
5416 unsigned long instr = *(unsigned long *)pc;
5417 #if 0
5418 char buf[128];
5420 - sprintf(buf, "V3 fault: address=0x%08lx, pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
5421 - addr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
5422 + sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
5423 + addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
5424 v3_readb(V3_LB_ISTAT));
5425 printk(KERN_DEBUG "%s", buf);
5426 printascii(buf);
5427 @@ -523,8 +524,6 @@
5428 #endif
5431 -extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
5434 * V3_LB_BASE? - local bus address
5435 * V3_LB_MAP? - pci bus address
5436 @@ -539,7 +538,10 @@
5438 * Hook in our fault handler for PCI errors
5440 - external_fault = v3_fault;
5441 + hook_fault_code(4, v3_pci_fault, SIGBUS, "external abort on linefetch");
5442 + hook_fault_code(6, v3_pci_fault, SIGBUS, "external abort on linefetch");
5443 + hook_fault_code(8, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
5444 + hook_fault_code(10, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
5446 spin_lock_irqsave(&v3_lock, flags);
5448 @@ -629,7 +631,7 @@
5449 #if 0
5450 ret = request_irq(IRQ_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL);
5451 if (ret)
5452 - printk(KERN_ERR "PCI: unable to grab local bus timeout ".
5453 + printk(KERN_ERR "PCI: unable to grab local bus timeout "
5454 "interrupt: %d\n", ret);
5455 #endif
5457 --- linux-2.4.25/arch/arm/mach-sa1100/pm.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
5458 +++ linux-2.4.25/arch/arm/mach-sa1100/pm.c 2004-03-31 17:15:09.000000000 +0200
5459 @@ -21,6 +21,8 @@
5461 * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
5462 * Storage is local on the stack now.
5463 + * 2003-06-25: Jeff Corrall <jcorrall@mac.com>
5464 + * Saved the GPIO levels for resume after sleep.
5466 #include <linux/config.h>
5467 #include <linux/init.h>
5468 @@ -70,13 +72,20 @@
5469 int pm_do_suspend(void)
5471 unsigned long sleep_save[SLEEP_SAVE_SIZE];
5472 + unsigned long sleep_save_gpsr;
5473 + unsigned long sleep_save_gpcr;
5474 + unsigned long delta;
5476 cli();
5478 leds_event(led_stop);
5480 /* preserve current time */
5481 - RCNR = xtime.tv_sec;
5482 + delta = xtime.tv_sec - RCNR;
5484 + /* save the current state of the GPIO output pins */
5485 + sleep_save_gpsr = GPDR & GPLR;
5486 + sleep_save_gpcr = GPDR & ~GPLR;
5488 /* save vital registers */
5489 SAVE(OSCR);
5490 @@ -121,6 +130,10 @@
5491 printk(KERN_DEBUG "*** made it back from resume\n");
5492 #endif
5494 + /* restore GPIO output state before enabling the pins */
5495 + GPSR = sleep_save_gpsr;
5496 + GPCR = sleep_save_gpcr;
5498 /* restore registers */
5499 RESTORE(GPDR);
5500 RESTORE(GRER);
5501 @@ -151,7 +164,7 @@
5502 RESTORE(ICMR);
5504 /* restore current time */
5505 - xtime.tv_sec = RCNR;
5506 + xtime.tv_sec = RCNR + delta;
5508 leds_event(led_start);
5510 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
5511 +++ linux-2.4.25/arch/arm/mach-sa1100/sa1100_usb.h 2004-03-31 17:15:09.000000000 +0200
5512 @@ -0,0 +1,193 @@
5514 + * sa1100_usb.h
5516 + * Public interface to the sa1100 USB core. For use by client modules
5517 + * like usb-eth and usb-char.
5519 + */
5521 +#ifndef _SA1100_USB_H
5522 +#define _SA1100_USB_H
5523 +#include <asm/byteorder.h>
5525 +typedef void (*usb_callback_t)(int flag, int size);
5527 +/* in usb_ctl.c (see also descriptor methods at bottom of file) */
5529 +// Open the USB client for client and initialize data structures
5530 +// to default values, but _do not_ start UDC.
5531 +int sa1100_usb_open( const char * client_name );
5533 +// Start UDC running
5534 +int sa1100_usb_start( void );
5536 +// Immediately stop udc, fire off completion routines w/-EINTR
5537 +int sa1100_usb_stop( void ) ;
5539 +// Disconnect client from usb core
5540 +int sa1100_usb_close( void ) ;
5542 +// set notify callback for when core reaches configured state
5543 +// return previous pointer (if any)
5544 +typedef void (*usb_notify_t)(void);
5545 +usb_notify_t sa1100_set_configured_callback( usb_notify_t callback );
5547 +/* in usb_send.c */
5548 +int sa1100_usb_xmitter_avail( void );
5549 +int sa1100_usb_send(char *buf, int len, usb_callback_t callback);
5550 +void sa1100_usb_send_reset(void);
5552 +/* in usb_recev.c */
5553 +int sa1100_usb_recv(char *buf, int len, usb_callback_t callback);
5554 +void sa1100_usb_recv_reset(void);
5556 +//////////////////////////////////////////////////////////////////////////////
5557 +// Descriptor Management
5558 +//////////////////////////////////////////////////////////////////////////////
5560 +#define DescriptorHeader \
5561 + __u8 bLength; \
5562 + __u8 bDescriptorType
5565 +// --- Device Descriptor -------------------
5567 +typedef struct {
5568 + DescriptorHeader;
5569 + __u16 bcdUSB; /* USB specification revision number in BCD */
5570 + __u8 bDeviceClass; /* USB class for entire device */
5571 + __u8 bDeviceSubClass; /* USB subclass information for entire device */
5572 + __u8 bDeviceProtocol; /* USB protocol information for entire device */
5573 + __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */
5574 + __u16 idVendor; /* USB vendor ID */
5575 + __u16 idProduct; /* USB product ID */
5576 + __u16 bcdDevice; /* vendor assigned device release number */
5577 + __u8 iManufacturer; /* index of manufacturer string */
5578 + __u8 iProduct; /* index of string that describes product */
5579 + __u8 iSerialNumber; /* index of string containing device serial number */
5580 + __u8 bNumConfigurations; /* number fo configurations */
5581 +} __attribute__ ((packed)) device_desc_t;
5583 +// --- Configuration Descriptor ------------
5585 +typedef struct {
5586 + DescriptorHeader;
5587 + __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */
5588 + __u8 bNumInterfaces; /* number of interfaces in this cfg */
5589 + __u8 bConfigurationValue; /* used to uniquely ID this cfg */
5590 + __u8 iConfiguration; /* index of string describing configuration */
5591 + __u8 bmAttributes; /* bitmap of attributes for ths cfg */
5592 + __u8 MaxPower; /* power draw in 2ma units */
5593 +} __attribute__ ((packed)) config_desc_t;
5595 +// bmAttributes:
5596 +enum { USB_CONFIG_REMOTEWAKE=0x20, USB_CONFIG_SELFPOWERED=0x40,
5597 + USB_CONFIG_BUSPOWERED=0x80 };
5598 +// MaxPower:
5599 +#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */
5601 +// --- Interface Descriptor ---------------
5603 +typedef struct {
5604 + DescriptorHeader;
5605 + __u8 bInterfaceNumber; /* Index uniquely identfying this interface */
5606 + __u8 bAlternateSetting; /* ids an alternate setting for this interface */
5607 + __u8 bNumEndpoints; /* number of endpoints in this interface */
5608 + __u8 bInterfaceClass; /* USB class info applying to this interface */
5609 + __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */
5610 + __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */
5611 + __u8 iInterface; /* index of string describing interface */
5612 +} __attribute__ ((packed)) intf_desc_t;
5614 +// --- Endpoint Descriptor ---------------
5616 +typedef struct {
5617 + DescriptorHeader;
5618 + __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
5619 + __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
5620 + __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */
5621 + __u8 bInterval; /* polling interval for this ep in this cfg */
5622 +} __attribute__ ((packed)) ep_desc_t;
5624 +// bEndpointAddress:
5625 +enum { USB_OUT= 0, USB_IN=1 };
5626 +#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
5627 +// bmAttributes:
5628 +enum { USB_EP_CNTRL=0, USB_EP_BULK=2, USB_EP_INT=3 };
5630 +// --- String Descriptor -------------------
5632 +typedef struct {
5633 + DescriptorHeader;
5634 + __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */
5635 +} __attribute__ ((packed)) string_desc_t;
5637 +/*=======================================================
5638 + * Handy helpers when working with above
5640 + */
5641 +// these are x86-style 16 bit "words" ...
5642 +#define make_word_c( w ) __constant_cpu_to_le16(w)
5643 +#define make_word( w ) __cpu_to_le16(w)
5645 +// descriptor types
5646 +enum { USB_DESC_DEVICE=1, USB_DESC_CONFIG=2, USB_DESC_STRING=3,
5647 + USB_DESC_INTERFACE=4, USB_DESC_ENDPOINT=5 };
5650 +/*=======================================================
5651 + * Default descriptor layout for SA-1100 and SA-1110 UDC
5652 + */
5654 +/* "config descriptor buffer" - that is, one config,
5655 + ..one interface and 2 endpoints */
5656 +struct cdb {
5657 + config_desc_t cfg;
5658 + intf_desc_t intf;
5659 + ep_desc_t ep1;
5660 + ep_desc_t ep2;
5661 +} __attribute__ ((packed));
5664 +/* all SA device descriptors */
5665 +typedef struct {
5666 + device_desc_t dev; /* device descriptor */
5667 + struct cdb b; /* bundle of descriptors for this cfg */
5668 +} __attribute__ ((packed)) desc_t;
5671 +/*=======================================================
5672 + * Descriptor API
5673 + */
5675 +/* Get the address of the statically allocated desc_t structure
5676 + in the usb core driver. Clients can modify this between
5677 + the time they call sa1100_usb_open() and sa1100_usb_start()
5679 +desc_t *
5680 +sa1100_usb_get_descriptor_ptr( void );
5683 +/* Set a pointer to the string descriptor at "index". The driver
5684 + ..has room for 8 string indicies internally. Index zero holds
5685 + ..a LANGID code and is set to US English by default. Inidices
5686 + ..1-7 are available for use in the config descriptors as client's
5687 + ..see fit. This pointer is assumed to be good as long as the
5688 + ..SA usb core is open (so statically allocate them). Returnes -EINVAL
5689 + ..if index out of range */
5690 +int sa1100_usb_set_string_descriptor( int index, string_desc_t * p );
5692 +/* reverse of above */
5693 +string_desc_t *
5694 +sa1100_usb_get_string_descriptor( int index );
5696 +/* kmalloc() a string descriptor and convert "p" to unicode in it */
5697 +string_desc_t *
5698 +sa1100_usb_kmalloc_string_descriptor( const char * p );
5705 +#endif /* _SA1100_USB_H */
5706 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
5707 +++ linux-2.4.25/arch/arm/mach-sa1100/sa1111-ohci.c 2004-03-31 17:15:09.000000000 +0200
5708 @@ -0,0 +1,140 @@
5709 +#include <linux/config.h>
5710 +#include <linux/sched.h>
5711 +#include <linux/pci.h>
5712 +#include <linux/mm.h>
5714 +#ifdef CONFIG_USB_OHCI
5717 + * The SA-1111 errata says that the DMA hardware needs to be exercised
5718 + * before the clocks are turned on to work properly. This code does
5719 + * a tiny dma transfer to prime to hardware.
5721 + * What DMA errata? I've checked October 1999 and February 2001, both
5722 + * of which do not mention such a bug, let alone any details of this
5723 + * work-around.
5724 + */
5725 +static void __init sa1111_dma_setup(void)
5727 + dma_addr_t dma_buf;
5728 + void * vbuf;
5730 + /* DMA init & setup */
5732 + /* WARNING: The SA-1111 L3 function is used as part of this
5733 + * SA-1111 DMA errata workaround.
5735 + * N.B., When the L3 function is enabled, it uses GPIO_B<4:5>
5736 + * and takes precedence over the PS/2 mouse and GPIO_B
5737 + * functions. Refer to "Intel StrongARM SA-1111 Microprocessor
5738 + * Companion Chip, Sect 10.2" for details. So this "fix" may
5739 + * "break" support of either PS/2 mouse or GPIO_B if
5740 + * precautions are not taken to avoid collisions in
5741 + * configuration and use of these pins. AFAIK, no precautions
5742 + * are taken at this time. So it is likely that the action
5743 + * taken here may cause problems in PS/2 mouse and/or GPIO_B
5744 + * pin use elsewhere.
5746 + * But wait, there's more... What we're doing here is
5747 + * obviously altogether a bad idea. We're indiscrimanately bit
5748 + * flipping config for a few different functions here which
5749 + * are "owned" by other drivers. This needs to be handled
5750 + * better than it is being done here at this time. */
5752 + /* prime the dma engine with a tiny dma */
5753 + SKPCR |= SKPCR_I2SCLKEN;
5754 + SKAUD |= SKPCR_L3CLKEN | SKPCR_SCLKEN;
5756 + SACR0 |= 0x00003305;
5757 + SACR1 = 0x00000000;
5759 + /*
5760 + * We need memory below 1MB.
5761 + * NOTE: consistent_alloc gives you some random virtual
5762 + * address as its return value, and the DMA address via
5763 + * the dma_addr_t pointer.
5764 + */
5765 + vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf);
5767 + SADTSA = (unsigned long)dma_buf;
5768 + SADTCA = 4;
5770 + SADTCS |= 0x00000011;
5771 + SKPCR |= SKPCR_DCLKEN;
5773 + /* wait */
5774 + udelay(100);
5776 + /* clear reserved but, then disable SAC */
5777 + SACR0 &= ~(0x00000002);
5778 + SACR0 &= ~(0x00000001);
5780 + /* toggle bit clock direction */
5781 + SACR0 |= 0x00000004;
5782 + SACR0 &= ~(0x00000004);
5784 + SKAUD &= ~(SKPCR_L3CLKEN | SKPCR_SCLKEN);
5786 + SKPCR &= ~SKPCR_I2SCLKEN;
5788 + consistent_free(vbuf, 4, dma_buf);
5792 + * reset the SA-1111 usb controller and turn on it's clocks
5793 + */
5794 +int __init sa1111_ohci_hcd_init(void)
5796 + unsigned int usb_reset = 0;
5798 + if (machine_is_xp860() ||
5799 + machine_has_neponset() ||
5800 + machine_is_pfs168() ||
5801 + machine_is_badge4())
5802 + usb_reset = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
5804 + /*
5805 + * turn on USB clocks
5806 + */
5807 + SKPCR |= SKPCR_UCLKEN;
5808 + udelay(100);
5810 + /*
5811 + * Force USB reset
5812 + */
5813 + USB_RESET = USB_RESET_FORCEIFRESET;
5814 + USB_RESET |= USB_RESET_FORCEHCRESET;
5815 + udelay(100);
5817 + /*
5818 + * Take out of reset
5819 + */
5820 + USB_RESET = 0;
5822 + /*
5823 + * set power sense and control lines (this from the diags code)
5824 + */
5825 + USB_RESET = usb_reset;
5827 + /*
5828 + * Huh? This is a _read only_ register --rmk
5829 + */
5830 + USB_STATUS = 0;
5832 + udelay(10);
5834 + /*
5835 + * compensate for dma bug
5836 + */
5837 + sa1111_dma_setup();
5839 + return 0;
5842 +void sa1111_ohci_hcd_cleanup(void)
5844 + /* turn the USB clock off */
5845 + SKPCR &= ~SKPCR_UCLKEN;
5848 +#endif /* CONFIG_USB_OHCI */
5849 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
5850 +++ linux-2.4.25/arch/arm/mach-sa1100/usb-char.c 2004-03-31 17:15:09.000000000 +0200
5851 @@ -0,0 +1,723 @@
5853 + * (C) Copyright 2000-2001 Extenex Corporation
5855 + * This program is free software; you can redistribute it and/or modify
5856 + * it under the terms of the GNU General Public License as published by
5857 + * the Free Software Foundation; either version 2 of the License, or
5858 + * (at your option) any later version.
5860 + * This program is distributed in the hope that it will be useful,
5861 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5862 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5863 + * GNU General Public License for more details.
5865 + * You should have received a copy of the GNU General Public License
5866 + * along with this program; if not, write to the Free Software
5867 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5869 + * usb-char.c
5871 + * Miscellaneous character device interface for SA1100 USB function
5872 + * driver.
5874 + * Background:
5875 + * The SA1100 function driver ported from the Compaq Itsy project
5876 + * has an interface, usb-eth.c, to feed network packets over the
5877 + * usb wire and into the Linux TCP/IP stack.
5879 + * This file replaces that one with a simple character device
5880 + * interface that allows unstructured "byte pipe" style reads and
5881 + * writes over the USB bulk endpoints by userspace programs.
5883 + * A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
5884 + * when set, (the default) causes the ethernet interface to be used.
5885 + * When not set, this more pedestrian character interface is linked
5886 + * in instead.
5888 + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
5890 + * ward.willats@extenex.com
5892 + * To do:
5893 + * - Can't dma into ring buffer directly with pci_map/unmap usb_recv
5894 + * uses and get bytes out at the same time DMA is going on. Investigate:
5895 + * a) changing usb_recv to use alloc_consistent() at client request; or
5896 + * b) non-ring-buffer based data structures. In the meantime, I am using
5897 + * a bounce buffer. Simple, but wasteful.
5898 + */
5900 +#include <linux/module.h>
5901 +#include <linux/config.h>
5902 +#include <linux/miscdevice.h>
5903 +#include <linux/slab.h>
5904 +#include <linux/init.h>
5905 +#include <linux/cache.h>
5906 +#include <linux/poll.h>
5907 +#include <linux/circ_buf.h>
5908 +#include <linux/timer.h>
5910 +#include <asm/io.h>
5911 +#include <asm/semaphore.h>
5912 +#include <asm/proc/page.h>
5913 +#include <asm/mach-types.h>
5915 +#include "usb-char.h"
5916 +#include "sa1100_usb.h"
5920 +//////////////////////////////////////////////////////////////////////////////
5921 +// Driver Options
5922 +//////////////////////////////////////////////////////////////////////////////
5924 +#define VERSION "0.4"
5927 +#define VERBOSITY 1
5929 +#if VERBOSITY
5930 +# define PRINTK(x, a...) printk (x, ## a)
5931 +#else
5932 +# define PRINTK(x, a...) /**/
5933 +#endif
5935 +//////////////////////////////////////////////////////////////////////////////
5936 +// Globals - Macros - Enums - Structures
5937 +//////////////////////////////////////////////////////////////////////////////
5938 +#ifndef MIN
5939 +#define MIN( a, b ) ((a)<(b)?(a):(b))
5940 +#endif
5942 +typedef int bool; enum { false = 0, true = 1 };
5944 +static const char pszMe[] = "usbchr: ";
5946 +static wait_queue_head_t wq_read;
5947 +static wait_queue_head_t wq_write;
5948 +static wait_queue_head_t wq_poll;
5950 +/* Serialze multiple writers onto the transmit hardware
5951 +.. since we sleep the writer during transmit to stay in
5952 +.. sync. (Multiple writers don't make much sense, but..) */
5953 +static DECLARE_MUTEX( xmit_sem );
5955 +// size of usb DATA0/1 packets. 64 is standard maximum
5956 +// for bulk transport, though most hosts seem to be able
5957 +// to handle larger.
5958 +#define TX_PACKET_SIZE 64
5959 +#define RX_PACKET_SIZE 64
5960 +#define RBUF_SIZE (4*PAGE_SIZE)
5962 +static struct wcirc_buf {
5963 + char *buf;
5964 + int in;
5965 + int out;
5966 +} rx_ring = { NULL, 0, 0 };
5968 +static struct {
5969 + unsigned long cnt_rx_complete;
5970 + unsigned long cnt_rx_errors;
5971 + unsigned long bytes_rx;
5972 + unsigned long cnt_tx_timeouts;
5973 + unsigned long cnt_tx_errors;
5974 + unsigned long bytes_tx;
5975 +} charstats;
5978 +static char * tx_buf = NULL;
5979 +static char * packet_buffer = NULL;
5980 +static int sending = 0;
5981 +static int usb_ref_count = 0;
5982 +static int last_tx_result = 0;
5983 +static int last_rx_result = 0;
5984 +static int last_tx_size = 0;
5985 +static struct timer_list tx_timer;
5987 +//////////////////////////////////////////////////////////////////////////////
5988 +// Prototypes
5989 +//////////////////////////////////////////////////////////////////////////////
5990 +static char * what_the_f( int e );
5991 +static void free_txrx_buffers( void );
5992 +static void twiddle_descriptors( void );
5993 +static void free_string_descriptors( void ) ;
5994 +static int usbc_open( struct inode *pInode, struct file *pFile );
5995 +static void rx_done_callback_packet_buffer( int flag, int size );
5997 +static void tx_timeout( unsigned long );
5998 +static void tx_done_callback( int flag, int size );
6000 +static ssize_t usbc_read( struct file *, char *, size_t, loff_t * );
6001 +static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * );
6002 +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
6003 +static int usbc_ioctl( struct inode *pInode, struct file *pFile,
6004 + unsigned int nCmd, unsigned long argument );
6005 +static int usbc_close( struct inode *pInode, struct file *pFile );
6007 +#ifdef CONFIG_SA1100_EXTENEX1
6008 +static void extenex_configured_notify_proc( void );
6009 +#endif
6010 +//////////////////////////////////////////////////////////////////////////////
6011 +// Private Helpers
6012 +//////////////////////////////////////////////////////////////////////////////
6014 +static char * what_the_f( int e )
6016 + char * p;
6017 + switch( e ) {
6018 + case 0:
6019 + p = "noErr";
6020 + break;
6021 + case -ENODEV:
6022 + p = "ENODEV - usb not in config state";
6023 + break;
6024 + case -EBUSY:
6025 + p = "EBUSY - another request on the hardware";
6026 + break;
6027 + case -EAGAIN:
6028 + p = "EAGAIN";
6029 + break;
6030 + case -EINTR:
6031 + p = "EINTR - interrupted\n";
6032 + break;
6033 + case -EPIPE:
6034 + p = "EPIPE - zero length xfer\n";
6035 + break;
6036 + default:
6037 + p = "????";
6038 + break;
6040 + return p;
6043 +static void free_txrx_buffers( void )
6045 + if ( rx_ring.buf != NULL ) {
6046 + kfree( rx_ring.buf );
6047 + rx_ring.buf = NULL;
6049 + if ( packet_buffer != NULL ) {
6050 + kfree( packet_buffer );
6051 + packet_buffer = NULL;
6053 + if ( tx_buf != NULL ) {
6054 + kfree( tx_buf );
6055 + tx_buf = NULL;
6059 +/* twiddle_descriptors()
6060 + * It is between open() and start(). Setup descriptors.
6061 + */
6062 +static void twiddle_descriptors( void )
6064 + desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
6065 + string_desc_t * pString;
6067 + pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
6068 + pDesc->b.ep1.bmAttributes = USB_EP_BULK;
6069 + pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
6070 + pDesc->b.ep2.bmAttributes = USB_EP_BULK;
6072 + if ( machine_is_extenex1() ) {
6073 +#ifdef CONFIG_SA1100_EXTENEX1
6074 + pDesc->dev.idVendor = make_word_c( 0xC9F );
6075 + pDesc->dev.idProduct = 1;
6076 + pDesc->dev.bcdDevice = make_word_c( 0x0001 );
6077 + pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
6078 + pDesc->b.cfg.MaxPower = 0;
6080 + pString = sa1100_usb_kmalloc_string_descriptor( "Extenex" );
6081 + if ( pString ) {
6082 + sa1100_usb_set_string_descriptor( 1, pString );
6083 + pDesc->dev.iManufacturer = 1;
6086 + pString = sa1100_usb_kmalloc_string_descriptor( "Handheld Theater" );
6087 + if ( pString ) {
6088 + sa1100_usb_set_string_descriptor( 2, pString );
6089 + pDesc->dev.iProduct = 2;
6092 + pString = sa1100_usb_kmalloc_string_descriptor( "00000000" );
6093 + if ( pString ) {
6094 + sa1100_usb_set_string_descriptor( 3, pString );
6095 + pDesc->dev.iSerialNumber = 3;
6098 + pString = sa1100_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
6099 + if ( pString ) {
6100 + sa1100_usb_set_string_descriptor( 4, pString );
6101 + pDesc->b.intf.iInterface = 4;
6103 + sa1100_set_configured_callback( extenex_configured_notify_proc );
6104 +#endif
6108 +static void free_string_descriptors( void )
6110 + if ( machine_is_extenex1() ) {
6111 + string_desc_t * pString;
6112 + int i;
6113 + for( i = 1 ; i <= 4 ; i++ ) {
6114 + pString = sa1100_usb_get_string_descriptor( i );
6115 + if ( pString )
6116 + kfree( pString );
6121 +//////////////////////////////////////////////////////////////////////////////
6122 +// ASYNCHRONOUS
6123 +//////////////////////////////////////////////////////////////////////////////
6124 +static void kick_start_rx( void )
6126 + if ( usb_ref_count ) {
6127 + int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
6128 + if ( total_space >= RX_PACKET_SIZE ) {
6129 + sa1100_usb_recv( packet_buffer,
6130 + RX_PACKET_SIZE,
6131 + rx_done_callback_packet_buffer
6132 + );
6137 + * rx_done_callback_packet_buffer()
6138 + * We have completed a DMA xfer into the temp packet buffer.
6139 + * Move to ring.
6141 + * flag values:
6142 + * on init, -EAGAIN
6143 + * on reset, -EINTR
6144 + * on RPE, -EIO
6145 + * on short packet -EPIPE
6146 + */
6147 +static void
6148 +rx_done_callback_packet_buffer( int flag, int size )
6150 + charstats.cnt_rx_complete++;
6152 + if ( flag == 0 || flag == -EPIPE ) {
6153 + size_t n;
6155 + charstats.bytes_rx += size;
6157 + n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
6158 + n = MIN( n, size );
6159 + size -= n;
6161 + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
6162 + rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
6163 + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
6164 + rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
6166 + wake_up_interruptible( &wq_read );
6167 + wake_up_interruptible( &wq_poll );
6169 + last_rx_result = 0;
6171 + kick_start_rx();
6173 + } else if ( flag != -EAGAIN ) {
6174 + charstats.cnt_rx_errors++;
6175 + last_rx_result = flag;
6176 + wake_up_interruptible( &wq_read );
6177 + wake_up_interruptible( &wq_poll );
6179 + else /* init, start a read */
6180 + kick_start_rx();
6184 +static void tx_timeout( unsigned long unused )
6186 + printk( "%stx timeout\n", pszMe );
6187 + sa1100_usb_send_reset();
6188 + charstats.cnt_tx_timeouts++;
6192 +// on init, -EAGAIN
6193 +// on reset, -EINTR
6194 +// on TPE, -EIO
6195 +static void tx_done_callback( int flags, int size )
6197 + if ( flags == 0 )
6198 + charstats.bytes_tx += size;
6199 + else
6200 + charstats.cnt_tx_errors++;
6201 + last_tx_size = size;
6202 + last_tx_result = flags;
6203 + sending = 0;
6204 + wake_up_interruptible( &wq_write );
6205 + wake_up_interruptible( &wq_poll );
6209 +//////////////////////////////////////////////////////////////////////////////
6210 +// Workers
6211 +//////////////////////////////////////////////////////////////////////////////
6213 +static int usbc_open( struct inode *pInode, struct file *pFile )
6215 + int retval = 0;
6217 + PRINTK( KERN_DEBUG "%sopen()\n", pszMe );
6219 + /* start usb core */
6220 + retval = sa1100_usb_open( "usb-char" );
6221 + if ( retval ) return retval;
6223 + /* allocate memory */
6224 + if ( usb_ref_count == 0 ) {
6225 + tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
6226 + if ( tx_buf == NULL ) {
6227 + printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );
6228 + goto malloc_fail;
6230 + rx_ring.buf =
6231 + (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
6233 + if ( rx_ring.buf == NULL ) {
6234 + printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );
6235 + goto malloc_fail;
6238 + packet_buffer =
6239 + (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
6241 + if ( packet_buffer == NULL ) {
6242 + printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe );
6243 + goto malloc_fail;
6245 + rx_ring.in = rx_ring.out = 0;
6246 + memset( &charstats, 0, sizeof( charstats ) );
6247 + sending = 0;
6248 + last_tx_result = 0;
6249 + last_tx_size = 0;
6252 + /* modify default descriptors */
6253 + twiddle_descriptors();
6255 + retval = sa1100_usb_start();
6256 + if ( retval ) {
6257 + printk( "%sAGHH! Could not USB core\n", pszMe );
6258 + free_txrx_buffers();
6259 + return retval;
6261 + usb_ref_count++; /* must do _before_ kick_start() */
6262 + MOD_INC_USE_COUNT;
6263 + kick_start_rx();
6264 + return 0;
6266 + malloc_fail:
6267 + free_txrx_buffers();
6268 + return -ENOMEM;
6272 + * Read endpoint. Note that you can issue a read to an
6273 + * unconfigured endpoint. Eventually, the host may come along
6274 + * and configure underneath this module and data will appear.
6275 + */
6276 +static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
6277 + size_t stCount, loff_t *pPos )
6279 + ssize_t retval;
6280 + int flags;
6281 + DECLARE_WAITQUEUE( wait, current );
6283 + PRINTK( KERN_DEBUG "%sread()\n", pszMe );
6285 + local_irq_save( flags );
6286 + if ( last_rx_result == 0 ) {
6287 + local_irq_restore( flags );
6288 + } else { /* an error happended and receiver is paused */
6289 + local_irq_restore( flags );
6290 + last_rx_result = 0;
6291 + kick_start_rx();
6294 + add_wait_queue( &wq_read, &wait );
6295 + while( 1 ) {
6296 + ssize_t bytes_avail;
6297 + ssize_t bytes_to_end;
6299 + set_current_state( TASK_INTERRUPTIBLE );
6301 + /* snap ring buf state */
6302 + local_irq_save( flags );
6303 + bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
6304 + bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
6305 + local_irq_restore( flags );
6307 + if ( bytes_avail != 0 ) {
6308 + ssize_t bytes_to_move = MIN( stCount, bytes_avail );
6309 + retval = 0; // will be bytes transfered
6310 + if ( bytes_to_move != 0 ) {
6311 + size_t n = MIN( bytes_to_end, bytes_to_move );
6312 + if ( copy_to_user( pUserBuffer,
6313 + &rx_ring.buf[ rx_ring.out ],
6314 + n ) ) {
6315 + retval = -EFAULT;
6316 + break;
6318 + bytes_to_move -= n;
6319 + retval += n;
6320 + // might go 1 char off end, so wrap
6321 + rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
6322 + if ( copy_to_user( pUserBuffer + n,
6323 + &rx_ring.buf[ rx_ring.out ],
6324 + bytes_to_move )
6325 + ) {
6326 + retval = -EFAULT;
6327 + break;
6329 + rx_ring.out += bytes_to_move; // cannot wrap
6330 + retval += bytes_to_move;
6331 + kick_start_rx();
6333 + break;
6335 + else if ( last_rx_result ) {
6336 + retval = last_rx_result;
6337 + break;
6339 + else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep
6340 + retval = -EAGAIN;
6341 + break;
6343 + else if ( signal_pending( current ) ) { // no data, can sleep, but signal
6344 + retval = -ERESTARTSYS;
6345 + break;
6347 + schedule(); // no data, can sleep
6349 + set_current_state( TASK_RUNNING );
6350 + remove_wait_queue( &wq_read, &wait );
6352 + if ( retval < 0 )
6353 + printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );
6354 + return retval;
6358 + * Write endpoint. This routine attempts to break the passed in buffer
6359 + * into usb DATA0/1 packet size chunks and send them to the host.
6360 + * (The lower-level driver tries to do this too, but easier for us
6361 + * to manage things here.)
6363 + * We are at the mercy of the host here, in that it must send an IN
6364 + * token to us to pull this data back, so hopefully some higher level
6365 + * protocol is expecting traffic to flow in that direction so the host
6366 + * is actually polling us. To guard against hangs, a 5 second timeout
6367 + * is used.
6369 + * This routine takes some care to only report bytes sent that have
6370 + * actually made it across the wire. Thus we try to stay in lockstep
6371 + * with the completion routine and only have one packet on the xmit
6372 + * hardware at a time. Multiple simultaneous writers will get
6373 + * "undefined" results.
6375 + */
6376 +static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer,
6377 + size_t stCount, loff_t *pPos )
6379 + ssize_t retval = 0;
6380 + ssize_t stSent = 0;
6382 + DECLARE_WAITQUEUE( wait, current );
6384 + PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount );
6386 + down( &xmit_sem ); // only one thread onto the hardware at a time
6388 + while( stCount != 0 && retval == 0 ) {
6389 + int nThisTime = MIN( TX_PACKET_SIZE, stCount );
6390 + copy_from_user( tx_buf, pUserBuffer, nThisTime );
6391 + sending = nThisTime;
6392 + retval = sa1100_usb_send( tx_buf, nThisTime, tx_done_callback );
6393 + if ( retval < 0 ) {
6394 + char * p = what_the_f( retval );
6395 + printk( "%sCould not queue xmission. rc=%d - %s\n",
6396 + pszMe, retval, p );
6397 + sending = 0;
6398 + break;
6400 + /* now have something on the diving board */
6401 + add_wait_queue( &wq_write, &wait );
6402 + tx_timer.expires = jiffies + ( HZ * 5 );
6403 + add_timer( &tx_timer );
6404 + while( 1 ) {
6405 + set_current_state( TASK_INTERRUPTIBLE );
6406 + if ( sending == 0 ) { /* it jumped into the pool */
6407 + del_timer( &tx_timer );
6408 + retval = last_tx_result;
6409 + if ( retval == 0 ) {
6410 + stSent += last_tx_size;
6411 + pUserBuffer += last_tx_size;
6412 + stCount -= last_tx_size;
6414 + else
6415 + printk( "%sxmission error rc=%d - %s\n",
6416 + pszMe, retval, what_the_f(retval) );
6417 + break;
6419 + else if ( signal_pending( current ) ) {
6420 + del_timer( &tx_timer );
6421 + printk( "%ssignal\n", pszMe );
6422 + retval = -ERESTARTSYS;
6423 + break;
6425 + schedule();
6427 + set_current_state( TASK_RUNNING );
6428 + remove_wait_queue( &wq_write, &wait );
6431 + up( &xmit_sem );
6433 + if ( 0 == retval )
6434 + retval = stSent;
6435 + return retval;
6438 +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
6440 + unsigned int retval = 0;
6442 + PRINTK( KERN_DEBUG "%poll()\n", pszMe );
6444 + poll_wait( pFile, &wq_poll, pWait );
6446 + if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
6447 + retval |= POLLIN | POLLRDNORM;
6448 + if ( sa1100_usb_xmitter_avail() )
6449 + retval |= POLLOUT | POLLWRNORM;
6450 + return retval;
6453 +static int usbc_ioctl( struct inode *pInode, struct file *pFile,
6454 + unsigned int nCmd, unsigned long argument )
6456 + int retval = 0;
6458 + switch( nCmd ) {
6460 + case USBC_IOC_FLUSH_RECEIVER:
6461 + sa1100_usb_recv_reset();
6462 + rx_ring.in = rx_ring.out = 0;
6463 + break;
6465 + case USBC_IOC_FLUSH_TRANSMITTER:
6466 + sa1100_usb_send_reset();
6467 + break;
6469 + case USBC_IOC_FLUSH_ALL:
6470 + sa1100_usb_recv_reset();
6471 + rx_ring.in = rx_ring.out = 0;
6472 + sa1100_usb_send_reset();
6473 + break;
6475 + default:
6476 + retval = -ENOIOCTLCMD;
6477 + break;
6480 + return retval;
6484 +static int usbc_close( struct inode *pInode, struct file * pFile )
6486 + PRINTK( KERN_DEBUG "%sclose()\n", pszMe );
6487 + if ( --usb_ref_count == 0 ) {
6488 + down( &xmit_sem );
6489 + sa1100_usb_stop();
6490 + free_txrx_buffers();
6491 + free_string_descriptors();
6492 + del_timer( &tx_timer );
6493 + sa1100_usb_close();
6494 + up( &xmit_sem );
6496 + MOD_DEC_USE_COUNT;
6497 + return 0;
6500 +#ifdef CONFIG_SA1100_EXTENEX1
6501 +#include "../../../drivers/char/ex_gpio.h"
6502 +void extenex_configured_notify_proc( void )
6504 + if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
6505 + printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe );
6507 +#endif
6508 +//////////////////////////////////////////////////////////////////////////////
6509 +// Initialization
6510 +//////////////////////////////////////////////////////////////////////////////
6512 +static struct file_operations usbc_fops = {
6513 + owner: THIS_MODULE,
6514 + open: usbc_open,
6515 + read: usbc_read,
6516 + write: usbc_write,
6517 + poll: usbc_poll,
6518 + ioctl: usbc_ioctl,
6519 + release: usbc_close,
6522 +static struct miscdevice usbc_misc_device = {
6523 + USBC_MINOR, "usb_char", &usbc_fops
6527 + * usbc_init()
6528 + */
6530 +int __init usbc_init( void )
6532 + int rc;
6534 +#if !defined( CONFIG_ARCH_SA1100 )
6535 + return -ENODEV;
6536 +#endif
6538 + if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
6539 + printk( KERN_WARNING "%sCould not register device 10, "
6540 + "%d. (%d)\n", pszMe, USBC_MINOR, rc );
6541 + return -EBUSY;
6544 + // initialize wait queues
6545 + init_waitqueue_head( &wq_read );
6546 + init_waitqueue_head( &wq_write );
6547 + init_waitqueue_head( &wq_poll );
6549 + // initialize tx timeout timer
6550 + init_timer( &tx_timer );
6551 + tx_timer.function = tx_timeout;
6553 + printk( KERN_INFO "USB Function Character Driver Interface"
6554 + " - %s, (C) 2001, Extenex Corp.\n", VERSION
6555 + );
6557 + return rc;
6560 +void __exit usbc_exit( void )
6564 +EXPORT_NO_SYMBOLS;
6566 +module_init(usbc_init);
6567 +module_exit(usbc_exit);
6571 +// end: usb-char.c
6575 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
6576 +++ linux-2.4.25/arch/arm/mach-sa1100/usb-char.h 2004-03-31 17:15:09.000000000 +0200
6577 @@ -0,0 +1,34 @@
6579 + * Copyright (C) 2001 Extenex Corporation
6581 + * usb-char.h
6583 + * Character device emulation client for SA-1100 client usb core.
6587 + */
6588 +#ifndef _USB_CHAR_H
6589 +#define _USB_CHAR_H
6591 +#define USBC_MAJOR 10 /* miscellaneous character device */
6592 +#define USBC_MINOR 240 /* in the "reserved for local use" range */
6594 +#define USBC_MAGIC 0x8E
6596 +/* zap everything in receive ring buffer */
6597 +#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 )
6599 +/* reset transmitter */
6600 +#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 )
6602 +/* do both of above */
6603 +#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 )
6610 +#endif /* _USB_CHAR_H */
6612 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
6613 +++ linux-2.4.25/arch/arm/mach-sa1100/usb-eth.c 2004-03-31 17:15:09.000000000 +0200
6614 @@ -0,0 +1,447 @@
6615 + /*
6616 + * Ethernet driver for the SA1100 USB client function
6617 + * Copyright (c) 2001 by Nicolas Pitre
6619 + * This code was loosely inspired by the original initial ethernet test driver
6620 + * Copyright (c) Compaq Computer Corporation, 1999
6622 + * This program is free software; you can redistribute it and/or modify
6623 + * it under the terms of the GNU General Public License version 2 as
6624 + * published by the Free Software Foundation.
6626 + * This is still work in progress...
6628 + * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
6629 + * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
6630 + * Now, since we do not know what size of packet we are receiving
6631 + * last usb packet in sequence will always be less than max packet
6632 + * receive endpoint can accept.
6633 + * Now the only way to check correct start of frame is to compare
6634 + * MAC address. Also now we are stalling on each receive error.
6636 + * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
6637 + * aligned buffer, but this breaks IP code (unaligned access).
6639 + * 01/04/2001 - stall endpoint operations appeared to be very unstable, so
6640 + * they are disabled now.
6642 + * 03/06/2001 - Readded "zerocopy" receive path (tunable).
6644 + */
6646 +// Define DMA_NO_COPY if you want data to arrive directly into the
6647 +// receive network buffers, instead of arriving into bounce buffer
6648 +// and then get copied to network buffer.
6649 +// This does not work correctly right now.
6650 +#undef DMA_NO_COPY
6652 +#include <linux/module.h>
6653 +#include <linux/init.h>
6654 +#include <linux/sched.h>
6655 +#include <linux/kernel.h>
6656 +#include <linux/errno.h>
6657 +#include <linux/timer.h>
6659 +#include <linux/netdevice.h>
6660 +#include <linux/etherdevice.h>
6661 +#include <linux/skbuff.h>
6662 +#include <linux/random.h>
6664 +#include "sa1100_usb.h"
6667 +#define ETHERNET_VENDOR_ID 0x49f
6668 +#define ETHERNET_PRODUCT_ID 0x505A
6669 +#define MAX_PACKET 32768
6670 +#define MIN(a, b) (((a) < (b)) ? (a) : (b))
6672 +// Should be global, so that insmod can change these
6673 +int usb_rsize=64;
6674 +int usb_wsize=64;
6676 +static struct usbe_info_t {
6677 + struct net_device *dev;
6678 + u16 packet_id;
6679 + struct net_device_stats stats;
6680 +} usbe_info;
6682 +static char usb_eth_name[16] = "usbf";
6683 +static struct net_device usb_eth_device;
6684 +static struct sk_buff *cur_tx_skb, *next_tx_skb;
6685 +static struct sk_buff *cur_rx_skb, *next_rx_skb;
6686 +static volatile int terminating;
6687 +#ifndef DMA_NO_COPY
6688 +static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
6689 +#endif
6691 +static int usb_change_mtu (struct net_device *net, int new_mtu)
6693 + if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
6694 + return -EINVAL;
6695 + // no second zero-length packet read wanted after mtu-sized packets
6696 + if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
6697 + return -EDOM;
6699 + net->mtu = new_mtu;
6700 + return 0;
6703 +static struct sk_buff *
6704 +usb_new_recv_skb(void)
6706 + struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
6708 + if (skb) {
6709 + skb_reserve(skb, 2);
6711 + return skb;
6714 +static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
6715 +static void
6716 +usb_recv_callback(int flag, int size)
6718 + struct sk_buff *skb;
6720 + if (terminating)
6721 + return;
6723 + skb = cur_rx_skb;
6725 + /* flag validation */
6726 + if (flag == 0) {
6727 + if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
6728 + usbe_info.stats.rx_over_errors++;
6729 + goto error;
6731 +#ifndef DMA_NO_COPY
6732 + memcpy(skb->tail,dmabuf,size);
6733 +#endif
6734 + skb_put(skb, size);
6735 + } else {
6736 + if (flag == -EIO) {
6737 + usbe_info.stats.rx_errors++;
6739 + goto error;
6742 + /* validate packet length */
6743 + if (size == usb_rsize ) {
6744 + /* packet not complete yet */
6745 + skb = NULL;
6748 + /*
6749 + * At this point skb is non null if we have a complete packet.
6750 + * If so take a fresh skb right away and restart USB receive without
6751 + * further delays, then process the packet. Otherwise resume USB
6752 + * receive on the current skb and exit.
6753 + */
6755 + if (skb)
6756 + cur_rx_skb = next_rx_skb;
6757 +#ifndef DMA_NO_COPY
6758 + sa1100_usb_recv(dmabuf, usb_rsize,
6759 + usb_recv_callback);
6760 +#else
6761 + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
6762 + usb_recv_callback);
6763 +#endif
6764 + if (!skb)
6765 + return;
6767 + next_rx_skb = usb_new_recv_skb();
6768 + if (!next_rx_skb) {
6769 + /*
6770 + * We can't aford loosing buffer space...
6771 + * So we drop the current packet and recycle its skb.
6772 + */
6773 + printk("%s: can't allocate new skb\n", __FUNCTION__);
6774 + usbe_info.stats.rx_dropped++;
6775 + skb_trim(skb, 0);
6776 + next_rx_skb = skb;
6777 + return;
6779 + if ( skb->len >= sizeof(struct ethhdr)) {
6780 + if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
6781 + // This frame is not for us. nor it is broadcast
6782 + usbe_info.stats.rx_frame_errors++;
6783 + kfree_skb(skb);
6784 + goto error;
6788 + if (skb->len) {
6789 + int status;
6790 +// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
6792 + skb->dev = &usb_eth_device;
6793 + skb->protocol = eth_type_trans (skb, &usb_eth_device);
6794 + usbe_info.stats.rx_packets++;
6795 + usbe_info.stats.rx_bytes += skb->len;
6796 + skb->ip_summed = CHECKSUM_NONE;
6797 + status = netif_rx (skb);
6798 + if (status != NET_RX_SUCCESS)
6799 + printk("netif_rx failed with code %d\n",status);
6800 + } else {
6801 +error:
6802 + /*
6803 + * Error due to HW addr mismatch, or IO error.
6804 + * Recycle the current skb and reset USB reception.
6805 + */
6806 + skb_trim(cur_rx_skb, 0);
6807 +// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
6808 +#ifndef DMA_NO_COPY
6809 + sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
6810 +#else
6811 + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback);
6812 +#endif
6817 +static void
6818 +usb_send_callback(int flag, int size)
6820 + struct net_device *dev = usbe_info.dev;
6821 + struct net_device_stats *stats;
6822 + struct sk_buff *skb=cur_tx_skb;
6823 + int ret;
6825 + if (terminating)
6826 + return;
6828 + stats = &usbe_info.stats;
6829 + switch (flag) {
6830 + case 0:
6831 + stats->tx_packets++;
6832 + stats->tx_bytes += size;
6833 + break;
6834 + case -EIO:
6835 + stats->tx_errors++;
6836 + break;
6837 + default:
6838 + stats->tx_dropped++;
6839 + break;
6842 + cur_tx_skb = next_tx_skb;
6843 + next_tx_skb = NULL;
6844 + dev_kfree_skb_irq(skb);
6845 + if (!cur_tx_skb)
6846 + return;
6848 + dev->trans_start = jiffies;
6849 + ret = sa1100_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback);
6850 + if (ret) {
6851 + /* If the USB core can't accept the packet, we drop it. */
6852 + dev_kfree_skb_irq(cur_tx_skb);
6853 + cur_tx_skb = NULL;
6854 + usbe_info.stats.tx_carrier_errors++;
6856 + netif_wake_queue(dev);
6859 +static int
6860 +usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
6862 + int ret;
6863 + unsigned long flags;
6865 + if (next_tx_skb) {
6866 + printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
6867 + return 1;
6870 + if (skb_shared (skb)) {
6871 + struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC);
6872 + if (!skb2) {
6873 + usbe_info.stats.tx_dropped++;
6874 + dev_kfree_skb(skb);
6875 + return 1;
6877 + skb = skb2;
6880 + if ((skb->len % usb_wsize) == 0) {
6881 + skb->len++; // other side will ignore this one, anyway.
6884 + local_irq_save(flags);
6885 + if (cur_tx_skb) {
6886 + next_tx_skb = skb;
6887 + netif_stop_queue(dev);
6888 + } else {
6889 + cur_tx_skb = skb;
6890 + dev->trans_start = jiffies;
6891 + ret = sa1100_usb_send(skb->data, skb->len, usb_send_callback);
6892 + if (ret) {
6893 + /* If the USB core can't accept the packet, we drop it. */
6894 + dev_kfree_skb(skb);
6895 + cur_tx_skb = NULL;
6896 + usbe_info.stats.tx_carrier_errors++;
6899 + local_irq_restore(flags);
6900 + return 0;
6903 +static void
6904 +usb_xmit_timeout(struct net_device *dev )
6906 + sa1100_usb_send_reset();
6907 + dev->trans_start = jiffies;
6908 + netif_wake_queue(dev);
6912 +static int
6913 +usb_eth_open(struct net_device *dev)
6915 + terminating = 0;
6916 + cur_tx_skb = next_tx_skb = NULL;
6917 + cur_rx_skb = usb_new_recv_skb();
6918 + next_rx_skb = usb_new_recv_skb();
6919 + if (!cur_rx_skb || !next_rx_skb) {
6920 + printk("%s: can't allocate new skb\n", __FUNCTION__);
6921 + if (cur_rx_skb)
6922 + kfree_skb(cur_rx_skb);
6923 + if (next_rx_skb)
6924 + kfree_skb(next_rx_skb);
6925 + return -ENOMEM;;
6928 + MOD_INC_USE_COUNT;
6929 +#ifndef DMA_NO_COPY
6930 + sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
6931 +#else
6932 + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
6933 + usb_recv_callback);
6934 +#endif
6935 + return 0;
6938 +static int
6939 +usb_eth_release(struct net_device *dev)
6941 + terminating = 1;
6942 + sa1100_usb_send_reset();
6943 + sa1100_usb_recv_reset();
6944 + if (cur_tx_skb)
6945 + kfree_skb(cur_tx_skb);
6946 + if (next_tx_skb)
6947 + kfree_skb(next_tx_skb);
6948 + if (cur_rx_skb)
6949 + kfree_skb(cur_rx_skb);
6950 + if (next_rx_skb)
6951 + kfree_skb(next_rx_skb);
6952 + MOD_DEC_USE_COUNT;
6953 + return 0;
6956 +static struct net_device_stats *
6957 +usb_eth_stats(struct net_device *dev)
6959 + struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv;
6960 + struct net_device_stats *stats=NULL;
6962 + if (priv)
6963 + stats = &priv->stats;
6964 + return stats;
6967 +static int
6968 +usb_eth_probe(struct net_device *dev)
6970 + u8 node_id [ETH_ALEN];
6972 + get_random_bytes (node_id, sizeof node_id);
6973 + node_id [0] &= 0xfe; // clear multicast bit
6975 + /*
6976 + * Assign the hardware address of the board:
6977 + * generate it randomly, as there can be many such
6978 + * devices on the bus.
6979 + */
6980 + memcpy (dev->dev_addr, node_id, sizeof node_id);
6982 + dev->open = usb_eth_open;
6983 + dev->change_mtu = usb_change_mtu;
6984 + dev->stop = usb_eth_release;
6985 + dev->hard_start_xmit = usb_eth_xmit;
6986 + dev->get_stats = usb_eth_stats;
6987 + dev->watchdog_timeo = 1*HZ;
6988 + dev->tx_timeout = usb_xmit_timeout;
6989 + dev->priv = &usbe_info;
6991 + usbe_info.dev = dev;
6993 + /* clear the statistics */
6994 + memset(&usbe_info.stats, 0, sizeof(struct net_device_stats));
6996 + ether_setup(dev);
6997 + dev->flags &= ~IFF_MULTICAST;
6998 + dev->flags &= ~IFF_BROADCAST;
6999 + //dev->flags |= IFF_NOARP;
7001 + return 0;
7004 +#ifdef MODULE
7005 +MODULE_PARM(usb_rsize, "1i");
7006 +MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to sa1100");
7007 +MODULE_PARM(usb_wsize, "1i");
7008 +MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from sa1100 to host");
7009 +#endif
7011 +static int __init
7012 +usb_eth_init(void)
7014 + int rc;
7016 +#ifndef DMA_NO_COPY
7017 + dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
7018 + if (!dmabuf)
7019 + return -ENOMEM;
7020 +#endif
7021 + strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
7022 + usb_eth_device.init = usb_eth_probe;
7023 + if (register_netdev(&usb_eth_device) != 0)
7024 + return -EIO;
7026 + rc = sa1100_usb_open( "usb-eth" );
7027 + if ( rc == 0 ) {
7028 + string_desc_t * pstr;
7029 + desc_t * pd = sa1100_usb_get_descriptor_ptr();
7031 + pd->b.ep1.wMaxPacketSize = make_word( usb_rsize );
7032 + pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
7033 + pd->dev.idVendor = ETHERNET_VENDOR_ID;
7034 + pd->dev.idProduct = ETHERNET_PRODUCT_ID;
7035 + pstr = sa1100_usb_kmalloc_string_descriptor( "SA1100 USB NIC" );
7036 + if ( pstr ) {
7037 + sa1100_usb_set_string_descriptor( 1, pstr );
7038 + pd->dev.iProduct = 1;
7040 + rc = sa1100_usb_start();
7042 + return rc;
7045 +module_init(usb_eth_init);
7047 +static void __exit
7048 +usb_eth_cleanup(void)
7050 + string_desc_t * pstr;
7051 + sa1100_usb_stop();
7052 + sa1100_usb_close();
7053 + if ( (pstr = sa1100_usb_get_string_descriptor(1)) != NULL )
7054 + kfree( pstr );
7055 +#ifndef DMA_NO_COPY
7056 + kfree(dmabuf);
7057 +#endif
7058 + unregister_netdev(&usb_eth_device);
7061 +module_exit(usb_eth_cleanup);
7062 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
7063 +++ linux-2.4.25/arch/arm/mach-sa1100/usb_ctl.c 2004-03-31 17:15:09.000000000 +0200
7064 @@ -0,0 +1,774 @@
7065 + /*
7066 + * Copyright (C) Compaq Computer Corporation, 1998, 1999
7067 + * Copyright (C) Extenex Corporation, 2001
7069 + * usb_ctl.c
7071 + * SA1100 USB controller core driver.
7073 + * This file provides interrupt routing and overall coordination
7074 + * of the three endpoints in usb_ep0, usb_receive (1), and usb_send (2).
7076 + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
7078 + */
7079 +#include <linux/config.h>
7080 +#include <linux/module.h>
7081 +#include <linux/init.h>
7082 +#include <linux/proc_fs.h>
7083 +#include <linux/tqueue.h>
7084 +#include <linux/delay.h>
7085 +#include <linux/sched.h>
7086 +#include <linux/slab.h>
7087 +#include <asm/io.h>
7088 +#include <asm/dma.h>
7089 +#include <asm/irq.h>
7090 +#include <asm/mach-types.h>
7092 +#include "sa1100_usb.h"
7093 +#include "usb_ctl.h"
7095 +//////////////////////////////////////////////////////////////////////////////
7096 +// Prototypes
7097 +//////////////////////////////////////////////////////////////////////////////
7099 +int usbctl_next_state_on_event( int event );
7100 +static void udc_int_hndlr(int, void *, struct pt_regs *);
7101 +static void initialize_descriptors( void );
7102 +static void soft_connect_hook( int enable );
7103 +static void udc_disable(void);
7104 +static void udc_enable(void);
7106 +#if CONFIG_PROC_FS
7107 +#define PROC_NODE_NAME "sausb"
7108 +static int usbctl_read_proc(char *page, char **start, off_t off,
7109 + int count, int *eof, void *data);
7110 +#endif
7112 +//////////////////////////////////////////////////////////////////////////////
7113 +// Globals
7114 +//////////////////////////////////////////////////////////////////////////////
7115 +static const char pszMe[] = "usbctl: ";
7116 +struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */
7118 +/* device descriptors */
7119 +static desc_t desc;
7121 +#define MAX_STRING_DESC 8
7122 +static string_desc_t * string_desc_array[ MAX_STRING_DESC ];
7123 +static string_desc_t sd_zero; /* special sd_zero holds language codes */
7125 +// called when configured
7126 +static usb_notify_t configured_callback = NULL;
7128 +enum { kStateZombie = 0, kStateZombieSuspend = 1,
7129 + kStateDefault = 2, kStateDefaultSuspend = 3,
7130 + kStateAddr = 4, kStateAddrSuspend = 5,
7131 + kStateConfig = 6, kStateConfigSuspend = 7
7134 +static int device_state_machine[8][6] = {
7135 +// suspend reset resume adddr config deconfig
7136 +/* zombie */ { kStateZombieSuspend, kStateDefault, kError, kError, kError, kError },
7137 +/* zom sus */ { kError, kStateDefault, kStateZombie, kError, kError, kError },
7138 +/* default */ { kStateDefaultSuspend, kError, kStateDefault, kStateAddr, kError, kError },
7139 +/* def sus */ { kError, kStateDefault, kStateDefault, kError, kError, kError },
7140 +/* addr */ { kStateAddrSuspend, kStateDefault, kError, kError, kStateConfig, kError },
7141 +/* addr sus */{ kError, kStateDefault, kStateAddr, kError, kError, kError },
7142 +/* config */ { kStateConfigSuspend, kStateDefault, kError, kError, kError, kStateAddr },
7143 +/* cfg sus */ { kError, kStateDefault, kStateConfig, kError, kError, kError }
7146 +/* "device state" is the usb device framework state, as opposed to the
7147 + "state machine state" which is whatever the driver needs and is much
7148 + more fine grained
7150 +static int sm_state_to_device_state[8] =
7151 +// zombie zom suspend default default sus
7152 +{ USB_STATE_POWERED, USB_STATE_SUSPENDED, USB_STATE_DEFAULT, USB_STATE_SUSPENDED,
7153 +// addr addr sus config config sus
7154 + USB_STATE_ADDRESS, USB_STATE_SUSPENDED, USB_STATE_CONFIGURED, USB_STATE_SUSPENDED
7157 +static char * state_names[8] =
7158 +{ "zombie", "zombie suspended", "default", "default suspended",
7159 + "address", "address suspended", "configured", "config suspended"
7162 +static char * event_names[6] =
7163 +{ "suspend", "reset", "resume",
7164 + "address assigned", "configure", "de-configure"
7167 +static char * device_state_names[] =
7168 +{ "not attached", "attached", "powered", "default",
7169 + "address", "configured", "suspended" };
7171 +static int sm_state = kStateZombie;
7173 +//////////////////////////////////////////////////////////////////////////////
7174 +// Async
7175 +//////////////////////////////////////////////////////////////////////////////
7176 +static void core_kicker(void);
7178 +static inline void enable_resume_mask_suspend( void );
7179 +static inline void enable_suspend_mask_resume(void);
7181 +static void
7182 +udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
7184 + __u32 status = Ser0UDCSR;
7186 + /* ReSeT Interrupt Request - UDC has been reset */
7187 + if ( status & UDCSR_RSTIR )
7189 + if ( usbctl_next_state_on_event( kEvReset ) != kError )
7191 + /* starting 20ms or so reset sequence now... */
7192 + printk("%sResetting\n", pszMe);
7193 + ep0_reset(); // just set state to idle
7194 + ep1_reset(); // flush dma, clear false stall
7195 + ep2_reset(); // flush dma, clear false stall
7197 + // mask reset ints, they flood during sequence, enable
7198 + // suspend and resume
7199 + Ser0UDCCR |= UDCCR_REM; // mask reset
7200 + Ser0UDCCR &= ~(UDCCR_SUSIM | UDCCR_RESIM); // enable suspend and resume
7201 + UDC_flip( Ser0UDCSR, status ); // clear all pending sources
7202 + return; // <-- no reason to continue if resetting
7204 + // else we have done something other than reset, so be sure reset enabled
7205 + UDC_clear( Ser0UDCCR, UDCCR_REM );
7207 + /* RESume Interrupt Request */
7208 + if ( status & UDCSR_RESIR )
7210 + usbctl_next_state_on_event( kEvResume );
7211 + core_kicker();
7212 + enable_suspend_mask_resume();
7215 + /* SUSpend Interrupt Request */
7216 + if ( status & UDCSR_SUSIR )
7218 + usbctl_next_state_on_event( kEvSuspend );
7219 + enable_resume_mask_suspend();
7222 + UDC_flip(Ser0UDCSR, status); // clear all pending sources
7224 + if (status & UDCSR_EIR)
7225 + ep0_int_hndlr();
7227 + if (status & UDCSR_RIR)
7228 + ep1_int_hndlr(status);
7230 + if (status & UDCSR_TIR)
7231 + ep2_int_hndlr(status);
7234 +static inline void enable_resume_mask_suspend( void )
7236 + int i = 0;
7238 + while( 1 ) {
7239 + Ser0UDCCR |= UDCCR_SUSIM; // mask future suspend events
7240 + udelay( i );
7241 + if ( (Ser0UDCCR & UDCCR_SUSIM) || (Ser0UDCSR & UDCSR_RSTIR) )
7242 + break;
7243 + if ( ++i == 50 ) {
7244 + printk( "%senable_resume(): Could not set SUSIM %8.8X\n",
7245 + pszMe, Ser0UDCCR );
7246 + break;
7250 + i = 0;
7251 + while( 1 ) {
7252 + Ser0UDCCR &= ~UDCCR_RESIM;
7253 + udelay( i );
7254 + if ( ( Ser0UDCCR & UDCCR_RESIM ) == 0
7255 + ||
7256 + (Ser0UDCSR & UDCSR_RSTIR)
7258 + break;
7259 + if ( ++i == 50 ) {
7260 + printk( "%senable_resume(): Could not clear RESIM %8.8X\n",
7261 + pszMe, Ser0UDCCR );
7262 + break;
7267 +static inline void enable_suspend_mask_resume(void)
7269 + int i = 0;
7270 + while( 1 ) {
7271 + Ser0UDCCR |= UDCCR_RESIM; // mask future resume events
7272 + udelay( i );
7273 + if ( Ser0UDCCR & UDCCR_RESIM || (Ser0UDCSR & UDCSR_RSTIR) )
7274 + break;
7275 + if ( ++i == 50 ) {
7276 + printk( "%senable_suspend(): Could not set RESIM %8.8X\n",
7277 + pszMe, Ser0UDCCR );
7278 + break;
7281 + i = 0;
7282 + while( 1 ) {
7283 + Ser0UDCCR &= ~UDCCR_SUSIM;
7284 + udelay( i );
7285 + if ( ( Ser0UDCCR & UDCCR_SUSIM ) == 0
7286 + ||
7287 + (Ser0UDCSR & UDCSR_RSTIR)
7289 + break;
7290 + if ( ++i == 50 ) {
7291 + printk( "%senable_suspend(): Could not clear SUSIM %8.8X\n",
7292 + pszMe, Ser0UDCCR );
7293 + break;
7299 +//////////////////////////////////////////////////////////////////////////////
7300 +// Public Interface
7301 +//////////////////////////////////////////////////////////////////////////////
7303 +/* Open SA usb core on behalf of a client, but don't start running */
7305 +int
7306 +sa1100_usb_open( const char * client )
7308 + if ( usbd_info.client_name != NULL )
7309 + return -EBUSY;
7311 + usbd_info.client_name = (char*) client;
7312 + memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));
7313 + memset(string_desc_array, 0, sizeof(string_desc_array));
7315 + /* hack to start in zombie suspended state */
7316 + sm_state = kStateZombieSuspend;
7317 + usbd_info.state = USB_STATE_SUSPENDED;
7319 + /* create descriptors for enumeration */
7320 + initialize_descriptors();
7322 + printk( "%sOpened for %s\n", pszMe, client );
7323 + return 0;
7326 +/* Start running. Must have called usb_open (above) first */
7327 +int
7328 +sa1100_usb_start( void )
7330 + if ( usbd_info.client_name == NULL ) {
7331 + printk( "%s%s - no client registered\n",
7332 + pszMe, __FUNCTION__ );
7333 + return -EPERM;
7336 + /* start UDC internal machinery running */
7337 + udc_enable();
7338 + udelay( 100 );
7340 + /* clear stall - receiver seems to start stalled? 19Jan01ww */
7341 + /* also clear other stuff just to be thurough 22Feb01ww */
7342 + UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC );
7343 + UDC_clear(Ser0UDCCS2, UDCCS2_FST | UDCCS2_TPE | UDCCS2_TPC );
7345 + /* mask everything */
7346 + Ser0UDCCR = 0xFC;
7348 + /* flush DMA and fire through some -EAGAINs */
7349 + ep1_init( usbd_info.dmach_rx );
7350 + ep2_init( usbd_info.dmach_tx );
7352 + /* give endpoint notification we are starting */
7353 + ep1_state_change_notify( USB_STATE_SUSPENDED );
7354 + ep2_state_change_notify( USB_STATE_SUSPENDED );
7356 + /* enable any platform specific hardware */
7357 + soft_connect_hook( 1 );
7359 + /* clear all top-level sources */
7360 + Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR |
7361 + UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ;
7363 + /* EXERIMENT - a short line in the spec says toggling this
7364 + ..bit diddles the internal state machine in the udc to
7365 + ..expect a suspend */
7366 + Ser0UDCCR |= UDCCR_RESIM;
7367 + /* END EXPERIMENT 10Feb01ww */
7369 + /* enable any platform specific hardware */
7370 + soft_connect_hook( 1 );
7372 + /* enable interrupts. If you are unplugged you will
7373 + immediately get a suspend interrupt. If you are plugged
7374 + and have a soft connect-circuit, you will get a reset
7375 + If you are plugged without a soft-connect, I think you
7376 + also get suspend. In short, start with suspend masked
7377 + and everything else enabled */
7378 + UDC_write( Ser0UDCCR, UDCCR_SUSIM );
7380 + printk( "%sStarted for %s\n", pszMe, usbd_info.client_name );
7381 + return 0;
7384 +/* Stop USB core from running */
7385 +int
7386 +sa1100_usb_stop( void )
7388 + if ( usbd_info.client_name == NULL ) {
7389 + printk( "%s%s - no client registered\n",
7390 + pszMe, __FUNCTION__ );
7391 + return -EPERM;
7393 + /* mask everything */
7394 + Ser0UDCCR = 0xFC;
7395 + ep1_reset();
7396 + ep2_reset();
7397 + udc_disable();
7398 + printk( "%sStopped\n", pszMe );
7399 + return 0;
7402 +/* Tell SA core client is through using it */
7403 +int
7404 +sa1100_usb_close( void )
7406 + if ( usbd_info.client_name == NULL ) {
7407 + printk( "%s%s - no client registered\n",
7408 + pszMe, __FUNCTION__ );
7409 + return -EPERM;
7411 + usbd_info.client_name = NULL;
7412 + printk( "%sClosed\n", pszMe );
7413 + return 0;
7416 +/* set a proc to be called when device is configured */
7417 +usb_notify_t sa1100_set_configured_callback( usb_notify_t func )
7419 + usb_notify_t retval = configured_callback;
7420 + configured_callback = func;
7421 + return retval;
7424 +/*====================================================
7425 + * Descriptor Manipulation.
7426 + * Use these between open() and start() above to setup
7427 + * the descriptors for your device.
7429 + */
7431 +/* get pointer to static default descriptor */
7432 +desc_t *
7433 +sa1100_usb_get_descriptor_ptr( void ) { return &desc; }
7435 +/* optional: set a string descriptor */
7436 +int
7437 +sa1100_usb_set_string_descriptor( int i, string_desc_t * p )
7439 + int retval;
7440 + if ( i < MAX_STRING_DESC ) {
7441 + string_desc_array[i] = p;
7442 + retval = 0;
7443 + } else {
7444 + retval = -EINVAL;
7446 + return retval;
7449 +/* optional: get a previously set string descriptor */
7450 +string_desc_t *
7451 +sa1100_usb_get_string_descriptor( int i )
7453 + return ( i < MAX_STRING_DESC )
7454 + ? string_desc_array[i]
7455 + : NULL;
7459 +/* optional: kmalloc and unicode up a string descriptor */
7460 +string_desc_t *
7461 +sa1100_usb_kmalloc_string_descriptor( const char * p )
7463 + string_desc_t * pResult = NULL;
7465 + if ( p ) {
7466 + int len = strlen( p );
7467 + int uni_len = len * sizeof( __u16 );
7468 + pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */
7469 + if ( pResult != NULL ) {
7470 + int i;
7471 + pResult->bLength = uni_len + 2;
7472 + pResult->bDescriptorType = USB_DESC_STRING;
7473 + for( i = 0; i < len ; i++ ) {
7474 + pResult->bString[i] = make_word( (__u16) p[i] );
7478 + return pResult;
7481 +//////////////////////////////////////////////////////////////////////////////
7482 +// Exports to rest of driver
7483 +//////////////////////////////////////////////////////////////////////////////
7485 +/* called by the int handler here and the two endpoint files when interesting
7486 + .."events" happen */
7488 +int
7489 +usbctl_next_state_on_event( int event )
7491 + int next_state = device_state_machine[ sm_state ][ event ];
7492 + if ( next_state != kError )
7494 + int next_device_state = sm_state_to_device_state[ next_state ];
7495 + printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
7496 + pszMe, state_names[ sm_state ], event_names[ event ],
7497 + state_names[ next_state ], device_state_names[ next_device_state ] );
7499 + sm_state = next_state;
7500 + if ( usbd_info.state != next_device_state )
7502 + if ( configured_callback != NULL
7503 + &&
7504 + next_device_state == USB_STATE_CONFIGURED
7505 + &&
7506 + usbd_info.state != USB_STATE_SUSPENDED
7507 + ) {
7508 + configured_callback();
7510 + usbd_info.state = next_device_state;
7511 + ep1_state_change_notify( next_device_state );
7512 + ep2_state_change_notify( next_device_state );
7515 +#if 0
7516 + else
7517 + printk( "%s%s --> [%s] --> ??? is an error.\n",
7518 + pszMe, state_names[ sm_state ], event_names[ event ] );
7519 +#endif
7520 + return next_state;
7523 +//////////////////////////////////////////////////////////////////////////////
7524 +// Private Helpers
7525 +//////////////////////////////////////////////////////////////////////////////
7527 +/* setup default descriptors */
7529 +static void
7530 +initialize_descriptors(void)
7532 + desc.dev.bLength = sizeof( device_desc_t );
7533 + desc.dev.bDescriptorType = USB_DESC_DEVICE;
7534 + desc.dev.bcdUSB = 0x100; /* 1.0 */
7535 + desc.dev.bDeviceClass = 0xFF; /* vendor specific */
7536 + desc.dev.bDeviceSubClass = 0;
7537 + desc.dev.bDeviceProtocol = 0;
7538 + desc.dev.bMaxPacketSize0 = 8; /* ep0 max fifo size */
7539 + desc.dev.idVendor = 0; /* vendor ID undefined */
7540 + desc.dev.idProduct = 0; /* product */
7541 + desc.dev.bcdDevice = 0; /* vendor assigned device release num */
7542 + desc.dev.iManufacturer = 0; /* index of manufacturer string */
7543 + desc.dev.iProduct = 0; /* index of product description string */
7544 + desc.dev.iSerialNumber = 0; /* index of string holding product s/n */
7545 + desc.dev.bNumConfigurations = 1;
7547 + desc.b.cfg.bLength = sizeof( config_desc_t );
7548 + desc.b.cfg.bDescriptorType = USB_DESC_CONFIG;
7549 + desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) );
7550 + desc.b.cfg.bNumInterfaces = 1;
7551 + desc.b.cfg.bConfigurationValue = 1;
7552 + desc.b.cfg.iConfiguration = 0;
7553 + desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED;
7554 + desc.b.cfg.MaxPower = USB_POWER( 500 );
7556 + desc.b.intf.bLength = sizeof( intf_desc_t );
7557 + desc.b.intf.bDescriptorType = USB_DESC_INTERFACE;
7558 + desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/
7559 + desc.b.intf.bAlternateSetting = 0;
7560 + desc.b.intf.bNumEndpoints = 2;
7561 + desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */
7562 + desc.b.intf.bInterfaceSubClass = 0;
7563 + desc.b.intf.bInterfaceProtocol = 0;
7564 + desc.b.intf.iInterface = 0;
7566 + desc.b.ep1.bLength = sizeof( ep_desc_t );
7567 + desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT;
7568 + desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_OUT );
7569 + desc.b.ep1.bmAttributes = USB_EP_BULK;
7570 + desc.b.ep1.wMaxPacketSize = make_word_c( 64 );
7571 + desc.b.ep1.bInterval = 0;
7573 + desc.b.ep2.bLength = sizeof( ep_desc_t );
7574 + desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT;
7575 + desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_IN );
7576 + desc.b.ep2.bmAttributes = USB_EP_BULK;
7577 + desc.b.ep2.wMaxPacketSize = make_word_c( 64 );
7578 + desc.b.ep2.bInterval = 0;
7580 + /* set language */
7581 + /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
7582 + sd_zero.bDescriptorType = USB_DESC_STRING;
7583 + sd_zero.bLength = sizeof( string_desc_t );
7584 + sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */
7585 + sa1100_usb_set_string_descriptor( 0, &sd_zero );
7588 +/* soft_connect_hook()
7589 + * Some devices have platform-specific circuitry to make USB
7590 + * not seem to be plugged in, even when it is. This allows
7591 + * software to control when a device 'appears' on the USB bus
7592 + * (after Linux has booted and this driver has loaded, for
7593 + * example). If you have such a circuit, control it here.
7594 + */
7595 +static void
7596 +soft_connect_hook( int enable )
7598 +#ifdef CONFIG_SA1100_EXTENEX1
7599 + if (machine_is_extenex1() ) {
7600 + if ( enable ) {
7601 + PPDR |= PPC_USB_SOFT_CON;
7602 + PPSR |= PPC_USB_SOFT_CON;
7603 + } else {
7604 + PPSR &= ~PPC_USB_SOFT_CON;
7605 + PPDR &= ~PPC_USB_SOFT_CON;
7608 +#endif
7611 +/* disable the UDC at the source */
7612 +static void
7613 +udc_disable(void)
7615 + soft_connect_hook( 0 );
7616 + UDC_set( Ser0UDCCR, UDCCR_UDD );
7620 +/* enable the udc at the source */
7621 +static void
7622 +udc_enable(void)
7624 + UDC_clear(Ser0UDCCR, UDCCR_UDD);
7627 +// HACK DEBUG 3Mar01ww
7628 +// Well, maybe not, it really seems to help! 08Mar01ww
7629 +static void
7630 +core_kicker( void )
7632 + __u32 car = Ser0UDCAR;
7633 + __u32 imp = Ser0UDCIMP;
7634 + __u32 omp = Ser0UDCOMP;
7636 + UDC_set( Ser0UDCCR, UDCCR_UDD );
7637 + udelay( 300 );
7638 + UDC_clear(Ser0UDCCR, UDCCR_UDD);
7640 + Ser0UDCAR = car;
7641 + Ser0UDCIMP = imp;
7642 + Ser0UDCOMP = omp;
7645 +//////////////////////////////////////////////////////////////////////////////
7646 +// Proc Filesystem Support
7647 +//////////////////////////////////////////////////////////////////////////////
7649 +#if CONFIG_PROC_FS
7651 +#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args )
7652 +#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num )
7653 +#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn )
7654 +#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v )
7656 +static int usbctl_read_proc(char *page, char **start, off_t off,
7657 + int count, int *eof, void *data)
7659 + const char * num_fmt = "%25.25s: %8.8lX\n";
7660 + const char * cnt_fmt = "%25.25s: %lu\n";
7661 + const char * yn_fmt = "%25.25s: %s\n";
7662 + const char * yes = "YES";
7663 + const char * no = "NO";
7664 + unsigned long v;
7665 + char * p = page;
7666 + int len;
7668 + SAY( "SA1100 USB Controller Core\n" );
7669 + SAY( "USB state: %s (%s) %d\n",
7670 + device_state_names[ sm_state_to_device_state[ sm_state ] ],
7671 + state_names[ sm_state ],
7672 + sm_state );
7674 + SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read );
7675 + SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written );
7676 + SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures );
7677 + SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures );
7679 + SAY( "\n" );
7681 + v = Ser0UDCAR;
7682 + SAY( "%25.25s: 0x%8.8lX - %ld\n", "Address Register", v, v );
7683 + v = Ser0UDCIMP;
7684 + SAY( "%25.25s: %ld (%8.8lX)\n", "IN max packet size", v+1, v );
7685 + v = Ser0UDCOMP;
7686 + SAY( "%25.25s: %ld (%8.8lX)\n", "OUT max packet size", v+1, v );
7688 + v = Ser0UDCCR;
7689 + SAY( "\nUDC Mask Register\n" );
7690 + SAYV( v );
7691 + SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no );
7692 + SAYC( "Suspend interrupts masked", ( v & UDCCR_SUSIM ) ? yes : no );
7693 + SAYC( "Resume interrupts masked", ( v & UDCCR_RESIM ) ? yes : no );
7694 + SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no );
7696 + v = Ser0UDCSR;
7697 + SAY( "\nUDC Interrupt Request Register\n" );
7698 + SAYV( v );
7699 + SAYC( "Reset pending", ( v & UDCSR_RSTIR ) ? yes : no );
7700 + SAYC( "Suspend pending", ( v & UDCSR_SUSIR ) ? yes : no );
7701 + SAYC( "Resume pending", ( v & UDCSR_RESIR ) ? yes : no );
7702 + SAYC( "ep0 pending", ( v & UDCSR_EIR ) ? yes : no );
7703 + SAYC( "receiver pending", ( v & UDCSR_RIR ) ? yes : no );
7704 + SAYC( "tramsitter pending", ( v & UDCSR_TIR ) ? yes : no );
7706 +#ifdef CONFIG_SA1100_EXTENEX1
7707 + SAYC( "\nSoft connect", (PPSR & PPC_USB_SOFT_CON) ? "Visible" : "Hidden" );
7708 +#endif
7710 +#if 0
7711 + v = Ser0UDCCS0;
7712 + SAY( "\nUDC Endpoint Zero Status Register\n" );
7713 + SAYV( v );
7714 + SAYC( "Out Packet Ready", ( v & UDCCS0_OPR ) ? yes : no );
7715 + SAYC( "In Packet Ready", ( v & UDCCS0_IPR ) ? yes : no );
7716 + SAYC( "Sent Stall", ( v & UDCCS0_SST ) ? yes : no );
7717 + SAYC( "Force Stall", ( v & UDCCS0_FST ) ? yes : no );
7718 + SAYC( "Data End", ( v & UDCCS0_DE ) ? yes : no );
7719 + SAYC( "Data Setup End", ( v & UDCCS0_SE ) ? yes : no );
7720 + SAYC( "Serviced (SO)", ( v & UDCCS0_SO ) ? yes : no );
7722 + v = Ser0UDCCS1;
7723 + SAY( "\nUDC Receiver Status Register\n" );
7724 + SAYV( v );
7725 + SAYC( "Receive Packet Complete", ( v & UDCCS1_RPC ) ? yes : no );
7726 + SAYC( "Sent Stall", ( v & UDCCS1_SST ) ? yes : no );
7727 + SAYC( "Force Stall", ( v & UDCCS1_FST ) ? yes : no );
7728 + SAYC( "Receive Packet Error", ( v & UDCCS1_RPE ) ? yes : no );
7729 + SAYC( "Receive FIFO not empty", ( v & UDCCS1_RNE ) ? yes : no );
7731 + v = Ser0UDCCS2;
7732 + SAY( "\nUDC Transmitter Status Register\n" );
7733 + SAYV( v );
7734 + SAYC( "FIFO has < 8 of 16 chars", ( v & UDCCS2_TFS ) ? yes : no );
7735 + SAYC( "Transmit Packet Complete", ( v & UDCCS2_TPC ) ? yes : no );
7736 + SAYC( "Transmit FIFO underrun", ( v & UDCCS2_TUR ) ? yes : no );
7737 + SAYC( "Transmit Packet Error", ( v & UDCCS2_TPE ) ? yes : no );
7738 + SAYC( "Sent Stall", ( v & UDCCS2_SST ) ? yes : no );
7739 + SAYC( "Force Stall", ( v & UDCCS2_FST ) ? yes : no );
7740 +#endif
7742 + len = ( p - page ) - off;
7743 + if ( len < 0 )
7744 + len = 0;
7745 + *eof = ( len <=count ) ? 1 : 0;
7746 + *start = page + off;
7747 + return len;
7750 +#endif /* CONFIG_PROC_FS */
7752 +//////////////////////////////////////////////////////////////////////////////
7753 +// Module Initialization and Shutdown
7754 +//////////////////////////////////////////////////////////////////////////////
7756 + * usbctl_init()
7757 + * Module load time. Allocate dma and interrupt resources. Setup /proc fs
7758 + * entry. Leave UDC disabled.
7759 + */
7760 +int __init usbctl_init( void )
7762 + int retval = 0;
7764 + udc_disable();
7766 + memset( &usbd_info, 0, sizeof( usbd_info ) );
7768 +#if CONFIG_PROC_FS
7769 + create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
7770 +#endif
7772 + /* setup rx dma */
7773 + retval = sa1100_request_dma(&usbd_info.dmach_rx, "USB receive", DMA_Ser0UDCRd);
7774 + if (retval) {
7775 + printk("%sunable to register for rx dma rc=%d\n", pszMe, retval );
7776 + goto err_rx_dma;
7779 + /* setup tx dma */
7780 + retval = sa1100_request_dma(&usbd_info.dmach_tx, "USB transmit", DMA_Ser0UDCWr);
7781 + if (retval) {
7782 + printk("%sunable to register for tx dma rc=%d\n",pszMe,retval);
7783 + goto err_tx_dma;
7786 + /* now allocate the IRQ. */
7787 + retval = request_irq(IRQ_Ser0UDC, udc_int_hndlr, SA_INTERRUPT,
7788 + "SA USB core", NULL);
7789 + if (retval) {
7790 + printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval);
7791 + goto err_irq;
7794 + printk( "SA1100 USB Controller Core Initialized\n");
7795 + return 0;
7797 +err_irq:
7798 + sa1100_free_dma(usbd_info.dmach_tx);
7799 + usbd_info.dmach_tx = 0;
7800 +err_tx_dma:
7801 + sa1100_free_dma(usbd_info.dmach_rx);
7802 + usbd_info.dmach_rx = 0;
7803 +err_rx_dma:
7804 + return retval;
7807 + * usbctl_exit()
7808 + * Release DMA and interrupt resources
7809 + */
7810 +void __exit usbctl_exit( void )
7812 + printk("Unloading SA1100 USB Controller\n");
7814 + udc_disable();
7816 +#if CONFIG_PROC_FS
7817 + remove_proc_entry ( PROC_NODE_NAME, NULL);
7818 +#endif
7820 + sa1100_free_dma(usbd_info.dmach_rx);
7821 + sa1100_free_dma(usbd_info.dmach_tx);
7822 + free_irq(IRQ_Ser0UDC, NULL);
7825 +EXPORT_SYMBOL( sa1100_usb_open );
7826 +EXPORT_SYMBOL( sa1100_usb_start );
7827 +EXPORT_SYMBOL( sa1100_usb_stop );
7828 +EXPORT_SYMBOL( sa1100_usb_close );
7831 +EXPORT_SYMBOL( sa1100_usb_get_descriptor_ptr );
7832 +EXPORT_SYMBOL( sa1100_usb_set_string_descriptor );
7833 +EXPORT_SYMBOL( sa1100_usb_get_string_descriptor );
7834 +EXPORT_SYMBOL( sa1100_usb_kmalloc_string_descriptor );
7837 +module_init( usbctl_init );
7838 +module_exit( usbctl_exit );
7839 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
7840 +++ linux-2.4.25/arch/arm/mach-sa1100/usb_ctl.h 2004-03-31 17:15:09.000000000 +0200
7841 @@ -0,0 +1,123 @@
7843 + * Copyright (C) Compaq Computer Corporation, 1998, 1999
7844 + * Copyright (C) Extenex Corporation 2001
7846 + * usb_ctl.h
7848 + * PRIVATE interface used to share info among components of the SA-1100 USB
7849 + * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core
7850 + * should use sa1100_usb.h.
7852 + */
7854 +#ifndef _USB_CTL_H
7855 +#define _USB_CTL_H
7857 +#include <asm/dma.h> /* dmach_t */
7861 + * These states correspond to those in the USB specification v1.0
7862 + * in chapter 8, Device Framework.
7863 + */
7864 +enum { USB_STATE_NOTATTACHED=0, USB_STATE_ATTACHED=1,USB_STATE_POWERED=2,
7865 + USB_STATE_DEFAULT=3, USB_STATE_ADDRESS=4, USB_STATE_CONFIGURED=5,
7866 + USB_STATE_SUSPENDED=6};
7868 +struct usb_stats_t {
7869 + unsigned long ep0_fifo_write_failures;
7870 + unsigned long ep0_bytes_written;
7871 + unsigned long ep0_fifo_read_failures;
7872 + unsigned long ep0_bytes_read;
7875 +struct usb_info_t
7877 + char * client_name;
7878 + dmach_t dmach_tx, dmach_rx;
7879 + int state;
7880 + unsigned char address;
7881 + struct usb_stats_t stats;
7884 +/* in usb_ctl.c */
7885 +extern struct usb_info_t usbd_info;
7888 + * Function Prototypes
7889 + */
7890 +enum { kError=-1, kEvSuspend=0, kEvReset=1,
7891 + kEvResume=2, kEvAddress=3, kEvConfig=4, kEvDeConfig=5 };
7892 +int usbctl_next_state_on_event( int event );
7894 +/* endpoint zero */
7895 +void ep0_reset(void);
7896 +void ep0_int_hndlr(void);
7898 +/* receiver */
7899 +void ep1_state_change_notify( int new_state );
7900 +int ep1_recv(void);
7901 +int ep1_init(int chn);
7902 +void ep1_int_hndlr(int status);
7903 +void ep1_reset(void);
7904 +void ep1_stall(void);
7906 +/* xmitter */
7907 +void ep2_state_change_notify( int new_state );
7908 +void ep2_reset(void);
7909 +int ep2_init(int chn);
7910 +void ep2_int_hndlr(int status);
7911 +void ep2_stall(void);
7913 +#define UDC_write(reg, val) { \
7914 + int i = 10000; \
7915 + do { \
7916 + (reg) = (val); \
7917 + if (i-- <= 0) { \
7918 + printk( "%s [%d]: write %#x to %p (%#x) failed\n", \
7919 + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
7920 + break; \
7921 + } \
7922 + } while((reg) != (val)); \
7925 +#define UDC_set(reg, val) { \
7926 + int i = 10000; \
7927 + do { \
7928 + (reg) |= (val); \
7929 + if (i-- <= 0) { \
7930 + printk( "%s [%d]: set %#x of %p (%#x) failed\n", \
7931 + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
7932 + break; \
7933 + } \
7934 + } while(!((reg) & (val))); \
7937 +#define UDC_clear(reg, val) { \
7938 + int i = 10000; \
7939 + do { \
7940 + (reg) &= ~(val); \
7941 + if (i-- <= 0) { \
7942 + printk( "%s [%d]: clear %#x of %p (%#x) failed\n", \
7943 + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
7944 + break; \
7945 + } \
7946 + } while((reg) & (val)); \
7949 +#define UDC_flip(reg, val) { \
7950 + int i = 10000; \
7951 + (reg) = (val); \
7952 + do { \
7953 + (reg) = (val); \
7954 + if (i-- <= 0) { \
7955 + printk( "%s [%d]: flip %#x of %p (%#x) failed\n", \
7956 + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
7957 + break; \
7958 + } \
7959 + } while(((reg) & (val))); \
7963 +#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}}
7964 +#endif /* _USB_CTL_H */
7965 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
7966 +++ linux-2.4.25/arch/arm/mach-sa1100/usb_ep0.c 2004-03-31 17:15:09.000000000 +0200
7967 @@ -0,0 +1,911 @@
7969 + * Copyright (C) Extenex Corporation 2001
7970 + * Much folklore gleaned from original code:
7971 + * Copyright (C) Compaq Computer Corporation, 1998, 1999
7973 + * usb_ep0.c - SA1100 USB controller driver.
7974 + * Endpoint zero management
7976 + * Please see:
7977 + * linux/Documentation/arm/SA1100/SA1100_USB
7978 + * for details. (Especially since Intel docs are full of
7979 + * errors about ep0 operation.) ward.willats@extenex.com.
7981 + * Intel also has a "Universal Serial Bus Client Device
7982 + * Validation for the StrongARM SA-1100 Microprocessor"
7983 + * document, which has flow charts and assembler test driver,
7984 + * but be careful, since it is just for validation and not
7985 + * a "real world" solution.
7987 + * A summary of three types of data-returning setups:
7989 + * 1. Setup request <= 8 bytes. That is, requests that can
7990 + * be fullfilled in one write to the FIFO. DE is set
7991 + * with IPR in queue_and_start_write(). (I don't know
7992 + * if there really are any of these!)
7994 + * 2. Setup requests > 8 bytes (requiring more than one
7995 + * IN to get back to the host), and we have at least
7996 + * as much or more data than the host requested. In
7997 + * this case we pump out everything we've got, and
7998 + * when the final interrupt comes in due to the UDC
7999 + * clearing the last IPR, we just set DE.
8001 + * 3. Setup requests > 8 bytes, but we don't have enough
8002 + * data to satisfy the request. In this case, we send
8003 + * everything we've got, and when the final interrupt
8004 + * comes in due to the UDC clearing the last IPR
8005 + * we write nothing to the FIFO and set both IPR and DE
8006 + * so the UDC sends an empty packet and forces the host
8007 + * to perform short packet retirement instead of stalling
8008 + * out.
8010 + */
8012 +#include <linux/delay.h>
8013 +#include "sa1100_usb.h" /* public interface */
8014 +#include "usb_ctl.h" /* private stuff */
8017 +// 1 == lots of trace noise, 0 = only "important' stuff
8018 +#define VERBOSITY 0
8020 +enum { true = 1, false = 0 };
8021 +typedef int bool;
8022 +#ifndef MIN
8023 +#define MIN( a, b ) ((a)<(b)?(a):(b))
8024 +#endif
8026 +#if 1 && !defined( ASSERT )
8027 +# define ASSERT(expr) \
8028 + if(!(expr)) { \
8029 + printk( "Assertion failed! %s,%s,%s,line=%d\n",\
8030 + #expr,__FILE__,__FUNCTION__,__LINE__); \
8032 +#else
8033 +# define ASSERT(expr)
8034 +#endif
8036 +#if VERBOSITY
8037 +#define PRINTKD(fmt, args...) printk( fmt , ## args)
8038 +#else
8039 +#define PRINTKD(fmt, args...)
8040 +#endif
8042 +/*================================================
8043 + * USB Protocol Stuff
8044 + */
8046 +/* Request Codes */
8047 +enum { GET_STATUS=0, CLEAR_FEATURE=1, SET_FEATURE=3,
8048 + SET_ADDRESS=5, GET_DESCRIPTOR=6, SET_DESCRIPTOR=7,
8049 + GET_CONFIGURATION=8, SET_CONFIGURATION=9, GET_INTERFACE=10,
8050 + SET_INTERFACE=11 };
8053 +/* USB Device Requests */
8054 +typedef struct
8056 + __u8 bmRequestType;
8057 + __u8 bRequest;
8058 + __u16 wValue;
8059 + __u16 wIndex;
8060 + __u16 wLength;
8061 +} usb_dev_request_t __attribute__ ((packed));
8063 +/***************************************************************************
8064 +Prototypes
8065 +***************************************************************************/
8066 +/* "setup handlers" -- the main functions dispatched to by the
8067 + .. isr. These represent the major "modes" of endpoint 0 operaton */
8068 +static void sh_setup_begin(void); /* setup begin (idle) */
8069 +static void sh_write( void ); /* writing data */
8070 +static void sh_write_with_empty_packet( void ); /* empty packet at end of xfer*/
8071 +/* called before both sh_write routines above */
8072 +static void common_write_preamble( void );
8074 +/* other subroutines */
8075 +static __u32 queue_and_start_write( void * p, int req, int act );
8076 +static void write_fifo( void );
8077 +static int read_fifo( usb_dev_request_t * p );
8078 +static void get_descriptor( usb_dev_request_t * pReq );
8080 +/* some voodo helpers 01Mar01ww */
8081 +static void set_cs_bits( __u32 set_bits );
8082 +static void set_de( void );
8083 +static void set_ipr( void );
8084 +static void set_ipr_and_de( void );
8085 +static bool clear_opr( void );
8087 +/***************************************************************************
8088 +Inline Helpers
8089 +***************************************************************************/
8091 +/* Data extraction from usb_request_t fields */
8092 +enum { kTargetDevice=0, kTargetInterface=1, kTargetEndpoint=2 };
8093 +static inline int request_target( __u8 b ) { return (int) ( b & 0x0F); }
8095 +static inline int windex_to_ep_num( __u16 w ) { return (int) ( w & 0x000F); }
8096 +inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
8098 +/* following is hook for self-powered flag in GET_STATUS. Some devices
8099 + .. might like to override and return real info */
8100 +static inline bool self_powered_hook( void ) { return true; }
8102 +/* print string descriptor */
8103 +static inline void psdesc( string_desc_t * p )
8105 + int i;
8106 + int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
8107 + printk( "'" );
8108 + for( i = 0 ; i < nchars ; i++ ) {
8109 + printk( "%c", (char) p->bString[i] );
8111 + printk( "'\n" );
8115 +#if VERBOSITY
8116 +/* "pcs" == "print control status" */
8117 +static inline void pcs( void )
8119 + __u32 foo = Ser0UDCCS0;
8120 + printk( "%8.8X: %s %s %s %s\n",
8121 + foo,
8122 + foo & UDCCS0_SE ? "SE" : "",
8123 + foo & UDCCS0_OPR ? "OPR" : "",
8124 + foo & UDCCS0_IPR ? "IPR" : "",
8125 + foo & UDCCS0_SST ? "SST" : ""
8126 + );
8128 +static inline void preq( usb_dev_request_t * pReq )
8130 + static char * tnames[] = { "dev", "intf", "ep", "oth" };
8131 + static char * rnames[] = { "std", "class", "vendor", "???" };
8132 + char * psz;
8133 + switch( pReq->bRequest ) {
8134 + case GET_STATUS: psz = "get stat"; break;
8135 + case CLEAR_FEATURE: psz = "clr feat"; break;
8136 + case SET_FEATURE: psz = "set feat"; break;
8137 + case SET_ADDRESS: psz = "set addr"; break;
8138 + case GET_DESCRIPTOR: psz = "get desc"; break;
8139 + case SET_DESCRIPTOR: psz = "set desc"; break;
8140 + case GET_CONFIGURATION: psz = "get cfg"; break;
8141 + case SET_CONFIGURATION: psz = "set cfg"; break;
8142 + case GET_INTERFACE: psz = "get intf"; break;
8143 + case SET_INTERFACE: psz = "set intf"; break;
8144 + default: psz = "unknown"; break;
8146 + printk( "- [%s: %s req to %s. dir=%s]\n", psz,
8147 + rnames[ (pReq->bmRequestType >> 5) & 3 ],
8148 + tnames[ pReq->bmRequestType & 3 ],
8149 + ( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
8152 +#else
8153 +static inline void pcs( void ){}
8154 +static inline void preq( void ){}
8155 +#endif
8157 +/***************************************************************************
8158 +Globals
8159 +***************************************************************************/
8160 +static const char pszMe[] = "usbep0: ";
8162 +/* pointer to current setup handler */
8163 +static void (*current_handler)(void) = sh_setup_begin;
8165 +/* global write struct to keep write
8166 + ..state around across interrupts */
8167 +static struct {
8168 + unsigned char *p;
8169 + int bytes_left;
8170 +} wr;
8172 +/***************************************************************************
8173 +Public Interface
8174 +***************************************************************************/
8176 +/* reset received from HUB (or controller just went nuts and reset by itself!)
8177 + so udc core has been reset, track this state here */
8178 +void
8179 +ep0_reset(void)
8181 + /* reset state machine */
8182 + current_handler = sh_setup_begin;
8183 + wr.p = NULL;
8184 + wr.bytes_left = 0;
8185 + usbd_info.address=0;
8188 +/* handle interrupt for endpoint zero */
8189 +void
8190 +ep0_int_hndlr( void )
8192 + PRINTKD( "/\\(%d)\n", Ser0UDCAR );
8193 + pcs();
8195 + /* if not in setup begin, we are returning data.
8196 + execute a common preamble to both write handlers
8197 + */
8198 + if ( current_handler != sh_setup_begin )
8199 + common_write_preamble();
8201 + (*current_handler)();
8203 + PRINTKD( "---\n" );
8204 + pcs();
8205 + PRINTKD( "\\/\n" );
8208 +/***************************************************************************
8209 +Setup Handlers
8210 +***************************************************************************/
8212 + * sh_setup_begin()
8213 + * This setup handler is the "idle" state of endpoint zero. It looks for OPR
8214 + * (OUT packet ready) to see if a setup request has been been received from the
8215 + * host. Requests without a return data phase are immediately handled. Otherwise,
8216 + * in the case of GET_XXXX the handler may be set to one of the sh_write_xxxx
8217 + * data pumpers if more than 8 bytes need to get back to the host.
8219 + */
8220 +static void
8221 +sh_setup_begin( void )
8223 + unsigned char status_buf[2]; /* returned in GET_STATUS */
8224 + usb_dev_request_t req;
8225 + int request_type;
8226 + int n;
8227 + __u32 cs_bits;
8228 + __u32 address;
8229 + __u32 cs_reg_in = Ser0UDCCS0;
8231 + if (cs_reg_in & UDCCS0_SST) {
8232 + PRINTKD( "%ssetup begin: sent stall. Continuing\n", pszMe );
8233 + set_cs_bits( UDCCS0_SST );
8236 + if ( cs_reg_in & UDCCS0_SE ) {
8237 + PRINTKD( "%ssetup begin: Early term of setup. Continuing\n", pszMe );
8238 + set_cs_bits( UDCCS0_SSE ); /* clear setup end */
8241 + /* Be sure out packet ready, otherwise something is wrong */
8242 + if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
8243 + /* we can get here early...if so, we'll int again in a moment */
8244 + PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
8245 + goto sh_sb_end;
8248 + /* read the setup request */
8249 + n = read_fifo( &req );
8250 + if ( n != sizeof( req ) ) {
8251 + printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
8252 + " Stalling out...\n",
8253 + pszMe, sizeof( req ), n );
8254 + /* force stall, serviced out */
8255 + set_cs_bits( UDCCS0_FST | UDCCS0_SO );
8256 + goto sh_sb_end;
8259 + /* Is it a standard request? (not vendor or class request) */
8260 + request_type = type_code_from_request( req.bmRequestType );
8261 + if ( request_type != 0 ) {
8262 + printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
8263 + pszMe, request_type );
8264 + set_cs_bits( UDCCS0_DE | UDCCS0_SO );
8265 + goto sh_sb_end;
8268 +#if VERBOSITY
8270 + unsigned char * pdb = (unsigned char *) &req;
8271 + PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
8272 + pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
8273 + );
8274 + preq( &req );
8276 +#endif
8278 + /* Handle it */
8279 + switch( req.bRequest ) {
8281 + /* This first bunch have no data phase */
8283 + case SET_ADDRESS:
8284 + address = (__u32) (req.wValue & 0x7F);
8285 + /* when SO and DE sent, UDC will enter status phase and ack,
8286 + ..propagating new address to udc core. Next control transfer
8287 + ..will be on the new address. You can't see the change in a
8288 + ..read back of CAR until then. (about 250us later, on my box).
8289 + ..The original Intel driver sets S0 and DE and code to check
8290 + ..that address has propagated here. I tried this, but it
8291 + ..would only work sometimes! The rest of the time it would
8292 + ..never propagate and we'd spin forever. So now I just set
8293 + ..it and pray...
8294 + */
8295 + Ser0UDCAR = address;
8296 + usbd_info.address = address;
8297 + usbctl_next_state_on_event( kEvAddress );
8298 + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
8299 + printk( "%sI have been assigned address: %d\n", pszMe, address );
8300 + break;
8303 + case SET_CONFIGURATION:
8304 + if ( req.wValue == 1 ) {
8305 + /* configured */
8306 + if (usbctl_next_state_on_event( kEvConfig ) != kError){
8307 + /* (re)set the out and in max packet sizes */
8308 + desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
8309 + __u32 out = __le16_to_cpu( pDesc->b.ep1.wMaxPacketSize );
8310 + __u32 in = __le16_to_cpu( pDesc->b.ep2.wMaxPacketSize );
8311 + Ser0UDCOMP = ( out - 1 );
8312 + Ser0UDCIMP = ( in - 1 );
8313 + printk( "%sConfigured (OMP=%8.8X IMP=%8.8X)\n", pszMe, out, in );
8315 + } else if ( req.wValue == 0 ) {
8316 + /* de-configured */
8317 + if (usbctl_next_state_on_event( kEvDeConfig ) != kError )
8318 + printk( "%sDe-Configured\n", pszMe );
8319 + } else {
8320 + printk( "%ssetup phase: Unknown "
8321 + "\"set configuration\" data %d\n",
8322 + pszMe, req.wValue );
8324 + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
8325 + break;
8327 + case CLEAR_FEATURE:
8328 + /* could check data length, direction...26Jan01ww */
8329 + if ( req.wValue == 0 ) { /* clearing ENDPOINT_HALT/STALL */
8330 + int ep = windex_to_ep_num( req.wIndex );
8331 + if ( ep == 1 ) {
8332 + printk( "%sclear feature \"endpoint halt\" "
8333 + " on receiver\n", pszMe );
8334 + ep1_reset();
8336 + else if ( ep == 2 ) {
8337 + printk( "%sclear feature \"endpoint halt\" "
8338 + "on xmitter\n", pszMe );
8339 + ep2_reset();
8340 + } else {
8341 + printk( "%sclear feature \"endpoint halt\" "
8342 + "on unsupported ep # %d\n",
8343 + pszMe, ep );
8345 + } else {
8346 + printk( "%sUnsupported feature selector (%d) "
8347 + "in clear feature. Ignored.\n" ,
8348 + pszMe, req.wValue );
8350 + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
8351 + break;
8353 + case SET_FEATURE:
8354 + if ( req.wValue == 0 ) { /* setting ENDPOINT_HALT/STALL */
8355 + int ep = windex_to_ep_num( req.wValue );
8356 + if ( ep == 1 ) {
8357 + printk( "%set feature \"endpoint halt\" "
8358 + "on receiver\n", pszMe );
8359 + ep1_stall();
8361 + else if ( ep == 2 ) {
8362 + printk( "%sset feature \"endpoint halt\" "
8363 + " on xmitter\n", pszMe );
8364 + ep2_stall();
8365 + } else {
8366 + printk( "%sset feature \"endpoint halt\" "
8367 + "on unsupported ep # %d\n",
8368 + pszMe, ep );
8371 + else {
8372 + printk( "%sUnsupported feature selector "
8373 + "(%d) in set feature\n",
8374 + pszMe, req.wValue );
8376 + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
8377 + break;
8380 + /* The rest have a data phase that writes back to the host */
8381 + case GET_STATUS:
8382 + /* return status bit flags */
8383 + status_buf[0] = status_buf[1] = 0;
8384 + n = request_target(req.bmRequestType);
8385 + switch( n ) {
8386 + case kTargetDevice:
8387 + if ( self_powered_hook() )
8388 + status_buf[0] |= 1;
8389 + break;
8390 + case kTargetInterface:
8391 + break;
8392 + case kTargetEndpoint:
8393 + /* return stalled bit */
8394 + n = windex_to_ep_num( req.wIndex );
8395 + if ( n == 1 )
8396 + status_buf[0] |= (Ser0UDCCS1 & UDCCS1_FST) >> 4;
8397 + else if ( n == 2 )
8398 + status_buf[0] |= (Ser0UDCCS2 & UDCCS2_FST) >> 5;
8399 + else {
8400 + printk( "%sUnknown endpoint (%d) "
8401 + "in GET_STATUS\n", pszMe, n );
8403 + break;
8404 + default:
8405 + printk( "%sUnknown target (%d) in GET_STATUS\n",
8406 + pszMe, n );
8407 + /* fall thru */
8408 + break;
8410 + cs_bits = queue_and_start_write( status_buf,
8411 + req.wLength,
8412 + sizeof( status_buf ) );
8413 + set_cs_bits( cs_bits );
8414 + break;
8415 + case GET_DESCRIPTOR:
8416 + get_descriptor( &req );
8417 + break;
8419 + case GET_CONFIGURATION:
8420 + status_buf[0] = (usbd_info.state == USB_STATE_CONFIGURED)
8421 + ? 1
8422 + : 0;
8423 + cs_bits = queue_and_start_write( status_buf, req.wLength, 1 );
8424 + set_cs_bits( cs_bits );
8425 + break;
8426 + case GET_INTERFACE:
8427 + printk( "%sfixme: get interface not supported\n", pszMe );
8428 + cs_bits = queue_and_start_write( NULL, req.wLength, 0 );
8429 + set_cs_bits( cs_bits );
8430 + break;
8431 + case SET_INTERFACE:
8432 + printk( "%sfixme: set interface not supported\n", pszMe );
8433 + set_cs_bits( UDCCS0_DE | UDCCS0_SO );
8434 + break;
8435 + default :
8436 + printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
8437 + break;
8438 + } /* switch( bRequest ) */
8440 +sh_sb_end:
8441 + return;
8445 + * common_wrtie_preamble()
8446 + * Called before execution of sh_write() or sh_write_with_empty_packet()
8447 + * Handles common abort conditions.
8449 + */
8450 +static void common_write_preamble( void )
8452 + /* If "setup end" has been set, the usb controller has
8453 + ..terminated a setup transaction before we set DE. This
8454 + ..happens during enumeration with some hosts. For example,
8455 + ..the host will ask for our device descriptor and specify
8456 + ..a return of 64 bytes. When we hand back the first 8, the
8457 + ..host will know our max packet size and turn around and
8458 + ..issue a new setup immediately. This causes the UDC to auto-ack
8459 + ..the new setup and set SE. We must then "unload" (process)
8460 + ..the new setup, which is what will happen after this preamble
8461 + ..is finished executing.
8462 + */
8463 + __u32 cs_reg_in = Ser0UDCCS0;
8465 + if ( cs_reg_in & UDCCS0_SE ) {
8466 + PRINTKD( "%swrite_preamble(): Early termination of setup\n", pszMe );
8467 + Ser0UDCCS0 = UDCCS0_SSE; /* clear setup end */
8468 + current_handler = sh_setup_begin;
8471 + if ( cs_reg_in & UDCCS0_SST ) {
8472 + PRINTKD( "%swrite_preamble(): UDC sent stall\n", pszMe );
8473 + Ser0UDCCS0 = UDCCS0_SST; /* clear setup end */
8474 + current_handler = sh_setup_begin;
8477 + if ( cs_reg_in & UDCCS0_OPR ) {
8478 + PRINTKD( "%swrite_preamble(): see OPR. Stopping write to "
8479 + "handle new SETUP\n", pszMe );
8480 + /* very rarely, you can get OPR and leftover IPR. Try to clear */
8481 + UDC_clear( Ser0UDCCS0, UDCCS0_IPR );
8482 + current_handler = sh_setup_begin;
8487 + * sh_write()
8488 + * This is the setup handler when we are in the data return phase of
8489 + * a setup request and have as much (or more) data than the host
8490 + * requested. If we enter this routine and bytes left is zero, the
8491 + * last data packet has gone (int is because IPR was just cleared)
8492 + * so we just set DE and reset. Otheriwse, we write another packet
8493 + * and set IPR.
8494 + */
8495 +static void sh_write()
8497 + PRINTKD( "W\n" );
8499 + if ( Ser0UDCCS0 & UDCCS0_IPR ) {
8500 + PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
8501 + return;
8504 + /* If bytes left is zero, we are coming in on the
8505 + ..interrupt after the last packet went out. And
8506 + ..we know we don't have to empty packet this transfer
8507 + ..so just set DE and we are done */
8509 + if ( 0 == wr.bytes_left ) {
8510 + /* that's it, so data end */
8511 + set_de();
8512 + wr.p = NULL; /* be anal */
8513 + current_handler = sh_setup_begin;
8514 + } else {
8515 + /* Otherwise, more data to go */
8516 + write_fifo();
8517 + set_ipr();
8521 + * sh_write_with_empty_packet()
8522 + * This is the setup handler when we don't have enough data to
8523 + * satisfy the host's request. After we send everything we've got
8524 + * we must send an empty packet (by setting IPR and DE) so the
8525 + * host can perform "short packet retirement" and not stall.
8527 + */
8528 +static void sh_write_with_empty_packet( void )
8530 + __u32 cs_reg_out = 0;
8531 + PRINTKD( "WE\n" );
8533 + if ( Ser0UDCCS0 & UDCCS0_IPR ) {
8534 + PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
8535 + return;
8538 + /* If bytes left is zero, we are coming in on the
8539 + ..interrupt after the last packet went out.
8540 + ..we must do short packet suff, so set DE and IPR
8541 + */
8543 + if ( 0 == wr.bytes_left ) {
8544 + set_ipr_and_de();
8545 + wr.p = NULL;
8546 + current_handler = sh_setup_begin;
8547 + PRINTKD( "%ssh_write empty() Sent empty packet \n", pszMe );
8548 + } else {
8549 + write_fifo(); /* send data */
8550 + set_ipr(); /* flag a packet is ready */
8552 + Ser0UDCCS0 = cs_reg_out;
8555 +/***************************************************************************
8556 +Other Private Subroutines
8557 +***************************************************************************/
8559 + * queue_and_start_write()
8560 + * p == data to send
8561 + * req == bytes host requested
8562 + * act == bytes we actually have
8563 + * Returns: bits to be flipped in ep0 control/status register
8565 + * Called from sh_setup_begin() to begin a data return phase. Sets up the
8566 + * global "wr"-ite structure and load the outbound FIFO with data.
8567 + * If can't send all the data, set appropriate handler for next interrupt.
8569 + */
8570 +static __u32 queue_and_start_write( void * in, int req, int act )
8572 + __u32 cs_reg_bits = UDCCS0_IPR;
8573 + unsigned char * p = (unsigned char*) in;
8575 + PRINTKD( "Qr=%d a=%d\n",req,act );
8577 + /* thou shalt not enter data phase until the serviced OUT is clear */
8578 + if ( ! clear_opr() ) {
8579 + printk( "%sSO did not clear OPR\n", pszMe );
8580 + return ( UDCCS0_DE | UDCCS0_SO ) ;
8582 + wr.p = p;
8583 + wr.bytes_left = MIN( act, req );
8585 + write_fifo();
8587 + if ( 0 == wr.bytes_left ) {
8588 + cs_reg_bits |= UDCCS0_DE; /* out in 1 so data end */
8589 + wr.p = NULL; /* be anal */
8591 + else if ( act < req ) /* we are going to short-change host */
8592 + current_handler = sh_write_with_empty_packet; /* so need nul to not stall */
8593 + else /* we have as much or more than requested */
8594 + current_handler = sh_write;
8596 + return cs_reg_bits; /* note: IPR was set uncondtionally at start of routine */
8599 + * write_fifo()
8600 + * Stick bytes in the 8 bytes endpoint zero FIFO.
8601 + * This version uses a variety of tricks to make sure the bytes
8602 + * are written correctly. 1. The count register is checked to
8603 + * see if the byte went in, and the write is attempted again
8604 + * if not. 2. An overall counter is used to break out so we
8605 + * don't hang in those (rare) cases where the UDC reverses
8606 + * direction of the FIFO underneath us without notification
8607 + * (in response to host aborting a setup transaction early).
8609 + */
8610 +static void write_fifo( void )
8612 + int bytes_this_time = MIN( wr.bytes_left, 8 );
8613 + int bytes_written = 0;
8614 + int i=0;
8616 + PRINTKD( "WF=%d: ", bytes_this_time );
8618 + while( bytes_this_time-- ) {
8619 + PRINTKD( "%2.2X ", *wr.p );
8620 + i = 0;
8621 + do {
8622 + Ser0UDCD0 = *wr.p;
8623 + udelay( 20 ); /* voodo 28Feb01ww */
8624 + i++;
8625 + } while( Ser0UDCWC == bytes_written && i < 10 );
8626 + if ( i == 50 ) {
8627 + printk( "%swrite_fifo: write failure\n", pszMe );
8628 + usbd_info.stats.ep0_fifo_write_failures++;
8631 + wr.p++;
8632 + bytes_written++;
8634 + wr.bytes_left -= bytes_written;
8636 + /* following propagation voodo so maybe caller writing IPR in
8637 + ..a moment might actually get it to stick 28Feb01ww */
8638 + udelay( 300 );
8640 + usbd_info.stats.ep0_bytes_written += bytes_written;
8641 + PRINTKD( "L=%d WCR=%8.8X\n", wr.bytes_left, Ser0UDCWC );
8644 + * read_fifo()
8645 + * Read 1-8 bytes out of FIFO and put in request.
8646 + * Called to do the initial read of setup requests
8647 + * from the host. Return number of bytes read.
8649 + * Like write fifo above, this driver uses multiple
8650 + * reads checked agains the count register with an
8651 + * overall timeout.
8653 + */
8654 +static int
8655 +read_fifo( usb_dev_request_t * request )
8657 + int bytes_read = 0;
8658 + int fifo_count;
8659 + int i;
8661 + unsigned char * pOut = (unsigned char*) request;
8663 + fifo_count = ( Ser0UDCWC & 0xFF );
8665 + ASSERT( fifo_count <= 8 );
8666 + PRINTKD( "RF=%d ", fifo_count );
8668 + while( fifo_count-- ) {
8669 + i = 0;
8670 + do {
8671 + *pOut = (unsigned char) Ser0UDCD0;
8672 + udelay( 10 );
8673 + } while( ( Ser0UDCWC & 0xFF ) != fifo_count && i < 10 );
8674 + if ( i == 10 ) {
8675 + printk( "%sread_fifo(): read failure\n", pszMe );
8676 + usbd_info.stats.ep0_fifo_read_failures++;
8678 + pOut++;
8679 + bytes_read++;
8682 + PRINTKD( "fc=%d\n", bytes_read );
8683 + usbd_info.stats.ep0_bytes_read++;
8684 + return bytes_read;
8688 + * get_descriptor()
8689 + * Called from sh_setup_begin to handle data return
8690 + * for a GET_DESCRIPTOR setup request.
8691 + */
8692 +static void get_descriptor( usb_dev_request_t * pReq )
8694 + __u32 cs_bits = 0;
8695 + string_desc_t * pString;
8696 + ep_desc_t * pEndpoint;
8698 + desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
8699 + int type = pReq->wValue >> 8;
8700 + int idx = pReq->wValue & 0xFF;
8702 + switch( type ) {
8703 + case USB_DESC_DEVICE:
8704 + cs_bits =
8705 + queue_and_start_write( &pDesc->dev,
8706 + pReq->wLength,
8707 + pDesc->dev.bLength );
8708 + break;
8710 + // return config descriptor buffer, cfg, intf, 2 ep
8711 + case USB_DESC_CONFIG:
8712 + cs_bits =
8713 + queue_and_start_write( &pDesc->b,
8714 + pReq->wLength,
8715 + sizeof( struct cdb ) );
8716 + break;
8718 + // not quite right, since doesn't do language code checking
8719 + case USB_DESC_STRING:
8720 + pString = sa1100_usb_get_string_descriptor( idx );
8721 + if ( pString ) {
8722 + if ( idx != 0 ) { // if not language index
8723 + printk( "%sReturn string %d: ", pszMe, idx );
8724 + psdesc( pString );
8726 + cs_bits =
8727 + queue_and_start_write( pString,
8728 + pReq->wLength,
8729 + pString->bLength );
8731 + else {
8732 + printk("%sunkown string index %d Stall.\n", pszMe, idx );
8733 + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
8735 + break;
8737 + case USB_DESC_INTERFACE:
8738 + if ( idx == pDesc->b.intf.bInterfaceNumber ) {
8739 + cs_bits =
8740 + queue_and_start_write( &pDesc->b.intf,
8741 + pReq->wLength,
8742 + pDesc->b.intf.bLength );
8744 + break;
8746 + case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */
8747 + if ( idx == 1 )
8748 + pEndpoint = &pDesc->b.ep1;
8749 + else if ( idx == 2 )
8750 + pEndpoint = &pDesc->b.ep2;
8751 + else
8752 + pEndpoint = NULL;
8753 + if ( pEndpoint ) {
8754 + cs_bits =
8755 + queue_and_start_write( pEndpoint,
8756 + pReq->wLength,
8757 + pEndpoint->bLength );
8758 + } else {
8759 + printk("%sunkown endpoint index %d Stall.\n", pszMe, idx );
8760 + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
8762 + break;
8765 + default :
8766 + printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
8767 + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
8768 + break;
8771 + set_cs_bits( cs_bits );
8775 +/* some voodo I am adding, since the vanilla macros just aren't doing it 1Mar01ww */
8777 +#define ABORT_BITS ( UDCCS0_SST | UDCCS0_SE )
8778 +#define OK_TO_WRITE (!( Ser0UDCCS0 & ABORT_BITS ))
8779 +#define BOTH_BITS (UDCCS0_IPR | UDCCS0_DE)
8781 +static void set_cs_bits( __u32 bits )
8783 + if ( bits & ( UDCCS0_SO | UDCCS0_SSE | UDCCS0_FST ) )
8784 + Ser0UDCCS0 = bits;
8785 + else if ( (bits & BOTH_BITS) == BOTH_BITS )
8786 + set_ipr_and_de();
8787 + else if ( bits & UDCCS0_IPR )
8788 + set_ipr();
8789 + else if ( bits & UDCCS0_DE )
8790 + set_de();
8793 +static void set_de( void )
8795 + int i = 1;
8796 + while( 1 ) {
8797 + if ( OK_TO_WRITE ) {
8798 + Ser0UDCCS0 |= UDCCS0_DE;
8799 + } else {
8800 + PRINTKD( "%sQuitting set DE because SST or SE set\n", pszMe );
8801 + break;
8803 + if ( Ser0UDCCS0 & UDCCS0_DE )
8804 + break;
8805 + udelay( i );
8806 + if ( ++i == 50 ) {
8807 + printk( "%sDangnabbbit! Cannot set DE! (DE=%8.8X CCS0=%8.8X)\n",
8808 + pszMe, UDCCS0_DE, Ser0UDCCS0 );
8809 + break;
8814 +static void set_ipr( void )
8816 + int i = 1;
8817 + while( 1 ) {
8818 + if ( OK_TO_WRITE ) {
8819 + Ser0UDCCS0 |= UDCCS0_IPR;
8820 + } else {
8821 + PRINTKD( "%sQuitting set IPR because SST or SE set\n", pszMe );
8822 + break;
8824 + if ( Ser0UDCCS0 & UDCCS0_IPR )
8825 + break;
8826 + udelay( i );
8827 + if ( ++i == 50 ) {
8828 + printk( "%sDangnabbbit! Cannot set IPR! (IPR=%8.8X CCS0=%8.8X)\n",
8829 + pszMe, UDCCS0_IPR, Ser0UDCCS0 );
8830 + break;
8837 +static void set_ipr_and_de( void )
8839 + int i = 1;
8840 + while( 1 ) {
8841 + if ( OK_TO_WRITE ) {
8842 + Ser0UDCCS0 |= BOTH_BITS;
8843 + } else {
8844 + PRINTKD( "%sQuitting set IPR/DE because SST or SE set\n", pszMe );
8845 + break;
8847 + if ( (Ser0UDCCS0 & BOTH_BITS) == BOTH_BITS)
8848 + break;
8849 + udelay( i );
8850 + if ( ++i == 50 ) {
8851 + printk( "%sDangnabbbit! Cannot set DE/IPR! (DE=%8.8X IPR=%8.8X CCS0=%8.8X)\n",
8852 + pszMe, UDCCS0_DE, UDCCS0_IPR, Ser0UDCCS0 );
8853 + break;
8858 +static bool clear_opr( void )
8860 + int i = 10000;
8861 + bool is_clear;
8862 + do {
8863 + Ser0UDCCS0 = UDCCS0_SO;
8864 + is_clear = ! ( Ser0UDCCS0 & UDCCS0_OPR );
8865 + if ( i-- <= 0 ) {
8866 + printk( "%sclear_opr(): failed\n", pszMe );
8867 + break;
8869 + } while( ! is_clear );
8870 + return is_clear;
8877 +/* end usb_ep0.c */
8879 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
8880 +++ linux-2.4.25/arch/arm/mach-sa1100/usb_recv.c 2004-03-31 17:15:09.000000000 +0200
8881 @@ -0,0 +1,205 @@
8883 + * Generic receive layer for the SA1100 USB client function
8884 + * Copyright (c) 2001 by Nicolas Pitre
8886 + * This code was loosely inspired by the original version which was
8887 + * Copyright (c) Compaq Computer Corporation, 1998-1999
8889 + * This program is free software; you can redistribute it and/or modify
8890 + * it under the terms of the GNU General Public License version 2 as
8891 + * published by the Free Software Foundation.
8893 + * This is still work in progress...
8895 + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
8896 + */
8898 +#include <linux/module.h>
8899 +#include <linux/pci.h>
8900 +#include <linux/errno.h>
8901 +#include <asm/dma.h>
8902 +#include <asm/system.h>
8904 +#include "sa1100_usb.h"
8905 +#include "usb_ctl.h"
8908 +static char *ep1_buf;
8909 +static int ep1_len;
8910 +static usb_callback_t ep1_callback;
8911 +static char *ep1_curdmabuf;
8912 +static dma_addr_t ep1_curdmapos;
8913 +static int ep1_curdmalen;
8914 +static int ep1_remain;
8915 +static int dmachn_rx;
8916 +static int rx_pktsize;
8918 +static int naking;
8920 +static void
8921 +ep1_start(void)
8923 + sa1100_dma_flush_all(dmachn_rx);
8924 + if (!ep1_curdmalen) {
8925 + ep1_curdmalen = rx_pktsize;
8926 + if (ep1_curdmalen > ep1_remain)
8927 + ep1_curdmalen = ep1_remain;
8928 + ep1_curdmapos = pci_map_single(NULL, ep1_curdmabuf, ep1_curdmalen,
8929 + PCI_DMA_FROMDEVICE);
8931 + sa1100_dma_queue_buffer(dmachn_rx, NULL, ep1_curdmapos, ep1_curdmalen);
8932 + if ( naking ) {
8933 + /* turn off NAK of OUT packets, if set */
8934 + UDC_flip( Ser0UDCCS1, UDCCS1_RPC );
8935 + naking = 0;
8939 +static void
8940 +ep1_done(int flag)
8942 + int size = ep1_len - ep1_remain;
8944 + if (!ep1_len)
8945 + return;
8946 + if (ep1_curdmalen)
8947 + pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
8948 + PCI_DMA_FROMDEVICE);
8949 + ep1_len = ep1_curdmalen = 0;
8950 + if (ep1_callback) {
8951 + ep1_callback(flag, size);
8955 +void
8956 +ep1_state_change_notify( int new_state )
8961 +void
8962 +ep1_stall( void )
8964 + /* SET_FEATURE force stall at UDC */
8965 + UDC_set( Ser0UDCCS1, UDCCS1_FST );
8968 +int
8969 +ep1_init(int chn)
8971 + desc_t * pd = sa1100_usb_get_descriptor_ptr();
8972 + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
8973 + dmachn_rx = chn;
8974 + sa1100_dma_flush_all(dmachn_rx);
8975 + ep1_done(-EAGAIN);
8976 + return 0;
8979 +void
8980 +ep1_reset(void)
8982 + desc_t * pd = sa1100_usb_get_descriptor_ptr();
8983 + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
8984 + sa1100_dma_flush_all(dmachn_rx);
8985 + UDC_clear(Ser0UDCCS1, UDCCS1_FST);
8986 + ep1_done(-EINTR);
8989 +void
8990 +ep1_int_hndlr(int udcsr)
8992 + dma_addr_t dma_addr;
8993 + unsigned int len;
8994 + int status = Ser0UDCCS1;
8996 + if ( naking ) printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking );
8998 + if (status & UDCCS1_RPC) {
9000 + if (!ep1_curdmalen) {
9001 + printk("usb_recv: RPC for non-existent buffer\n");
9002 + naking=1;
9003 + return;
9006 + sa1100_dma_stop(dmachn_rx);
9008 + if (status & UDCCS1_SST) {
9009 + printk("usb_recv: stall sent OMP=%d\n",Ser0UDCOMP);
9010 + UDC_flip(Ser0UDCCS1, UDCCS1_SST);
9011 + ep1_done(-EIO); // UDC aborted current transfer, so we do
9012 + return;
9015 + if (status & UDCCS1_RPE) {
9016 + printk("usb_recv: RPError %x\n", status);
9017 + UDC_flip(Ser0UDCCS1, UDCCS1_RPC);
9018 + ep1_done(-EIO);
9019 + return;
9022 + sa1100_dma_get_current(dmachn_rx, NULL, &dma_addr);
9023 + pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
9024 + PCI_DMA_FROMDEVICE);
9025 + len = dma_addr - ep1_curdmapos;
9026 + if (len < ep1_curdmalen) {
9027 + char *buf = ep1_curdmabuf + len;
9028 + while (Ser0UDCCS1 & UDCCS1_RNE) {
9029 + if (len >= ep1_curdmalen) {
9030 + printk("usb_recv: too much data in fifo\n");
9031 + break;
9033 + *buf++ = Ser0UDCDR;
9034 + len++;
9036 + } else if (Ser0UDCCS1 & UDCCS1_RNE) {
9037 + printk("usb_recv: fifo screwed, shouldn't contain data\n");
9038 + len = 0;
9040 + ep1_curdmalen = 0; /* dma unmap already done */
9041 + ep1_remain -= len;
9042 + naking = 1;
9043 + ep1_done((len) ? 0 : -EPIPE);
9045 + /* else, you can get here if we are holding NAK */
9048 +int
9049 +sa1100_usb_recv(char *buf, int len, usb_callback_t callback)
9051 + int flags;
9053 + if (ep1_len)
9054 + return -EBUSY;
9056 + local_irq_save(flags);
9057 + ep1_buf = buf;
9058 + ep1_len = len;
9059 + ep1_callback = callback;
9060 + ep1_remain = len;
9061 + ep1_curdmabuf = buf;
9062 + ep1_curdmalen = 0;
9063 + ep1_start();
9064 + local_irq_restore(flags);
9066 + return 0;
9069 +EXPORT_SYMBOL(sa1100_usb_recv);
9071 +void
9072 +sa1100_usb_recv_reset(void)
9074 + ep1_reset();
9077 +EXPORT_SYMBOL(sa1100_usb_recv_reset);
9079 +void
9080 +sa1100_usb_recv_stall(void)
9082 + ep1_stall();
9085 +EXPORT_SYMBOL(sa1100_usb_recv_stall);
9087 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
9088 +++ linux-2.4.25/arch/arm/mach-sa1100/usb_send.c 2004-03-31 17:15:09.000000000 +0200
9089 @@ -0,0 +1,205 @@
9091 + * Generic xmit layer for the SA1100 USB client function
9092 + * Copyright (c) 2001 by Nicolas Pitre
9094 + * This code was loosely inspired by the original version which was
9095 + * Copyright (c) Compaq Computer Corporation, 1998-1999
9097 + * This program is free software; you can redistribute it and/or modify
9098 + * it under the terms of the GNU General Public License version 2 as
9099 + * published by the Free Software Foundation.
9101 + * This is still work in progress...
9103 + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
9104 + * 15/03/2001 - ep2_start now sets UDCAR to overcome something that is hardware
9105 + * bug, I think. green@iXcelerator.com
9106 + */
9108 +#include <linux/module.h>
9109 +#include <linux/pci.h>
9110 +#include <linux/errno.h>
9111 +#include <linux/delay.h> // for the massive_attack hack 28Feb01ww
9112 +#include <asm/hardware.h>
9113 +#include <asm/dma.h>
9114 +#include <asm/system.h>
9115 +#include <asm/byteorder.h>
9117 +#include "sa1100_usb.h"
9118 +#include "usb_ctl.h"
9121 +static char *ep2_buf;
9122 +static int ep2_len;
9123 +static usb_callback_t ep2_callback;
9124 +static dma_addr_t ep2_dma;
9125 +static dma_addr_t ep2_curdmapos;
9126 +static int ep2_curdmalen;
9127 +static int ep2_remain;
9128 +static int dmachn_tx;
9129 +static int tx_pktsize;
9131 +/* device state is changing, async */
9132 +void
9133 +ep2_state_change_notify( int new_state )
9137 +/* set feature stall executing, async */
9138 +void
9139 +ep2_stall( void )
9141 + UDC_set( Ser0UDCCS2, UDCCS2_FST ); /* force stall at UDC */
9144 +static void
9145 +ep2_start(void)
9147 + if (!ep2_len)
9148 + return;
9150 + ep2_curdmalen = tx_pktsize;
9151 + if (ep2_curdmalen > ep2_remain)
9152 + ep2_curdmalen = ep2_remain;
9154 + /* must do this _before_ queue buffer.. */
9155 + UDC_flip( Ser0UDCCS2,UDCCS2_TPC ); /* stop NAKing IN tokens */
9156 + UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
9158 + /* Remove if never seen...8Mar01ww */
9160 + int massive_attack = 20;
9161 + while ( Ser0UDCIMP != ep2_curdmalen-1 && massive_attack-- ) {
9162 + printk( "usbsnd: Oh no you don't! Let me spin..." );
9163 + udelay( 500 );
9164 + printk( "and try again...\n" );
9165 + UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
9167 + if ( massive_attack != 20 ) {
9168 + if ( Ser0UDCIMP != ep2_curdmalen-1 )
9169 + printk( "usbsnd: Massive attack FAILED :-( %d\n",
9170 + 20 - massive_attack );
9171 + else
9172 + printk( "usbsnd: Massive attack WORKED :-) %d\n",
9173 + 20 - massive_attack );
9176 + /* End remove if never seen... 8Mar01ww */
9178 + Ser0UDCAR = usbd_info.address; // fighting stupid silicon bug
9179 + sa1100_dma_queue_buffer(dmachn_tx, NULL, ep2_curdmapos, ep2_curdmalen);
9182 +static void
9183 +ep2_done(int flag)
9185 + int size = ep2_len - ep2_remain;
9186 + if (ep2_len) {
9187 + pci_unmap_single(NULL, ep2_dma, ep2_len, PCI_DMA_TODEVICE);
9188 + ep2_len = 0;
9189 + if (ep2_callback)
9190 + ep2_callback(flag, size);
9194 +int
9195 +ep2_init(int chn)
9197 + desc_t * pd = sa1100_usb_get_descriptor_ptr();
9198 + tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
9199 + dmachn_tx = chn;
9200 + sa1100_dma_flush_all(dmachn_tx);
9201 + ep2_done(-EAGAIN);
9202 + return 0;
9205 +void
9206 +ep2_reset(void)
9208 + desc_t * pd = sa1100_usb_get_descriptor_ptr();
9209 + tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
9210 + UDC_clear(Ser0UDCCS2, UDCCS2_FST);
9211 + sa1100_dma_flush_all(dmachn_tx);
9212 + ep2_done(-EINTR);
9215 +void
9216 +ep2_int_hndlr(int udcsr)
9218 + int status = Ser0UDCCS2;
9220 + if (Ser0UDCAR != usbd_info.address) // check for stupid silicon bug.
9221 + Ser0UDCAR = usbd_info.address;
9223 + UDC_flip(Ser0UDCCS2, UDCCS2_SST);
9225 + if (status & UDCCS2_TPC) {
9226 + sa1100_dma_flush_all(dmachn_tx);
9228 + if (status & (UDCCS2_TPE | UDCCS2_TUR)) {
9229 + printk("usb_send: transmit error %x\n", status);
9230 + ep2_done(-EIO);
9231 + } else {
9232 +#if 1 // 22Feb01ww/Oleg
9233 + ep2_curdmapos += ep2_curdmalen;
9234 + ep2_remain -= ep2_curdmalen;
9235 +#else
9236 + ep2_curdmapos += Ser0UDCIMP + 1; // this is workaround
9237 + ep2_remain -= Ser0UDCIMP + 1; // for case when setting of Ser0UDCIMP was failed
9238 +#endif
9240 + if (ep2_remain != 0) {
9241 + ep2_start();
9242 + } else {
9243 + ep2_done(0);
9246 + } else {
9247 + printk("usb_send: Not TPC: UDCCS2 = %x\n", status);
9251 +int
9252 +sa1100_usb_send(char *buf, int len, usb_callback_t callback)
9254 + int flags;
9256 + if (usbd_info.state != USB_STATE_CONFIGURED)
9257 + return -ENODEV;
9259 + if (ep2_len)
9260 + return -EBUSY;
9262 + local_irq_save(flags);
9263 + ep2_buf = buf;
9264 + ep2_len = len;
9265 + ep2_dma = pci_map_single(NULL, buf, len, PCI_DMA_TODEVICE);
9266 + ep2_callback = callback;
9267 + ep2_remain = len;
9268 + ep2_curdmapos = ep2_dma;
9269 + ep2_start();
9270 + local_irq_restore(flags);
9272 + return 0;
9276 +void
9277 +sa1100_usb_send_reset(void)
9279 + ep2_reset();
9282 +int sa1100_usb_xmitter_avail( void )
9284 + if (usbd_info.state != USB_STATE_CONFIGURED)
9285 + return -ENODEV;
9286 + if (ep2_len)
9287 + return -EBUSY;
9288 + return 0;
9292 +EXPORT_SYMBOL(sa1100_usb_xmitter_avail);
9293 +EXPORT_SYMBOL(sa1100_usb_send);
9294 +EXPORT_SYMBOL(sa1100_usb_send_reset);
9295 --- linux-2.4.25/arch/arm/mm/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
9296 +++ linux-2.4.25/arch/arm/mm/Makefile 2004-03-31 17:15:09.000000000 +0200
9297 @@ -39,6 +39,8 @@
9298 p-$(CONFIG_CPU_ARM925T) += proc-arm925.o
9299 p-$(CONFIG_CPU_ARM926T) += proc-arm926.o
9300 p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o
9301 +p-$(CONFIG_CPU_ARM1020E) += proc-arm1020E.o
9302 +p-$(CONFIG_CPU_ARM1022) += proc-arm1022.o
9303 p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
9304 p-$(CONFIG_CPU_SA110) += proc-sa110.o
9305 p-$(CONFIG_CPU_SA1100) += proc-sa110.o
9306 --- linux-2.4.25/arch/arm/mm/alignment.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
9307 +++ linux-2.4.25/arch/arm/mm/alignment.c 2004-03-31 17:15:09.000000000 +0200
9308 @@ -11,7 +11,6 @@
9309 #include <linux/config.h>
9310 #include <linux/compiler.h>
9311 #include <linux/signal.h>
9312 -#include <linux/sched.h>
9313 #include <linux/kernel.h>
9314 #include <linux/errno.h>
9315 #include <linux/string.h>
9316 @@ -19,7 +18,6 @@
9317 #include <linux/ptrace.h>
9318 #include <linux/mman.h>
9319 #include <linux/mm.h>
9320 -#include <linux/interrupt.h>
9321 #include <linux/proc_fs.h>
9322 #include <linux/bitops.h>
9323 #include <linux/init.h>
9324 @@ -30,9 +28,7 @@
9325 #include <asm/pgtable.h>
9326 #include <asm/unaligned.h>
9328 -extern void
9329 -do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
9330 - int error_code, struct pt_regs *regs);
9331 +#include "fault.h"
9334 * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
9335 @@ -130,31 +126,6 @@
9336 return count;
9340 - * This needs to be done after sysctl_init, otherwise sys/ will be
9341 - * overwritten. Actually, this shouldn't be in sys/ at all since
9342 - * it isn't a sysctl, and it doesn't contain sysctl information.
9343 - * We now locate it in /proc/cpu/alignment instead.
9344 - */
9345 -static int __init alignment_init(void)
9347 - struct proc_dir_entry *res;
9349 - res = proc_mkdir("cpu", NULL);
9350 - if (!res)
9351 - return -ENOMEM;
9353 - res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
9354 - if (!res)
9355 - return -ENOMEM;
9357 - res->read_proc = proc_alignment_read;
9358 - res->write_proc = proc_alignment_write;
9360 - return 0;
9363 -__initcall(alignment_init);
9364 #endif /* CONFIG_PROC_FS */
9366 union offset_union {
9367 @@ -429,7 +400,7 @@
9368 * For alignment faults on the ARM922T/ARM920T the MMU makes
9369 * the FSR (and hence addr) equal to the updated base address
9370 * of the multiple access rather than the restored value.
9371 - * Switch this messsage off if we've got a ARM92[02], otherwise
9372 + * Switch this message off if we've got a ARM92[02], otherwise
9373 * [ls]dm alignment faults are noisy!
9375 #if !(defined CONFIG_CPU_ARM922T) && !(defined CONFIG_CPU_ARM920T)
9376 @@ -486,7 +457,8 @@
9377 return TYPE_ERROR;
9380 -int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
9381 +static int
9382 +do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
9384 union offset_union offset;
9385 unsigned long instr, instrptr;
9386 @@ -541,7 +513,7 @@
9387 case SHIFT_RORRRX:
9388 if (shiftval == 0) {
9389 offset.un >>= 1;
9390 - if (regs->ARM_cpsr & CC_C_BIT)
9391 + if (regs->ARM_cpsr & PSR_C_BIT)
9392 offset.un |= 1 << 31;
9393 } else
9394 offset.un = offset.un >> shiftval |
9395 @@ -577,7 +549,7 @@
9397 * We got a fault - fix it up, or die.
9399 - do_bad_area(current, current->mm, addr, error_code, regs);
9400 + do_bad_area(current, current->mm, addr, fsr, regs);
9401 return 0;
9403 bad:
9404 @@ -594,8 +566,8 @@
9406 if (ai_usermode & 1)
9407 printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%08lx "
9408 - "Address=0x%08lx Code 0x%02x\n", current->comm,
9409 - current->pid, instrptr, instr, addr, error_code);
9410 + "Address=0x%08lx FSR 0x%03x\n", current->comm,
9411 + current->pid, instrptr, instr, addr, fsr);
9413 if (ai_usermode & 2)
9414 goto fixup;
9415 @@ -607,3 +579,34 @@
9417 return 0;
9421 + * This needs to be done after sysctl_init, otherwise sys/ will be
9422 + * overwritten. Actually, this shouldn't be in sys/ at all since
9423 + * it isn't a sysctl, and it doesn't contain sysctl information.
9424 + * We now locate it in /proc/cpu/alignment instead.
9425 + */
9426 +static int __init alignment_init(void)
9428 +#ifdef CONFIG_PROC_FS
9429 + struct proc_dir_entry *res;
9431 + res = proc_mkdir("cpu", NULL);
9432 + if (!res)
9433 + return -ENOMEM;
9435 + res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
9436 + if (!res)
9437 + return -ENOMEM;
9439 + res->read_proc = proc_alignment_read;
9440 + res->write_proc = proc_alignment_write;
9441 +#endif
9443 + hook_fault_code(1, do_alignment, SIGILL, "alignment exception");
9444 + hook_fault_code(3, do_alignment, SIGILL, "alignment exception");
9446 + return 0;
9449 +__initcall(alignment_init);
9450 --- linux-2.4.25/arch/arm/mm/fault-armv.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
9451 +++ linux-2.4.25/arch/arm/mm/fault-armv.c 2004-03-31 17:15:09.000000000 +0200
9452 @@ -2,116 +2,90 @@
9453 * linux/arch/arm/mm/fault-armv.c
9455 * Copyright (C) 1995 Linus Torvalds
9456 - * Modifications for ARM processor (c) 1995-2001 Russell King
9457 + * Modifications for ARM processor (c) 1995-2003 Russell King
9459 * This program is free software; you can redistribute it and/or modify
9460 * it under the terms of the GNU General Public License version 2 as
9461 * published by the Free Software Foundation.
9463 -#include <linux/config.h>
9464 -#include <linux/signal.h>
9465 #include <linux/sched.h>
9466 #include <linux/kernel.h>
9467 -#include <linux/errno.h>
9468 -#include <linux/string.h>
9469 #include <linux/types.h>
9470 #include <linux/ptrace.h>
9471 -#include <linux/mman.h>
9472 #include <linux/mm.h>
9473 -#include <linux/interrupt.h>
9474 -#include <linux/proc_fs.h>
9475 #include <linux/bitops.h>
9476 #include <linux/init.h>
9478 -#include <asm/system.h>
9479 -#include <asm/uaccess.h>
9480 #include <asm/pgalloc.h>
9481 #include <asm/pgtable.h>
9482 +#include <asm/io.h>
9484 -extern void show_pte(struct mm_struct *mm, unsigned long addr);
9485 -extern int do_page_fault(unsigned long addr, int error_code,
9486 - struct pt_regs *regs);
9487 -extern int do_translation_fault(unsigned long addr, int error_code,
9488 - struct pt_regs *regs);
9489 -extern void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
9490 - unsigned long addr, int error_code,
9491 - struct pt_regs *regs);
9493 -#ifdef CONFIG_ALIGNMENT_TRAP
9494 -extern int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs);
9495 -#else
9496 -#define do_alignment do_bad
9497 -#endif
9499 +#include "fault.h"
9502 * Some section permission faults need to be handled gracefully.
9503 * They can happen due to a __{get,put}_user during an oops.
9505 static int
9506 -do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
9507 +do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
9509 struct task_struct *tsk = current;
9510 - do_bad_area(tsk, tsk->active_mm, addr, error_code, regs);
9511 + do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
9512 return 0;
9516 - * Hook for things that need to trap external faults. Note that
9517 - * we don't guarantee that this will be the final version of the
9518 - * interface.
9519 - */
9520 -int (*external_fault)(unsigned long addr, struct pt_regs *regs);
9522 -static int
9523 -do_external_fault(unsigned long addr, int error_code, struct pt_regs *regs)
9525 - if (external_fault)
9526 - return external_fault(addr, regs);
9527 - return 1;
9531 * This abort handler always returns "fault".
9533 static int
9534 -do_bad(unsigned long addr, int error_code, struct pt_regs *regs)
9535 +do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
9537 return 1;
9540 -static const struct fsr_info {
9541 - int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
9542 +static struct fsr_info {
9543 + int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
9544 int sig;
9545 const char *name;
9546 } fsr_info[] = {
9547 { do_bad, SIGSEGV, "vector exception" },
9548 - { do_alignment, SIGILL, "alignment exception" },
9549 + { do_bad, SIGILL, "alignment exception" },
9550 { do_bad, SIGKILL, "terminal exception" },
9551 - { do_alignment, SIGILL, "alignment exception" },
9552 - { do_external_fault, SIGBUS, "external abort on linefetch" },
9553 + { do_bad, SIGILL, "alignment exception" },
9554 + { do_bad, SIGBUS, "external abort on linefetch" },
9555 { do_translation_fault, SIGSEGV, "section translation fault" },
9556 - { do_external_fault, SIGBUS, "external abort on linefetch" },
9557 + { do_bad, SIGBUS, "external abort on linefetch" },
9558 { do_page_fault, SIGSEGV, "page translation fault" },
9559 - { do_external_fault, SIGBUS, "external abort on non-linefetch" },
9560 + { do_bad, SIGBUS, "external abort on non-linefetch" },
9561 { do_bad, SIGSEGV, "section domain fault" },
9562 - { do_external_fault, SIGBUS, "external abort on non-linefetch" },
9563 + { do_bad, SIGBUS, "external abort on non-linefetch" },
9564 { do_bad, SIGSEGV, "page domain fault" },
9565 { do_bad, SIGBUS, "external abort on translation" },
9566 { do_sect_fault, SIGSEGV, "section permission fault" },
9567 { do_bad, SIGBUS, "external abort on translation" },
9568 - { do_page_fault, SIGSEGV, "page permission fault" }
9569 + { do_page_fault, SIGSEGV, "page permission fault" },
9572 +void __init
9573 +hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
9574 + int sig, const char *name)
9576 + if (nr >= 0 && nr < ARRAY_SIZE(fsr_info)) {
9577 + fsr_info[nr].fn = fn;
9578 + fsr_info[nr].sig = sig;
9579 + fsr_info[nr].name = name;
9584 * Dispatch a data abort to the relevant handler.
9586 asmlinkage void
9587 -do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr)
9588 +do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
9590 const struct fsr_info *inf = fsr_info + (fsr & 15);
9592 - if (!inf->fn(addr, error_code, regs))
9593 + if (!inf->fn(addr, fsr, regs))
9594 return;
9596 printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
9597 @@ -127,25 +101,28 @@
9598 do_translation_fault(addr, 0, regs);
9601 +static unsigned long shared_pte_mask = L_PTE_CACHEABLE;
9604 * We take the easy way out of this problem - we make the
9605 * PTE uncacheable. However, we leave the write buffer on.
9607 -static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
9608 +static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
9610 pgd_t *pgd;
9611 pmd_t *pmd;
9612 pte_t *pte, entry;
9613 + int ret = 0;
9615 pgd = pgd_offset(vma->vm_mm, address);
9616 if (pgd_none(*pgd))
9617 - return;
9618 + goto no_pgd;
9619 if (pgd_bad(*pgd))
9620 goto bad_pgd;
9622 pmd = pmd_offset(pgd, address);
9623 if (pmd_none(*pmd))
9624 - return;
9625 + goto no_pmd;
9626 if (pmd_bad(*pmd))
9627 goto bad_pmd;
9629 @@ -156,27 +133,30 @@
9630 * If this page isn't present, or is already setup to
9631 * fault (ie, is old), we can safely ignore any issues.
9633 - if (pte_present(entry) && pte_val(entry) & L_PTE_CACHEABLE) {
9634 + if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
9635 flush_cache_page(vma, address);
9636 - pte_val(entry) &= ~L_PTE_CACHEABLE;
9637 + pte_val(entry) &= ~shared_pte_mask;
9638 set_pte(pte, entry);
9639 flush_tlb_page(vma, address);
9640 + ret = 1;
9642 - return;
9643 + return ret;
9645 bad_pgd:
9646 pgd_ERROR(*pgd);
9647 pgd_clear(pgd);
9648 - return;
9649 +no_pgd:
9650 + return 0;
9652 bad_pmd:
9653 pmd_ERROR(*pmd);
9654 pmd_clear(pmd);
9655 - return;
9656 +no_pmd:
9657 + return 0;
9660 static void
9661 -make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page)
9662 +make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
9664 struct vm_area_struct *mpnt;
9665 struct mm_struct *mm = vma->vm_mm;
9666 @@ -210,14 +190,17 @@
9667 if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
9668 continue;
9670 + off = mpnt->vm_start + (off << PAGE_SHIFT);
9673 * Ok, it is within mpnt. Fix it up.
9675 - adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT));
9676 - aliases ++;
9677 + aliases += adjust_pte(mpnt, off);
9679 if (aliases)
9680 adjust_pte(vma, addr);
9681 + else if (dirty)
9682 + flush_cache_page(vma, addr);
9686 @@ -242,11 +225,85 @@
9687 return;
9688 page = pfn_to_page(pfn);
9689 if (page->mapping) {
9690 - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
9691 + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
9693 + if (dirty) {
9694 unsigned long kvirt = (unsigned long)page_address(page);
9695 cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0);
9698 - make_coherent(vma, addr, page);
9699 + make_coherent(vma, addr, page, dirty);
9704 + * Check whether the write buffer has physical address aliasing
9705 + * issues. If it has, we need to avoid them for the case where
9706 + * we have several shared mappings of the same object in user
9707 + * space.
9708 + */
9709 +static int __init check_writebuffer(unsigned long *p1, unsigned long *p2)
9711 + register unsigned long zero = 0, one = 1, val;
9713 + mb();
9714 + *p1 = one;
9715 + mb();
9716 + *p2 = zero;
9717 + mb();
9718 + val = *p1;
9719 + mb();
9720 + return val != zero;
9723 +static inline void *map_page(struct page *page)
9725 + void *map;
9727 + map = __ioremap(page_to_phys(page), PAGE_SIZE, L_PTE_BUFFERABLE);
9728 + if (map)
9729 + get_page(page);
9730 + return map;
9733 +static inline void unmap_page(void *map)
9735 + iounmap(map);
9738 +void __init check_writebuffer_bugs(void)
9740 + struct page *page;
9741 + const char *reason;
9742 + unsigned long v = 1;
9744 + printk(KERN_INFO "CPU: Testing write buffer: ");
9746 + page = alloc_page(GFP_KERNEL);
9747 + if (page) {
9748 + unsigned long *p1, *p2;
9750 + p1 = map_page(page);
9751 + p2 = map_page(page);
9753 + if (p1 && p2) {
9754 + v = check_writebuffer(p1, p2);
9755 + reason = "enabling work-around";
9756 + } else {
9757 + reason = "unable to map memory\n";
9760 + unmap_page(p1);
9761 + unmap_page(p2);
9762 + put_page(page);
9763 + } else {
9764 + reason = "unable to grab page\n";
9767 + if (v) {
9768 + printk("FAIL - %s\n", reason);
9769 + shared_pte_mask |= L_PTE_BUFFERABLE;
9770 + } else {
9771 + printk("pass\n");
9774 --- linux-2.4.25/arch/arm/mm/fault-common.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
9775 +++ linux-2.4.25/arch/arm/mm/fault-common.c 2004-03-31 17:15:09.000000000 +0200
9776 @@ -11,21 +11,17 @@
9777 #include <linux/config.h>
9778 #include <linux/signal.h>
9779 #include <linux/sched.h>
9780 -#include <linux/kernel.h>
9781 -#include <linux/errno.h>
9782 #include <linux/string.h>
9783 -#include <linux/types.h>
9784 #include <linux/ptrace.h>
9785 -#include <linux/mman.h>
9786 #include <linux/mm.h>
9787 #include <linux/interrupt.h>
9788 -#include <linux/proc_fs.h>
9789 #include <linux/init.h>
9791 #include <asm/system.h>
9792 -#include <asm/uaccess.h>
9793 #include <asm/pgtable.h>
9794 -#include <asm/unaligned.h>
9795 +#include <asm/uaccess.h>
9797 +#include "fault.h"
9799 #ifdef CONFIG_CPU_26
9800 #define FAULT_CODE_WRITE 0x02
9801 @@ -34,13 +30,11 @@
9802 #define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
9803 #else
9805 - * On 32-bit processors, we define "mode" to be zero when reading,
9806 - * non-zero when writing. This now ties up nicely with the polarity
9807 - * of the 26-bit machines, and also means that we avoid the horrible
9808 - * gcc code for "int val = !other_val;".
9809 + * "code" is actually the FSR register. Bit 11 set means the
9810 + * instruction was performing a write.
9812 -#define DO_COW(m) (m)
9813 -#define READ_FAULT(m) (!(m))
9814 +#define DO_COW(code) ((code) & (1 << 11))
9815 +#define READ_FAULT(code) (!DO_COW(code))
9816 #endif
9819 @@ -54,16 +48,17 @@
9820 if (!mm)
9821 mm = &init_mm;
9823 - printk(KERN_ALERT "mm = %p pgd = %p\n", mm, mm->pgd);
9825 fs = get_fs();
9826 set_fs(get_ds());
9828 do {
9829 - pgd_t pg, *pgd = pgd_offset(mm, addr);
9830 + pgd_t pg, *pgd;
9831 pmd_t pm, *pmd;
9832 pte_t pt, *pte;
9834 - printk(KERN_ALERT "*pgd = ");
9835 + printk(KERN_ALERT "pgd = %p\n", mm->pgd);
9836 + pgd = pgd_offset(mm, addr);
9837 + printk(KERN_ALERT "[%08lx] *pgd=", addr);
9839 if (__get_user(pgd_val(pg), (unsigned long *)pgd)) {
9840 printk("(faulted)");
9841 @@ -122,7 +117,7 @@
9842 * Oops. The kernel tried to access some page that wasn't present.
9844 static void
9845 -__do_kernel_fault(struct mm_struct *mm, unsigned long addr, int error_code,
9846 +__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
9847 struct pt_regs *regs)
9849 unsigned long fixup;
9850 @@ -148,7 +143,7 @@
9851 "paging request", addr);
9853 show_pte(mm, addr);
9854 - die("Oops", regs, error_code);
9855 + die("Oops", regs, fsr);
9856 do_exit(SIGKILL);
9859 @@ -157,20 +152,20 @@
9860 * User mode accesses just cause a SIGSEGV
9862 static void
9863 -__do_user_fault(struct task_struct *tsk, unsigned long addr, int error_code,
9864 - int code, struct pt_regs *regs)
9865 +__do_user_fault(struct task_struct *tsk, unsigned long addr,
9866 + unsigned int fsr, int code, struct pt_regs *regs)
9868 struct siginfo si;
9870 #ifdef CONFIG_DEBUG_USER
9871 printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, "
9872 "lr=0x%08lx (bad address=0x%08lx, code %d)\n",
9873 - tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, error_code);
9874 + tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, fsr);
9875 show_regs(regs);
9876 #endif
9878 tsk->thread.address = addr;
9879 - tsk->thread.error_code = error_code;
9880 + tsk->thread.error_code = fsr;
9881 tsk->thread.trap_no = 14;
9882 si.si_signo = SIGSEGV;
9883 si.si_errno = 0;
9884 @@ -181,20 +176,20 @@
9886 void
9887 do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
9888 - int error_code, struct pt_regs *regs)
9889 + unsigned int fsr, struct pt_regs *regs)
9892 * If we are in kernel mode at this point, we
9893 * have no context to handle this fault with.
9895 if (user_mode(regs))
9896 - __do_user_fault(tsk, addr, error_code, SEGV_MAPERR, regs);
9897 + __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
9898 else
9899 - __do_kernel_fault(mm, addr, error_code, regs);
9900 + __do_kernel_fault(mm, addr, fsr, regs);
9903 static int
9904 -__do_page_fault(struct mm_struct *mm, unsigned long addr, int error_code,
9905 +__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
9906 struct task_struct *tsk)
9908 struct vm_area_struct *vma;
9909 @@ -212,7 +207,7 @@
9910 * memory access, so we can handle it.
9912 good_area:
9913 - if (READ_FAULT(error_code)) /* read? */
9914 + if (READ_FAULT(fsr)) /* read? */
9915 mask = VM_READ|VM_EXEC;
9916 else
9917 mask = VM_WRITE;
9918 @@ -227,7 +222,7 @@
9919 * than endlessly redo the fault.
9921 survive:
9922 - fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(error_code));
9923 + fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));
9926 * Handle the "normal" cases first - successful and sigbus
9927 @@ -260,7 +255,7 @@
9928 return fault;
9931 -int do_page_fault(unsigned long addr, int error_code, struct pt_regs *regs)
9932 +int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
9934 struct task_struct *tsk;
9935 struct mm_struct *mm;
9936 @@ -277,7 +272,7 @@
9937 goto no_context;
9939 down_read(&mm->mmap_sem);
9940 - fault = __do_page_fault(mm, addr, error_code, tsk);
9941 + fault = __do_page_fault(mm, addr, fsr, tsk);
9942 up_read(&mm->mmap_sem);
9945 @@ -308,7 +303,7 @@
9946 printk("VM: killing process %s\n", tsk->comm);
9947 do_exit(SIGKILL);
9948 } else
9949 - __do_user_fault(tsk, addr, error_code, fault == -1 ?
9950 + __do_user_fault(tsk, addr, fsr, fault == -1 ?
9951 SEGV_ACCERR : SEGV_MAPERR, regs);
9952 return 0;
9954 @@ -323,7 +318,7 @@
9955 * or user mode.
9957 tsk->thread.address = addr;
9958 - tsk->thread.error_code = error_code;
9959 + tsk->thread.error_code = fsr;
9960 tsk->thread.trap_no = 14;
9961 force_sig(SIGBUS, tsk);
9962 #ifdef CONFIG_DEBUG_USER
9963 @@ -336,7 +331,7 @@
9964 return 0;
9966 no_context:
9967 - __do_kernel_fault(mm, addr, error_code, regs);
9968 + __do_kernel_fault(mm, addr, fsr, regs);
9969 return 0;
9972 @@ -357,21 +352,23 @@
9973 * interrupt or a critical region, and should only copy the information
9974 * from the master page table, nothing more.
9976 -int do_translation_fault(unsigned long addr, int error_code, struct pt_regs *regs)
9977 +int do_translation_fault(unsigned long addr, unsigned int fsr,
9978 + struct pt_regs *regs)
9980 struct task_struct *tsk;
9981 - struct mm_struct *mm;
9982 int offset;
9983 pgd_t *pgd, *pgd_k;
9984 pmd_t *pmd, *pmd_k;
9986 if (addr < TASK_SIZE)
9987 - return do_page_fault(addr, error_code, regs);
9988 + return do_page_fault(addr, fsr, regs);
9990 offset = __pgd_offset(addr);
9993 * FIXME: CP15 C1 is write only on ARMv3 architectures.
9994 + * You really need to read the value in the page table
9995 + * register, not a copy.
9997 pgd = cpu_get_pgd() + offset;
9998 pgd_k = init_mm.pgd + offset;
9999 @@ -395,8 +392,7 @@
10001 bad_area:
10002 tsk = current;
10003 - mm = tsk->active_mm;
10005 - do_bad_area(tsk, mm, addr, error_code, regs);
10006 + do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
10007 return 0;
10009 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
10010 +++ linux-2.4.25/arch/arm/mm/fault.h 2004-03-31 17:15:09.000000000 +0200
10011 @@ -0,0 +1,9 @@
10012 +void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
10013 + unsigned long addr, unsigned int fsr, struct pt_regs *regs);
10015 +void show_pte(struct mm_struct *mm, unsigned long addr);
10017 +int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
10019 +int do_translation_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
10021 --- linux-2.4.25/arch/arm/mm/init.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
10022 +++ linux-2.4.25/arch/arm/mm/init.c 2004-03-31 17:15:09.000000000 +0200
10023 @@ -9,7 +9,6 @@
10025 #include <linux/config.h>
10026 #include <linux/signal.h>
10027 -#include <linux/sched.h>
10028 #include <linux/kernel.h>
10029 #include <linux/errno.h>
10030 #include <linux/string.h>
10031 @@ -18,7 +17,6 @@
10032 #include <linux/mman.h>
10033 #include <linux/mm.h>
10034 #include <linux/swap.h>
10035 -#include <linux/swapctl.h>
10036 #include <linux/smp.h>
10037 #include <linux/init.h>
10038 #include <linux/bootmem.h>
10039 --- linux-2.4.25/arch/arm/mm/ioremap.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
10040 +++ linux-2.4.25/arch/arm/mm/ioremap.c 2004-03-31 17:15:09.000000000 +0200
10041 @@ -144,7 +144,7 @@
10043 offset = phys_addr & ~PAGE_MASK;
10044 phys_addr &= PAGE_MASK;
10045 - size = PAGE_ALIGN(last_addr) - phys_addr;
10046 + size = PAGE_ALIGN(last_addr + 1) - phys_addr;
10049 * Ok, go for it..
10050 --- linux-2.4.25/arch/arm/mm/mm-armv.c~2.4.25-vrs2.patch 2003-11-28 19:26:19.000000000 +0100
10051 +++ linux-2.4.25/arch/arm/mm/mm-armv.c 2004-03-31 17:15:09.000000000 +0200
10052 @@ -9,7 +9,6 @@
10054 * Page table sludge for ARM v3 and v4 processor architectures.
10056 -#include <linux/sched.h>
10057 #include <linux/mm.h>
10058 #include <linux/init.h>
10059 #include <linux/bootmem.h>
10060 @@ -390,6 +389,9 @@
10061 init_maps->bufferable = 0;
10063 create_mapping(init_maps);
10065 + flush_cache_all();
10066 + flush_tlb_all();
10070 --- linux-2.4.25/arch/arm/mm/proc-arm1020.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
10071 +++ linux-2.4.25/arch/arm/mm/proc-arm1020.S 2004-03-31 17:15:09.000000000 +0200
10072 @@ -65,18 +65,21 @@
10074 * Returns:
10075 * r0 = address of abort
10076 - * r1 != 0 if writing
10077 - * r3 = FSR
10078 + * r1 = FSR
10079 + * r3 = corrupted
10080 * r4 = corrupted
10082 .align 5
10083 ENTRY(cpu_arm1020_data_abort)
10084 - mrc p15, 0, r3, c5, c0, 0 @ get FSR
10085 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
10086 mrc p15, 0, r0, c6, c0, 0 @ get FAR
10087 - ldr r1, [r2] @ read aborted instruction
10088 - and r3, r3, #255
10089 - tst r1, r1, lsr #21 @ C = bit 20
10090 - sbc r1, r1, r1 @ r1 = C - 1
10091 + tst r3, #PSR_T_BIT
10092 + ldrneh r3, [r2] @ read aborted thumb instruction
10093 + ldreq r3, [r2] @ read aborted ARM instruction
10094 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
10095 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
10096 + tst r3, #1 << 20 @ check write
10097 + orreq r1, r1, #1 << 11
10098 mov pc, lr
10101 @@ -170,10 +173,10 @@
10102 #endif
10103 subs r3, r3, #1
10104 cmp r3, #0
10105 - bge 2b @ entries 3F to 0
10106 + bhs 2b @ entries 3F to 0
10107 subs r1, r1, #1
10108 cmp r1, #0
10109 - bge 1b @ segments 7 to 0
10110 + bhs 1b @ segments 7 to 0
10111 #endif
10113 #ifndef CONFIG_CPU_ICACHE_DISABLE
10114 @@ -201,7 +204,7 @@
10115 bic r0, r0, #DCACHELINESIZE - 1
10116 sub r3, r1, r0
10117 cmp r3, #MAX_AREA_SIZE
10118 - bgt cpu_arm1020_cache_clean_invalidate_all_r2
10119 + bhi cpu_arm1020_cache_clean_invalidate_all_r2
10120 mcr p15, 0, r3, c7, c10, 4
10121 #ifndef CONFIG_CPU_DCACHE_DISABLE
10122 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
10123 @@ -214,7 +217,7 @@
10124 #endif
10125 add r0, r0, #DCACHELINESIZE
10126 cmp r0, r1
10127 - blt 1b
10128 + blo 1b
10129 #endif
10131 #ifndef CONFIG_CPU_ICACHE_DISABLE
10132 @@ -302,7 +305,7 @@
10133 #endif
10134 add r0, r0, #DCACHELINESIZE
10135 cmp r0, r1
10136 - blt 1b
10137 + blo 1b
10138 #else
10139 /* D cache off, but still drain the write buffer */
10140 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
10141 @@ -328,7 +331,7 @@
10142 bic r0, r0, #DCACHELINESIZE - 1
10143 sub r3, r1, r0
10144 cmp r3, #MAX_AREA_SIZE
10145 - bgt cpu_arm1020_cache_clean_invalidate_all_r2
10146 + bhi cpu_arm1020_cache_clean_invalidate_all_r2
10147 mcr p15, 0, r3, c7, c10, 4
10148 #ifndef CONFIG_CPU_DCACHE_DISABLE
10149 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
10150 @@ -341,7 +344,7 @@
10151 #endif
10152 add r0, r0, #DCACHELINESIZE
10153 cmp r0, r1
10154 - blt 1b
10155 + blo 1b
10156 #endif
10158 #ifndef CONFIG_CPU_BPREDICT_DISABLE
10159 @@ -488,7 +491,7 @@
10160 mov r0, r0
10161 #endif
10162 cmp r0, r1
10163 - blt 1b
10164 + blo 1b
10165 mov pc, lr
10168 @@ -541,10 +544,10 @@
10169 #endif
10170 subs r3, r3, #1
10171 cmp r3, #0
10172 - bge 2b @ entries 3F to 0
10173 + bhs 2b @ entries 3F to 0
10174 subs r1, r1, #1
10175 cmp r1, #0
10176 - bge 1b @ segments 15 to 0
10177 + bhs 1b @ segments 15 to 0
10179 #endif
10180 mov r1, #0
10181 @@ -603,7 +606,7 @@
10182 bic r2, r2, #3
10183 orr r2, r2, #HPTE_TYPE_SMALL
10185 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
10186 + tst r1, #LPTE_USER @ User?
10187 orrne r2, r2, #HPTE_AP_READ
10189 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
10190 @@ -740,12 +743,12 @@
10192 .type cpu_arch_name, #object
10193 cpu_arch_name:
10194 - .asciz "armv4"
10195 + .asciz "armv5t"
10196 .size cpu_arch_name, . - cpu_arch_name
10198 .type cpu_elf_name, #object
10199 cpu_elf_name:
10200 - .asciz "v4"
10201 + .asciz "v5"
10202 .size cpu_elf_name, . - cpu_elf_name
10203 .align
10205 @@ -753,9 +756,9 @@
10207 .type __arm1020_proc_info,#object
10208 __arm1020_proc_info:
10209 - .long 0x4100a200
10210 - .long 0xff00fff0
10211 - .long 0x00000c02 @ mmuflags
10212 + .long 0x4104a200 @ ARM 1020T (Architecture v5T)
10213 + .long 0xff0ffff0
10214 + .long 0x00000c0e @ mmuflags
10215 b __arm1020_setup
10216 .long cpu_arch_name
10217 .long cpu_elf_name
10218 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
10219 +++ linux-2.4.25/arch/arm/mm/proc-arm1020E.S 2004-03-31 17:15:09.000000000 +0200
10220 @@ -0,0 +1,718 @@
10222 + * linux/arch/arm/mm/proc-arm1020E.S: MMU functions for ARM1020E
10224 + * Copyright (C) 2000 ARM Limited
10225 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
10227 + * This program is free software; you can redistribute it and/or modify
10228 + * it under the terms of the GNU General Public License as published by
10229 + * the Free Software Foundation; either version 2 of the License, or
10230 + * (at your option) any later version.
10232 + * This program is distributed in the hope that it will be useful,
10233 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10234 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10235 + * GNU General Public License for more details.
10237 + * You should have received a copy of the GNU General Public License
10238 + * along with this program; if not, write to the Free Software
10239 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10242 + * These are the low level assembler for performing cache and TLB
10243 + * functions on the arm1020E.
10244 + */
10245 +#include <linux/linkage.h>
10246 +#include <linux/config.h>
10247 +#include <asm/assembler.h>
10248 +#include <asm/constants.h>
10249 +#include <asm/procinfo.h>
10250 +#include <asm/hardware.h>
10253 + * This is the maximum size of an area which will be invalidated
10254 + * using the single invalidate entry instructions. Anything larger
10255 + * than this, and we go for the whole cache.
10257 + * This value should be chosen such that we choose the cheapest
10258 + * alternative.
10259 + */
10260 +#define MAX_AREA_SIZE 32768
10263 + * the cache line size of the I and D cache
10264 + */
10265 +#define DCACHELINESIZE 32
10266 +#define ICACHELINESIZE 32
10269 + * and the page size
10270 + */
10271 +#define LOG2PAGESIZE 12 /* == 4096 Bytes */
10272 +#define PAGESIZE (1 << LOG2PAGESIZE)
10275 + * create some useful conditional macro definitions
10276 + * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
10277 + */
10278 +#ifdef CONFIG_CPU_DCACHE_DISABLE
10279 + #undef CONFIG_CPU_DCACHE_WRITETHROUGH
10280 + #undef CONFIG_CPU_DCACHE_WRITEBACK
10281 + #undef CONFIG_CPU_DCACHE_ENABLE
10282 +#else
10283 + #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10284 + #undef CONFIG_CPU_DCACHE_WRITEBACK
10285 + #else
10286 + #define CONFIG_CPU_DCACHE_WRITEBACK
10287 + #endif
10288 + #define CONFIG_CPU_DCACHE_ENABLE
10289 +#endif
10291 +#ifdef CONFIG_CPU_ICACHE_DISABLE
10292 + #undef CONFIG_CPU_ICACHE_ENABLE
10293 +#else
10294 + #define CONFIG_CPU_ICACHE_ENABLE
10295 +#endif
10297 + .text
10300 + * cpu_arm1020E_data_abort()
10302 + * obtain information about current aborted instruction
10303 + * Note: we read user space. This means we might cause a data
10304 + * abort here if the I-TLB and D-TLB aren't seeing the same
10305 + * picture. Unfortunately, this does happen. We live with it.
10307 + * r2 = address of aborted instruction
10308 + * r3 = cpsr
10310 + * Returns:
10311 + * r0 = address of abort
10312 + * r1 = FSR
10313 + * r3 = corrupted
10314 + * r4 = corrupted
10315 + */
10316 + .align 5
10317 +ENTRY(cpu_arm1020E_data_abort)
10318 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
10319 + mrc p15, 0, r0, c6, c0, 0 @ get FAR
10320 + tst r3, #PSR_T_BIT
10321 + ldrneh r3, [r2] @ read aborted thumb instruction
10322 + ldreq r3, [r2] @ read aborted ARM instruction
10323 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
10324 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
10325 + tst r3, #1 << 20 @ check write
10326 + orreq r1, r1, #1 << 11
10327 + mov pc, lr
10330 + * cpu_arm1020E_check_bugs()
10331 + */
10332 +ENTRY(cpu_arm1020E_check_bugs)
10333 + mrs ip, cpsr
10334 + bic ip, ip, #F_BIT
10335 + msr cpsr, ip
10336 + mov pc, lr
10339 + * cpu_arm1020E_proc_init()
10340 + */
10341 +ENTRY(cpu_arm1020E_proc_init)
10342 + mov pc, lr
10345 + * cpu_arm1020E_proc_fin()
10346 + */
10347 +ENTRY(cpu_arm1020E_proc_fin)
10348 + stmfd sp!, {lr}
10349 + mov ip, #F_BIT | I_BIT | SVC_MODE
10350 + msr cpsr_c, ip
10351 + bl cpu_arm1020E_cache_clean_invalidate_all
10352 + mrc p15, 0, r0, c1, c0, 0 @ ctrl register
10353 + bic r0, r0, #0x1000 @ ...i............
10354 + bic r0, r0, #0x000e @ ............wca.
10355 + mcr p15, 0, r0, c1, c0, 0 @ disable caches
10356 + ldmfd sp!, {pc}
10359 + * cpu_arm1020E_reset(loc)
10361 + * Perform a soft reset of the system. Put the CPU into the
10362 + * same state as it would be if it had been reset, and branch
10363 + * to what would be the reset vector.
10365 + * loc: location to jump to for soft reset
10366 + */
10367 + .align 5
10368 +ENTRY(cpu_arm1020E_reset)
10369 + mov ip, #0
10370 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
10371 + mcr p15, 0, ip, c7, c10, 4 @ drain WB
10372 + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
10373 + mrc p15, 0, ip, c1, c0, 0 @ ctrl register
10374 + bic ip, ip, #0x000f @ ............wcam
10375 + bic ip, ip, #0x1100 @ ...i...s........
10376 + mcr p15, 0, ip, c1, c0, 0 @ ctrl register
10377 + mov pc, r0
10380 + * cpu_arm1020E_do_idle()
10381 + */
10382 + .align 5
10383 +ENTRY(cpu_arm1020E_do_idle)
10384 + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
10385 + mov pc, lr
10387 +/* ================================= CACHE ================================ */
10391 + * cpu_arm1020E_cache_clean_invalidate_all()
10393 + * clean and invalidate all cache lines
10395 + * Note:
10396 + * 1. we should preserve r0 and ip at all times
10397 + */
10398 + .align 5
10399 +ENTRY(cpu_arm1020E_cache_clean_invalidate_all)
10400 + mov r2, #1
10401 +cpu_arm1020E_cache_clean_invalidate_all_r2:
10403 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10404 + mov r1, #0x0F << 5 @ 16 segments
10405 +1: orr r3, r1, #63 << 26 @ 64 entries
10406 +2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
10407 + subs r3, r3, #1 << 26
10408 + bcs 2b
10409 + subs r1, r1, #1 << 5
10410 + bcs 1b @ segments 15 to 0
10411 +#endif
10413 + mov r1, #0
10415 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10416 + mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
10417 +#endif
10419 +#ifdef CONFIG_CPU_ICACHE_ENABLE
10420 + teq r2, #0
10421 + mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
10422 +#endif
10423 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
10424 + mov pc, lr
10427 + * cpu_arm1020E_cache_clean_invalidate_range(start, end, flags)
10429 + * clean and invalidate all cache lines associated with this area of memory
10431 + * start: Area start address
10432 + * end: Area end address
10433 + * flags: nonzero for I cache as well
10434 + */
10435 + .align 5
10436 +ENTRY(cpu_arm1020E_cache_clean_invalidate_range)
10437 + bic r0, r0, #DCACHELINESIZE - 1
10438 + sub r3, r1, r0
10439 + cmp r3, #MAX_AREA_SIZE
10440 + bhs cpu_arm1020E_cache_clean_invalidate_all_r2
10442 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10443 + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
10444 +#endif
10445 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10446 + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
10447 +#endif
10448 +#ifdef CONFIG_CPU_ICACHE_ENABLE
10449 + teq r2, #0
10450 + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
10451 +#endif
10452 + add r0, r0, #DCACHELINESIZE
10453 + cmp r0, r1
10454 + bls 1b @ unsigned lower or same - must include end point (r1)!
10456 + mov r1, #0
10457 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
10458 + mov pc, lr
10461 + * cpu_arm1020E_flush_ram_page(page)
10463 + * clean and invalidate all cache lines associated with this area of memory
10465 + * page: page to clean and invalidate
10466 + */
10467 + .align 5
10468 +ENTRY(cpu_arm1020E_flush_ram_page)
10469 + mov r1, #PAGESIZE
10470 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
10471 + mov r0, r0, LSL #LOG2PAGESIZE
10473 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10474 + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
10475 +#endif
10476 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10477 + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
10478 +#endif
10479 +#ifdef CONFIG_CPU_ICACHE_ENABLE
10480 + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
10481 +#endif
10482 + add r0, r0, #DCACHELINESIZE
10483 + subs r1, r1, #DCACHELINESIZE
10484 + bne 1b
10486 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
10487 + mov pc, lr
10489 +/* ================================ D-CACHE =============================== */
10492 + * cpu_arm1020E_dcache_invalidate_range(start, end)
10494 + * throw away all D-cached data in specified region without an obligation
10495 + * to write them back. Note however that we must clean the D-cached entries
10496 + * around the boundaries if the start and/or end address are not cache
10497 + * aligned.
10499 + * start: virtual start address
10500 + * end: virtual end address
10501 + */
10502 + .align 5
10503 +ENTRY(cpu_arm1020E_dcache_invalidate_range)
10504 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10505 + bic r0, r0, #DCACHELINESIZE - 1
10506 +#endif
10507 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10508 + tst r0, #DCACHELINESIZE - 1
10509 + bic r0, r0, #DCACHELINESIZE - 1
10510 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
10511 + tst r1, #DCACHELINESIZE - 1
10512 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
10513 +#endif
10516 +#ifdef CONFIG_CPU_DCACHE_ENABLE
10517 + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
10518 +#endif
10519 +#ifdef CONFIG_CPU_ICACHE_ENABLE
10520 + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
10521 +#endif
10522 + add r0, r0, #DCACHELINESIZE
10523 + cmp r0, r1
10524 + bls 1b
10526 + /* Even if the D cache is off still drain the write buffer */
10527 + mov r0, #0
10528 + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
10529 + mov pc, lr
10532 + * cpu_arm1020E_dcache_clean_range(start, end)
10534 + * For the specified virtual address range, ensure that all caches contain
10535 + * clean data, such that peripheral accesses to the physical RAM fetch
10536 + * correct data.
10538 + * start: virtual start address
10539 + * end: virtual end address
10540 + */
10541 + .align 5
10542 +ENTRY(cpu_arm1020E_dcache_clean_range)
10544 + mov r2, #0
10546 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10547 + bic r0, r0, #DCACHELINESIZE - 1
10548 + sub r3, r1, r0
10549 + cmp r3, #MAX_AREA_SIZE
10550 + bhs cpu_arm1020E_cache_clean_invalidate_all_r2
10552 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
10553 + add r0, r0, #DCACHELINESIZE
10554 + cmp r0, r1
10555 + bls 1b
10556 +#endif
10558 + mcr p15, 0, r2, c7, c10, 4 @ drain WB
10559 + mov pc, lr
10562 + * cpu_arm1020E_dcache_clean_page(page)
10564 + * Cleans a single page of dcache so that if we have any future aliased
10565 + * mappings, they will be consistent at the time that they are created.
10567 + * page: virtual address of page to clean from dcache
10569 + * Note:
10570 + * we don't invalidate the entries since when we write the page
10571 + * out to disk, the entries may get reloaded into the cache.
10572 + */
10573 + .align 5
10574 +ENTRY(cpu_arm1020E_dcache_clean_page)
10575 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10576 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
10577 + mov r0, r0, LSL #LOG2PAGESIZE
10578 + mov r1, #PAGESIZE
10580 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
10581 + add r0, r0, #DCACHELINESIZE
10582 + subs r1, r1, #DCACHELINESIZE
10583 + bne 1b
10584 +#endif
10585 + mov r1, #0
10586 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
10587 + mov pc, lr
10590 + * cpu_arm1020E_dcache_clean_entry(addr)
10592 + * Clean the specified entry of any caches such that the MMU
10593 + * translation fetches will obtain correct data.
10595 + * addr: cache-unaligned virtual address
10596 + */
10597 + .align 5
10598 +ENTRY(cpu_arm1020E_dcache_clean_entry)
10599 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10600 + bic r0, r0, #DCACHELINESIZE - 1
10601 + mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
10602 +#endif
10603 + mov r1, #0
10604 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
10605 + mov pc, lr
10607 +/* ================================ I-CACHE =============================== */
10610 + * cpu_arm1020E_icache_invalidate_range(start, end)
10612 + * invalidate a range of virtual addresses from the Icache
10614 + * This is a little misleading, it is not intended to clean out
10615 + * the i-cache but to make sure that any data written to the
10616 + * range is made consistent. This means that when we execute code
10617 + * in that region, everything works as we expect.
10619 + * This generally means writing back data in the Dcache and
10620 + * write buffer and invalidating the Icache over that region
10622 + * start: virtual start address
10623 + * end: virtual end address
10625 + * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
10626 + * loop twice, once for i-cache, once for d-cache)
10627 + */
10628 + .align 5
10629 +ENTRY(cpu_arm1020E_icache_invalidate_range)
10630 + bic r0, r0, #ICACHELINESIZE - 1
10631 + sub r3, r1, r0
10632 + cmp r3, #MAX_AREA_SIZE
10633 + movhs r2, #1
10634 + bhs cpu_arm1020E_cache_clean_invalidate_all_r2
10637 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10638 + mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
10639 +#endif
10640 +#ifdef CONFIG_CPU_ICACHE_ENABLE
10641 + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
10642 +#endif
10643 + add r0, r0, #DCACHELINESIZE
10644 + cmp r0, r1
10645 + bls 1b @ unsigned lower or same - includes r1 entry
10647 + mov r0, #0
10648 + mcr p15, 0, r0, c7, c10, 4 @ drain WB
10649 + mov pc, lr
10651 +ENTRY(cpu_arm1020E_icache_invalidate_page)
10652 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
10653 + mov r0, r0, LSL #LOG2PAGESIZE
10654 + add r1, r0, #PAGESIZE
10655 + b cpu_arm1020E_icache_invalidate_range
10657 +/* ================================== TLB ================================= */
10660 + * cpu_arm1020E_tlb_invalidate_all()
10662 + * Invalidate all TLB entries
10663 + */
10664 + .align 5
10665 +ENTRY(cpu_arm1020E_tlb_invalidate_all)
10666 + mov r0, #0
10667 + mcr p15, 0, r0, c7, c10, 4 @ drain WB
10668 + mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
10669 + mov pc, lr
10672 + * cpu_arm1020E_tlb_invalidate_range(start, end)
10674 + * invalidate TLB entries covering the specified range
10676 + * start: range start address
10677 + * end: range end address
10678 + */
10679 + .align 5
10680 +ENTRY(cpu_arm1020E_tlb_invalidate_range)
10681 + sub r3, r1, r0
10682 + cmp r3, #256 * PAGESIZE
10683 + bhs cpu_arm1020E_tlb_invalidate_all
10684 + mov r3, #0
10685 + mcr p15, 0, r3, c7, c10, 4 @ drain WB
10686 + mov r3, #PAGESIZE
10687 + sub r3, r3, #1
10688 + bic r0, r0, r3
10689 +1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
10690 + mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
10691 + add r0, r0, #PAGESIZE
10692 + cmp r0, r1
10693 + bls 1b
10694 + mov pc, lr
10697 + * cpu_arm1020E_tlb_invalidate_page(page, flags)
10699 + * invalidate the TLB entries for the specified page.
10701 + * page: page to invalidate
10702 + * flags: non-zero if we include the I TLB
10703 + */
10704 + .align 5
10705 +ENTRY(cpu_arm1020E_tlb_invalidate_page)
10706 + mov r3, #0
10707 + mcr p15, 0, r3, c7, c10, 4 @ drain WB
10708 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
10709 + mov r0, r0, LSL #LOG2PAGESIZE
10710 + teq r1, #0
10711 + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
10712 + mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
10713 + mov pc, lr
10715 +/* =============================== PageTable ============================== */
10718 + * cpu_arm1020E_set_pgd(pgd)
10720 + * Set the translation base pointer to be as described by pgd.
10722 + * pgd: new page tables
10723 + */
10724 + .align 5
10725 +ENTRY(cpu_arm1020E_set_pgd)
10726 + stmfd sp!, {lr}
10727 + bl cpu_arm1020E_cache_clean_invalidate_all @ preserves r0
10728 + mov r1, #0
10729 + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
10730 + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
10731 + ldmfd sp!, {pc}
10734 + * cpu_arm1020E_set_pmd(pmdp, pmd)
10736 + * Set a level 1 translation table entry, and clean it out of
10737 + * any caches such that the MMUs can load it correctly.
10739 + * pmdp: pointer to PMD entry
10740 + * pmd: PMD value to store
10741 + */
10742 + .align 5
10743 +ENTRY(cpu_arm1020E_set_pmd)
10744 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10745 + eor r2, r1, #0x0a @ C & Section
10746 + tst r2, #0x0b
10747 + biceq r1, r1, #4 @ clear bufferable bit
10748 +#endif
10749 + str r1, [r0]
10750 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10751 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
10752 +#endif
10753 + mov r0, #0
10754 + mcr p15, 0, r0, c7, c10, 4 @ drain WB
10755 + mov pc, lr
10758 + * cpu_arm1020E_set_pte(ptep, pte)
10760 + * Set a PTE and flush it out
10761 + */
10762 + .align 5
10763 +ENTRY(cpu_arm1020E_set_pte)
10764 + str r1, [r0], #-1024 @ linux version
10766 + eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
10768 + bic r2, r1, #0xff0
10769 + bic r2, r2, #3
10770 + orr r2, r2, #HPTE_TYPE_SMALL
10772 + tst r1, #LPTE_USER @ User?
10773 + orrne r2, r2, #HPTE_AP_READ
10775 + tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
10776 + orreq r2, r2, #HPTE_AP_WRITE
10778 + tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
10779 + movne r2, #0
10781 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10782 + eor r3, r2, #0x0a @ C and Small Page?
10783 + tst r3, #0x0b @ if so..
10784 + biceq r2, r2, #0x04 @ clear the bufferable bit
10785 +#endif
10786 + str r2, [r0] @ hardware version
10787 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10788 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
10789 +#endif
10790 + mov r1, #0
10791 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
10792 + mov pc, lr
10795 +cpu_manu_name:
10796 + .asciz "ARM"
10797 +ENTRY(cpu_arm1020E_name)
10798 + .ascii "Arm1020E"
10799 +#ifdef CONFIG_CPU_ICACHE_ENABLE
10800 + .ascii "i"
10801 +#endif
10802 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10803 + .ascii "d"
10804 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
10805 + .ascii "(wt)"
10806 +#endif
10807 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
10808 + .ascii "(wb)"
10809 +#endif
10810 +#endif
10811 +#ifndef CONFIG_CPU_BPREDICT_DISABLE
10812 + .ascii "B"
10813 +#endif
10814 +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
10815 + .ascii "RR"
10816 +#endif
10817 + .ascii "\0"
10818 + .align
10820 + .section ".text.init", #alloc, #execinstr
10822 +__arm1020E_setup:
10823 + mov r0, #0
10824 + mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
10825 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
10826 + mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
10827 + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
10828 + mov r0, #0x1f @ Domains 0, 1 = client
10829 + mcr p15, 0, r0, c3, c0, 0 @ load domain access register
10831 + mrc p15, 0, r0, c1, c0, 0 @ Read current control register
10833 + * The only thing worth keeping from the initial control register is the endian bit
10834 + */
10836 + and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
10837 + orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
10839 + * Turn on what we want.
10840 + */
10841 + orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
10842 + orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
10843 + orr r0, r0, #0x2000 @ ..V............. Enable high vectors
10845 +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
10846 + orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
10847 +#endif
10849 +#ifndef CONFIG_CPU_BPREDICT_DISABLE
10850 + orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
10851 +#endif
10853 +#ifdef CONFIG_CPU_DCACHE_ENABLE
10854 + orr r0, r0, #0x0004 @ .............C.. Enable D cache
10855 +#endif
10856 +#ifndef CONFIG_CPU_WB_DISABLE
10857 + orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
10858 +#endif
10860 +#ifdef CONFIG_CPU_ICACHE_ENABLE
10861 + orr r0, r0, #0x1000 @ ...I............ Enable I Cache
10862 +#endif
10864 + mov pc, lr
10866 + .text
10869 + * Purpose : Function pointers used to access above functions - all calls
10870 + * come through these
10871 + */
10872 + .type arm1020E_processor_functions, #object
10873 +arm1020E_processor_functions:
10874 + .word cpu_arm1020E_data_abort
10875 + .word cpu_arm1020E_check_bugs
10876 + .word cpu_arm1020E_proc_init
10877 + .word cpu_arm1020E_proc_fin
10878 + .word cpu_arm1020E_reset
10879 + .word cpu_arm1020E_do_idle
10881 + /* cache */
10882 + .word cpu_arm1020E_cache_clean_invalidate_all
10883 + .word cpu_arm1020E_cache_clean_invalidate_range
10884 + .word cpu_arm1020E_flush_ram_page
10886 + /* dcache */
10887 + .word cpu_arm1020E_dcache_invalidate_range
10888 + .word cpu_arm1020E_dcache_clean_range
10889 + .word cpu_arm1020E_dcache_clean_page
10890 + .word cpu_arm1020E_dcache_clean_entry
10892 + /* icache */
10893 + .word cpu_arm1020E_icache_invalidate_range
10894 + .word cpu_arm1020E_icache_invalidate_page
10896 + /* tlb */
10897 + .word cpu_arm1020E_tlb_invalidate_all
10898 + .word cpu_arm1020E_tlb_invalidate_range
10899 + .word cpu_arm1020E_tlb_invalidate_page
10901 + /* pgtable */
10902 + .word cpu_arm1020E_set_pgd
10903 + .word cpu_arm1020E_set_pmd
10904 + .word cpu_arm1020E_set_pte
10905 + .size arm1020E_processor_functions, . - arm1020E_processor_functions
10907 + .type cpu_arm1020E_info, #object
10908 +cpu_arm1020E_info:
10909 + .long cpu_manu_name
10910 + .long cpu_arm1020E_name
10911 + .size cpu_arm1020E_info, . - cpu_arm1020E_info
10913 + .type cpu_arch_name, #object
10914 +cpu_arch_name:
10915 + .asciz "armv5te"
10916 + .size cpu_arch_name, . - cpu_arch_name
10918 + .type cpu_elf_name, #object
10919 +cpu_elf_name:
10920 + .asciz "v5"
10921 + .size cpu_elf_name, . - cpu_elf_name
10922 + .align
10924 + .section ".proc.info", #alloc, #execinstr
10926 + .type __arm1020E_proc_info,#object
10927 +__arm1020E_proc_info:
10928 + .long 0x4105a200 @ ARM 1020E (Architecture v5TE)
10929 + .long 0xff0ffff0
10930 + .long 0x00000c1e @ mmuflags
10931 + b __arm1020E_setup
10932 + .long cpu_arch_name
10933 + .long cpu_elf_name
10934 + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
10935 + .long cpu_arm1020E_info
10936 + .long arm1020E_processor_functions
10937 + .size __arm1020E_proc_info, . - __arm1020E_proc_info
10939 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
10940 +++ linux-2.4.25/arch/arm/mm/proc-arm1022.S 2004-03-31 17:15:09.000000000 +0200
10941 @@ -0,0 +1,716 @@
10943 + * linux/arch/arm/mm/proc-arm1022.S: MMU functions for ARM1022E
10945 + * Copyright (C) 2000 ARM Limited
10946 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
10948 + * This program is free software; you can redistribute it and/or modify
10949 + * it under the terms of the GNU General Public License as published by
10950 + * the Free Software Foundation; either version 2 of the License, or
10951 + * (at your option) any later version.
10953 + * This program is distributed in the hope that it will be useful,
10954 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10955 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10956 + * GNU General Public License for more details.
10958 + * You should have received a copy of the GNU General Public License
10959 + * along with this program; if not, write to the Free Software
10960 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10963 + * These are the low level assembler for performing cache and TLB
10964 + * functions on the arm1022E.
10965 + */
10966 +#include <linux/linkage.h>
10967 +#include <linux/config.h>
10968 +#include <asm/assembler.h>
10969 +#include <asm/constants.h>
10970 +#include <asm/procinfo.h>
10971 +#include <asm/hardware.h>
10974 + * This is the maximum size of an area which will be invalidated
10975 + * using the single invalidate entry instructions. Anything larger
10976 + * than this, and we go for the whole cache.
10978 + * This value should be chosen such that we choose the cheapest
10979 + * alternative.
10980 + */
10981 +#define MAX_AREA_SIZE 16384
10984 + * the cache line size of the I and D cache
10985 + */
10986 +#define DCACHELINESIZE 32
10987 +#define ICACHELINESIZE 32
10990 + * and the page size
10991 + */
10992 +#define LOG2PAGESIZE 12 /* == 4096 Bytes */
10993 +#define PAGESIZE (1 << LOG2PAGESIZE)
10996 + * create some useful conditional macro definitions
10997 + * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
10998 + */
10999 +#ifdef CONFIG_CPU_DCACHE_DISABLE
11000 + #undef CONFIG_CPU_DCACHE_WRITETHROUGH
11001 + #undef CONFIG_CPU_DCACHE_WRITEBACK
11002 + #undef CONFIG_CPU_DCACHE_ENABLE
11003 +#else
11004 + #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11005 + #undef CONFIG_CPU_DCACHE_WRITEBACK
11006 + #else
11007 + #define CONFIG_CPU_DCACHE_WRITEBACK
11008 + #endif
11009 + #define CONFIG_CPU_DCACHE_ENABLE
11010 +#endif
11012 +#ifdef CONFIG_CPU_ICACHE_DISABLE
11013 + #undef CONFIG_CPU_ICACHE_ENABLE
11014 +#else
11015 + #define CONFIG_CPU_ICACHE_ENABLE
11016 +#endif
11018 + .text
11021 + * cpu_arm1022_data_abort()
11023 + * obtain information about current aborted instruction
11024 + * Note: we read user space. This means we might cause a data
11025 + * abort here if the I-TLB and D-TLB aren't seeing the same
11026 + * picture. Unfortunately, this does happen. We live with it.
11028 + * r2 = address of aborted instruction
11029 + * r3 = cpsr
11031 + * Returns:
11032 + * r0 = address of abort
11033 + * r1 = FSR
11034 + * r3 = corrupted
11035 + * r4 = corrupted
11036 + */
11037 + .align 5
11038 +ENTRY(cpu_arm1022_data_abort)
11039 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
11040 + mrc p15, 0, r0, c6, c0, 0 @ get FAR
11041 + tst r3, #PSR_T_BIT
11042 + ldrneh r3, [r2] @ read aborted thumb instruction
11043 + ldreq r3, [r2] @ read aborted ARM instruction
11044 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
11045 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
11046 + tst r3, #1 << 20 @ check write
11047 + orreq r1, r1, #1 << 11
11048 + mov pc, lr
11051 + * cpu_arm1022_check_bugs()
11052 + */
11053 +ENTRY(cpu_arm1022_check_bugs)
11054 + mrs ip, cpsr
11055 + bic ip, ip, #F_BIT
11056 + msr cpsr, ip
11057 + mov pc, lr
11060 + * cpu_arm1022_proc_init()
11061 + */
11062 +ENTRY(cpu_arm1022_proc_init)
11063 + mov pc, lr
11066 + * cpu_arm1022_proc_fin()
11067 + */
11068 +ENTRY(cpu_arm1022_proc_fin)
11069 + stmfd sp!, {lr}
11070 + mov ip, #F_BIT | I_BIT | SVC_MODE
11071 + msr cpsr_c, ip
11072 + bl cpu_arm1022_cache_clean_invalidate_all
11073 + mrc p15, 0, r0, c1, c0, 0 @ ctrl register
11074 + bic r0, r0, #0x1000 @ ...i............
11075 + bic r0, r0, #0x000e @ ............wca.
11076 + mcr p15, 0, r0, c1, c0, 0 @ disable caches
11077 + ldmfd sp!, {pc}
11080 + * cpu_arm1022_reset(loc)
11082 + * Perform a soft reset of the system. Put the CPU into the
11083 + * same state as it would be if it had been reset, and branch
11084 + * to what would be the reset vector.
11086 + * loc: location to jump to for soft reset
11087 + */
11088 + .align 5
11089 +ENTRY(cpu_arm1022_reset)
11090 + mov ip, #0
11091 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
11092 + mcr p15, 0, ip, c7, c10, 4 @ drain WB
11093 + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
11094 + mrc p15, 0, ip, c1, c0, 0 @ ctrl register
11095 + bic ip, ip, #0x000f @ ............wcam
11096 + bic ip, ip, #0x1100 @ ...i...s........
11097 + mcr p15, 0, ip, c1, c0, 0 @ ctrl register
11098 + mov pc, r0
11101 + * cpu_arm1022_do_idle()
11102 + */
11103 + .align 5
11104 +ENTRY(cpu_arm1022_do_idle)
11105 + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
11106 + mov pc, lr
11108 +/* ================================= CACHE ================================ */
11112 + * cpu_arm1022_cache_clean_invalidate_all()
11114 + * clean and invalidate all cache lines
11116 + * Note:
11117 + * 1. we should preserve r0 and ip at all times
11118 + */
11119 + .align 5
11120 +ENTRY(cpu_arm1022_cache_clean_invalidate_all)
11121 + mov r2, #1
11122 +cpu_arm1022_cache_clean_invalidate_all_r2:
11124 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11125 + mov r1, #7 << 5 @ 8 segments
11126 +1: orr r3, r1, #63 << 26 @ 64 entries
11127 +2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
11128 + subs r3, r3, #1 << 26
11129 + bcs 2b
11130 + subs r1, r1, #1 << 5
11131 + bcs 1b @ segments 7 to 0
11132 +#endif
11134 + mov r1, #0
11136 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11137 + mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
11138 +#endif
11140 +#ifdef CONFIG_CPU_ICACHE_ENABLE
11141 + teq r2, #0
11142 + mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
11143 +#endif
11144 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
11145 + mov pc, lr
11148 + * cpu_arm1022_cache_clean_invalidate_range(start, end, flags)
11150 + * clean and invalidate all cache lines associated with this area of memory
11152 + * start: Area start address
11153 + * end: Area end address
11154 + * flags: nonzero for I cache as well
11155 + */
11156 + .align 5
11157 +ENTRY(cpu_arm1022_cache_clean_invalidate_range)
11158 + bic r0, r0, #DCACHELINESIZE - 1
11159 + sub r3, r1, r0
11160 + cmp r3, #MAX_AREA_SIZE
11161 + bhs cpu_arm1022_cache_clean_invalidate_all_r2
11163 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11164 + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
11165 +#endif
11166 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11167 + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
11168 +#endif
11169 +#ifdef CONFIG_CPU_ICACHE_ENABLE
11170 + teq r2, #0
11171 + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
11172 +#endif
11173 + add r0, r0, #DCACHELINESIZE
11174 + cmp r0, r1
11175 + bls 1b @ unsigned lower or same - must include end point (r1)!
11177 + mov r1, #0
11178 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
11179 + mov pc, lr
11182 + * cpu_arm1022_flush_ram_page(page)
11184 + * clean and invalidate all cache lines associated with this area of memory
11186 + * page: page to clean and invalidate
11187 + */
11188 + .align 5
11189 +ENTRY(cpu_arm1022_flush_ram_page)
11190 + mov r1, #PAGESIZE
11191 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
11192 + mov r0, r0, LSL #LOG2PAGESIZE
11194 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11195 + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
11196 +#endif
11197 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11198 + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
11199 +#endif
11200 +#ifdef CONFIG_CPU_ICACHE_ENABLE
11201 + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
11202 +#endif
11203 + add r0, r0, #DCACHELINESIZE
11204 + subs r1, r1, #DCACHELINESIZE
11205 + bne 1b
11207 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
11208 + mov pc, lr
11210 +/* ================================ D-CACHE =============================== */
11213 + * cpu_arm1022_dcache_invalidate_range(start, end)
11215 + * throw away all D-cached data in specified region without an obligation
11216 + * to write them back. Note however that we must clean the D-cached entries
11217 + * around the boundaries if the start and/or end address are not cache
11218 + * aligned.
11220 + * start: virtual start address
11221 + * end: virtual end address
11222 + */
11223 + .align 5
11224 +ENTRY(cpu_arm1022_dcache_invalidate_range)
11225 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11226 + bic r0, r0, #DCACHELINESIZE - 1
11227 +#endif
11228 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11229 + tst r0, #DCACHELINESIZE - 1
11230 + bic r0, r0, #DCACHELINESIZE - 1
11231 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
11232 + tst r1, #DCACHELINESIZE - 1
11233 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
11234 +#endif
11237 +#ifdef CONFIG_CPU_DCACHE_ENABLE
11238 + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
11239 +#endif
11240 +#ifdef CONFIG_CPU_ICACHE_ENABLE
11241 + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
11242 +#endif
11243 + add r0, r0, #DCACHELINESIZE
11244 + cmp r0, r1
11245 + bls 1b
11247 + /* Even if the D cache is off still drain the write buffer */
11248 + mov r0, #0
11249 + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
11250 + mov pc, lr
11253 + * cpu_arm1022_dcache_clean_range(start, end)
11255 + * For the specified virtual address range, ensure that all caches contain
11256 + * clean data, such that peripheral accesses to the physical RAM fetch
11257 + * correct data.
11259 + * start: virtual start address
11260 + * end: virtual end address
11261 + */
11262 + .align 5
11263 +ENTRY(cpu_arm1022_dcache_clean_range)
11265 + mov r2, #0
11267 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11268 + bic r0, r0, #DCACHELINESIZE - 1
11269 + sub r3, r1, r0
11270 + cmp r3, #MAX_AREA_SIZE
11271 + bhs cpu_arm1022_cache_clean_invalidate_all_r2
11273 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11274 + add r0, r0, #DCACHELINESIZE
11275 + cmp r0, r1
11276 + bls 1b
11277 +#endif
11279 + mcr p15, 0, r2, c7, c10, 4 @ drain WB
11280 + mov pc, lr
11283 + * cpu_arm1022_dcache_clean_page(page)
11285 + * Cleans a single page of dcache so that if we have any future aliased
11286 + * mappings, they will be consistent at the time that they are created.
11288 + * page: virtual address of page to clean from dcache
11290 + * Note:
11291 + * we don't invalidate the entries since when we write the page
11292 + * out to disk, the entries may get reloaded into the cache.
11293 + */
11294 + .align 5
11295 +ENTRY(cpu_arm1022_dcache_clean_page)
11296 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11297 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
11298 + mov r0, r0, LSL #LOG2PAGESIZE
11299 + mov r1, #PAGESIZE
11301 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11302 + add r0, r0, #DCACHELINESIZE
11303 + subs r1, r1, #DCACHELINESIZE
11304 + bne 1b
11305 +#endif
11306 + mov r1, #0
11307 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
11308 + mov pc, lr
11311 + * cpu_arm1022_dcache_clean_entry(addr)
11313 + * Clean the specified entry of any caches such that the MMU
11314 + * translation fetches will obtain correct data.
11316 + * addr: cache-unaligned virtual address
11317 + */
11318 + .align 5
11319 +ENTRY(cpu_arm1022_dcache_clean_entry)
11320 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11321 + bic r0, r0, #DCACHELINESIZE - 1
11322 + mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
11323 +#endif
11324 + mov r1, #0
11325 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
11326 + mov pc, lr
11328 +/* ================================ I-CACHE =============================== */
11331 + * cpu_arm1022_icache_invalidate_range(start, end)
11333 + * invalidate a range of virtual addresses from the Icache
11335 + * This is a little misleading, it is not intended to clean out
11336 + * the i-cache but to make sure that any data written to the
11337 + * range is made consistent. This means that when we execute code
11338 + * in that region, everything works as we expect.
11340 + * This generally means writing back data in the Dcache and
11341 + * write buffer and invalidating the Icache over that region
11343 + * start: virtual start address
11344 + * end: virtual end address
11346 + * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
11347 + * loop twice, once for i-cache, once for d-cache)
11348 + */
11349 + .align 5
11350 +ENTRY(cpu_arm1022_icache_invalidate_range)
11351 + bic r0, r0, #ICACHELINESIZE - 1
11352 + sub r3, r1, r0
11353 + cmp r3, #MAX_AREA_SIZE
11354 + movhs r2, #1
11355 + bhs cpu_arm1022_cache_clean_invalidate_all_r2
11357 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11358 + mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
11359 +#endif
11360 +#ifdef CONFIG_CPU_ICACHE_ENABLE
11361 + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
11362 +#endif
11363 + add r0, r0, #DCACHELINESIZE
11364 + cmp r0, r1
11365 + bls 1b @ unsigned lower or same - includes r1 entry
11367 + mov r0, #0
11368 + mcr p15, 0, r0, c7, c10, 4 @ drain WB
11369 + mov pc, lr
11371 +ENTRY(cpu_arm1022_icache_invalidate_page)
11372 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
11373 + mov r0, r0, LSL #LOG2PAGESIZE
11374 + add r1, r0, #PAGESIZE
11375 + b cpu_arm1022_icache_invalidate_range
11377 +/* ================================== TLB ================================= */
11380 + * cpu_arm1022_tlb_invalidate_all()
11382 + * Invalidate all TLB entries
11383 + */
11384 + .align 5
11385 +ENTRY(cpu_arm1022_tlb_invalidate_all)
11386 + mov r0, #0
11387 + mcr p15, 0, r0, c7, c10, 4 @ drain WB
11388 + mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
11389 + mov pc, lr
11392 + * cpu_arm1022_tlb_invalidate_range(start, end)
11394 + * invalidate TLB entries covering the specified range
11396 + * start: range start address
11397 + * end: range end address
11398 + */
11399 + .align 5
11400 +ENTRY(cpu_arm1022_tlb_invalidate_range)
11401 + sub r3, r1, r0
11402 + cmp r3, #256 * PAGESIZE
11403 + bhs cpu_arm1022_tlb_invalidate_all
11404 + mov r3, #0
11405 + mcr p15, 0, r3, c7, c10, 4 @ drain WB
11406 + mov r3, #PAGESIZE
11407 + sub r3, r3, #1
11408 + bic r0, r0, r3
11409 +1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
11410 + mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
11411 + add r0, r0, #PAGESIZE
11412 + cmp r0, r1
11413 + bls 1b
11414 + mov pc, lr
11417 + * cpu_arm1022_tlb_invalidate_page(page, flags)
11419 + * invalidate the TLB entries for the specified page.
11421 + * page: page to invalidate
11422 + * flags: non-zero if we include the I TLB
11423 + */
11424 + .align 5
11425 +ENTRY(cpu_arm1022_tlb_invalidate_page)
11426 + mov r3, #0
11427 + mcr p15, 0, r3, c7, c10, 4 @ drain WB
11428 + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
11429 + mov r0, r0, LSL #LOG2PAGESIZE
11430 + teq r1, #0
11431 + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
11432 + mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
11433 + mov pc, lr
11435 +/* =============================== PageTable ============================== */
11438 + * cpu_arm1022_set_pgd(pgd)
11440 + * Set the translation base pointer to be as described by pgd.
11442 + * pgd: new page tables
11443 + */
11444 + .align 5
11445 +ENTRY(cpu_arm1022_set_pgd)
11446 + stmfd sp!, {lr}
11447 + bl cpu_arm1022_cache_clean_invalidate_all @ preserves r0
11448 + mov r1, #0
11449 + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
11450 + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
11451 + ldmfd sp!, {pc}
11454 + * cpu_arm1022_set_pmd(pmdp, pmd)
11456 + * Set a level 1 translation table entry, and clean it out of
11457 + * any caches such that the MMUs can load it correctly.
11459 + * pmdp: pointer to PMD entry
11460 + * pmd: PMD value to store
11461 + */
11462 + .align 5
11463 +ENTRY(cpu_arm1022_set_pmd)
11464 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11465 + eor r2, r1, #0x0a @ C & Section
11466 + tst r2, #0x0b
11467 + biceq r1, r1, #4 @ clear bufferable bit
11468 +#endif
11469 + str r1, [r0]
11470 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11471 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11472 +#endif
11473 + mov r0, #0
11474 + mcr p15, 0, r0, c7, c10, 4 @ drain WB
11475 + mov pc, lr
11478 + * cpu_arm1022_set_pte(ptep, pte)
11480 + * Set a PTE and flush it out
11481 + */
11482 + .align 5
11483 +ENTRY(cpu_arm1022_set_pte)
11484 + str r1, [r0], #-1024 @ linux version
11486 + eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
11488 + bic r2, r1, #0xff0
11489 + bic r2, r2, #3
11490 + orr r2, r2, #HPTE_TYPE_SMALL
11492 + tst r1, #LPTE_USER @ User?
11493 + orrne r2, r2, #HPTE_AP_READ
11495 + tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
11496 + orreq r2, r2, #HPTE_AP_WRITE
11498 + tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
11499 + movne r2, #0
11501 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11502 + eor r3, r2, #0x0a @ C and Small Page?
11503 + tst r3, #0x0b @ if so..
11504 + biceq r2, r2, #0x04 @ clear the bufferable bit
11505 +#endif
11506 + str r2, [r0] @ hardware version
11507 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11508 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11509 +#endif
11510 + mov r1, #0
11511 + mcr p15, 0, r1, c7, c10, 4 @ drain WB
11512 + mov pc, lr
11515 +cpu_manu_name:
11516 + .asciz "ARM"
11517 +ENTRY(cpu_arm1022_name)
11518 + .ascii "Arm1022E"
11519 +#ifdef CONFIG_CPU_ICACHE_ENABLE
11520 + .ascii "i"
11521 +#endif
11522 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11523 + .ascii "d"
11524 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11525 + .ascii "(wt)"
11526 +#endif
11527 +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
11528 + .ascii "(wb)"
11529 +#endif
11530 +#endif
11531 +#ifndef CONFIG_CPU_BPREDICT_DISABLE
11532 + .ascii "B"
11533 +#endif
11534 +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
11535 + .ascii "RR"
11536 +#endif
11537 + .ascii "\0"
11538 + .align
11540 + .section ".text.init", #alloc, #execinstr
11542 +__arm1022_setup:
11543 + mov r0, #0
11544 + mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
11545 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
11546 + mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
11547 + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
11548 + mov r0, #0x1f @ Domains 0, 1 = client
11549 + mcr p15, 0, r0, c3, c0, 0 @ load domain access register
11551 + mrc p15, 0, r0, c1, c0, 0 @ Read current control register
11553 + * The only thing worth keeping from the initial control register is the endian bit
11554 + */
11556 + and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
11557 + orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
11559 + * Turn on what we want.
11560 + */
11561 + orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
11562 + orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
11563 + orr r0, r0, #0x2000 @ ..V............. Enable high vectors
11565 +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
11566 + orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
11567 +#endif
11569 +#ifndef CONFIG_CPU_BPREDICT_DISABLE
11570 + orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
11571 +#endif
11573 +#ifdef CONFIG_CPU_DCACHE_ENABLE
11574 + orr r0, r0, #0x0004 @ .............C.. Enable D cache
11575 +#endif
11576 +#ifndef CONFIG_CPU_WB_DISABLE
11577 + orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
11578 +#endif
11580 +#ifdef CONFIG_CPU_ICACHE_ENABLE
11581 + orr r0, r0, #0x1000 @ ...I............ Enable I Cache
11582 +#endif
11584 + mov pc, lr
11586 + .text
11589 + * Purpose : Function pointers used to access above functions - all calls
11590 + * come through these
11591 + */
11592 + .type arm1022_processor_functions, #object
11593 +arm1022_processor_functions:
11594 + .word cpu_arm1022_data_abort
11595 + .word cpu_arm1022_check_bugs
11596 + .word cpu_arm1022_proc_init
11597 + .word cpu_arm1022_proc_fin
11598 + .word cpu_arm1022_reset
11599 + .word cpu_arm1022_do_idle
11601 + /* cache */
11602 + .word cpu_arm1022_cache_clean_invalidate_all
11603 + .word cpu_arm1022_cache_clean_invalidate_range
11604 + .word cpu_arm1022_flush_ram_page
11606 + /* dcache */
11607 + .word cpu_arm1022_dcache_invalidate_range
11608 + .word cpu_arm1022_dcache_clean_range
11609 + .word cpu_arm1022_dcache_clean_page
11610 + .word cpu_arm1022_dcache_clean_entry
11612 + /* icache */
11613 + .word cpu_arm1022_icache_invalidate_range
11614 + .word cpu_arm1022_icache_invalidate_page
11616 + /* tlb */
11617 + .word cpu_arm1022_tlb_invalidate_all
11618 + .word cpu_arm1022_tlb_invalidate_range
11619 + .word cpu_arm1022_tlb_invalidate_page
11621 + /* pgtable */
11622 + .word cpu_arm1022_set_pgd
11623 + .word cpu_arm1022_set_pmd
11624 + .word cpu_arm1022_set_pte
11625 + .size arm1022_processor_functions, . - arm1022_processor_functions
11627 + .type cpu_arm1022_info, #object
11628 +cpu_arm1022_info:
11629 + .long cpu_manu_name
11630 + .long cpu_arm1022_name
11631 + .size cpu_arm1022_info, . - cpu_arm1022_info
11633 + .type cpu_arch_name, #object
11634 +cpu_arch_name:
11635 + .asciz "armv5t"
11636 + .size cpu_arch_name, . - cpu_arch_name
11638 + .type cpu_elf_name, #object
11639 +cpu_elf_name:
11640 + .asciz "v5"
11641 + .size cpu_elf_name, . - cpu_elf_name
11642 + .align
11644 + .section ".proc.info", #alloc, #execinstr
11646 + .type __arm1022_proc_info,#object
11647 +__arm1022_proc_info:
11648 + .long 0x4100a220 @ ARM 1022
11649 + .long 0xff00fff0
11650 + .long 0x00000c1e @ mmuflags
11651 + b __arm1022_setup
11652 + .long cpu_arch_name
11653 + .long cpu_elf_name
11654 + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
11655 + .long cpu_arm1022_info
11656 + .long arm1022_processor_functions
11657 + .size __arm1022_proc_info, . - __arm1022_proc_info
11658 --- linux-2.4.25/arch/arm/mm/proc-arm1026.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
11659 +++ linux-2.4.25/arch/arm/mm/proc-arm1026.S 2004-03-31 17:15:09.000000000 +0200
11660 @@ -66,19 +66,24 @@
11662 * Returns:
11663 * r0 = address of abort
11664 - * r1 != 0 if writing
11665 - * r3 = FSR
11666 + * r1 = FSR, bit 11 set if writing
11667 + * r3 = corrupted
11668 * r4 = corrupted
11670 .align 5
11671 ENTRY(cpu_arm1026_data_abort)
11672 - mrc p15, 0, r3, c5, c0, 0 @ get FSR
11673 - and r2, r3, #0b1101 @ Check for translation error
11674 - sub r1, r2, #0b0101
11676 - and r3, r3, #255
11677 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
11678 mrc p15, 0, r0, c6, c0, 0 @ get FAR
11680 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
11681 + tst r3, #PSR_J_BIT @ Java?
11682 + orrne r1, r1, #1 << 11 @ always assume write
11683 + movne pc, lr
11684 + tst r3, #PSR_T_BIT
11685 + ldrneh r3, [r2] @ read aborted thumb instruction
11686 + ldreq r3, [r2] @ read aborted ARM instruction
11687 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
11688 + tst r3, #1 << 20 @ check write
11689 + orreq r1, r1, #1 << 11
11690 mov pc, lr
11693 @@ -254,7 +259,7 @@
11695 .align 5
11696 ENTRY(cpu_arm1026_dcache_invalidate_range)
11697 -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
11698 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
11699 tst r0, #DCACHELINESIZE - 1
11700 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
11701 tst r1, #DCACHELINESIZE - 1
11702 @@ -279,7 +284,7 @@
11704 .align 5
11705 ENTRY(cpu_arm1026_dcache_clean_range)
11706 -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
11707 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
11708 bic r0, r0, #DCACHELINESIZE - 1
11709 sub r3, r1, r0
11710 cmp r3, #MAX_AREA_SIZE
11711 @@ -309,7 +314,7 @@
11713 .align 5
11714 ENTRY(cpu_arm1026_dcache_clean_page)
11715 -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
11716 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
11717 mov r1, #PAGESIZE
11718 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11719 add r0, r0, #DCACHELINESIZE
11720 @@ -330,7 +335,7 @@
11722 .align 5
11723 ENTRY(cpu_arm1026_dcache_clean_entry)
11724 -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
11725 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
11726 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11727 #endif
11728 mcr p15, 0, r0, c7, c10, 4 @ drain WB
11729 @@ -473,7 +478,7 @@
11730 biceq r1, r1, #4 @ clear bufferable bit
11731 #endif
11732 str r1, [r0]
11733 -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
11734 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
11735 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11736 #endif
11737 mcr p15, 0, r0, c7, c10, 4 @ drain WB
11738 @@ -494,7 +499,7 @@
11739 bic r2, r2, #3
11740 orr r2, r2, #HPTE_TYPE_SMALL
11742 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
11743 + tst r1, #LPTE_USER @ User?
11744 orrne r2, r2, #HPTE_AP_READ
11746 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
11747 @@ -634,12 +639,12 @@
11749 .type cpu_arch_name, #object
11750 cpu_arch_name:
11751 - .asciz "armv5EJ"
11752 + .asciz "armv5tej"
11753 .size cpu_arch_name, . - cpu_arch_name
11755 .type cpu_elf_name, #object
11756 cpu_elf_name:
11757 - .asciz "v5EJ"
11758 + .asciz "v5"
11759 .size cpu_elf_name, . - cpu_elf_name
11760 .align
11762 --- linux-2.4.25/arch/arm/mm/proc-arm6,7.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
11763 +++ linux-2.4.25/arch/arm/mm/proc-arm6,7.S 2004-03-31 17:15:09.000000000 +0200
11764 @@ -72,7 +72,7 @@
11765 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
11766 add r0, r0, #4096
11767 cmp r0, r1
11768 - blt 1b
11769 + blo 1b
11770 mov pc, lr
11772 ENTRY(cpu_arm7_tlb_invalidate_range)
11773 @@ -85,7 +85,7 @@
11774 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
11775 add r0, r0, #0x4000
11776 cmp r0, r1
11777 - blt 1b
11778 + blo 1b
11779 mov pc, lr
11780 #endif
11782 @@ -110,15 +110,13 @@
11783 * Purpose : obtain information about current aborted instruction
11785 * Returns : r0 = address of abort
11786 - * : r1 != 0 if writing
11787 - * : r3 = FSR
11788 + * : r1 = FSR, bit 11 set if writing
11789 + * : r3 = corrupted
11790 * : sp = pointer to registers
11793 ENTRY(cpu_arm6_data_abort)
11794 ldr r4, [r0] @ read instruction causing problem
11795 - tst r4, r4, lsr #21 @ C = bit 20
11796 - sbc r1, r1, r1 @ r1 = C - 1
11797 and r2, r4, #14 << 24
11798 teq r2, #8 << 24 @ was it ldm/stm
11799 bne Ldata_simple
11800 @@ -144,14 +142,14 @@
11801 addeq r7, r0, r7, lsl #2 @ Do correction (signed)
11802 Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
11803 Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
11804 - mrc p15, 0, r3, c5, c0, 0 @ get FSR
11805 - and r3, r3, #255
11806 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
11807 + bic r1, r1, #1 << 11 | 1 << 10
11808 + tst r4, #1 << 20
11809 + orreq r1, r1, #1 << 11
11810 mov pc, lr
11812 ENTRY(cpu_arm7_data_abort)
11813 ldr r4, [r0] @ read instruction causing problem
11814 - tst r4, r4, lsr #21 @ C = bit 20
11815 - sbc r1, r1, r1 @ r1 = C - 1
11816 and r2, r4, #15 << 24
11817 add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
11818 movs pc, lr
11819 @@ -336,7 +334,7 @@
11820 bic r2, r2, #3
11821 orr r2, r2, #HPTE_TYPE_SMALL
11823 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
11824 + tst r1, #LPTE_USER @ User?
11825 orrne r2, r2, #HPTE_AP_READ
11827 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
11828 --- linux-2.4.25/arch/arm/mm/proc-arm720.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
11829 +++ linux-2.4.25/arch/arm/mm/proc-arm720.S 2004-03-31 17:15:09.000000000 +0200
11830 @@ -97,7 +97,7 @@
11831 1: mcr p15, 0, r0, c8, c7, 1 @ flush TLB (v4)
11832 add r0, r0, #PAGESIZE
11833 cmp r0, r1
11834 - blt 1b
11835 + blo 1b
11836 mov pc, lr
11839 @@ -124,8 +124,8 @@
11840 * picture. Unfortunately, this does happen. We live with it.
11842 * Returns : r0 = address of abort
11843 - * : r1 != 0 if writing
11844 - * : r3 = FSR
11845 + * : r1 = FSR, bit 11 set if writing
11846 + * : r3 = corrupted
11847 * : sp = pointer to registers
11850 @@ -150,16 +150,16 @@
11851 addeq r7, r0, r7, lsl #2 @ Do correction (signed)
11852 Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
11853 Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
11854 - mrc p15, 0, r3, c5, c0, 0 @ get FSR
11855 - and r3, r3, #255
11856 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
11857 + bic r1, r1, #1 << 11 | 1 << 10
11858 + tst r4, #1 << 20
11859 + orreq r1, r1, #1 << 11
11860 mov pc, lr
11862 ENTRY(cpu_arm720_data_abort)
11863 - tst r3, #T_BIT
11864 + tst r3, #PSR_T_BIT
11865 bne .data_thumb_abort
11866 - ldr r4, [r0] @ read instruction causing problem
11867 - tst r4, r4, lsr #21 @ C = bit 20
11868 - sbc r1, r1, r1 @ r1 = C - 1
11869 + ldr r4, [r2] @ read instruction causing problem
11870 and r2, r4, #15 << 24
11871 add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
11872 movs pc, lr
11873 @@ -270,9 +270,9 @@
11874 b Ldata_saver7
11876 .data_thumb_abort:
11877 - ldrh r4, [r0] @ read instruction
11878 - tst r4, r4, lsr #12 @ C = bit 11
11879 - sbc r1, r1, r1 @ r1 = C - 1
11880 + ldrh r4, [r2] @ read instruction
11881 + tst r4, #1 << 11
11882 + orrne r4, r4, #1 << 20
11883 and r2, r4, #15 << 12
11884 add pc, pc, r2, lsr #10 @ lookup in table
11886 @@ -318,8 +318,8 @@
11887 and r0, r0, #15 @ number of regs to transfer
11888 ldr r7, [sp, #13 << 2]
11889 tst r4, #1 << 11
11890 - addne r7, r7, r0, lsl #2 @ increment SP if PUSH
11891 - subeq r7, r7, r0, lsr #2 @ decrement SP if POP
11892 + addeq r7, r7, r0, lsl #2 @ increment SP if PUSH
11893 + subne r7, r7, r0, lsl #2 @ decrement SP if POP
11894 str r7, [sp, #13 << 2]
11895 b Ldata_simple
11897 @@ -336,7 +336,7 @@
11898 and r0, r0, #15 @ number of regs to transfer
11899 and r5, r4, #7 << 8
11900 ldr r7, [sp, r5, lsr #6]
11901 - sub r7, r7, r0, lsr #2 @ always decrement
11902 + sub r7, r7, r0, lsl #2 @ always decrement
11903 str r7, [sp, r5, lsr #6]
11904 b Ldata_simple
11906 @@ -418,7 +418,7 @@
11907 bic r2, r2, #3
11908 orr r2, r2, #HPTE_TYPE_SMALL
11910 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
11911 + tst r1, #LPTE_USER @ User?
11912 orrne r2, r2, #HPTE_AP_READ
11914 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
11915 --- linux-2.4.25/arch/arm/mm/proc-arm920.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
11916 +++ linux-2.4.25/arch/arm/mm/proc-arm920.S 2004-03-31 17:15:09.000000000 +0200
11917 @@ -71,12 +71,16 @@
11919 .align 5
11920 ENTRY(cpu_arm920_data_abort)
11921 - mrc p15, 0, r3, c5, c0, 0 @ get FSR
11922 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
11923 mrc p15, 0, r0, c6, c0, 0 @ get FAR
11924 - ldr r1, [r2] @ read aborted instruction
11925 - and r3, r3, #255
11926 - tst r1, r1, lsr #21 @ C = bit 20
11927 - sbc r1, r1, r1 @ r1 = C - 1
11929 + tst r3, #PSR_T_BIT
11930 + ldrneh r3, [r2] @ read aborted thumb instruction
11931 + ldreq r3, [r2] @ read aborted ARM instruction
11932 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
11933 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
11934 + tst r3, #1 << 20 @ check write
11935 + orreq r1, r1, #1 << 11
11936 mov pc, lr
11939 @@ -186,10 +190,9 @@
11940 .align 5
11941 ENTRY(cpu_arm920_cache_clean_invalidate_range)
11942 bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM
11943 - bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
11944 sub r3, r1, r0
11945 cmp r3, #MAX_AREA_SIZE
11946 - bgt cpu_arm920_cache_clean_invalidate_all_r2
11947 + bhi cpu_arm920_cache_clean_invalidate_all_r2
11948 1: teq r2, #0
11949 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
11950 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
11951 @@ -207,7 +210,7 @@
11952 add r0, r0, #DCACHELINESIZE
11953 #endif
11954 cmp r0, r1
11955 - blt 1b
11956 + blo 1b
11958 mcr p15, 0, r1, c7, c10, 4 @ drain WB
11959 mov pc, lr
11960 @@ -253,18 +256,17 @@
11962 .align 5
11963 ENTRY(cpu_arm920_dcache_invalidate_range)
11964 -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
11965 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
11966 tst r0, #DCACHELINESIZE - 1
11967 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
11968 tst r1, #DCACHELINESIZE - 1
11969 mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
11970 #endif @ clean D entry
11971 bic r0, r0, #DCACHELINESIZE - 1
11972 - bic r1, r1, #DCACHELINESIZE - 1
11973 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
11974 add r0, r0, #DCACHELINESIZE
11975 cmp r0, r1
11976 - blt 1b
11977 + blo 1b
11978 mov pc, lr
11981 @@ -279,20 +281,17 @@
11983 .align 5
11984 ENTRY(cpu_arm920_dcache_clean_range)
11985 -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
11986 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
11987 bic r0, r0, #DCACHELINESIZE - 1
11988 sub r1, r1, r0
11989 cmp r1, #MAX_AREA_SIZE
11990 mov r2, #0
11991 - bgt cpu_arm920_cache_clean_invalidate_all_r2
11993 - bic r1, r1, #DCACHELINESIZE -1
11994 - add r1, r1, #DCACHELINESIZE
11995 + bhi cpu_arm920_cache_clean_invalidate_all_r2
11997 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
11998 add r0, r0, #DCACHELINESIZE
11999 subs r1, r1, #DCACHELINESIZE
12000 - bpl 1b
12001 + bcs 1b
12002 #endif
12003 mcr p15, 0, r2, c7, c10, 4 @ drain WB
12004 mov pc, lr
12005 @@ -312,7 +311,7 @@
12007 .align 5
12008 ENTRY(cpu_arm920_dcache_clean_page)
12009 -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
12010 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12011 mov r1, #PAGESIZE
12012 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
12013 add r0, r0, #DCACHELINESIZE
12014 @@ -333,7 +332,7 @@
12016 .align 5
12017 ENTRY(cpu_arm920_dcache_clean_entry)
12018 -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
12019 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12020 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
12021 #endif
12022 mcr p15, 0, r0, c7, c10, 4 @ drain WB
12023 @@ -365,16 +364,13 @@
12024 bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
12025 sub r1, r1, r0
12026 cmp r1, #MAX_AREA_SIZE
12027 - bgt cpu_arm920_cache_clean_invalidate_all_r2
12029 - bic r1, r1, #ICACHELINESIZE - 1
12030 - add r1, r1, #ICACHELINESIZE
12031 + bhi cpu_arm920_cache_clean_invalidate_all_r2
12033 1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry
12034 mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
12035 add r0, r0, #ICACHELINESIZE
12036 subs r1, r1, #ICACHELINESIZE
12037 - bne 1b
12038 + bcs 1b
12040 mov r0, #0
12041 mcr p15, 0, r0, c7, c10, 4 @ drain WB
12042 @@ -418,13 +414,12 @@
12043 mov r3, #PAGESIZE
12044 sub r3, r3, #1
12045 bic r0, r0, r3
12046 - bic r1, r1, r3
12048 1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
12049 mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
12050 add r0, r0, #PAGESIZE
12051 cmp r0, r1
12052 - blt 1b
12053 + blo 1b
12054 mov pc, lr
12057 @@ -457,7 +452,6 @@
12058 ENTRY(cpu_arm920_set_pgd)
12059 mov ip, #0
12060 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
12061 - /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
12062 mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
12063 #else
12064 @ && 'Clean & Invalidate whole DCache'
12065 @@ -514,7 +508,7 @@
12066 bic r2, r2, #3
12067 orr r2, r2, #HPTE_TYPE_SMALL
12069 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
12070 + tst r1, #LPTE_USER @ User?
12071 orrne r2, r2, #HPTE_AP_READ
12073 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
12074 --- linux-2.4.25/arch/arm/mm/proc-arm922.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
12075 +++ linux-2.4.25/arch/arm/mm/proc-arm922.S 2004-03-31 17:15:09.000000000 +0200
12076 @@ -62,17 +62,20 @@
12078 * Returns:
12079 * r0 = address of abort
12080 - * r1 != 0 if writing
12081 - * r3 = FSR
12082 + * r1 = FSR, bit 11 set if writing
12083 + * r3 = corrupted
12085 .align 5
12086 ENTRY(cpu_arm922_data_abort)
12087 - ldr r1, [r0] @ read aborted instruction
12088 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
12089 mrc p15, 0, r0, c6, c0, 0 @ get FAR
12090 - tst r1, r1, lsr #21 @ C = bit 20
12091 - mrc p15, 0, r3, c5, c0, 0 @ get FSR
12092 - sbc r1, r1, r1 @ r1 = C - 1
12093 - and r3, r3, #255
12094 + tst r3, #PSR_T_BIT
12095 + ldrneh r3, [r2] @ read aborted thumb instruction
12096 + ldreq r3, [r2] @ read aborted ARM instruction
12097 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
12098 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
12099 + tst r3, #1 << 20 @ check write
12100 + orreq r1, r1, #1 << 11
12101 mov pc, lr
12104 @@ -185,7 +188,7 @@
12105 bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
12106 sub r3, r1, r0
12107 cmp r3, #MAX_AREA_SIZE
12108 - bgt cpu_arm922_cache_clean_invalidate_all_r2
12109 + bhi cpu_arm922_cache_clean_invalidate_all_r2
12110 1: teq r2, #0
12111 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
12112 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
12113 @@ -203,7 +206,7 @@
12114 add r0, r0, #DCACHELINESIZE
12115 #endif
12116 cmp r0, r1
12117 - blt 1b
12118 + blo 1b
12120 mcr p15, 0, r1, c7, c10, 4 @ drain WB
12121 mov pc, lr
12122 @@ -249,7 +252,7 @@
12124 .align 5
12125 ENTRY(cpu_arm922_dcache_invalidate_range)
12126 -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
12127 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12128 tst r0, #DCACHELINESIZE - 1
12129 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
12130 tst r1, #DCACHELINESIZE - 1
12131 @@ -260,7 +263,7 @@
12132 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
12133 add r0, r0, #DCACHELINESIZE
12134 cmp r0, r1
12135 - blt 1b
12136 + blo 1b
12137 mov pc, lr
12140 @@ -275,12 +278,12 @@
12142 .align 5
12143 ENTRY(cpu_arm922_dcache_clean_range)
12144 -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
12145 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12146 bic r0, r0, #DCACHELINESIZE - 1
12147 sub r1, r1, r0
12148 cmp r1, #MAX_AREA_SIZE
12149 mov r2, #0
12150 - bgt cpu_arm922_cache_clean_invalidate_all_r2
12151 + bhi cpu_arm922_cache_clean_invalidate_all_r2
12153 bic r1, r1, #DCACHELINESIZE -1
12154 add r1, r1, #DCACHELINESIZE
12155 @@ -308,7 +311,7 @@
12157 .align 5
12158 ENTRY(cpu_arm922_dcache_clean_page)
12159 -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
12160 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12161 mov r1, #PAGESIZE
12162 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
12163 add r0, r0, #DCACHELINESIZE
12164 @@ -329,7 +332,7 @@
12166 .align 5
12167 ENTRY(cpu_arm922_dcache_clean_entry)
12168 -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
12169 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12170 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
12171 #endif
12172 mcr p15, 0, r0, c7, c10, 4 @ drain WB
12173 @@ -361,7 +364,7 @@
12174 bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
12175 sub r1, r1, r0
12176 cmp r1, #MAX_AREA_SIZE
12177 - bgt cpu_arm922_cache_clean_invalidate_all_r2
12178 + bhi cpu_arm922_cache_clean_invalidate_all_r2
12180 bic r1, r1, #ICACHELINESIZE - 1
12181 add r1, r1, #ICACHELINESIZE
12182 @@ -420,7 +423,7 @@
12183 mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
12184 add r0, r0, #PAGESIZE
12185 cmp r0, r1
12186 - blt 1b
12187 + blo 1b
12188 mov pc, lr
12191 @@ -510,7 +513,7 @@
12192 bic r2, r2, #3
12193 orr r2, r2, #HPTE_TYPE_SMALL
12195 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
12196 + tst r1, #LPTE_USER @ User?
12197 orrne r2, r2, #HPTE_AP_READ
12199 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
12200 --- linux-2.4.25/arch/arm/mm/proc-arm925.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
12201 +++ linux-2.4.25/arch/arm/mm/proc-arm925.S 2004-03-31 17:15:09.000000000 +0200
12202 @@ -69,24 +69,24 @@
12204 * Returns:
12205 * r0 = address of abort
12206 - * r1 != 0 if writing
12207 - * r3 = FSR
12208 + * r1 = FSR, bit 11 set if writing
12209 + * r3 = corrupted
12210 * r4 = corrupted
12212 .align 5
12213 ENTRY(cpu_arm925_data_abort)
12214 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
12215 mrc p15, 0, r0, c6, c0, 0 @ get FAR
12216 - mrc p15, 0, r4, c5, c0, 0 @ get FSR
12218 - tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
12219 - ldrneh r1, [r2] @ Read aborted Thumb instruction
12220 - tstne r1, r1, lsr #12 @ C = bit 11
12222 - ldreq r1, [r2] @ Read aborted ARM instruction
12223 - tsteq r1, r1, lsr #21 @ C = bit 20
12225 - sbc r1, r1, r1 @ r1 = C - 1
12226 - and r3, r4, #255
12227 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
12228 + tst r3, #PSR_J_BIT @ Java?
12229 + orrne r1, r1, #1 << 11 @ always assume write
12230 + movne pc, lr
12231 + tst r3, #PSR_T_BIT @ Thumb?
12232 + ldrneh r3, [r2] @ read aborted thumb instruction
12233 + ldreq r3, [r2] @ read aborted ARM instruction
12234 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
12235 + tst r3, #1 << 20 @ L = 0 -> write
12236 + orreq r1, r1, #1 << 11 @ yes.
12237 mov pc, lr
12240 @@ -207,7 +207,7 @@
12241 bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
12242 sub r3, r1, r0
12243 cmp r3, #MAX_AREA_SIZE
12244 - bgt cpu_arm925_cache_clean_invalidate_all_r2
12245 + bhi cpu_arm925_cache_clean_invalidate_all_r2
12246 1: teq r2, #0
12247 #ifdef CONFIG_CPU_ARM925_WRITETHROUGH
12248 mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
12249 @@ -225,7 +225,7 @@
12250 add r0, r0, #DCACHELINESIZE
12251 #endif
12252 cmp r0, r1
12253 - blt 1b
12254 + blo 1b
12256 mcr p15, 0, r1, c7, c10, 4 @ drain WB
12257 mov pc, lr
12258 @@ -282,7 +282,7 @@
12259 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
12260 add r0, r0, #DCACHELINESIZE
12261 cmp r0, r1
12262 - blt 1b
12263 + blo 1b
12264 mov pc, lr
12267 @@ -302,7 +302,7 @@
12268 sub r1, r1, r0
12269 cmp r1, #MAX_AREA_SIZE
12270 mov r2, #0
12271 - bgt cpu_arm925_cache_clean_invalidate_all_r2
12272 + bhi cpu_arm925_cache_clean_invalidate_all_r2
12274 bic r1, r1, #DCACHELINESIZE -1
12275 add r1, r1, #DCACHELINESIZE
12276 @@ -383,7 +383,7 @@
12277 bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
12278 sub r1, r1, r0
12279 cmp r1, #MAX_AREA_SIZE
12280 - bgt cpu_arm925_cache_clean_invalidate_all_r2
12281 + bhi cpu_arm925_cache_clean_invalidate_all_r2
12283 bic r1, r1, #ICACHELINESIZE - 1
12284 add r1, r1, #ICACHELINESIZE
12285 @@ -443,7 +443,7 @@
12286 mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
12287 add r0, r0, #PAGESIZE
12288 cmp r0, r1
12289 - blt 1b
12290 + blo 1b
12291 mov pc, lr
12294 @@ -532,7 +532,7 @@
12295 bic r2, r2, #3
12296 orr r2, r2, #HPTE_TYPE_SMALL
12298 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
12299 + tst r1, #LPTE_USER @ User?
12300 orrne r2, r2, #HPTE_AP_READ
12302 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
12303 --- linux-2.4.25/arch/arm/mm/proc-arm926.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
12304 +++ linux-2.4.25/arch/arm/mm/proc-arm926.S 2004-03-31 17:15:09.000000000 +0200
12305 @@ -66,28 +66,24 @@
12307 * Returns:
12308 * r0 = address of abort
12309 - * r1 != 0 if writing
12310 - * r3 = FSR
12311 + * r1 = FSR, bit 11 set if writing
12312 + * r3 = corrupted
12313 * r4 = corrupted
12315 .align 5
12316 ENTRY(cpu_arm926_data_abort)
12317 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
12318 mrc p15, 0, r0, c6, c0, 0 @ get FAR
12319 - mrc p15, 0, r4, c5, c0, 0 @ get FSR
12321 - tst r3, #1<<24 @ Check for Jbit (NE -> found)
12322 - movne r3, #-1 @ Mark as writing
12323 - bne 2f
12325 - tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
12326 - ldrneh r1, [r2] @ Read aborted Thumb instruction
12327 - ldreq r1, [r2] @ Read aborted ARM instruction
12328 - movne r1, r1, lsl #(20-12) @ shift thumb bit 10 to ARM bit 20
12329 - tsteq r1, r1, lsr #21 @ C = bit 20
12331 - sbc r1, r1, r1 @ r1 = C - 1
12333 - and r3, r4, #255
12334 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
12335 + tst r3, #PSR_J_BIT @ Java?
12336 + orrne r1, r1, #1 << 11 @ always assume write
12337 + movne pc, lr
12338 + tst r3, #PSR_T_BIT @ Thumb?
12339 + ldrneh r3, [r2] @ read aborted thumb instruction
12340 + ldreq r3, [r2] @ read aborted ARM instruction
12341 + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
12342 + tst r3, #1 << 20 @ L = 0 -> write
12343 + orreq r1, r1, #1 << 11 @ yes.
12344 mov pc, lr
12347 @@ -263,7 +259,7 @@
12349 .align 5
12350 ENTRY(cpu_arm926_dcache_invalidate_range)
12351 -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
12352 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12353 tst r0, #DCACHELINESIZE - 1
12354 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
12355 tst r1, #DCACHELINESIZE - 1
12356 @@ -288,7 +284,7 @@
12358 .align 5
12359 ENTRY(cpu_arm926_dcache_clean_range)
12360 -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
12361 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12362 bic r0, r0, #DCACHELINESIZE - 1
12363 sub r3, r1, r0
12364 cmp r3, #MAX_AREA_SIZE
12365 @@ -318,7 +314,7 @@
12367 .align 5
12368 ENTRY(cpu_arm926_dcache_clean_page)
12369 -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
12370 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12371 mov r1, #PAGESIZE
12372 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
12373 add r0, r0, #DCACHELINESIZE
12374 @@ -339,7 +335,7 @@
12376 .align 5
12377 ENTRY(cpu_arm926_dcache_clean_entry)
12378 -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
12379 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12380 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
12381 #endif
12382 mcr p15, 0, r0, c7, c10, 4 @ drain WB
12383 @@ -482,7 +478,7 @@
12384 biceq r1, r1, #4 @ clear bufferable bit
12385 #endif
12386 str r1, [r0]
12387 -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
12388 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
12389 mcr p15, 0, r0, c7, c10, 1 @ clean D entry
12390 #endif
12391 mcr p15, 0, r0, c7, c10, 4 @ drain WB
12392 @@ -503,7 +499,7 @@
12393 bic r2, r2, #3
12394 orr r2, r2, #HPTE_TYPE_SMALL
12396 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
12397 + tst r1, #LPTE_USER @ User?
12398 orrne r2, r2, #HPTE_AP_READ
12400 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
12401 --- linux-2.4.25/arch/arm/mm/proc-sa110.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
12402 +++ linux-2.4.25/arch/arm/mm/proc-sa110.S 2004-03-31 17:15:09.000000000 +0200
12403 @@ -86,12 +86,12 @@
12404 .align 5
12405 ENTRY(cpu_sa110_data_abort)
12406 ENTRY(cpu_sa1100_data_abort)
12407 - mrc p15, 0, r3, c5, c0, 0 @ get FSR
12408 + mrc p15, 0, r1, c5, c0, 0 @ get FSR
12409 mrc p15, 0, r0, c6, c0, 0 @ get FAR
12410 - ldr r1, [r2] @ read aborted instruction
12411 - and r3, r3, #255
12412 - tst r1, r1, lsr #21 @ C = bit 20
12413 - sbc r1, r1, r1 @ r1 = C - 1
12414 + ldr r3, [r2] @ read aborted instruction
12415 + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
12416 + tst r3, #1 << 20 @ check write
12417 + orreq r1, r1, #1 << 11
12418 mov pc, lr
12421 @@ -551,7 +551,7 @@
12422 bic r2, r2, #3
12423 orr r2, r2, #HPTE_TYPE_SMALL
12425 - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
12426 + tst r1, #LPTE_USER @ User?
12427 orrne r2, r2, #HPTE_AP_READ
12429 tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
12430 --- linux-2.4.25/arch/arm/tools/mach-types~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
12431 +++ linux-2.4.25/arch/arm/tools/mach-types 2004-03-31 17:15:09.000000000 +0200
12432 @@ -6,7 +6,7 @@
12433 # To add an entry into this database, please see Documentation/arm/README,
12434 # or contact rmk@arm.linux.org.uk
12436 -# Last update: Sat Jun 28 12:10:54 2003
12437 +# Last update: Tue Feb 10 17:10:34 2004
12439 # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
12441 @@ -202,7 +202,7 @@
12442 fester SA1100_FESTER FESTER 191
12443 gpi ARCH_GPI GPI 192
12444 smdk2410 ARCH_SMDK2410 SMDK2410 193
12445 -premium ARCH_PREMIUM PREMIUM 194
12446 +i519 ARCH_I519 I519 194
12447 nexio SA1100_NEXIO NEXIO 195
12448 bitbox SA1100_BITBOX BITBOX 196
12449 g200 SA1100_G200 G200 197
12450 @@ -228,7 +228,7 @@
12451 arnold SA1100_ARNOLD ARNOLD 217
12452 psiboard SA1100_PSIBOARD PSIBOARD 218
12453 jz8028 ARCH_JZ8028 JZ8028 219
12454 -h5400 ARCH_IPAQ3 IPAQ3 220
12455 +h5400 ARCH_H5400 H5400 220
12456 forte SA1100_FORTE FORTE 221
12457 acam SA1100_ACAM ACAM 222
12458 abox SA1100_ABOX ABOX 223
12459 @@ -259,7 +259,7 @@
12460 stork_egg ARCH_STORK_EGG STORK_EGG 248
12461 wismo SA1100_WISMO WISMO 249
12462 ezlinx ARCH_EZLINX EZLINX 250
12463 -at91rm9200 ARCH_AT91 AT91 251
12464 +at91rm9200 ARCH_AT91RM9200 AT91RM9200 251
12465 orion ARCH_ORION ORION 252
12466 neptune ARCH_NEPTUNE NEPTUNE 253
12467 hackkit SA1100_HACKKIT HACKKIT 254
12468 @@ -300,7 +300,7 @@
12469 inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
12470 adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
12471 iyonix ARCH_IYONIX IYONIX 291
12472 -damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
12473 +damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
12474 meg03 ARCH_MEG03 MEG03 293
12475 pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
12476 nwsc ARCH_NWSC NWSC 295
12477 @@ -356,3 +356,111 @@
12478 seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345
12479 ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346
12480 h1940 ARCH_H1940 H1940 347
12481 +scorpio ARCH_SCORPIO SCORPIO 348
12482 +viva ARCH_VIVA VIVA 349
12483 +pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350
12484 +csb335 ARCH_CSB335 CSB335 351
12485 +ixrd425 ARCH_IXRD425 IXRD425 352
12486 +iq80315 ARCH_IQ80315 IQ80315 353
12487 +nmp7312 ARCH_NMP7312 NMP7312 354
12488 +cx861xx ARCH_CX861XX CX861XX 355
12489 +enp2611 ARCH_ENP2611 ENP2611 356
12490 +xda SA1100_XDA XDA 357
12491 +csir_ims ARCH_CSIR_IMS CSIR_IMS 358
12492 +ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359
12493 +pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360
12494 +toto ARCH_TOTO TOTO 361
12495 +s3c2440 ARCH_S3C2440 S3C2440 362
12496 +ks8695p ARCH_KS8695P KS8695P 363
12497 +se4000 ARCH_SE4000 SE4000 364
12498 +quadriceps ARCH_QUADRICEPS QUADRICEPS 365
12499 +bronco ARCH_BRONCO BRONCO 366
12500 +esl_wireless_tab ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET 367
12501 +esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
12502 +s5c7375 ARCH_S5C7375 S5C7375 369
12503 +spearhead ARCH_SPEARHEAD SPEARHEAD 370
12504 +pantera ARCH_PANTERA PANTERA 371
12505 +prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
12506 +gumstik ARCH_GUMSTIK GUMSTIK 373
12507 +rcube ARCH_RCUBE RCUBE 374
12508 +rea_olv ARCH_REA_OLV REA_OLV 375
12509 +pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
12510 +s3c3410 ARCH_S3C3410 S3C3410 377
12511 +espd_4510b ARCH_ESPD_4510B ESPD_4510B 378
12512 +mp1x ARCH_MP1X MP1X 379
12513 +at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380
12514 +adsvgx ARCH_ADSVGX ADSVGX 381
12515 +omap1610 ARCH_OMAP1610 OMAP1610 382
12516 +pelee ARCH_PELEE PELEE 383
12517 +e7xx ARCH_E7XX E7XX 384
12518 +iq80331 ARCH_IQ80331 IQ80331 385
12519 +versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387
12520 +kev7a400 MACH_KEV7A400 KEV7A400 388
12521 +lpd7a400 MACH_LPD7A400 LPD7A400 389
12522 +lpd7a404 MACH_LPD7A404 LPD7A404 390
12523 +fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391
12524 +janus2m ARCH_JANUS2M JANUS2M 392
12525 +embtf MACH_EMBTF EMBTF 393
12526 +hpm MACH_HPM HPM 394
12527 +smdk2410tk MACH_SMDK2410TK SMDK2410TK 395
12528 +smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396
12529 +streetracer MACH_STREETRACER STREETRACER 397
12530 +eframe MACH_EFRAME EFRAME 398
12531 +csb337 MACH_CSB337 CSB337 399
12532 +pxa_lark MACH_PXA_LARK PXA_LARK 400
12533 +pxa_pnp2110 MACH_PNP2110 PNP2110 401
12534 +tcc72x MACH_TCC72X TCC72X 402
12535 +altair MACH_ALTAIR ALTAIR 403
12536 +kc3 MACH_KC3 KC3 404
12537 +sinteftd MACH_SINTEFTD SINTEFTD 405
12538 +mainstone MACH_MAINSTONE MAINSTONE 406
12539 +aday4x MACH_ADAY4X ADAY4X 407
12540 +lite300 MACH_LITE300 LITE300 408
12541 +s5c7376 MACH_S5C7376 S5C7376 409
12542 +mt02 MACH_MT02 MT02 410
12543 +mport3s MACH_MPORT3S MPORT3S 411
12544 +ra_alpha MACH_RA_ALPHA RA_ALPHA 412
12545 +xcep MACH_XCEP XCEP 413
12546 +arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414
12547 +stargate MACH_STARGATE STARGATE 415
12548 +armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
12549 +elroy_jack MACH_ELROY_JACK ELROY_JACK 417
12550 +backend MACH_BACKEND BACKEND 418
12551 +s5linbox MACH_S5LINBOX S5LINBOX 419
12552 +nomadik MACH_NOMADIK NOMADIK 420
12553 +ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421
12554 +at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422
12555 +corgi MACH_CORGI CORGI 423
12556 +poodle MACH_POODLE POODLE 424
12557 +ten MACH_TEN TEN 425
12558 +roverp5p MACH_ROVERP5P ROVERP5P 426
12559 +sc2700 MACH_SC2700 SC2700 427
12560 +ex_eagle MACH_EX_EAGLE EX_EAGLE 428
12561 +nx_pxa12 MACH_NX_PXA12 NX_PXA12 429
12562 +nx_pxa5 MACH_NX_PXA5 NX_PXA5 430
12563 +blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431
12564 +i819 MACH_I819 I819 432
12565 +ixmb995e MACH_IXMB995E IXMB995E 433
12566 +skyrider MACH_SKYRIDER SKYRIDER 434
12567 +skyhawk MACH_SKYHAWK SKYHAWK 435
12568 +enterprise MACH_ENTERPRISE ENTERPRISE 436
12569 +dep2410 MACH_DEP2410 DEP2410 437
12570 +armcore MACH_ARMCORE ARMCORE 438
12571 +hobbit MACH_HOBBIT HOBBIT 439
12572 +h7210 MACH_H7210 H7210 440
12573 +pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441
12574 +acc MACH_ACC ACC 442
12575 +esl_sarva MACH_ESL_SARVA ESL_SARVA 443
12576 +xm250 MACH_XM250 XM250 444
12577 +t6tc1xb MACH_T6TC1XB T6TC1XB 445
12578 +ess710 MACH_ESS710 ESS710 446
12579 +mx3ads MACH_MX3ADS MX3ADS 447
12580 +himalaya MACH_HIMALAYA HIMALAYA 448
12581 +bolfenk MACH_BOLFENK BOLFENK 449
12582 +at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
12583 +edb9312 MACH_EDB9312 EDB9312 451
12584 +omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452
12585 +aximx3 MACH_AXIMX3 AXIMX3 453
12586 +eb67xdip MACH_EB67XDIP EB67XDIP 454
12587 +webtxs MACH_WEBTXS WEBTXS 455
12588 +hawk MACH_HAWK HAWK 456
12589 --- linux-2.4.25/arch/i386/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
12590 +++ linux-2.4.25/arch/i386/config.in 2004-03-31 17:15:09.000000000 +0200
12591 @@ -9,6 +9,7 @@
12593 define_bool CONFIG_UID16 y
12595 +define_bool CONFIG_GENERIC_ISA_DMA y
12596 mainmenu_option next_comment
12597 comment 'Code maturity level options'
12598 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
12599 --- linux-2.4.25/arch/i386/kernel/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:19.000000000 +0100
12600 +++ linux-2.4.25/arch/i386/kernel/Makefile 2004-03-31 17:15:09.000000000 +0200
12601 @@ -7,8 +7,8 @@
12603 # Note 2! The CFLAGS definitions are now in the main makefile...
12605 -.S.o:
12606 - $(CC) $(AFLAGS) -traditional -c $< -o $*.o
12607 +USE_STANDARD_AS_RULE := true
12608 +EXTRA_AFLAGS := -traditional
12610 all: kernel.o head.o init_task.o
12612 --- linux-2.4.25/arch/i386/kernel/apm.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
12613 +++ linux-2.4.25/arch/i386/kernel/apm.c 2004-03-31 17:15:09.000000000 +0200
12614 @@ -1267,6 +1267,7 @@
12615 as->suspend_wait = 0;
12616 as->suspend_result = err;
12618 + ignore_normal_resume = 1;
12619 wake_up_interruptible(&apm_suspend_waitqueue);
12620 return err;
12622 @@ -1319,6 +1320,8 @@
12623 if (ignore_bounce
12624 && ((jiffies - last_resume) > bounce_interval))
12625 ignore_bounce = 0;
12626 + if (ignore_normal_resume && (event != APM_NORMAL_RESUME))
12627 + ignore_normal_resume = 0;
12629 switch (event) {
12630 case APM_SYS_STANDBY:
12631 --- linux-2.4.25/arch/i386/lib/Makefile~2.4.25-vrs2.patch 2001-09-10 16:31:30.000000000 +0200
12632 +++ linux-2.4.25/arch/i386/lib/Makefile 2004-03-31 17:15:09.000000000 +0200
12633 @@ -2,8 +2,7 @@
12634 # Makefile for i386-specific library files..
12637 -.S.o:
12638 - $(CC) $(AFLAGS) -c $< -o $*.o
12639 +USE_STANDARD_AS_RULE := true
12641 L_TARGET = lib.a
12643 --- linux-2.4.25/arch/i386/math-emu/Makefile~2.4.25-vrs2.patch 2000-12-29 23:07:20.000000000 +0100
12644 +++ linux-2.4.25/arch/i386/math-emu/Makefile 2004-03-31 17:15:09.000000000 +0200
12645 @@ -2,15 +2,15 @@
12646 # Makefile for wm-FPU-emu
12649 +USE_STANDARD_AS_RULE := true
12651 O_TARGET := math.o
12653 #DEBUG = -DDEBUGGING
12654 DEBUG =
12655 PARANOID = -DPARANOID
12656 CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION)
12658 -.S.o:
12659 - $(CC) $(AFLAGS) $(PARANOID) -c $<
12660 +EXTRA_AFLAGS := $(PARANOID)
12662 # From 'C' language sources:
12663 C_OBJS =fpu_entry.o errors.o \
12664 --- linux-2.4.25/arch/ia64/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
12665 +++ linux-2.4.25/arch/ia64/config.in 2004-03-31 17:15:09.000000000 +0200
12666 @@ -25,6 +25,7 @@
12667 define_bool CONFIG_SBUS n
12668 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
12669 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
12670 +define_bool CONFIG_GENERIC_ISA_DMA y
12672 choice 'IA-64 processor type' \
12673 "Itanium CONFIG_ITANIUM \
12674 --- linux-2.4.25/arch/m68k/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
12675 +++ linux-2.4.25/arch/m68k/config.in 2004-03-31 17:15:09.000000000 +0200
12676 @@ -6,6 +6,7 @@
12677 define_bool CONFIG_UID16 y
12678 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
12679 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
12680 +define_bool CONFIG_GENERIC_ISA_DMA y
12682 mainmenu_name "Linux/68k Kernel Configuration"
12684 --- linux-2.4.25/arch/mips/config.in~2.4.25-vrs2.patch 2002-11-29 00:53:09.000000000 +0100
12685 +++ linux-2.4.25/arch/mips/config.in 2004-03-31 17:15:09.000000000 +0200
12686 @@ -5,5 +5,6 @@
12687 define_bool CONFIG_MIPS y
12688 define_bool CONFIG_MIPS32 y
12689 define_bool CONFIG_MIPS64 n
12690 +define_bool CONFIG_GENERIC_ISA_DMA y
12692 source arch/mips/config-shared.in
12693 --- linux-2.4.25/arch/parisc/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
12694 +++ linux-2.4.25/arch/parisc/config.in 2004-03-31 17:15:09.000000000 +0200
12695 @@ -9,6 +9,7 @@
12696 define_bool CONFIG_UID16 n
12697 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
12698 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
12699 +define_bool CONFIG_GENERIC_ISA_DMA y
12701 mainmenu_option next_comment
12702 comment 'Code maturity level options'
12703 --- linux-2.4.25/arch/ppc/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
12704 +++ linux-2.4.25/arch/ppc/config.in 2004-03-31 17:15:09.000000000 +0200
12705 @@ -6,6 +6,7 @@
12706 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
12707 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
12708 define_bool CONFIG_HAVE_DEC_LOCK y
12709 +define_bool CONFIG_GENERIC_ISA_DMA y
12711 mainmenu_name "Linux/PowerPC Kernel Configuration"
12713 --- linux-2.4.25/arch/sh/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
12714 +++ linux-2.4.25/arch/sh/config.in 2004-03-31 17:15:09.000000000 +0200
12715 @@ -9,6 +9,7 @@
12716 define_bool CONFIG_UID16 y
12717 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
12718 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
12719 +define_bool CONFIG_GENERIC_ISA_DMA y
12721 mainmenu_option next_comment
12722 comment 'Code maturity level options'
12723 --- linux-2.4.25/arch/sparc/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
12724 +++ linux-2.4.25/arch/sparc/config.in 2004-03-31 17:15:09.000000000 +0200
12725 @@ -6,6 +6,7 @@
12727 define_bool CONFIG_UID16 y
12728 define_bool CONFIG_HIGHMEM y
12729 +define_bool CONFIG_GENERIC_ISA_DMA y
12731 mainmenu_option next_comment
12732 comment 'Code maturity level options'
12733 --- linux-2.4.25/arch/sparc64/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
12734 +++ linux-2.4.25/arch/sparc64/config.in 2004-03-31 17:15:09.000000000 +0200
12735 @@ -41,6 +41,7 @@
12736 define_bool CONFIG_HAVE_DEC_LOCK y
12737 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
12738 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
12739 +define_bool CONFIG_GENERIC_ISA_DMA y
12740 define_bool CONFIG_ISA n
12741 define_bool CONFIG_ISAPNP n
12742 define_bool CONFIG_EISA n
12743 --- linux-2.4.25/drivers/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:19.000000000 +0100
12744 +++ linux-2.4.25/drivers/Makefile 2004-03-31 17:15:09.000000000 +0200
12745 @@ -8,9 +8,9 @@
12747 mod-subdirs := dio hil mtd sbus video macintosh usb input telephony ide \
12748 message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
12749 - fc4 net/hamradio i2c acpi bluetooth usb/gadget
12750 + fc4 net/hamradio i2c l3 acpi bluetooth serial usb/gadget
12752 -subdir-y := parport char block net sound misc media cdrom hotplug
12753 +subdir-y := parport serial char block net sound misc media cdrom hotplug pld
12754 subdir-m := $(subdir-y)
12757 @@ -45,8 +45,12 @@
12758 # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch
12759 subdir-$(CONFIG_HAMRADIO) += net/hamradio
12760 subdir-$(CONFIG_I2C) += i2c
12761 +subdir-$(CONFIG_L3) += l3
12762 subdir-$(CONFIG_ACPI_BOOT) += acpi
12764 subdir-$(CONFIG_BLUEZ) += bluetooth
12765 +subdir-$(CONFIG_SSI) += ssi
12767 +subdir-$(CONFIG_ARCH_AT91RM9200)+= at91
12769 include $(TOPDIR)/Rules.make
12770 --- linux-2.4.25/drivers/acorn/char/i2c.c~2.4.25-vrs2.patch 2004-01-05 14:53:56.000000000 +0100
12771 +++ linux-2.4.25/drivers/acorn/char/i2c.c 2004-03-31 17:15:09.000000000 +0200
12772 @@ -166,7 +166,6 @@
12773 break;
12775 case RTC_RD_TIME:
12776 - memset(&rtctm, 0, sizeof(struct rtc_time));
12777 get_rtc_time(&rtc_raw, &year);
12778 rtctm.tm_sec = rtc_raw.secs;
12779 rtctm.tm_min = rtc_raw.mins;
12780 --- linux-2.4.25/drivers/acorn/net/ether1.c~2.4.25-vrs2.patch 2003-08-25 13:44:40.000000000 +0200
12781 +++ linux-2.4.25/drivers/acorn/net/ether1.c 2004-03-31 17:15:09.000000000 +0200
12782 @@ -80,7 +80,7 @@
12783 #define BUS_16 16
12784 #define BUS_8 8
12786 -static const card_ids __init ether1_cids[] = {
12787 +static card_ids __initdata ether1_cids[] = {
12788 { MANU_ACORN, PROD_ACORN_ETHER1 },
12789 { 0xffff, 0xffff }
12791 --- linux-2.4.25/drivers/acorn/net/ether3.c~2.4.25-vrs2.patch 2003-08-25 13:44:40.000000000 +0200
12792 +++ linux-2.4.25/drivers/acorn/net/ether3.c 2004-03-31 17:15:09.000000000 +0200
12793 @@ -75,7 +75,7 @@
12794 #include "ether3.h"
12796 static unsigned int net_debug = NET_DEBUG;
12797 -static const card_ids __init ether3_cids[] = {
12798 +static card_ids __initdata ether3_cids[] = {
12799 { MANU_ANT2, PROD_ANT_ETHER3 },
12800 { MANU_ANT, PROD_ANT_ETHER3 },
12801 { MANU_ANT, PROD_ANT_ETHERB },
12802 --- linux-2.4.25/drivers/acorn/net/etherh.c~2.4.25-vrs2.patch 2003-08-25 13:44:40.000000000 +0200
12803 +++ linux-2.4.25/drivers/acorn/net/etherh.c 2004-03-31 17:15:09.000000000 +0200
12804 @@ -57,7 +57,7 @@
12806 static unsigned int net_debug = NET_DEBUG;
12808 -static const card_ids __init etherh_cids[] = {
12809 +static card_ids __initdata etherh_cids[] = {
12810 { MANU_ANT, PROD_ANT_ETHERM },
12811 { MANU_I3, PROD_I3_ETHERLAN500 },
12812 { MANU_I3, PROD_I3_ETHERLAN600 },
12813 --- linux-2.4.25/drivers/acorn/scsi/cumana_1.c~2.4.25-vrs2.patch 2001-09-14 00:21:32.000000000 +0200
12814 +++ linux-2.4.25/drivers/acorn/scsi/cumana_1.c 2004-03-31 17:15:09.000000000 +0200
12815 @@ -153,20 +153,20 @@
12816 ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
12817 outb(0x00, instance->io_port - 577);
12819 - if (instance->irq != IRQ_NONE)
12820 + if (instance->irq != SCSI_IRQ_NONE)
12821 if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
12822 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
12823 instance->host_no, instance->irq);
12824 - instance->irq = IRQ_NONE;
12825 + instance->irq = SCSI_IRQ_NONE;
12828 - if (instance->irq == IRQ_NONE) {
12829 + if (instance->irq == SCSI_IRQ_NONE) {
12830 printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no);
12831 printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
12834 printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
12835 - if (instance->irq == IRQ_NONE)
12836 + if (instance->irq == SCSI_IRQ_NONE)
12837 printk ("s disabled");
12838 else
12839 printk (" %d", instance->irq);
12840 @@ -185,7 +185,7 @@
12842 int i;
12844 - if (shpnt->irq != IRQ_NONE)
12845 + if (shpnt->irq != SCSI_IRQ_NONE)
12846 free_irq (shpnt->irq, NULL);
12847 if (shpnt->io_port)
12848 release_region (shpnt->io_port, shpnt->n_io_port);
12849 --- linux-2.4.25/drivers/acorn/scsi/ecoscsi.c~2.4.25-vrs2.patch 2002-08-03 02:39:43.000000000 +0200
12850 +++ linux-2.4.25/drivers/acorn/scsi/ecoscsi.c 2004-03-31 17:15:09.000000000 +0200
12851 @@ -106,7 +106,7 @@
12852 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
12853 instance->io_port = 0x80ce8000;
12854 instance->n_io_port = 144;
12855 - instance->irq = IRQ_NONE;
12856 + instance->irq = SCSI_IRQ_NONE;
12858 if (check_region (instance->io_port, instance->n_io_port)) {
12859 scsi_unregister (instance);
12860 @@ -130,20 +130,20 @@
12861 return 0;
12864 - if (instance->irq != IRQ_NONE)
12865 + if (instance->irq != SCSI_IRQ_NONE)
12866 if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
12867 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
12868 instance->host_no, instance->irq);
12869 - instance->irq = IRQ_NONE;
12870 + instance->irq = SCSI_IRQ_NONE;
12873 - if (instance->irq != IRQ_NONE) {
12874 + if (instance->irq != SCSI_IRQ_NONE) {
12875 printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
12876 printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
12879 printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
12880 - if (instance->irq == IRQ_NONE)
12881 + if (instance->irq == SCSI_IRQ_NONE)
12882 printk ("s disabled");
12883 else
12884 printk (" %d", instance->irq);
12885 @@ -157,7 +157,7 @@
12887 int ecoscsi_release (struct Scsi_Host *shpnt)
12889 - if (shpnt->irq != IRQ_NONE)
12890 + if (shpnt->irq != SCSI_IRQ_NONE)
12891 free_irq (shpnt->irq, NULL);
12892 if (shpnt->io_port)
12893 release_region (shpnt->io_port, shpnt->n_io_port);
12894 --- linux-2.4.25/drivers/acorn/scsi/oak.c~2.4.25-vrs2.patch 2001-10-11 18:04:57.000000000 +0200
12895 +++ linux-2.4.25/drivers/acorn/scsi/oak.c 2004-03-31 17:15:09.000000000 +0200
12896 @@ -97,7 +97,7 @@
12899 #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
12900 -#define OAK_IRQ(card) (IRQ_NONE)
12901 +#define OAK_IRQ(card) (SCSI_IRQ_NONE)
12903 * Function : int oakscsi_detect(Scsi_Host_Template * tpnt)
12905 @@ -136,20 +136,20 @@
12906 instance->n_io_port = 255;
12907 request_region (instance->io_port, instance->n_io_port, "Oak SCSI");
12909 - if (instance->irq != IRQ_NONE)
12910 + if (instance->irq != SCSI_IRQ_NONE)
12911 if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
12912 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
12913 instance->host_no, instance->irq);
12914 - instance->irq = IRQ_NONE;
12915 + instance->irq = SCSI_IRQ_NONE;
12918 - if (instance->irq != IRQ_NONE) {
12919 + if (instance->irq != SCSI_IRQ_NONE) {
12920 printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
12921 printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
12924 printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
12925 - if (instance->irq == IRQ_NONE)
12926 + if (instance->irq == SCSI_IRQ_NONE)
12927 printk ("s disabled");
12928 else
12929 printk (" %d", instance->irq);
12930 @@ -172,7 +172,7 @@
12932 int i;
12934 - if (shpnt->irq != IRQ_NONE)
12935 + if (shpnt->irq != SCSI_IRQ_NONE)
12936 free_irq (shpnt->irq, NULL);
12937 if (shpnt->io_port)
12938 release_region (shpnt->io_port, shpnt->n_io_port);
12939 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
12940 +++ linux-2.4.25/drivers/at91/Makefile 2004-03-31 17:15:09.000000000 +0200
12941 @@ -0,0 +1,23 @@
12943 +# Makefile for the AT91RM9200-specific Linux kernel device drivers.
12945 +# Note! Dependencies are done automagically by 'make dep', which also
12946 +# removes any old dependencies. DON'T put your own dependencies here
12947 +# unless it's something special (not a .c file).
12949 +O_TARGET := at91drv.o
12951 +subdir-y := serial net watchdog rtc usb i2c spi mtd
12952 +subdir-m := $(subdir-y)
12954 +obj-$(CONFIG_SERIAL_AT91) += serial/at91serial.o
12955 +obj-$(CONFIG_AT91_ETHER) += net/at91net.o
12956 +obj-$(CONFIG_AT91_WATCHDOG) += watchdog/at91wdt.o
12957 +obj-$(CONFIG_AT91_RTC) += rtc/at91rtc.o
12958 +obj-$(CONFIG_USB) += usb/at91usb.o
12959 +obj-$(CONFIG_I2C_AT91) += i2c/at91i2c.o
12960 +obj-$(CONFIG_AT91_SPIDEV) += spi/at91spi.o
12961 +obj-$(CONFIG_MTD_AT91_DATAFLASH) += spi/at91spi.o mtd/at91mtd.o
12962 +obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += mtd/at91mtd.o
12964 +include $(TOPDIR)/Rules.make
12965 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
12966 +++ linux-2.4.25/drivers/at91/i2c/Makefile 2004-03-31 17:15:09.000000000 +0200
12967 @@ -0,0 +1,15 @@
12968 +# File: drivers/at91/i2c/Makefile
12970 +# Makefile for the Atmel AT91RM9200 I2C (TWI) device drivers
12973 +O_TARGET := at91i2c.o
12975 +obj-y :=
12976 +obj-m :=
12977 +obj-n :=
12978 +obj- :=
12980 +obj-$(CONFIG_I2C_AT91) += at91_i2c.o
12982 +include $(TOPDIR)/Rules.make
12983 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
12984 +++ linux-2.4.25/drivers/at91/i2c/at91_i2c.c 2004-03-31 17:15:09.000000000 +0200
12985 @@ -0,0 +1,257 @@
12987 + i2c Support for Atmel's AT91RM9200 Two-Wire Interface
12989 + (c) Rick Bronson
12991 + Borrowed heavily from original work by:
12992 + Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
12994 + This program is free software; you can redistribute it and/or modify
12995 + it under the terms of the GNU General Public License as published by
12996 + the Free Software Foundation; either version 2 of the License, or
12997 + (at your option) any later version.
12999 + This program is distributed in the hope that it will be useful,
13000 + but WITHOUT ANY WARRANTY; without even the implied warranty of
13001 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13002 + GNU General Public License for more details.
13004 + You should have received a copy of the GNU General Public License
13005 + along with this program; if not, write to the Free Software
13006 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13010 +#include <linux/module.h>
13011 +#include <linux/version.h>
13012 +#include <linux/kernel.h>
13013 +#include <linux/slab.h>
13014 +#include <linux/pci.h>
13015 +#include <linux/types.h>
13016 +#include <linux/delay.h>
13017 +#include <linux/i2c.h>
13018 +#include <linux/init.h>
13020 +#include <asm/arch/AT91RM9200_TWI.h>
13021 +#include <asm/arch/pio.h>
13022 +#include "at91_i2c.h"
13024 +#define DBG(x...) do {\
13025 + if (debug > 0) \
13026 + printk(KERN_DEBUG "i2c:" x); \
13027 + } while(0)
13029 +int debug = 0;
13031 +static struct at91_i2c_local *at91_i2c_device;
13034 + * Poll the i2c status register until the specified bit is set.
13035 + * Returns 0 if timed out (100 msec)
13036 + */
13037 +static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) {
13038 + int loop_cntr = 10000;
13039 + do {
13040 + udelay(10);
13041 + } while (!(twi->TWI_SR & bit) && (--loop_cntr > 0));
13043 + return (loop_cntr > 0);
13047 + * Generic i2c master transfer entrypoint
13048 + */
13049 +static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
13051 + struct at91_i2c_local *device = (struct at91_i2c_local *) adap->data;
13052 + AT91PS_TWI twi = (AT91PS_TWI) device->base_addr;
13054 + struct i2c_msg *pmsg;
13055 + int length;
13056 + unsigned char *buf;
13058 + /*
13059 + * i2c_smbus_xfer_emulated() in drivers/i2c/i2c-core.c states:
13060 + * "... In the case of writing, we need to use only one message;
13061 + * when reading, we need two..."
13062 + */
13064 + pmsg = msgs; /* look at 1st message, it contains the address/command */
13065 + if (num >= 1 && num <= 2) {
13066 + DBG("xfer: doing %s %d bytes to 0x%02x - %d messages\n",
13067 + pmsg->flags & I2C_M_RD ? "read" : "write",
13068 + pmsg->len, pmsg->buf[0], num);
13070 + /* Set the TWI Master Mode Register */
13071 + twi->TWI_MMR = (pmsg->addr << 16) | (pmsg->len << 8)
13072 + | ((pmsg + 1)->flags & I2C_M_RD ? AT91C_TWI_MREAD : 0);
13074 + /* Set TWI Internal Address Register with first messages data field */
13075 + if (pmsg->len == 1)
13076 + twi->TWI_IADR = pmsg->buf[0];
13077 + else if (pmsg->len == 2)
13078 + twi->TWI_IADR = pmsg->buf[0] << 8 | pmsg->buf[1];
13079 + else /* must be 3 */
13080 + twi->TWI_IADR = pmsg->buf[0] << 16 | pmsg->buf[1] << 8 | pmsg->buf[2];
13082 + /* 1st message contains the address/command */
13083 + if (num > 1)
13084 + pmsg++; /* go to real message */
13086 + length = pmsg->len;
13087 + buf = pmsg->buf;
13088 + if (length && buf) { /* sanity check */
13089 + if (pmsg->flags & I2C_M_RD) {
13090 + twi->TWI_CR = AT91C_TWI_START;
13091 + while (length--) {
13092 + if (!length)
13093 + twi->TWI_CR = AT91C_TWI_STOP;
13094 + /* Wait until transfer is finished */
13095 + if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) {
13096 + printk(KERN_ERR "at91_i2c: timeout 1\n");
13097 + return 0;
13099 + *buf++ = twi->TWI_RHR;
13101 + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
13102 + printk(KERN_ERR "at91_i2c: timeout 2\n");
13103 + return 0;
13105 + } else {
13106 + twi->TWI_CR = AT91C_TWI_START;
13107 + while (length--) {
13108 + twi->TWI_THR = *buf++;
13109 + if (!length)
13110 + twi->TWI_CR = AT91C_TWI_STOP;
13111 + if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) {
13112 + printk(KERN_ERR "at91_i2c: timeout 3\n");
13113 + return 0;
13116 + /* Wait until transfer is finished */
13117 + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
13118 + printk(KERN_ERR "at91_i2c: timeout 4\n");
13119 + return 0;
13123 + DBG("transfer complete\n");
13124 + return num;
13126 + else {
13127 + printk(KERN_ERR "at91_i2c: unexpected number of messages: %d\n", num);
13128 + return 0;
13133 + * Return list of supported functionality
13134 + */
13135 +static u32 at91_func(struct i2c_adapter *adapter)
13137 + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE
13138 + | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
13139 + | I2C_FUNC_SMBUS_BLOCK_DATA;
13143 + * Open
13144 + */
13145 +static void at91_inc(struct i2c_adapter *adapter)
13147 + MOD_INC_USE_COUNT;
13151 + * Close
13152 + */
13153 +static void at91_dec(struct i2c_adapter *adapter)
13155 + MOD_DEC_USE_COUNT;
13158 +/* For now, we only handle combined mode (smbus) */
13159 +static struct i2c_algorithm at91_algorithm = {
13160 + name:"at91 i2c",
13161 + id:I2C_ALGO_SMBUS,
13162 + master_xfer:at91_xfer,
13163 + functionality:at91_func,
13167 + * Main initialization routine
13168 + */
13169 +static int __init i2c_at91_init(void)
13171 + AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI;
13172 + struct at91_i2c_local *device;
13173 + int rc;
13175 + AT91_CfgPIO_TWI();
13176 + AT91_SYS->PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */
13178 + twi->TWI_IDR = 0x3ff; /* Disable all interrupts */
13179 + twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */
13180 + twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; /* Set Master mode */
13182 + /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */
13183 + twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8);
13185 + device = (struct at91_i2c_local *) kmalloc(sizeof(struct at91_i2c_local), GFP_KERNEL);
13186 + if (device == NULL) {
13187 + printk(KERN_ERR "at91_i2c: can't allocate inteface!\n");
13188 + return -ENOMEM;
13190 + memset(device, 0, sizeof(struct at91_i2c_local));
13191 + at91_i2c_device = device;
13193 + sprintf(device->adapter.name, "AT91RM9200");
13194 + device->adapter.data = (void *) device;
13195 + device->adapter.id = I2C_ALGO_SMBUS;
13196 + device->adapter.algo = &at91_algorithm;
13197 + device->adapter.algo_data = NULL;
13198 + device->adapter.inc_use = at91_inc;
13199 + device->adapter.dec_use = at91_dec;
13200 + device->adapter.client_register = NULL;
13201 + device->adapter.client_unregister = NULL;
13202 + device->base_addr = AT91C_VA_BASE_TWI;
13204 + rc = i2c_add_adapter(&device->adapter);
13205 + if (rc) {
13206 + printk(KERN_ERR "at91_i2c: Adapter %s registration failed\n", device->adapter.name);
13207 + device->adapter.data = NULL;
13208 + kfree(device);
13210 + else
13211 + printk(KERN_INFO "Found AT91 i2c\n");
13212 + return rc;
13216 + * Clean up routine
13217 + */
13218 +static void __exit i2c_at91_cleanup(void)
13220 + struct at91_i2c_local *device = at91_i2c_device;
13221 + int rc;
13223 + rc = i2c_del_adapter(&device->adapter);
13224 + device->adapter.data = NULL;
13225 + kfree(device);
13227 + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_TWI; /* disable peripheral clock */
13229 + /* We aren't that prepared to deal with this... */
13230 + if (rc)
13231 + printk(KERN_ERR "at91_i2c: i2c_del_adapter failed (%i), that's bad!\n", rc);
13234 +module_init(i2c_at91_init);
13235 +module_exit(i2c_at91_cleanup);
13237 +MODULE_AUTHOR("Rick Bronson");
13238 +MODULE_DESCRIPTION("I2C driver for Atmel AT91RM9200");
13239 +MODULE_LICENSE("GPL");
13240 +MODULE_PARM(debug, "i");
13242 +EXPORT_NO_SYMBOLS;
13243 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
13244 +++ linux-2.4.25/drivers/at91/i2c/at91_i2c.h 2004-03-31 17:15:09.000000000 +0200
13245 @@ -0,0 +1,43 @@
13247 + i2c Support for Atmel's AT91RM9200 Two-Wire Interface
13249 + (c) Rick Bronson
13251 + This program is free software; you can redistribute it and/or modify
13252 + it under the terms of the GNU General Public License as published by
13253 + the Free Software Foundation; either version 2 of the License, or
13254 + (at your option) any later version.
13256 + This program is distributed in the hope that it will be useful,
13257 + but WITHOUT ANY WARRANTY; without even the implied warranty of
13258 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13259 + GNU General Public License for more details.
13261 + You should have received a copy of the GNU General Public License
13262 + along with this program; if not, write to the Free Software
13263 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13266 +#ifndef AT91_I2C_H
13267 +#define AT91_I2C_H
13269 +#define AT91C_TWI_CLOCK 100000
13270 +#define AT91C_TWI_SCLOCK (10 * AT91C_MASTER_CLOCK / AT91C_TWI_CLOCK)
13271 +#define AT91C_TWI_CKDIV1 (2 << 16) /* TWI clock divider. NOTE: see Errata #22 */
13273 +#if (AT91C_TWI_SCLOCK % 10) >= 5
13274 +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 5)
13275 +#else
13276 +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 6)
13277 +#endif
13278 +#define AT91C_TWI_CLDIV3 ((AT91C_TWI_CLDIV2 + (4 - AT91C_TWI_CLDIV2 % 4)) >> 2)
13280 +#define AT91C_EEPROM_I2C_ADDRESS (0x50 << 16)
13282 +/* Physical interface */
13283 +struct at91_i2c_local {
13284 + struct i2c_adapter adapter;
13285 + unsigned long base_addr;
13288 +#endif
13289 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
13290 +++ linux-2.4.25/drivers/at91/mtd/Makefile 2004-03-31 17:15:09.000000000 +0200
13291 @@ -0,0 +1,19 @@
13292 +# File: drivers/at91/mtd/Makefile
13294 +# Makefile for the Atmel AT91RM9200 MTD devices.
13295 +# Includes: NAND flash (SmartMedia) & DataFlash
13298 +O_TARGET := at91mtd.o
13300 +export-objs :=
13302 +obj-y :=
13303 +obj-m :=
13304 +obj-n :=
13305 +obj- :=
13307 +obj-$(CONFIG_MTD_AT91_DATAFLASH) += at91_dataflash.o
13308 +obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += at91_nand.o
13310 +include $(TOPDIR)/Rules.make
13311 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
13312 +++ linux-2.4.25/drivers/at91/mtd/at91_dataflash.c 2004-03-31 17:15:09.000000000 +0200
13313 @@ -0,0 +1,495 @@
13315 + * Atmel DataFlash driver for Atmel AT91RM9200 (Thunder)
13317 + * (c) SAN People (Pty) Ltd
13319 + * This program is free software; you can redistribute it and/or
13320 + * modify it under the terms of the GNU General Public License
13321 + * as published by the Free Software Foundation; either version
13322 + * 2 of the License, or (at your option) any later version.
13325 +#include <linux/config.h>
13326 +#include <linux/module.h>
13327 +#include <linux/slab.h>
13328 +#include <linux/pci.h>
13329 +#include <linux/mtd/mtd.h>
13330 +#include <linux/mtd/partitions.h>
13332 +#include <asm/arch/AT91RM9200_SPI.h>
13333 +#include <asm/arch/pio.h>
13334 +#include "at91_dataflash.h"
13335 +#include "../spi/at91_spi.h"
13337 +#undef DEBUG_DATAFLASH
13339 +/* Detected DataFlash devices */
13340 +static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES];
13341 +static int nr_devices = 0;
13343 +/* ......................................................................... */
13345 +#ifdef CONFIG_MTD_PARTITIONS
13347 +static struct mtd_partition *mtd_parts = 0;
13348 +static int mtd_parts_nr = 0;
13350 +#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
13352 +static struct mtd_partition static_partitions[] =
13355 + name: "bootloader",
13356 + offset: 0,
13357 + size: 64 * 1024, /* 64 Kb */
13358 + mask_flags: MTD_WRITEABLE /* read-only */
13359 + },
13361 + name: "kernel",
13362 + offset: MTDPART_OFS_NXTBLK,
13363 + size: 768 *1024, /* 768 Kb */
13364 + },
13366 + name: "filesystem",
13367 + offset: MTDPART_OFS_NXTBLK,
13368 + size: MTDPART_SIZ_FULL,
13372 +int parse_cmdline_partitions(struct mtd_info *master,
13373 + struct mtd_partition **pparts, const char *mtd_id);
13375 +#endif
13377 +/* ......................................................................... */
13379 +/* Allocate a single SPI transfer descriptor. We're assuming that if multiple
13380 + SPI transfers occur at the same time, spi_access_bus() will serialize them.
13381 + If this is not valid, then either (i) each dataflash 'priv' structure
13382 + needs it's own transfer descriptor, (ii) we lock this one, or (iii) use
13383 + another mechanism. */
13384 +struct spi_transfer_list* spi_transfer_desc;
13387 + * Perform a SPI transfer to access the DataFlash device.
13388 + */
13389 +int do_spi_transfer(int nr, char* tx, int tx_len, char* rx, int rx_len,
13390 + char* txnext, int txnext_len, char* rxnext, int rxnext_len)
13392 + struct spi_transfer_list* list = spi_transfer_desc;
13394 + list->tx[0] = tx; list->txlen[0] = tx_len;
13395 + list->rx[0] = rx; list->rxlen[0] = rx_len;
13397 + list->tx[1] = txnext; list->txlen[1] = txnext_len;
13398 + list->rx[1] = rxnext; list->rxlen[1] = rxnext_len;
13400 + list->nr_transfers = nr;
13402 + return spi_transfer(list);
13405 +/* ......................................................................... */
13408 + * Poll the DataFlash device until it is READY.
13409 + */
13410 +void at91_dataflash_waitready(void)
13412 + char* command = kmalloc(2, GFP_KERNEL);
13414 + if (!command)
13415 + return;
13417 + do {
13418 + command[0] = OP_READ_STATUS;
13419 + command[1] = 0;
13421 + do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
13422 + } while ((command[1] & 0x80) == 0);
13424 + kfree(command);
13428 + * Return the status of the DataFlash device.
13429 + */
13430 +unsigned short at91_dataflash_status(void)
13432 + unsigned short status;
13433 + char* command = kmalloc(2, GFP_KERNEL);
13435 + if (!command)
13436 + return 0;
13438 + command[0] = OP_READ_STATUS;
13439 + command[1] = 0;
13441 + do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
13442 + status = command[1];
13444 + kfree(command);
13445 + return status;
13448 +/* ......................................................................... */
13451 + * Erase a block of flash.
13452 + */
13453 +int at91_dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
13455 + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
13456 + unsigned int pageaddr;
13457 + char* command;
13459 +#ifdef DEBUG_DATAFLASH
13460 + printk("dataflash_erase: addr=%i len=%i\n", instr->addr, instr->len);
13461 +#endif
13463 + /* Sanity checks */
13464 + if (instr->addr + instr->len > mtd->size)
13465 + return -EINVAL;
13466 + if ((instr->len != mtd->erasesize) || (instr->len != priv->page_size))
13467 + return -EINVAL;
13468 + if ((instr->addr % priv->page_size) != 0)
13469 + return -EINVAL;
13471 + command = kmalloc(4, GFP_KERNEL);
13472 + if (!command)
13473 + return -ENOMEM;
13475 + /* Calculate flash page address */
13476 + pageaddr = (instr->addr / priv->page_size) << priv->page_offset;
13478 + command[0] = OP_ERASE_PAGE;
13479 + command[1] = (pageaddr & 0x00FF0000) >> 16;
13480 + command[2] = (pageaddr & 0x0000FF00) >> 8;
13481 + command[3] = 0;
13482 +#ifdef DEBUG_DATAFLASH
13483 + printk("ERASE: (%x) %x %x %x [%i]\n", command[0], command[1], command[2], command[3], pageaddr);
13484 +#endif
13486 + /* Send command to SPI device */
13487 + spi_access_bus(priv->spi);
13488 + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
13490 + at91_dataflash_waitready(); /* poll status until ready */
13491 + spi_release_bus(priv->spi);
13493 + kfree(command);
13495 + /* Inform MTD subsystem that erase is complete */
13496 + instr->state = MTD_ERASE_DONE;
13497 + if (instr->callback)
13498 + instr->callback(instr);
13500 + return 0;
13504 + * Read from the DataFlash device.
13505 + * from : Start offset in flash device
13506 + * len : Amount to read
13507 + * retlen : About of data actually read
13508 + * buf : Buffer containing the data
13509 + */
13510 +int at91_dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
13512 + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
13513 + unsigned int addr;
13514 + char* command;
13516 +#ifdef DEBUG_DATAFLASH
13517 + printk("dataflash_read: %lli .. %lli\n", from, from+len);
13518 +#endif
13520 + *retlen = 0;
13522 + /* Sanity checks */
13523 + if (!len)
13524 + return 0;
13525 + if (from + len > mtd->size)
13526 + return -EINVAL;
13528 + /* Calculate flash page/byte address */
13529 + addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size);
13531 + command = kmalloc(8, GFP_KERNEL);
13532 + if (!command)
13533 + return -ENOMEM;
13535 + command[0] = OP_READ_CONTINUOUS;
13536 + command[1] = (addr & 0x00FF0000) >> 16;
13537 + command[2] = (addr & 0x0000FF00) >> 8;
13538 + command[3] = (addr & 0x000000FF);
13539 +#ifdef DEBUG_DATAFLASH
13540 + printk("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
13541 +#endif
13543 + /* Send command to SPI device */
13544 + spi_access_bus(priv->spi);
13545 + do_spi_transfer(2, command, 8, command, 8, buf, len, buf, len);
13546 + spi_release_bus(priv->spi);
13548 + *retlen = len;
13549 + kfree(command);
13550 + return 0;
13554 + * Write to the DataFlash device.
13555 + * to : Start offset in flash device
13556 + * len : Amount to write
13557 + * retlen : Amount of data actually written
13558 + * buf : Buffer containing the data
13559 + */
13560 +int at91_dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
13562 + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
13563 + unsigned int pageaddr, addr, offset, writelen;
13564 + size_t remaining;
13565 + char *writebuf;
13566 + unsigned short status;
13567 + int res = 0;
13568 + char* command;
13570 +#ifdef DEBUG_DATAFLASH
13571 + printk("dataflash_write: %lli .. %lli\n", to, to+len);
13572 +#endif
13574 + *retlen = 0;
13576 + /* Sanity checks */
13577 + if (!len)
13578 + return 0;
13579 + if (to + len > mtd->size)
13580 + return -EINVAL;
13582 + command = kmalloc(4, GFP_KERNEL);
13583 + if (!command)
13584 + return -ENOMEM;
13586 + pageaddr = ((unsigned)to / priv->page_size);
13587 + offset = ((unsigned)to % priv->page_size);
13588 + if (offset + len > priv->page_size)
13589 + writelen = priv->page_size - offset;
13590 + else
13591 + writelen = len;
13592 + writebuf = buf;
13593 + remaining = len;
13595 + /* Gain access to the SPI bus */
13596 + spi_access_bus(priv->spi);
13598 + while (remaining > 0) {
13599 +#ifdef DEBUG_DATAFLASH
13600 + printk("write @ %i:%i len=%i\n", pageaddr, offset, writelen);
13601 +#endif
13603 + /* (1) Transfer to Buffer1 */
13604 + if (writelen != priv->page_size) {
13605 + addr = pageaddr << priv->page_offset;
13606 + command[0] = OP_TRANSFER_BUF1;
13607 + command[1] = (addr & 0x00FF0000) >> 16;
13608 + command[2] = (addr & 0x0000FF00) >> 8;
13609 + command[3] = 0;
13610 +#ifdef DEBUG_DATAFLASH
13611 + printk("TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
13612 +#endif
13613 + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
13614 + at91_dataflash_waitready();
13617 + /* (2) Program via Buffer1 */
13618 + addr = (pageaddr << priv->page_offset) + offset;
13619 + command[0] = OP_PROGRAM_VIA_BUF1;
13620 + command[1] = (addr & 0x00FF0000) >> 16;
13621 + command[2] = (addr & 0x0000FF00) >> 8;
13622 + command[3] = (addr & 0x000000FF);
13623 +#ifdef DEBUG_DATAFLASH
13624 + printk("PROGRAM: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
13625 +#endif
13626 + do_spi_transfer(2, command, 4, command, 4, writebuf, writelen, writebuf, writelen);
13627 + at91_dataflash_waitready();
13629 + /* (3) Compare to Buffer1 */
13630 + addr = pageaddr << priv->page_offset;
13631 + command[0] = OP_COMPARE_BUF1;
13632 + command[1] = (addr & 0x00FF0000) >> 16;
13633 + command[2] = (addr & 0x0000FF00) >> 8;
13634 + command[3] = 0;
13635 +#ifdef DEBUG_DATAFLASH
13636 + printk("COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
13637 +#endif
13638 + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
13639 + at91_dataflash_waitready();
13641 + /* Get result of the compare operation */
13642 + status = at91_dataflash_status();
13643 + if ((status & 0x40) == 1) {
13644 + printk("at91_dataflash: Write error on page %i\n", pageaddr);
13645 + remaining = 0;
13646 + res = -EIO;
13649 + remaining = remaining - writelen;
13650 + pageaddr++;
13651 + offset = 0;
13652 + writebuf += writelen;
13653 + *retlen += writelen;
13655 + if (remaining > priv->page_size)
13656 + writelen = priv->page_size;
13657 + else
13658 + writelen = remaining;
13661 + /* Release SPI bus */
13662 + spi_release_bus(priv->spi);
13664 + kfree(command);
13665 + return res;
13668 +/* ......................................................................... */
13671 + * Initialize and register DataFlash device with MTD subsystem.
13672 + */
13673 +int add_dataflash(int channel, char *name, int size, int pagesize, int pageoffset)
13675 + struct mtd_info *device;
13676 + struct dataflash_local *priv;
13677 +#ifdef CONFIG_MTD_CMDLINE_PARTS
13678 + char mtdID[14];
13679 +#endif
13681 + if (nr_devices >= DATAFLASH_MAX_DEVICES) {
13682 + printk(KERN_ERR "at91_dataflash: Too many devices detected\n");
13683 + return 0;
13686 + device = (struct mtd_info *) kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
13687 + if (!device)
13688 + return -ENOMEM;
13689 + memset(device, 0, sizeof(struct mtd_info));
13691 + device->name = name;
13692 + device->size = size;
13693 + device->erasesize = pagesize;
13694 + device->module = THIS_MODULE;
13695 + device->type = MTD_NORFLASH;
13696 + device->flags = MTD_CAP_NORFLASH;
13697 + device->erase = at91_dataflash_erase;
13698 + device->read = at91_dataflash_read;
13699 + device->write = at91_dataflash_write;
13701 + priv = (struct dataflash_local *) kmalloc(sizeof(struct dataflash_local), GFP_KERNEL);
13702 + if (!priv) {
13703 + kfree(device);
13704 + return -ENOMEM;
13706 + memset(priv, 0, sizeof(struct dataflash_local));
13708 + priv->spi = channel;
13709 + priv->page_size = pagesize;
13710 + priv->page_offset = pageoffset;
13711 + device->priv = priv;
13713 + mtd_devices[nr_devices] = device;
13714 + nr_devices++;
13715 + printk("at91_dataflash: %s detected [spi%i] (%i bytes)\n", name, channel, size);
13717 +#ifdef CONFIG_MTD_PARTITIONS
13718 +#ifdef CONFIG_MTD_CMDLINE_PARTS
13719 + sprintf(mtdID, "dataflash%i", nr_devices-1);
13720 + mtd_parts_nr = parse_cmdline_partitions(device, &mtd_parts, mtdID);
13721 +#endif
13722 + if (mtd_parts_nr <= 0) {
13723 + mtd_parts = static_partitions;
13724 + mtd_parts_nr = NB_OF(static_partitions);
13727 + return add_mtd_partitions(device, mtd_parts, mtd_parts_nr);
13728 +#else
13729 + return add_mtd_device(device);
13730 +#endif
13734 + * Detect and initialize DataFlash device connected to specified SPI channel.
13735 + */
13736 +int at91_dataflash_detect(int channel)
13738 + int res = 0;
13739 + unsigned short status;
13741 + spi_access_bus(channel);
13742 + status = at91_dataflash_status();
13743 + if (status != 0xff) { /* no dataflash device there */
13744 + switch (status & 0x3c) {
13745 + case 0x2c: /* 1 0 1 1 */
13746 + res = add_dataflash(channel, "Atmel AT45DB161B", 4096*528, 528, 10);
13747 + break;
13748 + case 0x34: /* 1 1 0 1 */
13749 + res = add_dataflash(channel, "Atmel AT45DB321B", 8192*528, 528, 10);
13750 + break;
13751 + case 0x3c: /* 1 1 1 1 */
13752 + res = add_dataflash(channel, "Atmel AT45DB642", 8192*1056, 1056, 11);
13753 + break;
13754 + default:
13755 + printk(KERN_ERR "at91_dataflash: Unknown device (%x)\n", status & 0x3c);
13758 + spi_release_bus(channel);
13760 + return res;
13763 +int __init at91_dataflash_init(void)
13765 + spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
13766 + if (!spi_transfer_desc)
13767 + return -ENOMEM;
13769 + /* DataFlash (SPI chip select 0) */
13770 + at91_dataflash_detect(0);
13772 +#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
13773 + /* DataFlash card (SPI chip select 3) */
13774 + AT91_CfgPIO_DataFlashCard();
13775 + at91_dataflash_detect(3);
13776 +#endif
13778 + return 0;
13781 +void __exit at91_dataflash_exit(void)
13783 + int i;
13785 + for (i = 0; i < DATAFLASH_MAX_DEVICES; i++) {
13786 + if (mtd_devices[i]) {
13787 +#ifdef CONFIG_MTD_PARTITIONS
13788 + del_mtd_partitions(mtd_devices[i]);
13789 +#else
13790 + del_mtd_device(mtd_devices[i]);
13791 +#endif
13792 + kfree(mtd_devices[i]->priv);
13793 + kfree(mtd_devices[i]);
13796 + nr_devices = 0;
13797 + kfree(spi_transfer_desc);
13801 +EXPORT_NO_SYMBOLS;
13803 +module_init(at91_dataflash_init);
13804 +module_exit(at91_dataflash_exit);
13806 +MODULE_LICENSE("GPL")
13807 +MODULE_AUTHOR("Andrew Victor")
13808 +MODULE_DESCRIPTION("DataFlash driver for Atmel AT91RM9200")
13809 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
13810 +++ linux-2.4.25/drivers/at91/mtd/at91_dataflash.h 2004-03-31 17:15:09.000000000 +0200
13811 @@ -0,0 +1,42 @@
13813 + * Atmel DataFlash driver for the Atmel AT91RM9200 (Thunder)
13815 + * (c) SAN People (Pty) Ltd
13817 + * This program is free software; you can redistribute it and/or
13818 + * modify it under the terms of the GNU General Public License
13819 + * as published by the Free Software Foundation; either version
13820 + * 2 of the License, or (at your option) any later version.
13821 + */
13823 +#ifndef AT91_DATAFLASH_H
13824 +#define AT91_DATAFLASH_H
13826 +#define DATAFLASH_MAX_DEVICES 4 /* max number of dataflash devices */
13828 +#define OP_READ_CONTINUOUS 0xE8
13829 +#define OP_READ_PAGE 0xD2
13830 +#define OP_READ_BUFFER1 0xD4
13831 +#define OP_READ_BUFFER2 0xD6
13832 +#define OP_READ_STATUS 0xD7
13834 +#define OP_ERASE_PAGE 0x81
13835 +#define OP_ERASE_BLOCK 0x50
13837 +#define OP_TRANSFER_BUF1 0x53
13838 +#define OP_TRANSFER_BUF2 0x55
13839 +#define OP_COMPARE_BUF1 0x60
13840 +#define OP_COMPARE_BUF2 0x61
13842 +#define OP_PROGRAM_VIA_BUF1 0x82
13843 +#define OP_PROGRAM_VIA_BUF2 0x85
13845 +struct dataflash_local
13847 + int spi; /* SPI chip-select number */
13849 + unsigned int page_size; /* number of bytes per page */
13850 + unsigned short page_offset; /* page offset in flash address */
13853 +#endif
13854 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
13855 +++ linux-2.4.25/drivers/at91/mtd/at91_nand.c 2004-03-31 17:15:09.000000000 +0200
13856 @@ -0,0 +1,328 @@
13858 + * drivers/at91/mtd/at91_nand.c
13860 + * Copyright (c) 2003 Rick Bronson
13862 + * Derived from drivers/mtd/nand/autcpu12.c
13863 + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
13865 + * Derived from drivers/mtd/spia.c
13866 + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
13868 + * This program is free software; you can redistribute it and/or modify
13869 + * it under the terms of the GNU General Public License version 2 as
13870 + * published by the Free Software Foundation.
13872 + */
13874 +#include <linux/slab.h>
13875 +#include <linux/module.h>
13876 +#include <linux/mtd/mtd.h>
13877 +#include <linux/mtd/nand.h>
13878 +#include <linux/mtd/partitions.h>
13879 +#include <asm/io.h>
13880 +#include <asm/arch/hardware.h>
13881 +#include <asm/sizes.h>
13883 +#include <asm/arch/pio.h>
13884 +#include "at91_nand.h"
13887 + * MTD structure for AT91 board
13888 + */
13889 +static struct mtd_info *at91_mtd = NULL;
13890 +static struct nand_chip *my_nand_chip = NULL;
13892 +static int at91_fio_base;
13894 +#ifdef CONFIG_MTD_PARTITIONS
13897 + * Define partitions for flash devices
13898 + */
13900 +static struct mtd_partition partition_info32k[] = {
13901 + { name: "AT91 NAND partition 1, kernel",
13902 + offset: 0,
13903 + size: 1 * SZ_1M },
13904 + { name: "AT91 NAND partition 2, filesystem",
13905 + offset: 1 * SZ_1M,
13906 + size: 16 * SZ_1M },
13907 + { name: "AT91 NAND partition 3a, storage",
13908 + offset: (1 * SZ_1M) + (16 * SZ_1M),
13909 + size: 1 * SZ_1M },
13910 + { name: "AT91 NAND partition 3b, storage",
13911 + offset: (2 * SZ_1M) + (16 * SZ_1M),
13912 + size: 1 * SZ_1M },
13913 + { name: "AT91 NAND partition 3c, storage",
13914 + offset: (3 * SZ_1M) + (16 * SZ_1M),
13915 + size: 1 * SZ_1M },
13916 + { name: "AT91 NAND partition 3d, storage",
13917 + offset: (4 * SZ_1M) + (16 * SZ_1M),
13918 + size: 1 * SZ_1M },
13921 +static struct mtd_partition partition_info64k[] = {
13922 + { name: "AT91 NAND partition 1, kernel",
13923 + offset: 0,
13924 + size: 1 * SZ_1M },
13925 + { name: "AT91 NAND partition 2, filesystem",
13926 + offset: 1 * SZ_1M,
13927 + size: 16 * SZ_1M },
13928 + { name: "AT91 NAND partition 3, storage",
13929 + offset: (1 * SZ_1M) + (16 * SZ_1M),
13930 + size: 47 * SZ_1M },
13933 +#endif
13936 + * Hardware specific access to control-lines
13937 + */
13938 +static void at91_hwcontrol(int cmd)
13940 + struct nand_chip *my_nand = my_nand_chip;
13941 + switch(cmd)
13943 + case NAND_CTL_SETCLE:
13944 + my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_CLE;
13945 + break;
13946 + case NAND_CTL_CLRCLE:
13947 + my_nand->IO_ADDR_W = at91_fio_base;
13948 + break;
13949 + case NAND_CTL_SETALE:
13950 + my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_ALE;
13951 + break;
13952 + case NAND_CTL_CLRALE:
13953 + my_nand->IO_ADDR_W = at91_fio_base;
13954 + break;
13955 + case NAND_CTL_SETNCE:
13956 + break;
13957 + case NAND_CTL_CLRNCE:
13958 + break;
13963 + * Send command to NAND device
13964 + */
13965 +static void at91_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
13967 + register struct nand_chip *my_nand = mtd->priv;
13969 + /* Begin command latch cycle */
13970 + register unsigned long NAND_IO_ADDR = my_nand->IO_ADDR_W + AT91_SMART_MEDIA_CLE;
13972 + /*
13973 + * Write out the command to the device.
13974 + */
13975 + if (command != NAND_CMD_SEQIN)
13976 + writeb (command, NAND_IO_ADDR);
13977 + else {
13978 + if (mtd->oobblock == 256 && column >= 256) {
13979 + column -= 256;
13980 + writeb (NAND_CMD_RESET, NAND_IO_ADDR);
13981 + writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
13982 + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
13984 + else
13985 + if (mtd->oobblock == 512 && column >= 256) {
13986 + if (column < 512) {
13987 + column -= 256;
13988 + writeb (NAND_CMD_READ1, NAND_IO_ADDR);
13989 + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
13990 + } else {
13991 + column -= 512;
13992 + writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
13993 + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
13995 + } else {
13996 + writeb (NAND_CMD_READ0, NAND_IO_ADDR);
13997 + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
14001 + /* Set ALE and clear CLE to start address cycle */
14002 + NAND_IO_ADDR = at91_fio_base;
14004 + if (column != -1 || page_addr != -1)
14005 + NAND_IO_ADDR += AT91_SMART_MEDIA_ALE;
14007 + /* Serially input address */
14008 + if (column != -1)
14009 + writeb (column, NAND_IO_ADDR);
14010 + if (page_addr != -1) {
14011 + writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR);
14012 + writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR);
14013 + /* One more address cycle for higher density devices */
14014 + if (mtd->size & 0x0c000000) {
14015 + writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR);
14019 + /* wait until command is processed */
14020 + while (!my_nand->dev_ready())
14025 + * Read the Device Ready pin.
14026 + */
14027 +static int at91_device_ready(void)
14029 + return AT91_PIO_SmartMedia_RDY();
14032 + * Main initialization routine
14033 + */
14034 +static int __init at91_init (void)
14036 + struct nand_chip *my_nand;
14037 + int err = 0;
14039 + /* Allocate memory for MTD device structure and private data */
14040 + at91_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
14041 + if (!at91_mtd) {
14042 + printk ("Unable to allocate AT91 NAND MTD device structure.\n");
14043 + err = -ENOMEM;
14044 + goto out;
14047 + /* map physical adress */
14048 + at91_fio_base = (unsigned long) ioremap(AT91_SMARTMEDIA_BASE, SZ_8M);
14049 + if(!at91_fio_base) {
14050 + printk("ioremap AT91 NAND failed\n");
14051 + err = -EIO;
14052 + goto out_mtd;
14055 + /* Get pointer to private data */
14056 + my_nand_chip = my_nand = (struct nand_chip *) (&at91_mtd[1]);
14058 + /* Initialize structures */
14059 + memset((char *) at91_mtd, 0, sizeof(struct mtd_info));
14060 + memset((char *) my_nand, 0, sizeof(struct nand_chip));
14062 + /* Link the private data with the MTD structure */
14063 + at91_mtd->priv = my_nand;
14065 + /* Set address of NAND IO lines */
14066 + my_nand->IO_ADDR_R = at91_fio_base;
14067 + my_nand->IO_ADDR_W = at91_fio_base;
14068 + my_nand->hwcontrol = at91_hwcontrol;
14069 + my_nand->dev_ready = at91_device_ready;
14070 + my_nand->cmdfunc = at91_nand_command; /* we need our own */
14071 + my_nand->eccmode = NAND_ECC_SOFT; /* enable ECC */
14072 + /* 20 us command delay time */
14073 + my_nand->chip_delay = 20;
14075 + /* Setup Smart Media, first enable the address range of CS3 */
14076 + AT91_SYS->EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia;
14077 + /* set the bus interface characteristics based on
14078 + tDS Data Set up Time 30 - ns
14079 + tDH Data Hold Time 20 - ns
14080 + tALS ALE Set up Time 20 - ns
14081 + 16ns at 60 MHz ~= 3 */
14082 +#define AT91C_SM_ID_RWH (5 << 28) /* orig = 5 */
14083 +#define AT91C_SM_RWH (1 << 28) /* orig = 1 */
14084 +#define AT91C_SM_RWS (0 << 24) /* orig = 0 */
14085 +#define AT91C_SM_TDF (1 << 8) /* orig = 1 */
14086 +#define AT91C_SM_NWS (5) /* orig = 3 */
14087 + AT91_SYS->EBI_SMC2_CSR[3] = ( AT91C_SM_RWH | AT91C_SM_RWS |
14088 + AT91C_SMC2_ACSS_STANDARD |
14089 + AT91C_SMC2_DBW_8 | AT91C_SM_TDF |
14090 + AT91C_SMC2_WSEN | AT91C_SM_NWS);
14092 + AT91_CfgPIO_SmartMedia();
14094 + if (AT91_PIO_SmartMedia_CardDetect())
14095 + printk ("No ");
14096 + printk ("SmartMedia card inserted.\n");
14098 + /* Scan to find existance of the device */
14099 + if (nand_scan (at91_mtd)) {
14100 + err = -ENXIO;
14101 + goto out_ior;
14104 + /* Allocate memory for internal data buffer */
14105 + my_nand->data_buf = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
14106 + if (!my_nand->data_buf) {
14107 + printk ("Unable to allocate AT91 NAND data buffer.\n");
14108 + err = -ENOMEM;
14109 + goto out_ior;
14112 + /* Allocate memory for internal data buffer */
14113 + my_nand->data_cache = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
14114 + if (!my_nand->data_cache) {
14115 + printk ("Unable to allocate AT91 NAND data cache.\n");
14116 + err = -ENOMEM;
14117 + goto out_buf;
14119 + my_nand->cache_page = -1;
14121 +#ifdef CONFIG_MTD_PARTITIONS
14122 + /* Register the partitions */
14123 + switch(at91_mtd->size)
14125 + case SZ_32M:
14126 + err = add_mtd_partitions(at91_mtd, partition_info32k,
14127 + ARRAY_SIZE (partition_info32k));
14128 + break;
14129 + case SZ_64M:
14130 + err = add_mtd_partitions(at91_mtd, partition_info64k,
14131 + ARRAY_SIZE (partition_info64k));
14132 + break;
14133 + default:
14134 + printk ("Unsupported SmartMedia device\n");
14135 + err = -ENXIO;
14136 + goto out_cac;
14138 +#else
14139 + err = add_mtd_device(at91_mtd);
14140 +#endif
14141 + goto out;
14143 + out_cac:
14144 + kfree (my_nand->data_cache);
14145 + out_buf:
14146 + kfree (my_nand->data_buf);
14147 + out_ior:
14148 + iounmap((void *)at91_fio_base);
14149 + out_mtd:
14150 + kfree (at91_mtd);
14151 + out:
14152 + return err;
14156 + * Clean up routine
14157 + */
14158 +static void __exit at91_cleanup (void)
14160 + struct nand_chip *my_nand = (struct nand_chip *) &at91_mtd[1];
14162 + /* Unregister partitions */
14163 + del_mtd_partitions(at91_mtd);
14165 + /* Unregister the device */
14166 + del_mtd_device (at91_mtd);
14168 + /* Free internal data buffers */
14169 + kfree (my_nand->data_buf);
14170 + kfree (my_nand->data_cache);
14172 + /* unmap physical adress */
14173 + iounmap((void *)at91_fio_base);
14175 + /* Free the MTD device structure */
14176 + kfree (at91_mtd);
14179 +module_init(at91_init);
14180 +module_exit(at91_cleanup);
14182 +MODULE_LICENSE("GPL");
14183 +MODULE_AUTHOR("Rick Bronson");
14184 +MODULE_DESCRIPTION("Glue layer for SmartMediaCard on ATMEL AT91RM9200");
14185 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
14186 +++ linux-2.4.25/drivers/at91/mtd/at91_nand.h 2004-03-31 17:15:09.000000000 +0200
14187 @@ -0,0 +1,27 @@
14189 + * AT91RM9200 specific NAND (SmartMedia) defines
14191 + * (c) 2003 Rick Bronson
14193 + * This program is free software; you can redistribute it and/or modify
14194 + * it under the terms of the GNU General Public License as published by
14195 + * the Free Software Foundation; either version 2 of the License, or
14196 + * (at your option) any later version.
14198 + * This program is distributed in the hope that it will be useful,
14199 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14200 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14201 + * GNU General Public License for more details.
14203 + * You should have received a copy of the GNU General Public License
14204 + * along with this program; if not, write to the Free Software
14205 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14206 + */
14208 +#ifndef __AT91_NAND_H
14209 +#define __AT91_NAND_H
14211 +#define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */
14212 +#define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */
14214 +#endif
14215 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
14216 +++ linux-2.4.25/drivers/at91/net/Makefile 2004-03-31 17:15:09.000000000 +0200
14217 @@ -0,0 +1,15 @@
14218 +# File: drivers/at91/net/Makefile
14220 +# Makefile for the Atmel AT91RM9200 ethernet device drivers
14223 +O_TARGET := at91net.o
14225 +obj-y :=
14226 +obj-m :=
14227 +obj-n :=
14228 +obj- :=
14230 +obj-$(CONFIG_AT91_ETHER) += at91_ether.o
14232 +include $(TOPDIR)/Rules.make
14233 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
14234 +++ linux-2.4.25/drivers/at91/net/at91_ether.c 2004-03-31 17:15:09.000000000 +0200
14235 @@ -0,0 +1,877 @@
14237 + * Ethernet driver for the Atmel AT91RM9200 (Thunder)
14239 + * (c) SAN People (Pty) Ltd
14241 + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
14242 + * Initial version by Rick Bronson 01/11/2003
14244 + * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
14245 + * (Polaroid Corporation)
14247 + * This program is free software; you can redistribute it and/or
14248 + * modify it under the terms of the GNU General Public License
14249 + * as published by the Free Software Foundation; either version
14250 + * 2 of the License, or (at your option) any later version.
14251 + */
14253 +#include <linux/module.h>
14254 +#include <linux/init.h>
14255 +#include <linux/config.h>
14256 +#include <linux/mii.h>
14257 +#include <linux/netdevice.h>
14258 +#include <linux/etherdevice.h>
14259 +#include <linux/skbuff.h>
14260 +#include <asm/io.h>
14261 +#include <linux/pci.h>
14262 +#include <linux/crc32.h>
14263 +#include <asm/uaccess.h>
14264 +#include <linux/ethtool.h>
14266 +#include <asm/arch/AT91RM9200_EMAC.h>
14267 +#include <asm/arch/pio.h>
14268 +#include "at91_ether.h"
14270 +static struct net_device at91_dev;
14272 +/* ........................... PHY INTERFACE ........................... */
14275 + * Enable the MDIO bit in MAC control register
14276 + * When not called from an interrupt-handler, access to the PHY must be
14277 + * protected by a spinlock.
14278 + */
14279 +static void enable_mdi(AT91PS_EMAC regs)
14281 + regs->EMAC_CTL |= AT91C_EMAC_MPE; /* enable management port */
14285 + * Disable the MDIO bit in the MAC control register
14286 + */
14287 +static void disable_mdi(AT91PS_EMAC regs)
14289 + regs->EMAC_CTL &= ~AT91C_EMAC_MPE; /* disable management port */
14293 + * Write value to the a PHY register
14294 + * Note: MDI interface is assumed to already have been enabled.
14295 + */
14296 +static void write_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int value)
14298 + regs->EMAC_MAN = (AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W
14299 + | ((phy_addr & 0x1f) << 23) | (address << 18)) + (value & 0xffff);
14301 + /* Wait until IDLE bit in Network Status register is cleared */
14302 + // TODO: Enforce some maximum loop-count?
14303 + while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
14307 + * Read value stored in a PHY register.
14308 + * Note: MDI interface is assumed to already have been enabled.
14309 + */
14310 +static void read_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int *value)
14312 + regs->EMAC_MAN = AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_R
14313 + | ((phy_addr & 0x1f) << 23) | (address << 18);
14315 + /* Wait until IDLE bit in Network Status register is cleared */
14316 + // TODO: Enforce some maximum loop-count?
14317 + while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
14319 + *value = (regs->EMAC_MAN & 0x0000ffff);
14322 +/* ........................... PHY MANAGEMENT .......................... */
14325 + * Access the PHY to determine the current Link speed and Mode, and update the
14326 + * MAC accordingly.
14327 + * If no link or auto-negotiation is busy, then no changes are made.
14328 + * Returns: 0 : OK
14329 + * -1 : No link
14330 + * -2 : AutoNegotiation still in progress
14331 + */
14332 +static int update_linkspeed(struct net_device *dev, AT91PS_EMAC regs) {
14333 + unsigned int bmsr, bmcr, lpa, mac_cfg;
14334 + unsigned int speed, duplex;
14336 + /* Link status is latched, so read twice to get current value */
14337 + read_phy(regs, 0, MII_BMSR, &bmsr);
14338 + read_phy(regs, 0, MII_BMSR, &bmsr);
14339 + if (!(bmsr & BMSR_LSTATUS)) return -1; /* no link */
14341 + read_phy(regs, 0, MII_BMCR, &bmcr);
14342 + if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
14343 + if (!(bmsr & BMSR_ANEGCOMPLETE)) return -2; /* auto-negotitation in progress */
14345 + read_phy(regs, 0, MII_LPA, &lpa);
14346 + if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
14347 + else speed = SPEED_10;
14348 + if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
14349 + else duplex = DUPLEX_HALF;
14350 + } else {
14351 + speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
14352 + duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
14355 + /* Update the MAC */
14356 + mac_cfg = regs->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
14357 + if (speed == SPEED_100) {
14358 + if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
14359 + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD | AT91C_EMAC_FD;
14360 + else /* 100 Half Duplex */
14361 + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD;
14362 + } else {
14363 + if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
14364 + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_FD;
14365 + else /* 10 Half Duplex */
14366 + regs->EMAC_CFG = mac_cfg;
14369 + printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
14370 + return 0;
14374 + * Handle interrupts from the PHY
14375 + */
14376 +static void at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
14378 + struct net_device *dev = (struct net_device *) dev_id;
14379 + struct at91_private *lp = (struct at91_private *) dev->priv;
14380 + AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
14381 + int status;
14382 + unsigned int phy;
14384 + enable_mdi(emac);
14385 + if (lp->phy_type == MII_DM9161_ID)
14386 + read_phy(emac, 0, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
14387 + else if (lp->phy_type == MII_LXT971A_ID)
14388 + read_phy(emac, 0, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
14390 + status = AT91_SYS->PIOC_ISR; /* acknowledge interrupt in PIO */
14392 + status = update_linkspeed(dev, emac);
14393 + if (status == -1) { /* link is down */
14394 + netif_carrier_off(dev);
14395 + printk(KERN_INFO "%s: Link down.\n", dev->name);
14396 + } else if (status == -2) { /* auto-negotiation in progress */
14397 + /* Do nothing - another interrupt generated when negotiation complete */
14398 + } else { /* link is operational */
14399 + netif_carrier_on(dev);
14401 + disable_mdi(emac);
14405 + * Initialize and enable the PHY interrupt when link-state changes
14406 + */
14407 +static void enable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
14409 + struct at91_private *lp = (struct at91_private *) dev->priv;
14410 + unsigned int dsintr, status;
14412 + // TODO: Check error code. Really need a generic PIO (interrupt)
14413 + // layer since we're really only interested in the PC4 (DK) or PC2 (CSB337) line.
14414 + (void) request_irq(AT91C_ID_PIOC, at91ether_phy_interrupt, 0, dev->name, dev);
14416 + status = AT91_SYS->PIOC_ISR; /* clear any pending PIO interrupts */
14417 +#ifdef CONFIG_MACH_CSB337
14418 + AT91_SYS->PIOC_IER = AT91C_PIO_PC2; /* Enable interrupt */
14419 +#else
14420 + AT91_SYS->PIOC_IER = AT91C_PIO_PC4; /* Enable interrupt */
14421 +#endif
14423 + spin_lock_irq(&lp->lock);
14424 + enable_mdi(regs);
14426 + if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
14427 + read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
14428 + dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
14429 + write_phy(regs, 0, MII_DSINTR_REG, dsintr);
14431 + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
14432 + read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
14433 + dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
14434 + write_phy(regs, 0, MII_ISINTE_REG, dsintr);
14437 + disable_mdi(regs);
14438 + spin_unlock_irq(&lp->lock);
14442 + * Disable the PHY interrupt
14443 + */
14444 +static void disable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
14446 + struct at91_private *lp = (struct at91_private *) dev->priv;
14447 + unsigned int dsintr;
14449 + spin_lock_irq(&lp->lock);
14450 + enable_mdi(regs);
14452 + if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
14453 + read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
14454 + dsintr = dsintr | 0xf00; /* set bits 8..11 */
14455 + write_phy(regs, 0, MII_DSINTR_REG, dsintr);
14457 + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
14458 + read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
14459 + dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
14460 + write_phy(regs, 0, MII_ISINTE_REG, dsintr);
14463 + disable_mdi(regs);
14464 + spin_unlock_irq(&lp->lock);
14466 +#ifdef CONFIG_MACH_CSB337
14467 + AT91_SYS->PIOC_IDR = AT91C_PIO_PC2; /* Disable interrupt */
14468 +#else
14469 + AT91_SYS->PIOC_IDR = AT91C_PIO_PC4; /* Disable interrupt */
14470 +#endif
14471 + free_irq(AT91C_ID_PIOC, dev); /* Free interrupt handler */
14475 + * Perform a software reset of the PHY.
14476 + */
14477 +static void reset_phy(struct net_device *dev, AT91PS_EMAC regs)
14479 + struct at91_private *lp = (struct at91_private *) dev->priv;
14480 + unsigned int bmcr;
14482 + spin_lock_irq(&lp->lock);
14483 + enable_mdi(regs);
14485 + /* Perform PHY reset */
14486 + write_phy(regs, 0, MII_BMCR, BMCR_RESET);
14488 + /* Wait until PHY reset is complete */
14489 + do {
14490 + read_phy(regs, 0, MII_BMCR, &bmcr);
14491 + } while (!(bmcr && BMCR_RESET));
14493 + disable_mdi(regs);
14494 + spin_unlock_irq(&lp->lock);
14498 +/* ......................... ADDRESS MANAGEMENT ........................ */
14501 + * Set the ethernet MAC address in dev->dev_addr
14502 + */
14503 +static void get_mac_address(struct net_device *dev) {
14504 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14505 + char addr[6];
14506 + unsigned int hi, lo;
14508 + /* Check if bootloader set address in Specific-Address 1 */
14509 + hi = regs->EMAC_SA1H;
14510 + lo = regs->EMAC_SA1L;
14511 + addr[0] = (lo & 0xff);
14512 + addr[1] = (lo & 0xff00) >> 8;
14513 + addr[2] = (lo & 0xff0000) >> 16;
14514 + addr[3] = (lo & 0xff000000) >> 24;
14515 + addr[4] = (hi & 0xff);
14516 + addr[5] = (hi & 0xff00) >> 8;
14518 + if (is_valid_ether_addr(addr)) {
14519 + memcpy(dev->dev_addr, &addr, 6);
14520 + return;
14523 + /* Check if bootloader set address in Specific-Address 2 */
14524 + hi = regs->EMAC_SA2H;
14525 + lo = regs->EMAC_SA2L;
14526 + addr[0] = (lo & 0xff);
14527 + addr[1] = (lo & 0xff00) >> 8;
14528 + addr[2] = (lo & 0xff0000) >> 16;
14529 + addr[3] = (lo & 0xff000000) >> 24;
14530 + addr[4] = (hi & 0xff);
14531 + addr[5] = (hi & 0xff00) >> 8;
14533 + if (is_valid_ether_addr(addr)) {
14534 + memcpy(dev->dev_addr, &addr, 6);
14535 + return;
14540 + * Program the hardware MAC address from dev->dev_addr.
14541 + */
14542 +static void update_mac_address(struct net_device *dev)
14544 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14546 + regs->EMAC_SA1L = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]);
14547 + regs->EMAC_SA1H = (dev->dev_addr[5] << 8) | (dev->dev_addr[4]);
14550 +#ifdef AT91_ETHER_ADDR_CONFIGURABLE
14552 + * Store the new hardware address in dev->dev_addr, and update the MAC.
14553 + */
14554 +static int set_mac_address(struct net_device *dev, void* addr)
14556 + struct sockaddr *address = addr;
14558 + if (!is_valid_ether_addr(address->sa_data))
14559 + return -EADDRNOTAVAIL;
14561 + memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
14562 + update_mac_address(dev);
14564 + printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
14565 + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
14566 + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
14568 + return 0;
14570 +#endif
14573 + * Add multicast addresses to the internal multicast-hash table.
14574 + */
14575 +static void at91ether_sethashtable(struct net_device *dev, AT91PS_EMAC regs)
14577 + struct dev_mc_list *curr;
14578 + unsigned char mc_filter[2];
14579 + unsigned int i, bitnr;
14581 + mc_filter[0] = mc_filter[1] = 0;
14583 + curr = dev->mc_list;
14584 + for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
14585 + if (!curr) break; /* unexpected end of list */
14587 + bitnr = ether_crc(ETH_ALEN, curr->dmi_addr) >> 26;
14588 + mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
14591 + regs->EMAC_HSH = mc_filter[1];
14592 + regs->EMAC_HSL = mc_filter[0];
14596 + * Enable/Disable promiscuous and multicast modes.
14597 + */
14598 +static void at91ether_set_rx_mode(struct net_device *dev)
14600 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14602 + if (dev->flags & IFF_PROMISC) { /* Enable promiscuous mode */
14603 + regs->EMAC_CFG |= AT91C_EMAC_CAF;
14604 + } else if (dev->flags & (~IFF_PROMISC)) { /* Disable promiscuous mode */
14605 + regs->EMAC_CFG &= ~AT91C_EMAC_CAF;
14608 + if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
14609 + regs->EMAC_HSH = -1;
14610 + regs->EMAC_HSL = -1;
14611 + regs->EMAC_CFG |= AT91C_EMAC_MTI;
14612 + } else if (dev->mc_count > 0) { /* Enable specific multicasts */
14613 + at91ether_sethashtable(dev, regs);
14614 + regs->EMAC_CFG |= AT91C_EMAC_MTI;
14615 + } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
14616 + regs->EMAC_HSH = 0;
14617 + regs->EMAC_HSL = 0;
14618 + regs->EMAC_CFG &= ~AT91C_EMAC_MTI;
14622 +/* ............................... IOCTL ............................... */
14624 +static int mdio_read(struct net_device *dev, int phy_id, int location)
14626 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14627 + unsigned int value;
14629 + read_phy(regs, phy_id, location, &value);
14630 + return value;
14633 +static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
14635 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14637 + write_phy(regs, phy_id, location, value);
14641 + * ethtool support.
14642 + */
14643 +static int at91ether_ethtool_ioctl (struct net_device *dev, void *useraddr)
14645 + struct at91_private *lp = (struct at91_private *) dev->priv;
14646 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14647 + u32 ethcmd;
14648 + int res = 0;
14650 + if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
14651 + return -EFAULT;
14653 + spin_lock_irq(&lp->lock);
14654 + enable_mdi(regs);
14656 + switch (ethcmd) {
14657 + case ETHTOOL_GSET: {
14658 + struct ethtool_cmd ecmd = { ETHTOOL_GSET };
14659 + res = mii_ethtool_gset(&lp->mii, &ecmd);
14660 + if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
14661 + ecmd.supported = SUPPORTED_FIBRE;
14662 + ecmd.port = PORT_FIBRE;
14664 + if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
14665 + res = -EFAULT;
14666 + break;
14668 + case ETHTOOL_SSET: {
14669 + struct ethtool_cmd ecmd;
14670 + if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
14671 + res = -EFAULT;
14672 + else
14673 + res = mii_ethtool_sset(&lp->mii, &ecmd);
14674 + break;
14676 + case ETHTOOL_NWAY_RST: {
14677 + res = mii_nway_restart(&lp->mii);
14678 + break;
14680 + case ETHTOOL_GLINK: {
14681 + struct ethtool_value edata = { ETHTOOL_GLINK };
14682 + edata.data = mii_link_ok(&lp->mii);
14683 + if (copy_to_user(useraddr, &edata, sizeof(edata)))
14684 + res = -EFAULT;
14685 + break;
14687 + default:
14688 + res = -EOPNOTSUPP;
14691 + disable_mdi(regs);
14692 + spin_unlock_irq(&lp->lock);
14694 + return res;
14698 + * User-space ioctl interface.
14699 + */
14700 +static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
14702 + switch(cmd) {
14703 + case SIOCETHTOOL:
14704 + return at91ether_ethtool_ioctl(dev, (void *) rq->ifr_data);
14705 + default:
14706 + return -EOPNOTSUPP;
14710 +/* ................................ MAC ................................ */
14713 + * Initialize and start the Receiver and Transmit subsystems
14714 + */
14715 +static void at91ether_start(struct net_device *dev)
14717 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14718 + struct at91_private *lp = (struct at91_private *) dev->priv;
14719 + int i;
14720 + struct recv_desc_bufs *dlist, *dlist_phys;
14722 + dlist = lp->dlist;
14723 + dlist_phys = lp->dlist_phys;
14725 + for (i = 0; i < MAX_RX_DESCR; i++) {
14726 + dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
14727 + dlist->descriptors[i].size = 0;
14730 + /* Set the Wrap bit on the last descriptor */
14731 + dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
14733 + /* Reset buffer index */
14734 + lp->rxBuffIndex = 0;
14736 + /* Program address of descriptor list in Rx Buffer Queue register */
14737 + regs->EMAC_RBQP = (AT91_REG) dlist_phys;
14739 + /* Enable Receive and Transmit */
14740 + regs->EMAC_CTL |= (AT91C_EMAC_RE | AT91C_EMAC_TE);
14744 + * Open the ethernet interface
14745 + */
14746 +static int at91ether_open(struct net_device *dev)
14748 + struct at91_private *lp = (struct at91_private *) dev->priv;
14749 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14751 + if (!is_valid_ether_addr(dev->dev_addr))
14752 + return -EADDRNOTAVAIL;
14754 + AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Re-enable Peripheral clock */
14755 + regs->EMAC_CTL |= AT91C_EMAC_CSR; /* Clear internal statistics */
14757 + /* Enable PHY interrupt */
14758 + enable_phyirq(dev, regs);
14760 + /* Enable MAC interrupts */
14761 + regs->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
14762 + | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
14763 + | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
14765 + /* Determine current link speed */
14766 + spin_lock_irq(&lp->lock);
14767 + enable_mdi(regs);
14768 + (void) update_linkspeed(dev, regs);
14769 + disable_mdi(regs);
14770 + spin_unlock_irq(&lp->lock);
14772 + at91ether_start(dev);
14773 + netif_start_queue(dev);
14774 + return 0;
14778 + * Close the interface
14779 + */
14780 +static int at91ether_close(struct net_device *dev)
14782 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14784 + /* Disable Receiver and Transmitter */
14785 + regs->EMAC_CTL &= ~(AT91C_EMAC_TE | AT91C_EMAC_RE);
14787 + /* Disable PHY interrupt */
14788 + disable_phyirq(dev, regs);
14790 + /* Disable MAC interrupts */
14791 + regs->EMAC_IDR = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
14792 + | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
14793 + | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
14795 + netif_stop_queue(dev);
14797 + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
14799 + return 0;
14803 + * Transmit packet.
14804 + */
14805 +static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
14807 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14808 + struct at91_private *lp = (struct at91_private *) dev->priv;
14810 + if (regs->EMAC_TSR & AT91C_EMAC_BNQ) {
14811 + netif_stop_queue(dev);
14813 + /* Store packet information (to free when Tx completed) */
14814 + lp->skb = skb;
14815 + lp->skb_length = skb->len;
14816 + lp->skb_physaddr = pci_map_single(NULL, skb->data, skb->len, PCI_DMA_TODEVICE);
14817 + lp->stats.tx_bytes += skb->len;
14819 + /* Set address of the data in the Transmit Address register */
14820 + regs->EMAC_TAR = lp->skb_physaddr;
14821 + /* Set length of the packet in the Transmit Control register */
14822 + regs->EMAC_TCR = skb->len;
14824 + dev->trans_start = jiffies;
14825 + } else {
14826 + printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n");
14827 + return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
14828 + on this skb, he also reports -ENETDOWN and printk's, so either
14829 + we free and return(0) or don't free and return 1 */
14832 + return 0;
14836 + * Update the current statistics from the internal statistics registers.
14837 + */
14838 +static struct net_device_stats *at91ether_stats(struct net_device *dev)
14840 + struct at91_private *lp = (struct at91_private *) dev->priv;
14841 + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
14842 + int ale, lenerr, seqe, lcol, ecol;
14844 + if (netif_running(dev)) {
14845 + lp->stats.rx_packets += regs->EMAC_OK; /* Good frames received */
14846 + ale = regs->EMAC_ALE;
14847 + lp->stats.rx_frame_errors += ale; /* Alignment errors */
14848 + lenerr = regs->EMAC_ELR + regs->EMAC_USF;
14849 + lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
14850 + seqe = regs->EMAC_SEQE;
14851 + lp->stats.rx_crc_errors += seqe; /* CRC error */
14852 + lp->stats.rx_fifo_errors += regs->EMAC_DRFC; /* Receive buffer not available */
14853 + lp->stats.rx_errors += (ale + lenerr + seqe + regs->EMAC_CDE + regs->EMAC_RJB);
14855 + lp->stats.tx_packets += regs->EMAC_FRA; /* Frames successfully transmitted */
14856 + lp->stats.tx_fifo_errors += regs->EMAC_TUE; /* Transmit FIFO underruns */
14857 + lp->stats.tx_carrier_errors += regs->EMAC_CSE; /* Carrier Sense errors */
14858 + lp->stats.tx_heartbeat_errors += regs->EMAC_SQEE; /* Heartbeat error */
14860 + lcol = regs->EMAC_LCOL;
14861 + ecol = regs->EMAC_ECOL;
14862 + lp->stats.tx_window_errors += lcol; /* Late collisions */
14863 + lp->stats.tx_aborted_errors += ecol; /* 16 collisions */
14865 + lp->stats.collisions += (regs->EMAC_SCOL + regs->EMAC_MCOL + lcol + ecol);
14867 + return &lp->stats;
14871 + * Extract received frame from buffer descriptors and sent to upper layers.
14872 + * (Called from interrupt context)
14873 + */
14874 +static void at91ether_rx(struct net_device *dev)
14876 + struct at91_private *lp = (struct at91_private *) dev->priv;
14877 + struct recv_desc_bufs *dlist;
14878 + unsigned char *p_recv;
14879 + struct sk_buff *skb;
14880 + unsigned int pktlen;
14882 + dlist = lp->dlist;
14883 + while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
14884 + p_recv = dlist->recv_buf[lp->rxBuffIndex];
14885 + pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
14886 + skb = alloc_skb(pktlen + 2, GFP_ATOMIC);
14887 + if (skb != NULL) {
14888 + skb_reserve(skb, 2);
14889 + memcpy(skb_put(skb, pktlen), p_recv, pktlen);
14891 + skb->dev = dev;
14892 + skb->protocol = eth_type_trans(skb, dev);
14893 + skb->len = pktlen;
14894 + dev->last_rx = jiffies;
14895 + lp->stats.rx_bytes += pktlen;
14896 + netif_rx(skb);
14898 + else {
14899 + lp->stats.rx_dropped += 1;
14900 + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
14903 + if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
14904 + lp->stats.multicast++;
14906 + dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
14907 + if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
14908 + lp->rxBuffIndex = 0;
14909 + else
14910 + lp->rxBuffIndex++;
14915 + * MAC interrupt handler
14916 + */
14917 +static void at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs)
14919 + struct net_device *dev = (struct net_device *) dev_id;
14920 + struct at91_private *lp = (struct at91_private *) dev->priv;
14921 + AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
14922 + unsigned long intstatus;
14924 + /* MAC Interrupt Status register indicates what interrupts are pending.
14925 + It is automatically cleared once read. */
14926 + intstatus = emac->EMAC_ISR;
14928 + if (intstatus & AT91C_EMAC_RCOM) /* Receive complete */
14929 + at91ether_rx(dev);
14931 + if (intstatus & AT91C_EMAC_TCOM) { /* Transmit complete */
14932 + /* The TCOM bit is set even if the transmission failed. */
14933 + if (intstatus & (AT91C_EMAC_TUND | AT91C_EMAC_RTRY))
14934 + lp->stats.tx_errors += 1;
14936 + dev_kfree_skb_irq(lp->skb);
14937 + pci_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, PCI_DMA_TODEVICE);
14938 + netif_wake_queue(dev);
14941 + if (intstatus & AT91C_EMAC_RBNA)
14942 + printk("%s: RBNA error\n", dev->name);
14943 + if (intstatus & AT91C_EMAC_ROVR)
14944 + printk("%s: ROVR error\n", dev->name);
14948 + * Initialize the ethernet interface
14949 + */
14950 +static int at91ether_setup(struct net_device *dev, unsigned long phy_type)
14952 + struct at91_private *lp;
14953 + AT91PS_EMAC regs;
14954 + static int already_initialized = 0;
14955 + unsigned int val;
14957 + if (already_initialized)
14958 + return 0;
14960 + dev = init_etherdev(dev, sizeof(struct at91_private));
14961 + dev->base_addr = AT91C_VA_BASE_EMAC;
14962 + dev->irq = AT91C_ID_EMAC;
14963 + SET_MODULE_OWNER(dev);
14965 + /* Install the interrupt handler */
14966 + if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev))
14967 + return -EBUSY;
14969 + /* Allocate memory for private data structure */
14970 + lp = (struct at91_private *) kmalloc(sizeof(struct at91_private), GFP_KERNEL);
14971 + if (lp == NULL) {
14972 + free_irq(dev->irq, dev);
14973 + return -ENOMEM;
14975 + memset(lp, 0, sizeof(struct at91_private));
14976 + dev->priv = lp;
14978 + /* Allocate memory for DMA Receive descriptors */
14979 + lp->dlist = (struct recv_desc_bufs *) consistent_alloc(GFP_DMA | GFP_KERNEL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys);
14980 + if (lp->dlist == NULL) {
14981 + kfree(dev->priv);
14982 + free_irq(dev->irq, dev);
14983 + return -ENOMEM;
14986 + spin_lock_init(&lp->lock);
14988 + ether_setup(dev);
14989 + dev->open = at91ether_open;
14990 + dev->stop = at91ether_close;
14991 + dev->hard_start_xmit = at91ether_tx;
14992 + dev->get_stats = at91ether_stats;
14993 + dev->set_multicast_list = at91ether_set_rx_mode;
14994 + dev->do_ioctl = at91ether_ioctl;
14996 +#ifdef AT91_ETHER_ADDR_CONFIGURABLE
14997 + dev->set_mac_address = set_mac_address;
14998 +#endif
15000 + get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
15001 + update_mac_address(dev); /* Program ethernet address into MAC */
15003 + regs = (AT91PS_EMAC) dev->base_addr;
15004 + regs->EMAC_CTL = 0;
15006 +#ifdef CONFIG_AT91_ETHER_RMII
15007 + regs->EMAC_CFG = AT91C_EMAC_BIG | AT91C_EMAC_RMII;
15008 +#else
15009 + regs->EMAC_CFG = AT91C_EMAC_BIG;
15010 +#endif
15011 + if (phy_type == MII_LXT971A_ID)
15012 + regs->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; /* MDIO clock = system clock/64 */
15014 + if (phy_type == MII_DM9161_ID) {
15015 + spin_lock_irq(&lp->lock);
15016 + enable_mdi(regs);
15018 + read_phy(regs, 0, MII_DSCR_REG, &val);
15019 + if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
15020 + lp->phy_media = PORT_FIBRE;
15022 + disable_mdi(regs);
15023 + spin_unlock_irq(&lp->lock);
15026 + lp->mii.dev = dev; /* Support for ethtool */
15027 + lp->mii.mdio_read = mdio_read;
15028 + lp->mii.mdio_write = mdio_write;
15030 + lp->phy_type = phy_type; /* Type of PHY connected */
15032 + /* Determine current link speed */
15033 + spin_lock_irq(&lp->lock);
15034 + enable_mdi(regs);
15035 + (void) update_linkspeed(dev, regs);
15036 + disable_mdi(regs);
15037 + spin_unlock_irq(&lp->lock);
15039 + /* Display ethernet banner */
15040 + printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
15041 + dev->name, (uint) dev->base_addr, dev->irq,
15042 + regs->EMAC_CFG & AT91C_EMAC_SPD ? "100-" : "10-",
15043 + regs->EMAC_CFG & AT91C_EMAC_FD ? "FullDuplex" : "HalfDuplex",
15044 + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
15045 + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
15046 + if (phy_type == MII_DM9161_ID)
15047 + printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
15048 + else if (phy_type == MII_LXT971A_ID)
15049 + printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
15051 + already_initialized = 1;
15052 + return 0;
15056 + * Detect MAC and PHY and perform initialization
15057 + */
15058 +static int at91ether_probe(struct net_device *dev)
15060 + AT91PS_EMAC regs = (AT91PS_EMAC) AT91C_VA_BASE_EMAC;
15061 + unsigned int phyid1, phyid2;
15062 + int detected = -1;
15064 + /* Configure the hardware - RMII vs MII mode */
15065 +#ifdef CONFIG_AT91_ETHER_RMII
15066 + AT91_CfgPIO_EMAC_RMII();
15067 +#else
15068 + AT91_CfgPIO_EMAC_MII();
15069 +#endif
15071 + AT91_CfgPIO_EMAC_PHY(); /* Configure PHY interrupt */
15072 + AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Enable Peripheral clock */
15074 + /* Read the PHY ID registers */
15075 + enable_mdi(regs);
15076 + read_phy(regs, 0, MII_PHYSID1, &phyid1);
15077 + read_phy(regs, 0, MII_PHYSID2, &phyid2);
15078 + disable_mdi(regs);
15080 + /* Davicom 9161: PHY_ID1 = 0x181 PHY_ID2 = B881 */
15081 + if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_DM9161_ID) {
15082 + detected = at91ether_setup(dev, MII_DM9161_ID);
15084 + /* Intel LXT971A: PHY_ID1 = 0x13 PHY_ID2 = 78E0 */
15085 + else if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_LXT971A_ID) {
15086 + detected = at91ether_setup(dev, MII_LXT971A_ID);
15089 + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
15091 + return detected;
15094 +static int __init at91ether_init(void)
15096 + if (!at91ether_probe(&at91_dev))
15097 + return register_netdev(&at91_dev);
15099 + return -1;
15102 +static void __exit at91ether_exit(void)
15104 + unregister_netdev(&at91_dev);
15107 +module_init(at91ether_init)
15108 +module_exit(at91ether_exit)
15110 +MODULE_LICENSE("GPL");
15111 +MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
15112 +MODULE_AUTHOR("Andrew Victor");
15113 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
15114 +++ linux-2.4.25/drivers/at91/net/at91_ether.h 2004-03-31 17:15:09.000000000 +0200
15115 @@ -0,0 +1,81 @@
15117 + * Ethernet driver for the Atmel AT91RM9200 (Thunder)
15119 + * (c) SAN People (Pty) Ltd
15121 + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
15122 + * Initial version by Rick Bronson.
15124 + * This program is free software; you can redistribute it and/or
15125 + * modify it under the terms of the GNU General Public License
15126 + * as published by the Free Software Foundation; either version
15127 + * 2 of the License, or (at your option) any later version.
15128 + */
15130 +#ifndef AT91_ETHERNET
15131 +#define AT91_ETHERNET
15133 +#undef AT91_ETHER_ADDR_CONFIGURABLE /* MAC address can be changed? */
15136 +/* Davicom 9161 PHY */
15137 +#define MII_DM9161_ID 0x0181b880
15139 +/* Davicom specific registers */
15140 +#define MII_DSCR_REG 16
15141 +#define MII_DSCSR_REG 17
15142 +#define MII_DSINTR_REG 21
15144 +/* Intel LXT971A PHY */
15145 +#define MII_LXT971A_ID 0x001378E0
15147 +/* Intel specific registers */
15148 +#define MII_ISINTE_REG 18
15149 +#define MII_ISINTS_REG 19
15151 +/* ........................................................................ */
15153 +#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */
15154 +#define MAX_RX_DESCR 9 /* max number of receive buffers */
15156 +#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */
15157 +#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */
15159 +#define EMAC_BROADCAST 0x80000000 /* broadcast address */
15160 +#define EMAC_MULTICAST 0x40000000 /* multicast address */
15161 +#define EMAC_UNICAST 0x20000000 /* unicast address */
15163 +struct rbf_t
15165 + unsigned int addr;
15166 + unsigned long size;
15169 +struct recv_desc_bufs
15171 + struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */
15172 + char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */
15175 +struct at91_private
15177 + struct net_device_stats stats;
15178 + struct mii_if_info mii; /* ethtool support */
15180 + /* PHY */
15181 + unsigned long phy_type; /* type of PHY (PHY_ID) */
15182 + spinlock_t lock; /* lock for MDI interface */
15183 + short phy_media; /* media interface type */
15185 + /* Transmit */
15186 + struct sk_buff *skb; /* holds skb until xmit interrupt completes */
15187 + dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
15188 + int skb_length; /* saved skb length for pci_unmap_single */
15190 + /* Receive */
15191 + int rxBuffIndex; /* index into receive descriptor list */
15192 + struct recv_desc_bufs *dlist; /* descriptor list address */
15193 + struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */
15196 +#endif
15197 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
15198 +++ linux-2.4.25/drivers/at91/rtc/Makefile 2004-03-31 17:15:09.000000000 +0200
15199 @@ -0,0 +1,15 @@
15200 +# File: drivers/at91/rtc/Makefile
15202 +# Makefile for the Atmel AT91RM9200 real time clock device drivers
15205 +O_TARGET := at91rtc.o
15207 +obj-y :=
15208 +obj-m :=
15209 +obj-n :=
15210 +obj- :=
15212 +obj-$(CONFIG_AT91_RTC) += at91_rtc.o
15214 +include $(TOPDIR)/Rules.make
15215 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
15216 +++ linux-2.4.25/drivers/at91/rtc/at91_rtc.c 2004-03-31 17:15:09.000000000 +0200
15217 @@ -0,0 +1,441 @@
15219 + * Real Time Clock interface for Linux on Atmel AT91RM9200
15221 + * Copyright (c) 2002 Rick Bronson
15223 + * Based on sa1100-rtc.c by Nils Faerber
15224 + * Based on rtc.c by Paul Gortmaker
15225 + * Date/time conversion routines taken from arch/arm/kernel/time.c
15226 + * by Linus Torvalds and Russell King
15227 + * and the GNU C Library
15228 + * ( ... I love the GPL ... just take what you need! ;)
15230 + * This program is free software; you can redistribute it and/or
15231 + * modify it under the terms of the GNU General Public License
15232 + * as published by the Free Software Foundation; either version
15233 + * 2 of the License, or (at your option) any later version.
15235 + */
15237 +#include <linux/module.h>
15238 +#include <linux/fs.h>
15239 +#include <linux/miscdevice.h>
15240 +#include <linux/string.h>
15241 +#include <linux/init.h>
15242 +#include <linux/poll.h>
15243 +#include <linux/proc_fs.h>
15244 +#include <asm/bitops.h>
15245 +#include <asm/hardware.h>
15246 +#include <asm/irq.h>
15247 +#include <linux/rtc.h>
15249 +#define AT91_RTC_FREQ 1
15250 +#define EPOCH 1970
15252 +/* Those are the bits from a classic RTC we want to mimic */
15253 +#define AT91_RTC_IRQF 0x80 /* any of the following 3 is active */
15254 +#define AT91_RTC_PF 0x40
15255 +#define AT91_RTC_AF 0x20
15256 +#define AT91_RTC_UF 0x10
15258 +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
15259 +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
15261 +static unsigned long rtc_status = 0;
15262 +static unsigned long rtc_irq_data;
15263 +static unsigned int at91_alarm_year = EPOCH;
15265 +static struct fasync_struct *at91_rtc_async_queue;
15266 +static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_wait);
15267 +static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_update);
15268 +static spinlock_t at91_rtc_updlock; /* some spinlocks for saving/restoring interrupt levels */
15269 +extern spinlock_t at91_rtc_lock;
15271 +static const unsigned char days_in_mo[] =
15272 + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
15274 +#define is_leap(year) \
15275 + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
15277 +static const unsigned short int __mon_yday[2][13] =
15279 + /* Normal years. */
15280 + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
15281 + /* Leap years. */
15282 + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
15286 + * Returns day since start of the year [0-365]
15287 + * (from drivers/char/efirtc.c)
15288 + */
15289 +static inline int compute_yday(int year, int month, int day)
15291 + return __mon_yday[is_leap(year)][month] + day-1;
15295 + * Set current time and date in RTC
15296 + */
15297 +static void at91_rtc_settime(struct rtc_time *tval)
15299 + unsigned long flags;
15301 + /* Stop Time/Calendar from counting */
15302 + AT91_SYS->RTC_CR |= (AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
15304 + spin_lock_irqsave(&at91_rtc_updlock, flags); /* stop int's else we wakeup b4 we sleep */
15305 + AT91_SYS->RTC_IER = AT91C_RTC_ACKUPD;
15306 + interruptible_sleep_on(&at91_rtc_update); /* wait for ACKUPD interrupt to hit */
15307 + spin_unlock_irqrestore(&at91_rtc_updlock, flags);
15308 + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD;
15310 + AT91_SYS->RTC_TIMR = BIN2BCD(tval->tm_sec) << 0
15311 + | BIN2BCD(tval->tm_min) << 8
15312 + | BIN2BCD(tval->tm_hour) << 16;
15314 + AT91_SYS->RTC_CALR = BIN2BCD((tval->tm_year + 1900) / 100) /* century */
15315 + | BIN2BCD(tval->tm_year % 100) << 8 /* year */
15316 + | BIN2BCD(tval->tm_mon + 1) << 16 /* tm_mon starts at zero */
15317 + | BIN2BCD(tval->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
15318 + | BIN2BCD(tval->tm_mday) << 24;
15320 + /* Restart Time/Calendar */
15321 + AT91_SYS->RTC_CR &= ~(AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
15325 + * Decode time/date into rtc_time structure
15326 + */
15327 +static void at91_rtc_decodetime(AT91_REG *timereg, AT91_REG *calreg, struct rtc_time *tval)
15329 + unsigned int time, date;
15331 + do { /* must read twice in case it changes */
15332 + time = *timereg;
15333 + date = *calreg;
15334 + } while ((time != *timereg) || (date != *calreg));
15336 + tval->tm_sec = BCD2BIN((time & AT91C_RTC_SEC) >> 0);
15337 + tval->tm_min = BCD2BIN((time & AT91C_RTC_MIN) >> 8);
15338 + tval->tm_hour = BCD2BIN((time & AT91C_RTC_HOUR) >> 16);
15340 + /* The Calendar Alarm register does not have a field for
15341 + the year - so these will return an invalid value. When an
15342 + alarm is set, at91_alarm_year wille store the current year. */
15343 + tval->tm_year = BCD2BIN(date & AT91C_RTC_CENT) * 100; /* century */
15344 + tval->tm_year += BCD2BIN((date & AT91C_RTC_YEAR) >> 8); /* year */
15346 + tval->tm_wday = BCD2BIN((date & AT91C_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
15347 + tval->tm_mon = BCD2BIN(((date & AT91C_RTC_MONTH) >> 16) - 1);
15348 + tval->tm_mday = BCD2BIN((date & AT91C_RTC_DATE) >> 24);
15352 + * IRQ handler for the RTC
15353 + */
15354 +static void at91_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
15356 + unsigned int rtsr = AT91_SYS->RTC_SR & AT91_SYS->RTC_IMR;
15358 + /* update irq data & counter */
15359 + if (rtsr) { /* this interrupt is shared! Is it ours? */
15360 + if (rtsr & AT91C_RTC_ALARM)
15361 + rtc_irq_data |= (AT91_RTC_AF | AT91_RTC_IRQF);
15362 + if (rtsr & AT91C_RTC_SECEV)
15363 + rtc_irq_data |= (AT91_RTC_UF | AT91_RTC_IRQF);
15364 + if (rtsr & AT91C_RTC_ACKUPD)
15365 + wake_up_interruptible(&at91_rtc_update);
15366 + rtc_irq_data += 0x100;
15367 + AT91_SYS->RTC_SCCR = rtsr; /* clear status reg */
15369 + /* wake up waiting process */
15370 + wake_up_interruptible(&at91_rtc_wait);
15371 + kill_fasync(&at91_rtc_async_queue, SIGIO, POLL_IN);
15375 +static int at91_rtc_open(struct inode *inode, struct file *file)
15377 + if (test_and_set_bit(1, &rtc_status))
15378 + return -EBUSY;
15379 + rtc_irq_data = 0;
15380 + return 0;
15383 +static int at91_rtc_release(struct inode *inode, struct file *file)
15385 + rtc_status = 0;
15386 + return 0;
15389 +static int at91_rtc_fasync(int fd, struct file *filp, int on)
15391 + return fasync_helper(fd, filp, on, &at91_rtc_async_queue);
15394 +static unsigned int at91_rtc_poll(struct file *file, poll_table * wait)
15396 + poll_wait(file, &at91_rtc_wait, wait);
15397 + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
15400 +static ssize_t at91_rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos)
15402 + DECLARE_WAITQUEUE(wait, current);
15403 + unsigned long data;
15404 + ssize_t retval;
15406 + if (count < sizeof(unsigned long))
15407 + return -EINVAL;
15409 + add_wait_queue(&at91_rtc_wait, &wait);
15410 + set_current_state(TASK_INTERRUPTIBLE);
15411 + for (;;) {
15412 + spin_lock_irq(&at91_rtc_lock);
15413 + data = rtc_irq_data;
15414 + if (data != 0) {
15415 + rtc_irq_data = 0;
15416 + break;
15418 + spin_unlock_irq(&at91_rtc_lock);
15420 + if (file->f_flags & O_NONBLOCK) {
15421 + retval = -EAGAIN;
15422 + goto out;
15425 + if (signal_pending(current)) {
15426 + retval = -ERESTARTSYS;
15427 + goto out;
15430 + schedule();
15432 + spin_unlock_irq(&at91_rtc_lock);
15434 + data -= 0x100; /* the first IRQ wasn't actually missed */
15435 + retval = put_user(data, (unsigned long *) buf);
15436 + if (!retval)
15437 + retval = sizeof(unsigned long);
15439 +out:
15440 + set_current_state(TASK_RUNNING);
15441 + remove_wait_queue(&at91_rtc_wait, &wait);
15442 + return retval;
15446 + * Handle commands from user-space
15447 + */
15448 +static int at91_rtc_ioctl(struct inode *inode, struct file *file,
15449 + unsigned int cmd, unsigned long arg)
15451 + struct rtc_time tm, tm2;
15452 + int ret = 0;
15454 + spin_lock_irq(&at91_rtc_lock);
15455 + switch (cmd) {
15456 + case RTC_AIE_OFF: /* alarm off */
15457 + AT91_SYS->RTC_IDR = AT91C_RTC_ALARM;
15458 + rtc_irq_data = 0;
15459 + break;
15460 + case RTC_AIE_ON: /* alarm on */
15461 + AT91_SYS->RTC_IER = AT91C_RTC_ALARM;
15462 + rtc_irq_data = 0;
15463 + break;
15464 + case RTC_UIE_OFF: /* update off */
15465 + AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
15466 + rtc_irq_data = 0;
15467 + break;
15468 + case RTC_UIE_ON: /* update on */
15469 + AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
15470 + rtc_irq_data = 0;
15471 + break;
15472 + case RTC_PIE_OFF: /* periodic off */
15473 + AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
15474 + rtc_irq_data = 0;
15475 + break;
15476 + case RTC_PIE_ON: /* periodic on */
15477 + AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
15478 + rtc_irq_data = 0;
15479 + break;
15480 + case RTC_ALM_READ: /* read alarm */
15481 + memset(&tm, 0, sizeof(struct rtc_time));
15482 + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
15483 + tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
15484 + tm.tm_year = at91_alarm_year - 1900;
15485 + ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
15486 + break;
15487 + case RTC_ALM_SET: /* set alarm */
15488 + if (copy_from_user(&tm2, (struct rtc_time *) arg, sizeof(tm2)))
15489 + ret = -EFAULT;
15490 + else {
15491 + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
15492 + at91_alarm_year = tm.tm_year;
15493 + if ((unsigned) tm2.tm_hour < 24) /* do some range checking */
15494 + tm.tm_hour = tm2.tm_hour;
15495 + if ((unsigned) tm2.tm_min < 60)
15496 + tm.tm_min = tm2.tm_min;
15497 + if ((unsigned) tm2.tm_sec < 60)
15498 + tm.tm_sec = tm2.tm_sec;
15499 + AT91_SYS->RTC_TIMALR = BIN2BCD(tm.tm_sec) << 0
15500 + | BIN2BCD(tm.tm_min) << 8
15501 + | BIN2BCD(tm.tm_hour) << 16
15502 + | AT91C_RTC_HOUREN | AT91C_RTC_MINEN
15503 + | AT91C_RTC_SECEN;
15504 + AT91_SYS->RTC_CALALR = BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
15505 + | BIN2BCD(tm.tm_mday) << 24
15506 + | AT91C_RTC_DATEEN | AT91C_RTC_MONTHEN;
15508 + break;
15509 + case RTC_RD_TIME: /* read time */
15510 + memset(&tm, 0, sizeof(struct rtc_time));
15511 + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
15512 + tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
15513 + tm.tm_year = tm.tm_year - 1900;
15514 + ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
15515 + break;
15516 + case RTC_SET_TIME: /* set time */
15517 + if (!capable(CAP_SYS_TIME))
15518 + ret = -EACCES;
15519 + else {
15520 + if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(tm)))
15521 + ret = -EFAULT;
15522 + else {
15523 + int tm_year = tm.tm_year + 1900;
15524 + if (tm_year < EPOCH
15525 + || (unsigned) tm.tm_mon >= 12
15526 + || tm.tm_mday < 1
15527 + || tm.tm_mday > (days_in_mo[tm.tm_mon] + (tm.tm_mon == 1 && is_leap(tm_year)))
15528 + || (unsigned) tm.tm_hour >= 24
15529 + || (unsigned) tm.tm_min >= 60
15530 + || (unsigned) tm.tm_sec >= 60)
15531 + ret = -EINVAL;
15532 + else
15533 + at91_rtc_settime(&tm);
15536 + break;
15537 + case RTC_IRQP_READ: /* read periodic alarm frequency */
15538 + ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
15539 + break;
15540 + case RTC_IRQP_SET: /* set periodic alarm frequency */
15541 + if (arg != AT91_RTC_FREQ)
15542 + ret = -EINVAL;
15543 + break;
15544 + case RTC_EPOCH_READ: /* read epoch */
15545 + ret = put_user(EPOCH, (unsigned long *) arg);
15546 + break;
15547 + default:
15548 + ret = -EINVAL;
15549 + break;
15551 + spin_unlock_irq(&at91_rtc_lock);
15552 + return ret;
15556 + * Provide RTC information in /proc/driver/rtc
15557 + */
15558 +static int at91_rtc_read_proc(char *page, char **start, off_t off,
15559 + int count, int *eof, void *data)
15561 + char *p = page;
15562 + int len;
15563 + struct rtc_time tm;
15565 + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
15566 + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
15567 + "rtc_date\t: %04d-%02d-%02d\n"
15568 + "rtc_epoch\t: %04d\n",
15569 + tm.tm_hour, tm.tm_min, tm.tm_sec,
15570 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, EPOCH);
15571 + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
15572 + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
15573 + "alrm_date\t: %04d-%02d-%02d\n",
15574 + tm.tm_hour, tm.tm_min, tm.tm_sec,
15575 + at91_alarm_year, tm.tm_mon + 1, tm.tm_mday);
15576 + p += sprintf(p, "alarm_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ALARM) ? "yes" : "no");
15577 + p += sprintf(p, "update_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ACKUPD) ? "yes" : "no");
15578 + p += sprintf(p, "periodic_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_SECEV) ? "yes" : "no");
15579 + p += sprintf(p, "periodic_freq\t: %ld\n", (unsigned long) AT91_RTC_FREQ);
15581 + len = (p - page) - off;
15582 + if (len < 0)
15583 + len = 0;
15585 + *eof = (len <= count) ? 1 : 0;
15586 + *start = page + off;
15588 + return len;
15591 +static struct file_operations at91_rtc_fops = {
15592 + owner:THIS_MODULE,
15593 + llseek:no_llseek,
15594 + read:at91_rtc_read,
15595 + poll:at91_rtc_poll,
15596 + ioctl:at91_rtc_ioctl,
15597 + open:at91_rtc_open,
15598 + release:at91_rtc_release,
15599 + fasync:at91_rtc_fasync,
15602 +static struct miscdevice at91_rtc_miscdev = {
15603 + minor:RTC_MINOR,
15604 + name:"rtc",
15605 + fops:&at91_rtc_fops,
15609 + * Initialize and install RTC driver
15610 + */
15611 +static int __init at91_rtc_init(void)
15613 + int ret;
15615 + AT91_SYS->RTC_CR = 0;
15616 + AT91_SYS->RTC_MR = 0; /* put in 24 hour format */
15617 + /* Disable all interrupts */
15618 + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
15620 + spin_lock_init(&at91_rtc_updlock);
15621 + spin_lock_init(&at91_rtc_lock);
15623 + misc_register(&at91_rtc_miscdev);
15624 + create_proc_read_entry("driver/rtc", 0, 0, at91_rtc_read_proc, NULL);
15625 + ret = request_irq(AT91C_ID_SYS, at91_rtc_interrupt, SA_SHIRQ,
15626 + "at91_rtc", &rtc_status);
15627 + if (ret) {
15628 + printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", AT91C_ID_SYS);
15629 + remove_proc_entry("driver/rtc", NULL);
15630 + misc_deregister(&at91_rtc_miscdev);
15631 + return ret;
15634 + printk(KERN_INFO "AT91 Real Time Clock driver\n");
15635 + return 0;
15639 + * Disable and remove the RTC driver
15640 + */
15641 +static void __exit at91_rtc_exit(void)
15643 + /* Disable all interrupts */
15644 + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
15645 + free_irq(AT91C_ID_SYS, &rtc_status);
15647 + rtc_status = 0;
15648 + remove_proc_entry("driver/rtc", NULL);
15649 + misc_deregister(&at91_rtc_miscdev);
15652 +module_init(at91_rtc_init);
15653 +module_exit(at91_rtc_exit);
15655 +MODULE_AUTHOR("Rick Bronson");
15656 +MODULE_DESCRIPTION("AT91 Realtime Clock Driver (AT91_RTC)");
15657 +MODULE_LICENSE("GPL");
15658 +EXPORT_NO_SYMBOLS;
15659 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
15660 +++ linux-2.4.25/drivers/at91/serial/Makefile 2004-03-31 17:15:09.000000000 +0200
15661 @@ -0,0 +1,15 @@
15662 +# File: drivers/at91/serial/Makefile
15664 +# Makefile for the Atmel AT91RM9200 serial and console device drivers
15667 +O_TARGET := at91serial.o
15669 +obj-y :=
15670 +obj-m :=
15671 +obj-n :=
15672 +obj- :=
15674 +obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
15676 +include $(TOPDIR)/Rules.make
15677 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
15678 +++ linux-2.4.25/drivers/at91/serial/at91_serial.c 2004-03-31 17:15:09.000000000 +0200
15679 @@ -0,0 +1,870 @@
15681 + * linux/drivers/char/at91_serial.c
15683 + * Driver for Atmel AT91RM9200 Serial ports
15685 + * Copyright (c) Rick Bronson
15687 + * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
15688 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
15690 + * This program is free software; you can redistribute it and/or modify
15691 + * it under the terms of the GNU General Public License as published by
15692 + * the Free Software Foundation; either version 2 of the License, or
15693 + * (at your option) any later version.
15695 + * This program is distributed in the hope that it will be useful,
15696 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15697 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15698 + * GNU General Public License for more details.
15700 + * You should have received a copy of the GNU General Public License
15701 + * along with this program; if not, write to the Free Software
15702 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15704 + */
15705 +#include <linux/config.h>
15706 +#include <linux/module.h>
15707 +#include <linux/tty.h>
15708 +#include <linux/ioport.h>
15709 +#include <linux/slab.h>
15710 +#include <linux/init.h>
15711 +#include <linux/serial.h>
15712 +#include <linux/console.h>
15713 +#include <linux/sysrq.h>
15715 +#include <asm/arch/AT91RM9200_USART.h>
15716 +#include <asm/mach/serial_at91rm9200.h>
15717 +#include <asm/arch/pio.h>
15720 +#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
15721 +#define SUPPORT_SYSRQ
15722 +#endif
15724 +#include <linux/serial_core.h>
15726 +#define SERIAL_AT91_MAJOR TTY_MAJOR
15727 +#define CALLOUT_AT91_MAJOR TTYAUX_MAJOR
15728 +#define MINOR_START 64
15730 +#define AT91C_VA_BASE_DBGU ((unsigned long) &(AT91_SYS->DBGU_CR))
15731 +#define AT91_ISR_PASS_LIMIT 256
15733 +#define UART_PUT_CR(port,v) ((AT91PS_USART)(port)->membase)->US_CR = v
15734 +#define UART_GET_MR(port) ((AT91PS_USART)(port)->membase)->US_MR
15735 +#define UART_PUT_MR(port,v) ((AT91PS_USART)(port)->membase)->US_MR = v
15736 +#define UART_PUT_IER(port,v) ((AT91PS_USART)(port)->membase)->US_IER = v
15737 +#define UART_PUT_IDR(port,v) ((AT91PS_USART)(port)->membase)->US_IDR = v
15738 +#define UART_GET_IMR(port) ((AT91PS_USART)(port)->membase)->US_IMR
15739 +#define UART_GET_CSR(port) ((AT91PS_USART)(port)->membase)->US_CSR
15740 +#define UART_GET_CHAR(port) ((AT91PS_USART)(port)->membase)->US_RHR
15741 +#define UART_PUT_CHAR(port,v) ((AT91PS_USART)(port)->membase)->US_THR = v
15742 +#define UART_GET_BRGR(port) ((AT91PS_USART)(port)->membase)->US_BRGR
15743 +#define UART_PUT_BRGR(port,v) ((AT91PS_USART)(port)->membase)->US_BRGR = v
15744 +#define UART_PUT_RTOR(port,v) ((AT91PS_USART)(port)->membase)->US_RTOR = v
15746 +// #define UART_GET_CR(port) ((AT91PS_USART)(port)->membase)->US_CR // is write-only
15748 + /* PDC registers */
15749 +#define UART_PUT_PTCR(port,v) ((AT91PS_USART)(port)->membase)->US_PTCR = v
15750 +#define UART_PUT_RPR(port,v) ((AT91PS_USART)(port)->membase)->US_RPR = v
15751 +#define UART_PUT_RCR(port,v) ((AT91PS_USART)(port)->membase)->US_RCR = v
15752 +#define UART_GET_RCR(port) ((AT91PS_USART)(port)->membase)->US_RCR
15753 +#define UART_PUT_RNPR(port,v) ((AT91PS_USART)(port)->membase)->US_RNPR = v
15754 +#define UART_PUT_RNCR(port,v) ((AT91PS_USART)(port)->membase)->US_RNCR = v
15756 +static struct tty_driver normal, callout;
15757 +static struct tty_struct *at91_table[AT91C_NR_UART];
15758 +static struct termios *at91_termios[AT91C_NR_UART], *at91_termios_locked[AT91C_NR_UART];
15760 +const int at91_serialmap[AT91C_NR_UART] = AT91C_UART_MAP;
15762 +static int (*at91_open)(struct uart_port *);
15763 +static void (*at91_close)(struct uart_port *);
15765 +#ifdef SUPPORT_SYSRQ
15766 +static struct console at91_console;
15767 +#endif
15770 + * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
15771 + */
15772 +static u_int at91_tx_empty(struct uart_port *port)
15774 + return UART_GET_CSR(port) & AT91C_US_TXEMPTY ? TIOCSER_TEMT : 0;
15778 + * Set state of the modem control output lines
15779 + */
15780 +static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
15782 + unsigned int control = 0;
15784 + if (mctrl & TIOCM_RTS)
15785 + control |= AT91C_US_RTSEN;
15786 + else
15787 + control |= AT91C_US_RTSDIS;
15789 + if (mctrl & TIOCM_DTR)
15790 + control |= AT91C_US_DTREN;
15791 + else
15792 + control |= AT91C_US_DTRDIS;
15794 + UART_PUT_CR(port,control);
15798 + * Get state of the modem control input lines
15799 + */
15800 +static u_int at91_get_mctrl(struct uart_port *port)
15802 + unsigned int status, ret = 0;
15804 + status = UART_GET_CSR(port);
15805 + if (status & AT91C_US_DCD)
15806 + ret |= TIOCM_CD;
15807 + if (status & AT91C_US_CTS)
15808 + ret |= TIOCM_CTS;
15809 + if (status & AT91C_US_DSR)
15810 + ret |= TIOCM_DSR;
15811 + if (status & AT91C_US_RI)
15812 + ret |= TIOCM_RI;
15814 + return ret;
15818 + * Stop transmitting.
15819 + */
15820 +static void at91_stop_tx(struct uart_port *port, u_int from_tty)
15822 + UART_PUT_IDR(port, AT91C_US_TXRDY);
15823 + port->read_status_mask &= ~AT91C_US_TXRDY;
15827 + * Start transmitting.
15828 + */
15829 +static void at91_start_tx(struct uart_port *port, u_int from_tty)
15831 + unsigned long flags;
15833 + local_irq_save(flags);
15834 + port->read_status_mask |= AT91C_US_TXRDY;
15835 + UART_PUT_IER(port, AT91C_US_TXRDY);
15836 + local_irq_restore(flags);
15840 + * Stop receiving - port is in process of being closed.
15841 + */
15842 +static void at91_stop_rx(struct uart_port *port)
15844 + UART_PUT_IDR(port, AT91C_US_RXRDY);
15848 + * Enable modem status interrupts
15849 + */
15850 +static void at91_enable_ms(struct uart_port *port)
15852 + UART_PUT_IER(port, AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC);
15856 + * Control the transmission of a break signal
15857 + */
15858 +static void at91_break_ctl(struct uart_port *port, int break_state)
15860 + if (break_state != 0)
15861 + UART_PUT_CR(port, AT91C_US_STTBRK); /* start break */
15862 + else
15863 + UART_PUT_CR(port, AT91C_US_STPBRK); /* stop break */
15867 + * Characters received (called from interrupt handler)
15868 + */
15869 +static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
15871 + struct uart_info *info = port->info;
15872 + struct tty_struct *tty = info->tty;
15873 + unsigned int status, ch, flg, ignored = 0;
15875 + status = UART_GET_CSR(port);
15876 + while (status & (AT91C_US_RXRDY)) {
15877 + ch = UART_GET_CHAR(port);
15879 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
15880 + goto ignore_char;
15881 + port->icount.rx++;
15883 + flg = TTY_NORMAL;
15885 + /*
15886 + * note that the error handling code is
15887 + * out of the main execution path
15888 + */
15889 + if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
15890 + goto handle_error;
15892 + if (uart_handle_sysrq_char(port, ch, regs))
15893 + goto ignore_char;
15895 + error_return:
15896 + *tty->flip.flag_buf_ptr++ = flg;
15897 + *tty->flip.char_buf_ptr++ = ch;
15898 + tty->flip.count++;
15899 + ignore_char:
15900 + status = UART_GET_CSR(port);
15902 +out:
15903 + tty_flip_buffer_push(tty);
15904 + return;
15906 +handle_error:
15907 + if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
15908 + UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
15909 + if (status & (AT91C_US_PARE))
15910 + port->icount.parity++;
15911 + else if (status & (AT91C_US_FRAME))
15912 + port->icount.frame++;
15913 + if (status & (AT91C_US_OVRE))
15914 + port->icount.overrun++;
15916 + if (status & port->ignore_status_mask) {
15917 + if (++ignored > 100)
15918 + goto out;
15919 + goto ignore_char;
15922 + status &= port->read_status_mask;
15924 + UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
15925 + if (status & AT91C_US_PARE)
15926 + flg = TTY_PARITY;
15927 + else if (status & AT91C_US_FRAME)
15928 + flg = TTY_FRAME;
15930 + if (status & AT91C_US_OVRE) {
15931 + /*
15932 + * overrun does *not* affect the character
15933 + * we read from the FIFO
15934 + */
15935 + *tty->flip.flag_buf_ptr++ = flg;
15936 + *tty->flip.char_buf_ptr++ = ch;
15937 + tty->flip.count++;
15938 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
15939 + goto ignore_char;
15940 + ch = 0;
15941 + flg = TTY_OVERRUN;
15943 +#ifdef SUPPORT_SYSRQ
15944 + port->sysrq = 0;
15945 +#endif
15946 + goto error_return;
15950 + * Transmit characters (called from interrupt handler)
15951 + */
15952 +static void at91_tx_chars(struct uart_port *port)
15954 + struct circ_buf *xmit = &port->info->xmit;
15956 + if (port->x_char) {
15957 + UART_PUT_CHAR(port, port->x_char);
15958 + port->icount.tx++;
15959 + port->x_char = 0;
15960 + return;
15962 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
15963 + at91_stop_tx(port, 0);
15964 + return;
15967 + while (UART_GET_CSR(port) & AT91C_US_TXRDY) {
15968 + UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
15969 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
15970 + port->icount.tx++;
15971 + if (uart_circ_empty(xmit))
15972 + break;
15975 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
15976 + uart_write_wakeup(port);
15978 + if (uart_circ_empty(xmit))
15979 + at91_stop_tx(port, 0);
15983 + * Interrupt handler
15984 + */
15985 +static void at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
15987 + struct uart_port *port = dev_id;
15988 + unsigned int status, pending, pass_counter = 0;
15990 + status = UART_GET_CSR(port);
15991 + pending = status & port->read_status_mask;
15992 + if (pending) {
15993 + do {
15994 + if (pending & AT91C_US_RXRDY)
15995 + at91_rx_chars(port, regs);
15997 + /* Clear the relevent break bits */
15998 + if (pending & AT91C_US_RXBRK) {
15999 + UART_PUT_CR(port, AT91C_US_RSTSTA);
16000 + port->icount.brk++;
16001 +#ifdef SUPPORT_SYSRQ
16002 + if (port->line == at91_console.index && !port->sysrq) {
16003 + port->sysrq = jiffies + HZ*5;
16005 +#endif
16008 + // TODO: All reads to CSR will clear these interrupts!
16009 + if (pending & AT91C_US_RIIC) port->icount.rng++;
16010 + if (pending & AT91C_US_DSRIC) port->icount.dsr++;
16011 + if (pending & AT91C_US_DCDIC) {
16012 + port->icount.dcd++;
16013 + uart_handle_dcd_change(port, status & AT91C_US_DCD);
16015 + if (pending & AT91C_US_CTSIC) {
16016 + port->icount.cts++;
16017 + uart_handle_cts_change(port, status & AT91C_US_CTS);
16019 + if (pending & (AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC))
16020 + wake_up_interruptible(&port->info->delta_msr_wait);
16022 + if (pending & AT91C_US_TXRDY)
16023 + at91_tx_chars(port);
16024 + if (pass_counter++ > AT91_ISR_PASS_LIMIT)
16025 + break;
16027 + status = UART_GET_CSR(port);
16028 + pending = status & port->read_status_mask;
16029 + } while (pending);
16034 + * Perform initialization and enable port for reception
16035 + */
16036 +static int at91_startup(struct uart_port *port)
16038 + int retval;
16040 + /*
16041 + * Allocate the IRQ
16042 + */
16043 + retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port);
16044 + if (retval) {
16045 + printk("at91_serial: at91_startup - Can't get irq\n");
16046 + return retval;
16048 + /*
16049 + * If there is a specific "open" function (to register
16050 + * control line interrupts)
16051 + */
16052 + if (at91_open) {
16053 + retval = at91_open(port);
16054 + if (retval) {
16055 + free_irq(port->irq, port);
16056 + return retval;
16060 + /* Enable peripheral clock if required */
16061 + if (port->irq != AT91C_ID_SYS)
16062 + AT91_SYS->PMC_PCER = 1 << port->irq;
16064 + port->read_status_mask = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE
16065 + | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK;
16066 + /*
16067 + * Finally, clear and enable interrupts
16068 + */
16069 + UART_PUT_IDR(port, -1);
16070 + UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); /* enable xmit & rcvr */
16071 + UART_PUT_IER(port, AT91C_US_RXRDY); /* do receive only */
16072 + return 0;
16076 + * Disable the port
16077 + */
16078 +static void at91_shutdown(struct uart_port *port)
16080 + /*
16081 + * Free the interrupt
16082 + */
16083 + free_irq(port->irq, port);
16085 + /*
16086 + * If there is a specific "close" function (to unregister
16087 + * control line interrupts)
16088 + */
16089 + if (at91_close)
16090 + at91_close(port);
16092 + /*
16093 + * Disable all interrupts, port and break condition.
16094 + */
16095 + UART_PUT_CR(port, AT91C_US_RSTSTA);
16096 + UART_PUT_IDR(port, -1);
16098 + /* Disable peripheral clock if required */
16099 + if (port->irq != AT91C_ID_SYS)
16100 + AT91_SYS->PMC_PCDR = 1 << port->irq;
16103 +static struct uart_ops at91_pops; /* forward declaration */
16106 + * Change the port parameters
16107 + */
16108 +static void at91_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
16110 + unsigned long flags;
16111 + unsigned int mode, imr;
16113 + /* Get current mode register */
16114 + mode = UART_GET_MR(port) & ~(AT91C_US_CHRL | AT91C_US_NBSTOP | AT91C_US_PAR);
16116 + /* byte size */
16117 + switch (cflag & CSIZE) {
16118 + case CS5:
16119 + mode |= AT91C_US_CHRL_5_BITS;
16120 + break;
16121 + case CS6:
16122 + mode |= AT91C_US_CHRL_6_BITS;
16123 + break;
16124 + case CS7:
16125 + mode |= AT91C_US_CHRL_7_BITS;
16126 + break;
16127 + default:
16128 + mode |= AT91C_US_CHRL_8_BITS;
16129 + break;
16132 + /* stop bits */
16133 + if (cflag & CSTOPB)
16134 + mode |= AT91C_US_NBSTOP_2_BIT;
16136 + /* parity */
16137 + if (cflag & PARENB) {
16138 + if (cflag & CMSPAR) { /* Mark or Space parity */
16139 + if (cflag & PARODD)
16140 + mode |= AT91C_US_PAR_MARK;
16141 + else
16142 + mode |= AT91C_US_PAR_SPACE;
16144 + else if (cflag & PARODD)
16145 + mode |= AT91C_US_PAR_ODD;
16146 + else
16147 + mode |= AT91C_US_PAR_EVEN;
16149 + else
16150 + mode |= AT91C_US_PAR_NONE;
16152 + port->read_status_mask |= AT91C_US_OVRE;
16153 + if (iflag & INPCK)
16154 + port->read_status_mask |= AT91C_US_FRAME | AT91C_US_PARE;
16155 + if (iflag & (BRKINT | PARMRK))
16156 + port->read_status_mask |= AT91C_US_RXBRK;
16158 + /*
16159 + * Characters to ignore
16160 + */
16161 + port->ignore_status_mask = 0;
16162 + if (iflag & IGNPAR)
16163 + port->ignore_status_mask |= (AT91C_US_FRAME | AT91C_US_PARE);
16164 + if (iflag & IGNBRK) {
16165 + port->ignore_status_mask |= AT91C_US_RXBRK;
16166 + /*
16167 + * If we're ignoring parity and break indicators,
16168 + * ignore overruns too (for real raw support).
16169 + */
16170 + if (iflag & IGNPAR)
16171 + port->ignore_status_mask |= AT91C_US_OVRE;
16174 + // TODO: Ignore all characters if CREAD is set.
16176 + /* first, disable interrupts and drain transmitter */
16177 + local_irq_save(flags);
16178 + imr = UART_GET_IMR(port); /* get interrupt mask */
16179 + UART_PUT_IDR(port, -1); /* disable all interrupts */
16180 + local_irq_restore(flags);
16181 + while (!(UART_GET_CSR(port) & AT91C_US_TXEMPTY)) { barrier(); }
16183 + /* disable receiver and transmitter */
16184 + UART_PUT_CR(port, AT91C_US_TXDIS | AT91C_US_RXDIS);
16186 + /* set the parity, stop bits and data size */
16187 + UART_PUT_MR(port, mode);
16189 + /* set the baud rate */
16190 + UART_PUT_BRGR(port, quot);
16191 + UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN);
16193 + /* restore interrupts */
16194 + UART_PUT_IER(port, imr);
16196 + /* CTS flow-control and modem-status interrupts */
16197 + if (UART_ENABLE_MS(uart, cflag))
16198 + at91_pops.enable_ms(uart);
16202 + * Return string describing the specified port
16203 + */
16204 +static const char *at91_type(struct uart_port *port)
16206 + return port->type == PORT_AT91RM9200 ? "AT91_SERIAL" : NULL;
16210 + * Release the memory region(s) being used by 'port'.
16211 + */
16212 +static void at91_release_port(struct uart_port *port)
16214 + release_mem_region(port->mapbase,
16215 + port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K);
16219 + * Request the memory region(s) being used by 'port'.
16220 + */
16221 +static int at91_request_port(struct uart_port *port)
16223 + return request_mem_region(port->mapbase,
16224 + port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K,
16225 + "at91_serial") != NULL ? 0 : -EBUSY;
16230 + * Configure/autoconfigure the port.
16231 + */
16232 +static void at91_config_port(struct uart_port *port, int flags)
16234 + if (flags & UART_CONFIG_TYPE) {
16235 + port->type = PORT_AT91RM9200;
16236 + at91_request_port(port);
16241 + * Verify the new serial_struct (for TIOCSSERIAL).
16242 + */
16243 +static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
16245 + int ret = 0;
16246 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
16247 + ret = -EINVAL;
16248 + if (port->irq != ser->irq)
16249 + ret = -EINVAL;
16250 + if (ser->io_type != SERIAL_IO_MEM)
16251 + ret = -EINVAL;
16252 + if (port->uartclk / 16 != ser->baud_base)
16253 + ret = -EINVAL;
16254 + if ((void *)port->mapbase != ser->iomem_base)
16255 + ret = -EINVAL;
16256 + if (port->iobase != ser->port)
16257 + ret = -EINVAL;
16258 + if (ser->hub6 != 0)
16259 + ret = -EINVAL;
16260 + return ret;
16263 +static struct uart_ops at91_pops = {
16264 + tx_empty: at91_tx_empty,
16265 + set_mctrl: at91_set_mctrl,
16266 + get_mctrl: at91_get_mctrl,
16267 + stop_tx: at91_stop_tx,
16268 + start_tx: at91_start_tx,
16269 + stop_rx: at91_stop_rx,
16270 + enable_ms: at91_enable_ms,
16271 + break_ctl: at91_break_ctl,
16272 + startup: at91_startup,
16273 + shutdown: at91_shutdown,
16274 + change_speed: at91_change_speed,
16275 + type: at91_type,
16276 + release_port: at91_release_port,
16277 + request_port: at91_request_port,
16278 + config_port: at91_config_port,
16279 + verify_port: at91_verify_port,
16282 +static struct uart_port at91_ports[AT91C_NR_UART];
16284 +void __init at91_init_ports(void)
16286 + static int first = 1;
16287 + int i;
16289 + if (!first)
16290 + return;
16291 + first = 0;
16293 + for (i = 0; i < AT91C_NR_UART; i++) {
16294 + at91_ports[i].iotype = SERIAL_IO_MEM;
16295 + at91_ports[i].flags = ASYNC_BOOT_AUTOCONF;
16296 + at91_ports[i].uartclk = AT91C_MASTER_CLOCK;
16297 + at91_ports[i].ops = &at91_pops;
16298 + at91_ports[i].fifosize = 1;
16299 + at91_ports[i].line = i;
16303 +void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
16305 + if (fns->enable_ms)
16306 + at91_pops.enable_ms = fns->enable_ms;
16307 + if (fns->get_mctrl)
16308 + at91_pops.get_mctrl = fns->get_mctrl;
16309 + if (fns->set_mctrl)
16310 + at91_pops.set_mctrl = fns->set_mctrl;
16311 + at91_open = fns->open;
16312 + at91_close = fns->close;
16313 + at91_pops.pm = fns->pm;
16314 + at91_pops.set_wake = fns->set_wake;
16318 + * Setup ports.
16319 + */
16320 +void __init at91_register_uart(int idx, int port)
16322 + if ((idx < 0) || (idx >= AT91C_NR_UART)) {
16323 + printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx);
16324 + return;
16327 + switch (port) {
16328 + case 0:
16329 + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US0;
16330 + at91_ports[idx].mapbase = AT91C_VA_BASE_US0;
16331 + at91_ports[idx].irq = AT91C_ID_US0;
16332 + AT91_CfgPIO_USART0();
16333 + break;
16334 + case 1:
16335 + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US1;
16336 + at91_ports[idx].mapbase = AT91C_VA_BASE_US1;
16337 + at91_ports[idx].irq = AT91C_ID_US1;
16338 + AT91_CfgPIO_USART1();
16339 + break;
16340 + case 2:
16341 + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US2;
16342 + at91_ports[idx].mapbase = AT91C_VA_BASE_US2;
16343 + at91_ports[idx].irq = AT91C_ID_US2;
16344 + AT91_CfgPIO_USART2();
16345 + break;
16346 + case 3:
16347 + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US3;
16348 + at91_ports[idx].mapbase = AT91C_VA_BASE_US3;
16349 + at91_ports[idx].irq = AT91C_ID_US3;
16350 + AT91_CfgPIO_USART3();
16351 + break;
16352 + case 4:
16353 + at91_ports[idx].membase = (void *) AT91C_VA_BASE_DBGU;
16354 + at91_ports[idx].mapbase = AT91C_VA_BASE_DBGU;
16355 + at91_ports[idx].irq = AT91C_ID_SYS;
16356 + AT91_CfgPIO_DBGU();
16357 + break;
16358 + default:
16359 + printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port);
16363 +#ifdef CONFIG_SERIAL_AT91_CONSOLE
16366 + * Interrupts are disabled on entering
16367 + */
16368 +static void at91_console_write(struct console *co, const char *s, u_int count)
16370 + struct uart_port *port = at91_ports + co->index;
16371 + unsigned int status, i, imr;
16373 + /*
16374 + * First, save IMR and then disable interrupts
16375 + */
16376 + imr = UART_GET_IMR(port); /* get interrupt mask */
16377 + UART_PUT_IDR(port, AT91C_US_RXRDY | AT91C_US_TXRDY);
16379 + /*
16380 + * Now, do each character
16381 + */
16382 + for (i = 0; i < count; i++) {
16383 + do {
16384 + status = UART_GET_CSR(port);
16385 + } while (!(status & AT91C_US_TXRDY));
16386 + UART_PUT_CHAR(port, s[i]);
16387 + if (s[i] == '\n') {
16388 + do {
16389 + status = UART_GET_CSR(port);
16390 + } while (!(status & AT91C_US_TXRDY));
16391 + UART_PUT_CHAR(port, '\r');
16395 + /*
16396 + * Finally, wait for transmitter to become empty
16397 + * and restore IMR
16398 + */
16399 + do {
16400 + status = UART_GET_CSR(port);
16401 + } while (status & AT91C_US_TXRDY);
16402 + UART_PUT_IER(port, imr); /* set interrupts back the way they were */
16405 +static kdev_t at91_console_device(struct console *co)
16407 + return MKDEV(SERIAL_AT91_MAJOR, MINOR_START + co->index);
16411 + * If the port was already initialised (eg, by a boot loader), try to determine
16412 + * the current setup.
16413 + */
16414 +static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
16416 + unsigned int mr, quot;
16418 +// TODO: CR is a write-only register
16419 +// unsigned int cr;
16421 +// cr = UART_GET_CR(port) & (AT91C_US_RXEN | AT91C_US_TXEN);
16422 +// if (cr == (AT91C_US_RXEN | AT91C_US_TXEN)) {
16423 +// /* ok, the port was enabled */
16425 +// mr = UART_GET_MR(port) & AT91C_US_PAR;
16427 +// *parity = 'n';
16428 +// if (mr == AT91C_US_PAR_EVEN)
16429 +// *parity = 'e';
16430 +// else if (mr == AT91C_US_PAR_ODD)
16431 +// *parity = 'o';
16432 +// }
16434 + mr = UART_GET_MR(port) & AT91C_US_CHRL;
16435 + if (mr == AT91C_US_CHRL_8_BITS)
16436 + *bits = 8;
16437 + else
16438 + *bits = 7;
16440 + quot = UART_GET_BRGR(port);
16441 + *baud = port->uartclk / (16 * (quot));
16444 +static int __init at91_console_setup(struct console *co, char *options)
16446 + struct uart_port *port;
16447 + int baud = AT91C_CONSOLE_DEFAULT_BAUDRATE;
16448 + int bits = 8;
16449 + int parity = 'n';
16450 + int flow = 'n';
16452 + /*
16453 + * Check whether an invalid uart number has been specified, and
16454 + * if so, search for the first available port that does have
16455 + * console support.
16456 + */
16457 + port = uart_get_console(at91_ports, AT91C_NR_UART, co);
16459 + // TODO: The console port should be initialized, and clock enabled if
16460 + // we're not relying on the bootloader to do it.
16462 + if (options)
16463 + uart_parse_options(options, &baud, &parity, &bits, &flow);
16464 + else
16465 + at91_console_get_options(port, &baud, &parity, &bits);
16467 + return uart_set_options(port, co, baud, parity, bits, flow);
16470 +static struct console at91_console = {
16471 + name: "ttyS",
16472 + write: at91_console_write,
16473 + device: at91_console_device,
16474 + setup: at91_console_setup,
16475 + flags: CON_PRINTBUFFER,
16476 + index: AT91C_CONSOLE,
16479 +#define AT91_CONSOLE_DEVICE &at91_console
16481 +void __init at91_console_init(void)
16483 + at91_init_ports();
16484 + register_console(&at91_console);
16487 +#else
16488 +#define AT91_CONSOLE_DEVICE NULL
16489 +#endif
16491 +static struct uart_driver at91_reg = {
16492 + owner: THIS_MODULE,
16493 + normal_major: SERIAL_AT91_MAJOR,
16494 +#ifdef CONFIG_DEVFS_FS
16495 + normal_name: "ttyS%d",
16496 + callout_name: "cua%d",
16497 +#else
16498 + normal_name: "ttyS",
16499 + callout_name: "cua",
16500 +#endif
16501 + normal_driver: &normal,
16502 + callout_major: CALLOUT_AT91_MAJOR,
16503 + callout_driver: &callout,
16504 + table: at91_table,
16505 + termios: at91_termios,
16506 + termios_locked: at91_termios_locked,
16507 + minor: MINOR_START,
16508 + nr: AT91C_NR_UART,
16509 + cons: AT91_CONSOLE_DEVICE,
16512 +static int __init at91_serial_init(void)
16514 + int ret, i;
16516 + at91_init_ports();
16518 + ret = uart_register_driver(&at91_reg);
16519 + if (ret)
16520 + return ret;
16522 + for (i = 0; i < AT91C_NR_UART; i++) {
16523 + if (at91_serialmap[i] >= 0)
16524 + uart_add_one_port(&at91_reg, &at91_ports[i]);
16527 + return 0;
16530 +static void __exit at91_serial_exit(void)
16532 + int i;
16534 + for (i = 0; i < AT91C_NR_UART; i++) {
16535 + if (at91_serialmap[i] >= 0)
16536 + uart_remove_one_port(&at91_reg, &at91_ports[i]);
16539 + uart_unregister_driver(&at91_reg);
16542 +module_init(at91_serial_init);
16543 +module_exit(at91_serial_exit);
16545 +EXPORT_NO_SYMBOLS;
16547 +MODULE_AUTHOR("Rick Bronson");
16548 +MODULE_DESCRIPTION("AT91 generic serial port driver");
16549 +MODULE_LICENSE("GPL");
16550 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
16551 +++ linux-2.4.25/drivers/at91/spi/Makefile 2004-03-31 17:15:09.000000000 +0200
16552 @@ -0,0 +1,17 @@
16553 +# File: drivers/at91/spi/Makefile
16555 +# Makefile for the Atmel AT91RM9200 SPI device drivers
16558 +O_TARGET := at91spi.o
16560 +export-objs := at91_spi.o
16562 +obj-y := at91_spi.o
16563 +obj-m :=
16564 +obj-n :=
16565 +obj- :=
16567 +obj-$(CONFIG_AT91_SPIDEV) += at91_spidev.o
16569 +include $(TOPDIR)/Rules.make
16570 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
16571 +++ linux-2.4.25/drivers/at91/spi/at91_spi.c 2004-03-31 17:15:09.000000000 +0200
16572 @@ -0,0 +1,275 @@
16574 + * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 (Thunder)
16576 + * (c) SAN People (Pty) Ltd
16578 + * This program is free software; you can redistribute it and/or
16579 + * modify it under the terms of the GNU General Public License
16580 + * as published by the Free Software Foundation; either version
16581 + * 2 of the License, or (at your option) any later version.
16582 + */
16584 +#include <linux/init.h>
16585 +#include <linux/module.h>
16586 +#include <asm/semaphore.h>
16587 +#include <linux/pci.h>
16588 +#include <linux/sched.h>
16589 +#include <linux/completion.h>
16591 +#include <asm/arch/AT91RM9200_SPI.h>
16592 +#include <asm/arch/pio.h>
16593 +#include "at91_spi.h"
16595 +#undef DEBUG_SPI
16597 +static struct spi_local spi_dev[NR_SPI_DEVICES]; /* state of the SPI devices */
16598 +static int spi_enabled = 0;
16599 +static struct semaphore spi_lock; /* protect access to SPI bus */
16600 +static int current_device = -1; /* currently selected SPI device */
16602 +DECLARE_COMPLETION(transfer_complete);
16604 +/* SPI controller device */
16605 +AT91PS_SPI controller = (AT91PS_SPI) AT91C_VA_BASE_SPI;
16607 +/* ......................................................................... */
16610 + * Access and enable the SPI bus.
16611 + * This MUST be called before any transfers are performed.
16612 + */
16613 +void spi_access_bus(short device)
16615 + /* Ensure that requested device is valid */
16616 + if ((device < 0) || (device >= NR_SPI_DEVICES))
16617 + panic("at91_spi: spi_access_bus called with invalid device");
16619 + if (spi_enabled == 0) {
16620 + AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Enable Peripheral clock */
16621 + controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
16622 +#ifdef DEBUG_SPI
16623 + printk("SPI on\n");
16624 +#endif
16626 + MOD_INC_USE_COUNT;
16627 + spi_enabled++;
16629 + /* Lock the SPI bus */
16630 + down(&spi_lock);
16631 + current_device = device;
16633 + /* Enable PIO */
16634 + if (!spi_dev[device].pio_enabled) {
16635 + switch (device) {
16636 + case 0: AT91_CfgPIO_SPI_CS0();
16637 + case 1: AT91_CfgPIO_SPI_CS1();
16638 + case 2: AT91_CfgPIO_SPI_CS2();
16639 + case 3: AT91_CfgPIO_SPI_CS3();
16641 + spi_dev[device].pio_enabled = 1;
16642 +#ifdef DEBUG_SPI
16643 + printk("SPI CS%i enabled\n", device);
16644 +#endif
16647 + /* Configure SPI bus for device */
16648 + controller->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (spi_dev[device].pcs << 16);
16652 + * Relinquish control of the SPI bus.
16653 + */
16654 +void spi_release_bus(short device)
16656 + if (device != current_device)
16657 + panic("at91_spi: spi_release called with invalid device");
16659 + /* Release the SPI bus */
16660 + current_device = -1;
16661 + up(&spi_lock);
16663 + spi_enabled--;
16664 + MOD_DEC_USE_COUNT;
16665 + if (spi_enabled == 0) {
16666 + controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
16667 + AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Disable Peripheral clock */
16668 +#ifdef DEBUG_SPI
16669 + printk("SPI off\n");
16670 +#endif
16675 + * Perform a data transfer over the SPI bus
16676 + */
16677 +int spi_transfer(struct spi_transfer_list* list)
16679 + struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
16681 + if (!list)
16682 + panic("at91_spi: spi_transfer called with NULL transfer list");
16683 + if (current_device == -1)
16684 + panic("at91_spi: spi_transfer called without acquiring bus");
16686 +#ifdef DEBUG_SPI
16687 + printk("SPI transfer start [%i]\n", list->nr_transfers);
16688 +#endif
16690 + /* Store transfer list */
16691 + device->xfers = list;
16692 + list->curr = 0;
16694 + /* Assume there must be at least one transfer */
16695 + device->tx = pci_map_single(NULL, list->tx[0], list->txlen[0], PCI_DMA_TODEVICE);
16696 + device->rx = pci_map_single(NULL, list->rx[0], list->rxlen[0], PCI_DMA_FROMDEVICE);
16698 + /* Program PDC registers */
16699 + controller->SPI_TPR = device->tx;
16700 + controller->SPI_RPR = device->rx;
16701 + controller->SPI_TCR = list->txlen[0];
16702 + controller->SPI_RCR = list->rxlen[0];
16704 + /* Is there a second transfer? */
16705 + if (list->nr_transfers > 1) {
16706 + device->txnext = pci_map_single(NULL, list->tx[1], list->txlen[1], PCI_DMA_TODEVICE);
16707 + device->rxnext = pci_map_single(NULL, list->rx[1], list->rxlen[1], PCI_DMA_FROMDEVICE);
16709 + /* Program Next PDC registers */
16710 + controller->SPI_TNPR = device->txnext;
16711 + controller->SPI_RNPR = device->rxnext;
16712 + controller->SPI_TNCR = list->txlen[1];
16713 + controller->SPI_RNCR = list->rxlen[1];
16715 + else {
16716 + device->txnext = 0;
16717 + device->rxnext = 0;
16718 + controller->SPI_TNCR = 0;
16719 + controller->SPI_RNCR = 0;
16722 + // TODO: If we are doing consecutive transfers (at high speed, or
16723 + // small buffers), then it might be worth modifying the 'Delay between
16724 + // Consecutive Transfers' in the CSR registers.
16725 + // This is an issue if we cannot chain the next buffer fast enough
16726 + // in the interrupt handler.
16728 + /* Enable transmitter and receiver */
16729 + controller->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
16731 + controller->SPI_IER = AT91C_SPI_SPENDRX; /* enable buffer complete interrupt */
16732 + wait_for_completion(&transfer_complete);
16734 +#ifdef DEBUG_SPI
16735 + printk("SPI transfer end\n");
16736 +#endif
16738 + return 0;
16741 +/* ......................................................................... */
16744 + * Handle interrupts from the SPI controller.
16745 + */
16746 +void spi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
16748 + unsigned int status;
16749 + struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
16750 + struct spi_transfer_list *list = device->xfers;
16752 +#ifdef DEBUG_SPI
16753 + printk("SPI interrupt %i\n", current_device);
16754 +#endif
16756 + if (!list)
16757 + panic("at91_spi: spi_interrupt with a NULL transfer list");
16759 + status = controller->SPI_SR & controller->SPI_IMR; /* read status */
16761 + pci_unmap_single(NULL, device->tx, list->txlen[list->curr], PCI_DMA_TODEVICE);
16762 + pci_unmap_single(NULL, device->rx, list->rxlen[list->curr], PCI_DMA_FROMDEVICE);
16764 + device->tx = device->txnext; /* move next transfer to current transfer */
16765 + device->rx = device->rxnext;
16767 + list->curr = list->curr + 1;
16768 + if (list->curr == list->nr_transfers) { /* all transfers complete */
16769 + controller->SPI_IDR = AT91C_SPI_SPENDRX; /* disable interrupt */
16771 + /* Disable transmitter and receiver */
16772 + controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
16774 + device->xfers = NULL;
16775 + complete(&transfer_complete);
16777 + else if (list->curr+1 == list->nr_transfers) { /* no more next transfers */
16778 + device->txnext = 0;
16779 + device->rxnext = 0;
16780 + controller->SPI_TNCR = 0;
16781 + controller->SPI_RNCR = 0;
16783 + else {
16784 + int i = (list->curr)+1;
16786 + device->txnext = pci_map_single(NULL, list->tx[i], list->txlen[i], PCI_DMA_TODEVICE);
16787 + device->rxnext = pci_map_single(NULL, list->rx[i], list->rxlen[i], PCI_DMA_FROMDEVICE);
16788 + controller->SPI_TNPR = device->txnext;
16789 + controller->SPI_RNPR = device->rxnext;
16790 + controller->SPI_TNCR = list->txlen[i];
16791 + controller->SPI_RNCR = list->rxlen[i];
16795 +/* ......................................................................... */
16798 + * Initialize the SPI controller
16799 + */
16800 +static int __init at91_spi_init(void)
16802 + init_MUTEX(&spi_lock);
16804 + AT91_CfgPIO_SPI();
16806 + controller->SPI_CR = AT91C_SPI_SWRST; /* software reset of SPI controller */
16808 + /* Set Chip Select registers to good defaults */
16809 + controller->SPI_CSR0 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
16810 + controller->SPI_CSR1 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
16811 + controller->SPI_CSR2 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
16812 + controller->SPI_CSR3 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
16814 + controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
16816 + memset(&spi_dev, 0, sizeof(spi_dev));
16817 + spi_dev[0].pcs = 0xE;
16818 + spi_dev[1].pcs = 0xD;
16819 + spi_dev[2].pcs = 0xB;
16820 + spi_dev[3].pcs = 0x7;
16822 + if (request_irq(AT91C_ID_SPI, spi_interrupt, 0, "spi", NULL))
16823 + return -EBUSY;
16825 + controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
16827 + return 0;
16830 +static void at91_spi_exit(void)
16832 + controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
16834 + free_irq(AT91C_ID_SPI, 0);
16838 +EXPORT_SYMBOL(spi_access_bus);
16839 +EXPORT_SYMBOL(spi_release_bus);
16840 +EXPORT_SYMBOL(spi_transfer);
16842 +module_init(at91_spi_init);
16843 +module_exit(at91_spi_exit);
16845 +MODULE_LICENSE("GPL")
16846 +MODULE_AUTHOR("Andrew Victor")
16847 +MODULE_DESCRIPTION("SPI driver for Atmel AT91RM9200")
16848 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
16849 +++ linux-2.4.25/drivers/at91/spi/at91_spi.h 2004-03-31 17:15:09.000000000 +0200
16850 @@ -0,0 +1,56 @@
16852 + * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200
16854 + * (c) SAN People (Pty) Ltd
16856 + * This program is free software; you can redistribute it and/or
16857 + * modify it under the terms of the GNU General Public License
16858 + * as published by the Free Software Foundation; either version
16859 + * 2 of the License, or (at your option) any later version.
16860 + */
16862 +#ifndef AT91_SPI_H
16863 +#define AT91_SPI_H
16865 +/* Maximum number of buffers in a single SPI transfer.
16866 + * DataFlash uses maximum of 2
16867 + * spidev interface supports up to 8.
16868 + */
16869 +#define MAX_SPI_TRANSFERS 8
16871 +#define NR_SPI_DEVICES 4 /* number of devices on SPI bus */
16873 +#define DATAFLASH_CLK 6000000
16874 +#define DEFAULT_SPI_BAUD AT91C_MASTER_CLOCK / (2 * DATAFLASH_CLK)
16876 +#define SPI_MAJOR 153 /* registered device number */
16879 + * Describes the buffers for a SPI transfer.
16880 + * A transmit & receive buffer must be specified for each transfer
16881 + */
16882 +struct spi_transfer_list {
16883 + void* tx[MAX_SPI_TRANSFERS]; /* transmit */
16884 + int txlen[MAX_SPI_TRANSFERS];
16885 + void* rx[MAX_SPI_TRANSFERS]; /* receive */
16886 + int rxlen[MAX_SPI_TRANSFERS];
16887 + int nr_transfers; /* number of transfers */
16888 + int curr; /* current transfer */
16891 +struct spi_local {
16892 + unsigned int pcs; /* Peripheral Chip Select value */
16893 + short pio_enabled; /* has PIO been enabled? */
16895 + struct spi_transfer_list *xfers; /* current transfer list */
16896 + dma_addr_t tx, rx; /* DMA address for current transfer */
16897 + dma_addr_t txnext, rxnext; /* DMA address for next transfer */
16901 +/* Exported functions */
16902 +extern void spi_access_bus(short device);
16903 +extern void spi_release_bus(short device);
16904 +extern int spi_transfer(struct spi_transfer_list* list);
16906 +#endif
16907 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
16908 +++ linux-2.4.25/drivers/at91/spi/at91_spidev.c 2004-03-31 17:15:09.000000000 +0200
16909 @@ -0,0 +1,226 @@
16911 + * User-space interface to the SPI bus on Atmel AT91RM9200
16913 + * (c) SAN People (Pty) Ltd
16915 + * Based on SPI driver by Rick Bronson
16917 + * This program is free software; you can redistribute it and/or
16918 + * modify it under the terms of the GNU General Public License
16919 + * as published by the Free Software Foundation; either version
16920 + * 2 of the License, or (at your option) any later version.
16921 + */
16923 +#include <linux/module.h>
16924 +#include <linux/config.h>
16925 +#include <linux/init.h>
16926 +#include <linux/slab.h>
16927 +#include <linux/iobuf.h>
16928 +#include <linux/highmem.h>
16930 +#ifdef CONFIG_DEVFS_FS
16931 +#include <linux/devfs_fs_kernel.h>
16932 +#endif
16934 +#include "at91_spi.h"
16936 +#undef DEBUG_SPIDEV
16938 +#ifdef CONFIG_DEVFS_FS
16939 +static devfs_handle_t devfs_handle = NULL;
16940 +static devfs_handle_t devfs_spi[NR_SPI_DEVICES];
16941 +#endif
16943 +/* ......................................................................... */
16946 + * Read or Write to SPI bus.
16947 + */
16948 +static ssize_t spidev_rd_wr(struct file *file, char *buf, size_t count, loff_t *offset)
16950 + unsigned int spi_device = (unsigned int) file->private_data;
16951 + struct kiobuf *iobuf;
16952 + unsigned int ofs, pagelen;
16953 + int res, i;
16955 + struct spi_transfer_list* list = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
16956 + if (!list)
16957 + return -ENOMEM;
16959 + res = alloc_kiovec(1, &iobuf);
16960 + if (res) {
16961 + kfree(list);
16962 + return res;
16965 + res = map_user_kiobuf(READ, iobuf, (unsigned long) buf, count);
16966 + if (res) {
16967 + free_kiovec(1, &iobuf);
16968 + kfree(list);
16969 + return res;
16972 + /* More pages than transfer slots in spi_transfer_list */
16973 + if (iobuf->nr_pages >= MAX_SPI_TRANSFERS) {
16974 + unmap_kiobuf(iobuf);
16975 + free_kiovec(1, &iobuf);
16976 + kfree(list);
16977 + return -EFBIG;
16980 +#ifdef DEBUG_SPIDEV
16981 + printk("spidev_rd_rw: %i %i\n", count, iobuf->nr_pages);
16982 +#endif
16984 + /* Set default return value = transfer length */
16985 + res = count;
16987 + /*
16988 + * At this point, the virtual area buf[0] .. buf[count-1] will have
16989 + * corresponding pages mapped in the physical memory and locked until
16990 + * we unmap the kiobuf. The pages cannot be swapped out or moved
16991 + * around.
16992 + */
16993 + ofs = iobuf->offset;
16994 + pagelen = PAGE_SIZE - iobuf->offset;
16995 + if (count < pagelen)
16996 + pagelen = count;
16998 + for (i = 0; i < iobuf->nr_pages; i++) {
16999 + list->tx[i] = list->rx[i] = page_address(iobuf->maplist[i]) + ofs;
17000 + list->txlen[i] = list->rxlen[i] = pagelen;
17002 +#ifdef DEBUG_SPIDEV
17003 + printk(" %i: %x (%i)\n", i, list->tx[i], list->txlen[i]);
17004 +#endif
17006 + ofs = 0; /* all subsequent transfers start at beginning of a page */
17007 + count = count - pagelen;
17008 + pagelen = (count < PAGE_SIZE) ? count : PAGE_SIZE;
17010 + list->nr_transfers = iobuf->nr_pages;
17012 + /* Perform transfer on SPI bus */
17013 + spi_access_bus(spi_device);
17014 + spi_transfer(list);
17015 + spi_release_bus(spi_device);
17017 + unmap_kiobuf(iobuf);
17018 + free_kiovec(1, &iobuf);
17019 + kfree(list);
17021 + return res;
17024 +int spidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
17026 + int spi_device = MINOR(inode->i_rdev);
17028 + if (spi_device >= NR_SPI_DEVICES)
17029 + return -ENODEV;
17031 + // TODO: This interface can be used to configure the SPI bus.
17032 + // Configurable options could include: Speed, Clock Polarity, Clock Phase
17034 + switch(cmd) {
17035 + default:
17036 + return -ENOIOCTLCMD;
17041 + * Open the SPI device
17042 + */
17043 +int spidev_open(struct inode *inode, struct file *file)
17045 + unsigned int spi_device = MINOR(inode->i_rdev);
17047 + if (spi_device >= NR_SPI_DEVICES)
17048 + return -ENODEV;
17050 + MOD_INC_USE_COUNT;
17052 + /*
17053 + * 'private_data' is actually a pointer, but we overload it with the
17054 + * value we want to store.
17055 + */
17056 + (unsigned int) file->private_data = spi_device;
17058 + return 0;
17062 + * Close the SPI device
17063 + */
17064 +static int spidev_close(struct inode *inode, struct file *file)
17066 + MOD_DEC_USE_COUNT;
17067 + return 0;
17070 +/* ......................................................................... */
17072 +static struct file_operations spidev_fops = {
17073 + owner: THIS_MODULE,
17074 + llseek: no_llseek,
17075 + read: spidev_rd_wr,
17076 + write: spidev_rd_wr,
17077 + ioctl: spidev_ioctl,
17078 + open: spidev_open,
17079 + release: spidev_close,
17083 + * Install the SPI /dev interface driver
17084 + */
17085 +static int __init at91_spidev_init(void)
17087 + int i;
17088 + char name[3];
17090 +#ifdef CONFIG_DEVFS_FS
17091 + if (devfs_register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
17092 +#else
17093 + if (register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
17094 +#endif
17095 + printk(KERN_ERR "at91_spidev: Unable to get major %d for SPI bus\n", SPI_MAJOR);
17096 + return -EIO;
17099 +#ifdef CONFIG_DEVFS_FS
17100 + devfs_handle = devfs_mk_dir(NULL, "spi", NULL);
17102 + for (i = 0; i < NR_SPI_DEVICES; i++) {
17103 + sprintf (name, "%d", i);
17104 + devfs_spi[i] = devfs_register (devfs_handle, name,
17105 + DEVFS_FL_DEFAULT, SPI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
17106 + &spidev_fops, NULL);
17108 +#endif
17109 + printk(KERN_INFO "AT91 SPI driver loaded\n");
17111 + return 0;
17115 + * Remove the SPI /dev interface driver
17116 + */
17117 +static void at91_spidev_exit(void)
17119 +#ifdef CONFIG_DEVFS_FS
17120 + devfs_unregister(devfs_handle);
17121 + if (devfs_unregister_chrdev(SPI_MAJOR, "spi")) {
17122 +#else
17123 + if (unregister_chrdev(SPI_MAJOR,"spi")) {
17124 +#endif
17125 + printk(KERN_ERR "at91_spidev: Unable to release major %d for SPI bus\n", SPI_MAJOR);
17126 + return;
17130 +module_init(at91_spidev_init);
17131 +module_exit(at91_spidev_exit);
17133 +MODULE_LICENSE("GPL")
17134 +MODULE_AUTHOR("Andrew Victor")
17135 +MODULE_DESCRIPTION("SPI /dev interface for Atmel AT91RM9200")
17136 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
17137 +++ linux-2.4.25/drivers/at91/usb/Makefile 2004-03-31 17:15:09.000000000 +0200
17138 @@ -0,0 +1,17 @@
17139 +# File: drivers/at91/usb/Makefile
17141 +# Makefile for the Atmel AT91RM9200 USB device drivers
17144 +O_TARGET := at91usb.o
17146 +export-objs :=
17148 +obj-y :=
17149 +obj-m :=
17150 +obj-n :=
17151 +obj- :=
17153 +obj-$(CONFIG_USB_OHCI_AT91) += at91_usb-ohci.o
17155 +include $(TOPDIR)/Rules.make
17156 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
17157 +++ linux-2.4.25/drivers/at91/usb/at91_usb-ohci.c 2004-03-31 17:15:09.000000000 +0200
17158 @@ -0,0 +1,81 @@
17160 + * linux/drivers/at91/usb/at91_usb_ohci-at91.c
17162 + * (c) Rick Bronson
17164 + * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
17165 + * original OHCI driver modifications, and reworked into a cleaner form
17166 + * by Russell King <rmk@arm.linux.org.uk>.
17167 + */
17169 +#include <linux/module.h>
17170 +#include <linux/init.h>
17171 +#include <linux/sched.h>
17172 +#include <linux/ioport.h>
17173 +#include <linux/interrupt.h>
17174 +#include <linux/slab.h>
17175 +#include <linux/usb.h>
17176 +#include <asm/hardware.h>
17177 +#include <asm/irq.h>
17178 +#include <asm/io.h>
17180 +#include <asm/arch/AT91RM9200_UHP.h>
17183 + NOTE:
17184 + The following is so that we don't have to include usb-ohci.h or pci.h as the
17185 + usb-ohci.c driver needs these routines even when the architecture
17186 + has no PCI bus...
17189 +extern int __devinit hc_add_ohci(struct pci_dev *dev, int irq, void *membase,
17190 + unsigned long flags, void *ohci, const char *name,
17191 + const char *slot_name);
17192 +extern void hc_remove_ohci(void *ohci);
17194 +static void *at91_ohci;
17195 +AT91PS_UHP ohci_regs;
17197 +static int __init at91_ohci_init(void)
17199 + int ret;
17201 + ohci_regs = ioremap(AT91_UHP_BASE, SZ_4K);
17202 + if (!ohci_regs) {
17203 + printk(KERN_ERR "at91_usb-ohci: ioremap failed\n");
17204 + return -EIO;
17207 + /* Now, enable the USB clock */
17208 + AT91_SYS->PMC_SCER = AT91C_PMC_UHP; /* enable system clock */
17209 + AT91_SYS->PMC_PCER = 1 << AT91C_ID_UHP; /* enable peripheral clock */
17211 + /* Take Hc out of reset */
17212 + ohci_regs->UHP_HcControl = 2 << 6;
17214 + /* Initialise the generic OHCI driver. */
17215 + ret = hc_add_ohci((struct pci_dev *) 1, AT91C_ID_UHP,
17216 + (void *)ohci_regs, 0, &at91_ohci,
17217 + "usb-ohci", "at91");
17218 + if (ret)
17219 + iounmap(ohci_regs);
17221 + return ret;
17224 +static void __exit at91_ohci_exit(void)
17226 + hc_remove_ohci(at91_ohci);
17228 + /* Force UHP_Hc to reset */
17229 + ohci_regs->UHP_HcControl = 0;
17231 + /* Stop the USB clock. */
17232 + AT91_SYS->PMC_SCDR = AT91C_PMC_UHP; /* disable system clock */
17233 + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_UHP; /* disable peripheral clock */
17235 + iounmap(ohci_regs);
17238 +module_init(at91_ohci_init);
17239 +module_exit(at91_ohci_exit);
17240 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
17241 +++ linux-2.4.25/drivers/at91/watchdog/Makefile 2004-03-31 17:15:09.000000000 +0200
17242 @@ -0,0 +1,15 @@
17243 +# File: drivers/at91/watchdog/Makefile
17245 +# Makefile for the Atmel AT91RM9200 watchdog device driver
17248 +O_TARGET := at91wdt.o
17250 +obj-y :=
17251 +obj-m :=
17252 +obj-n :=
17253 +obj- :=
17255 +obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
17257 +include $(TOPDIR)/Rules.make
17258 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
17259 +++ linux-2.4.25/drivers/at91/watchdog/at91_wdt.c 2004-03-31 17:15:09.000000000 +0200
17260 @@ -0,0 +1,193 @@
17262 + * Watchdog driver for Atmel AT91RM9200 (Thunder)
17264 + * (c) SAN People (Pty) Ltd
17266 + * This program is free software; you can redistribute it and/or
17267 + * modify it under the terms of the GNU General Public License
17268 + * as published by the Free Software Foundation; either version
17269 + * 2 of the License, or (at your option) any later version.
17270 + */
17272 +#include <linux/module.h>
17273 +#include <linux/config.h>
17274 +#include <linux/miscdevice.h>
17275 +#include <linux/watchdog.h>
17276 +#include <asm/uaccess.h>
17277 +#include <linux/init.h>
17279 +#define WDT_DEFAULT_TIME 5 /* 5 seconds */
17280 +#define WDT_MAX_TIME 256 /* 256 seconds */
17282 +static int at91wdt_time = WDT_DEFAULT_TIME;
17283 +static int at91wdt_busy;
17285 +/* ......................................................................... */
17288 + * Disable the watchdog.
17289 + */
17290 +void at91_wdt_stop(void)
17292 + AT91_SYS->ST_WDMR = AT91C_ST_EXTEN;
17296 + * Enable and reset the watchdog.
17297 + */
17298 +void at91_wdt_start(void)
17300 + AT91_SYS->ST_WDMR = AT91C_ST_EXTEN | AT91C_ST_RSTEN | (((65536 * at91wdt_time) >> 8) & AT91C_ST_WDV);
17301 + AT91_SYS->ST_CR = AT91C_ST_WDRST;
17304 +/* ......................................................................... */
17307 + * Watchdog device is opened, and watchdog starts running.
17308 + */
17309 +static int at91_wdt_open(struct inode *inode, struct file *file)
17311 + if (test_and_set_bit(1, &at91wdt_busy))
17312 + return -EBUSY;
17313 + MOD_INC_USE_COUNT;
17315 + /*
17316 + * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
17318 + * Since WDV is a 16-bit counter, the maximum period is
17319 + * 65536 / 0.256 = 256 seconds.
17320 + */
17322 + at91_wdt_start();
17323 + return 0;
17327 + * Close the watchdog device.
17328 + * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
17329 + * disabled.
17330 + */
17331 +static int at91_wdt_close(struct inode *inode, struct file *file)
17333 +#ifndef CONFIG_WATCHDOG_NOWAYOUT
17334 + /* Disable the watchdog when file is closed */
17335 + at91_wdt_stop();
17336 +#endif
17338 + at91wdt_busy = 0;
17339 + MOD_DEC_USE_COUNT;
17340 + return 0;
17344 + * Handle commands from user-space.
17345 + */
17346 +static int at91_wdt_ioctl(struct inode *inode, struct file *file,
17347 + unsigned int cmd, unsigned long arg)
17349 + unsigned int new_value;
17350 + static struct watchdog_info info = {
17351 + identity: "at91 watchdog",
17352 + options: WDIOF_SETTIMEOUT,
17353 + };
17355 + switch(cmd) {
17356 + case WDIOC_KEEPALIVE:
17357 + AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
17358 + return 0;
17360 + case WDIOC_GETSUPPORT:
17361 + return copy_to_user((struct watchdog_info *)arg, &info, sizeof(info));
17363 + case WDIOC_SETTIMEOUT:
17364 + if (get_user(new_value, (int *)arg))
17365 + return -EFAULT;
17366 + if ((new_value <= 0) || (new_value > WDT_MAX_TIME))
17367 + return -EINVAL;
17369 + /* Restart watchdog with new time */
17370 + at91wdt_time = new_value;
17371 + at91_wdt_start();
17373 + /* Return current value */
17374 + return put_user(at91wdt_time, (int *)arg);
17376 + case WDIOC_GETTIMEOUT:
17377 + return put_user(at91wdt_time, (int *)arg);
17379 + case WDIOC_GETSTATUS:
17380 + return put_user(0, (int *)arg);
17382 + case WDIOC_SETOPTIONS:
17383 + if (get_user(new_value, (int *)arg))
17384 + return -EFAULT;
17385 + if (new_value & WDIOS_DISABLECARD)
17386 + at91_wdt_stop();
17387 + if (new_value & WDIOS_ENABLECARD)
17388 + at91_wdt_start();
17389 + return 0;
17391 + default:
17392 + return -ENOIOCTLCMD;
17397 + * Pat the watchdog whenever device is written to.
17398 + */
17399 +static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
17401 + /* Can't seek (pwrite) on this device */
17402 + if (ppos != &file->f_pos)
17403 + return -ESPIPE;
17405 + if (len) {
17406 + AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
17407 + return len;
17410 + return 0;
17413 +/* ......................................................................... */
17415 +static struct file_operations at91wdt_fops =
17417 + .owner = THIS_MODULE,
17418 + .ioctl = at91_wdt_ioctl,
17419 + .open = at91_wdt_open,
17420 + .release = at91_wdt_close,
17421 + .write = at91_wdt_write,
17424 +static struct miscdevice at91wdt_miscdev =
17426 + .minor = WATCHDOG_MINOR,
17427 + .name = "watchdog",
17428 + .fops = &at91wdt_fops,
17431 +static int __init at91_wdt_init(void)
17433 + int res;
17435 + res = misc_register(&at91wdt_miscdev);
17436 + if (res)
17437 + return res;
17439 + printk("AT91 Watchdog Timer enabled (%d seconds)\n", WDT_DEFAULT_TIME);
17440 + return 0;
17443 +static void __exit at91_wdt_exit(void)
17445 + misc_deregister(&at91wdt_miscdev);
17448 +module_init(at91_wdt_init);
17449 +module_exit(at91_wdt_exit);
17451 +MODULE_LICENSE("GPL")
17452 +MODULE_AUTHOR("Andrew Victor")
17453 +MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200")
17454 --- linux-2.4.25/drivers/block/Makefile~2.4.25-vrs2.patch 2003-06-13 16:51:32.000000000 +0200
17455 +++ linux-2.4.25/drivers/block/Makefile 2004-03-31 17:15:09.000000000 +0200
17456 @@ -27,11 +27,17 @@
17457 obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o
17458 obj-$(CONFIG_BLK_DEV_XD) += xd.o
17459 obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
17460 -obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
17461 +obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
17462 obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
17463 obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
17464 obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
17466 subdir-$(CONFIG_PARIDE) += paride
17468 +ifeq ($(CONFIG_ARCH_ACORN),y)
17469 +mod-subdirs += ../acorn/block
17470 +subdir-y += ../acorn/block
17471 +obj-y += ../acorn/block/acorn-block.o
17472 +endif
17474 include $(TOPDIR)/Rules.make
17475 --- linux-2.4.25/drivers/block/ll_rw_blk.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
17476 +++ linux-2.4.25/drivers/block/ll_rw_blk.c 2004-03-31 17:15:09.000000000 +0200
17477 @@ -32,6 +32,19 @@
17478 #include <linux/slab.h>
17479 #include <linux/module.h>
17481 +/* Maybe something to cleanup in 2.3?
17482 + * We shouldn't touch 0x3f2 on machines which don't have a PC floppy controller
17483 + * - it may contain something else which could cause a system hang. This is
17484 + * now selected by a configuration option, but maybe it ought to be in the
17485 + * floppy code itself? - rmk
17486 + */
17487 +#if defined(__i386__) || (defined(__arm__) && defined(CONFIG_ARCH_ACORN))
17488 +#define FLOPPY_BOOT_DISABLE
17489 +#endif
17490 +#ifdef CONFIG_BLK_DEV_FD
17491 +#undef FLOPPY_BOOT_DISABLE
17492 +#endif
17495 * MAC Floppy IWM hooks
17497 @@ -524,7 +537,7 @@
17498 elevator_init(&q->elevator, ELEVATOR_LINUS);
17499 blk_init_free_list(q);
17500 q->request_fn = rfn;
17501 - q->back_merge_fn = ll_back_merge_fn;
17502 + q->back_merge_fn = ll_back_merge_fn;
17503 q->front_merge_fn = ll_front_merge_fn;
17504 q->merge_requests_fn = ll_merge_requests_fn;
17505 q->make_request_fn = __make_request;
17506 @@ -1540,7 +1553,7 @@
17507 mfm_init();
17508 #endif
17509 #ifdef CONFIG_PARIDE
17510 - { extern void paride_init(void); paride_init(); };
17511 + { extern void paride_init(void); paride_init(); }
17512 #endif
17513 #ifdef CONFIG_MAC_FLOPPY
17514 swim3_init();
17515 @@ -1554,12 +1567,14 @@
17516 #ifdef CONFIG_ATARI_FLOPPY
17517 atari_floppy_init();
17518 #endif
17519 +#ifdef CONFIG_BLK_DEV_FD1772
17520 + fd1772_init();
17521 +#endif
17522 #ifdef CONFIG_BLK_DEV_FD
17523 floppy_init();
17524 -#else
17525 -#if defined(__i386__) /* Do we even need this? */
17526 - outb_p(0xc, 0x3f2);
17527 #endif
17528 +#ifdef FLOPPY_BOOT_DISABLE
17529 + outb_p(0xc, 0x3f2);
17530 #endif
17531 #ifdef CONFIG_CDU31A
17532 cdu31a_init();
17533 @@ -1617,7 +1632,7 @@
17534 jsfd_init();
17535 #endif
17536 return 0;
17540 EXPORT_SYMBOL(io_request_lock);
17541 EXPORT_SYMBOL(end_that_request_first);
17542 --- linux-2.4.25/drivers/cdrom/cdrom.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
17543 +++ linux-2.4.25/drivers/cdrom/cdrom.c 2004-03-31 17:15:09.000000000 +0200
17544 @@ -246,8 +246,8 @@
17545 #define CD_DVD 0x80
17547 /* Define this to remove _all_ the debugging messages */
17548 -/* #define ERRLOGMASK CD_NOTHING */
17549 -#define ERRLOGMASK (CD_WARNING)
17550 +#define ERRLOGMASK CD_NOTHING
17551 +/* #define ERRLOGMASK (CD_WARNING) */
17552 /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
17553 /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
17555 --- linux-2.4.25/drivers/char/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
17556 +++ linux-2.4.25/drivers/char/Config.in 2004-03-31 17:15:09.000000000 +0200
17557 @@ -20,10 +20,10 @@
17558 if [ "$CONFIG_IA64" = "y" ]; then
17559 bool ' Support for serial port described by EFI HCDP table' CONFIG_SERIAL_HCDP
17561 - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
17562 - tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
17563 - tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
17564 - fi
17566 +if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
17567 + dep_tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL $CONFIG_SERIAL
17568 + dep_tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL $CONFIG_SERIAL
17570 dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
17571 if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
17572 @@ -132,18 +132,6 @@
17573 bool ' SGI SN2 IOC4 serial port support' CONFIG_SGI_IOC4_SERIAL
17577 -if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
17578 - tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
17580 -if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
17581 - bool 'DC21285 serial port support' CONFIG_SERIAL_21285
17582 - if [ "$CONFIG_SERIAL_21285" = "y" ]; then
17583 - if [ "$CONFIG_OBSOLETE" = "y" ]; then
17584 - bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD
17585 - fi
17586 - bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE
17587 - fi
17588 if [ "$CONFIG_PARISC" = "y" ]; then
17589 bool ' PDC software console support' CONFIG_PDC_CONSOLE
17591 @@ -168,6 +156,16 @@
17592 if [ "$CONFIG_CPU_VR41XX" = "y" ]; then
17593 bool 'NEC VR4100 series Keyboard Interface Unit Support ' CONFIG_VR41XX_KIU
17595 +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
17596 + tristate 'AT91RM9200 SPI device interface' CONFIG_AT91_SPIDEV
17599 +source drivers/serial/Config.in
17601 +if [ "$CONFIG_ARCH_ANAKIN" = "y" ]; then
17602 + tristate 'Anakin touchscreen support' CONFIG_TOUCHSCREEN_ANAKIN
17605 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
17606 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
17607 int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
17608 @@ -190,6 +188,12 @@
17610 source drivers/i2c/Config.in
17612 +if [ "$CONFIG_I2C" != "n" ]; then
17613 + dep_tristate ' DS1307 RTC' CONFIG_I2C_DS1307 $CONFIG_I2C
17616 +source drivers/l3/Config.in
17618 mainmenu_option next_comment
17619 comment 'Mice'
17620 tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
17621 @@ -245,11 +249,13 @@
17622 tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT
17623 tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT
17624 tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
17625 - if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
17626 - tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG
17627 - if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
17628 - tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG
17629 - fi
17630 + if [ "$CONFIG_ARM" = "y" ]; then
17631 + dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE
17632 + dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER
17633 + dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100
17634 + dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT
17635 + dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA
17636 + dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200
17638 tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT
17639 tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
17640 @@ -326,6 +332,15 @@
17641 if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then
17642 tristate 'Dallas DS1742 RTC support' CONFIG_DS1742
17644 +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
17645 + tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC
17647 +if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
17648 + tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC
17650 +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
17651 + tristate 'AT91RM9200 Real Time Clock' CONFIG_AT91_RTC
17654 tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
17655 tristate 'Siemens R3964 line discipline' CONFIG_R3964
17656 --- linux-2.4.25/drivers/char/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
17657 +++ linux-2.4.25/drivers/char/Makefile 2004-03-31 17:15:09.000000000 +0200
17658 @@ -29,7 +29,7 @@
17660 mod-subdirs := joystick ftape drm drm-4.0 pcmcia
17662 -list-multi :=
17663 +list-multi :=
17665 KEYMAP =defkeymap.o
17666 KEYBD =pc_keyb.o
17667 @@ -106,11 +106,39 @@
17668 endif
17670 ifeq ($(ARCH),arm)
17671 - ifneq ($(CONFIG_PC_KEYMAP),y)
17672 - KEYMAP =
17673 + KEYMAP :=
17674 + KEYBD :=
17675 + ifeq ($(CONFIG_PC_KEYMAP),y)
17676 + KEYMAP := defkeymap.o
17677 endif
17678 - ifneq ($(CONFIG_PC_KEYB),y)
17679 - KEYBD =
17680 + ifeq ($(CONFIG_PC_KEYB),y)
17681 + KEYBD += pc_keyb.o
17682 + endif
17683 + ifeq ($(CONFIG_KMI_KEYB),y)
17684 + KEYBD += amba_kmi_keyb.o
17685 + endif
17686 + ifeq ($(CONFIG_SA1111),y)
17687 + KEYBD += sa1111_keyb.o
17688 + endif
17689 + ifeq ($(CONFIG_ARCH_EDB7211),y)
17690 + KEYBD += edb7211_keyb.o
17691 + endif
17692 + ifeq ($(CONFIG_ARCH_AUTCPU12),y)
17693 + KEYMAP := defkeymap.o
17694 + KEYBD += clps711x_keyb.o
17695 + endif
17696 + ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
17697 + KEYMAP = gckeymap.o
17698 + KEYBD += gc_keyb.o
17699 + endif
17700 + ifeq ($(CONFIG_SA1100_CERF_CPLD),y)
17701 + KEYBD += cerf_keyb.o
17702 + endif
17703 + ifeq ($(CONFIG_ARCH_FORTUNET),y)
17704 + KEYMAP := defkeymap.o
17705 + endif
17706 + ifeq ($(CONFIG_ARCH_GUIDEA07),y)
17707 + KEYMAP := defkeymap.o
17708 endif
17709 endif
17711 @@ -172,11 +200,9 @@
17712 obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
17713 obj-$(CONFIG_SERIAL) += $(SERIAL)
17714 obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
17715 -obj-$(CONFIG_SERIAL_21285) += serial_21285.o
17716 -obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
17717 -obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o
17718 obj-$(CONFIG_TS_AU1X00_ADS7846) += au1000_ts.o
17719 obj-$(CONFIG_SERIAL_DEC) += decserial.o
17720 +obj-$(CONFIG_TOUCHSCREEN_ANAKIN) += anakin_ts.o
17722 ifndef CONFIG_SUN_KEYBOARD
17723 obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD)
17724 @@ -253,6 +279,8 @@
17725 obj-$(CONFIG_SGI_DS1286) += ds1286.o
17726 obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
17727 obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
17728 +obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
17729 +obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o
17730 ifeq ($(CONFIG_PPC),)
17731 obj-$(CONFIG_NVRAM) += nvram.o
17732 endif
17733 @@ -291,6 +319,7 @@
17734 obj-$(CONFIG_NWFLASH) += nwflash.o
17735 obj-$(CONFIG_SCx200) += scx200.o
17736 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
17737 +obj-$(CONFIG_SA1100_CONSUS) += consusbutton.o
17739 # Only one watchdog can succeed. We probe the hardware watchdog
17740 # drivers first, then the softdog driver. This means if your hardware
17741 @@ -319,16 +348,28 @@
17742 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
17743 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
17744 obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
17745 +obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
17746 +obj-$(CONFIG_EPXA_WATCHDOG) += epxa_wdt.o
17747 +obj-$(CONFIG_OMAHA_WATCHDOG) += omaha_wdt.o
17748 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
17749 obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o
17750 obj-$(CONFIG_INDYDOG) += indydog.o
17751 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
17753 +# I2C char devices
17754 +obj-$(CONFIG_I2C_DS1307) += ds1307.o
17756 subdir-$(CONFIG_MWAVE) += mwave
17757 ifeq ($(CONFIG_MWAVE),y)
17758 obj-y += mwave/mwave.o
17759 endif
17761 +ifeq ($(CONFIG_ARCH_ACORN),y)
17762 +mod-subdirs += ../acorn/char
17763 +subdir-y += ../acorn/char
17764 +obj-y += ../acorn/char/acorn-char.o
17765 +endif
17767 subdir-$(CONFIG_IPMI_HANDLER) += ipmi
17768 ifeq ($(CONFIG_IPMI_HANDLER),y)
17769 obj-y += ipmi/ipmi.o
17770 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
17771 +++ linux-2.4.25/drivers/char/amba_kmi_keyb.c 2004-03-31 17:15:09.000000000 +0200
17772 @@ -0,0 +1,999 @@
17774 + * linux/drivers/char/amba_kmi_keyb.c
17776 + * AMBA Keyboard and Mouse Interface Driver
17778 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
17780 + * This program is free software; you can redistribute it and/or modify
17781 + * it under the terms of the GNU General Public License as published by
17782 + * the Free Software Foundation; either version 2 of the License, or
17783 + * (at your option) any later version.
17785 + * This program is distributed in the hope that it will be useful,
17786 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17787 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17788 + * GNU General Public License for more details.
17790 + * You should have received a copy of the GNU General Public License
17791 + * along with this program; if not, write to the Free Software
17792 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17794 + * This keyboard driver drives a PS/2 keyboard and mouse connected
17795 + * to the KMI interfaces. The KMI interfaces are nothing more than
17796 + * a uart; there is no inteligence in them to do keycode translation.
17797 + * We leave all that up to the keyboard itself.
17799 + * FIXES:
17800 + * dirk.uffmann@nokia.com: enabled PS/2 reconnection
17801 + */
17802 +#include <linux/config.h>
17803 +#include <linux/kernel.h>
17804 +#include <linux/sched.h>
17805 +#include <linux/interrupt.h> /* for in_interrupt */
17806 +#include <linux/timer.h>
17807 +#include <linux/init.h>
17808 +#include <linux/delay.h> /* for udelay */
17809 +#include <linux/kbd_kern.h> /* for keyboard_tasklet */
17810 +#include <linux/kbd_ll.h>
17812 +#include <asm/io.h>
17813 +#include <asm/hardware/amba_kmi.h>
17814 +#include <asm/mach/amba_kmi.h>
17815 +#include <asm/keyboard.h>
17817 +//#define DEBUG(s) printk s
17818 +#define DEBUG(s) do { } while (0)
17820 +#define CONFIG_AMBA_PS2_RECONNECT
17822 +#define KMI_BASE (kmi->base)
17824 +#define KMI_RESET 0x00
17825 +#define KMI_RESET_POR 0x01
17826 +#define KMI_RESET_DONE 0x02
17828 +#define KMI_NO_ACK 0xffff
17830 +#define PS2_O_RESET 0xff
17831 +#define PS2_O_RESEND 0xfe
17832 +#define PS2_O_DISABLE 0xf5
17833 +#define PS2_O_ENABLE 0xf4
17834 +#define PS2_O_ECHO 0xee
17837 + * Keyboard
17838 + */
17839 +#define PS2_O_SET_DEFAULT 0xf6
17840 +#define PS2_O_SET_RATE_DELAY 0xf3
17841 +#define PS2_O_SET_SCANSET 0xf0
17842 +#define PS2_O_INDICATORS 0xed
17845 + * Mouse
17846 + */
17847 +#define PS2_O_SET_SAMPLE 0xf3
17848 +#define PS2_O_SET_STREAM 0xea
17849 +#define PS2_O_SET_RES 0xe8
17850 +#define PS2_O_SET_SCALE21 0xe7
17851 +#define PS2_O_SET_SCALE11 0xe6
17852 +#define PS2_O_REQ_STATUS 0xe9
17855 + * Responses
17856 + */
17857 +#define PS2_I_RESEND 0xfe
17858 +#define PS2_I_DIAGFAIL 0xfc
17859 +#define PS2_I_ACK 0xfa
17860 +#define PS2_I_BREAK 0xf0
17861 +#define PS2_I_ECHO 0xee
17862 +#define PS2_I_BAT_OK 0xaa
17864 +static char *kmi_type[] = { "Keyboard", "Mouse" };
17866 +static struct kmi_info *kmi_keyb;
17867 +static struct kmi_info *kmi_mouse;
17869 +static inline void __kmi_send(struct kmi_info *kmi, u_int val)
17871 + u_int status;
17873 + do {
17874 + status = __raw_readb(KMISTAT);
17875 + } while (!(status & KMISTAT_TXEMPTY));
17877 + kmi->resend_count += 1;
17878 + __raw_writeb(val, KMIDATA);
17881 +static void kmi_send(struct kmi_info *kmi, u_int val)
17883 + kmi->last_tx = val;
17884 + kmi->resend_count = -1;
17885 + __kmi_send(kmi, val);
17888 +static u_int kmi_send_and_wait(struct kmi_info *kmi, u_int val, u_int timeo)
17890 + DECLARE_WAITQUEUE(wait, current);
17892 + if (kmi->present == 0)
17893 + return KMI_NO_ACK;
17895 + kmi->res = KMI_NO_ACK;
17896 + kmi->last_tx = val;
17897 + kmi->resend_count = -1;
17899 + if (current->pid != 0 && !in_interrupt()) {
17900 + add_wait_queue(&kmi->wait_q, &wait);
17901 + set_current_state(TASK_UNINTERRUPTIBLE);
17902 + __kmi_send(kmi, val);
17903 + schedule_timeout(timeo);
17904 + current->state = TASK_RUNNING;
17905 + remove_wait_queue(&kmi->wait_q, &wait);
17906 + } else {
17907 + int i;
17909 + __kmi_send(kmi, val);
17910 + for (i = 0; i < 1000; i++) {
17911 + if (kmi->res != KMI_NO_ACK)
17912 + break;
17913 + udelay(100);
17917 + return kmi->res;
17921 + * This lot should probably be separated into a separate file...
17922 + */
17923 +#ifdef CONFIG_KMI_MOUSE
17925 +#include <linux/fs.h> /* for struct file_ops */
17926 +#include <linux/poll.h> /* for poll_table */
17927 +#include <linux/miscdevice.h> /* for struct miscdev */
17928 +#include <linux/random.h> /* for add_mouse_randomness */
17929 +#include <linux/slab.h> /* for kmalloc */
17930 +#include <linux/smp_lock.h> /* for {un,}lock_kernel */
17931 +#include <linux/spinlock.h>
17933 +#include <asm/uaccess.h>
17935 +#define BUF_SZ 2048
17937 +static spinlock_t kmi_mouse_lock;
17938 +static int kmi_mouse_count;
17939 +static struct queue {
17940 + u_int head;
17941 + u_int tail;
17942 + struct fasync_struct *fasync;
17943 + unsigned char buf[BUF_SZ];
17944 +} *queue;
17946 +#define queue_empty() (queue->head == queue->tail)
17948 +static u_char get_from_queue(void)
17950 + unsigned long flags;
17951 + u_char res;
17953 + spin_lock_irqsave(&kmi_mouse_lock, flags);
17954 + res = queue->buf[queue->tail];
17955 + queue->tail = (queue->tail + 1) & (BUF_SZ-1);
17956 + spin_unlock_irqrestore(&kmi_mouse_lock, flags);
17958 + return res;
17961 +static ssize_t
17962 +kmi_mouse_read(struct file *file, char *buf, size_t count, loff_t *ppos)
17964 + ssize_t i = count;
17966 + if (queue_empty()) {
17967 + int ret;
17969 + if (file->f_flags & O_NONBLOCK)
17970 + return -EAGAIN;
17971 + ret = wait_event_interruptible(kmi_mouse->wait_q, !queue_empty());
17972 + if (ret)
17973 + return ret;
17975 + while (i > 0 && !queue_empty()) {
17976 + u_char c;
17977 + c = get_from_queue();
17978 + put_user(c, buf++);
17979 + i--;
17981 + if (count - i)
17982 + file->f_dentry->d_inode->i_atime = CURRENT_TIME;
17983 + return count - i;
17986 +static ssize_t
17987 +kmi_mouse_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
17989 + ssize_t retval = 0;
17991 + if (count > 32)
17992 + count = 32;
17994 + do {
17995 + char c;
17996 + get_user(c, buf++);
17997 + kmi_send_and_wait(kmi_mouse, c, HZ);
17998 + retval++;
17999 + } while (--count);
18001 + if (retval)
18002 + file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
18004 + return retval;
18007 +static unsigned int
18008 +kmi_mouse_poll(struct file *file, poll_table *wait)
18010 + poll_wait(file, &kmi_mouse->wait_q, wait);
18011 + return (!queue_empty()) ? POLLIN | POLLRDNORM : 0;
18014 +static int
18015 +kmi_mouse_release(struct inode *inode, struct file *file)
18017 + lock_kernel();
18018 + fasync_helper(-1, file, 0, &queue->fasync);
18019 + if (--kmi_mouse_count == 0)
18020 + kmi_send_and_wait(kmi_mouse, PS2_O_DISABLE, HZ);
18021 + unlock_kernel();
18022 + return 0;
18025 +static int
18026 +kmi_mouse_open(struct inode *inode, struct file *file)
18028 + if (kmi_mouse_count++)
18029 + return 0;
18030 + queue->head = queue->tail = 0;
18031 + kmi_send_and_wait(kmi_mouse, PS2_O_ENABLE, HZ);
18032 + return 0;
18035 +static int
18036 +kmi_mouse_fasync(int fd, struct file *filp, int on)
18038 + int retval = fasync_helper(fd, filp, on, &queue->fasync);
18039 + if (retval > 0)
18040 + retval = 0;
18041 + return retval;
18044 +static struct file_operations ps_fops = {
18045 + read: kmi_mouse_read,
18046 + write: kmi_mouse_write,
18047 + poll: kmi_mouse_poll,
18048 + open: kmi_mouse_open,
18049 + release: kmi_mouse_release,
18050 + fasync: kmi_mouse_fasync,
18053 +static struct miscdevice ps_mouse = {
18054 + minor: PSMOUSE_MINOR,
18055 + name: "psaux",
18056 + fops: &ps_fops,
18059 +static u_char kmi_mse_init_string[] = {
18060 + PS2_O_DISABLE,
18061 + PS2_O_SET_SAMPLE, 100,
18062 + PS2_O_SET_RES, 3,
18063 + PS2_O_SET_SCALE21
18067 + * The "normal" mouse scancode processing
18068 + */
18069 +static void kmi_mse_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
18071 + u_int head;
18073 + add_mouse_randomness(val);
18075 +#ifdef CONFIG_AMBA_PS2_RECONNECT
18076 + /* Try to detect a hot-plug event on the PS/2 mouse port */
18077 + switch (kmi->hotplug_state) {
18078 + case 0:
18079 + /* Maybe we lost contact... */
18080 + if (val == PS2_I_BAT_OK) {
18081 + kmi->hotplug_state++;
18082 + DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
18084 + break;
18086 + case 1:
18087 + /* Again, maybe (but only maybe) we lost contact... */
18088 + if (val == 0) {
18089 + kmi->hotplug_state++;
18090 + kmi_send(kmi, PS2_O_REQ_STATUS);
18091 + DEBUG(("%s: Got 0xAA 0x00. Sent Status Request\n", kmi->name));
18092 + } else {
18093 + kmi->hotplug_state = 0;
18094 + DEBUG(("%s: No 0x00 followed 0xAA. No reconnect.\n", kmi->name));
18096 + break;
18098 + case 2:
18099 + /* Eat up acknowledge */
18100 + if (val == PS2_I_ACK)
18101 + kmi->hotplug_state++;
18102 + else {
18103 + kmi->hotplug_state = 0;
18104 + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
18106 + break;
18108 + case 3:
18109 + /* check if data reporting is still enabled, then no POR has happend */
18110 + kmi->reconnect = !(val & 1<<5);
18111 + DEBUG(("%s: Data reporting disabled?: (%d)\n", kmi->name, kmi->reconnect));
18112 + kmi->hotplug_state++;
18113 + DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
18114 + break;
18116 + case 4:
18117 + /* Eat up one status byte */
18118 + kmi->hotplug_state++;
18119 + DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
18120 + break;
18122 + case 5:
18123 + /* Eat up another status byte */
18124 + if (kmi->reconnect) {
18125 + kmi->config_num = 0;
18126 + kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
18127 + kmi->config_num++;
18128 + kmi->hotplug_state++;
18129 + DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
18130 + } else {
18131 + kmi->hotplug_state = 0;
18132 + DEBUG(("%s: False Alarm...\n", kmi->name));
18134 + break;
18136 + case 6:
18137 + if (val == PS2_I_ACK && kmi->config_num < sizeof(kmi_mse_init_string)) {
18138 + kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
18139 + kmi->config_num++;
18140 + DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
18141 + } else {
18142 + if (val == PS2_I_ACK) {
18143 + DEBUG(("%s: Now enable the mouse again...\n", kmi->name));
18144 + queue->head = queue->tail = 0;
18145 + kmi_send(kmi, PS2_O_ENABLE);
18146 + kmi->hotplug_state++;
18147 + } else {
18148 + kmi->hotplug_state = 0;
18149 + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
18152 + break;
18154 + case 7:
18155 + /* Eat up last acknowledge from enable */
18156 + if (val == PS2_I_ACK)
18157 + printk(KERN_ERR "%s: reconnected\n", kmi->name);
18158 + else
18159 + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
18161 + kmi->hotplug_state = 0;
18162 + break;
18164 + } /* switch (kmi->hotplug_state) */
18166 + /* while inside hotplug mechanism, don't misinterpret values */
18167 + if (kmi->hotplug_state > 2)
18168 + return;
18169 +#endif
18171 + /* We are waiting for the mouse to respond to a kmi_send_and_wait() */
18172 + if (kmi->res == KMI_NO_ACK) {
18173 + if (val == PS2_I_RESEND) {
18174 + if (kmi->resend_count < 5)
18175 + __kmi_send(kmi, kmi->last_tx);
18176 + else {
18177 + printk(KERN_ERR "%s: too many resends\n", kmi->name);
18178 + return;
18182 + if (val == PS2_I_ACK) {
18183 + kmi->res = val;
18184 + wake_up(&kmi->wait_q);
18186 + return;
18189 + /* The mouse autonomously send new data, so wake up mouse_read() */
18190 + if (queue) {
18191 + head = queue->head;
18192 + queue->buf[head] = val;
18193 + head = (head + 1) & (BUF_SZ - 1);
18194 + if (head != queue->tail) {
18195 + queue->head = head;
18196 + kill_fasync(&queue->fasync, SIGIO, POLL_IN);
18197 + wake_up_interruptible(&kmi->wait_q);
18202 +static int kmi_init_mouse(struct kmi_info *kmi)
18204 + u_int ret, i;
18206 + if (kmi->present) {
18207 + kmi->rx = kmi_mse_intr;
18209 + for (i = 0; i < sizeof(kmi_mse_init_string); i++) {
18210 + ret = kmi_send_and_wait(kmi, kmi_mse_init_string[i], HZ);
18211 + if (ret != PS2_I_ACK)
18212 + printk("%s: didn't get ack (0x%2.2x)\n",
18213 + kmi->name, ret);
18217 + queue = kmalloc(sizeof(*queue), GFP_KERNEL);
18218 + if (queue) {
18219 + memset(queue, 0, sizeof(*queue));
18220 + misc_register(&ps_mouse);
18221 + ret = 0;
18222 + } else
18223 + ret = -ENOMEM;
18225 + return ret;
18227 +#endif /* CONFIG_KMI_MOUSE */
18230 + * The "program" we send to the keyboard to set it up how we want it:
18231 + * - default typematic delays
18232 + * - scancode set 1
18233 + */
18234 +static u_char kmi_kbd_init_string[] = {
18235 + PS2_O_DISABLE,
18236 + PS2_O_SET_DEFAULT,
18237 + PS2_O_SET_SCANSET, 0x01,
18238 + PS2_O_ENABLE
18241 +static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs);
18243 +static int __kmi_init_keyboard(struct kmi_info *kmi)
18245 + u_int ret, i;
18247 + if (!kmi->present)
18248 + return 0;
18250 + kmi->rx = kmi_kbd_intr;
18252 + for (i = 0; i < sizeof(kmi_kbd_init_string); i++) {
18253 + ret = kmi_send_and_wait(kmi, kmi_kbd_init_string[i], HZ);
18254 + if (ret != PS2_I_ACK)
18255 + printk("%s: didn't ack (0x%2.2x)\n",
18256 + kmi->name, ret);
18259 + return 0;
18262 +static void kmi_kbd_init_tasklet(unsigned long k)
18264 + struct kmi_info *kmi = (struct kmi_info *)k;
18265 + __kmi_init_keyboard(kmi);
18268 +static DECLARE_TASKLET_DISABLED(kmikbd_init_tasklet, kmi_kbd_init_tasklet, 0);
18271 + * The "normal" keyboard scancode processing
18272 + */
18273 +static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
18275 +#ifdef CONFIG_AMBA_PS2_RECONNECT
18276 + /* Try to detect a hot-plug event on the PS/2 keyboard port */
18277 + switch (kmi->hotplug_state) {
18278 + case 0:
18279 + /* Maybe we lost contact... */
18280 + if (val == PS2_I_BAT_OK) {
18281 + kmi_send(kmi, PS2_O_SET_SCANSET);
18282 + kmi->hotplug_state++;
18283 + DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
18285 + break;
18287 + case 1:
18288 + /* Eat up acknowledge */
18289 + if (val == PS2_I_ACK) {
18290 + /* Request scan code set: '2' if POR has happend, '1' is false alarm */
18291 + kmi_send(kmi, 0);
18292 + kmi->hotplug_state++;
18294 + else {
18295 + kmi->hotplug_state = 0;
18296 + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
18298 + break;
18300 + case 2:
18301 + /* Eat up acknowledge */
18302 + if (val == PS2_I_ACK)
18303 + kmi->hotplug_state++;
18304 + else {
18305 + kmi->hotplug_state = 0;
18306 + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
18308 + break;
18310 + case 3:
18311 + kmi->hotplug_state = 0;
18312 + if (val == 2) {
18313 + DEBUG(("%s: POR detected. Scan code is: (%d)\n", kmi->name, val));
18314 + kmi->present = 1;
18315 + tasklet_schedule(&kmikbd_init_tasklet);
18316 + printk(KERN_ERR "%s: reconnected\n", kmi->name);
18317 + return;
18319 + else
18320 + DEBUG(("%s: False Alarm...\n", kmi->name));
18321 + break;
18323 + } /* switch (kmi->hotplug_state) */
18324 +#endif
18326 + if (val == PS2_I_DIAGFAIL) {
18327 + printk(KERN_ERR "%s: diagnostic failed\n", kmi->name);
18328 + return;
18331 + /* We are waiting for the keyboard to respond to a kmi_send_and_wait() */
18332 + if (kmi->res == KMI_NO_ACK) {
18333 + if (val == PS2_I_RESEND) {
18334 + if (kmi->resend_count < 5)
18335 + __kmi_send(kmi, kmi->last_tx);
18336 + else {
18337 + printk(KERN_ERR "%s: too many resends\n", kmi->name);
18338 + return;
18342 + if (val >= 0xee) {
18343 + kmi->res = val;
18344 + wake_up(&kmi->wait_q);
18346 + return;
18349 +#ifdef CONFIG_VT
18350 + kbd_pt_regs = regs;
18351 + handle_scancode(val, !(val & 0x80));
18352 + tasklet_schedule(&keyboard_tasklet);
18353 +#endif
18356 +static void kmi_intr(int nr, void *devid, struct pt_regs *regs)
18358 + struct kmi_info *kmi = devid;
18359 + u_int status = __raw_readb(KMIIR);
18361 + if (status & KMIIR_RXINTR) {
18362 + u_int val = __raw_readb(KMIDATA);
18364 + if (kmi->rx)
18365 + kmi->rx(kmi, val, regs);
18369 +static int kmi_init_keyboard(struct kmi_info *kmi)
18371 + kmikbd_init_tasklet.data = (unsigned long)kmi;
18372 + tasklet_enable(&kmikbd_init_tasklet);
18374 + return __kmi_init_keyboard(kmi);
18378 + * Reset interrupt handler
18379 + */
18380 +static void __init
18381 +kmi_reset_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
18383 + if (kmi->state == KMI_RESET) {
18384 + if (val == PS2_I_ACK)
18385 + kmi->state = KMI_RESET_POR;
18386 + else {
18387 + val = KMI_NO_ACK;
18388 + goto finished;
18390 + } else if (kmi->state == KMI_RESET_POR) {
18391 +finished:
18392 + kmi->res = val;
18393 + kmi->state = KMI_RESET_DONE;
18394 + kmi->rx = NULL;
18395 + wake_up(&kmi->wait_q);
18400 + * Reset the device plugged into this interface
18401 + */
18402 +static int __init kmi_reset(struct kmi_info *kmi)
18404 + u_int res;
18405 + int ret = 0;
18407 + kmi->state = KMI_RESET;
18408 + kmi->rx = kmi_reset_intr;
18409 + res = kmi_send_and_wait(kmi, PS2_O_RESET, HZ);
18410 + kmi->rx = NULL;
18412 + if (res != PS2_I_BAT_OK) {
18413 + printk(KERN_ERR "%s: reset failed; ", kmi->name);
18414 + if (kmi->res != KMI_NO_ACK)
18415 + printk("code 0x%2.2x\n", kmi->res);
18416 + else
18417 + printk("no ack\n");
18418 + ret = -EINVAL;
18420 + return ret;
18423 +static int __init kmi_init_one_interface(struct kmi_info *kmi)
18425 + u_int stat;
18426 + int ret = -ENODEV;
18428 + init_waitqueue_head(&kmi->wait_q);
18430 + printk(KERN_INFO "%s at 0x%8.8x on irq %d (%s)\n", kmi->name,
18431 + kmi->base, kmi->irq, kmi_type[kmi->type]);
18433 + /*
18434 + * Initialise the KMI interface
18435 + */
18436 + __raw_writeb(kmi->divisor, KMICLKDIV);
18437 + __raw_writeb(KMICR_EN, KMICR);
18439 + /*
18440 + * Check that the data and clock lines are OK.
18441 + */
18442 + stat = __raw_readb(KMISTAT);
18443 + if ((stat & (KMISTAT_IC|KMISTAT_ID)) != (KMISTAT_IC|KMISTAT_ID)) {
18444 + printk(KERN_ERR "%s: %s%s%sline%s stuck low\n", kmi->name,
18445 + (stat & KMISTAT_IC) ? "" : "clock ",
18446 + (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "and ",
18447 + (stat & KMISTAT_ID) ? "" : "data ",
18448 + (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "s");
18449 + goto bad;
18452 + /*
18453 + * Claim the appropriate interrupts
18454 + */
18455 + ret = request_irq(kmi->irq, kmi_intr, 0, kmi->name, kmi);
18456 + if (ret)
18457 + goto bad;
18459 + /*
18460 + * Enable the receive interrupt, and reset the device.
18461 + */
18462 + __raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
18463 + kmi->present = 1;
18464 + kmi->present = kmi_reset(kmi) == 0;
18466 + switch (kmi->type) {
18467 + case KMI_KEYBOARD:
18468 + ret = kmi_init_keyboard(kmi);
18469 + break;
18471 +#ifdef CONFIG_KMI_MOUSE
18472 + case KMI_MOUSE:
18473 + ret = kmi_init_mouse(kmi);
18474 + break;
18475 +#endif
18478 + return ret;
18480 +bad:
18481 + /*
18482 + * Oh dear, the interface was bad, disable it.
18483 + */
18484 + __raw_writeb(0, KMICR);
18485 + return ret;
18488 +#ifdef CONFIG_VT
18490 + * The fragment between #ifdef above and #endif * CONFIG_VT *
18491 + * is from the pc_keyb.c driver. It is not copyrighted under the
18492 + * above notice. This code is by various authors; please see
18493 + * drivers/char/pc_keyb.c for further information.
18494 + */
18497 + * Translation of escaped scancodes to keycodes.
18498 + * This is now user-settable.
18499 + * The keycodes 1-88,96-111,119 are fairly standard, and
18500 + * should probably not be changed - changing might confuse X.
18501 + * X also interprets scancode 0x5d (KEY_Begin).
18503 + * For 1-88 keycode equals scancode.
18504 + */
18506 +#define E0_KPENTER 96
18507 +#define E0_RCTRL 97
18508 +#define E0_KPSLASH 98
18509 +#define E0_PRSCR 99
18510 +#define E0_RALT 100
18511 +#define E0_BREAK 101 /* (control-pause) */
18512 +#define E0_HOME 102
18513 +#define E0_UP 103
18514 +#define E0_PGUP 104
18515 +#define E0_LEFT 105
18516 +#define E0_RIGHT 106
18517 +#define E0_END 107
18518 +#define E0_DOWN 108
18519 +#define E0_PGDN 109
18520 +#define E0_INS 110
18521 +#define E0_DEL 111
18523 +#define E1_PAUSE 119
18525 +/* BTC */
18526 +#define E0_MACRO 112
18527 +/* LK450 */
18528 +#define E0_F13 113
18529 +#define E0_F14 114
18530 +#define E0_HELP 115
18531 +#define E0_DO 116
18532 +#define E0_F17 117
18533 +#define E0_KPMINPLUS 118
18535 + * My OmniKey generates e0 4c for the "OMNI" key and the
18536 + * right alt key does nada. [kkoller@nyx10.cs.du.edu]
18537 + */
18538 +#define E0_OK 124
18540 + * New microsoft keyboard is rumoured to have
18541 + * e0 5b (left window button), e0 5c (right window button),
18542 + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
18543 + * [or: Windows_L, Windows_R, TaskMan]
18544 + */
18545 +#define E0_MSLW 125
18546 +#define E0_MSRW 126
18547 +#define E0_MSTM 127
18549 +static u_char e0_keys[128] = {
18550 + 0, 0, 0, 0,
18551 + 0, 0, 0, 0,
18552 + 0, 0, 0, 0,
18553 + 0, 0, 0, 0,
18554 + 0, 0, 0, 0,
18555 + 0, 0, 0, 0,
18556 + 0, 0, 0, 0,
18557 + E0_KPENTER, E0_RCTRL, 0, 0,
18558 + 0, 0, 0, 0,
18559 + 0, 0, 0, 0,
18560 + 0, 0, 0, 0,
18561 + 0, 0, 0, 0,
18562 + 0, 0, 0, 0,
18563 + 0, E0_KPSLASH, 0, E0_PRSCR,
18564 + E0_RALT, 0, 0, 0,
18565 + 0, E0_F13, E0_F14, E0_HELP,
18566 + E0_DO, E0_F17, 0, 0,
18567 + 0, 0, E0_BREAK, E0_HOME,
18568 + E0_UP, E0_PGUP, 0, E0_LEFT,
18569 + E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,
18570 + E0_DOWN, E0_PGDN, E0_INS, E0_DEL,
18571 + 0, 0, 0, 0,
18572 + 0, 0, 0, E0_MSLW,
18573 + E0_MSRW, E0_MSTM, 0, 0,
18574 + 0, 0, 0, 0,
18575 + 0, 0, 0, 0,
18576 + 0, 0, 0, 0,
18577 + 0, 0, 0, E0_MACRO,
18578 + 0, 0, 0, 0,
18579 + 0, 0, 0, 0,
18580 + 0, 0, 0, 0,
18581 + 0, 0, 0, 0
18584 +#ifdef CONFIG_MAGIC_SYSRQ
18585 +u_char kmi_kbd_sysrq_xlate[128] =
18586 + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
18587 + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
18588 + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
18589 + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
18590 + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
18591 + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
18592 + "\r\000/"; /* 0x60 - 0x6f */
18593 +#endif
18595 +int kmi_kbd_setkeycode(u_int scancode, u_int keycode)
18597 + if (scancode < 128 || scancode > 255 || keycode > 127)
18598 + return -EINVAL;
18599 + e0_keys[scancode - 128] = keycode;
18600 + return 0;
18603 +int kmi_kbd_getkeycode(u_int scancode)
18605 + if (scancode < 128 || scancode > 255)
18606 + return -EINVAL;
18607 + return e0_keys[scancode - 128];
18610 +int kmi_kbd_translate(u_char scancode, u_char *keycode, char raw_mode)
18612 + static int prev_scancode = 0;
18614 + /* special prefix scancodes.. */
18615 + if (scancode == 0xe0 || scancode == 0xe1) {
18616 + prev_scancode = scancode;
18617 + return 0;
18620 + /* 0xff is sent by a few keyboards, ignore it. 0x00 is error */
18621 + if (scancode == 0x00 || scancode == 0xff) {
18622 + prev_scancode = 0;
18623 + return 0;
18626 + scancode &= 0x7f;
18628 + if (prev_scancode) {
18629 + int old_scancode = prev_scancode;
18631 + prev_scancode = 0;
18632 + switch (old_scancode) {
18633 + case 0xe0:
18634 + /*
18635 + * The keyboard maintains its own internal caps lock
18636 + * and num lock status. In caps lock mode, E0 AA
18637 + * precedes make code and E0 2A follows break code.
18638 + * In numlock mode, E0 2A precedes make code, and
18639 + * E0 AA follows break code. We do our own book-
18640 + * keeping, so we will just ignore these.
18642 + * For my keyboard there is no caps lock mode, but
18643 + * there are both Shift-L and Shift-R modes. The
18644 + * former mode generates E0 2A / E0 AA pairs, the
18645 + * latter E0 B6 / E0 36 pairs. So, we should also
18646 + * ignore the latter. - aeb@cwi.nl
18647 + */
18648 + if (scancode == 0x2a || scancode == 0x36)
18649 + return 0;
18650 + if (e0_keys[scancode])
18651 + *keycode = e0_keys[scancode];
18652 + else {
18653 + if (!raw_mode)
18654 + printk(KERN_INFO "kbd: unknown "
18655 + "scancode e0 %02x\n",
18656 + scancode);
18657 + return 0;
18659 + break;
18661 + case 0xe1:
18662 + if (scancode == 0x1d)
18663 + prev_scancode = 0x100;
18664 + else {
18665 + if (!raw_mode)
18666 + printk(KERN_INFO "kbd: unknown "
18667 + "scancode e1 %02x\n",
18668 + scancode);
18669 + return 0;
18671 + break;
18673 + case 0x100:
18674 + if (scancode == 0x45)
18675 + *keycode = E1_PAUSE;
18676 + else {
18677 + if (!raw_mode)
18678 + printk(KERN_INFO "kbd: unknown "
18679 + "scan code e1 1d %02x\n",
18680 + scancode);
18681 + return 0;
18683 + break;
18685 + } else
18686 + *keycode = scancode;
18687 + return 1;
18690 +char kmi_kbd_unexpected_up(u_char keycode)
18692 + return 0x80;
18695 +void kmi_kbd_leds(u_char leds)
18697 + struct kmi_info *kmi = kmi_keyb;
18698 + u_int ret;
18700 + if (kmi) {
18701 + ret = kmi_send_and_wait(kmi, PS2_O_INDICATORS, HZ);
18702 + if (ret != KMI_NO_ACK)
18703 + ret = kmi_send_and_wait(kmi, leds, HZ);
18704 + if (ret == KMI_NO_ACK)
18705 + kmi->present = 0;
18709 +int __init kmi_kbd_init(void)
18711 + int ret = -ENODEV;
18713 + if (kmi_keyb) {
18714 + strcpy(kmi_keyb->name, "kmikbd");
18715 + ret = kmi_init_one_interface(kmi_keyb);
18718 + if (ret == 0) {
18719 + k_setkeycode = kmi_kbd_setkeycode;
18720 + k_getkeycode = kmi_kbd_getkeycode;
18721 + k_translate = kmi_kbd_translate;
18722 + k_unexpected_up = kmi_kbd_unexpected_up;
18723 + k_leds = kmi_kbd_leds;
18724 +#ifdef CONFIG_MAGIC_SYSRQ
18725 + k_sysrq_xlate = kmi_kbd_sysrq_xlate;
18726 + k_sysrq_key = 0x54;
18727 +#endif
18730 + return ret;
18733 +#endif /* CONFIG_VT */
18735 +int register_kmi(struct kmi_info *kmi)
18737 + struct kmi_info **kmip = NULL;
18738 + int ret;
18740 + if (kmi->type == KMI_KEYBOARD)
18741 + kmip = &kmi_keyb;
18742 + else if (kmi->type == KMI_MOUSE)
18743 + kmip = &kmi_mouse;
18745 + ret = -EINVAL;
18746 + if (kmip) {
18747 + ret = -EBUSY;
18748 + if (!*kmip) {
18749 + *kmip = kmi;
18750 + ret = 0;
18754 + return ret;
18757 +#ifdef CONFIG_KMI_MOUSE
18758 +static int __init kmi_init(void)
18760 + int ret = -ENODEV;
18762 + if (kmi_mouse) {
18763 + strcpy(kmi_mouse->name, "kmimouse");
18764 + ret = kmi_init_one_interface(kmi_mouse);
18767 + return ret;
18770 +__initcall(kmi_init);
18771 +#endif
18772 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
18773 +++ linux-2.4.25/drivers/char/anakin_ts.c 2004-03-31 17:15:09.000000000 +0200
18774 @@ -0,0 +1,208 @@
18776 + * linux/drivers/char/anakin_ts.c
18778 + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
18780 + * This program is free software; you can redistribute it and/or modify
18781 + * it under the terms of the GNU General Public License version 2 as
18782 + * published by the Free Software Foundation.
18784 + * Changelog:
18785 + * 18-Apr-2001 TTC Created
18786 + * 23-Oct-2001 dwmw2 Cleanup
18787 + */
18789 +#include <linux/module.h>
18790 +#include <linux/types.h>
18791 +#include <linux/wait.h>
18792 +#include <linux/fs.h>
18793 +#include <linux/sched.h>
18794 +#include <linux/poll.h>
18795 +#include <linux/miscdevice.h>
18796 +#include <linux/init.h>
18797 +#include <linux/compiler.h>
18798 +#include <linux/interrupt.h>
18800 +#include <asm/io.h>
18801 +#include <asm/uaccess.h>
18802 +#include <asm/irq.h>
18805 + * TSBUF_SIZE must be a power of two
18806 + */
18807 +#define ANAKIN_TS_MINOR 16
18808 +#define TSBUF_SIZE 256
18809 +#define NEXT(index) (((index) + 1) & (TSBUF_SIZE - 1))
18811 +static unsigned short buffer[TSBUF_SIZE][4];
18812 +static int head, tail;
18813 +static DECLARE_WAIT_QUEUE_HEAD(queue);
18814 +static DECLARE_MUTEX(open_sem);
18815 +static spinlock_t tailptr_lock = SPIN_LOCK_UNLOCKED;
18816 +static struct fasync_struct *fasync;
18819 + * Interrupt handler and standard file operations
18820 + */
18821 +static void
18822 +anakin_ts_handler(int irq, void *dev_id, struct pt_regs *regs)
18824 + unsigned int status = __raw_readl(IO_BASE + IO_CONTROLLER + 0x24);
18826 + /*
18827 + * iPAQ format (u16 pressure, x, y, millisecs)
18828 + */
18829 + switch (status >> 20 & 3) {
18830 + case 0:
18831 + return;
18832 + case 2:
18833 + buffer[head][0] = 0;
18834 + break;
18835 + default:
18836 + buffer[head][0] = 0x7f;
18839 + if (unlikely((volatile int)tail == NEXT(head))) {
18840 + /* Run out of space in the buffer. Move the tail pointer */
18841 + spin_lock(&tailptr_lock);
18843 + if ((volatile int)tail == NEXT(head)) {
18844 + tail = NEXT(NEXT(head));
18846 + spin_unlock(&tailptr_lock);
18849 + buffer[head][1] = status >> 2 & 0xff;
18850 + buffer[head][2] = status >> 12 & 0xff;
18851 + buffer[head][3] = jiffies;
18852 + mb();
18853 + head = NEXT(head);
18855 + wake_up_interruptible(&queue);
18856 + kill_fasync(&fasync, SIGIO, POLL_IN);
18860 +static ssize_t
18861 +anakin_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
18863 + unsigned short data[4];
18864 + ssize_t written = 0;
18866 + if (head == tail) {
18867 + if (filp->f_flags & O_NONBLOCK)
18868 + return -EAGAIN;
18869 + if (wait_event_interruptible(queue, (volatile int)head != (volatile int)tail))
18870 + return -ERESTARTSYS;
18873 + while ((volatile int)head != (volatile int)tail && count >= sizeof data) {
18874 + /* Copy the data out with the spinlock held, so the
18875 + interrupt can't fill the buffer and move the tail
18876 + pointer while we're doing it */
18877 + spin_lock_irq(&tailptr_lock);
18879 + memcpy(data, buffer[tail], sizeof data);
18880 + tail = NEXT(tail);
18882 + spin_unlock_irq(&tailptr_lock);
18884 + if (copy_to_user(buf, data, sizeof data))
18885 + return -EFAULT;
18886 + count -= sizeof data;
18887 + buf += sizeof data;
18888 + written += sizeof data;
18890 + return written ? written : -EINVAL;
18893 +static unsigned int
18894 +anakin_ts_poll(struct file *filp, poll_table *wait)
18896 + poll_wait(filp, &queue, wait);
18897 + return head != tail ? POLLIN | POLLRDNORM : 0;
18900 +static int
18901 +anakin_ts_ioctl(struct inode *inode, struct file *filp,
18902 + unsigned int cmd, unsigned long arg)
18904 + /*
18905 + * Future ioctl goes here
18906 + */
18907 + return 0;
18910 +static int
18911 +anakin_ts_open(struct inode *inode, struct file *filp)
18913 + if (down_trylock(&open_sem))
18914 + return -EBUSY;
18915 + return 0;
18918 +static int
18919 +anakin_ts_fasync(int fd, struct file *filp, int on)
18921 + return fasync_helper(fd, filp, on, &fasync);
18924 +static int
18925 +anakin_ts_release(struct inode *inode, struct file *filp)
18927 + anakin_ts_fasync(-1, filp, 0);
18928 + up(&open_sem);
18929 + return 0;
18932 +static struct file_operations anakin_ts_fops = {
18933 + owner: THIS_MODULE,
18934 + read: anakin_ts_read,
18935 + poll: anakin_ts_poll,
18936 + ioctl: anakin_ts_ioctl,
18937 + open: anakin_ts_open,
18938 + release: anakin_ts_release,
18939 + fasync: anakin_ts_fasync,
18942 +static struct miscdevice anakin_ts_miscdev = {
18943 + ANAKIN_TS_MINOR,
18944 + "anakin_ts",
18945 + &anakin_ts_fops
18949 + * Initialization and exit routines
18950 + */
18951 +int __init
18952 +anakin_ts_init(void)
18954 + int retval;
18956 + if ((retval = request_irq(IRQ_TOUCHSCREEN, anakin_ts_handler,
18957 + SA_INTERRUPT, "anakin_ts", 0))) {
18958 + printk(KERN_WARNING "anakin_ts: failed to get IRQ\n");
18959 + return retval;
18961 + __raw_writel(1, IO_BASE + IO_CONTROLLER + 8);
18962 + misc_register(&anakin_ts_miscdev);
18964 + printk(KERN_NOTICE "Anakin touchscreen driver initialised\n");
18966 + return 0;
18969 +void __exit
18970 +anakin_ts_exit(void)
18972 + __raw_writel(0, IO_BASE + IO_CONTROLLER + 8);
18973 + free_irq(IRQ_TOUCHSCREEN, 0);
18974 + misc_deregister(&anakin_ts_miscdev);
18977 +module_init(anakin_ts_init);
18978 +module_exit(anakin_ts_exit);
18980 +MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
18981 +MODULE_DESCRIPTION("Anakin touchscreen driver");
18982 +MODULE_SUPPORTED_DEVICE("touchscreen/anakin");
18983 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
18984 +++ linux-2.4.25/drivers/char/cerf_keyb.c 2004-03-31 17:15:09.000000000 +0200
18985 @@ -0,0 +1,380 @@
18987 + cerf_keyb.c: This is the end. Daniel is writing a device driver!!!
18989 +#include <linux/config.h>
18991 +#include <linux/spinlock.h>
18992 +#include <linux/sched.h>
18993 +#include <linux/interrupt.h>
18994 +#include <linux/tty.h>
18995 +#include <linux/mm.h>
18996 +#include <linux/signal.h>
18997 +#include <linux/init.h>
18998 +#include <linux/kbd_ll.h>
18999 +#include <linux/delay.h>
19000 +#include <linux/random.h>
19001 +#include <linux/poll.h>
19002 +#include <linux/miscdevice.h>
19003 +#include <linux/slab.h>
19004 +#include <linux/kbd_kern.h>
19005 +#include <linux/smp_lock.h>
19006 +#include <linux/timer.h>
19008 +#include <asm/keyboard.h>
19009 +#include <asm/bitops.h>
19010 +#include <asm/uaccess.h>
19011 +#include <asm/irq.h>
19012 +#include <asm/system.h>
19014 +#include <asm/io.h>
19016 +#define KBD_REPORT_UNKN
19018 +#define KBD_REPORT_ERR /* Report keyboard errors */
19019 +#define KBD_REPORT_UNKN /* Report unknown scan codes */
19020 +#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */
19021 +#define KBD_NO_DATA (-1) /* No data */
19022 +#define KBD_REPEAT_START (0x20)
19023 +#define KBD_REPEAT_CONTINUE (0x05)
19024 +#define KBD_KEY_DOWN_MAX (0x10)
19025 +#define UINT_LEN (20)
19026 +#define SC_LIM (69)
19027 +#define KBD_ROWS (5)
19028 +#define KBD_COLUMNS (8)
19030 +#define KBD_KEYUP (0x80)
19031 +#define KBD_MODESCAN (0x7f)
19032 +#define KBD_CAPSSCAN (0x3a)
19033 +#define KBD_SHIFTSCAN (0x2a)
19034 +#define KBD_NUMCURSCAN (0x7c)
19035 +#define KBD_CTRLSCAN (0x1d)
19036 +#define KBD_ALTSCAN (0x38)
19038 +#define KBD_UP_OFF (0)
19039 +#define KBD_UP_ON (1)
19040 +#define KBD_DOWN (2)
19041 +#define KBD_DOWN_HOLD (3)
19045 +static unsigned char handle_kbd_event(void);
19046 +static unsigned char kbd_read_input(void);
19047 +static void column_set(unsigned int column);
19048 +static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]);
19050 +static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
19051 +static struct timer_list kbd_timer;
19053 +static short mode_ena = 0;
19054 +static short numcur_ena = 0;
19055 +static short shift_ena = 0;
19057 +#define E0_KPENTER 96
19058 +#define E0_RCTRL 97
19059 +#define E0_KPSLASH 98
19060 +#define E0_PRSCR 99
19061 +#define E0_RALT 100
19062 +#define E0_BREAK 101 /* (control-pause) */
19063 +#define E0_HOME 102
19064 +#define E0_UP 103
19065 +#define E0_PGUP 104
19066 +#define E0_LEFT 105
19067 +#define E0_RIGHT 106
19068 +#define E0_END 107
19069 +#define E0_DOWN 108
19070 +#define E0_PGDN 109
19071 +#define E0_INS 110
19072 +#define E0_DEL 111
19073 +#define E1_PAUSE 119
19074 +#define E0_MACRO 112
19075 +#define E0_F13 113
19076 +#define E0_F14 114
19077 +#define E0_HELP 115
19078 +#define E0_DO 116
19079 +#define E0_F17 117
19080 +#define E0_KPMINPLUS 118
19081 +#define E0_OK 124
19082 +#define E0_MSLW 125
19083 +#define E0_MSRW 126
19084 +#define E0_MSTM 127
19086 +static unsigned char e0_keys[128] = {
19087 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
19088 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
19089 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
19090 + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
19091 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
19092 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
19093 + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
19094 + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
19095 + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
19096 + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
19097 + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
19098 + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
19099 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
19100 + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
19101 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
19102 + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
19105 +static unsigned char cerf_normal_map[KBD_ROWS][KBD_COLUMNS] = {
19106 + {KBD_ALTSCAN, KBD_MODESCAN, 0x1e, 0x30, 0x2e, 0x20, 0x00, 0x00},
19107 + {0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x00},
19108 + {0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x00},
19109 + {0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x00},
19110 + {0x2c, KBD_SHIFTSCAN, KBD_CTRLSCAN, 0x39, KBD_NUMCURSCAN, 0x2b, 0x1c, 0x00}
19113 +static unsigned char cerf_mode_map[KBD_ROWS][KBD_COLUMNS] = {
19114 + {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
19115 + {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, //
19116 + {0x0d, 0x0c, 0x37, 0x35, 0x0d, 0x48, 0x28, 0x00},
19117 + {0x01, 0x33, 0x34, 0x00, 0x4b, 0x27, 0x4d, 0x00}, //
19118 + {0x0f, 0x00, KBD_CAPSSCAN, 0x0e, 0x00, 0x50, 0x00, 0x00}
19121 +static unsigned char cerf_numcur_map[KBD_ROWS][KBD_COLUMNS] = {
19122 + {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
19123 + {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00},
19124 + {0x0d, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00},
19125 + {0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x4d, 0x00},
19126 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00}
19129 +static void column_set(unsigned int column)
19131 + if (column < 0)
19133 + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
19134 + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
19136 + else
19138 + if(column < 4)
19140 + CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_A, 1 << (column % 4), 0xFF);
19141 + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
19143 + else
19145 + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
19146 + CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_B, 1 << (column % 4), 0xFF);
19151 +static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS])
19153 + int i, j;
19155 + for(i = 0; i < KBD_COLUMNS; i++)
19157 + column_set(i);
19158 + udelay(50);
19159 + for(j = 0; j < KBD_ROWS; j++)
19161 + if(mode_ena)
19162 + codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_mode_map[j][i]?cerf_mode_map[j][i]:cerf_normal_map[j][i]):0;
19163 + else if(numcur_ena)
19164 + codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_numcur_map[j][i]?cerf_numcur_map[j][i]:cerf_normal_map[j][i]):0;
19165 + else
19166 + codeval[j][i] = (GPLR & (1 << (20 + j)))?cerf_normal_map[j][i]:0;
19169 + column_set(-1);
19171 + return 0;
19174 +static unsigned char kbd_read_input(void)
19176 + int i, j, k, l;
19177 + unsigned char prev;
19178 + static unsigned char count = 0;
19180 + static unsigned char oldcodes[KBD_ROWS][KBD_COLUMNS]={{0,0,0,0,0,0,0,0},
19181 + {0,0,0,0,0,0,0,0},
19182 + {0,0,0,0,0,0,0,0},
19183 + {0,0,0,0,0,0,0,0},
19184 + {0,0,0,0,0,0,0,0}};
19185 + unsigned char inputcode[KBD_ROWS][KBD_COLUMNS];
19187 + memset(inputcode, 0, sizeof(unsigned char) * (KBD_ROWS * KBD_COLUMNS));
19188 + scancodes(inputcode);
19190 + for(i = 0; i < KBD_COLUMNS; i++)
19192 + for(j = 0; j < KBD_ROWS; j++)
19194 +// if(oldcodes[j][i] == 0xe0)
19195 +// oldcodes[j][i] =
19196 + if(oldcodes[j][i] != inputcode[j][i])
19198 + // Value of the key before entering this function
19199 + prev = oldcodes[j][i];
19201 + // KEYUP
19202 + if(inputcode[j][i] == 0 && oldcodes[j][i] != 0 && !(oldcodes[j][i] & KBD_KEYUP))
19204 + oldcodes[j][i] |= KBD_KEYUP;
19206 + if(mode_ena == KBD_UP_ON)
19207 + mode_ena = KBD_UP_OFF;
19208 + if(prev == KBD_MODESCAN)
19209 + if(mode_ena == KBD_DOWN_HOLD)
19210 + mode_ena = KBD_UP_OFF;
19211 + else if(mode_ena == KBD_DOWN)
19212 + mode_ena = KBD_UP_ON;
19213 + if(mode_ena == KBD_DOWN)
19214 + mode_ena = KBD_DOWN_HOLD;
19216 + // RESET KEYUP
19217 + else if(oldcodes[j][i] & KBD_KEYUP)
19218 + oldcodes[j][i] = 0;
19219 + // KEY DOWN
19220 + else
19222 + oldcodes[j][i] = inputcode[j][i];
19224 + // Parse out mode modifiers before the keyboard interpreter can touch them
19225 + if(inputcode[j][i] == KBD_MODESCAN)
19227 + if(!mode_ena)
19228 + mode_ena = KBD_DOWN;
19229 + continue;
19231 + if(inputcode[j][i] == KBD_NUMCURSCAN)
19233 + numcur_ena = numcur_ena?0:1;
19234 + continue;
19237 + //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);
19238 + return oldcodes[j][i];
19243 + return (unsigned char)(KBD_NO_DATA);
19246 +int cerf_kbd_translate(unsigned char scancode, unsigned char *keycode,
19247 + char raw_mode)
19249 + static int prev_scancode;
19251 + if (scancode == 0xe0 || scancode == 0xe1) {
19252 + prev_scancode = scancode;
19253 + return 0;
19256 + if (scancode == 0x00 || scancode == 0xff) {
19257 + prev_scancode = 0;
19258 + return 0;
19261 + scancode &= 0x7f;
19263 + if (prev_scancode) {
19264 + if (prev_scancode != 0xe0) {
19265 + if (prev_scancode == 0xe1 && scancode == 0x1d) {
19266 + prev_scancode = 0x100;
19267 + return 0;
19268 + } else if (prev_scancode == 0x100 && scancode == 0x45) {
19269 + prev_scancode = 0;
19270 + } else {
19271 +#ifdef KBD_REPORT_UNKN
19272 + if (!raw_mode)
19273 + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
19274 +#endif
19275 + prev_scancode = 0;
19276 + return 0;
19278 + } else {
19279 + prev_scancode = 0;
19280 + if (scancode == 0x2a || scancode == 0x36)
19281 + return 0;
19282 + else {
19283 +#ifdef KBD_REPORT_UNKN
19284 + if (!raw_mode)
19285 + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
19286 + scancode);
19287 +#endif
19288 + return 0;
19291 + } else
19292 + *keycode = scancode;
19293 + return 1;
19296 +static inline void handle_keyboard_event(unsigned char scancode)
19298 + if(scancode != (unsigned char)(KBD_NO_DATA))
19300 +#ifdef CONFIG_VT
19301 + handle_scancode(scancode, !(scancode & KBD_KEYUP));
19302 +#endif
19303 + tasklet_schedule(&keyboard_tasklet);
19307 +static unsigned char handle_kbd_event(void)
19309 + unsigned char scancode;
19311 + scancode = kbd_read_input();
19312 + handle_keyboard_event(scancode);
19314 + return 0;
19317 +/* Handle the automatic interrupts handled by the timer */
19318 +static void keyboard_interrupt(unsigned long foo)
19320 + spin_lock_irq(&kbd_controller_lock);
19321 + handle_kbd_event();
19322 + spin_unlock_irq(&kbd_controller_lock);
19324 + kbd_timer.expires = 8 + jiffies;
19325 + kbd_timer.data = 0x00000000;
19326 + kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
19328 + add_timer(&kbd_timer);
19331 +void cerf_leds(unsigned char leds)
19334 +char cerf_unexpected_up(unsigned char keycode)
19336 +return 0;
19338 +int cerf_getkeycode(unsigned int scancode)
19340 +return 0;
19342 +int cerf_setkeycode(unsigned int scancode, unsigned int keycode)
19344 +return 0;
19347 +void cerf_kbd_init_hw(void)
19349 + printk("Starting Cerf PDA Keyboard Driver... ");
19351 + k_setkeycode = cerf_setkeycode;
19352 + k_getkeycode = cerf_getkeycode;
19353 + k_translate = cerf_kbd_translate;
19354 + k_unexpected_up = cerf_unexpected_up;
19355 + k_leds = cerf_leds;
19357 + GPDR &= ~(GPIO_GPIO(20) | GPIO_GPIO(21) | GPIO_GPIO(22) | GPIO_GPIO(23) | GPIO_GPIO(24));
19358 + kbd_timer.expires = 40 + jiffies;
19359 + kbd_timer.data = 0x00000000;
19360 + kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
19362 + add_timer(&kbd_timer);
19364 + printk("Done\r\n");
19366 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
19367 +++ linux-2.4.25/drivers/char/clps711x_keyb.c 2004-03-31 17:15:09.000000000 +0200
19368 @@ -0,0 +1,547 @@
19370 + * drivers/char/clps711x_keyb.c
19372 + * Copyright (C) 2001 Thomas Gleixner <gleixner@autronix.de>
19374 + * based on drivers/edb7211_keyb.c, which is copyright (C) 2000 Bluemug Inc.
19375 + *
19376 + * Keyboard driver for ARM Linux on EP7xxx and CS89712 processors
19378 + * This program is free software; you can redistribute it and/or modify
19379 + * it under the terms of the GNU General Public License version 2 as
19380 + * published by the Free Software Foundation. See the file COPYING
19381 + * in the main directory of this archive for more details.
19384 + * Hardware:
19386 + * matrix scan keyboards based on EP7209,7211,7212,7312 and CS89712
19387 + * on chip keyboard scanner.
19388 + * Adaption for different machines is done in init function.
19390 + * Basic Function:
19392 + * Basicly the driver is interrupt driven. It sets all column drivers
19393 + * high. If any key is pressed, a interrupt occures. Now a seperate scan of
19394 + * each column is done. This scan is timer based, because we use a keyboard
19395 + * interface with decoupling capacitors (neccecary if you want to survive
19396 + * EMC compliance tests). Always one line is set high. When next timer event
19397 + * occures the scan data on port A are valid. This makes also sure, that no
19398 + * spurious keys are scanned. The kbd int on these CPU's is not deglitched!
19399 + * After scanning all columns, we switch back to int mode, if no key is
19400 + * pressed. If any is pressed we reschedule the scan within a programmable
19401 + * delay. If we would switch back to interrupt mode as long as a key is pressed,
19402 + * we come right back to the interrupt, because the int. is level triggered !
19403 + * The timer based scan of the seperate columns can also be done in one
19404 + * timer event (set fastscan to 1).
19406 + * Summary:
19407 + * The design of this keyboard controller chip is stupid at all !
19409 + * Matrix translation:
19410 + * The matrix translation table is based on standard XT scancodes. Maybe
19411 + * you have to adjust the KEYISPRINTABLE macro if you set other codes.
19413 + * HandyKey:
19415 + * On small matrix keyboards you don't have enough keys for operation.
19416 + * The intention was to implement a operation mode as it's used on handys.
19417 + * You can rotate trough four scancode levels and produce e.g. with a 4x3
19418 + * matrix 4*3*4 = 48 different keycodes. That's basicly enough for editing
19419 + * filenames or things like that. The HandyKey function takes care about
19420 + * nonprintable keys like cursors, backspace, del ...
19421 + * If a key is pressed and is a printable keycode, the code is put to the
19422 + * main keyboard handler and a cursor left is applied. If you press the same
19423 + * key again, the current character is deleted and the next level character
19424 + * is applied. (e.g. 1, a, b, c, 1 ....). If you press a different key, the
19425 + * driver applies cursor right, before processing the new key.
19426 + * The autocomplete feature moves the cursor right, if you do not press a
19427 + * key within a programmable time.
19428 + * If HandyKey is off, the keyboard behaviour is that of a standard keyboard
19429 + * HandyKey can be en/disabled from userspace with the proc/keyboard entry
19430 + *
19431 + * proc/keyboard:
19432 + *
19433 + * Read access gives back the actual state of the HandyKey function
19434 + * h:0 Disabled
19435 + * h:1 Enabled
19436 + * Write access has two functions. Changing the HandyKey mode and applying
19437 + * a different scancode translation table.
19438 + * Syntax is: h:0 disable Handykey
19439 + * h:1 enabled Handykey
19440 + * t:array[256] of bytes Transfer translation table
19441 + */
19443 +#include <linux/config.h>
19444 +#include <linux/sched.h>
19445 +#include <linux/interrupt.h>
19446 +#include <linux/tty.h>
19447 +#include <linux/tty_flip.h>
19448 +#include <linux/mm.h>
19449 +#include <linux/slab.h>
19450 +#include <linux/ptrace.h>
19451 +#include <linux/signal.h>
19452 +#include <linux/timer.h>
19453 +#include <linux/tqueue.h>
19454 +#include <linux/random.h>
19455 +#include <linux/ctype.h>
19456 +#include <linux/init.h>
19457 +#include <linux/kbd_ll.h>
19458 +#include <linux/kbd_kern.h>
19459 +#include <linux/delay.h>
19460 +#include <linux/proc_fs.h>
19462 +#include <asm/bitops.h>
19463 +#include <asm/keyboard.h>
19464 +#include <asm/irq.h>
19465 +#include <asm/hardware.h>
19466 +#include <asm/uaccess.h>
19468 +#include <asm/io.h>
19469 +#include <asm/system.h>
19471 +void clps711x_kbd_init_hw(void);
19474 + * Values for the keyboard column scan control register.
19475 + */
19476 +#define KBSC_HI 0x0 /* All driven high */
19477 +#define KBSC_LO 0x1 /* All driven low */
19478 +#define KBSC_X 0x2 /* All high impedance */
19479 +#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
19480 +#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
19481 +#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
19482 +#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
19483 +#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
19484 +#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
19485 +#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
19486 +#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
19489 +* Keycodes for cursor left/right and delete (used by HandyKey)
19491 +#define KEYCODE_CLEFT 0x4b
19492 +#define KEYCODE_CRIGHT 0x4d
19493 +#define KEYCODE_DEL 0x53
19494 +#define KEYISPRINTABLE(code) ( (code > 0x01 && code < 0x37 && code != 0x1c \
19495 + && code != 0x0e) || code == 0x39)
19497 +/* Simple translation table for the SysRq keys */
19498 +#ifdef CONFIG_MAGIC_SYSRQ
19499 +unsigned char clps711x_kbd_sysrq_xlate[128] =
19500 + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
19501 + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
19502 + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
19503 + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
19504 + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
19505 + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
19506 + "\r\000/"; /* 0x60 - 0x6f */
19507 +#endif
19509 +/*
19510 + * This table maps row/column keyboard matrix positions to XT scancodes.
19511 + * It's a default table, which can be overriden by writing to proc/keyboard
19512 + */
19513 +#ifdef CONFIG_ARCH_AUTCPU12
19514 +static unsigned char autcpu12_scancode[256] =
19516 +/* Column:
19517 + Row 0 1 2 3 4 5 6 7 */
19518 +/* A0 */ 0x08, 0x09, 0x0a, 0x0e, 0x05, 0x06, 0x00, 0x00,
19519 +/* A1 */ 0x07, 0x53, 0x02, 0x03, 0x04, 0x0f, 0x00, 0x00,
19520 +/* A2 */ 0x0c, 0x0b, 0x33, 0x1c, 0xff, 0x4b, 0x00, 0x00,
19521 +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
19522 +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19523 +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19524 +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19525 +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19527 +/* A0 */ 0x1e, 0x20, 0x22, 0x0e, 0x24, 0x32, 0x00, 0x00,
19528 +/* A1 */ 0x19, 0x53, 0x1f, 0x2f, 0x15, 0x0f, 0x00, 0x00,
19529 +/* A2 */ 0x0c, 0x39, 0x34, 0x1c, 0xff, 0x4b, 0x00, 0x00,
19530 +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
19531 +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19532 +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19533 +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19534 +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19536 +/* A0 */ 0x30, 0x12, 0x23, 0x0e, 0x25, 0x31, 0x00, 0x00,
19537 +/* A1 */ 0x10, 0x53, 0x14, 0x11, 0x2c, 0x0f, 0x00, 0x00,
19538 +/* A2 */ 0x0c, 0x0b, 0x27, 0x1c, 0xff, 0x4b, 0x00, 0x00,
19539 +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
19540 +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19541 +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19542 +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19543 +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19545 +/* A0 */ 0x2e, 0x21, 0x17, 0x0e, 0x26, 0x18, 0x00, 0x00,
19546 +/* A1 */ 0x13, 0x53, 0x16, 0x2D, 0x04, 0x0f, 0x00, 0x00,
19547 +/* A2 */ 0x0c, 0x39, 0x35, 0x1c, 0xff, 0x4b, 0x00, 0x00,
19548 +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
19549 +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19550 +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19551 +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19552 +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19554 +#endif
19556 +static int keys[8];
19557 +static int new_keys[8];
19558 +static int previous_keys[8];
19560 +static int fastscan;
19561 +static int scan_interval;
19562 +static int scan_delay;
19563 +static int last_column;
19564 +static int key_is_pressed;
19566 +static unsigned char *act_scancode;
19568 +static struct kbd_handy_key {
19569 + int ena;
19570 + int code;
19571 + int shift;
19572 + int autocomplete;
19573 + unsigned long expires;
19574 + unsigned long delay;
19575 + unsigned char left;
19576 + unsigned char right;
19577 + unsigned char del;
19578 +} khandy;
19580 +static struct tq_struct kbd_process_task;
19581 +static struct timer_list clps711x_kbd_timer;
19582 +static struct timer_list clps711x_kbdhandy_timer;
19583 +static struct proc_dir_entry *clps711x_keyboard_proc_entry = NULL;
19586 + * Translate a raw keycode to an XT keyboard scancode.
19587 + */
19588 +static int clps711x_translate(unsigned char scancode, unsigned char *keycode,
19589 + char raw_mode)
19591 + *keycode = act_scancode[scancode];
19592 + return 1;
19596 +* Initialize handykey structure
19597 +* clear code, clear shift
19598 +* scan scancode for cursor right/left and delete
19600 +static void clps711x_handykey_init(void) {
19602 + int i;
19604 + khandy.ena = 0;
19605 + khandy.code = 0;
19606 + khandy.shift = 0;
19607 + khandy.autocomplete = 0;
19608 + for(i = 0; i < 64; i++) {
19609 + switch(act_scancode[i]) {
19610 + case KEYCODE_CLEFT: khandy.left = i; break;
19611 + case KEYCODE_CRIGHT: khandy.right = i; break;
19612 + case KEYCODE_DEL: khandy.del = i; break;
19614 + }
19618 +* Check for handy key and process it
19620 +void inline clps711x_checkhandy(int col, int row) {
19622 + int scode, down;
19623 + unsigned char kcode;
19625 + scode = (row<<3) + col;
19626 + down = keys[col]>>row & 0x01;
19627 + kcode = act_scancode[scode];
19629 + if (!khandy.ena) {
19630 + if (khandy.code) {
19631 + handle_scancode(khandy.right,1);
19632 + handle_scancode(khandy.right,0);
19634 + khandy.code = 0;
19635 + khandy.shift = 0;
19636 + khandy.autocomplete = 0;
19639 + if(!kcode)
19640 + return;
19642 + if (!down || !khandy.ena) {
19643 + if (khandy.ena && KEYISPRINTABLE(act_scancode[scode]))
19644 + khandy.autocomplete = 1;
19645 + else
19646 + handle_scancode(scode + khandy.shift, down);
19647 + return;
19650 + khandy.autocomplete = 0;
19651 + if (KEYISPRINTABLE(kcode)) {
19652 + if (khandy.code) {
19653 + if(khandy.code == (scode|0x100)) {
19654 + handle_scancode(khandy.del,1);
19655 + handle_scancode(khandy.del,0);
19656 + khandy.shift = khandy.shift < 3*64 ? khandy.shift + 64 : 0 ;
19657 + } else {
19658 + handle_scancode(khandy.right,1);
19659 + handle_scancode(khandy.right,0);
19660 + khandy.shift = 0;
19661 + }
19663 + handle_scancode(scode + khandy.shift, 1);
19664 + handle_scancode(scode + khandy.shift, 0);
19665 + khandy.code = scode | 0x100;
19666 + handle_scancode(khandy.left,1);
19667 + handle_scancode(khandy.left,0);
19668 + } else {
19669 + if (khandy.code) {
19670 + khandy.code = 0;
19671 + handle_scancode(khandy.right,1);
19672 + handle_scancode(khandy.right,0);
19674 + khandy.shift = 0;
19675 + handle_scancode(scode, down);
19681 + * Process the new key data
19682 + */
19683 +static void clps711x_kbd_process(void* data)
19685 + int col,row,res;
19687 + for (col = 0; col < 8; col++) {
19688 + if (( res = previous_keys[col] ^ keys[col]) == 0)
19689 + continue;
19690 + for(row = 0; row < 8; row++) {
19691 + if ( ((res >> row) & 0x01) != 0)
19692 + clps711x_checkhandy(col,row);
19693 + }
19695 + /* Update the state variables. */
19696 + memcpy(previous_keys, keys, 8 * sizeof(int));
19698 + /* reschedule, if autocomplete pending */
19699 + if (khandy.autocomplete) {
19700 + khandy.expires = jiffies + khandy.delay;
19701 + mod_timer(&clps711x_kbdhandy_timer,khandy.expires);
19706 +static char clps711x_unexpected_up(unsigned char scancode)
19708 + return 0200;
19712 +* Handle timer event, for autocomplete function
19713 +* Reschedule keyboard process task
19715 +static void clps711x_kbdhandy_timeout(unsigned long data)
19717 + if(khandy.autocomplete) {
19718 + khandy.code = 0;
19719 + khandy.shift = 0;
19720 + khandy.autocomplete = 0;
19721 + handle_scancode(khandy.right,1);
19722 + handle_scancode(khandy.right,0);
19727 +* Handle timer event, while in pollmode
19729 +static void clps711x_kbd_timeout(unsigned long data)
19731 + int i;
19732 + unsigned long flags;
19733 + /*
19734 + * read bits of actual column or all columns in fastscan-mode
19735 + */
19736 + for (i = 0; i < 8; i++) {
19737 + new_keys[last_column - KBSC_COL0] = clps_readb(PADR) & 0xff;
19738 + key_is_pressed |= new_keys[last_column - KBSC_COL0];
19739 + last_column = last_column < KBSC_COL7 ? last_column + 1 : KBSC_COL0;
19740 + local_irq_save(flags);
19741 + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
19742 + | last_column, SYSCON1);
19743 + local_irq_restore(flags);
19744 + /*
19745 + * For fastscan, apply a short delay to settle scanlines
19746 + * else break and wait for next timeout
19747 + */
19748 + if (fastscan)
19749 + udelay(5);
19750 + else
19751 + break;
19754 + if (key_is_pressed)
19755 + khandy.autocomplete = 0;
19757 + /*
19758 + * switch to interupt mode, if all columns scanned and no key pressed
19759 + * else reschedule scan
19760 + */
19761 + if (last_column == KBSC_COL0) {
19762 + if (!key_is_pressed) {
19763 + local_irq_save(flags);
19764 + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
19765 + | KBSC_HI, SYSCON1);
19766 + local_irq_restore(flags);
19767 + clps_writel(0,KBDEOI);
19768 + enable_irq(IRQ_KBDINT);
19769 + } else {
19770 + clps711x_kbd_timer.expires = jiffies + scan_interval;
19771 + add_timer(&clps711x_kbd_timer);
19772 + }
19773 + key_is_pressed = 0;
19774 + memcpy(keys, new_keys, 8 * sizeof(int));
19775 + for (i = 0; i < 8; i++) {
19776 + if (previous_keys[i] != keys[i]) {
19777 + queue_task(&kbd_process_task, &tq_timer);
19778 + return;
19781 + } else {
19782 + clps711x_kbd_timer.expires = jiffies + scan_delay;
19783 + add_timer(&clps711x_kbd_timer);
19788 +* Keyboard interrupt, change to scheduling mode
19790 +static void clps711x_kbd_int(int irq, void *dev_id, struct pt_regs *regs)
19793 +#ifdef CONFIG_VT
19794 + kbd_pt_regs = regs;
19795 +#endif
19796 + disable_irq(IRQ_KBDINT);
19797 + khandy.autocomplete = 0;
19798 + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
19799 + | KBSC_COL0, SYSCON1);
19800 + clps711x_kbd_timer.expires = jiffies + scan_delay;
19801 + add_timer(&clps711x_kbd_timer);
19805 +static int clps711x_kbd_proc_keyboard_read(char *page, char **start, off_t off,
19806 + int count, int *eof, void *data)
19808 + if (count < 2)
19809 + return -EINVAL;
19811 + return sprintf(page,"h:%d\n",khandy.ena);
19814 +static int clps711x_kbd_proc_keyboard_write(struct file *file, const char *buffer,
19815 + unsigned long count, void *data)
19817 + unsigned char buf[260];
19819 + if (count < 3|| count > 258)
19820 + return -EINVAL;
19821 + if (copy_from_user(buf, buffer, count))
19822 + return -EFAULT;
19823 + if (buf[1] != ':')
19824 + return -EINVAL;
19826 + if (buf[0] == 'h') {
19827 + switch (buf[2]) {
19828 + case '0':
19829 + case '1':
19830 + case '2': khandy.ena = buf[2]-'0'; return count;
19832 + }
19834 + if (buf[0] == 't' && count == 258) {
19835 + memcpy(act_scancode,buf+2,256);
19836 + /* rescan cursor left/right and del */
19837 + clps711x_handykey_init();
19838 + return count;
19841 + return -EINVAL;
19846 + * Initialize the keyboard hardware.
19847 + * Set all columns high
19848 + * Install interrupt handler
19850 + * Machine dependent parameters:
19852 + * fastscan: 0 = timer based scan for each column
19853 + * 1 = full scan is done in one timer event
19854 + * scan_delay: time between column scans
19855 + * setup even if you use fastscan (leeds to timer mode)
19856 + * scan_interval: time between full scans
19857 + * handy.delay: timeout before last entry get's automatically valid
19858 + *
19859 + */
19860 +void __init clps711x_kbd_init_hw(void)
19863 + /*
19864 + * put here machine dependent init stuff
19865 + */
19866 + if (machine_is_autcpu12()) {
19867 + fastscan = 0;
19868 + scan_interval = 50*HZ/1000;
19869 + scan_delay = 20*HZ/1000;
19870 + khandy.delay = 750*HZ/1000;
19871 + act_scancode = autcpu12_scancode;
19872 + } else {
19873 + printk("No initialization, keyboard killed\n");
19874 + return;
19877 + last_column = KBSC_COL0;
19878 + key_is_pressed = 0;
19880 + clps711x_handykey_init();
19882 + /* Register the /proc entry */
19883 + clps711x_keyboard_proc_entry = create_proc_entry("keyboard", 0444,
19884 + &proc_root);
19885 + if (clps711x_keyboard_proc_entry == NULL)
19886 + printk("Couldn't create the /proc entry for the keyboard\n");
19887 + else {
19888 + clps711x_keyboard_proc_entry->read_proc =
19889 + &clps711x_kbd_proc_keyboard_read;
19890 + clps711x_keyboard_proc_entry->write_proc =
19891 + &clps711x_kbd_proc_keyboard_write;
19894 + /* Initialize the matrix processing task. */
19895 + k_translate = clps711x_translate;
19896 + k_unexpected_up = clps711x_unexpected_up;
19897 + kbd_process_task.routine = clps711x_kbd_process;
19898 + kbd_process_task.data = 0;
19900 + /* Setup the timer for keyboard polling, after kbd int */
19901 + init_timer(&clps711x_kbd_timer);
19902 + clps711x_kbd_timer.function = clps711x_kbd_timeout;
19903 + clps711x_kbd_timer.data = 0;
19904 + init_timer(&clps711x_kbdhandy_timer);
19905 + clps711x_kbdhandy_timer.function = clps711x_kbdhandy_timeout;
19906 + clps711x_kbdhandy_timer.data = 1;
19908 + /* Initialise scan hardware, request int */
19909 + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
19910 + | KBSC_HI, SYSCON1);
19911 + request_irq(IRQ_KBDINT, clps711x_kbd_int, 0,"keyboard", NULL);
19913 + printk("clps711x keyboard init done\n");
19916 --- linux-2.4.25/drivers/char/console.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
19917 +++ linux-2.4.25/drivers/char/console.c 2004-03-31 17:15:09.000000000 +0200
19918 @@ -72,8 +72,14 @@
19920 * Removed console_lock, enabled interrupts across all console operations
19921 * 13 March 2001, Andrew Morton
19923 + * Split out con_write_ctrl_* functions from do_con_write & changed
19924 + * vc_state to function pointer
19925 + * by Russell King <rmk@arm.linux.org.uk>, July 1998
19928 +#define CONSOLE_WIP
19930 #include <linux/module.h>
19931 #include <linux/sched.h>
19932 #include <linux/tty.h>
19933 @@ -228,7 +234,7 @@
19934 static inline unsigned short *screenpos(int currcons, int offset, int viewed)
19936 unsigned short *p;
19939 if (!viewed)
19940 p = (unsigned short *)(origin + offset);
19941 else if (!sw->con_screen_pos)
19942 @@ -729,7 +735,7 @@
19943 else {
19944 unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER);
19945 if (!p) {
19946 - for (i = first; i < currcons; i++)
19947 + for (i = first; i< currcons; i++)
19948 if (newscreens[i])
19949 kfree(newscreens[i]);
19950 return -ENOMEM;
19951 @@ -847,7 +853,7 @@
19952 /* the default colour table, for VGA+ colour systems */
19953 int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
19954 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
19955 -int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
19956 +int default_grn[] = {0x00,0x00,0xaa,0xaa,0x00,0x00,0xaa,0xaa,
19957 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
19958 int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
19959 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
19960 @@ -1393,6 +1399,19 @@
19961 need_wrap = 0;
19964 +static int con_write_ctrl_ESnormal(int, struct tty_struct *, unsigned int);
19965 +static int con_write_ctrl_ESesc(int, struct tty_struct *, unsigned int);
19966 +static int con_write_ctrl_ESnonstd(int, struct tty_struct *, unsigned int);
19967 +static int con_write_ctrl_ESpalette(int, struct tty_struct *, unsigned int);
19968 +static int con_write_ctrl_ESsquare(int, struct tty_struct *, unsigned int);
19969 +static int con_write_ctrl_ESgetpars(int, struct tty_struct *, unsigned int);
19970 +static int con_write_ctrl_ESgotpars(int, struct tty_struct *, unsigned int);
19971 +static int con_write_ctrl_ESpercent(int, struct tty_struct *, unsigned int);
19972 +static int con_write_ctrl_ESfunckey(int, struct tty_struct *, unsigned int);
19973 +static int con_write_ctrl_EShash(int, struct tty_struct *, unsigned int);
19974 +static int con_write_ctrl_ESsetG0(int, struct tty_struct *, unsigned int);
19975 +static int con_write_ctrl_ESsetG1(int, struct tty_struct *, unsigned int);
19977 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
19978 EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
19979 ESpalette };
19980 @@ -1402,7 +1421,7 @@
19982 top = 0;
19983 bottom = video_num_lines;
19984 - vc_state = ESnormal;
19985 + vc_state = con_write_ctrl_ESnormal;
19986 ques = 0;
19987 translate = set_translate(LAT1_MAP,currcons);
19988 G0_charset = LAT1_MAP;
19989 @@ -1500,328 +1519,426 @@
19990 disp_ctrl = 0;
19991 return;
19992 case 24: case 26:
19993 - vc_state = ESnormal;
19994 + vc_state = con_write_ctrl_ESnormal;
19995 return;
19996 case 27:
19997 - vc_state = ESesc;
19998 + vc_state = con_write_ctrl_ESesc;
19999 return;
20000 case 127:
20001 del(currcons);
20002 return;
20003 case 128+27:
20004 - vc_state = ESsquare;
20005 + vc_state = con_write_ctrl_ESsquare;
20006 return;
20008 - switch(vc_state) {
20009 - case ESesc:
20010 - vc_state = ESnormal;
20011 - switch (c) {
20012 - case '[':
20013 - vc_state = ESsquare;
20014 - return;
20015 - case ']':
20016 - vc_state = ESnonstd;
20017 - return;
20018 - case '%':
20019 - vc_state = ESpercent;
20020 - return;
20021 - case 'E':
20022 - cr(currcons);
20023 - lf(currcons);
20024 - return;
20025 - case 'M':
20026 - ri(currcons);
20027 - return;
20028 - case 'D':
20029 - lf(currcons);
20030 - return;
20031 - case 'H':
20032 - tab_stop[x >> 5] |= (1 << (x & 31));
20033 - return;
20034 - case 'Z':
20035 - respond_ID(tty);
20036 - return;
20037 - case '7':
20038 - save_cur(currcons);
20039 - return;
20040 - case '8':
20041 - restore_cur(currcons);
20042 - return;
20043 - case '(':
20044 - vc_state = ESsetG0;
20045 - return;
20046 - case ')':
20047 - vc_state = ESsetG1;
20048 - return;
20049 - case '#':
20050 - vc_state = EShash;
20051 - return;
20052 - case 'c':
20053 - reset_terminal(currcons,1);
20054 - return;
20055 - case '>': /* Numeric keypad */
20056 - clr_kbd(kbdapplic);
20057 - return;
20058 - case '=': /* Appl. keypad */
20059 - set_kbd(kbdapplic);
20060 - return;
20061 + vc_state(currcons, tty, c);
20064 +static int con_write_utf(int currcons, int c)
20066 + unsigned int chr;
20068 + /* Combine UTF-8 into Unicode */
20069 + /* Incomplete characters silently ignored */
20070 + if (c < 0x80) {
20071 + utf_count = 0;
20072 + return c;
20075 + if (utf_count > 0 && (c & 0xc0) == 0x80) {
20076 + chr = (utf_char << 6) | (c & 0x3f);
20077 + utf_count--;
20078 + if (utf_count == 0)
20079 + return chr;
20080 + } else {
20081 + unsigned int count;
20082 + if ((c & 0xe0) == 0xc0) {
20083 + count = 1;
20084 + chr = (c & 0x1f);
20085 + } else if ((c & 0xf0) == 0xe0) {
20086 + count = 2;
20087 + chr = (c & 0x0f);
20088 + } else if ((c & 0xf8) == 0xf0) {
20089 + count = 3;
20090 + chr = (c & 0x07);
20091 + } else if ((c & 0xfc) == 0xf8) {
20092 + count = 4;
20093 + chr = (c & 0x03);
20094 + } else if ((c & 0xfe) == 0xfc) {
20095 + count = 5;
20096 + chr = (c & 0x01);
20097 + } else {
20098 + count = 0;
20099 + chr = 0;
20101 - return;
20102 - case ESnonstd:
20103 - if (c=='P') { /* palette escape sequence */
20104 - for (npar=0; npar<NPAR; npar++)
20105 - par[npar] = 0 ;
20106 - npar = 0 ;
20107 - vc_state = ESpalette;
20108 - return;
20109 - } else if (c=='R') { /* reset palette */
20110 - reset_palette(currcons);
20111 - vc_state = ESnormal;
20112 - } else
20113 - vc_state = ESnormal;
20114 - return;
20115 - case ESpalette:
20116 - if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
20117 - par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
20118 - if (npar==7) {
20119 - int i = par[0]*3, j = 1;
20120 - palette[i] = 16*par[j++];
20121 - palette[i++] += par[j++];
20122 - palette[i] = 16*par[j++];
20123 - palette[i++] += par[j++];
20124 - palette[i] = 16*par[j++];
20125 - palette[i] += par[j];
20126 - set_palette(currcons);
20127 - vc_state = ESnormal;
20129 - } else
20130 - vc_state = ESnormal;
20131 - return;
20132 - case ESsquare:
20133 - for(npar = 0 ; npar < NPAR ; npar++)
20134 - par[npar] = 0;
20135 - npar = 0;
20136 - vc_state = ESgetpars;
20137 - if (c == '[') { /* Function key */
20138 - vc_state=ESfunckey;
20139 - return;
20140 + utf_count = count;
20143 + utf_char = chr;
20144 + return -1;
20147 +static int con_write_ctrl_ESnormal(int currcons, struct tty_struct *tty, unsigned int c)
20149 + return 0;
20152 +static int con_write_ctrl_ESesc(int currcons, struct tty_struct *tty, unsigned int c)
20154 + vc_state = con_write_ctrl_ESnormal;
20155 + switch (c) {
20156 + case '[':
20157 + vc_state = con_write_ctrl_ESsquare;
20158 + break;
20159 + case ']':
20160 + vc_state = con_write_ctrl_ESnonstd;
20161 + break;
20162 + case '%':
20163 + vc_state = con_write_ctrl_ESpercent;
20164 + break;
20165 + case 'E':
20166 + cr(currcons);
20167 + lf(currcons);
20168 + break;
20169 + case 'M':
20170 + ri(currcons);
20171 + break;
20172 + case 'D':
20173 + lf(currcons);
20174 + break;
20175 + case 'H':
20176 + tab_stop[x >> 5] |= (1 << (x & 31));
20177 + break;
20178 + case 'Z':
20179 + respond_ID(tty);
20180 + break;
20181 + case '7':
20182 + save_cur(currcons);
20183 + break;
20184 + case '8':
20185 + restore_cur(currcons);
20186 + return 1;
20187 + case '(':
20188 + vc_state = con_write_ctrl_ESsetG0;
20189 + break;
20190 + case ')':
20191 + vc_state = con_write_ctrl_ESsetG1;
20192 + break;
20193 + case '#':
20194 + vc_state = con_write_ctrl_EShash;
20195 + break;
20196 + case 'c':
20197 + reset_terminal(currcons,1);
20198 + return 1;
20199 + case '>': /* Numeric keypad */
20200 + clr_kbd(kbdapplic);
20201 + break;
20202 + case '=': /* Appl. keypad */
20203 + set_kbd(kbdapplic);
20204 + break;
20206 + return 0;
20209 +static int con_write_ctrl_ESnonstd(int currcons, struct tty_struct *tty, unsigned int c)
20211 + switch (c) {
20212 + case 'P': /* palette escape sequence */
20213 + for (npar=0; npar<NPAR; npar++)
20214 + par[npar] = 0 ;
20215 + npar = 0 ;
20216 + vc_state = con_write_ctrl_ESpalette;
20217 + break;
20218 + case 'R': /* reset palette */
20219 + reset_palette (currcons);
20220 + default:
20221 + vc_state = con_write_ctrl_ESnormal;
20223 + return 0;
20226 +static int con_write_ctrl_ESpalette(int currcons, struct tty_struct *tty, unsigned int c)
20228 + if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
20229 + par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
20230 + if (npar==7) {
20231 + int i = par[0]*3, j = 1;
20232 + palette[i] = 16*par[j++];
20233 + palette[i++] += par[j++];
20234 + palette[i] = 16*par[j++];
20235 + palette[i++] += par[j++];
20236 + palette[i] = 16*par[j++];
20237 + palette[i] += par[j];
20238 + set_palette(currcons);
20239 + vc_state = con_write_ctrl_ESnormal;
20241 - ques = (c=='?');
20242 - if (ques)
20243 - return;
20244 - case ESgetpars:
20245 - if (c==';' && npar<NPAR-1) {
20246 - npar++;
20247 - return;
20248 - } else if (c>='0' && c<='9') {
20249 - par[npar] *= 10;
20250 - par[npar] += c-'0';
20251 - return;
20252 - } else vc_state=ESgotpars;
20253 - case ESgotpars:
20254 - vc_state = ESnormal;
20255 - switch(c) {
20256 - case 'h':
20257 - set_mode(currcons,1);
20258 - return;
20259 - case 'l':
20260 - set_mode(currcons,0);
20261 - return;
20262 - case 'c':
20263 - if (ques) {
20264 - if (par[0])
20265 - cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
20266 - else
20267 - cursor_type = CUR_DEFAULT;
20268 - return;
20270 - break;
20271 - case 'm':
20272 - if (ques) {
20273 - clear_selection();
20274 - if (par[0])
20275 - complement_mask = par[0]<<8 | par[1];
20276 - else
20277 - complement_mask = s_complement_mask;
20278 - return;
20280 - break;
20281 - case 'n':
20282 - if (!ques) {
20283 - if (par[0] == 5)
20284 - status_report(tty);
20285 - else if (par[0] == 6)
20286 - cursor_report(currcons,tty);
20288 - return;
20289 + } else
20290 + vc_state = con_write_ctrl_ESnormal;
20291 + return 0;
20294 +static int con_write_ctrl_ESsquare(int currcons, struct tty_struct *tty, unsigned int c)
20296 + for(npar = 0 ; npar < NPAR ; npar++)
20297 + par[npar] = 0;
20298 + npar = 0;
20299 + vc_state = con_write_ctrl_ESgetpars;
20300 + if (c == '[') { /* Function key */
20301 + vc_state = con_write_ctrl_ESfunckey;
20302 + return 0;
20304 + ques = (c=='?');
20305 + if (ques)
20306 + return 0;
20307 + return con_write_ctrl_ESgetpars(currcons, tty, c);
20310 +static int con_write_ctrl_ESgetpars(int currcons, struct tty_struct *tty, unsigned int c)
20312 + if (c==';' && npar<NPAR-1) {
20313 + npar++;
20314 + return 0;
20315 + } else if (c>='0' && c<='9') {
20316 + par[npar] *= 10;
20317 + par[npar] += c-'0';
20318 + return 0;
20319 + } else vc_state = con_write_ctrl_ESgotpars;
20320 + return con_write_ctrl_ESgotpars(currcons, tty, c);
20323 +static int con_write_ctrl_ESgotpars(int currcons, struct tty_struct *tty, unsigned int c)
20325 + vc_state = con_write_ctrl_ESnormal;
20326 + switch(c) {
20327 + case 'h':
20328 + set_mode(currcons,1);
20329 + return 0;
20330 + case 'l':
20331 + set_mode(currcons,0);
20332 + return 0;
20333 + case 'c':
20334 + if (ques) {
20335 + if (par[0])
20336 + cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
20337 + else
20338 + cursor_type = CUR_DEFAULT;
20339 + return 0;
20341 + break;
20342 + case 'm':
20343 if (ques) {
20344 - ques = 0;
20345 - return;
20346 + clear_selection();
20347 + if (par[0])
20348 + complement_mask = par[0]<<8 | par[1];
20349 + else
20350 + complement_mask = s_complement_mask;
20351 + return 0;
20353 - switch(c) {
20354 - case 'G': case '`':
20355 - if (par[0]) par[0]--;
20356 - gotoxy(currcons,par[0],y);
20357 - return;
20358 - case 'A':
20359 - if (!par[0]) par[0]++;
20360 - gotoxy(currcons,x,y-par[0]);
20361 - return;
20362 - case 'B': case 'e':
20363 - if (!par[0]) par[0]++;
20364 - gotoxy(currcons,x,y+par[0]);
20365 - return;
20366 - case 'C': case 'a':
20367 - if (!par[0]) par[0]++;
20368 - gotoxy(currcons,x+par[0],y);
20369 - return;
20370 - case 'D':
20371 - if (!par[0]) par[0]++;
20372 - gotoxy(currcons,x-par[0],y);
20373 - return;
20374 - case 'E':
20375 - if (!par[0]) par[0]++;
20376 - gotoxy(currcons,0,y+par[0]);
20377 - return;
20378 - case 'F':
20379 - if (!par[0]) par[0]++;
20380 - gotoxy(currcons,0,y-par[0]);
20381 - return;
20382 - case 'd':
20383 - if (par[0]) par[0]--;
20384 - gotoxay(currcons,x,par[0]);
20385 - return;
20386 - case 'H': case 'f':
20387 - if (par[0]) par[0]--;
20388 - if (par[1]) par[1]--;
20389 - gotoxay(currcons,par[1],par[0]);
20390 - return;
20391 - case 'J':
20392 - csi_J(currcons,par[0]);
20393 - return;
20394 - case 'K':
20395 - csi_K(currcons,par[0]);
20396 - return;
20397 - case 'L':
20398 - csi_L(currcons,par[0]);
20399 - return;
20400 - case 'M':
20401 - csi_M(currcons,par[0]);
20402 - return;
20403 - case 'P':
20404 - csi_P(currcons,par[0]);
20405 - return;
20406 - case 'c':
20407 - if (!par[0])
20408 - respond_ID(tty);
20409 - return;
20410 - case 'g':
20411 - if (!par[0])
20412 - tab_stop[x >> 5] &= ~(1 << (x & 31));
20413 - else if (par[0] == 3) {
20414 - tab_stop[0] =
20415 - tab_stop[1] =
20416 - tab_stop[2] =
20417 - tab_stop[3] =
20418 - tab_stop[4] = 0;
20420 - return;
20421 - case 'm':
20422 - csi_m(currcons);
20423 - return;
20424 - case 'q': /* DECLL - but only 3 leds */
20425 - /* map 0,1,2,3 to 0,1,2,4 */
20426 - if (par[0] < 4)
20427 - setledstate(kbd_table + currcons,
20428 - (par[0] < 3) ? par[0] : 4);
20429 - return;
20430 - case 'r':
20431 - if (!par[0])
20432 - par[0]++;
20433 - if (!par[1])
20434 - par[1] = video_num_lines;
20435 - /* Minimum allowed region is 2 lines */
20436 - if (par[0] < par[1] &&
20437 - par[1] <= video_num_lines) {
20438 - top=par[0]-1;
20439 - bottom=par[1];
20440 - gotoxay(currcons,0,0);
20442 - return;
20443 - case 's':
20444 - save_cur(currcons);
20445 - return;
20446 - case 'u':
20447 - restore_cur(currcons);
20448 - return;
20449 - case 'X':
20450 - csi_X(currcons, par[0]);
20451 - return;
20452 - case '@':
20453 - csi_at(currcons,par[0]);
20454 - return;
20455 - case ']': /* setterm functions */
20456 - setterm_command(currcons);
20457 - return;
20458 + break;
20459 + case 'n':
20460 + if (!ques) {
20461 + if (par[0] == 5)
20462 + status_report(tty);
20463 + else if (par[0] == 6)
20464 + cursor_report(currcons,tty);
20466 - return;
20467 - case ESpercent:
20468 - vc_state = ESnormal;
20469 - switch (c) {
20470 - case '@': /* defined in ISO 2022 */
20471 - utf = 0;
20472 - return;
20473 - case 'G': /* prelim official escape code */
20474 - case '8': /* retained for compatibility */
20475 - utf = 1;
20476 - return;
20477 + return 0;
20479 + if (ques) {
20480 + ques = 0;
20481 + return 0;
20483 + switch(c) {
20484 + case 'G': case '`':
20485 + if (par[0]) par[0]--;
20486 + gotoxy(currcons,par[0],y);
20487 + break;
20488 + case 'A':
20489 + if (!par[0]) par[0]++;
20490 + gotoxy(currcons,x,y-par[0]);
20491 + break;
20492 + case 'B': case 'e':
20493 + if (!par[0]) par[0]++;
20494 + gotoxy(currcons,x,y+par[0]);
20495 + break;
20496 + case 'C': case 'a':
20497 + if (!par[0]) par[0]++;
20498 + gotoxy(currcons,x+par[0],y);
20499 + break;
20500 + case 'D':
20501 + if (!par[0]) par[0]++;
20502 + gotoxy(currcons,x-par[0],y);
20503 + break;
20504 + case 'E':
20505 + if (!par[0]) par[0]++;
20506 + gotoxy(currcons,0,y+par[0]);
20507 + break;
20508 + case 'F':
20509 + if (!par[0]) par[0]++;
20510 + gotoxy(currcons,0,y-par[0]);
20511 + break;
20512 + case 'd':
20513 + if (par[0]) par[0]--;
20514 + gotoxay(currcons,x,par[0]);
20515 + break;
20516 + case 'H': case 'f':
20517 + if (par[0]) par[0]--;
20518 + if (par[1]) par[1]--;
20519 + gotoxay(currcons,par[1],par[0]);
20520 + break;
20521 + case 'J':
20522 + csi_J(currcons,par[0]);
20523 + break;
20524 + case 'K':
20525 + csi_K(currcons,par[0]);
20526 + break;
20527 + case 'L':
20528 + csi_L(currcons,par[0]);
20529 + break;
20530 + case 'M':
20531 + csi_M(currcons,par[0]);
20532 + break;
20533 + case 'P':
20534 + csi_P(currcons,par[0]);
20535 + break;
20536 + case 'c':
20537 + if (!par[0])
20538 + respond_ID(tty);
20539 + break;
20540 + case 'g':
20541 + if (!par[0])
20542 + tab_stop[x >> 5] &= ~(1 << (x & 31));
20543 + else if (par[0] == 3) {
20544 + tab_stop[0] =
20545 + tab_stop[1] =
20546 + tab_stop[2] =
20547 + tab_stop[3] =
20548 + tab_stop[4] = 0;
20550 - return;
20551 - case ESfunckey:
20552 - vc_state = ESnormal;
20553 - return;
20554 - case EShash:
20555 - vc_state = ESnormal;
20556 - if (c == '8') {
20557 - /* DEC screen alignment test. kludge :-) */
20558 - video_erase_char =
20559 - (video_erase_char & 0xff00) | 'E';
20560 - csi_J(currcons, 2);
20561 - video_erase_char =
20562 - (video_erase_char & 0xff00) | ' ';
20563 - do_update_region(currcons, origin, screenbuf_size/2);
20564 + break;
20565 + case 'm':
20566 + csi_m(currcons);
20567 + return 1;
20568 + case 'q': /* DECLL - but only 3 leds */
20569 + /* map 0,1,2,3 to 0,1,2,4 */
20570 + if (par[0] < 4)
20571 + setledstate(kbd_table + currcons,
20572 + (par[0] < 3) ? par[0] : 4);
20573 + break;
20574 + case 'r':
20575 + if (!par[0])
20576 + par[0]++;
20577 + if (!par[1])
20578 + par[1] = video_num_lines;
20579 + /* Minimum allowed region is 2 lines */
20580 + if (par[0] < par[1] &&
20581 + par[1] <= video_num_lines) {
20582 + top=par[0]-1;
20583 + bottom=par[1];
20584 + gotoxay(currcons,0,0);
20586 - return;
20587 - case ESsetG0:
20588 - if (c == '0')
20589 - G0_charset = GRAF_MAP;
20590 - else if (c == 'B')
20591 - G0_charset = LAT1_MAP;
20592 - else if (c == 'U')
20593 - G0_charset = IBMPC_MAP;
20594 - else if (c == 'K')
20595 - G0_charset = USER_MAP;
20596 - if (charset == 0)
20597 - translate = set_translate(G0_charset,currcons);
20598 - vc_state = ESnormal;
20599 - return;
20600 - case ESsetG1:
20601 - if (c == '0')
20602 - G1_charset = GRAF_MAP;
20603 - else if (c == 'B')
20604 - G1_charset = LAT1_MAP;
20605 - else if (c == 'U')
20606 - G1_charset = IBMPC_MAP;
20607 - else if (c == 'K')
20608 - G1_charset = USER_MAP;
20609 - if (charset == 1)
20610 - translate = set_translate(G1_charset,currcons);
20611 - vc_state = ESnormal;
20612 - return;
20613 - default:
20614 - vc_state = ESnormal;
20615 + break;
20616 + case 's':
20617 + save_cur(currcons);
20618 + break;
20619 + case 'u':
20620 + restore_cur(currcons);
20621 + return 1;
20622 + case 'X':
20623 + csi_X(currcons, par[0]);
20624 + break;
20625 + case '@':
20626 + csi_at(currcons,par[0]);
20627 + break;
20628 + case ']': /* setterm functions */
20629 + setterm_command(currcons);
20630 + break;
20632 + return 0;
20635 +static int con_write_ctrl_ESpercent(int currcons, struct tty_struct *tty, unsigned int c)
20637 + vc_state = con_write_ctrl_ESnormal;
20638 + switch (c) {
20639 + case '@': /* defined in ISO 2022 */
20640 + utf = 0;
20641 + break;
20642 + case 'G': /* prelim official escape code */
20643 + case '8': /* retained for compatibility */
20644 + utf = 1;
20645 + break;
20647 + return 0;
20650 +static int con_write_ctrl_ESfunckey(int currcons, struct tty_struct *tty, unsigned int c)
20652 + vc_state = con_write_ctrl_ESnormal;
20653 + return 0;
20656 +static int con_write_ctrl_EShash(int currcons, struct tty_struct *tty, unsigned int c)
20658 + vc_state = con_write_ctrl_ESnormal;
20659 + if (c == '8') {
20660 + /* DEC screen alignment test. kludge :-) */
20661 + video_erase_char =
20662 + (video_erase_char & 0xff00) | 'E';
20663 + csi_J(currcons, 2);
20664 + video_erase_char =
20665 + (video_erase_char & 0xff00) | ' ';
20666 + do_update_region(currcons, origin, screenbuf_size/2);
20668 + return 0;
20671 +static int con_write_ctrl_ESsetG0(int currcons, struct tty_struct *tty, unsigned int c)
20673 + switch (c) {
20674 + case '0':
20675 + G0_charset = GRAF_MAP;
20676 + break;
20677 + case 'B':
20678 + G0_charset = LAT1_MAP;
20679 + break;
20680 + case 'U':
20681 + G0_charset = IBMPC_MAP;
20682 + break;
20683 + case 'K':
20684 + G0_charset = USER_MAP;
20685 + break;
20687 + if (charset == 0) {
20688 + translate = set_translate(G0_charset,currcons);
20689 + return 1;
20691 + vc_state = con_write_ctrl_ESnormal;
20692 + return 0;
20695 +static int con_write_ctrl_ESsetG1(int currcons, struct tty_struct *tty, unsigned int c)
20697 + switch (c) {
20698 + case '0':
20699 + G1_charset = GRAF_MAP;
20700 + break;
20701 + case 'B':
20702 + G1_charset = LAT1_MAP;
20703 + break;
20704 + case 'U':
20705 + G1_charset = IBMPC_MAP;
20706 + break;
20707 + case 'K':
20708 + G1_charset = USER_MAP;
20709 + break;
20711 + if (charset == 1) {
20712 + translate = set_translate(G1_charset,currcons);
20713 + return 1;
20715 + vc_state = con_write_ctrl_ESnormal;
20716 + return 0;
20719 /* This is a temporary buffer used to prepare a tty console write
20720 @@ -1855,7 +1972,7 @@
20721 unsigned long draw_from = 0, draw_to = 0;
20722 struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
20723 u16 himask, charmask;
20724 - const unsigned char *orig_buf = NULL;
20725 + const unsigned char *orig_buf;
20726 int orig_count;
20728 if (in_interrupt())
20729 @@ -1913,42 +2030,12 @@
20730 count--;
20732 if (utf) {
20733 - /* Combine UTF-8 into Unicode */
20734 - /* Incomplete characters silently ignored */
20735 - if(c > 0x7f) {
20736 - if (utf_count > 0 && (c & 0xc0) == 0x80) {
20737 - utf_char = (utf_char << 6) | (c & 0x3f);
20738 - utf_count--;
20739 - if (utf_count == 0)
20740 - tc = c = utf_char;
20741 - else continue;
20742 - } else {
20743 - if ((c & 0xe0) == 0xc0) {
20744 - utf_count = 1;
20745 - utf_char = (c & 0x1f);
20746 - } else if ((c & 0xf0) == 0xe0) {
20747 - utf_count = 2;
20748 - utf_char = (c & 0x0f);
20749 - } else if ((c & 0xf8) == 0xf0) {
20750 - utf_count = 3;
20751 - utf_char = (c & 0x07);
20752 - } else if ((c & 0xfc) == 0xf8) {
20753 - utf_count = 4;
20754 - utf_char = (c & 0x03);
20755 - } else if ((c & 0xfe) == 0xfc) {
20756 - utf_count = 5;
20757 - utf_char = (c & 0x01);
20758 - } else
20759 - utf_count = 0;
20760 + tc = con_write_utf(currcons, c);
20761 + if (tc < 0)
20762 continue;
20764 - } else {
20765 - tc = c;
20766 - utf_count = 0;
20768 - } else { /* no utf */
20769 - tc = translate[toggle_meta ? (c|0x80) : c];
20771 + c = tc;
20772 + } else /* no utf */
20773 + tc = translate[toggle_meta ? (c|0x80) : c];
20775 /* If the original code was a control character we
20776 * only allow a glyph to be displayed if the code is
20777 @@ -1966,7 +2053,7 @@
20778 && (c != 127 || disp_ctrl)
20779 && (c != 128+27);
20781 - if (vc_state == ESnormal && ok) {
20782 + if (vc_state == con_write_ctrl_ESnormal && ok) {
20783 /* Now try to find out how to display it */
20784 tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
20785 if ( tc == -4 ) {
20786 @@ -2112,7 +2199,7 @@
20787 if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
20788 currcons = kmsg_redirect - 1;
20790 - /* read `x' only after setting currecons properly (otherwise
20791 + /* read `x' only after setting currcons properly (otherwise
20792 the `x' macro will read the x of the foreground console). */
20793 myx = x;
20795 @@ -2475,8 +2562,8 @@
20796 console_driver.init_termios = tty_std_termios;
20797 console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
20798 /* Tell tty_register_driver() to skip consoles because they are
20799 - * registered before kmalloc() is ready. We'll patch them in later.
20800 - * See comments at console_init(); see also con_init_devfs().
20801 + * registered before kmalloc() is ready. We'll patch them in later.
20802 + * See comments at console_init(); see also con_init_devfs().
20804 console_driver.flags |= TTY_DRIVER_NO_DEVFS;
20805 console_driver.refcount = &console_refcount;
20806 @@ -2719,7 +2806,7 @@
20808 if (console_blank_hook && console_blank_hook(1))
20809 return;
20810 - if (vesa_blank_mode)
20811 + if (vesa_blank_mode)
20812 sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
20815 @@ -2893,7 +2980,7 @@
20816 if (!op->height) { /* Need to guess font height [compat] */
20817 int h, i;
20818 u8 *charmap = op->data, tmp;
20821 /* If from KDFONTOP ioctl, don't allow things which can be done in userland,
20822 so that we can get rid of this soon */
20823 if (!(op->flags & KD_FONT_FLAG_OLD))
20824 @@ -2940,18 +3027,18 @@
20825 op->data = old_op.data;
20826 if (!rc && !set) {
20827 int c = (op->width+7)/8 * 32 * op->charcount;
20830 if (op->data && op->charcount > old_op.charcount)
20831 rc = -ENOSPC;
20832 if (!(op->flags & KD_FONT_FLAG_OLD)) {
20833 - if (op->width > old_op.width ||
20834 + if (op->width > old_op.width ||
20835 op->height > old_op.height)
20836 rc = -ENOSPC;
20837 } else {
20838 if (op->width != 8)
20839 rc = -EIO;
20840 else if ((old_op.height && op->height > old_op.height) ||
20841 - op->height > 32)
20842 + op->height > 32)
20843 rc = -ENOSPC;
20845 if (!rc && op->data && copy_to_user(op->data, temp, c))
20846 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
20847 +++ linux-2.4.25/drivers/char/ds1307.c 2004-03-31 17:15:09.000000000 +0200
20848 @@ -0,0 +1,604 @@
20850 + * ds1307.c
20852 + * Device driver for Dallas Semiconductor's Real Time Controller DS1307.
20854 + * Copyright (C) 2002 Intrinsyc Software Inc.
20856 + * This program is free software; you can redistribute it and/or modify
20857 + * it under the terms of the GNU General Public License version 2 as
20858 + * published by the Free Software Foundation.
20860 + */
20862 +#include <linux/config.h>
20863 +#include <linux/module.h>
20864 +#include <linux/version.h>
20866 +#include <linux/kernel.h>
20867 +#include <linux/poll.h>
20868 +#include <linux/i2c.h>
20869 +#include <linux/slab.h>
20870 +#include <linux/init.h>
20871 +#include <linux/rtc.h>
20872 +#include <linux/string.h>
20873 +#include <linux/miscdevice.h>
20874 +#include <linux/proc_fs.h>
20876 +#include "ds1307.h"
20878 +#define DEBUG 0
20880 +#if DEBUG
20881 +static unsigned int rtc_debug = DEBUG;
20882 +#else
20883 +#define rtc_debug 0 /* gcc will remove all the debug code for us */
20884 +#endif
20886 +static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR;
20888 +struct i2c_driver ds1307_driver;
20889 +struct i2c_client *ds1307_i2c_client = 0;
20891 +static unsigned short ignore[] = { I2C_CLIENT_END };
20892 +static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END };
20894 +static struct i2c_client_address_data addr_data = {
20895 + normal_i2c: normal_addr,
20896 + normal_i2c_range: ignore,
20897 + probe: ignore,
20898 + probe_range: ignore,
20899 + ignore: ignore,
20900 + ignore_range: ignore,
20901 + force: ignore,
20904 +static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long);
20905 +static int ds1307_rtc_open(struct inode *inode, struct file *file);
20906 +static int ds1307_rtc_release(struct inode *inode, struct file *file);
20908 +static struct file_operations rtc_fops = {
20909 + owner: THIS_MODULE,
20910 + ioctl: ds1307_rtc_ioctl,
20911 + open: ds1307_rtc_open,
20912 + release: ds1307_rtc_release,
20915 +static struct miscdevice ds1307_rtc_miscdev = {
20916 + RTC_MINOR,
20917 + "rtc",
20918 + &rtc_fops
20921 +static int ds1307_probe(struct i2c_adapter *adap);
20922 +static int ds1307_detach(struct i2c_client *client);
20923 +static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg);
20925 +struct i2c_driver ds1307_driver = {
20926 + name: "DS1307",
20927 + id: I2C_DRIVERID_DS1307,
20928 + flags: I2C_DF_NOTIFY,
20929 + attach_adapter: ds1307_probe,
20930 + detach_client: ds1307_detach,
20931 + command: ds1307_command
20934 +static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED;
20936 +#define DAT(x) ((unsigned int)((x)->data)) /* keep the control register info */
20938 +static int
20939 +ds1307_readram( char *buf, int len)
20941 + unsigned long flags;
20942 + unsigned char ad[1] = { 0 };
20943 + int ret;
20944 + struct i2c_msg msgs[2] = {
20945 + { ds1307_i2c_client->addr , 0, 1, ad },
20946 + { ds1307_i2c_client->addr , I2C_M_RD, len, buf } };
20948 + spin_lock_irqsave(&ds1307_rtc_lock, flags);
20949 + ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
20950 + spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
20952 + return ret;
20955 +static void
20956 +ds1307_dumpram( void)
20958 + unsigned char buf[DS1307_RAM_SIZE];
20959 + int ret;
20961 + ret = ds1307_readram( buf, DS1307_RAM_SIZE);
20963 + if( ret > 0)
20965 + int i;
20966 + for( i=0; i<DS1307_RAM_SIZE; i++)
20968 + printk ("%02X ", buf[i]);
20969 + if( (i%8) == 7) printk ("\n");
20971 + printk ("\n");
20975 +static void
20976 +ds1307_enable_clock( int enable)
20978 + unsigned char buf[2], ad[1] = { 0 };
20979 + struct i2c_msg msgs[2] = {
20980 + { ds1307_i2c_client->addr , 0, 1, ad },
20981 + { ds1307_i2c_client->addr , I2C_M_RD, 1, buf }
20982 + };
20983 + unsigned char ctrl_info;
20984 + int ret;
20986 + if( enable)
20987 + ctrl_info = SQW_ENABLE | RATE_32768HZ;
20988 + else
20989 + ctrl_info = SQW_DISABLE;
20990 + ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info);
20992 + /* read addr 0 (Clock-Halt bit and second counter */
20993 + ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
20995 + if( enable)
20996 + buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */
20997 + else
20998 + buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */
20999 + buf[0] = 0; /* control register address on DS1307 */
21001 + ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2);
21004 +static int
21005 +ds1307_attach(struct i2c_adapter *adap, int addr, unsigned short flags,int kind)
21007 + struct i2c_client *c;
21008 + unsigned char buf[1], ad[1] = { 7 };
21009 + struct i2c_msg msgs[2] = {
21010 + { addr , 0, 1, ad },
21011 + { addr , I2C_M_RD, 1, buf }
21012 + };
21013 + int ret;
21015 + c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL);
21016 + if (!c)
21017 + return -ENOMEM;
21019 + strcpy(c->name, "DS1307");
21020 + c->id = ds1307_driver.id;
21021 + c->flags = 0;
21022 + c->addr = addr;
21023 + c->adapter = adap;
21024 + c->driver = &ds1307_driver;
21025 + c->data = NULL;
21027 + ret = i2c_transfer(c->adapter, msgs, 2);
21029 + if ( ret == 2 )
21031 + DAT(c) = buf[0];
21033 + else
21034 + printk ("ds1307_attach(): i2c_transfer() returned %d.\n",ret);
21036 + ds1307_i2c_client = c;
21037 + ds1307_enable_clock( 1);
21039 + return i2c_attach_client(c);
21042 +static int
21043 +ds1307_probe(struct i2c_adapter *adap)
21045 + return i2c_probe(adap, &addr_data, ds1307_attach);
21048 +static int
21049 +ds1307_detach(struct i2c_client *client)
21051 + i2c_detach_client(client);
21052 + ds1307_enable_clock( 0);
21054 + return 0;
21057 +static void
21058 +ds1307_convert_to_time( struct rtc_time *dt, char *buf)
21060 + dt->tm_sec = BCD_TO_BIN(buf[0]);
21061 + dt->tm_min = BCD_TO_BIN(buf[1]);
21063 + if ( TWELVE_HOUR_MODE(buf[2]) )
21065 + dt->tm_hour = HOURS_12(buf[2]);
21066 + if (HOURS_AP(buf[2])) /* PM */
21068 + dt->tm_hour += 12;
21071 + else /* 24-hour-mode */
21073 + dt->tm_hour = HOURS_24(buf[2]);
21076 + dt->tm_mday = BCD_TO_BIN(buf[4]);
21077 + /* dt->tm_mon is zero-based */
21078 + dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
21079 + /* year is 1900 + dt->tm_year */
21080 + dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
21082 + if( rtc_debug > 2)
21084 + printk("ds1307_get_datetime: year = %d\n", dt->tm_year);
21085 + printk("ds1307_get_datetime: mon = %d\n", dt->tm_mon);
21086 + printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday);
21087 + printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour);
21088 + printk("ds1307_get_datetime: min = %d\n", dt->tm_min);
21089 + printk("ds1307_get_datetime: sec = %d\n", dt->tm_sec);
21093 +static int
21094 +ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt)
21096 + unsigned char buf[7], addr[1] = { 0 };
21097 + struct i2c_msg msgs[2] = {
21098 + { client->addr, 0, 1, addr },
21099 + { client->addr, I2C_M_RD, 7, buf }
21100 + };
21101 + int ret = -EIO;
21103 + memset(buf, 0, sizeof(buf));
21105 + ret = i2c_transfer(client->adapter, msgs, 2);
21107 + if (ret == 2) {
21108 + ds1307_convert_to_time( dt, buf);
21109 + ret = 0;
21111 + else
21112 + printk("ds1307_get_datetime(), i2c_transfer() returned %d\n",ret);
21114 + return ret;
21117 +static int
21118 +ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
21120 + unsigned char buf[8];
21121 + int ret, len = 4;
21123 + if( rtc_debug > 2)
21125 + printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year);
21126 + printk("ds1307_set_datetime: tm_mon = %d\n", dt->tm_mon);
21127 + printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday);
21128 + printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour);
21129 + printk("ds1307_set_datetime: tm_min = %d\n", dt->tm_min);
21130 + printk("ds1307_set_datetime: tm_sec = %d\n", dt->tm_sec);
21133 + buf[0] = 0; /* register address on DS1307 */
21134 + buf[1] = (BIN_TO_BCD(dt->tm_sec));
21135 + buf[2] = (BIN_TO_BCD(dt->tm_min));
21136 + buf[3] = (BIN_TO_BCD(dt->tm_hour));
21138 + if (datetoo) {
21139 + len = 8;
21140 + /* we skip buf[4] as we don't use day-of-week. */
21141 + buf[5] = (BIN_TO_BCD(dt->tm_mday));
21142 + buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
21143 + /* The year only ranges from 0-99, we are being passed an offset from 1900,
21144 + * and the chip calulates leap years based on 2000, thus we adjust by 100.
21145 + */
21146 + buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
21148 + ret = i2c_master_send(client, (char *)buf, len);
21149 + if (ret == len)
21150 + ret = 0;
21151 + else
21152 + printk("ds1307_set_datetime(), i2c_master_send() returned %d\n",ret);
21155 + return ret;
21158 +static int
21159 +ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
21161 + *ctrl = DAT(client);
21163 + return 0;
21166 +static int
21167 +ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
21169 + unsigned char buf[2];
21170 + int ret;
21173 + buf[0] = 7; /* control register address on DS1307 */
21174 + buf[1] = *cinfo;
21175 + /* save the control reg info in the client data field so that get_ctrl
21176 + * function doesn't have to do an I2C transfer to get it.
21177 + */
21178 + DAT(client) = buf[1];
21180 + ret = i2c_master_send(client, (char *)buf, 2);
21182 + return ret;
21185 +static int
21186 +ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem)
21188 + unsigned char addr[1];
21189 + struct i2c_msg msgs[2] = {
21190 + { client->addr, 0, 1, addr },
21191 + { client->addr, I2C_M_RD, mem->nr, mem->data }
21192 + };
21194 + if ( (mem->loc < DS1307_RAM_ADDR_START) ||
21195 + ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
21196 + return -EINVAL;
21198 + addr[0] = mem->loc;
21200 + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
21203 +static int
21204 +ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem)
21206 + unsigned char addr[1];
21207 + struct i2c_msg msgs[2] = {
21208 + { client->addr, 0, 1, addr },
21209 + { client->addr, 0, mem->nr, mem->data }
21210 + };
21212 + if ( (mem->loc < DS1307_RAM_ADDR_START) ||
21213 + ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
21214 + return -EINVAL;
21216 + addr[0] = mem->loc;
21218 + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
21221 +static int
21222 +ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg)
21224 + switch (cmd) {
21225 + case DS1307_GETDATETIME:
21226 + return ds1307_get_datetime(client, arg);
21228 + case DS1307_SETTIME:
21229 + return ds1307_set_datetime(client, arg, 0);
21231 + case DS1307_SETDATETIME:
21232 + return ds1307_set_datetime(client, arg, 1);
21234 + case DS1307_GETCTRL:
21235 + return ds1307_get_ctrl(client, arg);
21237 + case DS1307_SETCTRL:
21238 + return ds1307_set_ctrl(client, arg);
21240 + case DS1307_MEM_READ:
21241 + return ds1307_read_mem(client, arg);
21243 + case DS1307_MEM_WRITE:
21244 + return ds1307_write_mem(client, arg);
21246 + default:
21247 + return -EINVAL;
21251 +static int
21252 +ds1307_rtc_open(struct inode *inode, struct file *file)
21254 + return 0;
21257 +static int
21258 +ds1307_rtc_release(struct inode *inode, struct file *file)
21260 + return 0;
21263 +static int
21264 +ds1307_rtc_ioctl( struct inode *inode, struct file *file,
21265 + unsigned int cmd, unsigned long arg)
21267 + unsigned long flags;
21268 + struct rtc_time wtime;
21269 + int status = 0;
21271 + switch (cmd) {
21272 + default:
21273 + case RTC_UIE_ON:
21274 + case RTC_UIE_OFF:
21275 + case RTC_PIE_ON:
21276 + case RTC_PIE_OFF:
21277 + case RTC_AIE_ON:
21278 + case RTC_AIE_OFF:
21279 + case RTC_ALM_SET:
21280 + case RTC_ALM_READ:
21281 + case RTC_IRQP_READ:
21282 + case RTC_IRQP_SET:
21283 + case RTC_EPOCH_READ:
21284 + case RTC_EPOCH_SET:
21285 + case RTC_WKALM_SET:
21286 + case RTC_WKALM_RD:
21287 + status = -EINVAL;
21288 + break;
21290 + case RTC_RD_TIME:
21291 + spin_lock_irqsave(&ds1307_rtc_lock, flags);
21292 + ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime);
21293 + spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
21295 + if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)))
21296 + status = -EFAULT;
21297 + break;
21299 + case RTC_SET_TIME:
21300 + if (!capable(CAP_SYS_TIME))
21302 + status = -EACCES;
21303 + break;
21306 + if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
21308 + status = -EFAULT;
21309 + break;
21312 + spin_lock_irqsave(&ds1307_rtc_lock, flags);
21313 + ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime);
21314 + spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
21315 + break;
21318 + return status;
21321 +static char *
21322 +ds1307_mon2str( unsigned int mon)
21324 + char *mon2str[12] = {
21325 + "Jan", "Feb", "Mar", "Apr", "May", "Jun",
21326 + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
21327 + };
21328 + if( mon > 11) return "error";
21329 + else return mon2str[ mon];
21332 +static int ds1307_rtc_proc_output( char *buf)
21334 +#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
21335 + unsigned char ram[DS1307_RAM_SIZE];
21336 + int ret;
21338 + char *p = buf;
21340 + ret = ds1307_readram( ram, DS1307_RAM_SIZE);
21341 + if( ret > 0)
21343 + int i;
21344 + struct rtc_time dt;
21345 + char text[9];
21347 + p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n");
21349 + ds1307_convert_to_time( &dt, ram);
21350 + p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n",
21351 + dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900,
21352 + dt.tm_hour, dt.tm_min, dt.tm_sec);
21354 + p += sprintf(p, "Clock halted : %s\n", CHECK(ram[0],0x80));
21355 + p += sprintf(p, "24h mode : %s\n", CHECK(ram[2],0x40));
21356 + p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10));
21357 + p += sprintf(p, "Freq : ");
21359 + switch( ram[7] & 0x03)
21361 + case RATE_1HZ:
21362 + p += sprintf(p, "1Hz\n");
21363 + break;
21364 + case RATE_4096HZ:
21365 + p += sprintf(p, "4.096kHz\n");
21366 + break;
21367 + case RATE_8192HZ:
21368 + p += sprintf(p, "8.192kHz\n");
21369 + break;
21370 + case RATE_32768HZ:
21371 + default:
21372 + p += sprintf(p, "32.768kHz\n");
21373 + break;
21377 + p += sprintf(p, "RAM dump:\n");
21378 + text[8]='\0';
21379 + for( i=0; i<DS1307_RAM_SIZE; i++)
21381 + p += sprintf(p, "%02X ", ram[i]);
21383 + if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.';
21384 + text[i%8] = ram[i];
21385 + if( (i%8) == 7) p += sprintf(p, "%s\n",text);
21387 + p += sprintf(p, "\n");
21389 + else
21391 + p += sprintf(p, "Failed to read RTC memory!\n");
21394 + return p - buf;
21397 +static int ds1307_rtc_read_proc(char *page, char **start, off_t off,
21398 + int count, int *eof, void *data)
21400 + int len = ds1307_rtc_proc_output (page);
21401 + if (len <= off+count) *eof = 1;
21402 + *start = page + off;
21403 + len -= off;
21404 + if (len>count) len = count;
21405 + if (len<0) len = 0;
21406 + return len;
21409 +static __init int ds1307_init(void)
21411 + int retval=0;
21413 + if( slave_address != 0xffff)
21415 + normal_addr[0] = slave_address;
21418 + if( normal_addr[0] == 0xffff)
21420 + printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n",
21421 + normal_addr[0]);
21422 + return -EINVAL;
21425 + retval = i2c_add_driver(&ds1307_driver);
21427 + if (retval==0)
21429 + misc_register (&ds1307_rtc_miscdev);
21430 + create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL);
21431 + printk("I2C: DS1307 RTC driver successfully loaded\n");
21433 + if( rtc_debug) ds1307_dumpram();
21435 + return retval;
21438 +static __exit void ds1307_exit(void)
21440 + remove_proc_entry (PROC_DS1307_NAME, NULL);
21441 + misc_deregister(&ds1307_rtc_miscdev);
21442 + i2c_del_driver(&ds1307_driver);
21445 +module_init(ds1307_init);
21446 +module_exit(ds1307_exit);
21448 +MODULE_PARM (slave_address, "i");
21449 +MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC.");
21451 +MODULE_AUTHOR ("Intrinsyc Software Inc.");
21452 +MODULE_LICENSE("GPL");
21453 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
21454 +++ linux-2.4.25/drivers/char/ds1307.h 2004-03-31 17:15:09.000000000 +0200
21455 @@ -0,0 +1,58 @@
21457 + * ds1307.h
21459 + * Copyright (C) 2002 Intrinsyc Software Inc.
21461 + * This program is free software; you can redistribute it and/or modify
21462 + * it under the terms of the GNU General Public License version 2 as
21463 + * published by the Free Software Foundation.
21465 + */
21466 +#ifndef DS1307_H
21467 +#define DS1307_H
21469 +#if defined(CONFIG_PXA_EMERSON_SBC) || defined(CONFIG_PXA_CERF_BOARD) || defined(CONFIG_MACH_CSB337)
21470 + #define DS1307_I2C_SLAVE_ADDR 0x68
21471 +#else
21472 + #define DS1307_I2C_SLAVE_ADDR 0xffff
21473 +#endif
21475 +#define DS1307_RAM_ADDR_START 0x08
21476 +#define DS1307_RAM_ADDR_END 0x3F
21477 +#define DS1307_RAM_SIZE 0x40
21479 +#define PROC_DS1307_NAME "driver/ds1307"
21481 +struct rtc_mem {
21482 + unsigned int loc;
21483 + unsigned int nr;
21484 + unsigned char *data;
21487 +#define DS1307_GETDATETIME 0
21488 +#define DS1307_SETTIME 1
21489 +#define DS1307_SETDATETIME 2
21490 +#define DS1307_GETCTRL 3
21491 +#define DS1307_SETCTRL 4
21492 +#define DS1307_MEM_READ 5
21493 +#define DS1307_MEM_WRITE 6
21495 +#define SQW_ENABLE 0x10 /* Square Wave Enable */
21496 +#define SQW_DISABLE 0x00 /* Square Wave disable */
21498 +#define RATE_32768HZ 0x03 /* Rate Select 32.768KHz */
21499 +#define RATE_8192HZ 0x02 /* Rate Select 8.192KHz */
21500 +#define RATE_4096HZ 0x01 /* Rate Select 4.096KHz */
21501 +#define RATE_1HZ 0x00 /* Rate Select 1Hz */
21503 +#define CLOCK_HALT 0x80 /* Clock Halt */
21505 +#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
21506 +#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
21508 +#define TWELVE_HOUR_MODE(n) (((n)>>6)&1)
21509 +#define HOURS_AP(n) (((n)>>5)&1)
21510 +#define HOURS_12(n) BCD_TO_BIN((n)&0x1F)
21511 +#define HOURS_24(n) BCD_TO_BIN((n)&0x3F)
21513 +#endif
21514 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
21515 +++ linux-2.4.25/drivers/char/edb7211_keyb.c 2004-03-31 17:15:09.000000000 +0200
21516 @@ -0,0 +1,335 @@
21518 + * drivers/char/edb7211_keyb.c
21520 + * Copyright (C) 2000 Blue Mug, Inc. All Rights Reserved.
21522 + * EDB7211 Keyboard driver for ARM Linux.
21524 + * The EP7211 keyboard hardware only supports generating interrupts for 64 keys.
21525 + * The EBD7211's keyboard has 84 keys. Therefore we need to poll for keys,
21526 + * instead of waiting for interrupts.
21528 + * In a real-world hardware situation, this would be a bad thing. It would
21529 + * kill power management.
21530 + */
21532 +#include <linux/config.h>
21533 +#include <linux/sched.h>
21534 +#include <linux/interrupt.h>
21535 +#include <linux/tty.h>
21536 +#include <linux/tty_flip.h>
21537 +#include <linux/mm.h>
21538 +#include <linux/slab.h>
21539 +#include <linux/ptrace.h>
21540 +#include <linux/signal.h>
21541 +#include <linux/timer.h>
21542 +#include <linux/tqueue.h>
21543 +#include <linux/random.h>
21544 +#include <linux/ctype.h>
21545 +#include <linux/init.h>
21546 +#include <linux/kbd_ll.h>
21547 +#include <linux/kbd_kern.h>
21548 +#include <linux/delay.h>
21550 +#include <asm/bitops.h>
21551 +#include <asm/keyboard.h>
21552 +#include <asm/irq.h>
21553 +#include <asm/hardware.h>
21555 +#include <asm/io.h>
21556 +#include <asm/system.h>
21560 + * The number of jiffies between keyboard scans.
21561 + */
21562 +#define KEYBOARD_SCAN_INTERVAL 5
21565 + * Values for the keyboard column scan control register.
21566 + */
21567 +#define KBSC_HI 0x0 /* All driven high */
21568 +#define KBSC_LO 0x1 /* All driven low */
21569 +#define KBSC_X 0x2 /* All high impedance */
21570 +#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
21571 +#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
21572 +#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
21573 +#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
21574 +#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
21575 +#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
21576 +#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
21577 +#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
21580 +/* XXX: Figure out what these values should be... */
21581 +/* Simple translation table for the SysRq keys */
21582 +#ifdef CONFIG_MAGIC_SYSRQ
21583 +unsigned char edb7211_kbd_sysrq_xlate[128] =
21584 + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
21585 + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
21586 + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
21587 + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
21588 + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
21589 + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
21590 + "\r\000/"; /* 0x60 - 0x6f */
21591 +#endif
21593 +/*
21594 + * Row/column to scancode mappings.
21596 + * This table maps row/column keyboard matrix positions to XT scancodes.
21597 + *
21598 + * The port A rows come first, followed by the extended rows.
21599 + */
21600 +static unsigned char colrow_2_scancode[128] =
21602 +/* Column:
21603 + Row 0 1 2 3 4 5 6 7 */
21604 +/* A0 */ 0x01, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x40, 0x41,
21605 +/* A1 */ 0x02, 0x07, 0x06, 0x05, 0x04, 0x03, 0x08, 0x09,
21606 +/* A2 */ 0x0f, 0x14, 0x13, 0x12, 0x11, 0x10, 0x15, 0x16,
21607 +/* A3 */ 0x3a, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x23, 0x24,
21608 +/* A4 */ 0x29, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x31, 0x32,
21609 +/* A5 */ 0x39, 0x35, 0x6F, 0x52, 0x00, 0x6B, 0x34, 0x33,
21610 +/* A6 */ 0x6A, 0x27, 0x28, 0x00, 0x1c, 0x6D, 0x26, 0x25,
21611 +/* A7 */ 0x67, 0x19, 0x1a, 0x1b, 0x2b, 0x68, 0x18, 0x17,
21612 +/* E0 */ 0x6C, 0x0c, 0x0d, 0x0e, 0x00, 0x66, 0x0b, 0x0a,
21613 +/* E1 */ 0x69, 0x44, 0x45, 0x37, 0x46, 0x77, 0x43, 0x42,
21614 +/* E2 */ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21615 +/* E3 */ 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21616 +/* E4 */ 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21617 +/* E5 */ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21618 +/* E6 */ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21619 +/* E7 */ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
21623 + * A bitfield array which contains the state of the keyboard after the last
21624 + * scan. A bit set in this array corresponds to a key down. Only the lower
21625 + * 16 bits of each array element are used.
21626 + */
21627 +static unsigned long previous_keys[8];
21628 +static unsigned long keys[8];
21631 +/* This will be set to a non-zero value if a key was found to be pressed
21632 + * in the last scan. */
21633 +static int key_is_pressed;
21635 +static struct tq_struct kbd_process_task;
21636 +static struct timer_list edb7211_kbd_timer;
21639 + * External methods.
21640 + */
21641 +void edb7211_kbd_init_hw(void);
21643 +/*
21644 + * Internal methods.
21645 + */
21646 +static int edb7211_kbd_scan_matrix(u_long* keys);
21647 +static void edb7211_kbd_timeout(unsigned long data);
21648 +static void edb7211_kbd_process(void* data);
21651 + * Translate a raw keycode to an XT keyboard scancode.
21652 + */
21653 +static int
21654 +edb7211_translate(unsigned char scancode, unsigned char *keycode,
21655 + char raw_mode)
21657 + *keycode = colrow_2_scancode[scancode & 0x7f];
21658 + return 1;
21662 + * Scan the keyboard matrix; for each key that is pressed, set the
21663 + * corresponding bit in the bitfield array.
21665 + * The parameter is expected to be an array of 8 32-bit values. Only the lower
21666 + * 16 bits of each value is used. Each value contains the row bits for the
21667 + * corresponding column.
21668 + */
21669 +static int
21670 +edb7211_kbd_scan_matrix(u_long* keys)
21672 + int column, row, key_pressed;
21673 + unsigned char port_a_data, ext_port_data;
21675 + key_pressed = 0;
21677 + /* Drive all the columns low. */
21678 + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_LO,
21679 + SYSCON1);
21681 + for (column = 0; column < 8; column++) {
21683 + /* Drive the column high. */
21684 + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) |
21685 + (KBSC_COL0 + column), SYSCON1);
21687 + /* Read port A and the extended port. */
21688 + port_a_data = clps_readb(PADR) & 0xff;
21689 + ext_port_data = __raw_readb(EP7211_VIRT_EXTKBD) & 0xff;
21691 + /* Drive all columns tri-state. */
21692 + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
21693 + SYSCON1);
21695 + /* Look at each column in port A. */
21696 + for (row=0; row < 8; row++) {
21697 + /* If the row's bit is set, set the bit in the bitfield.
21698 + * Otherwise, clear it.
21699 + */
21700 + if (port_a_data & (1 << row)) {
21701 + keys[column] |= (1 << row);
21702 + key_pressed = 1;
21703 + } else {
21704 + keys[column] &= ~(1 << row);
21708 + /* Look at each column in the extended port. */
21709 + for (row=0; row < 8; row++) {
21710 + /* If the row's bit is set, set the bit in the bitfield.
21711 + * Otherwise, clear it.
21712 + */
21713 + if (ext_port_data & (1 << row)) {
21714 + keys[column] |= (1 << (row + 8));
21715 + key_pressed = 1;
21716 + } else {
21717 + keys[column] &= ~(1 << (row + 8));
21721 + /*
21722 + * Short delay: The example code for the EDB7211 runs an empty
21723 + * loop 256 times. At this rate, there were some spurious keys
21724 + * generated. I doubled the delay to let the column drives
21725 + * settle some.
21726 + */
21727 + for (row=0; row < 512; row++) { }
21730 + /* If we could use interrupts, we would drive all columns high so
21731 + * that interrupts will be generated on key presses. But we can't,
21732 + * so we leave all columns floating.
21733 + */
21734 + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
21735 + SYSCON1);
21737 + return key_pressed;
21740 +/*
21741 + * XXX: This is really ugly; this needs to be reworked to have less levels of
21742 + * indentation.
21743 + */
21744 +static void
21745 +edb7211_kbd_timeout(unsigned long data)
21747 + /* Schedule the next timer event. */
21748 + edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
21749 + add_timer(&edb7211_kbd_timer);
21751 + if (edb7211_kbd_scan_matrix(keys) || key_is_pressed) {
21752 + queue_task(&kbd_process_task, &tq_timer);
21753 + } else {
21754 + key_is_pressed = 0;
21759 + * Process the keys that have been pressed.
21760 + */
21761 +static void
21762 +edb7211_kbd_process(void* data)
21764 + int i;
21766 + /* First check if any keys have been released. */
21767 + if (key_is_pressed) {
21768 + for (i=0; i < 8; i++) {
21769 + if (previous_keys[i]) {
21770 + int row;
21772 + for (row=0; row < 16; row++) {
21773 + if ((previous_keys[i] & (1 << row)) &&
21774 + !(keys[i] & (1 << row))) {
21775 + /* Generate the up event. */
21776 + handle_scancode(
21777 + (row<<3)+i, 0);
21784 + key_is_pressed = 0;
21786 + /* Now scan the keys and send press events. */
21787 + for (i=0; i < 8; i++) {
21788 + if (keys[i]) {
21789 + int row;
21791 + for (row=0; row < 16; row++) {
21792 + if (keys[i] & (1 << row)) {
21793 + if (previous_keys[i] & (1 << row)) {
21794 + /* Generate the hold event. */
21795 + handle_scancode((row<<3)+i, 1);
21796 + } else {
21797 + /* Generate the down event. */
21798 + handle_scancode((row<<3)+i, 1);
21801 + key_is_pressed = 1;
21807 + /* Update the state variables. */
21808 + memcpy(previous_keys, keys, 8 * sizeof(unsigned long));
21811 +static char edb7211_unexpected_up(unsigned char scancode)
21813 + return 0200;
21816 +static void edb7211_leds(unsigned char leds)
21821 + * Initialize the keyboard hardware. Set the column drives low and
21822 + * start the timer.
21823 + */
21824 +void __init
21825 +edb7211_kbd_init_hw(void)
21827 + k_translate = edb7211_translate;
21828 + k_unexpected_up = edb7211_unexpected_up;
21829 + k_leds = edb7211_leds;
21831 + /*
21832 + * If we had the ability to use interrupts, we would want to drive all
21833 + * columns high. But we have more keys than can generate interrupts, so
21834 + * we leave them floating.
21835 + */
21836 + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
21837 + SYSCON1);
21839 + /* Initialize the matrix processing task. */
21840 + kbd_process_task.routine = edb7211_kbd_process;
21841 + kbd_process_task.data = NULL;
21843 + /* Setup the timer to poll the keyboard. */
21844 + init_timer(&edb7211_kbd_timer);
21845 + edb7211_kbd_timer.function = edb7211_kbd_timeout;
21846 + edb7211_kbd_timer.data = (unsigned long)NULL;
21847 + edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
21848 + add_timer(&edb7211_kbd_timer);
21852 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
21853 +++ linux-2.4.25/drivers/char/epxa_wdt.c 2004-03-31 17:15:09.000000000 +0200
21854 @@ -0,0 +1,178 @@
21856 + * Watchdog driver for the Altera Excalibur EPXA1DB
21858 + * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
21859 + * Based on SA11x0 Watchdog driver by Oleg Drokin <green@crimea.edu>
21861 + * This program is free software; you can redistribute it and/or
21862 + * modify it under the terms of the GNU General Public License
21863 + * as published by the Free Software Foundation; either version
21864 + * 2 of the License, or (at your option) any later version.
21866 + * This material is provided "AS-IS" and at no charge
21868 + * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
21870 + * 1/08/2003 Initial release
21871 + */
21873 +#include <linux/module.h>
21874 +#include <linux/config.h>
21875 +#include <linux/types.h>
21876 +#include <linux/kernel.h>
21877 +#include <linux/fs.h>
21878 +#include <linux/mm.h>
21879 +#include <linux/miscdevice.h>
21880 +#include <linux/watchdog.h>
21881 +#include <linux/reboot.h>
21882 +#include <linux/smp_lock.h>
21883 +#include <linux/init.h>
21884 +#include <asm/uaccess.h>
21885 +#include <asm/hardware.h>
21887 +#define WATCHDOG00_TYPE (volatile unsigned int*)
21888 +#include <asm/arch/watchdog00.h>
21889 +#include <asm/bitops.h>
21891 +#define TIMER_MARGIN 30 /* (secs) Default is 30 seconds */
21893 +static int margin = TIMER_MARGIN; /* in seconds */
21894 +static int epxa1wdt_users;
21895 +static unsigned char last_written_byte;
21897 +#ifdef CONFIG_WATCHDOG_NOWAYOUT
21898 +static int nowayout=1;
21899 +#else
21900 +static int nowayout=0;
21901 +#endif
21903 +#ifdef MODULE
21904 +MODULE_PARM(margin,"i");
21905 +MODULE_PARM(nowayout, "i");
21906 +#endif
21909 + * Allow only one person to hold it open
21910 + */
21912 +static int epxa1dog_open(struct inode *inode, struct file *file)
21914 + if(test_and_set_bit(1,&epxa1wdt_users))
21915 + return -EBUSY;
21917 + /* Reset the Watchdog, just to be sure we don't set
21918 + a value close to actual value of WDOG_COUNT register */
21919 + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
21920 + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
21922 + /* Activate EPXA1DB Watchdog timer */
21923 + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
21925 + last_written_byte = 'V'; //in case user opens it only to ioctl
21926 + return 0;
21929 +static int epxa1dog_release(struct inode *inode, struct file *file)
21931 + /*
21932 + * Shut off the timer and set lock bit when no special
21933 + * character 'V' was last written
21934 + */
21936 + if ((last_written_byte != 'V') && (nowayout)) {
21937 + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)) |= WDOG_CR_LK_MSK;
21938 + printk("No special character 'V' was written to Watchdog just before closing it\n");
21939 + printk("WATCHDOG LOCKED - Reboot expected!!!\n");
21940 + } else
21941 + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))=0;
21943 + epxa1wdt_users = 0;
21945 + return 0;
21948 +static ssize_t epxa1dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
21950 + /* Can't seek (pwrite) on this device */
21951 + if (ppos != &file->f_pos)
21952 + return -ESPIPE;
21954 + /* Reset Watchdog timer. */
21955 + if(len) {
21956 + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
21957 + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
21958 + last_written_byte = *data;
21959 + return 1;
21961 + return 0;
21964 +static int epxa1dog_ioctl(struct inode *inode, struct file *file,
21965 + unsigned int cmd, unsigned long arg)
21967 + static struct watchdog_info ident = {
21968 + identity: "EPXA Watchdog",
21969 + };
21971 + switch(cmd){
21972 + default:
21973 + return -ENOIOCTLCMD;
21974 + case WDIOC_GETSUPPORT:
21975 + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
21976 +// case WDIOC_GETSTATUS: //TODO
21977 +// return put_user(0,(int *)arg);
21978 +// case WDIOC_GETBOOTSTATUS: //TODO
21979 +// return 0;
21980 + case WDIOC_KEEPALIVE:
21981 + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
21982 + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
21983 + return 0;
21984 + case WDIOC_SETTIMEOUT:
21985 + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
21986 + return 0;
21987 + case WDIOC_GETTIMEOUT:
21988 + return put_user( ((*WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)))/EXC_INPUT_CLK_FREQUENCY), (int*)arg);
21992 +static struct file_operations epxa1dog_fops = {
21993 + .owner = THIS_MODULE,
21994 + .write = epxa1dog_write,
21995 + .ioctl = epxa1dog_ioctl,
21996 + .open = epxa1dog_open,
21997 + .release = epxa1dog_release,
22000 +static struct miscdevice epxa1dog_miscdev=
22002 + .minor = WATCHDOG_MINOR,
22003 + .name = "EPXA watchdog",
22004 + .fops = &epxa1dog_fops
22007 +static int __init epxa1dog_init(void)
22009 + int ret;
22011 + ret = misc_register(&epxa1dog_miscdev);
22013 + if (ret)
22014 + return ret;
22016 + printk("EPXA Watchdog Timer: timer margin %d sec\n", margin);
22017 + printk("EPXA Watchdog Timer: no way out is %s\n", nowayout ? "enabled" : "disabled");
22019 + return 0;
22022 +static void __exit epxa1dog_exit(void)
22024 + misc_deregister(&epxa1dog_miscdev);
22027 +module_init(epxa1dog_init);
22028 +module_exit(epxa1dog_exit);
22030 +MODULE_AUTHOR("Krzysztof Marianski <kmarian@konin.lm.pl>");
22031 +MODULE_DESCRIPTION("EPXA Watchdog Timer");
22032 +MODULE_LICENSE("GPL");
22033 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
22034 +++ linux-2.4.25/drivers/char/gc_kbmap.h 2004-03-31 17:15:09.000000000 +0200
22035 @@ -0,0 +1,162 @@
22038 +#define KK_NONE 0x7f
22039 +#define KK_ESC 0x00
22040 +#define KK_F1 0x01
22041 +#define KK_F2 0x02
22042 +#define KK_F3 0x03
22043 +#define KK_F4 0x04
22044 +#define KK_F5 0x05
22045 +#define KK_F6 0x06
22046 +#define KK_F7 0x07
22047 +#define KK_F8 0x08
22048 +#define KK_F9 0x09
22049 +#define KK_F10 0x0a
22050 +#define KK_F11 0x0b
22051 +#define KK_F12 0x0c
22052 +#define KK_PRNT 0x0d
22053 +#define KK_SCRL 0x0e
22054 +#define KK_BRK 0x0f
22055 +#define KK_AGR 0x10
22056 +#define KK_1 0x11
22057 +#define KK_2 0x12
22058 +#define KK_3 0x13
22059 +#define KK_4 0x14
22060 +#define KK_5 0x15
22061 +#define KK_6 0x16
22062 +#define KK_7 0x17
22063 +#define KK_8 0x18
22064 +#define KK_9 0x19
22065 +#define KK_0 0x1a
22066 +#define KK_MINS 0x1b
22067 +#define KK_EQLS 0x1c
22068 +#define KK_BKSP 0x1e
22069 +#define KK_INS 0x1f
22070 +#define KK_HOME 0x20
22071 +#define KK_PGUP 0x21
22072 +#define KK_NUML 0x22
22073 +#define KP_SLH 0x23
22074 +#define KP_STR 0x24
22075 +#define KP_MNS 0x3a
22076 +#define KK_TAB 0x26
22077 +#define KK_Q 0x27
22078 +#define KK_W 0x28
22079 +#define KK_E 0x29
22080 +#define KK_R 0x2a
22081 +#define KK_T 0x2b
22082 +#define KK_Y 0x2c
22083 +#define KK_U 0x2d
22084 +#define KK_I 0x2e
22085 +#define KK_O 0x2f
22086 +#define KK_P 0x30
22087 +#define KK_LSBK 0x31
22088 +#define KK_RSBK 0x32
22089 +#define KK_ENTR 0x47
22090 +#define KK_DEL 0x34
22091 +#define KK_END 0x35
22092 +#define KK_PGDN 0x36
22093 +#define KP_7 0x37
22094 +#define KP_8 0x38
22095 +#define KP_9 0x39
22096 +#define KP_PLS 0x4b
22097 +#define KK_CAPS 0x5d
22098 +#define KK_A 0x3c
22099 +#define KK_S 0x3d
22100 +#define KK_D 0x3e
22101 +#define KK_F 0x3f
22102 +#define KK_G 0x40
22103 +#define KK_H 0x41
22104 +#define KK_J 0x42
22105 +#define KK_K 0x43
22106 +#define KK_L 0x44
22107 +#define KK_SEMI 0x45
22108 +#define KK_SQOT 0x46
22109 +#define KK_HASH 0x1d
22110 +#define KP_4 0x48
22111 +#define KP_5 0x49
22112 +#define KP_6 0x4a
22113 +#define KK_LSFT 0x4c
22114 +#define KK_BSLH 0x33
22115 +#define KK_Z 0x4e
22116 +#define KK_X 0x4f
22117 +#define KK_C 0x50
22118 +#define KK_V 0x51
22119 +#define KK_B 0x52
22120 +#define KK_N 0x53
22121 +#define KK_M 0x54
22122 +#define KK_COMA 0x55
22123 +#define KK_DOT 0x56
22124 +#define KK_FSLH 0x57
22125 +#define KK_RSFT 0x58
22126 +#define KK_UP 0x59
22127 +#define KP_1 0x5a
22128 +#define KP_2 0x5b
22129 +#define KP_3 0x5c
22130 +#define KP_ENT 0x67
22131 +#define KK_LCTL 0x3b
22132 +#define KK_LALT 0x5e
22133 +#define KK_SPCE 0x5f
22134 +#define KK_RALT 0x60
22135 +#define KK_RCTL 0x61
22136 +#define KK_LEFT 0x62
22137 +#define KK_DOWN 0x63
22138 +#define KK_RGHT 0x64
22139 +#define KP_0 0x65
22140 +#define KP_DOT 0x66
22142 +static char kbmap[128] = {
22143 +KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22144 +KK_NONE, KK_AGR, KK_BSLH, KK_TAB, KK_Z, KK_A, KK_X, KK_NONE,
22145 +KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22146 +KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22147 +KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22148 +KK_NONE, KK_ESC, KK_DEL, KK_Q, KK_CAPS, KK_S, KK_C, KK_3,
22149 +KK_NONE, KK_1, KK_NONE, KK_W, KK_NONE, KK_D, KK_V, KK_4,
22150 +KK_NONE, KK_2, KK_T, KK_E, KK_NONE, KK_F, KK_B, KK_5,
22151 +KK_NONE, KK_9, KK_Y, KK_R, KK_K, KK_G, KK_N, KK_6,
22152 +KK_NONE, KK_0, KK_U, KK_O, KK_L, KK_H, KK_M, KK_7,
22153 +KK_NONE, KK_MINS, KK_I, KK_P, KK_SEMI, KK_J, KK_COMA, KK_8,
22154 +KK_NONE, KK_EQLS, KK_ENTR, KK_LSBK, KK_BSLH, KK_FSLH, KK_DOT, KK_NONE,
22155 +KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22156 +KK_NONE, KK_BKSP, KK_DOWN, KK_RSBK, KK_UP, KK_LEFT, KK_SPCE, KK_RGHT,
22157 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22158 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
22160 +static char kbmapFN[128] = {
22161 +KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22162 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22163 +KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22164 +KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22165 +KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22166 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F3,
22167 +KK_NONE, KK_F1, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F4,
22168 +KK_NONE, KK_F2, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F5,
22169 +KK_NONE, KK_F9, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F6,
22170 +KK_NONE, KK_F10, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F7,
22171 +KK_NONE, KK_NUML, KK_NONE, KK_INS, KK_PRNT, KK_NONE, KK_NONE, KK_F8,
22172 +KK_NONE, KK_BRK, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22173 +KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22174 +KK_NONE, KK_NONE, KK_PGDN, KK_SCRL, KK_PGUP, KK_HOME, KK_NONE, KK_END,
22175 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22176 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
22178 +static char kbmapNL[128] = {
22179 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22180 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22181 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22182 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22183 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22184 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22185 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22186 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22187 +KK_NONE, KP_9, KK_NONE, KK_NONE, KP_2, KK_NONE, KK_NONE, KK_NONE,
22188 +KK_NONE, KP_STR, KP_4, KP_6, KP_3, KK_NONE, KP_0, KP_7,
22189 +KK_NONE, KK_NONE, KP_5, KP_MNS, KP_PLS, KP_1, KK_NONE, KP_8,
22190 +KK_NONE, KK_NONE, KP_ENT, KK_NONE, KK_NONE, KP_SLH, KP_DOT, KK_NONE,
22191 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22192 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22193 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
22194 +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
22198 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
22199 +++ linux-2.4.25/drivers/char/gc_keyb.c 2004-03-31 17:15:09.000000000 +0200
22200 @@ -0,0 +1,1145 @@
22202 + * linux/arch/arm/drivers/char/gc_keyb.c
22204 + * Copyright 2000 Applied Data Systems
22206 + * Keyboard & Smartio driver for GraphicsClient ARM Linux.
22207 + * Graphics Client is SA1110 based single board computer by
22208 + * Applied Data Systems (http://www.applieddata.net)
22210 + * Change log:
22211 + * 7-10/6/01 Thomas Thaele <tthaele@papenmeier.de>
22212 + * - Added Keyboard Sniffer on /dev/sio12 <minor = 12>
22213 + * - First implementation of PC- compatible Scancodes (thanks to pc_keyb.c)
22214 + * 3/23/01 Woojung Huh
22215 + * Power Management added
22216 + * 12/01/00 Woojung Huh
22217 + * Bug fixed
22218 + * 11/16/00 Woojung Huh [whuh@applieddata.net]
22219 + * Added smartio device driver on it
22220 + */
22223 + * Introduced setkeycode, ketkeycode for the GC+ by Thomas Thaele
22224 + * <tthaele@papenmeier.de> GC+ now performs like a real PC on the keyboard.
22225 + * Warning: this code is still beta! PrntScrn and Pause keys are not
22226 + * completely tested and implemented!!! Keyboard driver can be confused
22227 + * by hacking like crazy on the keyboard. (hardware problem on serial line?)
22228 + */
22230 +#include <linux/sched.h>
22231 +#include <linux/interrupt.h>
22232 +#include <linux/kbd_ll.h>
22233 +#include <linux/init.h>
22234 +#include <linux/delay.h>
22235 +#include <linux/kbd_kern.h>
22237 +#include <asm/irq.h>
22238 +#include <asm/hardware.h>
22239 +#include <asm/keyboard.h>
22240 +#include <linux/tqueue.h>
22241 +#include <linux/proc_fs.h>
22242 +#include <linux/pm.h>
22244 +#define ADS_AVR_IRQ 63
22246 +#define SMARTIO_IOCTL_BASES 's'
22247 +#define SMARTIO_KPD_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 0, int)
22248 +#define SMARTIO_KPD_SETUP _IOW(SMARTIO_IOCTL_BASES, 1, short)
22249 +#define SMARTIO_BL_CONTROL _IOW(SMARTIO_IOCTL_BASES, 2, char)
22250 +#define SMARTIO_BL_CONTRAST _IOW(SMARTIO_IOCTL_BASES, 3, char)
22251 +#define SMARTIO_PORT_CONFIG _IOW(SMARTIO_IOCTL_BASES, 4, char)
22252 +#define SMARTIO_SNIFFER_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 5, long)
22255 +/* Simple translation table for the SysRq keys */
22257 +#ifdef CONFIG_MAGIC_SYSRQ
22258 +unsigned char pckbd_sysrq_xlate[128] =
22259 + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
22260 + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
22261 + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
22262 + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
22263 + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
22264 + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
22265 + "\r\000/"; /* 0x60 - 0x6f */
22266 +#endif
22269 + * Translation of escaped scancodes to keycodes.
22270 + * This is now user-settable.
22271 + * The keycodes 1-88,96-111,119 are fairly standard, and
22272 + * should probably not be changed - changing might confuse X.
22273 + * X also interprets scancode 0x5d (KEY_Begin).
22275 + * For 1-88 keycode equals scancode.
22276 + */
22278 +#define E0_KPENTER 96
22279 +#define E0_RCTRL 97
22280 +#define E0_KPSLASH 98
22281 +#define E0_PRSCR 99
22282 +#define E0_RALT 100
22283 +#define E0_BREAK 101 /* (control-pause) */
22284 +#define E0_HOME 102
22285 +#define E0_UP 103
22286 +#define E0_PGUP 104
22287 +#define E0_LEFT 105
22288 +#define E0_RIGHT 106
22289 +#define E0_END 107
22290 +#define E0_DOWN 108
22291 +#define E0_PGDN 109
22292 +#define E0_INS 110
22293 +#define E0_DEL 111
22295 +#define E1_PAUSE 119
22298 + * The keycodes below are randomly located in 89-95,112-118,120-127.
22299 + * They could be thrown away (and all occurrences below replaced by 0),
22300 + * but that would force many users to use the `setkeycodes' utility, where
22301 + * they needed not before. It does not matter that there are duplicates, as
22302 + * long as no duplication occurs for any single keyboard.
22303 + */
22304 +#define SC_LIM 89
22306 +#define FOCUS_PF1 85 /* actual code! */
22307 +#define FOCUS_PF2 89
22308 +#define FOCUS_PF3 90
22309 +#define FOCUS_PF4 91
22310 +#define FOCUS_PF5 92
22311 +#define FOCUS_PF6 93
22312 +#define FOCUS_PF7 94
22313 +#define FOCUS_PF8 95
22314 +#define FOCUS_PF9 120
22315 +#define FOCUS_PF10 121
22316 +#define FOCUS_PF11 122
22317 +#define FOCUS_PF12 123
22319 +#define JAP_86 124
22320 +/* tfj@olivia.ping.dk:
22321 + * The four keys are located over the numeric keypad, and are
22322 + * labelled A1-A4. It's an rc930 keyboard, from
22323 + * Regnecentralen/RC International, Now ICL.
22324 + * Scancodes: 59, 5a, 5b, 5c.
22325 + */
22326 +#define RGN1 124
22327 +#define RGN2 125
22328 +#define RGN3 126
22329 +#define RGN4 127
22331 +static unsigned char high_keys[128 - SC_LIM] = {
22332 + RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
22333 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
22334 + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
22335 + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
22336 + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
22337 + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
22340 +/* BTC */
22341 +#define E0_MACRO 112
22342 +/* LK450 */
22343 +#define E0_F13 113
22344 +#define E0_F14 114
22345 +#define E0_HELP 115
22346 +#define E0_DO 116
22347 +#define E0_F17 117
22348 +#define E0_KPMINPLUS 118
22350 + * My OmniKey generates e0 4c for the "OMNI" key and the
22351 + * right alt key does nada. [kkoller@nyx10.cs.du.edu]
22352 + */
22353 +#define E0_OK 124
22355 + * New microsoft keyboard is rumoured to have
22356 + * e0 5b (left window button), e0 5c (right window button),
22357 + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
22358 + * [or: Windows_L, Windows_R, TaskMan]
22359 + */
22360 +#define E0_MSLW 125
22361 +#define E0_MSRW 126
22362 +#define E0_MSTM 127
22364 +static unsigned char e0_keys[128] = {
22365 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
22366 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
22367 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
22368 + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
22369 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
22370 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
22371 + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
22372 + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
22373 + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
22374 + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
22375 + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
22376 + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
22377 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
22378 + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
22379 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
22380 + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
22383 +int gc_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
22385 + if (scancode < SC_LIM || scancode > 255 || keycode > 127)
22386 + return -EINVAL;
22387 + if (scancode < 128)
22388 + high_keys[scancode - SC_LIM] = keycode;
22389 + else
22390 + e0_keys[scancode - 128] = keycode;
22391 + return 0;
22394 +int gc_kbd_getkeycode(unsigned int scancode)
22396 + return
22397 + (scancode < SC_LIM || scancode > 255) ? -EINVAL :
22398 + (scancode < 128) ? high_keys[scancode - SC_LIM] :
22399 + e0_keys[scancode - 128];
22402 +int gc_kbd_translate(unsigned char scancode, unsigned char *keycode,
22403 + char raw_mode)
22405 + static int prev_scancode;
22407 + /* special prefix scancodes.. */
22408 + if (scancode == 0xe0 || scancode == 0xe1) {
22409 + prev_scancode = scancode;
22410 + return 0;
22413 + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
22414 + if (scancode == 0x00 || scancode == 0xff) {
22415 + prev_scancode = 0;
22416 + return 0;
22419 + scancode &= 0x7f;
22421 + if (prev_scancode) {
22422 + /*
22423 + * usually it will be 0xe0, but a Pause key generates
22424 + * e1 1d 45 e1 9d c5 when pressed, and nothing when released
22425 + */
22426 + if (prev_scancode != 0xe0) {
22427 + if (prev_scancode == 0xe1 && scancode == 0x1d) {
22428 + prev_scancode = 0x100;
22429 + return 0;
22430 + } else if (prev_scancode == 0x100 && scancode == 0x45) {
22431 + *keycode = E1_PAUSE;
22432 + prev_scancode = 0;
22433 + } else {
22434 +#ifdef KBD_REPORT_UNKN
22435 + if (!raw_mode)
22436 + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
22437 +#endif
22438 + prev_scancode = 0;
22439 + return 0;
22441 + } else {
22442 + prev_scancode = 0;
22443 + /*
22444 + * The keyboard maintains its own internal caps lock and
22445 + * num lock statuses. In caps lock mode E0 AA precedes make
22446 + * code and E0 2A follows break code. In num lock mode,
22447 + * E0 2A precedes make code and E0 AA follows break code.
22448 + * We do our own book-keeping, so we will just ignore these.
22449 + */
22450 + /*
22451 + * For my keyboard there is no caps lock mode, but there are
22452 + * both Shift-L and Shift-R modes. The former mode generates
22453 + * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
22454 + * So, we should also ignore the latter. - aeb@cwi.nl
22455 + */
22456 + if (scancode == 0x2a || scancode == 0x36)
22457 + return 0;
22459 + if (e0_keys[scancode])
22460 + *keycode = e0_keys[scancode];
22461 + else {
22462 +#ifdef KBD_REPORT_UNKN
22463 + if (!raw_mode)
22464 + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
22465 + scancode);
22466 +#endif
22467 + return 0;
22470 + } else if (scancode >= SC_LIM) {
22471 + /* This happens with the FOCUS 9000 keyboard
22472 + Its keys PF1..PF12 are reported to generate
22473 + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
22474 + Moreover, unless repeated, they do not generate
22475 + key-down events, so we have to zero up_flag below */
22476 + /* Also, Japanese 86/106 keyboards are reported to
22477 + generate 0x73 and 0x7d for \ - and \ | respectively. */
22478 + /* Also, some Brazilian keyboard is reported to produce
22479 + 0x73 and 0x7e for \ ? and KP-dot, respectively. */
22481 + *keycode = high_keys[scancode - SC_LIM];
22483 + if (!*keycode) {
22484 + if (!raw_mode) {
22485 +#ifdef KBD_REPORT_UNKN
22486 + printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
22487 + " - ignored\n", scancode);
22488 +#endif
22490 + return 0;
22492 + } else
22493 + *keycode = scancode;
22494 + return 1;
22497 +// this table converts the hardware dependent codes of a MF-2 Keyboard to
22498 +// the codes normally comming out of a i8042. This table is 128 Bytes too
22499 +// big, but for stability reasons it should be kept like it is!
22500 +// There is no range checking in the code!
22501 +static int mf_two_kbdmap[256] = {
22502 + 00, 67, 65, 63, 61, 59, 60, 88, 00, 68, 66, 64, 62, 15, 41, 00,
22503 + 00, 56, 42, 00, 29, 16, 02, 00, 00, 00, 44, 31, 30, 17, 03, 00,
22504 + 00, 46, 45, 32, 18, 05, 04, 00, 00, 57, 47, 33, 20, 19, 06, 00,
22505 + 00, 49, 48, 35, 34, 21, 7, 00, 00, 00, 50, 36, 22, 8, 9, 00,
22506 + 00, 51, 37, 23, 24, 11, 10, 00, 00, 52, 53, 38, 39, 25, 12, 00,
22507 + 00, 00, 40, 00, 26, 13, 00, 00, 58, 54, 28, 27, 00, 43, 00, 00,
22508 + 00, 86, 00, 00, 00, 00, 14, 00, 00, 79, 00, 75, 71, 00, 00, 00,
22509 + 82, 83, 80, 76, 77, 72, 01, 69, 87, 78, 81, 74, 55, 73, 70, 00,
22510 + 00, 00, 00, 65, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22511 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22512 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22513 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22514 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22515 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22516 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22517 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 };
22520 +// some texts displayed by the proc_file_system
22521 +static char *kbd_sniff[2] = { "off", "on" };
22522 +static char *kbd_sniff_mode[2] = { "passive", "active" };
22524 +#define PASSIVE 0
22525 +#define ACTIVE 1
22527 +// is the sniffer active (1) or inactive (0)
22528 +static int SNIFFER = 0;
22529 +// do we get a copy (SNIFFMODE = PASSIVE) or do we get the original data (SNIFFMODE = ACTIVE)
22530 +// and have to reinsert the data
22531 +static int SNIFFMODE = PASSIVE;
22533 +// we allow only one process to sniff
22534 +static int sniffer_in_use = 0;
22536 +// timeout for the keyboard sniffer -1 = blocking, otherwise timeout in msecs
22537 +static long sniffer_timeout = -1;
22539 +// the value we sniffed from the keyboard
22540 +static int sniffed_value;
22542 +static char *smartio_version = "1.02 MF-II compatibility patch <tthaele@papenmeier.de>";
22543 +static char *smartio_date = "Aug-27-2001";
22545 +static int sio_reset_flag;
22546 +static int kbd_press_flag;
22548 +static void send_SSP_msg(unchar *pBuf, int num)
22550 + ushort tmp;
22551 + int i;
22553 + for (i=0;i<num;i++) {
22554 + while ((Ser4SSSR & SSSR_TNF) == 0);
22555 + tmp = pBuf[i];
22556 + Ser4SSDR = (tmp << 8);
22559 + // Throw away Echo
22560 + for (i=0;i<num;i++) {
22561 + while ((Ser4SSSR & SSSR_RNE) == 0);
22562 + tmp = Ser4SSDR;
22566 +static unchar ReadSSPByte(void)
22568 + if (Ser4SSSR & SSSR_ROR) {
22569 + printk("%s() : Overrun\n", __FUNCTION__);
22570 + return 0;
22573 + Ser4SSDR = 0x00;
22575 + while ((Ser4SSSR & SSSR_RNE) == 0);
22577 + return ((unchar) Ser4SSDR);
22580 +static ulong read_SSP_response(int num)
22582 + int i;
22583 + ulong ret;
22585 + // discard leading 0x00 and command echo 0 (command group value)
22586 + while (ReadSSPByte() == 0);
22587 + // discard command echo 1 (command code value)
22588 + ReadSSPByte();
22590 + // data from SMARTIO
22591 + // It assumes LSB first.
22592 + // NOTE:Some command uses MSB first order
22593 + ret = 0;
22594 + for (i=0;i<num;i++) {
22595 + ret |= ReadSSPByte() << (8*i);
22598 + return ret;
22601 +typedef struct t_SMARTIO_CMD {
22602 + unchar Group;
22603 + unchar Code;
22604 + unchar Opt[2];
22605 +} SMARTIO_CMD;
22607 +static SMARTIO_CMD RD_INT_CMD = { 0x83, 0x01, { 0x00, 0x00 } };
22608 +static SMARTIO_CMD RD_KBD_CMD = { 0x83, 0x02, { 0x00, 0x00 } };
22609 +static SMARTIO_CMD RD_ADC_CMD = { 0x83, 0x28, { 0x00, 0x00 } };
22610 +static SMARTIO_CMD RD_KPD_CMD = { 0x83, 0x04, { 0x00, 0x00 } };
22612 +static volatile ushort adc_value;
22613 +static volatile unchar kpd_value;
22614 +static unsigned int kpd_timeout = 10000; // 10000 msec
22616 +static ulong kbd_int, kpd_int, adc_int;
22618 +static void smartio_interrupt_task(void *data);
22620 +static struct tq_struct tq_smartio = {
22621 + { NULL, NULL }, // struct list_head
22622 + 0, // unsigned long sync
22623 + smartio_interrupt_task, // void (*routine)(void *)
22624 + NULL, // void *data
22627 +DECLARE_WAIT_QUEUE_HEAD(smartio_queue);
22628 +DECLARE_WAIT_QUEUE_HEAD(smartio_adc_queue);
22629 +DECLARE_WAIT_QUEUE_HEAD(smartio_kpd_queue);
22630 +DECLARE_WAIT_QUEUE_HEAD(keyboard_done_queue);
22631 +DECLARE_WAIT_QUEUE_HEAD(sniffer_queue);
22633 +static spinlock_t smartio_busy_lock = SPIN_LOCK_UNLOCKED;
22634 +static atomic_t smartio_busy = ATOMIC_INIT(0);
22636 +static int f_five_pressed = 0;
22637 +static int f_seven_pressed = 0;
22638 +//static int e_null_counter = 0;
22639 +//static int f_null_counter = 0;
22640 +//static int keydown = 0;
22641 +static unchar previous_code = 0;
22642 +//static int e0 = 0;
22644 +static void smartio_interrupt_task(void *arg)
22646 + unchar code;
22647 + unsigned long flags;
22648 + unchar dummy;
22650 + spin_lock_irqsave(&smartio_busy_lock, flags);
22651 + if (atomic_read(&smartio_busy) == 1) {
22652 + spin_unlock_irqrestore(&smartio_busy_lock, flags);
22653 + queue_task(&tq_smartio, &tq_timer);
22655 + else {
22656 + atomic_set(&smartio_busy, 1);
22657 + spin_unlock_irqrestore(&smartio_busy_lock, flags);
22660 + /* Read SMARTIO Interrupt Status to check which Interrupt is occurred
22661 + * and Clear SMARTIO Interrupt */
22662 + send_SSP_msg((unchar *) &RD_INT_CMD, 2);
22663 + code = (unchar) (read_SSP_response(1) & 0xFF);
22665 +#ifdef CONFIG_VT
22666 + if (code & 0x04) { // Keyboard Interrupt
22667 + kbd_int++;
22668 + /* Read Scan code */
22669 + send_SSP_msg((unchar *) &RD_KBD_CMD, 2);
22670 + code = (unchar) (read_SSP_response(1) & 0xFF);
22671 + dummy = code & 0x80;
22672 + if ((code == 0xE0) || (code == 0xE1) || (code == 0xF0)) { // combined code
22673 + if (code == 0xF0) {
22674 + if (!previous_code) {
22675 + code = 0xE0;
22676 + previous_code = 0xF0;
22677 + } else {
22678 + code = mf_two_kbdmap[code & 0x7F] | dummy;
22679 + previous_code = 0;
22681 + } else if (code == 0xE0) {
22682 + if (previous_code != 0) {
22683 + code = mf_two_kbdmap[code & 0x7F] | dummy;
22684 + previous_code = 0;
22685 + } else previous_code = code;
22686 + } else { // 0xE1
22687 + if (!previous_code) {
22688 + code = mf_two_kbdmap[code &0x7F] | dummy;
22689 + previous_code = 0;
22690 + } else {
22691 + previous_code = code;
22694 + } else {
22695 + if (code == 0x03) {
22696 + f_five_pressed = 1;
22697 + } else if (code == 0x83) {
22698 + if (f_five_pressed != 0) {
22699 + f_five_pressed = 0;
22700 + code = 0x03;
22701 + } else if (f_seven_pressed == 0) {
22702 + f_seven_pressed = 1;
22703 + code = 2;
22704 + dummy = 0;
22705 + } else {
22706 + f_seven_pressed = 0;
22707 + code = 2;
22710 + previous_code = 0;
22711 + code &= 0x7F;
22712 + code = mf_two_kbdmap[code] | dummy;
22714 + sniffed_value = (ushort)code;
22715 + if (SNIFFER) wake_up_interruptible(&sniffer_queue);
22716 + if (SNIFFMODE == PASSIVE) {
22717 + handle_scancode( code, (code & 0x80) ? 0 : 1 );
22718 + if (code & 0x80) {
22719 + wake_up_interruptible(&keyboard_done_queue);
22720 + mdelay(10); // this makes the whole thing a bit more stable
22721 + // keyboard handling can be corrupted when hitting
22722 + // thousands of keys like crazy. kbd_translate might catch up
22723 + // with irq routine? or there is simply a buffer overflow on
22724 + // the serial device? somehow it looses some key sequences.
22725 + // if a break code is lost or coruppted the keyboard starts
22726 + // to autorepeat like crazy and appears to hang.
22727 + // this needs further investigations! Thomas
22728 + kbd_press_flag = 0;
22730 + else
22731 + kbd_press_flag = 1;
22733 + code = 0; // prevent furthermore if ... then to react!
22735 +#endif
22736 + // ADC resolution is 10bit (0x000 ~ 0x3FF)
22737 + if (code & 0x02) { // ADC Complete Interrupt
22738 + adc_int++;
22739 + send_SSP_msg((unchar *) &RD_ADC_CMD, 2);
22740 + adc_value = (ushort) (read_SSP_response(2) & 0x3FF);
22741 + wake_up_interruptible(&smartio_adc_queue);
22744 + if (code & 0x08) { // Keypad interrupt
22745 + kpd_int++;
22746 + send_SSP_msg((unchar *) &RD_KPD_CMD, 2);
22747 + kpd_value = (unchar) (read_SSP_response(1) & 0xFF);
22748 + wake_up_interruptible(&smartio_kpd_queue);
22751 + spin_lock_irqsave(&smartio_busy_lock, flags);
22752 + atomic_set(&smartio_busy, 0);
22753 + spin_unlock_irqrestore(&smartio_busy_lock, flags);
22755 + enable_irq(ADS_AVR_IRQ);
22757 + wake_up_interruptible(&smartio_queue);
22760 +static void gc_sio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
22762 +#ifdef CONFIG_VT
22763 + kbd_pt_regs = regs;
22764 +#endif
22766 + // *NOTE*
22767 + // ADS SMARTIO interrupt is cleared after reading interrupt status
22768 + // from smartio.
22769 + // disable SMARTIO IRQ here and re-enable at samrtio_bh.
22770 + // 11/13/00 Woojung
22771 + disable_irq(ADS_AVR_IRQ);
22773 + queue_task(&tq_smartio, &tq_immediate);
22774 + mark_bh(IMMEDIATE_BH);
22777 +char gc_kbd_unexpected_up(unsigned char keycode)
22779 + return 0;
22782 +static inline void gc_sio_init(void)
22784 + GPDR |= (GPIO_GPIO10 | GPIO_GPIO12 | GPIO_GPIO13); // Output
22785 + GPDR &= ~GPIO_GPIO11;
22787 + // Alternative Function
22788 + GAFR |= (GPIO_GPIO10 | GPIO_GPIO11 | GPIO_GPIO12 | GPIO_GPIO13);
22790 + Ser4SSCR0 = 0xA707;
22791 + Ser4SSSR = SSSR_ROR;
22792 + Ser4SSCR1 = 0x0010;
22793 + Ser4SSCR0 = 0xA787;
22795 + // Reset SMARTIO
22796 + ADS_AVR_REG &= 0xFE;
22797 + mdelay(300); // 10 mSec
22798 + ADS_AVR_REG |= 0x01;
22799 + mdelay(10); // 10 mSec
22803 +void __init gc_kbd_init_hw(void)
22805 + printk (KERN_INFO "Graphics Client keyboard driver v1.0\n");
22807 + k_setkeycode = gc_kbd_setkeycode;
22808 + k_getkeycode = gc_kbd_getkeycode;
22809 + k_translate = gc_kbd_translate;
22810 + k_unexpected_up = gc_kbd_unexpected_up;
22811 +#ifdef CONFIG_MAGIC_SYSRQ
22812 + k_sysrq_key = 0x54;
22813 + /* sysrq table??? --rmk */
22814 +#endif
22816 + gc_sio_init();
22818 + if (request_irq(ADS_AVR_IRQ,gc_sio_interrupt,0,"smartio", NULL) != 0)
22819 + printk("Could not allocate SMARTIO IRQ!\n");
22821 + sio_reset_flag = 1;
22824 +/* SMARTIO ADC Interface */
22825 +#define SMARTIO_VERSION 0
22826 +#define SMARTIO_PORT_A 1
22827 +#define SMARTIO_PORT_B 2
22828 +#define SMARTIO_PORT_C 3
22829 +#define SMARTIO_PORT_D 4
22830 +#define SMARTIO_SELECT_OPTION 5
22831 +#define SMARTIO_BACKLITE 6
22832 +#define SMARTIO_KEYPAD 7
22833 +#define SMARTIO_ADC 8
22834 +#define SMARTIO_VEE_PWM 9
22835 +#define SMARTIO_SLEEP 11
22836 +#define SMARTIO_KBD_SNIFFER 12
22838 +static SMARTIO_CMD CONV_ADC_CMD = { 0x80, 0x28, { 0x00, 0x00 } };
22839 +static SMARTIO_CMD READ_PORT_CMD = { 0x82, 0x00, { 0x00, 0x00 } };
22841 +static SMARTIO_CMD READ_DEVVER_CMD = { 0x82, 0x05, { 0x00, 0x00 } };
22842 +static SMARTIO_CMD READ_DEVTYPE_CMD = { 0x82, 0x06, { 0x00, 0x00 } };
22843 +static SMARTIO_CMD READ_FWLEVEL_CMD = { 0x82, 0x07, { 0x00, 0x00 } };
22845 +static int lock_smartio(unsigned long *flags)
22847 + spin_lock_irqsave(&smartio_busy_lock, *flags);
22848 + if (atomic_read(&smartio_busy) == 1) {
22849 + spin_unlock_irqrestore(&smartio_busy_lock, *flags);
22850 + interruptible_sleep_on(&smartio_queue);
22852 + else {
22853 + atomic_set(&smartio_busy, 1);
22854 + spin_unlock_irqrestore(&smartio_busy_lock, *flags);
22857 + return 1;
22860 +static int unlock_smartio(unsigned long *flags)
22862 + spin_lock_irqsave(&smartio_busy_lock, *flags);
22863 + atomic_set(&smartio_busy, 0);
22864 + spin_unlock_irqrestore(&smartio_busy_lock, *flags);
22866 + return 1;
22869 +static ushort read_sio_adc(int channel)
22871 + unsigned long flags;
22873 + if ((channel < 0) || (channel > 7))
22874 + return 0xFFFF;
22876 + CONV_ADC_CMD.Opt[0] = (unchar) channel;
22878 + lock_smartio(&flags);
22879 + send_SSP_msg((unchar *) &CONV_ADC_CMD, 3);
22880 + unlock_smartio(&flags);
22882 + interruptible_sleep_on(&smartio_adc_queue);
22884 + return adc_value & 0x3FF;
22887 +static ushort read_sio_port(int port)
22889 + unsigned long flags;
22890 + ushort ret;
22892 + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
22893 + return 0xFFFF;
22895 + READ_PORT_CMD.Code = (unchar) port;
22897 + lock_smartio(&flags);
22898 + send_SSP_msg((unchar *) &READ_PORT_CMD, 2);
22899 + ret = read_SSP_response(1);
22900 + unlock_smartio(&flags);
22902 + return ret;
22905 +static ushort read_sio_kpd(void)
22907 + long timeout;
22909 + // kpd_timeout is mSec order
22910 + // interrupt_sleep_on_timeout is based on 10msec timer tick
22911 + if (kpd_timeout == -1) {
22912 + interruptible_sleep_on(&smartio_kpd_queue);
22914 + else {
22915 + timeout = interruptible_sleep_on_timeout(&smartio_kpd_queue,
22916 + kpd_timeout/10);
22917 + if (timeout == 0) {
22918 + // timeout without keypad input
22919 + return 0xFFFF;
22922 + return kpd_value;
22925 +static ushort read_sio_sniff(void)
22927 + long timeout;
22929 + // kpd_timeout is mSec order
22930 + // interrupt_sleep_on_timeout is based on 10msec timer tick
22931 + if (sniffer_timeout == -1) {
22932 + interruptible_sleep_on(&sniffer_queue);
22934 + else {
22935 + timeout = interruptible_sleep_on_timeout(&sniffer_queue,
22936 + sniffer_timeout/10);
22937 + if (timeout == 0) {
22938 + // timeout without keypad input
22939 + return -1;
22942 + return (ushort)sniffed_value;
22945 +static struct sio_ver {
22946 + uint DevVer;
22947 + uint DevType;
22948 + uint FwLevel;
22951 +static ushort read_sio_version(struct sio_ver *ptr)
22953 + unsigned long flags;
22954 + ushort ret;
22956 + // Read Device Version
22957 + lock_smartio(&flags);
22958 + send_SSP_msg((unchar *) &READ_DEVVER_CMD, 2);
22959 + ret = read_SSP_response(1);
22960 + unlock_smartio(&flags);
22961 + ptr->DevVer = (uint)ret;
22962 + // Read Device Type
22963 + lock_smartio(&flags);
22964 + send_SSP_msg((unchar *) &READ_DEVTYPE_CMD, 2);
22965 + ret = read_SSP_response(2);
22966 + unlock_smartio(&flags);
22967 + // swap MSB & LSB
22968 + ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
22969 + ptr->DevType = (uint)ret;
22970 + // Read Firmware Level
22971 + lock_smartio(&flags);
22972 + send_SSP_msg((unchar *) &READ_FWLEVEL_CMD, 2);
22973 + ret = read_SSP_response(2);
22974 + unlock_smartio(&flags);
22975 + // swap MSB & LSB
22976 + ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
22977 + ptr->FwLevel = (uint)ret;
22979 + return 0;
22982 +static ssize_t sio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
22984 + struct inode *inode = file->f_dentry->d_inode;
22985 + unsigned int minor = MINOR(inode->i_rdev);
22986 + ushort *ret = (ushort *)buf;
22988 + switch (minor) {
22989 + case SMARTIO_ADC:
22990 + if ((*ret = read_sio_adc(buf[0])) != 0xFFFF)
22991 + return sizeof(ushort); // 2 bytes
22992 + case SMARTIO_PORT_B:
22993 + case SMARTIO_PORT_C:
22994 + case SMARTIO_PORT_D:
22995 + if ((*ret = read_sio_port(minor)) != 0xFFFF)
22996 + return sizeof(ushort);
22997 + case SMARTIO_VERSION:
22998 + if ((read_sio_version((struct sio_ver *)buf)) != 0xFFFF)
22999 + return sizeof(struct sio_ver);
23000 + case SMARTIO_KEYPAD:
23001 + if ((*ret = read_sio_kpd()) != 0xFFFF)
23002 + return sizeof(ushort);
23003 + case SMARTIO_KBD_SNIFFER:
23004 + if ((*ret = read_sio_sniff()) != (ushort)-1)
23005 + return 1;
23006 + default :
23007 + return -ENXIO;
23011 +static SMARTIO_CMD WRITE_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
23012 +static SMARTIO_CMD SELECT_OPT_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
23013 +static SMARTIO_CMD CONTROL_BL_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
23014 +static SMARTIO_CMD CONTRAST_BL_CMD = { 0x80, 0x21, { 0x00, 0x00 } };
23015 +static SMARTIO_CMD CONTROL_KPD_CMD = { 0x80, 0x27, { 0x00, 0x00 } };
23016 +static SMARTIO_CMD CONTROL_VEE_CMD = { 0x80, 0x22, { 0x00, 0x00 } };
23018 +static ushort write_sio_port(int port, unchar value)
23020 + unsigned long flags;
23022 + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
23023 + return 0xFFFF;
23025 + WRITE_PORT_CMD.Code = (unchar) port;
23026 + WRITE_PORT_CMD.Opt[0] = (unchar) value;
23028 + lock_smartio(&flags);
23029 + send_SSP_msg((unchar *) &WRITE_PORT_CMD, 3);
23030 + unlock_smartio(&flags);
23032 + return 0;
23035 +static ushort write_sio_select(unchar select)
23037 + unsigned long flags;
23039 + if ((select < 1) || (select > 2))
23040 + return 0xFFFF;
23042 + SELECT_OPT_CMD.Code = (unchar) (select + 0x28);
23044 + lock_smartio(&flags);
23045 + send_SSP_msg((unchar *) &SELECT_OPT_CMD, 2);
23046 + unlock_smartio(&flags);
23048 + return 0;
23051 +static ushort control_sio_backlite(int cmd, int value)
23053 + unsigned long flags;
23055 + if (cmd == SMARTIO_BL_CONTRAST) {
23056 + value &= 0xFF;
23057 + CONTRAST_BL_CMD.Opt[0] = (unchar) value;
23059 + lock_smartio(&flags);
23060 + send_SSP_msg((unchar *) &CONTRAST_BL_CMD, 3);
23061 + unlock_smartio(&flags);
23063 + else if (cmd == SMARTIO_BL_CONTROL) {
23064 + if (value == 0x00) {
23065 + // Backlite OFF
23066 + CONTROL_BL_CMD.Code = 0x24;
23068 + else {
23069 + // Backlite ON
23070 + CONTROL_BL_CMD.Code = 0x23;
23072 + lock_smartio(&flags);
23073 + send_SSP_msg((unchar *) &CONTROL_BL_CMD, 2);
23074 + unlock_smartio(&flags);
23076 + else
23077 + return 0xFFFF;
23079 + return 0;
23082 +static ushort control_sio_keypad(int x, int y)
23084 + unsigned long flags;
23086 + if ( (x<1) || (x>8) || (y<1) || (y>8)) {
23087 + return 0xFFFF;
23090 + CONTROL_KPD_CMD.Opt[0] = (unchar) x;
23091 + CONTROL_KPD_CMD.Opt[1] = (unchar) y;
23093 + lock_smartio(&flags);
23094 + send_SSP_msg((unchar *) &CONTROL_KPD_CMD, 4);
23095 + unlock_smartio(&flags);
23097 + return 0;
23100 +static ushort control_sio_vee(int value)
23102 + unsigned long flags;
23104 + value &= 0xFF;
23105 + CONTROL_VEE_CMD.Opt[0] = (unchar) value;
23107 + lock_smartio(&flags);
23108 + send_SSP_msg((unchar *) &CONTROL_VEE_CMD, 3);
23109 + unlock_smartio(&flags);
23111 + return 0;
23114 +static ssize_t sio_write(struct file *file, const char *buf, size_t cont, loff_t *ppos)
23116 + struct inode *inode = file->f_dentry->d_inode;
23117 + unsigned int minor = MINOR(inode->i_rdev);
23119 + switch (minor) {
23120 + case SMARTIO_PORT_B:
23121 + case SMARTIO_PORT_C:
23122 + case SMARTIO_PORT_D:
23123 + if (write_sio_port(minor, buf[0]) != 0xFFFF)
23124 + return 1;
23125 + case SMARTIO_SELECT_OPTION:
23126 + if (write_sio_select(buf[0]) != 0xFFFF)
23127 + return 1;
23128 + case SMARTIO_BACKLITE:
23129 + if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF)
23130 + return 1;
23131 + case SMARTIO_KEYPAD:
23132 + if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF)
23133 + return 2;
23134 + case SMARTIO_VEE_PWM:
23135 + if (control_sio_vee(buf[0]) != 0xFFFF)
23136 + return 1;
23137 + case SMARTIO_KBD_SNIFFER:
23138 + // here are the scancodes injected
23139 + handle_scancode((unchar)buf[0], (buf[0] & 0x80) ? 0 : 1);
23140 + wake_up_interruptible(&keyboard_done_queue);
23141 + // give some time to process! File IO is a bit faster than manual typing ;-)
23142 + udelay(10000);
23143 + return 1;
23144 + default:
23145 + return -ENXIO;
23149 +static unsigned int sio_poll(struct file *file, struct poll_table_struct *wait)
23151 + return 0;
23154 +static SMARTIO_CMD IOCTL_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
23156 +static ushort ioctl_sio_port(int port, unchar value)
23158 + unsigned long flags;
23160 + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
23161 + return 0xFFFF;
23163 + IOCTL_PORT_CMD.Code = (unchar) port + 0x04; // 0x05 ~ 0x08
23164 + if (port == SMARTIO_PORT_B) {
23165 + // Port B has 4 bits only
23166 + IOCTL_PORT_CMD.Opt[0] = (unchar) value & 0x0F;
23168 + else
23169 + IOCTL_PORT_CMD.Opt[0] = (unchar) value;
23171 + lock_smartio(&flags);
23172 + send_SSP_msg((unchar *) &IOCTL_PORT_CMD, 3);
23173 + unlock_smartio(&flags);
23175 + return 0;
23178 +static int sio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
23180 + unsigned int minor = MINOR(inode->i_rdev);
23181 + unchar *buf = (unchar *)arg;
23183 + switch (minor) {
23184 + case SMARTIO_PORT_B:
23185 + case SMARTIO_PORT_C:
23186 + case SMARTIO_PORT_D:
23187 + if (cmd == SMARTIO_PORT_CONFIG) {
23188 + if (ioctl_sio_port(minor, buf[0]) != 0xFFFF)
23189 + return 0;
23191 + return -EINVAL;
23192 + case SMARTIO_SELECT_OPTION:
23193 + if (write_sio_select(buf[0]) != 0xFFFF) return 0;
23194 + return -EINVAL;
23195 + case SMARTIO_BACKLITE:
23196 + if (cmd == SMARTIO_BL_CONTROL) {
23197 + if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) return 0;
23199 + else if (cmd == SMARTIO_BL_CONTRAST) {
23200 + if (control_sio_backlite(SMARTIO_BL_CONTRAST, buf[0]) != 0xFFFF) return 0;
23202 + else return -EINVAL;
23203 + case SMARTIO_KEYPAD:
23204 + if (cmd == SMARTIO_KPD_TIMEOUT) {
23205 + kpd_timeout = *(long*)buf;
23206 + return 0;
23208 + else if (cmd == SMARTIO_KPD_SETUP) {
23209 + if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) return 0;
23211 + return -EINVAL;
23212 + case SMARTIO_VEE_PWM:
23213 + if (control_sio_vee(buf[0]) != 0xFFFF) return 0;
23214 + return -EINVAL;
23215 + case SMARTIO_KBD_SNIFFER:
23216 + if (cmd == SMARTIO_SNIFFER_TIMEOUT) {
23217 + sniffer_timeout = *(long*)buf;
23218 + if (sniffer_timeout < 0) sniffer_timeout = -1;
23219 + // the value will be devided by 10 later on
23220 + if (!sniffer_timeout) sniffer_timeout = 10;
23221 + return 0;
23223 + return -EINVAL;
23224 + default:
23225 + return -ENXIO;
23229 +static int sio_open(struct inode *inode, struct file *file)
23231 + unsigned int minor = MINOR(inode->i_rdev);
23233 + // we open all by default. we only have a special handler for the kbd sniffer
23234 + switch (minor) {
23235 + case SMARTIO_KBD_SNIFFER:
23236 + if (sniffer_in_use) return -EBUSY;
23237 + sniffer_in_use = 1;
23238 + SNIFFER = 1;
23239 + // sniff in active or passive mode
23240 + if ((file->f_flags & O_RDWR) == O_RDWR) SNIFFMODE = 1; else SNIFFMODE = 0;
23241 + // do we have a blocking or non blocking sniffer?
23242 + if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK) sniffer_timeout = 100; else sniffer_timeout = -1;
23243 + break;
23244 + default:
23245 + break;
23247 + return 0;
23250 +static int sio_close(struct inode *inode, struct file *file)
23252 + unsigned int minor = MINOR(inode->i_rdev);
23254 + switch (minor) {
23255 + case SMARTIO_KBD_SNIFFER:
23256 + SNIFFER = 0;
23257 + SNIFFMODE = 0;
23258 + sniffer_in_use = 0;
23259 + break;
23260 + default:
23261 + break;
23263 + return 0;
23266 +static struct file_operations sio_fops = {
23267 + read: sio_read,
23268 + write: sio_write,
23269 + poll: sio_poll,
23270 + ioctl: sio_ioctl,
23271 + open: sio_open,
23272 + release: sio_close,
23275 +static struct proc_dir_entry *sio_dir, *parent_dir = NULL;
23277 +#define SMARTIO_MAJOR 58
23278 +#define MAJOR_NR SMARTIO_MAJOR
23280 +#define PROC_NAME "sio"
23282 +static int sio_read_proc(char *buf, char **start, off_t pos, int count, int *eof, void *data)
23284 + char *p = buf;
23286 + p += sprintf(p, "ADS SMARTIO Status: \n");
23287 + p += sprintf(p, "\t Keyboard Interrupt : %lu\n", kbd_int);
23288 + p += sprintf(p, "\t Keypad Interrupt : %lu\n", kpd_int);
23289 + p += sprintf(p, "\t ADC Interrupt : %lu\n", adc_int);
23290 + p += sprintf(p, "\t Keyboard Sniffer : %s mode : %s\n", kbd_sniff[ SNIFFER ], kbd_sniff_mode [ SNIFFMODE ]);
23292 + return (p-buf);
23295 +#ifdef CONFIG_PM
23296 +static int pm_smartio_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
23298 + switch (rqst) {
23299 + case PM_RESUME:
23300 + gc_sio_init();
23301 + break;
23302 + case PM_SUSPEND:
23303 + // 4/5/01 Woojung
23304 + // It checks Keybard received pair of press/release code.
23305 + // System can sleep before receiving release code
23306 + if (kbd_press_flag) {
23307 + interruptible_sleep_on(&keyboard_done_queue);
23309 + break;
23312 + return 0;
23314 +#endif
23316 +void __init sio_init(void)
23318 + if (register_chrdev(MAJOR_NR, "sio", &sio_fops)) {
23319 + printk("smartio : unable to get major %d\n", MAJOR_NR);
23320 + return;
23322 + else {
23323 + printk("smartio driver initialized. version %s, date:%s\n",
23324 + smartio_version, smartio_date);
23326 + if (sio_reset_flag != 1) {
23327 + gc_sio_init();
23328 + if (request_irq(ADS_AVR_IRQ, gc_sio_interrupt,0,"sio",NULL) != 0){
23329 + printk("smartio : Could not allocate IRQ!\n");
23330 + return;
23334 + if ((sio_dir = create_proc_entry(PROC_NAME, 0, parent_dir)) == NULL) {
23335 + printk("smartio : Unable to create /proc entry\n");
23336 + return;
23338 + else {
23339 + sio_dir->read_proc = sio_read_proc;
23340 +#ifdef CONFIG_PM
23341 + pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_smartio_callback);
23342 +#endif
23346 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
23347 +++ linux-2.4.25/drivers/char/gckeymap.c 2004-03-31 17:15:09.000000000 +0200
23348 @@ -0,0 +1,262 @@
23349 +/* Do not edit this file! It was automatically generated by */
23350 +/* loadkeys --mktable defkeymap.map > defkeymap.c */
23352 +#include <linux/types.h>
23353 +#include <linux/keyboard.h>
23354 +#include <linux/kd.h>
23356 +u_short plain_map[NR_KEYS] = {
23357 + 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
23358 + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
23359 + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
23360 + 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
23361 + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
23362 + 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
23363 + 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
23364 + 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
23365 + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
23366 + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
23367 + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
23368 + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23369 + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
23370 + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
23371 + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
23372 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23375 +u_short shift_map[NR_KEYS] = {
23376 + 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
23377 + 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
23378 + 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
23379 + 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
23380 + 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
23381 + 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
23382 + 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
23383 + 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
23384 + 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
23385 + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
23386 + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
23387 + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23388 + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
23389 + 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
23390 + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
23391 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23394 +u_short altgr_map[NR_KEYS] = {
23395 + 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
23396 + 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
23397 + 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
23398 + 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
23399 + 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
23400 + 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
23401 + 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
23402 + 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
23403 + 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
23404 + 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
23405 + 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
23406 + 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23407 + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
23408 + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
23409 + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
23410 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23413 +u_short ctrl_map[NR_KEYS] = {
23414 + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
23415 + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
23416 + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
23417 + 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
23418 + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
23419 + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
23420 + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
23421 + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
23422 + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
23423 + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
23424 + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
23425 + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23426 + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
23427 + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
23428 + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
23429 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23432 +u_short shift_ctrl_map[NR_KEYS] = {
23433 + 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
23434 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
23435 + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
23436 + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
23437 + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
23438 + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
23439 + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
23440 + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23441 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
23442 + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
23443 + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
23444 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23445 + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
23446 + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
23447 + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
23448 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23451 +u_short alt_map[NR_KEYS] = {
23452 + 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
23453 + 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
23454 + 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
23455 + 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
23456 + 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
23457 + 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
23458 + 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
23459 + 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
23460 + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
23461 + 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
23462 + 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
23463 + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23464 + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
23465 + 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
23466 + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
23467 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23470 +u_short ctrl_alt_map[NR_KEYS] = {
23471 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23472 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23473 + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
23474 + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
23475 + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
23476 + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
23477 + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
23478 + 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
23479 + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
23480 + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
23481 + 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
23482 + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23483 + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
23484 + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
23485 + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
23486 + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23489 +ushort *key_maps[MAX_NR_KEYMAPS] = {
23490 + plain_map, shift_map, altgr_map, 0,
23491 + ctrl_map, shift_ctrl_map, 0, 0,
23492 + alt_map, 0, 0, 0,
23493 + ctrl_alt_map, 0
23496 +unsigned int keymap_count = 7;
23499 + * Philosophy: most people do not define more strings, but they who do
23500 + * often want quite a lot of string space. So, we statically allocate
23501 + * the default and allocate dynamically in chunks of 512 bytes.
23502 + */
23504 +char func_buf[] = {
23505 + '\033', '[', '[', 'A', 0,
23506 + '\033', '[', '[', 'B', 0,
23507 + '\033', '[', '[', 'C', 0,
23508 + '\033', '[', '[', 'D', 0,
23509 + '\033', '[', '[', 'E', 0,
23510 + '\033', '[', '1', '7', '~', 0,
23511 + '\033', '[', '1', '8', '~', 0,
23512 + '\033', '[', '1', '9', '~', 0,
23513 + '\033', '[', '2', '0', '~', 0,
23514 + '\033', '[', '2', '1', '~', 0,
23515 + '\033', '[', '2', '3', '~', 0,
23516 + '\033', '[', '2', '4', '~', 0,
23517 + '\033', '[', '2', '5', '~', 0,
23518 + '\033', '[', '2', '6', '~', 0,
23519 + '\033', '[', '2', '8', '~', 0,
23520 + '\033', '[', '2', '9', '~', 0,
23521 + '\033', '[', '3', '1', '~', 0,
23522 + '\033', '[', '3', '2', '~', 0,
23523 + '\033', '[', '3', '3', '~', 0,
23524 + '\033', '[', '3', '4', '~', 0,
23525 + '\033', '[', '1', '~', 0,
23526 + '\033', '[', '2', '~', 0,
23527 + '\033', '[', '3', '~', 0,
23528 + '\033', '[', '4', '~', 0,
23529 + '\033', '[', '5', '~', 0,
23530 + '\033', '[', '6', '~', 0,
23531 + '\033', '[', 'M', 0,
23532 + '\033', '[', 'P', 0,
23535 +char *funcbufptr = func_buf;
23536 +int funcbufsize = sizeof(func_buf);
23537 +int funcbufleft = 0; /* space left */
23539 +char *func_table[MAX_NR_FUNC] = {
23540 + func_buf + 0,
23541 + func_buf + 5,
23542 + func_buf + 10,
23543 + func_buf + 15,
23544 + func_buf + 20,
23545 + func_buf + 25,
23546 + func_buf + 31,
23547 + func_buf + 37,
23548 + func_buf + 43,
23549 + func_buf + 49,
23550 + func_buf + 55,
23551 + func_buf + 61,
23552 + func_buf + 67,
23553 + func_buf + 73,
23554 + func_buf + 79,
23555 + func_buf + 85,
23556 + func_buf + 91,
23557 + func_buf + 97,
23558 + func_buf + 103,
23559 + func_buf + 109,
23560 + func_buf + 115,
23561 + func_buf + 120,
23562 + func_buf + 125,
23563 + func_buf + 130,
23564 + func_buf + 135,
23565 + func_buf + 140,
23566 + func_buf + 145,
23567 + 0,
23568 + 0,
23569 + func_buf + 149,
23570 + 0,
23573 +struct kbdiacr accent_table[MAX_DIACR] = {
23574 + {'`', 'A', '\300'}, {'`', 'a', '\340'},
23575 + {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
23576 + {'^', 'A', '\302'}, {'^', 'a', '\342'},
23577 + {'~', 'A', '\303'}, {'~', 'a', '\343'},
23578 + {'"', 'A', '\304'}, {'"', 'a', '\344'},
23579 + {'O', 'A', '\305'}, {'o', 'a', '\345'},
23580 + {'0', 'A', '\305'}, {'0', 'a', '\345'},
23581 + {'A', 'A', '\305'}, {'a', 'a', '\345'},
23582 + {'A', 'E', '\306'}, {'a', 'e', '\346'},
23583 + {',', 'C', '\307'}, {',', 'c', '\347'},
23584 + {'`', 'E', '\310'}, {'`', 'e', '\350'},
23585 + {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
23586 + {'^', 'E', '\312'}, {'^', 'e', '\352'},
23587 + {'"', 'E', '\313'}, {'"', 'e', '\353'},
23588 + {'`', 'I', '\314'}, {'`', 'i', '\354'},
23589 + {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
23590 + {'^', 'I', '\316'}, {'^', 'i', '\356'},
23591 + {'"', 'I', '\317'}, {'"', 'i', '\357'},
23592 + {'-', 'D', '\320'}, {'-', 'd', '\360'},
23593 + {'~', 'N', '\321'}, {'~', 'n', '\361'},
23594 + {'`', 'O', '\322'}, {'`', 'o', '\362'},
23595 + {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
23596 + {'^', 'O', '\324'}, {'^', 'o', '\364'},
23597 + {'~', 'O', '\325'}, {'~', 'o', '\365'},
23598 + {'"', 'O', '\326'}, {'"', 'o', '\366'},
23599 + {'/', 'O', '\330'}, {'/', 'o', '\370'},
23600 + {'`', 'U', '\331'}, {'`', 'u', '\371'},
23601 + {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
23602 + {'^', 'U', '\333'}, {'^', 'u', '\373'},
23603 + {'"', 'U', '\334'}, {'"', 'u', '\374'},
23604 + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
23605 + {'T', 'H', '\336'}, {'t', 'h', '\376'},
23606 + {'s', 's', '\337'}, {'"', 'y', '\377'},
23607 + {'s', 'z', '\337'}, {'i', 'j', '\377'},
23610 +unsigned int accent_table_size = 68;
23611 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
23612 +++ linux-2.4.25/drivers/char/gckeymap.map 2004-03-31 17:15:09.000000000 +0200
23613 @@ -0,0 +1,357 @@
23614 +# Default kernel keymap. This uses 7 modifier combinations.
23615 +keymaps 0-2,4-5,8,12
23616 +# Change the above line into
23617 +# keymaps 0-2,4-6,8,12
23618 +# in case you want the entries
23619 +# altgr control keycode 83 = Boot
23620 +# altgr control keycode 111 = Boot
23621 +# below.
23623 +# In fact AltGr is used very little, and one more keymap can
23624 +# be saved by mapping AltGr to Alt (and adapting a few entries):
23625 +# keycode 100 = Alt
23627 +keycode 1 = Escape Escape
23628 + alt keycode 1 = Meta_Escape
23629 +keycode 2 = one exclam
23630 + alt keycode 2 = Meta_one
23631 +keycode 3 = two at at
23632 + control keycode 3 = nul
23633 + shift control keycode 3 = nul
23634 + alt keycode 3 = Meta_two
23635 +keycode 4 = three numbersign
23636 + control keycode 4 = Escape
23637 + alt keycode 4 = Meta_three
23638 +keycode 5 = four dollar dollar
23639 + control keycode 5 = Control_backslash
23640 + alt keycode 5 = Meta_four
23641 +keycode 6 = five percent
23642 + control keycode 6 = Control_bracketright
23643 + alt keycode 6 = Meta_five
23644 +keycode 7 = six asciicircum
23645 + control keycode 7 = Control_asciicircum
23646 + alt keycode 7 = Meta_six
23647 +keycode 8 = seven ampersand braceleft
23648 + control keycode 8 = Control_underscore
23649 + alt keycode 8 = Meta_seven
23650 +keycode 9 = eight asterisk bracketleft
23651 + control keycode 9 = Delete
23652 + alt keycode 9 = Meta_eight
23653 +keycode 10 = nine parenleft bracketright
23654 + alt keycode 10 = Meta_nine
23655 +keycode 11 = zero parenright braceright
23656 + alt keycode 11 = Meta_zero
23657 +keycode 12 = minus underscore backslash
23658 + control keycode 12 = Control_underscore
23659 + shift control keycode 12 = Control_underscore
23660 + alt keycode 12 = Meta_minus
23661 +keycode 13 = equal plus
23662 + alt keycode 13 = Meta_equal
23663 +keycode 14 = Delete Delete
23664 + control keycode 14 = BackSpace
23665 + alt keycode 14 = Meta_Delete
23666 +keycode 15 = Tab Tab
23667 + alt keycode 15 = Meta_Tab
23668 +keycode 16 = q
23669 +keycode 17 = w
23670 +keycode 18 = e
23671 + altgr keycode 18 = Hex_E
23672 +keycode 19 = r
23673 +keycode 20 = t
23674 +keycode 21 = y
23675 +keycode 22 = u
23676 +keycode 23 = i
23677 +keycode 24 = o
23678 +keycode 25 = p
23679 +keycode 26 = bracketleft braceleft
23680 + control keycode 26 = Escape
23681 + alt keycode 26 = Meta_bracketleft
23682 +keycode 27 = bracketright braceright asciitilde
23683 + control keycode 27 = Control_bracketright
23684 + alt keycode 27 = Meta_bracketright
23685 +keycode 28 = Return
23686 + alt keycode 28 = Meta_Control_m
23687 +keycode 29 = Control
23688 +keycode 30 = a
23689 + altgr keycode 30 = Hex_A
23690 +keycode 31 = s
23691 +keycode 32 = d
23692 + altgr keycode 32 = Hex_D
23693 +keycode 33 = f
23694 + altgr keycode 33 = Hex_F
23695 +keycode 34 = g
23696 +keycode 35 = h
23697 +keycode 36 = j
23698 +keycode 37 = k
23699 +keycode 38 = l
23700 +keycode 39 = semicolon colon
23701 + alt keycode 39 = Meta_semicolon
23702 +keycode 40 = apostrophe quotedbl
23703 + control keycode 40 = Control_g
23704 + alt keycode 40 = Meta_apostrophe
23705 +keycode 41 = grave asciitilde
23706 + control keycode 41 = nul
23707 + alt keycode 41 = Meta_grave
23708 +keycode 42 = Shift
23709 +keycode 43 = backslash bar
23710 + control keycode 43 = Control_backslash
23711 + alt keycode 43 = Meta_backslash
23712 +keycode 44 = z
23713 +keycode 45 = x
23714 +keycode 46 = c
23715 + altgr keycode 46 = Hex_C
23716 +keycode 47 = v
23717 +keycode 48 = b
23718 + altgr keycode 48 = Hex_B
23719 +keycode 49 = n
23720 +keycode 50 = m
23721 +keycode 51 = comma less
23722 + alt keycode 51 = Meta_comma
23723 +keycode 52 = period greater
23724 + control keycode 52 = Compose
23725 + alt keycode 52 = Meta_period
23726 +keycode 53 = slash question
23727 + control keycode 53 = Delete
23728 + alt keycode 53 = Meta_slash
23729 +keycode 54 = Shift
23730 +keycode 55 = KP_Multiply
23731 +keycode 56 = Alt
23732 +keycode 57 = space space
23733 + control keycode 57 = nul
23734 + alt keycode 57 = Meta_space
23735 +keycode 58 = Caps_Lock
23736 +keycode 59 = F1 F11 Console_13
23737 + control keycode 59 = F1
23738 + alt keycode 59 = Console_1
23739 + control alt keycode 59 = Console_1
23740 +keycode 60 = F2 F12 Console_14
23741 + control keycode 60 = F2
23742 + alt keycode 60 = Console_2
23743 + control alt keycode 60 = Console_2
23744 +keycode 61 = F3 F13 Console_15
23745 + control keycode 61 = F3
23746 + alt keycode 61 = Console_3
23747 + control alt keycode 61 = Console_3
23748 +keycode 62 = F4 F14 Console_16
23749 + control keycode 62 = F4
23750 + alt keycode 62 = Console_4
23751 + control alt keycode 62 = Console_4
23752 +keycode 63 = F5 F15 Console_17
23753 + control keycode 63 = F5
23754 + alt keycode 63 = Console_5
23755 + control alt keycode 63 = Console_5
23756 +keycode 64 = F6 F16 Console_18
23757 + control keycode 64 = F6
23758 + alt keycode 64 = Console_6
23759 + control alt keycode 64 = Console_6
23760 +keycode 65 = F7 F17 Console_19
23761 + control keycode 65 = F7
23762 + alt keycode 65 = Console_7
23763 + control alt keycode 65 = Console_7
23764 +keycode 66 = F8 F18 Console_20
23765 + control keycode 66 = F8
23766 + alt keycode 66 = Console_8
23767 + control alt keycode 66 = Console_8
23768 +keycode 67 = F9 F19 Console_21
23769 + control keycode 67 = F9
23770 + alt keycode 67 = Console_9
23771 + control alt keycode 67 = Console_9
23772 +keycode 68 = F10 F20 Console_22
23773 + control keycode 68 = F10
23774 + alt keycode 68 = Console_10
23775 + control alt keycode 68 = Console_10
23776 +keycode 69 = Num_Lock
23777 + shift keycode 69 = Bare_Num_Lock
23778 +keycode 70 = Scroll_Lock Show_Memory Show_Registers
23779 + control keycode 70 = Show_State
23780 + alt keycode 70 = Scroll_Lock
23781 +keycode 71 = KP_7
23782 + alt keycode 71 = Ascii_7
23783 + altgr keycode 71 = Hex_7
23784 +keycode 72 = KP_8
23785 + alt keycode 72 = Ascii_8
23786 + altgr keycode 72 = Hex_8
23787 +keycode 73 = KP_9
23788 + alt keycode 73 = Ascii_9
23789 + altgr keycode 73 = Hex_9
23790 +keycode 74 = KP_Subtract
23791 +keycode 75 = KP_4
23792 + alt keycode 75 = Ascii_4
23793 + altgr keycode 75 = Hex_4
23794 +keycode 76 = KP_5
23795 + alt keycode 76 = Ascii_5
23796 + altgr keycode 76 = Hex_5
23797 +keycode 77 = KP_6
23798 + alt keycode 77 = Ascii_6
23799 + altgr keycode 77 = Hex_6
23800 +keycode 78 = KP_Add
23801 +keycode 79 = KP_1
23802 + alt keycode 79 = Ascii_1
23803 + altgr keycode 79 = Hex_1
23804 +keycode 80 = KP_2
23805 + alt keycode 80 = Ascii_2
23806 + altgr keycode 80 = Hex_2
23807 +keycode 81 = KP_3
23808 + alt keycode 81 = Ascii_3
23809 + altgr keycode 81 = Hex_3
23810 +keycode 82 = KP_0
23811 + alt keycode 82 = Ascii_0
23812 + altgr keycode 82 = Hex_0
23813 +keycode 83 = KP_Period
23814 +# altgr control keycode 83 = Boot
23815 + control alt keycode 83 = Boot
23816 +keycode 84 = Last_Console
23817 +keycode 85 =
23818 +keycode 86 = less greater bar
23819 + alt keycode 86 = Meta_less
23820 +keycode 87 = F11 F11 Console_23
23821 + control keycode 87 = F11
23822 + alt keycode 87 = Console_11
23823 + control alt keycode 87 = Console_11
23824 +keycode 88 = F12 F12 Console_24
23825 + control keycode 88 = F12
23826 + alt keycode 88 = Console_12
23827 + control alt keycode 88 = Console_12
23828 +keycode 89 =
23829 +keycode 90 =
23830 +keycode 91 =
23831 +keycode 92 =
23832 +keycode 93 =
23833 +keycode 94 =
23834 +keycode 95 =
23835 +keycode 96 = KP_Enter
23836 +keycode 97 = Control
23837 +keycode 98 = KP_Divide
23838 +keycode 99 = Control_backslash
23839 + control keycode 99 = Control_backslash
23840 + alt keycode 99 = Control_backslash
23841 +keycode 100 = AltGr
23842 +keycode 101 = Break
23843 +keycode 102 = Find
23844 +keycode 103 = Up
23845 +keycode 104 = Prior
23846 + shift keycode 104 = Scroll_Backward
23847 +keycode 105 = Left
23848 + alt keycode 105 = Decr_Console
23849 +keycode 106 = Right
23850 + alt keycode 106 = Incr_Console
23851 +keycode 107 = Select
23852 +keycode 108 = Down
23853 +keycode 109 = Next
23854 + shift keycode 109 = Scroll_Forward
23855 +keycode 110 = Insert
23856 +keycode 111 = Remove
23857 +# altgr control keycode 111 = Boot
23858 + control alt keycode 111 = Boot
23859 +keycode 112 = Macro
23860 +keycode 113 = F13
23861 +keycode 114 = F14
23862 +keycode 115 = Help
23863 +keycode 116 = Do
23864 +keycode 117 = F17
23865 +keycode 118 = KP_MinPlus
23866 +keycode 119 = Pause
23867 +keycode 120 =
23868 +keycode 121 =
23869 +keycode 122 =
23870 +keycode 123 =
23871 +keycode 124 =
23872 +keycode 125 =
23873 +keycode 126 =
23874 +keycode 127 =
23875 +string F1 = "\033[[A"
23876 +string F2 = "\033[[B"
23877 +string F3 = "\033[[C"
23878 +string F4 = "\033[[D"
23879 +string F5 = "\033[[E"
23880 +string F6 = "\033[17~"
23881 +string F7 = "\033[18~"
23882 +string F8 = "\033[19~"
23883 +string F9 = "\033[20~"
23884 +string F10 = "\033[21~"
23885 +string F11 = "\033[23~"
23886 +string F12 = "\033[24~"
23887 +string F13 = "\033[25~"
23888 +string F14 = "\033[26~"
23889 +string F15 = "\033[28~"
23890 +string F16 = "\033[29~"
23891 +string F17 = "\033[31~"
23892 +string F18 = "\033[32~"
23893 +string F19 = "\033[33~"
23894 +string F20 = "\033[34~"
23895 +string Find = "\033[1~"
23896 +string Insert = "\033[2~"
23897 +string Remove = "\033[3~"
23898 +string Select = "\033[4~"
23899 +string Prior = "\033[5~"
23900 +string Next = "\033[6~"
23901 +string Macro = "\033[M"
23902 +string Pause = "\033[P"
23903 +compose '`' 'A' to 'ƀ'
23904 +compose '`' 'a' to 'Ć '
23905 +compose '\'' 'A' to 'Ɓ'
23906 +compose '\'' 'a' to 'Ć”'
23907 +compose '^' 'A' to 'Ƃ'
23908 +compose '^' 'a' to 'Ć¢'
23909 +compose '~' 'A' to 'ƃ'
23910 +compose '~' 'a' to 'Ć£'
23911 +compose '"' 'A' to 'Ƅ'
23912 +compose '"' 'a' to 'Ƥ'
23913 +compose 'O' 'A' to 'ƅ'
23914 +compose 'o' 'a' to 'Ć„'
23915 +compose '0' 'A' to 'ƅ'
23916 +compose '0' 'a' to 'Ć„'
23917 +compose 'A' 'A' to 'ƅ'
23918 +compose 'a' 'a' to 'Ć„'
23919 +compose 'A' 'E' to 'Ɔ'
23920 +compose 'a' 'e' to 'Ʀ'
23921 +compose ',' 'C' to 'Ƈ'
23922 +compose ',' 'c' to 'Ƨ'
23923 +compose '`' 'E' to 'ƈ'
23924 +compose '`' 'e' to 'ĆØ'
23925 +compose '\'' 'E' to 'Ɖ'
23926 +compose '\'' 'e' to 'Ć©'
23927 +compose '^' 'E' to 'Ɗ'
23928 +compose '^' 'e' to 'ĆŖ'
23929 +compose '"' 'E' to 'Ƌ'
23930 +compose '"' 'e' to 'Ć«'
23931 +compose '`' 'I' to 'ƌ'
23932 +compose '`' 'i' to 'Ƭ'
23933 +compose '\'' 'I' to 'ƍ'
23934 +compose '\'' 'i' to 'Ć­'
23935 +compose '^' 'I' to 'Ǝ'
23936 +compose '^' 'i' to 'Ć®'
23937 +compose '"' 'I' to 'Ə'
23938 +compose '"' 'i' to 'ĆÆ'
23939 +compose '-' 'D' to 'Ɛ'
23940 +compose '-' 'd' to 'Ć°'
23941 +compose '~' 'N' to 'Ƒ'
23942 +compose '~' 'n' to 'Ʊ'
23943 +compose '`' 'O' to 'ƒ'
23944 +compose '`' 'o' to 'Ć²'
23945 +compose '\'' 'O' to 'Ɠ'
23946 +compose '\'' 'o' to 'Ć³'
23947 +compose '^' 'O' to 'Ɣ'
23948 +compose '^' 'o' to 'Ć“'
23949 +compose '~' 'O' to 'ƕ'
23950 +compose '~' 'o' to 'Ƶ'
23951 +compose '"' 'O' to 'Ɩ'
23952 +compose '"' 'o' to 'ƶ'
23953 +compose '/' 'O' to 'Ƙ'
23954 +compose '/' 'o' to 'Ćø'
23955 +compose '`' 'U' to 'ƙ'
23956 +compose '`' 'u' to 'Ć¹'
23957 +compose '\'' 'U' to 'ƚ'
23958 +compose '\'' 'u' to 'Ćŗ'
23959 +compose '^' 'U' to 'ƛ'
23960 +compose '^' 'u' to 'Ć»'
23961 +compose '"' 'U' to 'Ɯ'
23962 +compose '"' 'u' to 'Ć¼'
23963 +compose '\'' 'Y' to 'Ɲ'
23964 +compose '\'' 'y' to 'Ć½'
23965 +compose 'T' 'H' to 'ƞ'
23966 +compose 't' 'h' to 'Ć¾'
23967 +compose 's' 's' to 'Ɵ'
23968 +compose '"' 'y' to 'Ćæ'
23969 +compose 's' 'z' to 'Ɵ'
23970 +compose 'i' 'j' to 'Ćæ'
23971 --- linux-2.4.25/drivers/char/generic_serial.c~2.4.25-vrs2.patch 2002-11-29 00:53:12.000000000 +0100
23972 +++ linux-2.4.25/drivers/char/generic_serial.c 2004-03-31 17:15:09.000000000 +0200
23973 @@ -883,6 +883,9 @@
23974 if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
23977 + /*
23978 + * should be using tty_get_baud_rate() here -- rmk
23979 + */
23980 baudrate = tiosp->c_cflag & CBAUD;
23981 if (baudrate & CBAUDEX) {
23982 baudrate &= ~CBAUDEX;
23983 @@ -957,6 +960,11 @@
23984 unsigned long flags;
23985 unsigned long page;
23987 + /*
23988 + * Do we expect to allocate tmp_buf from an interrupt routine?
23989 + * If not, then save_flags() cli() and restore_flags() are
23990 + * redundant here and should be replaced by a semaphore. -- rmk
23991 + */
23992 save_flags (flags);
23993 if (!tmp_buf) {
23994 page = get_free_page(GFP_KERNEL);
23995 @@ -976,6 +984,11 @@
23996 if (port->flags & ASYNC_INITIALIZED)
23997 return 0;
23999 + /*
24000 + * Do we expect to allocate xmit_buf from an interrupt routine?
24001 + * If not, then save_flags() cli() and restore_flags() are
24002 + * redundant here and should be replaced by a semaphore. -- rmk
24003 + */
24004 if (!port->xmit_buf) {
24005 /* We may sleep in get_free_page() */
24006 unsigned long tmp;
24007 @@ -1016,7 +1029,7 @@
24008 struct serial_struct sio;
24010 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
24011 - return(-EFAULT);
24012 + return -EFAULT;
24014 if (!capable(CAP_SYS_ADMIN)) {
24015 if ((sio.baud_base != port->baud_base) ||
24016 --- linux-2.4.25/drivers/char/keyboard.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
24017 +++ linux-2.4.25/drivers/char/keyboard.c 2004-03-31 17:15:09.000000000 +0200
24018 @@ -14,13 +14,17 @@
24019 * `Sticky' modifier keys, 951006.
24021 * 11-11-96: SAK should now work in the raw mode (Martin Mares)
24022 - *
24024 * Modified to provide 'generic' keyboard support by Hamish Macdonald
24025 * Merge with the m68k keyboard driver and split-off of the PC low-level
24026 * parts by Geert Uytterhoeven, May 1997
24028 * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
24029 * 30-07-98: Dead keys redone, aeb@cwi.nl.
24031 + * 04-04-1998: Added keyboard autorepeat support (some keyboards don't
24032 + * autorepeat, and some keyboard changers interfere with keyboard
24033 + * autorepeat settings). - Russell King (rmk@arm.linux.org.uk)
24036 #include <linux/config.h>
24037 @@ -30,6 +34,7 @@
24038 #include <linux/tty_flip.h>
24039 #include <linux/mm.h>
24040 #include <linux/string.h>
24041 +#include <linux/timer.h>
24042 #include <linux/random.h>
24043 #include <linux/init.h>
24045 @@ -61,6 +66,14 @@
24046 #define KBD_DEFLOCK 0
24047 #endif
24050 + * Default autorepeat settings.
24051 + * DEFAULT_REPEAT_TIMEOUT is the timeout from the keypress to the first repeat
24052 + * DEFAULT_REPEAT_INTERVAL is the timeout between successive repeats
24053 + */
24054 +#define DEFAULT_REPEAT_TIMEOUT HZ*300/1000
24055 +#define DEFAULT_REPEAT_INTERVAL HZ*30/1000
24057 void (*kbd_ledfunc)(unsigned int led);
24058 EXPORT_SYMBOL(handle_scancode);
24059 EXPORT_SYMBOL(kbd_ledfunc);
24060 @@ -82,21 +95,25 @@
24061 static unsigned long key_down[256/BITS_PER_LONG];
24063 static int dead_key_next;
24064 -/*
24066 * In order to retrieve the shift_state (for the mouse server), either
24067 - * the variable must be global, or a new procedure must be created to
24068 + * the variable must be global, or a new procedure must be created to
24069 * return the value. I chose the former way.
24071 int shift_state;
24072 static int npadch = -1; /* -1 or number assembled on pad */
24073 static unsigned char diacr;
24074 static char rep; /* flag telling character repeat */
24075 +static int kbd_repeatkeycode= -1;
24076 +static int kbd_repeattimeout = DEFAULT_REPEAT_TIMEOUT;
24077 +static int kbd_repeatinterval= DEFAULT_REPEAT_INTERVAL;
24078 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
24079 static struct tty_struct **ttytab;
24080 static struct kbd_struct * kbd = kbd_table;
24081 static struct tty_struct * tty;
24082 static unsigned char prev_scancode;
24084 +static void kbd_processkeycode(unsigned char scancode, char up_flag, int autorepeat);
24085 void compute_shiftstate(void);
24087 typedef void (*k_hand)(unsigned char value, char up_flag);
24088 @@ -163,7 +180,8 @@
24089 * string, and in both cases we might assume that it is
24090 * in utf-8 already.
24092 -void to_utf8(ushort c) {
24093 +void to_utf8(ushort c)
24095 if (c < 0x80)
24096 put_queue(c); /* 0******* */
24097 else if (c < 0x800) {
24098 @@ -182,17 +200,23 @@
24099 * Translation of escaped scancodes to keycodes.
24100 * This is now user-settable (for machines were it makes sense).
24103 int setkeycode(unsigned int scancode, unsigned int keycode)
24105 - return kbd_setkeycode(scancode, keycode);
24106 + return kbd_setkeycode(scancode, keycode);
24109 int getkeycode(unsigned int scancode)
24111 - return kbd_getkeycode(scancode);
24112 + return kbd_getkeycode(scancode);
24115 +static void key_callback(unsigned long nr);
24117 +static struct timer_list key_autorepeat_timer =
24119 + function: key_callback
24122 void handle_scancode(unsigned char scancode, int down)
24124 unsigned char keycode;
24125 @@ -201,6 +225,7 @@
24126 char have_keycode;
24128 pm_access(pm_kbd);
24130 add_keyboard_randomness(scancode | up_flag);
24132 tty = ttytab? ttytab[fg_console]: NULL;
24133 @@ -223,15 +248,15 @@
24134 if (raw_mode) {
24136 * The following is a workaround for hardware
24137 - * which sometimes send the key release event twice
24138 + * which sometimes send the key release event twice
24140 unsigned char next_scancode = scancode|up_flag;
24141 if (have_keycode && up_flag && next_scancode==prev_scancode) {
24142 /* unexpected 2nd release event */
24143 } else {
24144 - /*
24145 + /*
24146 * Only save previous scancode if it was a key-up
24147 - * and had a single-byte scancode.
24148 + * and had a single-byte scancode.
24150 if (!have_keycode)
24151 prev_scancode = 1;
24152 @@ -256,12 +281,35 @@
24153 * return the keycode if in MEDIUMRAW mode.
24156 + kbd_processkeycode(keycode, up_flag, 0);
24158 +out:
24159 + do_poke_blanked_console = 1;
24160 + schedule_console_callback();
24163 +static void
24164 +kbd_processkeycode(unsigned char keycode, char up_flag, int autorepeat)
24166 + char raw_mode = (kbd->kbdmode == VC_RAW);
24168 if (up_flag) {
24169 rep = 0;
24170 if(!test_and_clear_bit(keycode, key_down))
24171 up_flag = kbd_unexpected_up(keycode);
24172 - } else
24173 + } else {
24174 rep = test_and_set_bit(keycode, key_down);
24175 + /* If the keyboard autorepeated for us, ignore it.
24176 + * We do our own autorepeat processing.
24177 + */
24178 + if (rep && !autorepeat)
24179 + return;
24182 + if (kbd_repeatkeycode == keycode || !up_flag || raw_mode) {
24183 + kbd_repeatkeycode = -1;
24184 + del_timer(&key_autorepeat_timer);
24187 #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
24188 if (keycode == SYSRQ_KEY) {
24189 @@ -275,6 +323,23 @@
24191 #endif
24193 + /*
24194 + * Calculate the next time when we have to do some autorepeat
24195 + * processing. Note that we do not do autorepeat processing
24196 + * while in raw mode but we do do autorepeat processing in
24197 + * medium raw mode.
24198 + */
24199 + if (!up_flag && !raw_mode) {
24200 + kbd_repeatkeycode = keycode;
24201 + if (vc_kbd_mode(kbd, VC_REPEAT)) {
24202 + if (rep)
24203 + key_autorepeat_timer.expires = jiffies + kbd_repeatinterval;
24204 + else
24205 + key_autorepeat_timer.expires = jiffies + kbd_repeattimeout;
24206 + add_timer(&key_autorepeat_timer);
24210 if (kbd->kbdmode == VC_MEDIUMRAW) {
24211 /* soon keycodes will require more than one byte */
24212 put_queue(keycode + up_flag);
24213 @@ -343,9 +408,24 @@
24214 #endif
24217 + rep = 0;
24218 out:
24219 - do_poke_blanked_console = 1;
24220 - schedule_console_callback();
24224 + * This clears the key down arrays when the keyboard is reset. On
24225 + * keyboard reset, this must be called before any keycodes are
24226 + * received.
24227 + */
24228 +void kbd_reset_kdown(void)
24230 + int i;
24232 + for (i = 0; i < NR_SHIFT; i++)
24233 + k_down[i] = 0;
24234 + for (i = 0; i < SIZE(key_down); i++)
24235 + key_down[i] = 0;
24236 + shift_state = 0;
24239 void put_queue(int ch)
24240 @@ -453,7 +533,7 @@
24241 static void decr_console(void)
24243 int i;
24246 for (i = fg_console-1; i != fg_console; i--) {
24247 if (i == -1)
24248 i = MAX_NR_CONSOLES-1;
24249 @@ -531,7 +611,7 @@
24253 -static void do_null()
24254 +static void do_null(void)
24256 compute_shiftstate();
24258 @@ -646,8 +726,8 @@
24260 static void do_pad(unsigned char value, char up_flag)
24262 - static const char *pad_chars = "0123456789+-*/\015,.?()";
24263 - static const char *app_map = "pqrstuvwxylSRQMnnmPQ";
24264 + static const char *pad_chars = "0123456789+-*/\015,.?()#";
24265 + static const char *app_map = "pqrstuvwxylSRQMnnmPQS";
24267 if (up_flag)
24268 return; /* no action, if this is a key release */
24269 @@ -748,9 +828,10 @@
24273 -/* called after returning from RAW mode or when changing consoles -
24274 - recompute k_down[] and shift_state from key_down[] */
24275 -/* maybe called when keymap is undefined, so that shiftkey release is seen */
24276 +/* Called after returning from RAW mode or when changing consoles -
24277 + * recompute k_down[] and shift_state from key_down[]
24278 + * Maybe called when keymap is undefined so that shift key release is seen
24279 + */
24280 void compute_shiftstate(void)
24282 int i, j, k, sym, val;
24283 @@ -829,19 +910,22 @@
24287 - * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
24288 - * or (ii) whatever pattern of lights people want to show using KDSETLED,
24289 - * or (iii) specified bits of specified words in kernel memory.
24290 + * The leds display either
24291 + * (i) the status of NumLock, CapsLock, ScrollLock, or
24292 + * (ii) whatever pattern of lights people want to show using KDSETLED, or
24293 + * (iii) specified bits of specified words in kernel memory.
24296 static unsigned char ledstate = 0xff; /* undefined */
24297 static unsigned char ledioctl;
24299 -unsigned char getledstate(void) {
24300 +unsigned char getledstate(void)
24302 return ledstate;
24305 -void setledstate(struct kbd_struct *kbd, unsigned int led) {
24306 +void setledstate(struct kbd_struct *kbd, unsigned int led)
24308 if (!(led & ~7)) {
24309 ledioctl = led;
24310 kbd->ledmode = LED_SHOW_IOCTL;
24311 @@ -857,7 +941,8 @@
24312 } ledptrs[3];
24314 void register_leds(int console, unsigned int led,
24315 - unsigned int *addr, unsigned int mask) {
24316 + unsigned int *addr, unsigned int mask)
24318 struct kbd_struct *kbd = kbd_table + console;
24319 if (led < 3) {
24320 ledptrs[led].addr = addr;
24321 @@ -868,7 +953,8 @@
24322 kbd->ledmode = LED_SHOW_FLAGS;
24325 -static inline unsigned char getleds(void){
24326 +static inline unsigned char getleds(void)
24328 struct kbd_struct *kbd = kbd_table + fg_console;
24329 unsigned char leds;
24331 @@ -915,6 +1001,19 @@
24333 unsigned char leds = getleds();
24335 + if (rep && kbd_repeatkeycode != -1) {
24336 + tty = ttytab? ttytab[fg_console]: NULL;
24337 + kbd = kbd_table + fg_console;
24339 + /* This prevents the kbd_key routine from being called
24340 + * twice, once by this BH, and once by the interrupt
24341 + * routine.
24342 + */
24343 + kbd_disable_irq();
24344 + kbd_processkeycode(kbd_repeatkeycode, 0, 1);
24345 + kbd_enable_irq();
24348 if (leds != ledstate) {
24349 ledstate = leds;
24350 kbd_leds(leds);
24351 @@ -937,6 +1036,12 @@
24352 tasklet_enable(&keyboard_tasklet);
24355 +static void key_callback(unsigned long nr)
24357 + rep = 1;
24358 + tasklet_schedule(&keyboard_tasklet);
24361 typedef void (pm_kbd_func) (void);
24363 pm_callback pm_kbd_request_override = NULL;
24364 @@ -953,7 +1058,7 @@
24365 kbd0.slockstate = 0;
24366 kbd0.modeflags = KBD_DEFMODE;
24367 kbd0.kbdmode = VC_XLATE;
24370 for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
24371 kbd_table[i] = kbd0;
24373 @@ -963,7 +1068,7 @@
24375 tasklet_enable(&keyboard_tasklet);
24376 tasklet_schedule(&keyboard_tasklet);
24379 pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override);
24381 return 0;
24382 --- linux-2.4.25/drivers/char/mem.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
24383 +++ linux-2.4.25/drivers/char/mem.c 2004-03-31 17:15:09.000000000 +0200
24384 @@ -27,9 +27,6 @@
24385 #include <asm/io.h>
24386 #include <asm/pgalloc.h>
24388 -#ifdef CONFIG_I2C
24389 -extern int i2c_init_all(void);
24390 -#endif
24391 #ifdef CONFIG_FB
24392 extern void fbmem_init(void);
24393 #endif
24394 @@ -740,9 +737,6 @@
24395 printk("unable to get major %d for memory devs\n", MEM_MAJOR);
24396 memory_devfs_register();
24397 rand_initialize();
24398 -#ifdef CONFIG_I2C
24399 - i2c_init_all();
24400 -#endif
24401 #if defined (CONFIG_FB)
24402 fbmem_init();
24403 #endif
24404 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
24405 +++ linux-2.4.25/drivers/char/omaha-rtc.c 2004-03-31 17:15:09.000000000 +0200
24406 @@ -0,0 +1,566 @@
24408 + * (C) ARM Limited 2002.
24410 + * Real Time Clock interface for Linux on Omaha
24412 + * Based on sa1100-rtc.c
24414 + * Copyright (c) 2000 Nils Faerber
24416 + * Based on rtc.c by Paul Gortmaker
24417 + * Date/time conversion routines taken from arch/arm/kernel/time.c
24418 + * by Linus Torvalds and Russell King
24419 + * and the GNU C Library
24420 + * ( ... I love the GPL ... just take what you need! ;)
24422 + * This program is free software; you can redistribute it and/or
24423 + * modify it under the terms of the GNU General Public License
24424 + * as published by the Free Software Foundation; either version
24425 + * 2 of the License, or (at your option) any later version.
24427 + * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
24428 + * - added periodic timer capability using OSMR1
24429 + * - flag compatibility with other RTC chips
24430 + * - permission checks for ioctls
24431 + * - major cleanup, partial rewrite
24433 + * 0.03 2001-03-07 CIH <cih@coventive.com>
24434 + * - Modify the bug setups RTC clock.
24436 + * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
24437 + * - removed mktime(), added alarm irq clear
24439 + * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
24440 + * - initial release
24441 + */
24443 +#include <linux/module.h>
24444 +#include <linux/fs.h>
24445 +#include <linux/miscdevice.h>
24446 +#include <linux/string.h>
24447 +#include <linux/init.h>
24448 +#include <linux/poll.h>
24449 +#include <linux/proc_fs.h>
24450 +#include <asm/bitops.h>
24451 +#include <asm/io.h>
24452 +#include <asm/hardware.h>
24453 +#include <asm/irq.h>
24454 +#include <linux/rtc.h>
24455 +#include <linux/mc146818rtc.h>
24457 +#define DRIVER_VERSION "1.00"
24459 +#define epoch 1970
24461 +#define TIMER_FREQ 3686400
24463 +#define RTC_DEF_DIVIDER 32768 - 1
24464 +#define RTC_DEF_TRIM 0
24466 +/* Those are the bits from a classic RTC we want to mimic */
24467 +#define RTC_IRQF 0x80 /* any of the following 3 is active */
24468 +#define RTC_PF 0x40
24469 +#define RTC_AF 0x20
24470 +#define RTC_UF 0x10
24472 +// bitdefs for rtc registers
24473 +#define TICNT_ENABLE 0x80 // Enable tick interrupt
24474 +#define TICNT_PERIOD 0x7F // Divisor required for 1Hz tick
24475 +#define RTC_ENABLE 0x1 // Enable bit for RTC
24477 +static unsigned long rtc_status;
24478 +static unsigned long rtc_irq_data;
24479 +static unsigned long rtc_freq = 1024;
24481 +static struct fasync_struct *rtc_async_queue;
24482 +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
24484 +extern spinlock_t rtc_lock;
24486 +static const unsigned char days_in_mo[] =
24487 + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
24489 +#define is_leap(year) \
24490 + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
24492 +// all the alarm and rtc registers
24493 +static volatile unsigned int almsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMSEC);
24494 +static volatile unsigned int almmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMIN);
24495 +static volatile unsigned int almhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMHOUR);
24496 +static volatile unsigned int almday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMDAY);
24497 +static volatile unsigned int almmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMON);
24498 +static volatile unsigned int almyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMYEAR);
24500 +static volatile unsigned int bcdsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDSEC);
24501 +static volatile unsigned int bcdmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMIN);
24502 +static volatile unsigned int bcdhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDHOUR);
24503 +static volatile unsigned int bcdday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDAY);
24504 +static volatile unsigned int bcddate = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDATE);
24505 +static volatile unsigned int bcdmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMON);
24506 +static volatile unsigned int bcdyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDYEAR);
24509 + * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
24510 + */
24512 +static void decodetime (unsigned long t, struct rtc_time *tval)
24514 + long days, month, year, rem;
24516 + days = t / 86400;
24517 + rem = t % 86400;
24518 + tval->tm_hour = rem / 3600;
24519 + rem %= 3600;
24520 + tval->tm_min = rem / 60;
24521 + tval->tm_sec = rem % 60;
24522 + tval->tm_wday = (4 + days) % 7;
24524 +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
24526 + year = epoch;
24527 + while (days >= (365 + is_leap(year))) {
24528 + unsigned long yg = year + days / 365;
24529 + days -= ((yg - year) * 365
24530 + + LEAPS_THRU_END_OF (yg - 1)
24531 + - LEAPS_THRU_END_OF (year - 1));
24532 + year = yg;
24534 + tval->tm_year = year - 1900;
24535 + tval->tm_yday = days + 1;
24537 + month = 0;
24538 + if (days >= 31) {
24539 + days -= 31;
24540 + month++;
24541 + if (days >= (28 + is_leap(year))) {
24542 + days -= (28 + is_leap(year));
24543 + month++;
24544 + while (days >= days_in_mo[month]) {
24545 + days -= days_in_mo[month];
24546 + month++;
24550 + tval->tm_mon = month;
24551 + tval->tm_mday = days + 1;
24554 +// Get alarm time in seconds
24555 +static unsigned long get_alarm_time(void)
24557 + int sec, min,hour,date,mon,year;
24559 + // Read data from h/w
24560 + year = __raw_readb(almyear);
24561 + mon = __raw_readb(almmon);
24562 + date = __raw_readb(almday);
24563 + hour = __raw_readb(almhour);
24564 + min = __raw_readb(almmin);
24565 + sec = __raw_readb(almsec);
24567 + // convert all the data into binary
24568 + year = BCD_TO_BIN(year);
24569 + mon = BCD_TO_BIN(mon);
24570 + date = BCD_TO_BIN(date);
24571 + hour = BCD_TO_BIN(hour);
24572 + min = BCD_TO_BIN(min);
24573 + sec = BCD_TO_BIN(sec);
24575 + // convert year to 19xx or 20xx as appropriate
24576 + if (year > 69)
24577 + year += 1900;
24578 + else
24579 + year += 2000;
24581 + // Now calculate number of seconds since time began...
24582 + return mktime(year,mon,date,hour,min,sec);
24585 +// Get rtc time in seconds
24586 +static unsigned long get_rtc_time(void)
24588 + int sec,min,hour,day,date,mon,year;
24590 + // Read data from h/w
24591 + year = __raw_readb(bcdyear);
24592 + mon = __raw_readb(bcdmon);
24593 + date = __raw_readb(bcdday);
24594 + day = __raw_readb(bcddate);
24595 + hour = __raw_readb(bcdhour);
24596 + min = __raw_readb(bcdmin);
24597 + sec = __raw_readb(bcdsec);
24599 + // convert all the data into binary
24600 + year = BCD_TO_BIN(year);
24601 + mon = BCD_TO_BIN(mon);
24602 + date = BCD_TO_BIN(date);
24603 + day = BCD_TO_BIN(day);
24604 + hour = BCD_TO_BIN(hour);
24605 + min = BCD_TO_BIN(min);
24606 + sec = BCD_TO_BIN(sec);
24608 + // convert year to 19xx or 20xx as appropriate
24609 + if (year > 69)
24610 + year += 1900;
24611 + else
24612 + year += 2000;
24614 + // Now calculate number of seconds since time began...
24615 + return mktime(year,mon,date,hour,min,sec);
24618 +/* Sets time of alarm */
24619 +static void set_alarm_time(struct rtc_time *tval)
24622 + int sec,min,hour,day,mon,year;
24624 + // Convert data from binary to 8-bit bcd
24625 + sec = BIN_TO_BCD(tval->tm_sec);
24626 + min = BIN_TO_BCD(tval->tm_min);
24627 + hour = BIN_TO_BCD(tval->tm_hour);
24628 + day = BIN_TO_BCD(tval->tm_mday);
24629 + mon = BIN_TO_BCD(tval->tm_mon);
24631 + // Year is special
24632 + year = tval->tm_year;
24633 + if(year > 1999)
24634 + year -=2000;
24635 + else
24636 + year -=1900;
24638 + year = BIN_TO_BCD(year);
24640 + // Write all the registers
24641 + __raw_writeb(year,almyear);
24642 + __raw_writeb(mon,almmon);
24643 + __raw_writeb(day,almday);
24644 + __raw_writeb(hour,almhour);
24645 + __raw_writeb(min,almmin);
24646 + __raw_writeb(sec,almsec);
24649 +/* Sets time of alarm */
24650 +static void set_rtc_time(struct rtc_time *tval)
24653 + int sec,min,hour,day,date,mon,year;
24655 + // Convert data from binary to 8-bit bcd
24656 + sec = BIN_TO_BCD(tval->tm_sec);
24657 + min = BIN_TO_BCD(tval->tm_min);
24658 + hour = BIN_TO_BCD(tval->tm_hour);
24659 + day = BIN_TO_BCD(tval->tm_mday);
24660 + date = BIN_TO_BCD(tval->tm_wday);
24661 + mon = BIN_TO_BCD(tval->tm_mon);
24663 + // Year is special
24664 + year = tval->tm_year;
24665 + if(year > 1999)
24666 + year -=2000;
24667 + else
24668 + year -=1900;
24670 + year = BIN_TO_BCD(year);
24672 + // Write all the registers
24673 + __raw_writeb(year,bcdyear);
24674 + __raw_writeb(mon,bcdmon);
24675 + __raw_writeb(date,bcddate);
24676 + __raw_writeb(day,bcdday);
24677 + __raw_writeb(hour,bcdhour);
24678 + __raw_writeb(min,bcdmin);
24679 + __raw_writeb(sec,bcdsec);
24682 +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
24684 + /* update irq data & counter */
24685 + rtc_irq_data += 0x100;
24687 + /* wake up waiting process */
24688 + wake_up_interruptible(&rtc_wait);
24689 + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
24692 +static int rtc_open(struct inode *inode, struct file *file)
24694 + if (test_and_set_bit (1, &rtc_status))
24695 + return -EBUSY;
24696 + MOD_INC_USE_COUNT;
24697 + rtc_irq_data = 0;
24698 + return 0;
24701 +static int rtc_release(struct inode *inode, struct file *file)
24703 + rtc_status = 0;
24704 + MOD_DEC_USE_COUNT;
24705 + return 0;
24708 +static int rtc_fasync (int fd, struct file *filp, int on)
24710 + return fasync_helper (fd, filp, on, &rtc_async_queue);
24713 +static unsigned int rtc_poll(struct file *file, poll_table *wait)
24715 + poll_wait (file, &rtc_wait, wait);
24716 + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
24719 +static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
24721 + return -ESPIPE;
24724 +ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
24726 + DECLARE_WAITQUEUE(wait, current);
24727 + unsigned long data;
24728 + ssize_t retval;
24730 + if (count < sizeof(unsigned long))
24731 + return -EINVAL;
24733 + add_wait_queue(&rtc_wait, &wait);
24734 + set_current_state(TASK_INTERRUPTIBLE);
24735 + for (;;) {
24736 + spin_lock_irq (&rtc_lock);
24737 + data = rtc_irq_data;
24738 + if (data != 0) {
24739 + rtc_irq_data = 0;
24740 + break;
24742 + spin_unlock_irq (&rtc_lock);
24744 + if (file->f_flags & O_NONBLOCK) {
24745 + retval = -EAGAIN;
24746 + goto out;
24749 + if (signal_pending(current)) {
24750 + retval = -ERESTARTSYS;
24751 + goto out;
24754 + schedule();
24757 + spin_unlock_irq (&rtc_lock);
24759 + data -= 0x100; /* the first IRQ wasn't actually missed */
24761 + retval = put_user(data, (unsigned long *)buf);
24762 + if (!retval)
24763 + retval = sizeof(unsigned long);
24765 +out:
24766 + set_current_state(TASK_RUNNING);
24767 + remove_wait_queue(&rtc_wait, &wait);
24768 + return retval;
24771 +static int rtc_ioctl(struct inode *inode, struct file *file,
24772 + unsigned int cmd, unsigned long arg)
24774 + volatile unsigned int rtcalm = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCALM);
24775 + volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
24777 + struct rtc_time tm, tm2;
24778 + switch (cmd) {
24779 + case RTC_AIE_OFF:
24780 + spin_lock_irq(&rtc_lock);
24781 + __raw_writel(0,rtcalm);
24782 + rtc_irq_data = 0;
24783 + spin_unlock_irq(&rtc_lock);
24784 + return 0;
24785 + case RTC_AIE_ON:
24786 + spin_lock_irq(&rtc_lock);
24787 + __raw_writel(0x7F,rtcalm);
24788 + rtc_irq_data = 0;
24789 + spin_unlock_irq(&rtc_lock);
24790 + return 0;
24791 + case RTC_UIE_OFF:
24792 + spin_lock_irq(&rtc_lock);
24793 + __raw_writel(~TICNT_ENABLE,ticnt);
24794 + rtc_irq_data = 0;
24795 + spin_unlock_irq(&rtc_lock);
24796 + return 0;
24797 + case RTC_UIE_ON:
24798 + spin_lock_irq(&rtc_lock);
24799 + __raw_writel(TICNT_ENABLE|TICNT_PERIOD,ticnt);
24800 + rtc_irq_data = 0;
24801 + spin_unlock_irq(&rtc_lock);
24802 + return 0;
24803 + case RTC_PIE_OFF:
24804 + spin_lock_irq(&rtc_lock);
24805 + // Periodic int not available
24806 + rtc_irq_data = 0;
24807 + spin_unlock_irq(&rtc_lock);
24808 + return 0;
24809 + case RTC_PIE_ON:
24810 + spin_lock_irq(&rtc_lock);
24811 + // Periodic int not available
24812 + rtc_irq_data = 0;
24813 + spin_unlock_irq(&rtc_lock);
24814 + return 0;
24815 + case RTC_ALM_READ:
24816 + decodetime(get_alarm_time(),&tm);
24817 + break;
24818 + case RTC_ALM_SET:
24819 + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
24820 + return -EFAULT;
24821 + decodetime(get_rtc_time(),&tm);
24822 + if ((unsigned)tm2.tm_hour < 24)
24823 + tm.tm_hour = tm2.tm_hour;
24824 + if ((unsigned)tm2.tm_min < 60)
24825 + tm.tm_min = tm2.tm_min;
24826 + if ((unsigned)tm2.tm_sec < 60)
24827 + tm.tm_sec = tm2.tm_sec;
24829 + // Munge (as per sa1100)
24830 + tm.tm_year+=1900;
24831 + tm.tm_mon+=1;
24833 + // Set the alarm
24834 + set_alarm_time(&tm);
24835 + return 0;
24836 + case RTC_RD_TIME:
24837 + decodetime (get_rtc_time(), &tm);
24838 + break;
24839 + case RTC_SET_TIME:
24840 + if (!capable(CAP_SYS_TIME))
24841 + return -EACCES;
24842 + if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
24843 + return -EFAULT;
24844 + tm.tm_year += 1900;
24845 + if (tm.tm_year < epoch || (unsigned)tm.tm_mon >= 12 ||
24846 + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
24847 + (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
24848 + (unsigned)tm.tm_hour >= 24 ||
24849 + (unsigned)tm.tm_min >= 60 ||
24850 + (unsigned)tm.tm_sec >= 60)
24851 + return -EINVAL;
24852 + tm.tm_mon +=1; // wierd: same as sa1100 though (gets month wrong otherwise!)
24853 + set_rtc_time(&tm);
24854 + return 0;
24855 + case RTC_IRQP_READ:
24856 + return put_user(rtc_freq, (unsigned long *)arg);
24857 + case RTC_IRQP_SET:
24858 + if (arg < 1 || arg > TIMER_FREQ)
24859 + return -EINVAL;
24860 + if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
24861 + return -EACCES;
24862 + rtc_freq = arg;
24863 + return 0;
24864 + case RTC_EPOCH_READ:
24865 + return put_user (epoch, (unsigned long *)arg);
24866 + default:
24867 + return -EINVAL;
24869 + return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
24872 +static struct file_operations rtc_fops = {
24873 + .owner = THIS_MODULE,
24874 + .llseek = rtc_llseek,
24875 + .read = rtc_read,
24876 + .poll = rtc_poll,
24877 + .ioctl = rtc_ioctl,
24878 + .open = rtc_open,
24879 + .release = rtc_release,
24880 + .fasync = rtc_fasync,
24883 +static struct miscdevice omahartc_miscdev = {
24884 + .minor = RTC_MINOR,
24885 + .name = "rtc",
24886 + .fops = &rtc_fops,
24889 +static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
24891 + char *p = page;
24892 + int len;
24893 + struct rtc_time tm;
24895 + decodetime (get_rtc_time(), &tm);
24896 + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
24897 + "rtc_date\t: %04d-%02d-%02d\n"
24898 + "rtc_epoch\t: %04d\n",
24899 + tm.tm_hour, tm.tm_min, tm.tm_sec,
24900 + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
24901 + decodetime (get_alarm_time(), &tm);
24902 + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
24903 + "alrm_date\t: %04d-%02d-%02d\n",
24904 + tm.tm_hour, tm.tm_min, tm.tm_sec,
24905 + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
24906 + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
24908 + len = (p - page) - off;
24909 + if (len < 0)
24910 + len = 0;
24912 + *eof = (len <= count) ? 1 : 0;
24913 + *start = page + off;
24915 + return len;
24918 +static int __init rtc_init(void)
24920 + volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
24921 + volatile unsigned int rtccon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCCON);
24922 + int ret;
24924 + misc_register (&omahartc_miscdev);
24925 + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
24927 + // Enable RTC
24928 + __raw_writel(RTC_ENABLE,rtccon);
24930 + // Acquire 1Hz timer
24931 + ret = request_irq (OMAHA_INT_TICK, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
24932 + if (ret) {
24933 + printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_TICK);
24934 + goto IRQ_TICK_failed;
24937 + // Acquire RTC (Alarm interrupt)
24938 + ret = request_irq (OMAHA_INT_RTC, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
24939 + if (ret) {
24940 + printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_RTC);
24941 + goto IRQ_RTC_failed;
24944 + printk (KERN_INFO "Omaha Real Time Clock driver v" DRIVER_VERSION "\n");
24946 + // Program tick interrupt divisor to generate real 1Hz clock and enable the interrupt
24947 + __raw_writeb(TICNT_ENABLE|TICNT_PERIOD,ticnt);
24949 + return 0;
24951 +IRQ_TICK_failed:
24952 + free_irq (OMAHA_INT_TICK, NULL);
24953 +IRQ_RTC_failed:
24954 + free_irq(OMAHA_INT_RTC, NULL);
24955 + remove_proc_entry ("driver/rtc", NULL);
24956 + misc_deregister (&omahartc_miscdev);
24957 + return ret;
24960 +static void __exit rtc_exit(void)
24962 + free_irq (OMAHA_INT_TICK, NULL);
24963 + remove_proc_entry ("driver/rtc", NULL);
24964 + misc_deregister (&omahartc_miscdev);
24967 +module_init(rtc_init);
24968 +module_exit(rtc_exit);
24970 +MODULE_AUTHOR("ARM Limited <support@arm.com>");
24971 +MODULE_DESCRIPTION("Omaha Realtime Clock Driver (RTC)");
24972 +EXPORT_NO_SYMBOLS;
24973 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
24974 +++ linux-2.4.25/drivers/char/omaha_wdt.c 2004-03-31 17:15:09.000000000 +0200
24975 @@ -0,0 +1,193 @@
24977 + * Watchdog driver for the Omaha
24978 + * (C) ARM Limited 2002.
24980 + * Based on sa1100_wdt.c
24982 + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
24983 + * Based on SoftDog driver by Alan Cox <alan@redhat.com>
24985 + * This program is free software; you can redistribute it and/or
24986 + * modify it under the terms of the GNU General Public License
24987 + * as published by the Free Software Foundation; either version
24988 + * 2 of the License, or (at your option) any later version.
24990 + * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
24991 + * warranty for any of this software. This material is provided
24992 + * "AS-IS" and at no charge.
24994 + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
24996 + * 27/11/2000 Initial release
24997 + */
24999 +#include <linux/module.h>
25000 +#include <linux/config.h>
25001 +#include <linux/types.h>
25002 +#include <linux/kernel.h>
25003 +#include <linux/fs.h>
25004 +#include <linux/mm.h>
25005 +#include <linux/miscdevice.h>
25006 +#include <linux/watchdog.h>
25007 +#include <linux/reboot.h>
25008 +#include <linux/smp_lock.h>
25009 +#include <linux/init.h>
25010 +#include <asm/uaccess.h>
25011 +#include <asm/io.h>
25012 +#include <asm/hardware.h>
25013 +#include <asm/bitops.h>
25015 +#define TIMER_MARGIN 8 /* (secs) Default is 1 minute */
25016 +#define WT_TPS 7812 /* Watchdog ticks per second. */
25017 +#define WT_ENABLE 0x21 // Enable bits for watchdog
25018 +#define WT_CLKSEL_128 0x18 // Select 1/128 divider
25020 +static int omaha_margin = TIMER_MARGIN; /* in seconds */
25021 +static int omahawdt_users;
25022 +static int pre_margin;
25023 +#ifdef MODULE
25024 +MODULE_PARM(omaha_margin,"i");
25025 +#endif
25028 + * Allow only one person to hold it open
25029 + */
25031 +static int omahadog_open(struct inode *inode, struct file *file)
25033 + volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
25034 + volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
25035 + volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
25036 + unsigned int tmp;
25038 + if(test_and_set_bit(1,&omahawdt_users))
25039 + return -EBUSY;
25040 + MOD_INC_USE_COUNT;
25041 + /* Activate omaha Watchdog timer */
25043 + /* Assume that uhal has set up pre-scaler according
25044 + * to the system clock frequency (don't change it!)
25045 + *
25046 + * Ie. all counting occurs at 1MHz / 128 = 7812.5Hz
25048 + * Since we have 16-bit counter, maximum period is
25049 + * 65536/7812.5 = 8.338608 seconds!
25050 + */
25052 + pre_margin = WT_TPS * omaha_margin;
25054 + // Set count to the maximum
25055 + __raw_writel(pre_margin,wtcnt);
25057 + // Set the clock division factor
25058 + tmp = __raw_readl(wtcon);
25059 + tmp |= WT_CLKSEL_128;
25060 + __raw_writel(tmp,wtcon);
25062 + // Program an initial count into WTDAT
25063 + __raw_writel(0x8000,wtdat);
25065 + // enable the watchdog
25066 + tmp = __raw_readl(wtcon);
25067 + tmp |= WT_ENABLE;
25069 + __raw_writel(tmp,wtcon);
25071 + return 0;
25074 +static int omahadog_release(struct inode *inode, struct file *file)
25076 + volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
25077 + unsigned int tmp;
25079 + /*
25080 + * Shut off the timer.
25081 + * Lock it in if it's a module and we defined ...NOWAYOUT
25082 + */
25083 +#ifndef CONFIG_WATCHDOG_NOWAYOUT
25084 + tmp = __raw_readl(wtcon);
25085 + tmp &= ~WT_ENABLE;
25086 + __raw_writel(tmp,wtcon);
25087 +#endif
25088 + omahawdt_users = 0;
25089 + MOD_DEC_USE_COUNT;
25090 + return 0;
25093 +static ssize_t omahadog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
25095 + volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
25097 + /* Can't seek (pwrite) on this device */
25098 + if (ppos != &file->f_pos)
25099 + return -ESPIPE;
25101 + /* Refresh timer. */
25102 + if(len) {
25103 + __raw_writel(pre_margin,wtcnt);
25104 + return 1;
25106 + return 0;
25109 +static int omahadog_ioctl(struct inode *inode, struct file *file,
25110 + unsigned int cmd, unsigned long arg)
25112 + volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
25113 + static struct watchdog_info ident = {
25114 + identity: "omaha Watchdog",
25115 + };
25117 + switch(cmd){
25118 + default:
25119 + return -ENOIOCTLCMD;
25120 + case WDIOC_GETSUPPORT:
25121 + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
25122 + case WDIOC_GETSTATUS:
25123 + return put_user(0,(int *)arg);
25124 + case WDIOC_GETBOOTSTATUS:
25125 + return 0;
25126 + case WDIOC_KEEPALIVE:
25127 + __raw_writel(pre_margin,wtdat);
25128 + return 0;
25132 +static struct file_operations omahadog_fops=
25134 + .owner = THIS_MODULE,
25135 + .write = omahadog_write,
25136 + .ioctl = omahadog_ioctl,
25137 + .open = omahadog_open,
25138 + .release = omahadog_release,
25141 +static struct miscdevice omahadog_miscdev=
25143 + .minor = WATCHDOG_MINOR,
25144 + .name = "omaha watchdog",
25145 + .fops = &omahadog_fops
25148 +static int __init omahadog_init(void)
25150 + int ret;
25152 + ret = misc_register(&omahadog_miscdev);
25154 + if (ret)
25155 + return ret;
25157 + printk("Omaha Watchdog Timer: timer margin %d sec\n", omaha_margin);
25159 + return 0;
25162 +static void __exit omahadog_exit(void)
25164 + misc_deregister(&omahadog_miscdev);
25167 +module_init(omahadog_init);
25168 +module_exit(omahadog_exit);
25169 --- linux-2.4.25/drivers/char/pcmcia/Config.in~2.4.25-vrs2.patch 2002-11-29 00:53:12.000000000 +0100
25170 +++ linux-2.4.25/drivers/char/pcmcia/Config.in 2004-03-31 17:15:09.000000000 +0200
25171 @@ -5,7 +5,13 @@
25172 mainmenu_option next_comment
25173 comment 'PCMCIA character devices'
25175 -dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_SERIAL
25176 +if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_SERIAL_8250" = "y" ]; then
25177 + dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS y
25178 +else
25179 + if [ "$CONFIG_SERIAL" = "m" -o "$CONFIG_SERIAL_8250" = "m" ]; then
25180 + dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS m
25181 + fi
25183 if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" ]; then
25184 define_bool CONFIG_PCMCIA_CHRDEV y
25186 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
25187 +++ linux-2.4.25/drivers/char/pcmcia/memory_cs.c 2004-03-31 17:15:09.000000000 +0200
25188 @@ -0,0 +1,214 @@
25189 +#include <linux/module.h>
25190 +#include <linux/kernel.h>
25191 +#include <linux/init.h>
25192 +#include <linux/mtd.h>
25194 +#include <pcmcia/version.h>
25195 +#include <pcmcia/cs_types.h>
25196 +#include <pcmcia/cs.h>
25197 +#include <pcmcia/cistpl.h>
25198 +#include <pcmcia/ciscode.h>
25199 +#include <pcmcia/ds.h>
25200 +#include <pcmcia/cisreg.h>
25202 +#include <linux/mtd/map.h>
25203 +#include <linux/mtd/mtd.h>
25205 +static dev_info_t dev_info = "memory_cs";
25206 +static dev_link_t *dev_list;
25208 +struct memcs_dev {
25209 + dev_link_t link;
25210 + struct map_info map;
25213 +static __u8 mem_cs_read8(struct map_info *map, unsigned long ofs)
25215 + return readb(map->map_priv_1 + ofs);
25218 +static __u16 mem_cs_read16(struct map_info *map, unsigned long ofs)
25220 + return readw(map->map_priv_1 + ofs);
25223 +static __u32 mem_cs_read32(struct map_info *map, unsigned long ofs)
25225 + return readl(map->map_priv_1 + ofs);
25228 +static void mem_cs_copy_from(struct map_info *map, void *to, unsigned long ofs, ssize_t size)
25230 + memcpy_fromio(to, map->map_priv_1 + ofs, size);
25233 +static void mem_cs_write8(struct map_info *map, __u8 val, unsigned long ofs)
25235 + writeb(val, map->map_priv_1 + ofs);
25238 +static void mem_cs_write16(struct map_info *map, __u16 val, unsigned long ofs)
25240 + writew(val, map->map_priv_1 + ofs);
25243 +static void mem_cs_write32(struct map_info *map, __u32 val, unsigned long ofs)
25245 + writel(val, map->map_priv_1 + ofs);
25248 +static void mem_cs_copy_to(struct map_info *map, unsigned long ofs, const void *to, ssize_t size)
25250 + memcpy_toio(map->map_priv_1 + ofs, from, size);
25253 +static void mem_cs_release(u_long arg);
25255 +static void mem_cs_detach(dev_link_t *link)
25257 + del_timer(&link->release);
25258 + if (link->state & DEV_CONFIG) {
25259 + mem_cs_release((u_long)link);
25260 + if (link->state & DEV_STALE_CONFIG) {
25261 + link->state |= DEV_STALE_LINK;
25262 + return;
25266 + if (link->handle)
25267 + CardServices(DeregisterClient, link->handle);
25269 + kfree(link);
25272 +static void mem_cs_release(u_long arg)
25274 + dev_link_t *link = (dev_link_t *)arg;
25276 + link->dev = NULL;
25277 + if (link->win) {
25278 + CardServices(ReleaseWindow, link->win);
25280 + link->state &= ~DEV_CONFIG;
25282 + if (link->state & DEV_STALE_LINK)
25283 + mem_cs_detach(link);
25286 +static void mem_cs_config(dev_link_t *link)
25288 + struct memcs_dev *dev = link->priv;
25289 + cs_status_t status;
25290 + win_req_t req;
25292 + link->state |= DEV_CONFIG;
25294 + req.Attributes = word_width ? WIN_DATA_WIDTH_16 : WIN_DATA_WIDTH_8;
25295 + req.Base = 0;
25296 + req.Size = 0;
25297 + req.AccessSpeed = mem_speed;
25299 + link->win = (window_handle_t)link->handle;
25301 + CS_CHECK(RequestWindow, &link->win, &req);
25303 + CS_CHECK(GetStatus, link->handle, &status);
25305 + dev->map.buswidth = word_width ? 2 : 1;
25306 + dev->map.size = req.Size;
25307 + dev->map.map_priv_1 = ioremap(req.Base, req.Size);
25310 +static int
25311 +mem_cs_event(event_t event, int priority, event_callback_args_t *args)
25313 + dev_link_t *link = args->client_data;
25315 + switch (event) {
25316 + case CS_EVENT_CARD_REMOVAL:
25317 + link->state &= ~DEV_PRESENT;
25318 + if (link->state & DEV_CONFIG)
25319 + mod_timer(&link->release, jiffies + HZ/20);
25320 + break;
25322 + case CS_EVENT_CARD_INSERTION:
25323 + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
25324 + mem_cs_config(link);
25325 + break;
25327 + return 0;
25330 +static dev_link_t *mem_cs_attach(void)
25332 + struct memcs_dev *dev;
25333 + client_reg_t clnt;
25335 + dev = kmalloc(sizeof(*dev), GFP_KERNEL);
25336 + if (dev) {
25337 + memset(dev, 0, sizeof(*dev));
25339 + dev->map.read8 = mem_cs_read8;
25340 + dev->map.read16 = mem_cs_read16;
25341 + dev->map.read32 = mem_cs_read32;
25342 + dev->map.copy_from = mem_cs_copy_from;
25343 + dev->map.write8 = mem_cs_write8;
25344 + dev->map.write16 = mem_cs_write16;
25345 + dev->map.write32 = mem_cs_write32;
25346 + dev->map.copy_to = mem_cs_copy_to;
25348 + dev->link.release.function = &mem_cs_release;
25349 + dev->link.release.data = (u_long)link;
25350 + dev->link.priv = dev;
25352 + dev->link.next = dev_list;
25353 + dev_list = &dev->link;
25355 + clnt.dev_info = &dev_info;
25356 + clnt.Attributes = INOF_IO_CLIENT | INFO_CARD_SHARE;
25357 + clnt.EventMask =
25358 + CS_EVENT_WRITE_PROTECT | CS_EVENT_CARD_INSERTION |
25359 + CS_EVENT_CARD_REMOVAL | CS_EVENT_BATTERY_DEAD |
25360 + CS_EVENT_BATTERY_LOW;
25362 + clnt.event_handler = &mem_cs_event;
25363 + clnt.Version = 0x0210;
25364 + clnt.event_callback_args.client_data = &dev->link;
25366 + ret = CardServices(RegisterClient, &dev->link.handle, &clnt);
25367 + if (ret != CS_SUCCESS) {
25368 + error_info_t err = { RegisterClient, ret };
25369 + CardServices(ReportError, dev->link.handle, &err);
25370 + mem_cs_detach(&dev->link);
25371 + dev = NULL;
25375 + return &dev->link;
25378 +static int __init mem_cs_init(void)
25380 + servinfo_t serv;
25382 + CardServices(GetCardServicesInfo, &serv);
25383 + if (serv.Revision != CS_RELEASE_CODE) {
25384 + printk(KERN_NOTICE "memory_cs: Card services release "
25385 + "does not match\n");
25386 + return -ENXIO;
25388 + register_pccard_driver(&dev_info, mem_cs_attach, mem_cs_detach);
25389 + return 0;
25392 +static void __exit mem_cs_exit(void)
25394 + unregister_pccard_driver(&dev_info);
25395 + while (dev_list != NULL)
25396 + memory_detach(dev_list);
25399 +module_init(mem_cs_init);
25400 +module_exit(mem_cs_exit);
25402 +MODULE_LICENSE("GPL");
25403 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
25404 +++ linux-2.4.25/drivers/char/sa1100-rtc.c 2004-03-31 17:15:09.000000000 +0200
25405 @@ -0,0 +1,474 @@
25407 + * Real Time Clock interface for Linux on StrongARM SA1100
25409 + * Copyright (c) 2000 Nils Faerber
25411 + * Based on rtc.c by Paul Gortmaker
25412 + * Date/time conversion routines taken from arch/arm/kernel/time.c
25413 + * by Linus Torvalds and Russel King
25414 + * and the GNU C Library
25415 + * ( ... I love the GPL ... just take what you need! ;)
25417 + * This program is free software; you can redistribute it and/or
25418 + * modify it under the terms of the GNU General Public License
25419 + * as published by the Free Software Foundation; either version
25420 + * 2 of the License, or (at your option) any later version.
25422 + * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
25423 + * - added periodic timer capability using OSMR1
25424 + * - flag compatibility with other RTC chips
25425 + * - permission checks for ioctls
25426 + * - major cleanup, partial rewrite
25428 + * 0.03 2001-03-07 CIH <cih@coventive.com>
25429 + * - Modify the bug setups RTC clock.
25431 + * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
25432 + * - removed mktime(), added alarm irq clear
25434 + * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
25435 + * - initial release
25436 + */
25438 +#include <linux/module.h>
25439 +#include <linux/fs.h>
25440 +#include <linux/miscdevice.h>
25441 +#include <linux/string.h>
25442 +#include <linux/init.h>
25443 +#include <linux/poll.h>
25444 +#include <linux/proc_fs.h>
25445 +#include <asm/bitops.h>
25446 +#include <asm/hardware.h>
25447 +#include <asm/irq.h>
25448 +#include <linux/rtc.h>
25450 +#define DRIVER_VERSION "1.00"
25452 +#define TIMER_FREQ 3686400
25454 +#define RTC_DEF_DIVIDER 32768 - 1
25455 +#define RTC_DEF_TRIM 0
25457 +/* Those are the bits from a classic RTC we want to mimic */
25458 +#define RTC_IRQF 0x80 /* any of the following 3 is active */
25459 +#define RTC_PF 0x40
25460 +#define RTC_AF 0x20
25461 +#define RTC_UF 0x10
25463 +static unsigned long rtc_status;
25464 +static unsigned long rtc_irq_data;
25465 +static unsigned long rtc_freq = 1024;
25467 +static struct fasync_struct *rtc_async_queue;
25468 +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
25470 +extern spinlock_t rtc_lock;
25472 +static const unsigned char days_in_mo[] =
25473 + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
25475 +#define is_leap(year) \
25476 + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
25479 + * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
25480 + */
25482 +static void decodetime (unsigned long t, struct rtc_time *tval)
25484 + long days, month, year, rem;
25486 + days = t / 86400;
25487 + rem = t % 86400;
25488 + tval->tm_hour = rem / 3600;
25489 + rem %= 3600;
25490 + tval->tm_min = rem / 60;
25491 + tval->tm_sec = rem % 60;
25492 + tval->tm_wday = (4 + days) % 7;
25494 +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
25496 + year = 1970 + days / 365;
25497 + days -= ((year - 1970) * 365
25498 + + LEAPS_THRU_END_OF (year - 1)
25499 + - LEAPS_THRU_END_OF (1970 - 1));
25500 + if (days < 0) {
25501 + year -= 1;
25502 + days += 365 + is_leap(year);
25504 + tval->tm_year = year - 1900;
25505 + tval->tm_yday = days + 1;
25507 + month = 0;
25508 + if (days >= 31) {
25509 + days -= 31;
25510 + month++;
25511 + if (days >= (28 + is_leap(year))) {
25512 + days -= (28 + is_leap(year));
25513 + month++;
25514 + while (days >= days_in_mo[month]) {
25515 + days -= days_in_mo[month];
25516 + month++;
25520 + tval->tm_mon = month;
25521 + tval->tm_mday = days + 1;
25524 +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
25526 + unsigned int rtsr = RTSR;
25528 + /* clear interrupt sources */
25529 + RTSR = 0;
25530 + RTSR = (RTSR_AL|RTSR_HZ);
25532 + /* clear alarm interrupt if it has occurred */
25533 + if (rtsr & RTSR_AL)
25534 + rtsr &= ~RTSR_ALE;
25535 + RTSR = rtsr & (RTSR_ALE|RTSR_HZE);
25537 + /* update irq data & counter */
25538 + if (rtsr & RTSR_AL)
25539 + rtc_irq_data |= (RTC_AF|RTC_IRQF);
25540 + if (rtsr & RTSR_HZ)
25541 + rtc_irq_data |= (RTC_UF|RTC_IRQF);
25542 + rtc_irq_data += 0x100;
25544 + /* wake up waiting process */
25545 + wake_up_interruptible(&rtc_wait);
25546 + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
25549 +static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
25551 + /*
25552 + * If we match for the first time, the periodic interrupt flag won't
25553 + * be set. If it is, then we did wrap around (very unlikely but
25554 + * still possible) and compute the amount of missed periods.
25555 + * The match reg is updated only when the data is actually retrieved
25556 + * to avoid unnecessary interrupts.
25557 + */
25558 + OSSR = OSSR_M1; /* clear match on timer1 */
25559 + if (rtc_irq_data & RTC_PF) {
25560 + rtc_irq_data += (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))) << 8;
25561 + } else {
25562 + rtc_irq_data += (0x100|RTC_PF|RTC_IRQF);
25565 + wake_up_interruptible(&rtc_wait);
25566 + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
25569 +static int rtc_open(struct inode *inode, struct file *file)
25571 + if (test_and_set_bit (1, &rtc_status))
25572 + return -EBUSY;
25573 + rtc_irq_data = 0;
25574 + return 0;
25577 +static int rtc_release(struct inode *inode, struct file *file)
25579 + spin_lock_irq (&rtc_lock);
25580 + RTSR = 0;
25581 + RTSR = (RTSR_AL|RTSR_HZ);
25582 + OIER &= ~OIER_E1;
25583 + OSSR = OSSR_M1;
25584 + spin_unlock_irq (&rtc_lock);
25585 + rtc_status = 0;
25586 + return 0;
25589 +static int rtc_fasync (int fd, struct file *filp, int on)
25591 + return fasync_helper (fd, filp, on, &rtc_async_queue);
25594 +static unsigned int rtc_poll(struct file *file, poll_table *wait)
25596 + poll_wait (file, &rtc_wait, wait);
25597 + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
25600 +static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
25602 + return -ESPIPE;
25605 +ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
25607 + DECLARE_WAITQUEUE(wait, current);
25608 + unsigned long data;
25609 + ssize_t retval;
25611 + if (count < sizeof(unsigned long))
25612 + return -EINVAL;
25614 + add_wait_queue(&rtc_wait, &wait);
25615 + set_current_state(TASK_INTERRUPTIBLE);
25616 + for (;;) {
25617 + spin_lock_irq (&rtc_lock);
25618 + data = rtc_irq_data;
25619 + if (data != 0) {
25620 + rtc_irq_data = 0;
25621 + break;
25623 + spin_unlock_irq (&rtc_lock);
25625 + if (file->f_flags & O_NONBLOCK) {
25626 + retval = -EAGAIN;
25627 + goto out;
25630 + if (signal_pending(current)) {
25631 + retval = -ERESTARTSYS;
25632 + goto out;
25635 + schedule();
25638 + if (data & RTC_PF) {
25639 + /* interpolate missed periods and set match for the next one */
25640 + unsigned long period = TIMER_FREQ/rtc_freq;
25641 + unsigned long oscr = OSCR;
25642 + unsigned long osmr1 = OSMR1;
25643 + unsigned long missed = (oscr - osmr1)/period;
25644 + data += missed << 8;
25645 + OSSR = OSSR_M1; /* clear match on timer 1 */
25646 + OSMR1 = osmr1 + (missed + 1)*period;
25647 + /* ensure we didn't miss another match in the mean time */
25648 + while( (signed long)((osmr1 = OSMR1) - OSCR) <= 0 ) {
25649 + data += 0x100;
25650 + OSSR = OSSR_M1; /* clear match on timer 1 */
25651 + OSMR1 = osmr1 + period;
25654 + spin_unlock_irq (&rtc_lock);
25656 + data -= 0x100; /* the first IRQ wasn't actually missed */
25658 + retval = put_user(data, (unsigned long *)buf);
25659 + if (!retval)
25660 + retval = sizeof(unsigned long);
25662 +out:
25663 + set_current_state(TASK_RUNNING);
25664 + remove_wait_queue(&rtc_wait, &wait);
25665 + return retval;
25668 +static int rtc_ioctl(struct inode *inode, struct file *file,
25669 + unsigned int cmd, unsigned long arg)
25671 + struct rtc_time tm, tm2;
25673 + switch (cmd) {
25674 + case RTC_AIE_OFF:
25675 + spin_lock_irq(&rtc_lock);
25676 + RTSR &= ~RTSR_ALE;
25677 + rtc_irq_data = 0;
25678 + spin_unlock_irq(&rtc_lock);
25679 + return 0;
25680 + case RTC_AIE_ON:
25681 + spin_lock_irq(&rtc_lock);
25682 + RTSR |= RTSR_ALE;
25683 + rtc_irq_data = 0;
25684 + spin_unlock_irq(&rtc_lock);
25685 + return 0;
25686 + case RTC_UIE_OFF:
25687 + spin_lock_irq(&rtc_lock);
25688 + RTSR &= ~RTSR_HZE;
25689 + rtc_irq_data = 0;
25690 + spin_unlock_irq(&rtc_lock);
25691 + return 0;
25692 + case RTC_UIE_ON:
25693 + spin_lock_irq(&rtc_lock);
25694 + RTSR |= RTSR_HZE;
25695 + rtc_irq_data = 0;
25696 + spin_unlock_irq(&rtc_lock);
25697 + return 0;
25698 + case RTC_PIE_OFF:
25699 + spin_lock_irq(&rtc_lock);
25700 + OIER &= ~OIER_E1;
25701 + rtc_irq_data = 0;
25702 + spin_unlock_irq(&rtc_lock);
25703 + return 0;
25704 + case RTC_PIE_ON:
25705 + if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
25706 + return -EACCES;
25707 + spin_lock_irq(&rtc_lock);
25708 + OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
25709 + OIER |= OIER_E1;
25710 + rtc_irq_data = 0;
25711 + spin_unlock_irq(&rtc_lock);
25712 + return 0;
25713 + case RTC_ALM_READ:
25714 + decodetime (RTAR, &tm);
25715 + break;
25716 + case RTC_ALM_SET:
25717 + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
25718 + return -EFAULT;
25719 + decodetime (RCNR, &tm);
25720 + if ((unsigned)tm2.tm_hour < 24)
25721 + tm.tm_hour = tm2.tm_hour;
25722 + if ((unsigned)tm2.tm_min < 60)
25723 + tm.tm_min = tm2.tm_min;
25724 + if ((unsigned)tm2.tm_sec < 60)
25725 + tm.tm_sec = tm2.tm_sec;
25726 + RTAR = mktime ( tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
25727 + tm.tm_hour, tm.tm_min, tm.tm_sec);
25728 + return 0;
25729 + case RTC_RD_TIME:
25730 + decodetime (RCNR, &tm);
25731 + break;
25732 + case RTC_SET_TIME:
25733 + if (!capable(CAP_SYS_TIME))
25734 + return -EACCES;
25735 + if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
25736 + return -EFAULT;
25737 + tm.tm_year += 1900;
25738 + if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 ||
25739 + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
25740 + (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
25741 + (unsigned)tm.tm_hour >= 24 ||
25742 + (unsigned)tm.tm_min >= 60 ||
25743 + (unsigned)tm.tm_sec >= 60)
25744 + return -EINVAL;
25745 + RCNR = mktime ( tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
25746 + tm.tm_hour, tm.tm_min, tm.tm_sec);
25747 + return 0;
25748 + case RTC_IRQP_READ:
25749 + return put_user(rtc_freq, (unsigned long *)arg);
25750 + case RTC_IRQP_SET:
25751 + if (arg < 1 || arg > TIMER_FREQ)
25752 + return -EINVAL;
25753 + if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
25754 + return -EACCES;
25755 + rtc_freq = arg;
25756 + return 0;
25757 + case RTC_EPOCH_READ:
25758 + return put_user (1970, (unsigned long *)arg);
25759 + default:
25760 + return -EINVAL;
25762 + return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
25765 +static struct file_operations rtc_fops = {
25766 + owner: THIS_MODULE,
25767 + llseek: rtc_llseek,
25768 + read: rtc_read,
25769 + poll: rtc_poll,
25770 + ioctl: rtc_ioctl,
25771 + open: rtc_open,
25772 + release: rtc_release,
25773 + fasync: rtc_fasync,
25776 +static struct miscdevice sa1100rtc_miscdev = {
25777 + RTC_MINOR,
25778 + "rtc",
25779 + &rtc_fops
25782 +static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
25784 + char *p = page;
25785 + int len;
25786 + struct rtc_time tm;
25788 + decodetime (RCNR, &tm);
25789 + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
25790 + "rtc_date\t: %04d-%02d-%02d\n"
25791 + "rtc_epoch\t: %04d\n",
25792 + tm.tm_hour, tm.tm_min, tm.tm_sec,
25793 + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1970);
25794 + decodetime (RTAR, &tm);
25795 + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
25796 + "alrm_date\t: %04d-%02d-%02d\n",
25797 + tm.tm_hour, tm.tm_min, tm.tm_sec,
25798 + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
25799 + p += sprintf(p, "trim/divider\t: 0x%08x\n", RTTR);
25800 + p += sprintf(p, "alarm_IRQ\t: %s\n", (RTSR & RTSR_ALE) ? "yes" : "no" );
25801 + p += sprintf(p, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no");
25802 + p += sprintf(p, "periodic_IRQ\t: %s\n", (OIER & OIER_E1) ? "yes" : "no");
25803 + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
25805 + len = (p - page) - off;
25806 + if (len < 0)
25807 + len = 0;
25809 + *eof = (len <= count) ? 1 : 0;
25810 + *start = page + off;
25812 + return len;
25815 +static int __init rtc_init(void)
25817 + int ret;
25819 + misc_register (&sa1100rtc_miscdev);
25820 + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
25821 + ret = request_irq (IRQ_RTC1Hz, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
25822 + if (ret) {
25823 + printk (KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTC1Hz);
25824 + goto IRQ_RTC1Hz_failed;
25826 + ret = request_irq (IRQ_RTCAlrm, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
25827 + if (ret) {
25828 + printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTCAlrm);
25829 + goto IRQ_RTCAlrm_failed;
25831 + ret = request_irq (IRQ_OST1, timer1_interrupt, SA_INTERRUPT, "rtc timer", NULL);
25832 + if (ret) {
25833 + printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_OST1);
25834 + goto IRQ_OST1_failed;
25837 + printk (KERN_INFO "SA1100 Real Time Clock driver v" DRIVER_VERSION "\n");
25839 + /*
25840 + * According to the manual we should be able to let RTTR be zero
25841 + * and then a default diviser for a 32.768KHz clock is used.
25842 + * Apparently this doesn't work, at least for my SA1110 rev 5.
25843 + * If the clock divider is uninitialized then reset it to the
25844 + * default value to get the 1Hz clock.
25845 + */
25846 + if (RTTR == 0) {
25847 + RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
25848 + printk (KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
25849 + /* The current RTC value probably doesn't make sense either */
25850 + RCNR = 0;
25853 + return 0;
25855 +IRQ_OST1_failed:
25856 + free_irq (IRQ_RTCAlrm, NULL);
25857 +IRQ_RTCAlrm_failed:
25858 + free_irq (IRQ_RTC1Hz, NULL);
25859 +IRQ_RTC1Hz_failed:
25860 + remove_proc_entry ("driver/rtc", NULL);
25861 + misc_deregister (&sa1100rtc_miscdev);
25862 + return ret;
25865 +static void __exit rtc_exit(void)
25867 + free_irq (IRQ_OST1, NULL);
25868 + free_irq (IRQ_RTCAlrm, NULL);
25869 + free_irq (IRQ_RTC1Hz, NULL);
25870 + remove_proc_entry ("driver/rtc", NULL);
25871 + misc_deregister (&sa1100rtc_miscdev);
25874 +module_init(rtc_init);
25875 +module_exit(rtc_exit);
25877 +MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
25878 +MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
25879 +EXPORT_NO_SYMBOLS;
25880 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
25881 +++ linux-2.4.25/drivers/char/sa1100_wdt.c 2004-03-31 17:15:09.000000000 +0200
25882 @@ -0,0 +1,150 @@
25884 + * Watchdog driver for the SA11x0
25886 + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
25887 + * Based on SoftDog driver by Alan Cox <alan@redhat.com>
25889 + * This program is free software; you can redistribute it and/or
25890 + * modify it under the terms of the GNU General Public License
25891 + * as published by the Free Software Foundation; either version
25892 + * 2 of the License, or (at your option) any later version.
25894 + * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
25895 + * warranty for any of this software. This material is provided
25896 + * "AS-IS" and at no charge.
25898 + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
25900 + * 27/11/2000 Initial release
25901 + */
25903 +#include <linux/module.h>
25904 +#include <linux/config.h>
25905 +#include <linux/types.h>
25906 +#include <linux/kernel.h>
25907 +#include <linux/fs.h>
25908 +#include <linux/mm.h>
25909 +#include <linux/miscdevice.h>
25910 +#include <linux/watchdog.h>
25911 +#include <linux/reboot.h>
25912 +#include <linux/smp_lock.h>
25913 +#include <linux/init.h>
25914 +#include <asm/uaccess.h>
25915 +#include <asm/hardware.h>
25916 +#include <asm/bitops.h>
25918 +#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
25920 +static int sa1100_margin = TIMER_MARGIN; /* in seconds */
25921 +static int sa1100wdt_users;
25922 +static int pre_margin;
25923 +#ifdef MODULE
25924 +MODULE_PARM(sa1100_margin,"i");
25925 +#endif
25928 + * Allow only one person to hold it open
25929 + */
25931 +static int sa1100dog_open(struct inode *inode, struct file *file)
25933 + if(test_and_set_bit(1,&sa1100wdt_users))
25934 + return -EBUSY;
25935 + MOD_INC_USE_COUNT;
25936 + /* Activate SA1100 Watchdog timer */
25937 + pre_margin=3686400 * sa1100_margin;
25938 + OSMR3 = OSCR + pre_margin;
25939 + OSSR = OSSR_M3;
25940 + OWER = OWER_WME;
25941 + OIER |= OIER_E3;
25942 + return 0;
25945 +static int sa1100dog_release(struct inode *inode, struct file *file)
25947 + /*
25948 + * Shut off the timer.
25949 + * Lock it in if it's a module and we defined ...NOWAYOUT
25950 + */
25951 + OSMR3 = OSCR + pre_margin;
25952 +#ifndef CONFIG_WATCHDOG_NOWAYOUT
25953 + OIER &= ~OIER_E3;
25954 +#endif
25955 + sa1100wdt_users = 0;
25956 + MOD_DEC_USE_COUNT;
25957 + return 0;
25960 +static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
25962 + /* Can't seek (pwrite) on this device */
25963 + if (ppos != &file->f_pos)
25964 + return -ESPIPE;
25966 + /* Refresh OSMR3 timer. */
25967 + if(len) {
25968 + OSMR3 = OSCR + pre_margin;
25969 + return 1;
25971 + return 0;
25974 +static int sa1100dog_ioctl(struct inode *inode, struct file *file,
25975 + unsigned int cmd, unsigned long arg)
25977 + static struct watchdog_info ident = {
25978 + identity: "SA1100 Watchdog",
25979 + };
25981 + switch(cmd){
25982 + default:
25983 + return -ENOIOCTLCMD;
25984 + case WDIOC_GETSUPPORT:
25985 + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
25986 + case WDIOC_GETSTATUS:
25987 + return put_user(0,(int *)arg);
25988 + case WDIOC_GETBOOTSTATUS:
25989 + return put_user((RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0, (int *)arg);
25990 + case WDIOC_KEEPALIVE:
25991 + OSMR3 = OSCR + pre_margin;
25992 + return 0;
25996 +static struct file_operations sa1100dog_fops=
25998 + owner: THIS_MODULE,
25999 + write: sa1100dog_write,
26000 + ioctl: sa1100dog_ioctl,
26001 + open: sa1100dog_open,
26002 + release: sa1100dog_release,
26005 +static struct miscdevice sa1100dog_miscdev=
26007 + WATCHDOG_MINOR,
26008 + "SA1100 watchdog",
26009 + &sa1100dog_fops
26012 +static int __init sa1100dog_init(void)
26014 + int ret;
26016 + ret = misc_register(&sa1100dog_miscdev);
26018 + if (ret)
26019 + return ret;
26021 + printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin);
26023 + return 0;
26026 +static void __exit sa1100dog_exit(void)
26028 + misc_deregister(&sa1100dog_miscdev);
26031 +module_init(sa1100dog_init);
26032 +module_exit(sa1100dog_exit);
26033 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
26034 +++ linux-2.4.25/drivers/char/sa1111_keyb.c 2004-03-31 17:15:09.000000000 +0200
26035 @@ -0,0 +1,1153 @@
26037 + * SA1111 PS/2 keyboard/mouse driver
26039 + * 2000 by VASARA RESEARCH INC.
26041 + * Changelog:
26042 + * Jun.xx,2000: Kunihiko IMAI <imai@vasara.co.jp>
26043 + * Port to 2.4.0test1-ac19-rmk1-np1
26044 + * Apr.17,2000: Takafumi Kawana <kawana@pro.or.jp>
26045 + * Internal Release for XP860
26048 + * This driver is based on linux/drivers/char/pc_keyb.c
26049 + * Original declaration follows:
26052 + * linux/drivers/char/pc_keyb.c
26054 + * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
26055 + * See keyboard.c for the whole history.
26057 + * Major cleanup by Martin Mares, May 1997
26059 + * Combined the keyboard and PS/2 mouse handling into one file,
26060 + * because they share the same hardware.
26061 + * Johan Myreen <jem@iki.fi> 1998-10-08.
26063 + * Code fixes to handle mouse ACKs properly.
26064 + * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
26066 + */
26067 +#include <linux/config.h>
26068 +#include <linux/spinlock.h>
26069 +#include <linux/sched.h>
26070 +#include <linux/interrupt.h>
26071 +#include <linux/tty.h>
26072 +#include <linux/mm.h>
26073 +#include <linux/signal.h>
26074 +#include <linux/init.h>
26075 +#include <linux/kbd_ll.h>
26076 +#include <linux/delay.h>
26077 +#include <linux/random.h>
26078 +#include <linux/poll.h>
26079 +#include <linux/miscdevice.h>
26080 +#include <linux/slab.h>
26081 +#include <linux/kbd_kern.h>
26082 +#include <linux/ioport.h>
26084 +#include <asm/hardware.h>
26085 +#include <asm/bitops.h>
26086 +#include <asm/uaccess.h>
26087 +#include <asm/irq.h>
26088 +#include <asm/system.h>
26090 +#include <asm/io.h>
26092 +/* Some configuration switches are present in the include file... */
26094 +#include <linux/pc_keyb.h>
26095 +#include <asm/keyboard.h>
26096 +#include <asm/hardware/sa1111.h>
26098 +#define KBD_STAT_RXB (1<<4)
26099 +#define KBD_STAT_RXF (1<<5)
26100 +#define KBD_STAT_TXB (1<<6)
26101 +#define KBD_STAT_TXE (1<<7)
26102 +#define KBD_STAT_STP (1<<8)
26104 +#define MSE_STAT_RXB (1<<4)
26105 +#define MSE_STAT_RXF (1<<5)
26106 +#define MSE_STAT_TXB (1<<6)
26107 +#define MSE_STAT_TXE (1<<7)
26108 +#define MSE_STAT_STP (1<<8)
26110 +/* Simple translation table for the SysRq keys */
26112 +#ifdef CONFIG_MAGIC_SYSRQ
26113 +unsigned char sa1111_sysrq_xlate[128] = "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
26114 + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
26115 + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
26116 + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
26117 + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
26118 + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
26119 + "\r\000/"; /* 0x60 - 0x6f */
26120 +#endif
26122 +// static void kbd_write_command_w(int data);
26123 +static void kbd_write_output_w(int data);
26125 +spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
26126 +static void handle_kbd_event(void);
26128 +/* used only by send_data - set by keyboard_interrupt */
26129 +static volatile unsigned char reply_expected = 0;
26130 +static volatile unsigned char acknowledge = 0;
26131 +static volatile unsigned char resend = 0;
26134 +#if defined CONFIG_PSMOUSE
26136 + * PS/2 Auxiliary Device
26137 + */
26139 +static int __init psaux_init(void);
26141 +static struct aux_queue *queue; /* Mouse data buffer. */
26142 +static int aux_count = 0;
26143 +/* used when we send commands to the mouse that expect an ACK. */
26144 +static unsigned char mouse_reply_expected = 0;
26146 +#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
26147 +#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
26149 +#define MAX_RETRIES 60 /* some aux operations take long time */
26150 +#endif /* CONFIG_PSMOUSE */
26153 + * Wait for keyboard controller input buffer to drain.
26155 + * Don't use 'jiffies' so that we don't depend on
26156 + * interrupts..
26158 + * Quote from PS/2 System Reference Manual:
26160 + * "Address hex 0060 and address hex 0064 should be written only when
26161 + * the input-buffer-full bit and output-buffer-full bit in the
26162 + * Controller Status register are set 0."
26163 + */
26165 +static void kb_wait(void)
26167 + unsigned long timeout = KBC_TIMEOUT;
26169 + do {
26170 + /*
26171 + * "handle_kbd_event()" will handle any incoming events
26172 + * while we wait - keypresses or mouse movement.
26173 + */
26174 + handle_kbd_event();
26175 + if (KBDSTAT & KBD_STAT_TXE)
26176 + return;
26177 + mdelay(1);
26178 + timeout--;
26180 + while (timeout);
26181 +#ifdef KBD_REPORT_TIMEOUTS
26182 + printk(KERN_WARNING "Keyboard timed out[1]\n");
26183 +#endif
26187 + * Translation of escaped scancodes to keycodes.
26188 + * This is now user-settable.
26189 + * The keycodes 1-88,96-111,119 are fairly standard, and
26190 + * should probably not be changed - changing might confuse X.
26191 + * X also interprets scancode 0x5d (KEY_Begin).
26193 + * For 1-88 keycode equals scancode.
26194 + */
26196 +#define E0_KPENTER 96
26197 +#define E0_RCTRL 97
26198 +#define E0_KPSLASH 98
26199 +#define E0_PRSCR 99
26200 +#define E0_RALT 100
26201 +#define E0_BREAK 101 /* (control-pause) */
26202 +#define E0_HOME 102
26203 +#define E0_UP 103
26204 +#define E0_PGUP 104
26205 +#define E0_LEFT 105
26206 +#define E0_RIGHT 106
26207 +#define E0_END 107
26208 +#define E0_DOWN 108
26209 +#define E0_PGDN 109
26210 +#define E0_INS 110
26211 +#define E0_DEL 111
26213 +/* for USB 106 keyboard */
26214 +#define E0_YEN 124
26215 +#define E0_BACKSLASH 89
26218 +#define E1_PAUSE 119
26221 + * The keycodes below are randomly located in 89-95,112-118,120-127.
26222 + * They could be thrown away (and all occurrences below replaced by 0),
26223 + * but that would force many users to use the `setkeycodes' utility, where
26224 + * they needed not before. It does not matter that there are duplicates, as
26225 + * long as no duplication occurs for any single keyboard.
26226 + */
26227 +#define SC_LIM 89
26229 +#define FOCUS_PF1 85 /* actual code! */
26230 +#define FOCUS_PF2 89
26231 +#define FOCUS_PF3 90
26232 +#define FOCUS_PF4 91
26233 +#define FOCUS_PF5 92
26234 +#define FOCUS_PF6 93
26235 +#define FOCUS_PF7 94
26236 +#define FOCUS_PF8 95
26237 +#define FOCUS_PF9 120
26238 +#define FOCUS_PF10 121
26239 +#define FOCUS_PF11 122
26240 +#define FOCUS_PF12 123
26242 +#define JAP_86 124
26243 +/* tfj@olivia.ping.dk:
26244 + * The four keys are located over the numeric keypad, and are
26245 + * labelled A1-A4. It's an rc930 keyboard, from
26246 + * Regnecentralen/RC International, Now ICL.
26247 + * Scancodes: 59, 5a, 5b, 5c.
26248 + */
26249 +#define RGN1 124
26250 +#define RGN2 125
26251 +#define RGN3 126
26252 +#define RGN4 127
26254 +static unsigned char high_keys[128 - SC_LIM] = {
26255 + RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
26256 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
26257 + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
26258 + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
26259 + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
26260 + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
26263 +/* BTC */
26264 +#define E0_MACRO 112
26265 +/* LK450 */
26266 +#define E0_F13 113
26267 +#define E0_F14 114
26268 +#define E0_HELP 115
26269 +#define E0_DO 116
26270 +#define E0_F17 117
26271 +#define E0_KPMINPLUS 118
26273 + * My OmniKey generates e0 4c for the "OMNI" key and the
26274 + * right alt key does nada. [kkoller@nyx10.cs.du.edu]
26275 + */
26276 +#define E0_OK 124
26278 + * New microsoft keyboard is rumoured to have
26279 + * e0 5b (left window button), e0 5c (right window button),
26280 + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
26281 + * [or: Windows_L, Windows_R, TaskMan]
26282 + */
26283 +#define E0_MSLW 125
26284 +#define E0_MSRW 126
26285 +#define E0_MSTM 127
26287 +static unsigned char e0_keys[128] = {
26288 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
26289 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
26290 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
26291 + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
26292 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
26293 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
26294 + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
26295 + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
26296 + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
26297 + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, /* 0x48-0x4f */
26298 + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
26299 + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
26300 + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
26301 + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
26302 + //0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
26303 + 0, 0, 0, 0, 0, E0_BACKSLASH, 0, 0, /* 0x70-0x77 */
26304 + 0, 0, 0, E0_YEN, 0, 0, 0, 0 /* 0x78-0x7f */
26307 +int sa1111_setkeycode(unsigned int scancode, unsigned int keycode)
26309 + if (scancode < SC_LIM || scancode > 255 || keycode > 127)
26310 + return -EINVAL;
26311 + if (scancode < 128)
26312 + high_keys[scancode - SC_LIM] = keycode;
26313 + else
26314 + e0_keys[scancode - 128] = keycode;
26315 + return 0;
26318 +int sa1111_getkeycode(unsigned int scancode)
26320 + return
26321 + (scancode < SC_LIM || scancode > 255) ? -EINVAL :
26322 + (scancode <
26323 + 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128];
26326 +static int do_acknowledge(unsigned char scancode)
26328 + if (reply_expected) {
26329 + /* Unfortunately, we must recognise these codes only if we know they
26330 + * are known to be valid (i.e., after sending a command), because there
26331 + * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
26332 + * keys with such codes :(
26333 + */
26334 + if (scancode == KBD_REPLY_ACK) {
26335 + acknowledge = 1;
26336 + reply_expected = 0;
26337 + return 0;
26338 + } else if (scancode == KBD_REPLY_RESEND) {
26339 + resend = 1;
26340 + reply_expected = 0;
26341 + return 0;
26343 + /* Should not happen... */
26344 +#if 0
26345 + printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
26346 + scancode);
26347 +#endif
26349 + return 1;
26352 +int
26353 +sa1111_translate(unsigned char scancode, unsigned char *keycode,
26354 + char raw_mode)
26356 + static int prev_scancode = 0;
26358 + /* special prefix scancodes.. */
26359 + if (scancode == 0xe0 || scancode == 0xe1) {
26360 + prev_scancode = scancode;
26361 + return 0;
26364 + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
26365 + if (scancode == 0x00 || scancode == 0xff) {
26366 + prev_scancode = 0;
26367 + return 0;
26370 + scancode &= 0x7f;
26372 + if (prev_scancode) {
26373 + /*
26374 + * usually it will be 0xe0, but a Pause key generates
26375 + * e1 1d 45 e1 9d c5 when pressed, and nothing when released
26376 + */
26377 + if (prev_scancode != 0xe0) {
26378 + if (prev_scancode == 0xe1 && scancode == 0x1d) {
26379 + prev_scancode = 0x100;
26380 + return 0;
26382 + else if (prev_scancode == 0x100
26383 + && scancode == 0x45) {
26384 + *keycode = E1_PAUSE;
26385 + prev_scancode = 0;
26386 + } else {
26387 +#ifdef KBD_REPORT_UNKN
26388 + if (!raw_mode)
26389 + printk(KERN_INFO
26390 + "keyboard: unknown e1 escape sequence\n");
26391 +#endif
26392 + prev_scancode = 0;
26393 + return 0;
26395 + } else {
26396 + prev_scancode = 0;
26397 + /*
26398 + * The keyboard maintains its own internal caps lock and
26399 + * num lock statuses. In caps lock mode E0 AA precedes make
26400 + * code and E0 2A follows break code. In num lock mode,
26401 + * E0 2A precedes make code and E0 AA follows break code.
26402 + * We do our own book-keeping, so we will just ignore these.
26403 + */
26404 + /*
26405 + * For my keyboard there is no caps lock mode, but there are
26406 + * both Shift-L and Shift-R modes. The former mode generates
26407 + * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
26408 + * So, we should also ignore the latter. - aeb@cwi.nl
26409 + */
26410 + if (scancode == 0x2a || scancode == 0x36)
26411 + return 0;
26413 + if (e0_keys[scancode])
26414 + *keycode = e0_keys[scancode];
26415 + else {
26416 +#ifdef KBD_REPORT_UNKN
26417 + if (!raw_mode)
26418 + printk(KERN_INFO
26419 + "keyboard: unknown scancode e0 %02x\n",
26420 + scancode);
26421 +#endif
26422 + return 0;
26425 + } else if (scancode >= SC_LIM) {
26426 + /* This happens with the FOCUS 9000 keyboard
26427 + Its keys PF1..PF12 are reported to generate
26428 + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
26429 + Moreover, unless repeated, they do not generate
26430 + key-down events, so we have to zero up_flag below */
26431 + /* Also, Japanese 86/106 keyboards are reported to
26432 + generate 0x73 and 0x7d for \ - and \ | respectively. */
26433 + /* Also, some Brazilian keyboard is reported to produce
26434 + 0x73 and 0x7e for \ ? and KP-dot, respectively. */
26436 + *keycode = high_keys[scancode - SC_LIM];
26438 + if (!*keycode) {
26439 + if (!raw_mode) {
26440 +#ifdef KBD_REPORT_UNKN
26441 + printk(KERN_INFO
26442 + "keyboard: unrecognized scancode (%02x)"
26443 + " - ignored\n", scancode);
26444 +#endif
26446 + return 0;
26448 + } else
26449 + *keycode = scancode;
26450 + return 1;
26453 +char sa1111_unexpected_up(unsigned char keycode)
26455 + /* unexpected, but this can happen: maybe this was a key release for a
26456 + FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
26457 + if (keycode >= SC_LIM || keycode == 85)
26458 + return 0;
26459 + else
26460 + return 0200;
26463 +static unsigned char kbd_exists = 1;
26465 +static inline void handle_keyboard_event(unsigned char scancode)
26467 +#ifdef CONFIG_VT
26468 + kbd_exists = 1;
26469 + if (do_acknowledge(scancode))
26470 + handle_scancode(scancode, !(scancode & 0x80));
26471 +#endif
26472 + tasklet_schedule(&keyboard_tasklet);
26476 + * This reads the keyboard status port, and does the
26477 + * appropriate action.
26479 + * It requires that we hold the keyboard controller
26480 + * spinlock.
26481 + */
26482 +static void handle_kbd_event(void)
26484 + unsigned int status = KBDSTAT;
26485 + unsigned int work = 10000;
26486 + unsigned char scancode;
26488 + while (status & KBD_STAT_RXF) {
26489 + while (status & KBD_STAT_RXF) {
26490 + scancode = KBDDATA & 0xff;
26491 + if (!(status & KBD_STAT_STP))
26492 + handle_keyboard_event(scancode);
26493 + if (!--work) {
26494 + printk(KERN_ERR
26495 + "pc_keyb: keyboard controller jammed (0x%02X).\n",
26496 + status);
26497 + return;
26499 + status = KBDSTAT;
26501 + work = 10000;
26504 + if (status & KBD_STAT_STP)
26505 + KBDSTAT = KBD_STAT_STP;
26508 +static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
26510 + unsigned long flags;
26512 +#ifdef CONFIG_VT
26513 + kbd_pt_regs = regs;
26514 +#endif
26515 + spin_lock_irqsave(&kbd_controller_lock, flags);
26516 + handle_kbd_event();
26517 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26521 + * send_data sends a character to the keyboard and waits
26522 + * for an acknowledge, possibly retrying if asked to. Returns
26523 + * the success status.
26525 + * Don't use 'jiffies', so that we don't depend on interrupts
26526 + */
26527 +static int send_data(unsigned char data)
26529 + int retries = 3;
26531 + do {
26532 + unsigned long timeout = KBD_TIMEOUT;
26534 + acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
26535 + resend = 0;
26536 + reply_expected = 1;
26537 + kbd_write_output_w(data);
26538 + for (;;) {
26539 + if (acknowledge)
26540 + return 1;
26541 + if (resend)
26542 + break;
26543 + mdelay(1);
26544 + if (!--timeout) {
26545 +#ifdef KBD_REPORT_TIMEOUTS
26546 + printk(KERN_WARNING
26547 + "keyboard: Timeout - AT keyboard not present?\n");
26548 +#endif
26549 + return 0;
26553 + while (retries-- > 0);
26554 +#ifdef KBD_REPORT_TIMEOUTS
26555 + printk(KERN_WARNING
26556 + "keyboard: Too many NACKs -- noisy kbd cable?\n");
26557 +#endif
26558 + return 0;
26561 +void sa1111_leds(unsigned char leds)
26563 + if (kbd_exists
26564 + && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {
26565 + send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */
26566 + kbd_exists = 0;
26570 +#define KBD_NO_DATA (-1) /* No data */
26571 +#define KBD_BAD_DATA (-2) /* Parity or other error */
26573 +static int __init kbd_read_data(void)
26575 + int retval = KBD_NO_DATA;
26576 + unsigned int status;
26578 + status = KBDSTAT;
26579 + if (status & KBD_STAT_RXF) {
26580 + unsigned char data = KBDDATA;
26582 + retval = data;
26583 + if (status & KBD_STAT_STP)
26584 + retval = KBD_BAD_DATA;
26586 + return retval;
26589 +static void __init kbd_clear_input(void)
26591 + int maxread = 100; /* Random number */
26593 + do {
26594 + if (kbd_read_data() == KBD_NO_DATA)
26595 + break;
26597 + while (--maxread);
26600 +static int __init kbd_wait_for_input(void)
26602 + long timeout = KBD_INIT_TIMEOUT;
26604 + do {
26605 + int retval = kbd_read_data();
26606 + if (retval >= 0)
26607 + return retval;
26608 + mdelay(1);
26610 + while (--timeout);
26611 + return -1;
26614 +#if 0
26615 +static void kbd_write_command_w(int data)
26617 + unsigned long flags;
26619 + spin_lock_irqsave(&kbd_controller_lock, flags);
26620 + kb_wait();
26621 + kbd_write_command(data);
26622 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26624 +#endif
26626 +static void kbd_write_output_w(int data)
26628 + unsigned long flags;
26630 + spin_lock_irqsave(&kbd_controller_lock, flags);
26631 + kb_wait();
26632 + KBDDATA = data & 0xff;
26633 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26637 + * Test the keyboard interface. We basically check to make sure that
26638 + * we can drive each line to the keyboard independently of each other.
26639 + */
26640 +static int kbdif_test(void)
26642 + int ret = 0;
26644 + KBDCR = KBDCR_ENA | KBDCR_FKC;
26645 + udelay(2);
26646 + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBD) {
26647 + printk("Keyboard interface test failed[1]: %02x\n",
26648 + KBDSTAT);
26649 + ret = -ENODEV;
26652 + KBDCR = KBDCR_ENA;
26653 + udelay(2);
26654 + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != (KBDSTAT_KBC | KBDSTAT_KBD)) {
26655 + printk("Keyboard interface test failed[2]: %02x\n",
26656 + KBDSTAT);
26657 + ret = -ENODEV;
26660 + KBDCR = KBDCR_ENA | KBDCR_FKD;
26661 + udelay(2);
26662 + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBC) {
26663 + printk("Keyboard interface test failed[3]: %02x\n",
26664 + KBDSTAT);
26665 + ret = -ENODEV;
26668 + return ret;
26671 +static char *__init initialize_kbd(void)
26673 + int status;
26675 + /*
26676 + * Test the keyboard interface.
26677 + */
26678 + kbdif_test();
26680 + /*
26681 + * Ok, drop the force low bits, and wait a while,
26682 + * and clear the stop bit error flag.
26683 + */
26684 + KBDCR = KBDCR_ENA;
26685 + udelay(4);
26686 + KBDSTAT = KBD_STAT_STP;
26688 + /*
26689 + * Ok, we're now ready to talk to the keyboard. Reset
26690 + * it, just to make sure we're starting in a sane state.
26692 + * Set up to try again if the keyboard asks for RESEND.
26693 + */
26694 + do {
26695 + KBDDATA = KBD_CMD_RESET;
26696 + status = kbd_wait_for_input();
26697 + if (status == KBD_REPLY_ACK)
26698 + break;
26699 + if (status != KBD_REPLY_RESEND)
26700 + return "Keyboard reset failed, no ACK";
26701 + } while (1);
26703 + if (kbd_wait_for_input() != KBD_REPLY_POR)
26704 + return "Keyboard reset failed, no POR";
26706 + /*
26707 + * Set keyboard controller mode. During this, the keyboard should be
26708 + * in the disabled state.
26710 + * Set up to try again if the keyboard asks for RESEND.
26711 + */
26712 + do {
26713 + kbd_write_output_w(KBD_CMD_DISABLE);
26714 + status = kbd_wait_for_input();
26715 + if (status == KBD_REPLY_ACK)
26716 + break;
26717 + if (status != KBD_REPLY_RESEND)
26718 + return "Disable keyboard: no ACK";
26719 + } while (1);
26721 +#if 0 /*@@@ */
26722 + kbd_write_command_w(KBD_CCMD_WRITE_MODE);
26723 + kbd_write_output_w(KBD_MODE_KBD_INT
26724 + | KBD_MODE_SYS | KBD_MODE_DISABLE_MOUSE |
26725 + KBD_MODE_KCC);
26727 + /* ibm powerpc portables need this to use scan-code set 1 -- Cort */
26728 + kbd_write_command_w(KBD_CCMD_READ_MODE);
26729 + if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
26730 + /*
26731 + * If the controller does not support conversion,
26732 + * Set the keyboard to scan-code set 1.
26733 + */
26734 + kbd_write_output_w(0xF0);
26735 + kbd_wait_for_input();
26736 + kbd_write_output_w(0x01);
26737 + kbd_wait_for_input();
26739 +#else
26740 + kbd_write_output_w(0xf0);
26741 + kbd_wait_for_input();
26742 + kbd_write_output_w(0x01);
26743 + kbd_wait_for_input();
26744 +#endif
26747 + kbd_write_output_w(KBD_CMD_ENABLE);
26748 + if (kbd_wait_for_input() != KBD_REPLY_ACK)
26749 + return "Enable keyboard: no ACK";
26751 + /*
26752 + * Finally, set the typematic rate to maximum.
26753 + */
26754 + kbd_write_output_w(KBD_CMD_SET_RATE);
26755 + if (kbd_wait_for_input() != KBD_REPLY_ACK)
26756 + return "Set rate: no ACK";
26757 + kbd_write_output_w(0x00);
26758 + if (kbd_wait_for_input() != KBD_REPLY_ACK)
26759 + return "Set rate: no ACK";
26761 + return NULL;
26764 +int __init sa1111_kbd_init_hw(void)
26766 + char *msg;
26767 + int ret;
26769 + if (!request_mem_region(_KBDCR, 512, "keyboard"))
26770 + return -EBUSY;
26772 + SKPCR |= SKPCR_PTCLKEN;
26773 + KBDCLKDIV = 0;
26774 + KBDPRECNT = 127;
26776 + /* Flush any pending input. */
26777 + kbd_clear_input();
26779 + msg = initialize_kbd();
26780 + if (msg)
26781 + printk(KERN_WARNING "initialize_kbd: %s\n", msg);
26783 +#if defined CONFIG_PSMOUSE
26784 + psaux_init();
26785 +#endif
26787 + k_setkeycode = sa1111_setkeycode;
26788 + k_getkeycode = sa1111_getkeycode;
26789 + k_translate = sa1111_translate;
26790 + k_unexpected_up = sa1111_unexpected_up;
26791 + k_leds = sa1111_leds;
26792 +#ifdef CONFIG_MAGIC_SYSRQ
26793 + k_sysrq_xlate = sa1111_sysrq_xlate;
26794 + k_sysrq_key = 0x54;
26795 +#endif
26797 + /* Ok, finally allocate the IRQ, and off we go.. */
26798 + ret = request_irq(IRQ_TPRXINT, keyboard_interrupt, 0, "keyboard", NULL);
26799 + if (ret)
26800 + release_mem_region(_KBDCR, 512);
26802 + return ret;
26805 +#if defined CONFIG_PSMOUSE
26807 +static inline void handle_mouse_event(unsigned char scancode)
26809 + if (mouse_reply_expected) {
26810 + if (scancode == AUX_ACK) {
26811 + mouse_reply_expected--;
26812 + return;
26814 + mouse_reply_expected = 0;
26817 + add_mouse_randomness(scancode);
26818 + if (aux_count) {
26819 + int head = queue->head;
26821 + queue->buf[head] = scancode;
26822 + head = (head + 1) & (AUX_BUF_SIZE - 1);
26823 + if (head != queue->tail) {
26824 + queue->head = head;
26825 + if (queue->fasync)
26826 + kill_fasync(&queue->fasync, SIGIO,
26827 + POLL_IN);
26828 + wake_up_interruptible(&queue->proc_list);
26833 +static void handle_mse_event(void)
26835 + unsigned int msests = MSESTAT;
26836 + unsigned int work = 10000;
26837 + unsigned char scancode;
26839 + while (msests & MSE_STAT_RXF) {
26840 + while (msests & MSE_STAT_RXF) {
26841 + scancode = MSEDATA & 0xff;
26842 + if (!(msests & MSE_STAT_STP))
26843 + handle_mouse_event(scancode);
26844 + if (!--work) {
26845 + printk(KERN_ERR
26846 + "pc_keyb: mouse controller jammed (0x%02X).\n",
26847 + msests);
26848 + return;
26849 + /*XXX*/}
26850 + msests = MSESTAT;
26852 + work = 10000;
26856 +static void ms_wait(void)
26858 + unsigned long timeout = KBC_TIMEOUT;
26860 + do {
26861 + /*
26862 + * "handle_kbd_event()" will handle any incoming events
26863 + * while we wait - keypresses or mouse movement.
26864 + */
26865 + handle_mse_event();
26866 + if (MSESTAT & MSE_STAT_TXE)
26867 + return;
26868 + mdelay(1);
26869 + timeout--;
26871 + while (timeout);
26872 +#ifdef KBD_REPORT_TIMEOUTS
26873 + printk(KERN_WARNING "Mouse timed out[1]\n");
26874 +#endif
26877 +static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
26879 + unsigned long flags;
26881 + spin_lock_irqsave(&kbd_controller_lock, flags);
26882 + handle_mse_event();
26883 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26887 + * Check if this is a dual port controller.
26888 + */
26889 +static int __init detect_auxiliary_port(void)
26891 + unsigned long flags;
26892 + int loops = 10;
26893 + int retval = 0;
26895 + /* Check if the BIOS detected a device on the auxiliary port. */
26896 + if (aux_device_present == 0xaa)
26897 + return 1;
26899 + spin_lock_irqsave(&kbd_controller_lock, flags);
26901 + /* Put the value 0x5A in the output buffer using the "Write
26902 + * Auxiliary Device Output Buffer" command (0xD3). Poll the
26903 + * Status Register for a while to see if the value really
26904 + * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
26905 + * bit is also set to 1 in the Status Register, we assume this
26906 + * controller has an Auxiliary Port (a.k.a. Mouse Port).
26907 + */
26908 + // kb_wait();
26909 + // kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
26911 + SKPCR |= SKPCR_PMCLKEN;
26913 + MSECLKDIV = 0;
26914 + MSEPRECNT = 127;
26915 + MSECR = MSECR_ENA;
26916 + mdelay(50);
26917 + MSEDATA = 0xf4;
26918 + mdelay(50);
26920 + do {
26921 + unsigned int msests = MSESTAT;
26923 + if (msests & MSE_STAT_RXF) {
26924 + do {
26925 + msests = MSEDATA; /* dummy read */
26926 + mdelay(50);
26927 + msests = MSESTAT;
26929 + while (msests & MSE_STAT_RXF);
26930 + printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
26931 + retval = 1;
26932 + break;
26934 + mdelay(1);
26936 + while (--loops);
26937 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26939 + return retval;
26943 + * Send a byte to the mouse.
26944 + */
26945 +static void aux_write_dev(int val)
26947 + unsigned long flags;
26949 + spin_lock_irqsave(&kbd_controller_lock, flags);
26950 + // kb_wait();
26951 + // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
26952 + ms_wait();
26953 + MSEDATA = val;
26954 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26958 + * Send a byte to the mouse & handle returned ack
26959 + */
26960 +static void aux_write_ack(int val)
26962 + unsigned long flags;
26964 + spin_lock_irqsave(&kbd_controller_lock, flags);
26965 + // kb_wait();
26966 + // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
26967 + ms_wait();
26968 + MSEDATA = val;
26969 + /* we expect an ACK in response. */
26970 + mouse_reply_expected++;
26971 + ms_wait();
26972 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26975 +static unsigned char get_from_queue(void)
26977 + unsigned char result;
26978 + unsigned long flags;
26980 + spin_lock_irqsave(&kbd_controller_lock, flags);
26981 + result = queue->buf[queue->tail];
26982 + queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE - 1);
26983 + spin_unlock_irqrestore(&kbd_controller_lock, flags);
26984 + return result;
26988 +static inline int queue_empty(void)
26990 + return queue->head == queue->tail;
26993 +static int fasync_aux(int fd, struct file *filp, int on)
26995 + int retval;
26997 + retval = fasync_helper(fd, filp, on, &queue->fasync);
26998 + if (retval < 0)
26999 + return retval;
27000 + return 0;
27005 + * Random magic cookie for the aux device
27006 + */
27007 +#define AUX_DEV ((void *)queue)
27009 +static int release_aux(struct inode *inode, struct file *file)
27011 + fasync_aux(-1, file, 0);
27012 + if (--aux_count)
27013 + return 0;
27014 + // kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
27015 + // kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
27016 + aux_write_ack(AUX_DISABLE_DEV); /* Disable aux device */
27017 + MSECR &= ~MSECR_ENA;
27018 + free_irq(IRQ_MSRXINT, AUX_DEV);
27019 + return 0;
27023 + * Install interrupt handler.
27024 + * Enable auxiliary device.
27025 + */
27027 +static int open_aux(struct inode *inode, struct file *file)
27029 + if (aux_count++) {
27030 + return 0;
27032 + queue->head = queue->tail = 0; /* Flush input queue */
27033 + /* Don't enable the mouse controller until we've registered IRQ handler */
27034 + if (request_irq(IRQ_MSRXINT, mouse_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) {
27035 + aux_count--;
27036 + return -EBUSY;
27038 + MSECLKDIV = 0;
27039 + MSEPRECNT = 127;
27040 + MSECR &= ~MSECR_ENA;
27041 + mdelay(50);
27042 + MSECR = MSECR_ENA;
27043 + mdelay(50);
27044 + MSEDATA = 0xf4;
27045 + mdelay(50);
27046 + if (MSESTAT & 0x0100) {
27047 + MSESTAT = 0x0100; /* clear IRQ status */
27049 +/* kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); *//* Enable the
27050 + auxiliary port on
27051 + controller. */
27052 + aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
27053 + // kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
27055 + // send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
27057 + return 0;
27061 + * Put bytes from input queue to buffer.
27062 + */
27064 +static ssize_t
27065 +read_aux(struct file *file, char *buffer, size_t count, loff_t * ppos)
27067 + DECLARE_WAITQUEUE(wait, current);
27068 + ssize_t i = count;
27069 + unsigned char c;
27071 + if (queue_empty()) {
27072 + if (file->f_flags & O_NONBLOCK)
27073 + return -EAGAIN;
27074 + add_wait_queue(&queue->proc_list, &wait);
27075 + repeat:
27076 + set_current_state(TASK_INTERRUPTIBLE);
27077 + if (queue_empty() && !signal_pending(current)) {
27078 + schedule();
27079 + goto repeat;
27081 + current->state = TASK_RUNNING;
27082 + remove_wait_queue(&queue->proc_list, &wait);
27084 + while (i > 0 && !queue_empty()) {
27085 + c = get_from_queue();
27086 + put_user(c, buffer++);
27087 + i--;
27089 + if (count - i) {
27090 + file->f_dentry->d_inode->i_atime = CURRENT_TIME;
27091 + return count - i;
27093 + if (signal_pending(current))
27094 + return -ERESTARTSYS;
27095 + return 0;
27099 + * Write to the aux device.
27100 + */
27102 +static ssize_t
27103 +write_aux(struct file *file, const char *buffer, size_t count,
27104 + loff_t * ppos)
27106 + ssize_t retval = 0;
27108 + if (count) {
27109 + ssize_t written = 0;
27111 + if (count > 32)
27112 + count = 32; /* Limit to 32 bytes. */
27113 + do {
27114 + char c;
27115 + get_user(c, buffer++);
27116 + aux_write_dev(c);
27117 + written++;
27119 + while (--count);
27120 + retval = -EIO;
27121 + if (written) {
27122 + retval = written;
27123 + file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
27127 + return retval;
27130 +static unsigned int aux_poll(struct file *file, poll_table * wait)
27132 + poll_wait(file, &queue->proc_list, wait);
27133 + if (!queue_empty())
27134 + return POLLIN | POLLRDNORM;
27135 + return 0;
27138 +struct file_operations psaux_fops = {
27139 + read: read_aux,
27140 + write: write_aux,
27141 + poll: aux_poll,
27142 + open: open_aux,
27143 + release: release_aux,
27144 + fasync: fasync_aux,
27148 + * Initialize driver.
27149 + */
27150 +static struct miscdevice psaux_mouse = {
27151 + PSMOUSE_MINOR, "psaux", &psaux_fops
27155 +static int __init psaux_init(void)
27157 + int ret;
27159 + if (!request_mem_region(_MSECR, 512, "psaux"))
27160 + return -EBUSY;
27162 + if (!detect_auxiliary_port()) {
27163 + ret = -EIO;
27164 + goto out;
27167 + misc_register(&psaux_mouse);
27168 + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
27169 + memset(queue, 0, sizeof(*queue));
27170 + queue->head = queue->tail = 0;
27171 + init_waitqueue_head(&queue->proc_list);
27173 +#ifdef CONFIG_PSMOUSE
27174 + aux_write_ack(AUX_SET_SAMPLE);
27175 + aux_write_ack(100); /* 100 samples/sec */
27176 + aux_write_ack(AUX_SET_RES);
27177 + aux_write_ack(3); /* 8 counts per mm */
27178 + aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
27179 +#endif
27180 + ret = 0;
27182 + out:
27183 + if (ret)
27184 + release_mem_region(_MSECR, 512);
27185 + return ret;
27188 +#endif /* CONFIG_PSMOUSE */
27189 --- linux-2.4.25/drivers/char/serial.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
27190 +++ linux-2.4.25/drivers/char/serial.c 2004-03-31 17:15:09.000000000 +0200
27191 @@ -4527,6 +4527,14 @@
27195 + * If there is exactly one port of 8 bytes, use it.
27196 + */
27197 + if (num_port == 1 && pci_resource_len(dev, first_port) == 8) {
27198 + board->flags = first_port;
27199 + return 0;
27202 + /*
27203 * If there is 1 or 0 iomem regions, and exactly one port, use
27204 * it.
27206 --- linux-2.4.25/drivers/char/serial_21285.c~2.4.25-vrs2.patch
27207 +++ linux-2.4.25/drivers/char/serial_21285.c
27209 - * linux/drivers/char/serial_21285.c
27211 - * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
27213 - * Based on drivers/char/serial.c
27214 - */
27216 -#include <linux/config.h>
27217 -#include <linux/module.h>
27218 -#include <linux/errno.h>
27219 -#include <linux/signal.h>
27220 -#include <linux/sched.h>
27221 -#include <linux/interrupt.h>
27222 -#include <linux/tty.h>
27223 -#include <linux/tty_flip.h>
27224 -#include <linux/serial.h>
27225 -#include <linux/major.h>
27226 -#include <linux/ptrace.h>
27227 -#include <linux/ioport.h>
27228 -#include <linux/mm.h>
27229 -#include <linux/slab.h>
27230 -#include <linux/init.h>
27231 -#include <linux/console.h>
27233 -#include <asm/io.h>
27234 -#include <asm/irq.h>
27235 -#include <asm/uaccess.h>
27236 -#include <asm/dec21285.h>
27237 -#include <asm/hardware.h>
27239 -#define BAUD_BASE (mem_fclk_21285/64)
27241 -#define SERIAL_21285_NAME "ttyFB"
27242 -#define SERIAL_21285_MAJOR 204
27243 -#define SERIAL_21285_MINOR 4
27245 -#define SERIAL_21285_AUXNAME "cuafb"
27246 -#define SERIAL_21285_AUXMAJOR 205
27247 -#define SERIAL_21285_AUXMINOR 4
27249 -static struct tty_driver rs285_driver, callout_driver;
27250 -static int rs285_refcount;
27251 -static struct tty_struct *rs285_table[1];
27253 -static struct termios *rs285_termios[1];
27254 -static struct termios *rs285_termios_locked[1];
27256 -static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
27257 -static struct tty_struct *rs285_tty;
27258 -static int rs285_use_count;
27260 -static int rs285_write_room(struct tty_struct *tty)
27262 - return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
27265 -static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
27267 - if (!rs285_tty) {
27268 - disable_irq(IRQ_CONRX);
27269 - return;
27271 - while (!(*CSR_UARTFLG & 0x10)) {
27272 - int ch, flag;
27273 - ch = *CSR_UARTDR;
27274 - flag = *CSR_RXSTAT;
27275 - if (flag & 4)
27276 - tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
27277 - if (flag & 2)
27278 - flag = TTY_PARITY;
27279 - else if (flag & 1)
27280 - flag = TTY_FRAME;
27281 - tty_insert_flip_char(rs285_tty, ch, flag);
27283 - tty_flip_buffer_push(rs285_tty);
27286 -static void rs285_send_xchar(struct tty_struct *tty, char ch)
27288 - x_char = ch;
27289 - enable_irq(IRQ_CONTX);
27292 -static void rs285_throttle(struct tty_struct *tty)
27294 - if (I_IXOFF(tty))
27295 - rs285_send_xchar(tty, STOP_CHAR(tty));
27298 -static void rs285_unthrottle(struct tty_struct *tty)
27300 - if (I_IXOFF(tty)) {
27301 - if (x_char)
27302 - x_char = 0;
27303 - else
27304 - rs285_send_xchar(tty, START_CHAR(tty));
27308 -static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
27310 - while (!(*CSR_UARTFLG & 0x20)) {
27311 - if (x_char) {
27312 - *CSR_UARTDR = x_char;
27313 - x_char = 0;
27314 - continue;
27316 - if (putp == getp) {
27317 - disable_irq(IRQ_CONTX);
27318 - break;
27320 - *CSR_UARTDR = *getp;
27321 - if (++getp >= wbuf + sizeof(wbuf))
27322 - getp = wbuf;
27324 - if (rs285_tty)
27325 - wake_up_interruptible(&rs285_tty->write_wait);
27328 -static inline int rs285_xmit(int ch)
27330 - if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
27331 - return 0;
27332 - *putp = ch;
27333 - if (++putp >= wbuf + sizeof(wbuf))
27334 - putp = wbuf;
27335 - enable_irq(IRQ_CONTX);
27336 - return 1;
27339 -static int rs285_write(struct tty_struct *tty, int from_user,
27340 - const u_char * buf, int count)
27342 - int i;
27344 - if (from_user && verify_area(VERIFY_READ, buf, count))
27345 - return -EINVAL;
27347 - for (i = 0; i < count; i++) {
27348 - char ch;
27349 - if (from_user)
27350 - __get_user(ch, buf + i);
27351 - else
27352 - ch = buf[i];
27353 - if (!rs285_xmit(ch))
27354 - break;
27356 - return i;
27359 -static void rs285_put_char(struct tty_struct *tty, u_char ch)
27361 - rs285_xmit(ch);
27364 -static int rs285_chars_in_buffer(struct tty_struct *tty)
27366 - return sizeof(wbuf) - rs285_write_room(tty);
27369 -static void rs285_flush_buffer(struct tty_struct *tty)
27371 - disable_irq(IRQ_CONTX);
27372 - putp = getp = wbuf;
27373 - if (x_char)
27374 - enable_irq(IRQ_CONTX);
27377 -static inline void rs285_set_cflag(int cflag)
27379 - int h_lcr, baud, quot;
27381 - switch (cflag & CSIZE) {
27382 - case CS5:
27383 - h_lcr = 0x10;
27384 - break;
27385 - case CS6:
27386 - h_lcr = 0x30;
27387 - break;
27388 - case CS7:
27389 - h_lcr = 0x50;
27390 - break;
27391 - default: /* CS8 */
27392 - h_lcr = 0x70;
27393 - break;
27396 - if (cflag & CSTOPB)
27397 - h_lcr |= 0x08;
27398 - if (cflag & PARENB)
27399 - h_lcr |= 0x02;
27400 - if (!(cflag & PARODD))
27401 - h_lcr |= 0x04;
27403 - switch (cflag & CBAUD) {
27404 - case B200: baud = 200; break;
27405 - case B300: baud = 300; break;
27406 - case B1200: baud = 1200; break;
27407 - case B1800: baud = 1800; break;
27408 - case B2400: baud = 2400; break;
27409 - case B4800: baud = 4800; break;
27410 - default:
27411 - case B9600: baud = 9600; break;
27412 - case B19200: baud = 19200; break;
27413 - case B38400: baud = 38400; break;
27414 - case B57600: baud = 57600; break;
27415 - case B115200: baud = 115200; break;
27418 - /*
27419 - * The documented expression for selecting the divisor is:
27420 - * BAUD_BASE / baud - 1
27421 - * However, typically BAUD_BASE is not divisible by baud, so
27422 - * we want to select the divisor that gives us the minimum
27423 - * error. Therefore, we want:
27424 - * int(BAUD_BASE / baud - 0.5) ->
27425 - * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
27426 - * int((BAUD_BASE - (baud >> 1)) / baud)
27427 - */
27428 - quot = (BAUD_BASE - (baud >> 1)) / baud;
27430 - *CSR_UARTCON = 0;
27431 - *CSR_L_UBRLCR = quot & 0xff;
27432 - *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
27433 - *CSR_H_UBRLCR = h_lcr;
27434 - *CSR_UARTCON = 1;
27437 -static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
27439 - if (old && tty->termios->c_cflag == old->c_cflag)
27440 - return;
27441 - rs285_set_cflag(tty->termios->c_cflag);
27445 -static void rs285_stop(struct tty_struct *tty)
27447 - disable_irq(IRQ_CONTX);
27450 -static void rs285_start(struct tty_struct *tty)
27452 - enable_irq(IRQ_CONTX);
27455 -static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
27457 - int orig_jiffies = jiffies;
27458 - while (*CSR_UARTFLG & 8) {
27459 - current->state = TASK_INTERRUPTIBLE;
27460 - schedule_timeout(1);
27461 - if (signal_pending(current))
27462 - break;
27463 - if (timeout && time_after(jiffies, orig_jiffies + timeout))
27464 - break;
27466 - current->state = TASK_RUNNING;
27469 -static int rs285_open(struct tty_struct *tty, struct file *filp)
27471 - int line;
27473 - MOD_INC_USE_COUNT;
27474 - line = MINOR(tty->device) - tty->driver.minor_start;
27475 - if (line) {
27476 - MOD_DEC_USE_COUNT;
27477 - return -ENODEV;
27480 - tty->driver_data = NULL;
27481 - if (!rs285_tty)
27482 - rs285_tty = tty;
27484 - enable_irq(IRQ_CONRX);
27485 - rs285_use_count++;
27486 - return 0;
27489 -static void rs285_close(struct tty_struct *tty, struct file *filp)
27491 - if (!--rs285_use_count) {
27492 - rs285_wait_until_sent(tty, 0);
27493 - disable_irq(IRQ_CONRX);
27494 - disable_irq(IRQ_CONTX);
27495 - rs285_tty = NULL;
27497 - MOD_DEC_USE_COUNT;
27500 -static int __init rs285_init(void)
27502 - int baud = B9600;
27504 - if (machine_is_personal_server())
27505 - baud = B57600;
27507 - rs285_driver.magic = TTY_DRIVER_MAGIC;
27508 - rs285_driver.driver_name = "serial_21285";
27509 - rs285_driver.name = SERIAL_21285_NAME;
27510 - rs285_driver.major = SERIAL_21285_MAJOR;
27511 - rs285_driver.minor_start = SERIAL_21285_MINOR;
27512 - rs285_driver.num = 1;
27513 - rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
27514 - rs285_driver.subtype = SERIAL_TYPE_NORMAL;
27515 - rs285_driver.init_termios = tty_std_termios;
27516 - rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
27517 - rs285_driver.flags = TTY_DRIVER_REAL_RAW;
27518 - rs285_driver.refcount = &rs285_refcount;
27519 - rs285_driver.table = rs285_table;
27520 - rs285_driver.termios = rs285_termios;
27521 - rs285_driver.termios_locked = rs285_termios_locked;
27523 - rs285_driver.open = rs285_open;
27524 - rs285_driver.close = rs285_close;
27525 - rs285_driver.write = rs285_write;
27526 - rs285_driver.put_char = rs285_put_char;
27527 - rs285_driver.write_room = rs285_write_room;
27528 - rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
27529 - rs285_driver.flush_buffer = rs285_flush_buffer;
27530 - rs285_driver.throttle = rs285_throttle;
27531 - rs285_driver.unthrottle = rs285_unthrottle;
27532 - rs285_driver.send_xchar = rs285_send_xchar;
27533 - rs285_driver.set_termios = rs285_set_termios;
27534 - rs285_driver.stop = rs285_stop;
27535 - rs285_driver.start = rs285_start;
27536 - rs285_driver.wait_until_sent = rs285_wait_until_sent;
27538 - callout_driver = rs285_driver;
27539 - callout_driver.name = SERIAL_21285_AUXNAME;
27540 - callout_driver.major = SERIAL_21285_AUXMAJOR;
27541 - callout_driver.subtype = SERIAL_TYPE_CALLOUT;
27543 - if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
27544 - panic("Couldn't get rx irq for rs285");
27546 - if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
27547 - panic("Couldn't get tx irq for rs285");
27549 - if (tty_register_driver(&rs285_driver))
27550 - printk(KERN_ERR "Couldn't register 21285 serial driver\n");
27551 - if (tty_register_driver(&callout_driver))
27552 - printk(KERN_ERR "Couldn't register 21285 callout driver\n");
27554 - return 0;
27557 -static void __exit rs285_fini(void)
27559 - unsigned long flags;
27560 - int ret;
27562 - save_flags(flags);
27563 - cli();
27564 - ret = tty_unregister_driver(&callout_driver);
27565 - if (ret)
27566 - printk(KERN_ERR "Unable to unregister 21285 callout driver "
27567 - "(%d)\n", ret);
27568 - ret = tty_unregister_driver(&rs285_driver);
27569 - if (ret)
27570 - printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
27571 - ret);
27572 - free_irq(IRQ_CONTX, NULL);
27573 - free_irq(IRQ_CONRX, NULL);
27574 - restore_flags(flags);
27577 -module_init(rs285_init);
27578 -module_exit(rs285_fini);
27580 -#ifdef CONFIG_SERIAL_21285_CONSOLE
27581 -/************** console driver *****************/
27583 -static void rs285_console_write(struct console *co, const char *s, u_int count)
27585 - int i;
27587 - disable_irq(IRQ_CONTX);
27588 - for (i = 0; i < count; i++) {
27589 - while (*CSR_UARTFLG & 0x20);
27590 - *CSR_UARTDR = s[i];
27591 - if (s[i] == '\n') {
27592 - while (*CSR_UARTFLG & 0x20);
27593 - *CSR_UARTDR = '\r';
27596 - enable_irq(IRQ_CONTX);
27599 -static kdev_t rs285_console_device(struct console *c)
27601 - return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
27604 -static int __init rs285_console_setup(struct console *co, char *options)
27606 - int baud = 9600;
27607 - int bits = 8;
27608 - int parity = 'n';
27609 - int cflag = CREAD | HUPCL | CLOCAL;
27611 - if (machine_is_personal_server())
27612 - baud = 57600;
27614 - if (options) {
27615 - char *s = options;
27616 - baud = simple_strtoul(options, NULL, 10);
27617 - while (*s >= '0' && *s <= '9')
27618 - s++;
27619 - if (*s)
27620 - parity = *s++;
27621 - if (*s)
27622 - bits = *s - '0';
27625 - /*
27626 - * Now construct a cflag setting.
27627 - */
27628 - switch (baud) {
27629 - case 1200:
27630 - cflag |= B1200;
27631 - break;
27632 - case 2400:
27633 - cflag |= B2400;
27634 - break;
27635 - case 4800:
27636 - cflag |= B4800;
27637 - break;
27638 - case 9600:
27639 - cflag |= B9600;
27640 - break;
27641 - case 19200:
27642 - cflag |= B19200;
27643 - break;
27644 - case 38400:
27645 - cflag |= B38400;
27646 - break;
27647 - case 57600:
27648 - cflag |= B57600;
27649 - break;
27650 - case 115200:
27651 - cflag |= B115200;
27652 - break;
27653 - default:
27654 - cflag |= B9600;
27655 - break;
27657 - switch (bits) {
27658 - case 7:
27659 - cflag |= CS7;
27660 - break;
27661 - default:
27662 - cflag |= CS8;
27663 - break;
27665 - switch (parity) {
27666 - case 'o':
27667 - case 'O':
27668 - cflag |= PARODD;
27669 - break;
27670 - case 'e':
27671 - case 'E':
27672 - cflag |= PARENB;
27673 - break;
27675 - co->cflag = cflag;
27676 - rs285_set_cflag(cflag);
27677 - rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
27678 - if (options)
27679 - rs285_console_write(NULL, options, strlen(options));
27680 - else
27681 - rs285_console_write(NULL, "no options", 10);
27682 - rs285_console_write(NULL, "\n", 1);
27684 - return 0;
27687 -static struct console rs285_cons =
27689 - name: SERIAL_21285_NAME,
27690 - write: rs285_console_write,
27691 - device: rs285_console_device,
27692 - setup: rs285_console_setup,
27693 - flags: CON_PRINTBUFFER,
27694 - index: -1,
27697 -void __init rs285_console_init(void)
27699 - register_console(&rs285_cons);
27702 -#endif /* CONFIG_SERIAL_21285_CONSOLE */
27704 -MODULE_LICENSE("GPL");
27705 -EXPORT_NO_SYMBOLS;
27706 --- linux-2.4.25/drivers/char/serial_amba.c~2.4.25-vrs2.patch
27707 +++ linux-2.4.25/drivers/char/serial_amba.c
27709 - * linux/drivers/char/serial_amba.c
27711 - * Driver for AMBA serial ports
27713 - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
27715 - * Copyright 1999 ARM Limited
27716 - * Copyright (C) 2000 Deep Blue Solutions Ltd.
27718 - * This program is free software; you can redistribute it and/or modify
27719 - * it under the terms of the GNU General Public License as published by
27720 - * the Free Software Foundation; either version 2 of the License, or
27721 - * (at your option) any later version.
27723 - * This program is distributed in the hope that it will be useful,
27724 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
27725 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27726 - * GNU General Public License for more details.
27728 - * You should have received a copy of the GNU General Public License
27729 - * along with this program; if not, write to the Free Software
27730 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27733 - * This is a generic driver for ARM AMBA-type serial ports. They
27734 - * have a lot of 16550-like features, but are not register compatable.
27735 - * Note that although they do have CTS, DCD and DSR inputs, they do
27736 - * not have an RI input, nor do they have DTR or RTS outputs. If
27737 - * required, these have to be supplied via some other means (eg, GPIO)
27738 - * and hooked into this driver.
27740 - * This could very easily become a generic serial driver for dumb UARTs
27741 - * (eg, {82,16x}50, 21285, SA1100).
27742 - */
27744 -#include <linux/config.h>
27745 -#include <linux/module.h>
27746 -#include <linux/errno.h>
27747 -#include <linux/signal.h>
27748 -#include <linux/sched.h>
27749 -#include <linux/interrupt.h>
27750 -#include <linux/tty.h>
27751 -#include <linux/tty_flip.h>
27752 -#include <linux/major.h>
27753 -#include <linux/string.h>
27754 -#include <linux/fcntl.h>
27755 -#include <linux/ptrace.h>
27756 -#include <linux/ioport.h>
27757 -#include <linux/mm.h>
27758 -#include <linux/slab.h>
27759 -#include <linux/init.h>
27760 -#include <linux/circ_buf.h>
27761 -#include <linux/serial.h>
27762 -#include <linux/console.h>
27763 -#include <linux/sysrq.h>
27765 -#include <asm/system.h>
27766 -#include <asm/io.h>
27767 -#include <asm/irq.h>
27768 -#include <asm/uaccess.h>
27769 -#include <asm/bitops.h>
27771 -#include <asm/hardware/serial_amba.h>
27773 -#define SERIAL_AMBA_NAME "ttyAM"
27774 -#define SERIAL_AMBA_MAJOR 204
27775 -#define SERIAL_AMBA_MINOR 16
27776 -#define SERIAL_AMBA_NR 2
27778 -#define CALLOUT_AMBA_NAME "cuaam"
27779 -#define CALLOUT_AMBA_MAJOR 205
27780 -#define CALLOUT_AMBA_MINOR 16
27781 -#define CALLOUT_AMBA_NR SERIAL_AMBA_NR
27783 -#ifndef TRUE
27784 -#define TRUE 1
27785 -#endif
27786 -#ifndef FALSE
27787 -#define FALSE 0
27788 -#endif
27790 -#define DEBUG 0
27791 -#define DEBUG_LEDS 0
27793 -#if DEBUG_LEDS
27794 -extern int get_leds(void);
27795 -extern int set_leds(int);
27796 -#endif
27799 - * Access routines for the AMBA UARTs
27800 - */
27801 -#define UART_GET_INT_STATUS(p) IO_READ((p)->uart_base + AMBA_UARTIIR)
27802 -#define UART_GET_FR(p) IO_READ((p)->uart_base + AMBA_UARTFR)
27803 -#define UART_GET_CHAR(p) IO_READ((p)->uart_base + AMBA_UARTDR)
27804 -#define UART_PUT_CHAR(p, c) IO_WRITE((p)->uart_base + AMBA_UARTDR, (c))
27805 -#define UART_GET_RSR(p) IO_READ((p)->uart_base + AMBA_UARTRSR)
27806 -#define UART_GET_CR(p) IO_READ((p)->uart_base + AMBA_UARTCR)
27807 -#define UART_PUT_CR(p,c) IO_WRITE((p)->uart_base + AMBA_UARTCR, (c))
27808 -#define UART_GET_LCRL(p) IO_READ((p)->uart_base + AMBA_UARTLCR_L)
27809 -#define UART_PUT_LCRL(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c))
27810 -#define UART_GET_LCRM(p) IO_READ((p)->uart_base + AMBA_UARTLCR_M)
27811 -#define UART_PUT_LCRM(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c))
27812 -#define UART_GET_LCRH(p) IO_READ((p)->uart_base + AMBA_UARTLCR_H)
27813 -#define UART_PUT_LCRH(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c))
27814 -#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
27815 -#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
27816 -#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
27818 -#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE)
27819 -#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS)
27822 - * Things needed by tty driver
27823 - */
27824 -static struct tty_driver ambanormal_driver, ambacallout_driver;
27825 -static int ambauart_refcount;
27826 -static struct tty_struct *ambauart_table[SERIAL_AMBA_NR];
27827 -static struct termios *ambauart_termios[SERIAL_AMBA_NR];
27828 -static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR];
27830 -#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
27831 -#define SUPPORT_SYSRQ
27832 -#endif
27835 - * Things needed internally to this driver
27836 - */
27839 - * tmp_buf is used as a temporary buffer by serial_write. We need to
27840 - * lock it in case the copy_from_user blocks while swapping in a page,
27841 - * and some other program tries to do a serial write at the same time.
27842 - * Since the lock will only come under contention when the system is
27843 - * swapping and available memory is low, it makes sense to share one
27844 - * buffer across all the serial ports, since it significantly saves
27845 - * memory if large numbers of serial ports are open.
27846 - */
27847 -static u_char *tmp_buf;
27848 -static DECLARE_MUTEX(tmp_buf_sem);
27850 -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
27852 -/* number of characters left in xmit buffer before we ask for more */
27853 -#define WAKEUP_CHARS 256
27854 -#define AMBA_ISR_PASS_LIMIT 256
27856 -#define EVT_WRITE_WAKEUP 0
27858 -struct amba_icount {
27859 - __u32 cts;
27860 - __u32 dsr;
27861 - __u32 rng;
27862 - __u32 dcd;
27863 - __u32 rx;
27864 - __u32 tx;
27865 - __u32 frame;
27866 - __u32 overrun;
27867 - __u32 parity;
27868 - __u32 brk;
27869 - __u32 buf_overrun;
27873 - * Static information about the port
27874 - */
27875 -struct amba_port {
27876 - unsigned int uart_base;
27877 - unsigned int irq;
27878 - unsigned int uartclk;
27879 - unsigned int fifosize;
27880 - unsigned int tiocm_support;
27881 - void (*set_mctrl)(struct amba_port *, u_int mctrl);
27882 -};
27885 - * This is the state information which is persistent across opens
27886 - */
27887 -struct amba_state {
27888 - struct amba_icount icount;
27889 - unsigned int line;
27890 - unsigned int close_delay;
27891 - unsigned int closing_wait;
27892 - unsigned int custom_divisor;
27893 - unsigned int flags;
27894 - struct termios normal_termios;
27895 - struct termios callout_termios;
27897 - int count;
27898 - struct amba_info *info;
27901 -#define AMBA_XMIT_SIZE 1024
27903 - * This is the state information which is only valid when the port is open.
27904 - */
27905 -struct amba_info {
27906 - struct amba_port *port;
27907 - struct amba_state *state;
27908 - struct tty_struct *tty;
27909 - unsigned char x_char;
27910 - unsigned char old_status;
27911 - unsigned char read_status_mask;
27912 - unsigned char ignore_status_mask;
27913 - struct circ_buf xmit;
27914 - unsigned int flags;
27915 -#ifdef SUPPORT_SYSRQ
27916 - unsigned long sysrq;
27917 -#endif
27919 - unsigned int event;
27920 - unsigned int timeout;
27921 - unsigned int lcr_h;
27922 - unsigned int mctrl;
27923 - int blocked_open;
27924 - pid_t session;
27925 - pid_t pgrp;
27927 - struct tasklet_struct tlet;
27929 - wait_queue_head_t open_wait;
27930 - wait_queue_head_t close_wait;
27931 - wait_queue_head_t delta_msr_wait;
27934 -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
27935 -static struct console ambauart_cons;
27936 -#endif
27937 -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios);
27938 -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout);
27940 -#if 1 //def CONFIG_SERIAL_INTEGRATOR
27941 -static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl)
27945 -static struct amba_port amba_ports[SERIAL_AMBA_NR] = {
27947 - uart_base: IO_ADDRESS(INTEGRATOR_UART0_BASE),
27948 - irq: IRQ_UARTINT0,
27949 - uartclk: 14745600,
27950 - fifosize: 8,
27951 - set_mctrl: amba_set_mctrl_null,
27952 - },
27954 - uart_base: IO_ADDRESS(INTEGRATOR_UART1_BASE),
27955 - irq: IRQ_UARTINT1,
27956 - uartclk: 14745600,
27957 - fifosize: 8,
27958 - set_mctrl: amba_set_mctrl_null,
27961 -#endif
27963 -static struct amba_state amba_state[SERIAL_AMBA_NR];
27965 -static void ambauart_enable_rx_interrupt(struct amba_info *info)
27967 - unsigned int cr;
27969 - cr = UART_GET_CR(info->port);
27970 - cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE;
27971 - UART_PUT_CR(info->port, cr);
27974 -static void ambauart_disable_rx_interrupt(struct amba_info *info)
27976 - unsigned int cr;
27978 - cr = UART_GET_CR(info->port);
27979 - cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
27980 - UART_PUT_CR(info->port, cr);
27983 -static void ambauart_enable_tx_interrupt(struct amba_info *info)
27985 - unsigned int cr;
27987 - cr = UART_GET_CR(info->port);
27988 - cr |= AMBA_UARTCR_TIE;
27989 - UART_PUT_CR(info->port, cr);
27992 -static void ambauart_disable_tx_interrupt(struct amba_info *info)
27994 - unsigned int cr;
27996 - cr = UART_GET_CR(info->port);
27997 - cr &= ~AMBA_UARTCR_TIE;
27998 - UART_PUT_CR(info->port, cr);
28001 -static void ambauart_stop(struct tty_struct *tty)
28003 - struct amba_info *info = tty->driver_data;
28004 - unsigned long flags;
28006 - save_flags(flags); cli();
28007 - ambauart_disable_tx_interrupt(info);
28008 - restore_flags(flags);
28011 -static void ambauart_start(struct tty_struct *tty)
28013 - struct amba_info *info = tty->driver_data;
28014 - unsigned long flags;
28016 - save_flags(flags); cli();
28017 - if (info->xmit.head != info->xmit.tail
28018 - && info->xmit.buf)
28019 - ambauart_enable_tx_interrupt(info);
28020 - restore_flags(flags);
28025 - * This routine is used by the interrupt handler to schedule
28026 - * processing in the software interrupt portion of the driver.
28027 - */
28028 -static void ambauart_event(struct amba_info *info, int event)
28030 - info->event |= 1 << event;
28031 - tasklet_schedule(&info->tlet);
28034 -static void
28035 -#ifdef SUPPORT_SYSRQ
28036 -ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs)
28037 -#else
28038 -ambauart_rx_chars(struct amba_info *info)
28039 -#endif
28041 - struct tty_struct *tty = info->tty;
28042 - unsigned int status, ch, rsr, flg, ignored = 0;
28043 - struct amba_icount *icount = &info->state->icount;
28044 - struct amba_port *port = info->port;
28046 - status = UART_GET_FR(port);
28047 - while (UART_RX_DATA(status)) {
28048 - ch = UART_GET_CHAR(port);
28050 - if (tty->flip.count >= TTY_FLIPBUF_SIZE)
28051 - goto ignore_char;
28052 - icount->rx++;
28054 - flg = TTY_NORMAL;
28056 - /*
28057 - * Note that the error handling code is
28058 - * out of the main execution path
28059 - */
28060 - rsr = UART_GET_RSR(port);
28061 - if (rsr & AMBA_UARTRSR_ANY)
28062 - goto handle_error;
28063 -#ifdef SUPPORT_SYSRQ
28064 - if (info->sysrq) {
28065 - if (ch && time_before(jiffies, info->sysrq)) {
28066 - handle_sysrq(ch, regs, NULL, NULL);
28067 - info->sysrq = 0;
28068 - goto ignore_char;
28070 - info->sysrq = 0;
28072 -#endif
28073 - error_return:
28074 - *tty->flip.flag_buf_ptr++ = flg;
28075 - *tty->flip.char_buf_ptr++ = ch;
28076 - tty->flip.count++;
28077 - ignore_char:
28078 - status = UART_GET_FR(port);
28080 -out:
28081 - tty_flip_buffer_push(tty);
28082 - return;
28084 -handle_error:
28085 - if (rsr & AMBA_UARTRSR_BE) {
28086 - rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
28087 - icount->brk++;
28089 -#ifdef SUPPORT_SYSRQ
28090 - if (info->state->line == ambauart_cons.index) {
28091 - if (!info->sysrq) {
28092 - info->sysrq = jiffies + HZ*5;
28093 - goto ignore_char;
28096 -#endif
28097 - } else if (rsr & AMBA_UARTRSR_PE)
28098 - icount->parity++;
28099 - else if (rsr & AMBA_UARTRSR_FE)
28100 - icount->frame++;
28101 - if (rsr & AMBA_UARTRSR_OE)
28102 - icount->overrun++;
28104 - if (rsr & info->ignore_status_mask) {
28105 - if (++ignored > 100)
28106 - goto out;
28107 - goto ignore_char;
28109 - rsr &= info->read_status_mask;
28111 - if (rsr & AMBA_UARTRSR_BE)
28112 - flg = TTY_BREAK;
28113 - else if (rsr & AMBA_UARTRSR_PE)
28114 - flg = TTY_PARITY;
28115 - else if (rsr & AMBA_UARTRSR_FE)
28116 - flg = TTY_FRAME;
28118 - if (rsr & AMBA_UARTRSR_OE) {
28119 - /*
28120 - * CHECK: does overrun affect the current character?
28121 - * ASSUMPTION: it does not.
28122 - */
28123 - *tty->flip.flag_buf_ptr++ = flg;
28124 - *tty->flip.char_buf_ptr++ = ch;
28125 - tty->flip.count++;
28126 - if (tty->flip.count >= TTY_FLIPBUF_SIZE)
28127 - goto ignore_char;
28128 - ch = 0;
28129 - flg = TTY_OVERRUN;
28131 -#ifdef SUPPORT_SYSRQ
28132 - info->sysrq = 0;
28133 -#endif
28134 - goto error_return;
28137 -static void ambauart_tx_chars(struct amba_info *info)
28139 - struct amba_port *port = info->port;
28140 - int count;
28142 - if (info->x_char) {
28143 - UART_PUT_CHAR(port, info->x_char);
28144 - info->state->icount.tx++;
28145 - info->x_char = 0;
28146 - return;
28148 - if (info->xmit.head == info->xmit.tail
28149 - || info->tty->stopped
28150 - || info->tty->hw_stopped) {
28151 - ambauart_disable_tx_interrupt(info);
28152 - return;
28155 - count = port->fifosize;
28156 - do {
28157 - UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
28158 - info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1);
28159 - info->state->icount.tx++;
28160 - if (info->xmit.head == info->xmit.tail)
28161 - break;
28162 - } while (--count > 0);
28164 - if (CIRC_CNT(info->xmit.head,
28165 - info->xmit.tail,
28166 - AMBA_XMIT_SIZE) < WAKEUP_CHARS)
28167 - ambauart_event(info, EVT_WRITE_WAKEUP);
28169 - if (info->xmit.head == info->xmit.tail) {
28170 - ambauart_disable_tx_interrupt(info);
28174 -static void ambauart_modem_status(struct amba_info *info)
28176 - unsigned int status, delta;
28177 - struct amba_icount *icount = &info->state->icount;
28179 - status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
28181 - delta = status ^ info->old_status;
28182 - info->old_status = status;
28184 - if (!delta)
28185 - return;
28187 - if (delta & AMBA_UARTFR_DCD) {
28188 - icount->dcd++;
28189 -#ifdef CONFIG_HARD_PPS
28190 - if ((info->flags & ASYNC_HARDPPS_CD) &&
28191 - (status & AMBA_UARTFR_DCD)
28192 - hardpps();
28193 -#endif
28194 - if (info->flags & ASYNC_CHECK_CD) {
28195 - if (status & AMBA_UARTFR_DCD)
28196 - wake_up_interruptible(&info->open_wait);
28197 - else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
28198 - (info->flags & ASYNC_CALLOUT_NOHUP))) {
28199 - if (info->tty)
28200 - tty_hangup(info->tty);
28205 - if (delta & AMBA_UARTFR_DSR)
28206 - icount->dsr++;
28208 - if (delta & AMBA_UARTFR_CTS) {
28209 - icount->cts++;
28211 - if (info->flags & ASYNC_CTS_FLOW) {
28212 - status &= AMBA_UARTFR_CTS;
28214 - if (info->tty->hw_stopped) {
28215 - if (status) {
28216 - info->tty->hw_stopped = 0;
28217 - ambauart_enable_tx_interrupt(info);
28218 - ambauart_event(info, EVT_WRITE_WAKEUP);
28220 - } else {
28221 - if (!status) {
28222 - info->tty->hw_stopped = 1;
28223 - ambauart_disable_tx_interrupt(info);
28228 - wake_up_interruptible(&info->delta_msr_wait);
28232 -static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
28234 - struct amba_info *info = dev_id;
28235 - unsigned int status, pass_counter = 0;
28237 -#if DEBUG_LEDS
28238 - // tell the world
28239 - set_leds(get_leds() | RED_LED);
28240 -#endif
28242 - status = UART_GET_INT_STATUS(info->port);
28243 - do {
28244 - /*
28245 - * FIXME: what about clearing the interrupts?
28246 - */
28248 - if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
28249 -#ifdef SUPPORT_SYSRQ
28250 - ambauart_rx_chars(info, regs);
28251 -#else
28252 - ambauart_rx_chars(info);
28253 -#endif
28254 - if (status & AMBA_UARTIIR_TIS)
28255 - ambauart_tx_chars(info);
28256 - if (status & AMBA_UARTIIR_MIS)
28257 - ambauart_modem_status(info);
28258 - if (pass_counter++ > AMBA_ISR_PASS_LIMIT)
28259 - break;
28261 - status = UART_GET_INT_STATUS(info->port);
28262 - } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS));
28264 -#if DEBUG_LEDS
28265 - // tell the world
28266 - set_leds(get_leds() & ~RED_LED);
28267 -#endif
28270 -static void ambauart_tasklet_action(unsigned long data)
28272 - struct amba_info *info = (struct amba_info *)data;
28273 - struct tty_struct *tty;
28275 - tty = info->tty;
28276 - if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
28277 - return;
28279 - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
28280 - tty->ldisc.write_wakeup)
28281 - (tty->ldisc.write_wakeup)(tty);
28282 - wake_up_interruptible(&tty->write_wait);
28285 -static int ambauart_startup(struct amba_info *info)
28287 - unsigned long flags;
28288 - unsigned long page;
28289 - int retval = 0;
28291 - page = get_zeroed_page(GFP_KERNEL);
28292 - if (!page)
28293 - return -ENOMEM;
28295 - save_flags(flags); cli();
28297 - if (info->flags & ASYNC_INITIALIZED) {
28298 - free_page(page);
28299 - goto errout;
28302 - if (info->xmit.buf)
28303 - free_page(page);
28304 - else
28305 - info->xmit.buf = (unsigned char *) page;
28307 - /*
28308 - * Allocate the IRQ
28309 - */
28310 - retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info);
28311 - if (retval) {
28312 - if (capable(CAP_SYS_ADMIN)) {
28313 - if (info->tty)
28314 - set_bit(TTY_IO_ERROR, &info->tty->flags);
28315 - retval = 0;
28317 - goto errout;
28320 - info->mctrl = 0;
28321 - if (info->tty->termios->c_cflag & CBAUD)
28322 - info->mctrl = TIOCM_RTS | TIOCM_DTR;
28323 - info->port->set_mctrl(info->port, info->mctrl);
28325 - /*
28326 - * initialise the old status of the modem signals
28327 - */
28328 - info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
28330 - /*
28331 - * Finally, enable interrupts
28332 - */
28333 - ambauart_enable_rx_interrupt(info);
28335 - if (info->tty)
28336 - clear_bit(TTY_IO_ERROR, &info->tty->flags);
28337 - info->xmit.head = info->xmit.tail = 0;
28339 - /*
28340 - * Set up the tty->alt_speed kludge
28341 - */
28342 - if (info->tty) {
28343 - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
28344 - info->tty->alt_speed = 57600;
28345 - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
28346 - info->tty->alt_speed = 115200;
28347 - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
28348 - info->tty->alt_speed = 230400;
28349 - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
28350 - info->tty->alt_speed = 460800;
28353 - /*
28354 - * and set the speed of the serial port
28355 - */
28356 - ambauart_change_speed(info, 0);
28358 - info->flags |= ASYNC_INITIALIZED;
28359 - restore_flags(flags);
28360 - return 0;
28362 -errout:
28363 - restore_flags(flags);
28364 - return retval;
28368 - * This routine will shutdown a serial port; interrupts are disabled, and
28369 - * DTR is dropped if the hangup on close termio flag is on.
28370 - */
28371 -static void ambauart_shutdown(struct amba_info *info)
28373 - unsigned long flags;
28375 - if (!(info->flags & ASYNC_INITIALIZED))
28376 - return;
28378 - save_flags(flags); cli(); /* Disable interrupts */
28380 - /*
28381 - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
28382 - * here so the queue might never be woken up
28383 - */
28384 - wake_up_interruptible(&info->delta_msr_wait);
28386 - /*
28387 - * Free the IRQ
28388 - */
28389 - free_irq(info->port->irq, info);
28391 - if (info->xmit.buf) {
28392 - unsigned long pg = (unsigned long) info->xmit.buf;
28393 - info->xmit.buf = NULL;
28394 - free_page(pg);
28397 - /*
28398 - * disable all interrupts, disable the port
28399 - */
28400 - UART_PUT_CR(info->port, 0);
28402 - /* disable break condition and fifos */
28403 - UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) &
28404 - ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
28406 - if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
28407 - info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
28408 - info->port->set_mctrl(info->port, info->mctrl);
28410 - /* kill off our tasklet */
28411 - tasklet_kill(&info->tlet);
28412 - if (info->tty)
28413 - set_bit(TTY_IO_ERROR, &info->tty->flags);
28415 - info->flags &= ~ASYNC_INITIALIZED;
28416 - restore_flags(flags);
28419 -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios)
28421 - unsigned int lcr_h, baud, quot, cflag, old_cr, bits;
28422 - unsigned long flags;
28424 - if (!info->tty || !info->tty->termios)
28425 - return;
28427 - cflag = info->tty->termios->c_cflag;
28429 -#if DEBUG
28430 - printk("ambauart_set_cflag(0x%x) called\n", cflag);
28431 -#endif
28432 - /* byte size and parity */
28433 - switch (cflag & CSIZE) {
28434 - case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7; break;
28435 - case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8; break;
28436 - case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9; break;
28437 - default: lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8
28439 - if (cflag & CSTOPB) {
28440 - lcr_h |= AMBA_UARTLCR_H_STP2;
28441 - bits ++;
28443 - if (cflag & PARENB) {
28444 - lcr_h |= AMBA_UARTLCR_H_PEN;
28445 - bits++;
28446 - if (!(cflag & PARODD))
28447 - lcr_h |= AMBA_UARTLCR_H_EPS;
28449 - if (info->port->fifosize > 1)
28450 - lcr_h |= AMBA_UARTLCR_H_FEN;
28452 - do {
28453 - /* Determine divisor based on baud rate */
28454 - baud = tty_get_baud_rate(info->tty);
28455 - if (!baud)
28456 - baud = 9600;
28458 - if (baud == 38400 &&
28459 - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
28460 - quot = info->state->custom_divisor;
28461 - else
28462 - quot = (info->port->uartclk / (16 * baud)) - 1;
28464 - if (!quot && old_termios) {
28465 - info->tty->termios->c_cflag &= ~CBAUD;
28466 - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
28467 - old_termios = NULL;
28469 - } while (quot == 0 && old_termios);
28471 - /* As a last resort, if the quotient is zero, default to 9600 bps */
28472 - if (!quot)
28473 - quot = (info->port->uartclk / (16 * 9600)) - 1;
28475 - info->timeout = (info->port->fifosize * HZ * bits * quot) /
28476 - (info->port->uartclk / 16);
28477 - info->timeout += HZ/50; /* Add .02 seconds of slop */
28479 - if (cflag & CRTSCTS)
28480 - info->flags |= ASYNC_CTS_FLOW;
28481 - else
28482 - info->flags &= ~ASYNC_CTS_FLOW;
28483 - if (cflag & CLOCAL)
28484 - info->flags &= ~ASYNC_CHECK_CD;
28485 - else
28486 - info->flags |= ASYNC_CHECK_CD;
28488 - /*
28489 - * Set up parity check flag
28490 - */
28491 -#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
28493 - info->read_status_mask = AMBA_UARTRSR_OE;
28494 - if (I_INPCK(info->tty))
28495 - info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
28496 - if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
28497 - info->read_status_mask |= AMBA_UARTRSR_BE;
28499 - /*
28500 - * Characters to ignore
28501 - */
28502 - info->ignore_status_mask = 0;
28503 - if (I_IGNPAR(info->tty))
28504 - info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
28505 - if (I_IGNBRK(info->tty)) {
28506 - info->ignore_status_mask |= AMBA_UARTRSR_BE;
28507 - /*
28508 - * If we're ignoring parity and break indicators,
28509 - * ignore overruns to (for real raw support).
28510 - */
28511 - if (I_IGNPAR(info->tty))
28512 - info->ignore_status_mask |= AMBA_UARTRSR_OE;
28515 - /* first, disable everything */
28516 - save_flags(flags); cli();
28517 - old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE;
28519 - if ((info->flags & ASYNC_HARDPPS_CD) ||
28520 - (cflag & CRTSCTS) ||
28521 - !(cflag & CLOCAL))
28522 - old_cr |= AMBA_UARTCR_MSIE;
28524 - UART_PUT_CR(info->port, 0);
28525 - restore_flags(flags);
28527 - /* Set baud rate */
28528 - UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8));
28529 - UART_PUT_LCRL(info->port, (quot & 0xff));
28531 - /*
28532 - * ----------v----------v----------v----------v-----
28533 - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
28534 - * ----------^----------^----------^----------^-----
28535 - */
28536 - UART_PUT_LCRH(info->port, lcr_h);
28537 - UART_PUT_CR(info->port, old_cr);
28540 -static void ambauart_put_char(struct tty_struct *tty, u_char ch)
28542 - struct amba_info *info = tty->driver_data;
28543 - unsigned long flags;
28545 - if (!tty || !info->xmit.buf)
28546 - return;
28548 - save_flags(flags); cli();
28549 - if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) {
28550 - info->xmit.buf[info->xmit.head] = ch;
28551 - info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1);
28553 - restore_flags(flags);
28556 -static void ambauart_flush_chars(struct tty_struct *tty)
28558 - struct amba_info *info = tty->driver_data;
28559 - unsigned long flags;
28561 - if (info->xmit.head == info->xmit.tail
28562 - || tty->stopped
28563 - || tty->hw_stopped
28564 - || !info->xmit.buf)
28565 - return;
28567 - save_flags(flags); cli();
28568 - ambauart_enable_tx_interrupt(info);
28569 - restore_flags(flags);
28572 -static int ambauart_write(struct tty_struct *tty, int from_user,
28573 - const u_char * buf, int count)
28575 - struct amba_info *info = tty->driver_data;
28576 - unsigned long flags;
28577 - int c, ret = 0;
28579 - if (!tty || !info->xmit.buf || !tmp_buf)
28580 - return 0;
28582 - save_flags(flags);
28583 - if (from_user) {
28584 - down(&tmp_buf_sem);
28585 - while (1) {
28586 - int c1;
28587 - c = CIRC_SPACE_TO_END(info->xmit.head,
28588 - info->xmit.tail,
28589 - AMBA_XMIT_SIZE);
28590 - if (count < c)
28591 - c = count;
28592 - if (c <= 0)
28593 - break;
28595 - c -= copy_from_user(tmp_buf, buf, c);
28596 - if (!c) {
28597 - if (!ret)
28598 - ret = -EFAULT;
28599 - break;
28601 - cli();
28602 - c1 = CIRC_SPACE_TO_END(info->xmit.head,
28603 - info->xmit.tail,
28604 - AMBA_XMIT_SIZE);
28605 - if (c1 < c)
28606 - c = c1;
28607 - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
28608 - info->xmit.head = (info->xmit.head + c) &
28609 - (AMBA_XMIT_SIZE - 1);
28610 - restore_flags(flags);
28611 - buf += c;
28612 - count -= c;
28613 - ret += c;
28615 - up(&tmp_buf_sem);
28616 - } else {
28617 - cli();
28618 - while (1) {
28619 - c = CIRC_SPACE_TO_END(info->xmit.head,
28620 - info->xmit.tail,
28621 - AMBA_XMIT_SIZE);
28622 - if (count < c)
28623 - c = count;
28624 - if (c <= 0)
28625 - break;
28626 - memcpy(info->xmit.buf + info->xmit.head, buf, c);
28627 - info->xmit.head = (info->xmit.head + c) &
28628 - (AMBA_XMIT_SIZE - 1);
28629 - buf += c;
28630 - count -= c;
28631 - ret += c;
28633 - restore_flags(flags);
28635 - if (info->xmit.head != info->xmit.tail
28636 - && !tty->stopped
28637 - && !tty->hw_stopped)
28638 - ambauart_enable_tx_interrupt(info);
28639 - return ret;
28642 -static int ambauart_write_room(struct tty_struct *tty)
28644 - struct amba_info *info = tty->driver_data;
28646 - return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
28649 -static int ambauart_chars_in_buffer(struct tty_struct *tty)
28651 - struct amba_info *info = tty->driver_data;
28653 - return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
28656 -static void ambauart_flush_buffer(struct tty_struct *tty)
28658 - struct amba_info *info = tty->driver_data;
28659 - unsigned long flags;
28661 -#if DEBUG
28662 - printk("ambauart_flush_buffer(%d) called\n",
28663 - MINOR(tty->device) - tty->driver.minor_start);
28664 -#endif
28665 - save_flags(flags); cli();
28666 - info->xmit.head = info->xmit.tail = 0;
28667 - restore_flags(flags);
28668 - wake_up_interruptible(&tty->write_wait);
28669 - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
28670 - tty->ldisc.write_wakeup)
28671 - (tty->ldisc.write_wakeup)(tty);
28675 - * This function is used to send a high-priority XON/XOFF character to
28676 - * the device
28677 - */
28678 -static void ambauart_send_xchar(struct tty_struct *tty, char ch)
28680 - struct amba_info *info = tty->driver_data;
28682 - info->x_char = ch;
28683 - if (ch)
28684 - ambauart_enable_tx_interrupt(info);
28687 -static void ambauart_throttle(struct tty_struct *tty)
28689 - struct amba_info *info = tty->driver_data;
28690 - unsigned long flags;
28692 - if (I_IXOFF(tty))
28693 - ambauart_send_xchar(tty, STOP_CHAR(tty));
28695 - if (tty->termios->c_cflag & CRTSCTS) {
28696 - save_flags(flags); cli();
28697 - info->mctrl &= ~TIOCM_RTS;
28698 - info->port->set_mctrl(info->port, info->mctrl);
28699 - restore_flags(flags);
28703 -static void ambauart_unthrottle(struct tty_struct *tty)
28705 - struct amba_info *info = (struct amba_info *) tty->driver_data;
28706 - unsigned long flags;
28708 - if (I_IXOFF(tty)) {
28709 - if (info->x_char)
28710 - info->x_char = 0;
28711 - else
28712 - ambauart_send_xchar(tty, START_CHAR(tty));
28715 - if (tty->termios->c_cflag & CRTSCTS) {
28716 - save_flags(flags); cli();
28717 - info->mctrl |= TIOCM_RTS;
28718 - info->port->set_mctrl(info->port, info->mctrl);
28719 - restore_flags(flags);
28723 -static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo)
28725 - struct amba_state *state = info->state;
28726 - struct amba_port *port = info->port;
28727 - struct serial_struct tmp;
28729 - memset(&tmp, 0, sizeof(tmp));
28730 - tmp.type = 0;
28731 - tmp.line = state->line;
28732 - tmp.port = port->uart_base;
28733 - if (HIGH_BITS_OFFSET)
28734 - tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
28735 - tmp.irq = port->irq;
28736 - tmp.flags = 0;
28737 - tmp.xmit_fifo_size = port->fifosize;
28738 - tmp.baud_base = port->uartclk / 16;
28739 - tmp.close_delay = state->close_delay;
28740 - tmp.closing_wait = state->closing_wait;
28741 - tmp.custom_divisor = state->custom_divisor;
28743 - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
28744 - return -EFAULT;
28745 - return 0;
28748 -static int set_serial_info(struct amba_info *info,
28749 - struct serial_struct *newinfo)
28751 - struct serial_struct new_serial;
28752 - struct amba_state *state, old_state;
28753 - struct amba_port *port;
28754 - unsigned long new_port;
28755 - unsigned int i, change_irq, change_port;
28756 - int retval = 0;
28758 - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
28759 - return -EFAULT;
28761 - state = info->state;
28762 - old_state = *state;
28763 - port = info->port;
28765 - new_port = new_serial.port;
28766 - if (HIGH_BITS_OFFSET)
28767 - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
28769 - change_irq = new_serial.irq != port->irq;
28770 - change_port = new_port != port->uart_base;
28772 - if (!capable(CAP_SYS_ADMIN)) {
28773 - if (change_irq || change_port ||
28774 - (new_serial.baud_base != port->uartclk / 16) ||
28775 - (new_serial.close_delay != state->close_delay) ||
28776 - (new_serial.xmit_fifo_size != port->fifosize) ||
28777 - ((new_serial.flags & ~ASYNC_USR_MASK) !=
28778 - (state->flags & ~ASYNC_USR_MASK)))
28779 - return -EPERM;
28780 - state->flags = ((state->flags & ~ASYNC_USR_MASK) |
28781 - (new_serial.flags & ASYNC_USR_MASK));
28782 - info->flags = ((info->flags & ~ASYNC_USR_MASK) |
28783 - (new_serial.flags & ASYNC_USR_MASK));
28784 - state->custom_divisor = new_serial.custom_divisor;
28785 - goto check_and_exit;
28788 - if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
28789 - (new_serial.baud_base < 9600))
28790 - return -EINVAL;
28792 - if (new_serial.type && change_port) {
28793 - for (i = 0; i < SERIAL_AMBA_NR; i++)
28794 - if ((port != amba_ports + i) &&
28795 - amba_ports[i].uart_base != new_port)
28796 - return -EADDRINUSE;
28799 - if ((change_port || change_irq) && (state->count > 1))
28800 - return -EBUSY;
28802 - /*
28803 - * OK, past this point, all the error checking has been done.
28804 - * At this point, we start making changes.....
28805 - */
28806 - port->uartclk = new_serial.baud_base * 16;
28807 - state->flags = ((state->flags & ~ASYNC_FLAGS) |
28808 - (new_serial.flags & ASYNC_FLAGS));
28809 - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
28810 - (info->flags & ASYNC_INTERNAL_FLAGS));
28811 - state->custom_divisor = new_serial.custom_divisor;
28812 - state->close_delay = new_serial.close_delay * HZ / 100;
28813 - state->closing_wait = new_serial.closing_wait * HZ / 100;
28814 - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
28815 - port->fifosize = new_serial.xmit_fifo_size;
28817 - if (change_port || change_irq) {
28818 - /*
28819 - * We need to shutdown the serial port at the old
28820 - * port/irq combination.
28821 - */
28822 - ambauart_shutdown(info);
28823 - port->irq = new_serial.irq;
28824 - port->uart_base = new_port;
28827 -check_and_exit:
28828 - if (!port->uart_base)
28829 - return 0;
28830 - if (info->flags & ASYNC_INITIALIZED) {
28831 - if ((old_state.flags & ASYNC_SPD_MASK) !=
28832 - (state->flags & ASYNC_SPD_MASK) ||
28833 - (old_state.custom_divisor != state->custom_divisor)) {
28834 - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
28835 - info->tty->alt_speed = 57600;
28836 - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
28837 - info->tty->alt_speed = 115200;
28838 - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
28839 - info->tty->alt_speed = 230400;
28840 - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
28841 - info->tty->alt_speed = 460800;
28842 - ambauart_change_speed(info, NULL);
28844 - } else
28845 - retval = ambauart_startup(info);
28846 - return retval;
28851 - * get_lsr_info - get line status register info
28852 - */
28853 -static int get_lsr_info(struct amba_info *info, unsigned int *value)
28855 - unsigned int result, status;
28856 - unsigned long flags;
28858 - save_flags(flags); cli();
28859 - status = UART_GET_FR(info->port);
28860 - restore_flags(flags);
28861 - result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0;
28863 - /*
28864 - * If we're about to load something into the transmit
28865 - * register, we'll pretend the transmitter isn't empty to
28866 - * avoid a race condition (depending on when the transmit
28867 - * interrupt happens).
28868 - */
28869 - if (info->x_char ||
28870 - ((CIRC_CNT(info->xmit.head, info->xmit.tail,
28871 - AMBA_XMIT_SIZE) > 0) &&
28872 - !info->tty->stopped && !info->tty->hw_stopped))
28873 - result &= TIOCSER_TEMT;
28875 - return put_user(result, value);
28878 -static int get_modem_info(struct amba_info *info, unsigned int *value)
28880 - unsigned int result = info->mctrl;
28881 - unsigned int status;
28883 - status = UART_GET_FR(info->port);
28884 - if (status & AMBA_UARTFR_DCD)
28885 - result |= TIOCM_CAR;
28886 - if (status & AMBA_UARTFR_DSR)
28887 - result |= TIOCM_DSR;
28888 - if (status & AMBA_UARTFR_CTS)
28889 - result |= TIOCM_CTS;
28891 - return put_user(result, value);
28894 -static int set_modem_info(struct amba_info *info, unsigned int cmd,
28895 - unsigned int *value)
28897 - unsigned int arg, old;
28898 - unsigned long flags;
28900 - if (get_user(arg, value))
28901 - return -EFAULT;
28903 - old = info->mctrl;
28904 - switch (cmd) {
28905 - case TIOCMBIS:
28906 - info->mctrl |= arg;
28907 - break;
28909 - case TIOCMBIC:
28910 - info->mctrl &= ~arg;
28911 - break;
28913 - case TIOCMSET:
28914 - info->mctrl = arg;
28915 - break;
28917 - default:
28918 - return -EINVAL;
28920 - save_flags(flags); cli();
28921 - if (old != info->mctrl)
28922 - info->port->set_mctrl(info->port, info->mctrl);
28923 - restore_flags(flags);
28924 - return 0;
28927 -static void ambauart_break_ctl(struct tty_struct *tty, int break_state)
28929 - struct amba_info *info = tty->driver_data;
28930 - unsigned long flags;
28931 - unsigned int lcr_h;
28933 - save_flags(flags); cli();
28934 - lcr_h = UART_GET_LCRH(info->port);
28935 - if (break_state == -1)
28936 - lcr_h |= AMBA_UARTLCR_H_BRK;
28937 - else
28938 - lcr_h &= ~AMBA_UARTLCR_H_BRK;
28939 - UART_PUT_LCRH(info->port, lcr_h);
28940 - restore_flags(flags);
28943 -static int ambauart_ioctl(struct tty_struct *tty, struct file *file,
28944 - unsigned int cmd, unsigned long arg)
28946 - struct amba_info *info = tty->driver_data;
28947 - struct amba_icount cprev, cnow;
28948 - struct serial_icounter_struct icount;
28949 - unsigned long flags;
28951 - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
28952 - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
28953 - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
28954 - if (tty->flags & (1 << TTY_IO_ERROR))
28955 - return -EIO;
28958 - switch (cmd) {
28959 - case TIOCMGET:
28960 - return get_modem_info(info, (unsigned int *)arg);
28961 - case TIOCMBIS:
28962 - case TIOCMBIC:
28963 - case TIOCMSET:
28964 - return set_modem_info(info, cmd, (unsigned int *)arg);
28965 - case TIOCGSERIAL:
28966 - return get_serial_info(info,
28967 - (struct serial_struct *)arg);
28968 - case TIOCSSERIAL:
28969 - return set_serial_info(info,
28970 - (struct serial_struct *)arg);
28971 - case TIOCSERGETLSR: /* Get line status register */
28972 - return get_lsr_info(info, (unsigned int *)arg);
28973 - /*
28974 - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
28975 - * - mask passed in arg for lines of interest
28976 - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
28977 - * Caller should use TIOCGICOUNT to see which one it was
28978 - */
28979 - case TIOCMIWAIT:
28980 - save_flags(flags); cli();
28981 - /* note the counters on entry */
28982 - cprev = info->state->icount;
28983 - /* Force modem status interrupts on */
28984 - UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE);
28985 - restore_flags(flags);
28986 - while (1) {
28987 - interruptible_sleep_on(&info->delta_msr_wait);
28988 - /* see if a signal did it */
28989 - if (signal_pending(current))
28990 - return -ERESTARTSYS;
28991 - save_flags(flags); cli();
28992 - cnow = info->state->icount; /* atomic copy */
28993 - restore_flags(flags);
28994 - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
28995 - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
28996 - return -EIO; /* no change => error */
28997 - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
28998 - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
28999 - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
29000 - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
29001 - return 0;
29003 - cprev = cnow;
29005 - /* NOTREACHED */
29007 - /*
29008 - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
29009 - * Return: write counters to the user passed counter struct
29010 - * NB: both 1->0 and 0->1 transitions are counted except for
29011 - * RI where only 0->1 is counted.
29012 - */
29013 - case TIOCGICOUNT:
29014 - save_flags(flags); cli();
29015 - cnow = info->state->icount;
29016 - restore_flags(flags);
29017 - icount.cts = cnow.cts;
29018 - icount.dsr = cnow.dsr;
29019 - icount.rng = cnow.rng;
29020 - icount.dcd = cnow.dcd;
29021 - icount.rx = cnow.rx;
29022 - icount.tx = cnow.tx;
29023 - icount.frame = cnow.frame;
29024 - icount.overrun = cnow.overrun;
29025 - icount.parity = cnow.parity;
29026 - icount.brk = cnow.brk;
29027 - icount.buf_overrun = cnow.buf_overrun;
29029 - return copy_to_user((void *)arg, &icount, sizeof(icount))
29030 - ? -EFAULT : 0;
29032 - default:
29033 - return -ENOIOCTLCMD;
29035 - return 0;
29038 -static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios)
29040 - struct amba_info *info = tty->driver_data;
29041 - unsigned long flags;
29042 - unsigned int cflag = tty->termios->c_cflag;
29044 - if ((cflag ^ old_termios->c_cflag) == 0 &&
29045 - RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
29046 - return;
29048 - ambauart_change_speed(info, old_termios);
29050 - /* Handle transition to B0 status */
29051 - if ((old_termios->c_cflag & CBAUD) &&
29052 - !(cflag & CBAUD)) {
29053 - save_flags(flags); cli();
29054 - info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
29055 - info->port->set_mctrl(info->port, info->mctrl);
29056 - restore_flags(flags);
29059 - /* Handle transition away from B0 status */
29060 - if (!(old_termios->c_cflag & CBAUD) &&
29061 - (cflag & CBAUD)) {
29062 - save_flags(flags); cli();
29063 - info->mctrl |= TIOCM_DTR;
29064 - if (!(cflag & CRTSCTS) ||
29065 - !test_bit(TTY_THROTTLED, &tty->flags))
29066 - info->mctrl |= TIOCM_RTS;
29067 - info->port->set_mctrl(info->port, info->mctrl);
29068 - restore_flags(flags);
29071 - /* Handle turning off CRTSCTS */
29072 - if ((old_termios->c_cflag & CRTSCTS) &&
29073 - !(cflag & CRTSCTS)) {
29074 - tty->hw_stopped = 0;
29075 - ambauart_start(tty);
29078 -#if 0
29079 - /*
29080 - * No need to wake up processes in open wait, since they
29081 - * sample the CLOCAL flag once, and don't recheck it.
29082 - * XXX It's not clear whether the current behavior is correct
29083 - * or not. Hence, this may change.....
29084 - */
29085 - if (!(old_termios->c_cflag & CLOCAL) &&
29086 - (tty->termios->c_cflag & CLOCAL))
29087 - wake_up_interruptible(&info->open_wait);
29088 -#endif
29091 -static void ambauart_close(struct tty_struct *tty, struct file *filp)
29093 - struct amba_info *info = tty->driver_data;
29094 - struct amba_state *state;
29095 - unsigned long flags;
29097 - if (!info)
29098 - return;
29100 - state = info->state;
29102 -#if DEBUG
29103 - printk("ambauart_close() called\n");
29104 -#endif
29106 - save_flags(flags); cli();
29108 - if (tty_hung_up_p(filp)) {
29109 - MOD_DEC_USE_COUNT;
29110 - restore_flags(flags);
29111 - return;
29114 - if ((tty->count == 1) && (state->count != 1)) {
29115 - /*
29116 - * Uh, oh. tty->count is 1, which means that the tty
29117 - * structure will be freed. state->count should always
29118 - * be one in these conditions. If it's greater than
29119 - * one, we've got real problems, since it means the
29120 - * serial port won't be shutdown.
29121 - */
29122 - printk("ambauart_close: bad serial port count; tty->count is 1, "
29123 - "state->count is %d\n", state->count);
29124 - state->count = 1;
29126 - if (--state->count < 0) {
29127 - printk("rs_close: bad serial port count for %s%d: %d\n",
29128 - tty->driver.name, info->state->line, state->count);
29129 - state->count = 0;
29131 - if (state->count) {
29132 - MOD_DEC_USE_COUNT;
29133 - restore_flags(flags);
29134 - return;
29136 - info->flags |= ASYNC_CLOSING;
29137 - restore_flags(flags);
29138 - /*
29139 - * Save the termios structure, since this port may have
29140 - * separate termios for callout and dialin.
29141 - */
29142 - if (info->flags & ASYNC_NORMAL_ACTIVE)
29143 - info->state->normal_termios = *tty->termios;
29144 - if (info->flags & ASYNC_CALLOUT_ACTIVE)
29145 - info->state->callout_termios = *tty->termios;
29146 - /*
29147 - * Now we wait for the transmit buffer to clear; and we notify
29148 - * the line discipline to only process XON/XOFF characters.
29149 - */
29150 - tty->closing = 1;
29151 - if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
29152 - tty_wait_until_sent(tty, info->state->closing_wait);
29153 - /*
29154 - * At this point, we stop accepting input. To do this, we
29155 - * disable the receive line status interrupts.
29156 - */
29157 - if (info->flags & ASYNC_INITIALIZED) {
29158 - ambauart_disable_rx_interrupt(info);
29159 - /*
29160 - * Before we drop DTR, make sure the UART transmitter
29161 - * has completely drained; this is especially
29162 - * important if there is a transmit FIFO!
29163 - */
29164 - ambauart_wait_until_sent(tty, info->timeout);
29166 - ambauart_shutdown(info);
29167 - if (tty->driver.flush_buffer)
29168 - tty->driver.flush_buffer(tty);
29169 - if (tty->ldisc.flush_buffer)
29170 - tty->ldisc.flush_buffer(tty);
29171 - tty->closing = 0;
29172 - info->event = 0;
29173 - info->tty = NULL;
29174 - if (info->blocked_open) {
29175 - if (info->state->close_delay) {
29176 - set_current_state(TASK_INTERRUPTIBLE);
29177 - schedule_timeout(info->state->close_delay);
29179 - wake_up_interruptible(&info->open_wait);
29181 - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
29182 - ASYNC_CLOSING);
29183 - wake_up_interruptible(&info->close_wait);
29184 - MOD_DEC_USE_COUNT;
29187 -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout)
29189 - struct amba_info *info = (struct amba_info *) tty->driver_data;
29190 - unsigned long char_time, expire;
29191 - unsigned int status;
29193 - if (info->port->fifosize == 0)
29194 - return;
29196 - /*
29197 - * Set the check interval to be 1/5 of the estimated time to
29198 - * send a single character, and make it at least 1. The check
29199 - * interval should also be less than the timeout.
29201 - * Note: we have to use pretty tight timings here to satisfy
29202 - * the NIST-PCTS.
29203 - */
29204 - char_time = (info->timeout - HZ/50) / info->port->fifosize;
29205 - char_time = char_time / 5;
29206 - if (char_time == 0)
29207 - char_time = 1;
29208 - if (timeout && timeout < char_time)
29209 - char_time = timeout;
29210 - /*
29211 - * If the transmitter hasn't cleared in twice the approximate
29212 - * amount of time to send the entire FIFO, it probably won't
29213 - * ever clear. This assumes the UART isn't doing flow
29214 - * control, which is currently the case. Hence, if it ever
29215 - * takes longer than info->timeout, this is probably due to a
29216 - * UART bug of some kind. So, we clamp the timeout parameter at
29217 - * 2*info->timeout.
29218 - */
29219 - if (!timeout || timeout > 2 * info->timeout)
29220 - timeout = 2 * info->timeout;
29222 - expire = jiffies + timeout;
29223 -#if DEBUG
29224 - printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n",
29225 - MINOR(tty->device) - tty->driver.minor_start, jiffies,
29226 - expire);
29227 -#endif
29228 - while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) {
29229 - set_current_state(TASK_INTERRUPTIBLE);
29230 - schedule_timeout(char_time);
29231 - if (signal_pending(current))
29232 - break;
29233 - if (timeout && time_after(jiffies, expire))
29234 - break;
29235 - status = UART_GET_FR(info->port);
29237 - set_current_state(TASK_RUNNING);
29240 -static void ambauart_hangup(struct tty_struct *tty)
29242 - struct amba_info *info = tty->driver_data;
29243 - struct amba_state *state = info->state;
29245 - ambauart_flush_buffer(tty);
29246 - if (info->flags & ASYNC_CLOSING)
29247 - return;
29248 - ambauart_shutdown(info);
29249 - info->event = 0;
29250 - state->count = 0;
29251 - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
29252 - info->tty = NULL;
29253 - wake_up_interruptible(&info->open_wait);
29256 -static int block_til_ready(struct tty_struct *tty, struct file *filp,
29257 - struct amba_info *info)
29259 - DECLARE_WAITQUEUE(wait, current);
29260 - struct amba_state *state = info->state;
29261 - unsigned long flags;
29262 - int do_clocal = 0, extra_count = 0, retval;
29264 - /*
29265 - * If the device is in the middle of being closed, then block
29266 - * until it's done, and then try again.
29267 - */
29268 - if (tty_hung_up_p(filp) ||
29269 - (info->flags & ASYNC_CLOSING)) {
29270 - if (info->flags & ASYNC_CLOSING)
29271 - interruptible_sleep_on(&info->close_wait);
29272 - return (info->flags & ASYNC_HUP_NOTIFY) ?
29273 - -EAGAIN : -ERESTARTSYS;
29276 - /*
29277 - * If this is a callout device, then just make sure the normal
29278 - * device isn't being used.
29279 - */
29280 - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
29281 - if (info->flags & ASYNC_NORMAL_ACTIVE)
29282 - return -EBUSY;
29283 - if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
29284 - (info->flags & ASYNC_SESSION_LOCKOUT) &&
29285 - (info->session != current->session))
29286 - return -EBUSY;
29287 - if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
29288 - (info->flags & ASYNC_PGRP_LOCKOUT) &&
29289 - (info->pgrp != current->pgrp))
29290 - return -EBUSY;
29291 - info->flags |= ASYNC_CALLOUT_ACTIVE;
29292 - return 0;
29295 - /*
29296 - * If non-blocking mode is set, or the port is not enabled,
29297 - * then make the check up front and then exit.
29298 - */
29299 - if ((filp->f_flags & O_NONBLOCK) ||
29300 - (tty->flags & (1 << TTY_IO_ERROR))) {
29301 - if (info->flags & ASYNC_CALLOUT_ACTIVE)
29302 - return -EBUSY;
29303 - info->flags |= ASYNC_NORMAL_ACTIVE;
29304 - return 0;
29307 - if (info->flags & ASYNC_CALLOUT_ACTIVE) {
29308 - if (state->normal_termios.c_cflag & CLOCAL)
29309 - do_clocal = 1;
29310 - } else {
29311 - if (tty->termios->c_cflag & CLOCAL)
29312 - do_clocal = 1;
29315 - /*
29316 - * Block waiting for the carrier detect and the line to become
29317 - * free (i.e., not in use by the callout). While we are in
29318 - * this loop, state->count is dropped by one, so that
29319 - * rs_close() knows when to free things. We restore it upon
29320 - * exit, either normal or abnormal.
29321 - */
29322 - retval = 0;
29323 - add_wait_queue(&info->open_wait, &wait);
29324 - save_flags(flags); cli();
29325 - if (!tty_hung_up_p(filp)) {
29326 - extra_count = 1;
29327 - state->count--;
29329 - restore_flags(flags);
29330 - info->blocked_open++;
29331 - while (1) {
29332 - save_flags(flags); cli();
29333 - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
29334 - (tty->termios->c_cflag & CBAUD)) {
29335 - info->mctrl = TIOCM_DTR | TIOCM_RTS;
29336 - info->port->set_mctrl(info->port, info->mctrl);
29338 - restore_flags(flags);
29339 - set_current_state(TASK_INTERRUPTIBLE);
29340 - if (tty_hung_up_p(filp) ||
29341 - !(info->flags & ASYNC_INITIALIZED)) {
29342 - if (info->flags & ASYNC_HUP_NOTIFY)
29343 - retval = -EAGAIN;
29344 - else
29345 - retval = -ERESTARTSYS;
29346 - break;
29348 - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
29349 - !(info->flags & ASYNC_CLOSING) &&
29350 - (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD)))
29351 - break;
29352 - if (signal_pending(current)) {
29353 - retval = -ERESTARTSYS;
29354 - break;
29356 - schedule();
29358 - set_current_state(TASK_RUNNING);
29359 - remove_wait_queue(&info->open_wait, &wait);
29360 - if (extra_count)
29361 - state->count++;
29362 - info->blocked_open--;
29363 - if (retval)
29364 - return retval;
29365 - info->flags |= ASYNC_NORMAL_ACTIVE;
29366 - return 0;
29369 -static struct amba_info *ambauart_get(int line)
29371 - struct amba_info *info;
29372 - struct amba_state *state = amba_state + line;
29374 - state->count++;
29375 - if (state->info)
29376 - return state->info;
29377 - info = kmalloc(sizeof(struct amba_info), GFP_KERNEL);
29378 - if (info) {
29379 - memset(info, 0, sizeof(struct amba_info));
29380 - init_waitqueue_head(&info->open_wait);
29381 - init_waitqueue_head(&info->close_wait);
29382 - init_waitqueue_head(&info->delta_msr_wait);
29383 - info->flags = state->flags;
29384 - info->state = state;
29385 - info->port = amba_ports + line;
29386 - tasklet_init(&info->tlet, ambauart_tasklet_action,
29387 - (unsigned long)info);
29389 - if (state->info) {
29390 - kfree(info);
29391 - return state->info;
29393 - state->info = info;
29394 - return info;
29397 -static int ambauart_open(struct tty_struct *tty, struct file *filp)
29399 - struct amba_info *info;
29400 - int retval, line = MINOR(tty->device) - tty->driver.minor_start;
29402 -#if DEBUG
29403 - printk("ambauart_open(%d) called\n", line);
29404 -#endif
29406 - // is this a line that we've got?
29407 - MOD_INC_USE_COUNT;
29408 - if (line >= SERIAL_AMBA_NR) {
29409 - MOD_DEC_USE_COUNT;
29410 - return -ENODEV;
29413 - info = ambauart_get(line);
29414 - if (!info)
29415 - return -ENOMEM;
29417 - tty->driver_data = info;
29418 - info->tty = tty;
29419 - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
29421 - /*
29422 - * Make sure we have the temporary buffer allocated
29423 - */
29424 - if (!tmp_buf) {
29425 - unsigned long page = get_zeroed_page(GFP_KERNEL);
29426 - if (tmp_buf)
29427 - free_page(page);
29428 - else if (!page) {
29429 - MOD_DEC_USE_COUNT;
29430 - return -ENOMEM;
29432 - tmp_buf = (u_char *)page;
29435 - /*
29436 - * If the port is in the middle of closing, bail out now.
29437 - */
29438 - if (tty_hung_up_p(filp) ||
29439 - (info->flags & ASYNC_CLOSING)) {
29440 - if (info->flags & ASYNC_CLOSING)
29441 - interruptible_sleep_on(&info->close_wait);
29442 - MOD_DEC_USE_COUNT;
29443 - return -EAGAIN;
29446 - /*
29447 - * Start up the serial port
29448 - */
29449 - retval = ambauart_startup(info);
29450 - if (retval) {
29451 - MOD_DEC_USE_COUNT;
29452 - return retval;
29455 - retval = block_til_ready(tty, filp, info);
29456 - if (retval) {
29457 - MOD_DEC_USE_COUNT;
29458 - return retval;
29461 - if ((info->state->count == 1) &&
29462 - (info->flags & ASYNC_SPLIT_TERMIOS)) {
29463 - if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
29464 - *tty->termios = info->state->normal_termios;
29465 - else
29466 - *tty->termios = info->state->callout_termios;
29468 -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
29469 - if (ambauart_cons.cflag && ambauart_cons.index == line) {
29470 - tty->termios->c_cflag = ambauart_cons.cflag;
29471 - ambauart_cons.cflag = 0;
29473 -#endif
29474 - ambauart_change_speed(info, NULL);
29475 - info->session = current->session;
29476 - info->pgrp = current->pgrp;
29477 - return 0;
29480 -int __init ambauart_init(void)
29482 - int i;
29484 - ambanormal_driver.magic = TTY_DRIVER_MAGIC;
29485 - ambanormal_driver.driver_name = "serial_amba";
29486 - ambanormal_driver.name = SERIAL_AMBA_NAME;
29487 - ambanormal_driver.major = SERIAL_AMBA_MAJOR;
29488 - ambanormal_driver.minor_start = SERIAL_AMBA_MINOR;
29489 - ambanormal_driver.num = SERIAL_AMBA_NR;
29490 - ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL;
29491 - ambanormal_driver.subtype = SERIAL_TYPE_NORMAL;
29492 - ambanormal_driver.init_termios = tty_std_termios;
29493 - ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
29494 - ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
29495 - ambanormal_driver.refcount = &ambauart_refcount;
29496 - ambanormal_driver.table = ambauart_table;
29497 - ambanormal_driver.termios = ambauart_termios;
29498 - ambanormal_driver.termios_locked = ambauart_termios_locked;
29500 - ambanormal_driver.open = ambauart_open;
29501 - ambanormal_driver.close = ambauart_close;
29502 - ambanormal_driver.write = ambauart_write;
29503 - ambanormal_driver.put_char = ambauart_put_char;
29504 - ambanormal_driver.flush_chars = ambauart_flush_chars;
29505 - ambanormal_driver.write_room = ambauart_write_room;
29506 - ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer;
29507 - ambanormal_driver.flush_buffer = ambauart_flush_buffer;
29508 - ambanormal_driver.ioctl = ambauart_ioctl;
29509 - ambanormal_driver.throttle = ambauart_throttle;
29510 - ambanormal_driver.unthrottle = ambauart_unthrottle;
29511 - ambanormal_driver.send_xchar = ambauart_send_xchar;
29512 - ambanormal_driver.set_termios = ambauart_set_termios;
29513 - ambanormal_driver.stop = ambauart_stop;
29514 - ambanormal_driver.start = ambauart_start;
29515 - ambanormal_driver.hangup = ambauart_hangup;
29516 - ambanormal_driver.break_ctl = ambauart_break_ctl;
29517 - ambanormal_driver.wait_until_sent = ambauart_wait_until_sent;
29518 - ambanormal_driver.read_proc = NULL;
29520 - /*
29521 - * The callout device is just like the normal device except for
29522 - * the major number and the subtype code.
29523 - */
29524 - ambacallout_driver = ambanormal_driver;
29525 - ambacallout_driver.name = CALLOUT_AMBA_NAME;
29526 - ambacallout_driver.major = CALLOUT_AMBA_MAJOR;
29527 - ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT;
29528 - ambacallout_driver.read_proc = NULL;
29529 - ambacallout_driver.proc_entry = NULL;
29531 - if (tty_register_driver(&ambanormal_driver))
29532 - panic("Couldn't register AMBA serial driver\n");
29533 - if (tty_register_driver(&ambacallout_driver))
29534 - panic("Couldn't register AMBA callout driver\n");
29536 - for (i = 0; i < SERIAL_AMBA_NR; i++) {
29537 - struct amba_state *state = amba_state + i;
29538 - state->line = i;
29539 - state->close_delay = 5 * HZ / 10;
29540 - state->closing_wait = 30 * HZ;
29541 - state->callout_termios = ambacallout_driver.init_termios;
29542 - state->normal_termios = ambanormal_driver.init_termios;
29545 - return 0;
29548 -__initcall(ambauart_init);
29550 -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
29551 -/************** console driver *****************/
29554 - * This code is currently never used; console->read is never called.
29555 - * Therefore, although we have an implementation, we don't use it.
29556 - * FIXME: the "const char *s" should be fixed to "char *s" some day.
29557 - * (when the definition in include/linux/console.h is also fixed)
29558 - */
29559 -#ifdef used_and_not_const_char_pointer
29560 -static int ambauart_console_read(struct console *co, const char *s, u_int count)
29562 - struct amba_port *port = &amba_ports[co->index];
29563 - unsigned int status;
29564 - char *w;
29565 - int c;
29566 -#if DEBUG
29567 - printk("ambauart_console_read() called\n");
29568 -#endif
29570 - c = 0;
29571 - w = s;
29572 - while (c < count) {
29573 - status = UART_GET_FR(port);
29574 - if (UART_RX_DATA(status)) {
29575 - *w++ = UART_GET_CHAR(port);
29576 - c++;
29577 - } else {
29578 - // nothing more to get, return
29579 - return c;
29582 - // return the count
29583 - return c;
29585 -#endif
29588 - * Print a string to the serial port trying not to disturb
29589 - * any possible real use of the port...
29591 - * The console must be locked when we get here.
29592 - */
29593 -static void ambauart_console_write(struct console *co, const char *s, u_int count)
29595 - struct amba_port *port = &amba_ports[co->index];
29596 - unsigned int status, old_cr;
29597 - int i;
29599 - /*
29600 - * First save the CR then disable the interrupts
29601 - */
29602 - old_cr = UART_GET_CR(port);
29603 - UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
29605 - /*
29606 - * Now, do each character
29607 - */
29608 - for (i = 0; i < count; i++) {
29609 - do {
29610 - status = UART_GET_FR(port);
29611 - } while (!UART_TX_READY(status));
29612 - UART_PUT_CHAR(port, s[i]);
29613 - if (s[i] == '\n') {
29614 - do {
29615 - status = UART_GET_FR(port);
29616 - } while (!UART_TX_READY(status));
29617 - UART_PUT_CHAR(port, '\r');
29621 - /*
29622 - * Finally, wait for transmitter to become empty
29623 - * and restore the TCR
29624 - */
29625 - do {
29626 - status = UART_GET_FR(port);
29627 - } while (status & AMBA_UARTFR_BUSY);
29628 - UART_PUT_CR(port, old_cr);
29631 -static kdev_t ambauart_console_device(struct console *c)
29633 - return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
29636 -static int __init ambauart_console_setup(struct console *co, char *options)
29638 - struct amba_port *port;
29639 - int baud = 38400;
29640 - int bits = 8;
29641 - int parity = 'n';
29642 - u_int cflag = CREAD | HUPCL | CLOCAL;
29643 - u_int lcr_h, quot;
29645 - if (co->index >= SERIAL_AMBA_NR)
29646 - co->index = 0;
29648 - port = &amba_ports[co->index];
29650 - if (options) {
29651 - char *s = options;
29652 - baud = simple_strtoul(s, NULL, 10);
29653 - while (*s >= '0' && *s <= '9')
29654 - s++;
29655 - if (*s) parity = *s++;
29656 - if (*s) bits = *s - '0';
29659 - /*
29660 - * Now construct a cflag setting.
29661 - */
29662 - switch (baud) {
29663 - case 1200: cflag |= B1200; break;
29664 - case 2400: cflag |= B2400; break;
29665 - case 4800: cflag |= B4800; break;
29666 - default: cflag |= B9600; baud = 9600; break;
29667 - case 19200: cflag |= B19200; break;
29668 - case 38400: cflag |= B38400; break;
29669 - case 57600: cflag |= B57600; break;
29670 - case 115200: cflag |= B115200; break;
29672 - switch (bits) {
29673 - case 7: cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7; break;
29674 - default: cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8; break;
29676 - switch (parity) {
29677 - case 'o':
29678 - case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break;
29679 - case 'e':
29680 - case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN |
29681 - AMBA_UARTLCR_H_EPS; break;
29684 - co->cflag = cflag;
29686 - if (port->fifosize > 1)
29687 - lcr_h |= AMBA_UARTLCR_H_FEN;
29689 - quot = (port->uartclk / (16 * baud)) - 1;
29691 - UART_PUT_LCRL(port, (quot & 0xff));
29692 - UART_PUT_LCRM(port, (quot >> 8));
29693 - UART_PUT_LCRH(port, lcr_h);
29695 - /* we will enable the port as we need it */
29696 - UART_PUT_CR(port, 0);
29698 - return 0;
29701 -static struct console ambauart_cons =
29703 - name: SERIAL_AMBA_NAME,
29704 - write: ambauart_console_write,
29705 -#ifdef used_and_not_const_char_pointer
29706 - read: ambauart_console_read,
29707 -#endif
29708 - device: ambauart_console_device,
29709 - setup: ambauart_console_setup,
29710 - flags: CON_PRINTBUFFER,
29711 - index: -1,
29714 -void __init ambauart_console_init(void)
29716 - register_console(&ambauart_cons);
29719 -#endif /* CONFIG_SERIAL_AMBA_CONSOLE */
29721 -MODULE_LICENSE("GPL");
29722 -EXPORT_NO_SYMBOLS;
29723 --- linux-2.4.25/drivers/char/tty_io.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
29724 +++ linux-2.4.25/drivers/char/tty_io.c 2004-03-31 17:15:09.000000000 +0200
29725 @@ -19,7 +19,7 @@
29726 * Also restructured routines so that there is more of a separation
29727 * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
29728 * the low-level tty routines (serial.c, pty.c, console.c). This
29729 - * makes for cleaner and more compact code. -TYT, 9/17/92
29730 + * makes for cleaner and more compact code. -TYT, 9/17/92
29732 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
29733 * which can be dynamically activated and de-activated by the line
29734 @@ -41,7 +41,7 @@
29736 * New TIOCLINUX variants added.
29737 * -- mj@k332.feld.cvut.cz, 19-Nov-95
29738 - *
29740 * Restrict vt switching via ioctl()
29741 * -- grif@cs.ucr.edu, 5-Dec-95
29743 @@ -151,8 +151,7 @@
29744 extern void tty3215_init(void);
29745 extern void tub3270_con_init(void);
29746 extern void tub3270_init(void);
29747 -extern void rs285_console_init(void);
29748 -extern void sa1100_rs_console_init(void);
29749 +extern void uart_console_init(void);
29750 extern void sgi_serial_console_init(void);
29751 extern void sn_sal_serial_console_init(void);
29752 extern void sci_console_init(void);
29753 @@ -164,6 +163,7 @@
29754 extern void txx9_serial_console_init(void);
29755 extern void sb1250_serial_console_init(void);
29756 extern void arc_console_init(void);
29757 +extern void rs285_console_init(void);
29758 extern int hvc_console_init(void);
29760 #ifndef MIN
29761 @@ -201,7 +201,7 @@
29762 else
29763 sprintf(buf, name,
29764 idx + tty->driver.name_base);
29767 return buf;
29770 @@ -239,7 +239,7 @@
29771 #ifdef CHECK_TTY_COUNT
29772 struct list_head *p;
29773 int count = 0;
29776 file_list_lock();
29777 for(p = tty->tty_files.next; p != &tty->tty_files; p = p->next) {
29778 if(list_entry(p, struct file, f_list)->private_data == tty)
29779 @@ -255,7 +255,7 @@
29780 "!= #fd's(%d) in %s\n",
29781 kdevname(tty->device), tty->count, count, routine);
29782 return count;
29783 - }
29785 #endif
29786 return 0;
29788 @@ -264,14 +264,14 @@
29790 if (disc < N_TTY || disc >= NR_LDISCS)
29791 return -EINVAL;
29794 if (new_ldisc) {
29795 ldiscs[disc] = *new_ldisc;
29796 ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
29797 ldiscs[disc].num = disc;
29798 } else
29799 memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
29802 return 0;
29805 @@ -301,7 +301,7 @@
29806 o_ldisc = tty->ldisc;
29808 tty_wait_until_sent(tty, 0);
29811 /* Shutdown the current discipline. */
29812 if (tty->ldisc.close)
29813 (tty->ldisc.close)(tty);
29814 @@ -339,7 +339,7 @@
29816 int major, minor;
29817 struct tty_driver *p;
29820 minor = MINOR(device);
29821 major = MAJOR(device);
29823 @@ -456,7 +456,7 @@
29824 redirect = NULL;
29826 spin_unlock(&redirect_lock);
29829 check_tty_count(tty, "do_tty_hangup");
29830 file_list_lock();
29831 for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) {
29832 @@ -473,7 +473,7 @@
29833 filp->f_op = &hung_up_tty_fops;
29835 file_list_unlock();
29838 /* FIXME! What are the locking issues here? This may me overdoing things.. */
29840 unsigned long flags;
29841 @@ -510,7 +510,7 @@
29842 "error %d\n", -i);
29847 read_lock(&tasklist_lock);
29848 for_each_task(p) {
29849 if ((tty->session > 0) && (p->session == tty->session) &&
29850 @@ -550,7 +550,7 @@
29852 #ifdef TTY_DEBUG_HANGUP
29853 char buf[64];
29856 printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
29857 #endif
29858 schedule_task(&tty->tq_hangup);
29859 @@ -650,7 +650,7 @@
29860 wake_up_interruptible(&tty->write_wait);
29863 -static ssize_t tty_read(struct file * file, char * buf, size_t count,
29864 +static ssize_t tty_read(struct file * file, char * buf, size_t count,
29865 loff_t *ppos)
29867 int i;
29868 @@ -707,7 +707,7 @@
29869 size_t count)
29871 ssize_t ret = 0, written = 0;
29874 if (file->f_flags & O_NONBLOCK) {
29875 if (down_trylock(&tty->atomic_write))
29876 return -EAGAIN;
29877 @@ -835,7 +835,7 @@
29878 struct tty_struct *tty, *o_tty;
29879 struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
29880 struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
29881 - struct tty_driver *driver;
29882 + struct tty_driver *driver;
29883 int retval=0;
29884 int idx;
29886 @@ -845,7 +845,7 @@
29888 idx = MINOR(device) - driver->minor_start;
29890 - /*
29891 + /*
29892 * Check whether we need to acquire the tty semaphore to avoid
29893 * race conditions. For now, play it safe.
29895 @@ -859,7 +859,7 @@
29896 * First time open is complex, especially for PTY devices.
29897 * This code guarantees that either everything succeeds and the
29898 * TTY is ready for operation, or else the table slots are vacated
29899 - * and the allocated memory released. (Except that the termios
29900 + * and the allocated memory released. (Except that the termios
29901 * and locked termios may be retained.)
29904 @@ -938,13 +938,13 @@
29905 o_tty->link = tty;
29908 - /*
29909 + /*
29910 * All structures have been allocated, so now we install them.
29911 - * Failures after this point use release_mem to clean up, so
29912 + * Failures after this point use release_mem to clean up, so
29913 * there's no need to null out the local pointers.
29915 driver->table[idx] = tty;
29918 if (!*tp_loc)
29919 *tp_loc = tp;
29920 if (!*ltp_loc)
29921 @@ -954,7 +954,7 @@
29922 (*driver->refcount)++;
29923 tty->count++;
29925 - /*
29926 + /*
29927 * Structures all installed ... call the ldisc open routines.
29928 * If we fail here just call release_mem to clean up. No need
29929 * to decrement the use counts, as release_mem doesn't care.
29930 @@ -988,7 +988,7 @@
29931 if (driver->type == TTY_DRIVER_TYPE_PTY &&
29932 driver->subtype == PTY_TYPE_MASTER) {
29934 - * special case for PTY masters: only one open permitted,
29935 + * special case for PTY masters: only one open permitted,
29936 * and the slave side open count is incremented as well.
29938 if (tty->count) {
29939 @@ -1002,7 +1002,7 @@
29941 success:
29942 *ret_tty = tty;
29945 /* All paths come through here to release the semaphore */
29946 end_init:
29947 up_tty_sem(idx);
29948 @@ -1080,7 +1080,7 @@
29949 int pty_master, tty_closing, o_tty_closing, do_sleep;
29950 int idx;
29951 char buf[64];
29954 tty = (struct tty_struct *)filp->private_data;
29955 if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev"))
29956 return;
29957 @@ -1138,7 +1138,7 @@
29958 idx, kdevname(tty->device));
29959 return;
29961 - if (o_tty->termios_locked !=
29962 + if (o_tty->termios_locked !=
29963 tty->driver.other->termios_locked[idx]) {
29964 printk(KERN_DEBUG "release_dev: other->termios_locked["
29965 "%d] not o_termios_locked for (%s)\n",
29966 @@ -1204,11 +1204,11 @@
29967 printk(KERN_WARNING "release_dev: %s: read/write wait queue "
29968 "active!\n", tty_name(tty, buf));
29969 schedule();
29970 - }
29974 - * The closing flags are now consistent with the open counts on
29975 - * both sides, and we've completed the last operation that could
29976 + * The closing flags are now consistent with the open counts on
29977 + * both sides, and we've completed the last operation that could
29978 * block, so it's safe to proceed with closing.
29980 if (pty_master) {
29981 @@ -1266,7 +1266,7 @@
29982 /* check whether both sides are closing ... */
29983 if (!tty_closing || (o_tty && !o_tty_closing))
29984 return;
29987 #ifdef TTY_DEBUG_HANGUP
29988 printk(KERN_DEBUG "freeing tty structure...");
29989 #endif
29990 @@ -1284,14 +1284,14 @@
29991 (o_tty->ldisc.close)(o_tty);
29992 o_tty->ldisc = ldiscs[N_TTY];
29997 - * Make sure that the tty's task queue isn't activated.
29998 + * Make sure that the tty's task queue isn't activated.
30000 run_task_queue(&tq_timer);
30001 flush_scheduled_tasks();
30003 - /*
30004 + /*
30005 * The release_mem function takes care of the details of clearing
30006 * the slots and preserving the termios structure.
30008 @@ -1482,7 +1482,7 @@
30009 tty = (struct tty_struct *)filp->private_data;
30010 if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_fasync"))
30011 return 0;
30014 retval = fasync_helper(fd, filp, on, &tty->fasync);
30015 if (retval <= 0)
30016 return retval;
30017 @@ -1697,7 +1697,7 @@
30019 static int tty_generic_brk(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
30021 - if (cmd == TCSBRK && arg)
30022 + if (cmd == TCSBRK && arg)
30024 /* tcdrain case */
30025 int retval = tty_check_change(tty);
30026 @@ -1718,7 +1718,7 @@
30028 struct tty_struct *tty, *real_tty;
30029 int retval;
30032 tty = (struct tty_struct *)file->private_data;
30033 if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
30034 return -EINVAL;
30035 @@ -1738,7 +1738,7 @@
30036 if (tty->driver.ioctl)
30037 return tty->driver.ioctl(tty, file, cmd, arg);
30038 return -EINVAL;
30041 /* These two ioctl's always return success; even if */
30042 /* the driver doesn't support them. */
30043 case TCSBRK:
30044 @@ -1761,7 +1761,7 @@
30045 case TIOCSBRK:
30046 case TIOCCBRK:
30047 case TCSBRK:
30048 - case TCSBRKP:
30049 + case TCSBRKP:
30050 retval = tty_check_change(tty);
30051 if (retval)
30052 return retval;
30053 @@ -1824,7 +1824,7 @@
30054 case TIOCSBRK: /* Turn break on, unconditionally */
30055 tty->driver.break_ctl(tty, -1);
30056 return 0;
30059 case TIOCCBRK: /* Turn break off, unconditionally */
30060 tty->driver.break_ctl(tty, 0);
30061 return 0;
30062 @@ -1837,7 +1837,7 @@
30063 if (!arg)
30064 return send_break(tty, HZ/4);
30065 return 0;
30066 - case TCSBRKP: /* support for POSIX tcsendbreak() */
30067 + case TCSBRKP: /* support for POSIX tcsendbreak() */
30068 return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
30070 if (tty->driver.ioctl) {
30071 @@ -1859,7 +1859,7 @@
30072 * prevent trojan horses by killing all processes associated with this
30073 * tty when the user hits the "Secure Attention Key". Required for
30074 * super-paranoid applications --- see the Orange Book for more details.
30075 - *
30077 * This code could be nicer; ideally it should send a HUP, wait a few
30078 * seconds, then send a INT, and then a KILL signal. But you then
30079 * have to coordinate with the init process, since all processes associated
30080 @@ -1883,7 +1883,7 @@
30081 int session;
30082 int i;
30083 struct file *filp;
30086 if (!tty)
30087 return;
30088 session = tty->session;
30089 @@ -1968,7 +1968,7 @@
30090 count = tty->flip.count;
30091 tty->flip.count = 0;
30092 restore_flags(flags);
30095 tty->ldisc.receive_buf(tty, cp, fp, count);
30098 @@ -2000,7 +2000,7 @@
30099 i = cflag & CBAUD;
30100 if (i & CBAUDEX) {
30101 i &= ~CBAUDEX;
30102 - if (i < 1 || i+15 >= n_baud_table)
30103 + if (i < 1 || i+15 >= n_baud_table)
30104 tty->termios->c_cflag &= ~CBAUDEX;
30105 else
30106 i += 15;
30107 @@ -2013,7 +2013,7 @@
30109 return(tty->alt_speed);
30113 return baud_table[i];
30116 @@ -2079,7 +2079,7 @@
30117 mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
30118 break;
30120 - if ( (minor < driver->minor_start) ||
30121 + if ( (minor < driver->minor_start) ||
30122 (minor >= driver->minor_start + driver->num) ) {
30123 printk(KERN_ERR "Attempt to register invalid minor number "
30124 "with devfs (%d:%d).\n", (int)driver->major,(int)minor);
30125 @@ -2132,12 +2132,12 @@
30127 if (!driver->put_char)
30128 driver->put_char = tty_default_put_char;
30131 driver->prev = 0;
30132 driver->next = tty_drivers;
30133 if (tty_drivers) tty_drivers->prev = driver;
30134 tty_drivers = driver;
30137 if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
30138 for(i = 0; i < driver->num; i++)
30139 tty_register_devfs(driver, 0, driver->minor_start + i);
30140 @@ -2156,7 +2156,7 @@
30141 int i, found = 0;
30142 struct termios *tp;
30143 const char *othername = NULL;
30146 if (*driver->refcount)
30147 return -EBUSY;
30149 @@ -2166,7 +2166,7 @@
30150 else if (p->major == driver->major)
30151 othername = p->name;
30155 if (!found)
30156 return -ENOENT;
30158 @@ -2181,7 +2181,7 @@
30159 driver->prev->next = driver->next;
30160 else
30161 tty_drivers = driver->next;
30164 if (driver->next)
30165 driver->next->prev = driver->prev;
30167 @@ -2221,7 +2221,7 @@
30168 (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
30171 - * Set up the standard termios. Individual tty drivers may
30172 + * Set up the standard termios. Individual tty drivers may
30173 * deviate from this; this is used as a template.
30175 memset(&tty_std_termios, 0, sizeof(struct termios));
30176 @@ -2233,11 +2233,11 @@
30177 ECHOCTL | ECHOKE | IEXTEN;
30180 - * set up the console device so that later boot sequences can
30181 + * set up the console device so that later boot sequences can
30182 * inform about problems etc..
30184 #ifdef CONFIG_EARLY_PRINTK
30185 - disable_early_printk();
30186 + disable_early_printk();
30187 #endif
30188 #ifdef CONFIG_HVC_CONSOLE
30189 hvc_console_init();
30190 @@ -2288,18 +2288,12 @@
30191 #ifdef CONFIG_STDIO_CONSOLE
30192 stdio_console_init();
30193 #endif
30194 -#ifdef CONFIG_SERIAL_21285_CONSOLE
30195 - rs285_console_init();
30196 -#endif
30197 -#ifdef CONFIG_SERIAL_SA1100_CONSOLE
30198 - sa1100_rs_console_init();
30199 +#ifdef CONFIG_SERIAL_CORE_CONSOLE
30200 + uart_console_init();
30201 #endif
30202 #ifdef CONFIG_ARC_CONSOLE
30203 arc_console_init();
30204 #endif
30205 -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
30206 - ambauart_console_init();
30207 -#endif
30208 #ifdef CONFIG_SERIAL_TX3912_CONSOLE
30209 tx3912_console_init();
30210 #endif
30211 @@ -2315,6 +2309,9 @@
30212 #ifdef CONFIG_IP22_SERIAL
30213 sgi_serial_console_init();
30214 #endif
30215 +#ifdef CONFIG_SERIAL_21285_CONSOLE
30216 + rs285_console_init();
30217 +#endif
30220 static struct tty_driver dev_tty_driver, dev_syscons_driver;
30221 @@ -2347,7 +2344,7 @@
30222 dev_tty_driver.num = 1;
30223 dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
30224 dev_tty_driver.subtype = SYSTEM_TYPE_TTY;
30227 if (tty_register_driver(&dev_tty_driver))
30228 panic("Couldn't register /dev/tty driver\n");
30230 @@ -2363,7 +2360,7 @@
30231 panic("Couldn't register /dev/console driver\n");
30233 /* console calls tty_register_driver() before kmalloc() works.
30234 - * Thus, we can't devfs_register() then. Do so now, instead.
30235 + * Thus, we can't devfs_register() then. Do so now, instead.
30237 #ifdef CONFIG_VT
30238 con_init_devfs();
30239 @@ -2381,7 +2378,7 @@
30240 if (tty_register_driver(&dev_ptmx_driver))
30241 panic("Couldn't register /dev/ptmx driver\n");
30242 #endif
30245 #ifdef CONFIG_VT
30246 dev_console_driver = dev_tty_driver;
30247 dev_console_driver.driver_name = "/dev/vc/0";
30248 @@ -2441,10 +2438,10 @@
30249 pty_init();
30250 #ifdef CONFIG_MOXA_SMARTIO
30251 mxser_init();
30252 -#endif
30253 +#endif
30254 #ifdef CONFIG_MOXA_INTELLIO
30255 moxa_init();
30256 -#endif
30257 +#endif
30258 #ifdef CONFIG_VT
30259 vcs_init();
30260 #endif
30261 --- linux-2.4.25/drivers/char/wdt285.c~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
30262 +++ linux-2.4.25/drivers/char/wdt285.c 2004-03-31 17:15:09.000000000 +0200
30263 @@ -151,7 +151,7 @@
30264 if (get_user(new_margin, (int *)arg))
30265 return -EFAULT;
30266 /* Arbitrary, can't find the card's limits */
30267 - if ((new_marg < 0) || (new_margin > 60))
30268 + if ((new_margin < 0) || (new_margin > 60))
30269 return -EINVAL;
30270 soft_margin = new_margin;
30271 watchdog_ping();
30272 --- linux-2.4.25/drivers/char/wdt977.c~2.4.25-vrs2.patch 2002-11-29 00:53:12.000000000 +0100
30273 +++ linux-2.4.25/drivers/char/wdt977.c 2004-03-31 17:15:09.000000000 +0200
30274 @@ -27,6 +27,7 @@
30275 #include <asm/io.h>
30276 #include <asm/system.h>
30277 #include <asm/mach-types.h>
30278 +#include <asm/uaccess.h>
30280 #define WATCHDOG_MINOR 130
30282 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
30283 +++ linux-2.4.25/drivers/cpufreq/Kconfig 2004-03-31 17:15:09.000000000 +0200
30284 @@ -0,0 +1,38 @@
30285 +config CPU_FREQ_PROC_INTF
30286 + tristate "/proc/cpufreq interface (deprecated)"
30287 + depends on CPU_FREQ && PROC_FS
30288 + help
30289 + This enables the /proc/cpufreq interface for controlling
30290 + CPUFreq. Please note that it is recommended to use the sysfs
30291 + interface instead (which is built automatically).
30293 + For details, take a look at linux/Documentation/cpufreq.
30295 + If in doubt, say N.
30297 +config CPU_FREQ_GOV_USERSPACE
30298 + tristate "'userspace' governor for userspace frequency scaling"
30299 + depends on CPU_FREQ
30300 + help
30301 + Enable this cpufreq governor when you either want to set the
30302 + CPU frequency manually or when an userspace programm shall
30303 + be able to set the CPU dynamically, like on LART
30304 + ( http://www.lart.tudelft.nl/ )
30306 + For details, take a look at linux/Documentation/cpufreq.
30308 + If in doubt, say Y.
30310 +config CPU_FREQ_24_API
30311 + bool "/proc/sys/cpu/ interface (2.4. / OLD)"
30312 + depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
30313 + help
30314 + This enables the /proc/sys/cpu/ sysctl interface for controlling
30315 + the CPUFreq,"userspace" governor. This is the same interface
30316 + as known from the.4.-kernel patches for CPUFreq, and offers
30317 + the same functionality as long as "userspace" is the
30318 + selected governor for the specified CPU.
30320 + For details, take a look at linux/Documentation/cpufreq.
30322 + If in doubt, say N.
30323 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
30324 +++ linux-2.4.25/drivers/cpufreq/Makefile 2004-03-31 17:15:09.000000000 +0200
30325 @@ -0,0 +1,4 @@
30326 +#CPUfreq governors and cross-arch helpers
30327 +obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
30328 +obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o
30329 +obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o
30330 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
30331 +++ linux-2.4.25/drivers/cpufreq/cpufreq.c 2004-03-31 17:15:09.000000000 +0200
30332 @@ -0,0 +1,720 @@
30334 + * linux/kernel/cpufreq.c
30336 + * Copyright (C) 2001 Russell King
30337 + * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
30339 + * This program is free software; you can redistribute it and/or modify
30340 + * it under the terms of the GNU General Public License version 2 as
30341 + * published by the Free Software Foundation.
30343 + */
30345 +#include <linux/kernel.h>
30346 +#include <linux/module.h>
30347 +#include <linux/init.h>
30348 +#include <linux/notifier.h>
30349 +#include <linux/cpufreq.h>
30350 +#include <linux/delay.h>
30351 +#include <linux/interrupt.h>
30352 +#include <linux/spinlock.h>
30353 +#include <linux/slab.h>
30355 +#include <asm/semaphore.h>
30356 +/**
30357 + * The "cpufreq driver" - the arch- or hardware-dependend low
30358 + * level driver of CPUFreq support, and its spinlock. This lock
30359 + * also protects the cpufreq_cpu_data array.
30360 + */
30361 +static struct cpufreq_driver *cpufreq_driver;
30362 +static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
30363 +static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED;
30365 +/* internal prototype */
30366 +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
30369 +/**
30370 + * Two notifier lists: the "policy" list is involved in the
30371 + * validation process for a new CPU frequency policy; the
30372 + * "transition" list for kernel code that needs to handle
30373 + * changes to devices when the CPU clock speed changes.
30374 + * The mutex locks both lists.
30375 + */
30376 +static struct notifier_block *cpufreq_policy_notifier_list;
30377 +static struct notifier_block *cpufreq_transition_notifier_list;
30378 +static DECLARE_RWSEM (cpufreq_notifier_rwsem);
30381 +static LIST_HEAD(cpufreq_governor_list);
30382 +static DECLARE_MUTEX (cpufreq_governor_sem);
30385 + * backport info:
30386 + * we don't have a kobj we can use for ref-counting, so use a
30387 + * "unsigned int policy->use_count" and an "unload_sem" [idea from
30388 + * Pat Mochel's struct driver unload_sem] for proper reference counting.
30389 + */
30391 +static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
30393 + struct cpufreq_policy *data;
30394 + unsigned long flags;
30396 + if (cpu >= NR_CPUS)
30397 + goto err_out;
30399 + /* get the cpufreq driver */
30400 + spin_lock_irqsave(&cpufreq_driver_lock, flags);
30402 + if (!cpufreq_driver)
30403 + goto err_out_unlock;
30405 + /* get the CPU */
30406 + data = cpufreq_cpu_data[cpu];
30408 + if (!data)
30409 + goto err_out_unlock;
30411 + if (!data->use_count)
30412 + goto err_out_unlock;
30414 + data->use_count += 1;
30416 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30418 + return data;
30420 + err_out_unlock:
30421 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30422 + err_out:
30423 + return NULL;
30426 +static void cpufreq_cpu_put(struct cpufreq_policy *data)
30428 + unsigned long flags;
30430 + spin_lock_irqsave(&cpufreq_driver_lock, flags);
30431 + data->use_count -= 1;
30432 + if (!data->use_count) {
30433 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30434 + up(&data->unload_sem);
30435 + return;
30437 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30440 +/*********************************************************************
30441 + * SYSFS INTERFACE *
30442 + *********************************************************************/
30444 +/**
30445 + * cpufreq_parse_governor - parse a governor string
30446 + */
30447 +int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
30448 + struct cpufreq_governor **governor)
30450 + if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
30451 + *policy = CPUFREQ_POLICY_PERFORMANCE;
30452 + return 0;
30453 + } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
30454 + *policy = CPUFREQ_POLICY_POWERSAVE;
30455 + return 0;
30456 + } else {
30457 + struct cpufreq_governor *t;
30458 + down(&cpufreq_governor_sem);
30459 + if (!cpufreq_driver || !cpufreq_driver->target)
30460 + goto out;
30461 + list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
30462 + if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
30463 + *governor = t;
30464 + *policy = CPUFREQ_POLICY_GOVERNOR;
30465 + up(&cpufreq_governor_sem);
30466 + return 0;
30469 + out:
30470 + up(&cpufreq_governor_sem);
30472 + return -EINVAL;
30474 +EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
30477 +/* backport info:
30478 + * all the sysfs stuff is missing -- of course
30479 + */
30481 +/**
30482 + * cpufreq_add_dev - add a CPU device
30484 + * Adds the cpufreq interface for a CPU device.
30485 + */
30486 +static int cpufreq_add_dev (unsigned int cpu)
30488 + int ret = 0;
30489 + struct cpufreq_policy new_policy;
30490 + struct cpufreq_policy *policy;
30491 + unsigned long flags;
30493 + policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
30494 + if (!policy)
30495 + return -ENOMEM;
30496 + memset(policy, 0, sizeof(struct cpufreq_policy));
30498 + policy->cpu = cpu;
30499 + policy->use_count = 1;
30500 + init_MUTEX_LOCKED(&policy->lock);
30501 + init_MUTEX_LOCKED(&policy->unload_sem);
30503 + /* call driver. From then on the cpufreq must be able
30504 + * to accept all calls to ->verify and ->setpolicy for this CPU
30505 + */
30506 + ret = cpufreq_driver->init(policy);
30507 + if (ret)
30508 + goto err_out;
30510 + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
30512 + spin_lock_irqsave(&cpufreq_driver_lock, flags);
30513 + cpufreq_cpu_data[cpu] = policy;
30514 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30516 + up(&policy->lock);
30518 + /* set default policy */
30519 + ret = cpufreq_set_policy(&new_policy);
30520 + if (ret)
30521 + goto err_out_unregister;
30523 + return 0;
30526 + err_out_unregister:
30527 + spin_lock_irqsave(&cpufreq_driver_lock, flags);
30528 + cpufreq_cpu_data[cpu] = NULL;
30529 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30531 + err_out:
30532 + kfree(policy);
30533 + return ret;
30537 +/**
30538 + * cpufreq_remove_dev - remove a CPU device
30540 + * Removes the cpufreq interface for a CPU device.
30541 + */
30542 +static int cpufreq_remove_dev (unsigned int cpu)
30544 + unsigned long flags;
30545 + struct cpufreq_policy *data;
30547 + spin_lock_irqsave(&cpufreq_driver_lock, flags);
30548 + data = cpufreq_cpu_data[cpu];
30549 + if (!data) {
30550 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30551 + return -EINVAL;
30553 + cpufreq_cpu_data[cpu] = NULL;
30555 + data->use_count -= 1;
30556 + if (!data->use_count) {
30557 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30558 + up(&data->unload_sem);
30559 + } else {
30560 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
30561 + /* this will sleep until data->use_count gets to zero */
30562 + down(&data->unload_sem);
30563 + up(&data->unload_sem);
30566 + if (cpufreq_driver->target)
30567 + __cpufreq_governor(data, CPUFREQ_GOV_STOP);
30569 + if (cpufreq_driver->exit)
30570 + cpufreq_driver->exit(data);
30572 + kfree(data);
30574 + return 0;
30578 +/*********************************************************************
30579 + * NOTIFIER LISTS INTERFACE *
30580 + *********************************************************************/
30582 +/**
30583 + * cpufreq_register_notifier - register a driver with cpufreq
30584 + * @nb: notifier function to register
30585 + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
30587 + * Add a driver to one of two lists: either a list of drivers that
30588 + * are notified about clock rate changes (once before and once after
30589 + * the transition), or a list of drivers that are notified about
30590 + * changes in cpufreq policy.
30592 + * This function may sleep, and has the same return conditions as
30593 + * notifier_chain_register.
30594 + */
30595 +int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
30597 + int ret;
30599 + down_write(&cpufreq_notifier_rwsem);
30600 + switch (list) {
30601 + case CPUFREQ_TRANSITION_NOTIFIER:
30602 + ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
30603 + break;
30604 + case CPUFREQ_POLICY_NOTIFIER:
30605 + ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb);
30606 + break;
30607 + default:
30608 + ret = -EINVAL;
30610 + up_write(&cpufreq_notifier_rwsem);
30612 + return ret;
30614 +EXPORT_SYMBOL(cpufreq_register_notifier);
30617 +/**
30618 + * cpufreq_unregister_notifier - unregister a driver with cpufreq
30619 + * @nb: notifier block to be unregistered
30620 + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
30622 + * Remove a driver from the CPU frequency notifier list.
30624 + * This function may sleep, and has the same return conditions as
30625 + * notifier_chain_unregister.
30626 + */
30627 +int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
30629 + int ret;
30631 + down_write(&cpufreq_notifier_rwsem);
30632 + switch (list) {
30633 + case CPUFREQ_TRANSITION_NOTIFIER:
30634 + ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
30635 + break;
30636 + case CPUFREQ_POLICY_NOTIFIER:
30637 + ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb);
30638 + break;
30639 + default:
30640 + ret = -EINVAL;
30642 + up_write(&cpufreq_notifier_rwsem);
30644 + return ret;
30646 +EXPORT_SYMBOL(cpufreq_unregister_notifier);
30649 +/*********************************************************************
30650 + * GOVERNORS *
30651 + *********************************************************************/
30654 +int __cpufreq_driver_target(struct cpufreq_policy *policy,
30655 + unsigned int target_freq,
30656 + unsigned int relation)
30658 + return cpufreq_driver->target(policy, target_freq, relation);
30660 +EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
30663 +int cpufreq_driver_target(struct cpufreq_policy *policy,
30664 + unsigned int target_freq,
30665 + unsigned int relation)
30667 + unsigned int ret;
30669 + policy = cpufreq_cpu_get(policy->cpu);
30670 + if (!policy)
30671 + return -EINVAL;
30673 + down(&policy->lock);
30675 + ret = __cpufreq_driver_target(policy, target_freq, relation);
30677 + up(&policy->lock);
30679 + cpufreq_cpu_put(policy);
30681 + return ret;
30683 +EXPORT_SYMBOL_GPL(cpufreq_driver_target);
30686 +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
30688 + int ret = 0;
30690 + switch (policy->policy) {
30691 + case CPUFREQ_POLICY_POWERSAVE:
30692 + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
30693 + ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
30695 + break;
30696 + case CPUFREQ_POLICY_PERFORMANCE:
30697 + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
30698 + ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
30700 + break;
30701 + case CPUFREQ_POLICY_GOVERNOR:
30702 + ret = policy->governor->governor(policy, event);
30703 + break;
30704 + default:
30705 + ret = -EINVAL;
30708 + return ret;
30712 +int cpufreq_governor(unsigned int cpu, unsigned int event)
30714 + int ret = 0;
30715 + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
30717 + if (!policy)
30718 + return -EINVAL;
30720 + down(&policy->lock);
30721 + ret = __cpufreq_governor(policy, event);
30722 + up(&policy->lock);
30724 + cpufreq_cpu_put(policy);
30726 + return ret;
30728 +EXPORT_SYMBOL_GPL(cpufreq_governor);
30731 +int cpufreq_register_governor(struct cpufreq_governor *governor)
30733 + struct cpufreq_governor *t;
30735 + if (!governor)
30736 + return -EINVAL;
30738 + if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN))
30739 + return -EBUSY;
30740 + if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
30741 + return -EBUSY;
30743 + down(&cpufreq_governor_sem);
30745 + list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
30746 + if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
30747 + up(&cpufreq_governor_sem);
30748 + return -EBUSY;
30751 + list_add(&governor->governor_list, &cpufreq_governor_list);
30753 + up(&cpufreq_governor_sem);
30755 + return 0;
30757 +EXPORT_SYMBOL_GPL(cpufreq_register_governor);
30760 +void cpufreq_unregister_governor(struct cpufreq_governor *governor)
30762 + /* backport info:
30763 + * As the module usage count isn't assured in 2.4., check for removal
30764 + * of running cpufreq governor
30765 + */
30766 + unsigned int i;
30768 + if (!governor)
30769 + return;
30771 + down(&cpufreq_governor_sem);
30773 + for (i=0; i<NR_CPUS; i++) {
30774 + struct cpufreq_policy *policy = cpufreq_cpu_get(i);
30775 + if (!policy)
30776 + goto done;
30777 + down(&policy->lock);
30779 + if (policy->policy != CPUFREQ_POLICY_GOVERNOR)
30780 + goto unlock_done;
30781 + if (policy->governor != governor)
30782 + goto unlock_done;
30784 + /* stop old one, start performance [always present] */
30785 + __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
30786 + policy->policy = CPUFREQ_POLICY_PERFORMANCE;
30787 + __cpufreq_governor(policy, CPUFREQ_GOV_START);
30789 + unlock_done:
30790 + up(&policy->lock);
30791 + done:
30792 + cpufreq_cpu_put(policy);
30794 + list_del(&governor->governor_list);
30795 + up(&cpufreq_governor_sem);
30796 + return;
30798 +EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
30802 +/*********************************************************************
30803 + * POLICY INTERFACE *
30804 + *********************************************************************/
30806 +/**
30807 + * cpufreq_get_policy - get the current cpufreq_policy
30808 + * @policy: struct cpufreq_policy into which the current cpufreq_policy is written
30810 + * Reads the current cpufreq policy.
30811 + */
30812 +int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
30814 + struct cpufreq_policy *cpu_policy;
30815 + if (!policy)
30816 + return -EINVAL;
30818 + cpu_policy = cpufreq_cpu_get(cpu);
30819 + if (!cpu_policy)
30820 + return -EINVAL;
30822 + down(&cpu_policy->lock);
30823 + memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
30824 + up(&cpu_policy->lock);
30826 + cpufreq_cpu_put(cpu_policy);
30828 + return 0;
30830 +EXPORT_SYMBOL(cpufreq_get_policy);
30833 +/**
30834 + * cpufreq_set_policy - set a new CPUFreq policy
30835 + * @policy: policy to be set.
30837 + * Sets a new CPU frequency and voltage scaling policy.
30838 + */
30839 +int cpufreq_set_policy(struct cpufreq_policy *policy)
30841 + int ret = 0;
30842 + struct cpufreq_policy *data;
30844 + if (!policy)
30845 + return -EINVAL;
30847 + data = cpufreq_cpu_get(policy->cpu);
30848 + if (!data)
30849 + return -EINVAL;
30851 + /* lock this CPU */
30852 + down(&data->lock);
30854 + memcpy(&policy->cpuinfo,
30855 + &data->cpuinfo,
30856 + sizeof(struct cpufreq_cpuinfo));
30858 + /* verify the cpu speed can be set within this limit */
30859 + ret = cpufreq_driver->verify(policy);
30860 + if (ret)
30861 + goto error_out;
30863 + down_read(&cpufreq_notifier_rwsem);
30865 + /* adjust if necessary - all reasons */
30866 + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
30867 + policy);
30869 + /* adjust if necessary - hardware incompatibility*/
30870 + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE,
30871 + policy);
30873 + /* verify the cpu speed can be set within this limit,
30874 + which might be different to the first one */
30875 + ret = cpufreq_driver->verify(policy);
30876 + if (ret) {
30877 + up_read(&cpufreq_notifier_rwsem);
30878 + goto error_out;
30881 + /* notification of the new policy */
30882 + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
30883 + policy);
30885 + up_read(&cpufreq_notifier_rwsem);
30887 + data->min = policy->min;
30888 + data->max = policy->max;
30890 + if (cpufreq_driver->setpolicy) {
30891 + data->policy = policy->policy;
30892 + ret = cpufreq_driver->setpolicy(policy);
30893 + } else {
30894 + if ((policy->policy != data->policy) ||
30895 + ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) {
30896 + /* save old, working values */
30897 + unsigned int old_pol = data->policy;
30898 + struct cpufreq_governor *old_gov = data->governor;
30900 + /* end old governor */
30901 + __cpufreq_governor(data, CPUFREQ_GOV_STOP);
30903 + /* start new governor */
30904 + data->policy = policy->policy;
30905 + data->governor = policy->governor;
30906 + if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
30907 + /* new governor failed, so re-start old one */
30908 + data->policy = old_pol;
30909 + data->governor = old_gov;
30910 + __cpufreq_governor(data, CPUFREQ_GOV_START);
30912 + /* might be a policy change, too, so fall through */
30914 + __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
30917 + error_out:
30918 + up(&data->lock);
30919 + cpufreq_cpu_put(data);
30921 + return ret;
30923 +EXPORT_SYMBOL(cpufreq_set_policy);
30927 +/*********************************************************************
30928 + * EXTERNALLY AFFECTING FREQUENCY CHANGES *
30929 + *********************************************************************/
30931 +/**
30932 + * adjust_jiffies - adjust the system "loops_per_jiffy"
30934 + * This function alters the system "loops_per_jiffy" for the clock
30935 + * speed change. Note that loops_per_jiffy cannot be updated on SMP
30936 + * systems as each CPU might be scaled differently. So, use the arch
30937 + * per-CPU loops_per_jiffy value wherever possible.
30938 + */
30939 +#ifndef CONFIG_SMP
30940 +static unsigned long l_p_j_ref = 0;
30941 +static unsigned int l_p_j_ref_freq = 0;
30943 +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
30945 + if (!l_p_j_ref_freq) {
30946 + l_p_j_ref = loops_per_jiffy;
30947 + l_p_j_ref_freq = ci->old;
30949 + if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
30950 + (val == CPUFREQ_POSTCHANGE && ci->old > ci->new))
30951 + loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
30953 +#else
30954 +#define adjust_jiffies(x...) do {} while (0)
30955 +#endif
30958 +/**
30959 + * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
30961 + * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
30962 + * twice on all CPU frequency changes that have external effects.
30963 + */
30964 +void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
30966 + down_read(&cpufreq_notifier_rwsem);
30967 + switch (state) {
30968 + case CPUFREQ_PRECHANGE:
30969 + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
30970 + adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
30971 + break;
30972 + case CPUFREQ_POSTCHANGE:
30973 + adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
30974 + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
30975 + cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
30976 + break;
30978 + up_read(&cpufreq_notifier_rwsem);
30980 +EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
30984 +/*********************************************************************
30985 + * REGISTER / UNREGISTER CPUFREQ DRIVER *
30986 + *********************************************************************/
30988 +/**
30989 + * cpufreq_register_driver - register a CPU Frequency driver
30990 + * @driver_data: A struct cpufreq_driver containing the values#
30991 + * submitted by the CPU Frequency driver.
30993 + * Registers a CPU Frequency driver to this core code. This code
30994 + * returns zero on success, -EBUSY when another driver got here first
30995 + * (and isn't unregistered in the meantime).
30997 + */
30998 +int cpufreq_register_driver(struct cpufreq_driver *driver_data)
31000 + unsigned long flags;
31001 + unsigned int i;
31003 + if (!driver_data || !driver_data->verify || !driver_data->init ||
31004 + ((!driver_data->setpolicy) && (!driver_data->target)))
31005 + return -EINVAL;
31007 + spin_lock_irqsave(&cpufreq_driver_lock, flags);
31008 + if (cpufreq_driver) {
31009 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
31010 + return -EBUSY;
31012 + cpufreq_driver = driver_data;
31013 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
31015 + for (i=0; i<NR_CPUS; i++) {
31016 + if (cpu_online(i))
31017 + cpufreq_add_dev(i);
31020 + return 0;
31022 +EXPORT_SYMBOL_GPL(cpufreq_register_driver);
31025 +/**
31026 + * cpufreq_unregister_driver - unregister the current CPUFreq driver
31028 + * Unregister the current CPUFreq driver. Only call this if you have
31029 + * the right to do so, i.e. if you have succeeded in initialising before!
31030 + * Returns zero if successful, and -EINVAL if the cpufreq_driver is
31031 + * currently not initialised.
31032 + */
31033 +int cpufreq_unregister_driver(struct cpufreq_driver *driver)
31035 + unsigned long flags;
31036 + unsigned int i;
31038 + if (!cpufreq_driver || (driver != cpufreq_driver))
31039 + return -EINVAL;
31041 + for (i=0; i<NR_CPUS; i++) {
31042 + if (cpu_online(i))
31043 + cpufreq_remove_dev(i);
31046 + spin_lock_irqsave(&cpufreq_driver_lock, flags);
31047 + cpufreq_driver = NULL;
31048 + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
31050 + return 0;
31052 +EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
31053 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
31054 +++ linux-2.4.25/drivers/cpufreq/freq_table.c 2004-03-31 17:15:09.000000000 +0200
31055 @@ -0,0 +1,203 @@
31057 + * linux/drivers/cpufreq/freq_table.c
31059 + * Copyright (C) 2002 - 2003 Dominik Brodowski
31060 + */
31062 +#include <linux/kernel.h>
31063 +#include <linux/module.h>
31064 +#include <linux/init.h>
31065 +#include <linux/cpufreq.h>
31067 +/*********************************************************************
31068 + * FREQUENCY TABLE HELPERS *
31069 + *********************************************************************/
31071 +int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
31072 + struct cpufreq_frequency_table *table)
31074 + unsigned int min_freq = ~0;
31075 + unsigned int max_freq = 0;
31076 + unsigned int i = 0;
31078 + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
31079 + unsigned int freq = table[i].frequency;
31080 + if (freq == CPUFREQ_ENTRY_INVALID)
31081 + continue;
31082 + if (freq < min_freq)
31083 + min_freq = freq;
31084 + if (freq > max_freq)
31085 + max_freq = freq;
31088 + policy->min = policy->cpuinfo.min_freq = min_freq;
31089 + policy->max = policy->cpuinfo.max_freq = max_freq;
31091 + if (policy->min == ~0)
31092 + return -EINVAL;
31093 + else
31094 + return 0;
31096 +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
31099 +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
31100 + struct cpufreq_frequency_table *table)
31102 + unsigned int next_larger = ~0;
31103 + unsigned int i = 0;
31104 + unsigned int count = 0;
31106 + if (!cpu_online(policy->cpu))
31107 + return -EINVAL;
31109 + cpufreq_verify_within_limits(policy,
31110 + policy->cpuinfo.min_freq,
31111 + policy->cpuinfo.max_freq);
31113 + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
31114 + unsigned int freq = table[i].frequency;
31115 + if (freq == CPUFREQ_ENTRY_INVALID)
31116 + continue;
31117 + if ((freq >= policy->min) && (freq <= policy->max))
31118 + count++;
31119 + else if ((next_larger > freq) && (freq > policy->max))
31120 + next_larger = freq;
31123 + if (!count)
31124 + policy->max = next_larger;
31126 + cpufreq_verify_within_limits(policy,
31127 + policy->cpuinfo.min_freq,
31128 + policy->cpuinfo.max_freq);
31130 + return 0;
31132 +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
31135 +int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
31136 + struct cpufreq_frequency_table *table,
31137 + unsigned int target_freq,
31138 + unsigned int relation,
31139 + unsigned int *index)
31141 + struct cpufreq_frequency_table optimal = { .index = ~0, };
31142 + struct cpufreq_frequency_table suboptimal = { .index = ~0, };
31143 + unsigned int i;
31145 + switch (relation) {
31146 + case CPUFREQ_RELATION_H:
31147 + optimal.frequency = 0;
31148 + suboptimal.frequency = ~0;
31149 + break;
31150 + case CPUFREQ_RELATION_L:
31151 + optimal.frequency = ~0;
31152 + suboptimal.frequency = 0;
31153 + break;
31156 + if (!cpu_online(policy->cpu))
31157 + return -EINVAL;
31159 + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
31160 + unsigned int freq = table[i].frequency;
31161 + if (freq == CPUFREQ_ENTRY_INVALID)
31162 + continue;
31163 + if ((freq < policy->min) || (freq > policy->max))
31164 + continue;
31165 + switch(relation) {
31166 + case CPUFREQ_RELATION_H:
31167 + if (freq <= target_freq) {
31168 + if (freq >= optimal.frequency) {
31169 + optimal.frequency = freq;
31170 + optimal.index = i;
31172 + } else {
31173 + if (freq <= suboptimal.frequency) {
31174 + suboptimal.frequency = freq;
31175 + suboptimal.index = i;
31178 + break;
31179 + case CPUFREQ_RELATION_L:
31180 + if (freq >= target_freq) {
31181 + if (freq <= optimal.frequency) {
31182 + optimal.frequency = freq;
31183 + optimal.index = i;
31185 + } else {
31186 + if (freq >= suboptimal.frequency) {
31187 + suboptimal.frequency = freq;
31188 + suboptimal.index = i;
31191 + break;
31194 + if (optimal.index > i) {
31195 + if (suboptimal.index > i)
31196 + return -EINVAL;
31197 + *index = suboptimal.index;
31198 + } else
31199 + *index = optimal.index;
31201 + return 0;
31203 +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
31205 +static struct cpufreq_frequency_table *show_table[NR_CPUS];
31206 +/**
31207 + * show_scaling_governor - show the current policy for the specified CPU
31208 + */
31209 +static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
31211 + unsigned int i = 0;
31212 + unsigned int cpu = policy->cpu;
31213 + ssize_t count = 0;
31214 + struct cpufreq_frequency_table *table;
31216 + if (!show_table[cpu])
31217 + return -ENODEV;
31219 + table = show_table[cpu];
31221 + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
31222 + if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
31223 + continue;
31224 + count += sprintf(&buf[count], "%d ", table[i].frequency);
31226 + count += sprintf(&buf[count], "\n");
31228 + return count;
31232 +struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
31233 + .attr = { .name = "scaling_available_frequencies", .mode = 0444 },
31234 + .show = show_available_freqs,
31236 +EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
31239 + * if you use these, you must assure that the frequency table is valid
31240 + * all the time between get_attr and put_attr!
31241 + */
31242 +void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
31243 + unsigned int cpu)
31245 + show_table[cpu] = table;
31247 +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
31249 +void cpufreq_frequency_table_put_attr(unsigned int cpu)
31251 + show_table[cpu] = NULL;
31253 +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
31256 +MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
31257 +MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
31258 +MODULE_LICENSE ("GPL");
31259 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
31260 +++ linux-2.4.25/drivers/cpufreq/proc_intf.c 2004-03-31 17:15:09.000000000 +0200
31261 @@ -0,0 +1,244 @@
31263 + * linux/drivers/cpufreq/proc_intf.c
31265 + * Copyright (C) 2002 - 2003 Dominik Brodowski
31266 + */
31268 +#include <linux/kernel.h>
31269 +#include <linux/module.h>
31270 +#include <linux/init.h>
31271 +#include <linux/cpufreq.h>
31272 +#include <linux/ctype.h>
31273 +#include <linux/proc_fs.h>
31274 +#include <asm/uaccess.h>
31277 +/**
31278 + * cpufreq_parse_policy - parse a policy string
31279 + * @input_string: the string to parse.
31280 + * @policy: the policy written inside input_string
31282 + * This function parses a "policy string" - something the user echo'es into
31283 + * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy.
31284 + * If there are invalid/missing entries, they are replaced with current
31285 + * cpufreq policy.
31286 + */
31287 +static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy)
31289 + unsigned int min = 0;
31290 + unsigned int max = 0;
31291 + unsigned int cpu = 0;
31292 + char str_governor[16];
31293 + struct cpufreq_policy current_policy;
31294 + unsigned int result = -EFAULT;
31296 + if (!policy)
31297 + return -EINVAL;
31299 + policy->min = 0;
31300 + policy->max = 0;
31301 + policy->policy = 0;
31302 + policy->cpu = CPUFREQ_ALL_CPUS;
31304 + if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4)
31306 + policy->min = min;
31307 + policy->max = max;
31308 + policy->cpu = cpu;
31309 + result = 0;
31310 + goto scan_policy;
31312 + if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4)
31314 + if (!cpufreq_get_policy(&current_policy, cpu)) {
31315 + policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
31316 + policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
31317 + policy->cpu = cpu;
31318 + result = 0;
31319 + goto scan_policy;
31323 + if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3)
31325 + policy->min = min;
31326 + policy->max = max;
31327 + result = 0;
31328 + goto scan_policy;
31331 + if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3)
31333 + if (!cpufreq_get_policy(&current_policy, cpu)) {
31334 + policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
31335 + policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
31336 + result = 0;
31337 + goto scan_policy;
31341 + return -EINVAL;
31343 +scan_policy:
31344 + result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor);
31346 + return result;
31349 +/**
31350 + * cpufreq_proc_read - read /proc/cpufreq
31352 + * This function prints out the current cpufreq policy.
31353 + */
31354 +static int cpufreq_proc_read (
31355 + char *page,
31356 + char **start,
31357 + off_t off,
31358 + int count,
31359 + int *eof,
31360 + void *data)
31362 + char *p = page;
31363 + int len = 0;
31364 + struct cpufreq_policy policy;
31365 + unsigned int min_pctg = 0;
31366 + unsigned int max_pctg = 0;
31367 + unsigned int i = 0;
31369 + if (off != 0)
31370 + goto end;
31372 + p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n");
31373 + for (i=0;i<NR_CPUS;i++) {
31374 + if (!cpu_online(i))
31375 + continue;
31377 + if (cpufreq_get_policy(&policy, i))
31378 + continue;
31380 + if (!policy.cpuinfo.max_freq)
31381 + continue;
31383 + min_pctg = (policy.min * 100) / policy.cpuinfo.max_freq;
31384 + max_pctg = (policy.max * 100) / policy.cpuinfo.max_freq;
31386 + p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
31387 + i , policy.min, min_pctg, policy.max, max_pctg);
31388 + switch (policy.policy) {
31389 + case CPUFREQ_POLICY_POWERSAVE:
31390 + p += sprintf(p, "powersave\n");
31391 + break;
31392 + case CPUFREQ_POLICY_PERFORMANCE:
31393 + p += sprintf(p, "performance\n");
31394 + break;
31395 + case CPUFREQ_POLICY_GOVERNOR:
31396 + p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
31397 + break;
31398 + default:
31399 + p += sprintf(p, "INVALID\n");
31400 + break;
31403 +end:
31404 + len = (p - page);
31405 + if (len <= off+count)
31406 + *eof = 1;
31407 + *start = page + off;
31408 + len -= off;
31409 + if (len>count)
31410 + len = count;
31411 + if (len<0)
31412 + len = 0;
31414 + return len;
31418 +/**
31419 + * cpufreq_proc_write - handles writing into /proc/cpufreq
31421 + * This function calls the parsing script and then sets the policy
31422 + * accordingly.
31423 + */
31424 +static int cpufreq_proc_write (
31425 + struct file *file,
31426 + const char *buffer,
31427 + unsigned long count,
31428 + void *data)
31430 + int result = 0;
31431 + char proc_string[42] = {'\0'};
31432 + struct cpufreq_policy policy;
31433 + unsigned int i = 0;
31436 + if ((count > sizeof(proc_string) - 1))
31437 + return -EINVAL;
31439 + if (copy_from_user(proc_string, buffer, count))
31440 + return -EFAULT;
31442 + proc_string[count] = '\0';
31444 + result = cpufreq_parse_policy(proc_string, &policy);
31445 + if (result)
31446 + return -EFAULT;
31448 + if (policy.cpu == CPUFREQ_ALL_CPUS)
31450 + for (i=0; i<NR_CPUS; i++)
31452 + policy.cpu = i;
31453 + if (cpu_online(i))
31454 + cpufreq_set_policy(&policy);
31456 + }
31457 + else
31458 + cpufreq_set_policy(&policy);
31460 + return count;
31464 +/**
31465 + * cpufreq_proc_init - add "cpufreq" to the /proc root directory
31467 + * This function adds "cpufreq" to the /proc root directory.
31468 + */
31469 +static int __init cpufreq_proc_init (void)
31471 + struct proc_dir_entry *entry = NULL;
31473 + /* are these acceptable values? */
31474 + entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR,
31475 + &proc_root);
31477 + if (!entry) {
31478 + printk(KERN_ERR "unable to create /proc/cpufreq entry\n");
31479 + return -EIO;
31480 + } else {
31481 + entry->read_proc = cpufreq_proc_read;
31482 + entry->write_proc = cpufreq_proc_write;
31485 + return 0;
31489 +/**
31490 + * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory.
31492 + * This function removes "cpufreq" from the /proc root directory.
31493 + */
31494 +static void __exit cpufreq_proc_exit (void)
31496 + remove_proc_entry("cpufreq", &proc_root);
31497 + return;
31500 +MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
31501 +MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface");
31502 +MODULE_LICENSE ("GPL");
31504 +module_init(cpufreq_proc_init);
31505 +module_exit(cpufreq_proc_exit);
31506 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
31507 +++ linux-2.4.25/drivers/cpufreq/userspace.c 2004-03-31 17:15:09.000000000 +0200
31508 @@ -0,0 +1,591 @@
31510 + * drivers/cpufreq/userspace.c
31512 + * Copyright (C) 2001 Russell King
31513 + * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
31515 + * $Id: userspace.c,v 1.4 2003/03/07 10:30:20 db Exp $
31517 + * This program is free software; you can redistribute it and/or modify
31518 + * it under the terms of the GNU General Public License version 2 as
31519 + * published by the Free Software Foundation.
31521 + */
31523 +#include <linux/kernel.h>
31524 +#include <linux/module.h>
31525 +#include <linux/smp.h>
31526 +#include <linux/init.h>
31527 +#include <linux/spinlock.h>
31528 +#include <linux/interrupt.h>
31529 +#include <linux/ctype.h>
31530 +#include <linux/cpufreq.h>
31531 +#include <linux/sysctl.h>
31532 +#include <linux/types.h>
31533 +#include <linux/fs.h>
31534 +#include <linux/sysfs.h>
31536 +#include <asm/uaccess.h>
31538 +#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \
31539 + .ctl_name = CPU_NR_FREQ_MAX, \
31540 + .data = &cpu_max_freq[cpunr], \
31541 + .procname = "speed-max", \
31542 + .maxlen = sizeof(cpu_max_freq[cpunr]),\
31543 + .mode = 0444, \
31544 + .proc_handler = proc_dointvec, }
31546 +#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \
31547 + .ctl_name = CPU_NR_FREQ_MIN, \
31548 + .data = &cpu_min_freq[cpunr], \
31549 + .procname = "speed-min", \
31550 + .maxlen = sizeof(cpu_min_freq[cpunr]),\
31551 + .mode = 0444, \
31552 + .proc_handler = proc_dointvec, }
31554 +#define CTL_CPU_VARS_SPEED(cpunr) { \
31555 + .ctl_name = CPU_NR_FREQ, \
31556 + .procname = "speed", \
31557 + .mode = 0644, \
31558 + .proc_handler = cpufreq_procctl, \
31559 + .strategy = cpufreq_sysctl, \
31560 + .extra1 = (void*) (cpunr), }
31562 +#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\
31563 + CTL_CPU_VARS_SPEED_MAX(cpunr), \
31564 + CTL_CPU_VARS_SPEED_MIN(cpunr), \
31565 + CTL_CPU_VARS_SPEED(cpunr), \
31566 + { .ctl_name = 0, }, }
31568 +/* the ctl_table entry for each CPU */
31569 +#define CPU_ENUM(s) { \
31570 + .ctl_name = (CPU_NR + s), \
31571 + .procname = #s, \
31572 + .mode = 0555, \
31573 + .child = ctl_cpu_vars_##s }
31575 +/**
31576 + * A few values needed by the userspace governor
31577 + */
31578 +static unsigned int cpu_max_freq[NR_CPUS];
31579 +static unsigned int cpu_min_freq[NR_CPUS];
31580 +static unsigned int cpu_cur_freq[NR_CPUS];
31581 +static unsigned int cpu_is_managed[NR_CPUS];
31582 +static struct cpufreq_policy current_policy[NR_CPUS];
31584 +static DECLARE_MUTEX (userspace_sem);
31587 +/* keep track of frequency transitions */
31588 +static int
31589 +userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
31590 + void *data)
31592 + struct cpufreq_freqs *freq = data;
31594 + cpu_cur_freq[freq->cpu] = freq->new;
31596 + return 0;
31599 +static struct notifier_block userspace_cpufreq_notifier_block = {
31600 + .notifier_call = userspace_cpufreq_notifier
31604 +/**
31605 + * cpufreq_set - set the CPU frequency
31606 + * @freq: target frequency in kHz
31607 + * @cpu: CPU for which the frequency is to be set
31609 + * Sets the CPU frequency to freq.
31610 + */
31611 +int cpufreq_set(unsigned int freq, unsigned int cpu)
31613 + int ret = -EINVAL;
31615 + down(&userspace_sem);
31616 + if (!cpu_is_managed[cpu])
31617 + goto err;
31619 + if (freq < cpu_min_freq[cpu])
31620 + freq = cpu_min_freq[cpu];
31621 + if (freq > cpu_max_freq[cpu])
31622 + freq = cpu_max_freq[cpu];
31624 + ret = cpufreq_driver_target(&current_policy[cpu], freq,
31625 + CPUFREQ_RELATION_L);
31627 + err:
31628 + up(&userspace_sem);
31629 + return ret;
31631 +EXPORT_SYMBOL_GPL(cpufreq_set);
31634 +/**
31635 + * cpufreq_setmax - set the CPU to the maximum frequency
31636 + * @cpu - affected cpu;
31638 + * Sets the CPU frequency to the maximum frequency supported by
31639 + * this CPU.
31640 + */
31641 +int cpufreq_setmax(unsigned int cpu)
31643 + if (!cpu_is_managed[cpu] || !cpu_online(cpu))
31644 + return -EINVAL;
31645 + return cpufreq_set(cpu_max_freq[cpu], cpu);
31647 +EXPORT_SYMBOL_GPL(cpufreq_setmax);
31650 +/**
31651 + * cpufreq_get - get the current CPU frequency (in kHz)
31652 + * @cpu: CPU number
31654 + * Get the CPU current (static) CPU frequency
31655 + */
31656 +unsigned int cpufreq_get(unsigned int cpu)
31658 + return cpu_cur_freq[cpu];
31660 +EXPORT_SYMBOL(cpufreq_get);
31663 +#ifdef CONFIG_CPU_FREQ_24_API
31666 +/*********************** cpufreq_sysctl interface ********************/
31667 +static int
31668 +cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
31669 + void *buffer, size_t *lenp)
31671 + char buf[16], *p;
31672 + int cpu = (int) ctl->extra1;
31673 + int len, left = *lenp;
31675 + if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) {
31676 + *lenp = 0;
31677 + return 0;
31680 + if (write) {
31681 + unsigned int freq;
31683 + len = left;
31684 + if (left > sizeof(buf))
31685 + left = sizeof(buf);
31686 + if (copy_from_user(buf, buffer, left))
31687 + return -EFAULT;
31688 + buf[sizeof(buf) - 1] = '\0';
31690 + freq = simple_strtoul(buf, &p, 0);
31691 + cpufreq_set(freq, cpu);
31692 + } else {
31693 + len = sprintf(buf, "%d\n", cpufreq_get(cpu));
31694 + if (len > left)
31695 + len = left;
31696 + if (copy_to_user(buffer, buf, len))
31697 + return -EFAULT;
31700 + *lenp = len;
31701 + filp->f_pos += len;
31702 + return 0;
31705 +static int
31706 +cpufreq_sysctl(ctl_table *table, int *name, int nlen,
31707 + void *oldval, size_t *oldlenp,
31708 + void *newval, size_t newlen, void **context)
31710 + int cpu = (int) table->extra1;
31712 + if (!cpu_online(cpu))
31713 + return -EINVAL;
31715 + if (oldval && oldlenp) {
31716 + size_t oldlen;
31718 + if (get_user(oldlen, oldlenp))
31719 + return -EFAULT;
31721 + if (oldlen != sizeof(unsigned int))
31722 + return -EINVAL;
31724 + if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
31725 + put_user(sizeof(unsigned int), oldlenp))
31726 + return -EFAULT;
31728 + if (newval && newlen) {
31729 + unsigned int freq;
31731 + if (newlen != sizeof(unsigned int))
31732 + return -EINVAL;
31734 + if (get_user(freq, (unsigned int *)newval))
31735 + return -EFAULT;
31737 + cpufreq_set(freq, cpu);
31739 + return 1;
31742 +/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */
31743 +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
31744 + CTL_TABLE_CPU_VARS(0);
31745 +#if NR_CPUS > 1
31746 + CTL_TABLE_CPU_VARS(1);
31747 +#endif
31748 +#if NR_CPUS > 2
31749 + CTL_TABLE_CPU_VARS(2);
31750 +#endif
31751 +#if NR_CPUS > 3
31752 + CTL_TABLE_CPU_VARS(3);
31753 +#endif
31754 +#if NR_CPUS > 4
31755 + CTL_TABLE_CPU_VARS(4);
31756 +#endif
31757 +#if NR_CPUS > 5
31758 + CTL_TABLE_CPU_VARS(5);
31759 +#endif
31760 +#if NR_CPUS > 6
31761 + CTL_TABLE_CPU_VARS(6);
31762 +#endif
31763 +#if NR_CPUS > 7
31764 + CTL_TABLE_CPU_VARS(7);
31765 +#endif
31766 +#if NR_CPUS > 8
31767 + CTL_TABLE_CPU_VARS(8);
31768 +#endif
31769 +#if NR_CPUS > 9
31770 + CTL_TABLE_CPU_VARS(9);
31771 +#endif
31772 +#if NR_CPUS > 10
31773 + CTL_TABLE_CPU_VARS(10);
31774 +#endif
31775 +#if NR_CPUS > 11
31776 + CTL_TABLE_CPU_VARS(11);
31777 +#endif
31778 +#if NR_CPUS > 12
31779 + CTL_TABLE_CPU_VARS(12);
31780 +#endif
31781 +#if NR_CPUS > 13
31782 + CTL_TABLE_CPU_VARS(13);
31783 +#endif
31784 +#if NR_CPUS > 14
31785 + CTL_TABLE_CPU_VARS(14);
31786 +#endif
31787 +#if NR_CPUS > 15
31788 + CTL_TABLE_CPU_VARS(15);
31789 +#endif
31790 +#if NR_CPUS > 16
31791 + CTL_TABLE_CPU_VARS(16);
31792 +#endif
31793 +#if NR_CPUS > 17
31794 + CTL_TABLE_CPU_VARS(17);
31795 +#endif
31796 +#if NR_CPUS > 18
31797 + CTL_TABLE_CPU_VARS(18);
31798 +#endif
31799 +#if NR_CPUS > 19
31800 + CTL_TABLE_CPU_VARS(19);
31801 +#endif
31802 +#if NR_CPUS > 20
31803 + CTL_TABLE_CPU_VARS(20);
31804 +#endif
31805 +#if NR_CPUS > 21
31806 + CTL_TABLE_CPU_VARS(21);
31807 +#endif
31808 +#if NR_CPUS > 22
31809 + CTL_TABLE_CPU_VARS(22);
31810 +#endif
31811 +#if NR_CPUS > 23
31812 + CTL_TABLE_CPU_VARS(23);
31813 +#endif
31814 +#if NR_CPUS > 24
31815 + CTL_TABLE_CPU_VARS(24);
31816 +#endif
31817 +#if NR_CPUS > 25
31818 + CTL_TABLE_CPU_VARS(25);
31819 +#endif
31820 +#if NR_CPUS > 26
31821 + CTL_TABLE_CPU_VARS(26);
31822 +#endif
31823 +#if NR_CPUS > 27
31824 + CTL_TABLE_CPU_VARS(27);
31825 +#endif
31826 +#if NR_CPUS > 28
31827 + CTL_TABLE_CPU_VARS(28);
31828 +#endif
31829 +#if NR_CPUS > 29
31830 + CTL_TABLE_CPU_VARS(29);
31831 +#endif
31832 +#if NR_CPUS > 30
31833 + CTL_TABLE_CPU_VARS(30);
31834 +#endif
31835 +#if NR_CPUS > 31
31836 + CTL_TABLE_CPU_VARS(31);
31837 +#endif
31838 +#if NR_CPUS > 32
31839 +#error please extend CPU enumeration
31840 +#endif
31842 +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
31843 +static ctl_table ctl_cpu_table[NR_CPUS + 1] = {
31844 + CPU_ENUM(0),
31845 +#if NR_CPUS > 1
31846 + CPU_ENUM(1),
31847 +#endif
31848 +#if NR_CPUS > 2
31849 + CPU_ENUM(2),
31850 +#endif
31851 +#if NR_CPUS > 3
31852 + CPU_ENUM(3),
31853 +#endif
31854 +#if NR_CPUS > 4
31855 + CPU_ENUM(4),
31856 +#endif
31857 +#if NR_CPUS > 5
31858 + CPU_ENUM(5),
31859 +#endif
31860 +#if NR_CPUS > 6
31861 + CPU_ENUM(6),
31862 +#endif
31863 +#if NR_CPUS > 7
31864 + CPU_ENUM(7),
31865 +#endif
31866 +#if NR_CPUS > 8
31867 + CPU_ENUM(8),
31868 +#endif
31869 +#if NR_CPUS > 9
31870 + CPU_ENUM(9),
31871 +#endif
31872 +#if NR_CPUS > 10
31873 + CPU_ENUM(10),
31874 +#endif
31875 +#if NR_CPUS > 11
31876 + CPU_ENUM(11),
31877 +#endif
31878 +#if NR_CPUS > 12
31879 + CPU_ENUM(12),
31880 +#endif
31881 +#if NR_CPUS > 13
31882 + CPU_ENUM(13),
31883 +#endif
31884 +#if NR_CPUS > 14
31885 + CPU_ENUM(14),
31886 +#endif
31887 +#if NR_CPUS > 15
31888 + CPU_ENUM(15),
31889 +#endif
31890 +#if NR_CPUS > 16
31891 + CPU_ENUM(16),
31892 +#endif
31893 +#if NR_CPUS > 17
31894 + CPU_ENUM(17),
31895 +#endif
31896 +#if NR_CPUS > 18
31897 + CPU_ENUM(18),
31898 +#endif
31899 +#if NR_CPUS > 19
31900 + CPU_ENUM(19),
31901 +#endif
31902 +#if NR_CPUS > 20
31903 + CPU_ENUM(20),
31904 +#endif
31905 +#if NR_CPUS > 21
31906 + CPU_ENUM(21),
31907 +#endif
31908 +#if NR_CPUS > 22
31909 + CPU_ENUM(22),
31910 +#endif
31911 +#if NR_CPUS > 23
31912 + CPU_ENUM(23),
31913 +#endif
31914 +#if NR_CPUS > 24
31915 + CPU_ENUM(24),
31916 +#endif
31917 +#if NR_CPUS > 25
31918 + CPU_ENUM(25),
31919 +#endif
31920 +#if NR_CPUS > 26
31921 + CPU_ENUM(26),
31922 +#endif
31923 +#if NR_CPUS > 27
31924 + CPU_ENUM(27),
31925 +#endif
31926 +#if NR_CPUS > 28
31927 + CPU_ENUM(28),
31928 +#endif
31929 +#if NR_CPUS > 29
31930 + CPU_ENUM(29),
31931 +#endif
31932 +#if NR_CPUS > 30
31933 + CPU_ENUM(30),
31934 +#endif
31935 +#if NR_CPUS > 31
31936 + CPU_ENUM(31),
31937 +#endif
31938 +#if NR_CPUS > 32
31939 +#error please extend CPU enumeration
31940 +#endif
31942 + .ctl_name = 0,
31946 +static ctl_table ctl_cpu[2] = {
31948 + .ctl_name = CTL_CPU,
31949 + .procname = "cpu",
31950 + .mode = 0555,
31951 + .child = ctl_cpu_table,
31952 + },
31954 + .ctl_name = 0,
31958 +struct ctl_table_header *cpufreq_sysctl_table;
31960 +static inline void cpufreq_sysctl_init(void)
31962 + cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0);
31965 +static inline void cpufreq_sysctl_exit(void)
31967 + unregister_sysctl_table(cpufreq_sysctl_table);
31970 +#else
31971 +#define cpufreq_sysctl_init() do {} while(0)
31972 +#define cpufreq_sysctl_exit() do {} while(0)
31973 +#endif /* CONFIG_CPU_FREQ_24API */
31976 +/************************** sysfs interface ************************/
31977 +static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
31979 + return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
31982 +static ssize_t
31983 +store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
31985 + unsigned int freq = 0;
31986 + unsigned int ret;
31988 + ret = sscanf (buf, "%u", &freq);
31989 + if (ret != 1)
31990 + return -EINVAL;
31992 + cpufreq_set(freq, policy->cpu);
31994 + return count;
31997 +static struct freq_attr freq_attr_scaling_setspeed = {
31998 + .attr = { .name = "scaling_setspeed", .mode = 0644 },
31999 + .show = show_speed,
32000 + .store = store_speed,
32003 +static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
32004 + unsigned int event)
32006 + unsigned int cpu = policy->cpu;
32007 + switch (event) {
32008 + case CPUFREQ_GOV_START:
32009 + if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) ||
32010 + !policy->cur)
32011 + return -EINVAL;
32012 + down(&userspace_sem);
32013 + cpu_is_managed[cpu] = 1;
32014 + cpu_min_freq[cpu] = policy->min;
32015 + cpu_max_freq[cpu] = policy->max;
32016 + cpu_cur_freq[cpu] = policy->cur;
32017 + sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
32018 + memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
32019 + up(&userspace_sem);
32020 + break;
32021 + case CPUFREQ_GOV_STOP:
32022 + down(&userspace_sem);
32023 + cpu_is_managed[cpu] = 0;
32024 + cpu_min_freq[cpu] = 0;
32025 + cpu_max_freq[cpu] = 0;
32026 + sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
32027 + up(&userspace_sem);
32028 + module_put(THIS_MODULE);
32029 + break;
32030 + case CPUFREQ_GOV_LIMITS:
32031 + down(&userspace_sem);
32032 + cpu_min_freq[cpu] = policy->min;
32033 + cpu_max_freq[cpu] = policy->max;
32034 + if (policy->max < cpu_cur_freq[cpu])
32035 + cpufreq_driver_target(&current_policy[cpu], policy->max,
32036 + CPUFREQ_RELATION_H);
32037 + else if (policy->min > cpu_cur_freq[cpu])
32038 + cpufreq_driver_target(&current_policy[cpu], policy->min,
32039 + CPUFREQ_RELATION_L);
32040 + memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
32041 + up(&userspace_sem);
32042 + break;
32044 + return 0;
32047 +/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because
32048 + * of this, cpu_cur_freq[] needs to be set early.
32049 + */
32050 +#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100)
32051 +extern unsigned int sa11x0_getspeed(void);
32053 +static void cpufreq_sa11x0_compat(void)
32055 + cpu_cur_freq[0] = sa11x0_getspeed();
32057 +#else
32058 +#define cpufreq_sa11x0_compat() do {} while(0)
32059 +#endif
32062 +static struct cpufreq_governor cpufreq_gov_userspace = {
32063 + .name = "userspace",
32064 + .governor = cpufreq_governor_userspace,
32065 + .owner = THIS_MODULE,
32067 +EXPORT_SYMBOL(cpufreq_gov_userspace);
32069 +static int already_init = 0;
32071 +int cpufreq_gov_userspace_init(void)
32073 + if (!already_init) {
32074 + down(&userspace_sem);
32075 + cpufreq_sa11x0_compat();
32076 + cpufreq_sysctl_init();
32077 + cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
32078 + already_init = 1;
32079 + up(&userspace_sem);
32081 + return cpufreq_register_governor(&cpufreq_gov_userspace);
32083 +EXPORT_SYMBOL(cpufreq_gov_userspace_init);
32086 +static void __exit cpufreq_gov_userspace_exit(void)
32088 + cpufreq_unregister_governor(&cpufreq_gov_userspace);
32089 + cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
32090 + cpufreq_sysctl_exit();
32094 +MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux.org.uk>");
32095 +MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'");
32096 +MODULE_LICENSE ("GPL");
32098 +module_init(cpufreq_gov_userspace_init);
32099 +module_exit(cpufreq_gov_userspace_exit);
32100 --- linux-2.4.25/drivers/i2c/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
32101 +++ linux-2.4.25/drivers/i2c/Config.in 2004-03-31 17:15:09.000000000 +0200
32102 @@ -17,6 +17,15 @@
32103 int ' GPIO pin used for SCL' CONFIG_SCx200_I2C_SCL 12
32104 int ' GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13
32107 + dep_tristate ' Guide GPIO adapter' CONFIG_I2C_GUIDE $CONFIG_I2C_ALGOBIT
32108 + if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
32109 + dep_tristate ' Omaha I2C interface' CONFIG_I2C_OMAHA $CONFIG_I2C
32110 + fi
32111 + if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
32112 + dep_tristate ' Frodo I2C adapter' CONFIG_I2C_FRODO $CONFIG_I2C_ALGOBIT
32113 + dep_tristate ' SA1100 I2C GPIO adapter' CONFIG_I2C_BIT_SA1100_GPIO $CONFIG_I2C_ALGOBIT
32114 + fi
32117 dep_tristate 'NatSemi SCx200 ACCESS.bus' CONFIG_SCx200_ACB $CONFIG_I2C
32118 @@ -49,6 +58,10 @@
32119 dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C
32122 + if [ "$CONFIG_ARCH_AT91RM9200" = "y" ] ; then
32123 + dep_tristate 'Atmel AT91RM9200 I2C Two-Wire interface (TWI)' CONFIG_I2C_AT91 $CONFIG_I2C
32124 + fi
32126 if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then
32127 dep_tristate 'SiByte SMBus interface' CONFIG_I2C_ALGO_SIBYTE $CONFIG_I2C
32128 dep_tristate ' MAX1617 Temperature Sensor' CONFIG_I2C_MAX1617 $CONFIG_I2C_ALGO_SIBYTE
32129 --- linux-2.4.25/drivers/i2c/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
32130 +++ linux-2.4.25/drivers/i2c/Makefile 2004-03-31 17:15:09.000000000 +0200
32131 @@ -8,12 +8,21 @@
32132 i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
32133 i2c-proc.o
32135 +# Init order: core, chardev, bit adapters, pcf adapters
32137 obj-$(CONFIG_I2C) += i2c-core.o
32138 obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
32140 +# Bit adapters
32141 obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
32142 obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o
32143 obj-$(CONFIG_I2C_ELV) += i2c-elv.o
32144 obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o
32145 +obj-$(CONFIG_I2C_GUIDE) += i2c-guide.o
32146 +obj-$(CONFIG_I2C_FRODO) += i2c-frodo.o
32147 +obj-$(CONFIG_I2C_OMAHA) += i2c-omaha.o
32149 +# PCF adapters
32150 obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
32151 obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
32152 obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o
32153 @@ -30,4 +39,3 @@
32154 # This is needed for automatic patch generation: sensors code ends here
32156 include $(TOPDIR)/Rules.make
32158 --- linux-2.4.25/drivers/i2c/i2c-algo-bit.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
32159 +++ linux-2.4.25/drivers/i2c/i2c-algo-bit.c 2004-03-31 17:15:09.000000000 +0200
32160 @@ -169,7 +169,14 @@
32161 * 1 if the device acknowledged
32162 * 0 if the device did not ack
32163 * -ETIMEDOUT if an error occurred (while raising the scl line)
32164 - */
32166 + * tsong@iders.ca: an instruction to disable any timeconsuming interrupt
32167 + here except the heart beat of timer2 should be added before setsda(adap, sb).
32168 + because when interrupt occurs during
32169 + scl is set high, the interrupt service routine is served and may take long,
32170 + after the interrupt returns, sda could be sampled by the device(slave)
32171 + more than once, and this cause error problem.
32173 static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
32175 int i;
32176 @@ -582,9 +589,7 @@
32177 printk("\n");
32180 -#ifdef MODULE
32181 MOD_INC_USE_COUNT;
32182 -#endif
32183 i2c_add_adapter(adap);
32185 return 0;
32186 @@ -600,15 +605,13 @@
32188 DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name));
32190 -#ifdef MODULE
32191 MOD_DEC_USE_COUNT;
32192 -#endif
32193 return 0;
32196 -int __init i2c_algo_bit_init (void)
32197 +static int __init i2c_algo_bit_init (void)
32199 - printk(KERN_INFO "i2c-algo-bit.o: i2c bit algorithm module\n");
32200 + printk(KERN_DEBUG "i2c-algo-bit.o: i2c bit algorithm module\n");
32201 return 0;
32204 @@ -617,7 +620,6 @@
32205 EXPORT_SYMBOL(i2c_bit_add_bus);
32206 EXPORT_SYMBOL(i2c_bit_del_bus);
32208 -#ifdef MODULE
32209 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
32210 MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
32211 MODULE_LICENSE("GPL");
32212 @@ -631,12 +633,4 @@
32213 MODULE_PARM_DESC(i2c_debug,
32214 "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
32216 -int init_module(void)
32218 - return i2c_algo_bit_init();
32221 -void cleanup_module(void)
32224 -#endif
32225 +module_init(i2c_algo_bit_init);
32226 --- linux-2.4.25/drivers/i2c/i2c-algo-pcf.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
32227 +++ linux-2.4.25/drivers/i2c/i2c-algo-pcf.c 2004-03-31 17:15:09.000000000 +0200
32228 @@ -475,9 +475,7 @@
32229 return i;
32232 -#ifdef MODULE
32233 MOD_INC_USE_COUNT;
32234 -#endif
32236 i2c_add_adapter(adap);
32238 @@ -515,13 +513,11 @@
32239 return res;
32240 DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name));
32242 -#ifdef MODULE
32243 MOD_DEC_USE_COUNT;
32244 -#endif
32245 return 0;
32248 -int __init i2c_algo_pcf_init (void)
32249 +static int __init i2c_algo_pcf_init (void)
32251 printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n");
32252 return 0;
32253 @@ -531,7 +527,6 @@
32254 EXPORT_SYMBOL(i2c_pcf_add_bus);
32255 EXPORT_SYMBOL(i2c_pcf_del_bus);
32257 -#ifdef MODULE
32258 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
32259 MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
32260 MODULE_LICENSE("GPL");
32261 @@ -543,13 +538,4 @@
32262 MODULE_PARM_DESC(i2c_debug,
32263 "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
32266 -int init_module(void)
32268 - return i2c_algo_pcf_init();
32271 -void cleanup_module(void)
32274 -#endif
32275 +module_init(i2c_algo_pcf_init);
32276 --- linux-2.4.25/drivers/i2c/i2c-core.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
32277 +++ linux-2.4.25/drivers/i2c/i2c-core.c 2004-03-31 17:15:09.000000000 +0200
32278 @@ -41,7 +41,7 @@
32280 /* exclusive access to the bus */
32281 #define I2C_LOCK(adap) down(&adap->lock)
32282 -#define I2C_UNLOCK(adap) up(&adap->lock)
32283 +#define I2C_UNLOCK(adap) up(&adap->lock)
32285 #define ADAP_LOCK() down(&adap_lock)
32286 #define ADAP_UNLOCK() up(&adap_lock)
32287 @@ -67,7 +67,7 @@
32288 static int driver_count;
32290 /**** debug level */
32291 -static int i2c_debug=1;
32292 +static int i2c_debug = 0;
32294 /* ---------------------------------------------------
32295 * /proc entry declarations
32296 @@ -77,14 +77,14 @@
32297 #ifdef CONFIG_PROC_FS
32299 static int i2cproc_init(void);
32300 -static int i2cproc_cleanup(void);
32301 +static void i2cproc_cleanup(void);
32303 -static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
32304 +static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
32305 loff_t *ppos);
32306 static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
32307 int *eof , void *private);
32309 -/* To implement the dynamic /proc/bus/i2c-? files, we need our own
32310 +/* To implement the dynamic /proc/bus/i2c-? files, we need our own
32311 implementation of the read hook */
32312 static struct file_operations i2cproc_operations = {
32313 read: i2cproc_bus_read,
32314 @@ -101,8 +101,8 @@
32317 /* ---------------------------------------------------
32318 - * registering functions
32319 - * ---------------------------------------------------
32320 + * registering functions
32321 + * ---------------------------------------------------
32324 /* -----
32325 @@ -119,7 +119,7 @@
32326 if (NULL == adapters[i])
32327 break;
32328 if (I2C_ADAP_MAX == i) {
32329 - printk(KERN_WARNING
32330 + printk(KERN_WARNING
32331 " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
32332 adap->name);
32333 res = -ENOMEM;
32334 @@ -129,7 +129,7 @@
32335 adapters[i] = adap;
32336 adap_count++;
32337 ADAP_UNLOCK();
32340 /* init data types */
32341 init_MUTEX(&adap->lock);
32343 @@ -157,18 +157,18 @@
32344 #endif /* def CONFIG_PROC_FS */
32346 /* inform drivers of new adapters */
32347 - DRV_LOCK();
32348 + DRV_LOCK();
32349 for (j=0;j<I2C_DRIVER_MAX;j++)
32350 - if (drivers[j]!=NULL &&
32351 + if (drivers[j]!=NULL &&
32352 (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY)))
32353 /* We ignore the return code; if it fails, too bad */
32354 drivers[j]->attach_adapter(adap);
32355 DRV_UNLOCK();
32358 DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
32359 adap->name,i));
32361 - return 0;
32362 + return 0;
32365 ERROR1:
32366 @@ -203,13 +203,13 @@
32367 * this or hell will break loose...
32369 DRV_LOCK();
32370 - for (j = 0; j < I2C_DRIVER_MAX; j++)
32371 + for (j = 0; j < I2C_DRIVER_MAX; j++)
32372 if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
32373 if ((res = drivers[j]->attach_adapter(adap))) {
32374 printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
32375 "while detaching driver %s: driver not "
32376 "detached!",adap->name,drivers[j]->name);
32377 - goto ERROR1;
32378 + goto ERROR1;
32380 DRV_UNLOCK();
32382 @@ -241,8 +241,8 @@
32384 adapters[i] = NULL;
32385 adap_count--;
32387 - ADAP_UNLOCK();
32389 + ADAP_UNLOCK();
32390 DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
32391 return 0;
32393 @@ -269,7 +269,7 @@
32394 if (NULL == drivers[i])
32395 break;
32396 if (I2C_DRIVER_MAX == i) {
32397 - printk(KERN_WARNING
32398 + printk(KERN_WARNING
32399 " i2c-core.o: register_driver(%s) "
32400 "- enlarge I2C_DRIVER_MAX.\n",
32401 driver->name);
32402 @@ -279,11 +279,11 @@
32404 drivers[i] = driver;
32405 driver_count++;
32408 DRV_UNLOCK(); /* driver was successfully added */
32411 DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name));
32414 ADAP_LOCK();
32416 /* now look for instances of driver on our adapters
32417 @@ -314,11 +314,11 @@
32418 return -ENODEV;
32420 /* Have a look at each adapter, if clients of this driver are still
32421 - * attached. If so, detach them to be able to kill the driver
32422 + * attached. If so, detach them to be able to kill the driver
32423 * afterwards.
32425 DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n"));
32426 - /* removing clients does not depend on the notify flag, else
32427 + /* removing clients does not depend on the notify flag, else
32428 * invalid operation might (will!) result, when using stale client
32429 * pointers.
32431 @@ -333,7 +333,7 @@
32432 /* DUMMY drivers do not register their clients, so we have to
32433 * use a trick here: we call driver->attach_adapter to
32434 * *detach* it! Of course, each dummy driver should know about
32435 - * this or hell will break loose...
32436 + * this or hell will break loose...
32438 if ((res = driver->attach_adapter(adap))) {
32439 printk(KERN_WARNING "i2c-core.o: while unregistering "
32440 @@ -345,9 +345,9 @@
32441 return res;
32443 } else {
32444 - for (j=0;j<I2C_CLIENT_MAX;j++) {
32445 + for (j=0;j<I2C_CLIENT_MAX;j++) {
32446 struct i2c_client *client = adap->clients[j];
32447 - if (client != NULL &&
32448 + if (client != NULL &&
32449 client->driver == driver) {
32450 DEB2(printk(KERN_DEBUG "i2c-core.o: "
32451 "detaching client %s:\n",
32452 @@ -376,7 +376,7 @@
32453 drivers[i] = NULL;
32454 driver_count--;
32455 DRV_UNLOCK();
32458 DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name));
32459 return 0;
32461 @@ -384,7 +384,7 @@
32462 int i2c_check_addr (struct i2c_adapter *adapter, int addr)
32464 int i;
32465 - for (i = 0; i < I2C_CLIENT_MAX ; i++)
32466 + for (i = 0; i < I2C_CLIENT_MAX ; i++)
32467 if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
32468 return -EBUSY;
32469 return 0;
32470 @@ -402,7 +402,7 @@
32471 if (NULL == adapter->clients[i])
32472 break;
32473 if (I2C_CLIENT_MAX == i) {
32474 - printk(KERN_WARNING
32475 + printk(KERN_WARNING
32476 " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
32477 client->name);
32478 return -ENOMEM;
32479 @@ -410,9 +410,9 @@
32481 adapter->clients[i] = client;
32482 adapter->client_count++;
32484 - if (adapter->client_register)
32485 - if (adapter->client_register(client))
32487 + if (adapter->client_register)
32488 + if (adapter->client_register(client))
32489 printk(KERN_DEBUG "i2c-core.o: warning: client_register seems "
32490 "to have failed for client %02x at adapter %s\n",
32491 client->addr,adapter->name);
32492 @@ -421,7 +421,7 @@
32494 if(client->flags & I2C_CLIENT_ALLOW_USE)
32495 client->usage_count = 0;
32498 return 0;
32501 @@ -440,12 +440,12 @@
32502 client->name);
32503 return -ENODEV;
32506 - if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
32508 + if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
32509 (client->usage_count>0))
32510 return -EBUSY;
32512 - if (adapter->client_unregister != NULL)
32514 + if (adapter->client_unregister != NULL)
32515 if ((res = adapter->client_unregister(client))) {
32516 printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, "
32517 "client not detached",client->name);
32518 @@ -471,7 +471,7 @@
32520 void i2c_dec_use_client(struct i2c_client *client)
32524 if (client->driver->dec_use != NULL)
32525 client->driver->dec_use(client);
32527 @@ -479,65 +479,65 @@
32528 client->adapter->dec_use(client->adapter);
32531 -struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
32532 +struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
32533 struct i2c_client *prev)
32535 int i,j;
32538 /* Will iterate through the list of clients in each adapter of adapters-list
32539 - in search for a client that matches the search criteria. driver_id or
32540 - adapter_id are ignored if set to 0. If both are ignored this returns
32541 + in search for a client that matches the search criteria. driver_id or
32542 + adapter_id are ignored if set to 0. If both are ignored this returns
32543 first client found. */
32545 - i = j = 0;
32547 - /* set starting point */
32549 + i = j = 0;
32551 + /* set starting point */
32552 if(prev)
32554 if(!(prev->adapter))
32555 return (struct i2c_client *) -EINVAL;
32558 for(j=0; j < I2C_ADAP_MAX; j++)
32559 if(prev->adapter == adapters[j])
32560 break;
32563 /* invalid starting point? */
32564 if (I2C_ADAP_MAX == j) {
32565 printk(KERN_WARNING " i2c-core.o: get_client adapter for client:[%s] not found\n",
32566 prev->name);
32567 return (struct i2c_client *) -ENODEV;
32568 - }
32572 for(i=0; i < I2C_CLIENT_MAX; i++)
32573 if(prev == adapters[j]->clients[i])
32574 break;
32577 /* invalid starting point? */
32578 if (I2C_CLIENT_MAX == i) {
32579 printk(KERN_WARNING " i2c-core.o: get_client client:[%s] not found\n",
32580 prev->name);
32581 return (struct i2c_client *) -ENODEV;
32582 - }
32586 i++; /* start from one after prev */
32590 for(; j < I2C_ADAP_MAX; j++)
32592 if(!adapters[j])
32593 continue;
32596 if(adapter_id && (adapters[j]->id != adapter_id))
32597 continue;
32600 for(; i < I2C_CLIENT_MAX; i++)
32602 if(!adapters[j]->clients[i])
32603 continue;
32606 if(driver_id && (adapters[j]->clients[i]->driver->id != driver_id))
32607 continue;
32608 - if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
32609 + if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
32610 return adapters[j]->clients[i];
32612 i = 0;
32613 @@ -549,12 +549,12 @@
32614 int i2c_use_client(struct i2c_client *client)
32616 if(client->flags & I2C_CLIENT_ALLOW_USE) {
32617 - if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
32618 + if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
32619 client->usage_count++;
32620 else {
32621 - if(client->usage_count > 0)
32622 + if(client->usage_count > 0)
32623 return -EBUSY;
32624 - else
32625 + else
32626 client->usage_count++;
32629 @@ -575,9 +575,9 @@
32630 return -EPERM;
32635 i2c_dec_use_client(client);
32638 return 0;
32641 @@ -589,7 +589,7 @@
32642 #ifdef CONFIG_PROC_FS
32644 /* This function generates the output for /proc/bus/i2c */
32645 -int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
32646 +int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
32647 void *private)
32649 int i;
32650 @@ -615,7 +615,7 @@
32653 /* This function generates the output for /proc/bus/i2c-? */
32654 -ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
32655 +ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
32656 loff_t *ppos)
32658 struct inode * inode = file->f_dentry->d_inode;
32659 @@ -626,7 +626,7 @@
32660 int order[I2C_CLIENT_MAX];
32662 if (count > 4000)
32663 - return -EINVAL;
32664 + return -EINVAL;
32665 len_total = file->f_pos + count;
32666 /* Too bad if this gets longer (unlikely) */
32667 if (len_total > 4000)
32668 @@ -641,12 +641,12 @@
32669 sorted by address */
32670 order_nr=0;
32671 for (j = 0; j < I2C_CLIENT_MAX; j++) {
32672 - if ((client = adapters[i]->clients[j]) &&
32673 + if ((client = adapters[i]->clients[j]) &&
32674 (client->driver->id != I2C_DRIVERID_I2CDEV)) {
32675 - for(k = order_nr;
32676 - (k > 0) &&
32677 + for(k = order_nr;
32678 + (k > 0) &&
32679 adapters[i]->clients[order[k-1]]->
32680 - addr > client->addr;
32681 + addr > client->addr;
32682 k--)
32683 order[k] = order[k-1];
32684 order[k] = j;
32685 @@ -665,7 +665,7 @@
32686 len = len - file->f_pos;
32687 if (len > count)
32688 len = count;
32689 - if (len < 0)
32690 + if (len < 0)
32691 len = 0;
32692 if (copy_to_user (buf,kbuf+file->f_pos, len)) {
32693 kfree(kbuf);
32694 @@ -689,7 +689,7 @@
32695 printk("i2c-core.o: /proc/bus/ does not exist");
32696 i2cproc_cleanup();
32697 return -ENOENT;
32698 - }
32700 proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
32701 if (!proc_bus_i2c) {
32702 printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
32703 @@ -702,14 +702,13 @@
32704 return 0;
32707 -int i2cproc_cleanup(void)
32708 +static void i2cproc_cleanup(void)
32711 if (i2cproc_initialized >= 1) {
32712 remove_proc_entry("i2c",proc_bus);
32713 i2cproc_initialized -= 2;
32715 - return 0;
32719 @@ -751,10 +750,10 @@
32720 msg.flags = client->flags & I2C_M_TEN;
32721 msg.len = count;
32722 (const char *)msg.buf = buf;
32725 DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
32726 count,client->adapter->name));
32729 I2C_LOCK(adap);
32730 ret = adap->algo->master_xfer(adap,&msg,1);
32731 I2C_UNLOCK(adap);
32732 @@ -784,14 +783,14 @@
32734 DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
32735 count,client->adapter->name));
32738 I2C_LOCK(adap);
32739 ret = adap->algo->master_xfer(adap,&msg,1);
32740 I2C_UNLOCK(adap);
32743 DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",
32744 ret, count, client->addr));
32747 /* if everything went ok (i.e. 1 msg transmitted), return #bytes
32748 * transmitted, else error code.
32750 @@ -852,7 +851,7 @@
32751 found = 0;
32753 for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
32754 - if (((adap_id == address_data->force[i]) ||
32755 + if (((adap_id == address_data->force[i]) ||
32756 (address_data->force[i] == ANY_I2C_BUS)) &&
32757 (addr == address_data->force[i+1])) {
32758 DEB2(printk(KERN_DEBUG "i2c-core.o: found force parameter for adapter %d, addr %04x\n",
32759 @@ -862,7 +861,7 @@
32760 found = 1;
32763 - if (found)
32764 + if (found)
32765 continue;
32767 /* If this address is in one of the ignores, we can forget about
32768 @@ -870,7 +869,7 @@
32769 for (i = 0;
32770 !found && (address_data->ignore[i] != I2C_CLIENT_END);
32771 i += 2) {
32772 - if (((adap_id == address_data->ignore[i]) ||
32773 + if (((adap_id == address_data->ignore[i]) ||
32774 ((address_data->ignore[i] == ANY_I2C_BUS))) &&
32775 (addr == address_data->ignore[i+1])) {
32776 DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore parameter for adapter %d, "
32777 @@ -890,11 +889,11 @@
32778 found = 1;
32781 - if (found)
32782 + if (found)
32783 continue;
32785 - /* Now, we will do a detection, but only if it is in the normal or
32786 - probe entries */
32787 + /* Now, we will do a detection, but only if it is in the normal or
32788 + probe entries */
32789 for (i = 0;
32790 !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
32791 i += 1) {
32792 @@ -939,7 +938,7 @@
32793 "addr %04x\n", adap_id,addr));
32796 - if (!found)
32797 + if (!found)
32798 continue;
32800 /* OK, so we really should examine this address. First check
32801 @@ -1087,11 +1086,11 @@
32802 I2C_SMBUS_I2C_BLOCK_DATA,&data);
32805 -/* Simulate a SMBus command using the i2c protocol
32806 +/* Simulate a SMBus command using the i2c protocol
32807 No checking of parameters is done! */
32808 -static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
32809 +static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
32810 unsigned short flags,
32811 - char read_write, u8 command, int size,
32812 + char read_write, u8 command, int size,
32813 union i2c_smbus_data * data)
32815 /* So we need to generate a series of msgs. In the case of writing, we
32816 @@ -1101,7 +1100,7 @@
32817 unsigned char msgbuf0[34];
32818 unsigned char msgbuf1[34];
32819 int num = read_write == I2C_SMBUS_READ?2:1;
32820 - struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
32821 + struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
32822 { addr, flags | I2C_M_RD, 0, msgbuf1 }
32824 int i;
32825 @@ -1179,7 +1178,7 @@
32826 case I2C_SMBUS_BYTE_DATA:
32827 data->byte = msgbuf1[0];
32828 break;
32829 - case I2C_SMBUS_WORD_DATA:
32830 + case I2C_SMBUS_WORD_DATA:
32831 case I2C_SMBUS_PROC_CALL:
32832 data->word = msgbuf1[0] | (msgbuf1[1] << 8);
32833 break;
32834 @@ -1189,7 +1188,7 @@
32837 s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
32838 - char read_write, u8 command, int size,
32839 + char read_write, u8 command, int size,
32840 union i2c_smbus_data * data)
32842 s32 res;
32843 @@ -1207,7 +1206,7 @@
32846 /* You should always define `functionality'; the 'else' is just for
32847 - backward compatibility. */
32848 + backward compatibility. */
32849 u32 i2c_get_functionality (struct i2c_adapter *adap)
32851 if (adap->algo->functionality)
32852 @@ -1233,122 +1232,12 @@
32854 init_MUTEX(&adap_lock);
32855 init_MUTEX(&driver_lock);
32857 - i2cproc_init();
32859 - return 0;
32862 -#ifndef MODULE
32863 -#ifdef CONFIG_I2C_CHARDEV
32864 - extern int i2c_dev_init(void);
32865 -#endif
32866 -#ifdef CONFIG_I2C_ALGOBIT
32867 - extern int i2c_algo_bit_init(void);
32868 -#endif
32869 -#ifdef CONFIG_I2C_PHILIPSPAR
32870 - extern int i2c_bitlp_init(void);
32871 -#endif
32872 -#ifdef CONFIG_I2C_ELV
32873 - extern int i2c_bitelv_init(void);
32874 -#endif
32875 -#ifdef CONFIG_I2C_VELLEMAN
32876 - extern int i2c_bitvelle_init(void);
32877 -#endif
32878 -#ifdef CONFIG_I2C_BITVIA
32879 - extern int i2c_bitvia_init(void);
32880 -#endif
32882 -#ifdef CONFIG_I2C_ALGOPCF
32883 - extern int i2c_algo_pcf_init(void);
32884 -#endif
32885 -#ifdef CONFIG_I2C_ELEKTOR
32886 - extern int i2c_pcfisa_init(void);
32887 -#endif
32889 -#ifdef CONFIG_I2C_ALGO8XX
32890 - extern int i2c_algo_8xx_init(void);
32891 -#endif
32892 -#ifdef CONFIG_I2C_RPXLITE
32893 - extern int i2c_rpx_init(void);
32894 -#endif
32896 -#ifdef CONFIG_I2C_ALGO_SIBYTE
32897 - extern int i2c_algo_sibyte_init(void);
32898 - extern int i2c_sibyte_init(void);
32899 -#endif
32900 -#ifdef CONFIG_I2C_MAX1617
32901 - extern int i2c_max1617_init(void);
32902 -#endif
32904 -#ifdef CONFIG_I2C_PROC
32905 - extern int sensors_init(void);
32906 -#endif
32908 -/* This is needed for automatic patch generation: sensors code starts here */
32909 -/* This is needed for automatic patch generation: sensors code ends here */
32911 -int __init i2c_init_all(void)
32913 - /* --------------------- global ----- */
32914 - i2c_init();
32916 -#ifdef CONFIG_I2C_CHARDEV
32917 - i2c_dev_init();
32918 -#endif
32919 - /* --------------------- bit -------- */
32920 -#ifdef CONFIG_I2C_ALGOBIT
32921 - i2c_algo_bit_init();
32922 -#endif
32923 -#ifdef CONFIG_I2C_PHILIPSPAR
32924 - i2c_bitlp_init();
32925 -#endif
32926 -#ifdef CONFIG_I2C_ELV
32927 - i2c_bitelv_init();
32928 -#endif
32929 -#ifdef CONFIG_I2C_VELLEMAN
32930 - i2c_bitvelle_init();
32931 -#endif
32933 - /* --------------------- pcf -------- */
32934 -#ifdef CONFIG_I2C_ALGOPCF
32935 - i2c_algo_pcf_init();
32936 -#endif
32937 -#ifdef CONFIG_I2C_ELEKTOR
32938 - i2c_pcfisa_init();
32939 -#endif
32941 - /* --------------------- 8xx -------- */
32942 -#ifdef CONFIG_I2C_ALGO8XX
32943 - i2c_algo_8xx_init();
32944 -#endif
32945 -#ifdef CONFIG_I2C_RPXLITE
32946 - i2c_rpx_init();
32947 -#endif
32949 - /* --------------------- SiByte -------- */
32950 -#ifdef CONFIG_I2C_ALGO_SIBYTE
32951 - i2c_algo_sibyte_init();
32952 - i2c_sibyte_init();
32953 -#endif
32954 -#ifdef CONFIG_I2C_MAX1617
32955 - i2c_max1617_init();
32956 -#endif
32958 - /* -------------- proc interface ---- */
32959 -#ifdef CONFIG_I2C_PROC
32960 - sensors_init();
32961 -#endif
32962 -/* This is needed for automatic patch generation: sensors code starts here */
32963 -/* This is needed for automatic patch generation: sensors code ends here */
32964 + i2cproc_init();
32966 return 0;
32969 -#endif
32973 EXPORT_SYMBOL(i2c_add_adapter);
32974 EXPORT_SYMBOL(i2c_del_adapter);
32975 EXPORT_SYMBOL(i2c_add_driver);
32976 @@ -1385,7 +1274,6 @@
32977 EXPORT_SYMBOL(i2c_get_functionality);
32978 EXPORT_SYMBOL(i2c_check_functionality);
32980 -#ifdef MODULE
32981 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
32982 MODULE_DESCRIPTION("I2C-Bus main module");
32983 MODULE_LICENSE("GPL");
32984 @@ -1393,13 +1281,5 @@
32985 MODULE_PARM(i2c_debug, "i");
32986 MODULE_PARM_DESC(i2c_debug,"debug level");
32988 -int init_module(void)
32990 - return i2c_init();
32993 -void cleanup_module(void)
32995 - i2cproc_cleanup();
32997 -#endif
32998 +module_init(i2c_init);
32999 +module_exit(i2cproc_cleanup);
33000 --- linux-2.4.25/drivers/i2c/i2c-dev.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
33001 +++ linux-2.4.25/drivers/i2c/i2c-dev.c 2004-03-31 17:15:09.000000000 +0200
33002 @@ -1,5 +1,5 @@
33004 - i2c-dev.c - i2c-bus driver, char device interface
33005 + i2c-dev.c - i2c-bus driver, char device interface
33007 Copyright (C) 1995-97 Simon G. Vogl
33008 Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
33009 @@ -25,7 +25,7 @@
33011 /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
33013 -/* The devfs code is contributed by Philipp Matthias Hahn
33014 +/* The devfs code is contributed by Philipp Matthias Hahn
33015 <pmhahn@titan.lahn.de> */
33017 /* $Id: i2c-dev.c,v 1.40 2001/08/25 01:28:01 mds Exp $ */
33018 @@ -50,19 +50,14 @@
33019 #include <linux/i2c.h>
33020 #include <linux/i2c-dev.h>
33022 -#ifdef MODULE
33023 -extern int init_module(void);
33024 -extern int cleanup_module(void);
33025 -#endif /* def MODULE */
33027 /* struct file_operations changed too often in the 2.1 series for nice code */
33029 -static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
33030 +static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
33031 loff_t *offset);
33032 -static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
33033 +static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
33034 loff_t *offset);
33036 -static int i2cdev_ioctl (struct inode *inode, struct file *file,
33037 +static int i2cdev_ioctl (struct inode *inode, struct file *file,
33038 unsigned int cmd, unsigned long arg);
33039 static int i2cdev_open (struct inode *inode, struct file *file);
33041 @@ -73,13 +68,8 @@
33042 static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
33043 void *arg);
33045 -#ifdef MODULE
33046 -static
33047 -#else
33048 -extern
33049 -#endif
33050 - int __init i2c_dev_init(void);
33051 -static int i2cdev_cleanup(void);
33052 +static int __init i2c_dev_init(void);
33053 +static void i2cdev_cleanup(void);
33055 static struct file_operations i2cdev_fops = {
33056 owner: THIS_MODULE,
33057 @@ -185,7 +175,7 @@
33058 return ret;
33061 -int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
33062 +int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
33063 unsigned long arg)
33065 struct i2c_client *client = (struct i2c_client *)file->private_data;
33066 @@ -198,14 +188,14 @@
33067 unsigned long funcs;
33069 #ifdef DEBUG
33070 - printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
33071 + printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
33072 MINOR(inode->i_rdev),cmd, arg);
33073 #endif /* DEBUG */
33075 switch ( cmd ) {
33076 case I2C_SLAVE:
33077 case I2C_SLAVE_FORCE:
33078 - if ((arg > 0x3ff) ||
33079 + if ((arg > 0x3ff) ||
33080 (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
33081 return -EINVAL;
33082 if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
33083 @@ -224,8 +214,8 @@
33084 sizeof(unsigned long)))?-EFAULT:0;
33086 case I2C_RDWR:
33087 - if (copy_from_user(&rdwr_arg,
33088 - (struct i2c_rdwr_ioctl_data *)arg,
33089 + if (copy_from_user(&rdwr_arg,
33090 + (struct i2c_rdwr_ioctl_data *)arg,
33091 sizeof(rdwr_arg)))
33092 return -EFAULT;
33094 @@ -233,9 +223,9 @@
33095 * be sent at once */
33096 if (rdwr_arg.nmsgs > 42)
33097 return -EINVAL;
33100 rdwr_pa = (struct i2c_msg *)
33101 - kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
33102 + kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
33103 GFP_KERNEL);
33105 if (rdwr_pa == NULL) return -ENOMEM;
33106 @@ -312,9 +302,9 @@
33107 (struct i2c_smbus_ioctl_data *) arg,
33108 sizeof(struct i2c_smbus_ioctl_data)))
33109 return -EFAULT;
33110 - if ((data_arg.size != I2C_SMBUS_BYTE) &&
33111 + if ((data_arg.size != I2C_SMBUS_BYTE) &&
33112 (data_arg.size != I2C_SMBUS_QUICK) &&
33113 - (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
33114 + (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
33115 (data_arg.size != I2C_SMBUS_WORD_DATA) &&
33116 (data_arg.size != I2C_SMBUS_PROC_CALL) &&
33117 (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
33118 @@ -325,9 +315,9 @@
33119 #endif
33120 return -EINVAL;
33122 - /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
33123 + /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
33124 so the check is valid if size==I2C_SMBUS_QUICK too. */
33125 - if ((data_arg.read_write != I2C_SMBUS_READ) &&
33126 + if ((data_arg.read_write != I2C_SMBUS_READ) &&
33127 (data_arg.read_write != I2C_SMBUS_WRITE)) {
33128 #ifdef DEBUG
33129 printk(KERN_DEBUG "i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
33130 @@ -339,7 +329,7 @@
33131 /* Note that command values are always valid! */
33133 if ((data_arg.size == I2C_SMBUS_QUICK) ||
33134 - ((data_arg.size == I2C_SMBUS_BYTE) &&
33135 + ((data_arg.size == I2C_SMBUS_BYTE) &&
33136 (data_arg.read_write == I2C_SMBUS_WRITE)))
33137 /* These are special: we do not use data */
33138 return i2c_smbus_xfer(client->adapter, client->addr,
33139 @@ -358,13 +348,13 @@
33140 if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
33141 (data_arg.size == I2C_SMBUS_BYTE))
33142 datasize = sizeof(data_arg.data->byte);
33143 - else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
33144 + else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
33145 (data_arg.size == I2C_SMBUS_PROC_CALL))
33146 datasize = sizeof(data_arg.data->word);
33147 else /* size == I2C_SMBUS_BLOCK_DATA */
33148 datasize = sizeof(data_arg.data->block);
33150 - if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
33151 + if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
33152 (data_arg.read_write == I2C_SMBUS_WRITE)) {
33153 if (copy_from_user(&temp, data_arg.data, datasize))
33154 return -EFAULT;
33155 @@ -372,7 +362,7 @@
33156 res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
33157 data_arg.read_write,
33158 data_arg.command,data_arg.size,&temp);
33159 - if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
33160 + if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
33161 (data_arg.read_write == I2C_SMBUS_READ))) {
33162 if (copy_to_user(data_arg.data, &temp, datasize))
33163 return -EFAULT;
33164 @@ -479,7 +469,7 @@
33165 return -1;
33168 -int __init i2c_dev_init(void)
33169 +static int __init i2c_dev_init(void)
33171 int res;
33173 @@ -509,7 +499,7 @@
33174 return 0;
33177 -int i2cdev_cleanup(void)
33178 +static void i2cdev_cleanup(void)
33180 int res;
33182 @@ -517,9 +507,9 @@
33183 if ((res = i2c_del_driver(&i2cdev_driver))) {
33184 printk("i2c-dev.o: Driver deregistration failed, "
33185 "module not removed.\n");
33186 - return res;
33187 + return;
33189 - i2cdev_initialized --;
33190 + i2cdev_initialized --;
33193 if (i2cdev_initialized >= 1) {
33194 @@ -531,30 +521,17 @@
33195 #endif
33196 printk("i2c-dev.o: unable to release major %d for i2c bus\n",
33197 I2C_MAJOR);
33198 - return res;
33199 + return;
33201 i2cdev_initialized --;
33203 - return 0;
33206 EXPORT_NO_SYMBOLS;
33208 -#ifdef MODULE
33210 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
33211 MODULE_DESCRIPTION("I2C /dev entries driver");
33212 MODULE_LICENSE("GPL");
33214 -int init_module(void)
33216 - return i2c_dev_init();
33219 -int cleanup_module(void)
33221 - return i2cdev_cleanup();
33224 -#endif /* def MODULE */
33226 +module_init(i2c_dev_init);
33227 +module_exit(i2cdev_cleanup);
33228 --- linux-2.4.25/drivers/i2c/i2c-elektor.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
33229 +++ linux-2.4.25/drivers/i2c/i2c-elektor.c 2004-03-31 17:15:09.000000000 +0200
33230 @@ -181,16 +181,12 @@
33232 static void pcf_isa_inc_use(struct i2c_adapter *adap)
33234 -#ifdef MODULE
33235 MOD_INC_USE_COUNT;
33236 -#endif
33239 static void pcf_isa_dec_use(struct i2c_adapter *adap)
33241 -#ifdef MODULE
33242 MOD_DEC_USE_COUNT;
33243 -#endif
33247 @@ -219,7 +215,7 @@
33248 pcf_isa_unreg,
33251 -int __init i2c_pcfisa_init(void)
33252 +static int __init i2c_pcfisa_init(void)
33254 #ifdef __alpha__
33255 /* check to see we have memory mapped PCF8584 connected to the
33256 @@ -289,10 +285,14 @@
33257 return 0;
33260 +static void i2c_pcfisa_exit(void)
33262 + i2c_pcf_del_bus(&pcf_isa_ops);
33263 + pcf_isa_exit();
33266 EXPORT_NO_SYMBOLS;
33268 -#ifdef MODULE
33269 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
33270 MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
33271 MODULE_LICENSE("GPL");
33272 @@ -304,15 +304,5 @@
33273 MODULE_PARM(mmapped, "i");
33274 MODULE_PARM(i2c_debug, "i");
33276 -int init_module(void)
33278 - return i2c_pcfisa_init();
33281 -void cleanup_module(void)
33283 - i2c_pcf_del_bus(&pcf_isa_ops);
33284 - pcf_isa_exit();
33287 -#endif
33288 +module_init(i2c_pcfisa_init);
33289 +module_exit(i2c_pcfisa_exit);
33290 --- linux-2.4.25/drivers/i2c/i2c-elv.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
33291 +++ linux-2.4.25/drivers/i2c/i2c-elv.c 2004-03-31 17:15:09.000000000 +0200
33292 @@ -75,7 +75,7 @@
33293 PortData |=2;
33295 outb(PortData, DATA);
33299 static int bit_elv_getscl(void *data)
33301 @@ -90,7 +90,7 @@
33302 static int bit_elv_init(void)
33304 if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
33305 - return -ENODEV;
33306 + return -ENODEV;
33307 } else {
33308 /* test for ELV adap. */
33309 if (inb(base+1) & 0x80) { /* BUSY should be high */
33310 @@ -131,16 +131,12 @@
33312 static void bit_elv_inc_use(struct i2c_adapter *adap)
33314 -#ifdef MODULE
33315 MOD_INC_USE_COUNT;
33316 -#endif
33319 static void bit_elv_dec_use(struct i2c_adapter *adap)
33321 -#ifdef MODULE
33322 MOD_DEC_USE_COUNT;
33323 -#endif
33326 /* ------------------------------------------------------------------------
33327 @@ -164,10 +160,10 @@
33328 bit_elv_inc_use,
33329 bit_elv_dec_use,
33330 bit_elv_reg,
33331 - bit_elv_unreg,
33332 + bit_elv_unreg,
33335 -int __init i2c_bitelv_init(void)
33336 +static int __init i2c_bitelv_init(void)
33338 printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
33339 if (base==0) {
33340 @@ -194,24 +190,19 @@
33344 +static void __exit i2c_bitelv_exit(void)
33346 + i2c_bit_del_bus(&bit_elv_ops);
33347 + bit_elv_exit();
33350 EXPORT_NO_SYMBOLS;
33352 -#ifdef MODULE
33353 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
33354 MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
33355 MODULE_LICENSE("GPL");
33357 MODULE_PARM(base, "i");
33359 -int init_module(void)
33361 - return i2c_bitelv_init();
33364 -void cleanup_module(void)
33366 - i2c_bit_del_bus(&bit_elv_ops);
33367 - bit_elv_exit();
33370 -#endif
33371 +module_init(i2c_bitelv_init);
33372 +module_exit(i2c_bitelv_exit);
33373 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
33374 +++ linux-2.4.25/drivers/i2c/i2c-frodo.c 2004-03-31 17:15:09.000000000 +0200
33375 @@ -0,0 +1,114 @@
33378 + * linux/drivers/i2c/i2c-frodo.c
33380 + * Author: Abraham van der Merwe <abraham@2d3d.co.za>
33382 + * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110
33383 + * Development board (Frodo).
33385 + * This source code is free software; you can redistribute it and/or
33386 + * modify it under the terms of the GNU General Public License
33387 + * version 2 as published by the Free Software Foundation.
33388 + */
33390 +#include <linux/config.h>
33391 +#include <linux/version.h>
33392 +#include <linux/module.h>
33394 +#include <linux/kernel.h>
33395 +#include <linux/init.h>
33396 +#include <linux/delay.h>
33398 +#include <asm/hardware.h>
33400 +#include <linux/i2c.h>
33401 +#include <linux/i2c-algo-bit.h>
33403 +static void frodo_setsda (void *data,int state)
33405 + if (state)
33406 + frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
33407 + else
33408 + frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
33411 +static void frodo_setscl (void *data,int state)
33413 + if (state)
33414 + frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
33415 + else
33416 + frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
33419 +static int frodo_getsda (void *data)
33421 + return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SDA_IN) != 0);
33424 +static int frodo_getscl (void *data)
33426 + return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SCL_IN) != 0);
33429 +static struct i2c_algo_bit_data bit_frodo_data = {
33430 + setsda: frodo_setsda,
33431 + setscl: frodo_setscl,
33432 + getsda: frodo_getsda,
33433 + getscl: frodo_getscl,
33434 + udelay: 80,
33435 + mdelay: 80,
33436 + timeout: 100
33439 +static int frodo_client_register (struct i2c_client *client)
33441 + return (0);
33444 +static int frodo_client_unregister (struct i2c_client *client)
33446 + return (0);
33449 +static void frodo_inc_use (struct i2c_adapter *adapter)
33451 + MOD_INC_USE_COUNT;
33454 +static void frodo_dec_use (struct i2c_adapter *adapter)
33456 + MOD_DEC_USE_COUNT;
33459 +static struct i2c_adapter frodo_ops = {
33460 + name: "Frodo adapter driver",
33461 + id: I2C_HW_B_FRODO,
33462 + algo: NULL,
33463 + algo_data: &bit_frodo_data,
33464 + inc_use: frodo_inc_use,
33465 + dec_use: frodo_dec_use,
33466 + client_register: frodo_client_register,
33467 + client_unregister: frodo_client_unregister
33470 +static int __init i2c_frodo_init (void)
33472 + return (i2c_bit_add_bus (&frodo_ops));
33475 +EXPORT_NO_SYMBOLS;
33477 +static void __exit i2c_frodo_exit (void)
33479 + i2c_bit_del_bus (&frodo_ops);
33482 +MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
33483 +MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
33484 +MODULE_LICENSE ("GPL");
33485 +EXPORT_NO_SYMBOLS;
33487 +module_init (i2c_frodo_init);
33488 +module_exit (i2c_frodo_exit);
33490 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
33491 +++ linux-2.4.25/drivers/i2c/i2c-guide.c 2004-03-31 17:15:09.000000000 +0200
33492 @@ -0,0 +1,199 @@
33493 +/************************************************************************************\
33494 +Copyright : Copyright (C) 1995-2000 Simon G. Vogl
33495 + Copyright 2002 IDERs Incorporated
33496 +File Name : i2c-guide.c
33497 +Description : this i2c driver uses the GPIO port B pin 0 and pin 1 on the cs89712.
33498 +Notes : To change the bit rate, change the structure i2c_algo_bit_data
33499 + : to 10 10 100
33500 +Contact : tsong@iders.ca
33501 +License : This source code is free software; you can redistribute it and/or
33502 + modify it under the terms of the GNU General Public License
33503 + version 2 as published by the Free Software Foundation.
33504 +\************************************************************************************/
33506 +#include <linux/kernel.h>
33507 +#include <linux/ioport.h>
33508 +#include <linux/module.h>
33509 +#include <linux/init.h>
33510 +#include <linux/string.h> /* for 2.0 kernels to get NULL */
33511 +#include <asm/errno.h> /* for 2.0 kernels to get ENODEV */
33512 +#include <asm/io.h>
33514 +#include <asm/hardware/cs89712.h> // io operation ep_writel()
33515 +#include <asm/hardware/clps7111.h> // io operation clps_writel()
33516 +#include <asm/arch-clps711x/hardware.h> // io operation clps_writel()
33518 +#include <linux/i2c.h>
33519 +#include <linux/i2c-algo-bit.h>
33521 +/* ----- global defines ----------------------------------------------- */
33523 +#define DEB(x) /* should be reasonable open, close &c. */
33524 +#define DEB2(x) /* low level debugging - very slow */
33525 +#define DEBE(x) x /* error messages */
33526 + /* Pin Port Inverted name */
33527 +#define I2C_SDA 0x08 /* port B ctrl pin 3 (inv) */
33528 +#define I2C_SCL 0x04 /* port B ctrl pin 2 (inv) */
33530 +#define I2C_SDAIN 0x08 /* use the same pin with output */
33531 +#define I2C_SCLIN 0x04 /* use the same pin with output */
33533 +#define I2C_DMASK 0xf7 /* inverse of I2C_SDA */
33534 +#define I2C_CMASK 0xfb /* inverse of I2c_SCL */
33536 +#define PORTB_PIN0_SDA_OUTPUT 0x08 /* pin 3 direction of port B output */
33537 +#define PORTB_PIN0_SDA_INPUT 0xf7 /* pin 3 direction of port B input */
33539 +#define PORTB_PIN1_SCL_OUTPUT 0x04 /* pin 2 direction of port B output */
33540 +#define PORTB_PIN1_SCL_INPUT 0xfb /* pin 2 direction of port B input */
33542 +int base = 0;
33543 +#define DEFAULT_BASE PBDR
33545 +/* ----- local functions --------------------------------------------------- */
33547 +static void bit_guide_setscl(void* data, int state)
33549 + if (state) {
33550 + // set port B pin2 input
33551 + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN1_SCL_INPUT, PBDDR);
33553 + else {
33554 + // clear
33555 + clps_writeb((clps_readb(PBDR)) & I2C_CMASK, PBDR);
33556 + // set port B pin2 output
33557 + clps_writeb((clps_readb(PBDDR)) | PORTB_PIN1_SCL_OUTPUT, PBDDR);
33561 +static void bit_guide_setsda(void* data, int state)
33563 + if (state) {
33564 + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
33565 + // float pin 0 (actually drive high by pull up resistor)
33566 + // clps_writeb((clps_readb(PBDR)) | I2C_SDA, PBDR); // set Jan4 ori: eff
33567 + // printk("set sda high, state=%i\n",state);
33569 + else {
33570 + // clear
33571 + clps_writeb((clps_readb(PBDR)) & I2C_DMASK, PBDR);
33572 + // set port B pin 0 output
33573 + clps_writeb((clps_readb(PBDDR)) | PORTB_PIN0_SDA_OUTPUT, PBDDR);
33577 +static int bit_guide_getscl(void *data)
33579 + return ( 0 != ( (clps_readb(PBDR)) & I2C_SCLIN ) );
33582 +static int bit_guide_getsda(void *data)
33584 + // set port B pin 0 input Jan4 ori eff
33585 + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
33586 + return ( 0 != ( (clps_readb(PBDR) ) & I2C_SDAIN ) );
33589 +static int bit_guide_init(void)
33591 + bit_guide_setsda((void*)base,1);
33592 + bit_guide_setscl((void*)base,1);
33593 + return 0;
33596 +static int bit_guide_reg(struct i2c_client *client)
33598 + return 0;
33601 +static int bit_guide_unreg(struct i2c_client *client)
33603 + return 0;
33606 +static void bit_guide_inc_use(struct i2c_adapter *adap)
33608 +#ifdef MODULE
33609 + MOD_INC_USE_COUNT;
33610 +#endif
33613 +static void bit_guide_dec_use(struct i2c_adapter *adap)
33615 +#ifdef MODULE
33616 + MOD_DEC_USE_COUNT;
33617 +#endif
33620 +/* ------------------------------------------------------------------------
33621 + * Encapsulate the above functions in the correct operations structure.
33622 + * This is only done when more than one hardware adapter is supported.
33623 + */
33625 +/* last line (us, ms, timout)
33626 + * us dominates the bit rate: 10us means: 100Kbit/sec(25 means 40kbps)
33627 + * 10ms not known
33628 + * 100ms timeout
33629 + */
33630 +static struct i2c_algo_bit_data bit_guide_data = {
33631 + NULL,
33632 + bit_guide_setsda,
33633 + bit_guide_setscl,
33634 + bit_guide_getsda,
33635 + bit_guide_getscl,
33636 + 50, 10, 100, /* orginal (non-guide) value 10, 10, 100 */
33639 +static struct i2c_adapter bit_guide_ops = {
33640 + "Guide Port B: PIN2-SCL/PIN3-SDA",
33641 + I2C_HW_B_GUIDE,
33642 + NULL,
33643 + &bit_guide_data,
33644 + bit_guide_inc_use,
33645 + bit_guide_dec_use,
33646 + bit_guide_reg,
33647 + bit_guide_unreg,
33650 +static int __init i2c_bitguide_init(void)
33652 + printk("i2c-guide.o: Guide i2c port B adapter module.\n");
33653 + clps_writeb((clps_readb(PBDDR)) & 0xfd, PBDDR); // set service reuest pb1 as input
33654 + if (base==0) {
33655 + /* probe some values */
33656 + base=DEFAULT_BASE;
33657 + bit_guide_data.data=(void*)DEFAULT_BASE;
33658 + if (bit_guide_init()==0) {
33659 + if(i2c_bit_add_bus(&bit_guide_ops) < 0)
33660 + return -ENODEV;
33661 + } else {
33662 + return -ENODEV;
33664 + } else {
33665 + bit_guide_data.data=(void*)base;
33666 + if (bit_guide_init()==0) {
33667 + if(i2c_bit_add_bus(&bit_guide_ops) < 0)
33668 + return -ENODEV;
33669 + } else {
33670 + return -ENODEV;
33673 + printk("i2c-guide.o: found device at %#x.\n",base);
33674 + return 0;
33677 +EXPORT_NO_SYMBOLS;
33679 +MODULE_AUTHOR("T. C. Song <tsong@iders.ca>");
33680 +MODULE_DESCRIPTION("I2C-Bus adapter routines for Guide (cs89712) GPIO port B");
33681 +MODULE_LICENSE("GPL");
33683 +MODULE_PARM(base, "i");
33685 +module_init(i2c_bitguide_init);
33686 +/* for completeness, we should have a module_exit() function, but the
33687 + GUIDE requires this to always be loaded. If it is unloaded, the
33688 + operation of the GUIDE is undefined.
33689 + Nobody has written the i2c_bitguide_exit() routine yet, so it is not included.
33690 +module_exit(i2c_bitguide_exit);
33692 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
33693 +++ linux-2.4.25/drivers/i2c/i2c-omaha.c 2004-03-31 17:15:09.000000000 +0200
33694 @@ -0,0 +1,276 @@
33695 +/* ------------------------------------------------------------------------- *
33696 + Copyright ARM Limited 2002. All rights reserved.
33698 + i2c driver for Omaha
33700 + Notes:Based on i2c-elv.c
33702 + The S3C2400X01 has better support for I2C, but bit oriented operations
33703 + are directly supported by the other I2C layers, so we use that method
33704 + of performing I2C operations.
33706 + Copyright (C) 1995-2000 Simon G. Vogl
33708 + This program is free software; you can redistribute it and/or modify
33709 + it under the terms of the GNU General Public License as published by
33710 + the Free Software Foundation; either version 2 of the License, or
33711 + (at your option) any later version.
33713 + This program is distributed in the hope that it will be useful,
33714 + but WITHOUT ANY WARRANTY; without even the implied warranty of
33715 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33716 + GNU General Public License for more details.
33718 + You should have received a copy of the GNU General Public License
33719 + along with this program; if not, write to the Free Software
33720 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
33721 +/* ------------------------------------------------------------------------- */
33723 +#include <linux/kernel.h>
33724 +#include <linux/module.h>
33725 +#include <linux/delay.h>
33726 +#include <linux/slab.h>
33727 +#include <linux/version.h>
33728 +#include <linux/init.h>
33729 +#include <asm/irq.h>
33730 +#include <asm/io.h>
33731 +#include <asm/uaccess.h>
33732 +#include <linux/ioport.h>
33733 +#include <linux/errno.h>
33734 +#include <linux/sched.h>
33736 +#include <linux/i2c.h>
33737 +#include <linux/i2c-algo-bit.h>
33739 +#include <asm/io.h>
33740 +#include <asm/hardware.h>
33742 +/* ----- global defines ----------------------------------------------- */
33743 +#define DEB(x) if (i2c_debug>=1) x;
33744 +#define DEB2(x) if (i2c_debug>=2) x;
33745 +#define DEB3(x) if (i2c_debug>=3) x
33746 +#define DEBE(x) x // error messages
33747 +#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
33748 +#define DEBPROTO(x) if (i2c_debug>=9) { x; }
33749 + /* debug the protocol by showing transferred bits */
33751 +/* Register and bitdefs for Omaha */
33753 +// Port G control registers
33754 +static volatile unsigned int pgcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
33755 +static volatile unsigned int pgdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGDAT);
33757 +static volatile unsigned int opencr = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_OPENCR);
33759 +static int base = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
33761 +// Open drain control registers
33762 +#define OPC_CMD BIT2
33763 +#define OPC_DAT BIT3
33765 +// data bits in GPIO Port G data register
33766 +#define OMAHA_SDA BIT5
33767 +#define OMAHA_SCL BIT6
33768 +#define IIC_WP BIT3 // Write Protect for EEPROM
33770 +// input/out select bits in GPIO G control register
33771 +#define IIC_BITS (BIT12|BIT10|BIT6);
33774 +/* ----- local functions ---------------------------------------------- */
33777 +static void bit_omaha_setscl(void *data, int state)
33779 + unsigned int tmp;
33781 + if (state)
33783 + tmp = __raw_readl(pgdat);
33784 + tmp |= OMAHA_SCL;
33785 + __raw_writel(tmp,pgdat);
33787 + else
33789 + tmp = __raw_readl(pgdat);
33790 + tmp &= ~OMAHA_SCL;
33791 + __raw_writel(tmp,pgdat);
33795 +static void bit_omaha_setsda(void *data, int state)
33797 + unsigned int tmp;
33799 + // ensure that sda is an output at the moment
33800 + tmp = __raw_readl(pgcon);
33801 + tmp = tmp | BIT10;
33802 + __raw_writel(tmp,pgcon);
33804 + if (state)
33806 + tmp = __raw_readl(pgdat);
33807 + tmp |= OMAHA_SDA;
33808 + __raw_writel(tmp,pgdat);
33810 + else
33812 + tmp = __raw_readl(pgdat);
33813 + tmp &= ~OMAHA_SDA;
33814 + __raw_writel(tmp,pgdat);
33818 +static int bit_omaha_getscl(void *data)
33820 + if (__raw_readl(pgdat) & OMAHA_SCL)
33821 + return 1;
33822 + else
33823 + return 0;
33826 +static int bit_omaha_getsda(void *data)
33828 + unsigned int tmp;
33830 + // ensure that sda is an output at the moment
33831 + tmp = __raw_readl(pgcon);
33832 + tmp = tmp & ~BIT10;
33833 + __raw_writel(tmp,pgcon);
33835 + if (__raw_readl(pgdat) & OMAHA_SDA)
33836 + return 1;
33837 + else
33838 + return 0;
33841 +static int bit_omaha_init(void)
33843 + // Have we got some mmapped space?
33844 + if (request_region(base, 0x100, "i2c (omaha bus adapter)") < 0 )
33846 + printk("i2c-omaha.o: requested I/O region (0x%08x) is in use.\n", base);
33847 + return -ENODEV;
33850 + return 0;
33854 +static int bit_omaha_reg(struct i2c_client *client)
33856 + return 0;
33860 +static int bit_omaha_unreg(struct i2c_client *client)
33862 + return 0;
33865 +static void bit_omaha_inc_use(struct i2c_adapter *adap)
33867 + MOD_INC_USE_COUNT;
33870 +static void bit_omaha_dec_use(struct i2c_adapter *adap)
33872 + MOD_DEC_USE_COUNT;
33877 +/* ------------------------------------------------------------------------
33878 + * Encapsulate the above functions in the correct operations structure.
33879 + * This is only done when more than one hardware adapter is supported.
33880 + */
33881 +static struct i2c_algo_bit_data bit_omaha_data = {
33882 + NULL,
33883 + bit_omaha_setsda,
33884 + bit_omaha_setscl,
33885 + bit_omaha_getsda,
33886 + bit_omaha_getscl,
33887 + 10, 10, 20, /* waits, timeout */
33890 +static struct i2c_adapter bit_omaha_ops = {
33891 + "BIT-Type Omaha I2C adapter",
33892 + I2C_HW_B_OMAHA,
33893 + NULL,
33894 + &bit_omaha_data,
33895 + bit_omaha_inc_use,
33896 + bit_omaha_dec_use,
33897 + bit_omaha_reg,
33898 + bit_omaha_unreg,
33899 +};
33901 +static int __init i2c_omaha_init (void)
33903 + unsigned int tmp;
33905 + printk("i2c-omaha.o: i2c omaha adapter module\n");
33907 + if (bit_omaha_init() == 0) {
33908 + if(i2c_bit_add_bus(&bit_omaha_ops) < 0)
33910 + printk("Could not add bus!\n");
33911 + return -ENODEV;
33913 + } else {
33914 + printk("Could not pcf_omaha_init\n");
33915 + return -ENODEV;
33916 + }
33918 + // Program Port G bits to output function
33919 + tmp = __raw_readl(pgcon);
33920 + tmp |= IIC_BITS;
33921 + __raw_writel(tmp,pgcon);
33923 + // Ensure SDA and SCL are open-drain
33924 + tmp = __raw_readl(opencr);
33925 + tmp = tmp | OPC_CMD | OPC_DAT;
33926 + __raw_writel(tmp,opencr);
33928 + bit_omaha_setsda((void*)base,1);
33929 + bit_omaha_setscl((void*)base,1);
33931 + // Disable WP
33932 + tmp = __raw_readl(pgdat);
33933 + tmp = tmp & ~IIC_WP;
33934 + __raw_writel(tmp,pgdat);
33936 + return 0;
33939 +static void bit_omaha_exit(void)
33941 + release_region(base , 2);
33944 +static void i2c_omaha_exit(void)
33947 + i2c_bit_del_bus(&bit_omaha_ops);
33949 + bit_omaha_exit();
33953 +EXPORT_NO_SYMBOLS;
33955 +MODULE_AUTHOR("ARM Limited <support@arm.com>");
33956 +MODULE_DESCRIPTION("I2C-Bus adapter routines for Omaha");
33957 +MODULE_LICENSE("GPL");
33959 +MODULE_PARM(base, "i");
33960 +MODULE_PARM(irq, "i");
33961 +MODULE_PARM(clock, "i");
33962 +MODULE_PARM(own, "i");
33963 +MODULE_PARM(mmapped, "i");
33964 +MODULE_PARM(i2c_debug, "i");
33967 +module_init(i2c_omaha_init);
33968 +module_exit(i2c_omaha_exit);
33971 --- linux-2.4.25/drivers/i2c/i2c-philips-par.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
33972 +++ linux-2.4.25/drivers/i2c/i2c-philips-par.c 2004-03-31 17:15:09.000000000 +0200
33973 @@ -16,7 +16,7 @@
33974 You should have received a copy of the GNU General Public License
33975 along with this program; if not, write to the Free Software
33976 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
33977 -/* ------------------------------------------------------------------------- */
33978 +/* ------------------------------------------------------------------------- */
33980 /* With some changes from Kyƶsti MƤlkki <kmalkki@cc.hut.fi> and even
33981 Frodo Looijaard <frodol@dds.nl> */
33982 @@ -72,7 +72,7 @@
33984 static void bit_lp_setscl(void *data, int state)
33986 - /*be cautious about state of the control register -
33987 + /*be cautious about state of the control register -
33988 touch only the one bit needed*/
33989 if (state) {
33990 parport_write_control((struct parport *) data,
33991 @@ -126,7 +126,7 @@
33993 static int bit_lp_getsda2(void *data)
33995 - return (parport_read_status((struct parport *) data) &
33996 + return (parport_read_status((struct parport *) data) &
33997 PARPORT_STATUS_BUSY) ? 0 : 1;
34000 @@ -154,7 +154,7 @@
34001 * Encapsulate the above functions in the correct operations structure.
34002 * This is only done when more than one hardware adapter is supported.
34006 static struct i2c_algo_bit_data bit_lp_data = {
34007 NULL,
34008 bit_lp_setsda,
34009 @@ -162,7 +162,7 @@
34010 bit_lp_getsda,
34011 bit_lp_getscl,
34012 80, 80, 100, /* waits, timeout */
34013 -};
34016 static struct i2c_algo_bit_data bit_lp_data2 = {
34017 NULL,
34018 @@ -171,7 +171,7 @@
34019 bit_lp_getsda2,
34020 NULL,
34021 80, 80, 100, /* waits, timeout */
34022 -};
34025 static struct i2c_adapter bit_lp_ops = {
34026 "Philips Parallel port adapter",
34027 @@ -197,7 +197,7 @@
34028 printk(KERN_DEBUG "i2c-philips-par.o: attaching to %s\n", port->name);
34030 adapter->pdev = parport_register_device(port, "i2c-philips-par",
34031 - NULL, NULL, NULL,
34032 + NULL, NULL, NULL,
34033 PARPORT_FLAG_EXCL,
34034 NULL);
34035 if (!adapter->pdev) {
34036 @@ -257,16 +257,16 @@
34037 NULL
34040 -int __init i2c_bitlp_init(void)
34041 +static int __init i2c_bitlp_init(void)
34043 printk(KERN_INFO "i2c-philips-par.o: i2c Philips parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
34045 parport_register_driver(&i2c_driver);
34048 return 0;
34051 -void __exit i2c_bitlp_exit(void)
34052 +static void __exit i2c_bitlp_exit(void)
34054 parport_unregister_driver(&i2c_driver);
34056 @@ -279,14 +279,5 @@
34058 MODULE_PARM(type, "i");
34060 -#ifdef MODULE
34061 -int init_module(void)
34063 - return i2c_bitlp_init();
34066 -void cleanup_module(void)
34068 - i2c_bitlp_exit();
34070 -#endif
34071 +module_init(i2c_bitlp_init);
34072 +module_exit(i2c_bitlp_exit);
34073 --- linux-2.4.25/drivers/i2c/i2c-velleman.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
34074 +++ linux-2.4.25/drivers/i2c/i2c-velleman.c 2004-03-31 17:15:09.000000000 +0200
34075 @@ -65,7 +65,7 @@
34076 } else {
34077 outb(inb(CTRL) | I2C_SCL, CTRL);
34083 static void bit_velle_setsda(void *data, int state)
34084 @@ -75,8 +75,8 @@
34085 } else {
34086 outb(inb(CTRL) | I2C_SDA, CTRL);
34093 static int bit_velle_getscl(void *data)
34095 @@ -95,7 +95,7 @@
34096 base));
34097 return -ENODEV;
34098 } else {
34099 - request_region(base, (base == 0x3bc)? 3 : 8,
34100 + request_region(base, (base == 0x3bc)? 3 : 8,
34101 "i2c (Vellemann adapter)");
34102 bit_velle_setsda((void*)base,1);
34103 bit_velle_setscl((void*)base,1);
34104 @@ -104,7 +104,7 @@
34107 static void __exit bit_velle_exit(void)
34110 release_region( base , (base == 0x3bc)? 3 : 8 );
34113 @@ -121,16 +121,12 @@
34115 static void bit_velle_inc_use(struct i2c_adapter *adap)
34117 -#ifdef MODULE
34118 MOD_INC_USE_COUNT;
34119 -#endif
34122 static void bit_velle_dec_use(struct i2c_adapter *adap)
34124 -#ifdef MODULE
34125 MOD_DEC_USE_COUNT;
34126 -#endif
34129 /* ------------------------------------------------------------------------
34130 @@ -158,7 +154,7 @@
34131 bit_velle_unreg,
34134 -int __init i2c_bitvelle_init(void)
34135 +static int __init i2c_bitvelle_init(void)
34137 printk(KERN_INFO "i2c-velleman.o: i2c Velleman K8000 adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
34138 if (base==0) {
34139 @@ -184,24 +180,19 @@
34140 return 0;
34143 +static void __exit i2c_bitvelle_exit(void)
34145 + i2c_bit_del_bus(&bit_velle_ops);
34146 + bit_velle_exit();
34149 EXPORT_NO_SYMBOLS;
34151 -#ifdef MODULE
34152 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
34153 MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter");
34154 MODULE_LICENSE("GPL");
34156 MODULE_PARM(base, "i");
34158 -int init_module(void)
34160 - return i2c_bitvelle_init();
34163 -void cleanup_module(void)
34165 - i2c_bit_del_bus(&bit_velle_ops);
34166 - bit_velle_exit();
34169 -#endif
34170 +module_init(i2c_bitvelle_init);
34171 +module_exit(i2c_bitvelle_exit);
34172 --- linux-2.4.25/drivers/ide/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
34173 +++ linux-2.4.25/drivers/ide/Config.in 2004-03-31 17:15:09.000000000 +0200
34174 @@ -106,6 +106,9 @@
34175 define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS
34176 dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN
34178 + if [ "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
34179 + dep_bool ' RiscStation IDE' CONFIG_BLK_DEV_IDE_RISCSTATION $CONFIG_ARCH_RISCSTATION
34180 + fi
34181 if [ "$CONFIG_AMIGA" = "y" ]; then
34182 dep_bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
34183 dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
34184 --- linux-2.4.25/drivers/ide/arm/Makefile~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
34185 +++ linux-2.4.25/drivers/ide/arm/Makefile 2004-03-31 17:15:09.000000000 +0200
34186 @@ -6,6 +6,7 @@
34188 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
34189 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
34190 +obj-$(CONFIG_BLK_DEV_IDE_RISCSTATION) += rstation-ide.o
34192 EXTRA_CFLAGS := -I../
34194 --- linux-2.4.25/drivers/ide/arm/icside.c~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
34195 +++ linux-2.4.25/drivers/ide/arm/icside.c 2004-03-31 17:15:09.000000000 +0200
34196 @@ -1,7 +1,7 @@
34198 * linux/drivers/ide/arm/icside.c
34200 - * Copyright (c) 1996,1997 Russell King.
34201 + * Copyright (c) 1996-2003 Russell King.
34203 * Changelog:
34204 * 08-Jun-1996 RMK Created
34205 @@ -26,24 +26,6 @@
34206 #include <asm/ecard.h>
34207 #include <asm/io.h>
34209 -#include "ide-noise.h"
34212 - * FIXME: We want to drop the the MACRO CRAP!
34214 - * ec->iops->in{b/w/l}
34215 - * ec->iops->in{b/w/l}_p
34216 - * ec->iops->out{b/w/l}
34217 - * ec->iops->out{b/w/l}_p
34219 - * the new core supports clean MMIO calls and other goodies
34220 - */
34223 - * Maximum number of interfaces per card
34224 - */
34225 -#define MAX_IFS 2
34227 #define ICS_IDENT_OFFSET 0x8a0
34229 #define ICS_ARCIN_V5_INTRSTAT 0x000
34230 @@ -86,17 +68,20 @@
34231 ICS_ARCIN_V6_IDESTEPPING
34234 -static const card_ids icside_cids[] = {
34235 - { MANU_ICS, PROD_ICS_IDE },
34236 - { MANU_ICS2, PROD_ICS2_IDE },
34237 - { 0xffff, 0xffff }
34238 +struct icside_state {
34239 + unsigned int channel;
34240 + unsigned int enabled;
34241 + unsigned long irq_port;
34242 + unsigned long slot_port;
34243 + unsigned int type;
34244 + ide_hwif_t *hwif[2];
34247 -typedef enum {
34248 - ics_if_unknown,
34249 - ics_if_arcin_v5,
34250 - ics_if_arcin_v6
34251 -} iftype_t;
34252 +#define ICS_TYPE_A3IN 0
34253 +#define ICS_TYPE_A3USER 1
34254 +#define ICS_TYPE_V6 3
34255 +#define ICS_TYPE_V5 15
34256 +#define ICS_TYPE_NOTYPE ((unsigned int)-1)
34258 /* ---------------- Version 5 PCB Support Functions --------------------- */
34259 /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
34260 @@ -104,8 +89,10 @@
34262 static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
34264 - unsigned int memc_port = (unsigned int)ec->irq_data;
34265 - outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET);
34266 + struct icside_state *state = ec->irq_data;
34267 + unsigned int base = state->irq_port;
34269 + outb(0, base + ICS_ARCIN_V5_INTROFFSET);
34272 /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
34273 @@ -113,17 +100,15 @@
34275 static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
34277 - unsigned int memc_port = (unsigned int)ec->irq_data;
34278 - inb(memc_port + ICS_ARCIN_V5_INTROFFSET);
34279 + struct icside_state *state = ec->irq_data;
34280 + unsigned int base = state->irq_port;
34282 + inb(base + ICS_ARCIN_V5_INTROFFSET);
34285 static const expansioncard_ops_t icside_ops_arcin_v5 = {
34286 - icside_irqenable_arcin_v5,
34287 - icside_irqdisable_arcin_v5,
34288 - NULL,
34289 - NULL,
34290 - NULL,
34291 - NULL
34292 + .irqenable = icside_irqenable_arcin_v5,
34293 + .irqdisable = icside_irqdisable_arcin_v5,
34297 @@ -133,10 +118,21 @@
34299 static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
34301 - unsigned int ide_base_port = (unsigned int)ec->irq_data;
34302 + struct icside_state *state = ec->irq_data;
34303 + unsigned int base = state->irq_port;
34305 - outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
34306 - outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
34307 + state->enabled = 1;
34309 + switch (state->channel) {
34310 + case 0:
34311 + outb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
34312 + inb(base + ICS_ARCIN_V6_INTROFFSET_2);
34313 + break;
34314 + case 1:
34315 + outb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
34316 + inb(base + ICS_ARCIN_V6_INTROFFSET_1);
34317 + break;
34321 /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
34322 @@ -144,10 +140,12 @@
34324 static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
34326 - unsigned int ide_base_port = (unsigned int)ec->irq_data;
34327 + struct icside_state *state = ec->irq_data;
34329 - inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
34330 - inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
34331 + state->enabled = 0;
34333 + inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
34334 + inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
34337 /* Prototype: icside_irqprobe(struct expansion_card *ec)
34338 @@ -155,70 +153,49 @@
34340 static int icside_irqpending_arcin_v6(struct expansion_card *ec)
34342 - unsigned int ide_base_port = (unsigned int)ec->irq_data;
34343 + struct icside_state *state = ec->irq_data;
34345 - return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
34346 - inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
34347 + return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
34348 + inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
34351 static const expansioncard_ops_t icside_ops_arcin_v6 = {
34352 - icside_irqenable_arcin_v6,
34353 - icside_irqdisable_arcin_v6,
34354 - icside_irqpending_arcin_v6,
34355 - NULL,
34356 - NULL,
34357 - NULL
34358 + .irqenable = icside_irqenable_arcin_v6,
34359 + .irqdisable = icside_irqdisable_arcin_v6,
34360 + .irqpending = icside_irqpending_arcin_v6,
34363 -/* Prototype: icside_identifyif (struct expansion_card *ec)
34364 - * Purpose : identify IDE interface type
34365 - * Notes : checks the description string
34367 + * Handle routing of interrupts. This is called before
34368 + * we write the command to the drive.
34370 -static iftype_t __init icside_identifyif (struct expansion_card *ec)
34371 +static void icside_maskproc(ide_drive_t *drive, int mask)
34373 - unsigned int addr;
34374 - iftype_t iftype;
34375 - int id = 0;
34377 - iftype = ics_if_unknown;
34379 - addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
34381 - id = inb(addr) & 1;
34382 - id |= (inb(addr + 1) & 1) << 1;
34383 - id |= (inb(addr + 2) & 1) << 2;
34384 - id |= (inb(addr + 3) & 1) << 3;
34386 - switch (id) {
34387 - case 0: /* A3IN */
34388 - printk("icside: A3IN unsupported\n");
34389 - break;
34391 - case 1: /* A3USER */
34392 - printk("icside: A3USER unsupported\n");
34393 - break;
34394 + ide_hwif_t *hwif = HWIF(drive);
34395 + struct icside_state *state = hwif->hwif_data;
34396 + unsigned long flags;
34398 - case 3: /* ARCIN V6 */
34399 - printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no);
34400 - iftype = ics_if_arcin_v6;
34401 - break;
34402 + local_irq_save(flags);
34404 - case 15:/* ARCIN V5 (no id) */
34405 - printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no);
34406 - iftype = ics_if_arcin_v5;
34407 - break;
34408 + state->channel = hwif->channel;
34410 - default:/* we don't know - complain very loudly */
34411 - printk("icside: ***********************************\n");
34412 - printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id);
34413 - printk("icside: ***********************************\n");
34414 - printk("icside: please report this to linux@arm.linux.org.uk\n");
34415 - printk("icside: defaulting to ARCIN V5\n");
34416 - iftype = ics_if_arcin_v5;
34417 - break;
34418 + if (state->enabled && !mask) {
34419 + switch (hwif->channel) {
34420 + case 0:
34421 + outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
34422 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
34423 + break;
34424 + case 1:
34425 + outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
34426 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
34427 + break;
34429 + } else {
34430 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
34431 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
34434 - return iftype;
34435 + local_irq_restore(flags);
34438 #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
34439 @@ -234,125 +211,138 @@
34440 #define NR_ENTRIES 256
34441 #define TABLE_SIZE (NR_ENTRIES * 8)
34443 -static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
34444 +static void ide_build_sglist(ide_drive_t *drive, struct request *rq)
34446 - struct buffer_head *bh;
34447 + ide_hwif_t *hwif = HWIF(drive);
34448 struct scatterlist *sg = hwif->sg_table;
34449 + struct buffer_head *bh;
34450 int nents = 0;
34452 - if (rq->cmd == READ)
34453 - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
34454 - else
34455 - hwif->sg_dma_direction = PCI_DMA_TODEVICE;
34456 - bh = rq->bh;
34457 - do {
34458 - unsigned char *virt_addr = bh->b_data;
34459 - unsigned int size = bh->b_size;
34460 + BUG_ON(hwif->sg_dma_active);
34462 - while ((bh = bh->b_reqnext) != NULL) {
34463 - if ((virt_addr + size) != (unsigned char *)bh->b_data)
34464 - break;
34465 - size += bh->b_size;
34467 - memset(&sg[nents], 0, sizeof(*sg));
34468 - sg[nents].address = virt_addr;
34469 - sg[nents].length = size;
34470 - nents++;
34471 - } while (bh != NULL);
34472 + if (rq->cmd == IDE_DRIVE_TASKFILE) {
34473 + ide_task_t *args = rq->special;
34475 - return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
34477 + if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
34478 + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
34479 + else
34480 + hwif->sg_dma_direction = PCI_DMA_TODEVICE;
34482 -static int
34483 -icside_build_dmatable(ide_drive_t *drive, int ddir)
34485 - return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq, ddir);
34487 + memset(sg, 0, sizeof(*sg));
34488 + sg->address = rq->buffer;
34489 + sg->length = rq->nr_sectors * SECTOR_SIZE;
34490 + nents = 1;
34491 + } else {
34492 + if (rq->cmd == READ)
34493 + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
34494 + else
34495 + hwif->sg_dma_direction = PCI_DMA_TODEVICE;
34497 -/* Teardown mappings after DMA has completed. */
34498 -static void icside_destroy_dmatable(ide_drive_t *drive)
34500 - struct scatterlist *sg = HWIF(drive)->sg_table;
34501 - int nents = HWIF(drive)->sg_nents;
34502 + bh = rq->bh;
34503 + do {
34504 + unsigned long lastend;
34506 - pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
34507 + memset(sg, 0, sizeof(*sg));
34508 + sg->page = bh->b_page;
34509 + lastend = bh_phys(bh);
34511 + do {
34512 + lastend += bh->b_size;
34513 + sg->length += bh->b_size;
34515 + bh = bh->b_reqnext;
34516 + if (bh == NULL)
34517 + break;
34518 + } while (lastend == bh_phys(bh));
34520 + sg++;
34521 + nents++;
34522 + } while (bh != NULL);
34525 + nents = pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
34527 + hwif->sg_nents = nents;
34530 -static int
34531 -icside_config_if(ide_drive_t *drive, int xfer_mode)
34534 + * Configure the IOMD to give the appropriate timings for the transfer
34535 + * mode being requested. We take the advice of the ATA standards, and
34536 + * calculate the cycle time based on the transfer mode, and the EIDE
34537 + * MW DMA specs that the drive provides in the IDENTIFY command.
34539 + * We have the following IOMD DMA modes to choose from:
34541 + * Type Active Recovery Cycle
34542 + * A 250 (250) 312 (550) 562 (800)
34543 + * B 187 250 437
34544 + * C 125 (125) 125 (375) 250 (500)
34545 + * D 62 125 187
34547 + * (figures in brackets are actual measured timings)
34549 + * However, we also need to take care of the read/write active and
34550 + * recovery timings:
34552 + * Read Write
34553 + * Mode Active -- Recovery -- Cycle IOMD type
34554 + * MW0 215 50 215 480 A
34555 + * MW1 80 50 50 150 C
34556 + * MW2 70 25 25 120 C
34557 + */
34558 +static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode)
34560 - int func = ide_dma_off;
34561 + int on = 0, cycle_time = 0, use_dma_info = 0;
34563 + /*
34564 + * Limit the transfer speed to MW_DMA_2.
34565 + */
34566 + if (xfer_mode > XFER_MW_DMA_2)
34567 + xfer_mode = XFER_MW_DMA_2;
34569 switch (xfer_mode) {
34570 case XFER_MW_DMA_2:
34571 - /*
34572 - * The cycle time is limited to 250ns by the r/w
34573 - * pulse width (90ns), however we should still
34574 - * have a maximum burst transfer rate of 8MB/s.
34575 - */
34576 - drive->drive_data = 250;
34577 + cycle_time = 250;
34578 + use_dma_info = 1;
34579 break;
34581 case XFER_MW_DMA_1:
34582 - drive->drive_data = 250;
34583 + cycle_time = 250;
34584 + use_dma_info = 1;
34585 break;
34587 case XFER_MW_DMA_0:
34588 - drive->drive_data = 480;
34589 + cycle_time = 480;
34590 break;
34592 - default:
34593 - drive->drive_data = 0;
34594 + case XFER_SW_DMA_2:
34595 + case XFER_SW_DMA_1:
34596 + case XFER_SW_DMA_0:
34597 + cycle_time = 480;
34598 break;
34601 - if (!drive->init_speed)
34602 - drive->init_speed = (u8) xfer_mode;
34603 + /*
34604 + * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
34605 + * take care to note the values in the ID...
34606 + */
34607 + if (use_dma_info && drive->id->eide_dma_time > cycle_time)
34608 + cycle_time = drive->id->eide_dma_time;
34610 - if (drive->drive_data &&
34611 - ide_config_drive_speed(drive, (u8) xfer_mode) == 0)
34612 - func = ide_dma_on;
34613 + drive->drive_data = cycle_time;
34615 + if (cycle_time && ide_config_drive_speed(drive, xfer_mode) == 0)
34616 + on = 1;
34617 else
34618 drive->drive_data = 480;
34620 printk("%s: %s selected (peak %dMB/s)\n", drive->name,
34621 ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
34623 - drive->current_speed = (u8) xfer_mode;
34625 - return func;
34628 -static int
34629 -icside_set_speed(ide_drive_t *drive, u8 speed)
34631 - return icside_config_if(drive, speed);
34635 - * dma_intr() is the handler for disk read/write DMA interrupts
34636 - */
34637 -static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
34639 - u8 dma_stat = HWIF(drive)->ide_dma_end(drive);
34640 - /* get drive status */
34641 - u8 stat = HWIF(drive)->INB(IDE_STATUS_REG);
34642 - int i;
34643 + drive->current_speed = xfer_mode;
34645 - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
34646 - if (!dma_stat) {
34647 - struct request *rq = HWGROUP(drive)->rq;
34648 - rq = HWGROUP(drive)->rq;
34649 - for (i = rq->nr_sectors; i > 0;) {
34650 - i -= rq->current_nr_sectors;
34651 - DRIVER(drive)->end_request(drive, 1);
34653 - return ide_stopped;
34655 - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
34656 - drive->name, dma_stat);
34658 - return DRIVER(drive)->error(drive, "dma_intr", stat);
34659 + return on;
34663 @@ -361,19 +351,19 @@
34664 * This should be defined in one place only.
34666 struct drive_list_entry {
34667 - char * id_model;
34668 - char * id_firmware;
34669 + const char * id_model;
34670 + const char * id_firmware;
34673 -static struct drive_list_entry drive_whitelist [] = {
34674 +static const struct drive_list_entry drive_whitelist [] = {
34675 { "Micropolis 2112A", "ALL" },
34676 { "CONNER CTMA 4000", "ALL" },
34677 { "CONNER CTT8000-A", "ALL" },
34678 { "ST34342A", "ALL" },
34679 - { NULL, 0 }
34680 + { NULL, NULL }
34683 -static struct drive_list_entry drive_blacklist [] = {
34684 +static const struct drive_list_entry drive_blacklist [] = {
34685 { "WDC AC11000H", "ALL" },
34686 { "WDC AC22100H", "ALL" },
34687 { "WDC AC32500H", "ALL" },
34688 @@ -407,10 +397,11 @@
34689 { "PLEXTOR CD-R PX-W8432T", "ALL" },
34690 { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
34691 { "_NEC DV5800A", "ALL" },
34692 - { NULL, 0 }
34693 + { NULL, NULL }
34696 -static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
34697 +static int
34698 +in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
34700 for ( ; drive_table->id_model ; drive_table++)
34701 if ((!strcmp(drive_table->id_model, id->model)) &&
34702 @@ -420,41 +411,52 @@
34703 return 0;
34707 - * For both Blacklisted and Whitelisted drives.
34708 - * This is setup to be called as an extern for future support
34709 - * to other special driver code.
34710 - */
34711 -int check_drive_good_lists (ide_drive_t *drive)
34712 +static int icside_dma_host_off(ide_drive_t *drive)
34714 - struct hd_driveid *id = drive->id;
34715 - return in_drive_list(id, drive_whitelist);
34716 + return 0;
34719 -int check_drive_bad_lists (ide_drive_t *drive)
34720 +static int icside_dma_off_quietly(ide_drive_t *drive)
34722 - struct hd_driveid *id = drive->id;
34723 - int blacklist = in_drive_list(id, drive_blacklist);
34724 - if (blacklist)
34725 - printk("%s: Disabling DMA for %s\n", drive->name, id->model);
34726 - return(blacklist);
34727 + drive->using_dma = 0;
34728 + return icside_dma_host_off(drive);
34731 -int icside_dma_check(ide_drive_t *drive)
34732 +static int icside_dma_off(ide_drive_t *drive)
34734 + printk("%s: DMA disabled\n", drive->name);
34735 + return icside_dma_off_quietly(drive);
34738 +static int icside_dma_host_on(ide_drive_t *drive)
34740 + return 0;
34743 +static int icside_dma_on(ide_drive_t *drive)
34745 + drive->using_dma = 1;
34746 + return icside_dma_host_on(drive);
34749 +static int icside_dma_check(ide_drive_t *drive)
34751 struct hd_driveid *id = drive->id;
34752 ide_hwif_t *hwif = HWIF(drive);
34753 - int autodma = hwif->autodma;
34754 int xfer_mode = XFER_PIO_2;
34755 + int on;
34757 - if (!id || !(id->capability & 1) || !autodma)
34758 - return hwif->ide_dma_off_quietly(drive);
34759 + if (!id || !(id->capability & 1) || !hwif->autodma)
34760 + goto out;
34763 * Consult the list of known "bad" drives
34765 - if (check_drive_bad_lists(drive))
34766 - return hwif->ide_dma_off(drive);
34767 + if (in_drive_list(id, drive_blacklist)) {
34768 + printk("%s: Disabling DMA for %s (blacklisted)\n",
34769 + drive->name, id->model);
34770 + goto out;
34774 * Enable DMA on any drive that has multiword DMA
34775 @@ -473,192 +475,241 @@
34777 * Consult the list of known "good" drives
34779 - if (check_drive_good_lists(drive)) {
34780 + if (in_drive_list(id, drive_whitelist)) {
34781 if (id->eide_dma_time > 150)
34782 goto out;
34783 xfer_mode = XFER_MW_DMA_1;
34786 out:
34787 - if (icside_config_if(drive, xfer_mode))
34788 - return hwif->ide_dma_on(drive);
34789 - return hwif->ide_dma_off(drive);
34791 + on = icside_set_speed(drive, xfer_mode);
34793 -int icside_dma_verbose(ide_drive_t *drive)
34795 - printk(", DMA");
34796 - return 1;
34797 + if (on)
34798 + return icside_dma_on(drive);
34799 + else
34800 + return icside_dma_off(drive);
34803 -int icside_dma_test_irq(ide_drive_t *drive)
34804 +static int icside_dma_end(ide_drive_t *drive)
34806 ide_hwif_t *hwif = HWIF(drive);
34807 - return inb((unsigned long)hwif->hw.priv) & 1;
34810 -int icside_dma_host_off(ide_drive_t *drive)
34812 - return 0;
34814 + drive->waiting_for_dma = 0;
34816 -int icside_dma_off_quietly(ide_drive_t *drive)
34818 - drive->using_dma = 0;
34819 - return icside_dma_host_off(drive);
34821 + disable_dma(hwif->hw.dma);
34823 -int icside_dma_off(ide_drive_t *drive)
34825 - printk("%s: DMA disabled\n", drive->name);
34826 - return icside_dma_off_quietly(drive);
34828 + /* Teardown mappings after DMA has completed. */
34829 + pci_unmap_sg(NULL, hwif->sg_table, hwif->sg_nents,
34830 + hwif->sg_dma_direction);
34832 -int icside_dma_host_on(ide_drive_t *drive)
34834 - return 0;
34836 + hwif->sg_dma_active = 0;
34838 -int icside_dma_on(ide_drive_t *drive)
34840 - drive->using_dma = 1;
34841 - return icside_dma_host_on(drive);
34842 + return get_dma_residue(hwif->hw.dma) != 0;
34845 -int icside_dma_begin(ide_drive_t *drive)
34846 +static int icside_dma_begin(ide_drive_t *drive)
34848 ide_hwif_t *hwif = HWIF(drive);
34850 + /* We can not enable DMA on both channels simultaneously. */
34851 + BUG_ON(dma_channel_active(hwif->hw.dma));
34852 enable_dma(hwif->hw.dma);
34853 return 0;
34856 -int icside_dma_end(ide_drive_t *drive)
34857 +static int icside_dma_count(ide_drive_t *drive)
34859 - ide_hwif_t *hwif = HWIF(drive);
34861 - drive->waiting_for_dma = 0;
34862 - disable_dma(hwif->hw.dma);
34863 - icside_destroy_dmatable(drive);
34864 - return get_dma_residue(hwif->hw.dma) != 0;
34865 + return icside_dma_begin(drive);
34868 -int icside_dma_count (ide_drive_t *drive)
34870 + * dma_intr() is the handler for disk read/write DMA interrupts
34871 + */
34872 +static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
34874 - return icside_dma_begin(drive);
34875 + unsigned int stat;
34876 + int dma_stat;
34878 + dma_stat = icside_dma_end(drive);
34879 + stat = HWIF(drive)->INB(IDE_STATUS_REG);
34880 + if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
34881 + if (!dma_stat) {
34882 + struct request *rq = HWGROUP(drive)->rq;
34883 + int i;
34885 + for (i = rq->nr_sectors; i > 0; ) {
34886 + i -= rq->current_nr_sectors;
34887 + DRIVER(drive)->end_request(drive, 1);
34890 + return ide_stopped;
34892 + printk(KERN_ERR "%s: bad DMA status (dma_stat=%x)\n",
34893 + drive->name, dma_stat);
34896 + return DRIVER(drive)->error(drive, __FUNCTION__, stat);
34899 -int icside_dma_read(ide_drive_t *drive)
34900 +static int
34901 +icside_dma_common(ide_drive_t *drive, struct request *rq,
34902 + unsigned int dma_mode)
34904 - ide_hwif_t *hwif = HWIF(drive);
34905 -// ide_task_t *args = HWGROUP(drive)->rq->special;
34906 - int count = 0;
34907 - u8 lba48 = (drive->addressing == 1) ? 1 : 0;
34908 - task_ioreg_t command = WIN_NOP;
34909 + ide_hwif_t *hwif = HWIF(drive);
34911 - count = icside_build_dmatable(drive, PCI_DMA_FROMDEVICE);
34912 - if (!count)
34913 - return 1;
34914 - disable_dma(hwif->hw.dma);
34915 + /*
34916 + * We can not enable DMA on both channels.
34917 + */
34918 + BUG_ON(hwif->sg_dma_active);
34919 + BUG_ON(dma_channel_active(hwif->hw.dma));
34921 - /* Route the DMA signals to
34922 - * to the correct interface.
34923 + ide_build_sglist(drive, rq);
34925 + /*
34926 + * Ensure that we have the right interrupt routed.
34928 - HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
34929 + icside_maskproc(drive, 0);
34931 - /* Select the correct timing
34932 - * for this drive
34933 + /*
34934 + * Route the DMA signals to the correct interface.
34935 + */
34936 + outb(hwif->select_data, hwif->config_data);
34938 + /*
34939 + * Select the correct timing for this drive.
34941 set_dma_speed(hwif->hw.dma, drive->drive_data);
34943 - set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
34944 - set_dma_mode(hwif->hw.dma, DMA_MODE_READ);
34945 + /*
34946 + * Tell the DMA engine about the SG table and
34947 + * data direction.
34948 + */
34949 + set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents);
34950 + set_dma_mode(hwif->hw.dma, dma_mode);
34952 + return 0;
34955 +static int icside_dma_read(ide_drive_t *drive)
34957 + struct request *rq = HWGROUP(drive)->rq;
34958 + task_ioreg_t cmd;
34960 + if (icside_dma_common(drive, rq, DMA_MODE_READ))
34961 + return 1;
34963 drive->waiting_for_dma = 1;
34965 if (drive->media != ide_disk)
34966 return 0;
34968 - if (HWGROUP(drive)->handler != NULL) /* paranoia check */
34969 - BUG();
34970 - ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
34972 * FIX ME to use only ACB ide_task_t args Struct
34974 #if 0
34976 - ide_task_t *args = HWGROUP(drive)->rq->special;
34977 - command = args->tfRegister[IDE_COMMAND_OFFSET];
34978 + ide_task_t *args = rq->special;
34979 + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
34981 #else
34982 - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
34983 - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
34984 - ide_task_t *args = HWGROUP(drive)->rq->special;
34985 - command = args->tfRegister[IDE_COMMAND_OFFSET];
34986 + if (rq->cmd == IDE_DRIVE_TASKFILE) {
34987 + ide_task_t *args = rq->special;
34988 + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
34989 + } else if (drive->addressing == 1) {
34990 + cmd = WIN_READDMA_EXT;
34991 + } else {
34992 + cmd = WIN_READDMA;
34994 #endif
34995 - /* issue cmd to drive */
34996 - HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
34998 - return icside_dma_count(drive);
34999 + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
35001 + return icside_dma_begin(drive);
35004 -int icside_dma_write(ide_drive_t *drive)
35005 +static int icside_dma_write(ide_drive_t *drive)
35007 - ide_hwif_t *hwif = HWIF(drive);
35008 -// ide_task_t *args = HWGROUP(drive)->rq->special;
35009 - int count = 0;
35010 - u8 lba48 = (drive->addressing == 1) ? 1 : 0;
35011 - task_ioreg_t command = WIN_NOP;
35012 + struct request *rq = HWGROUP(drive)->rq;
35013 + task_ioreg_t cmd;
35015 - count = icside_build_dmatable(drive, PCI_DMA_TODEVICE);
35016 - if (!count)
35017 + if (icside_dma_common(drive, rq, DMA_MODE_WRITE))
35018 return 1;
35019 - disable_dma(hwif->hw.dma);
35021 - /* Route the DMA signals to
35022 - * to the correct interface.
35023 - */
35024 - HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
35026 - /* Select the correct timing
35027 - * for this drive
35028 - */
35029 - set_dma_speed(hwif->hw.dma, drive->drive_data);
35031 - set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
35032 - set_dma_mode(hwif->hw.dma, DMA_MODE_WRITE);
35034 drive->waiting_for_dma = 1;
35036 if (drive->media != ide_disk)
35037 return 0;
35039 - if (HWGROUP(drive)->handler != NULL)
35040 - BUG();
35041 - ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
35043 * FIX ME to use only ACB ide_task_t args Struct
35045 #if 0
35047 - ide_task_t *args = HWGROUP(drive)->rq->special;
35048 - command = args->tfRegister[IDE_COMMAND_OFFSET];
35049 + ide_task_t *args = rq->special;
35050 + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
35052 #else
35053 - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
35054 - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
35055 - ide_task_t *args = HWGROUP(drive)->rq->special;
35056 - command = args->tfRegister[IDE_COMMAND_OFFSET];
35057 + if (rq->cmd == IDE_DRIVE_TASKFILE) {
35058 + ide_task_t *args = rq->special;
35059 + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
35060 + } else if (drive->addressing == 1) {
35061 + cmd = WIN_WRITEDMA_EXT;
35062 + } else {
35063 + cmd = WIN_WRITEDMA;
35065 #endif
35066 - /* issue cmd to drive */
35067 - HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
35069 - return icside_dma_count(drive);
35070 + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
35072 + return icside_dma_begin(drive);
35075 -static int
35076 -icside_setup_dma(ide_hwif_t *hwif, int autodma)
35077 +static int icside_dma_test_irq(ide_drive_t *drive)
35079 + ide_hwif_t *hwif = HWIF(drive);
35080 + struct icside_state *state = hwif->hwif_data;
35082 + return inb(state->irq_port +
35083 + (hwif->channel ?
35084 + ICS_ARCIN_V6_INTRSTAT_2 :
35085 + ICS_ARCIN_V6_INTRSTAT_1)) & 1;
35088 +static int icside_dma_verbose(ide_drive_t *drive)
35090 + printk(", %s (peak %dMB/s)",
35091 + ide_xfer_verbose(drive->current_speed),
35092 + 2000 / drive->drive_data);
35093 + return 1;
35096 +static int icside_dma_timeout(ide_drive_t *drive)
35098 + printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
35100 + if (icside_dma_test_irq(drive))
35101 + return 0;
35103 + ide_dump_status(drive, "DMA timeout",
35104 + HWIF(drive)->INB(IDE_STATUS_REG));
35106 + return icside_dma_end(drive);
35109 +static int icside_dma_lostirq(ide_drive_t *drive)
35111 + printk(KERN_ERR "%s: IRQ lost\n", drive->name);
35112 + return 1;
35115 +static int icside_dma_init(ide_hwif_t *hwif)
35117 + int autodma = 0;
35119 +#ifdef CONFIG_IDEDMA_ICS_AUTO
35120 + autodma = 1;
35121 +#endif
35123 printk(" %s: SG-DMA", hwif->name);
35125 hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,
35126 @@ -666,40 +717,53 @@
35127 if (!hwif->sg_table)
35128 goto failed;
35130 - hwif->dmatable_cpu = NULL;
35131 - hwif->dmatable_dma = 0;
35132 - hwif->speedproc = icside_set_speed;
35133 - hwif->autodma = autodma;
35134 + hwif->atapi_dma = 1;
35135 + hwif->mwdma_mask = 7; /* MW0..2 */
35136 + hwif->swdma_mask = 7; /* SW0..2 */
35138 - hwif->ide_dma_check = icside_dma_check;
35139 - hwif->ide_dma_host_off = icside_dma_host_off;
35140 + hwif->dmatable_cpu = NULL;
35141 + hwif->dmatable_dma = 0;
35142 + hwif->speedproc = icside_set_speed;
35143 + hwif->autodma = autodma;
35145 + hwif->ide_dma_check = icside_dma_check;
35146 + hwif->ide_dma_host_off = icside_dma_host_off;
35147 hwif->ide_dma_off_quietly = icside_dma_off_quietly;
35148 - hwif->ide_dma_off = icside_dma_off;
35149 - hwif->ide_dma_host_on = icside_dma_host_on;
35150 - hwif->ide_dma_on = icside_dma_on;
35151 - hwif->ide_dma_read = icside_dma_read;
35152 - hwif->ide_dma_write = icside_dma_write;
35153 - hwif->ide_dma_count = icside_dma_count;
35154 - hwif->ide_dma_begin = icside_dma_begin;
35155 - hwif->ide_dma_end = icside_dma_end;
35156 - hwif->ide_dma_verbose = icside_dma_verbose;
35157 - hwif->ide_dma_bad_drive = check_drive_bad_lists;
35158 - hwif->ide_dma_good_drive = check_drive_good_lists;
35159 - hwif->ide_dma_test_irq = icside_dma_test_irq;
35160 + hwif->ide_dma_off = icside_dma_off;
35161 + hwif->ide_dma_host_on = icside_dma_host_on;
35162 + hwif->ide_dma_on = icside_dma_on;
35163 + hwif->ide_dma_read = icside_dma_read;
35164 + hwif->ide_dma_write = icside_dma_write;
35165 + hwif->ide_dma_count = icside_dma_count;
35166 + hwif->ide_dma_begin = icside_dma_begin;
35167 + hwif->ide_dma_end = icside_dma_end;
35168 + hwif->ide_dma_test_irq = icside_dma_test_irq;
35169 + hwif->ide_dma_verbose = icside_dma_verbose;
35170 + hwif->ide_dma_timeout = icside_dma_timeout;
35171 + hwif->ide_dma_lostirq = icside_dma_lostirq;
35173 - printk(" capable%s\n", autodma ?
35174 - ", auto-enable" : "");
35175 + printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
35177 return 1;
35179 failed:
35180 - printk(" -- ERROR, unable to allocate DMA table\n");
35181 + printk(" disabled, unable to allocate DMA table\n");
35182 return 0;
35185 +static void icside_dma_exit(ide_hwif_t *hwif)
35187 + if (hwif->sg_table) {
35188 + kfree(hwif->sg_table);
35189 + hwif->sg_table = NULL;
35192 +#else
35193 +#define icside_dma_init(hwif) (0)
35194 +#define icside_dma_exit(hwif) do { } while (0)
35195 #endif
35197 -static ide_hwif_t *
35198 -icside_find_hwif(unsigned long dataport)
35199 +static ide_hwif_t *icside_find_hwif(unsigned long dataport)
35201 ide_hwif_t *hwif;
35202 int index;
35203 @@ -716,13 +780,13 @@
35204 goto found;
35207 - return NULL;
35208 + hwif = NULL;
35209 found:
35210 return hwif;
35213 static ide_hwif_t *
35214 -icside_setup(unsigned long base, struct cardinfo *info, int irq)
35215 +icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec)
35217 unsigned long port = base + info->dataoffset;
35218 ide_hwif_t *hwif;
35219 @@ -740,8 +804,8 @@
35221 hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
35222 hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
35223 - hwif->hw.irq = irq;
35224 - hwif->irq = irq;
35225 + hwif->hw.irq = ec->irq;
35226 + hwif->irq = ec->irq;
35227 hwif->hw.dma = NO_DMA;
35228 hwif->noprobe = 0;
35229 hwif->chipset = ide_acorn;
35230 @@ -750,33 +814,39 @@
35231 return hwif;
35234 -static int __init icside_register_v5(struct expansion_card *ec, int autodma)
35235 +static int __init
35236 +icside_register_v5(struct icside_state *state, struct expansion_card *ec)
35238 unsigned long slot_port;
35239 ide_hwif_t *hwif;
35241 slot_port = ecard_address(ec, ECARD_MEMC, 0);
35243 + state->irq_port = slot_port;
35245 ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT);
35246 ec->irqmask = 1;
35247 - ec->irq_data = (void *)slot_port;
35248 - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5;
35249 + ec->irq_data = state;
35250 + ec->ops = &icside_ops_arcin_v5;
35253 * Be on the safe side - disable interrupts
35255 inb(slot_port + ICS_ARCIN_V5_INTROFFSET);
35257 - hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq);
35258 + hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec);
35260 - return hwif ? 0 : -1;
35261 + state->hwif[0] = hwif;
35263 + return hwif ? 0 : -ENODEV;
35266 -static int __init icside_register_v6(struct expansion_card *ec, int autodma)
35267 +static int __init
35268 +icside_register_v6(struct icside_state *state, struct expansion_card *ec)
35270 unsigned long slot_port, port;
35271 ide_hwif_t *hwif, *mate;
35272 - int sel = 0;
35273 + unsigned int sel = 0;
35275 slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
35276 port = ecard_address(ec, ECARD_EASI, ECARD_FAST);
35277 @@ -788,88 +858,185 @@
35279 outb(sel, slot_port);
35281 - ec->irq_data = (void *)port;
35282 - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6;
35285 * Be on the safe side - disable interrupts
35287 inb(port + ICS_ARCIN_V6_INTROFFSET_1);
35288 inb(port + ICS_ARCIN_V6_INTROFFSET_2);
35290 - hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq);
35291 - mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq);
35292 + /*
35293 + * Find and register the interfaces.
35294 + */
35295 + hwif = icside_setup(port, &icside_cardinfo_v6_1, ec);
35296 + mate = icside_setup(port, &icside_cardinfo_v6_2, ec);
35298 -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
35299 - if (ec->dma != NO_DMA) {
35300 - if (request_dma(ec->dma, hwif->name))
35301 - goto no_dma;
35302 + if (!hwif || !mate)
35303 + return -ENODEV;
35305 - if (hwif) {
35306 - hwif->config_data = slot_port;
35307 - hwif->select_data = sel;
35308 - hwif->hw.dma = ec->dma;
35309 - hwif->hw.priv = (void *)
35310 - (port + ICS_ARCIN_V6_INTRSTAT_1);
35311 - hwif->channel = 0;
35312 - icside_setup_dma(hwif, autodma);
35313 - hwif->drives[0].autodma = autodma;
35314 - hwif->drives[1].autodma = autodma;
35316 - if (mate) {
35317 - mate->config_data = slot_port;
35318 - mate->select_data = sel | 1;
35319 - mate->hw.dma = ec->dma;
35320 - mate->hw.priv = (void *)
35321 - (port + ICS_ARCIN_V6_INTRSTAT_2);
35322 - mate->channel = 1;
35323 - icside_setup_dma(mate, autodma);
35324 - mate->drives[0].autodma = autodma;
35325 - mate->drives[1].autodma = autodma;
35327 + state->irq_port = port;
35328 + state->slot_port = slot_port;
35329 + state->hwif[0] = hwif;
35330 + state->hwif[1] = mate;
35332 + ec->irq_data = state;
35333 + ec->ops = &icside_ops_arcin_v6;
35335 + hwif->maskproc = icside_maskproc;
35336 + hwif->channel = 0;
35337 + hwif->hwif_data = state;
35338 + hwif->mate = mate;
35339 + hwif->serialized = 1;
35340 + hwif->config_data = slot_port;
35341 + hwif->select_data = sel;
35342 + hwif->hw.dma = ec->dma;
35344 + mate->maskproc = icside_maskproc;
35345 + mate->channel = 1;
35346 + mate->hwif_data = state;
35347 + mate->mate = hwif;
35348 + mate->serialized = 1;
35349 + mate->config_data = slot_port;
35350 + mate->select_data = sel | 1;
35351 + mate->hw.dma = ec->dma;
35353 + if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
35354 + icside_dma_init(hwif);
35355 + icside_dma_init(mate);
35357 -no_dma:
35358 -#endif
35359 - return hwif || mate ? 0 : -1;
35360 + return 0;
35363 -int __init icside_init(void)
35364 +static int __init icside_probe(struct expansion_card *ec, const struct ecard_id *id)
35366 - int autodma = 0;
35367 + struct icside_state *state;
35368 + int ret;
35370 -#ifdef CONFIG_IDEDMA_ICS_AUTO
35371 - autodma = 1;
35372 -#endif
35373 + state = kmalloc(sizeof(struct icside_state), GFP_KERNEL);
35374 + if (!state) {
35375 + ret = -ENOMEM;
35376 + goto out;
35379 - ecard_startfind ();
35380 + memset(state, 0, sizeof(struct icside_state));
35381 + state->type = ICS_TYPE_NOTYPE;
35383 - do {
35384 - struct expansion_card *ec;
35385 - int result;
35387 + unsigned int addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
35388 + unsigned int type;
35390 - ec = ecard_find(0, icside_cids);
35391 - if (ec == NULL)
35392 - break;
35393 + type = inb(addr) & 1;
35394 + type |= (inb(addr + 1) & 1) << 1;
35395 + type |= (inb(addr + 2) & 1) << 2;
35396 + type |= (inb(addr + 3) & 1) << 3;
35398 - ecard_claim(ec);
35399 + state->type = type;
35402 - switch (icside_identifyif(ec)) {
35403 - case ics_if_arcin_v5:
35404 - result = icside_register_v5(ec, autodma);
35405 - break;
35406 + switch (state->type) {
35407 + case ICS_TYPE_A3IN:
35408 + printk(KERN_WARNING "icside: A3IN unsupported\n");
35409 + ret = -ENODEV;
35410 + break;
35412 - case ics_if_arcin_v6:
35413 - result = icside_register_v6(ec, autodma);
35414 - break;
35415 + case ICS_TYPE_A3USER:
35416 + printk(KERN_WARNING "icside: A3USER unsupported\n");
35417 + ret = -ENODEV;
35418 + break;
35420 - default:
35421 - result = -1;
35422 - break;
35424 + case ICS_TYPE_V5:
35425 + ret = icside_register_v5(state, ec);
35426 + break;
35428 - if (result)
35429 - ecard_release(ec);
35430 - } while (1);
35431 + case ICS_TYPE_V6:
35432 + ret = icside_register_v6(state, ec);
35433 + break;
35435 - return 0;
35436 + default:
35437 + printk(KERN_WARNING "icside: unknown interface type\n");
35438 + ret = -ENODEV;
35439 + break;
35442 + if (ret == 0) {
35443 + ecard_set_drvdata(ec, state);
35444 + } else {
35445 + kfree(state);
35447 + out:
35448 + return ret;
35451 +static void __devexit icside_remove(struct expansion_card *ec)
35453 + struct icside_state *state = ecard_get_drvdata(ec);
35455 + switch (state->type) {
35456 + case ICS_TYPE_V5:
35457 + /* FIXME: tell IDE to stop using the interface */
35459 + /* Disable interrupts */
35460 + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
35461 + break;
35463 + case ICS_TYPE_V6:
35464 + /* FIXME: tell IDE to stop using the interface */
35465 + icside_dma_exit(state->hwif[1]);
35466 + icside_dma_exit(state->hwif[0]);
35468 + if (ec->dma != NO_DMA)
35469 + free_dma(ec->dma);
35471 + /* Disable interrupts */
35472 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
35473 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
35475 + /* Reset the ROM pointer/EASI selection */
35476 + outb(0, state->slot_port);
35477 + break;
35480 + ecard_set_drvdata(ec, NULL);
35481 + ec->ops = NULL;
35482 + ec->irq_data = NULL;
35484 + kfree(state);
35487 +static void icside_shutdown(struct expansion_card *ec)
35489 + struct icside_state *state = ecard_get_drvdata(ec);
35491 + switch (state->type) {
35492 + case ICS_TYPE_V5:
35493 + /* Disable interrupts */
35494 + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
35495 + break;
35497 + case ICS_TYPE_V6:
35498 + /* Disable interrupts */
35499 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
35500 + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
35502 + /* Reset the ROM pointer/EASI selection */
35503 + outb(0, state->slot_port);
35504 + break;
35508 +static const struct ecard_id icside_ids[] = {
35509 + { MANU_ICS, PROD_ICS_IDE },
35510 + { MANU_ICS2, PROD_ICS2_IDE },
35511 + { 0xffff, 0xffff }
35514 +static struct ecard_driver icside_driver = {
35515 + .probe = icside_probe,
35516 + .remove = __devexit_p(icside_remove),
35517 + .shutdown = icside_shutdown,
35518 + .id_table = icside_ids,
35521 +int __init icside_init(void)
35523 + return ecard_register_driver(&icside_driver);
35525 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
35526 +++ linux-2.4.25/drivers/ide/arm/rstation-ide.c 2004-03-31 17:15:09.000000000 +0200
35527 @@ -0,0 +1,78 @@
35529 + * linux/drivers/ide/rs-ide.c
35531 + * Copyright (c) 2002 Ben Dooks
35532 + * Copyright (c) 2002 Simtec Electronics
35534 + * Simple RiscStation IDE support
35537 +#include <linux/module.h>
35538 +#include <linux/slab.h>
35539 +#include <linux/blkdev.h>
35540 +#include <linux/errno.h>
35541 +#include <linux/ide.h>
35542 +#include <linux/init.h>
35544 +#include <asm/hardware/iomd.h>
35545 +#include <asm/mach-types.h>
35546 +#include <asm/io.h>
35548 +#ifndef CONFIG_ARCH_RISCSTATION
35549 +#error "compiling this code for non-riscstation hardware is dangerous!"
35550 +#endif
35552 +#define DRV_PREFIX "ide-rs"
35554 +#define IRQ_PRI (40+3)
35555 +#define IRQ_SEC (40+4)
35557 +#define PORT_BASE ((0x2b800 - 0x10000) >> 2)
35558 +#define SEC_OFF (0x400 >> 2)
35560 +int __init rside_reg(unsigned long base, unsigned int irq);
35562 +int __init rside_init(void)
35564 + int iotcr;
35566 + if (!machine_is_riscstation()) {
35567 + printk(DRV_PREFIX ": hardware is not a RiscStation!\n");
35568 + return 0;
35571 + /* select correct area cycle time */
35573 + iotcr = inb(IOMD_IOTCR);
35574 + outb((iotcr & ~3) | 1, IOMD_IOTCR);
35576 + /* register h/w */
35578 + rside_reg(PORT_BASE, IRQ_PRI);
35579 + rside_reg(PORT_BASE + SEC_OFF, IRQ_SEC);
35581 + return 0;
35585 +int __init rside_reg(unsigned long port, unsigned int irq)
35587 + unsigned long addr, i;
35588 + hw_regs_t hw;
35590 + hw.irq = irq;
35592 + addr = port;
35594 + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
35595 + hw.io_ports[i] = (ide_ioreg_t)addr;
35596 + addr += 0x40 >> 2;
35599 + hw.io_ports[IDE_CONTROL_OFFSET] = port + ((0xb80 - 0x800) >> 2);
35601 + printk(DRV_PREFIX ": registering channel at %08lx, %08lx, irq %d\n",
35602 + port, hw.io_ports[IDE_CONTROL_OFFSET], irq);
35604 + return ide_register_hw(&hw, NULL);
35606 --- linux-2.4.25/drivers/ide/ide-probe.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
35607 +++ linux-2.4.25/drivers/ide/ide-probe.c 2004-03-31 17:15:09.000000000 +0200
35608 @@ -1296,11 +1296,11 @@
35609 hwif->name, hwif->major);
35610 return (hwif->present = 0);
35614 if (init_irq(hwif)) {
35615 int i = hwif->irq;
35617 - * It failed to initialise. Find the default IRQ for
35618 + * It failed to initialise. Find the default IRQ for
35619 * this port and try that.
35621 if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
35622 @@ -1318,7 +1318,7 @@
35623 printk("%s: probed IRQ %d failed, using default.\n",
35624 hwif->name, hwif->irq);
35628 init_gendisk(hwif);
35629 blk_dev[hwif->major].data = hwif;
35630 blk_dev[hwif->major].queue = ide_get_queue;
35631 --- linux-2.4.25/drivers/ide/ide-proc.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
35632 +++ linux-2.4.25/drivers/ide/ide-proc.c 2004-03-31 17:15:09.000000000 +0200
35633 @@ -425,6 +425,7 @@
35634 case ide_cy82c693: name = "cy82c693"; break;
35635 case ide_4drives: name = "4drives"; break;
35636 case ide_pmac: name = "pmac"; break;
35637 + case ide_acorn: name = "acorn"; break;
35638 default: name = "(unknown)"; break;
35640 len = sprintf(page, "%s\n", name);
35641 --- linux-2.4.25/drivers/ide/ide.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
35642 +++ linux-2.4.25/drivers/ide/ide.c 2004-03-31 17:15:09.000000000 +0200
35643 @@ -218,23 +218,14 @@
35644 static void init_hwif_data (unsigned int index)
35646 unsigned int unit;
35647 - hw_regs_t hw;
35648 ide_hwif_t *hwif = &ide_hwifs[index];
35650 /* bulk initialize hwif & drive info with zeros */
35651 memset(hwif, 0, sizeof(ide_hwif_t));
35652 - memset(&hw, 0, sizeof(hw_regs_t));
35654 /* fill in any non-zero initial values */
35655 hwif->index = index;
35656 - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
35657 - memcpy(&hwif->hw, &hw, sizeof(hw));
35658 - memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
35659 - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
35660 -#ifdef CONFIG_BLK_DEV_HD
35661 - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
35662 - hwif->noprobe = 1; /* may be overridden by ide_setup() */
35663 -#endif /* CONFIG_BLK_DEV_HD */
35664 + hwif->noprobe = 1;
35665 hwif->major = ide_hwif_to_major[index];
35666 hwif->name[0] = 'i';
35667 hwif->name[1] = 'd';
35668 @@ -276,6 +267,28 @@
35672 + * Old compatability function - initialise ports using ide_default_io_base
35673 + */
35674 +static void ide_old_init_default_hwifs(void)
35676 + unsigned int index;
35677 + ide_ioreg_t base;
35678 + ide_hwif_t *hwif;
35680 + for (index = 0; index < MAX_HWIFS; index++) {
35681 + hwif = &ide_hwifs[index];
35683 + base = ide_default_io_base(index);
35685 + if (base) {
35686 + ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->hw.irq);
35687 + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
35688 + hwif->noprobe = 0;
35694 * init_ide_data() sets reasonable default values into all fields
35695 * of all instances of the hwifs and drives, but only on the first call.
35696 * Subsequent calls have no effect (they don't wipe out anything).
35697 @@ -307,6 +320,7 @@
35698 init_hwif_data(index);
35700 /* Add default hw interfaces */
35701 + ide_old_init_default_hwifs();
35702 ide_init_default_hwifs();
35704 idebus_parameter = 0;
35705 @@ -2530,6 +2544,12 @@
35706 rapide_init();
35708 #endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
35709 +#ifdef CONFIG_BLK_DEV_IDE_RISCSTATION
35711 + extern void rside_init(void);
35712 + rside_init();
35714 +#endif /* CONFIG_BLK_DEV_IDE_RISCSTATION */
35715 #ifdef CONFIG_BLK_DEV_GAYLE
35717 extern void gayle_init(void);
35718 --- linux-2.4.25/drivers/ide/pci/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
35719 +++ linux-2.4.25/drivers/ide/pci/Makefile 2004-03-31 17:15:09.000000000 +0200
35720 @@ -15,7 +15,6 @@
35721 obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
35722 obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
35723 #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o
35724 -obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
35725 obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
35726 obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
35727 obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
35728 --- linux-2.4.25/drivers/ide/pci/sl82c105.c~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
35729 +++ linux-2.4.25/drivers/ide/pci/sl82c105.c 2004-03-31 17:15:09.000000000 +0200
35730 @@ -37,7 +37,7 @@
35731 #ifdef DEBUG
35732 #define DBG(arg) printk arg
35733 #else
35734 -#define DBG(fmt,...)
35735 +#define DBG(fmt...)
35736 #endif
35738 * SL82C105 PCI config register 0x40 bits.
35739 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
35740 +++ linux-2.4.25/drivers/ide/pci/sl82c105.c.2419 2004-03-31 17:15:09.000000000 +0200
35741 @@ -0,0 +1,380 @@
35743 + * linux/drivers/ide/sl82c105.c
35745 + * SL82C105/Winbond 553 IDE driver
35747 + * Maintainer unknown.
35749 + * Changelog:
35751 + * 15/11/1998 RMK Drive tuning added from Rebel.com's kernel
35752 + * sources
35753 + * 30/03/2002 RMK Add fixes specified in W83C553F errata.
35754 + * (with special thanks to Todd Inglett)
35755 + */
35757 +#include <linux/config.h>
35758 +#include <linux/types.h>
35759 +#include <linux/kernel.h>
35760 +#include <linux/timer.h>
35761 +#include <linux/mm.h>
35762 +#include <linux/ioport.h>
35763 +#include <linux/interrupt.h>
35764 +#include <linux/blkdev.h>
35765 +#include <linux/hdreg.h>
35766 +#include <linux/pci.h>
35767 +#include <linux/ide.h>
35769 +#include <asm/io.h>
35770 +#include <asm/dma.h>
35772 +#include "ide_modes.h"
35774 +extern char *ide_xfer_verbose (byte xfer_rate);
35777 + * SL82C105 PCI config register 0x40 bits.
35778 + */
35779 +#define CTRL_IDE_IRQB (1 << 30)
35780 +#define CTRL_IDE_IRQA (1 << 28)
35781 +#define CTRL_LEGIRQ (1 << 11)
35782 +#define CTRL_P1F16 (1 << 5)
35783 +#define CTRL_P1EN (1 << 4)
35784 +#define CTRL_P0F16 (1 << 1)
35785 +#define CTRL_P0EN (1 << 0)
35788 + * Convert a PIO mode and cycle time to the required on/off
35789 + * times for the interface. This has protection against run-away
35790 + * timings.
35791 + */
35792 +static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
35794 + unsigned int cmd_on;
35795 + unsigned int cmd_off;
35797 + cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
35798 + cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30;
35800 + if (cmd_on > 32)
35801 + cmd_on = 32;
35802 + if (cmd_on == 0)
35803 + cmd_on = 1;
35805 + if (cmd_off > 32)
35806 + cmd_off = 32;
35807 + if (cmd_off == 0)
35808 + cmd_off = 1;
35810 + return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00);
35814 + * Configure the drive and chipset for PIO
35815 + */
35816 +static void config_for_pio(ide_drive_t *drive, int pio, int report)
35818 + ide_hwif_t *hwif = HWIF(drive);
35819 + struct pci_dev *dev = hwif->pci_dev;
35820 + ide_pio_data_t p;
35821 + unsigned short drv_ctrl = 0x909;
35822 + unsigned int xfer_mode, reg;
35824 + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
35826 + pio = ide_get_best_pio_mode(drive, pio, 5, &p);
35828 + switch (pio) {
35829 + default:
35830 + case 0: xfer_mode = XFER_PIO_0; break;
35831 + case 1: xfer_mode = XFER_PIO_1; break;
35832 + case 2: xfer_mode = XFER_PIO_2; break;
35833 + case 3: xfer_mode = XFER_PIO_3; break;
35834 + case 4: xfer_mode = XFER_PIO_4; break;
35837 + if (ide_config_drive_speed(drive, xfer_mode) == 0)
35838 + drv_ctrl = get_timing_sl82c105(&p);
35840 + if (drive->using_dma == 0) {
35841 + /*
35842 + * If we are actually using MW DMA, then we can not
35843 + * reprogram the interface drive control register.
35844 + */
35845 + pci_write_config_word(dev, reg, drv_ctrl);
35846 + pci_read_config_word(dev, reg, &drv_ctrl);
35848 + if (report) {
35849 + printk("%s: selected %s (%dns) (%04X)\n", drive->name,
35850 + ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl);
35856 + * Configure the drive and the chipset for DMA
35857 + */
35858 +static int config_for_dma(ide_drive_t *drive)
35860 + ide_hwif_t *hwif = HWIF(drive);
35861 + struct pci_dev *dev = hwif->pci_dev;
35862 + unsigned short drv_ctrl = 0x909;
35863 + unsigned int reg;
35865 + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
35867 + if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0)
35868 + drv_ctrl = 0x0240;
35870 + pci_write_config_word(dev, reg, drv_ctrl);
35872 + return 0;
35877 + * Check to see if the drive and
35878 + * chipset is capable of DMA mode
35879 + */
35880 +static int sl82c105_check_drive(ide_drive_t *drive)
35882 + ide_dma_action_t dma_func = ide_dma_off_quietly;
35884 + do {
35885 + struct hd_driveid *id = drive->id;
35886 + ide_hwif_t *hwif = HWIF(drive);
35888 + if (!hwif->autodma)
35889 + break;
35891 + if (!id || !(id->capability & 1))
35892 + break;
35894 + /* Consult the list of known "bad" drives */
35895 + if (ide_dmaproc(ide_dma_bad_drive, drive)) {
35896 + dma_func = ide_dma_off;
35897 + break;
35900 + if (id->field_valid & 2) {
35901 + if (id->dma_mword & 7 || id->dma_1word & 7)
35902 + dma_func = ide_dma_on;
35903 + break;
35906 + if (ide_dmaproc(ide_dma_good_drive, drive)) {
35907 + dma_func = ide_dma_on;
35908 + break;
35910 + } while (0);
35912 + return HWIF(drive)->dmaproc(dma_func, drive);
35916 + * The SL82C105 holds off all IDE interrupts while in DMA mode until
35917 + * all DMA activity is completed. Sometimes this causes problems (eg,
35918 + * when the drive wants to report an error condition).
35920 + * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller
35921 + * state machine. We need to kick this to work around various bugs.
35922 + */
35923 +static inline void sl82c105_reset_host(struct pci_dev *dev)
35925 + u16 val;
35927 + pci_read_config_word(dev, 0x7e, &val);
35928 + pci_write_config_word(dev, 0x7e, val | (1 << 2));
35929 + pci_write_config_word(dev, 0x7e, val & ~(1 << 2));
35933 + * If we get an IRQ timeout, it might be that the DMA state machine
35934 + * got confused. Fix from Todd Inglett. Details from Winbond.
35936 + * This function is called when the IDE timer expires, the drive
35937 + * indicates that it is READY, and we were waiting for DMA to complete.
35938 + */
35939 +static int sl82c105_lostirq(ide_drive_t *drive)
35941 + ide_hwif_t *hwif = HWIF(drive);
35942 + struct pci_dev *dev = hwif->pci_dev;
35943 + u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
35944 + unsigned long dma_base = hwif->dma_base;
35946 + printk("sl82c105: lost IRQ: resetting host\n");
35948 + /*
35949 + * Check the raw interrupt from the drive.
35950 + */
35951 + pci_read_config_dword(dev, 0x40, &val);
35952 + if (val & mask)
35953 + printk("sl82c105: drive was requesting IRQ, but host lost it\n");
35955 + /*
35956 + * Was DMA enabled? If so, disable it - we're resetting the
35957 + * host. The IDE layer will be handling the drive for us.
35958 + */
35959 + val = inb(dma_base);
35960 + if (val & 1) {
35961 + outb(val & ~1, dma_base);
35962 + printk("sl82c105: DMA was enabled\n");
35965 + sl82c105_reset_host(dev);
35967 + /* ide_dmaproc would return 1, so we do as well */
35968 + return 1;
35972 + * ATAPI devices can cause the SL82C105 DMA state machine to go gaga.
35973 + * Winbond recommend that the DMA state machine is reset prior to
35974 + * setting the bus master DMA enable bit.
35976 + * The generic IDE core will have disabled the BMEN bit before this
35977 + * function is called.
35978 + */
35979 +static void sl82c105_before_bm_enable(ide_drive_t *drive)
35981 + ide_hwif_t *hwif = HWIF(drive);
35982 + struct pci_dev *dev = hwif->pci_dev;
35984 + sl82c105_reset_host(dev);
35988 + * Our very own dmaproc. We need to intercept various calls
35989 + * to fix up the SL82C105 specific behaviour.
35990 + */
35991 +static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
35993 + switch (func) {
35994 + case ide_dma_check:
35995 + return sl82c105_check_drive(drive);
35997 + case ide_dma_on:
35998 + if (config_for_dma(drive))
35999 + func = ide_dma_off;
36000 + /* fall through */
36002 + case ide_dma_off_quietly:
36003 + case ide_dma_off:
36004 + config_for_pio(drive, 4, 0);
36005 + break;
36007 + case ide_dma_read:
36008 + case ide_dma_write:
36009 + case ide_dma_begin:
36010 + case ide_dma_timeout:
36011 + sl82c105_before_bm_enable(drive);
36012 + break;
36014 + case ide_dma_lostirq:
36015 + return sl82c105_lostirq(drive);
36017 + default:
36018 + break;
36020 + return ide_dmaproc(func, drive);
36024 + * We only deal with PIO mode here - DMA mode 'using_dma' is not
36025 + * initialised at the point that this function is called.
36026 + */
36027 +static void tune_sl82c105(ide_drive_t *drive, byte pio)
36029 + config_for_pio(drive, pio, 1);
36031 + /*
36032 + * We support 32-bit I/O on this interface, and it
36033 + * doesn't have problems with interrupts.
36034 + */
36035 + drive->io_32bit = 1;
36036 + drive->unmask = 1;
36040 + * Return the revision of the Winbond bridge
36041 + * which this function is part of.
36042 + */
36043 +static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
36045 + struct pci_dev *bridge;
36046 + unsigned char rev;
36048 + /*
36049 + * The bridge should be part of the same device, but function 0.
36050 + */
36051 + bridge = pci_find_slot(dev->bus->number,
36052 + PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
36053 + if (!bridge)
36054 + return -1;
36056 + /*
36057 + * Make sure it is a Winbond 553 and is an ISA bridge.
36058 + */
36059 + if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
36060 + bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
36061 + bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA)
36062 + return -1;
36064 + /*
36065 + * We need to find function 0's revision, not function 1
36066 + */
36067 + pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
36069 + return rev;
36073 + * Enable the PCI device
36074 + */
36075 +unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg)
36077 + u32 val;
36079 + pci_read_config_dword(dev, 0x40, &val);
36080 + val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1EN | CTRL_P1F16;
36081 + pci_write_config_dword(dev, 0x40, val);
36083 + return dev->irq;
36086 +void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
36088 + unsigned int bridge_rev;
36089 + byte dma_state;
36091 + dma_state = inb(dma_base + 2);
36092 + bridge_rev = sl82c105_bridge_revision(hwif->pci_dev);
36093 + if (bridge_rev <= 5) {
36094 + hwif->autodma = 0;
36095 + hwif->drives[0].autotune = 1;
36096 + hwif->drives[1].autotune = 1;
36097 + printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
36098 + hwif->name, bridge_rev);
36099 + dma_state &= ~0x60;
36100 + } else {
36101 + dma_state |= 0x60;
36102 + hwif->autodma = 1;
36104 + outb(dma_state, dma_base + 2);
36106 + ide_setup_dma(hwif, dma_base, 8);
36108 + if (bridge_rev <= 5)
36109 + hwif->dmaproc = NULL;
36110 + else
36111 + hwif->dmaproc = sl82c105_dmaproc;
36115 + * Initialise the chip
36116 + */
36117 +void __init ide_init_sl82c105(ide_hwif_t *hwif)
36119 + hwif->tuneproc = tune_sl82c105;
36122 --- linux-2.4.25/drivers/input/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
36123 +++ linux-2.4.25/drivers/input/Config.in 2004-03-31 17:15:09.000000000 +0200
36124 @@ -15,5 +15,6 @@
36125 dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT
36126 dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT
36127 dep_tristate ' User level driver support' CONFIG_INPUT_UINPUT $CONFIG_INPUT
36128 +dep_tristate ' MX1 touchscreen support' CONFIG_INPUT_MX1TS $CONFIG_INPUT_MOUSEDEV $CONFIG_ARCH_MX1ADS
36130 endmenu
36131 --- linux-2.4.25/drivers/input/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
36132 +++ linux-2.4.25/drivers/input/Makefile 2004-03-31 17:15:09.000000000 +0200
36133 @@ -24,6 +24,7 @@
36134 obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
36135 obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
36136 obj-$(CONFIG_INPUT_EVDEV) += evdev.o
36137 +obj-$(CONFIG_INPUT_MX1TS) += mx1ts.o
36138 obj-$(CONFIG_INPUT_UINPUT) += uinput.o
36140 # The global Rules.make.
36141 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
36142 +++ linux-2.4.25/drivers/input/mx1ts.c 2004-03-31 17:15:09.000000000 +0200
36143 @@ -0,0 +1,508 @@
36145 + * linux/drivers/misc/mx1ts.c
36147 + * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
36149 + * Cloned from ucb1x00_ts.c
36151 + * This program is free software; you can redistribute it and/or modify
36152 + * it under the terms of the GNU General Public License version 2 as
36153 + * published by the Free Software Foundation.
36155 + */
36156 +#include <linux/config.h>
36157 +#include <linux/module.h>
36158 +#include <linux/init.h>
36159 +#include <linux/smp.h>
36160 +#include <linux/smp_lock.h>
36161 +#include <linux/sched.h>
36162 +#include <linux/completion.h>
36163 +#include <linux/delay.h>
36164 +#include <linux/string.h>
36165 +#include <linux/pm.h>
36167 +#include <asm/dma.h>
36169 +#include <linux/input.h>
36171 +#include "mx1ts.h"
36173 +#define DEV_IRQ_ID "mx1-ts"
36175 +struct mx1_ts {
36176 + struct input_dev idev;
36177 +#ifdef CONFIG_PM
36178 + struct pm_dev *pmdev;
36179 +#endif
36181 + wait_queue_head_t irq_wait;
36182 + struct completion init_exit;
36183 + int use_count;
36184 + u16 x_res;
36185 + u16 y_res;
36187 + int restart:1;
36190 +static struct mx1_ts mx1ts;
36191 +static u8 mx1_performing_auto_calibration = 0;
36192 +static u16 mx1_cal_auto_zero = 0;
36193 +static u16 mx1_cal_range_x = 0;
36194 +static u16 mx1_cal_range_y = 0;
36196 +static int mx1_ts_startup(struct mx1_ts *ts);
36197 +static void mx1_ts_shutdown(struct mx1_ts *ts);
36199 +static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs);
36200 +static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs);
36201 +static void mx1_ts_compare_int(int irq, void *dev_id, struct pt_regs *regs);
36203 +static void mx1_ts_enable_pen_touch_interrupt(void);
36204 +static void mx1_ts_disable_pen_touch_interrupt(void);
36205 +static void mx1_ts_enable_pen_up_interrupt(void);
36206 +static void mx1_ts_disable_pen_up_interrupt(void);
36207 +static void mx1_ts_enable_auto_sample(void);
36208 +static void mx1_ts_disable_auto_sample(void);
36209 +static void mx1_ts_start_auto_calibration(void);
36211 +static inline void mx1_reg_write(unsigned int reg, unsigned int val)
36213 + *((volatile unsigned int *)reg) = val;
36216 +static inline unsigned int mx1_reg_read(unsigned int reg)
36218 + return *((volatile unsigned int *)reg);
36221 +static inline void mx1_reg_clear_bit(unsigned int reg, unsigned int bit)
36223 + *((volatile unsigned int *)reg) &= ~bit;
36226 +static inline void mx1_reg_set_bit(unsigned int reg, unsigned int bit)
36228 + *((volatile unsigned int *)reg) |= bit;
36231 +static inline void mx1_ts_evt_add(struct mx1_ts *ts, u16 pressure, u16 x, u16 y)
36233 + input_report_abs(&ts->idev, ABS_X, (int)x - 32768);
36234 + input_report_abs(&ts->idev, ABS_Y, (int)y - 32768);
36235 + input_report_abs(&ts->idev, ABS_PRESSURE, (int)pressure);
36238 +static inline void mx1_ts_flush_fifo(void)
36240 + int i;
36241 + for (i = 0; i < 12; i++)
36242 + if (mx1_reg_read(ASP_ISTATR) & (ASP_PFF | ASP_PDR))
36243 + mx1_reg_read(ASP_PADFIFO);
36246 +static int mx1_ts_open(struct input_dev *idev)
36248 + struct mx1_ts *ts = (struct mx1_ts *)idev;
36250 + mx1_performing_auto_calibration = 0;
36251 + return mx1_ts_startup(ts);
36254 +static void mx1_ts_close(struct input_dev *idev)
36256 + struct mx1_ts *ts = (struct mx1_ts *)idev;
36258 + mx1_ts_shutdown(ts);
36261 +static inline int mx1_ts_enable_irqs(void)
36263 + int result;
36265 + result = request_irq(ASP_PENDATA_IRQ,
36266 + mx1_ts_pendata_int,
36267 + SA_INTERRUPT,
36268 + DEV_IRQ_ID,
36269 + DEV_IRQ_ID);
36270 + if (result) {
36271 + printk("Couldn't request pen data IRQ.\n");
36272 + return result;
36275 + result = request_irq(ASP_TOUCH_IRQ,
36276 + mx1_ts_touch_int,
36277 + SA_INTERRUPT,
36278 + DEV_IRQ_ID,
36279 + DEV_IRQ_ID);
36280 + if (result) {
36281 + printk("Couldn't request pen touch IRQ.\n");
36282 + free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
36283 + return result;
36286 + return result;
36289 +static inline int mx1_ts_disable_irqs(void)
36291 + free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
36292 + free_irq(ASP_TOUCH_IRQ, DEV_IRQ_ID);
36294 + return 0;
36297 +static inline int mx1_ts_register(struct mx1_ts *ts)
36299 + ts->idev.name = "Touchscreen panel";
36300 + ts->idev.open = mx1_ts_open;
36301 + ts->idev.close = mx1_ts_close;
36303 + __set_bit(EV_ABS, ts->idev.evbit);
36304 + __set_bit(ABS_X, ts->idev.absbit);
36305 + __set_bit(ABS_Y, ts->idev.absbit);
36306 + __set_bit(ABS_PRESSURE, ts->idev.absbit);
36308 + ts->idev.absmin[ABS_X] = 0;
36309 + ts->idev.absmax[ABS_X] = (u32)0x0000FFFF;
36310 + ts->idev.absfuzz[ABS_X] = 50;
36311 + ts->idev.absflat[ABS_X] = 0;
36313 + ts->idev.absmin[ABS_Y] = 0;
36314 + ts->idev.absmax[ABS_Y] = (u32)0x0000FFFF;
36315 + ts->idev.absfuzz[ABS_Y] = 50;
36316 + ts->idev.absflat[ABS_Y] = 0;
36318 + input_register_device(&ts->idev);
36320 + return 0;
36323 +static inline void mx1_ts_deregister(struct mx1_ts *ts)
36325 + input_unregister_device(&ts->idev);
36329 + * Handle the touch interrupt, generated when the pen is pressed/
36330 + * released.
36331 + */
36332 +static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs)
36334 + /* Clear the interrupt. */
36335 + mx1_reg_set_bit(ASP_ISTATR, ASP_PEN);
36337 + mx1_ts_disable_pen_touch_interrupt();
36338 + mx1_ts_start_auto_calibration();
36339 + mx1_ts_enable_pen_up_interrupt();
36343 + * Handle the pen data ready interrupt, generated when pen data is
36344 + * in the FIFO.
36345 + */
36346 +static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs)
36348 + static unsigned int auto_zero, pen_x, pen_y, pen_u;
36350 + if (mx1_reg_read(ASP_ISTATR) & 0x400) {
36351 + mx1_reg_set_bit(ASP_ISTATR, 0x400);
36353 + mx1_ts_disable_auto_sample();
36354 + mx1_ts_disable_pen_up_interrupt();
36355 + mx1_ts_enable_pen_touch_interrupt();
36357 + mx1_ts_evt_add(&mx1ts, 0, pen_x, pen_y);
36359 + mx1_ts_flush_fifo();
36361 + return;
36364 + if (mx1_performing_auto_calibration) {
36365 + unsigned int value;
36367 + mx1_cal_auto_zero = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
36368 + mx1_cal_range_x = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
36369 + mx1_cal_range_y = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
36371 + if ((mx1_cal_auto_zero >= mx1_cal_range_x) ||
36372 + (mx1_cal_auto_zero >= mx1_cal_range_y)) {
36373 + /* Invalid data. */
36374 + mx1_ts_start_auto_calibration();
36375 + return;
36378 + mx1_cal_range_x -= mx1_cal_auto_zero;
36379 + mx1_cal_range_y -= mx1_cal_auto_zero;
36381 + value = mx1_reg_read(ASP_ACNTLCR);
36382 + value &= ~0x04000000; /* XXX Undocumented. */
36383 + mx1_reg_write(ASP_ACNTLCR, value);
36385 + mx1_performing_auto_calibration = 0;
36387 + mx1_ts_enable_auto_sample();
36388 + } else {
36389 + /* There could be more than one sample in the FIFO, but we're
36390 + * only going to read one per call. The interrupt will be
36391 + * generated as long as there is data in the FIFO. */
36393 + if ((mx1_reg_read(ASP_ISTATR) & ASP_PDR) != ASP_PDR) {
36394 + return;
36397 + auto_zero = mx1_reg_read(ASP_PADFIFO);
36398 + if (auto_zero > (mx1_cal_auto_zero + 0x200)) {
36399 + return;
36402 + pen_x = mx1_reg_read(ASP_PADFIFO);
36403 + pen_y = mx1_reg_read(ASP_PADFIFO);
36404 + pen_u = mx1_reg_read(ASP_PADFIFO);
36406 + pen_x = (u32)(((pen_x - mx1_cal_auto_zero) << 16) /
36407 + mx1_cal_range_x);
36408 + pen_y = (u32)(((pen_y - mx1_cal_auto_zero) << 16) /
36409 + mx1_cal_range_y);
36411 + mx1_ts_evt_add(&mx1ts, pen_u, pen_x, pen_y);
36415 +static void mx1_ts_reset_asp(void)
36417 + unsigned int value;
36419 + mx1_ts_flush_fifo();
36421 + /* Soft reset the ASP module */
36422 + mx1_reg_write(ASP_ACNTLCR, ASP_SWRST);
36424 + /* Read back the reset value of the control register */
36425 + value = mx1_reg_read(ASP_ACNTLCR);
36427 + /* Enable the clock and wait for a short while */
36428 + value |= ASP_CLKEN;
36429 + mx1_reg_write(ASP_ACNTLCR, value);
36430 + udelay(100);
36432 + /* Set the value of the conrtol register. */
36433 + value = ASP_CLKEN | ASP_NM | ASP_SW6 | ASP_BGE;
36434 + mx1_reg_write(ASP_ACNTLCR, value);
36436 + /* Set the clock divide ratio to 2. */
36437 + mx1_reg_write(ASP_CLKDIV, 0x01);
36439 + /* Set the sample rate control register. These values should yield
36440 + * about 150 samples per second, which seems to give good smooth
36441 + * lines. */
36442 + value = (0x2 << ASP_DMCNT_SCALE) | /* Decimation ratio is 3 */
36443 + (0x1 << ASP_IDLECNT_SCALE) | /* Idle count is 1 clock */
36444 + (0x2 << ASP_DSCNT_SCALE); /* Data setup is 2 clocks */
36445 + mx1_reg_write(ASP_PSMPLRG, value);
36447 + /* Disable the compare function. */
36448 + mx1_reg_write(ASP_CMPCNTL, 0);
36451 +static void mx1_ts_enable_auto_sample(void)
36453 + unsigned int value;
36455 + mx1_ts_flush_fifo();
36457 + value = mx1_reg_read(ASP_ACNTLCR);
36459 + /* Set the mode to X then Y */
36460 + value &= ~ASP_MODE_MASK;
36461 + value |= ASP_MODE_ONLY_Y;
36463 + /* Enable auto zero. */
36464 + value |= ASP_AZE;
36466 + /* Enable auto sample. */
36467 + value |= ASP_AUTO;
36469 + /* Enable pen A/D. */
36470 + value |= ASP_PADE;
36471 + mx1_reg_write(ASP_ACNTLCR, value);
36473 + /* Enable pen data ready and full interrupt. */
36474 + value = mx1_reg_read(ASP_ICNTLR);
36475 + value |= ASP_PFFE | ASP_PDRE;
36476 + mx1_reg_write(ASP_ICNTLR, value);
36479 +static void mx1_ts_disable_auto_sample(void)
36481 + unsigned int value;
36483 + value = mx1_reg_read(ASP_ACNTLCR);
36485 + /* Set the mode to none */
36486 + value &= ~ASP_MODE_MASK;
36488 + /* Disable auto zero. */
36489 + value &= ~ASP_AZE;
36491 + /* Disable auto sample. */
36492 + value &= ~ASP_AUTO;
36494 + /* Disable pen A/D. */
36495 + value &= ~ASP_PADE;
36496 + mx1_reg_write(ASP_ACNTLCR, value);
36498 + /* Disable pen data ready and full interrupt. */
36499 + value = mx1_reg_read(ASP_ICNTLR);
36500 + value &= ~(ASP_PFFE | ASP_PDRE);
36501 + mx1_reg_write(ASP_ICNTLR, value);
36504 +static void mx1_ts_enable_pen_touch_interrupt(void)
36506 + unsigned int value;
36508 + /* Enable pen touch interrupt. */
36509 + value = mx1_reg_read(ASP_ICNTLR);
36510 + value |= ASP_EDGE | ASP_PIRQE;
36511 + mx1_reg_write(ASP_ICNTLR, value);
36514 +static void mx1_ts_disable_pen_touch_interrupt(void)
36516 + unsigned int value;
36518 + /* Enable pen touch interrupt. */
36519 + value = mx1_reg_read(ASP_ICNTLR);
36520 + value &= ~ASP_PIRQE;
36521 + mx1_reg_write(ASP_ICNTLR, value);
36524 +static void mx1_ts_enable_pen_up_interrupt(void)
36526 + unsigned int value;
36528 + /* Enable pen up interrupt. XXX: This feature is undocumented. */
36529 + value = mx1_reg_read(ASP_ICNTLR);
36530 + value |= ASP_PUPE;
36531 + mx1_reg_write(ASP_ICNTLR, value);
36534 +static void mx1_ts_disable_pen_up_interrupt(void)
36536 + unsigned int value;
36538 + /* Enable pen up interrupt. XXX: This feature is undocumented. */
36539 + value = mx1_reg_read(ASP_ICNTLR);
36540 + value &= ~ASP_PUPE;
36541 + mx1_reg_write(ASP_ICNTLR, value);
36544 +static void mx1_ts_start_auto_calibration(void)
36546 + unsigned int value;
36548 + mx1_performing_auto_calibration = 1;
36550 + value = mx1_reg_read(ASP_ACNTLCR);
36552 + /* Set the mode to X then Y */
36553 + value &= ~ASP_MODE_MASK;
36554 + value |= ASP_MODE_ONLY_X;
36556 + /* Enable auto zero. */
36557 + value |= ASP_AZE;
36559 + /* Enable auto calibrate. XXX: Undocumented bitfield. */
36560 + value |= 0x04000000;
36562 + /* Enable auto sample. */
36563 + value |= ASP_AUTO;
36565 + /* Enable pen A/D. */
36566 + value |= ASP_PADE;
36567 + mx1_reg_write(ASP_ACNTLCR, value);
36569 + /* Enable pen data ready and full interrupt. */
36570 + value = mx1_reg_read(ASP_ICNTLR);
36571 + value |= ASP_PFFE | ASP_PDRE | ASP_PUPE;
36572 + mx1_reg_write(ASP_ICNTLR, value);
36575 +static int mx1_ts_startup(struct mx1_ts *ts)
36577 + int ret = 0;
36579 + if (ts->use_count++ != 0)
36580 + goto out;
36582 + /*
36583 + * Reset the ASP.
36584 + */
36585 + mx1_ts_reset_asp();
36588 + /*
36589 + * XXX: Figure out if we need this...
36590 + * If we do this at all, we should allow the user to
36591 + * measure and read the X and Y resistance at any time.
36592 + */
36593 + //ts->x_res = mx1_ts_read_xres(ts);
36594 + //ts->y_res = mx1_ts_read_yres(ts);
36596 + mx1_ts_enable_pen_touch_interrupt();
36598 + out:
36599 + if (ret)
36600 + ts->use_count--;
36601 + return ret;
36605 + * Release touchscreen resources. Disable IRQs.
36606 + */
36607 +static void mx1_ts_shutdown(struct mx1_ts *ts)
36609 + if (--ts->use_count == 0) {
36610 + unsigned int value;
36612 + /* Turn off the ADC and associated circuitry. */
36613 + value = mx1_reg_read(ASP_ACNTLCR);
36614 + value &= !(ASP_CLKEN | ASP_PADE | ASP_BGE);
36615 + mx1_reg_write(ASP_ACNTLCR, value);
36620 + * Initialization.
36621 + */
36622 +static int __init mx1_ts_init(void)
36624 + int ret = 0;
36625 + struct mx1_ts *ts = &mx1ts;
36627 + mx1_ts_reset_asp();
36629 + /*
36630 + * Enable the IRQ's
36631 + */
36632 + if ((ret = mx1_ts_enable_irqs()))
36633 + return ret;
36635 + return mx1_ts_register(ts);
36638 +static void __exit mx1_ts_exit(void)
36640 + struct mx1_ts *ts = &mx1ts;
36642 + mx1_ts_disable_irqs();
36643 + mx1_ts_deregister(ts);
36646 +module_init(mx1_ts_init);
36647 +module_exit(mx1_ts_exit);
36649 +MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
36650 +MODULE_DESCRIPTION("MX1 touchscreen driver");
36651 +MODULE_LICENSE("GPL");
36652 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
36653 +++ linux-2.4.25/drivers/input/mx1ts.h 2004-03-31 17:15:09.000000000 +0200
36654 @@ -0,0 +1,108 @@
36656 + * linux/drivers/misc/mx1ts.h
36658 + * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
36660 + * This program is free software; you can redistribute it and/or modify
36661 + * it under the terms of the GNU General Public License version 2 as
36662 + * published by the Free Software Foundation.
36664 + */
36666 +/* Interrupt numbers */
36667 +#define ASP_COMPARE_IRQ 5
36668 +#define ASP_PENDATA_IRQ 33
36669 +#define ASP_TOUCH_IRQ 46
36671 +/* Analog signal processor (ASP) control registers */
36672 +#define ASP_ACNTLCR 0xF0215010 /* Control register */
36673 +#define ASP_PSMPLRG 0xF0215014 /* Pen A/D sampe rate control */
36674 +#define ASP_CMPCNTL 0xF0215030 /* Compare control register */
36675 +#define ASP_ICNTLR 0xF0215018 /* Interrupt control register */
36676 +#define ASP_ISTATR 0xF021501C /* Interrupt status register */
36677 +#define ASP_PADFIFO 0xF0215000 /* Pen sample FIFO */
36678 +#define ASP_CLKDIV 0xF021502C /* Clock divide register */
36680 +/* ASP control register bits */
36681 +#define ASP_CLKEN (1 << 25) /* Clock enable */
36682 +#define ASP_SWRST (1 << 23) /* Software reset */
36683 +#define ASP_U_SEL (1 << 21) /* U-channel resistor select */
36684 +#define ASP_AZ_SEL (1 << 20) /* Auto-zero position select */
36685 +#define ASP_LVM (1 << 19) /* Low voltage output */
36686 +#define ASP_NM (1 << 18) /* Normal voltage output */
36687 +#define ASP_HPM (1 << 17) /* High voltage output */
36688 +#define ASP_GLO (1 << 16) /* Low gain enable */
36689 +#define ASP_AZE (1 << 15) /* Auto-zero enable */
36690 +#define ASP_AUTO (1 << 14) /* Auto sampling */
36691 +#define ASP_SW8 (1 << 11) /* Switch control 8 */
36692 +#define ASP_SW7 (1 << 10)
36693 +#define ASP_SW6 (1 << 9)
36694 +#define ASP_SW5 (1 << 8)
36695 +#define ASP_SW4 (1 << 7)
36696 +#define ASP_SW3 (1 << 6)
36697 +#define ASP_SW2 (1 << 5)
36698 +#define ASP_SW1 (1 << 4) /* Switch control 1 */
36699 +#define ASP_VDAE (1 << 3) /* Voice D/A enable */
36700 +#define ASP_VADE (1 << 2) /* Voice A/D enable */
36701 +#define ASP_PADE (1 << 1) /* Pen A/D enable */
36702 +#define ASP_BGE (1 << 0) /* Bandgap enable */
36704 +#define ASP_MODE_MASK 0x00003000
36705 +#define ASP_MODE_NONE 0x00000000
36706 +#define ASP_MODE_ONLY_X 0x00001000
36707 +#define ASP_MODE_ONLY_Y 0x00002000
36708 +#define ASP_MODE_ONLY_U 0x00003000
36710 +/* ASP Pen A/D sample rate control register */
36711 +#define ASP_DMCNT_MASK (0x00007000) /* Decimation ratio count */
36712 +#define ASP_DMCNT_SCALE (12)
36713 +#define ASP_BIT_SELECT_MASK (0x00000C00) /* Bit select */
36714 +#define ASP_BIT_SELECT_SCALE (10)
36715 +#define ASP_IDLECNT_MASK (0x000003F0) /* Idle count */
36716 +#define ASP_IDLECNT_SCALE (4)
36717 +#define ASP_DSCNT_MASK (0x0000000F) /* Data setup count */
36718 +#define ASP_DSCNT_SCALE (0)
36720 +/* ASP compare control register */
36721 +#define ASP_INT (1 << 19) /* Interrupt status */
36722 +#define ASP_CC (1 << 18) /* Trigger on greater than */
36723 +#define ASP_INSEL_MASK (0x00030000)
36724 +#define ASP_INSEL_DISABLE (0x00000000)
36725 +#define ASP_INSEL_X (0x00010000)
36726 +#define ASP_INSEL_Y (0x00020000)
36727 +#define ASP_INSEL_U (0x00030000)
36728 +#define ASP_COMPARE_VAL_MASK (0x0000FFFF)
36729 +#define ASP_COMPARE_VAL_SCALE (0)
36731 +/* ASP interrupt control register bits */
36732 +#define ASP_PUPE (1 << 10) /* Pen up XXX undocumented */
36733 +#define ASP_VDDMAE (1 << 8) /* VDAC FIFO empty DMA */
36734 +#define ASP_VADMAE (1 << 7) /* VADC FIFO full DMA */
36735 +#define ASP_POL (1 << 6) /* Pen interrupt polarity */
36736 +#define ASP_EDGE (1 << 5) /* Edge trigger enable */
36737 +#define ASP_PIRQE (1 << 4) /* Pen interrupt enable */
36738 +#define ASP_VDAFEE (1 << 3) /* VDAC FIFO empty interrupt */
36739 +#define ASP_VADFFE (1 << 2) /* VADC FIFO full interrupt */
36740 +#define ASP_PFFE (1 << 1) /* Pen FIFO full interrupt */
36741 +#define ASP_PDRE (1 << 0) /* Pen data ready interrupt */
36743 +/* ASP interrupt/error status register bits */
36744 +#define ASP_PUP (1 << 10) /* Pen up XXX undocumented */
36745 +#define ASP_BGR (1 << 9) /* Bandgap ready */
36746 +#define ASP_VOV (1 << 8) /* Voice sample data overflow */
36747 +#define ASP_POV (1 << 7) /* Pen sample data overflow */
36748 +#define ASP_PEN (1 << 6) /* Pen interrupt */
36749 +#define ASP_VDAFF (1 << 5) /* VDAC FIFO full */
36750 +#define ASP_VDAFE (1 << 4) /* VDAC FIFO empty */
36751 +#define ASP_VADFF (1 << 3) /* VADC FIFO full */
36752 +#define ASP_VADDR (1 << 2) /* VADC data ready */
36753 +#define ASP_PFF (1 << 1) /* Pen sample FIFO full */
36754 +#define ASP_PDR (1 << 0) /* Pen data ready */
36756 +/* ASP Clock divide register */
36757 +#define ASP_PADC_CLK_MASK (0x0000001F)
36758 +#define ASP_PADC_CLK_SCALE (0)
36759 +#define ASP_VADC_CLK_MASK (0x000003E0)
36760 +#define ASP_VADC_CLK_SCALE (5)
36761 +#define ASP_VDAC_CLK_MASK (0x00003C00)
36762 +#define ASP_VDAC_CLK_SCALE (10)
36763 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
36764 +++ linux-2.4.25/drivers/l3/Config.in 2004-03-31 17:15:09.000000000 +0200
36765 @@ -0,0 +1,21 @@
36767 +# L3 bus configuration
36769 +mainmenu_option next_comment
36770 +comment 'L3 serial bus support'
36772 +tristate 'L3 support' CONFIG_L3
36773 +dep_bool ' L3 bit-banging interfaces' CONFIG_L3_ALGOBIT $CONFIG_L3
36774 +dep_bool ' SA11x0 GPIO adapter' CONFIG_L3_BIT_SA1100_GPIO $CONFIG_L3_ALGOBIT $CONFIG_ARCH_SA1100
36776 +comment 'Other L3 adapters'
36777 +dep_bool ' SA1111 adapter' CONFIG_L3_SA1111 $CONFIG_L3
36778 +endmenu
36780 +# i2c must come before this
36781 +if [ "$CONFIG_L3_BIT_SA1100_GPIO" = "y" -o \
36782 + "$CONFIG_I2C_BIT_SA1100_GPIO" = "y" ]; then
36783 + define_bool CONFIG_BIT_SA1100_GPIO y
36784 +else
36785 + define_bool CONFIG_BIT_SA1100_GPIO n
36787 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
36788 +++ linux-2.4.25/drivers/l3/Makefile 2004-03-31 17:15:09.000000000 +0200
36789 @@ -0,0 +1,23 @@
36791 +# Makefile for the L3 bus driver.
36794 +O_TARGET := l3.o
36796 +export-objs := l3-core.o l3-algo-bit.o
36797 +l3-y :=
36798 +l3-n :=
36799 +l3-drv-y :=
36800 +l3-drv-n :=
36802 +# Link order:
36803 +# (core, adapters, algorithms, drivers) then clients
36805 +l3-$(CONFIG_L3_ALGOBIT) += l3-algo-bit.o
36806 +l3-$(CONFIG_BIT_SA1100_GPIO) += l3-bit-sa1100.o
36807 +l3-$(CONFIG_L3_SA1111) += l3-sa1111.o
36809 +obj-$(CONFIG_L3) += l3-core.o $(l3-y) $(l3-drv-y)
36811 +include $(TOPDIR)/Rules.make
36813 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
36814 +++ linux-2.4.25/drivers/l3/l3-algo-bit.c 2004-03-31 17:15:09.000000000 +0200
36815 @@ -0,0 +1,175 @@
36817 + * L3 bus algorithm module.
36819 + * Copyright (C) 2001 Russell King, All Rights Reserved.
36821 + * This program is free software; you can redistribute it and/or modify
36822 + * it under the terms of the GNU General Public License version 2 as
36823 + * published by the Free Software Foundation.
36825 + * Note that L3 buses can share the same pins as I2C buses, so we must
36826 + * _not_ generate an I2C start condition. An I2C start condition is
36827 + * defined as a high-to-low transition of the data line while the clock
36828 + * is high. Therefore, we must only change the data line while the
36829 + * clock is low.
36830 + */
36831 +#include <linux/module.h>
36832 +#include <linux/kernel.h>
36833 +#include <linux/delay.h>
36834 +#include <linux/slab.h>
36835 +#include <linux/init.h>
36836 +#include <linux/errno.h>
36837 +#include <linux/sched.h>
36838 +#include <linux/l3/l3.h>
36839 +#include <linux/l3/algo-bit.h>
36841 +#define setdat(adap,val) adap->setdat(adap->data, val)
36842 +#define setclk(adap,val) adap->setclk(adap->data, val)
36843 +#define setmode(adap,val) adap->setmode(adap->data, val)
36844 +#define setdatin(adap) adap->setdir(adap->data, 1)
36845 +#define setdatout(adap) adap->setdir(adap->data, 0)
36846 +#define getdat(adap) adap->getdat(adap->data)
36849 + * Send one byte of data to the chip. Data is latched into the chip on
36850 + * the rising edge of the clock.
36851 + */
36852 +static void sendbyte(struct l3_algo_bit_data *adap, unsigned int byte)
36854 + int i;
36856 + for (i = 0; i < 8; i++) {
36857 + setclk(adap, 0);
36858 + udelay(adap->data_hold);
36859 + setdat(adap, byte & 1);
36860 + udelay(adap->data_setup);
36861 + setclk(adap, 1);
36862 + udelay(adap->clock_high);
36863 + byte >>= 1;
36868 + * Send a set of bytes to the chip. We need to pulse the MODE line
36869 + * between each byte, but never at the start nor at the end of the
36870 + * transfer.
36871 + */
36872 +static void sendbytes(struct l3_algo_bit_data *adap, const char *buf, int len)
36874 + int i;
36876 + for (i = 0; i < len; i++) {
36877 + if (i) {
36878 + udelay(adap->mode_hold);
36879 + setmode(adap, 0);
36880 + udelay(adap->mode);
36882 + setmode(adap, 1);
36883 + udelay(adap->mode_setup);
36884 + sendbyte(adap, buf[i]);
36889 + * Read one byte of data from the chip. Data is latched into the chip on
36890 + * the rising edge of the clock.
36891 + */
36892 +static unsigned int readbyte(struct l3_algo_bit_data *adap)
36894 + unsigned int byte = 0;
36895 + int i;
36897 + for (i = 0; i < 8; i++) {
36898 + setclk(adap, 0);
36899 + udelay(adap->data_hold + adap->data_setup);
36900 + setclk(adap, 1);
36901 + if (getdat(adap))
36902 + byte |= 1 << i;
36903 + udelay(adap->clock_high);
36906 + return byte;
36910 + * Read a set of bytes from the chip. We need to pulse the MODE line
36911 + * between each byte, but never at the start nor at the end of the
36912 + * transfer.
36913 + */
36914 +static void readbytes(struct l3_algo_bit_data *adap, char *buf, int len)
36916 + int i;
36918 + for (i = 0; i < len; i++) {
36919 + if (i) {
36920 + udelay(adap->mode_hold);
36921 + setmode(adap, 0);
36923 + setmode(adap, 1);
36924 + udelay(adap->mode_setup);
36925 + buf[i] = readbyte(adap);
36929 +static int l3_xfer(struct l3_adapter *l3_adap, struct l3_msg msgs[], int num)
36931 + struct l3_algo_bit_data *adap = l3_adap->algo_data;
36932 + int i;
36934 + /*
36935 + * If we share an I2C bus, ensure that it is in STOP mode
36936 + */
36937 + setclk(adap, 1);
36938 + setdat(adap, 1);
36939 + setmode(adap, 1);
36940 + setdatout(adap);
36941 + udelay(adap->mode);
36943 + for (i = 0; i < num; i++) {
36944 + struct l3_msg *pmsg = &msgs[i];
36946 + if (!(pmsg->flags & L3_M_NOADDR)) {
36947 + setmode(adap, 0);
36948 + udelay(adap->mode_setup);
36949 + sendbyte(adap, pmsg->addr);
36950 + udelay(adap->mode_hold);
36953 + if (pmsg->flags & L3_M_RD) {
36954 + setdatin(adap);
36955 + readbytes(adap, pmsg->buf, pmsg->len);
36956 + } else {
36957 + setdatout(adap);
36958 + sendbytes(adap, pmsg->buf, pmsg->len);
36962 + /*
36963 + * Ensure that we leave the bus in I2C stop mode.
36964 + */
36965 + setclk(adap, 1);
36966 + setdat(adap, 1);
36967 + setmode(adap, 0);
36968 + setdatin(adap);
36970 + return num;
36973 +static struct l3_algorithm l3_bit_algo = {
36974 + name: "L3 bit-shift algorithm",
36975 + xfer: l3_xfer,
36978 +int l3_bit_add_bus(struct l3_adapter *adap)
36980 + adap->algo = &l3_bit_algo;
36981 + return l3_add_adapter(adap);
36984 +int l3_bit_del_bus(struct l3_adapter *adap)
36986 + return l3_del_adapter(adap);
36989 +EXPORT_SYMBOL(l3_bit_add_bus);
36990 +EXPORT_SYMBOL(l3_bit_del_bus);
36991 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
36992 +++ linux-2.4.25/drivers/l3/l3-bit-sa1100.c 2004-03-31 17:15:09.000000000 +0200
36993 @@ -0,0 +1,277 @@
36995 + * linux/drivers/l3/l3-bit-sa1100.c
36997 + * Copyright (C) 2001 Russell King
36999 + * This program is free software; you can redistribute it and/or modify
37000 + * it under the terms of the GNU General Public License version 2 as
37001 + * published by the Free Software Foundation.
37003 + * This is a combined I2C and L3 bus driver.
37004 + */
37005 +#include <linux/config.h>
37006 +#include <linux/module.h>
37007 +#include <linux/kernel.h>
37008 +#include <linux/ioport.h>
37009 +#include <linux/delay.h>
37010 +#include <linux/slab.h>
37011 +#include <linux/init.h>
37012 +#include <linux/i2c-algo-bit.h>
37013 +#include <linux/l3/algo-bit.h>
37015 +#include <asm/system.h>
37016 +#include <asm/hardware.h>
37017 +#include <asm/mach-types.h>
37018 +#include <asm/arch/assabet.h>
37020 +#define NAME "l3-bit-sa1100-gpio"
37022 +struct bit_data {
37023 + unsigned int sda;
37024 + unsigned int scl;
37025 + unsigned int l3_mode;
37028 +static int getsda(void *data)
37030 + struct bit_data *bits = data;
37032 + return GPLR & bits->sda;
37035 +#ifdef CONFIG_I2C_BIT_SA1100_GPIO
37036 +static void i2c_setsda(void *data, int state)
37038 + struct bit_data *bits = data;
37039 + unsigned long flags;
37041 + local_irq_save(flags);
37042 + if (state)
37043 + GPDR &= ~bits->sda;
37044 + else {
37045 + GPCR = bits->sda;
37046 + GPDR |= bits->sda;
37048 + local_irq_restore(flags);
37051 +static void i2c_setscl(void *data, int state)
37053 + struct bit_data *bits = data;
37054 + unsigned long flags;
37056 + local_irq_save(flags);
37057 + if (state)
37058 + GPDR &= ~bits->scl;
37059 + else {
37060 + GPCR = bits->scl;
37061 + GPDR |= bits->scl;
37063 + local_irq_restore(flags);
37066 +static int i2c_getscl(void *data)
37068 + struct bit_data *bits = data;
37070 + return GPLR & bits->scl;
37073 +static struct i2c_algo_bit_data i2c_bit_data = {
37074 + setsda: i2c_setsda,
37075 + setscl: i2c_setscl,
37076 + getsda: getsda,
37077 + getscl: i2c_getscl,
37078 + udelay: 10,
37079 + mdelay: 10,
37080 + timeout: 100,
37083 +static struct i2c_adapter i2c_adapter = {
37084 + name: NAME,
37085 + algo_data: &i2c_bit_data,
37086 +// inc_use: i2c_inc_use,
37087 +// dec_use: i2c_dec_use,
37090 +#define LOCK &i2c_adapter.lock
37092 +static int __init i2c_init(struct bit_data *bits)
37094 + i2c_bit_data.data = bits;
37095 + return i2c_bit_add_bus(&i2c_adapter);
37098 +static void i2c_exit(void)
37100 + i2c_bit_del_bus(&i2c_adapter);
37103 +#else
37104 +static DECLARE_MUTEX(l3_lock);
37105 +#define LOCK &l3_lock
37106 +#define i2c_init(bits) (0)
37107 +#define i2c_exit() do { } while (0)
37108 +#endif
37110 +#ifdef CONFIG_L3_BIT_SA1100_GPIO
37112 + * iPAQs need the clock line driven hard high and low.
37113 + */
37114 +static void l3_setscl(void *data, int state)
37116 + struct bit_data *bits = data;
37117 + unsigned long flags;
37119 + local_irq_save(flags);
37120 + if (state)
37121 + GPSR = bits->scl;
37122 + else
37123 + GPCR = bits->scl;
37124 + GPDR |= bits->scl;
37125 + local_irq_restore(flags);
37128 +static void l3_setsda(void *data, int state)
37130 + struct bit_data *bits = data;
37132 + if (state)
37133 + GPSR = bits->sda;
37134 + else
37135 + GPCR = bits->sda;
37138 +static void l3_setdir(void *data, int in)
37140 + struct bit_data *bits = data;
37141 + unsigned long flags;
37143 + local_irq_save(flags);
37144 + if (in)
37145 + GPDR &= ~bits->sda;
37146 + else
37147 + GPDR |= bits->sda;
37148 + local_irq_restore(flags);
37151 +static void l3_setmode(void *data, int state)
37153 + struct bit_data *bits = data;
37155 + if (state)
37156 + GPSR = bits->l3_mode;
37157 + else
37158 + GPCR = bits->l3_mode;
37161 +static struct l3_algo_bit_data l3_bit_data = {
37162 + data: NULL,
37163 + setdat: l3_setsda,
37164 + setclk: l3_setscl,
37165 + setmode: l3_setmode,
37166 + setdir: l3_setdir,
37167 + getdat: getsda,
37168 + data_hold: 1,
37169 + data_setup: 1,
37170 + clock_high: 1,
37171 + mode_hold: 1,
37172 + mode_setup: 1,
37175 +static struct l3_adapter l3_adapter = {
37176 + owner: THIS_MODULE,
37177 + name: NAME,
37178 + algo_data: &l3_bit_data,
37179 + lock: LOCK,
37182 +static int __init l3_init(struct bit_data *bits)
37184 + l3_bit_data.data = bits;
37185 + return l3_bit_add_bus(&l3_adapter);
37188 +static void __exit l3_exit(void)
37190 + l3_bit_del_bus(&l3_adapter);
37192 +#else
37193 +#define l3_init(bits) (0)
37194 +#define l3_exit() do { } while (0)
37195 +#endif
37197 +static struct bit_data bit_data;
37199 +static int __init bus_init(void)
37201 + struct bit_data *bit = &bit_data;
37202 + unsigned long flags;
37203 + int ret;
37205 + if (machine_is_assabet() || machine_is_pangolin()) {
37206 + bit->sda = GPIO_GPIO15;
37207 + bit->scl = GPIO_GPIO18;
37208 + bit->l3_mode = GPIO_GPIO17;
37211 +#if defined(CONFIG_SA1100_H3600) || defined(CONFIG_SA1100_H3100)
37212 + if (machine_is_h3600() || machine_is_h3100()) {
37213 + bit->sda = GPIO_H3600_L3_DATA;
37214 + bit->scl = GPIO_H3600_L3_CLOCK;
37215 + bit->l3_mode = GPIO_H3600_L3_MODE;
37217 +#endif
37219 +#ifdef CONFIG_SA1100_STORK
37220 + if (machine_is_stork()) {
37221 + bit->sda = GPIO_STORK_L3_I2C_SDA;
37222 + bit->scl = GPIO_STORK_L3_I2C_SCL;
37223 + bit->l3_mode = GPIO_STORK_L3_MODE;
37225 +#endif
37227 + if (!bit->sda)
37228 + return -ENODEV;
37230 + /*
37231 + * Default level for L3 mode is low.
37232 + * We set SCL and SDA high (i2c idle state).
37233 + */
37234 + local_irq_save(flags);
37235 + GPDR &= ~(bit->scl | bit->sda);
37236 + GPCR = bit->l3_mode | bit->scl | bit->sda;
37237 + GPDR |= bit->l3_mode;
37238 + local_irq_restore(flags);
37240 + if (machine_is_assabet()) {
37241 + /*
37242 + * Release reset on UCB1300, ADI7171 and UDA1341. We
37243 + * need to do this here so that we can communicate on
37244 + * the I2C/L3 buses.
37245 + */
37246 + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
37247 + mdelay(1);
37248 + ASSABET_BCR_clear(ASSABET_BCR_CODEC_RST);
37249 + mdelay(1);
37250 + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
37253 + ret = i2c_init(bit);
37254 + if (ret == 0 && bit->l3_mode) {
37255 + ret = l3_init(bit);
37256 + if (ret)
37257 + i2c_exit();
37260 + return ret;
37263 +static void __exit bus_exit(void)
37265 + l3_exit();
37266 + i2c_exit();
37269 +module_init(bus_init);
37270 +module_exit(bus_exit);
37271 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
37272 +++ linux-2.4.25/drivers/l3/l3-core.c 2004-03-31 17:15:09.000000000 +0200
37273 @@ -0,0 +1,377 @@
37275 + * linux/drivers/l3/l3-core.c
37277 + * Copyright (C) 2001 Russell King
37279 + * General structure taken from i2c-core.c by Simon G. Vogl
37281 + * This program is free software; you can redistribute it and/or modify
37282 + * it under the terms of the GNU General Public License as published by
37283 + * the Free Software Foundation; either version 2 of the License.
37285 + * See linux/Documentation/l3 for further documentation.
37286 + */
37287 +#include <linux/module.h>
37288 +#include <linux/config.h>
37289 +#include <linux/kernel.h>
37290 +#include <linux/errno.h>
37291 +#include <linux/slab.h>
37292 +#include <linux/proc_fs.h>
37293 +#include <linux/kmod.h>
37294 +#include <linux/init.h>
37295 +#include <linux/l3/l3.h>
37297 +static DECLARE_MUTEX(adapter_lock);
37298 +static LIST_HEAD(adapter_list);
37300 +static DECLARE_MUTEX(driver_lock);
37301 +static LIST_HEAD(driver_list);
37303 +/**
37304 + * l3_add_adapter - register a new L3 bus adapter
37305 + * @adap: l3_adapter structure for the registering adapter
37307 + * Make the adapter available for use by clients using name adap->name.
37308 + * The adap->adapters list is initialised by this function.
37310 + * Returns 0;
37311 + */
37312 +int l3_add_adapter(struct l3_adapter *adap)
37314 + INIT_LIST_HEAD(&adap->clients);
37315 + down(&adapter_lock);
37316 + list_add(&adap->adapters, &adapter_list);
37317 + up(&adapter_lock);
37318 + return 0;
37321 +/**
37322 + * l3_del_adapter - unregister a L3 bus adapter
37323 + * @adap: l3_adapter structure to unregister
37325 + * Remove an adapter from the list of available L3 Bus adapters.
37327 + * Returns 0;
37328 + */
37329 +int l3_del_adapter(struct l3_adapter *adap)
37331 + down(&adapter_lock);
37332 + list_del(&adap->adapters);
37333 + up(&adapter_lock);
37334 + return 0;
37337 +static struct l3_adapter *__l3_get_adapter(const char *name)
37339 + struct list_head *l;
37341 + list_for_each(l, &adapter_list) {
37342 + struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters);
37344 + if (strcmp(adap->name, name) == 0)
37345 + return adap;
37348 + return NULL;
37351 +/**
37352 + * l3_get_adapter - get a reference to an adapter
37353 + * @name: driver name
37355 + * Obtain a l3_adapter structure for the specified adapter. If the adapter
37356 + * is not currently load, then load it. The adapter will be locked in core
37357 + * until all references are released via l3_put_adapter.
37358 + */
37359 +struct l3_adapter *l3_get_adapter(const char *name)
37361 + struct l3_adapter *adap;
37362 + int try;
37364 + for (try = 0; try < 2; try ++) {
37365 + down(&adapter_lock);
37366 + adap = __l3_get_adapter(name);
37367 + if (adap && !try_inc_mod_count(adap->owner))
37368 + adap = NULL;
37369 + up(&adapter_lock);
37371 + if (adap)
37372 + break;
37374 + if (try == 0)
37375 + request_module(name);
37378 + return adap;
37381 +/**
37382 + * l3_put_adapter - release a reference to an adapter
37383 + * @adap: driver to release reference
37385 + * Indicate to the L3 core that you no longer require the adapter reference.
37386 + * The adapter module may be unloaded when there are no references to its
37387 + * data structure.
37389 + * You must not use the reference after calling this function.
37390 + */
37391 +void l3_put_adapter(struct l3_adapter *adap)
37393 + if (adap && adap->owner)
37394 + __MOD_DEC_USE_COUNT(adap->owner);
37397 +/**
37398 + * l3_add_driver - register a new L3 device driver
37399 + * @driver - driver structure to make available
37401 + * Make the driver available for use by clients using name driver->name.
37402 + * The driver->drivers list is initialised by this function.
37404 + * Returns 0;
37405 + */
37406 +int l3_add_driver(struct l3_driver *driver)
37408 + down(&driver_lock);
37409 + list_add(&driver->drivers, &driver_list);
37410 + up(&driver_lock);
37411 + return 0;
37414 +/**
37415 + * l3_del_driver - unregister a L3 device driver
37416 + * @driver: driver to remove
37418 + * Remove an driver from the list of available L3 Bus device drivers.
37420 + * Returns 0;
37421 + */
37422 +int l3_del_driver(struct l3_driver *driver)
37424 + down(&driver_lock);
37425 + list_del(&driver->drivers);
37426 + up(&driver_lock);
37427 + return 0;
37430 +static struct l3_driver *__l3_get_driver(const char *name)
37432 + struct list_head *l;
37434 + list_for_each(l, &driver_list) {
37435 + struct l3_driver *drv = list_entry(l, struct l3_driver, drivers);
37437 + if (strcmp(drv->name, name) == 0)
37438 + return drv;
37441 + return NULL;
37444 +/**
37445 + * l3_get_driver - get a reference to a driver
37446 + * @name: driver name
37448 + * Obtain a l3_driver structure for the specified driver. If the driver is
37449 + * not currently load, then load it. The driver will be locked in core
37450 + * until all references are released via l3_put_driver.
37451 + */
37452 +struct l3_driver *l3_get_driver(const char *name)
37454 + struct l3_driver *drv;
37455 + int try;
37457 + for (try = 0; try < 2; try ++) {
37458 + down(&adapter_lock);
37459 + drv = __l3_get_driver(name);
37460 + if (drv && !try_inc_mod_count(drv->owner))
37461 + drv = NULL;
37462 + up(&adapter_lock);
37464 + if (drv)
37465 + break;
37467 + if (try == 0)
37468 + request_module(name);
37471 + return drv;
37474 +/**
37475 + * l3_put_driver - release a reference to a driver
37476 + * @drv: driver to release reference
37478 + * Indicate to the L3 core that you no longer require the driver reference.
37479 + * The driver module may be unloaded when there are no references to its
37480 + * data structure.
37482 + * You must not use the reference after calling this function.
37483 + */
37484 +void l3_put_driver(struct l3_driver *drv)
37486 + if (drv && drv->owner)
37487 + __MOD_DEC_USE_COUNT(drv->owner);
37490 +/**
37491 + * l3_attach_client - attach a client to an adapter and driver
37492 + * @client: client structure to attach
37493 + * @adap: adapter (module) name
37494 + * @drv: driver (module) name
37496 + * Attempt to attach a client (a user of a device driver) to a particular
37497 + * driver and adapter. If the specified driver or adapter aren't registered,
37498 + * request_module is used to load the relevant modules.
37500 + * Returns 0 on success, or negative error code.
37501 + */
37502 +int l3_attach_client(struct l3_client *client, const char *adap, const char *drv)
37504 + struct l3_adapter *adapter = l3_get_adapter(adap);
37505 + struct l3_driver *driver = l3_get_driver(drv);
37506 + int ret = -ENOENT;
37508 + if (!adapter)
37509 + printk(KERN_ERR "%s: unable to get adapter: %s\n",
37510 + __FUNCTION__, adap);
37511 + if (!driver)
37512 + printk(KERN_ERR "%s: unable to get driver: %s\n",
37513 + __FUNCTION__, drv);
37515 + if (adapter && driver) {
37516 + ret = 0;
37518 + client->adapter = adapter;
37519 + client->driver = driver;
37521 + list_add(&client->__adap, &adapter->clients);
37523 + if (driver->attach_client)
37524 + ret = driver->attach_client(client);
37527 + if (ret) {
37528 + l3_put_driver(driver);
37529 + l3_put_adapter(adapter);
37531 + return ret;
37534 +/**
37535 + * l3_detach_client - detach a client from an adapter and driver
37536 + * @client: client structure to detach
37538 + * Detach the client from the adapter and driver.
37539 + */
37540 +int l3_detach_client(struct l3_client *client)
37542 + struct l3_adapter *adapter = client->adapter;
37543 + struct l3_driver *driver = client->driver;
37545 + driver->detach_client(client);
37547 + client->adapter = NULL;
37548 + client->driver = NULL;
37550 + l3_put_driver(driver);
37551 + l3_put_adapter(adapter);
37553 + list_del(&client->__adap);
37555 + return 0;
37558 +/**
37559 + * l3_transfer - transfer information on an L3 bus
37560 + * @adap: adapter structure to perform transfer on
37561 + * @msgs: array of l3_msg structures describing transfer
37562 + * @num: number of l3_msg structures
37564 + * Transfer the specified messages to/from a device on the L3 bus.
37566 + * Returns number of messages successfully transferred, otherwise negative
37567 + * error code.
37568 + */
37569 +int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
37571 + int ret = -ENOSYS;
37573 + if (adap->algo->xfer) {
37574 + down(adap->lock);
37575 + ret = adap->algo->xfer(adap, msgs, num);
37576 + up(adap->lock);
37578 + return ret;
37581 +/**
37582 + * l3_write - send data to a device on an L3 bus
37583 + * @client: registered client structure
37584 + * @addr: L3 bus address
37585 + * @buf: buffer for bytes to send
37586 + * @len: number of bytes to send
37588 + * Send len bytes pointed to by buf to device address addr on the L3 bus
37589 + * described by client.
37591 + * Returns the number of bytes transferred, or negative error code.
37592 + */
37593 +int l3_write(struct l3_client *client, int addr, const char *buf, int len)
37595 + struct l3_adapter *adap = client->adapter;
37596 + struct l3_msg msg;
37597 + int ret;
37599 + msg.addr = addr;
37600 + msg.flags = 0;
37601 + msg.buf = (char *)buf;
37602 + msg.len = len;
37604 + ret = l3_transfer(adap, &msg, 1);
37605 + return ret == 1 ? len : ret;
37608 +/**
37609 + * l3_read - receive data from a device on an L3 bus
37610 + * @client: registered client structure
37611 + * @addr: L3 bus address
37612 + * @buf: buffer for bytes to receive
37613 + * @len: number of bytes to receive
37615 + * Receive len bytes from device address addr on the L3 bus described by
37616 + * client to a buffer pointed to by buf.
37618 + * Returns the number of bytes transferred, or negative error code.
37619 + */
37620 +int l3_read(struct l3_client *client, int addr, char *buf, int len)
37622 + struct l3_adapter *adap = client->adapter;
37623 + struct l3_msg msg;
37624 + int ret;
37626 + msg.addr = addr;
37627 + msg.flags = L3_M_RD;
37628 + msg.buf = buf;
37629 + msg.len = len;
37631 + ret = l3_transfer(adap, &msg, 1);
37632 + return ret == 1 ? len : ret;
37635 +EXPORT_SYMBOL(l3_add_adapter);
37636 +EXPORT_SYMBOL(l3_del_adapter);
37637 +EXPORT_SYMBOL(l3_get_adapter);
37638 +EXPORT_SYMBOL(l3_put_adapter);
37640 +EXPORT_SYMBOL(l3_add_driver);
37641 +EXPORT_SYMBOL(l3_del_driver);
37642 +EXPORT_SYMBOL(l3_get_driver);
37643 +EXPORT_SYMBOL(l3_put_driver);
37645 +EXPORT_SYMBOL(l3_attach_client);
37646 +EXPORT_SYMBOL(l3_detach_client);
37648 +EXPORT_SYMBOL(l3_transfer);
37649 +EXPORT_SYMBOL(l3_write);
37650 +EXPORT_SYMBOL(l3_read);
37651 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
37652 +++ linux-2.4.25/drivers/l3/l3-sa1111.c 2004-03-31 17:15:09.000000000 +0200
37653 @@ -0,0 +1,118 @@
37655 + * L3 SA1111 algorithm/adapter module.
37657 + * By Russell King,
37658 + * gratuitously ripped from sa1111-uda1341.c by John Dorsey.
37660 + * This program is free software; you can redistribute it and/or modify
37661 + * it under the terms of the GNU General Public License version 2 as
37662 + * published by the Free Software Foundation.
37663 + */
37664 +#include <linux/module.h>
37665 +#include <linux/init.h>
37666 +#include <linux/delay.h>
37667 +#include <linux/errno.h>
37668 +#include <linux/l3/l3.h>
37670 +#include <asm/hardware.h>
37671 +#include <asm/semaphore.h>
37672 +#include <asm/mach-types.h>
37673 +#include <asm/arch/assabet.h>
37674 +#include <asm/hardware/sa1111.h>
37676 +static inline unsigned char l3_sa1111_recv_byte(unsigned char addr)
37678 + unsigned char dat;
37680 + L3_CAR = addr;
37681 + while ((SASR0 & SASR0_L3RD) == 0)
37682 + mdelay(1);
37683 + dat = L3_CDR;
37684 + SASCR = SASCR_RDD;
37685 + return dat;
37688 +static void l3_sa1111_recv_msg(struct l3_msg *msg)
37690 + int len = msg->len;
37691 + char *p = msg->buf;
37693 + if (len > 1) {
37694 + SACR1 |= SACR1_L3MB;
37695 + while ((len--) > 1)
37696 + *p++ = l3_sa1111_recv_byte(msg->addr);
37698 + SACR1 &= ~SACR1_L3MB;
37699 + *p = l3_sa1111_recv_byte(msg->addr);
37702 +static inline void l3_sa1111_send_byte(unsigned char addr, unsigned char dat)
37704 + L3_CAR = addr;
37705 + L3_CDR = dat;
37706 + while ((SASR0 & SASR0_L3WD) == 0)
37707 + mdelay(1);
37708 + SASCR = SASCR_DTS;
37711 +static void l3_sa1111_send_msg(struct l3_msg *msg)
37713 + int len = msg->len;
37714 + char *p = msg->buf;
37716 + if (len > 1) {
37717 + SACR1 |= SACR1_L3MB;
37718 + while ((len--) > 1)
37719 + l3_sa1111_send_byte(msg->addr, *p++);
37721 + SACR1 &= ~SACR1_L3MB;
37722 + l3_sa1111_send_byte(msg->addr, *p);
37725 +static int l3_sa1111_xfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
37727 + int i;
37729 + for (i = 0; i < num; i++) {
37730 + struct l3_msg *pmsg = &msgs[i];
37732 + if (pmsg->flags & L3_M_RD)
37733 + l3_sa1111_recv_msg(pmsg);
37734 + else
37735 + l3_sa1111_send_msg(pmsg);
37738 + return num;
37741 +static struct l3_algorithm l3_sa1111_algo = {
37742 + name: "L3 SA1111 algorithm",
37743 + xfer: l3_sa1111_xfer,
37746 +static DECLARE_MUTEX(sa1111_lock);
37748 +static struct l3_adapter l3_sa1111_adapter = {
37749 + owner: THIS_MODULE,
37750 + name: "l3-sa1111",
37751 + algo: &l3_sa1111_algo,
37752 + lock: &sa1111_lock,
37755 +static int __init l3_sa1111_init(void)
37757 + int ret = -ENODEV;
37758 + if ((machine_is_assabet() && machine_has_neponset()) ||
37759 + machine_is_jornada720() || machine_is_accelent_sa() ||
37760 + machine_is_badge4())
37761 + ret = l3_add_adapter(&l3_sa1111_adapter);
37762 + return ret;
37765 +static void __exit l3_sa1111_exit(void)
37767 + l3_del_adapter(&l3_sa1111_adapter);
37770 +module_init(l3_sa1111_init);
37771 +module_exit(l3_sa1111_exit);
37772 --- linux-2.4.25/drivers/media/video/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
37773 +++ linux-2.4.25/drivers/media/video/Config.in 2004-03-31 17:15:09.000000000 +0200
37774 @@ -52,5 +52,8 @@
37775 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
37776 dep_tristate ' Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI
37778 +# unfortunately, this depends on having CONFIG_FB_CYBER2000
37779 +# set as well - we hook off of the VGA driver
37780 +dep_tristate ' NetWinder Video for Linux (EXPERIMENTAL)' CONFIG_VIDEO_CYBERPRO $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL $CONFIG_ARCH_NETWINDER
37782 endmenu
37783 --- linux-2.4.25/drivers/media/video/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
37784 +++ linux-2.4.25/drivers/media/video/Makefile 2004-03-31 17:15:09.000000000 +0200
37785 @@ -16,7 +16,7 @@
37786 obj-n :=
37787 obj- :=
37789 -SUB_DIRS :=
37790 +SUB_DIRS :=
37791 MOD_SUB_DIRS := $(SUB_DIRS)
37792 ALL_SUB_DIRS := $(SUB_DIRS)
37794 @@ -47,7 +47,8 @@
37795 obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o
37796 obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o
37797 obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o
37798 -obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o
37799 +obj-$(CONFIG_VIDEO_CYBERPRO) += cyberpro.o i2c-old.o saa7111.o
37800 +obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
37801 obj-$(CONFIG_VIDEO_PMS) += pms.o
37802 obj-$(CONFIG_VIDEO_PLANB) += planb.o
37803 obj-$(CONFIG_VIDEO_VINO) += saa7191.o indycam.o vino.o
37804 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
37805 +++ linux-2.4.25/drivers/media/video/cyberpro.c 2004-03-31 17:15:09.000000000 +0200
37806 @@ -0,0 +1,2091 @@
37808 + * CyberPro 2000 video capture driver for the Rebel.com NetWinder
37810 + * (C) 1999-2000 Russell King
37812 + * Re-written from Rebel.com's vidcap driver.
37814 + * Architecture
37815 + * ------------
37816 + * The NetWinder video capture consists of a SAA7111 video decoder chip
37817 + * connected to the CyberPro feature bus. The video data is captured to
37818 + * the VGA memory, where the CyberPro can overlay (by chromakeying) the
37819 + * data onto the VGA display.
37821 + * The CyberPro also has some nifty features, including a second overlay
37822 + * and picture in picture mode. We do not currently use these features.
37824 + * Power Saving
37825 + * ------------
37826 + * Please note that rev.5 NetWinders have the ability to hold the SAA7111
37827 + * decoder chip into reset, which saves power. The only time at which
37828 + * this is done is when the driver is unloaded, which implies that this
37829 + * is compiled as a module.
37831 + * In this case, you will want the kernel to automatically load this
37832 + * driver when required. Place the following line in /etc/modules.conf
37833 + * to enable this:
37835 + * alias char-major-81-0 cyberpro
37837 + * The relevant modules will be automatically loaded by modprobe on a
37838 + * as and when needed basis.
37840 + * Capture resolution
37841 + * ------------------
37842 + * The maximum useful capture resolution is:
37843 + * 625-line UK: 716x576
37844 + * 525-line US: ?
37846 + * Bugs
37847 + * ----
37848 + * 1. The CyberPro chip seems to be prone to randomly scribbling over VGA
37849 + * memory [hopefully fixed with new capture enable/freeze stuff]
37850 + * 2. read()ing pauses video capture, and sometimes triggers bug 1.
37851 + * 3. mmap() is not supported (requires BM-DMA - see bug 4)
37852 + * 4. Really, we want to do scatter BM-DMA. Is the CyberPro capable of this?
37853 + * The Cyberpro seems to randomly scribble to various PCI addresses if you
37854 + * transfer >16 words.
37855 + * 5. We shouldn't ignore O_NONBLOCK when reading a frame.
37856 + * 6. The incoming stream on the NetWinder is CCIR656, which is YUV422.
37857 + * CyberPro docs also call the format we capture and overlay "YUV422",
37858 + * but we actually seem to have Y, U, Y, V bytes (is this YUYV format?)
37859 + */
37860 +#include <linux/config.h>
37861 +#include <linux/module.h>
37862 +#include <linux/videodev.h>
37863 +#include <linux/video_decoder.h>
37864 +#include <linux/mm.h>
37865 +#include <linux/i2c-old.h>
37866 +#include <linux/spinlock.h>
37867 +#include <linux/slab.h>
37868 +#include <linux/vmalloc.h>
37869 +#include <linux/delay.h>
37870 +#include <linux/sched.h>
37871 +#include <linux/kmod.h>
37872 +#include <linux/pci.h>
37873 +#include <linux/init.h>
37875 +#include <asm/io.h>
37876 +#include <asm/irq.h>
37877 +#include <asm/pgtable.h>
37878 +#include <asm/pgalloc.h>
37880 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
37881 +MODULE_DESCRIPTION("CyberPro v4l video grabber");
37882 +MODULE_LICENSE("GPL");
37884 +#include "../../video/cyber2000fb.h"
37887 + * These enable various experimental features. Most of these
37888 + * are just plain broken or just don't work at the moment.
37889 + */
37891 + * Enable this if you want mmap() access. (see bug 4)
37892 + */
37893 +#undef USE_MMAP
37896 + * Enable this if you want mmio access. (slow)
37897 + */
37898 +#define USE_MMIO
37901 + * The V4L API is unclear whether VIDIOCSCAPTURE call is allowed while
37902 + * capture is running. The default is to disallow the call.
37904 + * Define this if you do want to allow the call while capture is active.
37905 + */
37906 +#undef ALLOW_SCAPTURE_WHILE_CAP
37909 + * We capture two frames
37910 + */
37911 +#define NR_FRAMES 2
37914 + * One frame of video is 202 pages, assuming YUV422 format, 716x576
37915 + */
37916 +#define NR_PAGES 202
37918 +struct src_info {
37919 + unsigned int offset; /* offset of source data */
37920 + unsigned int x; /* source x */
37921 + unsigned int y; /* source y */
37922 + unsigned int width; /* source width */
37923 + unsigned int height; /* source height */
37924 + unsigned int format; /* source format */
37927 +struct dst_info {
37928 + unsigned int x; /* destination x */
37929 + unsigned int y; /* destination y */
37930 + unsigned int width; /* destination width */
37931 + unsigned int height; /* destination height */
37932 + unsigned int chromakey; /* chromakey */
37933 + unsigned int flags; /* flags (eg, chromakey enable) */
37936 +struct cyberpro_vidinfo;
37938 +struct win_info {
37939 + void (*init)(struct cyberpro_vidinfo *dp, struct win_info *wi);
37940 + void (*set_src)(struct cyberpro_vidinfo *dp, struct win_info *wi);
37941 + void (*set_win)(struct cyberpro_vidinfo *dp, struct win_info *wi);
37942 + void (*ctl)(struct cyberpro_vidinfo *dp, struct win_info *wi, int on_off);
37944 + /* public */
37945 + struct src_info src;
37946 + struct dst_info dst;
37948 + /* private */
37949 + unsigned short vid_fifo_ctl;
37950 + unsigned char vid_fmt;
37951 + unsigned char vid_disp_ctl1;
37952 + unsigned char vid_fifo_ctl1;
37953 + unsigned char vid_misc_ctl1;
37956 +struct framebuf {
37957 + unsigned int offset; /* mmap offset for this frame */
37958 + unsigned int status;
37959 +#define FRAME_FREE 0
37960 +#define FRAME_DONE 1
37961 +#define FRAME_WAITING 2
37962 +#define FRAME_GRABBING 3
37964 + /*
37965 + * Bus-Master DMA stuff. Note that we should
37966 + * probably use the kiovec stuff instead.
37967 + */
37968 + unsigned long bus_addr[NR_PAGES]; /* list of pages */
37969 + struct page *pages[NR_PAGES];
37970 + void *buffer;
37971 + int dbg;
37974 +struct cyberpro_vidinfo {
37975 + struct video_device *dev;
37976 + struct i2c_bus *bus;
37977 + struct cyberpro_info info; /* host information */
37978 + unsigned char *regs;
37979 + unsigned int irq; /* PCI interrupt number */
37981 + /* hardware configuration */
37982 + unsigned int stream_fmt; /* format of stream from decoder*/
37984 + /* software settings */
37985 + unsigned int decoder:1; /* decoder loaded */
37986 + unsigned int interlace:1; /* interlace */
37987 + unsigned int buf_set:1; /* VIDIOCSFBUF has been issued */
37988 + unsigned int win_set:1; /* VIDIOCSWIN has been issued */
37989 + unsigned int cap_active:1; /* capture is active */
37990 + unsigned int ovl_active:1; /* overlay is active */
37991 + unsigned int mmaped:1; /* buffer is mmap()d */
37992 + unsigned int unused:25;
37994 + unsigned int users; /* number of users */
37995 + unsigned long cap_mem_offset; /* capture framebuffer offset */
37996 + void * buffer; /* kernel capture buffer */
37997 + unsigned int norm; /* video standard */
37999 + struct video_capability cap; /* capabilities */
38000 + struct video_picture pic; /* current picture settings */
38001 + struct video_buffer buf; /* display parameters */
38002 + struct video_capture capt; /* video capture params */
38004 + struct win_info *ovl; /* overlay window set */
38005 + struct win_info ext; /* "Extended" window info */
38006 + struct win_info v2; /* "V2" window info */
38007 + struct win_info x2; /* "X2" window info */
38009 + unsigned int bm_offset; /* Cap memory bus master offset */
38010 + unsigned int bm_index; /* Cap page index */
38012 +#ifdef USE_MMAP
38013 + unsigned int frame_idx; /* currently grabbing frame */
38014 + unsigned int frame_size;
38015 + struct framebuf frame[NR_FRAMES];
38016 + wait_queue_head_t frame_wait;
38017 +#endif
38019 + wait_queue_head_t vbl_wait;
38021 + /*
38022 + * cyberpro registers
38023 + */
38024 + unsigned char cap_mode1;
38025 + unsigned char cap_mode2;
38026 + unsigned char cap_miscctl;
38027 + unsigned char vfac1;
38028 + unsigned char vfac3;
38032 + * Our access methods.
38033 + */
38034 +#define cyberpro_writel(val,reg,dp) writel(val, (dp)->regs + (reg))
38035 +#define cyberpro_writew(val,reg,dp) writew(val, (dp)->regs + (reg))
38036 +#define cyberpro_writeb(val,reg,dp) writeb(val, (dp)->regs + (reg))
38038 +#define cyberpro_readb(reg,dp) readb((dp)->regs + (reg))
38040 +static inline void
38041 +cyberpro_grphw(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
38043 + cyberpro_writew((reg & 255) | val << 8, 0x3ce, dp);
38046 +static void cyberpro_grphw8(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
38048 + cyberpro_grphw(reg, val, dp);
38051 +static unsigned char cyberpro_grphr8(int reg, struct cyberpro_vidinfo *dp)
38053 + cyberpro_writeb(reg, 0x3ce, dp);
38054 + return cyberpro_readb(0x3cf, dp);
38057 +static void cyberpro_grphw16(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
38059 + cyberpro_grphw(reg, val, dp);
38060 + cyberpro_grphw(reg + 1, val >> 8, dp);
38063 +static void cyberpro_grphw24(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
38065 + cyberpro_grphw(reg, val, dp);
38066 + cyberpro_grphw(reg + 1, val >> 8, dp);
38067 + cyberpro_grphw(reg + 2, val >> 16, dp);
38070 +#if 0
38071 +static void
38072 +cyberpro_dbg_dump(void)
38074 + int i;
38075 + unsigned char idx[] =
38076 + { 0x30, 0x3e, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d,
38077 + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad };
38078 + printk(KERN_DEBUG);
38079 + for (i = 0; i < sizeof(idx); i++)
38080 + printk("%02x ", idx[i]);
38081 + printk("\n" KERN_DEBUG);
38082 + for (i = 0; i < sizeof(idx); i++)
38083 + printk("%02x ", cyberpro_grphr8(idx[i]));
38084 + printk("\n");
38086 +#endif
38089 + * On the NetWinder, we can put the SAA7111 to sleep by holding
38090 + * it in reset.
38092 + * Note: once we have initialised the SAA7111, we can't put it back to
38093 + * sleep and expect it to keep its settings. Maybe a better solution
38094 + * is to register/de-register the i2c bus in open/release?
38095 + */
38096 +static void
38097 +decoder_sleep(int sleep)
38099 +#ifdef CONFIG_ARCH_NETWINDER
38100 + extern spinlock_t gpio_lock;
38102 + spin_lock_irq(&gpio_lock);
38103 + cpld_modify(CPLD_7111_DISABLE, sleep ? CPLD_7111_DISABLE : 0);
38104 + spin_unlock_irq(&gpio_lock);
38106 + if (!sleep) {
38107 + /*
38108 + * wait 20ms for device to wake up
38109 + */
38110 + set_current_state(TASK_UNINTERRUPTIBLE);
38111 + schedule_timeout(HZ / 50);
38113 +#endif
38116 +/* -------------------------------- I2C support ---------------------------- */
38118 +#define I2C_DELAY 100
38120 +static void
38121 +cyberpro_i2c_setlines(struct i2c_bus *bus, int ctrl, int data)
38123 + struct cyberpro_vidinfo *dp = bus->data;
38124 + int v;
38126 + v = (ctrl ? EXT_LATCH2_I2C_CLKEN : 0x00) | (data ? EXT_LATCH2_I2C_DATEN : 0x00);
38127 + cyberpro_grphw8(EXT_LATCH2, v, dp);
38129 + udelay(I2C_DELAY);
38132 +static int
38133 +cyberpro_i2c_getdataline(struct i2c_bus *bus)
38135 + struct cyberpro_vidinfo *dp = bus->data;
38136 + unsigned long flags;
38137 + int v;
38139 + save_flags(flags);
38140 + cli();
38142 + v = cyberpro_grphr8(EXT_LATCH2, dp);
38144 + restore_flags(flags);
38146 + return v & EXT_LATCH2_I2C_DAT ? 1 : 0;
38149 +static void
38150 +cyberpro_i2c_attach(struct i2c_bus *bus, int id)
38152 + struct cyberpro_vidinfo *dp = bus->data;
38153 + int zero = 0;
38155 + if (id == I2C_DRIVERID_VIDEODECODER) {
38156 + __u16 norm = dp->norm;
38157 + i2c_control_device(bus, id, DECODER_SET_NORM, &norm);
38158 + i2c_control_device(bus, id, DECODER_SET_PICTURE, &dp->pic);
38159 + i2c_control_device(bus, id, DECODER_ENABLE_OUTPUT, &zero);
38161 + dp->decoder = 1;
38165 +static void
38166 +cyberpro_i2c_detach(struct i2c_bus *bus, int id)
38168 + struct cyberpro_vidinfo *dp = bus->data;
38170 + if (id == I2C_DRIVERID_VIDEODECODER)
38171 + dp->decoder = 0;
38174 +static struct i2c_bus cyberpro_i2c_bus = {
38175 + name: "",
38176 + id: I2C_BUSID_CYBER2000,
38177 + bus_lock: SPIN_LOCK_UNLOCKED,
38178 + attach_inform: cyberpro_i2c_attach,
38179 + detach_inform: cyberpro_i2c_detach,
38180 + i2c_setlines: cyberpro_i2c_setlines,
38181 + i2c_getdataline: cyberpro_i2c_getdataline,
38184 +/*------------------------- Extended Overlay Window -------------------------
38185 + * Initialise 1st overlay window (works)
38186 + */
38187 +static void
38188 +cyberpro_ext_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
38190 + wi->vid_fifo_ctl = 0xf87c;
38191 + wi->vid_fmt = EXT_VID_FMT_YUV422;
38192 + wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
38193 + EXT_VID_DISP_CTL1_NOCLIP;
38194 + wi->vid_fifo_ctl1 = EXT_VID_FIFO_CTL1_INTERLEAVE |
38195 + EXT_VID_FIFO_CTL1_OE_HIGH;
38196 + wi->vid_misc_ctl1 = 0;
38198 + cyberpro_grphw8 (EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
38199 + cyberpro_grphw16(EXT_DDA_X_INIT, 0x0800, dp);
38200 + cyberpro_grphw16(EXT_DDA_Y_INIT, 0x0800, dp);
38201 + cyberpro_grphw16(EXT_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
38202 + cyberpro_grphw8 (EXT_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
38206 + * Set the source parameters for the extended window
38207 + */
38208 +static void
38209 +cyberpro_ext_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
38211 + unsigned int phase, pitch;
38213 + pitch = (wi->src.width >> 2) & 0x0fff;
38214 + phase = (wi->src.width + 3) >> 2;
38216 + wi->vid_fmt &= ~7;
38217 + switch (wi->src.format) {
38218 + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
38219 + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
38220 + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
38221 + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
38222 + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
38225 + cyberpro_grphw24(EXT_MEM_START, wi->src.offset, dp);
38226 + cyberpro_grphw16(EXT_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
38227 + cyberpro_grphw8 (EXT_SRC_WIN_WIDTH, phase, dp);
38228 + cyberpro_grphw8 (EXT_VID_FMT, wi->vid_fmt, dp);
38232 + * Set overlay1 window
38233 + */
38234 +static void
38235 +cyberpro_ext_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
38237 + unsigned int xscale, yscale;
38238 + unsigned int xoff, yoff;
38240 + /*
38241 + * Note: the offset does not appear to be influenced by
38242 + * hardware scrolling.
38243 + */
38244 + xoff = yoff = 0;
38246 + xoff += wi->dst.x;
38247 + yoff += wi->dst.y;
38249 + xscale = wi->src.width;
38251 + if (wi->dst.width >= wi->src.width * 2) {
38252 + wi->vid_fmt |= EXT_VID_FMT_DBL_H_PIX;
38253 + xscale *= 2;
38254 + } else {
38255 + wi->vid_fmt &= ~EXT_VID_FMT_DBL_H_PIX;
38258 + xscale = ((xscale - /*2*/0) * 4096) / wi->dst.width;
38259 + yscale = ((wi->src.height - /*2*/0) * 4096) / wi->dst.height;
38261 + cyberpro_grphw16(EXT_X_START, xoff, dp);
38262 + cyberpro_grphw16(EXT_X_END, xoff + wi->dst.width, dp);
38263 + cyberpro_grphw16(EXT_Y_START, yoff, dp);
38264 + cyberpro_grphw16(EXT_Y_END, yoff + wi->dst.height, dp);
38265 + cyberpro_grphw24(EXT_COLOUR_COMPARE, wi->dst.chromakey, dp);
38266 + cyberpro_grphw16(EXT_DDA_X_INC, xscale, dp);
38267 + cyberpro_grphw16(EXT_DDA_Y_INC, yscale, dp);
38268 + cyberpro_grphw8(EXT_VID_FMT, wi->vid_fmt, dp);
38270 + if (wi->dst.flags & VIDEO_WINDOW_CHROMAKEY)
38271 + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_IGNORE_CCOMP;
38272 + else
38273 + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_IGNORE_CCOMP;
38277 + * Enable or disable the 1st overlay window. Note that for anything
38278 + * useful to be displayed, we must have capture enabled.
38279 + */
38280 +static void
38281 +cyberpro_ext_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
38283 + if (on)
38284 + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
38285 + else
38286 + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
38288 + cyberpro_grphw8(EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
38291 +/*------------------------------- V2 Overlay Window -------------------------
38292 + * Initialise 2nd overlay window (guesswork)
38293 + */
38294 +static void
38295 +cyberpro_v2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
38297 + wi->vid_fifo_ctl = 0xf87c;
38298 + wi->vid_fmt = EXT_VID_FMT_YUV422;
38299 + wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
38300 + EXT_VID_DISP_CTL1_NOCLIP;
38301 + wi->vid_fifo_ctl1 = 0x06;
38302 + wi->vid_misc_ctl1 = 0;
38304 + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
38305 + cyberpro_grphw8 (Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
38306 + /* No DDA init values */
38307 + cyberpro_grphw16(Y_V2_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
38308 + cyberpro_grphw8 (Y_V2_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
38312 + * Set the source parameters for the v2 window
38313 + */
38314 +static void
38315 +cyberpro_v2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
38317 + unsigned int phase, pitch;
38319 + pitch = (wi->src.width >> 2) & 0x0fff;
38320 + phase = (wi->src.width + 3) >> 2;
38322 + wi->vid_fmt &= ~7;
38323 + switch (wi->src.format) {
38324 + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
38325 + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
38326 + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
38327 + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
38328 + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
38331 + cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
38332 + cyberpro_grphw24(X_V2_VID_MEM_START, wi->src.offset, dp);
38333 + cyberpro_grphw16(X_V2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
38334 + cyberpro_grphw8 (X_V2_VID_SRC_WIN_WIDTH, phase, dp);
38336 + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
38337 + cyberpro_grphw8(Y_V2_VID_FMT, wi->vid_fmt, dp);
38341 + * Set v2 window
38342 + */
38343 +static void
38344 +cyberpro_v2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
38346 + unsigned int xscale, yscale;
38347 + unsigned int xoff, yoff;
38349 + /*
38350 + * Note: the offset does not appear to be influenced by
38351 + * hardware scrolling.
38352 + */
38353 + xoff = yoff = 0;
38355 + xoff += wi->dst.x;
38356 + yoff += wi->dst.y;
38358 + xscale = (wi->src.width * 4096) / wi->dst.width;
38359 + yscale = (wi->src.height * 4096) / wi->dst.height;
38361 + cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
38362 + cyberpro_grphw16(X_V2_X_START, xoff, dp);
38363 + cyberpro_grphw16(X_V2_X_END, xoff + wi->dst.width, dp);
38364 + cyberpro_grphw16(X_V2_Y_START, yoff, dp);
38365 + cyberpro_grphw16(X_V2_Y_END, yoff + wi->dst.height, dp);
38367 + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
38368 + cyberpro_grphw16(Y_V2_DDA_X_INC, xscale, dp);
38369 + cyberpro_grphw16(Y_V2_DDA_Y_INC, yscale, dp);
38373 + * Enable or disable the 2nd overlay window. Note that for anything
38374 + * useful to be displayed, we must have capture enabled.
38375 + */
38376 +static void
38377 +cyberpro_v2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
38379 + if (on)
38380 + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
38381 + else
38382 + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
38384 + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
38385 + cyberpro_grphw8(Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
38388 +/*--------------------------- X2 Overlay Window -----------------------------
38389 + * Initialise 3rd overlay window (guesswork)
38390 + */
38391 +static void
38392 +cyberpro_x2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
38394 + wi->vid_fmt = EXT_VID_FMT_YUV422;
38395 + wi->vid_disp_ctl1 = 0x40;
38396 + wi->vid_misc_ctl1 = 0;
38398 + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
38399 + cyberpro_grphw8 (K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
38400 + cyberpro_grphw16(K_X2_DDA_X_INIT, 0x0800, dp);
38401 + cyberpro_grphw16(K_X2_DDA_Y_INIT, 0x0800, dp);
38405 + * Set the source parameters for the x2 window
38406 + */
38407 +static void
38408 +cyberpro_x2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
38410 + unsigned int phase, pitch;
38412 + pitch = (wi->src.width >> 2) & 0x0fff;
38413 + phase = (wi->src.width + 3) >> 2;
38415 + wi->vid_fmt &= ~7;
38416 + switch (wi->src.format) {
38417 + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
38418 + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
38419 + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
38420 + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
38421 + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
38424 + cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
38425 + cyberpro_grphw24(J_X2_VID_MEM_START, wi->src.offset, dp);
38426 + cyberpro_grphw16(J_X2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
38427 + cyberpro_grphw8 (J_X2_VID_SRC_WIN_WIDTH, phase, dp);
38429 + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
38430 + cyberpro_grphw8(K_X2_VID_FMT, wi->vid_fmt, dp);
38434 + * Set x2 window
38435 + */
38436 +static void
38437 +cyberpro_x2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
38439 + unsigned int xscale, yscale;
38440 + unsigned int xoff, yoff;
38442 + /*
38443 + * Note: the offset does not appear to be influenced by
38444 + * hardware scrolling.
38445 + */
38446 + xoff = yoff = 0;
38448 + xoff += wi->dst.x;
38449 + yoff += wi->dst.y;
38451 + xscale = (wi->src.width * 4096) / wi->dst.width;
38452 + yscale = (wi->src.height * 4096) / wi->dst.height;
38454 + cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
38455 + cyberpro_grphw16(J_X2_X_START, xoff, dp);
38456 + cyberpro_grphw16(J_X2_X_END, xoff + wi->dst.width, dp);
38457 + cyberpro_grphw16(J_X2_Y_START, yoff, dp);
38458 + cyberpro_grphw16(J_X2_Y_END, yoff + wi->dst.height, dp);
38460 + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
38461 + cyberpro_grphw16(K_X2_DDA_X_INC, xscale, dp);
38462 + cyberpro_grphw16(K_X2_DDA_Y_INC, yscale, dp);
38466 + * Enable or disable the 3rd overlay window. Note that for anything
38467 + * useful to be displayed, we must have capture enabled.
38468 + */
38469 +static void
38470 +cyberpro_x2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
38472 + if (on)
38473 + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
38474 + else
38475 + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
38477 + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
38478 + cyberpro_grphw8(K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
38481 +/* ------------------------------------------------------------------------- */
38483 +#if 0
38484 +static void reset_seq(struct cyberpro_vidinfo *dp)
38486 + unsigned char ext_mem_ctl = cyberpro_grphr8(0x70, dp);
38488 + cyberpro_grphw8(ext_mem_ctl | 0x80, 0x70, dp);
38489 + cyberpro_grphw8(ext_mem_ctl, 0x70, dp);
38491 +#endif
38493 +#ifdef USE_MMAP
38495 + * Buffer support
38496 + */
38497 +static int
38498 +cyberpro_alloc_frame_buffer(struct cyberpro_vidinfo *dp,
38499 + struct framebuf *frame)
38501 + unsigned long addr;
38502 + void *buffer;
38503 + int pgidx;
38505 + if (frame->buffer)
38506 + return 0;
38508 + /*
38509 + * Allocate frame buffer
38510 + */
38511 + buffer = vmalloc(NR_PAGES * PAGE_SIZE);
38513 + if (frame->buffer) {
38514 + vfree(buffer);
38515 + return 0;
38518 + if (!buffer)
38519 + return -ENOMEM;
38521 + printk("Buffer allocated @ %p [", buffer);
38523 + frame->buffer = buffer;
38524 + frame->dbg = 1;
38526 + /*
38527 + * Don't leak information from the kernel.
38528 + */
38529 + memset(buffer, 0x5a, NR_PAGES * PAGE_SIZE);
38531 + /*
38532 + * Now, reserve all the pages, and calculate
38533 + * each pages' bus address.
38534 + */
38535 + addr = (unsigned long)buffer;
38536 + for (pgidx = 0; pgidx < NR_PAGES; pgidx++, addr += PAGE_SIZE) {
38537 + struct page *page;
38538 + pgd_t *pgd;
38539 + pmd_t *pmd;
38540 + pte_t *pte;
38542 + /*
38543 + * The page should be present. If not,
38544 + * vmalloc has gone nuts.
38545 + */
38546 + pgd = pgd_offset_k(addr);
38547 + if (pgd_none(*pgd))
38548 + BUG();
38549 + pmd = pmd_offset(pgd, addr);
38550 + if (pmd_none(*pmd))
38551 + BUG();
38552 + pte = pte_offset(pmd, addr);
38553 + if (!pte_present(*pte))
38554 + BUG();
38556 + page = pte_page(*pte);
38558 + frame->bus_addr[pgidx] = virt_to_bus((void *)page_address(page));
38559 + frame->pages[pgidx] = page;
38560 + SetPageReserved(page);
38562 + printk("%08lx (%08lx) ", page_address(page), frame->bus_addr[pgidx]);
38564 + printk("\n");
38566 + return 0;
38569 +static void
38570 +cyberpro_frames_free_one(struct cyberpro_vidinfo *dp, struct framebuf *frame)
38572 + void *buffer;
38573 + int pgidx;
38575 + frame->status = FRAME_FREE;
38576 + buffer = frame->buffer;
38577 + frame->buffer = NULL;
38579 + if (buffer) {
38580 + for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
38581 + frame->bus_addr[pgidx] = 0;
38582 + ClearPageReserved(frame->pages[pgidx]);
38583 + frame->pages[pgidx] = NULL;
38585 + vfree(buffer);
38589 +static void
38590 +cyberpro_busmaster_frame(struct cyberpro_vidinfo *dp, struct framebuf *frame)
38592 + unsigned long bus_addr;
38594 + bus_addr = frame->bus_addr[dp->bm_index];
38596 + if (frame->dbg) {
38597 + printk("Frame%d: %06x -> %08lx\n",
38598 + dp->frame_idx,
38599 + dp->bm_offset,
38600 + bus_addr);
38603 + cyber2000_outw(dp->bm_offset, BM_VID_ADDR_LOW);
38604 + cyber2000_outw(dp->bm_offset >> 16, BM_VID_ADDR_HIGH);
38606 + cyber2000_outw(bus_addr, BM_ADDRESS_LOW);
38607 + cyber2000_outw(bus_addr >> 16, BM_ADDRESS_HIGH);
38609 + /*
38610 + * One page-full only
38611 + */
38612 + cyber2000_outw(1023, BM_LENGTH);
38614 + /*
38615 + * Load length
38616 + */
38617 + cyber2000_outw(BM_CONTROL_INIT, BM_CONTROL);
38619 + /*
38620 + * Enable transfer
38621 + */
38622 + cyber2000_outw(BM_CONTROL_ENABLE|BM_CONTROL_IRQEN, BM_CONTROL);
38624 + dp->bm_offset += 1024;
38625 + dp->bm_index += 1;
38628 +static void cyberpro_busmaster_interrupt(struct cyberpro_vidinfo *dp)
38630 + struct framebuf *frame = dp->frame + dp->frame_idx;
38632 + /*
38633 + * Disable Busmaster operations
38634 + */
38635 + cyber2000_outw(0, BM_CONTROL);
38637 + if (frame->status == FRAME_GRABBING) {
38638 + /*
38639 + * We are still grabbing this frame to system
38640 + * memory. Transfer next page if there are
38641 + * more, or else flag this frame as complete.
38642 + */
38643 + if (dp->bm_index < NR_PAGES)
38644 + cyberpro_busmaster_frame(dp);
38645 + else {
38646 + unsigned int idx;
38648 + frame->status = FRAME_DONE;
38649 + frame->dbg = 0;
38651 + idx = dp->frame_idx + 1;
38652 + if (idx >= NR_FRAMES)
38653 + idx = 0;
38655 + dp->frame_idx = idx;
38657 + wake_up(&dp->frame_wait);
38662 +static void cyberpro_frames_vbl(struct cyberpro_vidinfo *dp, unsigned int stat)
38664 + struct framebuf *frame = dp->frame + dp->frame_idx;
38666 + /*
38667 + * No point capturing frames if the grabber isn't active.
38668 + */
38669 + if (stat & EXT_ROM_UCB4GH_FREEZE)
38670 + return;
38672 + /*
38673 + * If the next buffer is ready for grabbing,
38674 + * set up the bus master registers for the
38675 + * transfer.
38676 + */
38677 + if (frame->status == FRAME_WAITING) {
38678 + frame->status = FRAME_GRABBING;
38680 + dp->bm_offset = dp->cap_mem_offset;
38681 + dp->bm_index = 0;
38683 + cyberpro_busmaster_frame(dp, frame);
38687 +static void __init cyberpro_frames_init(struct cyberpro_vidinfo *dp)
38689 + unsigned int offset, maxsize;
38690 + int i;
38692 + init_waitqueue_head(&dp->frame_wait);
38694 + maxsize = 2 * dp->cap.maxwidth * dp->cap.maxheight;
38695 + dp->frame_size = PAGE_ALIGN(maxsize);
38696 + dp->frame_idx = 0;
38698 + for (i = offset = 0; i < NR_FRAMES; i++) {
38699 + dp->frame[i].offset = offset;
38700 + dp->frame[i].status = FRAME_FREE;
38701 + offset += dp->frame_size;
38705 +static void cyberpro_frames_free(struct cyberpro_vidinfo *dp)
38707 + int i;
38709 + dp->mmaped = 0;
38711 + /*
38712 + * Free all frame buffers
38713 + */
38714 + for (i = 0; i < NR_FRAMES; i++)
38715 + cyberpro_frames_free_one(dp, dp->frame + i);
38718 +#else
38719 +#define cyberpro_frames_vbl(dp,stat) do { } while (0)
38720 +#define cyberpro_frames_init(dp) do { } while (0)
38721 +#define cyberpro_frames_free(dp) do { } while (0)
38722 +#endif
38725 + * CyberPro Interrupts
38726 + * -------------------
38728 + * We don't really know how to signal an IRQ clear to the chip. However,
38729 + * disabling and re-enabling the capture interrupt enable seems to do what
38730 + * we want.
38731 + */
38732 +static void cyberpro_interrupt(int nr, void *dev_id, struct pt_regs *regs)
38734 + struct cyberpro_vidinfo *dp = dev_id;
38735 + unsigned char old_grphidx;
38736 + unsigned int status;
38738 + /*
38739 + * Save old graphics index register
38740 + */
38741 + old_grphidx = cyberpro_readb(0x3ce, dp);
38743 + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
38745 + /*
38746 + * Was it due to the Capture VSYNC?
38747 + */
38748 + if (status & EXT_ROM_UCB4GH_INTSTAT) {
38749 + /*
38750 + * Frob the IRQ enable bit to drop the request.
38751 + */
38752 + cyberpro_grphw8(VFAC_CTL3, dp->vfac3 & ~VFAC_CTL3_CAP_IRQ, dp);
38753 + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
38755 + cyberpro_frames_vbl(dp, status);
38756 + wake_up(&dp->vbl_wait);
38759 + /*
38760 + * Restore graphics controller index
38761 + */
38762 + cyberpro_writeb(old_grphidx, 0x3ce, dp);
38764 +#ifdef USE_MMAP
38765 + /*
38766 + * Do Bus-Master IRQ stuff
38767 + */
38768 + if (cyber2000_inb(BM_CONTROL) & (1 << 7))
38769 + cyberpro_busmaster_interrupt(dp);
38770 +#endif
38773 +static void cyberpro_capture(struct cyberpro_vidinfo *dp, int on)
38775 + DECLARE_WAITQUEUE(wait, current);
38776 + unsigned int status;
38778 + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
38780 + add_wait_queue(&dp->vbl_wait, &wait);
38781 + set_current_state(TASK_UNINTERRUPTIBLE);
38783 + if (!!on ^ !(status & EXT_ROM_UCB4GH_FREEZE)) {
38784 + if (on) {
38785 + schedule_timeout(40 * HZ / 1000);
38786 + dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
38787 + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
38789 + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
38790 + } else {
38791 + dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
38792 + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
38794 + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
38795 + if (!(status & EXT_ROM_UCB4GH_FREEZE))
38796 + schedule_timeout(40 * HZ / 1000);
38800 + current->state = TASK_RUNNING;
38801 + remove_wait_queue(&dp->vbl_wait, &wait);
38804 +static void cyberpro_capture_one(struct cyberpro_vidinfo *dp)
38806 + struct task_struct *tsk = current;
38807 + DECLARE_WAITQUEUE(wait, tsk);
38808 + unsigned int status;
38809 + unsigned long policy, rt_priority;
38811 + policy = tsk->policy;
38812 + rt_priority = tsk->rt_priority;
38814 + tsk->policy = SCHED_FIFO;
38815 + tsk->rt_priority = 1;
38817 + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
38819 + add_wait_queue(&dp->vbl_wait, &wait);
38820 + set_current_state(TASK_UNINTERRUPTIBLE);
38822 + schedule_timeout(40 * HZ / 1000);
38823 + dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
38824 + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
38826 + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
38827 + set_current_state(TASK_UNINTERRUPTIBLE);
38828 + schedule_timeout(40 * HZ / 1000);
38829 + set_current_state(TASK_UNINTERRUPTIBLE);
38830 + schedule_timeout(40 * HZ / 1000);
38832 + dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
38833 + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
38835 + set_current_state(TASK_UNINTERRUPTIBLE);
38836 + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
38838 + current->state = TASK_RUNNING;
38839 + remove_wait_queue(&dp->vbl_wait, &wait);
38841 + tsk->policy = policy;
38842 + tsk->rt_priority = rt_priority;
38845 +static void cyberpro_capture_set_win(struct cyberpro_vidinfo *dp)
38847 + unsigned int xstart, xend, ystart, yend;
38849 + xstart = 4 + dp->capt.x;
38850 + xend = xstart + dp->capt.width;
38852 + if (dp->cap_mode1 & EXT_CAP_MODE1_8BIT) {
38853 + /* 8-bit capture */
38854 + xstart *= 2;
38855 + xend *= 2;
38858 + xstart -= 1;
38859 + xend -= 1;
38861 + ystart = 18 + dp->capt.y;
38862 + yend = ystart + dp->capt.height / 2;
38864 + cyberpro_grphw16(CAP_X_START, xstart, dp);
38865 + cyberpro_grphw16(CAP_X_END, xend + 1, dp);
38866 + cyberpro_grphw16(CAP_Y_START, ystart, dp);
38867 + cyberpro_grphw16(CAP_Y_END, yend + 2, dp);
38869 + /*
38870 + * This should take account of capt.decimation
38871 + */
38872 + cyberpro_grphw16(CAP_DDA_X_INIT, 0x0800, dp);
38873 + cyberpro_grphw16(CAP_DDA_X_INC, 0x1000, dp);
38874 + cyberpro_grphw16(CAP_DDA_Y_INIT, 0x0800, dp);
38875 + cyberpro_grphw16(CAP_DDA_Y_INC, 0x1000, dp);
38877 + cyberpro_grphw8(CAP_PITCH, dp->capt.width >> 2, dp);
38880 +static void cyberpro_set_interlace(struct cyberpro_vidinfo *dp)
38882 + /*
38883 + * set interlace mode
38884 + */
38885 + if (dp->interlace) {
38886 + dp->vfac3 |= VFAC_CTL3_CAP_INTERLACE;
38887 + dp->cap_miscctl &= ~CAP_CTL_MISC_ODDEVEN;
38888 + dp->ovl->src.height = dp->capt.height;
38889 + } else {
38890 + dp->vfac3 &= ~VFAC_CTL3_CAP_INTERLACE;
38891 + dp->cap_miscctl |= CAP_CTL_MISC_ODDEVEN;
38892 + dp->ovl->src.height = dp->capt.height / 2;
38895 + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
38896 + cyberpro_grphw8(CAP_CTL_MISC, dp->cap_miscctl, dp);
38898 + dp->ovl->set_src(dp, dp->ovl);
38900 + if (dp->win_set)
38901 + dp->ovl->set_win(dp, dp->ovl);
38905 + * Calculate and set the address of the capture buffer. Note we
38906 + * also update the extended memory buffer for the overlay window.
38908 + * base: phys base address of display
38909 + * width: pixel width of display
38910 + * height: height of display
38911 + * depth: depth of display (8/16/24)
38912 + * bytesperline: number of bytes on a line
38914 + * We place the capture buffer 16K after the screen.
38915 + */
38916 +static int
38917 +cyberpro_set_buffer(struct cyberpro_vidinfo *dp, struct video_buffer *b)
38919 + unsigned long screensize, maxbufsz;
38921 + if (b->height <= 0 || b->width <= 0 || b->bytesperline <= 0)
38922 + return -EINVAL;
38924 + maxbufsz = dp->cap.maxwidth * dp->cap.maxheight * 2;
38925 + screensize = b->height * b->bytesperline + 16384;
38927 + if ((screensize + maxbufsz) >= dp->info.fb_size)
38928 + return -EINVAL;
38930 + dp->buf.base = b->base;
38931 + dp->buf.width = b->width;
38932 + dp->buf.height = b->height;
38933 + dp->buf.depth = b->depth;
38934 + dp->buf.bytesperline = b->bytesperline;
38935 + dp->cap_mem_offset = screensize >> 2;
38937 + cyberpro_grphw24(CAP_MEM_START, dp->cap_mem_offset, dp);
38939 + /*
38940 + * Setup the overlay source information.
38941 + */
38942 + dp->ovl->src.offset = dp->cap_mem_offset;
38943 + dp->ovl->set_src(dp, dp->ovl);
38945 + return 0;
38948 +static void cyberpro_hw_init(struct cyberpro_vidinfo *dp)
38950 + unsigned char old;
38952 + /*
38953 + * Enable access to bus-master registers
38954 + */
38955 + dp->info.enable_extregs(dp->info.info);
38957 + dp->vfac1 = VFAC_CTL1_PHILIPS |
38958 + VFAC_CTL1_FREEZE_CAPTURE |
38959 + VFAC_CTL1_FREEZE_CAPTURE_SYNC;
38960 + dp->vfac3 = VFAC_CTL3_CAP_IRQ;
38962 + dp->cap_miscctl = CAP_CTL_MISC_DISPUSED |
38963 + CAP_CTL_MISC_SYNCTZOR |
38964 + CAP_CTL_MISC_SYNCTZHIGH;
38966 + /*
38967 + * Setup bus-master mode
38968 + */
38969 + cyberpro_grphw8(BM_CTRL1, 0x88, dp);
38970 + cyberpro_grphw8(PCI_BM_CTL, PCI_BM_CTL_ENABLE, dp);
38971 + cyberpro_grphw8(BM_CTRL0, 0x44, dp);
38972 + cyberpro_grphw8(BM_CTRL1, 0x84, dp);
38974 + cyberpro_grphw24(CAP_MEM_START, 0, dp);
38976 + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
38977 + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
38978 + cyberpro_grphw8(VFAC_CTL2, 0, dp);
38980 + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
38981 + cyberpro_grphw8(EXT_TV_CTL, 0x80, dp);
38983 + cyberpro_grphw8(EXT_CAP_CTL1, 0x3f, dp); /* disable PIP */
38984 + cyberpro_grphw8(EXT_CAP_CTL2, 0xc0 | EXT_CAP_CTL2_ODDFRAMEIRQ, dp);
38986 + /*
38987 + * Configure capture mode to match the
38988 + * external video processor format
38989 + */
38990 + cyberpro_grphw8(EXT_CAP_MODE1, dp->cap_mode1, dp);
38991 + cyberpro_grphw8(EXT_CAP_MODE2, dp->cap_mode2, dp);
38993 + /* setup overlay */
38994 + cyberpro_grphw16(EXT_FIFO_CTL, 0x1010, dp);
38995 +// cyberpro_grphw16(EXT_FIFO_CTL, 0x1b0f, dp);
38997 + /*
38998 + * Always reset the capture parameters on each open.
38999 + */
39000 + dp->capt.x = 0;
39001 + dp->capt.y = 0;
39002 + dp->capt.width = dp->cap.maxwidth;
39003 + dp->capt.height = dp->cap.maxheight;
39004 + dp->capt.decimation = 0;
39005 + dp->capt.flags = 0;
39007 + cyberpro_capture_set_win(dp);
39009 + /*
39010 + * Enable VAFC
39011 + */
39012 + old = cyberpro_grphr8(EXT_LATCH1, dp);
39013 + cyberpro_grphw8(EXT_LATCH1, old | EXT_LATCH1_VAFC_EN, dp);
39015 + /*
39016 + * Enable capture (we hope that VSYNC=1)
39017 + */
39018 + dp->vfac1 |= VFAC_CTL1_CAPTURE;
39019 + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
39021 + /*
39022 + * The overlay source format is always the
39023 + * same as the capture stream format.
39024 + */
39025 + dp->ovl->src.width = dp->capt.width;
39026 + dp->ovl->src.height = dp->capt.height;
39027 + dp->ovl->src.format = dp->stream_fmt;
39029 + /*
39030 + * Initialise the overlay windows
39031 + */
39032 + dp->ext.init(dp, &dp->ext);
39033 + dp->v2.init(dp, &dp->v2);
39034 + dp->x2.init(dp, &dp->x2);
39037 +static void cyberpro_deinit(struct cyberpro_vidinfo *dp)
39039 + unsigned char old;
39041 + /*
39042 + * Stop any bus-master activity
39043 + */
39044 + cyberpro_writew(0, BM_CONTROL, dp);
39046 + /*
39047 + * Shut down overlay
39048 + */
39049 + if (dp->ovl_active)
39050 + dp->ovl->ctl(dp, dp->ovl, 0);
39051 + dp->ovl_active = 0;
39053 + /*
39054 + * Shut down capture
39055 + */
39056 + if (dp->cap_active)
39057 + cyberpro_capture(dp, 0);
39058 + dp->cap_active = 0;
39060 + /*
39061 + * Disable all capture
39062 + */
39063 + cyberpro_grphw8(VFAC_CTL1, 0, dp);
39065 + /*
39066 + * Disable VAFC
39067 + */
39068 + old = cyberpro_grphr8(EXT_LATCH1, dp);
39069 + cyberpro_grphw8(EXT_LATCH1, old & ~EXT_LATCH1_VAFC_EN, dp);
39071 + /*
39072 + * Disable interrupt (this allows it to float)
39073 + */
39074 + dp->vfac3 &= ~VFAC_CTL3_CAP_IRQ;
39075 + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
39077 + /*
39078 + * Switch off bus-master mode
39079 + */
39080 + cyberpro_grphw8(PCI_BM_CTL, 0, dp);
39082 + /*
39083 + * Disable access to bus-master registers
39084 + */
39085 + dp->info.disable_extregs(dp->info.info);
39088 +static int cyberpro_grabber_open(struct video_device *dev, int flags)
39090 + struct cyberpro_vidinfo *dp = dev->priv;
39091 + int ret, one = 1;
39093 + MOD_INC_USE_COUNT;
39095 + ret = -EBUSY;
39096 + if (flags || dp->users)
39097 + goto out;
39099 + dp->users += 1;
39101 + if (dp->users == 1) {
39102 + ret = request_irq(dp->irq, cyberpro_interrupt, SA_SHIRQ,
39103 + dp->info.dev_name, dp);
39105 + if (ret) {
39106 + dp->users -= 1;
39107 + goto out;
39110 + /*
39111 + * Initialise the VGA chip
39112 + */
39113 + cyberpro_hw_init(dp);
39115 + /*
39116 + * Enable the IRQ. This allows the IRQ to work as expected
39117 + * even if the IRQ line is missing the pull-up resistor.
39118 + */
39119 + enable_irq(dp->irq);
39121 + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
39122 + DECODER_ENABLE_OUTPUT, &one);
39125 + ret = 0;
39126 +out:
39127 + if (ret)
39128 + MOD_DEC_USE_COUNT;
39129 + return ret;
39132 +static void cyberpro_grabber_close(struct video_device *dev)
39134 + struct cyberpro_vidinfo *dp = dev->priv;
39136 + if (dp->users == 1) {
39137 + int zero = 0;
39139 + /*
39140 + * Disable the IRQ. This prevents problems with missing
39141 + * pull-up resistors on the PCI interrupt line.
39142 + */
39143 + disable_irq(dp->irq);
39145 + cyberpro_frames_free(dp);
39147 + /*
39148 + * Turn off the SAA7111 decoder
39149 + */
39150 + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
39151 + DECODER_ENABLE_OUTPUT, &zero);
39153 + /*
39154 + * Disable grabber
39155 + */
39156 + cyberpro_deinit(dp);
39158 + free_irq(dp->irq, dp);
39161 + dp->users -= 1;
39163 + MOD_DEC_USE_COUNT;
39167 + * Our general plan here is:
39168 + * 1. Set the CyberPro to perform a BM-DMA of one frame to this memory
39169 + * 2. Copy the frame to the userspace
39171 + * However, BM-DMA seems to be unreliable at the moment, especially on
39172 + * rev. 4 NetWinders.
39173 + */
39174 +static long
39175 +cyberpro_grabber_read(struct video_device *dev, char *buf,
39176 + unsigned long count, int noblock)
39178 + struct cyberpro_vidinfo *dp = dev->priv;
39179 + int ret = -EINVAL;
39181 +#ifdef USE_MMIO
39182 + unsigned long maxbufsz = dp->capt.width * dp->capt.height * 2;
39183 + char *disp = dp->info.fb + (dp->cap_mem_offset << 2);
39185 + /*
39186 + * If the buffer is mmap()'d, we shouldn't be using read()
39187 + */
39188 + if (dp->mmaped)
39189 + return -EINVAL;
39191 + if (count > maxbufsz)
39192 + count = maxbufsz;
39194 + if (dp->cap_active)
39195 + cyberpro_capture(dp, 0);
39196 + else
39197 + cyberpro_capture_one(dp);
39199 + ret = (int)count;
39200 + if (copy_to_user(buf, disp, count))
39201 + ret = -EFAULT;
39203 + /*
39204 + * unfreeze capture
39205 + */
39206 + if (dp->cap_active)
39207 + cyberpro_capture(dp, 1);
39208 +#endif
39210 + return ret;
39214 + * We don't support writing to the grabber
39215 + * (In theory, we could allow writing to a separate region of VGA memory,
39216 + * and display this using the second overlay window. This would allow us
39217 + * to do video conferencing for example).
39218 + */
39219 +static long
39220 +cyberpro_grabber_write(struct video_device *dev, const char *buf,
39221 + unsigned long count, int noblock)
39223 + return -EINVAL;
39226 +static int
39227 +cyberpro_grabber_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
39229 + struct cyberpro_vidinfo *dp = dev->priv;
39231 + switch (cmd) {
39232 + case VIDIOCGCAP:
39233 + return copy_to_user(arg, &dp->cap, sizeof(dp->cap))
39234 + ? -EFAULT : 0;
39236 + case VIDIOCGCHAN:
39238 + struct video_channel chan;
39240 + chan.channel = 0;
39241 + strcpy(chan.name, "Composite");
39242 + chan.tuners = 0;
39243 + chan.flags = 0;
39244 + chan.type = VIDEO_TYPE_CAMERA;
39245 + chan.norm = dp->norm;
39247 + return copy_to_user(arg, &chan, sizeof(chan)) ? -EFAULT : 0;
39250 + case VIDIOCGPICT:
39251 + return copy_to_user(arg, &dp->pic, sizeof(dp->pic))
39252 + ? -EINVAL : 0;
39254 + case VIDIOCGWIN:
39256 + struct video_window win;
39258 + win.x = dp->ovl->dst.x;
39259 + win.y = dp->ovl->dst.y;
39260 + win.width = dp->ovl->dst.width;
39261 + win.height = dp->ovl->dst.height;
39262 + win.chromakey = dp->ovl->dst.chromakey;
39263 + win.flags = VIDEO_WINDOW_CHROMAKEY |
39264 + (dp->interlace ? VIDEO_WINDOW_INTERLACE : 0);
39265 + win.clips = NULL;
39266 + win.clipcount = 0;
39268 + return copy_to_user(arg, &win, sizeof(win))
39269 + ? -EINVAL : 0;
39272 + case VIDIOCGFBUF:
39273 + return copy_to_user(arg, &dp->buf, sizeof(dp->buf))
39274 + ? -EINVAL : 0;
39276 + case VIDIOCGUNIT:
39278 + struct video_unit unit;
39280 + unit.video = dev->minor;
39281 + unit.vbi = VIDEO_NO_UNIT;
39282 + unit.radio = VIDEO_NO_UNIT;
39283 + unit.audio = VIDEO_NO_UNIT;
39284 + unit.teletext = VIDEO_NO_UNIT;
39286 + return copy_to_user(arg, &unit, sizeof(unit))
39287 + ? -EINVAL : 0;
39290 + case VIDIOCGCAPTURE:
39291 + return copy_to_user(arg, &dp->capt, sizeof(dp->capt))
39292 + ? -EFAULT : 0;
39294 + case VIDIOCSCHAN:
39296 + struct video_decoder_capability vdc;
39297 + struct video_channel v;
39298 + int ok;
39300 + if (copy_from_user(&v, arg, sizeof(v)))
39301 + return -EFAULT;
39303 + if (v.channel != 0)
39304 + return -EINVAL;
39306 + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
39307 + DECODER_GET_CAPABILITIES, &vdc);
39309 + switch (v.norm) {
39310 + case VIDEO_MODE_PAL:
39311 + ok = vdc.flags & VIDEO_DECODER_PAL;
39312 + break;
39313 + case VIDEO_MODE_NTSC:
39314 + ok = vdc.flags & VIDEO_DECODER_NTSC;
39315 + break;
39316 + case VIDEO_MODE_AUTO:
39317 + ok = vdc.flags & VIDEO_DECODER_AUTO;
39318 + break;
39319 + default:
39320 + ok = 0;
39322 + if (!ok)
39323 + return -EINVAL;
39325 + dp->norm = v.norm;
39327 + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
39328 + DECODER_SET_NORM, &v.norm);
39330 + return 0;
39333 + case VIDIOCSPICT:
39335 + struct video_picture p;
39337 + if (copy_from_user(&p, arg, sizeof(p)))
39338 + return -EFAULT;
39340 + if (p.palette != dp->stream_fmt ||
39341 + p.depth != 8)
39342 + return -EINVAL;
39344 + dp->pic = p;
39346 + /* p.depth sets the capture depth */
39347 + /* p.palette sets the capture palette */
39349 + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
39350 + DECODER_SET_PICTURE, &p);
39352 + return 0;
39355 + case VIDIOCSWIN: /* set the size & position of the overlay window */
39357 + struct video_window w;
39358 + int diff;
39360 + if (!dp->buf_set)
39361 + return -EINVAL;
39363 + if (copy_from_user(&w, arg, sizeof(w)))
39364 + return -EFAULT;
39366 + if (w.clipcount)
39367 + return -EINVAL;
39369 + /*
39370 + * Bound the overlay window by the size of the screen
39371 + */
39372 + if (w.x < 0)
39373 + w.x = 0;
39374 + if (w.y < 0)
39375 + w.y = 0;
39377 + if (w.x > dp->buf.width)
39378 + w.x = dp->buf.width;
39379 + if (w.y > dp->buf.height)
39380 + w.y = dp->buf.height;
39382 + if (w.width < dp->capt.width)
39383 + w.width = dp->capt.width;
39384 + if (w.height < dp->capt.height)
39385 + w.height = dp->capt.height;
39387 + if (w.x + w.width > dp->buf.width)
39388 + w.width = dp->buf.width - w.x;
39389 + if (w.y + w.height > dp->buf.height)
39390 + w.height = dp->buf.height - w.y;
39392 + /*
39393 + * We've tried to make the values fit, but
39394 + * they just won't.
39395 + */
39396 + if (w.width < dp->capt.width || w.height < dp->capt.height)
39397 + return -EINVAL;
39399 + diff = dp->ovl->dst.x != w.x ||
39400 + dp->ovl->dst.y != w.y ||
39401 + dp->ovl->dst.width != w.width ||
39402 + dp->ovl->dst.height != w.height ||
39403 + dp->ovl->dst.chromakey != w.chromakey ||
39404 + dp->ovl->dst.flags != w.flags;
39406 + if (!dp->win_set || diff) {
39407 + dp->ovl->dst.x = w.x;
39408 + dp->ovl->dst.y = w.y;
39409 + dp->ovl->dst.width = w.width;
39410 + dp->ovl->dst.height = w.height;
39411 + dp->ovl->dst.chromakey = w.chromakey;
39412 + dp->ovl->dst.flags = w.flags;
39414 + if (dp->ovl_active)
39415 + dp->ovl->ctl(dp, dp->ovl, 0);
39417 + dp->ovl->set_win(dp, dp->ovl);
39419 + if (dp->ovl_active)
39420 + dp->ovl->ctl(dp, dp->ovl, 1);
39422 + diff = w.flags & VIDEO_WINDOW_INTERLACE ? 1 : 0;
39423 + if (!dp->win_set || dp->interlace != diff) {
39424 + dp->interlace = diff;
39425 + cyberpro_set_interlace(dp);
39429 + dp->win_set = 1;
39431 + return 0;
39434 + case VIDIOCSFBUF: /* set frame buffer info */
39436 + struct video_buffer b;
39437 + int ret;
39439 + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
39440 + return -EPERM;
39442 + if (dp->cap_active)
39443 + return -EINVAL;
39445 + if (copy_from_user(&b, arg, sizeof(b)))
39446 + return -EFAULT;
39448 + ret = cyberpro_set_buffer(dp, &b);
39449 + if (ret == 0) {
39450 + dp->buf_set = 1;
39451 + dp->win_set = 0;
39454 + return ret;
39457 + case VIDIOCCAPTURE:
39459 + int on;
39461 + if (get_user(on, (int *)arg))
39462 + return -EFAULT;
39464 + if (( on && dp->ovl_active) ||
39465 + (!on && !dp->ovl_active))
39466 + return 0;
39468 + if (on && (!dp->buf_set || !dp->win_set))
39469 + return -EINVAL;
39471 + cyberpro_capture(dp, on);
39472 + dp->cap_active = on;
39473 + dp->ovl->ctl(dp, dp->ovl, on);
39474 + dp->ovl_active = on;
39476 + return 0;
39479 +#ifdef USE_MMAP
39480 + case VIDIOCSYNC:
39482 + DECLARE_WAITQUEUE(wait, current);
39483 + int buf;
39485 + /*
39486 + * The buffer must have been mmaped
39487 + * for this call to work.
39488 + */
39489 + if (!dp->mmaped)
39490 + return -EINVAL;
39492 + if (get_user(buf, (int *)arg))
39493 + return -EFAULT;
39495 + if (buf < 0 || buf >= NR_FRAMES)
39496 + return -EINVAL;
39498 + switch (dp->frame[buf].status) {
39499 + case FRAME_FREE:
39500 + return -EINVAL;
39502 + case FRAME_WAITING:
39503 + case FRAME_GRABBING:
39504 + add_wait_queue(&dp->frame_wait, &wait);
39505 + while (1) {
39506 + set_current_state(TASK_INTERRUPTIBLE);
39507 + if (signal_pending(current))
39508 + break;
39509 + if (dp->frame[buf].status == FRAME_DONE)
39510 + break;
39511 + schedule();
39513 + set_current_state(TASK_RUNNING);
39514 + remove_wait_queue(&dp->frame_wait, &wait);
39515 + if (signal_pending(current))
39516 + return -EINTR;
39517 + /*FALLTHROUGH*/
39518 + case FRAME_DONE:
39519 + dp->frame[buf].status = FRAME_FREE;
39520 + break;
39522 + return 0;
39525 + case VIDIOCMCAPTURE:
39527 + struct video_mmap vmap;
39529 + /*
39530 + * The buffer must have been mmaped
39531 + * for this call to work.
39532 + */
39533 + if (!dp->mmaped)
39534 + return -EINVAL;
39536 + if (copy_from_user(&vmap, arg, sizeof(vmap)))
39537 + return -EFAULT;
39539 + /*
39540 + * We can only capture in our source format/size.
39541 + */
39542 + if (vmap.frame >= NR_FRAMES ||
39543 + vmap.format != dp->stream_fmt ||
39544 + vmap.width != dp->capt.width ||
39545 + vmap.height != dp->capt.height)
39546 + return -EINVAL;
39548 + if (dp->frame[vmap.frame].status == FRAME_WAITING ||
39549 + dp->frame[vmap.frame].status == FRAME_GRABBING)
39550 + return -EBUSY;
39552 + dp->frame[vmap.frame].status = FRAME_WAITING;
39553 + return 0;
39556 + case VIDIOCGMBUF:
39558 + struct video_mbuf vmb;
39559 + unsigned int i;
39561 + vmb.frames = NR_FRAMES;
39562 + vmb.size = dp->frame_size * NR_FRAMES;
39564 + for (i = 0; i < NR_FRAMES; i++)
39565 + vmb.offsets[i] = dp->frame[i].offset;
39567 + return copy_to_user(arg, &vmb, sizeof(vmb)) ? -EFAULT : 0;
39569 +#endif
39571 + case VIDIOCSCAPTURE:
39573 + struct video_capture capt;
39575 +#ifndef ALLOW_SCAPTURE_WHILE_CAP
39576 + if (dp->cap_active)
39577 + return -EINVAL;
39578 +#endif
39580 + if (copy_from_user(&capt, arg, sizeof(capt)))
39581 + return -EFAULT;
39583 + if (capt.x < 0 || capt.width < 0 ||
39584 + capt.y < 0 || capt.height < 0 ||
39585 + capt.x + capt.width > dp->cap.maxwidth ||
39586 + capt.y + capt.height > dp->cap.maxheight)
39587 + return -EINVAL;
39589 + /*
39590 + * The capture width must be a multiple of 4
39591 + */
39592 + if (dp->capt.width & 3)
39593 + return -EINVAL;
39595 + dp->capt.x = capt.x;
39596 + dp->capt.y = capt.y;
39597 + dp->capt.width = capt.width;
39598 + dp->capt.height = capt.height;
39599 +#ifdef ALLOW_SCAPTURE_WHILE_CAP
39600 + if (dp->ovl_active)
39601 + dp->ovl->ctl(dp, dp->ovl, 0);
39602 + if (dp->cap_active)
39603 + cyberpro_capture(dp, 0);
39604 +#endif
39605 + cyberpro_capture_set_win(dp);
39607 + /*
39608 + * Update the overlay window information
39609 + */
39610 + dp->ovl->src.width = capt.width;
39611 + dp->ovl->src.height = capt.height;
39613 + dp->ovl->set_src(dp, dp->ovl);
39614 + if (dp->win_set)
39615 + dp->ovl->set_win(dp, dp->ovl);
39617 +#ifdef ALLOW_SCAPTURE_WHILE_CAP
39618 + if (dp->cap_active)
39619 + cyberpro_capture(dp, 1);
39620 + if (dp->ovl_active)
39621 + dp->ovl->ctl(dp, dp->ovl, 1);
39622 +#endif
39623 + return 0;
39626 + case VIDIOCGTUNER: /* no tuner */
39627 + case VIDIOCSTUNER:
39628 + return -EINVAL;
39631 + return -EINVAL;
39634 +#ifdef USE_MMAP
39635 +static int
39636 +cyberpro_grabber_mmap(struct video_device *dev, const char *addr, unsigned long size)
39638 + struct cyberpro_vidinfo *dp = dev->priv;
39639 + unsigned long vaddr = (unsigned long)addr;
39640 + pgprot_t prot;
39641 + int frame_idx, ret = -EINVAL;
39643 +#if defined(__arm__)
39644 + prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_USER | L_PTE_WRITE | L_PTE_DIRTY);
39645 +#elif defined(__i386__)
39646 + prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED);
39647 + if (boot_cpu_data.x86 > 3)
39648 + pgprot_val(prot) |= _PAGE_PCD;
39649 +#else
39650 +#error "Unsupported architecture"
39651 +#endif
39653 + /*
39654 + * The mmap() request must have the correct size.
39655 + */
39656 + if (size != NR_FRAMES * dp->frame_size)
39657 + goto out;
39659 + /*
39660 + * If it's already mapped, don't re-do
39661 + */
39662 + if (dp->mmaped)
39663 + goto out;
39664 + dp->mmaped = 1;
39666 + /*
39667 + * Map in each frame
39668 + */
39669 + for (frame_idx = 0; frame_idx < NR_FRAMES; frame_idx++) {
39670 + struct framebuf *frame;
39671 + int pgidx;
39673 + frame = dp->frame + frame_idx;
39675 + ret = cyberpro_alloc_frame_buffer(dp, frame);
39677 + /*
39678 + * If an error occurs, we can be lazy and leave what we've
39679 + * been able to do. Our release function will free any
39680 + * allocated buffers, and do_mmap_pgoff() will zap any
39681 + * inserted mappings.
39682 + */
39683 + if (ret)
39684 + goto out2;
39686 + /*
39687 + * Map in each page on a page by page basis. This is just
39688 + * a little on the inefficient side, but it's only run once.
39689 + */
39690 + for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
39691 + unsigned long virt;
39693 + virt = page_address(frame->pages[pgidx]);
39695 + ret = remap_page_range(vaddr, virt_to_phys((void *)virt),
39696 + PAGE_SIZE, prot);
39698 + if (ret)
39699 + goto out2;
39701 + vaddr += PAGE_SIZE;
39705 + out2:
39706 + if (ret)
39707 + dp->mmaped = 0;
39708 + out:
39709 + return ret;
39711 +#endif
39713 +static int __init cyberpro_grabber_init_done(struct video_device *dev)
39715 + struct cyberpro_vidinfo *dp;
39716 + struct cyberpro_info *info = dev->priv;
39717 + int ret;
39719 + dp = kmalloc(sizeof(*dp), GFP_KERNEL);
39720 + if (!dp)
39721 + return -ENOMEM;
39723 + memset(dp, 0, sizeof(*dp));
39725 + dev->priv = dp;
39726 + dp->info = *info;
39727 + dp->dev = dev;
39728 + dp->bus = &cyberpro_i2c_bus;
39729 + dp->regs = info->regs;
39730 + dp->irq = info->dev->irq;
39732 + strcpy(dp->cap.name, dev->name);
39733 + dp->cap.type = dev->type;
39734 + dp->cap.channels = 1;
39735 + dp->cap.audios = 0;
39736 + dp->cap.minwidth = 32;
39737 + dp->cap.maxwidth = 716;
39738 + dp->cap.minheight = 32;
39739 + dp->cap.maxheight = 576;
39741 + dp->pic.brightness = 32768;
39742 + dp->pic.hue = 32768;
39743 + dp->pic.colour = 32768;
39744 + dp->pic.contrast = 32768;
39745 + dp->pic.whiteness = 0;
39746 + dp->pic.depth = 8;
39747 + dp->pic.palette = VIDEO_PALETTE_YUV422;
39749 + /* dp->buf is setup by the user */
39750 + /* dp->cap_mem_offset setup by dp->buf */
39752 + dp->norm = VIDEO_MODE_AUTO;
39754 + /*
39755 + * The extended overlay window
39756 + */
39757 + dp->ext.init = cyberpro_ext_init;
39758 + dp->ext.set_src = cyberpro_ext_set_src;
39759 + dp->ext.set_win = cyberpro_ext_set_win;
39760 + dp->ext.ctl = cyberpro_ext_ctl;
39762 + /*
39763 + * The V2 overlay window
39764 + */
39765 + dp->v2.init = cyberpro_v2_init;
39766 + dp->v2.set_src = cyberpro_v2_set_src;
39767 + dp->v2.set_win = cyberpro_v2_set_win;
39768 + dp->v2.ctl = cyberpro_v2_ctl;
39770 + /*
39771 + * The X2 overlay window
39772 + */
39773 + dp->x2.init = cyberpro_x2_init;
39774 + dp->x2.set_src = cyberpro_x2_set_src;
39775 + dp->x2.set_win = cyberpro_x2_set_win;
39776 + dp->x2.ctl = cyberpro_x2_ctl;
39778 + /*
39779 + * Set the overlay window which we shall be using
39780 + */
39781 + dp->ovl = &dp->ext;
39783 + dp->cap_mode1 = EXT_CAP_MODE1_ALTFIFO;
39785 + /*
39786 + * Initialise hardware specific values.
39787 + * - CCIR656 8bit mode (YUV422 data)
39788 + * - Ignore Hgood signal
39789 + * - Invert Odd/Even field signal
39790 + */
39791 + dp->cap_mode1 |= EXT_CAP_MODE1_CCIR656 | EXT_CAP_MODE1_8BIT;
39792 + dp->cap_mode2 = EXT_CAP_MODE2_FIXSONY | EXT_CAP_MODE2_DATEND |
39793 + EXT_CAP_MODE2_CCIRINVOE;
39794 + dp->stream_fmt = VIDEO_PALETTE_YUV422;
39797 + init_waitqueue_head(&dp->vbl_wait);
39798 + cyberpro_frames_init(dp);
39800 + /*
39801 + * wake up the decoder
39802 + */
39803 + decoder_sleep(0);
39805 + dp->bus->data = dp;
39806 + strncpy(dp->bus->name, dev->name, sizeof(dp->bus->name));
39808 + pci_set_master(dp->info.dev);
39810 + ret = i2c_register_bus(dp->bus);
39812 + /*
39813 + * If we successfully registered the bus, but didn't initialise
39814 + * the decoder (because its driver is not present), request
39815 + * that it is loaded.
39816 + */
39817 + if (ret == 0 && !dp->decoder)
39818 + request_module("saa7111");
39820 + /*
39821 + * If that didn't work, then we're out of luck.
39822 + */
39823 + if (ret == 0 && !dp->decoder) {
39824 + i2c_unregister_bus(dp->bus);
39825 + ret = -ENXIO;
39828 + if (ret) {
39829 + kfree(dp);
39831 + /*
39832 + * put the decoder back to sleep
39833 + */
39834 + decoder_sleep(1);
39837 + return ret;
39840 +static struct video_device cyberpro_grabber = {
39841 + name: "",
39842 + type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
39843 + VID_TYPE_CHROMAKEY | VID_TYPE_SCALES |
39844 + VID_TYPE_SUBCAPTURE,
39845 + hardware: 0,
39846 + open: cyberpro_grabber_open,
39847 + close: cyberpro_grabber_close,
39848 + read: cyberpro_grabber_read,
39849 + write: cyberpro_grabber_write,
39850 + ioctl: cyberpro_grabber_ioctl,
39851 +#ifdef USE_MMAP
39852 + mmap: cyberpro_grabber_mmap,
39853 +#endif
39854 + initialize: cyberpro_grabber_init_done,
39857 +int init_cyber2000fb_viddev(void)
39859 + struct cyberpro_info info;
39861 + if (!cyber2000fb_attach(&info, 0))
39862 + return -ENXIO;
39864 + strncpy(cyberpro_grabber.name, info.dev_name, sizeof(cyberpro_grabber.name));
39866 + cyberpro_grabber.priv = &info;
39868 + return video_register_device(&cyberpro_grabber, VFL_TYPE_GRABBER, -1);
39872 + * This can be cleaned up when the SAA7111 code is fixed.
39873 + */
39874 +#ifdef MODULE
39875 +static int __init cyberpro_init(void)
39877 + disable_irq(35);
39878 + return init_cyber2000fb_viddev();
39881 +static void __exit cyberpro_exit(void)
39883 + video_unregister_device(&cyberpro_grabber);
39884 + kfree(cyberpro_grabber.priv);
39885 + i2c_unregister_bus(&cyberpro_i2c_bus);
39887 + /*
39888 + * put the decoder back to sleep
39889 + */
39890 + decoder_sleep(1);
39892 + cyber2000fb_detach(0);
39895 +module_init(cyberpro_init);
39896 +module_exit(cyberpro_exit);
39897 +#endif
39898 --- linux-2.4.25/drivers/media/video/i2c-old.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
39899 +++ linux-2.4.25/drivers/media/video/i2c-old.c 2004-03-31 17:15:09.000000000 +0200
39900 @@ -36,11 +36,20 @@
39901 static struct i2c_driver *drivers[I2C_DRIVER_MAX];
39902 static int bus_count = 0, driver_count = 0;
39904 +extern int saa7111_init(void);
39905 +extern int saa7185_init(void);
39906 +extern int bt819_init(void);
39907 +extern int bt856_init(void);
39909 int i2c_init(void)
39911 printk(KERN_INFO "i2c: initialized%s\n",
39912 scan ? " (i2c bus scan enabled)" : "");
39914 +#if defined(CONFIG_VIDEO_CYBERPRO)
39915 + saa7111_init();
39916 +#endif
39918 return 0;
39921 @@ -52,10 +61,10 @@
39922 int i,j,ack=1;
39923 unsigned char addr;
39924 LOCK_FLAGS;
39927 /* probe for device */
39928 LOCK_I2C_BUS(bus);
39929 - for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
39930 + for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
39932 i2c_start(bus);
39933 ack = i2c_sendbyte(bus,addr,0);
39934 @@ -87,8 +96,8 @@
39935 device->addr = addr;
39937 /* Attach */
39939 - if (driver->attach(device)!=0)
39941 + if (driver->attach(device)!=0)
39943 kfree(device);
39944 return;
39945 @@ -114,7 +123,7 @@
39946 for (i = 0; i < I2C_DEVICE_MAX; i++)
39947 if (device == device->driver->devices[i])
39948 break;
39949 - if (I2C_DEVICE_MAX == i)
39950 + if (I2C_DEVICE_MAX == i)
39952 printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n",
39953 device->name);
39954 @@ -126,7 +135,7 @@
39955 for (i = 0; i < I2C_DEVICE_MAX; i++)
39956 if (device == device->bus->devices[i])
39957 break;
39958 - if (I2C_DEVICE_MAX == i)
39959 + if (I2C_DEVICE_MAX == i)
39961 printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n",
39962 device->name);
39963 @@ -158,19 +167,19 @@
39964 busses[i] = bus;
39965 bus_count++;
39966 REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
39969 MOD_INC_USE_COUNT;
39971 - if (scan)
39972 + if (scan)
39974 /* scan whole i2c bus */
39975 LOCK_I2C_BUS(bus);
39976 - for (i = 0; i < 256; i+=2)
39977 + for (i = 0; i < 256; i+=2)
39979 i2c_start(bus);
39980 ack = i2c_sendbyte(bus,i,0);
39981 i2c_stop(bus);
39982 - if (!ack)
39983 + if (!ack)
39985 printk(KERN_INFO "i2c: scanning bus %s: found device at addr=0x%02x\n",
39986 bus->name,i);
39987 @@ -198,20 +207,20 @@
39988 for (i = 0; i < I2C_BUS_MAX; i++)
39989 if (bus == busses[i])
39990 break;
39991 - if (I2C_BUS_MAX == i)
39992 + if (I2C_BUS_MAX == i)
39994 printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n",
39995 bus->name);
39996 return -ENODEV;
40000 MOD_DEC_USE_COUNT;
40003 busses[i] = NULL;
40004 bus_count--;
40005 REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name));
40007 - return 0;
40008 + return 0;
40011 /* ----------------------------------------------------------------------- */
40012 @@ -231,9 +240,9 @@
40014 drivers[i] = driver;
40015 driver_count++;
40018 MOD_INC_USE_COUNT;
40021 REGPRINT(printk("i2c: driver registered: %s\n",driver->name));
40023 /* Probe available busses */
40024 @@ -256,7 +265,7 @@
40025 for (i = 0; i < I2C_DRIVER_MAX; i++)
40026 if (driver == drivers[i])
40027 break;
40028 - if (I2C_DRIVER_MAX == i)
40029 + if (I2C_DRIVER_MAX == i)
40031 printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n",
40032 driver->name);
40033 @@ -264,7 +273,7 @@
40036 MOD_DEC_USE_COUNT;
40039 drivers[i] = NULL;
40040 driver_count--;
40041 REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name));
40042 @@ -328,7 +337,7 @@
40043 int i2c_ack(struct i2c_bus *bus)
40045 int ack;
40048 I2C_SET(bus,0,1);
40049 I2C_SET(bus,1,1);
40050 ack = I2C_GET(bus);
40051 @@ -339,7 +348,7 @@
40052 int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack)
40054 int i, ack;
40057 I2C_SET(bus,0,0);
40058 for (i=7; i>=0; i--)
40059 (data&(1<<i)) ? i2c_one(bus) : i2c_zero(bus);
40060 @@ -354,9 +363,9 @@
40062 int i;
40063 unsigned char data=0;
40066 I2C_SET(bus,0,1);
40067 - for (i=7; i>=0; i--)
40068 + for (i=7; i>=0; i--)
40070 I2C_SET(bus,1,1);
40071 if (I2C_GET(bus))
40072 @@ -373,7 +382,7 @@
40073 int i2c_read(struct i2c_bus *bus, unsigned char addr)
40075 int ret;
40078 if (bus->i2c_read)
40079 return bus->i2c_read(bus, addr);
40081 --- linux-2.4.25/drivers/media/video/saa7111.c~2.4.25-vrs2.patch 2001-09-30 21:26:06.000000000 +0200
40082 +++ linux-2.4.25/drivers/media/video/saa7111.c 2004-03-31 17:15:09.000000000 +0200
40083 @@ -20,9 +20,9 @@
40084 along with this program; if not, write to the Free Software
40085 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40088 -#include <linux/module.h>
40089 +#include <linux/config.h>
40090 #include <linux/init.h>
40091 +#include <linux/module.h>
40092 #include <linux/delay.h>
40093 #include <linux/errno.h>
40094 #include <linux/fs.h>
40095 @@ -149,7 +149,11 @@
40096 0x0d, 0x00, /* 0d - HUE=0 */
40097 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
40098 0x0f, 0x00, /* 0f - reserved */
40099 +#ifndef CONFIG_ARCH_NETWINDER
40100 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
40101 +#else
40102 + 0x10, 0xc8, /* 10 - OFTS=YUV-CCIR656, HDEL=0, VLRN=1, YDEL=0 */
40103 +#endif
40104 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
40105 0x12, 0x00, /* 12 - output control 2 */
40106 0x13, 0x00, /* 13 - output control 3 */
40107 --- linux-2.4.25/drivers/message/i2o/i2o_core.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
40108 +++ linux-2.4.25/drivers/message/i2o/i2o_core.c 2004-03-31 17:15:09.000000000 +0200
40109 @@ -1665,14 +1665,14 @@
40111 memset(status, 0, 4);
40113 - msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
40114 - msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
40115 - msg[2]=core_context;
40116 - msg[3]=0;
40117 - msg[4]=0;
40118 - msg[5]=0;
40119 - msg[6]=virt_to_bus(status);
40120 - msg[7]=0; /* 64bit host FIXME */
40121 + writel(EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
40122 + writel(I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
40123 + writel(core_context, msg + 2);
40124 + writel(0, msg + 3);
40125 + writel(0, msg + 4);
40126 + writel(0, msg + 5);
40127 + writel(virt_to_bus(status), msg + 6);
40128 + writel(0, msg + 7); /* 64bit host FIXME */
40130 i2o_post_message(c,m);
40132 @@ -1781,15 +1781,15 @@
40133 return -ETIMEDOUT;
40134 msg=(u32 *)(c->mem_offset+m);
40136 - msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
40137 - msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
40138 - msg[2]=core_context;
40139 - msg[3]=0;
40140 - msg[4]=0;
40141 - msg[5]=0;
40142 - msg[6]=virt_to_bus(c->status_block);
40143 - msg[7]=0; /* 64bit host FIXME */
40144 - msg[8]=sizeof(i2o_status_block); /* always 88 bytes */
40145 + writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
40146 + writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
40147 + writel(core_context, msg + 2);
40148 + writel(0, msg + 3);
40149 + writel(0, msg + 4);
40150 + writel(0, msg + 5);
40151 + writel(virt_to_bus(c->status_block), msg + 6);
40152 + writel(0, msg + 7); /* 64bit host FIXME */
40153 + writel(sizeof(i2o_status_block), msg + 8); /* always 88 bytes */
40155 i2o_post_message(c,m);
40157 @@ -2193,15 +2193,15 @@
40159 memset(status, 0, 4);
40161 - msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
40162 - msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
40163 - msg[2]= core_context;
40164 - msg[3]= 0x0106; /* Transaction context */
40165 - msg[4]= 4096; /* Host page frame size */
40166 + writel(EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6, msg + 0);
40167 + writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, msg + 1);
40168 + writel(core_context, msg + 2);
40169 + writel(0x0106, msg + 3); /* Transaction context */
40170 + writel(PAGE_SIZE, msg + 4); /* Host page frame size */
40171 /* Frame size is in words. 256 bytes a frame for now */
40172 - msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size in words and Initcode */
40173 - msg[6]= 0xD0000004; /* Simple SG LE, EOB */
40174 - msg[7]= virt_to_bus(status);
40175 + writel(MSG_FRAME_SIZE<<16|0x80, msg + 5);/* Outbound msg frame size in words and Initcode */
40176 + writel(0xD0000004, msg + 6); /* Simple SG LE, EOB */
40177 + writel(virt_to_bus(status), msg + 7);
40179 i2o_post_message(c,m);
40181 --- linux-2.4.25/drivers/message/i2o/i2o_pci.c~2.4.25-vrs2.patch 2002-11-29 00:53:13.000000000 +0100
40182 +++ linux-2.4.25/drivers/message/i2o/i2o_pci.c 2004-03-31 17:15:09.000000000 +0200
40183 @@ -390,4 +390,4 @@
40184 MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o");
40185 module_init(i2o_pci_core_attach);
40186 module_exit(i2o_pci_core_detach);
40188 \ No newline at end of file
40190 --- linux-2.4.25/drivers/misc/Config.in~2.4.25-vrs2.patch 1999-12-26 00:04:56.000000000 +0100
40191 +++ linux-2.4.25/drivers/misc/Config.in 2004-03-31 17:15:09.000000000 +0200
40192 @@ -1,7 +1,17 @@
40194 -# Misc strange devices
40195 +# MCP drivers
40197 mainmenu_option next_comment
40198 -comment 'Misc devices'
40199 +comment 'Multimedia Capabilities Port drivers'
40201 +bool 'Multimedia drivers' CONFIG_MCP
40203 +# Interface drivers
40204 +dep_bool 'Support SA1100 MCP interface' CONFIG_MCP_SA1100 $CONFIG_MCP $CONFIG_ARCH_SA1100
40206 +# Chip drivers
40207 +dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP
40208 +dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND
40209 +dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200
40211 endmenu
40212 --- linux-2.4.25/drivers/misc/Makefile~2.4.25-vrs2.patch 2000-12-29 23:07:22.000000000 +0100
40213 +++ linux-2.4.25/drivers/misc/Makefile 2004-03-31 17:15:09.000000000 +0200
40214 @@ -11,6 +11,14 @@
40216 O_TARGET := misc.o
40218 +export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o
40220 +obj-$(CONFIG_MCP) += mcp-core.o
40221 +obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o
40222 +obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
40223 +obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o
40224 +obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
40226 include $(TOPDIR)/Rules.make
40228 fastdep:
40229 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
40230 +++ linux-2.4.25/drivers/misc/mcp-core.c 2004-03-31 17:15:09.000000000 +0200
40231 @@ -0,0 +1,155 @@
40233 + * linux/drivers/misc/mcp-core.c
40235 + * Copyright (C) 2001 Russell King
40237 + * This program is free software; you can redistribute it and/or modify
40238 + * it under the terms of the GNU General Public License as published by
40239 + * the Free Software Foundation; either version 2 of the License.
40241 + * Generic MCP (Multimedia Communications Port) layer. All MCP locking
40242 + * is solely held within this file.
40243 + */
40244 +#include <linux/module.h>
40245 +#include <linux/init.h>
40246 +#include <linux/errno.h>
40247 +#include <linux/smp.h>
40249 +#include <asm/dma.h>
40250 +#include <asm/system.h>
40252 +#include "mcp.h"
40254 +/**
40255 + * mcp_set_telecom_divisor - set the telecom divisor
40256 + * @mcp: MCP interface structure
40257 + * @div: SIB clock divisor
40259 + * Set the telecom divisor on the MCP interface. The resulting
40260 + * sample rate is SIBCLOCK/div.
40261 + */
40262 +void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
40264 + spin_lock_irq(&mcp->lock);
40265 + mcp->set_telecom_divisor(mcp, div);
40266 + spin_unlock_irq(&mcp->lock);
40269 +/**
40270 + * mcp_set_audio_divisor - set the audio divisor
40271 + * @mcp: MCP interface structure
40272 + * @div: SIB clock divisor
40274 + * Set the audio divisor on the MCP interface.
40275 + */
40276 +void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
40278 + spin_lock_irq(&mcp->lock);
40279 + mcp->set_audio_divisor(mcp, div);
40280 + spin_unlock_irq(&mcp->lock);
40283 +/**
40284 + * mcp_reg_write - write a device register
40285 + * @mcp: MCP interface structure
40286 + * @reg: 4-bit register index
40287 + * @val: 16-bit data value
40289 + * Write a device register. The MCP interface must be enabled
40290 + * to prevent this function hanging.
40291 + */
40292 +void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
40294 + unsigned long flags;
40296 + spin_lock_irqsave(&mcp->lock, flags);
40297 + mcp->reg_write(mcp, reg, val);
40298 + spin_unlock_irqrestore(&mcp->lock, flags);
40301 +/**
40302 + * mcp_reg_read - read a device register
40303 + * @mcp: MCP interface structure
40304 + * @reg: 4-bit register index
40306 + * Read a device register and return its value. The MCP interface
40307 + * must be enabled to prevent this function hanging.
40308 + */
40309 +unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
40311 + unsigned long flags;
40312 + unsigned int val;
40314 + spin_lock_irqsave(&mcp->lock, flags);
40315 + val = mcp->reg_read(mcp, reg);
40316 + spin_unlock_irqrestore(&mcp->lock, flags);
40318 + return val;
40321 +/**
40322 + * mcp_enable - enable the MCP interface
40323 + * @mcp: MCP interface to enable
40325 + * Enable the MCP interface. Each call to mcp_enable will need
40326 + * a corresponding call to mcp_disable to disable the interface.
40327 + */
40328 +void mcp_enable(struct mcp *mcp)
40330 + spin_lock_irq(&mcp->lock);
40331 + if (mcp->use_count++ == 0)
40332 + mcp->enable(mcp);
40333 + spin_unlock_irq(&mcp->lock);
40336 +/**
40337 + * mcp_disable - disable the MCP interface
40338 + * @mcp: MCP interface to disable
40340 + * Disable the MCP interface. The MCP interface will only be
40341 + * disabled once the number of calls to mcp_enable matches the
40342 + * number of calls to mcp_disable.
40343 + */
40344 +void mcp_disable(struct mcp *mcp)
40346 + unsigned long flags;
40348 + spin_lock_irqsave(&mcp->lock, flags);
40349 + if (--mcp->use_count == 0)
40350 + mcp->disable(mcp);
40351 + spin_unlock_irqrestore(&mcp->lock, flags);
40356 + * This needs re-working
40357 + */
40358 +static struct mcp *mcp_if;
40360 +struct mcp *mcp_get(void)
40362 + return mcp_if;
40365 +int mcp_register(struct mcp *mcp)
40367 + if (mcp_if)
40368 + return -EBUSY;
40369 + if (mcp->owner)
40370 + __MOD_INC_USE_COUNT(mcp->owner);
40371 + mcp_if = mcp;
40372 + return 0;
40375 +EXPORT_SYMBOL(mcp_set_telecom_divisor);
40376 +EXPORT_SYMBOL(mcp_set_audio_divisor);
40377 +EXPORT_SYMBOL(mcp_reg_write);
40378 +EXPORT_SYMBOL(mcp_reg_read);
40379 +EXPORT_SYMBOL(mcp_enable);
40380 +EXPORT_SYMBOL(mcp_disable);
40381 +EXPORT_SYMBOL(mcp_get);
40382 +EXPORT_SYMBOL(mcp_register);
40384 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
40385 +MODULE_DESCRIPTION("Core multimedia communications port driver");
40386 +MODULE_LICENSE("GPL");
40387 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
40388 +++ linux-2.4.25/drivers/misc/mcp-sa1100.c 2004-03-31 17:15:09.000000000 +0200
40389 @@ -0,0 +1,180 @@
40391 + * linux/drivers/misc/mcp-sa1100.c
40393 + * Copyright (C) 2001 Russell King
40395 + * This program is free software; you can redistribute it and/or modify
40396 + * it under the terms of the GNU General Public License as published by
40397 + * the Free Software Foundation; either version 2 of the License.
40399 + * SA1100 MCP (Multimedia Communications Port) driver.
40401 + * MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
40402 + */
40403 +#include <linux/module.h>
40404 +#include <linux/init.h>
40405 +#include <linux/errno.h>
40406 +#include <linux/kernel.h>
40407 +#include <linux/delay.h>
40408 +#include <linux/spinlock.h>
40410 +#include <asm/dma.h>
40411 +#include <asm/hardware.h>
40412 +#include <asm/system.h>
40414 +#include "mcp.h"
40416 +static void
40417 +mcp_sa1100_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
40419 + unsigned int mccr0;
40421 + divisor /= 32;
40423 + mccr0 = Ser4MCCR0 & ~0x00007f00;
40424 + mccr0 |= divisor << 8;
40425 + Ser4MCCR0 = mccr0;
40428 +static void
40429 +mcp_sa1100_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
40431 + unsigned int mccr0;
40433 + divisor /= 32;
40435 + mccr0 = Ser4MCCR0 & ~0x0000007f;
40436 + mccr0 |= divisor;
40437 + Ser4MCCR0 = mccr0;
40441 + * Write data to the device. The bit should be set after 3 subframe
40442 + * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
40443 + * We really should try doing something more productive while we
40444 + * wait.
40445 + */
40446 +static void
40447 +mcp_sa1100_write(struct mcp *mcp, unsigned int reg, unsigned int val)
40449 + int ret = -ETIME;
40450 + int i;
40452 + Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
40454 + for (i = 0; i < 2; i++) {
40455 + udelay(mcp->rw_timeout);
40456 + if (Ser4MCSR & MCSR_CWC) {
40457 + ret = 0;
40458 + break;
40462 + if (ret < 0)
40463 + printk(KERN_WARNING "mcp: write timed out\n");
40467 + * Read data from the device. The bit should be set after 3 subframe
40468 + * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
40469 + * We really should try doing something more productive while we
40470 + * wait.
40471 + */
40472 +static unsigned int
40473 +mcp_sa1100_read(struct mcp *mcp, unsigned int reg)
40475 + int ret = -ETIME;
40476 + int i;
40478 + Ser4MCDR2 = reg << 17 | MCDR2_Rd;
40480 + for (i = 0; i < 2; i++) {
40481 + udelay(mcp->rw_timeout);
40482 + if (Ser4MCSR & MCSR_CRC) {
40483 + ret = Ser4MCDR2 & 0xffff;
40484 + break;
40488 + if (ret < 0)
40489 + printk(KERN_WARNING "mcp: read timed out\n");
40491 + return ret;
40494 +static void mcp_sa1100_enable(struct mcp *mcp)
40496 + Ser4MCSR = -1;
40497 + Ser4MCCR0 |= MCCR0_MCE;
40500 +static void mcp_sa1100_disable(struct mcp *mcp)
40502 + Ser4MCCR0 &= ~MCCR0_MCE;
40505 +struct mcp mcp_sa1100 = {
40506 + owner: THIS_MODULE,
40507 + lock: SPIN_LOCK_UNLOCKED,
40508 + sclk_rate: 11981000,
40509 + dma_audio_rd: DMA_Ser4MCP0Rd,
40510 + dma_audio_wr: DMA_Ser4MCP0Wr,
40511 + dma_telco_rd: DMA_Ser4MCP1Rd,
40512 + dma_telco_wr: DMA_Ser4MCP1Wr,
40513 + set_telecom_divisor: mcp_sa1100_set_telecom_divisor,
40514 + set_audio_divisor: mcp_sa1100_set_audio_divisor,
40515 + reg_write: mcp_sa1100_write,
40516 + reg_read: mcp_sa1100_read,
40517 + enable: mcp_sa1100_enable,
40518 + disable: mcp_sa1100_disable,
40522 + * This needs re-working
40523 + */
40524 +static int mcp_sa1100_init(void)
40526 + struct mcp *mcp = &mcp_sa1100;
40527 + int ret = -ENODEV;
40529 + if (machine_is_accelent_sa() ||
40530 + machine_is_adsbitsy() || machine_is_assabet() ||
40531 + machine_is_cerf() || machine_is_flexanet() ||
40532 + machine_is_freebird() || machine_is_graphicsclient() ||
40533 + machine_is_graphicsmaster() || machine_is_lart() ||
40534 + machine_is_omnimeter() || machine_is_pfs168() ||
40535 + machine_is_shannon() || machine_is_simpad() ||
40536 + machine_is_simputer() || machine_is_yopy()) {
40537 + /*
40538 + * Setup the PPC unit correctly.
40539 + */
40540 + PPDR &= ~PPC_RXD4;
40541 + PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
40542 + PSDR |= PPC_RXD4;
40543 + PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
40544 + PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
40546 + Ser4MCSR = -1;
40547 + Ser4MCCR1 = 0;
40548 + Ser4MCCR0 = 0x00007f7f | MCCR0_ADM;
40550 + /*
40551 + * Calculate the read/write timeout (us) from the bit clock
40552 + * rate. This is the period for 3 64-bit frames. Always
40553 + * round this time up.
40554 + */
40555 + mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
40556 + mcp->sclk_rate;
40558 + ret = mcp_register(mcp);
40561 + return ret;
40564 +module_init(mcp_sa1100_init);
40565 +EXPORT_SYMBOL(mcp_sa1100_init);
40567 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
40568 +MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
40569 +MODULE_LICENSE("GPL");
40570 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
40571 +++ linux-2.4.25/drivers/misc/mcp.h 2004-03-31 17:15:09.000000000 +0200
40572 @@ -0,0 +1,44 @@
40574 + * linux/drivers/misc/mcp.h
40576 + * Copyright (C) 2001 Russell King, All Rights Reserved.
40578 + * This program is free software; you can redistribute it and/or modify
40579 + * it under the terms of the GNU General Public License as published by
40580 + * the Free Software Foundation; either version 2 of the License.
40581 + */
40582 +#ifndef MCP_H
40583 +#define MCP_H
40585 +struct mcp {
40586 + struct module *owner;
40587 + spinlock_t lock;
40588 + int use_count;
40589 + unsigned int sclk_rate;
40590 + unsigned int rw_timeout;
40591 + dma_device_t dma_audio_rd;
40592 + dma_device_t dma_audio_wr;
40593 + dma_device_t dma_telco_rd;
40594 + dma_device_t dma_telco_wr;
40595 + void (*set_telecom_divisor)(struct mcp *, unsigned int);
40596 + void (*set_audio_divisor)(struct mcp *, unsigned int);
40597 + void (*reg_write)(struct mcp *, unsigned int, unsigned int);
40598 + unsigned int (*reg_read)(struct mcp *, unsigned int);
40599 + void (*enable)(struct mcp *);
40600 + void (*disable)(struct mcp *);
40603 +void mcp_set_telecom_divisor(struct mcp *, unsigned int);
40604 +void mcp_set_audio_divisor(struct mcp *, unsigned int);
40605 +void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
40606 +unsigned int mcp_reg_read(struct mcp *, unsigned int);
40607 +void mcp_enable(struct mcp *);
40608 +void mcp_disable(struct mcp *);
40610 +/* noddy implementation alert! */
40611 +struct mcp *mcp_get(void);
40612 +int mcp_register(struct mcp *);
40614 +#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
40616 +#endif
40617 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
40618 +++ linux-2.4.25/drivers/misc/ucb1x00-audio.c 2004-03-31 17:15:09.000000000 +0200
40619 @@ -0,0 +1,378 @@
40621 + * linux/drivers/misc/ucb1x00-audio.c
40623 + * Copyright (C) 2001 Russell King, All Rights Reserved.
40625 + * This program is free software; you can redistribute it and/or modify
40626 + * it under the terms of the GNU General Public License version 2 as
40627 + * published by the Free Software Foundation.
40628 + */
40629 +#include <linux/module.h>
40630 +#include <linux/init.h>
40631 +#include <linux/fs.h>
40632 +#include <linux/errno.h>
40633 +#include <linux/slab.h>
40634 +#include <linux/sound.h>
40635 +#include <linux/soundcard.h>
40636 +#include <linux/list.h>
40638 +#include <asm/dma.h>
40639 +#include <asm/hardware.h>
40640 +#include <asm/semaphore.h>
40641 +#include <asm/uaccess.h>
40643 +#include "ucb1x00.h"
40645 +#include "../drivers/sound/sa1100-audio.h"
40647 +#define MAGIC 0x41544154
40649 +struct ucb1x00_audio {
40650 + struct file_operations fops;
40651 + struct file_operations mops;
40652 + struct ucb1x00 *ucb;
40653 + audio_stream_t output_stream;
40654 + audio_stream_t input_stream;
40655 + audio_state_t state;
40656 + unsigned int rate;
40657 + int dev_id;
40658 + int mix_id;
40659 + unsigned int daa_oh_bit;
40660 + unsigned int telecom;
40661 + unsigned int magic;
40662 + unsigned int ctrl_a;
40663 + unsigned int ctrl_b;
40665 + /* mixer info */
40666 + unsigned int mod_cnt;
40667 + unsigned short output_level;
40668 + unsigned short input_level;
40671 +#define REC_MASK (SOUND_MASK_VOLUME | SOUND_MASK_MIC)
40672 +#define DEV_MASK REC_MASK
40674 +static int
40675 +ucb1x00_mixer_ioctl(struct inode *ino, struct file *filp, uint cmd, ulong arg)
40677 + struct ucb1x00_audio *ucba;
40678 + unsigned int val, gain;
40679 + int ret = 0;
40681 + ucba = list_entry(filp->f_op, struct ucb1x00_audio, mops);
40683 + if (_IOC_TYPE(cmd) != 'M')
40684 + return -EINVAL;
40686 + if (cmd == SOUND_MIXER_INFO) {
40687 + struct mixer_info mi;
40689 + strncpy(mi.id, "UCB1x00", sizeof(mi.id));
40690 + strncpy(mi.name, "Philips UCB1x00", sizeof(mi.name));
40691 + mi.modify_counter = ucba->mod_cnt;
40692 + return copy_to_user((void *)arg, &mi, sizeof(mi)) ? -EFAULT : 0;
40695 + if (_IOC_DIR(cmd) & _IOC_WRITE) {
40696 + unsigned int left, right;
40698 + ret = get_user(val, (unsigned int *)arg);
40699 + if (ret)
40700 + goto out;
40702 + left = val & 255;
40703 + right = val >> 8;
40705 + if (left > 100)
40706 + left = 100;
40707 + if (right > 100)
40708 + right = 100;
40710 + gain = (left + right) / 2;
40712 + ret = -EINVAL;
40713 + if (!ucba->telecom) {
40714 + switch(_IOC_NR(cmd)) {
40715 + case SOUND_MIXER_VOLUME:
40716 + ucba->output_level = gain | gain << 8;
40717 + ucba->mod_cnt++;
40718 + ucba->ctrl_b = (ucba->ctrl_b & 0xff00) |
40719 + ((gain * 31) / 100);
40720 + ucb1x00_reg_write(ucba->ucb, UCB_AC_B,
40721 + ucba->ctrl_b);
40722 + ret = 0;
40723 + break;
40725 + case SOUND_MIXER_MIC:
40726 + ucba->input_level = gain | gain << 8;
40727 + ucba->mod_cnt++;
40728 + ucba->ctrl_a = (ucba->ctrl_a & 0x7f) |
40729 + (((gain * 31) / 100) << 7);
40730 + ucb1x00_reg_write(ucba->ucb, UCB_AC_A,
40731 + ucba->ctrl_a);
40732 + ret = 0;
40733 + break;
40738 + if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
40739 + switch (_IOC_NR(cmd)) {
40740 + case SOUND_MIXER_VOLUME:
40741 + val = ucba->output_level;
40742 + break;
40744 + case SOUND_MIXER_MIC:
40745 + val = ucba->input_level;
40746 + break;
40748 + case SOUND_MIXER_RECSRC:
40749 + case SOUND_MIXER_RECMASK:
40750 + val = ucba->telecom ? 0 : REC_MASK;
40751 + break;
40753 + case SOUND_MIXER_DEVMASK:
40754 + val = ucba->telecom ? 0 : DEV_MASK;
40755 + break;
40757 + case SOUND_MIXER_CAPS:
40758 + case SOUND_MIXER_STEREODEVS:
40759 + val = 0;
40760 + break;
40762 + default:
40763 + val = 0;
40764 + ret = -EINVAL;
40765 + break;
40768 + if (ret == 0)
40769 + ret = put_user(val, (int *)arg);
40771 + out:
40772 + return ret;
40775 +static int ucb1x00_audio_setrate(struct ucb1x00_audio *ucba, int rate)
40777 + unsigned int div_rate = ucb1x00_clkrate(ucba->ucb) / 32;
40778 + unsigned int div;
40780 + div = (div_rate + (rate / 2)) / rate;
40781 + if (div < 6)
40782 + div = 6;
40783 + if (div > 127)
40784 + div = 127;
40786 + ucba->ctrl_a = (ucba->ctrl_a & ~0x7f) | div;
40788 + if (ucba->telecom) {
40789 + ucb1x00_reg_write(ucba->ucb, UCB_TC_B, 0);
40790 + ucb1x00_set_telecom_divisor(ucba->ucb, div * 32);
40791 + ucb1x00_reg_write(ucba->ucb, UCB_TC_A, ucba->ctrl_a);
40792 + ucb1x00_reg_write(ucba->ucb, UCB_TC_B, ucba->ctrl_b);
40793 + } else {
40794 + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, 0);
40795 + ucb1x00_set_audio_divisor(ucba->ucb, div * 32);
40796 + ucb1x00_reg_write(ucba->ucb, UCB_AC_A, ucba->ctrl_a);
40797 + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, ucba->ctrl_b);
40800 + ucba->rate = div_rate / div;
40802 + return ucba->rate;
40805 +static int ucb1x00_audio_getrate(struct ucb1x00_audio *ucba)
40807 + return ucba->rate;
40810 +static void ucb1x00_audio_startup(void *data)
40812 + struct ucb1x00_audio *ucba = data;
40814 + ucb1x00_enable(ucba->ucb);
40815 + ucb1x00_audio_setrate(ucba, ucba->rate);
40817 + ucb1x00_reg_write(ucba->ucb, UCB_MODE, UCB_MODE_DYN_VFLAG_ENA);
40819 + /*
40820 + * Take off-hook
40821 + */
40822 + if (ucba->daa_oh_bit)
40823 + ucb1x00_io_write(ucba->ucb, 0, ucba->daa_oh_bit);
40826 +static void ucb1x00_audio_shutdown(void *data)
40828 + struct ucb1x00_audio *ucba = data;
40830 + /*
40831 + * Place on-hook
40832 + */
40833 + if (ucba->daa_oh_bit)
40834 + ucb1x00_io_write(ucba->ucb, ucba->daa_oh_bit, 0);
40836 + ucb1x00_reg_write(ucba->ucb, ucba->telecom ? UCB_TC_B : UCB_AC_B, 0);
40837 + ucb1x00_disable(ucba->ucb);
40840 +static int
40841 +ucb1x00_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
40843 + struct ucb1x00_audio *ucba;
40844 + int val, ret = 0;
40846 + ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
40848 + /*
40849 + * Make sure we have our magic number
40850 + */
40851 + if (ucba->magic != MAGIC)
40852 + return -ENODEV;
40854 + switch (cmd) {
40855 + case SNDCTL_DSP_STEREO:
40856 + ret = get_user(val, (int *)arg);
40857 + if (ret)
40858 + return ret;
40859 + if (val != 0)
40860 + return -EINVAL;
40861 + val = 0;
40862 + break;
40864 + case SNDCTL_DSP_CHANNELS:
40865 + case SOUND_PCM_READ_CHANNELS:
40866 + val = 1;
40867 + break;
40869 + case SNDCTL_DSP_SPEED:
40870 + ret = get_user(val, (int *)arg);
40871 + if (ret)
40872 + return ret;
40873 + val = ucb1x00_audio_setrate(ucba, val);
40874 + break;
40876 + case SOUND_PCM_READ_RATE:
40877 + val = ucb1x00_audio_getrate(ucba);
40878 + break;
40880 + case SNDCTL_DSP_SETFMT:
40881 + case SNDCTL_DSP_GETFMTS:
40882 + val = AFMT_S16_LE;
40883 + break;
40885 + default:
40886 + return ucb1x00_mixer_ioctl(inode, file, cmd, arg);
40889 + return put_user(val, (int *)arg);
40892 +static int ucb1x00_audio_open(struct inode *inode, struct file *file)
40894 + struct ucb1x00_audio *ucba;
40896 + ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
40898 + return sa1100_audio_attach(inode, file, &ucba->state);
40901 +static struct ucb1x00_audio *ucb1x00_audio_alloc(struct ucb1x00 *ucb)
40903 + struct ucb1x00_audio *ucba;
40905 + ucba = kmalloc(sizeof(*ucba), GFP_KERNEL);
40906 + if (ucba) {
40907 + memset(ucba, 0, sizeof(*ucba));
40909 + ucba->magic = MAGIC;
40910 + ucba->ucb = ucb;
40911 + ucba->fops.owner = THIS_MODULE;
40912 + ucba->fops.open = ucb1x00_audio_open;
40913 + ucba->mops.owner = THIS_MODULE;
40914 + ucba->mops.ioctl = ucb1x00_mixer_ioctl;
40915 + ucba->state.output_stream = &ucba->output_stream;
40916 + ucba->state.input_stream = &ucba->input_stream;
40917 + ucba->state.data = ucba;
40918 + ucba->state.hw_init = ucb1x00_audio_startup;
40919 + ucba->state.hw_shutdown = ucb1x00_audio_shutdown;
40920 + ucba->state.client_ioctl = ucb1x00_audio_ioctl;
40922 + /* There is a bug in the StrongARM causes corrupt MCP data to be sent to
40923 + * the codec when the FIFOs are empty and writes are made to the OS timer
40924 + * match register 0. To avoid this we must make sure that data is always
40925 + * sent to the codec.
40926 + */
40927 + ucba->state.need_tx_for_rx = 1;
40929 + init_MUTEX(&ucba->state.sem);
40930 + ucba->rate = 8000;
40932 + return ucba;
40935 +static struct ucb1x00_audio *audio, *telecom;
40937 +static int __init ucb1x00_audio_init(void)
40939 + struct ucb1x00 *ucb = ucb1x00_get();
40940 + struct ucb1x00_audio *a;
40942 + if (!ucb)
40943 + return -ENODEV;
40945 + a = ucb1x00_audio_alloc(ucb);
40946 + if (a) {
40947 + a->state.input_dma = ucb->mcp->dma_audio_rd;
40948 + a->state.input_id = "UCB1x00 audio in";
40949 + a->state.output_dma = ucb->mcp->dma_audio_wr;
40950 + a->state.output_id = "UCB1x00 audio out";
40951 + a->dev_id = register_sound_dsp(&a->fops, -1);
40952 + a->mix_id = register_sound_mixer(&a->mops, -1);
40953 + a->ctrl_a = 0;
40954 + a->ctrl_b = UCB_AC_B_IN_ENA|UCB_AC_B_OUT_ENA;
40955 + audio = a;
40958 + a = ucb1x00_audio_alloc(ucb);
40959 + if (a) {
40960 +#if 0
40961 + a->daa_oh_bit = UCB_IO_8;
40963 + ucb1x00_enable(ucb);
40964 + ucb1x00_io_write(ucb, a->daa_oh_bit, 0);
40965 + ucb1x00_io_set_dir(ucb, UCB_IO_7 | UCB_IO_6, a->daa_oh_bit);
40966 + ucb1x00_disable(ucb);
40967 +#endif
40969 + a->telecom = 1;
40970 + a->state.input_dma = ucb->mcp->dma_telco_rd;
40971 + a->state.input_id = "UCB1x00 telco in";
40972 + a->state.output_dma = ucb->mcp->dma_telco_wr;
40973 + a->state.output_id = "UCB1x00 telco out";
40974 + a->dev_id = register_sound_dsp(&a->fops, -1);
40975 + a->mix_id = register_sound_mixer(&a->mops, -1);
40976 + a->ctrl_a = 0;
40977 + a->ctrl_b = UCB_TC_B_IN_ENA|UCB_TC_B_OUT_ENA;
40978 + telecom = a;
40981 + return 0;
40984 +static void __exit ucb1x00_audio_exit(void)
40986 + unregister_sound_dsp(telecom->dev_id);
40987 + unregister_sound_dsp(audio->dev_id);
40988 + unregister_sound_mixer(telecom->mix_id);
40989 + unregister_sound_mixer(audio->mix_id);
40992 +module_init(ucb1x00_audio_init);
40993 +module_exit(ucb1x00_audio_exit);
40995 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
40996 +MODULE_DESCRIPTION("UCB1x00 telecom/audio driver");
40997 +MODULE_LICENSE("GPL");
40998 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
40999 +++ linux-2.4.25/drivers/misc/ucb1x00-core.c 2004-03-31 17:15:09.000000000 +0200
41000 @@ -0,0 +1,651 @@
41002 + * linux/drivers/misc/ucb1x00-core.c
41004 + * Copyright (C) 2001 Russell King, All Rights Reserved.
41006 + * This program is free software; you can redistribute it and/or modify
41007 + * it under the terms of the GNU General Public License as published by
41008 + * the Free Software Foundation; either version 2 of the License.
41010 + * The UCB1x00 core driver provides basic services for handling IO,
41011 + * the ADC, interrupts, and accessing registers. It is designed
41012 + * such that everything goes through this layer, thereby providing
41013 + * a consistent locking methodology, as well as allowing the drivers
41014 + * to be used on other non-MCP-enabled hardware platforms.
41016 + * Note that all locks are private to this file. Nothing else may
41017 + * touch them.
41018 + */
41019 +#include <linux/module.h>
41020 +#include <linux/kernel.h>
41021 +#include <linux/slab.h>
41022 +#include <linux/init.h>
41023 +#include <linux/errno.h>
41024 +#include <linux/interrupt.h>
41025 +#include <linux/pm.h>
41027 +#include <asm/dma.h>
41028 +#include <asm/hardware.h>
41029 +#include <asm/irq.h>
41030 +#include <asm/mach-types.h>
41031 +#include <asm/arch/shannon.h>
41033 +#include "ucb1x00.h"
41035 +/**
41036 + * ucb1x00_io_set_dir - set IO direction
41037 + * @ucb: UCB1x00 structure describing chip
41038 + * @in: bitfield of IO pins to be set as inputs
41039 + * @out: bitfield of IO pins to be set as outputs
41041 + * Set the IO direction of the ten general purpose IO pins on
41042 + * the UCB1x00 chip. The @in bitfield has priority over the
41043 + * @out bitfield, in that if you specify a pin as both input
41044 + * and output, it will end up as an input.
41046 + * ucb1x00_enable must have been called to enable the comms
41047 + * before using this function.
41049 + * This function takes a spinlock, disabling interrupts.
41050 + */
41051 +void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
41053 + unsigned long flags;
41055 + spin_lock_irqsave(&ucb->io_lock, flags);
41056 + ucb->io_dir |= out;
41057 + ucb->io_dir &= ~in;
41059 + ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
41060 + spin_unlock_irqrestore(&ucb->io_lock, flags);
41063 +/**
41064 + * ucb1x00_io_write - set or clear IO outputs
41065 + * @ucb: UCB1x00 structure describing chip
41066 + * @set: bitfield of IO pins to set to logic '1'
41067 + * @clear: bitfield of IO pins to set to logic '0'
41069 + * Set the IO output state of the specified IO pins. The value
41070 + * is retained if the pins are subsequently configured as inputs.
41071 + * The @clear bitfield has priority over the @set bitfield -
41072 + * outputs will be cleared.
41074 + * ucb1x00_enable must have been called to enable the comms
41075 + * before using this function.
41077 + * This function takes a spinlock, disabling interrupts.
41078 + */
41079 +void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
41081 + unsigned long flags;
41083 + spin_lock_irqsave(&ucb->io_lock, flags);
41084 + ucb->io_out |= set;
41085 + ucb->io_out &= ~clear;
41087 + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
41088 + spin_unlock_irqrestore(&ucb->io_lock, flags);
41091 +/**
41092 + * ucb1x00_io_read - read the current state of the IO pins
41093 + * @ucb: UCB1x00 structure describing chip
41095 + * Return a bitfield describing the logic state of the ten
41096 + * general purpose IO pins.
41098 + * ucb1x00_enable must have been called to enable the comms
41099 + * before using this function.
41101 + * This function does not take any semaphores or spinlocks.
41102 + */
41103 +unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
41105 + return ucb1x00_reg_read(ucb, UCB_IO_DATA);
41109 + * UCB1300 data sheet says we must:
41110 + * 1. enable ADC => 5us (including reference startup time)
41111 + * 2. select input => 51*tsibclk => 4.3us
41112 + * 3. start conversion => 102*tsibclk => 8.5us
41113 + * (tsibclk = 1/11981000)
41114 + * Period between SIB 128-bit frames = 10.7us
41115 + */
41117 +/**
41118 + * ucb1x00_adc_enable - enable the ADC converter
41119 + * @ucb: UCB1x00 structure describing chip
41121 + * Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
41122 + * Any code wishing to use the ADC converter must call this
41123 + * function prior to using it.
41125 + * This function takes the ADC semaphore to prevent two or more
41126 + * concurrent uses, and therefore may sleep. As a result, it
41127 + * can only be called from process context, not interrupt
41128 + * context.
41130 + * You should release the ADC as soon as possible using
41131 + * ucb1x00_adc_disable.
41132 + */
41133 +void ucb1x00_adc_enable(struct ucb1x00 *ucb)
41135 + down(&ucb->adc_sem);
41137 + ucb->adc_cr |= UCB_ADC_ENA;
41139 + ucb1x00_enable(ucb);
41140 + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
41143 +/**
41144 + * ucb1x00_adc_read - read the specified ADC channel
41145 + * @ucb: UCB1x00 structure describing chip
41146 + * @adc_channel: ADC channel mask
41147 + * @sync: wait for syncronisation pulse.
41149 + * Start an ADC conversion and wait for the result. Note that
41150 + * synchronised ADC conversions (via the ADCSYNC pin) must wait
41151 + * until the trigger is asserted and the conversion is finished.
41153 + * This function currently spins waiting for the conversion to
41154 + * complete (2 frames max without sync).
41156 + * If called for a synchronised ADC conversion, it may sleep
41157 + * with the ADC semaphore held.
41158 + */
41159 +unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
41161 + unsigned int val;
41163 + if (sync)
41164 + adc_channel |= UCB_ADC_SYNC_ENA;
41166 + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
41167 + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
41169 + for (;;) {
41170 + val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
41171 + if (val & UCB_ADC_DAT_VAL)
41172 + break;
41173 + /* yield to other processes */
41174 + set_current_state(TASK_INTERRUPTIBLE);
41175 + schedule_timeout(1);
41178 + return UCB_ADC_DAT(val);
41181 +/**
41182 + * ucb1x00_adc_disable - disable the ADC converter
41183 + * @ucb: UCB1x00 structure describing chip
41185 + * Disable the ADC converter and release the ADC semaphore.
41186 + */
41187 +void ucb1x00_adc_disable(struct ucb1x00 *ucb)
41189 + ucb->adc_cr &= ~UCB_ADC_ENA;
41190 + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
41191 + ucb1x00_disable(ucb);
41193 + up(&ucb->adc_sem);
41196 +#ifdef CONFIG_PM
41197 +static int ucb1x00_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
41199 + struct ucb1x00 *ucb = (struct ucb1x00 *)dev->data;
41200 + unsigned int isr;
41202 + if (rqst == PM_RESUME) {
41203 + ucb1x00_enable(ucb);
41204 + isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
41205 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
41206 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
41207 + ucb1x00_disable(ucb);
41210 + return 0;
41212 +#endif
41215 + * UCB1x00 Interrupt handling.
41217 + * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
41218 + * Since we need to read an internal register, we must re-enable
41219 + * SIBCLK to talk to the chip. We leave the clock running until
41220 + * we have finished processing all interrupts from the chip.
41221 + */
41222 +static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
41224 + struct ucb1x00 *ucb = devid;
41225 + struct ucb1x00_irq *irq;
41226 + unsigned int isr, i;
41228 + ucb1x00_enable(ucb);
41229 + isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
41230 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
41231 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
41233 + for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
41234 + if (isr & 1 && irq->fn)
41235 + irq->fn(i, irq->devid);
41236 + ucb1x00_disable(ucb);
41239 +/**
41240 + * ucb1x00_hook_irq - hook a UCB1x00 interrupt
41241 + * @ucb: UCB1x00 structure describing chip
41242 + * @idx: interrupt index
41243 + * @fn: function to call when interrupt is triggered
41244 + * @devid: device id to pass to interrupt handler
41246 + * Hook the specified interrupt. You can only register one handler
41247 + * for each interrupt source. The interrupt source is not enabled
41248 + * by this function; use ucb1x00_enable_irq instead.
41250 + * Interrupt handlers will be called with other interrupts enabled.
41252 + * Returns zero on success, or one of the following errors:
41253 + * -EINVAL if the interrupt index is invalid
41254 + * -EBUSY if the interrupt has already been hooked
41255 + */
41256 +int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
41258 + struct ucb1x00_irq *irq;
41259 + int ret = -EINVAL;
41261 + if (idx < 16) {
41262 + irq = ucb->irq_handler + idx;
41263 + ret = -EBUSY;
41265 + spin_lock_irq(&ucb->lock);
41266 + if (irq->fn == NULL) {
41267 + irq->devid = devid;
41268 + irq->fn = fn;
41269 + ret = 0;
41271 + spin_unlock_irq(&ucb->lock);
41273 + return ret;
41276 +/**
41277 + * ucb1x00_enable_irq - enable an UCB1x00 interrupt source
41278 + * @ucb: UCB1x00 structure describing chip
41279 + * @idx: interrupt index
41280 + * @edges: interrupt edges to enable
41282 + * Enable the specified interrupt to trigger on %UCB_RISING,
41283 + * %UCB_FALLING or both edges. The interrupt should have been
41284 + * hooked by ucb1x00_hook_irq.
41285 + */
41286 +void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
41288 + unsigned long flags;
41290 + if (idx < 16) {
41291 + spin_lock_irqsave(&ucb->lock, flags);
41293 + ucb1x00_enable(ucb);
41294 + if (edges & UCB_RISING) {
41295 + ucb->irq_ris_enbl |= 1 << idx;
41296 + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
41298 + if (edges & UCB_FALLING) {
41299 + ucb->irq_fal_enbl |= 1 << idx;
41300 + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
41302 + ucb1x00_disable(ucb);
41303 + spin_unlock_irqrestore(&ucb->lock, flags);
41307 +/**
41308 + * ucb1x00_disable_irq - disable an UCB1x00 interrupt source
41309 + * @ucb: UCB1x00 structure describing chip
41310 + * @edges: interrupt edges to disable
41312 + * Disable the specified interrupt triggering on the specified
41313 + * (%UCB_RISING, %UCB_FALLING or both) edges.
41314 + */
41315 +void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
41317 + unsigned long flags;
41319 + if (idx < 16) {
41320 + spin_lock_irqsave(&ucb->lock, flags);
41322 + ucb1x00_enable(ucb);
41323 + if (edges & UCB_RISING) {
41324 + ucb->irq_ris_enbl &= ~(1 << idx);
41325 + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
41327 + if (edges & UCB_FALLING) {
41328 + ucb->irq_fal_enbl &= ~(1 << idx);
41329 + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
41331 + ucb1x00_disable(ucb);
41332 + spin_unlock_irqrestore(&ucb->lock, flags);
41336 +/**
41337 + * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
41338 + * @ucb: UCB1x00 structure describing chip
41339 + * @idx: interrupt index
41340 + * @devid: device id.
41342 + * Disable the interrupt source and remove the handler. devid must
41343 + * match the devid passed when hooking the interrupt.
41345 + * Returns zero on success, or one of the following errors:
41346 + * -EINVAL if the interrupt index is invalid
41347 + * -ENOENT if devid does not match
41348 + */
41349 +int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
41351 + struct ucb1x00_irq *irq;
41352 + int ret;
41354 + if (idx >= 16)
41355 + goto bad;
41357 + irq = ucb->irq_handler + idx;
41358 + ret = -ENOENT;
41360 + spin_lock_irq(&ucb->lock);
41361 + if (irq->devid == devid) {
41362 + ucb->irq_ris_enbl &= ~(1 << idx);
41363 + ucb->irq_fal_enbl &= ~(1 << idx);
41365 + ucb1x00_enable(ucb);
41366 + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
41367 + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
41368 + ucb1x00_disable(ucb);
41370 + irq->fn = NULL;
41371 + irq->devid = NULL;
41372 + ret = 0;
41374 + spin_unlock_irq(&ucb->lock);
41375 + return ret;
41377 +bad:
41378 + printk(KERN_ERR "%s: freeing bad irq %d\n", __FUNCTION__, idx);
41379 + return -EINVAL;
41383 + * Try to probe our interrupt, rather than relying on lots of
41384 + * hard-coded machine dependencies. For reference, the expected
41385 + * IRQ mappings are:
41387 + * Machine Default IRQ
41388 + * adsbitsy IRQ_GPCIN4
41389 + * cerf IRQ_GPIO_UCB1200_IRQ
41390 + * flexanet IRQ_GPIO_GUI
41391 + * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ
41392 + * graphicsclient IRQ_GRAPHICSCLIENT_UCB1200
41393 + * graphicsmaster IRQ_GRAPHICSMASTER_UCB1200
41394 + * lart LART_IRQ_UCB1200
41395 + * omnimeter IRQ_GPIO23
41396 + * pfs168 IRQ_GPIO_UCB1300_IRQ
41397 + * simpad IRQ_GPIO_UCB1300_IRQ
41398 + * shannon SHANNON_IRQ_GPIO_IRQ_CODEC
41399 + * yopy IRQ_GPIO_UCB1200_IRQ
41400 + */
41401 +static int __init ucb1x00_detect_irq(struct ucb1x00 *ucb)
41403 + unsigned long mask;
41405 + mask = probe_irq_on();
41406 + if (!mask)
41407 + return NO_IRQ;
41409 + /*
41410 + * Enable the ADC interrupt.
41411 + */
41412 + ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
41413 + ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
41414 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
41415 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
41417 + /*
41418 + * Cause an ADC interrupt.
41419 + */
41420 + ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
41421 + ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
41423 + /*
41424 + * Wait for the conversion to complete.
41425 + */
41426 + while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
41427 + ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
41429 + /*
41430 + * Disable and clear interrupt.
41431 + */
41432 + ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
41433 + ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
41434 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
41435 + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
41437 + /*
41438 + * Read triggered interrupt.
41439 + */
41440 + return probe_irq_off(mask);
41444 + * This configures the UCB1x00 layer depending on the machine type
41445 + * we're running on. The UCB1x00 drivers should not contain any
41446 + * machine dependencies.
41448 + * We can get rid of some of these dependencies by using existing
41449 + * facilities provided by the kernel - namely IRQ probing. The
41450 + * machine specific files are expected to setup the IRQ levels on
41451 + * initialisation. With any luck, we'll get rid of all the
41452 + * machine dependencies here.
41453 + */
41454 +static int __init ucb1x00_configure(struct ucb1x00 *ucb)
41456 + unsigned int irq_gpio_pin = 0;
41457 + int irq, default_irq = NO_IRQ;
41459 + if (machine_is_adsbitsy())
41460 + default_irq = IRQ_GPCIN4;
41462 +// if (machine_is_assabet())
41463 +// default_irq = IRQ_GPIO23;
41465 +#ifdef CONFIG_SA1100_CERF
41466 + if (machine_is_cerf())
41467 + default_irq = IRQ_GPIO_UCB1200_IRQ;
41468 +#endif
41469 +#ifdef CONFIG_SA1100_FREEBIRD
41470 + if (machine_is_freebird())
41471 + default_irq = IRQ_GPIO_FREEBIRD_UCB1300_IRQ;
41472 +#endif
41473 +#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
41474 +// if (machine_is_graphicsclient())
41475 +// default_irq = IRQ_GRAPHICSCLIENT_UCB1200;
41476 +#endif
41477 +#if defined(CONFIG_SA1100_GRAPICSMASTER)
41478 + if (machine_is_graphicsmaster())
41479 + default_irq = IRQ_GRAPHICSMASTER_UCB1200;
41480 +#endif
41481 +#ifdef CONFIG_SA1100_LART
41482 + if (machine_is_lart()) {
41483 + default_irq = LART_IRQ_UCB1200;
41484 + irq_gpio_pin = LART_GPIO_UCB1200;
41486 +#endif
41487 + if (machine_is_omnimeter())
41488 + default_irq = IRQ_GPIO23;
41490 +#ifdef CONFIG_SA1100_PFS168
41491 + if (machine_is_pfs168())
41492 + default_irq = IRQ_GPIO_UCB1300_IRQ;
41493 +#endif
41494 +#ifdef CONFIG_SA1100_SIMPAD
41495 + if (machine_is_simpad())
41496 + default_irq = IRQ_GPIO_UCB1300_IRQ;
41497 +#endif
41498 +#ifdef CONFIG_SA1100_SIMPUTER
41499 + if (machine_is_simputer()) {
41500 + default_irq = IRQ_GPIO_UCB1300_IRQ;
41501 + irq_gpio_pin = GPIO_UCB1300_IRQ;
41503 +#endif
41504 + if (machine_is_shannon())
41505 + default_irq = SHANNON_IRQ_GPIO_IRQ_CODEC;
41506 +#ifdef CONFIG_SA1100_YOPY
41507 + if (machine_is_yopy())
41508 + default_irq = IRQ_GPIO_UCB1200_IRQ;
41509 +#endif
41510 +#ifdef CONFIG_SA1100_ACCELENT
41511 + if (machine_is_accelent_sa()) {
41512 + ucb->irq = IRQ_GPIO_UCB1200_IRQ;
41513 + irq_gpio_pin = GPIO_UCB1200_IRQ;
41515 +#endif
41517 + /*
41518 + * Eventually, this will disappear.
41519 + */
41520 + if (irq_gpio_pin)
41521 + set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
41523 + irq = ucb1x00_detect_irq(ucb);
41524 + if (irq != NO_IRQ) {
41525 + if (default_irq != NO_IRQ && irq != default_irq)
41526 + printk(KERN_ERR "UCB1x00: probed IRQ%d != default IRQ%d\n",
41527 + irq, default_irq);
41528 + if (irq == default_irq)
41529 + printk(KERN_ERR "UCB1x00: probed IRQ%d correctly. "
41530 + "Please remove machine dependencies from "
41531 + "ucb1x00-core.c\n", irq);
41532 + ucb->irq = irq;
41533 + } else {
41534 + printk(KERN_ERR "UCB1x00: IRQ probe failed, using IRQ%d\n",
41535 + default_irq);
41536 + ucb->irq = default_irq;
41539 + return ucb->irq == NO_IRQ ? -ENODEV : 0;
41542 +struct ucb1x00 *my_ucb;
41544 +/**
41545 + * ucb1x00_get - get the UCB1x00 structure describing a chip
41546 + * @ucb: UCB1x00 structure describing chip
41548 + * Return the UCB1x00 structure describing a chip.
41550 + * FIXME: Currently very noddy indeed, which currently doesn't
41551 + * matter since we only support one chip.
41552 + */
41553 +struct ucb1x00 *ucb1x00_get(void)
41555 + return my_ucb;
41558 +static int __init ucb1x00_init(void)
41560 + struct mcp *mcp;
41561 + unsigned int id;
41562 + int ret = -ENODEV;
41564 + mcp = mcp_get();
41565 + if (!mcp)
41566 + goto no_mcp;
41568 + mcp_enable(mcp);
41569 + id = mcp_reg_read(mcp, UCB_ID);
41571 + if (id != UCB_ID_1200 && id != UCB_ID_1300) {
41572 + printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
41573 + goto out;
41576 + my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
41577 + ret = -ENOMEM;
41578 + if (!my_ucb)
41579 + goto out;
41581 + if (machine_is_shannon()) {
41582 + /* reset the codec */
41583 + GPDR |= SHANNON_GPIO_CODEC_RESET;
41584 + GPCR = SHANNON_GPIO_CODEC_RESET;
41585 + GPSR = SHANNON_GPIO_CODEC_RESET;
41589 + memset(my_ucb, 0, sizeof(struct ucb1x00));
41591 + spin_lock_init(&my_ucb->lock);
41592 + spin_lock_init(&my_ucb->io_lock);
41593 + sema_init(&my_ucb->adc_sem, 1);
41595 + my_ucb->id = id;
41596 + my_ucb->mcp = mcp;
41598 + ret = ucb1x00_configure(my_ucb);
41599 + if (ret)
41600 + goto out;
41602 + ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);
41603 + if (ret) {
41604 + printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
41605 + my_ucb->irq, ret);
41606 + kfree(my_ucb);
41607 + my_ucb = NULL;
41608 + goto out;
41611 +#ifdef CONFIG_PM
41612 + my_ucb->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_pm);
41613 + if (my_ucb->pmdev == NULL)
41614 + printk("ucb1x00: unable to register in PM.\n");
41615 + else
41616 + my_ucb->pmdev->data = my_ucb;
41617 +#endif
41619 +out:
41620 + mcp_disable(mcp);
41621 +no_mcp:
41622 + return ret;
41625 +static void __exit ucb1x00_exit(void)
41627 + free_irq(my_ucb->irq, my_ucb);
41628 + kfree(my_ucb);
41631 +module_init(ucb1x00_init);
41632 +module_exit(ucb1x00_exit);
41634 +EXPORT_SYMBOL(ucb1x00_get);
41636 +EXPORT_SYMBOL(ucb1x00_io_set_dir);
41637 +EXPORT_SYMBOL(ucb1x00_io_write);
41638 +EXPORT_SYMBOL(ucb1x00_io_read);
41640 +EXPORT_SYMBOL(ucb1x00_adc_enable);
41641 +EXPORT_SYMBOL(ucb1x00_adc_read);
41642 +EXPORT_SYMBOL(ucb1x00_adc_disable);
41644 +EXPORT_SYMBOL(ucb1x00_hook_irq);
41645 +EXPORT_SYMBOL(ucb1x00_free_irq);
41646 +EXPORT_SYMBOL(ucb1x00_enable_irq);
41647 +EXPORT_SYMBOL(ucb1x00_disable_irq);
41649 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
41650 +MODULE_DESCRIPTION("UCB1x00 core driver");
41651 +MODULE_LICENSE("GPL");
41652 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
41653 +++ linux-2.4.25/drivers/misc/ucb1x00-ts.c 2004-03-31 17:15:09.000000000 +0200
41654 @@ -0,0 +1,664 @@
41656 + * linux/drivers/misc/ucb1x00-ts.c
41658 + * Copyright (C) 2001 Russell King, All Rights Reserved.
41660 + * This program is free software; you can redistribute it and/or modify
41661 + * it under the terms of the GNU General Public License version 2 as
41662 + * published by the Free Software Foundation.
41664 + * 21-Jan-2002 <jco@ict.es> :
41666 + * Added support for synchronous A/D mode. This mode is useful to
41667 + * avoid noise induced in the touchpanel by the LCD, provided that
41668 + * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
41669 + * It is important to note that the signal connected to the ADCSYNC
41670 + * pin should provide pulses even when the LCD is blanked, otherwise
41671 + * a pen touch needed to unblank the LCD will never be read.
41672 + */
41673 +#include <linux/config.h>
41674 +#include <linux/module.h>
41675 +#include <linux/init.h>
41676 +#include <linux/smp.h>
41677 +#include <linux/smp_lock.h>
41678 +#include <linux/sched.h>
41679 +#include <linux/completion.h>
41680 +#include <linux/delay.h>
41681 +#include <linux/string.h>
41682 +#include <linux/pm.h>
41684 +#include <asm/dma.h>
41685 +#include <asm/semaphore.h>
41687 +#include "ucb1x00.h"
41690 + * Define this if you want the UCB1x00 stuff to talk to the input layer
41691 + */
41692 +#undef USE_INPUT
41694 +#ifndef USE_INPUT
41696 +#include <linux/fs.h>
41697 +#include <linux/miscdevice.h>
41698 +#include <linux/poll.h>
41701 + * This structure is nonsense - millisecs is not very useful
41702 + * since the field size is too small. Also, we SHOULD NOT
41703 + * be exposing jiffies to user space directly.
41704 + */
41705 +struct ts_event {
41706 + u16 pressure;
41707 + u16 x;
41708 + u16 y;
41709 + u16 pad;
41710 + struct timeval stamp;
41713 +#define NR_EVENTS 16
41715 +#else
41717 +#include <linux/input.h>
41719 +#endif
41721 +struct ucb1x00_ts {
41722 +#ifdef USE_INPUT
41723 + struct input_dev idev;
41724 +#endif
41725 + struct ucb1x00 *ucb;
41726 +#ifdef CONFIG_PM
41727 + struct pm_dev *pmdev;
41728 +#endif
41730 + wait_queue_head_t irq_wait;
41731 + struct semaphore sem;
41732 + struct completion init_exit;
41733 + struct task_struct *rtask;
41734 + int use_count;
41735 + u16 x_res;
41736 + u16 y_res;
41738 +#ifndef USE_INPUT
41739 + struct fasync_struct *fasync;
41740 + wait_queue_head_t read_wait;
41741 + u8 evt_head;
41742 + u8 evt_tail;
41743 + struct ts_event events[NR_EVENTS];
41744 +#endif
41745 + int restart:1;
41746 + int adcsync:1;
41749 +static struct ucb1x00_ts ucbts;
41750 +static int adcsync = UCB_NOSYNC;
41752 +static int ucb1x00_ts_startup(struct ucb1x00_ts *ts);
41753 +static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts);
41755 +#ifndef USE_INPUT
41757 +#define ucb1x00_ts_evt_pending(ts) ((volatile u8)(ts)->evt_head != (ts)->evt_tail)
41758 +#define ucb1x00_ts_evt_get(ts) ((ts)->events + (ts)->evt_tail)
41759 +#define ucb1x00_ts_evt_pull(ts) ((ts)->evt_tail = ((ts)->evt_tail + 1) & (NR_EVENTS - 1))
41760 +#define ucb1x00_ts_evt_clear(ts) ((ts)->evt_head = (ts)->evt_tail = 0)
41762 +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
41764 + int next_head;
41766 + next_head = (ts->evt_head + 1) & (NR_EVENTS - 1);
41767 + if (next_head != ts->evt_tail) {
41768 + ts->events[ts->evt_head].pressure = pressure;
41769 + ts->events[ts->evt_head].x = x;
41770 + ts->events[ts->evt_head].y = y;
41771 + do_gettimeofday(&ts->events[ts->evt_head].stamp);
41772 + ts->evt_head = next_head;
41774 + if (ts->fasync)
41775 + kill_fasync(&ts->fasync, SIGIO, POLL_IN);
41776 + wake_up_interruptible(&ts->read_wait);
41780 +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
41782 + ucb1x00_ts_evt_add(ts, 0, 0, 0);
41786 + * User space driver interface.
41787 + */
41788 +static ssize_t
41789 +ucb1x00_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
41791 + DECLARE_WAITQUEUE(wait, current);
41792 + struct ucb1x00_ts *ts = filp->private_data;
41793 + char *ptr = buffer;
41794 + int err = 0;
41796 + add_wait_queue(&ts->read_wait, &wait);
41797 + while (count >= sizeof(struct ts_event)) {
41798 + err = -ERESTARTSYS;
41799 + if (signal_pending(current))
41800 + break;
41802 + if (ucb1x00_ts_evt_pending(ts)) {
41803 + struct ts_event *evt = ucb1x00_ts_evt_get(ts);
41805 + err = copy_to_user(ptr, evt, sizeof(struct ts_event));
41806 + ucb1x00_ts_evt_pull(ts);
41808 + if (err)
41809 + break;
41811 + ptr += sizeof(struct ts_event);
41812 + count -= sizeof(struct ts_event);
41813 + continue;
41816 + set_current_state(TASK_INTERRUPTIBLE);
41817 + err = -EAGAIN;
41818 + if (filp->f_flags & O_NONBLOCK)
41819 + break;
41820 + schedule();
41822 + current->state = TASK_RUNNING;
41823 + remove_wait_queue(&ts->read_wait, &wait);
41825 + return ptr == buffer ? err : ptr - buffer;
41828 +static unsigned int ucb1x00_ts_poll(struct file *filp, poll_table *wait)
41830 + struct ucb1x00_ts *ts = filp->private_data;
41831 + int ret = 0;
41833 + poll_wait(filp, &ts->read_wait, wait);
41834 + if (ucb1x00_ts_evt_pending(ts))
41835 + ret = POLLIN | POLLRDNORM;
41837 + return ret;
41840 +static int ucb1x00_ts_fasync(int fd, struct file *filp, int on)
41842 + struct ucb1x00_ts *ts = filp->private_data;
41844 + return fasync_helper(fd, filp, on, &ts->fasync);
41847 +static int ucb1x00_ts_open(struct inode *inode, struct file *filp)
41849 + struct ucb1x00_ts *ts = &ucbts;
41850 + int ret = 0;
41852 + ret = ucb1x00_ts_startup(ts);
41853 + if (ret == 0)
41854 + filp->private_data = ts;
41856 + return ret;
41860 + * Release touchscreen resources. Disable IRQs.
41861 + */
41862 +static int ucb1x00_ts_release(struct inode *inode, struct file *filp)
41864 + struct ucb1x00_ts *ts = filp->private_data;
41866 + down(&ts->sem);
41867 + ucb1x00_ts_fasync(-1, filp, 0);
41868 + ucb1x00_ts_shutdown(ts);
41869 + up(&ts->sem);
41871 + return 0;
41874 +static struct file_operations ucb1x00_fops = {
41875 + owner: THIS_MODULE,
41876 + read: ucb1x00_ts_read,
41877 + poll: ucb1x00_ts_poll,
41878 + open: ucb1x00_ts_open,
41879 + release: ucb1x00_ts_release,
41880 + fasync: ucb1x00_ts_fasync,
41884 + * The official UCB1x00 touchscreen is a miscdevice:
41885 + * 10 char Non-serial mice, misc features
41886 + * 14 = /dev/touchscreen/ucb1x00 UCB 1x00 touchscreen
41887 + */
41888 +static struct miscdevice ucb1x00_ts_dev = {
41889 + minor: 14,
41890 + name: "touchscreen/ucb1x00",
41891 + fops: &ucb1x00_fops,
41894 +static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
41896 + init_waitqueue_head(&ts->read_wait);
41897 + return misc_register(&ucb1x00_ts_dev);
41900 +static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
41902 + misc_deregister(&ucb1x00_ts_dev);
41905 +#else
41907 +#define ucb1x00_ts_evt_clear(ts) do { } while (0)
41909 +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
41911 + input_report_abs(&ts->idev, ABS_X, x);
41912 + input_report_abs(&ts->idev, ABS_Y, y);
41913 + input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
41916 +static int ucb1x00_ts_open(struct input_dev *idev)
41918 + struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
41920 + return ucb1x00_ts_startup(ts);
41923 +static void ucb1x00_ts_close(struct input_dev *idev)
41925 + struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
41927 + down(&ts->sem);
41928 + ucb1x00_ts_shutdown(ts);
41929 + up(&ts->sem);
41932 +static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
41934 + ts->idev.name = "Touchscreen panel";
41935 + ts->idev.idproduct = ts->ucb->id;
41936 + ts->idev.open = ucb1x00_ts_open;
41937 + ts->idev.close = ucb1x00_ts_close;
41939 + __set_bit(EV_ABS, ts->idev.evbit);
41940 + __set_bit(ABS_X, ts->idev.absbit);
41941 + __set_bit(ABS_Y, ts->idev.absbit);
41942 + __set_bit(ABS_PRESSURE, ts->idev.absbit);
41944 + input_register_device(&ts->idev);
41946 + return 0;
41949 +static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
41951 + input_unregister_device(&ts->idev);
41954 +#endif
41957 + * Switch to interrupt mode.
41958 + */
41959 +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
41961 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
41962 + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
41963 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
41964 + UCB_TS_CR_MODE_INT);
41968 + * Switch to pressure mode, and read pressure. We don't need to wait
41969 + * here, since both plates are being driven.
41970 + */
41971 +static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
41973 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
41974 + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
41975 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
41976 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
41978 + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
41982 + * Switch to X position mode and measure Y plate. We switch the plate
41983 + * configuration in pressure mode, then switch to position mode. This
41984 + * gives a faster response time. Even so, we need to wait about 55us
41985 + * for things to stabilise.
41986 + */
41987 +static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
41989 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
41990 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
41991 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
41992 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
41993 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
41994 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
41995 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
41996 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
41997 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
41999 + udelay(55);
42001 + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
42005 + * Switch to Y position mode and measure X plate. We switch the plate
42006 + * configuration in pressure mode, then switch to position mode. This
42007 + * gives a faster response time. Even so, we need to wait about 55us
42008 + * for things to stabilise.
42009 + */
42010 +static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
42012 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
42013 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
42014 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
42015 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
42016 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
42017 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
42018 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
42019 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
42020 + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
42022 + udelay(55);
42024 + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
42028 + * Switch to X plate resistance mode. Set MX to ground, PX to
42029 + * supply. Measure current.
42030 + */
42031 +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
42033 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
42034 + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
42035 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
42036 + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
42040 + * Switch to Y plate resistance mode. Set MY to ground, PY to
42041 + * supply. Measure current.
42042 + */
42043 +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
42045 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
42046 + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
42047 + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
42048 + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
42052 + * This is a RT kernel thread that handles the ADC accesses
42053 + * (mainly so we can use semaphores in the UCB1200 core code
42054 + * to serialise accesses to the ADC).
42055 + */
42056 +static int ucb1x00_thread(void *_ts)
42058 + struct ucb1x00_ts *ts = _ts;
42059 + struct task_struct *tsk = current;
42060 + DECLARE_WAITQUEUE(wait, tsk);
42061 + int valid;
42063 + ts->rtask = tsk;
42065 + daemonize();
42066 + reparent_to_init();
42067 + strcpy(tsk->comm, "ktsd");
42068 + tsk->tty = NULL;
42069 + /*
42070 + * We could run as a real-time thread. However, thus far
42071 + * this doesn't seem to be necessary.
42072 + */
42073 +// tsk->policy = SCHED_FIFO;
42074 +// tsk->rt_priority = 1;
42076 + /* only want to receive SIGKILL */
42077 + spin_lock_irq(&tsk->sigmask_lock);
42078 + siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
42079 + recalc_sigpending(tsk);
42080 + spin_unlock_irq(&tsk->sigmask_lock);
42082 + complete(&ts->init_exit);
42084 + valid = 0;
42086 + add_wait_queue(&ts->irq_wait, &wait);
42087 + for (;;) {
42088 + unsigned int x, y, p, val;
42089 + signed long timeout;
42091 + ts->restart = 0;
42093 + ucb1x00_adc_enable(ts->ucb);
42095 + x = ucb1x00_ts_read_xpos(ts);
42096 + y = ucb1x00_ts_read_ypos(ts);
42097 + p = ucb1x00_ts_read_pressure(ts);
42099 + /*
42100 + * Switch back to interrupt mode.
42101 + */
42102 + ucb1x00_ts_mode_int(ts);
42103 + ucb1x00_adc_disable(ts->ucb);
42105 + set_task_state(tsk, TASK_UNINTERRUPTIBLE);
42106 + schedule_timeout(HZ / 100);
42107 + if (signal_pending(tsk))
42108 + break;
42110 + ucb1x00_enable(ts->ucb);
42111 + val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
42113 + if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
42114 + set_task_state(tsk, TASK_INTERRUPTIBLE);
42116 + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
42117 + ucb1x00_disable(ts->ucb);
42119 + /*
42120 + * If we spat out a valid sample set last time,
42121 + * spit out a "pen off" sample here.
42122 + */
42123 + if (valid) {
42124 + ucb1x00_ts_event_release(ts);
42125 + valid = 0;
42128 + timeout = MAX_SCHEDULE_TIMEOUT;
42129 + } else {
42130 + ucb1x00_disable(ts->ucb);
42132 + /*
42133 + * Filtering is policy. Policy belongs in user
42134 + * space. We therefore leave it to user space
42135 + * to do any filtering they please.
42136 + */
42137 + if (!ts->restart) {
42138 + ucb1x00_ts_evt_add(ts, p, x, y);
42139 + valid = 1;
42142 + set_task_state(tsk, TASK_INTERRUPTIBLE);
42143 + timeout = HZ / 100;
42146 + schedule_timeout(timeout);
42147 + if (signal_pending(tsk))
42148 + break;
42151 + remove_wait_queue(&ts->irq_wait, &wait);
42153 + ts->rtask = NULL;
42154 + ucb1x00_ts_evt_clear(ts);
42155 + complete_and_exit(&ts->init_exit, 0);
42159 + * We only detect touch screen _touches_ with this interrupt
42160 + * handler, and even then we just schedule our task.
42161 + */
42162 +static void ucb1x00_ts_irq(int idx, void *id)
42164 + struct ucb1x00_ts *ts = id;
42165 + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
42166 + wake_up(&ts->irq_wait);
42169 +static int ucb1x00_ts_startup(struct ucb1x00_ts *ts)
42171 + int ret = 0;
42173 + if (down_interruptible(&ts->sem))
42174 + return -EINTR;
42176 + if (ts->use_count++ != 0)
42177 + goto out;
42179 + if (ts->rtask)
42180 + panic("ucb1x00: rtask running?");
42182 + init_waitqueue_head(&ts->irq_wait);
42183 + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
42184 + if (ret < 0)
42185 + goto out;
42187 + /*
42188 + * If we do this at all, we should allow the user to
42189 + * measure and read the X and Y resistance at any time.
42190 + */
42191 + ucb1x00_adc_enable(ts->ucb);
42192 + ts->x_res = ucb1x00_ts_read_xres(ts);
42193 + ts->y_res = ucb1x00_ts_read_yres(ts);
42194 + ucb1x00_adc_disable(ts->ucb);
42196 + init_completion(&ts->init_exit);
42197 + ret = kernel_thread(ucb1x00_thread, ts, 0);
42198 + if (ret >= 0) {
42199 + wait_for_completion(&ts->init_exit);
42200 + ret = 0;
42201 + } else {
42202 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
42205 + out:
42206 + if (ret)
42207 + ts->use_count--;
42208 + up(&ts->sem);
42209 + return ret;
42213 + * Release touchscreen resources. Disable IRQs.
42214 + */
42215 +static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts)
42217 + if (--ts->use_count == 0) {
42218 + if (ts->rtask) {
42219 + send_sig(SIGKILL, ts->rtask, 1);
42220 + wait_for_completion(&ts->init_exit);
42223 + ucb1x00_enable(ts->ucb);
42224 + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
42225 + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
42226 + ucb1x00_disable(ts->ucb);
42230 +#ifdef CONFIG_PM
42231 +static int ucb1x00_ts_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
42233 + struct ucb1x00_ts *ts = (struct ucb1x00_ts *) (dev->data);
42235 + if (rqst == PM_RESUME && ts->rtask != NULL) {
42236 + /*
42237 + * Restart the TS thread to ensure the
42238 + * TS interrupt mode is set up again
42239 + * after sleep.
42240 + */
42241 + ts->restart = 1;
42242 + wake_up(&ts->irq_wait);
42244 + return 0;
42246 +#endif
42250 + * Initialisation.
42251 + */
42252 +static int __init ucb1x00_ts_init(void)
42254 + struct ucb1x00_ts *ts = &ucbts;
42256 + ts->ucb = ucb1x00_get();
42257 + if (!ts->ucb)
42258 + return -ENODEV;
42260 + ts->adcsync = adcsync;
42261 + init_MUTEX(&ts->sem);
42263 +#ifdef CONFIG_PM
42264 + ts->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_ts_pm);
42265 + if (ts->pmdev == NULL)
42266 + printk("ucb1x00_ts: unable to register in PM.\n");
42267 + else
42268 + ts->pmdev->data = ts;
42269 +#endif
42270 + return ucb1x00_ts_register(ts);
42273 +static void __exit ucb1x00_ts_exit(void)
42275 + struct ucb1x00_ts *ts = &ucbts;
42277 + ucb1x00_ts_deregister(ts);
42279 +#ifdef CONFIG_PM
42280 + if (ts->pmdev)
42281 + pm_unregister(ts->pmdev);
42282 +#endif
42285 +#ifndef MODULE
42288 + * Parse kernel command-line options.
42290 + * syntax : ucbts=[sync|nosync],...
42291 + */
42292 +static int __init ucb1x00_ts_setup(char *str)
42294 + char *p;
42296 + while ((p = strsep(&str, ",")) != NULL) {
42297 + if (strcmp(p, "sync") == 0)
42298 + adcsync = UCB_SYNC;
42301 + return 1;
42304 +__setup("ucbts=", ucb1x00_ts_setup);
42306 +#else
42308 +MODULE_PARM(adcsync, "i");
42309 +MODULE_PARM_DESC(adcsync, "Enable use of ADCSYNC signal");
42311 +#endif
42313 +module_init(ucb1x00_ts_init);
42314 +module_exit(ucb1x00_ts_exit);
42316 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
42317 +MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
42318 +MODULE_LICENSE("GPL");
42319 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
42320 +++ linux-2.4.25/drivers/misc/ucb1x00.h 2004-03-31 17:15:09.000000000 +0200
42321 @@ -0,0 +1,232 @@
42323 + * linux/drivers/misc/ucb1x00.h
42325 + * Copyright (C) 2001 Russell King, All Rights Reserved.
42327 + * This program is free software; you can redistribute it and/or modify
42328 + * it under the terms of the GNU General Public License as published by
42329 + * the Free Software Foundation; either version 2 of the License.
42330 + */
42331 +#ifndef UCB1200_H
42332 +#define UCB1200_H
42334 +#define UCB_IO_DATA 0x00
42335 +#define UCB_IO_DIR 0x01
42337 +#define UCB_IO_0 (1 << 0)
42338 +#define UCB_IO_1 (1 << 1)
42339 +#define UCB_IO_2 (1 << 2)
42340 +#define UCB_IO_3 (1 << 3)
42341 +#define UCB_IO_4 (1 << 4)
42342 +#define UCB_IO_5 (1 << 5)
42343 +#define UCB_IO_6 (1 << 6)
42344 +#define UCB_IO_7 (1 << 7)
42345 +#define UCB_IO_8 (1 << 8)
42346 +#define UCB_IO_9 (1 << 9)
42348 +#define UCB_IE_RIS 0x02
42349 +#define UCB_IE_FAL 0x03
42350 +#define UCB_IE_STATUS 0x04
42351 +#define UCB_IE_CLEAR 0x04
42352 +#define UCB_IE_ADC (1 << 11)
42353 +#define UCB_IE_TSPX (1 << 12)
42354 +#define UCB_IE_TSMX (1 << 13)
42355 +#define UCB_IE_TCLIP (1 << 14)
42356 +#define UCB_IE_ACLIP (1 << 15)
42358 +#define UCB_IRQ_TSPX 12
42360 +#define UCB_TC_A 0x05
42361 +#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
42362 +#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
42364 +#define UCB_TC_B 0x06
42365 +#define UCB_TC_B_VOICE_ENA (1 << 3)
42366 +#define UCB_TC_B_CLIP (1 << 4)
42367 +#define UCB_TC_B_ATT (1 << 6)
42368 +#define UCB_TC_B_SIDE_ENA (1 << 11)
42369 +#define UCB_TC_B_MUTE (1 << 13)
42370 +#define UCB_TC_B_IN_ENA (1 << 14)
42371 +#define UCB_TC_B_OUT_ENA (1 << 15)
42373 +#define UCB_AC_A 0x07
42374 +#define UCB_AC_B 0x08
42375 +#define UCB_AC_B_LOOP (1 << 8)
42376 +#define UCB_AC_B_MUTE (1 << 13)
42377 +#define UCB_AC_B_IN_ENA (1 << 14)
42378 +#define UCB_AC_B_OUT_ENA (1 << 15)
42380 +#define UCB_TS_CR 0x09
42381 +#define UCB_TS_CR_TSMX_POW (1 << 0)
42382 +#define UCB_TS_CR_TSPX_POW (1 << 1)
42383 +#define UCB_TS_CR_TSMY_POW (1 << 2)
42384 +#define UCB_TS_CR_TSPY_POW (1 << 3)
42385 +#define UCB_TS_CR_TSMX_GND (1 << 4)
42386 +#define UCB_TS_CR_TSPX_GND (1 << 5)
42387 +#define UCB_TS_CR_TSMY_GND (1 << 6)
42388 +#define UCB_TS_CR_TSPY_GND (1 << 7)
42389 +#define UCB_TS_CR_MODE_INT (0 << 8)
42390 +#define UCB_TS_CR_MODE_PRES (1 << 8)
42391 +#define UCB_TS_CR_MODE_POS (2 << 8)
42392 +#define UCB_TS_CR_BIAS_ENA (1 << 11)
42393 +#define UCB_TS_CR_TSPX_LOW (1 << 12)
42394 +#define UCB_TS_CR_TSMX_LOW (1 << 13)
42396 +#define UCB_ADC_CR 0x0a
42397 +#define UCB_ADC_SYNC_ENA (1 << 0)
42398 +#define UCB_ADC_VREFBYP_CON (1 << 1)
42399 +#define UCB_ADC_INP_TSPX (0 << 2)
42400 +#define UCB_ADC_INP_TSMX (1 << 2)
42401 +#define UCB_ADC_INP_TSPY (2 << 2)
42402 +#define UCB_ADC_INP_TSMY (3 << 2)
42403 +#define UCB_ADC_INP_AD0 (4 << 2)
42404 +#define UCB_ADC_INP_AD1 (5 << 2)
42405 +#define UCB_ADC_INP_AD2 (6 << 2)
42406 +#define UCB_ADC_INP_AD3 (7 << 2)
42407 +#define UCB_ADC_EXT_REF (1 << 5)
42408 +#define UCB_ADC_START (1 << 7)
42409 +#define UCB_ADC_ENA (1 << 15)
42411 +#define UCB_ADC_DATA 0x0b
42412 +#define UCB_ADC_DAT_VAL (1 << 15)
42413 +#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
42415 +#define UCB_ID 0x0c
42416 +#define UCB_ID_1200 0x1004
42417 +#define UCB_ID_1300 0x1005
42419 +#define UCB_MODE 0x0d
42420 +#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
42421 +#define UCB_MODE_AUD_OFF_CAN (1 << 13)
42423 +#include "mcp.h"
42425 +struct ucb1x00;
42427 +struct ucb1x00_irq {
42428 + void *devid;
42429 + void (*fn)(int, void *);
42432 +struct ucb1x00 {
42433 + spinlock_t lock;
42434 + struct mcp *mcp;
42435 + struct pm_dev *pmdev;
42436 + unsigned int irq;
42437 + struct semaphore adc_sem;
42438 + spinlock_t io_lock;
42439 + u16 id;
42440 + u16 io_dir;
42441 + u16 io_out;
42442 + u16 adc_cr;
42443 + u16 irq_fal_enbl;
42444 + u16 irq_ris_enbl;
42445 + struct ucb1x00_irq irq_handler[16];
42448 +/**
42449 + * ucb1x00_clkrate - return the UCB1x00 SIB clock rate
42450 + * @ucb: UCB1x00 structure describing chip
42452 + * Return the SIB clock rate in Hz.
42453 + */
42454 +static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb)
42456 + return mcp_get_sclk_rate(ucb->mcp);
42459 +/**
42460 + * ucb1x00_enable - enable the UCB1x00 SIB clock
42461 + * @ucb: UCB1x00 structure describing chip
42463 + * Enable the SIB clock. This can be called multiple times.
42464 + */
42465 +static inline void ucb1x00_enable(struct ucb1x00 *ucb)
42467 + mcp_enable(ucb->mcp);
42470 +/**
42471 + * ucb1x00_disable - disable the UCB1x00 SIB clock
42472 + * @ucb: UCB1x00 structure describing chip
42474 + * Disable the SIB clock. The SIB clock will only be disabled
42475 + * when the number of ucb1x00_enable calls match the number of
42476 + * ucb1x00_disable calls.
42477 + */
42478 +static inline void ucb1x00_disable(struct ucb1x00 *ucb)
42480 + mcp_disable(ucb->mcp);
42483 +/**
42484 + * ucb1x00_reg_write - write a UCB1x00 register
42485 + * @ucb: UCB1x00 structure describing chip
42486 + * @reg: UCB1x00 4-bit register index to write
42487 + * @val: UCB1x00 16-bit value to write
42489 + * Write the UCB1x00 register @reg with value @val. The SIB
42490 + * clock must be running for this function to return.
42491 + */
42492 +static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val)
42494 + mcp_reg_write(ucb->mcp, reg, val);
42497 +/**
42498 + * ucb1x00_reg_read - read a UCB1x00 register
42499 + * @ucb: UCB1x00 structure describing chip
42500 + * @reg: UCB1x00 4-bit register index to write
42502 + * Read the UCB1x00 register @reg and return its value. The SIB
42503 + * clock must be running for this function to return.
42504 + */
42505 +static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg)
42507 + return mcp_reg_read(ucb->mcp, reg);
42509 +/**
42510 + * ucb1x00_set_audio_divisor -
42511 + * @ucb: UCB1x00 structure describing chip
42512 + * @div: SIB clock divisor
42513 + */
42514 +static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div)
42516 + mcp_set_audio_divisor(ucb->mcp, div);
42519 +/**
42520 + * ucb1x00_set_telecom_divisor -
42521 + * @ucb: UCB1x00 structure describing chip
42522 + * @div: SIB clock divisor
42523 + */
42524 +static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div)
42526 + mcp_set_telecom_divisor(ucb->mcp, div);
42529 +struct ucb1x00 *ucb1x00_get(void);
42531 +void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int);
42532 +void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int);
42533 +unsigned int ucb1x00_io_read(struct ucb1x00 *ucb);
42535 +#define UCB_NOSYNC (0)
42536 +#define UCB_SYNC (1)
42538 +unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
42539 +void ucb1x00_adc_enable(struct ucb1x00 *ucb);
42540 +void ucb1x00_adc_disable(struct ucb1x00 *ucb);
42543 + * Which edges of the IRQ do you want to control today?
42544 + */
42545 +#define UCB_RISING (1 << 0)
42546 +#define UCB_FALLING (1 << 1)
42548 +int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
42549 +void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
42550 +void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
42551 +int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
42553 +#endif
42554 --- linux-2.4.25/drivers/mtd/chips/cfi_probe.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
42555 +++ linux-2.4.25/drivers/mtd/chips/cfi_probe.c 2004-03-31 17:15:09.000000000 +0200
42556 @@ -65,6 +65,10 @@
42557 return 0;
42559 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
42561 + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
42562 + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
42564 cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
42566 if (!qry_present(map,base,cfi))
42567 @@ -84,6 +88,8 @@
42568 /* Eep. This chip also had the QRY marker.
42569 * Is it an alias for the new one? */
42570 cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
42571 + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
42572 + cfi_send_gen_cmd(0xFF, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
42574 /* If the QRY marker goes away, it's an alias */
42575 if (!qry_present(map, chips[i].start, cfi)) {
42576 @@ -96,7 +102,8 @@
42577 * too and if it's the same, assume it's an alias. */
42578 /* FIXME: Use other modes to do a proper check */
42579 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
42581 + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
42582 + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
42583 if (qry_present(map, base, cfi)) {
42584 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
42585 map->name, base, chips[i].start);
42586 @@ -119,6 +126,10 @@
42587 /* Put it back into Read Mode */
42588 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
42590 + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
42591 + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
42594 printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
42595 map->name, cfi->interleave, cfi->device_type*8, base,
42596 map->buswidth*8);
42597 @@ -165,6 +176,20 @@
42598 cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
42599 cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
42601 + /*
42602 + * ST screwed up the CFI interface for buffer writes on their parts,
42603 + * so this needs to be fixed up by hand here.
42605 + * A possible enhancment is that instead of just reverting back
42606 + * to word write (as this does), we could use the ST specific double
42607 + * word write instead.
42608 + */
42610 + if (cfi_read_query(map,base) == 0x20){
42611 + cfi->cfiq->BufWriteTimeoutTyp = 0;
42612 + cfi->cfiq->BufWriteTimeoutMax = 0;
42615 #ifdef DEBUG_CFI
42616 /* Dump the information therein */
42617 print_cfi_ident(cfi->cfiq);
42618 @@ -182,6 +207,9 @@
42619 /* Put it back into Read Mode */
42620 cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
42622 + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
42623 + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
42625 return 1;
42628 --- linux-2.4.25/drivers/mtd/devices/Config.in~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
42629 +++ linux-2.4.25/drivers/mtd/devices/Config.in 2004-03-31 17:15:09.000000000 +0200
42630 @@ -17,6 +17,15 @@
42631 if [ "$CONFIG_SA1100_LART" = "y" ]; then
42632 dep_tristate ' 28F160xx flash driver for LART' CONFIG_MTD_LART $CONFIG_MTD
42634 +if [ "$CONFIG_ARCH_MX1ADS" = "y" ]; then
42635 + dep_tristate ' SyncFlash driver for MX1ADS' CONFIG_MTD_SYNCFLASH $CONFIG_MTD
42637 +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
42638 + dep_tristate ' AT91RM9200 DataFlash support' CONFIG_MTD_AT91_DATAFLASH $CONFIG_MTD
42639 + if [ "$CONFIG_MTD_AT91_DATAFLASH" = "y" -o "$CONFIG_MTD_AT91_DATAFLASH" = "m" ]; then
42640 + bool ' Enable DataFlash card? ' CONFIG_MTD_AT91_DATAFLASH_CARD
42641 + fi
42643 dep_tristate ' Test driver using RAM' CONFIG_MTD_MTDRAM $CONFIG_MTD
42644 if [ "$CONFIG_MTD_MTDRAM" = "y" -o "$CONFIG_MTD_MTDRAM" = "m" ]; then
42645 int 'MTDRAM device size in KiB' CONFIG_MTDRAM_TOTAL_SIZE 4096
42646 --- linux-2.4.25/drivers/mtd/devices/Makefile~2.4.25-vrs2.patch 2002-11-29 00:53:13.000000000 +0100
42647 +++ linux-2.4.25/drivers/mtd/devices/Makefile 2004-03-31 17:15:09.000000000 +0200
42648 @@ -21,6 +21,7 @@
42649 obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
42650 obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
42651 obj-$(CONFIG_MTD_LART) += lart.o
42652 +obj-$(CONFIG_MTD_SYNCFLASH) += syncflash.o
42653 obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
42655 include $(TOPDIR)/Rules.make
42656 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
42657 +++ linux-2.4.25/drivers/mtd/devices/syncflash.c 2004-03-31 17:15:09.000000000 +0200
42658 @@ -0,0 +1,615 @@
42660 + * MTD driver for Micron SyncFlash flash memory.
42662 + * Author: Jon McClintock <jonm@bluemug.com>
42664 + * Based loosely upon the LART flash driver, authored by Abraham vd Merwe
42665 + * <abraham@2d3d.co.za>.
42667 + * Copyright 2003, Blue Mug, Inc. for Motorola, Inc.
42669 + * This code is free software; you can redistribute it and/or modify
42670 + * it under the terms of the GNU General Public License version 2 as
42671 + * published by the Free Software Foundation.
42673 + * References:
42675 + * [1] Micron SyncFlash homepage
42676 + * - http://www.syncflash.com/
42678 + * [2] MT28S4M16LC -- 4Mx16 SyncFlash memory datasheet
42679 + * - http://syncflash.com/pdfs/datasheets/mt28s4m16lc_6.pdf
42681 + * [3] MTD internal API documentation
42682 + * - http://www.linux-mtd.infradead.org/tech/
42684 + * Limitations:
42686 + * Even though this driver is written for Micron SyncFlash, it is quite
42687 + * specific to the Motorola MX1 ADS development board.
42688 + */
42690 +#include <linux/kernel.h>
42691 +#include <linux/module.h>
42692 +#include <linux/types.h>
42693 +#include <linux/version.h>
42694 +#include <linux/errno.h>
42695 +#include <linux/mtd/mtd.h>
42696 +#include <asm/io.h>
42698 +/* partition support */
42699 +#define HAVE_PARTITIONS
42700 +#ifdef HAVE_PARTITIONS
42701 +#include <linux/mtd/partitions.h>
42702 +#endif
42704 +#ifndef CONFIG_ARCH_MX1ADS
42705 +#error The SyncFlash driver currently only supports the MX1 ADS platform.
42706 +#endif
42709 + * General flash configuration parameters.
42710 + */
42711 +#define BUSWIDTH 4
42712 +#define FLASH_BLOCKSIZE (256 * 1024 * BUSWIDTH)
42713 +#define FLASH_NUMBLOCKS 16
42715 +#define BUSWIDTH 4
42716 +#define FLASH_ADDRESS IO_ADDRESS(MX1ADS_FLASH_BASE)
42718 +#define FLASH_MANUFACTURER 0x002C002C
42719 +#define FLASH_DEVICE_ID 0x00D300D3
42722 + * The size and extent of the bootloader in flash.
42723 + */
42724 +#define NUM_BOOTLOADER_BLOCKS 1
42725 +#define BOOTLOADER_START 0x00000000
42726 +#define BOOTLOADER_LEN (NUM_BOOTLOADER_BLOCKS * FLASH_BLOCKSIZE)
42729 + * The size and extent of the kernel in flash.
42730 + */
42731 +#define NUM_KERNEL_BLOCKS 1
42732 +#define KERNEL_START (BOOTLOADER_START + BOOTLOADER_LEN)
42733 +#define KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE)
42735 +/* File system */
42736 +#define NUM_FILESYSTEM_BLOCKS 14
42737 +#define FILESYSTEM_START (KERNEL_START + KERNEL_LEN)
42738 +#define FILESYSTEM_LEN (NUM_FILESYSTEM_BLOCKS * FLASH_BLOCKSIZE)
42742 + * SDRAM controller register location and values. These are very specific
42743 + * to the MX1.
42744 + */
42745 +#define SDRAMC_REGISTER IO_ADDRESS(0x00221004)
42748 + * This the mask we use to get the start of a block from a given address.
42749 + */
42750 +#define BLOCK_MASK (0xFFF00000)
42753 + * This is the A10 address line of the SyncFlash; it's used to initiate
42754 + * a precharge command.
42755 + */
42756 +#define SYNCFLASH_A10 (0x00100000)
42759 + * SDRAM controller MODE settings.
42760 + */
42761 +#define CMD_NORMAL (0x81020300) /* Normal Mode */
42762 +#define CMD_PREC (CMD_NORMAL + 0x10000000) /* Precharge command */
42763 +#define CMD_AUTO (CMD_NORMAL + 0x20000000) /* Auto refresh */
42764 +#define CMD_LMR (CMD_NORMAL + 0x30000000) /* Load Mode Register */
42765 +#define CMD_LCR (CMD_NORMAL + 0x60000000) /* LCR Command */
42766 +#define CMD_PROGRAM (CMD_NORMAL + 0x70000000) /* SyncFlash Program */
42769 + * SyncFlash LCR Commands adjusted for the DBMX1 AHB internal address bus .
42770 + */
42771 +#define LCR_READ_STATUS (0x0001C000) /* 0x70 */
42772 +#define LCR_READ_CONFIG (0x00024000) /* 0x90 */
42773 +#define LCR_ERASE_CONFIRM (0x00008000) /* 0x20 */
42774 +#define LCR_ERASE_NVMODE (0x0000C000) /* 0x30 */
42775 +#define LCR_PROG_NVMODE (0x00028000) /* 0xA0 */
42776 +#define LCR_SR_CLEAR (0x00014000) /* 0x50 */
42779 + * Status register bits
42780 + */
42781 +#define SR_VPS_ERROR (1 << 8) /* Power-Up status error */
42782 +#define SR_ISM_READY (1 << 7) /* State machine isn't busy */
42783 +#define SR_ERASE_ERROR (1 << 5) /* Erase/Unprotect error */
42784 +#define SR_PROGRAM_ERROR (1 << 4) /* Program/Protect error */
42785 +#define SR_DEVICE_PROTECTED (1 << 3) /* Device is protected */
42786 +#define SR_ISM_STATUS_H (1 << 2) /* Bank ISM status, high bit */
42787 +#define SR_ISM_STATUS_L (1 << 1) /* Bank ISM status, low bit */
42788 +#define SR_DEVICE_ISM_STATUS (1 << 0) /* ISM is device-level */
42790 +#define SR_ERROR (SR_VPS_ERROR|SR_ERASE_ERROR|SR_PROGRAM_ERROR|SR_DEVICE_PROTECTED)
42792 +#define STATUS_VALUE(a) ((a) | ((a) << 16))
42795 + * Device configuration register offsets
42796 + */
42797 +#define DC_MANUFACTURER (0 * BUSWIDTH)
42798 +#define DC_DEVICE_ID (1 * BUSWIDTH)
42799 +#define DC_BLOCK_PROTECT (2 * BUSWIDTH)
42800 +#define DC_DEVICE_PROTECT (3 * BUSWIDTH)
42802 +#define FL_WORD(addr) (*(volatile unsigned long*)(addr))
42804 +static char module_name[] = "syncflash";
42806 +inline __u8 read8 (__u32 offset)
42808 + return *(volatile __u8 *) (FLASH_ADDRESS + offset);
42811 +inline __u32 read32 (__u32 offset)
42813 + return *(volatile __u32 *) (FLASH_ADDRESS + offset);
42816 +inline void write32 (__u32 x,__u32 offset)
42818 + *(volatile __u32 *) (FLASH_ADDRESS + offset) = x;
42821 +static __u32 read_device_configuration_register(__u32 reg_number)
42823 + __u32 tmp;
42825 + /* Setup the SDRAM controller to issue an LCR command. */
42826 + FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
42828 + /* Perform a read to issue the Read Device Configuration Command. */
42829 + tmp = read32(LCR_READ_CONFIG);
42831 + /* Return the SDRAM controller to normal mode. */
42832 + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
42834 + /* Return the value of the specified register. */
42835 + tmp = read32(reg_number);
42837 + return tmp;
42841 + * Get the status of the flash devices.
42842 + */
42843 +static __u32 flash_read_status()
42845 + __u32 status, tmp;
42847 + /* Enter the SyncFlash Program READ/WRITE mode. */
42848 + FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
42850 + /* Read the status register. */
42851 + status = read32(LCR_READ_STATUS);
42853 + /* Clear the status register. */
42854 + FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
42855 + tmp = read32(LCR_SR_CLEAR);
42857 + /* Return to Normal mode. */
42858 + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
42860 + return status;
42864 + * Loop until both write state machines are ready.
42865 + */
42866 +static __u32 flash_status_wait()
42868 + __u32 status;
42869 + do {
42870 + status = flash_read_status();
42871 + } while ((status & STATUS_VALUE(SR_ISM_READY)) !=
42872 + STATUS_VALUE(SR_ISM_READY));
42873 + return status;
42877 + * Loop until the Write State machine is ready, then do a full error
42878 + * check. Clear status and leave the flash in Read Array mode; return
42879 + * 0 for no error, -1 for error.
42880 + */
42881 +static int flash_status_full_check()
42883 + __u32 status;
42885 + status = flash_status_wait() & STATUS_VALUE(SR_ERROR);
42886 + return status ? -EIO : 0;
42890 + * Return the flash to the normal mode.
42891 + */
42892 +static void flash_normal_mode()
42894 + __u32 tmp;
42896 + /* First issue a precharge all command. */
42897 + FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
42898 + tmp = read32(SYNCFLASH_A10);
42900 + /* Now place the SDRAM controller in Normal mode. */
42901 + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
42905 + * Probe for SyncFlash memory on MX1ADS board.
42907 + * Returns 1 if we found SyncFlash memory, 0 otherwise.
42908 + */
42909 +static int flash_probe (void)
42911 + __u32 manufacturer, device_id;
42913 + /* For some reason, the first read doesn't work, so we do it
42914 + * twice. */
42915 + manufacturer = read_device_configuration_register(DC_MANUFACTURER);
42916 + manufacturer = read_device_configuration_register(DC_MANUFACTURER);
42917 + device_id = read_device_configuration_register(DC_DEVICE_ID);
42919 + printk("SyncFlash probe: manufacturer 0x%08lx, device_id 0x%08lx\n",
42920 + manufacturer, device_id);
42921 + return (manufacturer == FLASH_MANUFACTURER &&
42922 + device_id == FLASH_DEVICE_ID);
42926 + * Erase one block of flash memory at offset ``offset'' which is any
42927 + * address within the block which should be erased.
42929 + * Returns 0 if successful, -1 otherwise.
42930 + */
42931 +static inline int erase_block (__u32 offset)
42933 + __u32 tmp;
42935 + /* Mask off the lower bits of the address to get the first address
42936 + * in the flash block. */
42937 + offset &= (__u32)BLOCK_MASK;
42939 + /* Perform a read and precharge of the bank before the LCR|ACT|WRIT
42940 + * sequence to avoid the inadvertent precharge command occurring
42941 + * during the LCR_ACT_WRIT sequence. */
42942 + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
42943 + tmp = read32(offset);
42944 + FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
42945 + tmp = read32(offset);
42947 + /* Now start the actual erase. */
42949 + /* LCR|ACT|WRIT sequence */
42950 + FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
42951 + write32(0, offset + LCR_ERASE_CONFIRM);
42953 + /* Return to normal mode to issue the erase confirm. */
42954 + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
42955 + write32(0xD0D0D0D0, offset);
42957 + if (flash_status_full_check()) {
42958 + printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",
42959 + module_name, offset);
42960 + return (-1);
42963 + flash_normal_mode();
42965 + return 0;
42968 +static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
42970 + __u32 addr,len;
42971 + int i,first;
42973 + /* sanity checks */
42974 + if (instr->addr + instr->len > mtd->size) return (-EINVAL);
42976 + /*
42977 + * check that both start and end of the requested erase are
42978 + * aligned with the erasesize at the appropriate addresses.
42980 + * skip all erase regions which are ended before the start of
42981 + * the requested erase. Actually, to save on the calculations,
42982 + * we skip to the first erase region which starts after the
42983 + * start of the requested erase, and then go back one.
42984 + */
42985 + for (i = 0; (i < mtd->numeraseregions) &&
42986 + (instr->addr >= mtd->eraseregions[i].offset); i++) ;
42987 + i--;
42989 + /*
42990 + * ok, now i is pointing at the erase region in which this
42991 + * erase request starts. Check the start of the requested
42992 + * erase range is aligned with the erase size which is in
42993 + * effect here.
42994 + */
42995 + if (instr->addr & (mtd->eraseregions[i].erasesize - 1))
42996 + return (-EINVAL);
42998 + /* Remember the erase region we start on */
42999 + first = i;
43001 + /*
43002 + * next, check that the end of the requested erase is aligned
43003 + * with the erase region at that address.
43005 + * as before, drop back one to point at the region in which
43006 + * the address actually falls
43007 + */
43008 + for (;
43009 + (i < mtd->numeraseregions) &&
43010 + ((instr->addr + instr->len) >= mtd->eraseregions[i].offset) ;
43011 + i++) ;
43012 + i--;
43014 + /* is the end aligned on a block boundary? */
43015 + if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1))
43016 + return (-EINVAL);
43018 + addr = instr->addr;
43019 + len = instr->len;
43021 + i = first;
43023 + /* now erase those blocks */
43024 + while (len)
43026 + if (erase_block (addr))
43028 + instr->state = MTD_ERASE_FAILED;
43029 + return (-EIO);
43032 + addr += mtd->eraseregions[i].erasesize;
43033 + len -= mtd->eraseregions[i].erasesize;
43035 + if (addr == (mtd->eraseregions[i].offset +
43036 + (mtd->eraseregions[i].erasesize *
43037 + mtd->eraseregions[i].numblocks)))
43038 + i++;
43041 + instr->state = MTD_ERASE_DONE;
43042 + if (instr->callback) instr->callback (instr);
43044 + return (0);
43047 +static int flash_read (struct mtd_info *mtd, loff_t from,
43048 + size_t len, size_t *retlen, u_char *buf)
43050 + /* Sanity checks. */
43051 + if (!len) return (0);
43052 + if (from + len > mtd->size) return (-EINVAL);
43054 + /* Ensure that we are in normal mode. */
43055 + flash_normal_mode();
43057 + /* We always read len bytes. */
43058 + *retlen = len;
43060 + /* first, we read bytes until we reach a dword boundary */
43061 + if (from & (BUSWIDTH - 1))
43063 + int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
43064 + while (len && gap--) *buf++ = read8(from++), len--;
43067 + /* now we read dwords until we reach a non-dword boundary */
43068 + while (len >= BUSWIDTH)
43070 + *((__u32 *) buf) = read32(from);
43072 + buf += BUSWIDTH;
43073 + from += BUSWIDTH;
43074 + len -= BUSWIDTH;
43077 + /* top up the last unaligned bytes */
43078 + if (len & (BUSWIDTH - 1))
43079 + while (len--) *buf++ = read8(from++);
43081 + return (0);
43085 + * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
43086 + * must be 32 bits, i.e. it must be on a dword boundary.
43088 + * Returns 0 if successful, -1 otherwise.
43089 + */
43090 +static int flash_write_dword(__u32 offset, __u32 x)
43092 + __u32 tmp;
43094 + /* First issue a precharge all command. */
43095 + FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
43096 + tmp = read32(SYNCFLASH_A10);
43098 + /* Enter the SyncFlash programming mode. */
43099 + FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
43100 + write32(x, offset);
43102 + /* Wait for the write to complete. */
43103 + flash_status_wait();
43105 + /* Return to normal mode. */
43106 + flash_normal_mode();
43108 + return 0;
43111 +static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
43113 + __u8 tmp[4];
43114 + int i,n;
43116 + *retlen = 0;
43118 + /* Sanity checks */
43119 + if (!len) return (0);
43120 + if (to + len > mtd->size) return (-EINVAL);
43122 + /* First, we write a 0xFF.... padded byte until we reach a
43123 + * dword boundary. */
43124 + if (to & (BUSWIDTH - 1))
43126 + __u32 aligned = to & ~(BUSWIDTH - 1);
43127 + int gap = to - aligned;
43129 + i = n = 0;
43131 + while (gap--) tmp[i++] = 0xFF;
43132 + while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
43133 + while (i < BUSWIDTH) tmp[i++] = 0xFF;
43135 + if (flash_write_dword(aligned, *((__u32 *) tmp)))
43136 + return (-EIO);
43138 + to += n;
43139 + buf += n;
43140 + *retlen += n;
43143 + /* Now we write dwords until we reach a non-dword boundary. */
43144 + while (len >= BUSWIDTH)
43146 + if (flash_write_dword (to,*((__u32 *) buf))) return (-EIO);
43148 + to += BUSWIDTH;
43149 + buf += BUSWIDTH;
43150 + *retlen += BUSWIDTH;
43151 + len -= BUSWIDTH;
43154 + /* Top up the last unaligned bytes, padded with 0xFF.... */
43155 + if (len & (BUSWIDTH - 1))
43157 + i = n = 0;
43159 + while (len--) tmp[i++] = buf[n++];
43160 + while (i < BUSWIDTH) tmp[i++] = 0xFF;
43162 + if (flash_write_dword (to,*((__u32 *) tmp))) return (-EIO);
43164 + *retlen += n;
43167 + return flash_status_full_check();
43172 +#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
43174 +static struct mtd_info mtd;
43176 +static struct mtd_erase_region_info erase_regions[] =
43178 + /* flash blocks */
43180 + offset: 0x00000000,
43181 + erasesize: FLASH_BLOCKSIZE,
43182 + numblocks: FLASH_NUMBLOCKS
43183 + },
43186 +#ifdef HAVE_PARTITIONS
43187 +static struct mtd_partition syncflash_partitions[] =
43189 + /* bootloader */
43191 + name: "bootloader",
43192 + offset: BOOTLOADER_START,
43193 + size: BOOTLOADER_LEN,
43194 + mask_flags: 0
43195 + },
43196 + /* Kernel */
43198 + name: "kernel",
43199 + offset: KERNEL_START, /* MTDPART_OFS_APPEND */
43200 + size: KERNEL_LEN,
43201 + mask_flags: 0
43202 + },
43203 + /* file system */
43205 + name: "file system",
43206 + offset: FILESYSTEM_START, /* MTDPART_OFS_APPEND */
43207 + size: FILESYSTEM_LEN, /* MTDPART_SIZ_FULL */
43208 + mask_flags: 0
43211 +#endif
43213 +int __init syncflash_init (void)
43215 + int result;
43217 + memset (&mtd,0,sizeof (mtd));
43219 + printk ("MTD driver for Micron SyncFlash.\n");
43220 + printk ("%s: Probing for SyncFlash on MX1ADS...\n",module_name);
43222 + if (!flash_probe ())
43224 + printk (KERN_WARNING "%s: Found no SyncFlash devices\n",
43225 + module_name);
43226 + return (-ENXIO);
43229 + printk ("%s: Found a SyncFlash device.\n",module_name);
43231 + mtd.name = module_name;
43232 + mtd.type = MTD_NORFLASH;
43233 + mtd.flags = MTD_CAP_NORFLASH;
43234 + mtd.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS;
43236 + mtd.erasesize = FLASH_BLOCKSIZE;
43237 + mtd.numeraseregions = NB_OF(erase_regions);
43238 + mtd.eraseregions = erase_regions;
43240 + mtd.module = THIS_MODULE;
43242 + mtd.erase = flash_erase;
43243 + mtd.read = flash_read;
43244 + mtd.write = flash_write;
43246 +#ifndef HAVE_PARTITIONS
43247 + result = add_mtd_device(&mtd);
43248 +#else
43249 + result = add_mtd_partitions(&mtd,
43250 + syncflash_partitions,
43251 + NB_OF(syncflash_partitions));
43252 +#endif
43254 + return (result);
43257 +void __exit syncflash_exit (void)
43259 +#ifndef HAVE_PARTITIONS
43260 + del_mtd_device (&mtd);
43261 +#else
43262 + del_mtd_partitions (&mtd);
43263 +#endif
43266 +module_init (syncflash_init);
43267 +module_exit (syncflash_exit);
43269 +MODULE_LICENSE("GPL");
43270 +MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
43271 +MODULE_DESCRIPTION("MTD driver for Micron MT28S4M16LC SyncFlash on MX1ADS board");
43274 --- linux-2.4.25/drivers/mtd/maps/Config.in~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
43275 +++ linux-2.4.25/drivers/mtd/maps/Config.in 2004-03-31 17:15:09.000000000 +0200
43276 @@ -81,10 +81,10 @@
43277 dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS
43278 dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE
43279 dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310
43280 - dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
43281 - dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET
43282 + dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_FORTUNET
43283 + dep_tristate ' CFI Flash device mapped on Epxa' CONFIG_MTD_EPXA $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
43284 dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12
43285 - dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI
43286 + dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_ARCH_EDB7212 $CONFIG_MTD_CFI
43287 dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE
43288 dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA
43290 --- linux-2.4.25/drivers/mtd/maps/Makefile~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
43291 +++ linux-2.4.25/drivers/mtd/maps/Makefile 2004-03-31 17:15:09.000000000 +0200
43292 @@ -3,11 +3,7 @@
43294 # $Id: Makefile,v 1.37 2003/01/24 14:26:38 dwmw2 Exp $
43296 -BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/)
43298 -ifeq ($(BELOW25),y)
43299 O_TARGET := mapslink.o
43300 -endif
43302 # Chip mappings
43303 obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
43304 @@ -17,7 +13,7 @@
43305 obj-$(CONFIG_MTD_DC21285) += dc21285.o
43306 obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
43307 obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
43308 -obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
43309 +obj-$(CONFIG_MTD_EPXA) += epxa-flash.o
43310 obj-$(CONFIG_MTD_IQ80310) += iq80310.o
43311 obj-$(CONFIG_MTD_L440GX) += l440gx.o
43312 obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
43313 @@ -29,9 +25,9 @@
43314 obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
43315 ifneq ($(CONFIG_MTD_PHYSMAP),n)
43316 ifeq ($(CONFIG_MTD_PHYSMAP_BUSWIDTH),8)
43317 - obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
43318 + obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
43319 else
43320 - obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
43321 + obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
43322 endif
43323 endif
43324 obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
43325 @@ -39,6 +35,9 @@
43326 obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
43327 obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
43328 obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
43329 +ifeq ($(CONFIG_ASSABET_NEPONSET),y)
43330 + obj-$(CONFIG_MTD_SA1100) += neponset-flash.o
43331 +endif
43332 obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
43333 obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
43334 obj-$(CONFIG_MTD_NETSC520) += netsc520.o
43335 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
43336 +++ linux-2.4.25/drivers/mtd/maps/epxa-flash.c 2004-03-31 17:15:09.000000000 +0200
43337 @@ -0,0 +1,234 @@
43339 + * Flash memory access on EPXA based devices
43341 + * (C) 2000 Nicolas Pitre <nico@cam.org>
43342 + * Copyright (C) 2001 Altera Corporation
43343 + * Copyright (C) 2001 Red Hat, Inc.
43345 + * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
43347 + * This program is free software; you can redistribute it and/or modify
43348 + * it under the terms of the GNU General Public License as published by
43349 + * the Free Software Foundation; either version 2 of the License, or
43350 + * (at your option) any later version.
43352 + * This program is distributed in the hope that it will be useful,
43353 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
43354 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43355 + * GNU General Public License for more details.
43357 + * You should have received a copy of the GNU General Public License
43358 + * along with this program; if not, write to the Free Software
43359 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43360 + */
43362 +#include <linux/config.h>
43363 +#include <linux/module.h>
43364 +#include <linux/types.h>
43365 +#include <linux/kernel.h>
43366 +#include <asm/io.h>
43367 +#include <linux/mtd/mtd.h>
43368 +#include <linux/mtd/map.h>
43369 +#include <linux/mtd/partitions.h>
43371 +#include <asm/hardware.h>
43372 +#ifdef CONFIG_EPXA10DB
43373 +#define BOARD_NAME "EPXA10DB"
43374 +#else
43375 +#define BOARD_NAME "EPXA1DB"
43376 +#endif
43378 +static int nr_parts = 0;
43379 +static struct mtd_partition *parts;
43381 +static struct mtd_info *mymtd;
43383 +extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
43384 +static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
43386 +static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
43388 + return __raw_readb(map->map_priv_1 + ofs);
43391 +static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
43393 + return __raw_readw(map->map_priv_1 + ofs);
43396 +static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
43398 + return __raw_readl(map->map_priv_1 + ofs);
43401 +static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
43403 + memcpy_fromio(to, map->map_priv_1 + from, len);
43406 +static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
43408 + __raw_writeb(d, map->map_priv_1 + adr);
43409 + mb();
43412 +static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
43414 + __raw_writew(d, map->map_priv_1 + adr);
43415 + mb();
43418 +static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
43420 + __raw_writel(d, map->map_priv_1 + adr);
43421 + mb();
43424 +static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
43426 + memcpy_toio(map->map_priv_1 + to, from, len);
43429 +static struct map_info epxa_map = {
43430 + .name = "EPXA flash",
43431 + .size = FLASH_SIZE,
43432 + .buswidth = 2,
43433 + .read8 = epxa_read8,
43434 + .read16 = epxa_read16,
43435 + .read32 = epxa_read32,
43436 + .copy_from = epxa_copy_from,
43437 + .write8 = epxa_write8,
43438 + .write16 = epxa_write16,
43439 + .write32 = epxa_write32,
43440 + .copy_to = epxa_copy_to
43443 +static int __init epxa_mtd_init(void)
43445 + int i;
43447 + printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
43448 + epxa_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_START, FLASH_SIZE);
43449 + if (!epxa_map.map_priv_1) {
43450 + printk("Failed to ioremap %s flash\n",BOARD_NAME);
43451 + return -EIO;
43454 + mymtd = do_map_probe("cfi_probe", &epxa_map);
43455 + if (!mymtd) {
43456 + iounmap((void *)epxa_map.map_priv_1);
43457 + return -ENXIO;
43460 + mymtd->module = THIS_MODULE;
43462 + /* Unlock the flash device. */
43463 + if(mymtd->unlock){
43464 + for (i=0; i<mymtd->numeraseregions;i++){
43465 + int j;
43466 + for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
43467 + mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
43472 +#ifdef CONFIG_MTD_REDBOOT_PARTS
43473 + nr_parts = parse_redboot_partitions(mymtd, &parts);
43475 + if (nr_parts > 0) {
43476 + add_mtd_partitions(mymtd, parts, nr_parts);
43477 + return 0;
43479 +#endif
43480 +#ifdef CONFIG_MTD_AFS_PARTS
43481 + nr_parts = parse_afs_partitions(mymtd, &parts);
43483 + if (nr_parts > 0) {
43484 + add_mtd_partitions(mymtd, parts, nr_parts);
43485 + return 0;
43487 +#endif
43489 + /* No recognised partitioning schemes found - use defaults */
43490 + nr_parts = epxa_default_partitions(mymtd, &parts);
43491 + if (nr_parts > 0) {
43492 + add_mtd_partitions(mymtd, parts, nr_parts);
43493 + return 0;
43496 + /* If all else fails... */
43497 + add_mtd_device(mymtd);
43498 + return 0;
43501 +static void __exit epxa_mtd_cleanup(void)
43503 + if (mymtd) {
43504 + if (nr_parts)
43505 + del_mtd_partitions(mymtd);
43506 + else
43507 + del_mtd_device(mymtd);
43508 + map_destroy(mymtd);
43510 + if (epxa_map.map_priv_1) {
43511 + iounmap((void *)epxa_map.map_priv_1);
43512 + epxa_map.map_priv_1 = 0;
43518 + * This will do for now, once we decide which bootldr we're finally
43519 + * going to use then we'll remove this function and do it properly
43521 + * Partions are currently (as offsets from base of flash):
43522 + * 0x00000000 - 0x003FFFFF - bootloader (!)
43523 + * 0x00400000 - 0x00FFFFFF - Flashdisk
43524 + */
43526 +static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
43528 + struct mtd_partition *parts;
43529 + int ret;
43530 + int npartitions = 0;
43531 + char *names;
43532 + const char *name = "jffs";
43534 + printk("Using default partitions for %s\n",BOARD_NAME);
43535 + npartitions=1;
43536 + parts = kmalloc(npartitions*sizeof(*parts)+strlen(name)+1, GFP_KERNEL);
43537 + if (!parts) {
43538 + ret = -ENOMEM;
43539 + goto out;
43541 + memzero(parts,npartitions*sizeof(*parts)+strlen(name));
43543 + names = (char *)&parts[npartitions];
43544 + parts[0].name = names;
43545 + names += strlen(name) + 1;
43546 + strcpy(parts[0].name, name);
43548 +#ifdef CONFIG_EPXA10DB_R2
43549 + parts[0].size = FLASH_SIZE-0x00400000;
43550 + parts[0].offset = 0x00400000;
43551 +#elif defined CONFIG_EPXA10DB_R3
43552 + parts[0].size = 0x00800000;
43553 + parts[0].offset = 0x00800000;
43554 +#else
43555 + parts[0].size = FLASH_SIZE-0x00180000;
43556 + parts[0].offset = 0x00180000;
43557 +#endif
43558 + ret = npartitions;
43560 + out:
43561 + *pparts = parts;
43562 + return ret;
43566 +module_init(epxa_mtd_init);
43567 +module_exit(epxa_mtd_cleanup);
43569 +MODULE_AUTHOR("Clive Davies");
43570 +MODULE_DESCRIPTION("Altera epxa mtd flash map");
43571 +MODULE_LICENSE("GPL");
43572 --- linux-2.4.25/drivers/mtd/maps/epxa10db-flash.c~2.4.25-vrs2.patch
43573 +++ linux-2.4.25/drivers/mtd/maps/epxa10db-flash.c
43575 - * Flash memory access on EPXA based devices
43577 - * (C) 2000 Nicolas Pitre <nico@cam.org>
43578 - * Copyright (C) 2001 Altera Corporation
43579 - * Copyright (C) 2001 Red Hat, Inc.
43581 - * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
43583 - * This program is free software; you can redistribute it and/or modify
43584 - * it under the terms of the GNU General Public License as published by
43585 - * the Free Software Foundation; either version 2 of the License, or
43586 - * (at your option) any later version.
43588 - * This program is distributed in the hope that it will be useful,
43589 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
43590 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43591 - * GNU General Public License for more details.
43593 - * You should have received a copy of the GNU General Public License
43594 - * along with this program; if not, write to the Free Software
43595 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43596 - */
43598 -#include <linux/config.h>
43599 -#include <linux/module.h>
43600 -#include <linux/types.h>
43601 -#include <linux/kernel.h>
43602 -#include <asm/io.h>
43603 -#include <linux/mtd/mtd.h>
43604 -#include <linux/mtd/map.h>
43605 -#include <linux/mtd/partitions.h>
43607 -#include <asm/hardware.h>
43608 -#ifdef CONFIG_EPXA10DB
43609 -#define BOARD_NAME "EPXA10DB"
43610 -#else
43611 -#define BOARD_NAME "EPXA1DB"
43612 -#endif
43614 -static int nr_parts = 0;
43615 -static struct mtd_partition *parts;
43617 -static struct mtd_info *mymtd;
43619 -extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
43620 -static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
43622 -static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
43624 - return __raw_readb(map->map_priv_1 + ofs);
43627 -static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
43629 - return __raw_readw(map->map_priv_1 + ofs);
43632 -static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
43634 - return __raw_readl(map->map_priv_1 + ofs);
43637 -static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
43639 - memcpy_fromio(to, (void *)(map->map_priv_1 + from), len);
43642 -static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
43644 - __raw_writeb(d, map->map_priv_1 + adr);
43645 - mb();
43648 -static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
43650 - __raw_writew(d, map->map_priv_1 + adr);
43651 - mb();
43654 -static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
43656 - __raw_writel(d, map->map_priv_1 + adr);
43657 - mb();
43660 -static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
43662 - memcpy_toio((void *)(map->map_priv_1 + to), from, len);
43667 -static struct map_info epxa_map = {
43668 - name: "EPXA flash",
43669 - size: FLASH_SIZE,
43670 - buswidth: 2,
43671 - read8: epxa_read8,
43672 - read16: epxa_read16,
43673 - read32: epxa_read32,
43674 - copy_from: epxa_copy_from,
43675 - write8: epxa_write8,
43676 - write16: epxa_write16,
43677 - write32: epxa_write32,
43678 - copy_to: epxa_copy_to
43682 -static int __init epxa_mtd_init(void)
43684 - int i;
43686 - printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
43687 - epxa_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
43688 - if (!epxa_map.map_priv_1) {
43689 - printk("Failed to ioremap %s flash\n",BOARD_NAME);
43690 - return -EIO;
43693 - mymtd = do_map_probe("cfi_probe", &epxa_map);
43694 - if (!mymtd) {
43695 - iounmap((void *)epxa_map.map_priv_1);
43696 - return -ENXIO;
43699 - mymtd->module = THIS_MODULE;
43701 - /* Unlock the flash device. */
43702 - if(mymtd->unlock){
43703 - for (i=0; i<mymtd->numeraseregions;i++){
43704 - int j;
43705 - for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
43706 - mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
43711 -#ifdef CONFIG_MTD_REDBOOT_PARTS
43712 - nr_parts = parse_redboot_partitions(mymtd, &parts);
43714 - if (nr_parts > 0) {
43715 - add_mtd_partitions(mymtd, parts, nr_parts);
43716 - return 0;
43718 -#endif
43719 -#ifdef CONFIG_MTD_AFS_PARTS
43720 - nr_parts = parse_afs_partitions(mymtd, &parts);
43722 - if (nr_parts > 0) {
43723 - add_mtd_partitions(mymtd, parts, nr_parts);
43724 - return 0;
43726 -#endif
43728 - /* No recognised partitioning schemes found - use defaults */
43729 - nr_parts = epxa_default_partitions(mymtd, &parts);
43730 - if (nr_parts > 0) {
43731 - add_mtd_partitions(mymtd, parts, nr_parts);
43732 - return 0;
43735 - /* If all else fails... */
43736 - add_mtd_device(mymtd);
43737 - return 0;
43740 -static void __exit epxa_mtd_cleanup(void)
43742 - if (mymtd) {
43743 - if (nr_parts)
43744 - del_mtd_partitions(mymtd);
43745 - else
43746 - del_mtd_device(mymtd);
43747 - map_destroy(mymtd);
43749 - if (epxa_map.map_priv_1) {
43750 - iounmap((void *)epxa_map.map_priv_1);
43751 - epxa_map.map_priv_1 = 0;
43756 -/*
43757 - * This will do for now, once we decide which bootldr we're finally
43758 - * going to use then we'll remove this function and do it properly
43760 - * Partions are currently (as offsets from base of flash):
43761 - * 0x00000000 - 0x003FFFFF - bootloader (!)
43762 - * 0x00400000 - 0x00FFFFFF - Flashdisk
43763 - */
43765 -static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
43767 - struct mtd_partition *parts;
43768 - int ret, i;
43769 - int npartitions = 0;
43770 - char *names;
43771 - const char *name = "jffs";
43773 - printk("Using default partitions for %s\n",BOARD_NAME);
43774 - npartitions=1;
43775 - parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
43776 - memzero(parts,npartitions*sizeof(*parts)+strlen(name));
43777 - if (!parts) {
43778 - ret = -ENOMEM;
43779 - goto out;
43781 - i=0;
43782 - names = (char *)&parts[npartitions];
43783 - parts[i].name = names;
43784 - names += strlen(name) + 1;
43785 - strcpy(parts[i].name, name);
43787 -#ifdef CONFIG_EPXA10DB
43788 - parts[i].size = FLASH_SIZE-0x00400000;
43789 - parts[i].offset = 0x00400000;
43790 -#else
43791 - parts[i].size = FLASH_SIZE-0x00180000;
43792 - parts[i].offset = 0x00180000;
43793 -#endif
43795 - out:
43796 - *pparts = parts;
43797 - return npartitions;
43801 -module_init(epxa_mtd_init);
43802 -module_exit(epxa_mtd_cleanup);
43804 -MODULE_AUTHOR("Clive Davies");
43805 -MODULE_DESCRIPTION("Altera epxa mtd flash map");
43806 -MODULE_LICENSE("GPL");
43807 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
43808 +++ linux-2.4.25/drivers/mtd/maps/neponset-flash.c 2004-03-31 17:15:09.000000000 +0200
43809 @@ -0,0 +1,109 @@
43811 + * Flash memory access on SA11x0 based devices
43812 + *
43813 + * (C) 2000 Nicolas Pitre <nico@cam.org>
43814 + *
43815 + * $Id: neponset-flash.c,v 1.18 2001/07/14 00:59:17 thockin Exp $
43816 + */
43818 +#include <linux/config.h>
43819 +#include <linux/module.h>
43820 +#include <linux/types.h>
43821 +#include <linux/kernel.h>
43823 +#include <linux/mtd/mtd.h>
43824 +#include <linux/mtd/map.h>
43825 +#include <linux/mtd/partitions.h>
43827 +#include <asm/hardware.h>
43828 +#include <asm/io.h>
43829 +#include <asm/arch/assabet.h>
43831 +static __u8 read8(struct map_info *map, unsigned long ofs)
43833 + return readb(map->map_priv_1 + ofs);
43836 +static __u16 read16(struct map_info *map, unsigned long ofs)
43838 + return readw(map->map_priv_1 + ofs);
43841 +static __u32 read32(struct map_info *map, unsigned long ofs)
43843 + return readl(map->map_priv_1 + ofs);
43846 +static void copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
43848 + memcpy_fromio(to, map->map_priv_1 + from, len);
43851 +static void write8(struct map_info *map, __u8 d, unsigned long adr)
43853 + writeb(d, map->map_priv_1 + adr);
43856 +static void write16(struct map_info *map, __u16 d, unsigned long adr)
43858 + writew(d, map->map_priv_1 + adr);
43861 +static void write32(struct map_info *map, __u32 d, unsigned long adr)
43863 + writel(d, map->map_priv_1 + adr);
43866 +static void copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
43868 + memcpy_toio(map->map_priv_1 + to, from, len);
43871 +#define MAX_SZ (32 * 1024 * 1024)
43873 +static struct map_info neponset_map = {
43874 + name: "Neponset",
43875 + size: MAX_SZ,
43876 + buswidth: 4,
43877 + read8: read8,
43878 + read16: read16,
43879 + read32: read32,
43880 + copy_from: copy_from,
43881 + write8: write8,
43882 + write16: write16,
43883 + write32: write32,
43884 + copy_to: copy_to,
43887 +extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
43888 +extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
43890 +static struct mtd_info *neponset_mtd;
43892 +int __init neponset_mtd_init(void)
43894 + if (!machine_is_assabet() || !machine_has_neponset())
43895 + return -ENODEV;
43897 + neponset_map.map_priv_1 = (unsigned int)ioremap(0x08000000, MAX_SZ);
43898 + if (!neponset_map.map_priv_1)
43899 + return -ENOMEM;
43901 + neponset_mtd = do_map_probe("cfi_probe", &neponset_map);
43902 + if (!neponset_mtd)
43903 + return -ENXIO;
43904 + neponset_mtd->module = THIS_MODULE;
43905 + add_mtd_device(neponset_mtd);
43906 + return 0;
43909 +static void __exit neponset_mtd_cleanup(void)
43911 + if (neponset_mtd)
43912 + map_destroy(neponset_mtd);
43913 + if (neponset_map.map_priv_1)
43914 + iounmap((void *)neponset_map.map_priv_1);
43917 +module_init(neponset_mtd_init);
43918 +module_exit(neponset_mtd_cleanup);
43919 --- linux-2.4.25/drivers/mtd/maps/sa1100-flash.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
43920 +++ linux-2.4.25/drivers/mtd/maps/sa1100-flash.c 2004-03-31 17:15:09.000000000 +0200
43921 @@ -97,6 +97,32 @@
43922 * entries. Thanks.
43925 +#ifdef CONFIG_SA1100_ADSAGC
43926 +#define ADSAGC_FLASH_SIZE 0x02000000
43927 +static struct mtd_partition adsagc_partitions[] = {
43929 + name: "bootROM",
43930 + size: 0x80000,
43931 + offset: 0,
43932 + mask_flags: MTD_WRITEABLE, /* force read-only */
43933 + }, {
43934 + name: "zImage",
43935 + size: 0x100000,
43936 + offset: MTDPART_OFS_APPEND,
43937 + mask_flags: MTD_WRITEABLE, /* force read-only */
43938 + }, {
43939 + name: "ramdisk.gz",
43940 + size: 0x300000,
43941 + offset: MTDPART_OFS_APPEND,
43942 + mask_flags: MTD_WRITEABLE, /* force read-only */
43943 + }, {
43944 + name: "User FS",
43945 + size: MTDPART_SIZ_FULL,
43946 + offset: MTDPART_OFS_APPEND,
43949 +#endif
43951 #ifdef CONFIG_SA1100_ADSBITSY
43952 #define ADSBITSY_FLASH_SIZE 0x02000000
43953 static struct mtd_partition adsbitsy_partitions[] = {
43954 @@ -123,6 +149,32 @@
43956 #endif
43958 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
43959 +#define ADSBITSYPLUS_FLASH_SIZE 0x02000000
43960 +static struct mtd_partition adsbitsyplus_partitions[] = {
43962 + name: "bootROM",
43963 + size: 0x80000,
43964 + offset: 0,
43965 + mask_flags: MTD_WRITEABLE, /* force read-only */
43966 + }, {
43967 + name: "zImage",
43968 + size: 0x100000,
43969 + offset: MTDPART_OFS_APPEND,
43970 + mask_flags: MTD_WRITEABLE, /* force read-only */
43971 + }, {
43972 + name: "ramdisk.gz",
43973 + size: 0x300000,
43974 + offset: MTDPART_OFS_APPEND,
43975 + mask_flags: MTD_WRITEABLE, /* force read-only */
43976 + }, {
43977 + name: "User FS",
43978 + size: MTDPART_SIZ_FULL,
43979 + offset: MTDPART_OFS_APPEND,
43982 +#endif
43984 #ifdef CONFIG_SA1100_ASSABET
43985 /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
43986 #define ASSABET4_FLASH_SIZE 0x00400000
43987 @@ -438,7 +490,7 @@
43988 #endif
43990 #ifdef CONFIG_SA1100_GRAPHICSMASTER
43991 -#define GRAPHICSMASTER_FLASH_SIZE 0x01000000
43992 +#define GRAPHICSMASTER_FLASH_SIZE 0x02000000
43993 static struct mtd_partition graphicsmaster_partitions[] = {
43995 name: "zImage",
43996 @@ -507,6 +559,38 @@
43998 #endif
44000 +#ifdef CONFIG_SA1100_HACKKIT
44001 +#define HACKKIT_FLASH_SIZE 0x01000000
44002 +static struct mtd_partition hackkit_partitions[] = {
44004 + name: "BLOB",
44005 + size: 0x00040000,
44006 + offset: 0x00000000,
44007 + mask_flags: MTD_WRITEABLE, /* force read-only */
44008 + }, {
44009 + name: "config",
44010 + size: 0x00040000,
44011 + offset: MTDPART_OFS_APPEND,
44012 + }, {
44013 + name: "kernel",
44014 + size: 0x00100000,
44015 + offset: MTDPART_OFS_APPEND,
44016 + }, {
44017 + name: "initrd",
44018 + size: 0x00180000,
44019 + offset: MTDPART_OFS_APPEND,
44020 + }, {
44021 + name: "rootfs",
44022 + size: 0x700000,
44023 + offset: MTDPART_OFS_APPEND,
44024 + }, {
44025 + name: "data",
44026 + size: MTDPART_SIZ_FULL,
44027 + offset: MTDPART_OFS_APPEND,
44030 +#endif
44032 #ifdef CONFIG_SA1100_HUW_WEBPANEL
44033 #define HUW_WEBPANEL_FLASH_SIZE 0x01000000
44034 static struct mtd_partition huw_webpanel_partitions[] = {
44035 @@ -555,12 +639,12 @@
44036 offset: 0x00540000,
44037 }, {
44038 name: "JORNADA720 usr local",
44039 - size: 0 /* will expand to the end of the flash */
44040 + size: 0, /* will expand to the end of the flash */
44041 offset: 0x00d00000,
44045 -static void jornada720_set_vpp(int vpp)
44046 +static void jornada720_set_vpp(struct map_info *map, int vpp)
44048 if (vpp)
44049 PPSR |= 0x80;
44050 @@ -571,6 +655,27 @@
44052 #endif
44054 +#ifdef CONFIG_SA1100_NANOENGINE
44055 +/* nanoEngine has one 28F320B3B Flash part in bank 0: */
44056 +#define NANOENGINE_FLASH_SIZE 0x00400000
44057 +static struct mtd_partition nanoengine_partitions[] = {
44059 + name: "nanoEngine boot firmware and parameter table",
44060 + size: 0x00010000, /* 32K */
44061 + offset: 0x00000000,
44062 + mask_flags: MTD_WRITEABLE, /* force read-only */
44063 + },{
44064 + name: "kernel/initrd reserved",
44065 + size: 0x002f0000,
44066 + offset: 0x00010000,
44067 + },{
44068 + name: "experimental filesystem allocation",
44069 + size: 0x00100000,
44070 + offset: 0x00300000,
44073 +#endif
44075 #ifdef CONFIG_SA1100_PANGOLIN
44076 #define PANGOLIN_FLASH_SIZE 0x04000000
44077 static struct mtd_partition pangolin_partitions[] = {
44078 @@ -699,6 +804,32 @@
44080 #endif /* CONFIG_SA1100_SIMPAD */
44082 +#ifdef CONFIG_SA1100_SIMPUTER
44083 +#define SIMPUTER_FLASH_SIZE 0x02000000
44084 +static struct mtd_partition simputer_partitions[] = {
44086 + name: "blob+logo",
44087 + offset: 0,
44088 + size: 0x00040000
44089 + },
44091 + name: "kernel",
44092 + offset: MTDPART_OFS_APPEND,
44093 + size: 0x000C0000
44094 + },
44096 + name: "/(cramfs)",
44097 + offset: MTDPART_OFS_APPEND,
44098 + size: 0x00200000
44099 + },
44101 + name: "/usr/local(jffs2)",
44102 + offset: MTDPART_OFS_APPEND,
44103 + size: MTDPART_SIZ_FULL /* expand till the end */
44106 +#endif
44108 #ifdef CONFIG_SA1100_STORK
44109 #define STORK_FLASH_SIZE 0x02000000
44110 static struct mtd_partition stork_partitions[] = {
44111 @@ -766,7 +897,7 @@
44112 #endif
44114 extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
44115 -extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
44116 +extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
44118 static struct mtd_partition *parsed_parts;
44119 static struct mtd_info *mymtd;
44120 @@ -787,6 +918,14 @@
44122 part_type = "static";
44124 +#ifdef CONFIG_SA1100_ADSAGC
44125 + if (machine_is_adsagc()) {
44126 + parts = adsagc_partitions;
44127 + nb_parts = ARRAY_SIZE(adsagc_partitions);
44128 + sa1100_map.size = ADSAGC_FLASH_SIZE;
44129 + sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
44131 +#endif
44132 #ifdef CONFIG_SA1100_ADSBITSY
44133 if (machine_is_adsbitsy()) {
44134 parts = adsbitsy_partitions;
44135 @@ -795,6 +934,14 @@
44136 sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
44138 #endif
44139 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
44140 + if (machine_is_adsbitsyplus()) {
44141 + parts = adsbitsyplus_partitions;
44142 + nb_parts = ARRAY_SIZE(adsbitsyplus_partitions);
44143 + sa1100_map.size = ADSBITSYPLUS_FLASH_SIZE;
44144 + sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
44146 +#endif
44147 #ifdef CONFIG_SA1100_ASSABET
44148 if (machine_is_assabet()) {
44149 parts = assabet_partitions;
44150 @@ -869,6 +1016,13 @@
44151 sa1100_map.set_vpp = h3600_set_vpp;
44153 #endif
44154 +#ifdef CONFIG_SA1100_HACKKIT
44155 + if (machine_is_hackkit()) {
44156 + parts = hackkit_partitions;
44157 + nb_parts = ARRAY_SIZE(hackkit_partitions);
44158 + sa1100_map.size = HACKKIT_FLASH_SIZE;
44160 +#endif
44161 #ifdef CONFIG_SA1100_HUW_WEBPANEL
44162 if (machine_is_huw_webpanel()) {
44163 parts = huw_webpanel_partitions;
44164 @@ -884,6 +1038,13 @@
44165 sa1100_map.set_vpp = jornada720_set_vpp;
44167 #endif
44168 +#ifdef CONFIG_SA1100_NANOENGINE
44169 + if (machine_is_nanoengine()) {
44170 + parts = nanoengine_partitions;
44171 + nb_parts = ARRAY_SIZE(nanoengine_partitions);
44172 + sa1100_map.size = NANOENGINE_FLASH_SIZE;
44174 +#endif
44175 #ifdef CONFIG_SA1100_PANGOLIN
44176 if (machine_is_pangolin()) {
44177 parts = pangolin_partitions;
44178 @@ -919,6 +1080,13 @@
44179 sa1100_map.size = SIMPAD_FLASH_SIZE;
44181 #endif
44182 +#ifdef CONFIG_SA1100_SIMPUTER
44183 + if (machine_is_simputer()) {
44184 + parts = simputer_partitions;
44185 + nb_parts = ARRAY_SIZE(simputer_partitions);
44186 + sa1100_map.size = SIMPUTER_FLASH_SIZE;
44188 +#endif
44189 #ifdef CONFIG_SA1100_STORK
44190 if (machine_is_stork()) {
44191 parts = stork_partitions;
44192 @@ -953,7 +1121,9 @@
44193 * specific machine settings might have been set above.
44195 printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8);
44196 - mymtd = do_map_probe("cfi_probe", &sa1100_map);
44197 + mymtd = do_map_probe("jedec_probe", &sa1100_map);
44198 + if (!mymtd)
44199 + mymtd = do_map_probe("cfi_probe", &sa1100_map);
44200 ret = -ENXIO;
44201 if (!mymtd)
44202 goto out_err;
44203 --- linux-2.4.25/drivers/net/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
44204 +++ linux-2.4.25/drivers/net/Config.in 2004-03-31 17:15:09.000000000 +0200
44205 @@ -30,9 +30,15 @@
44206 if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
44207 source drivers/acorn/net/Config.in
44209 + if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
44210 + tristate ' AT91RM9200 Ethernet support' CONFIG_AT91_ETHER
44211 + if [ "$CONFIG_AT91_ETHER" = "y" -o "$CONFIG_AT91_ETHER" = "m" ]; then
44212 + bool ' RMII interface? ' CONFIG_AT91_ETHER_RMII
44213 + fi
44214 + fi
44216 if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
44217 - tristate ' Altera Ether00 support' CONFIG_ETHER00
44218 + tristate ' Altera Ether00 support' CONFIG_ETHER00
44220 if [ "$CONFIG_PPC" = "y" ]; then
44221 dep_tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE $CONFIG_ALL_PPC
44222 --- linux-2.4.25/drivers/net/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
44223 +++ linux-2.4.25/drivers/net/Makefile 2004-03-31 17:15:09.000000000 +0200
44224 @@ -243,6 +243,7 @@
44225 # non-drivers/net drivers who want mii lib
44226 obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
44227 obj-$(CONFIG_USB_USBNET) += mii.o
44228 +obj-$(CONFIG_AT91_ETHER) += mii.o
44230 ifeq ($(CONFIG_ARCH_ACORN),y)
44231 mod-subdirs += ../acorn/net
44232 @@ -267,4 +268,3 @@
44234 rcpci.o: $(rcpci-objs)
44235 $(LD) -r -o $@ $(rcpci-objs)
44237 --- linux-2.4.25/drivers/net/am79c961a.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
44238 +++ linux-2.4.25/drivers/net/am79c961a.c 2004-03-31 17:15:09.000000000 +0200
44239 @@ -54,25 +54,36 @@
44240 #ifdef __arm__
44241 static void write_rreg(u_long base, u_int reg, u_int val)
44243 - __asm__("str%?h %1, [%2] @ NET_RAP
44244 - str%?h %0, [%2, #-4] @ NET_RDP
44245 - " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
44246 + __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
44247 + "str%?h %0, [%2, #-4] @ NET_RDP"
44248 + : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
44251 static inline unsigned short read_rreg(u_long base_addr, u_int reg)
44253 unsigned short v;
44254 - __asm__("str%?h %1, [%2] @ NET_RAP
44255 - ldr%?h %0, [%2, #-4] @ NET_RDP
44256 - " : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
44257 + __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
44258 + "ldr%?h %0, [%2, #-4] @ NET_RDP"
44259 + : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
44260 return v;
44263 static inline void write_ireg(u_long base, u_int reg, u_int val)
44265 - __asm__("str%?h %1, [%2] @ NET_RAP
44266 - str%?h %0, [%2, #8] @ NET_IDP
44267 - " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
44268 + __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
44269 + "str%?h %0, [%2, #8] @ NET_IDP"
44270 + : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
44273 +static inline unsigned short read_ireg(u_long base_addr, u_int reg)
44275 + u_short v;
44276 + __asm__(
44277 + "str%?h %1, [%2] @ NAT_RAP\n\t"
44278 + "str%?h %0, [%2, #8] @ NET_IDP\n\t"
44279 + : "=r" (v)
44280 + : "r" (reg), "r" (ISAIO_BASE + 0x0464));
44281 + return v;
44284 #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
44285 @@ -91,16 +102,16 @@
44287 while (length > 8) {
44288 unsigned int tmp, tmp2;
44289 - __asm__ __volatile__("
44290 - ldm%?ia %1!, {%2, %3}
44291 - str%?h %2, [%0], #4
44292 - mov%? %2, %2, lsr #16
44293 - str%?h %2, [%0], #4
44294 - str%?h %3, [%0], #4
44295 - mov%? %3, %3, lsr #16
44296 - str%?h %3, [%0], #4
44297 - " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
44298 - : "0" (offset), "1" (buf));
44299 + __asm__ __volatile__(
44300 + "ldm%?ia %1!, {%2, %3}\n\t"
44301 + "str%?h %2, [%0], #4\n\t"
44302 + "mov%? %2, %2, lsr #16\n\t"
44303 + "str%?h %2, [%0], #4\n\t"
44304 + "str%?h %3, [%0], #4\n\t"
44305 + "mov%? %3, %3, lsr #16\n\t"
44306 + "str%?h %3, [%0], #4"
44307 + : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
44308 + : "0" (offset), "1" (buf));
44309 length -= 8;
44311 while (length > 0) {
44312 @@ -118,36 +129,36 @@
44313 length = (length + 1) & ~1;
44314 if ((int)buf & 2) {
44315 unsigned int tmp;
44316 - __asm__ __volatile__("
44317 - ldr%?h %2, [%0], #4
44318 - str%?b %2, [%1], #1
44319 - mov%? %2, %2, lsr #8
44320 - str%?b %2, [%1], #1
44321 - " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
44322 + __asm__ __volatile__(
44323 + "ldr%?h %2, [%0], #4\n\t"
44324 + "str%?b %2, [%1], #1\n\t"
44325 + "mov%? %2, %2, lsr #8\n\t"
44326 + "str%?b %2, [%1], #1"
44327 + : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
44328 length -= 2;
44330 while (length > 8) {
44331 unsigned int tmp, tmp2, tmp3;
44332 - __asm__ __volatile__("
44333 - ldr%?h %2, [%0], #4
44334 - ldr%?h %3, [%0], #4
44335 - orr%? %2, %2, %3, lsl #16
44336 - ldr%?h %3, [%0], #4
44337 - ldr%?h %4, [%0], #4
44338 - orr%? %3, %3, %4, lsl #16
44339 - stm%?ia %1!, {%2, %3}
44340 - " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
44341 - : "0" (offset), "1" (buf));
44342 + __asm__ __volatile__(
44343 + "ldr%?h %2, [%0], #4\n\t"
44344 + "ldr%?h %3, [%0], #4\n\t"
44345 + "orr%? %2, %2, %3, lsl #16\n\t"
44346 + "ldr%?h %3, [%0], #4\n\t"
44347 + "ldr%?h %4, [%0], #4\n\t"
44348 + "orr%? %3, %3, %4, lsl #16\n\t"
44349 + "stm%?ia %1!, {%2, %3}"
44350 + : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
44351 + : "0" (offset), "1" (buf));
44352 length -= 8;
44354 while (length > 0) {
44355 unsigned int tmp;
44356 - __asm__ __volatile__("
44357 - ldr%?h %2, [%0], #4
44358 - str%?b %2, [%1], #1
44359 - mov%? %2, %2, lsr #8
44360 - str%?b %2, [%1], #1
44361 - " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
44362 + __asm__ __volatile__(
44363 + "ldr%?h %2, [%0], #4\n\t"
44364 + "str%?b %2, [%1], #1\n\t"
44365 + "mov%? %2, %2, lsr #8\n\t"
44366 + "str%?b %2, [%1], #1"
44367 + : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
44368 length -= 2;
44371 @@ -254,9 +265,27 @@
44372 write_rreg (dev->base_addr, BASERXH, 0);
44373 write_rreg (dev->base_addr, CSR0, CSR0_STOP);
44374 write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
44375 + write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
44376 write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
44379 +static void am79c961_timer(unsigned long data)
44381 + struct net_device *dev = (struct net_device *)data;
44382 + struct dev_priv *priv = (struct dev_priv *)dev->priv;
44383 + unsigned int lnkstat, carrier;
44385 + lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
44386 + carrier = netif_carrier_ok(dev);
44388 + if (lnkstat && !carrier)
44389 + netif_carrier_on(dev);
44390 + else if (!lnkstat && carrier)
44391 + netif_carrier_off(dev);
44393 + mod_timer(&priv->timer, jiffies + 5*HZ);
44397 * Open/initialize the board.
44399 @@ -274,6 +303,11 @@
44401 am79c961_init_for_open(dev);
44403 + netif_carrier_off(dev);
44405 + priv->timer.expires = jiffies;
44406 + add_timer(&priv->timer);
44408 netif_start_queue(dev);
44410 return 0;
44411 @@ -288,7 +322,10 @@
44412 struct dev_priv *priv = (struct dev_priv *)dev->priv;
44413 unsigned long flags;
44415 + del_timer_sync(&priv->timer);
44417 netif_stop_queue(dev);
44418 + netif_carrier_off(dev);
44420 spin_lock_irqsave(priv->chip_lock, flags);
44421 write_rreg (dev->base_addr, CSR0, CSR0_STOP);
44422 @@ -413,15 +450,6 @@
44423 unsigned int hdraddr, bufaddr;
44424 unsigned int head;
44425 unsigned long flags;
44427 - /* FIXME: I thought the 79c961 could do padding - RMK ??? */
44428 - if(length < ETH_ZLEN)
44430 - skb = skb_padto(skb, ETH_ZLEN);
44431 - if(skb == NULL)
44432 - return 0;
44433 - length = ETH_ZLEN;
44436 head = priv->txhead;
44437 hdraddr = priv->txhdr + (head << 3);
44438 @@ -431,7 +459,7 @@
44439 head = 0;
44441 am_writebuffer (dev, bufaddr, skb->data, length);
44442 - am_writeword (dev, hdraddr + 4, -length);
44443 + am_writeword (dev, hdraddr + 4, -skb->len);
44444 am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
44445 priv->txhead = head;
44447 @@ -448,6 +476,8 @@
44448 if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
44449 netif_stop_queue(dev);
44451 + priv->stats.tx_bytes += skb->len;
44453 dev_kfree_skb(skb);
44455 return 0;
44456 @@ -520,6 +550,7 @@
44457 am79c961_tx(struct net_device *dev, struct dev_priv *priv)
44459 do {
44460 + signed short len;
44461 u_int hdraddr;
44462 u_int status;
44464 @@ -555,6 +586,8 @@
44465 continue;
44467 priv->stats.tx_packets ++;
44468 + len = am_readword (dev, hdraddr + 4);
44469 + priv->stats.tx_bytes += -len;
44470 } while (priv->txtail != priv->txhead);
44472 netif_wake_queue(dev);
44473 @@ -565,17 +598,23 @@
44475 struct net_device *dev = (struct net_device *)dev_id;
44476 struct dev_priv *priv = (struct dev_priv *)dev->priv;
44477 - u_int status;
44478 + u_int status, n = 100;
44480 - status = read_rreg(dev->base_addr, CSR0);
44481 - write_rreg(dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
44482 + do {
44483 + status = read_rreg(dev->base_addr, CSR0);
44484 + write_rreg(dev->base_addr, CSR0, status &
44485 + (CSR0_IENA|CSR0_TINT|CSR0_RINT|
44486 + CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
44488 - if (status & CSR0_RINT)
44489 - am79c961_rx(dev, priv);
44490 - if (status & CSR0_TINT)
44491 - am79c961_tx(dev, priv);
44492 - if (status & CSR0_MISS)
44493 - priv->stats.rx_dropped ++;
44494 + if (status & CSR0_RINT)
44495 + am79c961_rx(dev, priv);
44496 + if (status & CSR0_TINT)
44497 + am79c961_tx(dev, priv);
44498 + if (status & CSR0_MISS)
44499 + priv->stats.rx_dropped ++;
44500 + if (status & CSR0_CERR)
44501 + mod_timer(&priv->timer, jiffies);
44502 + } while (--n && status & (CSR0_RINT | CSR0_TINT));
44506 @@ -587,10 +626,10 @@
44508 struct dev_priv *priv = (struct dev_priv *)dev->priv;
44510 - spin_lock_irq(priv->chip_lock);
44511 + spin_lock_irq(&priv->chip_lock);
44512 write_rreg (dev->base_addr, CSR0, CSR0_STOP);
44513 write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
44514 - spin_unlock_irq(priv->chip_lock);
44515 + spin_unlock_irq(&priv->chip_lock);
44517 am79c961_ramtest(dev, 0x66);
44518 am79c961_ramtest(dev, 0x99);
44519 @@ -655,6 +694,11 @@
44520 printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
44523 + spin_lock_init(&priv->chip_lock);
44524 + init_timer(&priv->timer);
44525 + priv->timer.data = (unsigned long)dev;
44526 + priv->timer.function = am79c961_timer;
44528 if (am79c961_hw_init(dev))
44529 goto release;
44531 --- linux-2.4.25/drivers/net/am79c961a.h~2.4.25-vrs2.patch 2000-09-19 00:15:22.000000000 +0200
44532 +++ linux-2.4.25/drivers/net/am79c961a.h 2004-03-31 17:15:09.000000000 +0200
44533 @@ -58,6 +58,18 @@
44534 #define CSR3_BABLM 0x4000
44535 #define CSR3_MASKALL 0x5F00
44537 +#define CSR4 4
44538 +#define CSR4_JABM 0x0001
44539 +#define CSR4_JAB 0x0002
44540 +#define CSR4_TXSTRTM 0x0004
44541 +#define CSR4_TXSTRT 0x0008
44542 +#define CSR4_RCVCCOM 0x0010
44543 +#define CSR4_RCVCCO 0x0020
44544 +#define CSR4_MFCOM 0x0100
44545 +#define CSR4_MFCO 0x0200
44546 +#define CSR4_ASTRP_RCV 0x0400
44547 +#define CSR4_APAD_XMIT 0x0800
44549 #define CTRL1 5
44550 #define CTRL1_SPND 0x0001
44552 @@ -93,6 +105,8 @@
44553 #define SIZERXR 76
44554 #define SIZETXR 78
44556 +#define CSR_MFC 112
44558 #define RMD_ENP 0x0100
44559 #define RMD_STP 0x0200
44560 #define RMD_CRC 0x0800
44561 @@ -112,6 +126,9 @@
44562 #define TST_UFLO 0x4000
44563 #define TST_BUFF 0x8000
44565 +#define ISALED0 0x0004
44566 +#define ISALED0_LNKST 0x8000
44568 struct dev_priv {
44569 struct net_device_stats stats;
44570 unsigned long rxbuffer[RX_BUFFERS];
44571 @@ -123,6 +140,7 @@
44572 unsigned long rxhdr;
44573 unsigned long txhdr;
44574 spinlock_t chip_lock;
44575 + struct timer_list timer;
44578 extern int am79c961_probe (struct net_device *dev);
44579 --- linux-2.4.25/drivers/net/cirrus.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
44580 +++ linux-2.4.25/drivers/net/cirrus.c 2004-03-31 17:15:09.000000000 +0200
44581 @@ -75,6 +75,7 @@
44582 typedef struct {
44583 struct net_device_stats stats;
44584 u16 txlen;
44585 + u16 txafter; /* Default is After5 (0) */
44586 } cirrus_t;
44588 typedef struct {
44589 @@ -230,13 +231,19 @@
44590 cirrus_t *priv = (cirrus_t *) dev->priv;
44591 u16 status;
44593 + /* Tx start must be done with irq disabled
44594 + * else status can be wrong */
44595 + disable_irq (dev->irq);
44597 netif_stop_queue (dev);
44599 - cirrus_write (dev,PP_TxCMD,TxStart (After5));
44600 + cirrus_write (dev,PP_TxCMD,TxStart (priv->txafter));
44601 cirrus_write (dev,PP_TxLength,skb->len);
44603 status = cirrus_read (dev,PP_BusST);
44605 + enable_irq (dev->irq);
44607 if ((status & TxBidErr)) {
44608 printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);
44609 priv->stats.tx_errors++;
44610 @@ -249,7 +256,6 @@
44611 printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);
44612 priv->stats.tx_errors++;
44613 priv->txlen = 0;
44614 - /* FIXME: store skb and send it in interrupt handler */
44615 return (1);
44618 @@ -310,11 +316,18 @@
44620 if ((RegContent (status) & TxUnderrun)) {
44621 priv->stats.tx_errors++;
44622 - priv->stats.tx_fifo_errors++;
44623 + /* Shift start tx, if underruns come too often */
44624 + switch (priv->stats.tx_fifo_errors++) {
44625 + case 3: priv->txafter = After381; break;
44626 + case 6: priv->txafter = After1021; break;
44627 + case 9: priv->txafter = AfterAll; break;
44630 + /* Wakeup only for tx events ! */
44631 + if ((RegContent (status) & (TxUnderrun | Rdy4Tx))) {
44632 + priv->txlen = 0;
44633 + netif_wake_queue (dev);
44635 - /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */
44636 - priv->txlen = 0;
44637 - netif_wake_queue (dev);
44638 break;
44640 case TxCOL:
44641 @@ -428,7 +441,7 @@
44642 else
44643 cirrus_clear (dev,PP_RxCTL,PromiscuousA);
44645 - if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)
44646 + if ((dev->flags & IFF_ALLMULTI) || dev->mc_list)
44647 cirrus_set (dev,PP_RxCTL,MulticastA);
44648 else
44649 cirrus_clear (dev,PP_RxCTL,MulticastA);
44650 --- linux-2.4.25/drivers/net/cs89x0.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
44651 +++ linux-2.4.25/drivers/net/cs89x0.c 2004-03-31 17:15:09.000000000 +0200
44652 @@ -115,6 +115,7 @@
44656 +#include <linux/config.h>
44657 #include <linux/kernel.h>
44658 #include <linux/sched.h>
44659 #include <linux/types.h>
44660 @@ -427,18 +428,18 @@
44661 /* if they give us an odd I/O address, then do ONE write to
44662 the address port, to get it back to address zero, where we
44663 expect to find the EISA signature word. An IO with a base of 0x3
44664 - will skip the test for the ADD_PORT. */
44665 + will skip the test for the ADD_PORT. */
44666 if (ioaddr & 1) {
44667 if (net_debug > 1)
44668 printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
44669 - if ((ioaddr & 2) != 2)
44670 + if ((ioaddr & 2) != 2)
44671 if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) {
44672 printk(KERN_ERR "%s: bad signature 0x%x\n",
44673 dev->name, inw((ioaddr & ~3)+ ADD_PORT));
44674 retval = -ENODEV;
44675 goto out2;
44677 - ioaddr &= ~3;
44678 + ioaddr &= ~3;
44679 outw(PP_ChipID, ioaddr + ADD_PORT);
44681 printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
44682 @@ -446,7 +447,7 @@
44683 if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
44684 printk(KERN_ERR "%s: incorrect signature 0x%x\n",
44685 dev->name, inw(ioaddr + DATA_PORT));
44686 - retval = -ENODEV;
44687 + retval = -ENODEV;
44688 goto out2;
44691 @@ -477,7 +478,7 @@
44692 dev->base_addr);
44694 reset_chip(dev);
44697 /* Here we read the current configuration of the chip. If there
44698 is no Extended EEPROM then the idea is to not disturb the chip
44699 configuration, it should have been correctly setup by automatic
44700 --- linux-2.4.25/drivers/net/ether00.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
44701 +++ linux-2.4.25/drivers/net/ether00.c 2004-03-31 17:15:09.000000000 +0200
44702 @@ -38,6 +38,7 @@
44703 #include <asm/arch/ether00.h>
44704 #include <asm/arch/tdkphy.h>
44706 +static int ether00_get_ethernet_address(struct net_device* dev);
44708 MODULE_AUTHOR("Clive Davies");
44709 MODULE_DESCRIPTION("Altera Ether00 IP core driver");
44710 @@ -734,8 +735,11 @@
44711 int result,tmp;
44712 struct net_priv* priv;
44714 - if (!is_valid_ether_addr(dev->dev_addr))
44715 - return -EINVAL;
44716 + if (!ether00_get_ethernet_address(dev)){
44717 + printk("%s: Invalid ethernet MAC address. Please set using "
44718 + "ifconfig\n", dev->name);
44719 + return -EINVAL;
44722 dev->base_addr=(unsigned int)ioremap_nocache(base,SZ_4K);
44724 @@ -906,10 +910,9 @@
44728 -static void ether00_get_ethernet_address(struct net_device* dev)
44729 +static int ether00_get_ethernet_address(struct net_device* dev)
44731 struct mtd_info *mymtd=NULL;
44732 - int i;
44733 size_t retlen;
44736 @@ -926,11 +929,7 @@
44737 #ifdef CONFIG_ARCH_CAMELOT
44738 #ifdef CONFIG_MTD
44739 /* get the mtd_info structure for the first mtd device*/
44740 - for(i=0;i<MAX_MTD_DEVICES;i++){
44741 - mymtd=get_mtd_device(NULL,i);
44742 - if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash"))
44743 - break;
44745 + mymtd=get_mtd_device(NULL,0);
44747 if(!mymtd || !mymtd->read_user_prot_reg){
44748 printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name);
44749 @@ -947,9 +946,7 @@
44750 #endif
44751 #endif
44753 - if (!is_valid_ether_addr(dev->dev_addr))
44754 - printk("%s: Invalid ethernet MAC address. Please set using "
44755 - "ifconfig\n", dev->name);
44756 + return (is_valid_ether_addr(dev->dev_addr));
44760 @@ -966,8 +963,6 @@
44761 dev->tx_timeout=ether00_tx_timeout;
44762 dev->watchdog_timeo=TX_TIMEOUT;
44764 - ether00_get_ethernet_address(dev);
44766 SET_MODULE_OWNER(dev);
44767 return 0;
44769 --- linux-2.4.25/drivers/net/irda/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
44770 +++ linux-2.4.25/drivers/net/irda/Config.in 2004-03-31 17:15:09.000000000 +0200
44771 @@ -40,7 +40,7 @@
44772 dep_tristate 'VIA IrCC (Experimental)' CONFIG_VIA_IRCC_FIR $CONFIG_IRDA
44774 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
44775 - dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA
44776 + dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
44779 endmenu
44780 --- linux-2.4.25/drivers/net/irda/sa1100_ir.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
44781 +++ linux-2.4.25/drivers/net/irda/sa1100_ir.c 2004-03-31 17:15:09.000000000 +0200
44782 @@ -38,11 +38,7 @@
44784 #include <asm/arch/assabet.h>
44786 -#ifndef CONFIG_SA1100_H3600
44787 -#define clr_h3600_egpio(x) do { } while (0)
44788 -#define set_h3600_egpio(x) do { } while (0)
44789 -#endif
44791 +/* Yopy wants fixing */
44792 #ifndef GPIO_IRDA_FIR
44793 #define GPIO_IRDA_FIR (0)
44794 #endif
44795 @@ -174,8 +170,8 @@
44797 if (machine_is_assabet())
44798 ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
44799 - if (machine_is_h3600())
44800 - clr_h3600_egpio(EGPIO_H3600_IR_FSEL);
44801 + if (machine_is_h3xxx())
44802 + clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
44803 if (machine_is_yopy())
44804 PPSR &= ~GPIO_IRDA_FIR;
44806 @@ -199,8 +195,8 @@
44808 if (machine_is_assabet())
44809 ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
44810 - if (machine_is_h3600())
44811 - set_h3600_egpio(EGPIO_H3600_IR_FSEL);
44812 + if (machine_is_h3xxx())
44813 + set_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
44814 if (machine_is_yopy())
44815 PPSR |= GPIO_IRDA_FIR;
44817 @@ -246,10 +242,7 @@
44818 static inline int
44819 sa1100_irda_set_power_h3600(struct sa1100_irda *si, unsigned int state)
44821 - if (state)
44822 - set_h3600_egpio(EGPIO_H3600_IR_ON);
44823 - else
44824 - clr_h3600_egpio(EGPIO_H3600_IR_ON);
44825 + assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state );
44826 return 0;
44829 @@ -283,7 +276,7 @@
44831 if (machine_is_assabet())
44832 ret = sa1100_irda_set_power_assabet(si, state);
44833 - if (machine_is_h3600())
44834 + if (machine_is_h3xxx())
44835 ret = sa1100_irda_set_power_h3600(si, state);
44836 if (machine_is_yopy())
44837 ret = sa1100_irda_set_power_yopy(si, state);
44838 @@ -727,11 +720,6 @@
44839 netif_wake_queue(dev);
44843 - * Note that we will never build up a backlog of frames; the protocol is a
44844 - * half duplex protocol which basically means we transmit a frame, we
44845 - * receive a frame, we transmit the next frame etc.
44846 - */
44847 static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
44849 struct sa1100_irda *si = dev->priv;
44850 @@ -758,6 +746,8 @@
44853 if (!IS_FIR(si)) {
44854 + netif_stop_queue(dev);
44856 si->tx_buff.data = si->tx_buff.head;
44857 si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
44858 si->tx_buff.truesize);
44859 --- linux-2.4.25/drivers/net/irda/w83977af_ir.c~2.4.25-vrs2.patch 2002-11-29 00:53:13.000000000 +0100
44860 +++ linux-2.4.25/drivers/net/irda/w83977af_ir.c 2004-03-31 17:15:09.000000000 +0200
44861 @@ -205,7 +205,7 @@
44863 /* FIXME: The HP HDLS-1100 does not support 1152000! */
44864 self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
44865 - IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
44866 + IR_115200/*|IR_576000|IR_1152000|(IR_4000000 << 8)*/;
44868 /* The HP HDLS-1100 needs 1 ms according to the specs */
44869 self->qos.min_turn_time.bits = qos_mtt_bits;
44870 @@ -1341,7 +1341,7 @@
44871 case SIOCSBANDWIDTH: /* Set bandwidth */
44872 if (!capable(CAP_NET_ADMIN)) {
44873 ret = -EPERM;
44874 - goto out;
44875 + break;
44877 w83977af_change_speed(self, irq->ifr_baudrate);
44878 break;
44879 --- linux-2.4.25/drivers/net/smc9194.c~2.4.25-vrs2.patch 2003-06-13 16:51:35.000000000 +0200
44880 +++ linux-2.4.25/drivers/net/smc9194.c 2004-03-31 17:15:09.000000000 +0200
44881 @@ -12,8 +12,8 @@
44882 . AUI/TP selection ( mine has 10Base2/10BaseT select )
44884 . Arguments:
44885 - . io = for the base address
44886 - . irq = for the IRQ
44887 + . io = for the base address
44888 + . irq = for the IRQ
44889 . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 )
44891 . author:
44892 @@ -51,12 +51,21 @@
44893 . allocation
44894 . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet
44895 . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ"
44896 + . 06/23/01 Russell King Separate out IO functions for different bus
44897 + . types.
44898 + . Use dev->name instead of CARDNAME for printk
44899 + . Add ethtool support, full duplex support
44900 + . Add LAN91C96 support.
44901 . 11/08/01 Matt Domsch Use common crc32 function
44902 ----------------------------------------------------------------------------*/
44904 +#define DRV_NAME "smc9194"
44905 +#define DRV_VERSION "0.15"
44907 static const char version[] =
44908 - "smc9194.c:v0.14 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
44909 + DRV_NAME ".c:v" DRV_VERSION " 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
44911 +#include <linux/config.h>
44912 #include <linux/module.h>
44913 #include <linux/version.h>
44914 #include <linux/kernel.h>
44915 @@ -69,16 +78,26 @@
44916 #include <linux/in.h>
44917 #include <linux/slab.h>
44918 #include <linux/string.h>
44919 +#include <linux/delay.h>
44920 #include <linux/init.h>
44921 #include <linux/crc32.h>
44922 -#include <asm/bitops.h>
44923 -#include <asm/io.h>
44924 #include <linux/errno.h>
44925 +#include <linux/ethtool.h>
44927 #include <linux/netdevice.h>
44928 #include <linux/etherdevice.h>
44929 #include <linux/skbuff.h>
44931 +#include <asm/bitops.h>
44932 +#include <asm/irq.h>
44933 +#include <asm/io.h>
44934 +#include <asm/uaccess.h>
44936 +#ifdef CONFIG_ARCH_SA1100
44937 +#include <asm/hardware.h>
44938 +#include <asm/arch/assabet.h>
44939 +#endif
44941 #include "smc9194.h"
44942 /*------------------------------------------------------------------------
44944 @@ -152,29 +171,27 @@
44945 -------------------------------------------------------------------------*/
44946 #define CARDNAME "SMC9194"
44948 +static const char *chip_ids[15] = {
44949 + NULL,
44950 + NULL,
44951 + NULL,
44952 + "SMC91C90/91C92", /* 3 */
44953 + "SMC91C94/91C96", /* 4 */
44954 + "SMC91C95", /* 5 */
44955 + NULL,
44956 + "SMC91C100", /* 7 */
44957 + "SMC91C100FD", /* 8 */
44958 + NULL,
44959 + NULL,
44960 + NULL,
44961 + NULL,
44962 + NULL,
44963 + NULL
44966 -/* store this information for the driver.. */
44967 -struct smc_local {
44968 - /*
44969 - these are things that the kernel wants me to keep, so users
44970 - can find out semi-useless statistics of how well the card is
44971 - performing
44972 - */
44973 - struct net_device_stats stats;
44975 - /*
44976 - If I have to wait until memory is available to send
44977 - a packet, I will store the skbuff here, until I get the
44978 - desired memory. Then, I'll send it out and free it.
44979 - */
44980 - struct sk_buff * saved_skb;
44982 - /*
44983 - . This keeps track of how many packets that I have
44984 - . sent out. When an TX_EMPTY interrupt comes, I know
44985 - . that all of these have been sent.
44986 - */
44987 - int packets_waiting;
44988 +static const char * interfaces[2] = {
44989 + "TP",
44990 + "AUI"
44994 @@ -202,6 +219,11 @@
44995 static int smc_open(struct net_device *dev);
44998 + . This handles the ethtool interface
45000 +static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
45003 . Our watchdog timed out. Called by the networking layer
45005 static void smc_timeout(struct net_device *dev);
45006 @@ -217,11 +239,11 @@
45007 . This routine allows the proc file system to query the driver's
45008 . statistics.
45010 -static struct net_device_stats * smc_query_statistics( struct net_device *dev);
45011 +static struct net_device_stats * smc_query_statistics(struct net_device *dev);
45014 - . Finally, a call to set promiscuous mode ( for TCPDUMP and related
45015 - . programs ) and multicast modes.
45016 + . Finally, a call to set promiscuous mode (for TCPDUMP and related
45017 + . programs) and multicast modes.
45019 static void smc_set_multicast_list(struct net_device *dev);
45021 @@ -240,12 +262,12 @@
45022 . This is a separate procedure to handle the receipt of a packet, to
45023 . leave the interrupt code looking slightly cleaner
45025 -static inline void smc_rcv( struct net_device *dev );
45026 +static inline void smc_rcv(struct net_device *dev);
45028 . This handles a TX interrupt, which is only called when an error
45029 . relating to a packet is sent.
45031 -static inline void smc_tx( struct net_device * dev );
45032 +static inline void smc_tx(struct net_device * dev);
45035 ------------------------------------------------------------
45036 @@ -261,39 +283,287 @@
45038 static int smc_probe(struct net_device *dev, int ioaddr);
45041 - . A rather simple routine to print out a packet for debugging purposes.
45043 -#if SMC_DEBUG > 2
45044 -static void print_packet( byte *, int );
45045 -#endif
45047 -#define tx_done(dev) 1
45049 /* this is called to actually send the packet to the chip */
45050 -static void smc_hardware_send_packet( struct net_device * dev );
45051 +static void smc_hardware_send_packet(struct net_device * dev);
45053 /* Since I am not sure if I will have enough room in the chip's ram
45054 . to store the packet, I call this routine, which either sends it
45055 . now, or generates an interrupt when the card is ready for the
45056 . packet */
45057 -static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device *dev );
45058 +static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *dev);
45060 /* this does a soft reset on the device */
45061 -static void smc_reset( int ioaddr );
45062 +static void smc_reset(struct net_device *dev);
45064 /* Enable Interrupts, Receive, and Transmit */
45065 -static void smc_enable( int ioaddr );
45066 +static void smc_enable(struct net_device *dev);
45068 /* this puts the device in an inactive state */
45069 -static void smc_shutdown( int ioaddr );
45070 +static void smc_shutdown(struct net_device *dev);
45072 /* This routine will find the IRQ of the driver if one is not
45073 . specified in the input to the device. */
45074 -static int smc_findirq( int ioaddr );
45075 +static int smc_findirq(struct net_device *dev);
45077 +#ifndef CONFIG_ASSABET_NEPONSET
45079 - . Function: smc_reset( int ioaddr )
45080 + * These functions allow us to handle IO addressing as we wish - this
45081 + * ethernet controller can be connected to a variety of busses. Some
45082 + * busses do not support 16 bit or 32 bit transfers. --rmk
45083 + */
45084 +static inline u8 smc_inb(u_int base, u_int reg)
45086 + return inb(base + reg);
45089 +static inline u16 smc_inw(u_int base, u_int reg)
45091 + return inw(base + reg);
45094 +static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
45096 + u_int port = base + reg;
45097 +#ifdef USE_32_BIT
45098 + /* QUESTION: Like in the TX routine, do I want
45099 + to send the DWORDs or the bytes first, or some
45100 + mixture. A mixture might improve already slow PIO
45101 + performance */
45102 + PRINTK3((" Reading %d dwords (and %d bytes) \n",
45103 + len >> 2, len & 3));
45104 + insl(port, data, len >> 2);
45105 + /* read the left over bytes */
45106 + insb(port, data + (len & ~3), len & 3);
45107 +#else
45108 + PRINTK3((" Reading %d words and %d byte(s) \n",
45109 + len >> 1, len & 1));
45110 + insw(port, data, len >> 1);
45111 + if (len & 1) {
45112 + data += len & ~1;
45113 + *data = inb(port);
45115 +#endif
45118 +static inline void smc_outb(u8 val, u_int base, u_int reg)
45120 + outb(val, base + reg);
45123 +static inline void smc_outw(u16 val, u_int base, u_int reg)
45125 + outw(val, base + reg);
45128 +static inline void smc_outl(u32 val, u_int base, u_int reg)
45130 + u_int port = base + reg;
45131 +#ifdef USE_32_BIT
45132 + outl(val, port);
45133 +#else
45134 + outw(val, port);
45135 + outw(val >> 16, port);
45136 +#endif
45139 +static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
45141 + u_int port = base + reg;
45142 +#ifdef USE_32_BIT
45143 + if (len & 2) {
45144 + outsl(port, data, len >> 2);
45145 + outw(*((word *)(data + (len & ~3))), port);
45147 + else
45148 + outsl(port, data, len >> 2);
45149 +#else
45150 + outsw(port, data, len >> 1);
45151 +#endif
45155 +/*-------------------------------------------------------------------------
45156 + . I define some macros to make it easier to do somewhat common
45157 + . or slightly complicated, repeated tasks.
45158 + --------------------------------------------------------------------------*/
45160 +/* select a register bank, 0 to 3 */
45162 +#define SMC_SELECT_BANK(x) \
45163 + { \
45164 + smc_outw(x, ioaddr, BANK_SELECT); \
45165 + }
45167 +/* define a small delay for the reset */
45168 +#define SMC_DELAY() \
45169 + { \
45170 + smc_inw(ioaddr, RCR); \
45171 + smc_inw(ioaddr, RCR); \
45172 + smc_inw(ioaddr, RCR); \
45175 +/* this enables an interrupt in the interrupt mask register */
45176 +#define SMC_ENABLE_INT(x) \
45177 + { \
45178 + byte mask; \
45179 + mask = smc_inb(ioaddr, INT_MASK); \
45180 + mask |= (x); \
45181 + smc_outb(mask, ioaddr, INT_MASK); \
45184 +/* this sets the absolutel interrupt mask */
45185 +#define SMC_SET_INT(x) \
45186 + { \
45187 + smc_outw((x), INT_MASK); \
45190 +#else
45192 +#undef SMC_IO_EXTENT
45193 +#define SMC_IO_EXTENT (16 << 2)
45196 + * These functions allow us to handle IO addressing as we wish - this
45197 + * ethernet controller can be connected to a variety of busses. Some
45198 + * busses do not support 16 bit or 32 bit transfers. --rmk
45199 + */
45200 +static inline u8 smc_inb(u_int base, u_int reg)
45202 + u_int port = base + reg * 4;
45204 + return readb(port);
45207 +static inline u16 smc_inw(u_int base, u_int reg)
45209 + u_int port = base + reg * 4;
45211 + return readb(port) | readb(port + 4) << 8;
45214 +static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
45216 + u_int port = base + reg * 4;
45218 + insb(port, data, len);
45221 +static inline void smc_outb(u8 val, u_int base, u_int reg)
45223 + u_int port = base + reg * 4;
45225 + writeb(val, port);
45228 +static inline void smc_outw(u16 val, u_int base, u_int reg)
45230 + u_int port = base + reg * 4;
45232 + writeb(val, port);
45233 + writeb(val >> 8, port + 4);
45236 +static inline void smc_outl(u32 val, u_int base, u_int reg)
45238 + u_int port = base + reg * 4;
45240 + writeb(val, port);
45241 + writeb(val >> 8, port + 4);
45242 + writeb(val >> 16, port + 8);
45243 + writeb(val >> 24, port + 12);
45246 +static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
45248 + u_int port = base + reg * 4;
45250 + outsb(port, data, len & ~1);
45253 +/*-------------------------------------------------------------------------
45254 + . I define some macros to make it easier to do somewhat common
45255 + . or slightly complicated, repeated tasks.
45256 + --------------------------------------------------------------------------*/
45258 +/* select a register bank, 0 to 3 */
45260 +#define SMC_SELECT_BANK(x) \
45261 + { \
45262 + smc_outb(x, ioaddr, BANK_SELECT); \
45263 + }
45265 +/* define a small delay for the reset */
45266 +#define SMC_DELAY() \
45267 + { \
45268 + smc_inb(ioaddr, RCR); \
45269 + smc_inb(ioaddr, RCR); \
45270 + smc_inb(ioaddr, RCR); \
45273 +/* this enables an interrupt in the interrupt mask register */
45274 +#define SMC_ENABLE_INT(x) \
45275 + { \
45276 + byte mask; \
45277 + mask = smc_inb(ioaddr, INT_MASK); \
45278 + mask |= (x); \
45279 + smc_outb(mask, ioaddr, INT_MASK); \
45282 +/* this sets the absolutel interrupt mask */
45283 +#define SMC_SET_INT(x) \
45284 + { \
45285 + smc_outb((x), ioaddr, INT_MASK); \
45288 +#endif
45291 + . A rather simple routine to print out a packet for debugging purposes.
45293 +#if SMC_DEBUG > 2
45294 +static void print_packet(byte * buf, int length)
45296 + int i;
45297 + int remainder;
45298 + int lines;
45300 + printk("Packet of length %d \n", length);
45301 + lines = length / 16;
45302 + remainder = length % 16;
45304 + for (i = 0; i < lines ; i ++) {
45305 + int cur;
45307 + for (cur = 0; cur < 8; cur ++) {
45308 + byte a, b;
45310 + a = *(buf ++);
45311 + b = *(buf ++);
45312 + printk("%02x%02x ", a, b);
45314 + printk("\n");
45316 + for (i = 0; i < remainder/2 ; i++) {
45317 + byte a, b;
45319 + a = *(buf ++);
45320 + b = *(buf ++);
45321 + printk("%02x%02x ", a, b);
45323 + if (remainder & 1) {
45324 + byte a;
45326 + a = *buf++;
45327 + printk("%02x", a);
45329 + printk("\n");
45331 +#else
45332 +#define print_packet(buf,len) do { } while (0)
45333 +#endif
45336 + . Function: smc_reset(struct net_device *dev)
45337 . Purpose:
45338 . This sets the SMC91xx chip to its normal state, hopefully from whatever
45339 . mess that any other DOS driver has put it in.
45340 @@ -309,36 +579,37 @@
45341 . 5. clear all interrupts
45344 -static void smc_reset( int ioaddr )
45345 +static void smc_reset(struct net_device *dev)
45347 + u_int ioaddr = dev->base_addr;
45349 /* This resets the registers mostly to defaults, but doesn't
45350 affect EEPROM. That seems unnecessary */
45351 - SMC_SELECT_BANK( 0 );
45352 - outw( RCR_SOFTRESET, ioaddr + RCR );
45353 + SMC_SELECT_BANK(0);
45354 + smc_outw(RCR_SOFTRESET, ioaddr, RCR);
45356 /* this should pause enough for the chip to be happy */
45357 - SMC_DELAY( );
45358 + SMC_DELAY();
45360 /* Set the transmit and receive configuration registers to
45361 default values */
45362 - outw( RCR_CLEAR, ioaddr + RCR );
45363 - outw( TCR_CLEAR, ioaddr + TCR );
45364 + smc_outw(RCR_CLEAR, ioaddr, RCR);
45365 + smc_outw(TCR_CLEAR, ioaddr, TCR);
45367 /* set the control register to automatically
45368 release successfully transmitted packets, to make the best
45369 use out of our limited memory */
45370 - SMC_SELECT_BANK( 1 );
45371 - outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL );
45372 + SMC_SELECT_BANK(1);
45373 + smc_outw(smc_inw(ioaddr, CONTROL) | CTL_AUTO_RELEASE, ioaddr, CONTROL);
45375 /* Reset the MMU */
45376 - SMC_SELECT_BANK( 2 );
45377 - outw( MC_RESET, ioaddr + MMU_CMD );
45378 + SMC_SELECT_BANK(2);
45379 + smc_outw(MC_RESET, ioaddr, MMU_CMD);
45381 /* Note: It doesn't seem that waiting for the MMU busy is needed here,
45382 but this is a place where future chipsets _COULD_ break. Be wary
45383 of issuing another MMU command right after this */
45385 - outb( 0, ioaddr + INT_MASK );
45386 + SMC_SET_INT(0);
45390 @@ -349,20 +620,21 @@
45391 . 2. Enable the receiver
45392 . 3. Enable interrupts
45394 -static void smc_enable( int ioaddr )
45395 +static void smc_enable(struct net_device *dev)
45397 - SMC_SELECT_BANK( 0 );
45398 + u_int ioaddr = dev->base_addr;
45399 + SMC_SELECT_BANK(0);
45400 /* see the header file for options in TCR/RCR NORMAL*/
45401 - outw( TCR_NORMAL, ioaddr + TCR );
45402 - outw( RCR_NORMAL, ioaddr + RCR );
45403 + smc_outw(TCR_NORMAL, ioaddr, TCR);
45404 + smc_outw(RCR_NORMAL, ioaddr, RCR);
45406 /* now, enable interrupts */
45407 - SMC_SELECT_BANK( 2 );
45408 - outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK );
45409 + SMC_SELECT_BANK(2);
45410 + SMC_SET_INT(SMC_INTERRUPT_MASK);
45414 - . Function: smc_shutdown
45415 + . Function: smc_shutdown(struct net_device *dev)
45416 . Purpose: closes down the SMC91xxx chip.
45417 . Method:
45418 . 1. zero the interrupt mask
45419 @@ -375,26 +647,28 @@
45420 . the manual says that it will wake up in response to any I/O requests
45421 . in the register space. Empirical results do not show this working.
45423 -static void smc_shutdown( int ioaddr )
45424 +static void smc_shutdown(struct net_device *dev)
45426 + u_int ioaddr = dev->base_addr;
45428 /* no more interrupts for me */
45429 - SMC_SELECT_BANK( 2 );
45430 - outb( 0, ioaddr + INT_MASK );
45431 + SMC_SELECT_BANK(2);
45432 + SMC_SET_INT(0);
45434 /* and tell the card to stay away from that nasty outside world */
45435 - SMC_SELECT_BANK( 0 );
45436 - outb( RCR_CLEAR, ioaddr + RCR );
45437 - outb( TCR_CLEAR, ioaddr + TCR );
45438 + SMC_SELECT_BANK(0);
45439 + smc_outb(RCR_CLEAR, ioaddr, RCR);
45440 + smc_outb(TCR_CLEAR, ioaddr, TCR);
45441 #if 0
45442 /* finally, shut the chip down */
45443 - SMC_SELECT_BANK( 1 );
45444 - outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL );
45445 + SMC_SELECT_BANK(1);
45446 + smc_outw(smc_inw(ioaddr, CONTROL), CTL_POWERDOWN, ioaddr, CONTROL);
45447 #endif
45452 - . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds )
45453 + . Function: smc_setmulticast(int ioaddr, int count, dev_mc_list * adds)
45454 . Purpose:
45455 . This sets the internal hardware table to filter out unwanted multicast
45456 . packets before they take up memory.
45457 @@ -411,26 +685,28 @@
45461 -static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) {
45462 +static void smc_setmulticast(struct net_device *dev, int count, struct dev_mc_list * addrs)
45464 + u_int ioaddr = dev->base_addr;
45465 int i;
45466 - unsigned char multicast_table[ 8 ];
45467 + unsigned char multicast_table[8];
45468 struct dev_mc_list * cur_addr;
45469 /* table for flipping the order of 3 bits */
45470 unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
45472 /* start with a table of all zeros: reject all */
45473 - memset( multicast_table, 0, sizeof( multicast_table ) );
45474 + memset(multicast_table, 0, sizeof(multicast_table));
45476 cur_addr = addrs;
45477 - for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) {
45478 + for (i = 0; i < count ; i ++, cur_addr = cur_addr->next) {
45479 int position;
45481 /* do we have a pointer here? */
45482 - if ( !cur_addr )
45483 + if (!cur_addr)
45484 break;
45485 /* make sure this is a multicast address - shouldn't this
45486 be a given if we have it here ? */
45487 - if ( !( *cur_addr->dmi_addr & 1 ) )
45488 + if (!(*cur_addr->dmi_addr & 1))
45489 continue;
45491 /* only use the low order bits */
45492 @@ -442,15 +718,15 @@
45495 /* now, the table can be loaded into the chipset */
45496 - SMC_SELECT_BANK( 3 );
45497 + SMC_SELECT_BANK(3);
45499 - for ( i = 0; i < 8 ; i++ ) {
45500 - outb( multicast_table[i], ioaddr + MULTICAST1 + i );
45501 + for (i = 0; i < 8 ; i++) {
45502 + smc_outb(multicast_table[i], ioaddr, MULTICAST1 + i);
45507 - . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
45508 + . Function: smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *)
45509 . Purpose:
45510 . Attempt to allocate memory for a packet, if chip-memory is not
45511 . available, then tell the card to generate an interrupt when it
45512 @@ -465,10 +741,10 @@
45513 . o (NO): Enable interrupts and let the interrupt handler deal with it.
45514 . o (YES):Send it now.
45516 -static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
45517 +static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device * dev)
45519 struct smc_local *lp = (struct smc_local *)dev->priv;
45520 - unsigned short ioaddr = dev->base_addr;
45521 + u_int ioaddr = dev->base_addr;
45522 word length;
45523 unsigned short numPages;
45524 word time_out;
45525 @@ -477,15 +753,16 @@
45526 /* Well, I want to send the packet.. but I don't know
45527 if I can send it right now... */
45529 - if ( lp->saved_skb) {
45530 + if (lp->saved_skb) {
45531 /* THIS SHOULD NEVER HAPPEN. */
45532 lp->stats.tx_aborted_errors++;
45533 - printk(CARDNAME": Bad Craziness - sent packet while busy.\n" );
45534 + printk("%s: Bad Craziness - sent packet while busy.\n",
45535 + dev->name);
45536 return 1;
45539 length = skb->len;
45542 if(length < ETH_ZLEN)
45544 skb = skb_padto(skb, ETH_ZLEN);
45545 @@ -497,18 +774,18 @@
45546 length = ETH_ZLEN;
45548 lp->saved_skb = skb;
45552 ** The MMU wants the number of pages to be the number of 256 bytes
45553 - ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
45554 + ** 'pages', minus 1 (since a packet can't ever have 0 pages :))
45556 ** Pkt size for allocating is data length +6 (for additional status words,
45557 ** length and ctl!) If odd size last byte is included in this header.
45559 - numPages = ((length & 0xfffe) + 6) / 256;
45560 + numPages = ((length & 0xfffe) + 6) / 256;
45562 - if (numPages > 7 ) {
45563 - printk(CARDNAME": Far too big packet error. \n");
45564 + if (numPages > 7) {
45565 + printk("%s: Far too big packet error.\n", dev->name);
45566 /* freeing the packet is a good thing here... but should
45567 . any packets of this size get down here? */
45568 dev_kfree_skb (skb);
45569 @@ -517,12 +794,13 @@
45570 netif_wake_queue(dev);
45571 return 0;
45574 /* either way, a packet is waiting now */
45575 lp->packets_waiting++;
45577 /* now, try to allocate the memory */
45578 - SMC_SELECT_BANK( 2 );
45579 - outw( MC_ALLOC | numPages, ioaddr + MMU_CMD );
45580 + SMC_SELECT_BANK(2);
45581 + smc_outw(MC_ALLOC | numPages, ioaddr, MMU_CMD);
45583 . Performance Hack
45585 @@ -539,21 +817,21 @@
45586 do {
45587 word status;
45589 - status = inb( ioaddr + INTERRUPT );
45590 - if ( status & IM_ALLOC_INT ) {
45591 + status = smc_inb(ioaddr, INTERRUPT);
45592 + if (status & IM_ALLOC_INT) {
45593 /* acknowledge the interrupt */
45594 - outb( IM_ALLOC_INT, ioaddr + INTERRUPT );
45595 - break;
45596 + smc_outb(IM_ALLOC_INT, ioaddr, INTERRUPT);
45597 + break;
45599 - } while ( -- time_out );
45600 + } while (-- time_out);
45602 - if ( !time_out ) {
45603 + if (!time_out) {
45604 /* oh well, wait until the chip finds memory later */
45605 - SMC_ENABLE_INT( IM_ALLOC_INT );
45606 - PRINTK2((CARDNAME": memory allocation deferred. \n"));
45607 + SMC_ENABLE_INT(IM_ALLOC_INT);
45608 + PRINTK2(("%s: memory allocation deferred.\n", dev->name));
45609 /* it's deferred, but I'll handle it later */
45610 - return 0;
45612 + return 0;
45614 /* or YES! I can send the packet now.. */
45615 smc_hardware_send_packet(dev);
45616 netif_wake_queue(dev);
45617 @@ -561,46 +839,46 @@
45621 - . Function: smc_hardware_send_packet(struct net_device * )
45622 + . Function: smc_hardware_send_packet(struct net_device *)
45623 . Purpose:
45624 . This sends the actual packet to the SMC9xxx chip.
45626 . Algorithm:
45627 . First, see if a saved_skb is available.
45628 - . ( this should NOT be called if there is no 'saved_skb'
45629 + . (this should NOT be called if there is no 'saved_skb'
45630 . Now, find the packet number that the chip allocated
45631 . Point the data pointers at it in memory
45632 . Set the length word in the chip's memory
45633 . Dump the packet to chip memory
45634 - . Check if a last byte is needed ( odd length packet )
45635 + . Check if a last byte is needed (odd length packet)
45636 . if so, set the control flag right
45637 . Tell the card to send it
45638 . Enable the transmit interrupt, so I know if it failed
45639 . Free the kernel data if I actually sent it.
45641 -static void smc_hardware_send_packet( struct net_device * dev )
45642 +static void smc_hardware_send_packet(struct net_device *dev)
45644 struct smc_local *lp = (struct smc_local *)dev->priv;
45645 - byte packet_no;
45646 - struct sk_buff * skb = lp->saved_skb;
45647 - word length;
45648 - unsigned short ioaddr;
45649 - byte * buf;
45651 - ioaddr = dev->base_addr;
45652 + struct sk_buff *skb = lp->saved_skb;
45653 + word length, lastword;
45654 + u_int ioaddr = dev->base_addr;
45655 + byte packet_no;
45656 + byte *buf;
45658 - if ( !skb ) {
45659 - PRINTK((CARDNAME": In XMIT with no packet to send \n"));
45660 + if (!skb) {
45661 + PRINTK(("%s: In XMIT with no packet to send\n", dev->name));
45662 return;
45665 length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
45666 buf = skb->data;
45668 /* If I get here, I _know_ there is a packet slot waiting for me */
45669 - packet_no = inb( ioaddr + PNR_ARR + 1 );
45670 - if ( packet_no & 0x80 ) {
45671 + packet_no = smc_inb(ioaddr, PNR_ARR + 1);
45672 + if (packet_no & 0x80) {
45673 /* or isn't there? BAD CHIP! */
45674 - printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n");
45675 + printk(KERN_DEBUG "%s: Memory allocation failed.\n",
45676 + dev->name);
45677 dev_kfree_skb_any(skb);
45678 lp->saved_skb = NULL;
45679 netif_wake_queue(dev);
45680 @@ -608,26 +886,19 @@
45683 /* we have a packet address, so tell the card to use it */
45684 - outb( packet_no, ioaddr + PNR_ARR );
45685 + smc_outb(packet_no, ioaddr, PNR_ARR);
45687 /* point to the beginning of the packet */
45688 - outw( PTR_AUTOINC , ioaddr + POINTER );
45689 + smc_outw(PTR_AUTOINC, ioaddr, POINTER);
45691 - PRINTK3((CARDNAME": Trying to xmit packet of length %x\n", length ));
45692 -#if SMC_DEBUG > 2
45693 - print_packet( buf, length );
45694 -#endif
45695 + PRINTK3(("%s: Trying to xmit packet of length %x\n",
45696 + dev->name, length));
45698 - /* send the packet length ( +6 for status, length and ctl byte )
45699 - and the status word ( set to zeros ) */
45700 -#ifdef USE_32_BIT
45701 - outl( (length +6 ) << 16 , ioaddr + DATA_1 );
45702 -#else
45703 - outw( 0, ioaddr + DATA_1 );
45704 - /* send the packet length ( +6 for status words, length, and ctl*/
45705 - outb( (length+6) & 0xFF,ioaddr + DATA_1 );
45706 - outb( (length+6) >> 8 , ioaddr + DATA_1 );
45707 -#endif
45708 + print_packet(buf, length);
45710 + /* send the packet length (+6 for status, length and ctl byte)
45711 + and the status word (set to zeros) */
45712 + smc_outl((length + 6) << 16, ioaddr, DATA_1);
45714 /* send the actual data
45715 . I _think_ it's faster to send the longs first, and then
45716 @@ -636,32 +907,22 @@
45717 . a good idea to check which is optimal? But that could take
45718 . almost as much time as is saved?
45720 -#ifdef USE_32_BIT
45721 - if ( length & 0x2 ) {
45722 - outsl(ioaddr + DATA_1, buf, length >> 2 );
45723 - outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
45725 - else
45726 - outsl(ioaddr + DATA_1, buf, length >> 2 );
45727 -#else
45728 - outsw(ioaddr + DATA_1 , buf, (length ) >> 1);
45729 -#endif
45730 - /* Send the last byte, if there is one. */
45731 + smc_outs(ioaddr, DATA_1, buf, length);
45733 - if ( (length & 1) == 0 ) {
45734 - outw( 0, ioaddr + DATA_1 );
45735 - } else {
45736 - outb( buf[length -1 ], ioaddr + DATA_1 );
45737 - outb( 0x20, ioaddr + DATA_1);
45739 + /* Send the last byte, if there is one. */
45740 + if ((length & 1) == 0)
45741 + lastword = 0;
45742 + else
45743 + lastword = 0x2000 | buf[length - 1];
45744 + smc_outw(lastword, ioaddr, DATA_1);
45746 /* enable the interrupts */
45747 - SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) );
45748 + SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
45750 /* and let the chipset deal with it */
45751 - outw( MC_ENQUEUE , ioaddr + MMU_CMD );
45752 + smc_outw(MC_ENQUEUE, ioaddr, MMU_CMD);
45754 - PRINTK2((CARDNAME": Sent packet of length %d \n",length));
45755 + PRINTK2(("%s: Sent packet of length %d\n", dev->name, length));
45757 lp->saved_skb = NULL;
45758 dev_kfree_skb_any (skb);
45759 @@ -676,7 +937,7 @@
45761 /*-------------------------------------------------------------------------
45763 - | smc_init( struct net_device * dev )
45764 + | smc_init(struct net_device * dev)
45765 | Input parameters:
45766 | dev->base_addr == 0, try to find all possible locations
45767 | dev->base_addr == 1, return failure code
45768 @@ -691,6 +952,65 @@
45770 int __init smc_init(struct net_device *dev)
45772 + int ret = -ENODEV;
45773 +#if defined(CONFIG_ASSABET_NEPONSET)
45774 + if (machine_is_assabet() && machine_has_neponset()) {
45775 + unsigned int *addr;
45776 + unsigned char ecor;
45777 + unsigned long flags;
45779 + NCR_0 |= NCR_ENET_OSC_EN;
45780 + dev->irq = IRQ_NEPONSET_SMC9196;
45782 + /*
45783 + * Map the attribute space. This is overkill, but clean.
45784 + */
45785 + addr = ioremap(0x18000000 + (1 << 25), 64 * 1024 * 4);
45786 + if (!addr)
45787 + return -ENOMEM;
45789 + /*
45790 + * Reset the device. We must disable IRQs around this.
45791 + */
45792 + local_irq_save(flags);
45793 + ecor = readl(addr + ECOR) & ~ECOR_RESET;
45794 + writel(ecor | ECOR_RESET, addr + ECOR);
45795 + udelay(100);
45797 + /*
45798 + * The device will ignore all writes to the enable bit while
45799 + * reset is asserted, even if the reset bit is cleared in the
45800 + * same write. Must clear reset first, then enable the device.
45801 + */
45802 + writel(ecor, addr + ECOR);
45803 + writel(ecor | ECOR_ENABLE, addr + ECOR);
45805 + /*
45806 + * Force byte mode.
45807 + */
45808 + writel(readl(addr + ECSR) | ECSR_IOIS8, addr + ECSR);
45809 + local_irq_restore(flags);
45811 + iounmap(addr);
45813 + /*
45814 + * Wait for the chip to wake up.
45815 + */
45816 + mdelay(1);
45818 + /*
45819 + * Map the real registers.
45820 + */
45821 + addr = ioremap(0x18000000, 8 * 1024);
45822 + if (!addr)
45823 + return -ENOMEM;
45825 + ret = smc_probe(dev, (int)addr);
45826 + if (ret)
45827 + iounmap(addr);
45830 +#elif defined(CONFIG_ISA)
45831 int i;
45832 int base_addr = dev->base_addr;
45834 @@ -708,7 +1028,8 @@
45835 return 0;
45837 /* couldn't find anything */
45838 - return -ENODEV;
45839 +#endif
45840 + return ret;
45843 /*----------------------------------------------------------------------
45844 @@ -718,10 +1039,11 @@
45845 . interrupt, so an auto-detect routine can detect it, and find the IRQ,
45846 ------------------------------------------------------------------------
45848 -int __init smc_findirq( int ioaddr )
45849 +int __init smc_findirq(struct net_device *dev)
45851 int timeout = 20;
45852 unsigned long cookie;
45853 + u_int ioaddr = dev->base_addr;
45856 /* I have to do a STI() here, because this is called from
45857 @@ -737,26 +1059,25 @@
45858 * when done.
45862 + /* enable ALLOCation interrupts ONLY. */
45863 SMC_SELECT_BANK(2);
45864 - /* enable ALLOCation interrupts ONLY */
45865 - outb( IM_ALLOC_INT, ioaddr + INT_MASK );
45866 + SMC_SET_INT(IM_ALLOC_INT);
45869 . Allocate 512 bytes of memory. Note that the chip was just
45870 . reset so all the memory is available
45872 - outw( MC_ALLOC | 1, ioaddr + MMU_CMD );
45873 + smc_outw(MC_ALLOC | 1, ioaddr, MMU_CMD);
45876 . Wait until positive that the interrupt has been generated
45878 - while ( timeout ) {
45879 + while (timeout) {
45880 byte int_status;
45882 - int_status = inb( ioaddr + INTERRUPT );
45883 + int_status = smc_inb(ioaddr, INTERRUPT);
45885 - if ( int_status & IM_ALLOC_INT )
45886 + if (int_status & IM_ALLOC_INT)
45887 break; /* got the interrupt */
45888 timeout--;
45890 @@ -775,7 +1096,7 @@
45891 SMC_DELAY();
45893 /* and disable all interrupts again */
45894 - outb( 0, ioaddr + INT_MASK );
45895 + SMC_SET_INT(0);
45897 /* clear hardware interrupts again, because that's how it
45898 was when I was called... */
45899 @@ -785,8 +1106,87 @@
45900 return probe_irq_off(cookie);
45903 +static int __init smc_probe_chip(struct net_device *dev, int ioaddr)
45905 + unsigned int temp;
45907 + /* First, see if the high byte is 0x33 */
45908 + temp = smc_inw(ioaddr, BANK_SELECT);
45909 + if ((temp & 0xFF00) != 0x3300)
45910 + return -ENODEV;
45912 + /* The above MIGHT indicate a device, but I need to write to further
45913 + test this. */
45914 + smc_outw(0, ioaddr, BANK_SELECT);
45915 + temp = smc_inw(ioaddr, BANK_SELECT);
45916 + if ((temp & 0xFF00) != 0x3300)
45917 + return -ENODEV;
45919 +#ifndef CONFIG_ASSABET_NEPONSET
45920 + /* well, we've already written once, so hopefully another time won't
45921 + hurt. This time, I need to switch the bank register to bank 1,
45922 + so I can access the base address register */
45923 + SMC_SELECT_BANK(1);
45924 + temp = smc_inw(ioaddr, BASE);
45925 + if (ioaddr != (temp >> 3 & 0x3E0)) {
45926 + printk("%s: IOADDR %x doesn't match configuration (%x)."
45927 + "Probably not a SMC chip\n", dev->name,
45928 + ioaddr, (base_address_register >> 3) & 0x3E0);
45929 + /* well, the base address register didn't match. Must not have
45930 + been a SMC chip after all. */
45931 + return -ENODEV;
45933 +#endif
45935 + return 0;
45939 + . If dev->irq is 0, then the device has to be banged on to see
45940 + . what the IRQ is.
45942 + . This banging doesn't always detect the IRQ, for unknown reasons.
45943 + . a workaround is to reset the chip and try again.
45945 + . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
45946 + . be what is requested on the command line. I don't do that, mostly
45947 + . because the card that I have uses a non-standard method of accessing
45948 + . the IRQs, and because this _should_ work in most configurations.
45950 + . Specifying an IRQ is done with the assumption that the user knows
45951 + . what (s)he is doing. No checking is done!!!!
45954 +static int __init smc_probe_irq(struct net_device *dev)
45956 + if (dev->irq < 2) {
45957 + int trials;
45959 + trials = 3;
45960 + while (trials--) {
45961 + dev->irq = smc_findirq(dev);
45962 + if (dev->irq)
45963 + break;
45964 + /* kick the card and try again */
45965 + smc_reset(dev);
45968 + if (dev->irq == 0) {
45969 + printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
45970 + dev->name);
45971 + return -ENODEV;
45974 + /*
45975 + * Some machines (eg, PCs) need to cannonicalize their IRQs.
45976 + */
45977 + dev->irq = irq_cannonicalize(dev->irq);
45979 + return 0;
45982 /*----------------------------------------------------------------------
45983 - . Function: smc_probe( int ioaddr )
45984 + . Function: smc_probe(struct net_device *dev, int ioaddr)
45986 . Purpose:
45987 . Tests to see if a given ioaddr points to an SMC9xxx chip.
45988 @@ -816,16 +1216,14 @@
45990 static int __init smc_probe(struct net_device *dev, int ioaddr)
45992 + struct smc_local *smc;
45993 int i, memory, retval;
45994 static unsigned version_printed;
45995 - unsigned int bank;
45997 const char *version_string;
45998 - const char *if_string;
46000 /* registers */
46001 word revision_register;
46002 - word base_address_register;
46003 word configuration_register;
46004 word memory_info_register;
46005 word memory_cfg_register;
46006 @@ -834,44 +1232,24 @@
46007 if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
46008 return -EBUSY;
46010 - /* First, see if the high byte is 0x33 */
46011 - bank = inw( ioaddr + BANK_SELECT );
46012 - if ( (bank & 0xFF00) != 0x3300 ) {
46013 - retval = -ENODEV;
46014 - goto err_out;
46016 - /* The above MIGHT indicate a device, but I need to write to further
46017 - test this. */
46018 - outw( 0x0, ioaddr + BANK_SELECT );
46019 - bank = inw( ioaddr + BANK_SELECT );
46020 - if ( (bank & 0xFF00 ) != 0x3300 ) {
46021 - retval = -ENODEV;
46022 - goto err_out;
46024 - /* well, we've already written once, so hopefully another time won't
46025 - hurt. This time, I need to switch the bank register to bank 1,
46026 - so I can access the base address register */
46027 - SMC_SELECT_BANK(1);
46028 - base_address_register = inw( ioaddr + BASE );
46029 - if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) {
46030 - printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)."
46031 - "Probably not a SMC chip\n",
46032 - ioaddr, base_address_register >> 3 & 0x3E0 );
46033 - /* well, the base address register didn't match. Must not have
46034 - been a SMC chip after all. */
46035 - retval = -ENODEV;
46036 + /*
46037 + * Do the basic probes.
46038 + */
46039 + retval = smc_probe_chip(dev, ioaddr);
46040 + if (retval)
46041 goto err_out;
46044 /* check if the revision register is something that I recognize.
46045 These might need to be added to later, as future revisions
46046 could be added. */
46047 SMC_SELECT_BANK(3);
46048 - revision_register = inw( ioaddr + REVISION );
46049 - if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) {
46050 + revision_register = smc_inw(ioaddr, REVISION);
46051 + version_string = chip_ids[(revision_register >> 4) & 15];
46052 + if (!version_string) {
46053 /* I don't recognize this chip, so... */
46054 - printk(CARDNAME ": IO %x: Unrecognized revision register:"
46055 - " %x, Contact author. \n", ioaddr, revision_register );
46056 + printk("%s: IO %x: unrecognized revision register: %x, "
46057 + "contact author.\n", dev->name, ioaddr,
46058 + revision_register);
46060 retval = -ENODEV;
46061 goto err_out;
46062 @@ -882,138 +1260,122 @@
46063 against the hardware address, or do some other tests. */
46065 if (version_printed++ == 0)
46066 - printk("%s", version);
46067 + printk(KERN_INFO "%s", version);
46069 /* fill in some of the fields */
46070 dev->base_addr = ioaddr;
46073 - . Get the MAC address ( bank 1, regs 4 - 9 )
46074 + . Get the MAC address (bank 1, regs 4 - 9)
46076 - SMC_SELECT_BANK( 1 );
46077 - for ( i = 0; i < 6; i += 2 ) {
46078 + SMC_SELECT_BANK(1);
46079 + for (i = 0; i < 6; i += 2) {
46080 word address;
46082 - address = inw( ioaddr + ADDR0 + i );
46083 - dev->dev_addr[ i + 1] = address >> 8;
46084 - dev->dev_addr[ i ] = address & 0xFF;
46085 + address = smc_inw(ioaddr, ADDR0 + i);
46086 + dev->dev_addr[i + 1] = address >> 8;
46087 + dev->dev_addr[i] = address & 0xFF;
46090 + if (!is_valid_ether_addr(dev->dev_addr))
46091 + printk("%s: Invalid ethernet MAC address. Please set using "
46092 + "ifconfig\n", dev->name);
46094 /* get the memory information */
46096 - SMC_SELECT_BANK( 0 );
46097 - memory_info_register = inw( ioaddr + MIR );
46098 - memory_cfg_register = inw( ioaddr + MCR );
46099 - memory = ( memory_cfg_register >> 9 ) & 0x7; /* multiplier */
46100 - memory *= 256 * ( memory_info_register & 0xFF );
46101 + SMC_SELECT_BANK(0);
46102 + memory_info_register = smc_inw(ioaddr, MIR);
46103 + memory_cfg_register = smc_inw(ioaddr, MCR);
46104 + memory = (memory_cfg_register >> 9) & 0x7; /* multiplier */
46105 + memory *= 256 * (memory_info_register & 0xFF);
46107 + /* now, reset the chip, and put it into a known state */
46108 + smc_reset(dev);
46111 - Now, I want to find out more about the chip. This is sort of
46112 - redundant, but it's cleaner to have it in both, rather than having
46113 - one VERY long probe procedure.
46114 - */
46115 - SMC_SELECT_BANK(3);
46116 - revision_register = inw( ioaddr + REVISION );
46117 - version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ];
46118 - if ( !version_string ) {
46119 - /* I shouldn't get here because this call was done before.... */
46120 - retval = -ENODEV;
46121 + * Ok, now that we have everything in a
46122 + * sane state, probe for the interrupt.
46123 + */
46124 + retval = smc_probe_irq(dev);
46125 + if (retval)
46126 goto err_out;
46129 - /* is it using AUI or 10BaseT ? */
46130 - if ( dev->if_port == 0 ) {
46131 - SMC_SELECT_BANK(1);
46132 - configuration_register = inw( ioaddr + CONFIG );
46133 - if ( configuration_register & CFG_AUI_SELECT )
46134 - dev->if_port = 2;
46135 - else
46136 - dev->if_port = 1;
46137 + /* Initialize the private structure. */
46138 + if (dev->priv == NULL) {
46139 + dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
46140 + if (dev->priv == NULL) {
46141 + retval = -ENOMEM;
46142 + goto err_out;
46145 - if_string = interfaces[ dev->if_port - 1 ];
46147 - /* now, reset the chip, and put it into a known state */
46148 - smc_reset( ioaddr );
46149 + smc = dev->priv;
46151 + /* set the private data to zero by default */
46152 + memset(smc, 0, sizeof(struct smc_local));
46155 - . If dev->irq is 0, then the device has to be banged on to see
46156 - . what the IRQ is.
46158 - . This banging doesn't always detect the IRQ, for unknown reasons.
46159 - . a workaround is to reset the chip and try again.
46161 - . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
46162 - . be what is requested on the command line. I don't do that, mostly
46163 - . because the card that I have uses a non-standard method of accessing
46164 - . the IRQs, and because this _should_ work in most configurations.
46166 - . Specifying an IRQ is done with the assumption that the user knows
46167 - . what (s)he is doing. No checking is done!!!!
46169 - */
46170 - if ( dev->irq < 2 ) {
46171 - int trials;
46172 + * Get the interface characteristics.
46173 + * is it using AUI or 10BaseT ?
46174 + */
46175 + switch (dev->if_port) {
46176 + case IF_PORT_10BASET:
46177 + smc->port = PORT_TP;
46178 + break;
46180 - trials = 3;
46181 - while ( trials-- ) {
46182 - dev->irq = smc_findirq( ioaddr );
46183 - if ( dev->irq )
46184 - break;
46185 - /* kick the card and try again */
46186 - smc_reset( ioaddr );
46187 + case IF_PORT_AUI:
46188 + smc->port = PORT_AUI;
46189 + break;
46191 + default:
46192 + SMC_SELECT_BANK(1);
46193 + configuration_register = smc_inw(ioaddr, CONFIG);
46194 + if (configuration_register & CFG_AUI_SELECT) {
46195 + dev->if_port = IF_PORT_AUI;
46196 + smc->port = PORT_AUI;
46197 + } else {
46198 + dev->if_port = IF_PORT_10BASET;
46199 + smc->port = PORT_TP;
46202 - if (dev->irq == 0 ) {
46203 - printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");
46204 - retval = -ENODEV;
46205 - goto err_out;
46206 + break;
46209 - /* now, print out the card info, in a short format.. */
46210 + /* all interfaces are half-duplex by default */
46211 + smc->duplex = DUPLEX_HALF;
46213 - printk("%s: %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
46214 - version_string, revision_register & 0xF, ioaddr, dev->irq,
46215 - if_string, memory );
46216 + /* now, print out the card info, in a short format.. */
46217 + printk("%s: %s (rev %d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
46218 + version_string, revision_register & 15, ioaddr, dev->irq,
46219 + interfaces[smc->port], memory);
46221 . Print the Ethernet address
46223 printk("ADDR: ");
46224 for (i = 0; i < 5; i++)
46225 - printk("%2.2x:", dev->dev_addr[i] );
46226 - printk("%2.2x \n", dev->dev_addr[5] );
46229 - /* Initialize the private structure. */
46230 - if (dev->priv == NULL) {
46231 - dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
46232 - if (dev->priv == NULL) {
46233 - retval = -ENOMEM;
46234 - goto err_out;
46237 - /* set the private data to zero by default */
46238 - memset(dev->priv, 0, sizeof(struct smc_local));
46239 + printk("%2.2x:", dev->dev_addr[i]);
46240 + printk("%2.2x\n", dev->dev_addr[5]);
46242 /* Fill in the fields of the device structure with ethernet values. */
46243 ether_setup(dev);
46245 /* Grab the IRQ */
46246 - retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
46247 - if (retval) {
46248 + retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
46249 + if (retval) {
46250 printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
46251 dev->irq, retval);
46252 kfree(dev->priv);
46253 dev->priv = NULL;
46254 - goto err_out;
46256 + goto err_out;
46259 - dev->open = smc_open;
46260 - dev->stop = smc_close;
46261 - dev->hard_start_xmit = smc_wait_to_send_packet;
46262 - dev->tx_timeout = smc_timeout;
46263 - dev->watchdog_timeo = HZ/20;
46264 - dev->get_stats = smc_query_statistics;
46265 - dev->set_multicast_list = smc_set_multicast_list;
46266 + dev->open = smc_open;
46267 + dev->stop = smc_close;
46268 + dev->hard_start_xmit = smc_wait_to_send_packet;
46269 + dev->tx_timeout = smc_timeout;
46270 + dev->watchdog_timeo = HZ/20;
46271 + dev->get_stats = smc_query_statistics;
46272 + dev->set_multicast_list = smc_set_multicast_list;
46273 + dev->do_ioctl = smc_ioctl;
46275 return 0;
46277 @@ -1022,42 +1384,43 @@
46278 return retval;
46281 -#if SMC_DEBUG > 2
46282 -static void print_packet( byte * buf, int length )
46284 + * This is responsible for setting the chip appropriately
46285 + * for the interface type. This should only be called while
46286 + * the interface is up and running.
46287 + */
46288 +static void smc_set_port(struct net_device *dev)
46290 -#if 0
46291 - int i;
46292 - int remainder;
46293 - int lines;
46295 - printk("Packet of length %d \n", length );
46296 - lines = length / 16;
46297 - remainder = length % 16;
46299 - for ( i = 0; i < lines ; i ++ ) {
46300 - int cur;
46301 + struct smc_local *smc = dev->priv;
46302 + u_int ioaddr = dev->base_addr;
46303 + u_int val;
46305 - for ( cur = 0; cur < 8; cur ++ ) {
46306 - byte a, b;
46307 + SMC_SELECT_BANK(1);
46308 + val = smc_inw(ioaddr, CONFIG);
46309 + switch (smc->port) {
46310 + case PORT_TP:
46311 + val &= ~CFG_AUI_SELECT;
46312 + break;
46314 - a = *(buf ++ );
46315 - b = *(buf ++ );
46316 - printk("%02x%02x ", a, b );
46318 - printk("\n");
46319 + case PORT_AUI:
46320 + val |= CFG_AUI_SELECT;
46321 + break;
46323 - for ( i = 0; i < remainder/2 ; i++ ) {
46324 - byte a, b;
46325 + smc_outw(val, ioaddr, CONFIG);
46327 - a = *(buf ++ );
46328 - b = *(buf ++ );
46329 - printk("%02x%02x ", a, b );
46330 + SMC_SELECT_BANK(0);
46331 + val = smc_inw(ioaddr, TCR);
46332 + switch (smc->duplex) {
46333 + case DUPLEX_HALF:
46334 + val &= ~TCR_FDSE;
46335 + break;
46337 + case DUPLEX_FULL:
46338 + val |= TCR_FDSE;
46339 + break;
46341 - printk("\n");
46342 -#endif
46343 + smc_outw(val, ioaddr, TCR);
46345 -#endif
46349 * Open and Initialize the board
46350 @@ -1067,48 +1430,141 @@
46352 static int smc_open(struct net_device *dev)
46354 - int ioaddr = dev->base_addr;
46355 + struct smc_local *smc = dev->priv;
46356 + u_int ioaddr = dev->base_addr;
46357 + int i;
46359 - int i; /* used to set hw ethernet address */
46360 + /*
46361 + * Check that the address is valid. If its not, refuse
46362 + * to bring the device up. The user must specify an
46363 + * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
46364 + */
46365 + if (!is_valid_ether_addr(dev->dev_addr))
46366 + return -EINVAL;
46368 /* clear out all the junk that was put here before... */
46369 - memset(dev->priv, 0, sizeof(struct smc_local));
46370 + smc->saved_skb = NULL;
46371 + smc->packets_waiting = 0;
46373 /* reset the hardware */
46375 - smc_reset( ioaddr );
46376 - smc_enable( ioaddr );
46377 + smc_reset(dev);
46378 + smc_enable(dev);
46380 /* Select which interface to use */
46382 - SMC_SELECT_BANK( 1 );
46383 - if ( dev->if_port == 1 ) {
46384 - outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT,
46385 - ioaddr + CONFIG );
46387 - else if ( dev->if_port == 2 ) {
46388 - outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT,
46389 - ioaddr + CONFIG );
46391 + smc_set_port(dev);
46394 - According to Becker, I have to set the hardware address
46395 + According to Becker, I have to set the hardware address
46396 at this point, because the (l)user can set it with an
46397 ioctl. Easily done...
46399 - SMC_SELECT_BANK( 1 );
46400 - for ( i = 0; i < 6; i += 2 ) {
46401 + SMC_SELECT_BANK(1);
46402 + for (i = 0; i < 6; i += 2) {
46403 word address;
46405 - address = dev->dev_addr[ i + 1 ] << 8 ;
46406 - address |= dev->dev_addr[ i ];
46407 - outw( address, ioaddr + ADDR0 + i );
46408 + address = dev->dev_addr[i + 1] << 8 ;
46409 + address |= dev->dev_addr[i];
46410 + smc_outw(address, ioaddr, ADDR0 + i);
46413 netif_start_queue(dev);
46414 return 0;
46418 + * This is our template. Fill the rest in at run-time
46419 + */
46420 +static const struct ethtool_cmd ecmd_template = {
46421 + supported: SUPPORTED_10baseT_Half |
46422 + SUPPORTED_10baseT_Full |
46423 + SUPPORTED_TP |
46424 + SUPPORTED_AUI,
46425 + speed: SPEED_10,
46426 + autoneg: AUTONEG_DISABLE,
46427 + maxtxpkt: 1,
46428 + maxrxpkt: 1,
46429 + transceiver: XCVR_INTERNAL,
46432 +static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
46434 + struct smc_local *smc = dev->priv;
46435 + u32 etcmd;
46436 + int ret = -EINVAL;
46438 + if (cmd != SIOCETHTOOL)
46439 + return -EOPNOTSUPP;
46441 + if (get_user(etcmd, (u32 *)rq->ifr_data))
46442 + return -EFAULT;
46444 + switch (etcmd) {
46445 + case ETHTOOL_GSET: {
46446 + struct ethtool_cmd ecmd = ecmd_template;
46448 + ecmd.cmd = etcmd;
46449 + ecmd.port = smc->port;
46450 + ecmd.duplex = smc->duplex;
46452 + ret = copy_to_user(rq->ifr_data, &ecmd, sizeof(ecmd))
46453 + ? -EFAULT : 0;
46454 + break;
46457 + case ETHTOOL_SSET: {
46458 + struct ethtool_cmd ecmd;
46460 + ret = -EPERM;
46461 + if (!capable(CAP_NET_ADMIN))
46462 + break;
46464 + ret = -EFAULT;
46465 + if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
46466 + break;
46468 + /*
46469 + * Sanity-check the arguments.
46470 + */
46471 + ret = -EINVAL;
46472 + if (ecmd.autoneg != AUTONEG_DISABLE)
46473 + break;
46474 + if (ecmd.speed != SPEED_10)
46475 + break;
46476 + if (ecmd.duplex != DUPLEX_HALF && ecmd.duplex != DUPLEX_FULL)
46477 + break;
46478 + if (ecmd.port != PORT_TP && ecmd.port != PORT_AUI)
46479 + break;
46481 + smc->port = ecmd.port;
46482 + smc->duplex = ecmd.duplex;
46484 + if (netif_running(dev))
46485 + smc_set_port(dev);
46487 + ret = 0;
46488 + break;
46491 + case ETHTOOL_GDRVINFO: {
46492 + struct ethtool_drvinfo edrv;
46494 + memset(&edrv, 0, sizeof(edrv));
46496 + edrv.cmd = etcmd;
46497 + strcpy(edrv.driver, DRV_NAME);
46498 + strcpy(edrv.version, DRV_VERSION);
46499 + sprintf(edrv.bus_info, "ISA:%8.8lx:%d",
46500 + dev->base_addr, dev->irq);
46502 + ret = copy_to_user(rq->ifr_data, &edrv, sizeof(edrv))
46503 + ? -EFAULT : 0;
46504 + break;
46508 + return ret;
46511 /*--------------------------------------------------------
46512 . Called by the kernel to send a packet out into the void
46513 . of the net. This routine is largely based on
46514 @@ -1120,12 +1576,10 @@
46516 /* If we get here, some higher level has decided we are broken.
46517 There should really be a "kick me" function call instead. */
46518 - printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
46519 - tx_done(dev) ? "IRQ conflict" :
46520 - "network cable problem");
46521 + printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
46522 /* "kick" the adaptor */
46523 - smc_reset( dev->base_addr );
46524 - smc_enable( dev->base_addr );
46525 + smc_reset(dev);
46526 + smc_enable(dev);
46527 dev->trans_start = jiffies;
46528 /* clear anything saved */
46529 ((struct smc_local *)dev->priv)->saved_skb = NULL;
46530 @@ -1145,10 +1599,10 @@
46532 ---------------------------------------------------------------------*/
46534 -static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
46535 +static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
46537 struct net_device *dev = dev_id;
46538 - int ioaddr = dev->base_addr;
46539 + u_int ioaddr = dev->base_addr;
46540 struct smc_local *lp = (struct smc_local *)dev->priv;
46542 byte status;
46543 @@ -1161,45 +1615,45 @@
46547 - PRINTK3((CARDNAME": SMC interrupt started \n"));
46548 + PRINTK3(("%s: SMC interrupt started\n", dev->name));
46550 - saved_bank = inw( ioaddr + BANK_SELECT );
46551 + saved_bank = smc_inw(ioaddr, BANK_SELECT);
46553 SMC_SELECT_BANK(2);
46554 - saved_pointer = inw( ioaddr + POINTER );
46555 + saved_pointer = smc_inw(ioaddr, POINTER);
46557 - mask = inb( ioaddr + INT_MASK );
46558 + mask = smc_inb(ioaddr, INT_MASK);
46559 /* clear all interrupts */
46560 - outb( 0, ioaddr + INT_MASK );
46561 + SMC_SET_INT(0);
46564 /* set a timeout value, so I don't stay here forever */
46565 timeout = 4;
46567 - PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
46568 + PRINTK2((KERN_WARNING "%s: MASK IS %x\n", dev->name, mask));
46569 do {
46570 /* read the status flag, and mask it */
46571 - status = inb( ioaddr + INTERRUPT ) & mask;
46572 - if (!status )
46573 + status = smc_inb(ioaddr, INTERRUPT) & mask;
46574 + if (!status)
46575 break;
46577 - PRINTK3((KERN_WARNING CARDNAME
46578 - ": Handling interrupt status %x \n", status ));
46579 + PRINTK3((KERN_WARNING "%s: handling interrupt status %x\n",
46580 + dev->name, status));
46582 if (status & IM_RCV_INT) {
46583 /* Got a packet(s). */
46584 - PRINTK2((KERN_WARNING CARDNAME
46585 - ": Receive Interrupt\n"));
46586 + PRINTK2((KERN_WARNING "%s: receive interrupt\n",
46587 + dev->name));
46588 smc_rcv(dev);
46589 - } else if (status & IM_TX_INT ) {
46590 - PRINTK2((KERN_WARNING CARDNAME
46591 - ": TX ERROR handled\n"));
46592 + } else if (status & IM_TX_INT) {
46593 + PRINTK2((KERN_WARNING "%s: TX ERROR handled\n",
46594 + dev->name));
46595 smc_tx(dev);
46596 - outb(IM_TX_INT, ioaddr + INTERRUPT );
46597 - } else if (status & IM_TX_EMPTY_INT ) {
46598 + smc_outb(IM_TX_INT, ioaddr, INTERRUPT);
46599 + } else if (status & IM_TX_EMPTY_INT) {
46600 /* update stats */
46601 - SMC_SELECT_BANK( 0 );
46602 - card_stats = inw( ioaddr + COUNTER );
46603 + SMC_SELECT_BANK(0);
46604 + card_stats = smc_inw(ioaddr, COUNTER);
46605 /* single collisions */
46606 lp->stats.collisions += card_stats & 0xF;
46607 card_stats >>= 4;
46608 @@ -1208,60 +1662,63 @@
46610 /* these are for when linux supports these statistics */
46612 - SMC_SELECT_BANK( 2 );
46613 - PRINTK2((KERN_WARNING CARDNAME
46614 - ": TX_BUFFER_EMPTY handled\n"));
46615 - outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
46616 + SMC_SELECT_BANK(2);
46617 + PRINTK2((KERN_WARNING "%s: TX_BUFFER_EMPTY handled\n",
46618 + dev->name));
46619 + smc_outb(IM_TX_EMPTY_INT, ioaddr, INTERRUPT);
46620 mask &= ~IM_TX_EMPTY_INT;
46621 lp->stats.tx_packets += lp->packets_waiting;
46622 lp->packets_waiting = 0;
46624 - } else if (status & IM_ALLOC_INT ) {
46625 - PRINTK2((KERN_DEBUG CARDNAME
46626 - ": Allocation interrupt \n"));
46627 + } else if (status & IM_ALLOC_INT) {
46628 + PRINTK2((KERN_DEBUG "%s: Allocation interrupt\n",
46629 + dev->name));
46630 /* clear this interrupt so it doesn't happen again */
46631 mask &= ~IM_ALLOC_INT;
46633 - smc_hardware_send_packet( dev );
46634 + smc_hardware_send_packet(dev);
46636 /* enable xmit interrupts based on this */
46637 - mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
46638 + mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
46640 /* and let the card send more packets to me */
46641 netif_wake_queue(dev);
46643 - PRINTK2((CARDNAME": Handoff done successfully.\n"));
46644 - } else if (status & IM_RX_OVRN_INT ) {
46645 + PRINTK2(("%s: Handoff done successfully.\n",
46646 + dev->name));
46647 + } else if (status & IM_RX_OVRN_INT) {
46648 lp->stats.rx_errors++;
46649 lp->stats.rx_fifo_errors++;
46650 - outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
46651 - } else if (status & IM_EPH_INT ) {
46652 - PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
46653 - } else if (status & IM_ERCV_INT ) {
46654 - PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
46655 - outb( IM_ERCV_INT, ioaddr + INTERRUPT );
46656 + smc_outb(IM_RX_OVRN_INT, ioaddr, INTERRUPT);
46657 + } else if (status & IM_EPH_INT) {
46658 + PRINTK(("%s: UNSUPPORTED: EPH INTERRUPT\n",
46659 + dev->name));
46660 + } else if (status & IM_ERCV_INT) {
46661 + PRINTK(("%s: UNSUPPORTED: ERCV INTERRUPT\n",
46662 + dev->name));
46663 + smc_outb(IM_ERCV_INT, ioaddr, INTERRUPT);
46665 - } while ( timeout -- );
46666 + } while (timeout --);
46669 /* restore state register */
46670 - SMC_SELECT_BANK( 2 );
46671 - outb( mask, ioaddr + INT_MASK );
46672 + SMC_SELECT_BANK(2);
46673 + SMC_SET_INT(mask);
46675 - PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
46676 - outw( saved_pointer, ioaddr + POINTER );
46677 + PRINTK3((KERN_WARNING "%s: MASK is now %x\n", dev->name, mask));
46678 + smc_outw(saved_pointer, ioaddr, POINTER);
46680 - SMC_SELECT_BANK( saved_bank );
46681 + SMC_SELECT_BANK(saved_bank);
46683 - PRINTK3((CARDNAME ": Interrupt done\n"));
46684 + PRINTK3(("%s: Interrupt done\n", dev->name));
46685 return;
46688 /*-------------------------------------------------------------
46690 - . smc_rcv - receive a packet from the card
46691 + . smc_rcv - receive a packet from the card
46693 - . There is ( at least ) a packet waiting to be read from
46694 + . There is (at least) a packet waiting to be read from
46695 . chip-memory.
46697 . o Read the status
46698 @@ -1272,55 +1729,57 @@
46699 static void smc_rcv(struct net_device *dev)
46701 struct smc_local *lp = (struct smc_local *)dev->priv;
46702 - int ioaddr = dev->base_addr;
46703 + u_int ioaddr = dev->base_addr;
46704 int packet_number;
46705 word status;
46706 word packet_length;
46708 /* assume bank 2 */
46710 - packet_number = inw( ioaddr + FIFO_PORTS );
46711 + packet_number = smc_inw(ioaddr, FIFO_PORTS);
46713 - if ( packet_number & FP_RXEMPTY ) {
46714 + if (packet_number & FP_RXEMPTY) {
46715 /* we got called , but nothing was on the FIFO */
46716 - PRINTK((CARDNAME ": WARNING: smc_rcv with nothing on FIFO. \n"));
46717 + PRINTK(("%s: WARNING: smc_rcv with nothing on FIFO.\n",
46718 + dev->name));
46719 /* don't need to restore anything */
46720 return;
46723 /* start reading from the start of the packet */
46724 - outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER );
46725 + smc_outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr, POINTER);
46727 /* First two words are status and packet_length */
46728 - status = inw( ioaddr + DATA_1 );
46729 - packet_length = inw( ioaddr + DATA_1 );
46730 + status = smc_inw(ioaddr, DATA_1);
46731 + packet_length = smc_inw(ioaddr, DATA_1);
46733 packet_length &= 0x07ff; /* mask off top bits */
46735 - PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ));
46736 + PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length));
46738 . the packet length contains 3 extra words :
46739 . status, length, and an extra word with an odd byte .
46741 packet_length -= 6;
46743 - if ( !(status & RS_ERRORS ) ){
46744 + if (!(status & RS_ERRORS)){
46745 /* do stuff to make a new packet */
46746 struct sk_buff * skb;
46747 byte * data;
46749 /* read one extra byte */
46750 - if ( status & RS_ODDFRAME )
46751 + if (status & RS_ODDFRAME)
46752 packet_length++;
46754 /* set multicast stats */
46755 - if ( status & RS_MULTICAST )
46756 + if (status & RS_MULTICAST)
46757 lp->stats.multicast++;
46759 - skb = dev_alloc_skb( packet_length + 5);
46760 + skb = dev_alloc_skb(packet_length + 5);
46762 - if ( skb == NULL ) {
46763 - printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n");
46764 + if (skb == NULL) {
46765 + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
46766 + dev->name);
46767 lp->stats.rx_dropped++;
46768 goto done;
46770 @@ -1330,36 +1789,15 @@
46771 ! in the worse case
46774 - skb_reserve( skb, 2 ); /* 16 bit alignment */
46775 + skb_reserve(skb, 2); /* 16 bit alignment */
46777 skb->dev = dev;
46778 - data = skb_put( skb, packet_length);
46779 + data = skb_put(skb, packet_length);
46781 -#ifdef USE_32_BIT
46782 - /* QUESTION: Like in the TX routine, do I want
46783 - to send the DWORDs or the bytes first, or some
46784 - mixture. A mixture might improve already slow PIO
46785 - performance */
46786 - PRINTK3((" Reading %d dwords (and %d bytes) \n",
46787 - packet_length >> 2, packet_length & 3 ));
46788 - insl(ioaddr + DATA_1 , data, packet_length >> 2 );
46789 - /* read the left over bytes */
46790 - insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC),
46791 - packet_length & 0x3 );
46792 -#else
46793 - PRINTK3((" Reading %d words and %d byte(s) \n",
46794 - (packet_length >> 1 ), packet_length & 1 ));
46795 - insw(ioaddr + DATA_1 , data, packet_length >> 1);
46796 - if ( packet_length & 1 ) {
46797 - data += packet_length & ~1;
46798 - *(data++) = inb( ioaddr + DATA_1 );
46800 -#endif
46801 -#if SMC_DEBUG > 2
46802 - print_packet( data, packet_length );
46803 -#endif
46804 + smc_ins(ioaddr, DATA_1, data, packet_length);
46805 + print_packet(data, packet_length);
46807 - skb->protocol = eth_type_trans(skb, dev );
46808 + skb->protocol = eth_type_trans(skb, dev);
46809 netif_rx(skb);
46810 dev->last_rx = jiffies;
46811 lp->stats.rx_packets++;
46812 @@ -1368,15 +1806,17 @@
46813 /* error ... */
46814 lp->stats.rx_errors++;
46816 - if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++;
46817 - if ( status & (RS_TOOSHORT | RS_TOOLONG ) )
46818 + if (status & RS_ALGNERR)
46819 + lp->stats.rx_frame_errors++;
46820 + if (status & (RS_TOOSHORT | RS_TOOLONG))
46821 lp->stats.rx_length_errors++;
46822 - if ( status & RS_BADCRC) lp->stats.rx_crc_errors++;
46823 + if (status & RS_BADCRC)
46824 + lp->stats.rx_crc_errors++;
46827 done:
46828 /* error or good, tell the card to get rid of this packet */
46829 - outw( MC_RELEASE, ioaddr + MMU_CMD );
46830 + smc_outw(MC_RELEASE, ioaddr, MMU_CMD);
46834 @@ -1389,62 +1829,64 @@
46835 . Algorithm:
46836 . Save pointer and packet no
46837 . Get the packet no from the top of the queue
46838 - . check if it's valid ( if not, is this an error??? )
46839 + . check if it's valid (if not, is this an error???)
46840 . read the status word
46841 . record the error
46842 - . ( resend? Not really, since we don't want old packets around )
46843 + . (resend? Not really, since we don't want old packets around)
46844 . Restore saved values
46845 ************************************************************************/
46846 -static void smc_tx( struct net_device * dev )
46847 +static void smc_tx(struct net_device * dev)
46849 - int ioaddr = dev->base_addr;
46850 + u_int ioaddr = dev->base_addr;
46851 struct smc_local *lp = (struct smc_local *)dev->priv;
46852 byte saved_packet;
46853 byte packet_no;
46854 word tx_status;
46857 - /* assume bank 2 */
46858 + /* assume bank 2 */
46860 - saved_packet = inb( ioaddr + PNR_ARR );
46861 - packet_no = inw( ioaddr + FIFO_PORTS );
46862 + saved_packet = smc_inb(ioaddr, PNR_ARR);
46863 + packet_no = smc_inw(ioaddr, FIFO_PORTS);
46864 packet_no &= 0x7F;
46866 /* select this as the packet to read from */
46867 - outb( packet_no, ioaddr + PNR_ARR );
46868 + smc_outb(packet_no, ioaddr, PNR_ARR);
46870 /* read the first word from this packet */
46871 - outw( PTR_AUTOINC | PTR_READ, ioaddr + POINTER );
46872 + smc_outw(PTR_AUTOINC | PTR_READ, ioaddr, POINTER);
46874 - tx_status = inw( ioaddr + DATA_1 );
46875 - PRINTK3((CARDNAME": TX DONE STATUS: %4x \n", tx_status ));
46876 + tx_status = smc_inw(ioaddr, DATA_1);
46877 + PRINTK3(("%s: TX DONE STATUS: %4x\n", dev->name, tx_status));
46879 lp->stats.tx_errors++;
46880 - if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++;
46881 - if ( tx_status & TS_LATCOL ) {
46882 - printk(KERN_DEBUG CARDNAME
46883 - ": Late collision occurred on last xmit.\n");
46884 + if (tx_status & TS_LOSTCAR)
46885 + lp->stats.tx_carrier_errors++;
46886 + if (tx_status & TS_LATCOL) {
46887 + printk(KERN_DEBUG "%s: Late collision occurred on "
46888 + "last xmit.\n", dev->name);
46889 lp->stats.tx_window_errors++;
46891 #if 0
46892 - if ( tx_status & TS_16COL ) { ... }
46893 + if (tx_status & TS_16COL) { ... }
46894 #endif
46896 - if ( tx_status & TS_SUCCESS ) {
46897 - printk(CARDNAME": Successful packet caused interrupt \n");
46898 + if (tx_status & TS_SUCCESS) {
46899 + printk("%s: Successful packet caused interrupt\n",
46900 + dev->name);
46902 /* re-enable transmit */
46903 - SMC_SELECT_BANK( 0 );
46904 - outw( inw( ioaddr + TCR ) | TCR_ENABLE, ioaddr + TCR );
46905 + SMC_SELECT_BANK(0);
46906 + smc_outw(smc_inw(ioaddr, TCR) | TCR_ENABLE, ioaddr, TCR);
46908 /* kill the packet */
46909 - SMC_SELECT_BANK( 2 );
46910 - outw( MC_FREEPKT, ioaddr + MMU_CMD );
46911 + SMC_SELECT_BANK(2);
46912 + smc_outw(MC_FREEPKT, ioaddr, MMU_CMD);
46914 /* one less packet waiting for me */
46915 lp->packets_waiting--;
46917 - outb( saved_packet, ioaddr + PNR_ARR );
46918 + smc_outb(saved_packet, ioaddr, PNR_ARR);
46919 return;
46922 @@ -1460,7 +1902,7 @@
46924 netif_stop_queue(dev);
46925 /* clear everything */
46926 - smc_shutdown( dev->base_addr );
46927 + smc_shutdown(dev);
46929 /* Update the statistics here. */
46930 return 0;
46931 @@ -1481,16 +1923,16 @@
46933 . This routine will, depending on the values passed to it,
46934 . either make it accept multicast packets, go into
46935 - . promiscuous mode ( for TCPDUMP and cousins ) or accept
46936 + . promiscuous mode (for TCPDUMP and cousins) or accept
46937 . a select set of multicast packets
46939 static void smc_set_multicast_list(struct net_device *dev)
46941 - short ioaddr = dev->base_addr;
46942 + u_int ioaddr = dev->base_addr;
46944 SMC_SELECT_BANK(0);
46945 - if ( dev->flags & IFF_PROMISC )
46946 - outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR );
46947 + if (dev->flags & IFF_PROMISC)
46948 + smc_outw(smc_inw(ioaddr, RCR) | RCR_PROMISC, ioaddr, RCR);
46950 /* BUG? I never disable promiscuous mode if multicasting was turned on.
46951 Now, I turn off promiscuous mode, but I don't do anything to multicasting
46952 @@ -1502,34 +1944,34 @@
46953 checked before the table is
46955 else if (dev->flags & IFF_ALLMULTI)
46956 - outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR );
46957 + smc_outw(smc_inw(ioaddr, RCR) | RCR_ALMUL, ioaddr, RCR);
46959 /* We just get all multicast packets even if we only want them
46960 . from one source. This will be changed at some future
46961 . point. */
46962 - else if (dev->mc_count ) {
46963 + else if (dev->mc_count) {
46964 /* support hardware multicasting */
46966 /* be sure I get rid of flags I might have set */
46967 - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
46968 - ioaddr + RCR );
46969 + smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
46970 + ioaddr, RCR);
46971 /* NOTE: this has to set the bank, so make sure it is the
46972 last thing called. The bank is set to zero at the top */
46973 - smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
46974 + smc_setmulticast(dev, dev->mc_count, dev->mc_list);
46976 - else {
46977 - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
46978 - ioaddr + RCR );
46979 + else {
46980 + smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
46981 + ioaddr, RCR);
46984 since I'm disabling all multicast entirely, I need to
46985 clear the multicast list
46987 - SMC_SELECT_BANK( 3 );
46988 - outw( 0, ioaddr + MULTICAST1 );
46989 - outw( 0, ioaddr + MULTICAST2 );
46990 - outw( 0, ioaddr + MULTICAST3 );
46991 - outw( 0, ioaddr + MULTICAST4 );
46992 + SMC_SELECT_BANK(3);
46993 + smc_outw(0, ioaddr, MULTICAST1);
46994 + smc_outw(0, ioaddr, MULTICAST2);
46995 + smc_outw(0, ioaddr, MULTICAST3);
46996 + smc_outw(0, ioaddr, MULTICAST4);
47000 @@ -1550,21 +1992,26 @@
47002 int init_module(void)
47004 - int result;
47006 if (io == 0)
47007 - printk(KERN_WARNING
47008 - CARDNAME": You shouldn't use auto-probing with insmod!\n" );
47009 + printk(KERN_WARNING CARDNAME
47010 + ": You shouldn't use auto-probing with insmod!\n");
47012 + /*
47013 + * Note: dev->if_port has changed to be 2.4 compliant.
47014 + * We keep the ifport insmod parameter the same though.
47015 + */
47016 + switch (ifport) {
47017 + case 1: devSMC9194.if_port = IF_PORT_10BASET; break;
47018 + case 2: devSMC9194.if_port = IF_PORT_AUI; break;
47019 + default: devSMC9194.if_port = 0; break;
47022 /* copy the parameters from insmod into the device structure */
47023 devSMC9194.base_addr = io;
47024 devSMC9194.irq = irq;
47025 - devSMC9194.if_port = ifport;
47026 - devSMC9194.init = smc_init;
47027 - if ((result = register_netdev(&devSMC9194)) != 0)
47028 - return result;
47029 + devSMC9194.init = smc_init;
47031 - return 0;
47032 + return register_netdev(&devSMC9194);
47035 void cleanup_module(void)
47036 --- linux-2.4.25/drivers/net/smc9194.h~2.4.25-vrs2.patch 2001-09-08 21:13:55.000000000 +0200
47037 +++ linux-2.4.25/drivers/net/smc9194.h 2004-03-31 17:15:09.000000000 +0200
47038 @@ -63,10 +63,11 @@
47040 #define TCR 0 /* transmit control register */
47041 #define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
47042 +#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
47043 +#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
47044 #define TCR_FDUPLX 0x0800 /* receive packets sent out */
47045 #define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */
47046 -#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
47047 -#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
47048 +#define TCR_FDSE 0x8000 /* full duplex, switched ethernet */
47050 #define TCR_CLEAR 0 /* do NOTHING */
47051 /* the normal settings for the TCR register : */
47052 @@ -107,7 +108,10 @@
47053 #define CTL_CR_ENABLE 0x40
47054 #define CTL_TE_ENABLE 0x0020
47055 #define CTL_AUTO_RELEASE 0x0800
47056 -#define CTL_EPROM_ACCESS 0x0003 /* high if Eprom is being read */
47057 +#define CTL_EPROM_SELECT 0x0004
47058 +#define CTL_EPROM_RELOAD 0x0002
47059 +#define CTL_EPROM_STORE 0x0001
47060 +#define CTL_EPROM_ACCESS (CTL_EPROM_RELOAD | CTL_EPROM_STORE) /* high if Eprom is being read */
47062 /* BANK 2 */
47063 #define MMU_CMD 0
47064 @@ -130,7 +134,6 @@
47065 #define PTR_READ 0x2000
47066 #define PTR_RCV 0x8000
47067 #define PTR_AUTOINC 0x4000
47068 -#define PTR_AUTO_INC 0x0040
47070 #define DATA_1 8
47071 #define DATA_2 10
47072 @@ -162,17 +165,6 @@
47073 #define CHIP_9195 5
47074 #define CHIP_91100 7
47076 -static const char * chip_ids[ 15 ] = {
47077 - NULL, NULL, NULL,
47078 - /* 3 */ "SMC91C90/91C92",
47079 - /* 4 */ "SMC91C94",
47080 - /* 5 */ "SMC91C95",
47081 - NULL,
47082 - /* 7 */ "SMC91C100",
47083 - /* 8 */ "SMC91C100FD",
47084 - NULL, NULL, NULL,
47085 - NULL, NULL, NULL};
47088 . Transmit status bits
47090 @@ -192,40 +184,20 @@
47091 #define RS_MULTICAST 0x0001
47092 #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
47094 -static const char * interfaces[ 2 ] = { "TP", "AUI" };
47096 -/*-------------------------------------------------------------------------
47097 - . I define some macros to make it easier to do somewhat common
47098 - . or slightly complicated, repeated tasks.
47099 - --------------------------------------------------------------------------*/
47101 -/* select a register bank, 0 to 3 */
47103 -#define SMC_SELECT_BANK(x) { outw( x, ioaddr + BANK_SELECT ); }
47105 -/* define a small delay for the reset */
47106 -#define SMC_DELAY() { inw( ioaddr + RCR );\
47107 - inw( ioaddr + RCR );\
47108 - inw( ioaddr + RCR ); }
47110 -/* this enables an interrupt in the interrupt mask register */
47111 -#define SMC_ENABLE_INT(x) {\
47112 - unsigned char mask;\
47113 - SMC_SELECT_BANK(2);\
47114 - mask = inb( ioaddr + INT_MASK );\
47115 - mask |= (x);\
47116 - outb( mask, ioaddr + INT_MASK ); \
47119 -/* this disables an interrupt from the interrupt mask register */
47121 + * SMC91C96 ethernet config and status registers.
47122 + * These are in the "attribute" space.
47123 + */
47124 +#define ECOR 0x8000
47125 +#define ECOR_RESET 0x80
47126 +#define ECOR_LEVEL_IRQ 0x40
47127 +#define ECOR_WR_ATTRIB 0x04
47128 +#define ECOR_ENABLE 0x01
47130 -#define SMC_DISABLE_INT(x) {\
47131 - unsigned char mask;\
47132 - SMC_SELECT_BANK(2);\
47133 - mask = inb( ioaddr + INT_MASK );\
47134 - mask &= ~(x);\
47135 - outb( mask, ioaddr + INT_MASK ); \
47137 +#define ECSR 0x8002
47138 +#define ECSR_IOIS8 0x20
47139 +#define ECSR_PWRDWN 0x04
47140 +#define ECSR_INT 0x02
47142 /*----------------------------------------------------------------------
47143 . Define the interrupts that I want to receive from the card
47144 @@ -237,5 +209,36 @@
47145 --------------------------------------------------------------------------*/
47146 #define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT)
47148 +/* store this information for the driver.. */
47149 +struct smc_local {
47150 + /*
47151 + these are things that the kernel wants me to keep, so users
47152 + can find out semi-useless statistics of how well the card is
47153 + performing
47154 + */
47155 + struct net_device_stats stats;
47157 + /*
47158 + If I have to wait until memory is available to send
47159 + a packet, I will store the skbuff here, until I get the
47160 + desired memory. Then, I'll send it out and free it.
47161 + */
47162 + struct sk_buff * saved_skb;
47164 + /*
47165 + . This keeps track of how many packets that I have
47166 + . sent out. When an TX_EMPTY interrupt comes, I know
47167 + . that all of these have been sent.
47168 + */
47169 + int packets_waiting;
47171 + /*
47172 + . Interface status. These correspond to the parameters
47173 + . in the ethtool_cmd structure.
47174 + */
47175 + u8 duplex;
47176 + u8 port;
47179 #endif /* _SMC_9194_H_ */
47181 --- linux-2.4.25/drivers/parport/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
47182 +++ linux-2.4.25/drivers/parport/Config.in 2004-03-31 17:15:09.000000000 +0200
47183 @@ -27,7 +27,8 @@
47184 dep_tristate ' Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA $CONFIG_PCMCIA $CONFIG_PARPORT_PC $CONFIG_HOTPLUG
47186 if [ "$CONFIG_ARM" = "y" ]; then
47187 - dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
47188 + dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT $CONFIG_ARCH_ARC
47189 + dep_tristate ' Accelent SA1110 IDP' CONFIG_PARPORT_IDP $CONFIG_PARPORT $CONFIG_SA1100_ACCELENT
47191 if [ "$CONFIG_AMIGA" = "y" ]; then
47192 dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
47193 --- linux-2.4.25/drivers/parport/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
47194 +++ linux-2.4.25/drivers/parport/Makefile 2004-03-31 17:15:09.000000000 +0200
47195 @@ -29,6 +29,7 @@
47196 obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o
47197 obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o
47198 obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o
47199 +obj-$(CONFIG_PARPORT_IDP) += parport_idp.o
47200 obj-$(CONFIG_PARPORT_IP22) += parport_ip22.o
47202 include $(TOPDIR)/Rules.make
47203 --- linux-2.4.25/drivers/parport/init.c~2.4.25-vrs2.patch 2002-11-29 00:53:14.000000000 +0100
47204 +++ linux-2.4.25/drivers/parport/init.c 2004-03-31 17:15:09.000000000 +0200
47205 @@ -164,6 +164,9 @@
47206 #ifdef CONFIG_PARPORT_SUNBPP
47207 parport_sunbpp_init();
47208 #endif
47209 +#ifdef CONFIG_PARPORT_IDP
47210 + parport_idp_init();
47211 +#endif
47212 return 0;
47215 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
47216 +++ linux-2.4.25/drivers/parport/parport_idp.c 2004-03-31 17:15:09.000000000 +0200
47217 @@ -0,0 +1,247 @@
47218 +/* Low-level polled-mode parallel port routines for the Accelent IDP
47220 + * Author: Rich Dulabahn <rich@accelent.com>
47222 + * Inspiration taken from parport_amiga.c and parport_atari.c.
47224 + * To use, under menuconfig:
47225 + * 1) Turn on <*> Accelent IDP under Parallel port setup
47226 + * 2) Turn on <*> Parallel printer support under Character devices
47228 + * This will give you parport0 configured as /dev/lp0
47230 + * To make the correct /dev/lp* entries, enter /dev and type this:
47232 + * mknod lp0 c 6 0
47233 + * mknod lp1 c 6 1
47234 + * mknod lp2 c 6 2
47236 + */
47238 +#include <linux/module.h>
47239 +#include <linux/init.h>
47240 +#include <linux/parport.h>
47241 +#include <asm/hardware.h>
47244 + * Parallel data port is port H, data
47245 + * Parallel data direction is port H, direction
47246 + * Control port is port I, data, lowest 4 bits
47247 + * Status port is port G, data, upper 5 bits
47248 + */
47250 +#define INPUTPOWERHANDLER 0
47251 +/* masks */
47252 +#define CONTROL_MASK 0x0f
47253 +#define STATUS_MASK 0xf8
47255 +#undef DEBUG
47257 +#ifdef DEBUG
47258 +#define DPRINTK printk
47259 +#else
47260 +#define DPRINTK(stuff...)
47261 +#endif
47263 +static struct parport *this_port = NULL;
47265 +static unsigned char
47266 +parport_idp_read_data(struct parport *p)
47268 + unsigned char c;
47270 + c = IDP_FPGA_PORTH_DATA;
47271 + DPRINTK("read_data:0x%x\n",c);
47272 + return c;
47275 +static void
47276 +parport_idp_write_data(struct parport *p, unsigned char data)
47278 + IDP_FPGA_PORTH_DATA = data;
47279 + DPRINTK("write_data:0x%x\n",data);
47282 +static unsigned char
47283 +parport_idp_read_control(struct parport *p)
47285 + unsigned char c;
47287 + c = IDP_FPGA_PORTI_DATA & CONTROL_MASK;
47288 + DPRINTK("read_control:0x%x\n",c);
47289 + return c;
47292 +static void
47293 +parport_idp_write_control(struct parport *p, unsigned char control)
47295 + unsigned int temp;
47297 + temp = IDP_FPGA_PORTH_DATA;
47298 + temp &= ~CONTROL_MASK;
47299 + IDP_FPGA_PORTI_DATA = (temp | (control & CONTROL_MASK));
47300 +DPRINTK("write_control:0x%x\n",control);
47303 +static unsigned char
47304 +parport_idp_frob_control(struct parport *p, unsigned char mask,
47305 + unsigned char val)
47307 + unsigned char c;
47309 +/* From the parport-lowlevel.txt file...*/
47310 +/* This is equivalent to reading from the control register, masking out
47311 +the bits in mask, exclusive-or'ing with the bits in val, and writing
47312 +the result to the control register. */
47314 +/* Easy enough, right? */
47316 + c = parport_idp_read_control(p);
47317 + parport_idp_write_control(p, (c & ~mask) ^ val);
47318 + DPRINTK("frob_control:0x%x\n",c);
47319 + return c;
47322 +static unsigned char
47323 +parport_idp_read_status(struct parport *p)
47325 + unsigned char c;
47327 + c = IDP_FPGA_PORTG_DATA & STATUS_MASK;
47328 + c ^= 0x80; /* toggle S7 bit, active low */
47329 + DPRINTK("read_status:0x%x\n",c);
47330 + return c;
47333 +static void
47334 +parport_idp_init_state(struct pardevice *d, struct parport_state *s)
47338 +static void
47339 +parport_idp_save_state(struct parport *p, struct parport_state *s)
47343 +static void
47344 +parport_idp_restore_state(struct parport *p, struct parport_state *s)
47348 +static void
47349 +parport_idp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
47353 +static void
47354 +parport_idp_enable_irq(struct parport *p)
47358 +static void
47359 +parport_idp_disable_irq(struct parport *p)
47363 +static void
47364 +parport_idp_data_forward(struct parport *p)
47366 + IDP_FPGA_PORTH_DIR = 0x00; /* 0 sets to output */
47367 + DPRINTK("data_forward:0x%x\n",0);
47370 +static void
47371 +parport_idp_data_reverse(struct parport *p)
47373 + IDP_FPGA_PORTH_DIR = 0xff; /* and 1 sets to input */
47374 + DPRINTK("data_reverse:0x%x\n",0xff);
47377 +static void
47378 +parport_idp_inc_use_count(void)
47380 + MOD_INC_USE_COUNT;
47383 +static void
47384 +parport_idp_dec_use_count(void)
47386 + MOD_DEC_USE_COUNT;
47389 +static struct parport_operations parport_idp_ops = {
47390 + parport_idp_write_data,
47391 + parport_idp_read_data,
47393 + parport_idp_write_control,
47394 + parport_idp_read_control,
47395 + parport_idp_frob_control,
47397 + parport_idp_read_status,
47399 + parport_idp_enable_irq,
47400 + parport_idp_disable_irq,
47402 + parport_idp_data_forward,
47403 + parport_idp_data_reverse,
47405 + parport_idp_init_state,
47406 + parport_idp_save_state,
47407 + parport_idp_restore_state,
47409 + parport_idp_inc_use_count,
47410 + parport_idp_dec_use_count,
47412 + parport_ieee1284_epp_write_data,
47413 + parport_ieee1284_epp_read_data,
47414 + parport_ieee1284_epp_write_addr,
47415 + parport_ieee1284_epp_read_addr,
47417 + parport_ieee1284_ecp_write_data,
47418 + parport_ieee1284_ecp_read_data,
47419 + parport_ieee1284_ecp_write_addr,
47421 + parport_ieee1284_write_compat,
47422 + parport_ieee1284_read_nibble,
47423 + parport_ieee1284_read_byte,
47427 +int __init
47428 +parport_idp_init(void)
47430 + struct parport *p;
47432 + p = parport_register_port((unsigned long)0,PARPORT_IRQ_NONE,PARPORT_DMA_NONE,&parport_idp_ops);
47434 + if (!p) return 0; /* return 0 on failure */
47436 + this_port=p;
47437 + printk("%s: Accelent IDP parallel port registered.\n", p->name);
47438 + parport_proc_register(p);
47439 + parport_announce_port(p);
47441 + return 1;
47444 +#ifdef MODULE
47446 +MODULE_AUTHOR("Rich Dulabahn");
47447 +MODULE_DESCRIPTION("Parport Driver for Accelent IDP");
47448 +MODULE_SUPPORTED_DEVICE("Accelent IDP builtin Parallel Port");
47449 +MODULE_LICENSE("GPL");
47451 +int
47452 +init_module(void)
47454 + return parport_idp_init() ? 0 : -ENODEV;
47457 +void
47458 +cleanup_module(void)
47460 + parport_proc_unregister(this_port);
47461 + parport_unregister_port(this_port);
47463 +#endif
47465 --- linux-2.4.25/drivers/pci/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
47466 +++ linux-2.4.25/drivers/pci/Makefile 2004-03-31 17:15:09.000000000 +0200
47467 @@ -13,7 +13,7 @@
47469 export-objs := pci.o
47471 -obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
47472 +obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o bridge.o
47473 obj-$(CONFIG_PROC_FS) += proc.o
47475 ifndef CONFIG_SPARC64
47476 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
47477 +++ linux-2.4.25/drivers/pci/bridge.c 2004-03-31 17:15:09.000000000 +0200
47478 @@ -0,0 +1,149 @@
47481 + * Copyright (c) 2001 Red Hat, Inc. All rights reserved.
47483 + * This software may be freely redistributed under the terms
47484 + * of the GNU public license.
47485 + *
47486 + * You should have received a copy of the GNU General Public License
47487 + * along with this program; if not, write to the Free Software
47488 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
47490 + * Author: Arjan van de Ven <arjanv@redhat.com>
47492 + */
47496 + * Generic PCI driver for PCI bridges for powermanagement purposes
47498 + */
47500 +#include <linux/config.h>
47501 +#include <linux/module.h>
47502 +#include <linux/kernel.h>
47503 +#include <linux/pci.h>
47504 +#include <linux/init.h>
47506 +static struct pci_device_id bridge_pci_table[] __devinitdata = {
47507 + {/* handle all PCI bridges */
47508 + class: ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
47509 + class_mask: ~0,
47510 + vendor: PCI_ANY_ID,
47511 + device: PCI_ANY_ID,
47512 + subvendor: PCI_ANY_ID,
47513 + subdevice: PCI_ANY_ID,
47514 + },
47515 + {0,},
47518 +static int bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id);
47519 +static int pci_bridge_save_state_bus(struct pci_bus *bus, int force);
47520 +int pci_generic_resume_compare(struct pci_dev *pdev);
47522 +int pci_bridge_force_restore = 0;
47527 +static int __init bridge_setup(char *str)
47529 + if (!strcmp(str,"force"))
47530 + pci_bridge_force_restore = 1;
47531 + else if (!strcmp(str,"noforce"))
47532 + pci_bridge_force_restore = 0;
47533 + return 0;
47536 +__setup("resume=",bridge_setup);
47539 +static int pci_bridge_save_state_bus(struct pci_bus *bus, int force)
47541 + struct list_head *list;
47542 + int error = 0;
47544 + list_for_each(list, &bus->children) {
47545 + error = pci_bridge_save_state_bus(pci_bus_b(list),force);
47546 + if (error) return error;
47548 + list_for_each(list, &bus->devices) {
47549 + pci_generic_suspend_save(pci_dev_b(list),0);
47551 + return 0;
47555 +static int pci_bridge_restore_state_bus(struct pci_bus *bus, int force)
47557 + struct list_head *list;
47558 + int error = 0;
47559 + static int printed_warning=0;
47561 + list_for_each(list, &bus->children) {
47562 + error = pci_bridge_restore_state_bus(pci_bus_b(list),force);
47563 + if (error) return error;
47565 + list_for_each(list, &bus->devices) {
47566 + if (force)
47567 + pci_generic_resume_restore(pci_dev_b(list));
47568 + else {
47569 + error = pci_generic_resume_compare(pci_dev_b(list));
47570 + if (error && !printed_warning++) {
47571 + printk(KERN_WARNING "resume warning: bios doesn't restore PCI state properly\n");
47572 + printk(KERN_WARNING "resume warning: if resume failed, try booting with resume=force\n");
47574 + if (error)
47575 + return error;
47578 + return 0;
47581 +static int bridge_suspend(struct pci_dev *dev, u32 force)
47583 + pci_generic_suspend_save(dev,force);
47584 + if (dev->subordinate)
47585 + pci_bridge_save_state_bus(dev->subordinate,force);
47586 + return 0;
47589 +static int bridge_resume(struct pci_dev *dev)
47592 + pci_generic_resume_restore(dev);
47593 + if (dev->subordinate)
47594 + pci_bridge_restore_state_bus(dev->subordinate,pci_bridge_force_restore);
47595 + return 0;
47599 +MODULE_DEVICE_TABLE(pci, bridge_pci_table);
47600 +static struct pci_driver bridge_ops = {
47601 + name: "PCI Bridge",
47602 + id_table: bridge_pci_table,
47603 + probe: bridge_probe,
47604 + suspend: bridge_suspend,
47605 + resume: bridge_resume
47608 +static int __devinit bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
47610 + return 0;
47613 +static int __init bridge_init(void)
47615 + pci_register_driver(&bridge_ops);
47616 + return 0;
47619 +static void __exit bridge_exit(void)
47621 + pci_unregister_driver(&bridge_ops);
47625 +module_init(bridge_init)
47626 +module_exit(bridge_exit)
47628 --- linux-2.4.25/drivers/pci/pci.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
47629 +++ linux-2.4.25/drivers/pci/pci.c 2004-03-31 17:15:09.000000000 +0200
47630 @@ -359,6 +359,48 @@
47631 return 0;
47634 +int
47635 +pci_compare_state(struct pci_dev *dev, u32 *buffer)
47637 + int i;
47638 + unsigned int temp;
47640 + if (buffer) {
47641 + for (i = 0; i < 16; i++) {
47642 + pci_read_config_dword(dev,i*4,&temp);
47643 + if (temp!=buffer[i])
47644 + return 1;
47647 + return 0;
47650 +int pci_generic_suspend_save(struct pci_dev *pdev, u32 state)
47652 + if (pdev)
47653 + pci_save_state(pdev,pdev->saved_state);
47654 + return 0;
47657 +int pci_generic_resume_restore(struct pci_dev *pdev)
47659 + if (pdev)
47660 + pci_restore_state(pdev,pdev->saved_state);
47661 + return 0;
47664 +int pci_generic_resume_compare(struct pci_dev *pdev)
47666 + int retval=0;
47667 + if (pdev)
47668 + retval = pci_compare_state(pdev,pdev->saved_state);
47669 + return retval;
47672 +EXPORT_SYMBOL(pci_generic_suspend_save);
47673 +EXPORT_SYMBOL(pci_generic_resume_restore);
47674 +EXPORT_SYMBOL(pci_generic_resume_compare);
47677 * pci_enable_device_bars - Initialize some of a device for use
47678 * @dev: PCI device to be initialized
47679 --- linux-2.4.25/drivers/pci/setup-bus.c~2.4.25-vrs2.patch 2003-06-13 16:51:35.000000000 +0200
47680 +++ linux-2.4.25/drivers/pci/setup-bus.c 2004-03-31 17:15:09.000000000 +0200
47681 @@ -12,6 +12,8 @@
47683 * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
47684 * PCI-PCI bridges cleanup, sorted resource allocation.
47685 + * May 2001, Russell King <rmk@arm.linux.org.uk>
47686 + * Allocate prefetchable memory regions where available.
47687 * Feb 2002, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
47688 * Converted to allocation in 3 passes, which gives
47689 * tighter packing. Prefetchable range support.
47690 @@ -160,8 +162,10 @@
47691 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
47693 /* Check if we have VGA behind the bridge.
47694 - Enable ISA in either case (FIXME!). */
47695 - l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
47696 + Enable ISA in either case. */
47697 + l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ?
47698 + PCI_BRIDGE_CTL_VGA | PCI_BRIDGE_CTL_NO_ISA :
47699 + PCI_BRIDGE_CTL_NO_ISA;
47700 pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
47703 --- linux-2.4.25/drivers/pcmcia/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
47704 +++ linux-2.4.25/drivers/pcmcia/Config.in 2004-03-31 17:15:09.000000000 +0200
47705 @@ -14,21 +14,19 @@
47707 tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA
47708 if [ "$CONFIG_PCMCIA" != "n" ]; then
47709 + # yes, I really mean the following...
47710 + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ARCH_SA1100" = "y" ]; then
47711 + define_bool CONFIG_PCMCIA_PROBE y
47712 + fi
47713 if [ "$CONFIG_PCI" != "n" ]; then
47714 bool ' CardBus support' CONFIG_CARDBUS
47716 + dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
47717 + bool ' i82365 compatible bridge support' CONFIG_I82365
47718 bool ' Databook TCIC host bridge support' CONFIG_TCIC
47719 if [ "$CONFIG_HD64465" = "y" ]; then
47720 dep_tristate ' HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
47722 - dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
47723 - bool ' i82365 compatible bridge support' CONFIG_I82365
47724 - if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
47725 - dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_PCMCIA
47726 - fi
47727 - if [ "$CONFIG_8xx" = "y" ]; then
47728 - dep_tristate ' M8xx support' CONFIG_PCMCIA_M8XX $CONFIG_PCMCIA
47729 - fi
47730 if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
47731 dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA
47732 if [ "$CONFIG_PCMCIA_AU1X00" != "n" ]; then
47733 @@ -44,5 +42,9 @@
47734 dep_tristate ' NEC VRC4173 CARDU support' CONFIG_PCMCIA_VRC4173 $CONFIG_PCMCIA
47737 +if [ "$CONFIG_ARM" = "y" ]; then
47738 + dep_tristate ' CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA
47739 + dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
47742 endmenu
47743 --- linux-2.4.25/drivers/pcmcia/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
47744 +++ linux-2.4.25/drivers/pcmcia/Makefile 2004-03-31 17:15:09.000000000 +0200
47745 @@ -65,15 +65,18 @@
47746 au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o
47747 au1000_ss-objs-$(CONFIG_PCMCIA_XXS1500) += au1000_xxs1500.o
47749 +obj-$(CONFIG_PCMCIA_CLPS6700) += clps6700.o
47750 obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
47751 -obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
47752 obj-$(CONFIG_PCMCIA_SIBYTE) += sibyte_generic.o
47754 sa1100_cs-objs-y := sa1100_generic.o
47755 +sa1100_cs-objs-$(CONFIG_SA1100_ADSAGC) += sa1100_graphicsmaster.o sa1111_generic.o
47756 sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
47757 +sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSYPLUS) += sa1100_adsbitsyplus.o sa1111_generic.o
47758 sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
47759 sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
47760 sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
47761 +sa1100_cs-objs-$(CONFIG_SA1100_CONSUS) += sa1100_neponset.o sa1111_generic.o
47762 sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
47763 sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
47764 sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
47765 --- linux-2.4.25/drivers/pcmcia/cistpl.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
47766 +++ linux-2.4.25/drivers/pcmcia/cistpl.c 2004-03-31 17:15:09.000000000 +0200
47767 @@ -286,7 +286,7 @@
47768 s->cis_mem.flags &= ~MAP_ACTIVE;
47769 s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
47770 if (!(s->cap.features & SS_CAP_STATIC_MAP))
47771 - release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
47772 + release_mem_resource(s->cis_mem.sys_start, s->cap.map_size);
47773 bus_iounmap(s->cap.bus, s->cis_virt);
47774 s->cis_mem.sys_start = 0;
47775 s->cis_virt = NULL;
47776 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
47777 +++ linux-2.4.25/drivers/pcmcia/clps6700.c 2004-03-31 17:15:09.000000000 +0200
47778 @@ -0,0 +1,498 @@
47780 + * linux/drivers/pcmcia/clps6700.c
47782 + * Copyright (C) 2000 Deep Blue Solutions Ltd
47784 + * This program is free software; you can redistribute it and/or modify
47785 + * it under the terms of the GNU General Public License as published by
47786 + * the Free Software Foundation; either version 2 of the License, or
47787 + * (at your option) any later version.
47789 + * This program is distributed in the hope that it will be useful,
47790 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
47791 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47792 + * GNU General Public License for more details.
47794 + * You should have received a copy of the GNU General Public License
47795 + * along with this program; if not, write to the Free Software
47796 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47797 + */
47798 +#include <linux/module.h>
47799 +#include <linux/kernel.h>
47800 +#include <linux/slab.h>
47801 +#include <linux/errno.h>
47802 +#include <linux/sched.h>
47803 +#include <linux/proc_fs.h>
47804 +#include <linux/spinlock.h>
47805 +#include <linux/init.h>
47807 +#include <asm/io.h>
47808 +#include <asm/irq.h>
47809 +#include <asm/hardware.h>
47810 +#include <asm/page.h>
47812 +#include <asm/arch/syspld.h>
47813 +#include <asm/hardware/clps7111.h>
47815 +#include <pcmcia/version.h>
47816 +#include <pcmcia/cs_types.h>
47817 +#include <pcmcia/ss.h>
47819 +#include "clps6700.h"
47821 +#define DEBUG
47823 +MODULE_AUTHOR("Russell King");
47824 +MODULE_DESCRIPTION("CL-PS6700 PCMCIA socket driver");
47826 +#define NR_CLPS6700 2
47828 +struct clps6700_skt {
47829 + u_int nr;
47830 + u_int physbase;
47831 + u_int regbase;
47832 + u_int pmr;
47833 + u_int cpcr;
47834 + u_int cpcr_3v3;
47835 + u_int cpcr_5v0;
47836 + u_int cur_pmr;
47837 + u_int cur_cicr;
47838 + u_int cur_pcimr;
47839 + u_int cur_cpcr;
47840 + void (*handler)(void *, u_int);
47841 + void *handler_info;
47843 + u_int ev_pending;
47844 + spinlock_t ev_lock;
47847 +static struct clps6700_skt *skts[NR_CLPS6700];
47849 +static int clps6700_sock_init(u_int sock)
47851 + struct clps6700_skt *skt = skts[sock];
47853 + skt->cur_cicr = 0;
47854 + skt->cur_pmr = skt->pmr;
47855 + skt->cur_pcimr = 0;
47856 + skt->cur_cpcr = skt->cpcr;
47858 +#ifdef DEBUG
47859 + printk("skt%d: sock_init()\n", sock);
47860 +#endif
47862 + __raw_writel(skt->cur_pmr, skt->regbase + PMR);
47863 + __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
47864 + __raw_writel(0x01f8, skt->regbase + SICR);
47865 + __raw_writel(0x0000, skt->regbase + DMACR);
47866 + __raw_writel(skt->cur_cicr, skt->regbase + CICR);
47867 + __raw_writel(0x1f00, skt->regbase + CITR0A);
47868 + __raw_writel(0x0000, skt->regbase + CITR0B);
47869 + __raw_writel(0x1f00, skt->regbase + CITR1A);
47870 + __raw_writel(0x0000, skt->regbase + CITR1B);
47871 + __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
47873 + /*
47874 + * Enable Auto Idle Mode in PM register
47875 + */
47876 + __raw_writel(-1, skt->regbase + PCIRR1);
47877 + __raw_writel(-1, skt->regbase + PCIRR2);
47878 + __raw_writel(-1, skt->regbase + PCIRR3);
47880 + return 0;
47883 +static int clps6700_suspend(u_int sock)
47885 + return 0;
47888 +static int clps6700_register_callback(u_int sock, void (*handler)(void *, u_int), void *info)
47890 + struct clps6700_skt *skt = skts[sock];
47892 +#ifdef DEBUG
47893 + printk("skt%d: register_callback: %p (%p)\n", sock, handler, info);
47894 +#endif
47896 + skt->handler_info = info;
47897 + skt->handler = handler;
47899 + return 0;
47902 +static int clps6700_inquire_socket(u_int sock, socket_cap_t *cap)
47904 + cap->features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_MEM_ALIGN;
47905 + cap->irq_mask = 0; /* available IRQs for this socket */
47906 + cap->map_size = PAGE_SIZE; /* minimum mapping size */
47907 + cap->pci_irq = 0; /* PCI interrupt number */
47908 + cap->cb_dev = NULL;
47909 + cap->bus = NULL;
47910 + return 0;
47913 +static int __clps6700_get_status(struct clps6700_skt *skt)
47915 + unsigned int v, val;
47917 + v = __raw_readl(skt->regbase + PCIILR);
47918 + val = 0;
47919 + if ((v & (PCM_CD1 | PCM_CD2)) == 0)
47920 + val |= SS_DETECT;
47921 + if ((v & (PCM_BVD2 | PCM_BVD1)) == PCM_BVD1)
47922 + val |= SS_BATWARN;
47923 + if ((v & PCM_BVD2) == 0)
47924 + val |= SS_BATDEAD;
47926 + if (v & PCM_RDYL)
47927 + val |= SS_READY;
47928 + if (v & PCM_VS1)
47929 + val |= SS_3VCARD;
47930 + if (v & PCM_VS2)
47931 + val |= SS_XVCARD;
47933 +#ifdef DEBUG
47934 + printk("skt%d: PCIILR: %08x -> (%s %s %s %s %s %s)\n",
47935 + skt->nr, v,
47936 + val & SS_READY ? "rdy" : "---",
47937 + val & SS_DETECT ? "det" : "---",
47938 + val & SS_BATWARN ? "bw" : "--",
47939 + val & SS_BATDEAD ? "bd" : "--",
47940 + val & SS_3VCARD ? "3v" : "--",
47941 + val & SS_XVCARD ? "xv" : "--");
47942 +#endif
47943 + return val;
47946 +static int clps6700_get_status(u_int sock, u_int *valp)
47948 + struct clps6700_skt *skt = skts[sock];
47950 + *valp = __clps6700_get_status(skt);
47952 + return 0; /* not used! */
47955 +static int clps6700_get_socket(u_int sock, socket_state_t *state)
47957 + return -EINVAL;
47960 +static int clps6700_set_socket(u_int sock, socket_state_t *state)
47962 + struct clps6700_skt *skt = skts[sock];
47963 + unsigned long flags;
47964 + u_int cpcr = skt->cur_cpcr, pmr = skt->cur_pmr, cicr = skt->cur_cicr;
47965 + u_int pcimr = 0;
47967 + cicr &= ~(CICR_ENABLE | CICR_RESET | CICR_IOMODE);
47969 + if (state->flags & SS_PWR_AUTO)
47970 + pmr |= PMR_DCAR | PMR_PDCR;
47972 + /*
47973 + * Note! We must NOT assert the Card Enable bit until reset has
47974 + * been de-asserted. Some cards indicate not ready, which then
47975 + * hangs our next access. (Bug in CLPS6700?)
47976 + */
47977 + if (state->flags & SS_RESET)
47978 + cicr |= CICR_RESET | CICR_RESETOE;
47979 + else if (state->flags & SS_OUTPUT_ENA)
47980 + cicr |= CICR_ENABLE;
47982 + if (state->flags & SS_IOCARD) {
47983 + cicr |= CICR_IOMODE;
47985 +/* if (state->csc_mask & SS_STSCHG)*/
47986 + } else {
47987 + if (state->csc_mask & SS_BATDEAD)
47988 + pcimr |= PCM_BVD2;
47989 + if (state->csc_mask & SS_BATWARN)
47990 + pcimr |= PCM_BVD1;
47991 + if (state->csc_mask & SS_READY)
47992 + pcimr |= PCM_RDYL;
47995 + if (state->csc_mask & SS_DETECT)
47996 + pcimr |= PCM_CD1 | PCM_CD2;
47998 + switch (state->Vcc) {
47999 + case 0: break;
48000 + case 33: cpcr |= skt->cpcr_3v3; pmr |= PMR_CPE; break;
48001 + case 50: cpcr |= skt->cpcr_5v0; pmr |= PMR_CPE; break;
48002 + default: return -EINVAL;
48005 +#ifdef DEBUG
48006 + printk("skt%d: PMR: %04x, CPCR: %04x, CICR: %04x PCIMR: %04x "
48007 + "(Vcc = %d, flags = %c%c%c%c, csc = %c%c%c%c%c)\n",
48008 + sock, pmr, cpcr, cicr, pcimr, state->Vcc,
48009 + state->flags & SS_RESET ? 'r' : '-',
48010 + state->flags & SS_PWR_AUTO ? 'p' : '-',
48011 + state->flags & SS_IOCARD ? 'i' : '-',
48012 + state->flags & SS_OUTPUT_ENA ? 'o' : '-',
48013 + state->csc_mask & SS_STSCHG ? 's' : '-',
48014 + state->csc_mask & SS_BATDEAD ? 'd' : '-',
48015 + state->csc_mask & SS_BATWARN ? 'w' : '-',
48016 + state->csc_mask & SS_READY ? 'r' : '-',
48017 + state->csc_mask & SS_DETECT ? 'c' : '-');
48018 +#endif
48020 + save_flags_cli(flags);
48022 + if (skt->cur_cpcr != cpcr) {
48023 + skt->cur_cpcr = cpcr;
48024 + __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
48027 + if (skt->cur_pmr != pmr) {
48028 + skt->cur_pmr = pmr;
48029 + __raw_writel(skt->cur_pmr, skt->regbase + PMR);
48031 + if (skt->cur_pcimr != pcimr) {
48032 + skt->cur_pcimr = pcimr;
48033 + __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
48035 + if (skt->cur_cicr != cicr) {
48036 + skt->cur_cicr = cicr;
48037 + __raw_writel(skt->cur_cicr, skt->regbase + CICR);
48040 + restore_flags(flags);
48042 + return 0;
48045 +static int clps6700_get_io_map(u_int sock, struct pccard_io_map *io)
48047 + return -EINVAL;
48050 +static int clps6700_set_io_map(u_int sock, struct pccard_io_map *io)
48052 + printk("skt%d: iomap: %d: speed %d, flags %X start %X stop %X\n",
48053 + sock, io->map, io->speed, io->flags, io->start, io->stop);
48054 + return 0;
48057 +static int clps6700_get_mem_map(u_int sock, struct pccard_mem_map *mem)
48059 + return -EINVAL;
48063 + * Set the memory map attributes for this socket. (ie, mem->speed)
48064 + * Note that since we have SS_CAP_STATIC_MAP set, we don't need to do
48065 + * any mapping here at all; we just need to return the address (suitable
48066 + * for ioremap) to map the requested space in mem->sys_start.
48068 + * flags & MAP_ATTRIB indicates whether we want attribute space.
48069 + */
48070 +static int clps6700_set_mem_map(u_int sock, struct pccard_mem_map *mem)
48072 + struct clps6700_skt *skt = skts[sock];
48073 + u_int off;
48075 + printk("skt%d: memmap: %d: speed %d, flags %X start %lX stop %lX card %X\n",
48076 + sock, mem->map, mem->speed, mem->flags, mem->sys_start,
48077 + mem->sys_stop, mem->card_start);
48079 + if (mem->flags & MAP_ATTRIB)
48080 + off = CLPS6700_ATTRIB_BASE;
48081 + else
48082 + off = CLPS6700_MEM_BASE;
48084 + mem->sys_start = skt->physbase + off;
48085 + mem->sys_start += mem->card_start;
48087 + return 0;
48090 +static void clps6700_proc_setup(u_int sock, struct proc_dir_entry *base)
48094 +static struct pccard_operations clps6700_operations = {
48095 + init: clps6700_sock_init,
48096 + suspend: clps6700_suspend,
48097 + register_callback: clps6700_register_callback,
48098 + inquire_socket: clps6700_inquire_socket,
48099 + get_status: clps6700_get_status,
48100 + get_socket: clps6700_get_socket,
48101 + set_socket: clps6700_set_socket,
48102 + get_io_map: clps6700_get_io_map,
48103 + set_io_map: clps6700_set_io_map,
48104 + get_mem_map: clps6700_get_mem_map,
48105 + set_mem_map: clps6700_set_mem_map,
48106 + proc_setup: clps6700_proc_setup
48109 +static void clps6700_bh(void *dummy)
48111 + int i;
48113 + for (i = 0; i < NR_CLPS6700; i++) {
48114 + struct clps6700_skt *skt = skts[i];
48115 + unsigned long flags;
48116 + u_int events;
48118 + if (!skt)
48119 + continue;
48121 + /*
48122 + * Note! We must read the pending event state
48123 + * with interrupts disabled, otherwise we race
48124 + * with our own interrupt routine!
48125 + */
48126 + spin_lock_irqsave(&skt->ev_lock, flags);
48127 + events = skt->ev_pending;
48128 + skt->ev_pending = 0;
48129 + spin_unlock_irqrestore(&skt->ev_lock, flags);
48131 + if (skt->handler && events)
48132 + skt->handler(skt->handler_info, events);
48136 +static struct tq_struct clps6700_task = {
48137 + routine: clps6700_bh
48140 +static void clps6700_interrupt(int irq, void *dev_id, struct pt_regs *regs)
48142 + struct clps6700_skt *skt = dev_id;
48143 + u_int val, events;
48145 + val = __raw_readl(skt->regbase + PCISR);
48146 + if (!val)
48147 + return;
48149 + __raw_writel(val, skt->regbase + PCICR);
48151 + events = 0;
48152 + if (val & (PCM_CD1 | PCM_CD2))
48153 + events |= SS_DETECT;
48154 + if (val & PCM_BVD1)
48155 + events |= SS_BATWARN;
48156 + if (val & PCM_BVD2)
48157 + events |= SS_BATDEAD;
48158 + if (val & PCM_RDYL)
48159 + events |= SS_READY;
48161 + spin_lock(&skt->ev_lock);
48162 + skt->ev_pending |= events;
48163 + spin_unlock(&skt->ev_lock);
48164 + schedule_task(&clps6700_task);
48167 +static int __init clps6700_init_skt(int nr)
48169 + struct clps6700_skt *skt;
48170 + int ret;
48172 + skt = kmalloc(sizeof(struct clps6700_skt), GFP_KERNEL);
48173 + if (!skt)
48174 + return -ENOMEM;
48176 + memset(skt, 0, sizeof(struct clps6700_skt));
48178 + spin_lock_init(&skt->ev_lock);
48180 + skt->nr = nr;
48181 + skt->physbase = nr ? CS5_PHYS_BASE : CS4_PHYS_BASE;
48182 + skt->pmr = PMR_AUTOIDLE | PMR_MCPE | PMR_CDWEAK;
48183 + skt->cpcr = CPCR_PDIR(PCTL1|PCTL0);
48184 + skt->cpcr_3v3 = CPCR_PON(PCTL0);
48185 + skt->cpcr_5v0 = CPCR_PON(PCTL0); /* we only do 3v3 */
48187 + skt->cur_pmr = skt->pmr;
48189 + skt->regbase = (u_int)ioremap(skt->physbase + CLPS6700_REG_BASE,
48190 + CLPS6700_REG_SIZE);
48191 + ret = -ENOMEM;
48192 + if (!skt->regbase)
48193 + goto err_free;
48195 + skts[nr] = skt;
48197 + ret = request_irq(IRQ_EINT3, clps6700_interrupt,
48198 + SA_SHIRQ, "pcmcia", skt);
48200 + if (ret) {
48201 + printk(KERN_ERR "clps6700: unable to grab irq%d (%d)\n",
48202 + IRQ_EINT3, ret);
48203 + goto err_unmap;
48205 + return 0;
48207 +err_unmap:
48208 + iounmap((void *)skt->regbase);
48209 +err_free:
48210 + kfree(skt);
48211 + skts[nr] = NULL;
48212 + return ret;
48215 +static void clps6700_free_resources(void)
48217 + int i;
48219 + for (i = NR_CLPS6700; i >= 0; i--) {
48220 + struct clps6700_skt *skt = skts[i];
48222 + skts[i] = NULL;
48223 + if (skt == NULL)
48224 + continue;
48226 + free_irq(IRQ_EINT3, skt);
48227 + if (skt->regbase) {
48228 + __raw_writel(skt->pmr, skt->regbase + PMR);
48229 + __raw_writel(skt->cpcr, skt->regbase + CPCR);
48230 + __raw_writel(0, skt->regbase + CICR);
48231 + __raw_writel(0, skt->regbase + PCIMR);
48233 + iounmap((void *)skt->regbase);
48234 + kfree(skt);
48238 +static int __init clps6700_init(void)
48240 + unsigned int v;
48241 + int err, nr;
48243 + PLD_CF = 0;
48244 + v = clps_readl(SYSCON2) | SYSCON2_PCCARD1 | SYSCON2_PCCARD2;
48245 + clps_writel(v, SYSCON2);
48246 + v = clps_readl(SYSCON1) | SYSCON1_EXCKEN;
48247 + clps_writel(v, SYSCON1);
48249 + for (nr = 0; nr < NR_CLPS6700; nr++) {
48250 + err = clps6700_init_skt(nr);
48251 + if (err)
48252 + goto free;
48255 + err = register_ss_entry(nr, &clps6700_operations);
48256 + if (err)
48257 + goto free;
48259 + return 0;
48261 +free:
48262 + clps6700_free_resources();
48263 + /*
48264 + * An error occurred. Unmap and free all CLPS6700
48265 + */
48266 + return err;
48269 +static void __exit clps6700_exit(void)
48271 + unregister_ss_entry(&clps6700_operations);
48272 + clps6700_free_resources();
48275 +module_init(clps6700_init);
48276 +module_exit(clps6700_exit);
48277 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
48278 +++ linux-2.4.25/drivers/pcmcia/clps6700.h 2004-03-31 17:15:09.000000000 +0200
48279 @@ -0,0 +1,85 @@
48280 +#define PCISR 0x0000 /* PC Card Interrupt Status Register */
48281 +#define PCIMR 0x0400 /* PC Card Interrupt Mask Register */
48282 +#define PCICR 0x0800 /* PC Card Interrupt Clear Register */
48283 +#define PCIOSR 0x0c00 /* PC Card Interrupt Output Select Regsiter */
48284 +#define PCIRR1 0x1000 /* PC Card Interrupt Reserved Register 1 */
48285 +#define PCIRR2 0x1400 /* PC Card Interrupt Reserved Register 2 */
48286 +#define PCIRR3 0x1800 /* PC Card Interrupt Reserved Register 3 */
48287 +#define PCIILR 0x1c00 /* PC Card Interrupt Input Level Register */
48288 +#define SICR 0x2000 /* System Interface Configuration Register */
48289 +#define CICR 0x2400 /* Card Interface Configuration Register */
48290 +#define PMR 0x2800 /* Power Management Register */
48291 +#define CPCR 0x2c00 /* Card Power Control Register */
48292 +#define CITR0A 0x3000 /* Card Interface Timing Register 0A */
48293 +#define CITR0B 0x3400 /* Card Interface Timing Register 0B */
48294 +#define CITR1A 0x3800 /* Card Interface Timing Register 1A */
48295 +#define CITR1B 0x3c00 /* Card Interface Timing Register 1B */
48296 +#define DMACR 0x4000 /* DMA Control Register */
48297 +#define DIR 0x4400 /* Device Information Register */
48299 +#define CLPS6700_ATTRIB_BASE 0x00000000
48300 +#define CLPS6700_IO_BASE 0x04000000
48301 +#define CLPS6700_MEM_BASE 0x08000000
48302 +#define CLPS6700_REG_BASE 0x0c000000
48303 +#define CLPS6700_REG_SIZE 0x00005000
48306 +#define PMR_AUTOIDLE (1 << 0) /* auto idle mode */
48307 +#define PMR_FORCEIDLE (1 << 1) /* force idle mode */
48308 +#define PMR_PDCS (1 << 2) /* Power down card on standby */
48309 +#define PMR_PDCR (1 << 3) /* Power down card on removal */
48310 +#define PMR_DCAR (1 << 4) /* Disable card access on removal */
48311 +#define PMR_CPE (1 << 5) /* Card power enable */
48312 +#define PMR_MCPE (1 << 6) /* Monitor card power enable */
48313 +#define PMR_PDREQLSEL (1 << 7) /* If set, PDREQL is a GPIO pin */
48314 +#define PMR_DISSTBY (1 << 8) /* Disable standby */
48315 +#define PMR_ACCSTBY (1 << 9) /* Complete card accesses before standby*/
48316 +#define PMR_CDUNPROT (0 << 10) /* Card detect inputs unprotected */
48317 +#define PMR_CDPROT (1 << 10) /* Card detect inputs protected */
48318 +#define PMR_CDWEAK (2 << 10) /* Weak pullup except in standby */
48319 +#define PMR_CDWEAKAL (3 << 10) /* Weak pullup */
48321 +#define CPCR_PON(x) ((x)&7) /* PCTL[2:0] value when PMR_CPE = 1 */
48322 +#define CPCR_POFF(x) (((x)&7)<<3) /* PCTL[2:0] value when PMR_CPE = 0 */
48323 +#define CPCR_PDIR(x) (((x)&7)<<6) /* PCTL[2:0] direction */
48324 +#define CPCR_CON(x) (((x)&1)<<9) /* GPIO value when PMR_CPE = 1 */
48325 +#define CPCR_COFF(x) (((x)&1)<<10) /* GPIO value when PMR_CPE = 0 */
48326 +#define CPCR_CDIR(x) (((x)&1)<<11) /* GPIO direction (PMR_PDREQLSEL = 1) */
48327 +#define CPCR_VS(x) (((x)&3)<<12) /* VS[2:1] output value */
48328 +#define CPCR_VSDIR(x) (((x)&3)<<14) /* VS[2:1] direction */
48330 +#define PCTL0 (1 << 0)
48331 +#define PCTL1 (1 << 1)
48332 +#define PCTL2 (1 << 2)
48334 +#define CICR_ASRTMR1 (1 << 0) /* Timer 1 select for attribute read */
48335 +#define CICR_ASWTMR1 (1 << 1) /* Timer 1 select for attribute write */
48336 +#define CICR_IOSRTMR1 (1 << 2) /* Timer 1 select for IO read */
48337 +#define CICR_IOSWTMR1 (1 << 3) /* Timer 1 select for IO write */
48338 +#define CICR_MEMSRTMR1 (1 << 4) /* Timer 1 select for memory read */
48339 +#define CICR_MEMSWTMR1 (1 << 5) /* Timer 1 select for memory write */
48340 +#define CICR_AUTOIOSZ (1 << 6) /* Auto size I/O accesses */
48341 +#define CICR_CAW (1 << 7) /* Card access width */
48342 +#define CICR_IOMODE (1 << 8) /* IO mode select */
48343 +#define CICR_ENABLE (1 << 10) /* Card enable */
48344 +#define CICR_RESETOE (1 << 11) /* Card reset output enable */
48345 +#define CICR_RESET (1 << 12) /* Card reset */
48348 +#define RD_FAIL (1 << 14)
48349 +#define WR_FAIL (1 << 13)
48350 +#define IDLE (1 << 12)
48352 +#define FFOTHLD (1 << 11)
48353 +#define PCM_RDYL (1 << 10)
48354 +#define PCM_WP (1 << 9)
48355 +#define PCTL (1 << 8)
48357 +#define PDREQ_L (1 << 6)
48358 +#define PCM_VS2 (1 << 5)
48359 +#define PCM_VS1 (1 << 4)
48361 +#define PCM_CD2 (1 << 3)
48362 +#define PCM_CD1 (1 << 2)
48363 +#define PCM_BVD2 (1 << 1)
48364 +#define PCM_BVD1 (1 << 0)
48365 --- linux-2.4.25/drivers/pcmcia/cs.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
48366 +++ linux-2.4.25/drivers/pcmcia/cs.c 2004-03-31 17:15:09.000000000 +0200
48367 @@ -3,7 +3,7 @@
48368 Kernel Card Services -- core services
48370 cs.c 1.271 2000/10/02 20:27:49
48373 The contents of this file are subject to the Mozilla Public
48374 License Version 1.1 (the "License"); you may not use this file
48375 except in compliance with the License. You may obtain a copy of
48376 @@ -28,7 +28,7 @@
48377 and other provisions required by the GPL. If you do not delete
48378 the provisions above, a recipient may use your version of this
48379 file under either the MPL or the GPL.
48382 ======================================================================*/
48384 #include <linux/module.h>
48385 @@ -92,7 +92,7 @@
48386 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
48387 MODULE_DESCRIPTION("Linux Kernel Card Services " CS_RELEASE
48388 "\n options:" OPTIONS);
48389 -MODULE_LICENSE("Dual MPL/GPL");
48390 +MODULE_LICENSE("Dual MPL/GPL");
48392 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
48394 @@ -123,7 +123,7 @@
48395 static const char *version =
48396 "cs.c 1.279 2001/10/13 00:08:28 (David Hinds)";
48397 #endif
48400 /*====================================================================*/
48402 socket_state_t dead_socket = {
48403 @@ -299,7 +299,7 @@
48405 Low-level PC Card interface drivers need to register with Card
48406 Services using these calls.
48409 ======================================================================*/
48411 static int setup_socket(socket_info_t *);
48412 @@ -331,7 +331,7 @@
48413 s->use_bus_pm = use_bus_pm;
48414 s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
48415 spin_lock_init(&s->lock);
48418 for (i = 0; i < sockets; i++)
48419 if (socket_table[i] == NULL) break;
48420 socket_table[i] = s;
48421 @@ -365,7 +365,7 @@
48422 for (ns = 0; ns < nsock; ns++) {
48423 pcmcia_register_socket (ns, ss_entry, 0);
48427 return 0;
48428 } /* register_ss_entry */
48430 @@ -457,7 +457,7 @@
48431 static void shutdown_socket(socket_info_t *s)
48433 client_t **c;
48436 DEBUG(1, "cs: shutdown_socket(%p)\n", s);
48438 /* Blank out the socket state */
48439 @@ -561,7 +561,7 @@
48440 have several causes: card insertion, a call to reset_socket, or
48441 recovery from a suspend/resume cycle. Unreset_socket() sends
48442 a CS event that matches the cause of the reset.
48445 ======================================================================*/
48447 static void reset_socket(socket_info_t *s)
48448 @@ -616,7 +616,7 @@
48449 s->state &= ~SOCKET_SETUP_PENDING;
48450 } else {
48451 send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
48452 - if (s->reset_handle) {
48453 + if (s->reset_handle) {
48454 s->reset_handle->event_callback_args.info = NULL;
48455 EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,
48456 CS_EVENT_PRI_LOW);
48457 @@ -631,7 +631,7 @@
48458 valid clients. Parse_events() interprets the event bits from
48459 a card status change report. Do_shutdown() handles the high
48460 priority stuff associated with a card removal.
48463 ======================================================================*/
48465 static int send_event(socket_info_t *s, event_t event, int priority)
48466 @@ -641,7 +641,7 @@
48467 DEBUG(1, "cs: send_event(sock %d, event %d, pri %d)\n",
48468 s->sock, event, priority);
48469 ret = 0;
48470 - for (; client; client = client->next) {
48471 + for (; client; client = client->next) {
48472 if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
48473 continue;
48474 if (client->EventMask & event) {
48475 @@ -675,10 +675,17 @@
48476 static void parse_events(void *info, u_int events)
48478 socket_info_t *s = info;
48480 if (events & SS_DETECT) {
48481 int status;
48483 get_socket_status(s, &status);
48485 + /*
48486 + * If our socket state indicates that a card is present and
48487 + * either the socket has not been suspended (for some reason)
48488 + * or the card has been removed, shut down the socket first.
48489 + */
48490 if ((s->state & SOCKET_PRESENT) &&
48491 (!(s->state & SOCKET_SUSPEND) ||
48492 !(status & SS_DETECT)))
48493 @@ -716,7 +723,7 @@
48495 This does not comply with the latest PC Card spec for handling
48496 power management events.
48499 ======================================================================*/
48501 void pcmcia_suspend_socket (socket_info_t *s)
48502 @@ -773,7 +780,7 @@
48503 /*======================================================================
48505 Special stuff for managing IO windows, because they are scarce.
48508 ======================================================================*/
48510 static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
48511 @@ -862,7 +869,7 @@
48512 Access_configuration_register() reads and writes configuration
48513 registers in attribute memory. Memory window 0 is reserved for
48514 this and the tuple reading services.
48517 ======================================================================*/
48519 int pcmcia_access_configuration_register(client_handle_t handle,
48520 @@ -872,7 +879,7 @@
48521 config_t *c;
48522 int addr;
48523 u_char val;
48526 if (CHECK_HANDLE(handle))
48527 return CS_BAD_HANDLE;
48528 s = SOCKET(handle);
48529 @@ -890,7 +897,7 @@
48530 return CS_CONFIGURATION_LOCKED;
48532 addr = (c->ConfigBase + reg->Offset) >> 1;
48535 switch (reg->Action) {
48536 case CS_READ:
48537 read_cis_mem(s, 1, addr, 1, &val);
48538 @@ -913,7 +920,7 @@
48539 It is normally called by Driver Services after it has identified
48540 a newly inserted card. An instance of that driver will then be
48541 eligible to register as a client of this socket.
48544 ======================================================================*/
48546 int pcmcia_bind_device(bind_req_t *req)
48547 @@ -949,23 +956,23 @@
48548 region. It is normally called by Driver Services after it has
48549 identified a memory device type. An instance of the corresponding
48550 driver will then be able to register to control this region.
48553 ======================================================================*/
48555 int pcmcia_bind_mtd(mtd_bind_t *req)
48557 socket_info_t *s;
48558 memory_handle_t region;
48561 if (CHECK_SOCKET(req->Socket))
48562 return CS_BAD_SOCKET;
48563 s = SOCKET(req);
48566 if (req->Attributes & REGION_TYPE_AM)
48567 region = s->a_region;
48568 else
48569 region = s->c_region;
48572 while (region) {
48573 if (region->info.CardOffset == req->CardOffset) break;
48574 region = region->info.next;
48575 @@ -973,7 +980,7 @@
48576 if (!region || (region->mtd != NULL))
48577 return CS_BAD_OFFSET;
48578 strncpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
48581 DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
48582 req->Attributes, req->CardOffset, (char *)req->dev_info);
48583 return CS_SUCCESS;
48584 @@ -988,7 +995,7 @@
48585 memory_handle_t region;
48586 u_long flags;
48587 int i, sn;
48590 DEBUG(1, "cs: deregister_client(%p)\n", handle);
48591 if (CHECK_HANDLE(handle))
48592 return CS_BAD_HANDLE;
48593 @@ -1007,7 +1014,7 @@
48594 for (region = s->c_region; region; region = region->info.next)
48595 if (region->mtd == handle) region->mtd = NULL;
48599 sn = handle->Socket; s = socket_table[sn];
48601 if ((handle->state & CLIENT_STALE) ||
48602 @@ -1032,7 +1039,7 @@
48604 if (--s->real_clients == 0)
48605 register_callback(s, NULL, NULL);
48608 return CS_SUCCESS;
48609 } /* deregister_client */
48611 @@ -1043,7 +1050,7 @@
48613 socket_info_t *s;
48614 config_t *c;
48617 if (CHECK_HANDLE(handle))
48618 return CS_BAD_HANDLE;
48619 s = SOCKET(handle);
48620 @@ -1055,7 +1062,7 @@
48621 return CS_BAD_ARGS;
48622 } else
48623 config->Function = handle->Function;
48626 #ifdef CONFIG_CARDBUS
48627 if (s->state & SOCKET_CARDBUS) {
48628 u_char fn = config->Function;
48629 @@ -1076,16 +1083,16 @@
48630 return CS_SUCCESS;
48632 #endif
48635 c = (s->config != NULL) ? &s->config[config->Function] : NULL;
48638 if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
48639 config->Attributes = 0;
48640 config->Vcc = s->socket.Vcc;
48641 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
48642 return CS_SUCCESS;
48646 /* !!! This is a hack !!! */
48647 memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
48648 config->Attributes |= CONF_VALID_CLIENT;
48649 @@ -1099,14 +1106,14 @@
48650 config->NumPorts2 = c->io.NumPorts2;
48651 config->Attributes2 = c->io.Attributes2;
48652 config->IOAddrLines = c->io.IOAddrLines;
48655 return CS_SUCCESS;
48656 } /* get_configuration_info */
48658 /*======================================================================
48660 Return information about this version of Card Services.
48663 ======================================================================*/
48665 int pcmcia_get_card_services_info(servinfo_t *info)
48666 @@ -1124,7 +1131,7 @@
48668 Note that get_first_client() *does* recognize the Socket field
48669 in the request structure.
48672 ======================================================================*/
48674 int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
48675 @@ -1239,7 +1246,7 @@
48677 Get the current socket state bits. We don't support the latched
48678 SocketState yet: I haven't seen any point for it.
48681 ======================================================================*/
48683 int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
48684 @@ -1247,7 +1254,7 @@
48685 socket_info_t *s;
48686 config_t *c;
48687 int val;
48690 if (CHECK_HANDLE(handle))
48691 return CS_BAD_HANDLE;
48692 s = SOCKET(handle);
48693 @@ -1263,7 +1270,7 @@
48694 return CS_NO_CARD;
48695 if (s->state & SOCKET_SETUP_PENDING)
48696 status->CardState |= CS_EVENT_CARD_INSERTION;
48699 /* Get info from the PRR, if necessary */
48700 if (handle->Function == BIND_FN_ALL) {
48701 if (status->Function && (status->Function >= s->functions))
48702 @@ -1309,7 +1316,7 @@
48703 /*======================================================================
48705 Change the card address of an already open memory window.
48708 ======================================================================*/
48710 int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
48711 @@ -1338,7 +1345,7 @@
48712 /*======================================================================
48714 Modify a locked socket configuration
48717 ======================================================================*/
48719 int pcmcia_modify_configuration(client_handle_t handle,
48720 @@ -1346,7 +1353,7 @@
48722 socket_info_t *s;
48723 config_t *c;
48726 if (CHECK_HANDLE(handle))
48727 return CS_BAD_HANDLE;
48728 s = SOCKET(handle); c = CONFIG(handle);
48729 @@ -1354,7 +1361,7 @@
48730 return CS_NO_CARD;
48731 if (!(c->state & CONFIG_LOCKED))
48732 return CS_CONFIGURATION_LOCKED;
48735 if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
48736 if (mod->Attributes & CONF_ENABLE_IRQ) {
48737 c->Attributes |= CONF_ENABLE_IRQ;
48738 @@ -1406,7 +1413,7 @@
48739 win->ctl.flags |= MAP_USE_WAIT;
48740 win->ctl.speed = req->AccessSpeed;
48741 set_mem_map(win->sock, &win->ctl);
48744 return CS_SUCCESS;
48745 } /* modify_window */
48747 @@ -1416,7 +1423,7 @@
48748 caller with a socket. The driver must have already been bound
48749 to a socket with bind_device() -- in fact, bind_device()
48750 allocates the client structure that will be used.
48753 ======================================================================*/
48755 int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
48756 @@ -1424,7 +1431,7 @@
48757 client_t *client;
48758 socket_info_t *s;
48759 socket_t ns;
48762 /* Look for unbound client with matching dev_info */
48763 client = NULL;
48764 for (ns = 0; ns < sockets; ns++) {
48765 @@ -1464,7 +1471,7 @@
48767 if (s->state & SOCKET_CARDBUS)
48768 client->state |= CLIENT_CARDBUS;
48771 if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
48772 (client->Function != BIND_FN_ALL)) {
48773 cistpl_longlink_mfc_t mfc;
48774 @@ -1479,7 +1486,7 @@
48775 return CS_OUT_OF_RESOURCE;
48776 memset(s->config, 0, sizeof(config_t) * s->functions);
48780 DEBUG(1, "cs: register_client(): client 0x%p, sock %d, dev %s\n",
48781 client, client->Socket, client->dev_info);
48782 if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
48783 @@ -1501,13 +1508,13 @@
48784 pccard_io_map io = { 0, 0, 0, 0, 1 };
48785 socket_info_t *s;
48786 int i;
48789 if (CHECK_HANDLE(handle) ||
48790 !(handle->state & CLIENT_CONFIG_LOCKED))
48791 return CS_BAD_HANDLE;
48792 handle->state &= ~CLIENT_CONFIG_LOCKED;
48793 s = SOCKET(handle);
48796 #ifdef CONFIG_CARDBUS
48797 if (handle->state & CLIENT_CARDBUS) {
48798 cb_disable(s);
48799 @@ -1515,7 +1522,7 @@
48800 return CS_SUCCESS;
48802 #endif
48805 if (!(handle->state & CLIENT_STALE)) {
48806 config_t *c = CONFIG(handle);
48807 if (--(s->lock_count) == 0) {
48808 @@ -1536,7 +1543,7 @@
48810 c->state &= ~CONFIG_LOCKED;
48814 return CS_SUCCESS;
48815 } /* release_configuration */
48817 @@ -1547,25 +1554,25 @@
48818 the actual socket configuration, so if the client is "stale", we
48819 don't bother checking the port ranges against the current socket
48820 values.
48823 ======================================================================*/
48825 int pcmcia_release_io(client_handle_t handle, io_req_t *req)
48827 socket_info_t *s;
48830 if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
48831 return CS_BAD_HANDLE;
48832 handle->state &= ~CLIENT_IO_REQ;
48833 s = SOCKET(handle);
48836 #ifdef CONFIG_CARDBUS
48837 if (handle->state & CLIENT_CARDBUS) {
48838 cb_release(s);
48839 return CS_SUCCESS;
48841 #endif
48844 if (!(handle->state & CLIENT_STALE)) {
48845 config_t *c = CONFIG(handle);
48846 if (c->state & CONFIG_LOCKED)
48847 @@ -1581,7 +1588,7 @@
48848 release_io_space(s, req->BasePort1, req->NumPorts1);
48849 if (req->NumPorts2)
48850 release_io_space(s, req->BasePort2, req->NumPorts2);
48853 return CS_SUCCESS;
48854 } /* release_io */
48856 @@ -1594,7 +1601,7 @@
48857 return CS_BAD_HANDLE;
48858 handle->state &= ~CLIENT_IRQ_REQ;
48859 s = SOCKET(handle);
48862 if (!(handle->state & CLIENT_STALE)) {
48863 config_t *c = CONFIG(handle);
48864 if (c->state & CONFIG_LOCKED)
48865 @@ -1608,16 +1615,16 @@
48866 s->irq.AssignedIRQ = 0;
48871 if (req->Attributes & IRQ_HANDLE_PRESENT) {
48872 bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance);
48875 -#ifdef CONFIG_ISA
48876 +#ifdef CONFIG_PCMCIA_PROBE
48877 if (req->AssignedIRQ != s->cap.pci_irq)
48878 undo_irq(req->Attributes, req->AssignedIRQ);
48879 #endif
48882 return CS_SUCCESS;
48883 } /* cs_release_irq */
48885 @@ -1626,7 +1633,7 @@
48886 int pcmcia_release_window(window_handle_t win)
48888 socket_info_t *s;
48891 if ((win == NULL) || (win->magic != WINDOW_MAGIC))
48892 return CS_BAD_HANDLE;
48893 s = win->sock;
48894 @@ -1640,11 +1647,11 @@
48896 /* Release system memory */
48897 if(!(s->cap.features & SS_CAP_STATIC_MAP))
48898 - release_mem_region(win->base, win->size);
48899 + release_mem_resource(win->base, win->size);
48900 win->handle->state &= ~CLIENT_WIN_REQ(win->index);
48902 win->magic = 0;
48905 return CS_SUCCESS;
48906 } /* release_window */
48908 @@ -1658,13 +1665,13 @@
48909 socket_info_t *s;
48910 config_t *c;
48911 pccard_io_map iomap;
48914 if (CHECK_HANDLE(handle))
48915 return CS_BAD_HANDLE;
48916 i = handle->Socket; s = socket_table[i];
48917 if (!(s->state & SOCKET_PRESENT))
48918 return CS_NO_CARD;
48921 #ifdef CONFIG_CARDBUS
48922 if (handle->state & CLIENT_CARDBUS) {
48923 if (!(req->IntType & INT_CARDBUS))
48924 @@ -1677,7 +1684,7 @@
48925 return CS_SUCCESS;
48927 #endif
48930 if (req->IntType & INT_CARDBUS)
48931 return CS_UNSUPPORTED_MODE;
48932 c = CONFIG(handle);
48933 @@ -1692,9 +1699,9 @@
48934 s->socket.Vpp = req->Vpp1;
48935 if (set_socket(s, &s->socket))
48936 return CS_BAD_VPP;
48939 c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
48942 /* Pick memory or I/O card, DMA mode, interrupt */
48943 c->IntType = req->IntType;
48944 c->Attributes = req->Attributes;
48945 @@ -1712,7 +1719,7 @@
48946 s->socket.io_irq = 0;
48947 set_socket(s, &s->socket);
48948 s->lock_count++;
48951 /* Set up CIS configuration registers */
48952 base = c->ConfigBase = req->ConfigBase;
48953 c->Present = c->CardValues = req->Present;
48954 @@ -1757,7 +1764,7 @@
48955 u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
48956 write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
48960 /* Configure I/O windows */
48961 if (c->state & CONFIG_IO_REQ) {
48962 iomap.speed = io_speed;
48963 @@ -1779,24 +1786,24 @@
48964 s->io[i].Config++;
48969 c->state |= CONFIG_LOCKED;
48970 handle->state |= CLIENT_CONFIG_LOCKED;
48971 return CS_SUCCESS;
48972 } /* request_configuration */
48974 /*======================================================================
48977 Request_io() reserves ranges of port addresses for a socket.
48978 I have not implemented range sharing or alias addressing.
48981 ======================================================================*/
48983 int pcmcia_request_io(client_handle_t handle, io_req_t *req)
48985 socket_info_t *s;
48986 config_t *c;
48989 if (CHECK_HANDLE(handle))
48990 return CS_BAD_HANDLE;
48991 s = SOCKET(handle);
48992 @@ -1855,7 +1862,7 @@
48993 hooked, we don't guarantee that an irq will still be available
48994 when the configuration is locked. Now that I think about it,
48995 there might be a way to fix this using a dummy handler.
48998 ======================================================================*/
49000 int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
49001 @@ -1863,7 +1870,7 @@
49002 socket_info_t *s;
49003 config_t *c;
49004 int ret = CS_IN_USE, irq = 0;
49007 if (CHECK_HANDLE(handle))
49008 return CS_BAD_HANDLE;
49009 s = SOCKET(handle);
49010 @@ -1875,7 +1882,7 @@
49011 if (c->state & CONFIG_IRQ_REQ)
49012 return CS_IN_USE;
49014 -#ifdef CONFIG_ISA
49015 +#ifdef CONFIG_PCMCIA_PROBE
49016 if (s->irq.AssignedIRQ != 0) {
49017 /* If the interrupt is already assigned, it must match */
49018 irq = s->irq.AssignedIRQ;
49019 @@ -1909,7 +1916,7 @@
49021 if (req->Attributes & IRQ_HANDLE_PRESENT) {
49022 if (bus_request_irq(s->cap.bus, irq, req->Handler,
49023 - ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
49024 + ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
49025 (s->functions > 1) ||
49026 (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0,
49027 handle->dev_info, req->Instance))
49028 @@ -1919,7 +1926,7 @@
49029 c->irq.Attributes = req->Attributes;
49030 s->irq.AssignedIRQ = req->AssignedIRQ = irq;
49031 s->irq.Config++;
49034 c->state |= CONFIG_IRQ_REQ;
49035 handle->state |= CLIENT_IRQ_REQ;
49036 return CS_SUCCESS;
49037 @@ -1938,7 +1945,7 @@
49038 window_t *win;
49039 u_long align;
49040 int w;
49043 if (CHECK_HANDLE(*handle))
49044 return CS_BAD_HANDLE;
49045 s = SOCKET(*handle);
49046 @@ -2005,7 +2012,7 @@
49047 /* Return window handle */
49048 req->Base = win->ctl.sys_start;
49049 *wh = win;
49052 return CS_SUCCESS;
49053 } /* request_window */
49055 @@ -2014,14 +2021,14 @@
49056 I'm not sure which "reset" function this is supposed to use,
49057 but for now, it uses the low-level interface's reset, not the
49058 CIS register.
49061 ======================================================================*/
49063 int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
49065 int i, ret;
49066 socket_info_t *s;
49069 if (CHECK_HANDLE(handle))
49070 return CS_BAD_HANDLE;
49071 i = handle->Socket; s = socket_table[i];
49072 @@ -2049,14 +2056,14 @@
49074 These shut down or wake up a socket. They are sort of user
49075 initiated versions of the APM suspend and resume actions.
49078 ======================================================================*/
49080 int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
49082 int i;
49083 socket_info_t *s;
49086 if (CHECK_HANDLE(handle))
49087 return CS_BAD_HANDLE;
49088 i = handle->Socket; s = socket_table[i];
49089 @@ -2077,7 +2084,7 @@
49091 int i;
49092 socket_info_t *s;
49095 if (CHECK_HANDLE(handle))
49096 return CS_BAD_HANDLE;
49097 i = handle->Socket; s = socket_table[i];
49098 @@ -2095,7 +2102,7 @@
49099 /*======================================================================
49101 These handle user requests to eject or insert a card.
49104 ======================================================================*/
49106 int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
49107 @@ -2103,7 +2110,7 @@
49108 int i, ret;
49109 socket_info_t *s;
49110 u_long flags;
49113 if (CHECK_HANDLE(handle))
49114 return CS_BAD_HANDLE;
49115 i = handle->Socket; s = socket_table[i];
49116 @@ -2119,9 +2126,9 @@
49117 spin_lock_irqsave(&s->lock, flags);
49118 do_shutdown(s);
49119 spin_unlock_irqrestore(&s->lock, flags);
49122 return CS_SUCCESS;
49125 } /* eject_card */
49127 int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
49128 @@ -2129,7 +2136,7 @@
49129 int i, status;
49130 socket_info_t *s;
49131 u_long flags;
49134 if (CHECK_HANDLE(handle))
49135 return CS_BAD_HANDLE;
49136 i = handle->Socket; s = socket_table[i];
49137 @@ -2157,7 +2164,7 @@
49139 Maybe this should send a CS_EVENT_CARD_INSERTION event if we
49140 haven't sent one to this client yet?
49143 ======================================================================*/
49145 int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask)
49146 @@ -2189,7 +2196,7 @@
49147 printk(KERN_NOTICE);
49148 else
49149 printk(KERN_NOTICE "%s: ", handle->dev_info);
49152 for (i = 0; i < SERVICE_COUNT; i++)
49153 if (service_table[i].key == err->func) break;
49154 if (i < SERVICE_COUNT)
49155 @@ -2347,13 +2354,13 @@
49156 default:
49157 return CS_UNSUPPORTED_FUNCTION; break;
49161 } /* CardServices */
49163 /*======================================================================
49165 OS-specific module glue goes here
49168 ======================================================================*/
49169 /* in alpha order */
49170 EXPORT_SYMBOL(pcmcia_access_configuration_register);
49171 @@ -2450,4 +2457,3 @@
49172 module_exit(exit_pcmcia_cs);
49174 /*====================================================================*/
49176 --- linux-2.4.25/drivers/pcmcia/ds.c~2.4.25-vrs2.patch 2001-11-12 18:39:01.000000000 +0100
49177 +++ linux-2.4.25/drivers/pcmcia/ds.c 2004-03-31 17:15:09.000000000 +0200
49178 @@ -55,6 +55,7 @@
49179 #include <pcmcia/bulkmem.h>
49180 #include <pcmcia/cistpl.h>
49181 #include <pcmcia/ds.h>
49182 +#include <linux/devfs_fs_kernel.h>
49184 /*====================================================================*/
49186 @@ -880,6 +881,8 @@
49187 EXPORT_SYMBOL(register_pccard_driver);
49188 EXPORT_SYMBOL(unregister_pccard_driver);
49190 +static devfs_handle_t devfs_handle;
49192 /*====================================================================*/
49194 int __init init_pcmcia_ds(void)
49195 @@ -957,8 +960,13 @@
49196 if (i == -EBUSY)
49197 printk(KERN_NOTICE "unable to find a free device # for "
49198 "Driver Services\n");
49199 - else
49200 + else {
49201 major_dev = i;
49202 + devfs_handle = devfs_register(NULL, "pcmcia", DEVFS_FL_DEFAULT,
49203 + major_dev, 0,
49204 + S_IFCHR | S_IRUSR | S_IWUSR,
49205 + &ds_fops, NULL);
49208 #ifdef CONFIG_PROC_FS
49209 if (proc_pccard)
49210 @@ -983,7 +991,9 @@
49211 remove_proc_entry("drivers", proc_pccard);
49212 #endif
49213 if (major_dev != -1)
49214 - unregister_chrdev(major_dev, "pcmcia");
49215 + devfs_unregister_chrdev(major_dev, "pcmcia");
49216 + devfs_unregister(devfs_handle);
49218 for (i = 0; i < sockets; i++)
49219 pcmcia_deregister_client(socket_table[i].handle);
49220 sockets = 0;
49221 --- linux-2.4.25/drivers/pcmcia/i82365.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
49222 +++ linux-2.4.25/drivers/pcmcia/i82365.c 2004-03-31 17:15:09.000000000 +0200
49223 @@ -28,7 +28,7 @@
49224 and other provisions required by the GPL. If you do not delete
49225 the provisions above, a recipient may use your version of this
49226 file under either the MPL or the GPL.
49229 ======================================================================*/
49231 #include <linux/module.h>
49232 @@ -65,6 +65,15 @@
49233 #include "ricoh.h"
49234 #include "o2micro.h"
49236 +#ifdef CONFIG_ARCH_EBSA110
49237 +#define I365_MASK (1 << 6)
49238 +#define SOCKIRQ2REG(sock,irq) ((irq) ? ((sock) ? 3 : 4) : 0)
49239 +#define REG2SOCKIRQ(sock,reg) (6)
49240 +#else
49241 +#define SOCKIRQ2REG(sock,irq) (irq)
49242 +#define REG2SOCKIRQ(sock,reg) (reg)
49243 +#endif
49245 #ifdef PCMCIA_DEBUG
49246 static int pc_debug = PCMCIA_DEBUG;
49247 MODULE_PARM(pc_debug, "i");
49248 @@ -173,13 +182,15 @@
49249 } socket_info_t;
49251 /* Where we keep track of our sockets... */
49252 -static int sockets = 0;
49253 -static socket_info_t socket[8] = {
49254 - { 0, }, /* ... */
49256 +static int sockets /* = 0 */;
49257 +static socket_info_t socket[8] /* = {
49258 + { 0, },
49259 +} */;
49261 /* Default ISA interrupt mask */
49262 +#ifndef I365_MASK
49263 #define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */
49264 +#endif
49266 static int grab_irq;
49267 static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
49268 @@ -303,7 +314,7 @@
49270 The VIA controllers also use these routines, as they are mostly
49271 Cirrus lookalikes, without the timing registers.
49274 ======================================================================*/
49276 #define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
49277 @@ -389,7 +400,7 @@
49278 Code to save and restore global state information for Vadem VG468
49279 and VG469 controllers, and to set and report global configuration
49280 options.
49283 ======================================================================*/
49285 static void vg46x_get_state(u_short s)
49286 @@ -411,7 +422,7 @@
49287 static u_int __init vg46x_set_opts(u_short s, char *buf)
49289 vg46x_state_t *p = &socket[s].state.vg46x;
49292 flip(p->ctl, VG468_CTL_ASYNC, async_clock);
49293 flip(p->ema, VG469_MODE_CABLE, cable_mode);
49294 if (p->ctl & VG468_CTL_ASYNC)
49295 @@ -436,7 +447,7 @@
49296 /*======================================================================
49298 Generic routines to get and set controller options
49301 ======================================================================*/
49303 static void get_bridge_state(u_short s)
49304 @@ -489,7 +500,7 @@
49305 /*======================================================================
49307 Interrupt testing code, for ISA and PCI interrupts
49310 ======================================================================*/
49312 static volatile u_int irq_hits;
49313 @@ -517,7 +528,7 @@
49316 /* Generate one interrupt */
49317 - i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
49318 + i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (SOCKIRQ2REG(sock, irq) << 4));
49319 i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
49320 udelay(1000);
49322 @@ -526,7 +537,7 @@
49323 /* mask all interrupts */
49324 i365_set(sock, I365_CSCINT, 0);
49325 DEBUG(2, " hits = %d\n", irq_hits);
49328 return (irq_hits != 1);
49331 @@ -540,7 +551,7 @@
49332 /* Don't probe level-triggered interrupts -- reserved for PCI */
49333 mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
49334 #endif
49337 if (do_scan) {
49338 set_bridge_state(sock);
49339 i365_set(sock, I365_CSCINT, 0);
49340 @@ -551,7 +562,7 @@
49341 if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
49342 mask1 ^= (1 << i);
49346 printk(KERN_INFO " ISA irqs (");
49347 if (mask1) {
49348 printk("scanned");
49349 @@ -565,12 +576,12 @@
49350 if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
49352 printk(") = ");
49355 for (i = 0; i < 16; i++)
49356 if (mask1 & (1<<i))
49357 printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
49358 if (mask1 == 0) printk("none!");
49361 return mask1;
49364 @@ -598,14 +609,14 @@
49365 /* Use the next free entry in the socket table */
49366 socket[sockets].ioaddr = port;
49367 socket[sockets].psock = sock;
49370 /* Wake up a sleepy Cirrus controller */
49371 if (wakeup) {
49372 i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
49373 /* Pause at least 50 ms */
49374 mdelay(50);
49378 if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
49379 return -1;
49380 switch (val) {
49381 @@ -618,7 +629,7 @@
49382 case 0x88: case 0x89: case 0x8a:
49383 type = IS_IBM; break;
49387 /* Check for Vadem VG-468 chips */
49388 outb(0x0e, port);
49389 outb(0x37, port);
49390 @@ -633,7 +644,7 @@
49391 val = i365_get(sockets, RF5C_CHIP_ID);
49392 if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
49393 type = IS_RF5Cx96;
49396 /* Check for Cirrus CL-PD67xx chips */
49397 i365_set(sockets, PD67_CHIP_INFO, 0);
49398 val = i365_get(sockets, PD67_CHIP_INFO);
49399 @@ -655,14 +666,14 @@
49400 bound to a (non PC Card) Linux driver. We leave these alone.
49402 We make an exception for cards that seem to be serial devices.
49405 ======================================================================*/
49407 static int __init is_alive(u_short sock)
49409 u_char stat;
49410 u_short start, stop;
49413 stat = i365_get(sock, I365_STATUS);
49414 start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
49415 stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
49416 @@ -697,7 +708,7 @@
49418 base = sockets-ns;
49419 if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
49422 if (base == 0) printk("\n");
49423 printk(KERN_INFO " %s", pcic[type].name);
49424 printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
49425 @@ -713,7 +724,7 @@
49426 mask &= I365_MASK & set_bridge_opts(base, ns);
49427 /* Scan for ISA interrupts */
49428 mask = isa_scan(base, mask);
49431 /* Poll if only two interrupts available */
49432 if (!poll_interval) {
49433 u_int tmp = (mask & 0xff20);
49434 @@ -735,15 +746,15 @@
49435 printk(" status change on irq %d\n", cs_irq);
49440 if (!isa_irq) {
49441 if (poll_interval == 0)
49442 poll_interval = HZ;
49443 printk(" polling interval = %d ms\n",
49444 poll_interval * 1000 / HZ);
49450 /* Update socket interrupt information, capabilities */
49451 for (i = 0; i < ns; i++) {
49452 t[i].cap.features |= SS_CAP_PCCARD;
49453 @@ -866,12 +877,12 @@
49454 events = pending_events[i];
49455 pending_events[i] = 0;
49456 spin_unlock_irq(&pending_event_lock);
49457 - /*
49458 - SS_DETECT events need a small delay here. The reason for this is that
49459 + /*
49460 + SS_DETECT events need a small delay here. The reason for this is that
49461 the "is there a card" electronics need time to see the card after the
49462 - "we have a card coming in" electronics have seen it.
49463 + "we have a card coming in" electronics have seen it.
49465 - if (events & SS_DETECT)
49466 + if (events & SS_DETECT)
49467 mdelay(4);
49468 if (socket[i].handler)
49469 socket[i].handler(socket[i].info, events);
49470 @@ -890,7 +901,7 @@
49471 int i, j, csc;
49472 u_int events, active;
49473 u_long flags = 0;
49476 DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
49478 for (j = 0; j < 20; j++) {
49479 @@ -906,20 +917,20 @@
49480 continue;
49482 events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
49487 /* Several sockets will send multiple "new card detected"
49488 - events in rapid succession. However, the rest of the pcmcia expects
49489 + events in rapid succession. However, the rest of the pcmcia expects
49490 only one such event. We just ignore these events by having a
49491 timeout */
49493 if (events) {
49494 - if ((jiffies - last_detect_jiffies)<(HZ/20))
49495 + if ((jiffies - last_detect_jiffies)<(HZ/20))
49496 events = 0;
49497 last_detect_jiffies = jiffies;
49503 if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
49504 events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
49505 else {
49506 @@ -980,11 +991,11 @@
49507 static int i365_get_status(u_short sock, u_int *value)
49509 u_int status;
49512 status = i365_get(sock, I365_STATUS);
49513 *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
49514 ? SS_DETECT : 0;
49517 if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
49518 *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
49519 else {
49520 @@ -1005,7 +1016,7 @@
49521 *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
49526 DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
49527 return 0;
49528 } /* i365_get_status */
49529 @@ -1016,7 +1027,7 @@
49531 socket_info_t *t = &socket[sock];
49532 u_char reg, vcc, vpp;
49535 reg = i365_get(sock, I365_POWER);
49536 state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
49537 state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
49538 @@ -1057,14 +1068,14 @@
49539 reg = i365_get(sock, I365_INTCTL);
49540 state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
49541 if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
49542 - state->io_irq = reg & I365_IRQ_MASK;
49544 + state->io_irq = REG2SOCKIRQ(sock, reg & I365_IRQ_MASK);
49546 /* speaker control */
49547 if (t->flags & IS_CIRRUS) {
49548 if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
49549 state->flags |= SS_SPKR_ENA;
49553 /* Card status change mask */
49554 reg = i365_get(sock, I365_CSCINT);
49555 state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
49556 @@ -1075,7 +1086,7 @@
49557 state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
49558 state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
49562 DEBUG(1, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
49563 "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
49564 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
49565 @@ -1088,21 +1099,21 @@
49567 socket_info_t *t = &socket[sock];
49568 u_char reg;
49571 DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
49572 "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
49573 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
49576 /* First set global controller options */
49577 set_bridge_state(sock);
49580 /* IO card, RESET flag, IO interrupt */
49581 reg = t->intr;
49582 - reg |= state->io_irq;
49583 + reg |= SOCKIRQ2REG(sock, state->io_irq);
49584 reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
49585 reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
49586 i365_set(sock, I365_INTCTL, reg);
49589 reg = I365_PWR_NORESET;
49590 if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
49591 if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
49592 @@ -1165,7 +1176,7 @@
49593 default: return -EINVAL;
49598 if (reg != i365_get(sock, I365_POWER))
49599 i365_set(sock, I365_POWER, reg);
49601 @@ -1175,9 +1186,9 @@
49602 i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
49603 state->flags & SS_SPKR_ENA);
49607 /* Card status change interrupt mask */
49608 - reg = t->cs_irq << 4;
49609 + reg = SOCKIRQ2REG(sock, t->cs_irq) << 4;
49610 if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
49611 if (state->flags & SS_IOCARD) {
49612 if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
49613 @@ -1188,7 +1199,7 @@
49615 i365_set(sock, I365_CSCINT, reg);
49616 i365_get(sock, I365_CSC);
49619 return 0;
49620 } /* i365_set_socket */
49622 @@ -1197,7 +1208,7 @@
49623 static int i365_get_io_map(u_short sock, struct pccard_io_map *io)
49625 u_char map, ioctl, addr;
49628 map = io->map;
49629 if (map > 1) return -EINVAL;
49630 io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START);
49631 @@ -1220,7 +1231,7 @@
49632 static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
49634 u_char map, ioctl;
49637 DEBUG(1, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
49638 "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
49639 io->speed, io->start, io->stop);
49640 @@ -1250,30 +1261,30 @@
49642 u_short base, i;
49643 u_char map, addr;
49646 map = mem->map;
49647 if (map > 4) return -EINVAL;
49648 addr = i365_get(sock, I365_ADDRWIN);
49649 mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
49650 base = I365_MEM(map);
49653 i = i365_get_pair(sock, base+I365_W_START);
49654 mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0;
49655 mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0;
49656 mem->sys_start = ((u_long)(i & 0x0fff) << 12);
49659 i = i365_get_pair(sock, base+I365_W_STOP);
49660 mem->speed = (i & I365_MEM_WS0) ? 1 : 0;
49661 mem->speed += (i & I365_MEM_WS1) ? 2 : 0;
49662 mem->speed = to_ns(mem->speed);
49663 mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff;
49666 i = i365_get_pair(sock, base+I365_W_OFF);
49667 mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
49668 mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0;
49669 mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
49670 mem->card_start &= 0x3ffffff;
49673 DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
49674 "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed,
49675 mem->sys_start, mem->sys_stop, mem->card_start);
49676 @@ -1281,12 +1292,12 @@
49677 } /* i365_get_mem_map */
49679 /*====================================================================*/
49682 static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
49684 u_short base, i;
49685 u_char map;
49688 DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
49689 "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
49690 mem->sys_start, mem->sys_stop, mem->card_start);
49691 @@ -1297,17 +1308,17 @@
49692 return -EINVAL;
49693 if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
49694 return -EINVAL;
49697 /* Turn off the window before changing anything */
49698 if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
49699 i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
49702 base = I365_MEM(map);
49703 i = (mem->sys_start >> 12) & 0x0fff;
49704 if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
49705 if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
49706 i365_set_pair(sock, base+I365_W_START, i);
49709 i = (mem->sys_stop >> 12) & 0x0fff;
49710 switch (to_cycles(mem->speed)) {
49711 case 0: break;
49712 @@ -1316,12 +1327,12 @@
49713 default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
49715 i365_set_pair(sock, base+I365_W_STOP, i);
49718 i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
49719 if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
49720 if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
49721 i365_set_pair(sock, base+I365_W_OFF, i);
49724 /* Turn on the window if necessary */
49725 if (mem->flags & MAP_ACTIVE)
49726 i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
49727 @@ -1332,7 +1343,7 @@
49729 Routines for accessing socket information and register dumps via
49730 /proc/bus/pccard/...
49733 ======================================================================*/
49735 #ifdef CONFIG_PROC_FS
49736 @@ -1353,7 +1364,7 @@
49737 u_short sock = (socket_info_t *)data - socket;
49738 char *p = buf;
49739 int i, top;
49742 u_long flags = 0;
49743 ISA_LOCK(sock, flags);
49744 top = 0x40;
49745 @@ -1399,7 +1410,7 @@
49747 /*====================================================================*/
49749 -/* this is horribly ugly... proper locking needs to be done here at
49750 +/* this is horribly ugly... proper locking needs to be done here at
49751 * some time... */
49752 #define LOCKED(x) do { \
49753 int retval; \
49754 @@ -1532,7 +1543,7 @@
49755 /* Set up interrupt handler(s) */
49756 if (grab_irq != 0)
49757 request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
49760 if (register_ss_entry(sockets, &pcic_operations) != 0)
49761 printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
49763 @@ -1544,9 +1555,9 @@
49764 poll_timer.expires = jiffies + poll_interval;
49765 add_timer(&poll_timer);
49769 return 0;
49772 } /* init_i82365 */
49774 static void __exit exit_i82365(void)
49775 --- linux-2.4.25/drivers/pcmcia/rsrc_mgr.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
49776 +++ linux-2.4.25/drivers/pcmcia/rsrc_mgr.c 2004-03-31 17:15:09.000000000 +0200
49777 @@ -28,7 +28,7 @@
49778 and other provisions required by the GPL. If you do not delete
49779 the provisions above, a recipient may use your version of this
49780 file under either the MPL or the GPL.
49783 ======================================================================*/
49785 #define __NO_VERSION__
49786 @@ -55,6 +55,10 @@
49787 #include <pcmcia/cistpl.h>
49788 #include "cs_internal.h"
49790 +#ifndef ISAMEM_PHYS
49791 +#define ISAMEM_PHYS 0
49792 +#endif
49794 /*====================================================================*/
49796 /* Parameters that can be set with 'insmod' */
49797 @@ -62,7 +66,7 @@
49798 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
49800 INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
49801 -#ifdef CONFIG_ISA
49802 +#ifdef CONFIG_PCMCIA_PROBE
49803 INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
49804 INT_MODULE_PARM(mem_limit, 0x10000);
49805 #endif
49806 @@ -85,7 +89,7 @@
49807 /* IO port resource database */
49808 static resource_map_t io_db = { 0, 0, &io_db };
49810 -#ifdef CONFIG_ISA
49811 +#ifdef CONFIG_PCMCIA_PROBE
49813 typedef struct irq_info_t {
49814 u_int Attributes;
49815 @@ -133,6 +137,7 @@
49816 static inline int check_mem_resource(unsigned long b, unsigned long n,
49817 struct pci_dev *dev)
49819 + b += ISAMEM_PHYS;
49820 return check_resource(resource_parent(b, n, IORESOURCE_MEM, dev), b, n);
49823 @@ -169,10 +174,15 @@
49824 static int request_mem_resource(unsigned long b, unsigned long n,
49825 char *name, struct pci_dev *dev)
49827 - struct resource *res = make_resource(b, n, IORESOURCE_MEM, name);
49828 - struct resource *pr = resource_parent(b, n, IORESOURCE_MEM, dev);
49829 + struct resource *res;
49830 + struct resource *pr;
49831 int err = -ENOMEM;
49833 + b += ISAMEM_PHYS;
49835 + res = make_resource(b, n, IORESOURCE_MEM, name);
49836 + pr = resource_parent(b, n, IORESOURCE_MEM, dev);
49838 if (res) {
49839 err = request_resource(pr, res);
49840 if (err)
49841 @@ -181,10 +191,16 @@
49842 return err;
49845 +void release_mem_resource(unsigned long b, unsigned long n)
49847 + b += ISAMEM_PHYS;
49848 + release_mem_region(b, n);
49851 /*======================================================================
49853 These manage the internal databases of available resources.
49856 ======================================================================*/
49858 static int add_interval(resource_map_t *map, u_long base, u_long num)
49859 @@ -248,25 +264,25 @@
49861 These routines examine a region of IO or memory addresses to
49862 determine what ranges might be genuinely available.
49865 ======================================================================*/
49867 -#ifdef CONFIG_ISA
49868 +#ifdef CONFIG_PCMCIA_PROBE
49869 static void do_io_probe(ioaddr_t base, ioaddr_t num)
49873 ioaddr_t i, j, bad, any;
49874 u_char *b, hole, most;
49877 printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
49878 base, base+num-1);
49881 /* First, what does a floating port look like? */
49882 b = kmalloc(256, GFP_KERNEL);
49883 if (!b) {
49884 printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
49885 return;
49886 - }
49888 memset(b, 0, 256);
49889 for (i = base, most = 0; i < base+num; i += 8) {
49890 if (check_io_resource(i, 8, NULL))
49891 @@ -308,7 +324,7 @@
49892 printk(" %#04x-%#04x", bad, i-1);
49897 printk(any ? "\n" : " clean.\n");
49899 #endif
49900 @@ -318,7 +334,7 @@
49901 The memory probe. If the memory list includes a 64K-aligned block
49902 below 1MB, we probe in 64K chunks, and as soon as we accumulate at
49903 least mem_limit free space, we quit.
49906 ======================================================================*/
49908 static int do_mem_probe(u_long base, u_long num,
49909 @@ -332,7 +348,7 @@
49910 bad = fail = 0;
49911 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
49912 for (i = j = base; i < base+num; i = j + step) {
49913 - if (!fail) {
49914 + if (!fail) {
49915 for (j = i; j < base+num; j += step)
49916 if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) &&
49917 is_valid(j))
49918 @@ -356,7 +372,7 @@
49919 return (num - bad);
49922 -#ifdef CONFIG_ISA
49923 +#ifdef CONFIG_PCMCIA_PROBE
49925 static u_long inv_probe(int (*is_valid)(u_long),
49926 int (*do_cksum)(u_long),
49927 @@ -383,7 +399,7 @@
49928 static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
49929 static int hi = 0, lo = 0;
49930 u_long b, i, ok = 0;
49933 if (!probe_mem) return;
49934 /* We do up to four passes through the list */
49935 if (!force_low) {
49936 @@ -414,14 +430,14 @@
49940 -#else /* CONFIG_ISA */
49941 +#else /* CONFIG_PCMCIA_PROBE */
49943 void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
49944 int force_low, socket_info_t *s)
49946 resource_map_t *m, *n;
49947 static int done = 0;
49950 if (!probe_mem || done++)
49951 return;
49953 @@ -432,7 +448,7 @@
49957 -#endif /* CONFIG_ISA */
49958 +#endif /* CONFIG_PCMCIA_PROBE */
49960 /*======================================================================
49962 @@ -444,7 +460,7 @@
49963 should be a power of two, greater than or equal to 'num'. A value
49964 of 0 means that all bits of *base are significant. *base should
49965 also be strictly less than 'align'.
49968 ======================================================================*/
49970 int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
49971 @@ -452,7 +468,7 @@
49973 ioaddr_t try;
49974 resource_map_t *m;
49977 for (m = io_db.next; m != &io_db; m = m->next) {
49978 try = (m->base & ~(align-1)) + *base;
49979 for (try = (try >= m->base) ? try : try+align;
49980 @@ -500,10 +516,10 @@
49981 This checks to see if an interrupt is available, with support
49982 for interrupt sharing. We don't support reserving interrupts
49983 yet. If the interrupt is available, we allocate it.
49986 ======================================================================*/
49988 -#ifdef CONFIG_ISA
49989 +#ifdef CONFIG_PCMCIA_PROBE
49991 static void fake_irq(int i, void *d, struct pt_regs *r) { }
49992 static inline int check_irq(int irq)
49993 @@ -570,7 +586,7 @@
49995 /*====================================================================*/
49997 -#ifdef CONFIG_ISA
49998 +#ifdef CONFIG_PCMCIA_PROBE
50000 void undo_irq(u_int Attributes, int irq)
50002 @@ -600,7 +616,7 @@
50004 The various adjust_* calls form the external interface to the
50005 resource database.
50008 ======================================================================*/
50010 static int adjust_memory(adjust_t *adj)
50011 @@ -632,7 +648,7 @@
50012 default:
50013 ret = CS_UNSUPPORTED_FUNCTION;
50017 return ret;
50020 @@ -641,7 +657,7 @@
50021 static int adjust_io(adjust_t *adj)
50023 int base, num;
50026 base = adj->resource.io.BasePort;
50027 num = adj->resource.io.NumPorts;
50028 if ((base < 0) || (base > 0xffff))
50029 @@ -653,7 +669,7 @@
50030 case ADD_MANAGED_RESOURCE:
50031 if (add_interval(&io_db, base, num) != 0)
50032 return CS_IN_USE;
50033 -#ifdef CONFIG_ISA
50034 +#ifdef CONFIG_PCMCIA_PROBE
50035 if (probe_io)
50036 do_io_probe(base, num);
50037 #endif
50038 @@ -673,15 +689,15 @@
50040 static int adjust_irq(adjust_t *adj)
50042 -#ifdef CONFIG_ISA
50043 +#ifdef CONFIG_PCMCIA_PROBE
50044 int irq;
50045 irq_info_t *info;
50048 irq = adj->resource.irq.IRQ;
50049 if ((irq < 0) || (irq > 15))
50050 return CS_BAD_IRQ;
50051 info = &irq_table[irq];
50054 switch (adj->Action) {
50055 case ADD_MANAGED_RESOURCE:
50056 if (info->Attributes & RES_REMOVED)
50057 @@ -716,7 +732,7 @@
50059 if (CHECK_HANDLE(handle))
50060 return CS_BAD_HANDLE;
50063 switch (adj->Resource) {
50064 case RES_MEMORY_RANGE:
50065 return adjust_memory(adj);
50066 @@ -736,7 +752,7 @@
50067 void release_resource_db(void)
50069 resource_map_t *p, *q;
50072 for (p = mem_db.next; p != &mem_db; p = q) {
50073 q = p->next;
50074 kfree(p);
50075 --- linux-2.4.25/drivers/pcmcia/sa1100.h~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50076 +++ linux-2.4.25/drivers/pcmcia/sa1100.h 2004-03-31 17:15:09.000000000 +0200
50077 @@ -204,7 +204,9 @@
50078 extern struct pcmcia_low_level flexanet_pcmcia_ops;
50079 extern struct pcmcia_low_level simpad_pcmcia_ops;
50080 extern struct pcmcia_low_level graphicsmaster_pcmcia_ops;
50081 +extern struct pcmcia_low_level adsagc_pcmcia_ops;
50082 extern struct pcmcia_low_level adsbitsy_pcmcia_ops;
50083 +extern struct pcmcia_low_level adsbitsyplus_pcmcia_ops;
50084 extern struct pcmcia_low_level stork_pcmcia_ops;
50085 extern struct pcmcia_low_level badge4_pcmcia_ops;
50087 --- linux-2.4.25/drivers/pcmcia/sa1100_adsbitsy.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50088 +++ linux-2.4.25/drivers/pcmcia/sa1100_adsbitsy.c 2004-03-31 17:15:09.000000000 +0200
50089 @@ -11,28 +11,156 @@
50091 #include <linux/kernel.h>
50092 #include <linux/sched.h>
50093 +#include <linux/ioport.h>
50095 #include <asm/hardware.h>
50096 +#include <asm/hardware/sa1111.h>
50097 +#include <asm/irq.h>
50099 #include "sa1100_generic.h"
50100 #include "sa1111_generic.h"
50102 +int adsbitsy_smc91111_present(void);
50104 +#ifndef CONFIG_SMC91111
50105 +#define adsbitsy_smc91111_present() 0
50106 +#endif
50108 +static struct irqs {
50109 + int irq;
50110 + const char *str;
50111 +} irqs[] = {
50112 + { S0_CD_VALID, "SA1111 PCMCIA card detect" },
50113 + { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
50114 + { S1_CD_VALID, "SA1111 CF card detect" },
50115 + { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
50118 static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
50120 - /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
50121 - PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
50122 + int ret=0;
50123 + int nirq = 0;
50124 + int slots = 0;
50125 + int i;
50127 - /* Disable Power 3.3V/5V for PCMCIA/CF */
50128 - PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
50129 + /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
50130 + PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
50132 - /* Why? */
50133 - MECR = 0x09430943;
50134 + /* Disable Power 3.3V/5V for PCMCIA */
50135 + PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
50137 - return sa1111_pcmcia_init(init);
50138 + if (!request_mem_region(_PCCR, 512, "PCMCIA"))
50139 + return -1;
50142 + INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
50143 + SA1111_IRQMASK_HI(S0_CD_VALID) |
50144 + SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
50146 + nirq = 2;
50147 + slots = 1;
50149 + if (!adsbitsy_smc91111_present()) {
50150 + /* If the SMC91111 is used CF cannot be used */
50151 + /* Set GPIO_A<3:2> to be outputs for CF power controller: */
50152 + PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
50154 + /* Disable Power 3.3V/5V for CF */
50155 + PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
50157 + INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
50158 + SA1111_IRQMASK_HI(S1_CD_VALID) |
50159 + SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
50161 + nirq = 4;
50162 + slots = 2;
50165 + for (i = ret = 0; i < nirq; i++) {
50166 + ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
50167 + irqs[i].str, NULL);
50168 + if (ret)
50169 + break;
50172 + if (i < nirq) {
50173 + printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
50174 + irqs[i].irq, ret);
50175 + while (i--)
50176 + free_irq(irqs[i].irq, NULL);
50178 + release_mem_region(_PCCR, 16);
50181 + return ret ? -1 : slots;
50184 -static int
50185 -adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
50186 +static int adsbitsy_pcmcia_shutdown(void)
50189 + free_irq(S0_CD_VALID, NULL);
50190 + free_irq(S0_BVD1_STSCHG, NULL);
50191 + INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
50193 + if (!adsbitsy_smc91111_present()) {
50194 + free_irq(S1_CD_VALID, NULL);
50195 + free_irq(S1_BVD1_STSCHG, NULL);
50196 + INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
50199 + return 0;
50203 +static int adsbitsy_pcmcia_socket_state(struct pcmcia_state_array *state)
50205 + unsigned long status;
50207 + if (adsbitsy_smc91111_present()) {
50208 + if(state->size<1) return -1;
50210 + else
50211 + if(state->size<2) return -1;
50213 + memset(state->state, 0,
50214 + (state->size)*sizeof(struct pcmcia_state));
50216 + status = PCSR;
50218 + state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
50219 + state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
50220 + state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
50221 + state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
50222 + state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
50223 + state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
50224 + state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
50226 + if (state->size > 1) {
50227 + if (adsbitsy_smc91111_present()) {
50228 + // If there is SMC91111 on ADS Bitsy connector board
50229 + // it returns not detect/ready/...
50230 + state->state[1].detect = 0;
50231 + state->state[1].ready = 0;
50232 + state->state[1].bvd1 = 0;
50233 + state->state[1].bvd2 = 0;
50234 + state->state[1].wrprot = 0;
50235 + state->state[1].vs_3v = 0;
50236 + state->state[1].vs_Xv = 0;
50238 + else {
50239 + state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
50240 + state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
50241 + state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
50242 + state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
50243 + state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
50244 + state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
50245 + state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
50248 + return 1;
50251 +static int adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
50253 unsigned int pa_dwr_mask, pa_dwr_set;
50254 int ret;
50255 @@ -54,10 +182,11 @@
50257 switch (conf->vcc) {
50258 default:
50259 - case 0: pa_dwr_set = 0; break;
50260 + case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
50261 case 33: pa_dwr_set = GPIO_GPIO2; break;
50262 case 50: pa_dwr_set = GPIO_GPIO3; break;
50264 + break;
50266 default:
50267 return -1;
50268 @@ -83,8 +212,8 @@
50270 struct pcmcia_low_level adsbitsy_pcmcia_ops = {
50271 init: adsbitsy_pcmcia_init,
50272 - shutdown: sa1111_pcmcia_shutdown,
50273 - socket_state: sa1111_pcmcia_socket_state,
50274 + shutdown: adsbitsy_pcmcia_shutdown,
50275 + socket_state: adsbitsy_pcmcia_socket_state,
50276 get_irq_info: sa1111_pcmcia_get_irq_info,
50277 configure_socket: adsbitsy_pcmcia_configure_socket,
50279 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
50280 +++ linux-2.4.25/drivers/pcmcia/sa1100_adsbitsyplus.c 2004-03-31 17:15:09.000000000 +0200
50281 @@ -0,0 +1,236 @@
50283 + * drivers/pcmcia/sa1100_adsbitsyplus.c
50285 + * PCMCIA implementation routines for ADS Bitsy Plus
50287 + * Created Feb 7, 2003 by Robert Whaley <rwhaley@applieddata.net>
50289 + * This file comes from sa1100_adsbitsy.c of Woojung Huh <whuh@applieddata.net>
50291 + */
50292 +#include <linux/kernel.h>
50293 +#include <linux/sched.h>
50294 +#include <linux/ioport.h>
50296 +#include <asm/hardware.h>
50297 +#include <asm/hardware/sa1111.h>
50298 +#include <asm/irq.h>
50300 +#include "sa1100_generic.h"
50301 +#include "sa1111_generic.h"
50303 +int adsbitsy_smc91111_present(void);
50305 +#ifndef CONFIG_SMC91111
50306 +#define adsbitsy_smc91111_present() 0
50307 +#endif
50309 +static struct irqs {
50310 + int irq;
50311 + const char *str;
50312 +} irqs[] = {
50313 + { S0_CD_VALID, "SA1111 PCMCIA card detect" },
50314 + { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
50315 + { S1_CD_VALID, "SA1111 CF card detect" },
50316 + { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
50319 +#define sock0_3_3_reverse_logic() ((ADS_CPLD_IO2 & ADS_IO2_CPLD_REV_MASK) >= ADS_IO2_CPLD_REV_5_MAGIC)
50321 +static int adsbitsyplus_pcmcia_init(struct pcmcia_init *init)
50323 + int ret=0;
50324 + int nirq = 0;
50325 + int slots = 0;
50326 + int i;
50328 + /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
50329 + PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
50331 + /* Disable Power 3.3V/5V for PCMCIA */
50332 + if (sock0_3_3_reverse_logic())
50333 + PA_DWR = (PA_DWR & ~GPIO_GPIO0) | GPIO_GPIO1;
50334 + else
50335 + PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
50337 + if (!request_mem_region(_PCCR, 512, "PCMCIA"))
50338 + return -1;
50341 + INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
50342 + SA1111_IRQMASK_HI(S0_CD_VALID) |
50343 + SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
50345 + nirq = 2;
50346 + slots = 1;
50348 + if (!adsbitsy_smc91111_present()) {
50349 + /* If the SMC91111 is used CF cannot be used */
50350 + /* Set GPIO_A<3:2> to be outputs for CF power controller: */
50351 + PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
50353 + /* Disable Power 3.3V/5V for CF */
50354 + PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
50356 + INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
50357 + SA1111_IRQMASK_HI(S1_CD_VALID) |
50358 + SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
50360 + nirq = 4;
50361 + slots = 2;
50364 + for (i = ret = 0; i < nirq; i++) {
50365 + ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
50366 + irqs[i].str, NULL);
50367 + if (ret)
50368 + break;
50371 + if (i < nirq) {
50372 + printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
50373 + irqs[i].irq, ret);
50374 + while (i--)
50375 + free_irq(irqs[i].irq, NULL);
50377 + release_mem_region(_PCCR, 16);
50380 + return ret ? -1 : slots;
50383 +static int adsbitsyplus_pcmcia_shutdown(void)
50386 + free_irq(S0_CD_VALID, NULL);
50387 + free_irq(S0_BVD1_STSCHG, NULL);
50388 + INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
50390 + if (!adsbitsy_smc91111_present()) {
50391 + free_irq(S1_CD_VALID, NULL);
50392 + free_irq(S1_BVD1_STSCHG, NULL);
50393 + INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
50396 + return 0;
50400 +static int adsbitsyplus_pcmcia_socket_state(struct pcmcia_state_array *state)
50402 + unsigned long status;
50404 + if (adsbitsy_smc91111_present()) {
50405 + if(state->size<1) return -1;
50407 + else
50408 + if(state->size<2) return -1;
50410 + memset(state->state, 0,
50411 + (state->size)*sizeof(struct pcmcia_state));
50413 + status = PCSR;
50415 + state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
50416 + state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
50417 + state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
50418 + state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
50419 + state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
50420 + state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
50421 + state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
50423 + if (state->size > 1) {
50424 + if (adsbitsy_smc91111_present()) {
50425 + // If there is SMC91111 on ADS Bitsy connector board
50426 + // it returns not detect/ready/...
50427 + state->state[1].detect = 0;
50428 + state->state[1].ready = 0;
50429 + state->state[1].bvd1 = 0;
50430 + state->state[1].bvd2 = 0;
50431 + state->state[1].wrprot = 0;
50432 + state->state[1].vs_3v = 0;
50433 + state->state[1].vs_Xv = 0;
50435 + else {
50436 + state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
50437 + state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
50438 + state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
50439 + state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
50440 + state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
50441 + state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
50442 + state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
50445 + return 1;
50448 +static int adsbitsyplus_pcmcia_configure_socket(const struct pcmcia_configure *conf)
50450 + unsigned int pa_dwr_mask, pa_dwr_set;
50451 + int ret;
50453 + switch (conf->sock) {
50454 + case 0:
50455 + pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
50457 + if (sock0_3_3_reverse_logic()) {
50458 + switch (conf->vcc) {
50459 + default:
50460 + case 0: pa_dwr_set = GPIO_GPIO1; break;
50461 + case 33: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
50462 + case 50: pa_dwr_set = 0; break;
50464 + } else {
50465 + switch (conf->vcc) {
50466 + default:
50467 + case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
50468 + case 33: pa_dwr_set = GPIO_GPIO1; break;
50469 + case 50: pa_dwr_set = GPIO_GPIO0; break;
50472 + break;
50474 + case 1:
50475 + pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
50477 + switch (conf->vcc) {
50478 + default:
50479 + case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
50480 + case 33: pa_dwr_set = GPIO_GPIO2; break;
50481 + case 50: pa_dwr_set = GPIO_GPIO3; break;
50483 + break;
50485 + default:
50486 + return -1;
50489 + if (conf->vpp != conf->vcc && conf->vpp != 0) {
50490 + printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
50491 + __FUNCTION__, conf->vpp);
50492 + return -1;
50495 + ret = sa1111_pcmcia_configure_socket(conf);
50496 + if (ret == 0) {
50497 + unsigned long flags;
50499 + local_irq_save(flags);
50500 + PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
50501 + local_irq_restore(flags);
50504 + return ret;
50507 +struct pcmcia_low_level adsbitsyplus_pcmcia_ops = {
50508 + init: adsbitsyplus_pcmcia_init,
50509 + shutdown: adsbitsyplus_pcmcia_shutdown,
50510 + socket_state: adsbitsyplus_pcmcia_socket_state,
50511 + get_irq_info: sa1111_pcmcia_get_irq_info,
50512 + configure_socket: adsbitsyplus_pcmcia_configure_socket,
50514 + socket_init: sa1111_pcmcia_socket_init,
50515 + socket_suspend: sa1111_pcmcia_socket_suspend,
50518 --- linux-2.4.25/drivers/pcmcia/sa1100_freebird.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50519 +++ linux-2.4.25/drivers/pcmcia/sa1100_freebird.c 2004-03-31 17:15:09.000000000 +0200
50520 @@ -67,9 +67,6 @@
50522 if(state_array->size<2) return -1;
50524 - memset(state_array->state, 0,
50525 - (state_array->size)*sizeof(struct pcmcia_state));
50527 levels = LINKUP_PRS;
50528 //printk("LINKUP_PRS=%x \n",levels);
50530 --- linux-2.4.25/drivers/pcmcia/sa1100_generic.c~2.4.25-vrs2.patch 2003-06-13 16:51:35.000000000 +0200
50531 +++ linux-2.4.25/drivers/pcmcia/sa1100_generic.c 2004-03-31 17:15:09.000000000 +0200
50532 @@ -992,10 +992,18 @@
50533 if(machine_is_graphicsmaster())
50534 pcmcia_low_level = &graphicsmaster_pcmcia_ops;
50535 #endif
50536 +#ifdef CONFIG_SA1100_ADSAGC
50537 + if(machine_is_adsagc())
50538 + pcmcia_low_level = &graphicsmaster_pcmcia_ops;
50539 +#endif
50540 #ifdef CONFIG_SA1100_ADSBITSY
50541 if(machine_is_adsbitsy())
50542 pcmcia_low_level = &adsbitsy_pcmcia_ops;
50543 #endif
50544 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
50545 + if(machine_is_adsbitsyplus())
50546 + pcmcia_low_level = &adsbitsyplus_pcmcia_ops;
50547 +#endif
50548 #ifdef CONFIG_SA1100_STORK
50549 if(machine_is_stork())
50550 pcmcia_low_level = &stork_pcmcia_ops;
50551 @@ -1067,7 +1075,7 @@
50552 * We initialize the MECR to default values here, because we are
50553 * not guaranteed to see a SetIOMap operation at runtime.
50555 - mecr = 0;
50556 + mecr = MECR;
50558 clock = cpufreq_get(0);
50560 --- linux-2.4.25/drivers/pcmcia/sa1100_graphicsclient.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50561 +++ linux-2.4.25/drivers/pcmcia/sa1100_graphicsclient.c 2004-03-31 17:15:09.000000000 +0200
50562 @@ -3,6 +3,8 @@
50564 * PCMCIA implementation routines for Graphics Client Plus
50566 + * Nov/14/01 Woojung
50567 + * Set MECR at initializing time
50568 * 9/12/01 Woojung
50569 * Turn power OFF at startup
50570 * 1/31/2001 Woojung Huh
50571 @@ -19,11 +21,6 @@
50572 #include <asm/irq.h>
50573 #include "sa1100_generic.h"
50575 -#error This is broken!
50577 -#define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
50578 -#define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
50580 static volatile unsigned long *PCMCIA_Status =
50581 ((volatile unsigned long *) ADS_p2v(_ADS_CS_STATUS));
50583 @@ -46,20 +43,23 @@
50584 *PCMCIA_Power &= ~0x03;
50586 /* Register interrupts */
50587 - irq = S0_CD_IRQ;
50588 + irq = IRQ_GRAPHICSCLIENT_S0_CD;
50589 res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
50590 if (res < 0) {
50591 - printk(KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq);
50592 + printk(KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__, irq);
50593 return -1;
50596 + // Nov/14/01 WH
50597 + MECR = 0x00000943;
50599 return 1; // 1 PCMCIA Slot
50602 static int gcplus_pcmcia_shutdown(void)
50604 /* disable IRQs */
50605 - free_irq( S0_CD_IRQ, NULL);
50606 + free_irq( IRQ_GRAPHICSCLIENT_S0_CD, NULL);
50608 /* Shutdown PCMCIA power */
50609 mdelay(2); // 2msec
50610 @@ -74,9 +74,6 @@
50612 if(state_array->size<1) return -1;
50614 - memset(state_array->state, 0,
50615 - (state_array->size)*sizeof(struct pcmcia_state));
50617 levels=*PCMCIA_Status;
50619 state_array->state[0].detect=(levels & ADS_CS_ST_A_CD)?1:0;
50620 @@ -96,7 +93,7 @@
50621 return -1;
50623 if (info->sock == 0)
50624 - info->irq = S0_STS_IRQ;
50625 + info->irq = IRQ_GRAPHICSCLIENT_S0_STS;
50627 return 0;
50629 @@ -143,6 +140,11 @@
50631 restore_flags(flags);
50633 + if (configure->irq)
50634 + enable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
50635 + else
50636 + disable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
50638 return 0;
50641 --- linux-2.4.25/drivers/pcmcia/sa1100_graphicsmaster.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50642 +++ linux-2.4.25/drivers/pcmcia/sa1100_graphicsmaster.c 2004-03-31 17:15:09.000000000 +0200
50643 @@ -12,13 +12,13 @@
50644 #include <linux/sched.h>
50646 #include <asm/hardware.h>
50647 +#include <asm/hardware/sa1111.h>
50649 #include "sa1100_generic.h"
50650 #include "sa1111_generic.h"
50652 static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
50654 - int return_val=0;
50656 /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
50657 PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
50658 @@ -26,9 +26,6 @@
50659 /* Disable Power 3.3V/5V for PCMCIA/CF */
50660 PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
50662 - /* why? */
50663 - MECR = 0x09430943;
50665 return sa1111_pcmcia_init(init);
50668 @@ -59,6 +56,10 @@
50669 case 33: pa_dwr_set = GPIO_GPIO3; break;
50670 case 50: pa_dwr_set = GPIO_GPIO2; break;
50672 + break;
50674 + default:
50675 + return -1;
50678 if (conf->vpp != conf->vcc && conf->vpp != 0) {
50679 --- linux-2.4.25/drivers/pcmcia/sa1100_h3600.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50680 +++ linux-2.4.25/drivers/pcmcia/sa1100_h3600.c 2004-03-31 17:15:09.000000000 +0200
50681 @@ -29,6 +29,9 @@
50682 set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_IRQ0 | GPIO_H3600_PCMCIA_IRQ1,
50683 GPIO_FALLING_EDGE);
50685 + set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1,
50686 + GPIO_NO_EDGES);
50689 * Register interrupts
50691 --- linux-2.4.25/drivers/pcmcia/sa1100_jornada720.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50692 +++ linux-2.4.25/drivers/pcmcia/sa1100_jornada720.c 2004-03-31 17:15:09.000000000 +0200
50693 @@ -8,6 +8,7 @@
50694 #include <linux/sched.h>
50696 #include <asm/hardware.h>
50697 +#include <asm/hardware/sa1111.h>
50699 #include "sa1100_generic.h"
50700 #include "sa1111_generic.h"
50701 @@ -88,7 +89,7 @@
50703 local_irq_save(flags);
50704 PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
50705 - locla_irq_restore(flags);
50706 + local_irq_restore(flags);
50709 return ret;
50710 --- linux-2.4.25/drivers/pcmcia/sa1100_pangolin.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50711 +++ linux-2.4.25/drivers/pcmcia/sa1100_pangolin.c 2004-03-31 17:15:09.000000000 +0200
50712 @@ -53,9 +53,6 @@
50714 if(state_array->size<2) return -1;
50716 - memset(state_array->state, 0,
50717 - (state_array->size)*sizeof(struct pcmcia_state));
50719 levels=GPLR;
50720 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
50721 state_array->state[1].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
50722 --- linux-2.4.25/drivers/pcmcia/sa1100_shannon.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50723 +++ linux-2.4.25/drivers/pcmcia/sa1100_shannon.c 2004-03-31 17:15:09.000000000 +0200
50724 @@ -53,9 +53,6 @@
50726 unsigned long levels;
50728 - memset(state_array->state, 0,
50729 - state_array->size * sizeof(struct pcmcia_state));
50731 levels = GPLR;
50733 state_array->state[0].detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
50734 --- linux-2.4.25/drivers/pcmcia/sa1100_simpad.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50735 +++ linux-2.4.25/drivers/pcmcia/sa1100_simpad.c 2004-03-31 17:15:09.000000000 +0200
50736 @@ -63,9 +63,6 @@
50738 if(state_array->size<2) return -1;
50740 - memset(state_array->state, 0,
50741 - (state_array->size)*sizeof(struct pcmcia_state));
50743 levels=GPLR;
50745 state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
50746 --- linux-2.4.25/drivers/pcmcia/sa1100_stork.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
50747 +++ linux-2.4.25/drivers/pcmcia/sa1100_stork.c 2004-03-31 17:15:09.000000000 +0200
50748 @@ -79,9 +79,6 @@
50750 if(state_array->size<2) return -1;
50752 - memset(state_array->state, 0,
50753 - (state_array->size)*sizeof(struct pcmcia_state));
50755 levels=GPLR;
50757 if (debug > 1)
50758 --- linux-2.4.25/drivers/pcmcia/sa1100_yopy.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
50759 +++ linux-2.4.25/drivers/pcmcia/sa1100_yopy.c 2004-03-31 17:15:09.000000000 +0200
50760 @@ -73,9 +73,6 @@
50761 if (state_array->size != 1)
50762 return -1;
50764 - memset(state_array->state, 0,
50765 - state_array->size * sizeof(struct pcmcia_state));
50767 levels = GPLR;
50769 state_array->state[0].detect = (levels & GPIO_CF_CD) ? 0 : 1;
50770 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
50771 +++ linux-2.4.25/drivers/pld/Makefile 2004-03-31 17:15:09.000000000 +0200
50772 @@ -0,0 +1,28 @@
50774 +# Makefile for the kernel pld device drivers.
50776 +# Note! Dependencies are done automagically by 'make dep', which also
50777 +# removes any old dependencies. DON'T put your own dependencies here
50778 +# unless it's something special (ie not a .c file).
50780 +# Note 2! The CFLAGS definitions are now inherited from the
50781 +# parent makes..
50783 +# $Id: $
50786 +O_TARGET := pld.o
50788 +export-objs := pld_hotswap.o
50789 +obj-y :=
50790 +obj-m :=
50791 +obj-n :=
50792 +obj- :=
50794 +obj-$(CONFIG_PLD) += pld_epxa.o
50795 +obj-$(CONFIG_PLD_HOTSWAP) += pld_hotswap.o
50797 +include $(TOPDIR)/Rules.make
50799 +fastdep:
50801 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
50802 +++ linux-2.4.25/drivers/pld/pld_epxa.c 2004-03-31 17:15:09.000000000 +0200
50803 @@ -0,0 +1,375 @@
50806 + * drivers/char/epxapld.c
50808 + * Copyright (C) 2001 Altera Corporation
50810 + * This program is free software; you can redistribute it and/or modify
50811 + * it under the terms of the GNU General Public License as published by
50812 + * the Free Software Foundation; either version 2 of the License, or
50813 + * (at your option) any later version.
50815 + * This program is distributed in the hope that it will be useful,
50816 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
50817 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50818 + * GNU General Public License for more details.
50820 + * You should have received a copy of the GNU General Public License
50821 + * along with this program; if not, write to the Free Software
50822 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
50823 + */
50825 +#include <linux/config.h>
50826 +#include <linux/errno.h>
50827 +#include <linux/fs.h>
50828 +#include <linux/slab.h>
50829 +#include <linux/ioport.h>
50830 +#include <linux/init.h>
50831 +#include <linux/errno.h>
50832 +#include <linux/module.h>
50833 +#include <asm/io.h>
50834 +#include <asm/uaccess.h>
50835 +#include <asm/arch/excalibur.h>
50836 +#include <asm/arch/hardware.h>
50837 +#define PLD_CONF00_TYPE (volatile unsigned int *)
50838 +#define MODE_CTRL00_TYPE (volatile unsigned int *)
50839 +//#define DEBUG(x) x
50840 +#define DEBUG(x)
50842 +#include <asm/arch/mode_ctrl00.h>
50843 +#include <asm/arch/pld_conf00.h>
50844 +#ifdef CONFIG_PLD_HOTSWAP
50845 +#include <linux/pld/pld_hotswap.h>
50846 +#endif
50847 +#include <linux/pld/pld_epxa.h>
50850 + * Macros
50851 + */
50854 +#define PLD_BASE (IO_ADDRESS(EXC_PLD_CONFIG00_BASE))
50855 +#define CLOCK_DIV_RATIO ((1 + EXC_AHB2_CLK_FREQUENCY/32000000) & CONFIG_CONTROL_CLOCK_RATIO_MSK)
50857 + * STRUCTURES
50858 + */
50861 +struct pld_sbihdr{
50862 + unsigned int fpos;
50863 + unsigned int temp;
50866 +static DECLARE_MUTEX(pld_sem);
50869 +static void lock_pld (void)
50871 + /* Lock the pld i/f */
50872 + unsigned int tmp;
50874 + tmp = readl(CONFIG_CONTROL(PLD_BASE));
50875 + tmp |= CONFIG_CONTROL_LK_MSK;
50877 + writel(tmp,CONFIG_CONTROL(PLD_BASE));
50880 +static void unlock_excalibur_pld (void)
50882 + /* Unlock the pld i/f */
50884 + if (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK ){
50885 + writel(CONFIG_UNLOCK_MAGIC, CONFIG_UNLOCK(PLD_BASE));
50886 + while (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK);
50891 +static int place_pld_into_configure_mode (void)
50893 + unsigned int tmp;
50896 + if( readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK ){
50897 + /*
50898 + * Already being configured!!!
50899 + */
50900 + printk(KERN_WARNING "pld0: Device already being configured!\n");
50901 + return -EBUSY;
50904 + /* Set up the config clock */
50906 + writel(CLOCK_DIV_RATIO,CONFIG_CONTROL_CLOCK(PLD_BASE));
50907 + while(readl(CONFIG_CONTROL_CLOCK(PLD_BASE))
50908 + !=CLOCK_DIV_RATIO);
50909 + /* Tell the device we wish to configure it */
50910 + tmp = readl(CONFIG_CONTROL(PLD_BASE));
50911 + tmp |= CONFIG_CONTROL_CO_MSK;
50912 + writel(tmp,CONFIG_CONTROL(PLD_BASE));
50915 + /*
50916 + * Wait for the busy bit to clear then check for errors.
50917 + */
50919 + while((tmp=readl(CONFIG_CONTROL(PLD_BASE))&CONFIG_CONTROL_B_MSK ));
50921 + if ( tmp & CONFIG_CONTROL_E_MSK ){
50922 + if ( tmp & CONFIG_CONTROL_ES_0_MSK ){
50923 + /* Already being programmed via JTAG */
50924 + printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
50925 + return -EBUSY;
50928 + if ( tmp & CONFIG_CONTROL_ES_1_MSK ){
50929 + /* No config clock configured */
50930 + printk(KERN_ERR "pld0:No config clock!\n");
50931 + BUG();
50932 + return -EBUSY;
50934 + if ( tmp & CONFIG_CONTROL_ES_2_MSK ){
50935 + /* Already being programmed via External device */
50936 + printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
50937 + return -EBUSY;
50941 + return 0;
50945 +static int write_pld_data_word(unsigned int config_data)
50947 + unsigned int tmp;
50949 + do{
50950 + tmp = readl(CONFIG_CONTROL(PLD_BASE));
50952 + while ( ( tmp & CONFIG_CONTROL_B_MSK ) &&
50953 + !( tmp & CONFIG_CONTROL_E_MSK ));
50955 + if ( tmp & CONFIG_CONTROL_E_MSK ){
50956 + printk("pld0: Error writing pld data, CONFIG_CONTROL=%#x\n",tmp);
50958 + return -EILSEQ;
50961 + writel(config_data,CONFIG_CONTROL_DATA(PLD_BASE));
50962 + return 0;
50967 +static int wait_for_device_to_configure (void)
50969 + int i=0x10000;
50971 + while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
50973 + /*
50974 + * Wait for the config bit (CO) to go low, indicating that everything
50975 + * is Ok. If it doesn't, assume that is screwed up somehow and
50976 + * clear the CO bit to abort the configuration.
50977 + */
50979 + while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
50981 + while (i&&(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK)){
50982 + i--;
50985 + if (!i){
50986 + writel(0,CONFIG_CONTROL(PLD_BASE));
50987 + printk(KERN_WARNING "pld0: Invalid PLD config data\n");
50988 + return -EILSEQ;
50991 + return 0;
50996 +static int pld_open(struct inode* inode, struct file *filep)
50999 + struct pld_sbihdr* sbihdr;
51001 + /* Check the device minor number */
51002 + if(minor(inode->i_rdev)){
51003 + DEBUG(printk("pld0: minor=%d",minor(inode->i_rdev));)
51004 + return -ENODEV;
51007 + /* Create our private data and link it to the file structure */
51008 + sbihdr=kmalloc(sizeof(struct pld_sbihdr),GFP_KERNEL);
51010 + if(!sbihdr)
51011 + return -ENOMEM;
51013 + filep->private_data=sbihdr;
51015 + sbihdr->fpos=0;
51016 + sbihdr->temp=0;
51017 + return 0;
51020 +static int pld_release(struct inode* inode, struct file *filep){
51021 + int ret_code;
51023 + kfree(filep->private_data);
51024 + ret_code=wait_for_device_to_configure();
51025 + lock_pld();
51026 + return ret_code;
51029 +static ssize_t pld_write(struct file* filep, const char* data, size_t count, loff_t* ppos){
51031 + struct pld_sbihdr* sbihdr=filep->private_data;
51032 + int bytes_left=count;
51033 + int result;
51034 + DEBUG(int i=0);
51037 + /* Can't seek (pwrite) on pld. */
51038 + if (ppos != &filep->f_pos)
51039 + return -ESPIPE;
51042 + /* Check access to the whole are in one go */
51043 + if(!access_ok(VERIFY_READ,(const void*)data, count)){
51044 + return -EFAULT;
51047 + /*
51048 + * We now lock against writes.
51049 + */
51050 + if (down_interruptible(&pld_sem))
51051 + return -ERESTARTSYS;
51053 + if(!sbihdr->fpos){
51054 + /*
51055 + * unlock the pld and place in configure mode
51056 + */
51057 + unlock_excalibur_pld();
51058 + result=place_pld_into_configure_mode();
51059 + if(result)
51060 + return result;
51062 + DEBUG(printk("data= %#x count=%#x 0ffset=%#x\n",*data, count, *ppos));
51064 + while(bytes_left){
51065 + char tmp;
51066 + __get_user(tmp,data);
51067 + /* read our header ! */
51068 + sbihdr->temp|=tmp << (8*(sbihdr->fpos&3));
51069 + if((sbihdr->fpos&3)==3){
51070 + if(write_pld_data_word(sbihdr->temp))
51072 + DEBUG(printk("pos=%d\n",sbihdr->fpos);)
51073 + return -EILSEQ;
51075 + DEBUG(if(i<10){)
51076 + DEBUG(printk("fpos2 :%#x data=%#x\n",sbihdr->fpos,sbihdr->temp));
51077 + DEBUG(i++);
51078 + DEBUG(});
51079 + sbihdr->temp=0;
51080 + DEBUG(words_written++);
51082 + sbihdr->fpos++;
51083 + data++;
51084 + bytes_left--;
51087 + up(&pld_sem);
51088 + return (count);
51091 +int pld_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
51094 + switch(cmd){
51096 +#ifdef CONFIG_PLD_HOTSWAP
51097 + case PLD_IOC_ADD_PLD_DEV:
51099 + struct pldhs_dev_desc desc;
51100 + struct pldhs_dev_info info;
51101 + char *name;
51102 + void *data;
51103 + int result=0;
51105 + result=copy_from_user(&desc,(const void*)arg,sizeof(struct pldhs_dev_desc));
51106 + if(result)
51107 + return -EFAULT;
51108 + result=copy_from_user(&info,(const void*)desc.info,sizeof(struct pldhs_dev_info));
51109 + if(result)
51110 + return -EFAULT;
51111 + name=kmalloc(info.nsize,GFP_KERNEL);
51112 + if(!name)
51113 + return -ENOMEM;
51115 + result=copy_from_user(name,(const void*)desc.name,info.nsize);
51116 + if(result){
51117 + result=-EFAULT;
51118 + goto ioctl_out;
51121 + data=kmalloc(info.pssize,GFP_KERNEL);
51122 + if(!data){
51123 + result=-ENOMEM;
51124 + goto ioctl_out;
51127 + result=copy_from_user(data,(const void*)desc.data,info.pssize);
51128 + if(result){
51129 + result=-EFAULT;
51130 + goto ioctl_out1;
51132 + result=pldhs_add_device(&info,name,data);
51134 + ioctl_out1:
51135 + kfree(data);
51136 + ioctl_out:
51137 + kfree(name);
51138 + return result;
51142 + case PLD_IOC_REMOVE_PLD_DEVS:
51143 + pldhs_remove_devices();
51144 + return 0;
51146 + case PLD_IOC_SET_INT_MODE:
51147 + if(cmd==3){
51148 + printk(KERN_INFO "Interrupt mode set to 3 (Six individual interrupts)\n");
51149 + return 0;
51150 + }else{
51151 + printk(KERN_INFO "There is no interrupt handler available for this mode (%d). You will need to add one\n to implement whatever scheme you require\n");
51152 + return -EACCES;
51154 +#endif
51155 + default:
51156 + return -ENOTTY;
51161 +static struct file_operations pld_fops={
51162 + write: pld_write,
51163 + ioctl: pld_ioctl,
51164 + open: pld_open,
51165 + release: pld_release
51168 +static int __init pld_init(void){
51169 + int major;
51170 + major=register_chrdev(0,"pld",&pld_fops);
51171 + printk(KERN_INFO "Using PLD major num=%d\n",major);
51172 + if (major<0){
51173 + return major;
51175 + return 0;
51178 +__initcall(pld_init);
51179 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
51180 +++ linux-2.4.25/drivers/pld/pld_hotswap.c 2004-03-31 17:15:09.000000000 +0200
51181 @@ -0,0 +1,188 @@
51183 + * linux/drivers/pld/pld_hotswap.c
51185 + * Pld driver for Altera EPXA Excalibur devices
51188 + * Copyright 2001 Altera Corporation (cdavies@altera.com)
51190 + * This program is free software; you can redistribute it and/or modify
51191 + * it under the terms of the GNU General Public License as published by
51192 + * the Free Software Foundation; either version 2 of the License, or
51193 + * (at your option) any later version.
51195 + * This program is distributed in the hope that it will be useful,
51196 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
51197 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51198 + * GNU General Public License for more details.
51200 + * You should have received a copy of the GNU General Public License
51201 + * along with this program; if not, write to the Free Software
51202 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51204 + * $Id: $
51206 + */
51209 + * pld_hotswap ops contains the basic operation required for adding
51210 + * and removing devices from the system.
51211 + */
51213 +#include <linux/config.h>
51214 +#include <linux/module.h>
51215 +#include <linux/kernel.h>
51216 +#include <linux/types.h>
51217 +#include <linux/pagemap.h>
51218 +#include <linux/slab.h>
51219 +#include <linux/smp_lock.h>
51220 +#include <linux/init.h>
51221 +#include <linux/kmod.h>
51222 +#include <linux/proc_fs.h>
51223 +#include <linux/list.h>
51224 +#include <asm/uaccess.h>
51225 +#include <linux/pld/pld_hotswap.h>
51228 +static struct pld_hotswap_ops pldhs_driver_list={
51229 + list: LIST_HEAD_INIT(pldhs_driver_list.list),
51230 + name: "",
51233 +static spinlock_t list_lock=SPIN_LOCK_UNLOCKED;
51237 +static struct pld_hotswap_ops * pldhs_find_driver(char* name)
51239 + struct pld_hotswap_ops * ptr;
51240 + struct list_head *list_pos;
51242 + spin_lock(&list_lock);
51243 + list_for_each(list_pos,&pldhs_driver_list.list){
51244 + ptr=(struct pld_hotswap_ops *)list_pos;
51245 + if(!strcmp(name, ptr->name)){
51246 + spin_unlock(&list_lock);
51247 + return ptr;
51251 + spin_unlock(&list_lock);
51252 + return 0;
51257 +int pldhs_register_driver(struct pld_hotswap_ops *drv)
51260 + /* Check that the device is not already on the list
51261 + * if so, do nothing */
51262 + if(pldhs_find_driver(drv->name)){
51263 + return 0;
51266 + printk(KERN_INFO "PLD: Registering hotswap driver %s\n",drv->name);
51267 + /* Add this at the start of the list */
51268 + spin_lock(&list_lock);
51269 + list_add((struct list_head*)drv,&pldhs_driver_list.list);
51270 + spin_unlock(&list_lock);
51272 + return 0;
51275 +int pldhs_unregister_driver(char *name)
51277 + struct pld_hotswap_ops *ptr;
51279 + ptr=pldhs_find_driver(name);
51280 + if(!ptr){
51281 + return -ENODEV;
51284 + printk(KERN_INFO "PLD: Unregistering hotswap driver%s\n",name);
51285 + spin_lock(&list_lock);
51286 + list_del((struct list_head*)ptr);
51287 + spin_unlock(&list_lock);
51289 + return 0;
51292 +int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data)
51294 + struct pld_hotswap_ops * ptr;
51296 + ptr=pldhs_find_driver(drv_name);
51298 + if(!ptr){
51299 + /* try requesting this module*/
51300 + request_module(drv_name);
51301 + /* is the driver there now? */
51302 + ptr=pldhs_find_driver(drv_name);
51303 + if(!ptr){
51304 + printk("pld hotswap: Failed to load a driver for %s\n",drv_name);
51305 + return -ENODEV;
51309 + if(!ptr->add_device){
51310 + printk(KERN_WARNING "pldhs: no add_device() function for driver %s\n",drv_name);
51311 + return 0;
51314 + return ptr->add_device(dev_info,dev_ps_data);
51317 +int pldhs_remove_devices(void)
51319 + struct list_head *list_pos;
51320 + struct pld_hotswap_ops * ptr;
51323 + spin_lock(&list_lock);
51324 + list_for_each(list_pos,&pldhs_driver_list.list){
51325 + ptr=(struct pld_hotswap_ops *)list_pos;
51326 + if(ptr->remove_devices)
51327 + ptr->remove_devices();
51330 + spin_unlock(&list_lock);
51332 + return 0;
51335 +#ifdef CONFIG_PROC_FS
51336 +int pldhs_read_proc(char* buf,char** start,off_t offset,int count,int *eof,void *data){
51339 + struct list_head *list_pos;
51340 + struct pld_hotswap_ops * ptr;
51341 + int i,len=0;
51343 + *start=buf;
51344 + spin_lock(&list_lock);
51345 + list_for_each(list_pos,&pldhs_driver_list.list){
51346 + ptr=(struct pld_hotswap_ops *)list_pos;
51347 + if(ptr->proc_read){
51348 + i=ptr->proc_read(buf,start,offset,count,eof,data);
51349 + count-=i;
51350 + len+=i;
51351 + *start+=i;
51354 + spin_unlock(&list_lock);
51356 + *start=NULL;
51357 + *eof=1;
51358 + return len;
51361 +void __init pldhs_init(void){
51362 + create_proc_read_entry("pld",0,NULL,pldhs_read_proc,NULL);
51365 +__initcall(pldhs_init);
51366 +#endif
51368 +EXPORT_SYMBOL(pldhs_register_driver);
51369 +EXPORT_SYMBOL(pldhs_unregister_driver);
51370 --- linux-2.4.25/drivers/scsi/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
51371 +++ linux-2.4.25/drivers/scsi/Makefile 2004-03-31 17:15:09.000000000 +0200
51372 @@ -21,7 +21,7 @@
51374 O_TARGET := scsidrv.o
51376 -export-objs := scsi_syms.o 53c700.o
51377 +export-objs := scsi_syms.o 53c700.o scsi_error.o
51378 mod-subdirs := pcmcia ../acorn/scsi
51381 --- linux-2.4.25/drivers/scsi/scsi.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
51382 +++ linux-2.4.25/drivers/scsi/scsi.c 2004-03-31 17:15:09.000000000 +0200
51383 @@ -1334,14 +1334,10 @@
51385 int scsi_retry_command(Scsi_Cmnd * SCpnt)
51387 - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
51388 - sizeof(SCpnt->data_cmnd));
51389 - SCpnt->request_buffer = SCpnt->buffer;
51390 - SCpnt->request_bufflen = SCpnt->bufflen;
51391 - SCpnt->use_sg = SCpnt->old_use_sg;
51392 - SCpnt->cmd_len = SCpnt->old_cmd_len;
51393 - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
51394 - SCpnt->underflow = SCpnt->old_underflow;
51395 + /*
51396 + * Restore the SCSI command state.
51397 + */
51398 + scsi_setup_cmd_retry(SCpnt);
51401 * Zero the sense information from the last time we tried
51402 --- linux-2.4.25/drivers/scsi/scsi.h~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
51403 +++ linux-2.4.25/drivers/scsi/scsi.h 2004-03-31 17:15:09.000000000 +0200
51404 @@ -465,6 +465,7 @@
51405 int sectors);
51406 extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
51407 extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt);
51408 +extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt);
51409 extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int);
51410 extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
51411 int block_sectors);
51412 @@ -588,6 +589,7 @@
51413 unsigned changed:1; /* Data invalid due to media change */
51414 unsigned busy:1; /* Used to prevent races */
51415 unsigned lockable:1; /* Able to prevent media removal */
51416 + unsigned locked:1; /* Media removal disabled */
51417 unsigned borken:1; /* Tell the Seagate driver to be
51418 * painfully slow on this device */
51419 unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */
51420 --- linux-2.4.25/drivers/scsi/scsi_dma.c~2.4.25-vrs2.patch 2002-02-25 20:38:04.000000000 +0100
51421 +++ linux-2.4.25/drivers/scsi/scsi_dma.c 2004-03-31 17:15:09.000000000 +0200
51422 @@ -30,6 +30,15 @@
51423 typedef unsigned char FreeSectorBitmap;
51424 #elif SECTORS_PER_PAGE <= 32
51425 typedef unsigned int FreeSectorBitmap;
51426 +#elif SECTORS_PER_PAGE <= 64
51427 +#if 0
51428 +typedef unsigned long long FreeSectorBitmap;
51429 +#else
51430 +typedef struct {
51431 + unsigned long l,h;
51432 +} FreeSectorBitmap;
51433 +#define LARGE_MALLOC
51434 +#endif
51435 #else
51436 #error You lose.
51437 #endif
51438 @@ -69,6 +78,7 @@
51439 * to allocate more memory in order to be able to write the
51440 * data to disk, you would wedge the system.
51442 +#ifndef LARGE_MALLOC
51443 void *scsi_malloc(unsigned int len)
51445 unsigned int nbits, mask;
51446 @@ -167,6 +177,97 @@
51447 panic("scsi_free:Bad offset");
51450 +#else
51452 +void *scsi_malloc(unsigned int len)
51454 + unsigned int nbits;
51455 + unsigned long maskl, maskh, flags;
51456 + FreeSectorBitmap *fsb;
51457 + int i;
51459 + if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
51460 + return NULL;
51462 + save_flags_cli (flags);
51463 + nbits = len >> 9;
51464 + if (nbits < 32) {
51465 + maskl = (1 << nbits) - 1;
51466 + maskh = 0;
51467 + } else {
51468 + maskl = (unsigned long)-1;
51469 + maskh = (1 << (nbits - 32)) - 1;
51472 + fsb = dma_malloc_freelist;
51474 + for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) {
51475 + unsigned long mml, mmh;
51476 + int j;
51477 + mml = maskl;
51478 + mmh = maskh;
51479 + j = 0;
51480 + do {
51481 + if ((fsb->l & mml) == 0 && (fsb->h & mmh) == 0) {
51482 + fsb->h |= mmh;
51483 + fsb->l |= mml;
51484 + restore_flags (flags);
51485 + scsi_dma_free_sectors -= nbits;
51486 +#ifdef DEBUG
51487 + printk("SMalloc: %d %p\n",len, dma_malloc_pages[i] + (j << 9));
51488 +#endif
51489 + return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
51491 + mmh = (mmh << 1) | (mml >> 31);
51492 + mml <<= 1;
51493 + j++;
51494 + } while (!(mmh & (1 << 31)));
51495 + fsb ++;
51497 + return NULL; /* Nope. No more */
51500 +int scsi_free(void *obj, unsigned int len)
51502 + unsigned int page, sector, nbits;
51503 + unsigned long maskl, maskh, flags;
51505 +#ifdef DEBUG
51506 + printk("scsi_free %p %d\n",obj, len);
51507 +#endif
51509 + for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
51510 + unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
51511 + if ((unsigned long) obj >= page_addr &&
51512 + (unsigned long) obj < page_addr + PAGE_SIZE) {
51513 + sector = (((unsigned long) obj) - page_addr) >> 9;
51514 + nbits = len >> 9;
51515 + if (nbits < 32) {
51516 + maskl = (1 << nbits) - 1;
51517 + maskh = 0;
51518 + } else {
51519 + maskl = (unsigned long)-1;
51520 + maskh = (1 << (nbits - 32)) - 1;
51522 + if ((sector + nbits) > SECTORS_PER_PAGE)
51523 + panic ("scsi_free:Bad memory alignment");
51524 + maskh = (maskh << sector) | (maskl >> (32 - sector));
51525 + maskl = maskl << sector;
51526 + save_flags_cli(flags);
51527 + if (((dma_malloc_freelist[page].l & maskl) != maskl) ||
51528 + ((dma_malloc_freelist[page].h & maskh) != maskh))
51529 + panic("scsi_free:Trying to free unused memory");
51530 + scsi_dma_free_sectors += nbits;
51531 + dma_malloc_freelist[page].l &= ~maskl;
51532 + dma_malloc_freelist[page].h &= ~maskh;
51533 + restore_flags(flags);
51534 + return 0;
51537 + panic("scsi_free:Bad offset");
51539 +#endif
51543 * Function: scsi_resize_dma_pool
51544 --- linux-2.4.25/drivers/scsi/scsi_error.c~2.4.25-vrs2.patch 2002-11-29 00:53:14.000000000 +0100
51545 +++ linux-2.4.25/drivers/scsi/scsi_error.c 2004-03-31 17:15:09.000000000 +0200
51546 @@ -35,6 +35,8 @@
51547 #include "hosts.h"
51548 #include "constants.h"
51550 +#include <scsi/scsi_ioctl.h> /* grr */
51553 * We must always allow SHUTDOWN_SIGS. Even if we are not a module,
51554 * the host drivers that we are using may be loaded as modules, and
51555 @@ -49,6 +51,13 @@
51557 #define SHUTDOWN_SIGS (sigmask(SIGHUP))
51560 + * The number of times we retry a REQUEST SENSE and TEST UNIT READY
51561 + * respectively. This is arbitary.
51562 + */
51563 +#define SENSE_RETRIES 5
51564 +#define TUR_RETRIES 5
51566 #ifdef DEBUG
51567 #define SENSE_TIMEOUT SCSI_TIMEOUT
51568 #define ABORT_TIMEOUT SCSI_TIMEOUT
51569 @@ -385,16 +394,12 @@
51571 STATIC int scsi_eh_retry_command(Scsi_Cmnd * SCpnt)
51573 - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
51574 - sizeof(SCpnt->data_cmnd));
51575 - SCpnt->request_buffer = SCpnt->buffer;
51576 - SCpnt->request_bufflen = SCpnt->bufflen;
51577 - SCpnt->use_sg = SCpnt->old_use_sg;
51578 - SCpnt->cmd_len = SCpnt->old_cmd_len;
51579 - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
51580 - SCpnt->underflow = SCpnt->old_underflow;
51581 + int tries = 0;
51583 - scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
51584 + do {
51585 + scsi_setup_cmd_retry(SCpnt);
51586 + scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
51587 + } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SCpnt->allowed);
51590 * Hey, we are done. Let's look to see what happened.
51591 @@ -421,16 +426,10 @@
51592 static unsigned char generic_sense[6] =
51593 {REQUEST_SENSE, 0, 0, 0, 255, 0};
51594 unsigned char scsi_result0[256], *scsi_result = NULL;
51595 - int saved_result;
51596 + int saved_result, tries;
51598 ASSERT_LOCK(&io_request_lock, 0);
51600 - memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
51601 - sizeof(generic_sense));
51603 - if (SCpnt->device->scsi_level <= SCSI_2)
51604 - SCpnt->cmnd[1] = SCpnt->lun << 5;
51606 scsi_result = (!SCpnt->host->hostt->unchecked_isa_dma)
51607 ? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA);
51609 @@ -438,24 +437,41 @@
51610 printk("cannot allocate scsi_result in scsi_request_sense.\n");
51611 return FAILED;
51613 - /*
51614 - * Zero the sense buffer. Some host adapters automatically always request
51615 - * sense, so it is not a good idea that SCpnt->request_buffer and
51616 - * SCpnt->sense_buffer point to the same address (DB).
51617 - * 0 is not a valid sense code.
51618 - */
51619 - memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
51620 - memset((void *) scsi_result, 0, 256);
51622 saved_result = SCpnt->result;
51623 - SCpnt->request_buffer = scsi_result;
51624 - SCpnt->request_bufflen = 256;
51625 - SCpnt->use_sg = 0;
51626 - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
51627 - SCpnt->sc_data_direction = SCSI_DATA_READ;
51628 - SCpnt->underflow = 0;
51630 - scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
51631 + tries = 0;
51632 + do {
51633 + memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
51634 + sizeof(generic_sense));
51636 + if (SCpnt->device->scsi_level <= SCSI_2)
51637 + SCpnt->cmnd[1] = SCpnt->lun << 5;
51639 + /*
51640 + * Zero the sense buffer. Some host adapters automatically
51641 + * always request sense, so it is not a good idea that
51642 + * SCpnt->request_buffer and SCpnt->sense_buffer point to
51643 + * the same address (DB). 0 is not a valid sense code.
51644 + */
51645 + memset((void *) SCpnt->sense_buffer, 0,
51646 + sizeof(SCpnt->sense_buffer));
51647 + memset((void *) scsi_result, 0, 256);
51649 + SCpnt->request_buffer = scsi_result;
51650 + SCpnt->request_bufflen = 256;
51651 + SCpnt->use_sg = 0;
51652 + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
51653 + SCpnt->sc_data_direction = SCSI_DATA_READ;
51654 + SCpnt->underflow = 0;
51656 + scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
51657 + /*
51658 + * If the SCSI device responded with "logical unit
51659 + * is in process of becoming ready", we need to
51660 + * retry this command.
51661 + */
51662 + } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SENSE_RETRIES);
51664 /* Last chance to have valid sense data */
51665 if (!scsi_sense_valid(SCpnt))
51666 @@ -470,15 +486,8 @@
51667 * When we eventually call scsi_finish, we really wish to complete
51668 * the original request, so let's restore the original data. (DB)
51670 - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
51671 - sizeof(SCpnt->data_cmnd));
51672 SCpnt->result = saved_result;
51673 - SCpnt->request_buffer = SCpnt->buffer;
51674 - SCpnt->request_bufflen = SCpnt->bufflen;
51675 - SCpnt->use_sg = SCpnt->old_use_sg;
51676 - SCpnt->cmd_len = SCpnt->old_cmd_len;
51677 - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
51678 - SCpnt->underflow = SCpnt->old_underflow;
51679 + scsi_setup_cmd_retry(SCpnt);
51682 * Hey, we are done. Let's look to see what happened.
51683 @@ -496,40 +505,42 @@
51685 static unsigned char tur_command[6] =
51686 {TEST_UNIT_READY, 0, 0, 0, 0, 0};
51687 + int tries = 0;
51689 - memcpy((void *) SCpnt->cmnd, (void *) tur_command,
51690 - sizeof(tur_command));
51691 + do {
51692 + memcpy((void *) SCpnt->cmnd, (void *) tur_command,
51693 + sizeof(tur_command));
51695 - if (SCpnt->device->scsi_level <= SCSI_2)
51696 - SCpnt->cmnd[1] = SCpnt->lun << 5;
51697 + if (SCpnt->device->scsi_level <= SCSI_2)
51698 + SCpnt->cmnd[1] = SCpnt->lun << 5;
51700 - /*
51701 - * Zero the sense buffer. The SCSI spec mandates that any
51702 - * untransferred sense data should be interpreted as being zero.
51703 - */
51704 - memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
51705 + /*
51706 + * Zero the sense buffer. The SCSI spec mandates that any
51707 + * untransferred sense data should be interpreted as being zero.
51708 + */
51709 + memset((void *) SCpnt->sense_buffer, 0,
51710 + sizeof(SCpnt->sense_buffer));
51712 - SCpnt->request_buffer = NULL;
51713 - SCpnt->request_bufflen = 0;
51714 - SCpnt->use_sg = 0;
51715 - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
51716 - SCpnt->underflow = 0;
51717 - SCpnt->sc_data_direction = SCSI_DATA_NONE;
51718 + SCpnt->request_buffer = NULL;
51719 + SCpnt->request_bufflen = 0;
51720 + SCpnt->use_sg = 0;
51721 + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
51722 + SCpnt->underflow = 0;
51723 + SCpnt->sc_data_direction = SCSI_DATA_NONE;
51725 - scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
51726 + scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
51727 + /*
51728 + * If the SCSI device responded with "logical unit
51729 + * is in process of becoming ready", we need to
51730 + * retry this command.
51731 + */
51732 + } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < TUR_RETRIES);
51735 * When we eventually call scsi_finish, we really wish to complete
51736 * the original request, so let's restore the original data. (DB)
51738 - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
51739 - sizeof(SCpnt->data_cmnd));
51740 - SCpnt->request_buffer = SCpnt->buffer;
51741 - SCpnt->request_bufflen = SCpnt->bufflen;
51742 - SCpnt->use_sg = SCpnt->old_use_sg;
51743 - SCpnt->cmd_len = SCpnt->old_cmd_len;
51744 - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
51745 - SCpnt->underflow = SCpnt->old_underflow;
51746 + scsi_setup_cmd_retry(SCpnt);
51749 * Hey, we are done. Let's look to see what happened.
51750 @@ -589,7 +600,6 @@
51752 host = SCpnt->host;
51754 - retry:
51756 * We will use a queued command if possible, otherwise we will emulate the
51757 * queuing and calling of completion function ourselves.
51758 @@ -672,14 +682,13 @@
51759 SCSI_LOG_ERROR_RECOVERY(3,
51760 printk("scsi_send_eh_cmnd: scsi_eh_completed_normally %x\n", ret));
51761 switch (ret) {
51762 - case SUCCESS:
51763 - SCpnt->eh_state = SUCCESS;
51764 - break;
51765 - case NEEDS_RETRY:
51766 - goto retry;
51767 - case FAILED:
51768 default:
51769 - SCpnt->eh_state = FAILED;
51770 + ret = FAILED;
51771 + /*FALLTHROUGH*/
51772 + case FAILED:
51773 + case NEEDS_RETRY:
51774 + case SUCCESS:
51775 + SCpnt->eh_state = ret;
51776 break;
51778 } else {
51779 @@ -1220,6 +1229,82 @@
51783 + * Function: scsi_eh_lock_done
51785 + * Purpose: free the command and request structures associated
51786 + * with the error handlers door lock request
51788 + * Arguments: SCpnt - the SCSI command block for the door lock request.
51790 + * Returns: Nothing
51792 + * Notes: We completed the asynchronous door lock request, and
51793 + * it has either locked the door or failed. We must free
51794 + * the command structures associated with this request.
51795 + */
51796 +static void scsi_eh_lock_done(struct scsi_cmnd *SCpnt)
51798 + struct scsi_request *SRpnt = SCpnt->sc_request;
51800 + SCpnt->sc_request = NULL;
51801 + SRpnt->sr_command = NULL;
51803 + scsi_release_command(SCpnt);
51804 + scsi_release_request(SRpnt);
51809 + * Function: scsi_eh_lock_door
51811 + * Purpose: Prevent medium removal for the specified device
51813 + * Arguments: dev - SCSI device to prevent medium removal
51815 + * Locking: We must be called from process context;
51816 + * scsi_allocate_request() may sleep.
51818 + * Returns: Nothing
51820 + * Notes: We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request
51821 + * on the head of the devices request queue, and continue.
51823 + * Bugs: scsi_allocate_request() may sleep waiting for existing
51824 + * requests to be processed. However, since we haven't
51825 + * kicked off any request processing for this host, this
51826 + * may deadlock.
51828 + * If scsi_allocate_request() fails for what ever reason,
51829 + * we completely forget to lock the door.
51830 + */
51831 +STATIC void scsi_eh_lock_door(struct scsi_device *dev)
51833 + struct scsi_request *SRpnt = scsi_allocate_request(dev);
51835 + if (SRpnt == NULL) {
51836 + /* what now? */
51837 + return;
51840 + SRpnt->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
51841 + SRpnt->sr_cmnd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
51842 + SRpnt->sr_cmnd[2] = 0;
51843 + SRpnt->sr_cmnd[3] = 0;
51844 + SRpnt->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
51845 + SRpnt->sr_cmnd[5] = 0;
51846 + SRpnt->sr_data_direction = SCSI_DATA_NONE;
51847 + SRpnt->sr_bufflen = 0;
51848 + SRpnt->sr_buffer = NULL;
51849 + SRpnt->sr_allowed = 5;
51850 + SRpnt->sr_done = scsi_eh_lock_done;
51851 + SRpnt->sr_timeout_per_command = 10 * HZ;
51852 + SRpnt->sr_cmd_len = COMMAND_SIZE(SRpnt->sr_cmnd[0]);
51854 + scsi_insert_special_req(SRpnt, 1);
51859 * Function: scsi_restart_operations
51861 * Purpose: Restart IO operations to the specified host.
51862 @@ -1241,6 +1326,15 @@
51863 ASSERT_LOCK(&io_request_lock, 0);
51866 + * If the door was locked, we need to insert a door lock request
51867 + * onto the head of the SCSI request queue for the device. There
51868 + * is no point trying to lock the door of an off-line device.
51869 + */
51870 + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
51871 + if (SDpnt->online && SDpnt->locked)
51872 + scsi_eh_lock_door(SDpnt);
51874 + /*
51875 * Next free up anything directly waiting upon the host. This will be
51876 * requests for character device operations, and also for ioctls to queued
51877 * block devices.
51878 @@ -1260,8 +1354,7 @@
51879 request_queue_t *q;
51880 if ((host->can_queue > 0 && (host->host_busy >= host->can_queue))
51881 || (host->host_blocked)
51882 - || (host->host_self_blocked)
51883 - || (SDpnt->device_blocked)) {
51884 + || (host->host_self_blocked)) {
51885 break;
51887 q = &SDpnt->request_queue;
51888 @@ -1271,136 +1364,202 @@
51892 - * Function: scsi_unjam_host
51893 + * Function: scsi_eh_find_failed_command
51895 - * Purpose: Attempt to fix a host which has a command that failed for
51896 - * some reason.
51897 + * Purpose: Find a failed Scsi_Cmnd structure on a device.
51899 - * Arguments: host - host that needs unjamming.
51900 - *
51901 - * Returns: Nothing
51902 + * Arguments: SDpnt - Scsi_Device structure
51904 - * Notes: When we come in here, we *know* that all commands on the
51905 - * bus have either completed, failed or timed out. We also
51906 - * know that no further commands are being sent to the host,
51907 - * so things are relatively quiet and we have freedom to
51908 - * fiddle with things as we wish.
51909 + * Returns: Pointer to Scsi_Cmnd structure, or NULL on failure
51910 + */
51911 +STATIC Scsi_Cmnd *scsi_eh_find_failed_command(Scsi_Device *SDpnt)
51913 + Scsi_Cmnd *SCpnt;
51915 + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
51916 + if (SCpnt->state == SCSI_STATE_FAILED ||
51917 + SCpnt->state == SCSI_STATE_TIMEOUT)
51918 + return SCpnt;
51920 + return NULL;
51925 + * Function: scsi_eh_test_and_retry
51927 - * Additional note: This is only the *default* implementation. It is possible
51928 - * for individual drivers to supply their own version of this
51929 - * function, and if the maintainer wishes to do this, it is
51930 - * strongly suggested that this function be taken as a template
51931 - * and modified. This function was designed to correctly handle
51932 - * problems for about 95% of the different cases out there, and
51933 - * it should always provide at least a reasonable amount of error
51934 - * recovery.
51935 + * Purpose: Try to retry a failed command.
51937 - * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
51938 - * have scsi_finish_command() called for it. We do all of
51939 - * the retry stuff here, so when we restart the host after we
51940 - * return it should have an empty queue.
51941 + * Arguments: SCpnt - scsi command structure
51942 + * done - list of commands that have been successfully
51943 + * completed.
51945 + * Returns: SUCCESS or FAILED
51947 + * Note: If the TEST UNIT READY command successfully executes,
51948 + * but returns some form of "device not ready", we wait
51949 + * a while, and retry 3 times. The device could be still
51950 + * re-initialising.
51952 -STATIC int scsi_unjam_host(struct Scsi_Host *host)
51953 +STATIC int scsi_eh_test_and_retry(Scsi_Cmnd *SCpnt, Scsi_Cmnd **done)
51955 - int devices_failed;
51956 - int numfailed;
51957 - int ourrtn;
51958 - int rtn = FALSE;
51959 - int result;
51960 - Scsi_Cmnd *SCloop;
51961 - Scsi_Cmnd *SCpnt;
51962 - Scsi_Device *SDpnt;
51963 - Scsi_Device *SDloop;
51964 - Scsi_Cmnd *SCdone;
51965 - int timed_out;
51966 + int rtn, tries = 3;
51968 - ASSERT_LOCK(&io_request_lock, 0);
51969 + do {
51970 + rtn = scsi_test_unit_ready(SCpnt);
51971 + if (rtn != SUCCESS)
51972 + return rtn;
51974 - SCdone = NULL;
51975 + if (scsi_unit_is_ready(SCpnt))
51976 + break;
51978 + if (tries-- == 0)
51979 + return FAILED;
51981 + scsi_sleep(5 * HZ);
51982 + } while (1);
51984 + rtn = scsi_eh_retry_command(SCpnt);
51985 + if (rtn == SUCCESS) {
51986 + SCpnt->host->host_failed--;
51987 + scsi_eh_finish_command(done, SCpnt);
51990 + return rtn;
51993 - /*
51994 - * First, protect against any sort of race condition. If any of the outstanding
51995 - * commands are in states that indicate that we are not yet blocked (i.e. we are
51996 - * not in a quiet state) then we got woken up in error. If we ever end up here,
51997 - * we need to re-examine some of the assumptions.
51998 - */
51999 - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52000 - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
52001 - if (SCpnt->state == SCSI_STATE_FAILED
52002 - || SCpnt->state == SCSI_STATE_TIMEOUT
52003 - || SCpnt->state == SCSI_STATE_INITIALIZING
52004 - || SCpnt->state == SCSI_STATE_UNUSED) {
52005 - continue;
52007 - /*
52008 - * Rats. Something is still floating around out there. This could
52009 - * be the result of the fact that the upper level drivers are still frobbing
52010 - * commands that might have succeeded. There are two outcomes. One is that
52011 - * the command block will eventually be freed, and the other one is that
52012 - * the command will be queued and will be finished along the way.
52013 - */
52014 - SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
52017 - * panic("SCSI Error handler woken too early\n");
52018 + * Function: scsi_eh_restart_device
52020 - * This is no longer a problem, since now the code cares only about
52021 - * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
52022 - * Other states are useful only to release active commands when devices are
52023 - * set offline. If (host->host_active == host->host_busy) we can safely assume
52024 - * that there are no commands in state other then TIMEOUT od FAILED. (DB)
52025 + * Purpose: Retry all failed or timed out commands for a device
52027 - * FIXME:
52028 - * It is not easy to release correctly commands according to their state when
52029 - * devices are set offline, when the state is neither TIMEOUT nor FAILED.
52030 - * When a device is set offline, we can have some command with
52031 - * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
52032 - * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
52033 - * (DB, 17 May 1998)
52034 + * Arguments: SDpnt - SCSI device to retry
52035 + * done - list of commands that have been successfully
52036 + * completed.
52038 + * Returns: SUCCESS or failure code
52040 +STATIC int scsi_eh_restart_device(Scsi_Device *SDpnt, Scsi_Cmnd **done)
52042 + Scsi_Cmnd *SCpnt, *SCnext;
52043 + int rtn = SUCCESS;
52045 + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
52046 + SCnext = SCpnt->next;
52048 + if (SCpnt->state == SCSI_STATE_FAILED ||
52049 + SCpnt->state == SCSI_STATE_TIMEOUT) {
52050 + rtn = scsi_eh_test_and_retry(SCpnt, done);
52051 + if (rtn != SUCCESS)
52052 + break;
52056 + return rtn;
52060 + * Function: scsi_eh_set_device_offline
52062 + * Purpose: set a device off line
52064 + * Arguments: SDpnt - SCSI device to take off line
52065 + * done - list of commands that have been successfully
52066 + * completed.
52067 + * reason - text string describing why the device is off-line
52069 + * Returns: Nothing
52071 + * Notes: In addition, we complete each failed or timed out command
52072 + * attached to this device.
52073 + */
52074 +STATIC void scsi_eh_set_device_offline(Scsi_Device *SDpnt, Scsi_Cmnd **done,
52075 + const char *reason)
52077 + Scsi_Cmnd *SCpnt, *SCnext;
52079 + printk(KERN_ERR "scsi: device set offline - %s: "
52080 + "host %d channel %d id %d lun %d\n",
52081 + reason, SDpnt->host->host_no, SDpnt->channel,
52082 + SDpnt->id, SDpnt->lun);
52084 + SDpnt->online = FALSE;
52086 + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
52087 + SCnext = SCpnt->next;
52089 + switch (SCpnt->state) {
52090 + case SCSI_STATE_TIMEOUT:
52091 + SCpnt->result |= DRIVER_TIMEOUT;
52092 + /*FALLTHROUGH*/
52094 + case SCSI_STATE_FAILED:
52095 + SCSI_LOG_ERROR_RECOVERY(3,
52096 + printk("Finishing command for device %d %x\n",
52097 + SDpnt->id, SCpnt->result));
52099 + SDpnt->host->host_failed--;
52100 + scsi_eh_finish_command(done, SCpnt);
52101 + break;
52103 + default:
52104 + break;
52109 +static void scsi_unjam_request_sense(struct Scsi_Host *host, Scsi_Cmnd **done)
52111 + int rtn;
52112 + int result;
52113 + Scsi_Cmnd *SCpnt;
52114 + Scsi_Device *SDpnt;
52117 * Next, see if we need to request sense information. if so,
52118 * then get it now, so we have a better idea of what to do.
52119 - * FIXME(eric) this has the unfortunate side effect that if a host
52120 - * adapter does not automatically request sense information, that we end
52121 - * up shutting it down before we request it. All hosts should be doing this
52122 - * anyways, so for now all I have to say is tough noogies if you end up in here.
52123 - * On second thought, this is probably a good idea. We *really* want to give
52124 - * authors an incentive to automatically request this.
52125 + * FIXME(eric) this has the unfortunate side effect that if a
52126 + * host adapter does not automatically request sense information,
52127 + * that we end up shutting it down before we request it. All
52128 + * hosts should be doing this anyways, so for now all I have
52129 + * to say is tough noogies if you end up in here. On second
52130 + * thought, this is probably a good idea. We *really* want
52131 + * to give authors an incentive to automatically request this.
52133 - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
52134 + SCSI_LOG_ERROR_RECOVERY(3,
52135 + printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
52137 for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52138 for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
52139 - if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt)) {
52140 + if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt))
52141 continue;
52143 - SCSI_LOG_ERROR_RECOVERY(2, printk("scsi_unjam_host: Requesting sense for %d\n",
52144 - SCpnt->target));
52146 + SCSI_LOG_ERROR_RECOVERY(2,
52147 + printk("scsi_unjam_host: Requesting sense for %d\n",
52148 + SCpnt->target));
52149 rtn = scsi_request_sense(SCpnt);
52150 - if (rtn != SUCCESS) {
52151 + if (rtn != SUCCESS)
52152 continue;
52154 - SCSI_LOG_ERROR_RECOVERY(3, printk("Sense requested for %p - result %x\n",
52155 - SCpnt, SCpnt->result));
52157 + SCSI_LOG_ERROR_RECOVERY(3,
52158 + printk("Sense requested for %p - result %x\n",
52159 + SCpnt, SCpnt->result));
52160 SCSI_LOG_ERROR_RECOVERY(3, print_sense("bh", SCpnt));
52162 result = scsi_decide_disposition(SCpnt);
52165 - * If the result was normal, then just pass it along to the
52166 - * upper level.
52167 + * If the result was normal, then just pass
52168 + * it along to the upper level.
52170 if (result == SUCCESS) {
52171 SCpnt->host->host_failed--;
52172 - scsi_eh_finish_command(&SCdone, SCpnt);
52173 + scsi_eh_finish_command(done, SCpnt);
52175 - if (result != NEEDS_RETRY) {
52176 + if (result != NEEDS_RETRY)
52177 continue;
52181 * We only come in here if we want to retry a
52182 * command. The test to see whether the command
52183 @@ -1410,20 +1569,29 @@
52185 SCpnt->state = NEEDS_RETRY;
52186 rtn = scsi_eh_retry_command(SCpnt);
52187 - if (rtn != SUCCESS) {
52188 + if (rtn != SUCCESS)
52189 continue;
52193 * We eventually hand this one back to the top level.
52195 SCpnt->host->host_failed--;
52196 - scsi_eh_finish_command(&SCdone, SCpnt);
52197 + scsi_eh_finish_command(done, SCpnt);
52202 +static void scsi_unjam_count(struct Scsi_Host *host, Scsi_Cmnd **done)
52204 + Scsi_Device *SDpnt;
52205 + Scsi_Cmnd *SCpnt;
52206 + int devices_failed;
52207 + int numfailed;
52208 + int timed_out;
52211 - * Go through the list of commands and figure out where we stand and how bad things
52212 - * really are.
52213 + * Go through the list of commands and figure out where we
52214 + * stand and how bad things really are.
52216 numfailed = 0;
52217 timed_out = 0;
52218 @@ -1433,359 +1601,478 @@
52220 for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
52221 if (SCpnt->state == SCSI_STATE_FAILED) {
52222 - SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d failed\n",
52223 - SCpnt->target));
52224 + SCSI_LOG_ERROR_RECOVERY(5,
52225 + printk("Command to ID %d failed\n",
52226 + SCpnt->target));
52227 numfailed++;
52228 device_error++;
52230 if (SCpnt->state == SCSI_STATE_TIMEOUT) {
52231 - SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d timedout\n",
52232 - SCpnt->target));
52233 + SCSI_LOG_ERROR_RECOVERY(5,
52234 + printk("Command to ID %d timedout\n",
52235 + SCpnt->target));
52236 timed_out++;
52237 device_error++;
52240 - if (device_error > 0) {
52241 + if (device_error > 0)
52242 devices_failed++;
52246 - SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d+%d commands on %d devices require eh work\n",
52247 - numfailed, timed_out, devices_failed));
52248 + SCSI_LOG_ERROR_RECOVERY(2,
52249 + printk("Total of %d+%d commands on %d devices require eh work\n",
52250 + numfailed, timed_out, devices_failed));
52253 +static void scsi_unjam_abort(struct Scsi_Host *host, Scsi_Cmnd **done)
52255 + Scsi_Device *SDpnt;
52256 + Scsi_Cmnd *SCpnt;
52257 + int rtn;
52259 - if (host->host_failed == 0) {
52260 - ourrtn = TRUE;
52261 - goto leave;
52264 - * Next, try and see whether or not it makes sense to try and abort
52265 - * the running command. This only works out to be the case if we have
52266 - * one command that has timed out. If the command simply failed, it
52267 - * makes no sense to try and abort the command, since as far as the
52268 - * host adapter is concerned, it isn't running.
52269 + * Next, try and see whether or not it makes sense to try and
52270 + * abort the running command. This only works out to be the
52271 + * case if we have one command that has timed out. If the
52272 + * command simply failed, it makes no sense to try and abort
52273 + * the command, since as far as the host adapter is concerned,
52274 + * it isn't running.
52277 - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
52278 + SCSI_LOG_ERROR_RECOVERY(3,
52279 + printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
52281 for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52282 - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
52283 - if (SCloop->state != SCSI_STATE_TIMEOUT) {
52284 + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
52285 + if (SCpnt->state != SCSI_STATE_TIMEOUT)
52286 continue;
52288 - rtn = scsi_try_to_abort_command(SCloop, ABORT_TIMEOUT);
52289 - if (rtn == SUCCESS) {
52290 - rtn = scsi_test_unit_ready(SCloop);
52292 - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
52293 - rtn = scsi_eh_retry_command(SCloop);
52295 - if (rtn == SUCCESS) {
52296 - SCloop->host->host_failed--;
52297 - scsi_eh_finish_command(&SCdone, SCloop);
52301 + rtn = scsi_try_to_abort_command(SCpnt, ABORT_TIMEOUT);
52302 + if (rtn == SUCCESS)
52303 + scsi_eh_test_and_retry(SCpnt, done);
52308 +static void scsi_unjam_device_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
52310 + Scsi_Device *SDpnt;
52311 + Scsi_Cmnd *SCpnt;
52312 + int rtn;
52314 - /*
52315 - * If we have corrected all of the problems, then we are done.
52316 - */
52317 - if (host->host_failed == 0) {
52318 - ourrtn = TRUE;
52319 - goto leave;
52322 * Either the abort wasn't appropriate, or it didn't succeed.
52323 - * Now try a bus device reset. Still, look to see whether we have
52324 - * multiple devices that are jammed or not - if we have multiple devices,
52325 - * it makes no sense to try BUS_DEVICE_RESET - we really would need
52326 - * to try a BUS_RESET instead.
52327 + * Now try a bus device reset. Still, look to see whether we
52328 + * have multiple devices that are jammed or not - if we have
52329 + * multiple devices, it makes no sense to try BUS_DEVICE_RESET
52330 + * - we really would need to try a BUS_RESET instead.
52332 - * Does this make sense - should we try BDR on each device individually?
52333 - * Yes, definitely.
52334 + * Does this make sense - should we try BDR on each device
52335 + * individually? Yes, definitely.
52337 - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
52338 + SCSI_LOG_ERROR_RECOVERY(3,
52339 + printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
52341 for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52342 - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
52343 - if (SCloop->state == SCSI_STATE_FAILED
52344 - || SCloop->state == SCSI_STATE_TIMEOUT) {
52345 - break;
52349 - if (SCloop == NULL) {
52350 + SCpnt = scsi_eh_find_failed_command(SDpnt);
52351 + if (SCpnt == NULL)
52352 continue;
52356 - * OK, we have a device that is having problems. Try and send
52357 - * a bus device reset to it.
52359 - * FIXME(eric) - make sure we handle the case where multiple
52360 - * commands to the same device have failed. They all must
52361 - * get properly restarted.
52362 + * OK, we have a device that is having problems.
52363 + * Try and send a bus device reset to it.
52365 - rtn = scsi_try_bus_device_reset(SCloop, RESET_TIMEOUT);
52366 + rtn = scsi_try_bus_device_reset(SCpnt, RESET_TIMEOUT);
52368 - if (rtn == SUCCESS) {
52369 - rtn = scsi_test_unit_ready(SCloop);
52370 + /*
52371 + * A successful bus device reset causes all commands
52372 + * currently executing on the device to terminate.
52373 + * We expect the HBA driver to "forget" all commands
52374 + * associated with this device.
52376 + * Retry each failed or timed out command currently
52377 + * outstanding for this device.
52379 + * If any command fails, bail out. We will try a
52380 + * bus reset instead.
52381 + */
52382 + if (rtn == SUCCESS)
52383 + scsi_eh_restart_device(SDpnt, done);
52387 - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
52388 - rtn = scsi_eh_retry_command(SCloop);
52389 +static void scsi_unjam_bus_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
52391 + Scsi_Device *SDpnt;
52392 + Scsi_Cmnd *SCpnt;
52393 + int rtn, channel, max_channel = 0;
52395 - if (rtn == SUCCESS) {
52396 - SCloop->host->host_failed--;
52397 - scsi_eh_finish_command(&SCdone, SCloop);
52402 + /*
52403 + * If we ended up here, we have serious problems. The only thing
52404 + * left to try is a full bus reset. If someone has grabbed the
52405 + * bus and isn't letting go, then perhaps this will help.
52406 + */
52407 + SCSI_LOG_ERROR_RECOVERY(3,
52408 + printk("scsi_unjam_host: Try hard bus reset\n"));
52410 - if (host->host_failed == 0) {
52411 - ourrtn = TRUE;
52412 - goto leave;
52415 - * If we ended up here, we have serious problems. The only thing left
52416 - * to try is a full bus reset. If someone has grabbed the bus and isn't
52417 - * letting go, then perhaps this will help.
52418 + * Find the maximum channel number for this host.
52420 - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard bus reset\n"));
52421 + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
52422 + if (SDpnt->channel > max_channel)
52423 + max_channel = SDpnt->channel;
52425 - /*
52426 - * We really want to loop over the various channels, and do this on
52427 - * a channel by channel basis. We should also check to see if any
52428 - * of the failed commands are on soft_reset devices, and if so, skip
52429 - * the reset.
52430 + /*
52431 + * Loop over each channel, and see if it any device on
52432 + * each channel has failed.
52434 - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52435 - next_device:
52436 - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
52437 - if (SCpnt->state != SCSI_STATE_FAILED
52438 - && SCpnt->state != SCSI_STATE_TIMEOUT) {
52439 + for (channel = 0; channel <= max_channel; channel++) {
52440 + Scsi_Cmnd *failed_command;
52441 + int soft_reset;
52443 + try_again:
52444 + failed_command = NULL;
52445 + soft_reset = 0;
52447 + /*
52448 + * Loop over each device on this channel locating any
52449 + * failed command. We need a Scsi_Cmnd structure to
52450 + * call the bus reset function.
52452 + * We also need to check if any of the failed commands
52453 + * are on soft_reset devices, and if so, skip the reset.
52454 + */
52455 + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52456 + if (SDpnt->channel != channel)
52457 continue;
52459 - /*
52460 - * We have a failed command. Make sure there are no other failed
52461 - * commands on the same channel that are timed out and implement a
52462 - * soft reset.
52463 - */
52464 - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
52465 - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
52466 - if (SCloop->channel != SCpnt->channel) {
52467 - continue;
52469 - if (SCloop->state != SCSI_STATE_FAILED
52470 - && SCloop->state != SCSI_STATE_TIMEOUT) {
52471 - continue;
52473 - if (SDloop->soft_reset && SCloop->state == SCSI_STATE_TIMEOUT) {
52474 - /*
52475 - * If this device uses the soft reset option, and this
52476 - * is one of the devices acting up, then our only
52477 - * option is to wait a bit, since the command is
52478 - * supposedly still running.
52480 - * FIXME(eric) - right now we will just end up falling
52481 - * through to the 'take device offline' case.
52483 - * FIXME(eric) - It is possible that the command completed
52484 - * *after* the error recovery procedure started, and if this
52485 - * is the case, we are worrying about nothing here.
52486 - */
52488 - scsi_sleep(1 * HZ);
52489 - goto next_device;
52493 + SCpnt = scsi_eh_find_failed_command(SDpnt);
52494 + if (SCpnt)
52495 + failed_command = SCpnt;
52498 - * We now know that we are able to perform a reset for the
52499 - * bus that SCpnt points to. There are no soft-reset devices
52500 - * with outstanding timed out commands.
52501 + * If this device has timed out or failed commands,
52502 + * and uses the soft_reset option.
52504 - rtn = scsi_try_bus_reset(SCpnt);
52505 - if (rtn == SUCCESS) {
52506 - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
52507 - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
52508 - if (SCloop->channel != SCpnt->channel) {
52509 - continue;
52511 - if (SCloop->state != SCSI_STATE_FAILED
52512 - && SCloop->state != SCSI_STATE_TIMEOUT) {
52513 - continue;
52515 - rtn = scsi_test_unit_ready(SCloop);
52516 + if (SCpnt && SDpnt->soft_reset)
52517 + soft_reset = 1;
52520 - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
52521 - rtn = scsi_eh_retry_command(SCloop);
52522 + /*
52523 + * If this channel hasn't failed, we
52524 + * don't need to reset it.
52525 + */
52526 + if (!failed_command)
52527 + continue;
52529 - if (rtn == SUCCESS) {
52530 - SCpnt->host->host_failed--;
52531 - scsi_eh_finish_command(&SCdone, SCloop);
52534 - /*
52535 - * If the bus reset worked, but we are still unable to
52536 - * talk to the device, take it offline.
52537 - * FIXME(eric) - is this really the correct thing to do?
52538 - */
52539 - if (rtn != SUCCESS) {
52540 - printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after bus reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
52541 + /*
52542 + * If this device uses the soft reset option, and this
52543 + * is one of the devices acting up, then our only
52544 + * option is to wait a bit, since the command is
52545 + * supposedly still running.
52547 + * FIXME(eric) - right now we will just end up falling
52548 + * through to the 'take device offline' case.
52550 + * FIXME(eric) - It is possible that the command completed
52551 + * *after* the error recovery procedure started, and if
52552 + * this is the case, we are worrying about nothing here.
52554 + * FIXME(rmk) - This should be bounded; we shouldn't wait
52555 + * for an infinite amount of time for any device.
52556 + */
52557 + if (soft_reset) {
52558 + SCSI_LOG_ERROR_RECOVERY(3,
52559 + printk("scsi_unjam_host: unable to try bus "
52560 + "reset for host %d channel %d\n",
52561 + host->host_no, channel));
52562 + scsi_sleep(1 * HZ);
52563 + goto try_again;
52566 - SDloop->online = FALSE;
52567 - SDloop->host->host_failed--;
52568 - scsi_eh_finish_command(&SCdone, SCloop);
52572 + /*
52573 + * We now know that we are able to perform a reset for the
52574 + * bus that SCpnt points to. There are no soft-reset devices
52575 + * with outstanding timed out commands.
52576 + */
52577 + rtn = scsi_try_bus_reset(failed_command);
52579 + /*
52580 + * If we failed to reset the bus, move on to the next bus.
52581 + */
52582 + if (rtn != SUCCESS)
52583 + continue;
52585 + /*
52586 + * We succeeded. Retry each failed command.
52587 + */
52588 + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52589 + if (SDpnt->channel != channel)
52590 + continue;
52592 + rtn = scsi_eh_restart_device(SDpnt, done);
52594 + if (rtn != SUCCESS) {
52595 + SCpnt = scsi_eh_find_failed_command(SDpnt);
52597 + /*
52598 + * This device failed again. Since a bus
52599 + * reset freed it up, chances are we've
52600 + * hit the same problem, so try the same
52601 + * solution. We also need to ensure that
52602 + * the SCSI bus is in the BUS FREE state
52603 + * so we can try to talk to other devices.
52604 + */
52605 + scsi_try_bus_reset(SCpnt);
52606 + scsi_eh_set_device_offline(SDpnt, done,
52607 + "not ready or command retry "
52608 + "failed after bus reset");
52614 +static void scsi_unjam_host_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
52616 + Scsi_Device *SDpnt;
52617 + Scsi_Cmnd *SCpnt;
52618 + Scsi_Cmnd *failed_command = NULL;
52619 + int rtn, soft_reset;
52621 - if (host->host_failed == 0) {
52622 - ourrtn = TRUE;
52623 - goto leave;
52626 - * If we ended up here, we have serious problems. The only thing left
52627 - * to try is a full host reset - perhaps the firmware on the device
52628 - * crashed, or something like that.
52629 + * If we ended up here, we have serious problems. The only thing
52630 + * left to try is a full host reset - perhaps the firmware on the
52631 + * device crashed, or something like that.
52633 - * It is assumed that a succesful host reset will cause *all* information
52634 - * about the command to be flushed from both the host adapter *and* the
52635 - * device.
52636 + * It is assumed that a succesful host reset will cause *all*
52637 + * information about the command to be flushed from both the host
52638 + * adapter *and* the device.
52640 - * FIXME(eric) - it isn't clear that devices that implement the soft reset
52641 - * option can ever be cleared except via cycling the power. The problem is
52642 - * that sending the host reset command will cause the host to forget
52643 - * about the pending command, but the device won't forget. For now, we
52644 - * skip the host reset option if any of the failed devices are configured
52645 - * to use the soft reset option.
52646 + * FIXME(eric) - it isn't clear that devices that implement the
52647 + * soft reset option can ever be cleared except via cycling the
52648 + * power. The problem is that sending the host reset command will
52649 + * cause the host to forget about the pending command, but the
52650 + * device won't forget. For now, we skip the host reset option
52651 + * if any of the failed devices are configured to use the soft
52652 + * reset option.
52654 + SCSI_LOG_ERROR_RECOVERY(3,
52655 + printk("scsi_unjam_host: Try host reset\n"));
52657 + try_again:
52658 + failed_command = NULL;
52659 + soft_reset = 0;
52661 for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52662 - next_device2:
52663 - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
52664 - if (SCpnt->state != SCSI_STATE_FAILED
52665 - && SCpnt->state != SCSI_STATE_TIMEOUT) {
52666 - continue;
52668 - if (SDpnt->soft_reset && SCpnt->state == SCSI_STATE_TIMEOUT) {
52669 - /*
52670 - * If this device uses the soft reset option, and this
52671 - * is one of the devices acting up, then our only
52672 - * option is to wait a bit, since the command is
52673 - * supposedly still running.
52675 - * FIXME(eric) - right now we will just end up falling
52676 - * through to the 'take device offline' case.
52677 - */
52678 - SCSI_LOG_ERROR_RECOVERY(3,
52679 - printk("scsi_unjam_host: Unable to try hard host reset\n"));
52680 + /*
52681 + * Locate any failed commands for this device.
52682 + */
52683 + SCpnt = scsi_eh_find_failed_command(SDpnt);
52684 + if (SCpnt)
52685 + failed_command = SCpnt;
52687 - /*
52688 - * Due to the spinlock, we will never get out of this
52689 - * loop without a proper wait. (DB)
52690 - */
52691 - scsi_sleep(1 * HZ);
52692 + /*
52693 + * If this device has timed out or failed commands,
52694 + * and uses the soft_reset option.
52695 + */
52696 + if (SCpnt && SDpnt->soft_reset)
52697 + soft_reset = 1;
52700 - goto next_device2;
52702 - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard host reset\n"));
52703 + /*
52704 + * If this device uses the soft reset option, and this
52705 + * is one of the devices acting up, then our only
52706 + * option is to wait a bit, since the command is
52707 + * supposedly still running.
52709 + * FIXME(eric) - right now we will just end up falling
52710 + * through to the 'take device offline' case.
52712 + * FIXME(rmk) - This should be bounded; we shouldn't wait
52713 + * for an infinite amount of time for any device.
52714 + */
52715 + if (soft_reset) {
52716 + SCSI_LOG_ERROR_RECOVERY(3,
52717 + printk("scsi_unjam_host: unable to try "
52718 + "hard host reset\n"));
52721 - * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
52722 + * Due to the spinlock, we will never get out of this
52723 + * loop without a proper wait. (DB)
52725 - rtn = scsi_try_host_reset(SCpnt);
52726 - if (rtn == SUCCESS) {
52727 - /*
52728 - * FIXME(eric) we assume that all commands are flushed from the
52729 - * controller. We should get a DID_RESET for all of the commands
52730 - * that were pending. We should ignore these so that we can
52731 - * guarantee that we are in a consistent state.
52733 - * I believe this to be the case right now, but this needs to be
52734 - * tested.
52735 - */
52736 - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
52737 - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
52738 - if (SCloop->state != SCSI_STATE_FAILED
52739 - && SCloop->state != SCSI_STATE_TIMEOUT) {
52740 - continue;
52742 - rtn = scsi_test_unit_ready(SCloop);
52744 - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
52745 - rtn = scsi_eh_retry_command(SCloop);
52746 + scsi_sleep(1 * HZ);
52748 - if (rtn == SUCCESS) {
52749 - SCpnt->host->host_failed--;
52750 - scsi_eh_finish_command(&SCdone, SCloop);
52753 - if (rtn != SUCCESS) {
52754 - printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after host reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
52755 - SDloop->online = FALSE;
52756 - SDloop->host->host_failed--;
52757 - scsi_eh_finish_command(&SCdone, SCloop);
52763 + goto try_again;
52766 + SCSI_LOG_ERROR_RECOVERY(3,
52767 + printk("scsi_unjam_host: Try hard host reset\n"));
52770 - * If we solved all of the problems, then let's rev up the engines again.
52771 - */
52772 - if (host->host_failed == 0) {
52773 - ourrtn = TRUE;
52774 - goto leave;
52776 - /*
52777 - * If the HOST RESET failed, then for now we assume that the entire host
52778 - * adapter is too hosed to be of any use. For our purposes, however, it is
52779 - * easier to simply take the devices offline that correspond to commands
52780 - * that failed.
52781 + * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
52783 - SCSI_LOG_ERROR_RECOVERY(1, printk("scsi_unjam_host: Take device offline\n"));
52784 + rtn = scsi_try_host_reset(failed_command);
52785 + if (rtn == SUCCESS) {
52786 + /*
52787 + * FIXME(eric) we assume that all commands are flushed from
52788 + * the controller. We should get a DID_RESET for all of the
52789 + * commands that were pending. We should ignore these so
52790 + * that we can guarantee that we are in a consistent state.
52792 + * I believe this to be the case right now, but this needs
52793 + * to be tested.
52794 + */
52795 + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52796 + rtn = scsi_eh_restart_device(SDpnt, done);
52798 - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52799 - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
52800 - if (SCloop->state == SCSI_STATE_FAILED || SCloop->state == SCSI_STATE_TIMEOUT) {
52801 - SDloop = SCloop->device;
52802 - if (SDloop->online == TRUE) {
52803 - printk(KERN_INFO "scsi: device set offline - command error recover failed: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
52804 - SDloop->online = FALSE;
52806 + if (rtn != SUCCESS) {
52807 + SCpnt = scsi_eh_find_failed_command(SDpnt);
52810 - * This should pass the failure up to the top level driver, and
52811 - * it will have to try and do something intelligent with it.
52812 + * This device failed again. Since a host
52813 + * reset freed it up, chances are we've
52814 + * hit the same problem, so try the same
52815 + * solution. We also need to ensure that
52816 + * the SCSI bus is in the BUS FREE state
52817 + * so we can try to talk to other devices.
52819 - SCloop->host->host_failed--;
52821 - if (SCloop->state == SCSI_STATE_TIMEOUT) {
52822 - SCloop->result |= (DRIVER_TIMEOUT << 24);
52824 - SCSI_LOG_ERROR_RECOVERY(3, printk("Finishing command for device %d %x\n",
52825 - SDloop->id, SCloop->result));
52827 - scsi_eh_finish_command(&SCdone, SCloop);
52828 + scsi_try_host_reset(SCpnt);
52829 + scsi_eh_set_device_offline(SDpnt, done,
52830 + "not ready or command retry "
52831 + "failed after host reset");
52837 - if (host->host_failed != 0) {
52838 +static void scsi_unjam_failure(struct Scsi_Host *host, Scsi_Cmnd **done)
52840 + Scsi_Device *SDpnt;
52842 + /*
52843 + * If the HOST RESET failed, then for now we assume that the
52844 + * entire host adapter is too hosed to be of any use. For our
52845 + * purposes, however, it is easier to simply take the devices
52846 + * offline that correspond to commands that failed.
52847 + */
52848 + SCSI_LOG_ERROR_RECOVERY(1,
52849 + printk("scsi_unjam_host: Take device offline\n"));
52851 + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
52852 + scsi_eh_set_device_offline(SDpnt, done,
52853 + "command error recover failed");
52855 + if (host->host_failed != 0)
52856 panic("scsi_unjam_host: Miscount of number of failed commands.\n");
52859 SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Returning\n"));
52862 - ourrtn = FALSE;
52863 +static void (*unjam_method[])(struct Scsi_Host *, Scsi_Cmnd **) = {
52864 + scsi_unjam_request_sense,
52865 + scsi_unjam_count,
52866 + scsi_unjam_abort,
52867 + scsi_unjam_device_reset,
52868 + scsi_unjam_bus_reset,
52869 + scsi_unjam_host_reset,
52870 + scsi_unjam_failure,
52873 - leave:
52875 + * Function: scsi_unjam_host
52877 + * Purpose: Attempt to fix a host which has a command that failed for
52878 + * some reason.
52880 + * Arguments: host - host that needs unjamming.
52881 + *
52882 + * Returns: Nothing
52884 + * Notes: When we come in here, we *know* that all commands on the
52885 + * bus have either completed, failed or timed out. We also
52886 + * know that no further commands are being sent to the host,
52887 + * so things are relatively quiet and we have freedom to
52888 + * fiddle with things as we wish.
52890 + * Additional note: This is only the *default* implementation. It is possible
52891 + * for individual drivers to supply their own version of this
52892 + * function, and if the maintainer wishes to do this, it is
52893 + * strongly suggested that this function be taken as a template
52894 + * and modified. This function was designed to correctly handle
52895 + * problems for about 95% of the different cases out there, and
52896 + * it should always provide at least a reasonable amount of error
52897 + * recovery.
52899 + * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
52900 + * have scsi_finish_command() called for it. We do all of
52901 + * the retry stuff here, so when we restart the host after we
52902 + * return it should have an empty queue.
52903 + */
52904 +STATIC int scsi_unjam_host(struct Scsi_Host *host)
52906 + Scsi_Cmnd *SCdone = NULL;
52907 + Scsi_Cmnd *SCpnt;
52908 + Scsi_Device *SDpnt;
52909 + int ourrtn = FALSE;
52910 + int i;
52912 + ASSERT_LOCK(&io_request_lock, 0);
52914 + /*
52915 + * First, protect against any sort of race condition. If any of the outstanding
52916 + * commands are in states that indicate that we are not yet blocked (i.e. we are
52917 + * not in a quiet state) then we got woken up in error. If we ever end up here,
52918 + * we need to re-examine some of the assumptions.
52919 + */
52920 + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
52921 + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
52922 + if (SCpnt->state == SCSI_STATE_FAILED
52923 + || SCpnt->state == SCSI_STATE_TIMEOUT
52924 + || SCpnt->state == SCSI_STATE_INITIALIZING
52925 + || SCpnt->state == SCSI_STATE_UNUSED) {
52926 + continue;
52928 + /*
52929 + * Rats. Something is still floating around out there. This could
52930 + * be the result of the fact that the upper level drivers are still frobbing
52931 + * commands that might have succeeded. There are two outcomes. One is that
52932 + * the command block will eventually be freed, and the other one is that
52933 + * the command will be queued and will be finished along the way.
52934 + */
52935 + SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
52938 + * panic("SCSI Error handler woken too early\n");
52940 + * This is no longer a problem, since now the code cares only about
52941 + * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
52942 + * Other states are useful only to release active commands when devices are
52943 + * set offline. If (host->host_active == host->host_busy) we can safely assume
52944 + * that there are no commands in state other then TIMEOUT od FAILED. (DB)
52946 + * FIXME:
52947 + * It is not easy to release correctly commands according to their state when
52948 + * devices are set offline, when the state is neither TIMEOUT nor FAILED.
52949 + * When a device is set offline, we can have some command with
52950 + * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
52951 + * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
52952 + * (DB, 17 May 1998)
52953 + */
52957 + for (i = 0; i < ARRAY_SIZE(unjam_method); i++) {
52958 + unjam_method[i](host, &SCdone);
52960 + /*
52961 + * If we solved all of the problems, then
52962 + * let's rev up the engines again.
52963 + */
52964 + if (host->host_failed == 0) {
52965 + ourrtn = TRUE;
52966 + break;
52971 * We should have a list of commands that we 'finished' during the course of
52972 @@ -2025,3 +2312,17 @@
52973 * tab-width: 8
52974 * End:
52977 +EXPORT_SYMBOL(scsi_eh_times_out);
52978 +EXPORT_SYMBOL(scsi_eh_retry_command);
52979 +EXPORT_SYMBOL(scsi_request_sense);
52980 +EXPORT_SYMBOL(scsi_test_unit_ready);
52981 +EXPORT_SYMBOL(scsi_unit_is_ready);
52982 +EXPORT_SYMBOL(scsi_eh_finish_command);
52983 +EXPORT_SYMBOL(scsi_try_to_abort_command);
52984 +EXPORT_SYMBOL(scsi_try_bus_device_reset);
52985 +EXPORT_SYMBOL(scsi_try_bus_reset);
52986 +EXPORT_SYMBOL(scsi_try_host_reset);
52987 +EXPORT_SYMBOL(scsi_sense_valid);
52988 +EXPORT_SYMBOL(scsi_done);
52989 +EXPORT_SYMBOL(scsi_decide_disposition);
52990 --- linux-2.4.25/drivers/scsi/scsi_ioctl.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
52991 +++ linux-2.4.25/drivers/scsi/scsi_ioctl.c 2004-03-31 17:15:09.000000000 +0200
52992 @@ -153,6 +153,29 @@
52993 return result;
52996 +int scsi_set_medium_removal(Scsi_Device *dev, char state)
52998 + char scsi_cmd[MAX_COMMAND_SIZE];
52999 + int ret;
53001 + if (!dev->removable || !dev->lockable)
53002 + return 0;
53004 + scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
53005 + scsi_cmd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
53006 + scsi_cmd[2] = 0;
53007 + scsi_cmd[3] = 0;
53008 + scsi_cmd[4] = state;
53009 + scsi_cmd[5] = 0;
53011 + ret = ioctl_internal_command(dev, scsi_cmd, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
53013 + if (ret == 0)
53014 + dev->locked = state == SCSI_REMOVAL_PREVENT;
53016 + return ret;
53020 * This interface is depreciated - users should use the scsi generic (sg)
53021 * interface instead, as this is a more flexible approach to performing
53022 @@ -450,24 +473,9 @@
53023 return scsi_ioctl_send_command((Scsi_Device *) dev,
53024 (Scsi_Ioctl_Command *) arg);
53025 case SCSI_IOCTL_DOORLOCK:
53026 - if (!dev->removable || !dev->lockable)
53027 - return 0;
53028 - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
53029 - scsi_cmd[1] = cmd_byte1;
53030 - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
53031 - scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
53032 - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
53033 - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
53034 - break;
53035 + return scsi_set_medium_removal(dev, SCSI_REMOVAL_PREVENT);
53036 case SCSI_IOCTL_DOORUNLOCK:
53037 - if (!dev->removable || !dev->lockable)
53038 - return 0;
53039 - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
53040 - scsi_cmd[1] = cmd_byte1;
53041 - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
53042 - scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
53043 - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
53044 - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
53045 + return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW);
53046 case SCSI_IOCTL_TEST_UNIT_READY:
53047 scsi_cmd[0] = TEST_UNIT_READY;
53048 scsi_cmd[1] = cmd_byte1;
53049 --- linux-2.4.25/drivers/scsi/scsi_lib.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
53050 +++ linux-2.4.25/drivers/scsi/scsi_lib.c 2004-03-31 17:15:09.000000000 +0200
53051 @@ -208,6 +208,30 @@
53055 + * Function: scsi_setup_cmd_retry()
53057 + * Purpose: Restore the command state for a retry
53059 + * Arguments: SCpnt - command to be restored
53061 + * Returns: Nothing
53063 + * Notes: Immediately prior to retrying a command, we need
53064 + * to restore certain fields that we saved above.
53065 + */
53066 +void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt)
53068 + memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
53069 + sizeof(SCpnt->data_cmnd));
53070 + SCpnt->request_buffer = SCpnt->buffer;
53071 + SCpnt->request_bufflen = SCpnt->bufflen;
53072 + SCpnt->use_sg = SCpnt->old_use_sg;
53073 + SCpnt->cmd_len = SCpnt->old_cmd_len;
53074 + SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
53075 + SCpnt->underflow = SCpnt->old_underflow;
53079 * Function: scsi_queue_next_request()
53081 * Purpose: Handle post-processing of completed commands.
53082 @@ -723,7 +747,7 @@
53083 printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",
53084 SCpnt->host->host_no, (int) SCpnt->channel,
53085 (int) SCpnt->target, (int) SCpnt->lun);
53086 - print_command(SCpnt->cmnd);
53087 + print_command(SCpnt->data_cmnd);
53088 print_sense("sd", SCpnt);
53089 SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
53090 return;
53091 @@ -898,8 +922,17 @@
53092 * space. Technically the error handling thread should be
53093 * doing this crap, but the error handler isn't used by
53094 * most hosts.
53096 + * (rmk)
53097 + * Trying to lock the door can cause deadlocks. We therefore
53098 + * only use this for old hosts; our door locking is now done
53099 + * by the error handler in scsi_restart_operations for new
53100 + * eh hosts.
53102 + * Note that we don't clear was_reset here; this is used by
53103 + * st.c, and either one or other has to die.
53105 - if (SDpnt->was_reset) {
53106 + if (SHpnt->hostt->use_new_eh_code == 0 && SDpnt->was_reset) {
53108 * We need to relock the door, but we might
53109 * be in an interrupt handler. Only do this
53110 @@ -910,7 +943,7 @@
53111 * this work.
53113 SDpnt->was_reset = 0;
53114 - if (SDpnt->removable && !in_interrupt()) {
53115 + if (SDpnt->removable && SDpnt->locked && !in_interrupt()) {
53116 spin_unlock_irq(&io_request_lock);
53117 scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
53118 spin_lock_irq(&io_request_lock);
53119 --- linux-2.4.25/drivers/scsi/scsi_syms.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
53120 +++ linux-2.4.25/drivers/scsi/scsi_syms.c 2004-03-31 17:15:09.000000000 +0200
53121 @@ -103,3 +103,6 @@
53122 extern int scsi_delete_timer(Scsi_Cmnd *);
53123 EXPORT_SYMBOL(scsi_add_timer);
53124 EXPORT_SYMBOL(scsi_delete_timer);
53126 +extern int scsi_set_medium_removal(Scsi_Device *dev, char state);
53127 +EXPORT_SYMBOL(scsi_set_medium_removal);
53128 --- linux-2.4.25/drivers/scsi/sd.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
53129 +++ linux-2.4.25/drivers/scsi/sd.c 2004-03-31 17:15:09.000000000 +0200
53130 @@ -399,6 +399,7 @@
53131 this_count = 0xffff;
53133 SCpnt->cmnd[0] += READ_10 - READ_6;
53134 + SCpnt->cmnd[1] |= 1 << 3; /* Set FUA --rmk */
53135 SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
53136 SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
53137 SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
53138 @@ -524,7 +525,7 @@
53139 if (SDev->removable)
53140 if (SDev->access_count==1)
53141 if (scsi_block_when_processing_errors(SDev))
53142 - scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL);
53143 + scsi_set_medium_removal(SDev, SCSI_REMOVAL_PREVENT);
53146 return 0;
53147 @@ -553,7 +554,7 @@
53148 if (SDev->removable) {
53149 if (!SDev->access_count)
53150 if (scsi_block_when_processing_errors(SDev))
53151 - scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL);
53152 + scsi_set_medium_removal(SDev, SCSI_REMOVAL_ALLOW);
53154 if (SDev->host->hostt->module)
53155 __MOD_DEC_USE_COUNT(SDev->host->hostt->module);
53156 --- linux-2.4.25/drivers/scsi/sr_ioctl.c~2.4.25-vrs2.patch 2002-11-29 00:53:14.000000000 +0100
53157 +++ linux-2.4.25/drivers/scsi/sr_ioctl.c 2004-03-31 17:15:09.000000000 +0200
53158 @@ -214,9 +214,8 @@
53160 int sr_lock_door(struct cdrom_device_info *cdi, int lock)
53162 - return scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
53163 - lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
53164 - 0);
53165 + return scsi_set_medium_removal(scsi_CDs[MINOR(cdi->dev)].device,
53166 + lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
53169 int sr_drive_status(struct cdrom_device_info *cdi, int slot)
53170 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
53171 +++ linux-2.4.25/drivers/serial/21285.c 2004-03-31 17:15:09.000000000 +0200
53172 @@ -0,0 +1,600 @@
53174 + * linux/drivers/char/serial_21285.c
53176 + * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
53178 + * Based on drivers/char/serial.c
53180 + * $Id: 21285.c,v 1.4.2.1 2002/10/24 09:53:23 rmk Exp $
53181 + */
53182 +#include <linux/config.h>
53183 +#include <linux/module.h>
53184 +#include <linux/errno.h>
53185 +#include <linux/signal.h>
53186 +#include <linux/sched.h>
53187 +#include <linux/interrupt.h>
53188 +#include <linux/tty.h>
53189 +#include <linux/tty_flip.h>
53190 +#include <linux/serial.h>
53191 +#include <linux/major.h>
53192 +#include <linux/ptrace.h>
53193 +#include <linux/ioport.h>
53194 +#include <linux/mm.h>
53195 +#include <linux/slab.h>
53196 +#include <linux/init.h>
53197 +#include <linux/console.h>
53199 +#include <asm/io.h>
53200 +#include <asm/irq.h>
53201 +#include <asm/uaccess.h>
53202 +#include <asm/hardware/dec21285.h>
53203 +#include <asm/hardware.h>
53205 +#define BAUD_BASE (mem_fclk_21285/64)
53207 +#define SERIAL_21285_NAME "ttyFB"
53208 +#define SERIAL_21285_MAJOR 204
53209 +#define SERIAL_21285_MINOR 4
53211 +#define SERIAL_21285_AUXNAME "cuafb"
53212 +#define SERIAL_21285_AUXMAJOR 205
53213 +#define SERIAL_21285_AUXMINOR 4
53215 +#ifdef CONFIG_SERIAL_21285_OLD
53216 +#include <asm/mach-types.h>
53218 + * Compatability with a mistake made a long time ago.
53219 + * Note - the use of "ttyI", "/dev/ttyS0" and major/minor 5,64
53220 + * is HIGHLY DEPRECIATED, and will be removed in the 2.5
53221 + * kernel series.
53222 + * -- rmk 15/04/2000
53223 + */
53224 +#define SERIAL_21285_OLD_NAME "ttyI"
53225 +#define SERIAL_21285_OLD_MAJOR TTY_MAJOR
53226 +#define SERIAL_21285_OLD_MINOR 64
53228 +static struct tty_driver rs285_old_driver;
53229 +#endif
53231 +static struct tty_driver rs285_driver, callout_driver;
53232 +static int rs285_refcount;
53233 +static struct tty_struct *rs285_table[1];
53235 +static struct termios *rs285_termios[1];
53236 +static struct termios *rs285_termios_locked[1];
53238 +static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
53239 +static struct tty_struct *rs285_tty;
53240 +static DECLARE_MUTEX(rs285_sem);
53241 +static int rs285_use_count;
53242 +static unsigned long rs285_irq_enabled;
53244 +#define TX_IRQ_BIT (0)
53245 +#define RX_IRQ_BIT (1)
53247 +static void rs285_stop_tx(void)
53249 + if (test_and_clear_bit(TX_IRQ_BIT, &rs285_irq_enabled))
53250 + disable_irq(IRQ_CONTX);
53253 +static void rs285_start_tx(void)
53255 + if (!test_and_set_bit(TX_IRQ_BIT, &rs285_irq_enabled))
53256 + enable_irq(IRQ_CONTX);
53259 +static void rs285_stop_rx(void)
53261 + if (test_and_clear_bit(RX_IRQ_BIT, &rs285_irq_enabled))
53262 + disable_irq(IRQ_CONRX);
53265 +static void rs285_start_rx(void)
53267 + if (!test_and_set_bit(RX_IRQ_BIT, &rs285_irq_enabled))
53268 + enable_irq(IRQ_CONRX);
53271 +static int rs285_write_room(struct tty_struct *tty)
53273 + return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
53276 +static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
53278 + if (!rs285_tty) {
53279 + rs285_stop_rx();
53280 + return;
53282 + while (!(*CSR_UARTFLG & 0x10)) {
53283 + int ch, flag;
53284 + ch = *CSR_UARTDR;
53285 + flag = *CSR_RXSTAT;
53286 + if (flag & 4)
53287 + tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
53288 + if (flag & 2)
53289 + flag = TTY_PARITY;
53290 + else if (flag & 1)
53291 + flag = TTY_FRAME;
53292 + tty_insert_flip_char(rs285_tty, ch, flag);
53294 + tty_flip_buffer_push(rs285_tty);
53297 +static void rs285_send_xchar(struct tty_struct *tty, char ch)
53299 + x_char = ch;
53300 + rs285_start_tx();
53303 +static void rs285_throttle(struct tty_struct *tty)
53305 + if (I_IXOFF(tty))
53306 + rs285_send_xchar(tty, STOP_CHAR(tty));
53309 +static void rs285_unthrottle(struct tty_struct *tty)
53311 + if (I_IXOFF(tty)) {
53312 + if (x_char)
53313 + x_char = 0;
53314 + else
53315 + rs285_send_xchar(tty, START_CHAR(tty));
53319 +static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
53321 + while (!(*CSR_UARTFLG & 0x20)) {
53322 + if (x_char) {
53323 + *CSR_UARTDR = x_char;
53324 + x_char = 0;
53325 + continue;
53327 + if (putp == getp) {
53328 + rs285_stop_tx();
53329 + break;
53331 + *CSR_UARTDR = *getp;
53332 + if (++getp >= wbuf + sizeof(wbuf))
53333 + getp = wbuf;
53335 + if (rs285_tty)
53336 + wake_up_interruptible(&rs285_tty->write_wait);
53339 +static inline int rs285_xmit(int ch)
53341 + if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
53342 + return 0;
53343 + *putp = ch;
53344 + if (++putp >= wbuf + sizeof(wbuf))
53345 + putp = wbuf;
53346 + rs285_start_tx();
53347 + return 1;
53350 +static int rs285_write(struct tty_struct *tty, int from_user,
53351 + const u_char * buf, int count)
53353 + int i;
53355 + if (from_user && verify_area(VERIFY_READ, buf, count))
53356 + return -EINVAL;
53358 + for (i = 0; i < count; i++) {
53359 + char ch;
53360 + if (from_user)
53361 + __get_user(ch, buf + i);
53362 + else
53363 + ch = buf[i];
53364 + if (!rs285_xmit(ch))
53365 + break;
53367 + return i;
53370 +static void rs285_put_char(struct tty_struct *tty, u_char ch)
53372 + rs285_xmit(ch);
53375 +static int rs285_chars_in_buffer(struct tty_struct *tty)
53377 + return sizeof(wbuf) - rs285_write_room(tty);
53380 +static void rs285_flush_buffer(struct tty_struct *tty)
53382 + rs285_stop_tx();
53383 + putp = getp = wbuf;
53384 + if (x_char)
53385 + rs285_start_tx();
53388 +static inline void rs285_set_cflag(int cflag)
53390 + int h_lcr, baud, quot;
53392 + switch (cflag & CSIZE) {
53393 + case CS5:
53394 + h_lcr = 0x10;
53395 + break;
53396 + case CS6:
53397 + h_lcr = 0x30;
53398 + break;
53399 + case CS7:
53400 + h_lcr = 0x50;
53401 + break;
53402 + default: /* CS8 */
53403 + h_lcr = 0x70;
53404 + break;
53407 + if (cflag & CSTOPB)
53408 + h_lcr |= 0x08;
53409 + if (cflag & PARENB)
53410 + h_lcr |= 0x02;
53411 + if (!(cflag & PARODD))
53412 + h_lcr |= 0x04;
53414 + switch (cflag & CBAUD) {
53415 + case B200: baud = 200; break;
53416 + case B300: baud = 300; break;
53417 + case B1200: baud = 1200; break;
53418 + case B1800: baud = 1800; break;
53419 + case B2400: baud = 2400; break;
53420 + case B4800: baud = 4800; break;
53421 + default:
53422 + case B9600: baud = 9600; break;
53423 + case B19200: baud = 19200; break;
53424 + case B38400: baud = 38400; break;
53425 + case B57600: baud = 57600; break;
53426 + case B115200: baud = 115200; break;
53429 + /*
53430 + * The documented expression for selecting the divisor is:
53431 + * BAUD_BASE / baud - 1
53432 + * However, typically BAUD_BASE is not divisible by baud, so
53433 + * we want to select the divisor that gives us the minimum
53434 + * error. Therefore, we want:
53435 + * int(BAUD_BASE / baud - 0.5) ->
53436 + * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
53437 + * int((BAUD_BASE - (baud >> 1)) / baud)
53438 + */
53439 + quot = (BAUD_BASE - (baud >> 1)) / baud;
53441 + *CSR_UARTCON = 0;
53442 + *CSR_L_UBRLCR = quot & 0xff;
53443 + *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
53444 + *CSR_H_UBRLCR = h_lcr;
53445 + *CSR_UARTCON = 1;
53448 +static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
53450 + if (old && tty->termios->c_cflag == old->c_cflag)
53451 + return;
53452 + rs285_set_cflag(tty->termios->c_cflag);
53456 +static void rs285_stop(struct tty_struct *tty)
53458 + rs285_stop_tx();
53461 +static void rs285_start(struct tty_struct *tty)
53463 + rs285_start_tx();
53466 +static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
53468 + int orig_jiffies = jiffies;
53469 + while (*CSR_UARTFLG & 8) {
53470 + set_current_state(TASK_INTERRUPTIBLE);
53471 + schedule_timeout(1);
53472 + if (signal_pending(current))
53473 + break;
53474 + if (timeout && time_after(jiffies, orig_jiffies + timeout))
53475 + break;
53477 + set_current_state(TASK_RUNNING);
53480 +static int rs285_open(struct tty_struct *tty, struct file *filp)
53482 + int line, ret;
53484 + MOD_INC_USE_COUNT;
53486 + line = MINOR(tty->device) - tty->driver.minor_start;
53487 + if (line)
53488 + return -ENODEV;
53490 + ret = down_interruptible(&rs285_sem);
53491 + if (ret)
53492 + return ret;
53494 + tty->driver_data = NULL;
53495 + rs285_tty = tty;
53497 + if (rs285_use_count == 0) {
53498 + rs285_irq_enabled = 3;
53499 + ret = request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL);
53500 + if (ret == 0) {
53501 + ret = request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285",
53502 + NULL);
53503 + if (ret)
53504 + free_irq(IRQ_CONRX, NULL);
53508 + if (ret == 0)
53509 + rs285_use_count++;
53511 + up(&rs285_sem);
53513 + return ret;
53516 +static void rs285_close(struct tty_struct *tty, struct file *filp)
53518 + down(&rs285_sem);
53519 + if (!--rs285_use_count) {
53520 + rs285_wait_until_sent(tty, 0);
53521 + rs285_stop_rx();
53522 + rs285_stop_tx();
53523 + rs285_tty = NULL;
53524 + free_irq(IRQ_CONTX, NULL);
53525 + free_irq(IRQ_CONRX, NULL);
53527 + up(&rs285_sem);
53528 + MOD_DEC_USE_COUNT;
53531 +static int __init rs285_init(void)
53533 + int baud = B9600;
53535 + if (machine_is_personal_server())
53536 + baud = B57600;
53538 + rs285_driver.magic = TTY_DRIVER_MAGIC;
53539 + rs285_driver.driver_name = "serial_21285";
53540 + rs285_driver.name = SERIAL_21285_NAME;
53541 + rs285_driver.major = SERIAL_21285_MAJOR;
53542 + rs285_driver.minor_start = SERIAL_21285_MINOR;
53543 + rs285_driver.num = 1;
53544 + rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
53545 + rs285_driver.subtype = SERIAL_TYPE_NORMAL;
53546 + rs285_driver.init_termios = tty_std_termios;
53547 + rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
53548 + rs285_driver.flags = TTY_DRIVER_REAL_RAW;
53549 + rs285_driver.refcount = &rs285_refcount;
53550 + rs285_driver.table = rs285_table;
53551 + rs285_driver.termios = rs285_termios;
53552 + rs285_driver.termios_locked = rs285_termios_locked;
53554 + rs285_driver.open = rs285_open;
53555 + rs285_driver.close = rs285_close;
53556 + rs285_driver.write = rs285_write;
53557 + rs285_driver.put_char = rs285_put_char;
53558 + rs285_driver.write_room = rs285_write_room;
53559 + rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
53560 + rs285_driver.flush_buffer = rs285_flush_buffer;
53561 + rs285_driver.throttle = rs285_throttle;
53562 + rs285_driver.unthrottle = rs285_unthrottle;
53563 + rs285_driver.send_xchar = rs285_send_xchar;
53564 + rs285_driver.set_termios = rs285_set_termios;
53565 + rs285_driver.stop = rs285_stop;
53566 + rs285_driver.start = rs285_start;
53567 + rs285_driver.wait_until_sent = rs285_wait_until_sent;
53569 + callout_driver = rs285_driver;
53570 + callout_driver.name = SERIAL_21285_AUXNAME;
53571 + callout_driver.major = SERIAL_21285_AUXMAJOR;
53572 + callout_driver.subtype = SERIAL_TYPE_CALLOUT;
53574 +#ifdef CONFIG_SERIAL_21285_OLD
53575 + if (!machine_is_ebsa285() && !machine_is_netwinder()) {
53576 + rs285_old_driver = rs285_driver;
53577 + rs285_old_driver.name = SERIAL_21285_OLD_NAME;
53578 + rs285_old_driver.major = SERIAL_21285_OLD_MAJOR;
53579 + rs285_old_driver.minor_start = SERIAL_21285_OLD_MINOR;
53581 + if (tty_register_driver(&rs285_old_driver))
53582 + printk(KERN_ERR "Couldn't register old 21285 serial driver\n");
53584 +#endif
53586 + if (tty_register_driver(&rs285_driver))
53587 + printk(KERN_ERR "Couldn't register 21285 serial driver\n");
53588 + if (tty_register_driver(&callout_driver))
53589 + printk(KERN_ERR "Couldn't register 21285 callout driver\n");
53591 + return 0;
53594 +static void __exit rs285_fini(void)
53596 + unsigned long flags;
53597 + int ret;
53599 + save_flags(flags);
53600 + cli();
53601 + ret = tty_unregister_driver(&callout_driver);
53602 + if (ret)
53603 + printk(KERN_ERR "Unable to unregister 21285 callout driver "
53604 + "(%d)\n", ret);
53605 + ret = tty_unregister_driver(&rs285_driver);
53606 + if (ret)
53607 + printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
53608 + ret);
53609 +#ifdef CONFIG_SERIAL_21285_OLD
53610 + if (!machine_is_ebsa285() && !machine_is_netwinder()) {
53611 + ret = tty_unregister_driver(&rs285_old_driver);
53612 + if (ret)
53613 + printk(KERN_ERR "Unable to unregister old 21285 "
53614 + "driver (%d)\n", ret);
53616 +#endif
53617 + free_irq(IRQ_CONTX, NULL);
53618 + free_irq(IRQ_CONRX, NULL);
53619 + restore_flags(flags);
53622 +module_init(rs285_init);
53623 +module_exit(rs285_fini);
53625 +#ifdef CONFIG_SERIAL_21285_CONSOLE
53626 +/************** console driver *****************/
53628 +static void rs285_console_write(struct console *co, const char *s, u_int count)
53630 + int i;
53632 + rs285_stop_tx();
53633 + for (i = 0; i < count; i++) {
53634 + while (*CSR_UARTFLG & 0x20);
53635 + *CSR_UARTDR = s[i];
53636 + if (s[i] == '\n') {
53637 + while (*CSR_UARTFLG & 0x20);
53638 + *CSR_UARTDR = '\r';
53641 + rs285_start_tx();
53644 +static kdev_t rs285_console_device(struct console *c)
53646 + return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
53649 +static int __init rs285_console_setup(struct console *co, char *options)
53651 + int baud = 9600;
53652 + int bits = 8;
53653 + int parity = 'n';
53654 + int cflag = CREAD | HUPCL | CLOCAL;
53656 + if (machine_is_personal_server())
53657 + baud = 57600;
53659 + if (options) {
53660 + char *s = options;
53661 + baud = simple_strtoul(options, NULL, 10);
53662 + while (*s >= '0' && *s <= '9')
53663 + s++;
53664 + if (*s)
53665 + parity = *s++;
53666 + if (*s)
53667 + bits = *s - '0';
53670 + /*
53671 + * Now construct a cflag setting.
53672 + */
53673 + switch (baud) {
53674 + case 1200:
53675 + cflag |= B1200;
53676 + break;
53677 + case 2400:
53678 + cflag |= B2400;
53679 + break;
53680 + case 4800:
53681 + cflag |= B4800;
53682 + break;
53683 + case 9600:
53684 + cflag |= B9600;
53685 + break;
53686 + case 19200:
53687 + cflag |= B19200;
53688 + break;
53689 + case 38400:
53690 + cflag |= B38400;
53691 + break;
53692 + case 57600:
53693 + cflag |= B57600;
53694 + break;
53695 + case 115200:
53696 + cflag |= B115200;
53697 + break;
53698 + default:
53699 + cflag |= B9600;
53700 + break;
53702 + switch (bits) {
53703 + case 7:
53704 + cflag |= CS7;
53705 + break;
53706 + default:
53707 + cflag |= CS8;
53708 + break;
53710 + switch (parity) {
53711 + case 'o':
53712 + case 'O':
53713 + cflag |= PARODD;
53714 + break;
53715 + case 'e':
53716 + case 'E':
53717 + cflag |= PARENB;
53718 + break;
53720 + co->cflag = cflag;
53721 + rs285_set_cflag(cflag);
53722 + rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
53723 + if (options)
53724 + rs285_console_write(NULL, options, strlen(options));
53725 + else
53726 + rs285_console_write(NULL, "no options", 10);
53727 + rs285_console_write(NULL, "\n", 1);
53729 + return 0;
53732 +#ifdef CONFIG_SERIAL_21285_OLD
53733 +static struct console rs285_old_cons =
53735 + SERIAL_21285_OLD_NAME,
53736 + rs285_console_write,
53737 + NULL,
53738 + rs285_console_device,
53739 + NULL,
53740 + rs285_console_setup,
53741 + CON_PRINTBUFFER,
53742 + -1,
53743 + 0,
53744 + NULL
53746 +#endif
53748 +static struct console rs285_cons =
53750 + name: SERIAL_21285_NAME,
53751 + write: rs285_console_write,
53752 + device: rs285_console_device,
53753 + setup: rs285_console_setup,
53754 + flags: CON_PRINTBUFFER,
53755 + index: -1,
53758 +void __init rs285_console_init(void)
53760 +#ifdef CONFIG_SERIAL_21285_OLD
53761 + if (!machine_is_ebsa285() && !machine_is_netwinder())
53762 + register_console(&rs285_old_cons);
53763 +#endif
53764 + register_console(&rs285_cons);
53767 +#endif /* CONFIG_SERIAL_21285_CONSOLE */
53769 +EXPORT_NO_SYMBOLS;
53771 +MODULE_LICENSE("GPL");
53772 +MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
53773 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
53774 +++ linux-2.4.25/drivers/serial/8250.c 2004-03-31 17:15:09.000000000 +0200
53775 @@ -0,0 +1,2170 @@
53777 + * linux/drivers/serial/8250.c
53779 + * Driver for 8250/16550-type serial ports
53781 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
53783 + * Copyright (C) 2001 Russell King.
53785 + * This program is free software; you can redistribute it and/or modify
53786 + * it under the terms of the GNU General Public License as published by
53787 + * the Free Software Foundation; either version 2 of the License, or
53788 + * (at your option) any later version.
53790 + * $Id: 8250.c,v 1.14.2.8 2002/10/24 14:31:31 rmk Exp $
53792 + * A note about mapbase / membase
53794 + * mapbase is the physical address of the IO port. Currently, we don't
53795 + * support this very well, and it may well be dropped from this driver
53796 + * in future. As such, mapbase should be NULL.
53798 + * membase is an 'ioremapped' cookie. This is compatible with the old
53799 + * serial.c driver, and is currently the preferred form.
53800 + */
53801 +#include <linux/config.h>
53802 +#include <linux/module.h>
53803 +#include <linux/errno.h>
53804 +#include <linux/sched.h>
53805 +#include <linux/tty.h>
53806 +#include <linux/tty_flip.h>
53807 +#include <linux/major.h>
53808 +#include <linux/ptrace.h>
53809 +#include <linux/ioport.h>
53810 +#include <linux/init.h>
53811 +#include <linux/serial.h>
53812 +#include <linux/console.h>
53813 +#include <linux/sysrq.h>
53814 +#include <linux/serial_reg.h>
53815 +#include <linux/serialP.h>
53816 +#include <linux/delay.h>
53817 +#include <linux/serial_core.h>
53818 +#include <linux/kmod.h>
53820 +#include <asm/system.h>
53821 +#include <asm/io.h>
53822 +#include <asm/irq.h>
53823 +#include <asm/uaccess.h>
53824 +#include <asm/bitops.h>
53826 +#include "8250.h"
53829 + * Configuration:
53830 + * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option
53831 + * is unsafe when used on edge-triggered interrupts.
53832 + */
53833 +unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
53836 + * Debugging.
53837 + */
53838 +#if 0
53839 +#define DEBUG_AUTOCONF(fmt...) printk(fmt)
53840 +#else
53841 +#define DEBUG_AUTOCONF(fmt...) do { } while (0)
53842 +#endif
53844 +#if 0
53845 +#define DEBUG_INTR(fmt...) printk(fmt)
53846 +#else
53847 +#define DEBUG_INTR(fmt...) do { } while (0)
53848 +#endif
53850 +#define PASS_LIMIT 256
53853 + * We default to IRQ0 for the "no irq" hack. Some
53854 + * machine types want others as well - they're free
53855 + * to redefine this in their header file.
53856 + */
53857 +#define is_real_interrupt(irq) ((irq) != 0)
53860 + * This converts from our new CONFIG_ symbols to the symbols
53861 + * that asm/serial.h expects. You _NEED_ to comment out the
53862 + * linux/config.h include contained inside asm/serial.h for
53863 + * this to work.
53864 + */
53865 +#undef CONFIG_SERIAL_MANY_PORTS
53866 +#undef CONFIG_SERIAL_DETECT_IRQ
53867 +#undef CONFIG_SERIAL_MULTIPORT
53868 +#undef CONFIG_HUB6
53870 +#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
53871 +#define CONFIG_SERIAL_DETECT_IRQ 1
53872 +#endif
53873 +#ifdef CONFIG_SERIAL_8250_MULTIPORT
53874 +#define CONFIG_SERIAL_MULTIPORT 1
53875 +#endif
53876 +#ifdef CONFIG_SERIAL_8250_HUB6
53877 +#define CONFIG_HUB6 1
53878 +#endif
53879 +#ifdef CONFIG_SERIAL_8250_MANY_PORTS
53880 +#define CONFIG_SERIAL_MANY_PORTS 1
53881 +#endif
53883 +#include <asm/serial.h>
53885 +static struct old_serial_port old_serial_port[] = {
53886 + SERIAL_PORT_DFNS /* defined in asm/serial.h */
53889 +#define UART_NR ARRAY_SIZE(old_serial_port)
53891 +static struct tty_driver normal, callout;
53892 +static struct tty_struct *serial8250_table[UART_NR];
53893 +static struct termios *serial8250_termios[UART_NR], *serial8250_termios_locked[UART_NR];
53895 +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
53897 +#define PORT_RSA_MAX 4
53898 +static int probe_rsa[PORT_RSA_MAX];
53899 +static int force_rsa[PORT_RSA_MAX];
53900 +#endif /* CONFIG_SERIAL_8250_RSA */
53902 +struct uart_8250_port {
53903 + struct uart_port port;
53904 + struct timer_list timer; /* "no irq" timer */
53905 + struct list_head list; /* ports on this IRQ */
53906 + unsigned int capabilities; /* port capabilities */
53907 + unsigned char acr;
53908 + unsigned char ier;
53909 + unsigned short rev;
53910 + unsigned char lcr;
53911 + unsigned char mcr;
53912 + unsigned char mcr_mask; /* mask of user bits */
53913 + unsigned char mcr_force; /* mask of forced bits */
53914 + unsigned char efr;
53915 + unsigned int lsr_break_flag;
53917 + /*
53918 + * We provide a per-port pm hook.
53919 + */
53920 + void (*pm)(struct uart_port *port,
53921 + unsigned int state, unsigned int old);
53924 +struct irq_info {
53925 + spinlock_t lock;
53926 + struct list_head *head;
53929 +static struct irq_info irq_lists[NR_IRQS];
53932 + * Here we define the default xmit fifo size used for each type of UART.
53933 + */
53934 +static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
53935 + { "unknown", 1, 0 },
53936 + { "8250", 1, 0 },
53937 + { "16450", 1, 0 },
53938 + { "16550", 1, 0 },
53939 + { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
53940 + { "Cirrus", 1, 0 },
53941 + { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
53942 + { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
53943 + { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO },
53944 + { "Startech", 1, 0 },
53945 + { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO },
53946 + { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
53947 + { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
53948 + { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }
53951 +static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
53953 + offset <<= up->port.regshift;
53955 + switch (up->port.iotype) {
53956 +#ifdef CONFIG_SERIAL_8250_HUB6
53957 + case SERIAL_IO_HUB6:
53958 + outb(up->port.hub6 - 1 + offset, up->port.iobase);
53959 + return inb(up->port.iobase + 1);
53960 +#endif
53962 + case SERIAL_IO_MEM:
53963 + return readb(up->port.membase + offset);
53965 + default:
53966 + return inb(up->port.iobase + offset);
53970 +static _INLINE_ void
53971 +serial_out(struct uart_8250_port *up, int offset, int value)
53973 + offset <<= up->port.regshift;
53975 + switch (up->port.iotype) {
53976 +#ifdef CONFIG_SERIAL_8250_HUB6
53977 + case SERIAL_IO_HUB6:
53978 + outb(up->port.hub6 - 1 + offset, up->port.iobase);
53979 + outb(value, up->port.iobase + 1);
53980 + break;
53981 +#endif
53983 + case SERIAL_IO_MEM:
53984 + writeb(value, up->port.membase + offset);
53985 + break;
53987 + default:
53988 + outb(value, up->port.iobase + offset);
53993 + * We used to support using pause I/O for certain machines. We
53994 + * haven't supported this for a while, but just in case it's badly
53995 + * needed for certain old 386 machines, I've left these #define's
53996 + * in....
53997 + */
53998 +#define serial_inp(up, offset) serial_in(up, offset)
53999 +#define serial_outp(up, offset, value) serial_out(up, offset, value)
54003 + * For the 16C950
54004 + */
54005 +static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
54007 + serial_out(up, UART_SCR, offset);
54008 + serial_out(up, UART_ICR, value);
54011 +static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
54013 + unsigned int value;
54015 + serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
54016 + serial_out(up, UART_SCR, offset);
54017 + value = serial_in(up, UART_ICR);
54018 + serial_icr_write(up, UART_ACR, up->acr);
54020 + return value;
54023 +#ifdef CONFIG_SERIAL_8250_RSA
54025 + * Attempts to turn on the RSA FIFO. Returns zero on failure.
54026 + * We set the port uart clock rate if we succeed.
54027 + */
54028 +static int __enable_rsa(struct uart_8250_port *up)
54030 + unsigned char mode;
54031 + int result;
54033 + mode = serial_inp(up, UART_RSA_MSR);
54034 + result = mode & UART_RSA_MSR_FIFO;
54036 + if (!result) {
54037 + serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
54038 + mode = serial_inp(up, UART_RSA_MSR);
54039 + result = mode & UART_RSA_MSR_FIFO;
54042 + if (result)
54043 + up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
54045 + return result;
54048 +static void enable_rsa(struct uart_8250_port *up)
54050 + if (up->port.type == PORT_RSA) {
54051 + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
54052 + spin_lock_irq(&up->port.lock);
54053 + __enable_rsa(up);
54054 + spin_unlock_irq(&up->port.lock);
54056 + if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
54057 + serial_outp(up, UART_RSA_FRR, 0);
54062 + * Attempts to turn off the RSA FIFO. Returns zero on failure.
54063 + * It is unknown why interrupts were disabled in here. However,
54064 + * the caller is expected to preserve this behaviour by grabbing
54065 + * the spinlock before calling this function.
54066 + */
54067 +static void disable_rsa(struct uart_8250_port *up)
54069 + unsigned char mode;
54070 + int result;
54072 + if (up->port.type == PORT_RSA &&
54073 + up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
54074 + spin_lock_irq(&up->port.lock);
54076 + mode = serial_inp(up, UART_RSA_MSR);
54077 + result = !(mode & UART_RSA_MSR_FIFO);
54079 + if (!result) {
54080 + serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
54081 + mode = serial_inp(up, UART_RSA_MSR);
54082 + result = !(mode & UART_RSA_MSR_FIFO);
54085 + if (result)
54086 + up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
54087 + spin_unlock_irq(&up->port.lock);
54090 +#endif /* CONFIG_SERIAL_8250_RSA */
54093 + * This is a quickie test to see how big the FIFO is.
54094 + * It doesn't work at all the time, more's the pity.
54095 + */
54096 +static int size_fifo(struct uart_8250_port *up)
54098 + unsigned char old_fcr, old_mcr, old_dll, old_dlm;
54099 + int count;
54101 + old_fcr = serial_inp(up, UART_FCR);
54102 + old_mcr = serial_inp(up, UART_MCR);
54103 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
54104 + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
54105 + serial_outp(up, UART_MCR, UART_MCR_LOOP);
54106 + serial_outp(up, UART_LCR, UART_LCR_DLAB);
54107 + old_dll = serial_inp(up, UART_DLL);
54108 + old_dlm = serial_inp(up, UART_DLM);
54109 + serial_outp(up, UART_DLL, 0x01);
54110 + serial_outp(up, UART_DLM, 0x00);
54111 + serial_outp(up, UART_LCR, 0x03);
54112 + for (count = 0; count < 256; count++)
54113 + serial_outp(up, UART_TX, count);
54114 + mdelay(20);/* FIXME - schedule_timeout */
54115 + for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
54116 + (count < 256); count++)
54117 + serial_inp(up, UART_RX);
54118 + serial_outp(up, UART_FCR, old_fcr);
54119 + serial_outp(up, UART_MCR, old_mcr);
54120 + serial_outp(up, UART_LCR, UART_LCR_DLAB);
54121 + serial_outp(up, UART_DLL, old_dll);
54122 + serial_outp(up, UART_DLM, old_dlm);
54124 + return count;
54128 + * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
54129 + * When this function is called we know it is at least a StarTech
54130 + * 16650 V2, but it might be one of several StarTech UARTs, or one of
54131 + * its clones. (We treat the broken original StarTech 16650 V1 as a
54132 + * 16550, and why not? Startech doesn't seem to even acknowledge its
54133 + * existence.)
54134 + *
54135 + * What evil have men's minds wrought...
54136 + */
54137 +static void autoconfig_has_efr(struct uart_8250_port *up)
54139 + unsigned char id1, id2, id3, rev, saved_dll, saved_dlm;
54141 + /*
54142 + * First we check to see if it's an Oxford Semiconductor UART.
54144 + * If we have to do this here because some non-National
54145 + * Semiconductor clone chips lock up if you try writing to the
54146 + * LSR register (which serial_icr_read does)
54147 + */
54149 + /*
54150 + * Check for Oxford Semiconductor 16C950.
54152 + * EFR [4] must be set else this test fails.
54154 + * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
54155 + * claims that it's needed for 952 dual UART's (which are not
54156 + * recommended for new designs).
54157 + */
54158 + up->acr = 0;
54159 + serial_out(up, UART_LCR, 0xBF);
54160 + serial_out(up, UART_EFR, 0x10);
54161 + serial_out(up, UART_LCR, 0x00);
54162 + id1 = serial_icr_read(up, UART_ID1);
54163 + id2 = serial_icr_read(up, UART_ID2);
54164 + id3 = serial_icr_read(up, UART_ID3);
54165 + rev = serial_icr_read(up, UART_REV);
54167 + DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
54169 + if (id1 == 0x16 && id2 == 0xC9 &&
54170 + (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
54171 + up->port.type = PORT_16C950;
54172 + up->rev = rev | (id3 << 8);
54173 + return;
54176 + /*
54177 + * We check for a XR16C850 by setting DLL and DLM to 0, and then
54178 + * reading back DLL and DLM. The chip type depends on the DLM
54179 + * value read back:
54180 + * 0x10 - XR16C850 and the DLL contains the chip revision.
54181 + * 0x12 - XR16C2850.
54182 + * 0x14 - XR16C854.
54183 + */
54184 + serial_outp(up, UART_LCR, UART_LCR_DLAB);
54185 + saved_dll = serial_inp(up, UART_DLL);
54186 + saved_dlm = serial_inp(up, UART_DLM);
54187 + serial_outp(up, UART_DLL, 0);
54188 + serial_outp(up, UART_DLM, 0);
54189 + id2 = serial_inp(up, UART_DLL);
54190 + id1 = serial_inp(up, UART_DLM);
54191 + serial_outp(up, UART_DLL, saved_dll);
54192 + serial_outp(up, UART_DLM, saved_dlm);
54194 + DEBUG_AUTOCONF("850id=%02x:%02x ", id1, id2);
54196 + if (id1 == 0x10 || id1 == 0x12 || id1 == 0x14) {
54197 + if (id1 == 0x10)
54198 + up->rev = id2;
54199 + up->port.type = PORT_16850;
54200 + return;
54203 + /*
54204 + * It wasn't an XR16C850.
54206 + * We distinguish between the '654 and the '650 by counting
54207 + * how many bytes are in the FIFO. I'm using this for now,
54208 + * since that's the technique that was sent to me in the
54209 + * serial driver update, but I'm not convinced this works.
54210 + * I've had problems doing this in the past. -TYT
54211 + */
54212 + if (size_fifo(up) == 64)
54213 + up->port.type = PORT_16654;
54214 + else
54215 + up->port.type = PORT_16650V2;
54219 + * We detected a chip without a FIFO. Only two fall into
54220 + * this category - the original 8250 and the 16450. The
54221 + * 16450 has a scratch register (accessible with LCR=0)
54222 + */
54223 +static void autoconfig_8250(struct uart_8250_port *up)
54225 + unsigned char scratch, status1, status2;
54227 + up->port.type = PORT_8250;
54229 + scratch = serial_in(up, UART_SCR);
54230 + serial_outp(up, UART_SCR, 0xa5);
54231 + status1 = serial_in(up, UART_SCR);
54232 + serial_outp(up, UART_SCR, 0x5a);
54233 + status2 = serial_in(up, UART_SCR);
54234 + serial_outp(up, UART_SCR, scratch);
54236 + if (status1 == 0xa5 && status2 == 0x5a)
54237 + up->port.type = PORT_16450;
54241 + * We know that the chip has FIFOs. Does it have an EFR? The
54242 + * EFR is located in the same register position as the IIR and
54243 + * we know the top two bits of the IIR are currently set. The
54244 + * EFR should contain zero. Try to read the EFR.
54245 + */
54246 +static void autoconfig_16550a(struct uart_8250_port *up)
54248 + unsigned char status1, status2;
54250 + up->port.type = PORT_16550A;
54252 + /*
54253 + * Check for presence of the EFR when DLAB is set.
54254 + * Only ST16C650V1 UARTs pass this test.
54255 + */
54256 + serial_outp(up, UART_LCR, UART_LCR_DLAB);
54257 + if (serial_in(up, UART_EFR) == 0) {
54258 + DEBUG_AUTOCONF("EFRv1 ");
54259 + up->port.type = PORT_16650;
54260 + return;
54263 + /*
54264 + * Maybe it requires 0xbf to be written to the LCR.
54265 + * (other ST16C650V2 UARTs, TI16C752A, etc)
54266 + */
54267 + serial_outp(up, UART_LCR, 0xBF);
54268 + if (serial_in(up, UART_EFR) == 0) {
54269 + DEBUG_AUTOCONF("EFRv2 ");
54270 + autoconfig_has_efr(up);
54271 + return;
54274 + /*
54275 + * Check for a National Semiconductor SuperIO chip.
54276 + * Attempt to switch to bank 2, read the value of the LOOP bit
54277 + * from EXCR1. Switch back to bank 0, change it in MCR. Then
54278 + * switch back to bank 2, read it from EXCR1 again and check
54279 + * it's changed. If so, set baud_base in EXCR2 to 921600.
54280 + */
54281 + serial_outp(up, UART_LCR, 0);
54282 + status1 = serial_in(up, UART_MCR);
54283 + serial_outp(up, UART_LCR, 0xE0);
54284 + status2 = serial_in(up, 0x02); /* EXCR1 */
54286 + if (!((status2 ^ status1) & UART_MCR_LOOP)) {
54287 + serial_outp(up, UART_LCR, 0);
54288 + serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
54289 + serial_outp(up, UART_LCR, 0xE0);
54290 + status2 = serial_in(up, 0x02); /* EXCR1 */
54291 + serial_outp(up, UART_LCR, 0);
54292 + serial_outp(up, UART_MCR, status1);
54294 + if ((status2 ^ status1) & UART_MCR_LOOP) {
54295 + serial_outp(up, UART_LCR, 0xE0);
54296 + status1 = serial_in(up, 0x04); /* EXCR1 */
54297 + status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
54298 + status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
54299 + serial_outp(up, 0x04, status1);
54300 + serial_outp(up, UART_LCR, 0);
54302 + up->port.type = PORT_NS16550A;
54303 + up->port.uartclk = 921600*16;
54304 + return;
54308 + /*
54309 + * No EFR. Try to detect a TI16750, which only sets bit 5 of
54310 + * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
54311 + * Try setting it with and without DLAB set. Cheap clones
54312 + * set bit 5 without DLAB set.
54313 + */
54314 + serial_outp(up, UART_LCR, 0);
54315 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
54316 + status1 = serial_in(up, UART_IIR) >> 5;
54317 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
54318 + serial_outp(up, UART_LCR, UART_LCR_DLAB);
54319 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
54320 + status2 = serial_in(up, UART_IIR) >> 5;
54321 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
54323 + DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
54325 + if (status1 == 6 && status2 == 7) {
54326 + up->port.type = PORT_16750;
54327 + return;
54332 + * This routine is called by rs_init() to initialize a specific serial
54333 + * port. It determines what type of UART chip this serial port is
54334 + * using: 8250, 16450, 16550, 16550A. The important question is
54335 + * whether or not this UART is a 16550A or not, since this will
54336 + * determine whether or not we can use its FIFO features or not.
54337 + */
54338 +static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
54340 + unsigned char status1, scratch, scratch2, scratch3;
54341 + unsigned char save_lcr, save_mcr;
54342 + unsigned long flags;
54344 + if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
54345 + return;
54347 + DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ",
54348 + up->port.line, up->port.iobase, up->port.membase);
54350 + /*
54351 + * We really do need global IRQs disabled here - we're going to
54352 + * be frobbing the chips IRQ enable register to see if it exists.
54353 + */
54354 + spin_lock_irqsave(&up->port.lock, flags);
54356 + if (!(up->port.flags & UPF_BUGGY_UART)) {
54357 + /*
54358 + * Do a simple existence test first; if we fail this,
54359 + * there's no point trying anything else.
54360 + *
54361 + * 0x80 is used as a nonsense port to prevent against
54362 + * false positives due to ISA bus float. The
54363 + * assumption is that 0x80 is a non-existent port;
54364 + * which should be safe since include/asm/io.h also
54365 + * makes this assumption.
54367 + * Note: this is safe as long as MCR bit 4 is clear
54368 + * and the device is in "PC" mode.
54369 + */
54370 + scratch = serial_inp(up, UART_IER);
54371 + serial_outp(up, UART_IER, 0);
54372 +#ifdef __i386__
54373 + outb(0xff, 0x080);
54374 +#endif
54375 + scratch2 = serial_inp(up, UART_IER);
54376 + serial_outp(up, UART_IER, 0x0F);
54377 +#ifdef __i386__
54378 + outb(0, 0x080);
54379 +#endif
54380 + scratch3 = serial_inp(up, UART_IER);
54381 + serial_outp(up, UART_IER, scratch);
54382 + if (scratch2 != 0 || scratch3 != 0x0F) {
54383 + /*
54384 + * We failed; there's nothing here
54385 + */
54386 + DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
54387 + scratch2, scratch3);
54388 + goto out;
54392 + save_mcr = serial_in(up, UART_MCR);
54393 + save_lcr = serial_in(up, UART_LCR);
54395 + /*
54396 + * Check to see if a UART is really there. Certain broken
54397 + * internal modems based on the Rockwell chipset fail this
54398 + * test, because they apparently don't implement the loopback
54399 + * test mode. So this test is skipped on the COM 1 through
54400 + * COM 4 ports. This *should* be safe, since no board
54401 + * manufacturer would be stupid enough to design a board
54402 + * that conflicts with COM 1-4 --- we hope!
54403 + */
54404 + if (!(up->port.flags & UPF_SKIP_TEST)) {
54405 + serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
54406 + status1 = serial_inp(up, UART_MSR) & 0xF0;
54407 + serial_outp(up, UART_MCR, save_mcr);
54408 + if (status1 != 0x90) {
54409 + DEBUG_AUTOCONF("LOOP test failed (%02x) ",
54410 + status1);
54411 + goto out;
54415 + /*
54416 + * We're pretty sure there's a port here. Lets find out what
54417 + * type of port it is. The IIR top two bits allows us to find
54418 + * out if its 8250 or 16450, 16550, 16550A or later. This
54419 + * determines what we test for next.
54421 + * We also initialise the EFR (if any) to zero for later. The
54422 + * EFR occupies the same register location as the FCR and IIR.
54423 + */
54424 + serial_outp(up, UART_LCR, 0xBF);
54425 + serial_outp(up, UART_EFR, 0);
54426 + serial_outp(up, UART_LCR, 0);
54428 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
54429 + scratch = serial_in(up, UART_IIR) >> 6;
54431 + DEBUG_AUTOCONF("iir=%d ", scratch);
54433 + switch (scratch) {
54434 + case 0:
54435 + autoconfig_8250(up);
54436 + break;
54437 + case 1:
54438 + up->port.type = PORT_UNKNOWN;
54439 + break;
54440 + case 2:
54441 + up->port.type = PORT_16550;
54442 + break;
54443 + case 3:
54444 + autoconfig_16550a(up);
54445 + break;
54448 +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
54449 + /*
54450 + * Only probe for RSA ports if we got the region.
54451 + */
54452 + if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
54453 + int i;
54455 + for (i = 0 ; i < PORT_RSA_MAX ; ++i) {
54456 + if (!probe_rsa[i] && !force_rsa[i])
54457 + break;
54458 + if (((probe_rsa[i] != up->port.iobase) ||
54459 + check_region(up->port.iobase + UART_RSA_BASE, 16)) &&
54460 + (force_rsa[i] != up->port.iobase))
54461 + continue;
54462 + if (__enable_rsa(up)) {
54463 + up->port.type = PORT_RSA;
54464 + break;
54468 +#endif
54469 + serial_outp(up, UART_LCR, save_lcr);
54471 + up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
54472 + up->capabilities = uart_config[up->port.type].flags;
54474 + if (up->port.type == PORT_UNKNOWN)
54475 + goto out;
54477 + /*
54478 + * Reset the UART.
54479 + */
54480 +#ifdef CONFIG_SERIAL_8250_RSA
54481 + if (up->port.type == PORT_RSA)
54482 + serial_outp(up, UART_RSA_FRR, 0);
54483 +#endif
54484 + serial_outp(up, UART_MCR, save_mcr);
54485 + serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
54486 + UART_FCR_CLEAR_RCVR |
54487 + UART_FCR_CLEAR_XMIT));
54488 + serial_outp(up, UART_FCR, 0);
54489 + (void)serial_in(up, UART_RX);
54490 + serial_outp(up, UART_IER, 0);
54492 + out:
54493 + spin_unlock_irqrestore(&up->port.lock, flags);
54495 +#ifdef CONFIG_SERIAL_8250_RSA
54496 + if (up->port.iobase && up->port.type == PORT_RSA) {
54497 + release_region(up->port.iobase, 8);
54498 + request_region(up->port.iobase + UART_RSA_BASE, 16,
54499 + "serial_rsa");
54501 +#endif
54502 + DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
54505 +static void autoconfig_irq(struct uart_8250_port *up)
54507 + unsigned char save_mcr, save_ier;
54508 + unsigned char save_ICP = 0;
54509 + unsigned int ICP = 0;
54510 + unsigned long irqs;
54511 + int irq;
54513 + if (up->port.flags & UPF_FOURPORT) {
54514 + ICP = (up->port.iobase & 0xfe0) | 0x1f;
54515 + save_ICP = inb_p(ICP);
54516 + outb_p(0x80, ICP);
54517 + (void) inb_p(ICP);
54520 + /* forget possible initially masked and pending IRQ */
54521 + probe_irq_off(probe_irq_on());
54522 + save_mcr = serial_inp(up, UART_MCR);
54523 + save_ier = serial_inp(up, UART_IER);
54524 + serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
54526 + irqs = probe_irq_on();
54527 + serial_outp(up, UART_MCR, 0);
54528 + udelay (10);
54529 + if (up->port.flags & UPF_FOURPORT) {
54530 + serial_outp(up, UART_MCR,
54531 + UART_MCR_DTR | UART_MCR_RTS);
54532 + } else {
54533 + serial_outp(up, UART_MCR,
54534 + UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
54536 + serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
54537 + (void)serial_inp(up, UART_LSR);
54538 + (void)serial_inp(up, UART_RX);
54539 + (void)serial_inp(up, UART_IIR);
54540 + (void)serial_inp(up, UART_MSR);
54541 + serial_outp(up, UART_TX, 0xFF);
54542 + udelay (20);
54543 + irq = probe_irq_off(irqs);
54545 + serial_outp(up, UART_MCR, save_mcr);
54546 + serial_outp(up, UART_IER, save_ier);
54548 + if (up->port.flags & UPF_FOURPORT)
54549 + outb_p(save_ICP, ICP);
54551 + up->port.irq = (irq > 0) ? irq : 0;
54554 +static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
54556 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54558 + if (up->ier & UART_IER_THRI) {
54559 + up->ier &= ~UART_IER_THRI;
54560 + serial_out(up, UART_IER, up->ier);
54562 + if (up->port.type == PORT_16C950 && tty_stop) {
54563 + up->acr |= UART_ACR_TXDIS;
54564 + serial_icr_write(up, UART_ACR, up->acr);
54568 +static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
54570 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54572 + if (!(up->ier & UART_IER_THRI)) {
54573 + up->ier |= UART_IER_THRI;
54574 + serial_out(up, UART_IER, up->ier);
54576 + /*
54577 + * We only do this from uart_start
54578 + */
54579 + if (tty_start && up->port.type == PORT_16C950) {
54580 + up->acr &= ~UART_ACR_TXDIS;
54581 + serial_icr_write(up, UART_ACR, up->acr);
54585 +static void serial8250_stop_rx(struct uart_port *port)
54587 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54589 + up->ier &= ~UART_IER_RLSI;
54590 + up->port.read_status_mask &= ~UART_LSR_DR;
54591 + serial_out(up, UART_IER, up->ier);
54594 +static void serial8250_enable_ms(struct uart_port *port)
54596 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54598 + up->ier |= UART_IER_MSI;
54599 + serial_out(up, UART_IER, up->ier);
54602 +static _INLINE_ void
54603 +receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
54605 + struct tty_struct *tty = up->port.info->tty;
54606 + unsigned char ch;
54607 + int max_count = 256;
54609 + do {
54610 + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
54611 + /*
54612 + * FIXME: Deadlock can happen here if we're a
54613 + * low-latency port. We're holding the per-port
54614 + * spinlock, and we call flush_to_ldisc->
54615 + * n_tty_receive_buf->n_tty_receive_char->
54616 + * opost->uart_put_char.
54617 + */
54618 + tty->flip.tqueue.routine((void *)tty);
54619 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
54620 + return; // if TTY_DONT_FLIP is set
54622 + ch = serial_inp(up, UART_RX);
54623 + *tty->flip.char_buf_ptr = ch;
54624 + *tty->flip.flag_buf_ptr = TTY_NORMAL;
54625 + up->port.icount.rx++;
54627 + if (*status & (UART_LSR_BI | UART_LSR_PE |
54628 + UART_LSR_FE | UART_LSR_OE)) {
54629 + /*
54630 + * For statistics only
54631 + */
54632 + if (*status & UART_LSR_BI) {
54633 + *status &= ~(UART_LSR_FE | UART_LSR_PE);
54634 + up->port.icount.brk++;
54635 + /*
54636 + * We do the SysRQ and SAK checking
54637 + * here because otherwise the break
54638 + * may get masked by ignore_status_mask
54639 + * or read_status_mask.
54640 + */
54641 + if (uart_handle_break(&up->port))
54642 + goto ignore_char;
54643 + } else if (*status & UART_LSR_PE)
54644 + up->port.icount.parity++;
54645 + else if (*status & UART_LSR_FE)
54646 + up->port.icount.frame++;
54647 + if (*status & UART_LSR_OE)
54648 + up->port.icount.overrun++;
54650 + /*
54651 + * Mask off conditions which should be ingored.
54652 + */
54653 + *status &= up->port.read_status_mask;
54655 +#ifdef CONFIG_SERIAL_8250_CONSOLE
54656 + if (up->port.line == up->port.cons->index) {
54657 + /* Recover the break flag from console xmit */
54658 + *status |= up->lsr_break_flag;
54659 + up->lsr_break_flag = 0;
54661 +#endif
54662 + if (*status & UART_LSR_BI) {
54663 + DEBUG_INTR("handling break....");
54664 + *tty->flip.flag_buf_ptr = TTY_BREAK;
54665 + } else if (*status & UART_LSR_PE)
54666 + *tty->flip.flag_buf_ptr = TTY_PARITY;
54667 + else if (*status & UART_LSR_FE)
54668 + *tty->flip.flag_buf_ptr = TTY_FRAME;
54670 + if (uart_handle_sysrq_char(&up->port, ch, regs))
54671 + goto ignore_char;
54672 + if ((*status & up->port.ignore_status_mask) == 0) {
54673 + tty->flip.flag_buf_ptr++;
54674 + tty->flip.char_buf_ptr++;
54675 + tty->flip.count++;
54677 + if ((*status & UART_LSR_OE) &&
54678 + tty->flip.count < TTY_FLIPBUF_SIZE) {
54679 + /*
54680 + * Overrun is special, since it's reported
54681 + * immediately, and doesn't affect the current
54682 + * character.
54683 + */
54684 + *tty->flip.flag_buf_ptr = TTY_OVERRUN;
54685 + tty->flip.flag_buf_ptr++;
54686 + tty->flip.char_buf_ptr++;
54687 + tty->flip.count++;
54689 + ignore_char:
54690 + *status = serial_inp(up, UART_LSR);
54691 + } while ((*status & UART_LSR_DR) && (max_count-- > 0));
54692 + tty_flip_buffer_push(tty);
54695 +static _INLINE_ void transmit_chars(struct uart_8250_port *up)
54697 + struct circ_buf *xmit = &up->port.info->xmit;
54698 + int count;
54700 + if (up->port.x_char) {
54701 + serial_outp(up, UART_TX, up->port.x_char);
54702 + up->port.icount.tx++;
54703 + up->port.x_char = 0;
54704 + return;
54706 + if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
54707 + serial8250_stop_tx(&up->port, 0);
54708 + return;
54711 + count = up->port.fifosize;
54712 + do {
54713 + serial_out(up, UART_TX, xmit->buf[xmit->tail]);
54714 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
54715 + up->port.icount.tx++;
54716 + if (uart_circ_empty(xmit))
54717 + break;
54718 + } while (--count > 0);
54720 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
54721 + uart_write_wakeup(&up->port);
54723 + DEBUG_INTR("THRE...");
54725 + if (uart_circ_empty(xmit))
54726 + serial8250_stop_tx(&up->port, 0);
54729 +static _INLINE_ void check_modem_status(struct uart_8250_port *up)
54731 + int status;
54733 + status = serial_in(up, UART_MSR);
54735 + if ((status & UART_MSR_ANY_DELTA) == 0)
54736 + return;
54738 + if (status & UART_MSR_TERI)
54739 + up->port.icount.rng++;
54740 + if (status & UART_MSR_DDSR)
54741 + up->port.icount.dsr++;
54742 + if (status & UART_MSR_DDCD)
54743 + uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
54744 + if (status & UART_MSR_DCTS)
54745 + uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
54747 + wake_up_interruptible(&up->port.info->delta_msr_wait);
54751 + * This handles the interrupt from one port.
54752 + */
54753 +static inline void
54754 +serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
54756 + unsigned int status = serial_inp(up, UART_LSR);
54758 + DEBUG_INTR("status = %x...", status);
54760 + if (status & UART_LSR_DR)
54761 + receive_chars(up, &status, regs);
54762 + check_modem_status(up);
54763 + if (status & UART_LSR_THRE)
54764 + transmit_chars(up);
54768 + * This is the serial driver's interrupt routine.
54770 + * Arjan thinks the old way was overly complex, so it got simplified.
54771 + * Alan disagrees, saying that need the complexity to handle the weird
54772 + * nature of ISA shared interrupts. (This is a special exception.)
54774 + * In order to handle ISA shared interrupts properly, we need to check
54775 + * that all ports have been serviced, and therefore the ISA interrupt
54776 + * line has been de-asserted.
54778 + * This means we need to loop through all ports. checking that they
54779 + * don't have an interrupt pending.
54780 + */
54781 +static void serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
54783 + struct irq_info *i = dev_id;
54784 + struct list_head *l, *end = NULL;
54785 + int pass_counter = 0;
54787 + DEBUG_INTR("serial8250_interrupt(%d)...", irq);
54789 + spin_lock(&i->lock);
54791 + l = i->head;
54792 + do {
54793 + struct uart_8250_port *up;
54794 + unsigned int iir;
54796 + up = list_entry(l, struct uart_8250_port, list);
54798 + iir = serial_in(up, UART_IIR);
54799 + if (!(iir & UART_IIR_NO_INT)) {
54800 + spin_lock(&up->port.lock);
54801 + serial8250_handle_port(up, regs);
54802 + spin_unlock(&up->port.lock);
54804 + end = NULL;
54805 + } else if (end == NULL)
54806 + end = l;
54808 + l = l->next;
54810 + if (l == i->head && pass_counter++ > PASS_LIMIT) {
54811 + /* If we hit this, we're dead. */
54812 + printk(KERN_ERR "serial8250: too much work for "
54813 + "irq%d\n", irq);
54814 + break;
54816 + } while (l != end);
54818 + spin_unlock(&i->lock);
54820 + DEBUG_INTR("end.\n");
54824 + * To support ISA shared interrupts, we need to have one interrupt
54825 + * handler that ensures that the IRQ line has been deasserted
54826 + * before returning. Failing to do this will result in the IRQ
54827 + * line being stuck active, and, since ISA irqs are edge triggered,
54828 + * no more IRQs will be seen.
54829 + */
54830 +static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
54832 + spin_lock_irq(&i->lock);
54834 + if (!list_empty(i->head)) {
54835 + if (i->head == &up->list)
54836 + i->head = i->head->next;
54837 + list_del(&up->list);
54838 + } else {
54839 + BUG_ON(i->head != &up->list);
54840 + i->head = NULL;
54843 + spin_unlock_irq(&i->lock);
54846 +static int serial_link_irq_chain(struct uart_8250_port *up)
54848 + struct irq_info *i = irq_lists + up->port.irq;
54849 + int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
54851 + spin_lock_irq(&i->lock);
54853 + if (i->head) {
54854 + list_add(&up->list, i->head);
54855 + spin_unlock_irq(&i->lock);
54857 + ret = 0;
54858 + } else {
54859 + INIT_LIST_HEAD(&up->list);
54860 + i->head = &up->list;
54861 + spin_unlock_irq(&i->lock);
54863 + ret = request_irq(up->port.irq, serial8250_interrupt,
54864 + irq_flags, "serial", i);
54865 + if (ret < 0)
54866 + serial_do_unlink(i, up);
54869 + return ret;
54872 +static void serial_unlink_irq_chain(struct uart_8250_port *up)
54874 + struct irq_info *i = irq_lists + up->port.irq;
54876 + BUG_ON(i->head == NULL);
54878 + if (list_empty(i->head))
54879 + free_irq(up->port.irq, i);
54881 + serial_do_unlink(i, up);
54885 + * This function is used to handle ports that do not have an
54886 + * interrupt. This doesn't work very well for 16450's, but gives
54887 + * barely passable results for a 16550A. (Although at the expense
54888 + * of much CPU overhead).
54889 + */
54890 +static void serial8250_timeout(unsigned long data)
54892 + struct uart_8250_port *up = (struct uart_8250_port *)data;
54893 + unsigned int timeout;
54894 + unsigned int iir;
54896 + iir = serial_in(up, UART_IIR);
54897 + if (!(iir & UART_IIR_NO_INT)) {
54898 + spin_lock(&up->port.lock);
54899 + serial8250_handle_port(up, NULL);
54900 + spin_unlock(&up->port.lock);
54903 + timeout = up->port.timeout;
54904 + timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
54905 + mod_timer(&up->timer, jiffies + timeout);
54908 +static unsigned int serial8250_tx_empty(struct uart_port *port)
54910 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54911 + unsigned long flags;
54912 + unsigned int ret;
54914 + spin_lock_irqsave(&up->port.lock, flags);
54915 + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
54916 + spin_unlock_irqrestore(&up->port.lock, flags);
54918 + return ret;
54921 +static unsigned int serial8250_get_mctrl(struct uart_port *port)
54923 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54924 + unsigned long flags;
54925 + unsigned char status;
54926 + unsigned int ret;
54928 + spin_lock_irqsave(&up->port.lock, flags);
54929 + status = serial_in(up, UART_MSR);
54930 + spin_unlock_irqrestore(&up->port.lock, flags);
54932 + ret = 0;
54933 + if (status & UART_MSR_DCD)
54934 + ret |= TIOCM_CAR;
54935 + if (status & UART_MSR_RI)
54936 + ret |= TIOCM_RNG;
54937 + if (status & UART_MSR_DSR)
54938 + ret |= TIOCM_DSR;
54939 + if (status & UART_MSR_CTS)
54940 + ret |= TIOCM_CTS;
54941 + return ret;
54944 +static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
54946 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54947 + unsigned char mcr = 0;
54949 + if (mctrl & TIOCM_RTS)
54950 + mcr |= UART_MCR_RTS;
54951 + if (mctrl & TIOCM_DTR)
54952 + mcr |= UART_MCR_DTR;
54953 + if (mctrl & TIOCM_OUT1)
54954 + mcr |= UART_MCR_OUT1;
54955 + if (mctrl & TIOCM_OUT2)
54956 + mcr |= UART_MCR_OUT2;
54957 + if (mctrl & TIOCM_LOOP)
54958 + mcr |= UART_MCR_LOOP;
54960 + mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
54962 + serial_out(up, UART_MCR, mcr);
54965 +static void serial8250_break_ctl(struct uart_port *port, int break_state)
54967 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54968 + unsigned long flags;
54970 + spin_lock_irqsave(&up->port.lock, flags);
54971 + if (break_state == -1)
54972 + up->lcr |= UART_LCR_SBC;
54973 + else
54974 + up->lcr &= ~UART_LCR_SBC;
54975 + serial_out(up, UART_LCR, up->lcr);
54976 + spin_unlock_irqrestore(&up->port.lock, flags);
54979 +static int serial8250_startup(struct uart_port *port)
54981 + struct uart_8250_port *up = (struct uart_8250_port *)port;
54982 + unsigned long flags;
54983 + unsigned char lsr, iir;
54984 + int retval;
54986 + up->capabilities = uart_config[up->port.type].flags;
54987 + up->mcr = 0;
54988 + up->efr = 0;
54989 + up->ier = 0;
54991 + if (up->port.type == PORT_16C950) {
54992 + /* Wake up and initialize UART */
54993 + up->acr = 0;
54994 + serial_outp(up, UART_LCR, 0xBF);
54995 + serial_outp(up, UART_EFR, UART_EFR_ECB);
54996 + serial_outp(up, UART_IER, 0);
54997 + serial_outp(up, UART_LCR, 0);
54998 + serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
54999 + serial_outp(up, UART_LCR, 0xBF);
55000 + serial_outp(up, UART_EFR, UART_EFR_ECB);
55001 + serial_outp(up, UART_LCR, 0);
55004 +#ifdef CONFIG_SERIAL_8250_RSA
55005 + /*
55006 + * If this is an RSA port, see if we can kick it up to the
55007 + * higher speed clock.
55008 + */
55009 + enable_rsa(up);
55010 +#endif
55012 + /*
55013 + * Clear the FIFO buffers and disable them.
55014 + * (they will be reeanbled in change_speed())
55015 + */
55016 + if (up->capabilities & UART_CLEAR_FIFO) {
55017 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
55018 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
55019 + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
55020 + serial_outp(up, UART_FCR, 0);
55023 + /*
55024 + * Clear the interrupt registers.
55025 + */
55026 + (void) serial_inp(up, UART_LSR);
55027 + (void) serial_inp(up, UART_RX);
55028 + (void) serial_inp(up, UART_IIR);
55029 + (void) serial_inp(up, UART_MSR);
55031 + /*
55032 + * At this point, there's no way the LSR could still be 0xff;
55033 + * if it is, then bail out, because there's likely no UART
55034 + * here.
55035 + */
55036 + if (!(up->port.flags & UPF_BUGGY_UART) &&
55037 + (serial_inp(up, UART_LSR) == 0xff)) {
55038 + printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
55039 + return -ENODEV;
55042 + /*
55043 + * If the "interrupt" for this port doesn't correspond with any
55044 + * hardware interrupt, we use a timer-based system. The original
55045 + * driver used to do this with IRQ0.
55046 + */
55047 + if (!is_real_interrupt(up->port.irq)) {
55048 + unsigned int timeout = up->port.timeout;
55050 + timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
55052 + up->timer.data = (unsigned long)up;
55053 + mod_timer(&up->timer, jiffies + timeout);
55054 + } else {
55055 + retval = serial_link_irq_chain(up);
55056 + if (retval)
55057 + return retval;
55060 + /*
55061 + * Now, initialize the UART
55062 + */
55063 + serial_outp(up, UART_LCR, UART_LCR_WLEN8);
55065 + spin_lock_irqsave(&up->port.lock, flags);
55066 + if (up->port.flags & UPF_FOURPORT) {
55067 + if (!is_real_interrupt(up->port.irq))
55068 + up->port.mctrl |= TIOCM_OUT1;
55069 + } else
55070 + /*
55071 + * Most PC uarts need OUT2 raised to enable interrupts.
55072 + */
55073 + if (is_real_interrupt(up->port.irq))
55074 + up->port.mctrl |= TIOCM_OUT2;
55076 + serial8250_set_mctrl(&up->port, up->port.mctrl);
55078 + /*
55079 + * Do a quick test to see if we receive an
55080 + * interrupt when we enable the TX irq.
55081 + */
55082 + serial_outp(up, UART_IER, UART_IER_THRI);
55083 + lsr = serial_in(up, UART_LSR);
55084 + iir = serial_in(up, UART_IIR);
55085 + serial_outp(up, UART_IER, 0);
55087 + if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
55088 + up->capabilities |= UART_BAD_TX_ENABLE;
55089 + printk("ttyS%d - enabling bad tx status workarounds\n",
55090 + port->line);
55093 + spin_unlock_irqrestore(&up->port.lock, flags);
55095 + /*
55096 + * Finally, enable interrupts. Note: Modem status interrupts
55097 + * are set via change_speed(), which will be occuring imminently
55098 + * anyway, so we don't enable them here.
55099 + */
55100 + up->ier = UART_IER_RLSI | UART_IER_RDI;
55101 + serial_outp(up, UART_IER, up->ier);
55103 + if (up->port.flags & UPF_FOURPORT) {
55104 + unsigned int icp;
55105 + /*
55106 + * Enable interrupts on the AST Fourport board
55107 + */
55108 + icp = (up->port.iobase & 0xfe0) | 0x01f;
55109 + outb_p(0x80, icp);
55110 + (void) inb_p(icp);
55113 + /*
55114 + * And clear the interrupt registers again for luck.
55115 + */
55116 + (void) serial_inp(up, UART_LSR);
55117 + (void) serial_inp(up, UART_RX);
55118 + (void) serial_inp(up, UART_IIR);
55119 + (void) serial_inp(up, UART_MSR);
55121 + return 0;
55124 +static void serial8250_shutdown(struct uart_port *port)
55126 + struct uart_8250_port *up = (struct uart_8250_port *)port;
55127 + unsigned long flags;
55129 + /*
55130 + * Disable interrupts from this port
55131 + */
55132 + up->ier = 0;
55133 + serial_outp(up, UART_IER, 0);
55135 + spin_lock_irqsave(&up->port.lock, flags);
55136 + if (up->port.flags & UPF_FOURPORT) {
55137 + /* reset interrupts on the AST Fourport board */
55138 + inb((up->port.iobase & 0xfe0) | 0x1f);
55139 + up->port.mctrl |= TIOCM_OUT1;
55140 + } else
55141 + up->port.mctrl &= ~TIOCM_OUT2;
55143 + serial8250_set_mctrl(&up->port, up->port.mctrl);
55144 + spin_unlock_irqrestore(&up->port.lock, flags);
55146 + /*
55147 + * Disable break condition and FIFOs
55148 + */
55149 + serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
55150 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
55151 + UART_FCR_CLEAR_RCVR |
55152 + UART_FCR_CLEAR_XMIT);
55153 + serial_outp(up, UART_FCR, 0);
55155 +#ifdef CONFIG_SERIAL_8250_RSA
55156 + /*
55157 + * Reset the RSA board back to 115kbps compat mode.
55158 + */
55159 + disable_rsa(up);
55160 +#endif
55162 + /*
55163 + * Read data port to reset things, and then unlink from
55164 + * the IRQ chain.
55165 + */
55166 + (void) serial_in(up, UART_RX);
55168 + if (!is_real_interrupt(up->port.irq))
55169 + del_timer_sync(&up->timer);
55170 + else
55171 + serial_unlink_irq_chain(up);
55174 +static void serial8250_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
55176 + struct uart_8250_port *up = (struct uart_8250_port *)port;
55177 + unsigned char cval, fcr = 0;
55178 + unsigned long flags;
55180 + switch (cflag & CSIZE) {
55181 + case CS5:
55182 + cval = 0x00;
55183 + break;
55184 + case CS6:
55185 + cval = 0x01;
55186 + break;
55187 + case CS7:
55188 + cval = 0x02;
55189 + break;
55190 + default:
55191 + case CS8:
55192 + cval = 0x03;
55193 + break;
55196 + if (cflag & CSTOPB)
55197 + cval |= 0x04;
55198 + if (cflag & PARENB)
55199 + cval |= UART_LCR_PARITY;
55200 + if (!(cflag & PARODD))
55201 + cval |= UART_LCR_EPAR;
55202 +#ifdef CMSPAR
55203 + if (cflag & CMSPAR)
55204 + cval |= UART_LCR_SPAR;
55205 +#endif
55207 + /*
55208 + * Work around a bug in the Oxford Semiconductor 952 rev B
55209 + * chip which causes it to seriously miscalculate baud rates
55210 + * when DLL is 0.
55211 + */
55212 + if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
55213 + up->rev == 0x5201)
55214 + quot ++;
55216 + if (up->capabilities & UART_USE_FIFO) {
55217 + if ((up->port.uartclk / quot) < (2400 * 16))
55218 + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
55219 +#ifdef CONFIG_SERIAL_8250_RSA
55220 + else if (up->port.type == PORT_RSA)
55221 + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
55222 +#endif
55223 + else
55224 + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
55226 + if (up->port.type == PORT_16750)
55227 + fcr |= UART_FCR7_64BYTE;
55229 + /*
55230 + * Ok, we're now changing the port state. Do it with
55231 + * interrupts disabled.
55232 + */
55233 + spin_lock_irqsave(&up->port.lock, flags);
55235 + up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
55236 + if (iflag & IGNPAR)
55237 + up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
55238 + if (iflag & (BRKINT | PARMRK))
55239 + up->port.read_status_mask |= UART_LSR_BI;
55241 + /*
55242 + * Characteres to ignore
55243 + */
55244 + up->port.ignore_status_mask = 0;
55245 + if (iflag & IGNPAR)
55246 + up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
55247 + if (iflag & IGNBRK) {
55248 + up->port.ignore_status_mask |= UART_LSR_BI;
55249 + /*
55250 + * If we're ignoring parity and break indicators,
55251 + * ignore overruns too (for real raw support).
55252 + */
55253 + if (iflag & IGNPAR)
55254 + up->port.ignore_status_mask |= UART_LSR_OE;
55257 + /*
55258 + * ignore all characters if CREAD is not set
55259 + */
55260 + if ((cflag & CREAD) == 0)
55261 + up->port.ignore_status_mask |= UART_LSR_DR;
55263 + /*
55264 + * CTS flow control flag and modem status interrupts
55265 + */
55266 + up->ier &= ~UART_IER_MSI;
55267 + if (UART_ENABLE_MS(&up->port, cflag))
55268 + up->ier |= UART_IER_MSI;
55270 + serial_out(up, UART_IER, up->ier);
55272 + if (up->capabilities & UART_MCRAFE) {
55273 + /*
55274 + * TI16C750 hardware flow control
55275 + */
55276 + up->mcr &= ~UART_MCR_AFE;
55277 + if (cflag & CRTSCTS)
55278 + up->mcr |= UART_MCR_AFE;
55280 + if (up->capabilities & UART_EFRAFE) {
55281 + /*
55282 + * TI16C752/Startech hardware flow control
55283 + * FIXME:
55284 + * - TI16C752 requires control thresholds
55285 + * to be set for auto-RTS.
55286 + * - We only enable auto-CTS here.
55287 + * Note: ST16C654 does not allow MCR bit 1
55288 + * to override RTS when UART_EFR_RTS is set.
55289 + */
55290 + up->efr &= ~UART_EFR_CTS;
55291 + if (cflag & CRTSCTS)
55292 + up->efr |= UART_EFR_CTS;
55293 + serial_outp(up, UART_LCR, 0xBF);
55294 + serial_outp(up, UART_EFR, up->efr);
55297 + if (up->capabilities & UART_NATSEMI) {
55298 + /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
55299 + serial_outp(up, UART_LCR, 0xe0);
55300 + } else {
55301 + serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
55303 + serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */
55304 + serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */
55305 + if (up->port.type == PORT_16750)
55306 + serial_outp(up, UART_FCR, fcr); /* set fcr */
55307 + serial_outp(up, UART_LCR, cval); /* reset DLAB */
55308 + up->lcr = cval; /* Save LCR */
55309 + if (up->port.type != PORT_16750) {
55310 + if (fcr & UART_FCR_ENABLE_FIFO) {
55311 + /* emulated UARTs (Lucent Venus 167x) need two steps */
55312 + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
55314 + serial_outp(up, UART_FCR, fcr); /* set fcr */
55316 + serial8250_set_mctrl(&up->port, up->port.mctrl);
55317 + spin_unlock_irqrestore(&up->port.lock, flags);
55320 +static void
55321 +serial8250_pm(struct uart_port *port, unsigned int state,
55322 + unsigned int oldstate)
55324 + struct uart_8250_port *up = (struct uart_8250_port *)port;
55325 + if (state) {
55326 + /* sleep */
55327 + if (up->capabilities & UART_STARTECH) {
55328 + /* Arrange to enter sleep mode */
55329 + serial_outp(up, UART_LCR, 0xBF);
55330 + serial_outp(up, UART_EFR, UART_EFR_ECB);
55331 + serial_outp(up, UART_LCR, 0);
55332 + serial_outp(up, UART_IER, UART_IERX_SLEEP);
55333 + serial_outp(up, UART_LCR, 0xBF);
55334 + serial_outp(up, UART_EFR, 0);
55335 + serial_outp(up, UART_LCR, 0);
55337 + if (up->port.type == PORT_16750) {
55338 + /* Arrange to enter sleep mode */
55339 + serial_outp(up, UART_IER, UART_IERX_SLEEP);
55341 + } else {
55342 + /* wake */
55343 + if (up->capabilities & UART_STARTECH) {
55344 + /* Wake up UART */
55345 + serial_outp(up, UART_LCR, 0xBF);
55346 + serial_outp(up, UART_EFR, UART_EFR_ECB);
55347 + /*
55348 + * Turn off LCR == 0xBF so we actually set the IER
55349 + * register on the XR16C850
55350 + */
55351 + serial_outp(up, UART_LCR, 0);
55352 + serial_outp(up, UART_IER, 0);
55353 + /*
55354 + * Now reset LCR so we can turn off the ECB bit
55355 + */
55356 + serial_outp(up, UART_LCR, 0xBF);
55357 + serial_outp(up, UART_EFR, 0);
55358 + /*
55359 + * For a XR16C850, we need to set the trigger levels
55360 + */
55361 + if (up->port.type == PORT_16850) {
55362 + unsigned char fctr;
55364 + fctr = serial_inp(up, UART_FCTR) &
55365 + ~(UART_FCTR_RX | UART_FCTR_TX);
55366 + serial_outp(up, UART_FCTR, fctr |
55367 + UART_FCTR_TRGD |
55368 + UART_FCTR_RX);
55369 + serial_outp(up, UART_TRG, UART_TRG_96);
55370 + serial_outp(up, UART_FCTR, fctr |
55371 + UART_FCTR_TRGD |
55372 + UART_FCTR_TX);
55373 + serial_outp(up, UART_TRG, UART_TRG_96);
55375 + serial_outp(up, UART_LCR, 0);
55378 + if (up->port.type == PORT_16750) {
55379 + /* Wake up UART */
55380 + serial_outp(up, UART_IER, 0);
55386 + * Resource handling. This is complicated by the fact that resources
55387 + * depend on the port type. Maybe we should be claiming the standard
55388 + * 8250 ports, and then trying to get other resources as necessary?
55389 + */
55390 +static int
55391 +serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
55393 + unsigned int size = 8 << up->port.regshift;
55394 + int ret = 0;
55396 + switch (up->port.iotype) {
55397 + case SERIAL_IO_MEM:
55398 + if (up->port.mapbase) {
55399 + *res = request_mem_region(up->port.mapbase, size, "serial");
55400 + if (!*res)
55401 + ret = -EBUSY;
55403 + break;
55405 + case SERIAL_IO_HUB6:
55406 + case SERIAL_IO_PORT:
55407 + *res = request_region(up->port.iobase, size, "serial");
55408 + if (!*res)
55409 + ret = -EBUSY;
55410 + break;
55412 + return ret;
55415 +static int
55416 +serial8250_request_rsa_resource(struct uart_8250_port *up, struct resource **res)
55418 + unsigned int size = 8 << up->port.regshift;
55419 + unsigned long start;
55420 + int ret = 0;
55422 + switch (up->port.iotype) {
55423 + case SERIAL_IO_MEM:
55424 + if (up->port.mapbase) {
55425 + start = up->port.mapbase;
55426 + start += UART_RSA_BASE << up->port.regshift;
55427 + *res = request_mem_region(start, size, "serial-rsa");
55428 + if (!*res)
55429 + ret = -EBUSY;
55431 + break;
55433 + case SERIAL_IO_HUB6:
55434 + case SERIAL_IO_PORT:
55435 + start = up->port.iobase;
55436 + start += UART_RSA_BASE << up->port.regshift;
55437 + *res = request_region(start, size, "serial-rsa");
55438 + if (!*res)
55439 + ret = -EBUSY;
55440 + break;
55443 + return ret;
55446 +static void serial8250_release_port(struct uart_port *port)
55448 + struct uart_8250_port *up = (struct uart_8250_port *)port;
55449 + unsigned long start, offset = 0, size = 0;
55451 + if (up->port.type == PORT_RSA) {
55452 + offset = UART_RSA_BASE << up->port.regshift;
55453 + size = 8;
55456 + size <<= up->port.regshift;
55458 + switch (up->port.iotype) {
55459 + case SERIAL_IO_MEM:
55460 + if (up->port.mapbase) {
55461 + /*
55462 + * Unmap the area.
55463 + */
55464 + if (up->port.flags & UPF_IOREMAP) {
55465 + iounmap(up->port.membase);
55466 + up->port.membase = NULL;
55469 + start = up->port.mapbase;
55471 + if (size)
55472 + release_mem_region(start + offset, size);
55473 + release_mem_region(start, 8 << up->port.regshift);
55475 + break;
55477 + case SERIAL_IO_HUB6:
55478 + case SERIAL_IO_PORT:
55479 + start = up->port.iobase;
55481 + if (size)
55482 + release_region(start + offset, size);
55483 + release_region(start + offset, 8 << up->port.regshift);
55484 + break;
55486 + default:
55487 + break;
55491 +static int serial8250_request_port(struct uart_port *port)
55493 + struct uart_8250_port *up = (struct uart_8250_port *)port;
55494 + struct resource *res = NULL, *res_rsa = NULL;
55495 + int ret = 0;
55497 + if (up->port.flags & UPF_RESOURCES) {
55498 + if (up->port.type == PORT_RSA) {
55499 + ret = serial8250_request_rsa_resource(up, &res_rsa);
55500 + if (ret < 0)
55501 + return ret;
55504 + ret = serial8250_request_std_resource(up, &res);
55507 + /*
55508 + * If we have a mapbase, then request that as well.
55509 + */
55510 + if (ret == 0 && up->port.flags & UPF_IOREMAP) {
55511 + int size = res->end - res->start + 1;
55513 + up->port.membase = ioremap(up->port.mapbase, size);
55514 + if (!up->port.membase)
55515 + ret = -ENOMEM;
55518 + if (ret < 0) {
55519 + if (res_rsa)
55520 + release_resource(res_rsa);
55521 + if (res)
55522 + release_resource(res);
55524 + return ret;
55527 +static void serial8250_config_port(struct uart_port *port, int flags)
55529 + struct uart_8250_port *up = (struct uart_8250_port *)port;
55530 + struct resource *res_std = NULL, *res_rsa = NULL;
55531 + int probeflags = PROBE_ANY;
55532 + int ret;
55534 +#ifdef CONFIG_MCA
55535 + /*
55536 + * Don't probe for MCA ports on non-MCA machines.
55537 + */
55538 + if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)
55539 + return;
55540 +#endif
55542 + /*
55543 + * Find the region that we can probe for. This in turn
55544 + * tells us whether we can probe for the type of port.
55545 + */
55546 + if (up->port.flags & UPF_RESOURCES) {
55547 + ret = serial8250_request_std_resource(up, &res_std);
55548 + if (ret < 0)
55549 + return;
55551 + ret = serial8250_request_rsa_resource(up, &res_rsa);
55552 + if (ret < 0)
55553 + probeflags &= ~PROBE_RSA;
55554 + } else {
55555 + probeflags &= ~PROBE_RSA;
55558 + if (flags & UART_CONFIG_TYPE)
55559 + autoconfig(up, probeflags);
55560 + if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
55561 + autoconfig_irq(up);
55563 + /*
55564 + * If the port wasn't an RSA port, release the resource.
55565 + */
55566 + if (up->port.type != PORT_RSA && res_rsa)
55567 + release_resource(res_rsa);
55569 + if (up->port.type == PORT_UNKNOWN && res_std)
55570 + release_resource(res_std);
55573 +static int
55574 +serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
55576 + if (ser->irq >= NR_IRQS || ser->irq < 0 ||
55577 + ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
55578 + ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||
55579 + ser->type == PORT_STARTECH)
55580 + return -EINVAL;
55581 + return 0;
55584 +static const char *
55585 +serial8250_type(struct uart_port *port)
55587 + int type = port->type;
55589 + if (type >= ARRAY_SIZE(uart_config))
55590 + type = 0;
55591 + return uart_config[type].name;
55594 +static struct uart_ops serial8250_pops = {
55595 + .tx_empty = serial8250_tx_empty,
55596 + .set_mctrl = serial8250_set_mctrl,
55597 + .get_mctrl = serial8250_get_mctrl,
55598 + .stop_tx = serial8250_stop_tx,
55599 + .start_tx = serial8250_start_tx,
55600 + .stop_rx = serial8250_stop_rx,
55601 + .enable_ms = serial8250_enable_ms,
55602 + .break_ctl = serial8250_break_ctl,
55603 + .startup = serial8250_startup,
55604 + .shutdown = serial8250_shutdown,
55605 + .change_speed = serial8250_change_speed,
55606 + .pm = serial8250_pm,
55607 + .type = serial8250_type,
55608 + .release_port = serial8250_release_port,
55609 + .request_port = serial8250_request_port,
55610 + .config_port = serial8250_config_port,
55611 + .verify_port = serial8250_verify_port,
55614 +static struct uart_8250_port serial8250_ports[UART_NR];
55616 +static void __init serial8250_isa_init_ports(void)
55618 + struct uart_8250_port *up;
55619 + static int first = 1;
55620 + int i;
55622 + if (!first)
55623 + return;
55624 + first = 0;
55626 + for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
55627 + i++, up++) {
55628 + up->port.iobase = old_serial_port[i].port;
55629 + up->port.irq = irq_cannonicalize(old_serial_port[i].irq);
55630 + up->port.uartclk = old_serial_port[i].baud_base * 16;
55631 + up->port.flags = old_serial_port[i].flags |
55632 + UPF_RESOURCES;
55633 + up->port.hub6 = old_serial_port[i].hub6;
55634 + up->port.membase = old_serial_port[i].iomem_base;
55635 + up->port.iotype = old_serial_port[i].io_type;
55636 + up->port.regshift = old_serial_port[i].iomem_reg_shift;
55637 + up->port.ops = &serial8250_pops;
55639 + if (up->port.iotype == UPIO_MEM && up->port.mapbase)
55640 + up->port.flags |= UPF_IOREMAP;
55642 + if (share_irqs)
55643 + up->port.flags |= UPF_SHARE_IRQ;
55647 +static void __init serial8250_register_ports(struct uart_driver *drv)
55649 + int i;
55651 + serial8250_isa_init_ports();
55653 + for (i = 0; i < UART_NR; i++) {
55654 + struct uart_8250_port *up = &serial8250_ports[i];
55656 + up->port.line = i;
55657 + up->port.ops = &serial8250_pops;
55658 + init_timer(&up->timer);
55659 + up->timer.function = serial8250_timeout;
55661 + /*
55662 + * ALPHA_KLUDGE_MCR needs to be killed.
55663 + */
55664 + up->mcr_mask = ~ALPHA_KLUDGE_MCR;
55665 + up->mcr_force = ALPHA_KLUDGE_MCR;
55667 + uart_add_one_port(drv, &up->port);
55671 +#ifdef CONFIG_SERIAL_8250_CONSOLE
55673 +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
55676 + * Wait for transmitter & holding register to empty
55677 + */
55678 +static inline void wait_for_xmitr(struct uart_8250_port *up)
55680 + unsigned int status, tmout = 10000;
55682 + /* Wait up to 10ms for the character(s) to be sent. */
55683 + do {
55684 + status = serial_in(up, UART_LSR);
55686 + if (status & UART_LSR_BI)
55687 + up->lsr_break_flag = UART_LSR_BI;
55689 + if (--tmout == 0)
55690 + break;
55691 + udelay(1);
55692 + } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
55694 + /* Wait up to 1s for flow control if necessary */
55695 + if (up->port.flags & UPF_CONS_FLOW) {
55696 + tmout = 1000000;
55697 + while (--tmout &&
55698 + ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
55699 + udelay(1);
55704 + * Print a string to the serial port trying not to disturb
55705 + * any possible real use of the port...
55707 + * The console_lock must be held when we get here.
55708 + */
55709 +static void
55710 +serial8250_console_write(struct console *co, const char *s, unsigned int count)
55712 + struct uart_8250_port *up = &serial8250_ports[co->index];
55713 + unsigned int ier;
55714 + int i;
55716 + /*
55717 + * First save the UER then disable the interrupts
55718 + */
55719 + ier = serial_in(up, UART_IER);
55720 + serial_out(up, UART_IER, 0);
55722 + /*
55723 + * Now, do each character
55724 + */
55725 + for (i = 0; i < count; i++, s++) {
55726 + wait_for_xmitr(up);
55728 + /*
55729 + * Send the character out.
55730 + * If a LF, also do CR...
55731 + */
55732 + serial_out(up, UART_TX, *s);
55733 + if (*s == 10) {
55734 + wait_for_xmitr(up);
55735 + serial_out(up, UART_TX, 13);
55739 + /*
55740 + * Finally, wait for transmitter to become empty
55741 + * and restore the IER
55742 + */
55743 + wait_for_xmitr(up);
55744 + serial_out(up, UART_IER, ier);
55747 +static kdev_t serial8250_console_device(struct console *co)
55749 + return MKDEV(TTY_MAJOR, 64 + co->index);
55752 +static int __init serial8250_console_setup(struct console *co, char *options)
55754 + struct uart_port *port;
55755 + int baud = 9600;
55756 + int bits = 8;
55757 + int parity = 'n';
55758 + int flow = 'n';
55760 + /*
55761 + * Check whether an invalid uart number has been specified, and
55762 + * if so, search for the first available port that does have
55763 + * console support.
55764 + */
55765 + if (co->index >= UART_NR)
55766 + co->index = 0;
55767 + port = &serial8250_ports[co->index].port;
55769 + /*
55770 + * Temporary fix.
55771 + */
55772 + spin_lock_init(&port->lock);
55774 + if (options)
55775 + uart_parse_options(options, &baud, &parity, &bits, &flow);
55777 + return uart_set_options(port, co, baud, parity, bits, flow);
55780 +static struct console serial8250_console = {
55781 + .name = "ttyS",
55782 + .write = serial8250_console_write,
55783 + .device = serial8250_console_device,
55784 + .setup = serial8250_console_setup,
55785 + .flags = CON_PRINTBUFFER,
55786 + .index = -1,
55789 +void __init serial8250_console_init(void)
55791 + serial8250_isa_init_ports();
55792 + register_console(&serial8250_console);
55795 +#define SERIAL8250_CONSOLE &serial8250_console
55796 +#else
55797 +#define SERIAL8250_CONSOLE NULL
55798 +#endif
55800 +static struct uart_driver serial8250_reg = {
55801 + .owner = THIS_MODULE,
55802 +#ifdef CONFIG_DEVFS_FS
55803 + .normal_name = "tts/%d",
55804 + .callout_name = "cua/%d",
55805 +#else
55806 + .normal_name = "ttyS",
55807 + .callout_name = "cua",
55808 +#endif
55809 + .normal_major = TTY_MAJOR,
55810 + .callout_major = TTYAUX_MAJOR,
55811 + .normal_driver = &normal,
55812 + .callout_driver = &callout,
55813 + .table = serial8250_table,
55814 + .termios = serial8250_termios,
55815 + .termios_locked = serial8250_termios_locked,
55816 + .minor = 64,
55817 + .nr = UART_NR,
55818 + .cons = SERIAL8250_CONSOLE,
55822 + * register_serial and unregister_serial allows for 16x50 serial ports to be
55823 + * configured at run-time, to support PCMCIA modems.
55824 + */
55826 +static int __register_serial(struct serial_struct *req, int line)
55828 + struct uart_port port;
55830 + port.iobase = req->port;
55831 + port.membase = req->iomem_base;
55832 + port.irq = req->irq;
55833 + port.uartclk = req->baud_base * 16;
55834 + port.fifosize = req->xmit_fifo_size;
55835 + port.regshift = req->iomem_reg_shift;
55836 + port.iotype = req->io_type;
55837 + port.flags = req->flags | UPF_BOOT_AUTOCONF;
55838 + port.mapbase = req->iomap_base;
55839 + port.line = line;
55841 + if (share_irqs)
55842 + port.flags |= UPF_SHARE_IRQ;
55844 + if (HIGH_BITS_OFFSET)
55845 + port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
55847 + /*
55848 + * If a clock rate wasn't specified by the low level
55849 + * driver, then default to the standard clock rate.
55850 + */
55851 + if (port.uartclk == 0)
55852 + port.uartclk = BASE_BAUD * 16;
55854 + return uart_register_port(&serial8250_reg, &port);
55857 +/**
55858 + * register_serial - configure a 16x50 serial port at runtime
55859 + * @req: request structure
55861 + * Configure the serial port specified by the request. If the
55862 + * port exists and is in use an error is returned. If the port
55863 + * is not currently in the table it is added.
55865 + * The port is then probed and if necessary the IRQ is autodetected
55866 + * If this fails an error is returned.
55868 + * On success the port is ready to use and the line number is returned.
55869 + */
55870 +int register_serial(struct serial_struct *req)
55872 + return __register_serial(req, -1);
55875 +/**
55876 + * unregister_serial - remove a 16x50 serial port at runtime
55877 + * @line: serial line number
55879 + * Remove one serial port. This may be called from interrupt
55880 + * context.
55881 + */
55882 +void unregister_serial(int line)
55884 + uart_unregister_port(&serial8250_reg, line);
55888 + * This is for ISAPNP only.
55889 + */
55890 +void serial8250_get_irq_map(unsigned int *map)
55892 + int i;
55894 + for (i = 0; i < UART_NR; i++) {
55895 + if (serial8250_ports[i].port.type != PORT_UNKNOWN &&
55896 + serial8250_ports[i].port.irq < 16)
55897 + *map |= 1 << serial8250_ports[i].port.irq;
55901 +static int __init serial8250_init(void)
55903 + int ret, i;
55905 + for (i = 0; i < NR_IRQS; i++)
55906 + spin_lock_init(&irq_lists[i].lock);
55908 + ret = uart_register_driver(&serial8250_reg);
55909 + if (ret >= 0)
55910 + serial8250_register_ports(&serial8250_reg);
55912 + return ret;
55915 +static void __exit serial8250_exit(void)
55917 + int i;
55919 + for (i = 0; i < UART_NR; i++)
55920 + uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);
55922 + uart_unregister_driver(&serial8250_reg);
55925 +module_init(serial8250_init);
55926 +module_exit(serial8250_exit);
55928 +EXPORT_SYMBOL(register_serial);
55929 +EXPORT_SYMBOL(unregister_serial);
55930 +EXPORT_SYMBOL(serial8250_get_irq_map);
55932 +MODULE_LICENSE("GPL");
55933 +MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
55935 +MODULE_PARM(share_irqs, "i");
55936 +MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
55937 + " (unsafe)");
55939 +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
55940 +MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
55941 +MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
55942 +MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
55943 +MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
55944 +#endif /* CONFIG_SERIAL_8250_RSA */
55946 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
55947 +++ linux-2.4.25/drivers/serial/8250.h 2004-03-31 17:15:09.000000000 +0200
55948 @@ -0,0 +1,88 @@
55950 + * linux/drivers/serial/8250.h
55952 + * Driver for 8250/16550-type serial ports
55954 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
55956 + * Copyright (C) 2001 Russell King.
55958 + * This program is free software; you can redistribute it and/or modify
55959 + * it under the terms of the GNU General Public License as published by
55960 + * the Free Software Foundation; either version 2 of the License, or
55961 + * (at your option) any later version.
55963 + * $Id: 8250.h,v 1.1.1.1.2.1 2002/10/24 09:53:24 rmk Exp $
55964 + */
55966 +#include <linux/config.h>
55968 +struct serial8250_probe {
55969 + struct module *owner;
55970 + int (*pci_init_one)(struct pci_dev *dev);
55971 + void (*pci_remove_one)(struct pci_dev *dev);
55972 + void (*pnp_init)(void);
55975 +int serial8250_register_probe(struct serial8250_probe *probe);
55976 +void serial8250_unregister_probe(struct serial8250_probe *probe);
55977 +void serial8250_get_irq_map(unsigned int *map);
55979 +struct old_serial_port {
55980 + unsigned int uart;
55981 + unsigned int baud_base;
55982 + unsigned int port;
55983 + unsigned int irq;
55984 + unsigned int flags;
55985 + unsigned char hub6;
55986 + unsigned char io_type;
55987 + unsigned char *iomem_base;
55988 + unsigned short iomem_reg_shift;
55991 +struct serial8250_config {
55992 + const char *name;
55993 + unsigned int dfl_xmit_fifo_size;
55994 + unsigned int flags;
55997 +#define UART_CLEAR_FIFO 0x01
55998 +#define UART_USE_FIFO 0x02
55999 +#define UART_STARTECH 0x04
56000 +#define UART_NATSEMI 0x08
56001 +#define UART_MCRAFE 0x10 /* TI16C750-style auto-flow */
56002 +#define UART_EFRAFE 0x20 /* TI16C752/startech auto-flow */
56004 +#define UART_BAD_TX_ENABLE 0x80000000
56006 +#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
56007 +#define SERIAL_INLINE
56008 +#endif
56010 +#ifdef SERIAL_INLINE
56011 +#define _INLINE_ inline
56012 +#else
56013 +#define _INLINE_
56014 +#endif
56016 +#define PROBE_RSA (1 << 0)
56017 +#define PROBE_ANY (~0)
56019 +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
56021 +#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
56022 +#define SERIAL8250_SHARE_IRQS 1
56023 +#else
56024 +#define SERIAL8250_SHARE_IRQS 0
56025 +#endif
56027 +#if defined(__alpha__) && !defined(CONFIG_PCI)
56029 + * Digital did something really horribly wrong with the OUT1 and OUT2
56030 + * lines on at least some ALPHA's. The failure mode is that if either
56031 + * is cleared, the machine locks up with endless interrupts.
56032 + */
56033 +#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
56034 +#else
56035 +#define ALPHA_KLUDGE_MCR 0
56036 +#endif
56037 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
56038 +++ linux-2.4.25/drivers/serial/8250_pci.c 2004-03-31 17:15:09.000000000 +0200
56039 @@ -0,0 +1,1080 @@
56041 + * linux/drivers/char/serial_8250_pci.c
56043 + * Probe module for 8250/16550-type PCI serial ports.
56045 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
56047 + * Copyright (C) 2001 Russell King, All Rights Reserved.
56049 + * This program is free software; you can redistribute it and/or modify
56050 + * it under the terms of the GNU General Public License as published by
56051 + * the Free Software Foundation; either version 2 of the License.
56053 + * $Id: 8250_pci.c,v 1.8.2.1 2002/10/24 09:53:24 rmk Exp $
56054 + */
56055 +#include <linux/config.h>
56056 +#include <linux/module.h>
56057 +#include <linux/init.h>
56058 +#include <linux/pci.h>
56059 +#include <linux/sched.h>
56060 +#include <linux/string.h>
56061 +#include <linux/kernel.h>
56062 +#include <linux/slab.h>
56063 +#include <linux/serial.h>
56065 +/* 2.4.6 compatibility cruft ;( */
56066 +#define pci_board __pci_board
56067 +#include <linux/serialP.h>
56068 +#undef pci_board
56070 +#include <asm/bitops.h>
56071 +#include <asm/byteorder.h>
56072 +#include <asm/serial.h>
56074 +#include "8250.h"
56076 +#ifndef IS_PCI_REGION_IOPORT
56077 +#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
56078 + IORESOURCE_IO)
56079 +#endif
56080 +#ifndef IS_PCI_REGION_IOMEM
56081 +#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
56082 + IORESOURCE_MEM)
56083 +#endif
56084 +#ifndef PCI_IRQ_RESOURCE
56085 +#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
56086 +#endif
56088 +#ifndef pci_get_subvendor
56089 +#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
56090 +#define pci_get_subdevice(dev) ((dev)->subsystem_device)
56091 +#endif
56093 +struct serial_private {
56094 + unsigned int nr;
56095 + struct pci_board *board;
56096 + int line[0];
56099 +struct pci_board {
56100 + int flags;
56101 + int num_ports;
56102 + int base_baud;
56103 + int uart_offset;
56104 + int reg_shift;
56105 + int (*init_fn)(struct pci_dev *dev, struct pci_board *board,
56106 + int enable);
56107 + int first_uart_offset;
56110 +static int
56111 +get_pci_port(struct pci_dev *dev, struct pci_board *board,
56112 + struct serial_struct *req, int idx)
56114 + unsigned long port;
56115 + int base_idx;
56116 + int max_port;
56117 + int offset;
56119 + base_idx = SPCI_FL_GET_BASE(board->flags);
56120 + if (board->flags & SPCI_FL_BASE_TABLE)
56121 + base_idx += idx;
56123 + if (board->flags & SPCI_FL_REGION_SZ_CAP) {
56124 + max_port = pci_resource_len(dev, base_idx) / 8;
56125 + if (idx >= max_port)
56126 + return 1;
56129 + offset = board->first_uart_offset;
56131 + /* Timedia/SUNIX uses a mixture of BARs and offsets */
56132 + /* Ugh, this is ugly as all hell --- TYT */
56133 + if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
56134 + switch(idx) {
56135 + case 0: base_idx=0;
56136 + break;
56137 + case 1: base_idx=0; offset=8;
56138 + break;
56139 + case 2: base_idx=1;
56140 + break;
56141 + case 3: base_idx=1; offset=8;
56142 + break;
56143 + case 4: /* BAR 2*/
56144 + case 5: /* BAR 3 */
56145 + case 6: /* BAR 4*/
56146 + case 7: base_idx=idx-2; /* BAR 5*/
56149 + /* Some Titan cards are also a little weird */
56150 + if (dev->vendor == PCI_VENDOR_ID_TITAN &&
56151 + (dev->device == PCI_DEVICE_ID_TITAN_400L ||
56152 + dev->device == PCI_DEVICE_ID_TITAN_800L)) {
56153 + switch (idx) {
56154 + case 0: base_idx = 1;
56155 + break;
56156 + case 1: base_idx = 2;
56157 + break;
56158 + default:
56159 + base_idx = 4;
56160 + offset = 8 * (idx - 2);
56164 + port = pci_resource_start(dev, base_idx) + offset;
56166 + if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
56167 + port += idx * (board->uart_offset ? board->uart_offset : 8);
56169 + if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
56170 + req->port = port;
56171 + if (HIGH_BITS_OFFSET)
56172 + req->port_high = port >> HIGH_BITS_OFFSET;
56173 + else
56174 + req->port_high = 0;
56175 + return 0;
56177 + req->io_type = SERIAL_IO_MEM;
56178 + req->iomem_base = ioremap(port, board->uart_offset);
56179 + req->iomem_reg_shift = board->reg_shift;
56180 + req->port = 0;
56181 + return 0;
56184 +static _INLINE_ int get_pci_irq(struct pci_dev *dev,
56185 + struct pci_board *board,
56186 + int idx)
56188 + int base_idx;
56190 + if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
56191 + return dev->irq;
56193 + base_idx = SPCI_FL_GET_IRQBASE(board->flags);
56194 + if (board->flags & SPCI_FL_IRQ_TABLE)
56195 + base_idx += idx;
56197 + return PCI_IRQ_RESOURCE(dev, base_idx);
56201 + * Some PCI serial cards using the PLX 9050 PCI interface chip require
56202 + * that the card interrupt be explicitly enabled or disabled. This
56203 + * seems to be mainly needed on card using the PLX which also use I/O
56204 + * mapped memory.
56205 + */
56206 +static int __devinit
56207 +pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
56209 + u8 data, *p, irq_config;
56210 + int pci_config;
56212 + irq_config = 0x41;
56213 + pci_config = PCI_COMMAND_MEMORY;
56214 + if (dev->vendor == PCI_VENDOR_ID_PANACOM)
56215 + irq_config = 0x43;
56216 + if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
56217 + (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
56218 + /*
56219 + * As the megawolf cards have the int pins active
56220 + * high, and have 2 UART chips, both ints must be
56221 + * enabled on the 9050. Also, the UARTS are set in
56222 + * 16450 mode by default, so we have to enable the
56223 + * 16C950 'enhanced' mode so that we can use the deep
56224 + * FIFOs
56225 + */
56226 + irq_config = 0x5b;
56227 + pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
56230 + pci_read_config_byte(dev, PCI_COMMAND, &data);
56232 + if (enable)
56233 + pci_write_config_byte(dev, PCI_COMMAND,
56234 + data | pci_config);
56236 + /* enable/disable interrupts */
56237 + p = ioremap(pci_resource_start(dev, 0), 0x80);
56238 + writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c);
56239 + iounmap(p);
56241 + if (!enable)
56242 + pci_write_config_byte(dev, PCI_COMMAND,
56243 + data & ~pci_config);
56244 + return 0;
56249 + * SIIG serial cards have an PCI interface chip which also controls
56250 + * the UART clocking frequency. Each UART can be clocked independently
56251 + * (except cards equiped with 4 UARTs) and initial clocking settings
56252 + * are stored in the EEPROM chip. It can cause problems because this
56253 + * version of serial driver doesn't support differently clocked UART's
56254 + * on single PCI card. To prevent this, initialization functions set
56255 + * high frequency clocking for all UART's on given card. It is safe (I
56256 + * hope) because it doesn't touch EEPROM settings to prevent conflicts
56257 + * with other OSes (like M$ DOS).
56259 + * SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
56260 + *
56261 + * There is two family of SIIG serial cards with different PCI
56262 + * interface chip and different configuration methods:
56263 + * - 10x cards have control registers in IO and/or memory space;
56264 + * - 20x cards have control registers in standard PCI configuration space.
56265 + */
56267 +#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
56268 +#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
56270 +static int __devinit
56271 +pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
56273 + u16 data, *p;
56275 + if (!enable) return 0;
56277 + p = ioremap(pci_resource_start(dev, 0), 0x80);
56279 + switch (dev->device & 0xfff8) {
56280 + case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
56281 + data = 0xffdf;
56282 + break;
56283 + case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
56284 + data = 0xf7ff;
56285 + break;
56286 + default: /* 1S1P, 4S */
56287 + data = 0xfffb;
56288 + break;
56291 + writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
56292 + iounmap(p);
56293 + return 0;
56296 +#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
56297 +#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
56299 +static int __devinit
56300 +pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
56302 + u8 data;
56304 + if (!enable) return 0;
56306 + /* Change clock frequency for the first UART. */
56307 + pci_read_config_byte(dev, 0x6f, &data);
56308 + pci_write_config_byte(dev, 0x6f, data & 0xef);
56310 + /* If this card has 2 UART, we have to do the same with second UART. */
56311 + if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
56312 + ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
56313 + pci_read_config_byte(dev, 0x73, &data);
56314 + pci_write_config_byte(dev, 0x73, data & 0xef);
56316 + return 0;
56319 +/* Added for EKF Intel i960 serial boards */
56320 +static int __devinit
56321 +pci_inteli960ni_fn(struct pci_dev *dev,
56322 + struct pci_board *board,
56323 + int enable)
56325 + unsigned long oldval;
56327 + if (!(pci_get_subdevice(dev) & 0x1000))
56328 + return(-1);
56330 + if (!enable) /* is there something to deinit? */
56331 + return(0);
56333 + /* is firmware started? */
56334 + pci_read_config_dword(dev, 0x44, (void*) &oldval);
56335 + if (oldval == 0x00001000L) { /* RESET value */
56336 + printk(KERN_DEBUG "Local i960 firmware missing");
56337 + return(-1);
56339 + return(0);
56343 + * Timedia has an explosion of boards, and to avoid the PCI table from
56344 + * growing *huge*, we use this function to collapse some 70 entries
56345 + * in the PCI table into one, for sanity's and compactness's sake.
56346 + */
56347 +static unsigned short timedia_single_port[] = {
56348 + 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 };
56349 +static unsigned short timedia_dual_port[] = {
56350 + 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
56351 + 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
56352 + 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
56353 + 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
56354 + 0xD079, 0 };
56355 +static unsigned short timedia_quad_port[] = {
56356 + 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
56357 + 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
56358 + 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
56359 + 0xB157, 0 };
56360 +static unsigned short timedia_eight_port[] = {
56361 + 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
56362 + 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 };
56363 +static struct timedia_struct {
56364 + int num;
56365 + unsigned short *ids;
56366 +} timedia_data[] = {
56367 + { 1, timedia_single_port },
56368 + { 2, timedia_dual_port },
56369 + { 4, timedia_quad_port },
56370 + { 8, timedia_eight_port },
56371 + { 0, 0 }
56374 +static int __devinit
56375 +pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable)
56377 + int i, j;
56378 + unsigned short *ids;
56380 + if (!enable)
56381 + return 0;
56383 + for (i=0; timedia_data[i].num; i++) {
56384 + ids = timedia_data[i].ids;
56385 + for (j=0; ids[j]; j++) {
56386 + if (pci_get_subdevice(dev) == ids[j]) {
56387 + board->num_ports = timedia_data[i].num;
56388 + return 0;
56392 + return 0;
56395 +static int __devinit
56396 +pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
56398 + __set_current_state(TASK_UNINTERRUPTIBLE);
56399 + schedule_timeout(HZ/10);
56400 + return 0;
56404 + * This is the configuration table for all of the PCI serial boards
56405 + * which we support. It is directly indexed by the pci_board_num_t enum
56406 + * value, which is encoded in the pci_device_id PCI probe table's
56407 + * driver_data member.
56408 + */
56409 +enum pci_board_num_t {
56410 + pbn_b0_1_115200,
56411 + pbn_default = 0,
56413 + pbn_b0_2_115200,
56414 + pbn_b0_4_115200,
56416 + pbn_b0_1_921600,
56417 + pbn_b0_2_921600,
56418 + pbn_b0_4_921600,
56420 + pbn_b0_bt_1_115200,
56421 + pbn_b0_bt_2_115200,
56422 + pbn_b0_bt_1_460800,
56423 + pbn_b0_bt_2_460800,
56425 + pbn_b1_1_115200,
56426 + pbn_b1_2_115200,
56427 + pbn_b1_4_115200,
56428 + pbn_b1_8_115200,
56430 + pbn_b1_2_921600,
56431 + pbn_b1_4_921600,
56432 + pbn_b1_8_921600,
56434 + pbn_b1_2_1382400,
56435 + pbn_b1_4_1382400,
56436 + pbn_b1_8_1382400,
56438 + pbn_b2_8_115200,
56439 + pbn_b2_4_460800,
56440 + pbn_b2_8_460800,
56441 + pbn_b2_16_460800,
56442 + pbn_b2_4_921600,
56443 + pbn_b2_8_921600,
56445 + pbn_b2_bt_1_115200,
56446 + pbn_b2_bt_2_115200,
56447 + pbn_b2_bt_4_115200,
56448 + pbn_b2_bt_2_921600,
56450 + pbn_panacom,
56451 + pbn_panacom2,
56452 + pbn_panacom4,
56453 + pbn_plx_romulus,
56454 + pbn_oxsemi,
56455 + pbn_timedia,
56456 + pbn_intel_i960,
56457 + pbn_sgi_ioc3,
56458 +#ifdef CONFIG_DDB5074
56459 + pbn_nec_nile4,
56460 +#endif
56461 +#if 0
56462 + pbn_dci_pccom8,
56463 +#endif
56464 + pbn_xircom_combo,
56466 + pbn_siig10x_0,
56467 + pbn_siig10x_1,
56468 + pbn_siig10x_2,
56469 + pbn_siig10x_4,
56470 + pbn_siig20x_0,
56471 + pbn_siig20x_2,
56472 + pbn_siig20x_4,
56474 + pbn_computone_4,
56475 + pbn_computone_6,
56476 + pbn_computone_8,
56479 +static struct pci_board pci_boards[] __devinitdata = {
56480 + /*
56481 + * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
56482 + * Offset to get to next UART's registers,
56483 + * Register shift to use for memory-mapped I/O,
56484 + * Initialization function, first UART offset
56485 + */
56487 + /* Generic serial board, pbn_b0_1_115200, pbn_default */
56488 + { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200,
56489 + pbn_default */
56491 + { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */
56492 + { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */
56494 + { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */
56495 + { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */
56496 + { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */
56498 + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
56499 + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
56500 + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
56501 + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
56503 + { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */
56504 + { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */
56505 + { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */
56506 + { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */
56508 + { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */
56509 + { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */
56510 + { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */
56512 + { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */
56513 + { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */
56514 + { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */
56516 + { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */
56517 + { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */
56518 + { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */
56519 + { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */
56520 + { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */
56521 + { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */
56523 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
56524 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
56525 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
56526 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
56528 + { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */
56529 + 0x400, 7, pci_plx9050_fn },
56530 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */
56531 + 0x400, 7, pci_plx9050_fn },
56532 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */
56533 + 0x400, 7, pci_plx9050_fn },
56534 + { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */
56535 + 0x20, 2, pci_plx9050_fn, 0x03 },
56536 + /* This board uses the size of PCI Base region 0 to
56537 + * signal now many ports are available */
56538 + { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
56539 + { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */
56540 + 0, 0, pci_timedia_fn },
56541 + /* EKF addition for i960 Boards form EKF with serial port */
56542 + { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */
56543 + 8<<2, 2, pci_inteli960ni_fn, 0x10000},
56544 + { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */
56545 + 1, 458333, 0, 0, 0, 0x20178 },
56546 +#ifdef CONFIG_DDB5074
56547 + /*
56548 + * NEC Vrc-5074 (Nile 4) builtin UART.
56549 + * Conditionally compiled in since this is a motherboard device.
56550 + */
56551 + { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */
56552 + 64, 3, NULL, 0x300 },
56553 +#endif
56554 +#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ /* pbn_dci_pccom8 */
56555 + { SPCI_FL_BASE3, 8, 115200, 8 },
56556 +#endif
56557 + { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */
56558 + 0, 0, pci_xircom_fn },
56560 + { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */
56561 + 0, 0, pci_siig10x_fn },
56562 + { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */
56563 + 0, 0, pci_siig10x_fn },
56564 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */
56565 + 0, 0, pci_siig10x_fn },
56566 + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */
56567 + 0, 0, pci_siig10x_fn },
56568 + { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */
56569 + 0, 0, pci_siig20x_fn },
56570 + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */
56571 + 0, 0, pci_siig20x_fn },
56572 + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */
56573 + 0, 0, pci_siig20x_fn },
56575 + { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */
56576 + 0x40, 2, NULL, 0x200 },
56577 + { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */
56578 + 0x40, 2, NULL, 0x200 },
56579 + { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */
56580 + 0x40, 2, NULL, 0x200 },
56584 + * Given a complete unknown PCI device, try to use some heuristics to
56585 + * guess what the configuration might be, based on the pitiful PCI
56586 + * serial specs. Returns 0 on success, 1 on failure.
56587 + */
56588 +static int __devinit serial_pci_guess_board(struct pci_dev *dev,
56589 + struct pci_board *board)
56591 + int num_iomem = 0, num_port = 0, first_port = -1;
56592 + int i;
56594 + /*
56595 + * If it is not a communications device or the programming
56596 + * interface is greater than 6, give up.
56598 + * (Should we try to make guesses for multiport serial devices
56599 + * later?)
56600 + */
56601 + if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
56602 + ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
56603 + (dev->class & 0xff) > 6)
56604 + return 1;
56606 + for (i=0; i < 6; i++) {
56607 + if (IS_PCI_REGION_IOPORT(dev, i)) {
56608 + num_port++;
56609 + if (first_port == -1)
56610 + first_port = i;
56612 + if (IS_PCI_REGION_IOMEM(dev, i))
56613 + num_iomem++;
56616 + /*
56617 + * If there is 1 or 0 iomem regions, and exactly one port, use
56618 + * it.
56619 + */
56620 + if (num_iomem <= 1 && num_port == 1) {
56621 + board->flags = first_port;
56622 + return 0;
56624 + return 1;
56628 + * return -1 to refuse
56629 + */
56630 +static int pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
56632 + struct serial_private *priv;
56633 + struct pci_board *board, tmp;
56634 + struct serial_struct serial_req;
56635 + int base_baud, rc, k;
56637 + board = &pci_boards[ent->driver_data];
56639 + rc = pci_enable_device(dev);
56640 + if (rc)
56641 + return rc;
56643 + if (ent->driver_data == pbn_default &&
56644 + serial_pci_guess_board(dev, board))
56645 + return -ENODEV;
56646 + else if (serial_pci_guess_board(dev, &tmp) == 0) {
56647 + printk(KERN_INFO "Redundant entry in serial pci_table. "
56648 + "Please send the output of\n"
56649 + "lspci -vv, this message (%d,%d,%d,%d)\n"
56650 + "and the manufacturer and name of "
56651 + "serial board or modem board\n"
56652 + "to serial-pci-info@lists.sourceforge.net.\n",
56653 + dev->vendor, dev->device,
56654 + pci_get_subvendor(dev), pci_get_subdevice(dev));
56658 + priv = kmalloc(sizeof(struct serial_private) +
56659 + sizeof(unsigned int) * board->num_ports,
56660 + GFP_KERNEL);
56661 + if (!priv)
56662 + return -ENOMEM;
56664 + /*
56665 + * Run the initialization function, if any
56666 + */
56667 + if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0)) {
56668 + kfree(priv);
56669 + return -ENODEV;
56672 + base_baud = board->base_baud;
56673 + if (!base_baud)
56674 + base_baud = BASE_BAUD;
56675 + memset(&serial_req, 0, sizeof(serial_req));
56676 + for (k=0; k < board->num_ports; k++) {
56677 + serial_req.irq = get_pci_irq(dev, board, k);
56678 + if (get_pci_port(dev, board, &serial_req, k))
56679 + break;
56680 +#ifdef SERIAL_DEBUG_PCI
56681 + printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
56682 + serial_req.port, serial_req.irq, serial_req.io_type);
56683 +#endif
56684 + serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
56685 + serial_req.baud_base = base_baud;
56686 + priv->line[k] = register_serial(&serial_req);
56687 + if (priv->line[k] < 0)
56688 + break;
56691 + priv->board = board;
56692 + priv->nr = k;
56694 + pci_set_drvdata(dev, priv);
56696 + return 0;
56699 +static void pci_remove_one(struct pci_dev *dev)
56701 + struct serial_private *priv = pci_get_drvdata(dev);
56702 + int i;
56704 + pci_set_drvdata(dev, NULL);
56706 + for (i = 0; i < priv->nr; i++)
56707 + unregister_serial(priv->line[i]);
56709 + priv->board->init_fn(dev, priv->board, 0);
56711 + kfree(priv);
56714 +static struct pci_device_id serial_pci_tbl[] __devinitdata = {
56715 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
56716 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56717 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
56718 + pbn_b1_8_1382400 },
56719 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
56720 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56721 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
56722 + pbn_b1_4_1382400 },
56723 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
56724 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56725 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
56726 + pbn_b1_2_1382400 },
56727 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56728 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56729 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
56730 + pbn_b1_8_1382400 },
56731 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56732 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56733 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
56734 + pbn_b1_4_1382400 },
56735 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56736 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56737 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
56738 + pbn_b1_2_1382400 },
56739 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56740 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56741 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
56742 + pbn_b1_8_921600 },
56743 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56744 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56745 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
56746 + pbn_b1_8_921600 },
56747 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56748 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56749 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
56750 + pbn_b1_4_921600 },
56751 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56752 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56753 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
56754 + pbn_b1_4_921600 },
56755 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56756 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56757 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
56758 + pbn_b1_2_921600 },
56759 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56760 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56761 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
56762 + pbn_b1_8_921600 },
56763 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56764 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56765 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
56766 + pbn_b1_8_921600 },
56767 + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
56768 + PCI_SUBVENDOR_ID_CONNECT_TECH,
56769 + PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
56770 + pbn_b1_4_921600 },
56772 + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
56773 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56774 + pbn_b2_bt_1_115200 },
56775 + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
56776 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56777 + pbn_b2_bt_2_115200 },
56778 + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
56779 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56780 + pbn_b2_bt_4_115200 },
56781 + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
56782 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56783 + pbn_b2_bt_2_115200 },
56784 + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
56785 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56786 + pbn_b2_bt_4_115200 },
56787 + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
56788 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56789 + pbn_b2_8_115200 },
56791 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
56792 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56793 + pbn_b2_bt_2_115200 },
56794 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
56795 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56796 + pbn_b2_bt_2_921600 },
56797 + /* VScom SPCOM800, from sl@s.pl */
56798 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
56799 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56800 + pbn_b2_8_921600 },
56801 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
56802 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56803 + pbn_b2_4_921600 },
56804 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
56805 + PCI_SUBVENDOR_ID_KEYSPAN,
56806 + PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
56807 + pbn_panacom },
56808 + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
56809 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56810 + pbn_panacom4 },
56811 + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
56812 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56813 + pbn_panacom2 },
56814 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
56815 + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
56816 + PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
56817 + pbn_b2_4_460800 },
56818 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
56819 + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
56820 + PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
56821 + pbn_b2_8_460800 },
56822 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
56823 + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
56824 + PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
56825 + pbn_b2_16_460800 },
56826 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
56827 + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
56828 + PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
56829 + pbn_b2_16_460800 },
56830 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
56831 + PCI_SUBVENDOR_ID_CHASE_PCIRAS,
56832 + PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
56833 + pbn_b2_4_460800 },
56834 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
56835 + PCI_SUBVENDOR_ID_CHASE_PCIRAS,
56836 + PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
56837 + pbn_b2_8_460800 },
56838 + /* Megawolf Romulus PCI Serial Card, from Mike Hudson */
56839 + /* (Exoray@isys.ca) */
56840 + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
56841 + 0x10b5, 0x106a, 0, 0,
56842 + pbn_plx_romulus },
56843 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
56844 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56845 + pbn_b1_4_115200 },
56846 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
56847 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56848 + pbn_b1_2_115200 },
56849 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
56850 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56851 + pbn_b1_8_115200 },
56852 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
56853 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56854 + pbn_b1_8_115200 },
56855 + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
56856 + PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0,
56857 + pbn_b0_4_921600 },
56858 + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
56859 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56860 + pbn_b0_4_115200 },
56861 + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
56862 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56863 + pbn_b0_2_115200 },
56865 + /* Digitan DS560-558, from jimd@esoft.com */
56866 + { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
56867 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56868 + pbn_b1_1_115200 },
56870 + /* 3Com US Robotics 56k Voice Internal PCI model 5610 */
56871 + { PCI_VENDOR_ID_USR, 0x1008,
56872 + PCI_ANY_ID, PCI_ANY_ID, },
56874 + /* Titan Electronic cards */
56875 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
56876 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56877 + pbn_b0_1_921600 },
56878 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
56879 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56880 + pbn_b0_2_921600 },
56881 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
56882 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56883 + pbn_b0_4_921600 },
56884 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
56885 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56886 + pbn_b0_4_921600 },
56887 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
56888 + PCI_ANY_ID, PCI_ANY_ID,
56889 + SPCI_FL_BASE1, 1, 921600 },
56890 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
56891 + PCI_ANY_ID, PCI_ANY_ID,
56892 + SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
56893 + /* The 400L and 800L have a custom hack in get_pci_port */
56894 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
56895 + PCI_ANY_ID, PCI_ANY_ID,
56896 + SPCI_FL_BASE_TABLE, 4, 921600 },
56897 + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
56898 + PCI_ANY_ID, PCI_ANY_ID,
56899 + SPCI_FL_BASE_TABLE, 8, 921600 },
56901 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
56902 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56903 + pbn_siig10x_0 },
56904 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
56905 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56906 + pbn_siig10x_0 },
56907 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
56908 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56909 + pbn_siig10x_0 },
56910 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
56911 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56912 + pbn_siig10x_1 },
56913 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
56914 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56915 + pbn_siig10x_1 },
56916 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
56917 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56918 + pbn_siig10x_1 },
56919 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
56920 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56921 + pbn_siig10x_2 },
56922 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
56923 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56924 + pbn_siig10x_2 },
56925 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
56926 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56927 + pbn_siig10x_2 },
56928 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
56929 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56930 + pbn_siig10x_2 },
56931 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
56932 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56933 + pbn_siig10x_2 },
56934 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
56935 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56936 + pbn_siig10x_2 },
56937 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
56938 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56939 + pbn_siig10x_4 },
56940 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
56941 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56942 + pbn_siig10x_4 },
56943 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
56944 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56945 + pbn_siig10x_4 },
56946 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
56947 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56948 + pbn_siig20x_0 },
56949 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
56950 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56951 + pbn_siig20x_0 },
56952 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
56953 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56954 + pbn_siig20x_0 },
56955 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
56956 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56957 + pbn_siig20x_0 },
56958 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
56959 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56960 + pbn_siig20x_0 },
56961 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
56962 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56963 + pbn_siig20x_0 },
56964 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
56965 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56966 + pbn_siig20x_0 },
56967 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
56968 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56969 + pbn_siig20x_0 },
56970 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
56971 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56972 + pbn_siig20x_0 },
56973 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
56974 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56975 + pbn_siig20x_2 },
56976 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
56977 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56978 + pbn_siig20x_2 },
56979 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
56980 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56981 + pbn_siig20x_2 },
56982 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
56983 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56984 + pbn_siig20x_2 },
56985 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
56986 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56987 + pbn_siig20x_2 },
56988 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
56989 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56990 + pbn_siig20x_2 },
56991 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
56992 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56993 + pbn_siig20x_4 },
56994 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
56995 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56996 + pbn_siig20x_4 },
56997 + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
56998 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
56999 + pbn_siig20x_4 },
57001 + /* Computone devices submitted by Doug McNash dmcnash@computone.com */
57002 + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
57003 + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
57004 + 0, 0, pbn_computone_4 },
57005 + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
57006 + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
57007 + 0, 0, pbn_computone_8 },
57008 + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
57009 + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
57010 + 0, 0, pbn_computone_6 },
57012 + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
57013 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
57014 + { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
57015 + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
57017 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
57018 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57019 + pbn_b0_bt_2_115200 },
57020 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
57021 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57022 + pbn_b0_bt_2_115200 },
57023 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
57024 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57025 + pbn_b0_bt_2_115200 },
57026 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
57027 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57028 + pbn_b0_bt_2_460800 },
57029 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
57030 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57031 + pbn_b0_bt_2_460800 },
57032 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
57033 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57034 + pbn_b0_bt_2_460800 },
57035 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
57036 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57037 + pbn_b0_bt_1_115200 },
57038 + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
57039 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57040 + pbn_b0_bt_1_460800 },
57042 + /* RAStel 2 port modem, gerg@moreton.com.au */
57043 + { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
57044 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57045 + pbn_b2_bt_2_115200 },
57047 + /* EKF addition for i960 Boards form EKF with serial port */
57048 + { PCI_VENDOR_ID_INTEL, 0x1960,
57049 + 0xE4BF, PCI_ANY_ID, 0, 0,
57050 + pbn_intel_i960 },
57052 + /* Xircom Cardbus/Ethernet combos */
57053 + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
57054 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57055 + pbn_xircom_combo },
57057 + /*
57058 + * Untested PCI modems, sent in from various folks...
57059 + */
57061 + /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
57062 + { PCI_VENDOR_ID_ROCKWELL, 0x1004,
57063 + 0x1048, 0x1500, 0, 0,
57064 + pbn_b1_1_115200 },
57066 + { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
57067 + 0xFF00, 0, 0, 0,
57068 + pbn_sgi_ioc3 },
57070 +#ifdef CONFIG_DDB5074
57071 + /*
57072 + * NEC Vrc-5074 (Nile 4) builtin UART.
57073 + * Conditionally compiled in since this is a motherboard device.
57074 + */
57075 + { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
57076 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57077 + pbn_nec_nile4 },
57078 +#endif
57080 +#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */
57081 + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
57082 + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
57083 + pbn_dci_pccom8 },
57084 +#endif
57086 + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
57087 + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, },
57088 + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
57089 + PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, },
57090 + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
57091 + PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, },
57092 + { 0, }
57095 +static struct pci_driver serial_pci_driver = {
57096 + name: "serial",
57097 + probe: pci_init_one,
57098 + remove: pci_remove_one,
57099 + id_table: serial_pci_tbl,
57102 +static int __init serial8250_pci_init(void)
57104 + return pci_module_init(&serial_pci_driver);
57107 +static void __exit serial8250_pci_exit(void)
57109 + pci_unregister_driver(&serial_pci_driver);
57112 +module_init(serial8250_pci_init);
57113 +module_exit(serial8250_pci_exit);
57115 +EXPORT_NO_SYMBOLS;
57117 +MODULE_LICENSE("GPL");
57118 +MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
57119 +MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
57120 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
57121 +++ linux-2.4.25/drivers/serial/8250_pnp.c 2004-03-31 17:15:09.000000000 +0200
57122 @@ -0,0 +1,553 @@
57124 + * linux/drivers/char/serial_8250_pnp.c
57126 + * Probe module for 8250/16550-type ISAPNP serial ports.
57128 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
57130 + * Copyright (C) 2001 Russell King, All Rights Reserved.
57132 + * This program is free software; you can redistribute it and/or modify
57133 + * it under the terms of the GNU General Public License as published by
57134 + * the Free Software Foundation; either version 2 of the License.
57136 + * $Id: 8250_pnp.c,v 1.3.2.1 2002/10/24 09:53:25 rmk Exp $
57137 + */
57138 +#include <linux/config.h>
57139 +#include <linux/module.h>
57140 +#include <linux/init.h>
57141 +#include <linux/pci.h>
57142 +#include <linux/isapnp.h>
57143 +#include <linux/string.h>
57144 +#include <linux/kernel.h>
57145 +#include <linux/serial.h>
57146 +#include <linux/serialP.h>
57148 +#include <asm/bitops.h>
57149 +#include <asm/byteorder.h>
57150 +#include <asm/serial.h>
57152 +#include "8250.h"
57154 +static struct serial_state rs_table[] = { };
57155 +#define NR_PORTS 0
57157 +struct pnpbios_device_id
57159 + char id[8];
57160 + unsigned long driver_data;
57163 +static const struct pnpbios_device_id pnp_dev_table[] = {
57164 + /* Archtek America Corp. */
57165 + /* Archtek SmartLink Modem 3334BT Plug & Play */
57166 + { "AAC000F", 0 },
57167 + /* Anchor Datacomm BV */
57168 + /* SXPro 144 External Data Fax Modem Plug & Play */
57169 + { "ADC0001", 0 },
57170 + /* SXPro 288 External Data Fax Modem Plug & Play */
57171 + { "ADC0002", 0 },
57172 + /* Rockwell 56K ACF II Fax+Data+Voice Modem */
57173 + { "AKY1021", SPCI_FL_NO_SHIRQ },
57174 + /* AZT3005 PnP SOUND DEVICE */
57175 + { "AZT4001", 0 },
57176 + /* Best Data Products Inc. Smart One 336F PnP Modem */
57177 + { "BDP3336", 0 },
57178 + /* Boca Research */
57179 + /* Boca Complete Ofc Communicator 14.4 Data-FAX */
57180 + { "BRI0A49", 0 },
57181 + /* Boca Research 33,600 ACF Modem */
57182 + { "BRI1400", 0 },
57183 + /* Boca 33.6 Kbps Internal FD34FSVD */
57184 + { "BRI3400", 0 },
57185 + /* Boca 33.6 Kbps Internal FD34FSVD */
57186 + { "BRI0A49", 0 },
57187 + /* Best Data Products Inc. Smart One 336F PnP Modem */
57188 + { "BDP3336", 0 },
57189 + /* Computer Peripherals Inc */
57190 + /* EuroViVa CommCenter-33.6 SP PnP */
57191 + { "CPI4050", 0 },
57192 + /* Creative Labs */
57193 + /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
57194 + { "CTL3001", 0 },
57195 + /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
57196 + { "CTL3011", 0 },
57197 + /* Creative */
57198 + /* Creative Modem Blaster Flash56 DI5601-1 */
57199 + { "DMB1032", 0 },
57200 + /* Creative Modem Blaster V.90 DI5660 */
57201 + { "DMB2001", 0 },
57202 + /* FUJITSU */
57203 + /* Fujitsu 33600 PnP-I2 R Plug & Play */
57204 + { "FUJ0202", 0 },
57205 + /* Fujitsu FMV-FX431 Plug & Play */
57206 + { "FUJ0205", 0 },
57207 + /* Fujitsu 33600 PnP-I4 R Plug & Play */
57208 + { "FUJ0206", 0 },
57209 + /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
57210 + { "FUJ0209", 0 },
57211 + /* Archtek America Corp. */
57212 + /* Archtek SmartLink Modem 3334BT Plug & Play */
57213 + { "GVC000F", 0 },
57214 + /* Hayes */
57215 + /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
57216 + { "HAY0001", 0 },
57217 + /* Hayes Optima 336 V.34 + FAX + Voice PnP */
57218 + { "HAY000C", 0 },
57219 + /* Hayes Optima 336B V.34 + FAX + Voice PnP */
57220 + { "HAY000D", 0 },
57221 + /* Hayes Accura 56K Ext Fax Modem PnP */
57222 + { "HAY5670", 0 },
57223 + /* Hayes Accura 56K Ext Fax Modem PnP */
57224 + { "HAY5674", 0 },
57225 + /* Hayes Accura 56K Fax Modem PnP */
57226 + { "HAY5675", 0 },
57227 + /* Hayes 288, V.34 + FAX */
57228 + { "HAYF000", 0 },
57229 + /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
57230 + { "HAYF001", 0 },
57231 + /* IBM */
57232 + /* IBM Thinkpad 701 Internal Modem Voice */
57233 + { "IBM0033", 0 },
57234 + /* Intertex */
57235 + /* Intertex 28k8 33k6 Voice EXT PnP */
57236 + { "IXDC801", 0 },
57237 + /* Intertex 33k6 56k Voice EXT PnP */
57238 + { "IXDC901", 0 },
57239 + /* Intertex 28k8 33k6 Voice SP EXT PnP */
57240 + { "IXDD801", 0 },
57241 + /* Intertex 33k6 56k Voice SP EXT PnP */
57242 + { "IXDD901", 0 },
57243 + /* Intertex 28k8 33k6 Voice SP INT PnP */
57244 + { "IXDF401", 0 },
57245 + /* Intertex 28k8 33k6 Voice SP EXT PnP */
57246 + { "IXDF801", 0 },
57247 + /* Intertex 33k6 56k Voice SP EXT PnP */
57248 + { "IXDF901", 0 },
57249 + /* Kortex International */
57250 + /* KORTEX 28800 Externe PnP */
57251 + { "KOR4522", 0 },
57252 + /* KXPro 33.6 Vocal ASVD PnP */
57253 + { "KORF661", 0 },
57254 + /* Lasat */
57255 + /* LASAT Internet 33600 PnP */
57256 + { "LAS4040", 0 },
57257 + /* Lasat Safire 560 PnP */
57258 + { "LAS4540", 0 },
57259 + /* Lasat Safire 336 PnP */
57260 + { "LAS5440", 0 },
57261 + /* Microcom, Inc. */
57262 + /* Microcom TravelPorte FAST V.34 Plug & Play */
57263 + { "MNP0281", 0 },
57264 + /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
57265 + { "MNP0336", 0 },
57266 + /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
57267 + { "MNP0339", 0 },
57268 + /* Microcom DeskPorte 28.8P Plug & Play */
57269 + { "MNP0342", 0 },
57270 + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
57271 + { "MNP0500", 0 },
57272 + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
57273 + { "MNP0501", 0 },
57274 + /* Microcom DeskPorte 28.8S Internal Plug & Play */
57275 + { "MNP0502", 0 },
57276 + /* Motorola */
57277 + /* Motorola BitSURFR Plug & Play */
57278 + { "MOT1105", 0 },
57279 + /* Motorola TA210 Plug & Play */
57280 + { "MOT1111", 0 },
57281 + /* Motorola HMTA 200 (ISDN) Plug & Play */
57282 + { "MOT1114", 0 },
57283 + /* Motorola BitSURFR Plug & Play */
57284 + { "MOT1115", 0 },
57285 + /* Motorola Lifestyle 28.8 Internal */
57286 + { "MOT1190", 0 },
57287 + /* Motorola V.3400 Plug & Play */
57288 + { "MOT1501", 0 },
57289 + /* Motorola Lifestyle 28.8 V.34 Plug & Play */
57290 + { "MOT1502", 0 },
57291 + /* Motorola Power 28.8 V.34 Plug & Play */
57292 + { "MOT1505", 0 },
57293 + /* Motorola ModemSURFR External 28.8 Plug & Play */
57294 + { "MOT1509", 0 },
57295 + /* Motorola Premier 33.6 Desktop Plug & Play */
57296 + { "MOT150A", 0 },
57297 + /* Motorola VoiceSURFR 56K External PnP */
57298 + { "MOT150F", 0 },
57299 + /* Motorola ModemSURFR 56K External PnP */
57300 + { "MOT1510", 0 },
57301 + /* Motorola ModemSURFR 56K Internal PnP */
57302 + { "MOT1550", 0 },
57303 + /* Motorola ModemSURFR Internal 28.8 Plug & Play */
57304 + { "MOT1560", 0 },
57305 + /* Motorola Premier 33.6 Internal Plug & Play */
57306 + { "MOT1580", 0 },
57307 + /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
57308 + { "MOT15B0", 0 },
57309 + /* Motorola VoiceSURFR 56K Internal PnP */
57310 + { "MOT15F0", 0 },
57311 + /* Com 1 */
57312 + /* Deskline K56 Phone System PnP */
57313 + { "MVX00A1", 0 },
57314 + /* PC Rider K56 Phone System PnP */
57315 + { "MVX00F2", 0 },
57316 + /* Pace 56 Voice Internal Plug & Play Modem */
57317 + { "PMC2430", 0 },
57318 + /* Generic */
57319 + /* Generic standard PC COM port */
57320 + { "PNP0500", 0 },
57321 + /* Generic 16550A-compatible COM port */
57322 + { "PNP0501", 0 },
57323 + /* Compaq 14400 Modem */
57324 + { "PNPC000", 0 },
57325 + /* Compaq 2400/9600 Modem */
57326 + { "PNPC001", 0 },
57327 + /* Dial-Up Networking Serial Cable between 2 PCs */
57328 + { "PNPC031", 0 },
57329 + /* Dial-Up Networking Parallel Cable between 2 PCs */
57330 + { "PNPC032", 0 },
57331 + /* Standard 9600 bps Modem */
57332 + { "PNPC100", 0 },
57333 + /* Standard 14400 bps Modem */
57334 + { "PNPC101", 0 },
57335 + /* Standard 28800 bps Modem*/
57336 + { "PNPC102", 0 },
57337 + /* Standard Modem*/
57338 + { "PNPC103", 0 },
57339 + /* Standard 9600 bps Modem*/
57340 + { "PNPC104", 0 },
57341 + /* Standard 14400 bps Modem*/
57342 + { "PNPC105", 0 },
57343 + /* Standard 28800 bps Modem*/
57344 + { "PNPC106", 0 },
57345 + /* Standard Modem */
57346 + { "PNPC107", 0 },
57347 + /* Standard 9600 bps Modem */
57348 + { "PNPC108", 0 },
57349 + /* Standard 14400 bps Modem */
57350 + { "PNPC109", 0 },
57351 + /* Standard 28800 bps Modem */
57352 + { "PNPC10A", 0 },
57353 + /* Standard Modem */
57354 + { "PNPC10B", 0 },
57355 + /* Standard 9600 bps Modem */
57356 + { "PNPC10C", 0 },
57357 + /* Standard 14400 bps Modem */
57358 + { "PNPC10D", 0 },
57359 + /* Standard 28800 bps Modem */
57360 + { "PNPC10E", 0 },
57361 + /* Standard Modem */
57362 + { "PNPC10F", 0 },
57363 + /* Standard PCMCIA Card Modem */
57364 + { "PNP2000", 0 },
57365 + /* Rockwell */
57366 + /* Modular Technology */
57367 + /* Rockwell 33.6 DPF Internal PnP */
57368 + /* Modular Technology 33.6 Internal PnP */
57369 + { "ROK0030", 0 },
57370 + /* Kortex International */
57371 + /* KORTEX 14400 Externe PnP */
57372 + { "ROK0100", 0 },
57373 + /* Viking Components, Inc */
57374 + /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
57375 + { "ROK4920", 0 },
57376 + /* Rockwell */
57377 + /* British Telecom */
57378 + /* Modular Technology */
57379 + /* Rockwell 33.6 DPF External PnP */
57380 + /* BT Prologue 33.6 External PnP */
57381 + /* Modular Technology 33.6 External PnP */
57382 + { "RSS00A0", 0 },
57383 + /* Viking 56K FAX INT */
57384 + { "RSS0262", 0 },
57385 + /* SupraExpress 28.8 Data/Fax PnP modem */
57386 + { "SUP1310", 0 },
57387 + /* SupraExpress 33.6 Data/Fax PnP modem */
57388 + { "SUP1421", 0 },
57389 + /* SupraExpress 33.6 Data/Fax PnP modem */
57390 + { "SUP1590", 0 },
57391 + /* SupraExpress 33.6 Data/Fax PnP modem */
57392 + { "SUP1760", 0 },
57393 + /* Phoebe Micro */
57394 + /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
57395 + { "TEX0011", 0 },
57396 + /* Archtek America Corp. */
57397 + /* Archtek SmartLink Modem 3334BT Plug & Play */
57398 + { "UAC000F", 0 },
57399 + /* 3Com Corp. */
57400 + /* Gateway Telepath IIvi 33.6 */
57401 + { "USR0000", 0 },
57402 + /* Sportster Vi 14.4 PnP FAX Voicemail */
57403 + { "USR0004", 0 },
57404 + /* U.S. Robotics 33.6K Voice INT PnP */
57405 + { "USR0006", 0 },
57406 + /* U.S. Robotics 33.6K Voice EXT PnP */
57407 + { "USR0007", 0 },
57408 + /* U.S. Robotics 33.6K Voice INT PnP */
57409 + { "USR2002", 0 },
57410 + /* U.S. Robotics 56K Voice INT PnP */
57411 + { "USR2070", 0 },
57412 + /* U.S. Robotics 56K Voice EXT PnP */
57413 + { "USR2080", 0 },
57414 + /* U.S. Robotics 56K FAX INT */
57415 + { "USR3031", 0 },
57416 + /* U.S. Robotics 56K Voice INT PnP */
57417 + { "USR3070", 0 },
57418 + /* U.S. Robotics 56K Voice EXT PnP */
57419 + { "USR3080", 0 },
57420 + /* U.S. Robotics 56K Voice INT PnP */
57421 + { "USR3090", 0 },
57422 + /* U.S. Robotics 56K Message */
57423 + { "USR9100", 0 },
57424 + /* U.S. Robotics 56K FAX EXT PnP*/
57425 + { "USR9160", 0 },
57426 + /* U.S. Robotics 56K FAX INT PnP*/
57427 + { "USR9170", 0 },
57428 + /* U.S. Robotics 56K Voice EXT PnP*/
57429 + { "USR9180", 0 },
57430 + /* U.S. Robotics 56K Voice INT PnP*/
57431 + { "USR9190", 0 },
57432 + { "", 0 }
57435 +static void inline avoid_irq_share(struct pci_dev *dev)
57437 + int i, map = 0x1FF8;
57438 + struct serial_state *state = rs_table;
57439 + struct isapnp_irq *irq;
57440 + struct isapnp_resources *res = dev->sysdata;
57442 + for (i = 0; i < NR_PORTS; i++) {
57443 + if (state->type != PORT_UNKNOWN)
57444 + clear_bit(state->irq, &map);
57445 + state++;
57448 + for ( ; res; res = res->alt)
57449 + for(irq = res->irq; irq; irq = irq->next)
57450 + irq->map = map;
57453 +static char *modem_names[] __devinitdata = {
57454 + "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
57455 + "56K", "56k", "K56", "33.6", "28.8", "14.4",
57456 + "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
57457 + "33600", "28800", "14400", "V.90", "V.34", "V.32", 0
57460 +static int __devinit check_name(char *name)
57462 + char **tmp;
57464 + for (tmp = modem_names; *tmp; tmp++)
57465 + if (strstr(name, *tmp))
57466 + return 1;
57468 + return 0;
57471 +static int inline check_compatible_id(struct pci_dev *dev)
57473 + int i;
57474 + for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
57475 + if ((dev->vendor_compatible[i] ==
57476 + ISAPNP_VENDOR('P', 'N', 'P')) &&
57477 + (swab16(dev->device_compatible[i]) >= 0xc000) &&
57478 + (swab16(dev->device_compatible[i]) <= 0xdfff))
57479 + return 0;
57480 + return 1;
57484 + * Given a complete unknown ISA PnP device, try to use some heuristics to
57485 + * detect modems. Currently use such heuristic set:
57486 + * - dev->name or dev->bus->name must contain "modem" substring;
57487 + * - device must have only one IO region (8 byte long) with base adress
57488 + * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
57490 + * Such detection looks very ugly, but can detect at least some of numerous
57491 + * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[]
57492 + * table.
57493 + */
57494 +static int serial_pnp_guess_board(struct pci_dev *dev, int *flags)
57496 + struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
57497 + struct isapnp_resources *resa;
57499 + if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
57500 + !(check_compatible_id(dev)))
57501 + return -ENODEV;
57503 + if (!res || res->next)
57504 + return -ENODEV;
57506 + for (resa = res->alt; resa; resa = resa->alt) {
57507 + struct isapnp_port *port;
57508 + for (port = res->port; port; port = port->next)
57509 + if ((port->size == 8) &&
57510 + ((port->min == 0x2f8) ||
57511 + (port->min == 0x3f8) ||
57512 + (port->min == 0x2e8) ||
57513 + (port->min == 0x3e8)))
57514 + return 0;
57517 + return -ENODEV;
57520 +static int
57521 +pnp_init_one(struct pci_dev *dev, const struct pnpbios_device_id *ent,
57522 + char *slot_name)
57524 + struct serial_struct serial_req;
57525 + int ret, line, flags = ent ? ent->driver_data : 0;
57527 + if (!ent) {
57528 + ret = serial_pnp_guess_board(dev, &flags);
57529 + if (ret)
57530 + return ret;
57533 + if (dev->prepare(dev) < 0) {
57534 + printk("serial: PNP device '%s' prepare failed\n",
57535 + slot_name);
57536 + return -ENODEV;
57539 + if (dev->active)
57540 + return -ENODEV;
57542 + if (flags & SPCI_FL_NO_SHIRQ)
57543 + avoid_irq_share(dev);
57545 + if (dev->activate(dev) < 0) {
57546 + printk("serial: PNP device '%s' activate failed\n",
57547 + slot_name);
57548 + return -ENODEV;
57551 + memset(&serial_req, 0, sizeof(serial_req));
57552 + serial_req.irq = dev->irq_resource[0].start;
57553 + serial_req.port = pci_resource_start(dev, 0);
57554 + if (HIGH_BITS_OFFSET)
57555 + serial_req.port = pci_resource_start(dev, 0) >> HIGH_BITS_OFFSET;
57557 +#ifdef SERIAL_DEBUG_PCI
57558 + printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
57559 + serial_req.port, serial_req.irq, serial_req.io_type);
57560 +#endif
57562 + serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
57563 + serial_req.baud_base = 115200;
57564 + line = register_serial(&serial_req);
57566 + if (line >= 0) {
57567 + pci_set_drvdata(dev, (void *)(line + 1));
57569 + /*
57570 + * Public health warning: remove this once the 2.5
57571 + * pnpbios_module_init() stuff is incorporated.
57572 + */
57573 + dev->driver = (void *)pnp_dev_table;
57574 + } else
57575 + dev->deactivate(dev);
57577 + return line >= 0 ? 0 : -ENODEV;
57580 +static void pnp_remove_one(struct pci_dev *dev)
57582 + int line = (int)pci_get_drvdata(dev);
57584 + if (line) {
57585 + pci_set_drvdata(dev, NULL);
57587 + unregister_serial(line - 1);
57589 + dev->deactivate(dev);
57593 +static char hex[] = "0123456789ABCDEF";
57596 + * This function should vanish when 2.5 comes around and
57597 + * we have pnpbios_module_init()
57598 + */
57599 +static void pnp_init(void)
57601 + const struct pnpbios_device_id *id;
57602 + struct pci_dev *dev = NULL;
57604 +#ifdef SERIAL_DEBUG_PNP
57605 + printk("Entered probe_serial_pnp()\n");
57606 +#endif
57608 + isapnp_for_each_dev(dev) {
57609 + char slot_name[8];
57610 + u32 pnpid;
57612 + if (dev->active)
57613 + continue;
57615 + pnpid = dev->vendor << 16 | dev->device;
57616 + pnpid = cpu_to_le32(pnpid);
57618 +#define HEX(id,a) hex[((id)>>a) & 15]
57619 +#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
57620 + slot_name[0] = CHAR(pnpid, 26);
57621 + slot_name[1] = CHAR(pnpid, 21);
57622 + slot_name[2] = CHAR(pnpid, 16);
57623 + slot_name[3] = HEX(pnpid, 12);
57624 + slot_name[4] = HEX(pnpid, 8);
57625 + slot_name[5] = HEX(pnpid, 4);
57626 + slot_name[6] = HEX(pnpid, 0);
57627 + slot_name[7] = '\0';
57629 + for (id = pnp_dev_table; id->id[0]; id++)
57630 + if (memcmp(id->id, slot_name, 7) == 0)
57631 + break;
57633 + if (id->id[0])
57634 + pnp_init_one(dev, id, slot_name);
57635 + else
57636 + pnp_init_one(dev, NULL, slot_name);
57639 +#ifdef SERIAL_DEBUG_PNP
57640 + printk("Leaving probe_serial_pnp() (probe finished)\n");
57641 +#endif
57644 +static int __init serial8250_pnp_init(void)
57646 + if (!isapnp_present()) {
57647 +#ifdef SERIAL_DEBUG_PNP
57648 + printk("Leaving probe_serial_pnp() (no isapnp)\n");
57649 +#endif
57650 + return -ENODEV;
57652 + pnp_init();
57653 + return 0;
57656 +static void __exit serial8250_pnp_exit(void)
57658 + struct pci_dev *dev = NULL;
57660 + isapnp_for_each_dev(dev) {
57661 + if (dev->driver != (void *)pnp_dev_table)
57662 + continue;
57663 + pnp_remove_one(dev);
57667 +module_init(serial8250_pnp_init);
57668 +module_exit(serial8250_pnp_exit);
57670 +EXPORT_NO_SYMBOLS;
57672 +MODULE_LICENSE("GPL");
57673 +MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
57674 +MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
57676 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
57677 +++ linux-2.4.25/drivers/serial/Config.in 2004-03-31 17:15:09.000000000 +0200
57678 @@ -0,0 +1,91 @@
57680 +# Serial device configuration
57682 +# $Id: Config.in,v 1.4 2001/10/12 15:46:58 rmk Exp $
57684 +mainmenu_option next_comment
57685 +comment 'Serial drivers'
57687 +if [ "$CONFIG_ARM" = "y" ]; then
57688 + # I don't have this in my tree yet.
57689 + dep_bool 'Anakin serial port support' CONFIG_SERIAL_ANAKIN $CONFIG_ARCH_ANAKIN
57690 + dep_bool ' Console on Anakin serial port' CONFIG_SERIAL_ANAKIN_CONSOLE $CONFIG_SERIAL_ANAKIN
57691 + if [ "$CONFIG_SERIAL_ANAKIN" = "y" ]; then
57692 + int ' Default Anakin serial baudrate' CONFIG_ANAKIN_DEFAULT_BAUDRATE 9600
57693 + fi
57695 + dep_tristate 'ARM AMBA serial port support' CONFIG_SERIAL_AMBA $CONFIG_ARCH_INTEGRATOR
57696 + dep_bool ' Support for console on AMBA serial port' CONFIG_SERIAL_AMBA_CONSOLE $CONFIG_SERIAL_AMBA
57697 + if [ "$CONFIG_SERIAL_AMBA" = "y" ]; then
57698 + define_bool CONFIG_SERIAL_INTEGRATOR y
57699 + fi
57701 + dep_tristate 'CLPS711X serial port support' CONFIG_SERIAL_CLPS711X $CONFIG_ARCH_CLPS711X
57702 + dep_bool ' Support for console on CLPS711X serial port' CONFIG_SERIAL_CLPS711X_CONSOLE $CONFIG_SERIAL_CLPS711X
57704 + dep_bool 'DC21285 serial port support' CONFIG_SERIAL_21285 $CONFIG_FOOTBRIDGE
57705 + dep_bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD $CONFIG_SERIAL_21285 $CONFIG_OBSOLETE
57706 + dep_bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE $CONFIG_SERIAL_21285
57708 + dep_bool 'Excalibur serial port (uart00) support' CONFIG_SERIAL_UART00 $CONFIG_ARCH_CAMELOT
57709 + dep_bool ' Support for console on Excalibur serial port' CONFIG_SERIAL_UART00_CONSOLE $CONFIG_SERIAL_UART00
57712 + dep_bool 'SA1100 serial port support' CONFIG_SERIAL_SA1100 $CONFIG_ARCH_SA1100
57713 + dep_bool ' Console on SA1100 serial port' CONFIG_SERIAL_SA1100_CONSOLE $CONFIG_SERIAL_SA1100
57714 + if [ "$CONFIG_SERIAL_SA1100" = "y" ]; then
57715 + int ' Default SA1100 serial baudrate' CONFIG_SA1100_DEFAULT_BAUDRATE 9600
57716 + fi
57718 + dep_tristate 'ARM Omaha serial port support' CONFIG_SERIAL_OMAHA $CONFIG_ARCH_OMAHA
57719 + dep_bool ' Support for console on Omaha serial port' CONFIG_SERIAL_OMAHA_CONSOLE $CONFIG_SERIAL_OMAHA
57721 + dep_tristate 'AT91RM9200 serial port support' CONFIG_SERIAL_AT91 $CONFIG_ARCH_AT91RM9200
57722 + dep_bool ' Console on AT91RM9200 serial port' CONFIG_SERIAL_AT91_CONSOLE $CONFIG_SERIAL_AT91
57726 +# The new 8250/16550 serial drivers
57727 +dep_tristate '8250/16550 and compatible serial support (EXPERIMENTAL)' CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
57728 +dep_bool ' Console on 8250/16550 and compatible serial port (EXPERIMENTAL)' CONFIG_SERIAL_8250_CONSOLE $CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
57730 +dep_mbool 'Extended 8250/16550 serial driver options' CONFIG_SERIAL_8250_EXTENDED $CONFIG_SERIAL_8250
57731 +dep_bool ' Support more than 4 serial ports' CONFIG_SERIAL_8250_MANY_PORTS $CONFIG_SERIAL_8250_EXTENDED
57732 +dep_bool ' Support for sharing serial interrupts' CONFIG_SERIAL_8250_SHARE_IRQ $CONFIG_SERIAL_8250_EXTENDED
57733 +dep_bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_8250_DETECT_IRQ $CONFIG_SERIAL_8250_EXTENDED
57734 +dep_bool ' Support special multiport boards' CONFIG_SERIAL_8250_MULTIPORT $CONFIG_SERIAL_8250_EXTENDED
57735 +dep_bool ' Support Bell Technologies HUB6 card' CONFIG_SERIAL_8250_HUB6 $CONFIG_SERIAL_8250_EXTENDED
57737 +if [ "$CONFIG_SERIAL_AMBA" = "y" -o \
57738 + "$CONFIG_SERIAL_CLPS711X" = "y" -o \
57739 + "$CONFIG_SERIAL_SA1100" = "y" -o \
57740 + "$CONFIG_SERIAL_ANAKIN" = "y" -o \
57741 + "$CONFIG_SERIAL_UART00" = "y" -o \
57742 + "$CONFIG_SERIAL_8250" = "y" -o \
57743 + "$CONFIG_SERIAL_OMAHA" = "y" -o \
57744 + "$CONFIG_SERIAL_AT91" = "y" ]; then
57745 + define_bool CONFIG_SERIAL_CORE y
57746 +else
57747 + if [ "$CONFIG_SERIAL_AMBA" = "m" -o \
57748 + "$CONFIG_SERIAL_CLPS711X" = "m" -o \
57749 + "$CONFIG_SERIAL_SA1100" = "m" -o \
57750 + "$CONFIG_SERIAL_ANAKIN" = "m" -o \
57751 + "$CONFIG_SERIAL_UART00" = "m" -o \
57752 + "$CONFIG_SERIAL_8250" = "m" -o \
57753 + "$CONFIG_SERIAL_OMAHA" = "m" -o \
57754 + "$CONFIG_SERIAL_AT91" = "m" ]; then
57755 + define_bool CONFIG_SERIAL_CORE m
57756 + fi
57758 +if [ "$CONFIG_SERIAL_AMBA_CONSOLE" = "y" -o \
57759 + "$CONFIG_SERIAL_CLPS711X_CONSOLE" = "y" -o \
57760 + "$CONFIG_SERIAL_SA1100_CONSOLE" = "y" -o \
57761 + "$CONFIG_SERIAL_ANAKIN_CONSOLE" = "y" -o \
57762 + "$CONFIG_SERIAL_UART00_CONSOLE" = "y" -o \
57763 + "$CONFIG_SERIAL_8250_CONSOLE" = "y" -o \
57764 + "$CONFIG_SERIAL_OMAHA" = "y" -o \
57765 + "$CONFIG_SERIAL_AT91_CONSOLE" = "y" ]; then
57766 + define_bool CONFIG_SERIAL_CORE_CONSOLE y
57769 +endmenu
57770 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
57771 +++ linux-2.4.25/drivers/serial/Makefile 2004-03-31 17:15:09.000000000 +0200
57772 @@ -0,0 +1,39 @@
57774 +# Makefile for the kernel serial device drivers.
57776 +# Note! Dependencies are done automagically by 'make dep', which also
57777 +# removes any old dependencies. DON'T put your own dependencies here
57778 +# unless it's something special (ie not a .c file).
57780 +# Note 2! The CFLAGS definitions are now inherited from the
57781 +# parent makes..
57783 +# $Id: Makefile,v 1.2 2001/10/12 15:46:58 rmk Exp $
57786 +O_TARGET := serial.o
57788 +export-objs := core.o 8250.o
57789 +obj-y :=
57790 +obj-m :=
57791 +obj-n :=
57792 +obj- :=
57794 +serial-8250-y :=
57795 +serial-8250-$(CONFIG_PCI) += 8250_pci.o
57796 +serial-8250-$(CONFIG_ISAPNP) += 8250_pnp.o
57797 +obj-$(CONFIG_SERIAL_CORE) += core.o
57798 +obj-$(CONFIG_SERIAL_21285) += 21285.o
57799 +obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
57800 +obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o
57801 +obj-$(CONFIG_SERIAL_AMBA) += amba.o
57802 +obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
57803 +obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
57804 +obj-$(CONFIG_SERIAL_UART00) += uart00.o
57805 +obj-$(CONFIG_SERIAL_OMAHA) += omaha.o
57806 +obj-$(CONFIG_SERIAL_AT91US3) += at91us3.o
57808 +include $(TOPDIR)/Rules.make
57810 +fastdep:
57812 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
57813 +++ linux-2.4.25/drivers/serial/amba.c 2004-03-31 17:15:09.000000000 +0200
57814 @@ -0,0 +1,770 @@
57816 + * linux/drivers/char/serial_amba.c
57818 + * Driver for AMBA serial ports
57820 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
57822 + * Copyright 1999 ARM Limited
57823 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
57825 + * This program is free software; you can redistribute it and/or modify
57826 + * it under the terms of the GNU General Public License as published by
57827 + * the Free Software Foundation; either version 2 of the License, or
57828 + * (at your option) any later version.
57830 + * This program is distributed in the hope that it will be useful,
57831 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
57832 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57833 + * GNU General Public License for more details.
57835 + * You should have received a copy of the GNU General Public License
57836 + * along with this program; if not, write to the Free Software
57837 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
57839 + * $Id: amba.c,v 1.9.2.2 2002/10/24 09:53:25 rmk Exp $
57841 + * This is a generic driver for ARM AMBA-type serial ports. They
57842 + * have a lot of 16550-like features, but are not register compatable.
57843 + * Note that although they do have CTS, DCD and DSR inputs, they do
57844 + * not have an RI input, nor do they have DTR or RTS outputs. If
57845 + * required, these have to be supplied via some other means (eg, GPIO)
57846 + * and hooked into this driver.
57847 + */
57848 +#include <linux/config.h>
57849 +#include <linux/module.h>
57850 +#include <linux/tty.h>
57851 +#include <linux/ioport.h>
57852 +#include <linux/init.h>
57853 +#include <linux/sched.h>
57854 +#include <linux/serial.h>
57855 +#include <linux/console.h>
57856 +#include <linux/sysrq.h>
57858 +#include <asm/io.h>
57859 +#include <asm/irq.h>
57861 +#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
57862 +#define SUPPORT_SYSRQ
57863 +#endif
57865 +#include <linux/serial_core.h>
57867 +#include <asm/hardware/serial_amba.h>
57869 +#define UART_NR 2
57871 +#define SERIAL_AMBA_MAJOR 204
57872 +#define SERIAL_AMBA_MINOR 16
57873 +#define SERIAL_AMBA_NR UART_NR
57875 +#define CALLOUT_AMBA_NAME "cuaam"
57876 +#define CALLOUT_AMBA_MAJOR 205
57877 +#define CALLOUT_AMBA_MINOR 16
57878 +#define CALLOUT_AMBA_NR UART_NR
57880 +static struct tty_driver normal, callout;
57881 +static struct tty_struct *amba_table[UART_NR];
57882 +static struct termios *amba_termios[UART_NR], *amba_termios_locked[UART_NR];
57883 +#ifdef SUPPORT_SYSRQ
57884 +static struct console amba_console;
57885 +#endif
57887 +#define AMBA_ISR_PASS_LIMIT 256
57890 + * Access macros for the AMBA UARTs
57891 + */
57892 +#define UART_GET_INT_STATUS(p) readb((p)->membase + AMBA_UARTIIR)
57893 +#define UART_PUT_ICR(p, c) writel((c), (p)->membase + AMBA_UARTICR)
57894 +#define UART_GET_FR(p) readb((p)->membase + AMBA_UARTFR)
57895 +#define UART_GET_CHAR(p) readb((p)->membase + AMBA_UARTDR)
57896 +#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + AMBA_UARTDR)
57897 +#define UART_GET_RSR(p) readb((p)->membase + AMBA_UARTRSR)
57898 +#define UART_GET_CR(p) readb((p)->membase + AMBA_UARTCR)
57899 +#define UART_PUT_CR(p,c) writel((c), (p)->membase + AMBA_UARTCR)
57900 +#define UART_GET_LCRL(p) readb((p)->membase + AMBA_UARTLCR_L)
57901 +#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + AMBA_UARTLCR_L)
57902 +#define UART_GET_LCRM(p) readb((p)->membase + AMBA_UARTLCR_M)
57903 +#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + AMBA_UARTLCR_M)
57904 +#define UART_GET_LCRH(p) readb((p)->membase + AMBA_UARTLCR_H)
57905 +#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + AMBA_UARTLCR_H)
57906 +#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
57907 +#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
57908 +#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
57910 +#define UART_DUMMY_RSR_RX 256
57911 +#define UART_PORT_SIZE 64
57914 + * On the Integrator platform, the port RTS and DTR are provided by
57915 + * bits in the following SC_CTRLS register bits:
57916 + * RTS DTR
57917 + * UART0 7 6
57918 + * UART1 5 4
57919 + */
57920 +#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
57921 +#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
57924 + * We wrap our port structure around the generic uart_port.
57925 + */
57926 +struct uart_amba_port {
57927 + struct uart_port port;
57928 + unsigned int dtr_mask;
57929 + unsigned int rts_mask;
57930 + unsigned int old_status;
57933 +static void ambauart_stop_tx(struct uart_port *port, unsigned int tty_stop)
57935 + unsigned int cr;
57937 + cr = UART_GET_CR(port);
57938 + cr &= ~AMBA_UARTCR_TIE;
57939 + UART_PUT_CR(port, cr);
57942 +static void ambauart_start_tx(struct uart_port *port, unsigned int tty_start)
57944 + unsigned int cr;
57946 + cr = UART_GET_CR(port);
57947 + cr |= AMBA_UARTCR_TIE;
57948 + UART_PUT_CR(port, cr);
57951 +static void ambauart_stop_rx(struct uart_port *port)
57953 + unsigned int cr;
57955 + cr = UART_GET_CR(port);
57956 + cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
57957 + UART_PUT_CR(port, cr);
57960 +static void ambauart_enable_ms(struct uart_port *port)
57962 + unsigned int cr;
57964 + cr = UART_GET_CR(port);
57965 + cr |= AMBA_UARTCR_MSIE;
57966 + UART_PUT_CR(port, cr);
57969 +static void
57970 +#ifdef SUPPORT_SYSRQ
57971 +ambauart_rx_chars(struct uart_port *port, struct pt_regs *regs)
57972 +#else
57973 +ambauart_rx_chars(struct uart_port *port)
57974 +#endif
57976 + struct tty_struct *tty = port->info->tty;
57977 + unsigned int status, ch, rsr, max_count = 256;
57979 + status = UART_GET_FR(port);
57980 + while (UART_RX_DATA(status) && max_count--) {
57981 + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
57982 + tty->flip.tqueue.routine((void *)tty);
57983 + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
57984 + printk(KERN_WARNING "TTY_DONT_FLIP set\n");
57985 + return;
57989 + ch = UART_GET_CHAR(port);
57991 + *tty->flip.char_buf_ptr = ch;
57992 + *tty->flip.flag_buf_ptr = TTY_NORMAL;
57993 + port->icount.rx++;
57995 + /*
57996 + * Note that the error handling code is
57997 + * out of the main execution path
57998 + */
57999 + rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
58000 + if (rsr & AMBA_UARTRSR_ANY) {
58001 + if (rsr & AMBA_UARTRSR_BE) {
58002 + rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
58003 + port->icount.brk++;
58004 + if (uart_handle_break(port))
58005 + goto ignore_char;
58006 + } else if (rsr & AMBA_UARTRSR_PE)
58007 + port->icount.parity++;
58008 + else if (rsr & AMBA_UARTRSR_FE)
58009 + port->icount.frame++;
58010 + if (rsr & AMBA_UARTRSR_OE)
58011 + port->icount.overrun++;
58013 + rsr &= port->read_status_mask;
58015 + if (rsr & AMBA_UARTRSR_BE)
58016 + *tty->flip.flag_buf_ptr = TTY_BREAK;
58017 + else if (rsr & AMBA_UARTRSR_PE)
58018 + *tty->flip.flag_buf_ptr = TTY_PARITY;
58019 + else if (rsr & AMBA_UARTRSR_FE)
58020 + *tty->flip.flag_buf_ptr = TTY_FRAME;
58023 + if (uart_handle_sysrq_char(port, ch, regs))
58024 + goto ignore_char;
58026 + if ((rsr & port->ignore_status_mask) == 0) {
58027 + tty->flip.flag_buf_ptr++;
58028 + tty->flip.char_buf_ptr++;
58029 + tty->flip.count++;
58031 + if ((rsr & AMBA_UARTRSR_OE) &&
58032 + tty->flip.count < TTY_FLIPBUF_SIZE) {
58033 + /*
58034 + * Overrun is special, since it's reported
58035 + * immediately, and doesn't affect the current
58036 + * character
58037 + */
58038 + *tty->flip.char_buf_ptr++ = 0;
58039 + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
58040 + tty->flip.count++;
58042 + ignore_char:
58043 + status = UART_GET_FR(port);
58045 + tty_flip_buffer_push(tty);
58046 + return;
58049 +static void ambauart_tx_chars(struct uart_port *port)
58051 + struct circ_buf *xmit = &port->info->xmit;
58052 + int count;
58054 + if (port->x_char) {
58055 + UART_PUT_CHAR(port, port->x_char);
58056 + port->icount.tx++;
58057 + port->x_char = 0;
58058 + return;
58060 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
58061 + ambauart_stop_tx(port, 0);
58062 + return;
58065 + count = port->fifosize >> 1;
58066 + do {
58067 + UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
58068 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
58069 + port->icount.tx++;
58070 + if (uart_circ_empty(xmit))
58071 + break;
58072 + } while (--count > 0);
58074 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
58075 + uart_write_wakeup(port);
58077 + if (uart_circ_empty(xmit))
58078 + ambauart_stop_tx(port, 0);
58081 +static void ambauart_modem_status(struct uart_port *port)
58083 + struct uart_amba_port *uap = (struct uart_amba_port *)port;
58084 + unsigned int status, delta;
58086 + UART_PUT_ICR(&uap->port, 0);
58088 + status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY;
58090 + delta = status ^ uap->old_status;
58091 + uap->old_status = status;
58093 + if (!delta)
58094 + return;
58096 + if (delta & AMBA_UARTFR_DCD)
58097 + uart_handle_dcd_change(&uap->port, status & AMBA_UARTFR_DCD);
58099 + if (delta & AMBA_UARTFR_DSR)
58100 + uap->port.icount.dsr++;
58102 + if (delta & AMBA_UARTFR_CTS)
58103 + uart_handle_cts_change(&uap->port, status & AMBA_UARTFR_CTS);
58105 + wake_up_interruptible(&uap->port.info->delta_msr_wait);
58108 +static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
58110 + struct uart_port *port = dev_id;
58111 + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
58113 + status = UART_GET_INT_STATUS(port);
58114 + do {
58115 + if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
58116 +#ifdef SUPPORT_SYSRQ
58117 + ambauart_rx_chars(port, regs);
58118 +#else
58119 + ambauart_rx_chars(port);
58120 +#endif
58121 + if (status & AMBA_UARTIIR_TIS)
58122 + ambauart_tx_chars(port);
58123 + if (status & AMBA_UARTIIR_MIS)
58124 + ambauart_modem_status(port);
58126 + if (pass_counter-- == 0)
58127 + break;
58129 + status = UART_GET_INT_STATUS(port);
58130 + } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS |
58131 + AMBA_UARTIIR_TIS));
58134 +static unsigned int ambauart_tx_empty(struct uart_port *port)
58136 + return UART_GET_FR(port) & AMBA_UARTFR_BUSY ? 0 : TIOCSER_TEMT;
58139 +static unsigned int ambauart_get_mctrl(struct uart_port *port)
58141 + unsigned int result = 0;
58142 + unsigned int status;
58144 + status = UART_GET_FR(port);
58145 + if (status & AMBA_UARTFR_DCD)
58146 + result |= TIOCM_CAR;
58147 + if (status & AMBA_UARTFR_DSR)
58148 + result |= TIOCM_DSR;
58149 + if (status & AMBA_UARTFR_CTS)
58150 + result |= TIOCM_CTS;
58152 + return result;
58155 +static void ambauart_set_mctrl(struct uart_port *port, unsigned int mctrl)
58157 + struct uart_amba_port *uap = (struct uart_amba_port *)port;
58158 + unsigned int ctrls = 0, ctrlc = 0;
58160 + if (mctrl & TIOCM_RTS)
58161 + ctrlc |= uap->rts_mask;
58162 + else
58163 + ctrls |= uap->rts_mask;
58165 + if (mctrl & TIOCM_DTR)
58166 + ctrlc |= uap->dtr_mask;
58167 + else
58168 + ctrls |= uap->dtr_mask;
58170 + __raw_writel(ctrls, SC_CTRLS);
58171 + __raw_writel(ctrlc, SC_CTRLC);
58174 +static void ambauart_break_ctl(struct uart_port *port, int break_state)
58176 + unsigned long flags;
58177 + unsigned int lcr_h;
58179 + spin_lock_irqsave(&port->lock, flags);
58180 + lcr_h = UART_GET_LCRH(port);
58181 + if (break_state == -1)
58182 + lcr_h |= AMBA_UARTLCR_H_BRK;
58183 + else
58184 + lcr_h &= ~AMBA_UARTLCR_H_BRK;
58185 + UART_PUT_LCRH(port, lcr_h);
58186 + spin_unlock_irqrestore(&port->lock, flags);
58189 +static int ambauart_startup(struct uart_port *port)
58191 + struct uart_amba_port *uap = (struct uart_amba_port *)port;
58192 + int retval;
58194 + /*
58195 + * Allocate the IRQ
58196 + */
58197 + retval = request_irq(port->irq, ambauart_int, 0, "amba", port);
58198 + if (retval)
58199 + return retval;
58201 + /*
58202 + * initialise the old status of the modem signals
58203 + */
58204 + uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
58206 + /*
58207 + * Finally, enable interrupts
58208 + */
58209 + UART_PUT_CR(port, AMBA_UARTCR_UARTEN | AMBA_UARTCR_RIE |
58210 + AMBA_UARTCR_RTIE);
58212 + return 0;
58215 +static void ambauart_shutdown(struct uart_port *port)
58217 + /*
58218 + * Free the interrupt
58219 + */
58220 + free_irq(port->irq, port);
58222 + /*
58223 + * disable all interrupts, disable the port
58224 + */
58225 + UART_PUT_CR(port, 0);
58227 + /* disable break condition and fifos */
58228 + UART_PUT_LCRH(port, UART_GET_LCRH(port) &
58229 + ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
58232 +static void ambauart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
58234 + unsigned int lcr_h, old_cr;
58235 + unsigned long flags;
58237 +#if DEBUG
58238 + printk("ambauart_set_cflag(0x%x) called\n", cflag);
58239 +#endif
58240 + /* byte size and parity */
58241 + switch (cflag & CSIZE) {
58242 + case CS5:
58243 + lcr_h = AMBA_UARTLCR_H_WLEN_5;
58244 + break;
58245 + case CS6:
58246 + lcr_h = AMBA_UARTLCR_H_WLEN_6;
58247 + break;
58248 + case CS7:
58249 + lcr_h = AMBA_UARTLCR_H_WLEN_7;
58250 + break;
58251 + default: // CS8
58252 + lcr_h = AMBA_UARTLCR_H_WLEN_8;
58253 + break;
58255 + if (cflag & CSTOPB)
58256 + lcr_h |= AMBA_UARTLCR_H_STP2;
58257 + if (cflag & PARENB) {
58258 + lcr_h |= AMBA_UARTLCR_H_PEN;
58259 + if (!(cflag & PARODD))
58260 + lcr_h |= AMBA_UARTLCR_H_EPS;
58262 + if (port->fifosize > 1)
58263 + lcr_h |= AMBA_UARTLCR_H_FEN;
58265 + spin_lock_irqsave(&port->lock, flags);
58267 + port->read_status_mask = AMBA_UARTRSR_OE;
58268 + if (iflag & INPCK)
58269 + port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
58270 + if (iflag & (BRKINT | PARMRK))
58271 + port->read_status_mask |= AMBA_UARTRSR_BE;
58273 + /*
58274 + * Characters to ignore
58275 + */
58276 + port->ignore_status_mask = 0;
58277 + if (iflag & IGNPAR)
58278 + port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
58279 + if (iflag & IGNBRK) {
58280 + port->ignore_status_mask |= AMBA_UARTRSR_BE;
58281 + /*
58282 + * If we're ignoring parity and break indicators,
58283 + * ignore overruns too (for real raw support).
58284 + */
58285 + if (iflag & IGNPAR)
58286 + port->ignore_status_mask |= AMBA_UARTRSR_OE;
58289 + /*
58290 + * Ignore all characters if CREAD is not set.
58291 + */
58292 + if ((cflag & CREAD) == 0)
58293 + port->ignore_status_mask |= UART_DUMMY_RSR_RX;
58295 + old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE;
58297 + if (UART_ENABLE_MS(port, cflag))
58298 + old_cr |= AMBA_UARTCR_MSIE;
58300 + UART_PUT_CR(port, 0);
58302 + /* Set baud rate */
58303 + quot -= 1;
58304 + UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
58305 + UART_PUT_LCRL(port, (quot & 0xff));
58307 + /*
58308 + * ----------v----------v----------v----------v-----
58309 + * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
58310 + * ----------^----------^----------^----------^-----
58311 + */
58312 + UART_PUT_LCRH(port, lcr_h);
58313 + UART_PUT_CR(port, old_cr);
58315 + spin_unlock_irqrestore(&port->lock, flags);
58318 +static const char *ambauart_type(struct uart_port *port)
58320 + return port->type == PORT_AMBA ? "AMBA" : NULL;
58324 + * Release the memory region(s) being used by 'port'
58325 + */
58326 +static void ambauart_release_port(struct uart_port *port)
58328 + release_mem_region(port->mapbase, UART_PORT_SIZE);
58332 + * Request the memory region(s) being used by 'port'
58333 + */
58334 +static int ambauart_request_port(struct uart_port *port)
58336 + return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba")
58337 + != NULL ? 0 : -EBUSY;
58341 + * Configure/autoconfigure the port.
58342 + */
58343 +static void ambauart_config_port(struct uart_port *port, int flags)
58345 + if (flags & UART_CONFIG_TYPE) {
58346 + port->type = PORT_AMBA;
58347 + ambauart_request_port(port);
58352 + * verify the new serial_struct (for TIOCSSERIAL).
58353 + */
58354 +static int ambauart_verify_port(struct uart_port *port, struct serial_struct *ser)
58356 + int ret = 0;
58357 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
58358 + ret = -EINVAL;
58359 + if (ser->irq < 0 || ser->irq >= NR_IRQS)
58360 + ret = -EINVAL;
58361 + if (ser->baud_base < 9600)
58362 + ret = -EINVAL;
58363 + return ret;
58366 +static struct uart_ops amba_pops = {
58367 + .tx_empty = ambauart_tx_empty,
58368 + .set_mctrl = ambauart_set_mctrl,
58369 + .get_mctrl = ambauart_get_mctrl,
58370 + .stop_tx = ambauart_stop_tx,
58371 + .start_tx = ambauart_start_tx,
58372 + .stop_rx = ambauart_stop_rx,
58373 + .enable_ms = ambauart_enable_ms,
58374 + .break_ctl = ambauart_break_ctl,
58375 + .startup = ambauart_startup,
58376 + .shutdown = ambauart_shutdown,
58377 + .change_speed = ambauart_change_speed,
58378 + .type = ambauart_type,
58379 + .release_port = ambauart_release_port,
58380 + .request_port = ambauart_request_port,
58381 + .config_port = ambauart_config_port,
58382 + .verify_port = ambauart_verify_port,
58385 +static struct uart_amba_port amba_ports[UART_NR] = {
58387 + .port = {
58388 + .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
58389 + .mapbase = INTEGRATOR_UART0_BASE,
58390 + .iotype = SERIAL_IO_MEM,
58391 + .irq = IRQ_UARTINT0,
58392 + .uartclk = 14745600,
58393 + .fifosize = 16,
58394 + .ops = &amba_pops,
58395 + .flags = ASYNC_BOOT_AUTOCONF,
58396 + .line = 0,
58397 + },
58398 + .dtr_mask = 1 << 5,
58399 + .rts_mask = 1 << 4,
58400 + },
58402 + .port = {
58403 + .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
58404 + .mapbase = INTEGRATOR_UART1_BASE,
58405 + .iotype = SERIAL_IO_MEM,
58406 + .irq = IRQ_UARTINT1,
58407 + .uartclk = 14745600,
58408 + .fifosize = 16,
58409 + .ops = &amba_pops,
58410 + .flags = ASYNC_BOOT_AUTOCONF,
58411 + .line = 1,
58412 + },
58413 + .dtr_mask = 1 << 7,
58414 + .rts_mask = 1 << 6,
58418 +#ifdef CONFIG_SERIAL_AMBA_CONSOLE
58420 +static void ambauart_console_write(struct console *co, const char *s, unsigned int count)
58422 + struct uart_port *port = &amba_ports[co->index].port;
58423 + unsigned int status, old_cr;
58424 + int i;
58426 + /*
58427 + * First save the CR then disable the interrupts
58428 + */
58429 + old_cr = UART_GET_CR(port);
58430 + UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
58432 + /*
58433 + * Now, do each character
58434 + */
58435 + for (i = 0; i < count; i++) {
58436 + do {
58437 + status = UART_GET_FR(port);
58438 + } while (!UART_TX_READY(status));
58439 + UART_PUT_CHAR(port, s[i]);
58440 + if (s[i] == '\n') {
58441 + do {
58442 + status = UART_GET_FR(port);
58443 + } while (!UART_TX_READY(status));
58444 + UART_PUT_CHAR(port, '\r');
58448 + /*
58449 + * Finally, wait for transmitter to become empty
58450 + * and restore the TCR
58451 + */
58452 + do {
58453 + status = UART_GET_FR(port);
58454 + } while (status & AMBA_UARTFR_BUSY);
58455 + UART_PUT_CR(port, old_cr);
58458 +static kdev_t ambauart_console_device(struct console *co)
58460 + return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + co->index);
58463 +static void __init
58464 +ambauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
58466 + if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) {
58467 + unsigned int lcr_h, quot;
58468 + lcr_h = UART_GET_LCRH(port);
58470 + *parity = 'n';
58471 + if (lcr_h & AMBA_UARTLCR_H_PEN) {
58472 + if (lcr_h & AMBA_UARTLCR_H_EPS)
58473 + *parity = 'e';
58474 + else
58475 + *parity = 'o';
58478 + if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7)
58479 + *bits = 7;
58480 + else
58481 + *bits = 8;
58483 + quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8;
58484 + *baud = port->uartclk / (16 * (quot + 1));
58488 +static int __init ambauart_console_setup(struct console *co, char *options)
58490 + struct uart_port *port;
58491 + int baud = 38400;
58492 + int bits = 8;
58493 + int parity = 'n';
58494 + int flow = 'n';
58496 + /*
58497 + * Check whether an invalid uart number has been specified, and
58498 + * if so, search for the first available port that does have
58499 + * console support.
58500 + */
58501 + if (co->index >= UART_NR)
58502 + co->index = 0;
58503 + port = &amba_ports[co->index].port;
58505 + if (options)
58506 + uart_parse_options(options, &baud, &parity, &bits, &flow);
58507 + else
58508 + ambauart_console_get_options(port, &baud, &parity, &bits);
58510 + return uart_set_options(port, co, baud, parity, bits, flow);
58513 +static struct console amba_console = {
58514 + .name = "ttyAM",
58515 + .write = ambauart_console_write,
58516 + .device = ambauart_console_device,
58517 + .setup = ambauart_console_setup,
58518 + .flags = CON_PRINTBUFFER,
58519 + .index = -1,
58522 +void __init ambauart_console_init(void)
58524 + register_console(&amba_console);
58527 +#define AMBA_CONSOLE &amba_console
58528 +#else
58529 +#define AMBA_CONSOLE NULL
58530 +#endif
58532 +static struct uart_driver amba_reg = {
58533 + .owner = THIS_MODULE,
58534 + .normal_major = SERIAL_AMBA_MAJOR,
58535 +#ifdef CONFIG_DEVFS_FS
58536 + .normal_name = "ttyAM%d",
58537 + .callout_name = "cuaam%d",
58538 +#else
58539 + .normal_name = "ttyAM",
58540 + .callout_name = "cuaam",
58541 +#endif
58542 + .normal_driver = &normal,
58543 + .callout_major = CALLOUT_AMBA_MAJOR,
58544 + .callout_driver = &callout,
58545 + .table = amba_table,
58546 + .termios = amba_termios,
58547 + .termios_locked = amba_termios_locked,
58548 + .minor = SERIAL_AMBA_MINOR,
58549 + .nr = UART_NR,
58550 + .cons = AMBA_CONSOLE,
58553 +static int __init ambauart_init(void)
58555 + int ret;
58557 + ret = uart_register_driver(&amba_reg);
58558 + if (ret == 0) {
58559 + int i;
58561 + for (i = 0; i < UART_NR; i++)
58562 + uart_add_one_port(&amba_reg, &amba_ports[i].port);
58564 + return ret;
58567 +static void __exit ambauart_exit(void)
58569 + int i;
58571 + for (i = 0; i < UART_NR; i++)
58572 + uart_remove_one_port(&amba_reg, &amba_ports[i].port);
58574 + uart_unregister_driver(&amba_reg);
58577 +module_init(ambauart_init);
58578 +module_exit(ambauart_exit);
58580 +EXPORT_NO_SYMBOLS;
58582 +MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
58583 +MODULE_DESCRIPTION("ARM AMBA serial port driver");
58584 +MODULE_LICENSE("GPL");
58585 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
58586 +++ linux-2.4.25/drivers/serial/anakin.c 2004-03-31 17:15:09.000000000 +0200
58587 @@ -0,0 +1,545 @@
58589 + * linux/drivers/char/serial_anakin.c
58591 + * Based on driver for AMBA serial ports, by ARM Limited,
58592 + * Deep Blue Solutions Ltd., Linus Torvalds and Theodore Ts'o.
58594 + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
58596 + * Copyright (C) 2001 Blue Mug, Inc. for Acunia N.V.
58598 + * This program is free software; you can redistribute it and/or modify
58599 + * it under the terms of the GNU General Public License version 2 as
58600 + * published by the Free Software Foundation.
58602 + * Changelog:
58603 + * 20-Apr-2001 TTC Created
58604 + * 05-May-2001 W/TTC Updated for serial_core.c
58605 + * 27-Jun-2001 jonm Minor changes; add mctrl support, switch to
58606 + * SA_INTERRUPT. Works reliably now. No longer requires
58607 + * changes to the serial_core API.
58609 + * $Id: anakin.c,v 1.5.2.2 2002/10/24 09:53:25 rmk Exp $
58610 + */
58612 +#include <linux/config.h>
58613 +#include <linux/module.h>
58614 +#include <linux/errno.h>
58615 +#include <linux/signal.h>
58616 +#include <linux/sched.h>
58617 +#include <linux/interrupt.h>
58618 +#include <linux/tty.h>
58619 +#include <linux/tty_flip.h>
58620 +#include <linux/major.h>
58621 +#include <linux/string.h>
58622 +#include <linux/fcntl.h>
58623 +#include <linux/ptrace.h>
58624 +#include <linux/ioport.h>
58625 +#include <linux/mm.h>
58626 +#include <linux/slab.h>
58627 +#include <linux/init.h>
58628 +#include <linux/circ_buf.h>
58629 +#include <linux/serial.h>
58630 +#include <linux/console.h>
58631 +#include <linux/sysrq.h>
58633 +#include <asm/system.h>
58634 +#include <asm/io.h>
58635 +#include <asm/irq.h>
58636 +#include <asm/uaccess.h>
58637 +#include <asm/bitops.h>
58639 +#include <linux/serial_core.h>
58641 +#include <asm/arch/serial_reg.h>
58643 +#define UART_NR 5
58645 +#define SERIAL_ANAKIN_NAME "ttyAN"
58646 +#define SERIAL_ANAKIN_MAJOR 204
58647 +#define SERIAL_ANAKIN_MINOR 32
58649 +#define CALLOUT_ANAKIN_NAME "cuaan"
58650 +#define CALLOUT_ANAKIN_MAJOR 205
58651 +#define CALLOUT_ANAKIN_MINOR 32
58653 +static struct tty_driver normal, callout;
58654 +static struct tty_struct *anakin_table[UART_NR];
58655 +static struct termios *anakin_termios[UART_NR], *anakin_termios_locked[UART_NR];
58656 +static struct uart_state anakin_state[UART_NR];
58657 +static u_int txenable[NR_IRQS]; /* Software interrupt register */
58659 +static inline unsigned int
58660 +anakin_in(struct uart_port *port, u_int offset)
58662 + return __raw_readl(port->base + offset);
58665 +static inline void
58666 +anakin_out(struct uart_port *port, u_int offset, unsigned int value)
58668 + __raw_writel(value, port->base + offset);
58671 +static void
58672 +anakin_stop_tx(struct uart_port *port, u_int from_tty)
58674 + txenable[port->irq] = 0;
58677 +static inline void
58678 +anakin_transmit_buffer(struct uart_info *info)
58680 + struct uart_port *port = info->port;
58682 + while (!(anakin_in(port, 0x10) & TXEMPTY));
58683 + anakin_out(port, 0x14, info->xmit.buf[info->xmit.tail]);
58684 + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
58685 + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE-1);
58686 + info->state->icount.tx++;
58688 + if (info->xmit.head == info->xmit.tail)
58689 + anakin_stop_tx(port, 0);
58692 +static inline void
58693 +anakin_transmit_x_char(struct uart_info *info)
58695 + struct uart_port *port = info->port;
58697 + anakin_out(port, 0x14, info->x_char);
58698 + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
58699 + info->state->icount.tx++;
58700 + info->x_char = 0;
58703 +static void
58704 +anakin_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
58706 + unsigned int flags;
58708 + save_flags_cli(flags);
58710 + // is it this... or below: if (nonempty
58711 + if (!txenable[port->irq]) {
58712 + txenable[port->irq] = TXENABLE;
58714 + if ((anakin_in(port, 0x10) & TXEMPTY) && nonempty) {
58715 + anakin_transmit_buffer((struct uart_info*)port->unused);
58719 + restore_flags(flags);
58722 +static void
58723 +anakin_stop_rx(struct uart_port *port)
58725 + unsigned long flags;
58727 + save_flags_cli(flags);
58728 + while (anakin_in(port, 0x10) & RXRELEASE)
58729 + anakin_in(port, 0x14);
58730 + anakin_out(port, 0x18, anakin_in(port, 0x18) | BLOCKRX);
58731 + restore_flags(flags);
58734 +static void
58735 +anakin_enable_ms(struct uart_port *port)
58739 +static inline void
58740 +anakin_rx_chars(struct uart_info *info)
58742 + unsigned int ch;
58743 + struct tty_struct *tty = info->tty;
58745 + if (!(anakin_in(info->port, 0x10) & RXRELEASE))
58746 + return;
58748 + ch = anakin_in(info->port, 0x14) & 0xff;
58750 + if (tty->flip.count < TTY_FLIPBUF_SIZE) {
58751 + *tty->flip.char_buf_ptr++ = ch;
58752 + *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
58753 + info->state->icount.rx++;
58754 + tty->flip.count++;
58755 + }
58756 + tty_flip_buffer_push(tty);
58759 +static inline void
58760 +anakin_overrun_chars(struct uart_info *info)
58762 + unsigned int ch;
58764 + ch = anakin_in(info->port, 0x14);
58765 + info->state->icount.overrun++;
58768 +static inline void
58769 +anakin_tx_chars(struct uart_info *info)
58771 + if (info->x_char) {
58772 + anakin_transmit_x_char(info);
58773 + return;
58776 + if (info->xmit.head == info->xmit.tail
58777 + || info->tty->stopped
58778 + || info->tty->hw_stopped) {
58779 + anakin_stop_tx(info->port, 0);
58780 + return;
58783 + anakin_transmit_buffer(info);
58785 + if (CIRC_CNT(info->xmit.head,
58786 + info->xmit.tail,
58787 + UART_XMIT_SIZE) < WAKEUP_CHARS)
58788 + uart_event(info, EVT_WRITE_WAKEUP);
58791 +static void
58792 +anakin_int(int irq, void *dev_id, struct pt_regs *regs)
58794 + unsigned int status;
58795 + struct uart_info *info = dev_id;
58797 + status = anakin_in(info->port, 0x1c);
58799 + if (status & RX)
58800 + anakin_rx_chars(info);
58802 + if (status & OVERRUN)
58803 + anakin_overrun_chars(info);
58805 + if (txenable[info->port->irq] && (status & TX))
58806 + anakin_tx_chars(info);
58809 +static u_int
58810 +anakin_tx_empty(struct uart_port *port)
58812 + return anakin_in(port, 0x10) & TXEMPTY ? TIOCSER_TEMT : 0;
58815 +static u_int
58816 +anakin_get_mctrl(struct uart_port *port)
58818 + unsigned int status = 0;
58820 + status |= (anakin_in(port, 0x10) & CTS ? TIOCM_CTS : 0);
58821 + status |= (anakin_in(port, 0x18) & DCD ? TIOCM_CAR : 0);
58822 + status |= (anakin_in(port, 0x18) & DTR ? TIOCM_DTR : 0);
58823 + status |= (anakin_in(port, 0x18) & RTS ? TIOCM_RTS : 0);
58825 + return status;
58828 +static void
58829 +anakin_set_mctrl(struct uart_port *port, u_int mctrl)
58831 + unsigned int status;
58833 + status = anakin_in(port, 0x18);
58835 + if (mctrl & TIOCM_RTS)
58836 + status |= RTS;
58837 + else
58838 + status &= ~RTS;
58840 + if (mctrl & TIOCM_CAR)
58841 + status |= DCD;
58842 + else
58843 + status &= ~DCD;
58845 + anakin_out(port, 0x18, status);
58848 +static void
58849 +anakin_break_ctl(struct uart_port *port, int break_state)
58851 + unsigned int status;
58853 + status = anakin_in(port, 0x20);
58855 + if (break_state == -1)
58856 + status |= SETBREAK;
58857 + else
58858 + status &= ~SETBREAK;
58860 + anakin_out(port, 0x20, status);
58863 +static int
58864 +anakin_startup(struct uart_port *port, struct uart_info *info)
58866 + int retval;
58867 + unsigned int read,write;
58869 + /*
58870 + * Allocate the IRQ
58871 + */
58872 + retval = request_irq(port->irq, anakin_int, SA_INTERRUPT, "serial_anakin", info);
58873 + if (retval)
58874 + return retval;
58876 + port->ops->set_mctrl(port, info->mctrl);
58878 + /*
58879 + * initialise the old status of the modem signals
58880 + */
58881 + port->old_status = 0;
58883 + /*
58884 + * Finally, disable IRQ and softIRQs for first byte)
58885 + */
58886 + txenable[port->irq] = 0;
58887 + read = anakin_in(port, 0x18);
58888 + write = (read & ~(RTS | DTR | BLOCKRX)) | IRQENABLE;
58889 + anakin_out(port, 0x18, write);
58891 + /* Store the uart_info pointer so we can reference it in
58892 + * anakin_start_tx() */
58893 + port->unused = (u_int)info;
58895 + return 0;
58898 +static void
58899 +anakin_shutdown(struct uart_port *port, struct uart_info *info)
58901 + /*
58902 + * Free the interrupt
58903 + */
58904 + free_irq(port->irq, info);
58906 + /*
58907 + * disable all interrupts, disable the port
58908 + */
58909 + anakin_out(port, 0x18, anakin_in(port, 0x18) & ~IRQENABLE);
58912 +static void
58913 +anakin_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
58915 + unsigned int flags;
58917 + save_flags_cli(flags);
58918 + while (!(anakin_in(port, 0x10) & TXEMPTY));
58919 + anakin_out(port, 0x10, (anakin_in(port, 0x10) & ~PRESCALER)
58920 + | (quot << 3));
58922 + //parity always set to none
58923 + anakin_out(port, 0x18, anakin_in(port, 0x18) & ~PARITY);
58924 + restore_flags(flags);
58927 +static const char *anakin_type(struct port *port)
58929 + return port->type == PORT_ANAKIN ? "ANAKIN" : NULL;
58932 +static struct uart_ops anakin_pops = {
58933 + tx_empty: anakin_tx_empty,
58934 + set_mctrl: anakin_set_mctrl,
58935 + get_mctrl: anakin_get_mctrl,
58936 + stop_tx: anakin_stop_tx,
58937 + start_tx: anakin_start_tx,
58938 + stop_rx: anakin_stop_rx,
58939 + enable_ms: anakin_enable_ms,
58940 + break_ctl: anakin_break_ctl,
58941 + startup: anakin_startup,
58942 + shutdown: anakin_shutdown,
58943 + change_speed: anakin_change_speed,
58944 + type: anakin_type,
58947 +static struct uart_port anakin_ports[UART_NR] = {
58949 + base: IO_BASE + UART0,
58950 + irq: IRQ_UART0,
58951 + uartclk: 3686400,
58952 + fifosize: 0,
58953 + ops: &anakin_pops,
58954 + },
58956 + base: IO_BASE + UART1,
58957 + irq: IRQ_UART1,
58958 + uartclk: 3686400,
58959 + fifosize: 0,
58960 + ops: &anakin_pops,
58961 + },
58963 + base: IO_BASE + UART2,
58964 + irq: IRQ_UART2,
58965 + uartclk: 3686400,
58966 + fifosize: 0,
58967 + ops: &anakin_pops,
58968 + },
58970 + base: IO_BASE + UART3,
58971 + irq: IRQ_UART3,
58972 + uartclk: 3686400,
58973 + fifosize: 0,
58974 + ops: &anakin_pops,
58975 + },
58977 + base: IO_BASE + UART4,
58978 + irq: IRQ_UART4,
58979 + uartclk: 3686400,
58980 + fifosize: 0,
58981 + ops: &anakin_pops,
58982 + },
58986 +#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
58988 +static void
58989 +anakin_console_write(struct console *co, const char *s, u_int count)
58991 + struct uart_port *port = anakin_ports + co->index;
58992 + unsigned int flags, status, i;
58994 + /*
58995 + * First save the status then disable the interrupts
58996 + */
58997 + save_flags_cli(flags);
58998 + status = anakin_in(port, 0x18);
58999 + anakin_out(port, 0x18, status & ~IRQENABLE);
59000 + restore_flags(flags);
59002 + /*
59003 + * Now, do each character
59004 + */
59005 + for (i = 0; i < count; i++, s++) {
59006 + while (!(anakin_in(port, 0x10) & TXEMPTY));
59008 + /*
59009 + * Send the character out.
59010 + * If a LF, also do CR...
59011 + */
59012 + anakin_out(port, 0x14, *s);
59013 + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
59015 + if (*s == 10) {
59016 + while (!(anakin_in(port, 0x10) & TXEMPTY));
59017 + anakin_out(port, 0x14, 13);
59018 + anakin_out(port, 0x18, anakin_in(port, 0x18)
59019 + | SENDREQUEST);
59023 + /*
59024 + * Finally, wait for transmitter to become empty
59025 + * and restore the interrupts
59026 + */
59027 + while (!(anakin_in(port, 0x10) & TXEMPTY));
59029 + if (status & IRQENABLE)
59030 + save_flags_cli(flags);
59031 + anakin_out(port, 0x18, anakin_in(port, 0x18) | IRQENABLE);
59032 + restore_flags(flags);
59035 +static kdev_t
59036 +anakin_console_device(struct console *co)
59038 + return MKDEV(SERIAL_ANAKIN_MAJOR, SERIAL_ANAKIN_MINOR + co->index);
59042 + * Read the current UART setup.
59043 + */
59044 +static void __init
59045 +anakin_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
59047 + int paritycode;
59049 + *baud = GETBAUD (anakin_in(port, 0x10) & PRESCALER);
59050 + paritycode = GETPARITY(anakin_in(port, 0x18) & PARITY);
59051 + switch (paritycode) {
59052 + case NONEPARITY: *parity = 'n'; break;
59053 + case ODDPARITY: *parity = 'o'; break;
59054 + case EVENPARITY: *parity = 'e'; break;
59056 + *bits = 8;
59059 +static int __init
59060 +anakin_console_setup(struct console *co, char *options)
59062 + struct uart_port *port;
59063 + int baud = CONFIG_ANAKIN_DEFAULT_BAUDRATE;
59064 + int bits = 8;
59065 + int parity = 'n';
59067 + /*
59068 + * Check whether an invalid uart number has been specified, and
59069 + * if so, search for the first available port that does have
59070 + * console support.
59071 + */
59072 + port = uart_get_console(anakin_ports, UART_NR, co);
59074 + if (options)
59075 + uart_parse_options(options, &baud, &parity, &bits);
59076 + else
59077 + anakin_console_get_options(port, &baud, &parity, &bits);
59079 + return uart_set_options(port, co, baud, parity, bits);
59082 +static struct console anakin_console = {
59083 + name: SERIAL_ANAKIN_NAME,
59084 + write: anakin_console_write,
59085 + device: anakin_console_device,
59086 + setup: anakin_console_setup,
59087 + flags: CON_PRINTBUFFER,
59088 + index: -1,
59091 +void __init
59092 +anakin_console_init(void)
59094 + register_console(&anakin_console);
59097 +#define ANAKIN_CONSOLE &anakin_console
59098 +#else
59099 +#define ANAKIN_CONSOLE NULL
59100 +#endif
59102 +static struct uart_register anakin_reg = {
59103 + normal_major: SERIAL_ANAKIN_MAJOR,
59104 + normal_name: SERIAL_ANAKIN_NAME,
59105 + normal_driver: &normal,
59106 + callout_major: CALLOUT_ANAKIN_MAJOR,
59107 + callout_name: CALLOUT_ANAKIN_NAME,
59108 + callout_driver: &callout,
59109 + table: anakin_table,
59110 + termios: anakin_termios,
59111 + termios_locked: anakin_termios_locked,
59112 + minor: SERIAL_ANAKIN_MINOR,
59113 + nr: UART_NR,
59114 + state: anakin_state,
59115 + port: anakin_ports,
59116 + cons: ANAKIN_CONSOLE,
59119 +static int __init
59120 +anakin_init(void)
59122 + return uart_register_port(&anakin_reg);
59125 +__initcall(anakin_init);
59127 +MODULE_DESCRIPTION("Anakin serial driver");
59128 +MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
59129 +MODULE_SUPPORTED_DEVICE("ttyAN");
59130 +MODULE_LICENSE("GPL");
59132 +EXPORT_NO_SYMBOLS;
59133 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
59134 +++ linux-2.4.25/drivers/serial/clps711x.c 2004-03-31 17:15:09.000000000 +0200
59135 @@ -0,0 +1,635 @@
59137 + * linux/drivers/char/serial_clps711x.c
59139 + * Driver for CLPS711x serial ports
59141 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
59143 + * Copyright 1999 ARM Limited
59144 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
59146 + * This program is free software; you can redistribute it and/or modify
59147 + * it under the terms of the GNU General Public License as published by
59148 + * the Free Software Foundation; either version 2 of the License, or
59149 + * (at your option) any later version.
59151 + * This program is distributed in the hope that it will be useful,
59152 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59153 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59154 + * GNU General Public License for more details.
59156 + * You should have received a copy of the GNU General Public License
59157 + * along with this program; if not, write to the Free Software
59158 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
59160 + * $Id: clps711x.c,v 1.12.2.2 2002/10/24 09:53:25 rmk Exp $
59162 + */
59163 +#include <linux/config.h>
59164 +#include <linux/module.h>
59165 +#include <linux/errno.h>
59166 +#include <linux/signal.h>
59167 +#include <linux/sched.h>
59168 +#include <linux/interrupt.h>
59169 +#include <linux/tty.h>
59170 +#include <linux/tty_flip.h>
59171 +#include <linux/major.h>
59172 +#include <linux/string.h>
59173 +#include <linux/fcntl.h>
59174 +#include <linux/ptrace.h>
59175 +#include <linux/ioport.h>
59176 +#include <linux/mm.h>
59177 +#include <linux/slab.h>
59178 +#include <linux/init.h>
59179 +#include <linux/circ_buf.h>
59180 +#include <linux/serial.h>
59181 +#include <linux/console.h>
59182 +#include <linux/sysrq.h>
59184 +#include <asm/bitops.h>
59185 +#include <asm/hardware.h>
59186 +#include <asm/io.h>
59187 +#include <asm/irq.h>
59188 +#include <asm/system.h>
59189 +#include <asm/uaccess.h>
59191 +#include <linux/serial_core.h>
59193 +#include <asm/hardware/clps7111.h>
59195 +#define UART_NR 2
59197 +#define SERIAL_CLPS711X_NAME "ttyAM"
59198 +#define SERIAL_CLPS711X_MAJOR 204
59199 +#define SERIAL_CLPS711X_MINOR 16
59200 +#define SERIAL_CLPS711X_NR UART_NR
59202 +#define CALLOUT_CLPS711X_NAME "cuaam"
59203 +#define CALLOUT_CLPS711X_MAJOR 205
59204 +#define CALLOUT_CLPS711X_MINOR 16
59205 +#define CALLOUT_CLPS711X_NR UART_NR
59207 +static struct tty_driver normal, callout;
59208 +static struct tty_struct *clps711x_table[UART_NR];
59209 +static struct termios *clps711x_termios[UART_NR], *clps711x_termios_locked[UART_NR];
59212 + * We use the relevant SYSCON register as a base address for these ports.
59213 + */
59214 +#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
59215 +#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
59216 +#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
59217 +#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
59219 +#define TX_IRQ(port) ((port)->irq)
59220 +#define RX_IRQ(port) ((port)->irq + 1)
59222 +#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
59224 +#define tx_enabled(port) ((port)->unused[0])
59226 +static void
59227 +clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
59229 + if (tx_enabled(port)) {
59230 + disable_irq(TX_IRQ(port));
59231 + tx_enabled(port) = 0;
59235 +static void
59236 +clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
59238 + if (!tx_enabled(port)) {
59239 + enable_irq(TX_IRQ(port));
59240 + tx_enabled(port) = 1;
59244 +static void clps711xuart_stop_rx(struct uart_port *port)
59246 + disable_irq(RX_IRQ(port));
59249 +static void clps711xuart_enable_ms(struct uart_port *port)
59253 +static void clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
59255 + struct uart_port *port = dev_id;
59256 + struct tty_struct *tty = port->info->tty;
59257 + unsigned int status, ch, flg, ignored = 0;
59259 + status = clps_readl(SYSFLG(port));
59260 + while (!(status & SYSFLG_URXFE)) {
59261 + ch = clps_readl(UARTDR(port));
59263 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
59264 + goto ignore_char;
59265 + port->icount.rx++;
59267 + flg = TTY_NORMAL;
59269 + /*
59270 + * Note that the error handling code is
59271 + * out of the main execution path
59272 + */
59273 + if (ch & UART_ANY_ERR)
59274 + goto handle_error;
59276 + if (uart_handle_sysrq_char(port, ch, regs))
59277 + goto ignore_char;
59279 + error_return:
59280 + *tty->flip.flag_buf_ptr++ = flg;
59281 + *tty->flip.char_buf_ptr++ = ch;
59282 + tty->flip.count++;
59283 + ignore_char:
59284 + status = clps_readl(SYSFLG(port));
59286 + out:
59287 + tty_flip_buffer_push(tty);
59288 + return;
59290 + handle_error:
59291 + if (ch & UARTDR_PARERR)
59292 + port->icount.parity++;
59293 + else if (ch & UARTDR_FRMERR)
59294 + port->icount.frame++;
59295 + if (ch & UARTDR_OVERR)
59296 + port->icount.overrun++;
59298 + if (ch & port->ignore_status_mask) {
59299 + if (++ignored > 100)
59300 + goto out;
59301 + goto ignore_char;
59303 + ch &= port->read_status_mask;
59305 + if (ch & UARTDR_PARERR)
59306 + flg = TTY_PARITY;
59307 + else if (ch & UARTDR_FRMERR)
59308 + flg = TTY_FRAME;
59310 + if (ch & UARTDR_OVERR) {
59311 + /*
59312 + * CHECK: does overrun affect the current character?
59313 + * ASSUMPTION: it does not.
59314 + */
59315 + *tty->flip.flag_buf_ptr++ = flg;
59316 + *tty->flip.char_buf_ptr++ = ch;
59317 + tty->flip.count++;
59318 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
59319 + goto ignore_char;
59320 + ch = 0;
59321 + flg = TTY_OVERRUN;
59323 +#ifdef SUPPORT_SYSRQ
59324 + port->sysrq = 0;
59325 +#endif
59326 + goto error_return;
59329 +static void clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
59331 + struct uart_port *port = dev_id;
59332 + struct circ_buf *xmit = &port->info->xmit;
59333 + int count;
59335 + if (port->x_char) {
59336 + clps_writel(port->x_char, UARTDR(port));
59337 + port->icount.tx++;
59338 + port->x_char = 0;
59339 + return;
59341 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
59342 + clps711xuart_stop_tx(port, 0);
59343 + return;
59346 + count = port->fifosize >> 1;
59347 + do {
59348 + clps_writel(xmit->buf[xmit->tail], UARTDR(port));
59349 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
59350 + port->icount.tx++;
59351 + if (uart_circ_empty(xmit))
59352 + break;
59353 + } while (--count > 0);
59355 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
59356 + uart_write_wakeup(port);
59358 + if (uart_circ_empty(xmit))
59359 + clps711xuart_stop_tx(port, 0);
59362 +static unsigned int clps711xuart_tx_empty(struct uart_port *port)
59364 + unsigned int status = clps_readl(SYSFLG(port));
59365 + return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
59368 +static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
59370 + unsigned int port_addr;
59371 + unsigned int result = 0;
59372 + unsigned int status;
59374 + port_addr = SYSFLG(port);
59375 + if (port_addr == SYSFLG1) {
59376 + status = clps_readl(SYSFLG1);
59377 + if (status & SYSFLG1_DCD)
59378 + result |= TIOCM_CAR;
59379 + if (status & SYSFLG1_DSR)
59380 + result |= TIOCM_DSR;
59381 + if (status & SYSFLG1_CTS)
59382 + result |= TIOCM_CTS;
59385 + return result;
59388 +static void
59389 +clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
59393 +static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
59395 + unsigned long flags;
59396 + unsigned int ubrlcr;
59398 + spin_lock_irqsave(&port->lock, flags);
59399 + ubrlcr = clps_readl(UBRLCR(port));
59400 + if (break_state == -1)
59401 + ubrlcr |= UBRLCR_BREAK;
59402 + else
59403 + ubrlcr &= ~UBRLCR_BREAK;
59404 + clps_writel(ubrlcr, UBRLCR(port));
59405 + spin_unlock_irqrestore(&port->lock, flags);
59408 +static int clps711xuart_startup(struct uart_port *port)
59410 + unsigned int syscon;
59411 + int retval;
59413 + tx_enabled(port) = 1;
59415 + /*
59416 + * Allocate the IRQs
59417 + */
59418 + retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
59419 + "clps711xuart_tx", port);
59420 + if (retval)
59421 + return retval;
59423 + retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
59424 + "clps711xuart_rx", port);
59425 + if (retval) {
59426 + free_irq(TX_IRQ(port), port);
59427 + return retval;
59430 + /*
59431 + * enable the port
59432 + */
59433 + syscon = clps_readl(SYSCON(port));
59434 + syscon |= SYSCON_UARTEN;
59435 + clps_writel(syscon, SYSCON(port));
59437 + return 0;
59440 +static void clps711xuart_shutdown(struct uart_port *port)
59442 + unsigned int ubrlcr, syscon;
59444 + /*
59445 + * Free the interrupt
59446 + */
59447 + free_irq(TX_IRQ(port), port); /* TX interrupt */
59448 + free_irq(RX_IRQ(port), port); /* RX interrupt */
59450 + /*
59451 + * disable the port
59452 + */
59453 + syscon = clps_readl(SYSCON(port));
59454 + syscon &= ~SYSCON_UARTEN;
59455 + clps_writel(syscon, SYSCON(port));
59457 + /*
59458 + * disable break condition and fifos
59459 + */
59460 + ubrlcr = clps_readl(UBRLCR(port));
59461 + ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
59462 + clps_writel(ubrlcr, UBRLCR(port));
59465 +static void clps711xuart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
59467 + unsigned int ubrlcr;
59468 + unsigned long flags;
59470 +#if DEBUG
59471 + printk("clps711xuart_change_speed(cflag=0x%x, iflag=0x%x, quot=%d) called\n",
59472 + cflag, iflag, quot);
59473 +#endif
59474 + /* byte size and parity */
59475 + switch (cflag & CSIZE) {
59476 + case CS5:
59477 + ubrlcr = UBRLCR_WRDLEN5;
59478 + break;
59479 + case CS6:
59480 + ubrlcr = UBRLCR_WRDLEN6;
59481 + break;
59482 + case CS7:
59483 + ubrlcr = UBRLCR_WRDLEN7;
59484 + break;
59485 + default: // CS8
59486 + ubrlcr = UBRLCR_WRDLEN8;
59487 + break;
59489 + if (cflag & CSTOPB)
59490 + ubrlcr |= UBRLCR_XSTOP;
59491 + if (cflag & PARENB) {
59492 + ubrlcr |= UBRLCR_PRTEN;
59493 + if (!(cflag & PARODD))
59494 + ubrlcr |= UBRLCR_EVENPRT;
59496 + if (port->fifosize > 1)
59497 + ubrlcr |= UBRLCR_FIFOEN;
59499 + spin_lock_irqsave(&port->lock, flags);
59501 + port->read_status_mask = UARTDR_OVERR;
59502 + if (iflag & INPCK)
59503 + port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
59505 + /*
59506 + * Characters to ignore
59507 + */
59508 + port->ignore_status_mask = 0;
59509 + if (iflag & IGNPAR)
59510 + port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
59511 + if (iflag & IGNBRK) {
59512 + /*
59513 + * If we're ignoring parity and break indicators,
59514 + * ignore overruns to (for real raw support).
59515 + */
59516 + if (iflag & IGNPAR)
59517 + port->ignore_status_mask |= UARTDR_OVERR;
59520 + quot -= 1;
59522 + clps_writel(ubrlcr | quot, UBRLCR(port));
59524 + spin_unlock_irqrestore(&port->lock, flags);
59527 +static const char *clps711xuart_type(struct uart_port *port)
59529 + return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
59533 + * Configure/autoconfigure the port.
59534 + */
59535 +static void clps711xuart_config_port(struct uart_port *port, int flags)
59537 + if (flags & UART_CONFIG_TYPE)
59538 + port->type = PORT_CLPS711X;
59541 +static void clps711xuart_release_port(struct uart_port *port)
59545 +static int clps711xuart_request_port(struct uart_port *port)
59547 + return 0;
59550 +static struct uart_ops clps711x_pops = {
59551 + .tx_empty = clps711xuart_tx_empty,
59552 + .set_mctrl = clps711xuart_set_mctrl_null,
59553 + .get_mctrl = clps711xuart_get_mctrl,
59554 + .stop_tx = clps711xuart_stop_tx,
59555 + .start_tx = clps711xuart_start_tx,
59556 + .stop_rx = clps711xuart_stop_rx,
59557 + .enable_ms = clps711xuart_enable_ms,
59558 + .break_ctl = clps711xuart_break_ctl,
59559 + .startup = clps711xuart_startup,
59560 + .shutdown = clps711xuart_shutdown,
59561 + .change_speed = clps711xuart_change_speed,
59562 + .type = clps711xuart_type,
59563 + .config_port = clps711xuart_config_port,
59564 + .release_port = clps711xuart_release_port,
59565 + .request_port = clps711xuart_request_port,
59568 +static struct uart_port clps711x_ports[UART_NR] = {
59570 + .iobase = SYSCON1,
59571 + .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
59572 + .uartclk = 3686400,
59573 + .fifosize = 16,
59574 + .ops = &clps711x_pops,
59575 + .line = 0,
59576 + .flags = ASYNC_BOOT_AUTOCONF,
59577 + },
59579 + .iobase = SYSCON2,
59580 + .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
59581 + .uartclk = 3686400,
59582 + .fifosize = 16,
59583 + .ops = &clps711x_pops,
59584 + .line = 1,
59585 + .flags = ASYNC_BOOT_AUTOCONF,
59589 +#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
59591 + * Print a string to the serial port trying not to disturb
59592 + * any possible real use of the port...
59594 + * The console_lock must be held when we get here.
59596 + * Note that this is called with interrupts already disabled
59597 + */
59598 +static void
59599 +clps711xuart_console_write(struct console *co, const char *s,
59600 + unsigned int count)
59602 + struct uart_port *port = clps711x_ports + co->index;
59603 + unsigned int status, syscon;
59604 + int i;
59606 + /*
59607 + * Ensure that the port is enabled.
59608 + */
59609 + syscon = clps_readl(SYSCON(port));
59610 + clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
59612 + /*
59613 + * Now, do each character
59614 + */
59615 + for (i = 0; i < count; i++) {
59616 + do {
59617 + status = clps_readl(SYSFLG(port));
59618 + } while (status & SYSFLG_UTXFF);
59619 + clps_writel(s[i], UARTDR(port));
59620 + if (s[i] == '\n') {
59621 + do {
59622 + status = clps_readl(SYSFLG(port));
59623 + } while (status & SYSFLG_UTXFF);
59624 + clps_writel('\r', UARTDR(port));
59628 + /*
59629 + * Finally, wait for transmitter to become empty
59630 + * and restore the uart state.
59631 + */
59632 + do {
59633 + status = clps_readl(SYSFLG(port));
59634 + } while (status & SYSFLG_UBUSY);
59636 + clps_writel(syscon, SYSCON(port));
59639 +static kdev_t clps711xuart_console_device(struct console *co)
59641 + return MKDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR + co->index);
59644 +static void __init
59645 +clps711xuart_console_get_options(struct uart_port *port, int *baud,
59646 + int *parity, int *bits)
59648 + if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
59649 + unsigned int ubrlcr, quot;
59651 + ubrlcr = clps_readl(UBRLCR(port));
59653 + *parity = 'n';
59654 + if (ubrlcr & UBRLCR_PRTEN) {
59655 + if (ubrlcr & UBRLCR_EVENPRT)
59656 + *parity = 'e';
59657 + else
59658 + *parity = 'o';
59661 + if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
59662 + *bits = 7;
59663 + else
59664 + *bits = 8;
59666 + quot = ubrlcr & UBRLCR_BAUD_MASK;
59667 + *baud = port->uartclk / (16 * (quot + 1));
59671 +static int __init clps711xuart_console_setup(struct console *co, char *options)
59673 + struct uart_port *port;
59674 + int baud = 38400;
59675 + int bits = 8;
59676 + int parity = 'n';
59677 + int flow = 'n';
59679 + /*
59680 + * Check whether an invalid uart number has been specified, and
59681 + * if so, search for the first available port that does have
59682 + * console support.
59683 + */
59684 + port = uart_get_console(clps711x_ports, UART_NR, co);
59686 + if (options)
59687 + uart_parse_options(options, &baud, &parity, &bits, &flow);
59688 + else
59689 + clps711xuart_console_get_options(port, &baud, &parity, &bits);
59691 + return uart_set_options(port, co, baud, parity, bits, flow);
59694 +static struct console clps711x_console = {
59695 + .name = SERIAL_CLPS711X_NAME,
59696 + .write = clps711xuart_console_write,
59697 + .device = clps711xuart_console_device,
59698 + .setup = clps711xuart_console_setup,
59699 + .flags = CON_PRINTBUFFER,
59700 + .index = -1,
59703 +void __init clps711xuart_console_init(void)
59705 + register_console(&clps711x_console);
59708 +#define CLPS711X_CONSOLE &clps711x_console
59709 +#else
59710 +#define CLPS711X_CONSOLE NULL
59711 +#endif
59713 +static struct uart_driver clps711x_reg = {
59714 +#ifdef CONFIG_DEVFS_FS
59715 + .normal_name = SERIAL_CLPS711X_NAME,
59716 + .callout_name = CALLOUT_CLPS711X_NAME,
59717 +#else
59718 + .normal_name = SERIAL_CLPS711X_NAME,
59719 + .callout_name = CALLOUT_CLPS711X_NAME,
59720 +#endif
59722 + .normal_major = SERIAL_CLPS711X_MAJOR,
59723 + .normal_driver = &normal,
59724 + .callout_major = CALLOUT_CLPS711X_MAJOR,
59725 + .callout_driver = &callout,
59727 + .table = clps711x_table,
59728 + .termios = clps711x_termios,
59729 + .termios_locked = clps711x_termios_locked,
59731 + .minor = SERIAL_CLPS711X_MINOR,
59732 + .nr = UART_NR,
59734 + .cons = CLPS711X_CONSOLE,
59737 +static int __init clps711xuart_init(void)
59739 + int ret, i;
59741 + printk(KERN_INFO "Serial: CLPS711x driver\n");
59743 + ret = uart_register_driver(&clps711x_reg);
59744 + if (ret)
59745 + return ret;
59747 + for (i = 0; i < UART_NR; i++)
59748 + uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
59750 + return 0;
59753 +static void __exit clps711xuart_exit(void)
59755 + int i;
59757 + for (i = 0; i < UART_NR; i++)
59758 + uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
59760 + uart_unregister_driver(&clps711x_reg);
59763 +module_init(clps711xuart_init);
59764 +module_exit(clps711xuart_exit);
59766 +EXPORT_NO_SYMBOLS;
59768 +MODULE_AUTHOR("Deep Blue Solutions Ltd");
59769 +MODULE_DESCRIPTION("CLPS-711x generic serial driver");
59770 +MODULE_LICENSE("GPL");
59771 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
59772 +++ linux-2.4.25/drivers/serial/core.c 2004-03-31 17:15:09.000000000 +0200
59773 @@ -0,0 +1,2584 @@
59775 + * linux/drivers/serial/core.c
59777 + * Driver core for serial ports
59779 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
59781 + * Copyright 1999 ARM Limited
59782 + * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
59784 + * This program is free software; you can redistribute it and/or modify
59785 + * it under the terms of the GNU General Public License as published by
59786 + * the Free Software Foundation; either version 2 of the License, or
59787 + * (at your option) any later version.
59789 + * This program is distributed in the hope that it will be useful,
59790 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59791 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59792 + * GNU General Public License for more details.
59794 + * You should have received a copy of the GNU General Public License
59795 + * along with this program; if not, write to the Free Software
59796 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
59798 + * $Id: core.c,v 1.20.2.5 2002/03/13 15:22:26 rmk Exp $
59800 + */
59801 +#include <linux/config.h>
59802 +#include <linux/module.h>
59803 +#include <linux/errno.h>
59804 +#include <linux/tty.h>
59805 +#include <linux/string.h>
59806 +#include <linux/fcntl.h>
59807 +#include <linux/ptrace.h>
59808 +#include <linux/ioport.h>
59809 +#include <linux/mm.h>
59810 +#include <linux/slab.h>
59811 +#include <linux/init.h>
59812 +#include <linux/console.h>
59813 +#include <linux/sysrq.h>
59814 +#include <linux/pm.h>
59815 +#include <linux/serial_core.h>
59816 +#include <linux/smp_lock.h>
59818 +#include <asm/irq.h>
59819 +#include <asm/uaccess.h>
59821 +#undef DEBUG
59822 +#ifdef DEBUG
59823 +#define DPRINTK(x...) printk(x)
59824 +#else
59825 +#define DPRINTK(x...) do { } while (0)
59826 +#endif
59828 +#ifndef CONFIG_PM
59829 +#define pm_access(pm) do { } while (0)
59830 +#define pm_unregister(pm) do { } while (0)
59831 +#endif
59834 + * This is used to lock changes in serial line configuration.
59835 + */
59836 +static DECLARE_MUTEX(port_sem);
59838 +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
59840 +#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
59842 +#ifdef CONFIG_SERIAL_CORE_CONSOLE
59843 +#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
59844 +#else
59845 +#define uart_console(port) (0)
59846 +#endif
59848 +static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
59849 +static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
59850 +static void uart_change_pm(struct uart_state *state, int pm_state);
59853 + * This routine is used by the interrupt handler to schedule processing in
59854 + * the software interrupt portion of the driver.
59855 + */
59856 +void uart_write_wakeup(struct uart_port *port)
59858 + struct uart_info *info = port->info;
59859 + tasklet_schedule(&info->tlet);
59862 +static void uart_stop(struct tty_struct *tty)
59864 + struct uart_state *state = tty->driver_data;
59865 + struct uart_port *port = state->port;
59866 + unsigned long flags;
59868 + spin_lock_irqsave(&port->lock, flags);
59869 + port->ops->stop_tx(port, 1);
59870 + spin_unlock_irqrestore(&port->lock, flags);
59873 +static void __uart_start(struct tty_struct *tty)
59875 + struct uart_state *state = tty->driver_data;
59876 + struct uart_port *port = state->port;
59878 + if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
59879 + !tty->stopped && !tty->hw_stopped)
59880 + port->ops->start_tx(port, 1);
59883 +static void uart_start(struct tty_struct *tty)
59885 + struct uart_state *state = tty->driver_data;
59886 + struct uart_port *port = state->port;
59887 + unsigned long flags;
59889 + pm_access(state->pm);
59891 + spin_lock_irqsave(&port->lock, flags);
59892 + __uart_start(tty);
59893 + spin_unlock_irqrestore(&port->lock, flags);
59896 +static void uart_tasklet_action(unsigned long data)
59898 + struct uart_state *state = (struct uart_state *)data;
59899 + struct tty_struct *tty;
59901 + tty = state->info->tty;
59902 + if (tty) {
59903 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
59904 + tty->ldisc.write_wakeup)
59905 + tty->ldisc.write_wakeup(tty);
59906 + wake_up_interruptible(&tty->write_wait);
59910 +static inline void
59911 +uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
59913 + unsigned long flags;
59914 + unsigned int old;
59916 + spin_lock_irqsave(&port->lock, flags);
59917 + old = port->mctrl;
59918 + port->mctrl = (old & ~clear) | set;
59919 + if (old != port->mctrl)
59920 + port->ops->set_mctrl(port, port->mctrl);
59921 + spin_unlock_irqrestore(&port->lock, flags);
59924 +#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0)
59925 +#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear)
59927 +static inline unsigned int uart_get_altspeed(struct uart_port *port)
59929 + unsigned int flags = port->flags & UPF_SPD_MASK;
59930 + unsigned int altbaud = 0;
59932 + if (flags == ASYNC_SPD_HI)
59933 + altbaud = 57600;
59934 + if (flags == ASYNC_SPD_VHI)
59935 + altbaud = 115200;
59936 + if (flags == ASYNC_SPD_SHI)
59937 + altbaud = 230400;
59938 + if (flags == ASYNC_SPD_WARP)
59939 + altbaud = 460800;
59941 + return altbaud;
59945 + * Startup the port. This will be called once per open. All calls
59946 + * will be serialised by the per-port semaphore.
59947 + */
59948 +static int uart_startup(struct uart_state *state, int init_hw)
59950 + struct uart_info *info = state->info;
59951 + struct uart_port *port = state->port;
59952 + unsigned long page;
59953 + int retval = 0;
59955 + if (info->flags & UIF_INITIALIZED)
59956 + return 0;
59958 + /*
59959 + * Set the TTY IO error marker - we will only clear this
59960 + * once we have successfully opened the port. Also set
59961 + * up the tty->alt_speed kludge
59962 + */
59963 + if (info->tty)
59964 + set_bit(TTY_IO_ERROR, &info->tty->flags);
59966 + if (port->type == PORT_UNKNOWN)
59967 + return 0;
59969 + /*
59970 + * Initialise and allocate the transmit and temporary
59971 + * buffer.
59972 + */
59973 + if (!info->xmit.buf) {
59974 + page = get_zeroed_page(GFP_KERNEL);
59975 + if (!page)
59976 + return -ENOMEM;
59978 + info->xmit.buf = (unsigned char *) page;
59979 + info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE;
59980 + init_MUTEX(&info->tmpbuf_sem);
59981 + uart_circ_clear(&info->xmit);
59984 + port->mctrl = 0;
59986 + retval = port->ops->startup(port);
59987 + if (retval == 0) {
59988 + if (init_hw) {
59989 + /*
59990 + * Initialise the hardware port settings.
59991 + */
59992 + uart_change_speed(state, NULL);
59994 + /*
59995 + * Setup the RTS and DTR signals once the
59996 + * port is open and ready to respond.
59997 + */
59998 + if (info->tty->termios->c_cflag & CBAUD)
59999 + uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
60002 + info->flags |= UIF_INITIALIZED;
60004 + clear_bit(TTY_IO_ERROR, &info->tty->flags);
60007 + if (retval && capable(CAP_SYS_ADMIN))
60008 + retval = 0;
60010 + return retval;
60014 + * This routine will shutdown a serial port; interrupts are disabled, and
60015 + * DTR is dropped if the hangup on close termio flag is on. Calls to
60016 + * uart_shutdown are serialised by the per-port semaphore.
60017 + */
60018 +static void uart_shutdown(struct uart_state *state)
60020 + struct uart_info *info = state->info;
60021 + struct uart_port *port = state->port;
60023 + if (!(info->flags & UIF_INITIALIZED))
60024 + return;
60026 + /*
60027 + * Turn off DTR and RTS early.
60028 + */
60029 + if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
60030 + uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
60032 + /*
60033 + * clear delta_msr_wait queue to avoid mem leaks: we may free
60034 + * the irq here so the queue might never be woken up. Note
60035 + * that we won't end up waiting on delta_msr_wait again since
60036 + * any outstanding file descriptors should be pointing at
60037 + * hung_up_tty_fops now.
60038 + */
60039 + wake_up_interruptible(&info->delta_msr_wait);
60041 + /*
60042 + * Free the IRQ and disable the port.
60043 + */
60044 + port->ops->shutdown(port);
60046 + /*
60047 + * Free the transmit buffer page.
60048 + */
60049 + if (info->xmit.buf) {
60050 + free_page((unsigned long)info->xmit.buf);
60051 + info->xmit.buf = NULL;
60052 + info->tmpbuf = NULL;
60055 + /*
60056 + * kill off our tasklet
60057 + */
60058 + tasklet_kill(&info->tlet);
60059 + if (info->tty)
60060 + set_bit(TTY_IO_ERROR, &info->tty->flags);
60062 + info->flags &= ~UIF_INITIALIZED;
60065 +/**
60066 + * uart_update_timeout - update per-port FIFO timeout.
60067 + * @port: uart_port structure describing the port.
60068 + * @cflag: termios cflag value
60069 + * @quot: uart clock divisor quotient
60071 + * Set the port FIFO timeout value. The @cflag value should
60072 + * reflect the actual hardware settings.
60073 + */
60074 +void
60075 +uart_update_timeout(struct uart_port *port, unsigned int cflag,
60076 + unsigned int baud)
60078 + unsigned int bits;
60080 + /* byte size and parity */
60081 + switch (cflag & CSIZE) {
60082 + case CS5:
60083 + bits = 7;
60084 + break;
60085 + case CS6:
60086 + bits = 8;
60087 + break;
60088 + case CS7:
60089 + bits = 9;
60090 + break;
60091 + default:
60092 + bits = 10;
60093 + break; // CS8
60096 + if (cflag & CSTOPB)
60097 + bits++;
60098 + if (cflag & PARENB)
60099 + bits++;
60101 + /*
60102 + * The total number of bits to be transmitted in the fifo.
60103 + */
60104 + bits = bits * port->fifosize;
60106 + /*
60107 + * Figure the timeout to send the above number of bits.
60108 + * Add .02 seconds of slop
60109 + */
60110 + port->timeout = (HZ * bits) / baud + HZ/50;
60113 +EXPORT_SYMBOL(uart_update_timeout);
60115 +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
60117 + u_int quot;
60119 + /* Special case: B0 rate */
60120 + if (!baud)
60121 + baud = 9600;
60123 + /* Old HI/VHI/custom speed handling */
60124 + if (baud == 38400 &&
60125 + ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
60126 + quot = port->custom_divisor;
60127 + else
60128 + quot = port->uartclk / (16 * baud);
60130 + return quot;
60133 +static void
60134 +uart_change_speed(struct uart_state *state, struct termios *old_termios)
60136 + struct tty_struct *tty = state->info->tty;
60137 + struct uart_port *port = state->port;
60138 + struct termios *termios;
60139 + unsigned int quot, baud, cflag, try;
60141 + /*
60142 + * If we have no tty, termios, or the port does not exist,
60143 + * then we can't set the parameters for this port.
60144 + */
60145 + if (!tty || !tty->termios || port->type == PORT_UNKNOWN)
60146 + return;
60148 + termios = tty->termios;
60150 + cflag = termios->c_cflag;
60152 + for (try = 0; try < 2; try ++) {
60153 + /* Determine divisor based on baud rate */
60154 + baud = tty_get_baud_rate(tty);
60155 + quot = uart_calculate_quot(port, baud);
60156 + if (quot)
60157 + break;
60159 + /*
60160 + * Oops, the quotient was zero. Try again with
60161 + * the old baud rate if possible.
60162 + */
60163 + termios->c_cflag &= ~CBAUD;
60164 + if (old_termios) {
60165 + termios->c_cflag |=
60166 + (old_termios->c_cflag & CBAUD);
60167 + old_termios = NULL;
60168 + continue;
60171 + /*
60172 + * As a last resort, if the quotient is zero,
60173 + * default to 9600 bps
60174 + */
60175 + termios->c_cflag |= B9600;
60178 + uart_update_timeout(port, cflag, port->uartclk / (16 * quot));
60180 + if (termios->c_cflag & CRTSCTS)
60181 + state->info->flags |= UIF_CTS_FLOW;
60182 + else
60183 + state->info->flags &= ~UIF_CTS_FLOW;
60184 + if (termios->c_cflag & CLOCAL)
60185 + state->info->flags &= ~UIF_CHECK_CD;
60186 + else
60187 + state->info->flags |= UIF_CHECK_CD;
60189 + /*
60190 + * Set up parity check flag
60191 + */
60192 + pm_access(state->pm);
60194 + port->ops->change_speed(port, cflag, termios->c_iflag, quot);
60197 +static inline void
60198 +__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
60200 + unsigned long flags;
60202 + if (!circ->buf)
60203 + return;
60205 + spin_lock_irqsave(&port->lock, flags);
60206 + if (uart_circ_chars_free(circ) != 0) {
60207 + circ->buf[circ->head] = c;
60208 + circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
60210 + spin_unlock_irqrestore(&port->lock, flags);
60213 +static inline int
60214 +__uart_user_write(struct uart_port *port, struct circ_buf *circ,
60215 + const unsigned char *buf, int count)
60217 + unsigned long flags;
60218 + int c, ret = 0;
60220 + if (down_interruptible(&port->info->tmpbuf_sem))
60221 + return -EINTR;
60223 + while (1) {
60224 + int c1;
60225 + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
60226 + if (count < c)
60227 + c = count;
60228 + if (c <= 0)
60229 + break;
60231 + c -= copy_from_user(port->info->tmpbuf, buf, c);
60232 + if (!c) {
60233 + if (!ret)
60234 + ret = -EFAULT;
60235 + break;
60237 + spin_lock_irqsave(&port->lock, flags);
60238 + c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
60239 + if (c1 < c)
60240 + c = c1;
60241 + memcpy(circ->buf + circ->head, port->info->tmpbuf, c);
60242 + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
60243 + spin_unlock_irqrestore(&port->lock, flags);
60244 + buf += c;
60245 + count -= c;
60246 + ret += c;
60248 + up(&port->info->tmpbuf_sem);
60250 + return ret;
60253 +static inline int
60254 +__uart_kern_write(struct uart_port *port, struct circ_buf *circ,
60255 + const unsigned char *buf, int count)
60257 + unsigned long flags;
60258 + int c, ret = 0;
60260 + spin_lock_irqsave(&port->lock, flags);
60261 + while (1) {
60262 + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
60263 + if (count < c)
60264 + c = count;
60265 + if (c <= 0)
60266 + break;
60267 + memcpy(circ->buf + circ->head, buf, c);
60268 + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
60269 + buf += c;
60270 + count -= c;
60271 + ret += c;
60273 + spin_unlock_irqrestore(&port->lock, flags);
60275 + return ret;
60278 +static void uart_put_char(struct tty_struct *tty, unsigned char ch)
60280 + struct uart_state *state = tty->driver_data;
60282 + __uart_put_char(state->port, &state->info->xmit, ch);
60285 +static void uart_flush_chars(struct tty_struct *tty)
60287 + uart_start(tty);
60290 +static int
60291 +uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf,
60292 + int count)
60294 + struct uart_state *state = tty->driver_data;
60295 + int ret;
60297 + if (!state->info->xmit.buf)
60298 + return 0;
60300 + if (from_user)
60301 + ret = __uart_user_write(state->port, &state->info->xmit, buf, count);
60302 + else
60303 + ret = __uart_kern_write(state->port, &state->info->xmit, buf, count);
60305 + uart_start(tty);
60306 + return ret;
60309 +static int uart_write_room(struct tty_struct *tty)
60311 + struct uart_state *state = tty->driver_data;
60313 + return uart_circ_chars_free(&state->info->xmit);
60316 +static int uart_chars_in_buffer(struct tty_struct *tty)
60318 + struct uart_state *state = tty->driver_data;
60320 + return uart_circ_chars_pending(&state->info->xmit);
60323 +static void uart_flush_buffer(struct tty_struct *tty)
60325 + struct uart_state *state = tty->driver_data;
60326 + struct uart_port *port = state->port;
60327 + unsigned long flags;
60329 + DPRINTK("uart_flush_buffer(%d) called\n",
60330 + MINOR(tty->device) - tty->driver.minor_start);
60332 + spin_lock_irqsave(&port->lock, flags);
60333 + uart_circ_clear(&state->info->xmit);
60334 + spin_unlock_irqrestore(&port->lock, flags);
60335 + wake_up_interruptible(&tty->write_wait);
60336 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
60337 + tty->ldisc.write_wakeup)
60338 + (tty->ldisc.write_wakeup)(tty);
60342 + * This function is used to send a high-priority XON/XOFF character to
60343 + * the device
60344 + */
60345 +static void uart_send_xchar(struct tty_struct *tty, char ch)
60347 + struct uart_state *state = tty->driver_data;
60348 + struct uart_port *port = state->port;
60349 + unsigned long flags;
60351 + if (port->ops->send_xchar)
60352 + port->ops->send_xchar(port, ch);
60353 + else {
60354 + port->x_char = ch;
60355 + if (ch) {
60356 + spin_lock_irqsave(&port->lock, flags);
60357 + port->ops->start_tx(port, 0);
60358 + spin_unlock_irqrestore(&port->lock, flags);
60363 +static void uart_throttle(struct tty_struct *tty)
60365 + struct uart_state *state = tty->driver_data;
60367 + if (I_IXOFF(tty))
60368 + uart_send_xchar(tty, STOP_CHAR(tty));
60370 + if (tty->termios->c_cflag & CRTSCTS)
60371 + uart_clear_mctrl(state->port, TIOCM_RTS);
60374 +static void uart_unthrottle(struct tty_struct *tty)
60376 + struct uart_state *state = tty->driver_data;
60377 + struct uart_port *port = state->port;
60379 + if (I_IXOFF(tty)) {
60380 + if (port->x_char)
60381 + port->x_char = 0;
60382 + else
60383 + uart_send_xchar(tty, START_CHAR(tty));
60386 + if (tty->termios->c_cflag & CRTSCTS)
60387 + uart_set_mctrl(port, TIOCM_RTS);
60390 +static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo)
60392 + struct uart_port *port = state->port;
60393 + struct serial_struct tmp;
60395 + memset(&tmp, 0, sizeof(tmp));
60396 + tmp.type = port->type;
60397 + tmp.line = port->line;
60398 + tmp.port = port->iobase;
60399 + if (HIGH_BITS_OFFSET)
60400 + tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
60401 + tmp.irq = port->irq;
60402 + tmp.flags = port->flags;
60403 + tmp.xmit_fifo_size = port->fifosize;
60404 + tmp.baud_base = port->uartclk / 16;
60405 + tmp.close_delay = state->close_delay;
60406 + tmp.closing_wait = state->closing_wait;
60407 + tmp.custom_divisor = port->custom_divisor;
60408 + tmp.hub6 = port->hub6;
60409 + tmp.io_type = port->iotype;
60410 + tmp.iomem_reg_shift = port->regshift;
60411 + tmp.iomem_base = (void *)port->mapbase;
60413 + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
60414 + return -EFAULT;
60415 + return 0;
60418 +static int
60419 +uart_set_info(struct uart_state *state, struct serial_struct *newinfo)
60421 + struct serial_struct new_serial;
60422 + struct uart_port *port = state->port;
60423 + unsigned long new_port;
60424 + unsigned int change_irq, change_port, old_flags;
60425 + unsigned int old_custom_divisor;
60426 + int retval = 0;
60428 + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
60429 + return -EFAULT;
60431 + new_port = new_serial.port;
60432 + if (HIGH_BITS_OFFSET)
60433 + new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
60435 + new_serial.irq = irq_cannonicalize(new_serial.irq);
60437 + /*
60438 + * This semaphore protects state->count. It is also
60439 + * very useful to prevent opens. Also, take the
60440 + * port configuration semaphore to make sure that a
60441 + * module insertion/removal doesn't change anything
60442 + * under us.
60443 + */
60444 + down(&state->sem);
60446 + change_irq = new_serial.irq != port->irq;
60448 + /*
60449 + * Since changing the 'type' of the port changes its resource
60450 + * allocations, we should treat type changes the same as
60451 + * IO port changes.
60452 + */
60453 + change_port = new_port != port->iobase ||
60454 + (unsigned long)new_serial.iomem_base != port->mapbase ||
60455 + new_serial.hub6 != port->hub6 ||
60456 + new_serial.io_type != port->iotype ||
60457 + new_serial.iomem_reg_shift != port->regshift ||
60458 + new_serial.type != port->type;
60460 + old_flags = port->flags;
60461 + old_custom_divisor = port->custom_divisor;
60463 + if (!capable(CAP_SYS_ADMIN)) {
60464 + retval = -EPERM;
60465 + if (change_irq || change_port ||
60466 + (new_serial.baud_base != port->uartclk / 16) ||
60467 + (new_serial.close_delay != state->close_delay) ||
60468 + (new_serial.closing_wait != state->closing_wait) ||
60469 + (new_serial.xmit_fifo_size != port->fifosize) ||
60470 + (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0))
60471 + goto exit;
60472 + port->flags = ((port->flags & ~UPF_USR_MASK) |
60473 + (new_serial.flags & UPF_USR_MASK));
60474 + port->custom_divisor = new_serial.custom_divisor;
60475 + goto check_and_exit;
60478 + /*
60479 + * Ask the low level driver to verify the settings.
60480 + */
60481 + if (port->ops->verify_port)
60482 + retval = port->ops->verify_port(port, &new_serial);
60484 + if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
60485 + (new_serial.baud_base < 9600))
60486 + retval = -EINVAL;
60488 + if (retval)
60489 + goto exit;
60491 + if (change_port || change_irq) {
60492 + retval = -EBUSY;
60494 + /*
60495 + * Make sure that we are the sole user of this port.
60496 + */
60497 + if (uart_users(state) > 1)
60498 + goto exit;
60500 + /*
60501 + * We need to shutdown the serial port at the old
60502 + * port/type/irq combination.
60503 + */
60504 + uart_shutdown(state);
60507 + if (change_port) {
60508 + unsigned long old_iobase, old_mapbase;
60509 + unsigned int old_type, old_iotype, old_hub6, old_shift;
60511 + old_iobase = port->iobase;
60512 + old_mapbase = port->mapbase;
60513 + old_type = port->type;
60514 + old_hub6 = port->hub6;
60515 + old_iotype = port->iotype;
60516 + old_shift = port->regshift;
60518 + /*
60519 + * Free and release old regions
60520 + */
60521 + if (old_type != PORT_UNKNOWN)
60522 + port->ops->release_port(port);
60524 + port->iobase = new_port;
60525 + port->type = new_serial.type;
60526 + port->hub6 = new_serial.hub6;
60527 + port->iotype = new_serial.io_type;
60528 + port->regshift = new_serial.iomem_reg_shift;
60529 + port->mapbase = (unsigned long)new_serial.iomem_base;
60531 + /*
60532 + * Claim and map the new regions
60533 + */
60534 + if (port->type != PORT_UNKNOWN) {
60535 + retval = port->ops->request_port(port);
60536 + } else {
60537 + /* Always success - Jean II */
60538 + retval = 0;
60541 + /*
60542 + * If we fail to request resources for the
60543 + * new port, try to restore the old settings.
60544 + */
60545 + if (retval && old_type != PORT_UNKNOWN) {
60546 + port->iobase = old_iobase;
60547 + port->type = old_type;
60548 + port->hub6 = old_hub6;
60549 + port->iotype = old_iotype;
60550 + port->regshift = old_shift;
60551 + port->mapbase = old_mapbase;
60552 + retval = port->ops->request_port(port);
60553 + /*
60554 + * If we failed to restore the old settings,
60555 + * we fail like this.
60556 + */
60557 + if (retval)
60558 + port->type = PORT_UNKNOWN;
60560 + /*
60561 + * We failed anyway.
60562 + */
60563 + retval = -EBUSY;
60567 + port->irq = new_serial.irq;
60568 + port->uartclk = new_serial.baud_base * 16;
60569 + port->flags = (port->flags & ~UPF_CHANGE_MASK) |
60570 + (new_serial.flags & UPF_CHANGE_MASK);
60571 + port->custom_divisor = new_serial.custom_divisor;
60572 + state->close_delay = new_serial.close_delay * HZ / 100;
60573 + state->closing_wait = new_serial.closing_wait * HZ / 100;
60574 + port->fifosize = new_serial.xmit_fifo_size;
60575 + if (state->info->tty)
60576 + state->info->tty->low_latency =
60577 + (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
60579 + check_and_exit:
60580 + retval = 0;
60581 + if (port->type == PORT_UNKNOWN)
60582 + goto exit;
60583 + if (state->info->flags & UIF_INITIALIZED) {
60584 + if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
60585 + old_custom_divisor != port->custom_divisor) {
60586 + state->info->tty->alt_speed = uart_get_altspeed(port);
60587 + uart_change_speed(state, NULL);
60589 + } else
60590 + retval = uart_startup(state, 1);
60591 + exit:
60592 + up(&state->sem);
60593 + return retval;
60598 + * uart_get_lsr_info - get line status register info.
60599 + * Note: uart_ioctl protects us against hangups.
60600 + */
60601 +static int uart_get_lsr_info(struct uart_state *state, unsigned int *value)
60603 + struct uart_port *port = state->port;
60604 + unsigned int result;
60606 + result = port->ops->tx_empty(port);
60608 + /*
60609 + * If we're about to load something into the transmit
60610 + * register, we'll pretend the transmitter isn't empty to
60611 + * avoid a race condition (depending on when the transmit
60612 + * interrupt happens).
60613 + */
60614 + if (port->x_char ||
60615 + ((uart_circ_chars_pending(&state->info->xmit) > 0) &&
60616 + !state->info->tty->stopped && !state->info->tty->hw_stopped))
60617 + result &= ~TIOCSER_TEMT;
60619 + return put_user(result, value);
60622 +static int uart_tiocmget(struct tty_struct *tty, struct file *file)
60624 + struct uart_state *state = tty->driver_data;
60625 + struct uart_port *port = state->port;
60626 + int result = -EIO;
60628 + down(&state->sem);
60629 + if ((!file || !tty_hung_up_p(file)) &&
60630 + !(tty->flags & (1 << TTY_IO_ERROR))) {
60631 + result = port->mctrl;
60632 + result |= port->ops->get_mctrl(port);
60634 + up(&state->sem);
60636 + return result;
60639 +static int
60640 +uart_tiocmset(struct tty_struct *tty, struct file *file,
60641 + unsigned int set, unsigned int clear)
60643 + struct uart_state *state = tty->driver_data;
60644 + struct uart_port *port = state->port;
60645 + int ret = -EIO;
60647 + down(&state->sem);
60648 + if ((!file || !tty_hung_up_p(file)) &&
60649 + !(tty->flags & (1 << TTY_IO_ERROR))) {
60650 + uart_update_mctrl(port, set, clear);
60651 + ret = 0;
60653 + up(&state->sem);
60654 + return ret;
60657 +static void uart_break_ctl(struct tty_struct *tty, int break_state)
60659 + struct uart_state *state = tty->driver_data;
60660 + struct uart_port *port = state->port;
60662 + BUG_ON(!kernel_locked());
60664 + down(&state->sem);
60666 + if (port->type != PORT_UNKNOWN)
60667 + port->ops->break_ctl(port, break_state);
60669 + up(&state->sem);
60672 +static int uart_do_autoconfig(struct uart_state *state)
60674 + struct uart_port *port = state->port;
60675 + int flags, ret;
60677 + if (!capable(CAP_SYS_ADMIN))
60678 + return -EPERM;
60680 + /*
60681 + * Take the per-port semaphore. This prevents count from
60682 + * changing, and hence any extra opens of the port while
60683 + * we're auto-configuring.
60684 + */
60685 + if (down_interruptible(&state->sem))
60686 + return -ERESTARTSYS;
60688 + ret = -EBUSY;
60689 + if (uart_users(state) == 1) {
60690 + uart_shutdown(state);
60692 + /*
60693 + * If we already have a port type configured,
60694 + * we must release its resources.
60695 + */
60696 + if (port->type != PORT_UNKNOWN)
60697 + port->ops->release_port(port);
60699 + flags = UART_CONFIG_TYPE;
60700 + if (port->flags & UPF_AUTO_IRQ)
60701 + flags |= UART_CONFIG_IRQ;
60703 + /*
60704 + * This will claim the ports resources if
60705 + * a port is found.
60706 + */
60707 + port->ops->config_port(port, flags);
60709 + ret = uart_startup(state, 1);
60711 + up(&state->sem);
60712 + return ret;
60716 + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
60717 + * - mask passed in arg for lines of interest
60718 + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
60719 + * Caller should use TIOCGICOUNT to see which one it was
60720 + */
60721 +static int
60722 +uart_wait_modem_status(struct uart_state *state, unsigned long arg)
60724 + struct uart_port *port = state->port;
60725 + DECLARE_WAITQUEUE(wait, current);
60726 + struct uart_icount cprev, cnow;
60727 + int ret;
60729 + /*
60730 + * note the counters on entry
60731 + */
60732 + spin_lock_irq(&port->lock);
60733 + memcpy(&cprev, &port->icount, sizeof(struct uart_icount));
60735 + /*
60736 + * Force modem status interrupts on
60737 + */
60738 + port->ops->enable_ms(port);
60739 + spin_unlock_irq(&port->lock);
60741 + add_wait_queue(&state->info->delta_msr_wait, &wait);
60742 + for (;;) {
60743 + spin_lock_irq(&port->lock);
60744 + memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
60745 + spin_unlock_irq(&port->lock);
60747 + set_current_state(TASK_INTERRUPTIBLE);
60749 + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
60750 + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
60751 + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
60752 + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
60753 + ret = 0;
60754 + break;
60757 + schedule();
60759 + /* see if a signal did it */
60760 + if (signal_pending(current)) {
60761 + ret = -ERESTARTSYS;
60762 + break;
60765 + cprev = cnow;
60768 + current->state = TASK_RUNNING;
60769 + remove_wait_queue(&state->info->delta_msr_wait, &wait);
60771 + return ret;
60775 + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
60776 + * Return: write counters to the user passed counter struct
60777 + * NB: both 1->0 and 0->1 transitions are counted except for
60778 + * RI where only 0->1 is counted.
60779 + */
60780 +static int
60781 +uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt)
60783 + struct serial_icounter_struct icount;
60784 + struct uart_icount cnow;
60785 + struct uart_port *port = state->port;
60787 + spin_lock_irq(&port->lock);
60788 + memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
60789 + spin_unlock_irq(&port->lock);
60791 + icount.cts = cnow.cts;
60792 + icount.dsr = cnow.dsr;
60793 + icount.rng = cnow.rng;
60794 + icount.dcd = cnow.dcd;
60795 + icount.rx = cnow.rx;
60796 + icount.tx = cnow.tx;
60797 + icount.frame = cnow.frame;
60798 + icount.overrun = cnow.overrun;
60799 + icount.parity = cnow.parity;
60800 + icount.brk = cnow.brk;
60801 + icount.buf_overrun = cnow.buf_overrun;
60803 + return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
60807 + * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here.
60808 + */
60809 +static int
60810 +uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
60811 + unsigned long arg)
60813 + struct uart_state *state = tty->driver_data;
60814 + int ret = -ENOIOCTLCMD;
60816 + BUG_ON(!kernel_locked());
60818 + /*
60819 + * These ioctls don't rely on the hardware to be present.
60820 + */
60821 + switch (cmd) {
60822 + case TIOCGSERIAL:
60823 + ret = uart_get_info(state, (struct serial_struct *)arg);
60824 + break;
60826 + case TIOCSSERIAL:
60827 + ret = uart_set_info(state, (struct serial_struct *)arg);
60828 + break;
60830 + case TIOCSERCONFIG:
60831 + ret = uart_do_autoconfig(state);
60832 + break;
60834 + case TIOCSERGWILD: /* obsolete */
60835 + case TIOCSERSWILD: /* obsolete */
60836 + ret = 0;
60837 + break;
60840 + if (ret != -ENOIOCTLCMD)
60841 + goto out;
60843 + if (tty->flags & (1 << TTY_IO_ERROR)) {
60844 + ret = -EIO;
60845 + goto out;
60848 + /*
60849 + * The following should only be used when hardware is present.
60850 + */
60851 + switch (cmd) {
60852 + case TIOCMIWAIT:
60853 + ret = uart_wait_modem_status(state, arg);
60854 + break;
60856 + case TIOCGICOUNT:
60857 + ret = uart_get_count(state, (struct serial_icounter_struct *)arg);
60858 + break;
60860 + case TIOCMGET:
60862 + int val;
60863 + val = uart_tiocmget(tty, filp);
60864 + if (val >= 0) {
60865 + ret = put_user(val, (int *)arg);
60866 + } else {
60867 + ret = val;
60870 + break;
60872 + case TIOCMBIS:
60873 + case TIOCMBIC:
60874 + case TIOCMSET:
60876 + int val, set = 0, clear = 0;
60877 + ret = get_user(val, (int *)arg);
60878 + if (ret)
60879 + break;
60881 + switch (cmd) {
60882 + case TIOCMBIS:
60883 + set = val;
60884 + break;
60885 + case TIOCMBIC:
60886 + clear = val;
60887 + break;
60888 + case TIOCMSET:
60889 + set = val;
60890 + clear = ~val;
60891 + break;
60894 + set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
60895 + clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
60897 + ret = uart_tiocmset(tty, filp, set, clear);
60899 + break;
60902 + if (ret != -ENOIOCTLCMD)
60903 + goto out;
60905 + down(&state->sem);
60907 + if (tty_hung_up_p(filp)) {
60908 + ret = -EIO;
60909 + goto out_up;
60912 + /*
60913 + * All these rely on hardware being present and need to be
60914 + * protected against the tty being hung up.
60915 + */
60916 + switch (cmd) {
60917 + case TIOCSERGETLSR: /* Get line status register */
60918 + ret = uart_get_lsr_info(state, (unsigned int *)arg);
60919 + break;
60921 + default: {
60922 + struct uart_port *port = state->port;
60923 + if (port->ops->ioctl)
60924 + ret = port->ops->ioctl(port, cmd, arg);
60925 + break;
60928 + out_up:
60929 + up(&state->sem);
60930 + out:
60931 + return ret;
60934 +static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
60936 + struct uart_state *state = tty->driver_data;
60937 + unsigned long flags;
60938 + unsigned int cflag = tty->termios->c_cflag;
60940 + BUG_ON(!kernel_locked());
60942 + /*
60943 + * These are the bits that are used to setup various
60944 + * flags in the low level driver.
60945 + */
60946 +#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
60948 + if ((cflag ^ old_termios->c_cflag) == 0 &&
60949 + RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
60950 + return;
60952 + uart_change_speed(state, old_termios);
60954 + /* Handle transition to B0 status */
60955 + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
60956 + uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
60958 + /* Handle transition away from B0 status */
60959 + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
60960 + unsigned int mask = TIOCM_DTR;
60961 + if (!(cflag & CRTSCTS) ||
60962 + !test_bit(TTY_THROTTLED, &tty->flags))
60963 + mask |= TIOCM_RTS;
60964 + uart_set_mctrl(state->port, mask);
60967 + /* Handle turning off CRTSCTS */
60968 + if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
60969 + spin_lock_irqsave(&state->port->lock, flags);
60970 + tty->hw_stopped = 0;
60971 + __uart_start(tty);
60972 + spin_unlock_irqrestore(&state->port->lock, flags);
60975 +#if 0
60976 + /*
60977 + * No need to wake up processes in open wait, since they
60978 + * sample the CLOCAL flag once, and don't recheck it.
60979 + * XXX It's not clear whether the current behavior is correct
60980 + * or not. Hence, this may change.....
60981 + */
60982 + if (!(old_termios->c_cflag & CLOCAL) &&
60983 + (tty->termios->c_cflag & CLOCAL))
60984 + wake_up_interruptible(&state->info->open_wait);
60985 +#endif
60989 + * In 2.4.5, calls to this will be serialized via the BKL in
60990 + * linux/drivers/char/tty_io.c:tty_release()
60991 + * linux/drivers/char/tty_io.c:do_tty_handup()
60992 + */
60993 +static void uart_close(struct tty_struct *tty, struct file *filp)
60995 + struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
60996 + struct uart_state *state = tty->driver_data;
60997 + struct uart_port *port;
60999 + BUG_ON(!kernel_locked());
61001 + if (!state || !state->port)
61002 + return;
61004 + port = state->port;
61006 + DPRINTK("uart_close(%d) called\n", port->line);
61008 + down(&state->sem);
61010 + if (tty_hung_up_p(filp))
61011 + goto done;
61013 + if ((tty->count == 1) && (state->count != 1)) {
61014 + /*
61015 + * Uh, oh. tty->count is 1, which means that the tty
61016 + * structure will be freed. state->count should always
61017 + * be one in these conditions. If it's greater than
61018 + * one, we've got real problems, since it means the
61019 + * serial port won't be shutdown.
61020 + */
61021 + printk("uart_close: bad serial port count; tty->count is 1, "
61022 + "state->count is %d\n", state->count);
61023 + state->count = 1;
61025 + if (--state->count < 0) {
61026 + printk("rs_close: bad serial port count for %s%d: %d\n",
61027 + tty->driver.name, port->line, state->count);
61028 + state->count = 0;
61030 + if (state->count)
61031 + goto done;
61033 + /*
61034 + * Save the termios structure, since this port may have
61035 + * separate termios for callout and dialin.
61036 + */
61037 + if (state->info->flags & UIF_NORMAL_ACTIVE)
61038 + state->normal_termios = *tty->termios;
61039 + if (state->info->flags & UIF_CALLOUT_ACTIVE)
61040 + state->callout_termios = *tty->termios;
61042 + /*
61043 + * Now we wait for the transmit buffer to clear; and we notify
61044 + * the line discipline to only process XON/XOFF characters by
61045 + * setting tty->closing.
61046 + */
61047 + tty->closing = 1;
61049 + if (state->closing_wait != USF_CLOSING_WAIT_NONE)
61050 + tty_wait_until_sent(tty, state->closing_wait);
61052 + /*
61053 + * At this point, we stop accepting input. To do this, we
61054 + * disable the receive line status interrupts.
61055 + */
61056 + if (state->info->flags & UIF_INITIALIZED) {
61057 + unsigned long flags;
61058 + spin_lock_irqsave(&port->lock, flags);
61059 + port->ops->stop_rx(port);
61060 + spin_unlock_irqrestore(&port->lock, flags);
61061 + /*
61062 + * Before we drop DTR, make sure the UART transmitter
61063 + * has completely drained; this is especially
61064 + * important if there is a transmit FIFO!
61065 + */
61066 + uart_wait_until_sent(tty, port->timeout);
61069 + uart_shutdown(state);
61070 + uart_flush_buffer(tty);
61071 + if (tty->ldisc.flush_buffer)
61072 + tty->ldisc.flush_buffer(tty);
61073 + tty->closing = 0;
61074 + state->info->tty = NULL;
61076 + if (state->info->blocked_open) {
61077 + if (state->close_delay) {
61078 + set_current_state(TASK_INTERRUPTIBLE);
61079 + schedule_timeout(state->close_delay);
61080 + set_current_state(TASK_RUNNING);
61082 + } else if (!uart_console(port)) {
61083 + uart_change_pm(state, 3);
61086 + /*
61087 + * Wake up anyone trying to open this port.
61088 + */
61089 + state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
61090 + wake_up_interruptible(&state->info->open_wait);
61092 + done:
61093 + up(&state->sem);
61094 + if (drv->owner)
61095 + __MOD_DEC_USE_COUNT(drv->owner);
61098 +static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
61100 + struct uart_state *state = tty->driver_data;
61101 + struct uart_port *port = state->port;
61102 + unsigned long char_time, expire;
61104 + BUG_ON(!kernel_locked());
61106 + if (port->type == PORT_UNKNOWN || port->fifosize == 0)
61107 + return;
61109 + /*
61110 + * Set the check interval to be 1/5 of the estimated time to
61111 + * send a single character, and make it at least 1. The check
61112 + * interval should also be less than the timeout.
61114 + * Note: we have to use pretty tight timings here to satisfy
61115 + * the NIST-PCTS.
61116 + */
61117 + char_time = (port->timeout - HZ/50) / port->fifosize;
61118 + char_time = char_time / 5;
61119 + if (char_time == 0)
61120 + char_time = 1;
61121 + if (timeout && timeout < char_time)
61122 + char_time = timeout;
61124 + /*
61125 + * If the transmitter hasn't cleared in twice the approximate
61126 + * amount of time to send the entire FIFO, it probably won't
61127 + * ever clear. This assumes the UART isn't doing flow
61128 + * control, which is currently the case. Hence, if it ever
61129 + * takes longer than port->timeout, this is probably due to a
61130 + * UART bug of some kind. So, we clamp the timeout parameter at
61131 + * 2*port->timeout.
61132 + */
61133 + if (timeout == 0 || timeout > 2 * port->timeout)
61134 + timeout = 2 * port->timeout;
61136 + expire = jiffies + timeout;
61138 + DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
61139 + port->line, jiffies, expire);
61141 + /*
61142 + * Check whether the transmitter is empty every 'char_time'.
61143 + * 'timeout' / 'expire' give us the maximum amount of time
61144 + * we wait.
61145 + */
61146 + while (!port->ops->tx_empty(port)) {
61147 + set_current_state(TASK_INTERRUPTIBLE);
61148 + schedule_timeout(char_time);
61149 + if (signal_pending(current))
61150 + break;
61151 + if (time_after(jiffies, expire))
61152 + break;
61154 + set_current_state(TASK_RUNNING); /* might not be needed */
61158 + * This is called with the BKL held in
61159 + * linux/drivers/char/tty_io.c:do_tty_hangup()
61160 + * We're called from the eventd thread, so we can sleep for
61161 + * a _short_ time only.
61162 + */
61163 +static void uart_hangup(struct tty_struct *tty)
61165 + struct uart_state *state = tty->driver_data;
61167 + BUG_ON(!kernel_locked());
61168 + DPRINTK("uart_hangup(%d)\n", state->port->line);
61170 + down(&state->sem);
61171 + if (state->info && state->info->flags & (UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE)) {
61172 + uart_flush_buffer(tty);
61173 + uart_shutdown(state);
61174 + state->count = 0;
61175 + state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
61176 + state->info->tty = NULL;
61177 + wake_up_interruptible(&state->info->open_wait);
61178 + wake_up_interruptible(&state->info->delta_msr_wait);
61180 + up(&state->sem);
61184 + * Copy across the serial console cflag setting into the termios settings
61185 + * for the initial open of the port. This allows continuity between the
61186 + * kernel settings, and the settings init adopts when it opens the port
61187 + * for the first time.
61188 + */
61189 +static void uart_update_termios(struct uart_state *state)
61191 + struct tty_struct *tty = state->info->tty;
61192 + struct uart_port *port = state->port;
61194 + if (uart_console(port) && port->cons->cflag) {
61195 + tty->termios->c_cflag = port->cons->cflag;
61196 + port->cons->cflag = 0;
61199 + /*
61200 + * If the device failed to grab its irq resources,
61201 + * or some other error occurred, don't try to talk
61202 + * to the port hardware.
61203 + */
61204 + if (!(tty->flags & (1 << TTY_IO_ERROR))) {
61205 + /*
61206 + * Make termios settings take effect.
61207 + */
61208 + uart_change_speed(state, NULL);
61210 + /*
61211 + * And finally enable the RTS and DTR signals.
61212 + */
61213 + if (tty->termios->c_cflag & CBAUD)
61214 + uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
61219 + * Block the open until the port is ready. We must be called with
61220 + * the per-port semaphore held.
61221 + */
61222 +static int
61223 +uart_block_til_ready(struct file *filp, struct uart_state *state)
61225 + DECLARE_WAITQUEUE(wait, current);
61226 + struct uart_info *info = state->info;
61227 + struct uart_port *port = state->port;
61228 + struct termios *termios;
61230 + /*
61231 + * If this is a callout device, then just make sure the normal
61232 + * device isn't being used.
61233 + */
61234 + if (info->tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
61235 + if (info->flags & UIF_NORMAL_ACTIVE)
61236 + return -EBUSY;
61237 + if ((info->flags & UIF_CALLOUT_ACTIVE) &&
61238 + (info->flags & ASYNC_SESSION_LOCKOUT) &&
61239 + (info->session != current->session))
61240 + return -EBUSY;
61241 + if ((info->flags & UIF_CALLOUT_ACTIVE) &&
61242 + (info->flags & ASYNC_PGRP_LOCKOUT) &&
61243 + (info->pgrp != current->pgrp))
61244 + return -EBUSY;
61245 + info->flags |= UIF_CALLOUT_ACTIVE;
61246 + return 0;
61249 + if (info->flags & UIF_CALLOUT_ACTIVE) {
61250 + termios = &state->normal_termios;
61251 + } else {
61252 + termios = state->info->tty->termios;
61255 + info->blocked_open++;
61256 + state->count--;
61258 + add_wait_queue(&info->open_wait, &wait);
61259 + while (1) {
61260 + set_current_state(TASK_INTERRUPTIBLE);
61262 + /*
61263 + * If we have been hung up, tell userspace/restart open.
61264 + */
61265 + if (tty_hung_up_p(filp) || info->tty == NULL)
61266 + break;
61268 + /*
61269 + * If the port has been closed, tell userspace/restart open.
61270 + */
61271 + if (!(info->flags & UIF_INITIALIZED))
61272 + break;
61274 + /*
61275 + * If non-blocking mode is set, or CLOCAL mode is set,
61276 + * we don't want to wait for the modem status lines to
61277 + * indicate that the port is ready.
61279 + * Also, if the port is not enabled/configured, we want
61280 + * to allow the open to succeed here. Note that we will
61281 + * have set TTY_IO_ERROR for a non-existant port.
61282 + */
61283 + if ((filp->f_flags & O_NONBLOCK) ||
61284 + (termios->c_cflag & CLOCAL) ||
61285 + (info->tty->flags & (1 << TTY_IO_ERROR))) {
61286 + break;
61289 + if (!(info->flags & UIF_CALLOUT_ACTIVE)) {
61290 + /*
61291 + * Set DTR to allow modem to know we're waiting. Do
61292 + * not set RTS here - we want to make sure we catch
61293 + * the data from the modem.
61294 + */
61295 + if (info->tty->termios->c_cflag & CBAUD)
61296 + uart_set_mctrl(port, TIOCM_DTR);
61298 + /*
61299 + * and wait for the carrier to indicate that the
61300 + * modem is ready for us.
61301 + */
61302 + if (port->ops->get_mctrl(port) & TIOCM_CAR)
61303 + break;
61306 + up(&state->sem);
61307 + schedule();
61308 + down(&state->sem);
61310 + if (signal_pending(current))
61311 + break;
61313 + set_current_state(TASK_RUNNING);
61314 + remove_wait_queue(&info->open_wait, &wait);
61316 + state->count++;
61317 + info->blocked_open--;
61319 + info->flags |= UIF_NORMAL_ACTIVE;
61321 + if (signal_pending(current))
61322 + return -ERESTARTSYS;
61324 + if (!info->tty || tty_hung_up_p(filp))
61325 + return -EAGAIN;
61327 + return 0;
61330 +static struct uart_state *uart_get(struct uart_driver *drv, int line)
61332 + struct uart_state *state;
61334 + down(&port_sem);
61335 + state = drv->state + line;
61336 + if (down_interruptible(&state->sem)) {
61337 + state = ERR_PTR(-ERESTARTSYS);
61338 + goto out;
61341 + state->count++;
61342 + if (!state->port) {
61343 + state->count--;
61344 + up(&state->sem);
61345 + state = ERR_PTR(-ENXIO);
61346 + goto out;
61349 + if (!state->info) {
61350 + state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
61351 + if (state->info) {
61352 + memset(state->info, 0, sizeof(struct uart_info));
61353 + init_waitqueue_head(&state->info->open_wait);
61354 + init_waitqueue_head(&state->info->delta_msr_wait);
61356 + /*
61357 + * Link the info into the other structures.
61358 + */
61359 + state->port->info = state->info;
61361 + tasklet_init(&state->info->tlet, uart_tasklet_action,
61362 + (unsigned long)state);
61363 + } else {
61364 + state->count--;
61365 + up(&state->sem);
61366 + state = ERR_PTR(-ENOMEM);
61370 + out:
61371 + up(&port_sem);
61372 + return state;
61376 + * In 2.4.5, calls to uart_open are serialised by the BKL in
61377 + * linux/fs/devices.c:chrdev_open()
61378 + * Note that if this fails, then uart_close() _will_ be called.
61379 + */
61380 +static int uart_open(struct tty_struct *tty, struct file *filp)
61382 + struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
61383 + struct uart_state *state;
61384 + int retval, line = MINOR(tty->device) - tty->driver.minor_start;
61386 + BUG_ON(!kernel_locked());
61387 + DPRINTK("uart_open(%d) called\n", line);
61389 + /*
61390 + * tty->driver->num won't change, so we won't fail here with
61391 + * tty->driver_data set to something non-NULL (and therefore
61392 + * we won't get caught by uart_close()).
61393 + */
61394 + retval = -ENODEV;
61395 + if (line >= tty->driver.num)
61396 + goto fail;
61398 + if (!try_inc_mod_count(drv->owner))
61399 + goto fail;
61401 + /*
61402 + * We take the semaphore inside uart_get to guarantee that we won't
61403 + * be re-entered while allocating the info structure, or while we
61404 + * request any IRQs that the driver may need. This also has the nice
61405 + * side-effect that it delays the action of uart_hangup, so we can
61406 + * guarantee that info->tty will always contain something reasonable.
61407 + */
61408 + state = uart_get(drv, line);
61409 + if (IS_ERR(state)) {
61410 + retval = PTR_ERR(state);
61411 + if (!tty->driver_data)
61412 + goto out;
61413 + else
61414 + goto fail;
61417 + /*
61418 + * Once we set tty->driver_data here, we are guaranteed that
61419 + * uart_close() will decrement the driver module use count.
61420 + * Any failures from here onwards should not touch the count.
61421 + */
61422 + tty->driver_data = state;
61423 + tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
61424 + tty->alt_speed = uart_get_altspeed(state->port);
61425 + state->info->tty = tty;
61427 + /*
61428 + * If the port is in the middle of closing, bail out now.
61429 + */
61430 + if (tty_hung_up_p(filp)) {
61431 + retval = -EAGAIN;
61432 + state->count--;
61433 + up(&state->sem);
61434 + goto fail;
61437 + /*
61438 + * Make sure the device is in D0 state.
61439 + */
61440 + if (state->count == 1)
61441 + uart_change_pm(state, 0);
61443 + /*
61444 + * Start up the serial port.
61445 + */
61446 + retval = uart_startup(state, 0);
61448 + /*
61449 + * If we succeeded, wait until the port is ready.
61450 + */
61451 + if (retval == 0)
61452 + retval = uart_block_til_ready(filp, state);
61454 + /*
61455 + * If this is the first open to succeed, adjust things to suit.
61456 + */
61457 + if (retval == 0 && state->count == 1) {
61458 + if (state->port->flags & UPF_SPLIT_TERMIOS) {
61459 + if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
61460 + *tty->termios = state->normal_termios;
61461 + else
61462 + *tty->termios = state->callout_termios;
61465 + uart_update_termios(state);
61467 + state->info->session = current->session;
61468 + state->info->pgrp = current->pgrp;
61470 + up(&state->sem);
61472 + return 0;
61474 + out:
61475 + if (drv->owner)
61476 + __MOD_DEC_USE_COUNT(drv->owner);
61477 + fail:
61478 + return retval;
61481 +static const char *uart_type(struct uart_port *port)
61483 + const char *str = NULL;
61485 + if (port->ops->type)
61486 + str = port->ops->type(port);
61488 + if (!str)
61489 + str = "unknown";
61491 + return str;
61494 +#ifdef CONFIG_PROC_FS
61496 +static int uart_line_info(char *buf, struct uart_driver *drv, int i)
61498 + struct uart_state *state = drv->state + i;
61499 + struct uart_port *port = state->port;
61500 + char stat_buf[32];
61501 + unsigned int status;
61502 + int ret;
61504 + if (!port)
61505 + return 0;
61507 + ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d",
61508 + port->line, uart_type(port),
61509 + port->iobase, port->irq);
61511 + if (port->type == PORT_UNKNOWN) {
61512 + strcat(buf, "\n");
61513 + return ret + 1;
61516 + status = port->ops->get_mctrl(port);
61518 + ret += sprintf(buf + ret, " tx:%d rx:%d",
61519 + port->icount.tx, port->icount.rx);
61520 + if (port->icount.frame)
61521 + ret += sprintf(buf + ret, " fe:%d",
61522 + port->icount.frame);
61523 + if (port->icount.parity)
61524 + ret += sprintf(buf + ret, " pe:%d",
61525 + port->icount.parity);
61526 + if (port->icount.brk)
61527 + ret += sprintf(buf + ret, " brk:%d",
61528 + port->icount.brk);
61529 + if (port->icount.overrun)
61530 + ret += sprintf(buf + ret, " oe:%d",
61531 + port->icount.overrun);
61533 +#define INFOBIT(bit,str) \
61534 + if (port->mctrl & (bit)) \
61535 + strcat(stat_buf, (str))
61536 +#define STATBIT(bit,str) \
61537 + if (status & (bit)) \
61538 + strcat(stat_buf, (str))
61540 + stat_buf[0] = '\0';
61541 + stat_buf[1] = '\0';
61542 + INFOBIT(TIOCM_RTS, "|RTS");
61543 + STATBIT(TIOCM_CTS, "|CTS");
61544 + INFOBIT(TIOCM_DTR, "|DTR");
61545 + STATBIT(TIOCM_DSR, "|DSR");
61546 + STATBIT(TIOCM_CAR, "|CD");
61547 + STATBIT(TIOCM_RNG, "|RI");
61548 + if (stat_buf[0])
61549 + stat_buf[0] = ' ';
61550 + strcat(stat_buf, "\n");
61552 + ret += sprintf(buf + ret, stat_buf);
61553 + return ret;
61556 +static int uart_read_proc(char *page, char **start, off_t off,
61557 + int count, int *eof, void *data)
61559 + struct tty_driver *ttydrv = data;
61560 + struct uart_driver *drv = ttydrv->driver_state;
61561 + int i, len = 0, l;
61562 + off_t begin = 0;
61564 + len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n",
61565 + "", "", "");
61566 + for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) {
61567 + l = uart_line_info(page + len, drv, i);
61568 + len += l;
61569 + if (len + begin > off + count)
61570 + goto done;
61571 + if (len + begin < off) {
61572 + begin += len;
61573 + len = 0;
61576 + *eof = 1;
61577 + done:
61578 + if (off >= len + begin)
61579 + return 0;
61580 + *start = page + (off - begin);
61581 + return (count < begin + len - off) ? count : (begin + len - off);
61583 +#endif
61585 +#ifdef CONFIG_SERIAL_CORE_CONSOLE
61587 + * Check whether an invalid uart number has been specified, and
61588 + * if so, search for the first available port that does have
61589 + * console support.
61590 + */
61591 +struct uart_port * __init
61592 +uart_get_console(struct uart_port *ports, int nr, struct console *co)
61594 + int idx = co->index;
61596 + if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 &&
61597 + ports[idx].membase == NULL))
61598 + for (idx = 0; idx < nr; idx++)
61599 + if (ports[idx].iobase != 0 ||
61600 + ports[idx].membase != NULL)
61601 + break;
61603 + co->index = idx;
61605 + return ports + idx;
61608 +/**
61609 + * uart_parse_options - Parse serial port baud/parity/bits/flow contro.
61610 + * @options: pointer to option string
61611 + * @baud: pointer to an 'int' variable for the baud rate.
61612 + * @parity: pointer to an 'int' variable for the parity.
61613 + * @bits: pointer to an 'int' variable for the number of data bits.
61614 + * @flow: pointer to an 'int' variable for the flow control character.
61616 + * uart_parse_options decodes a string containing the serial console
61617 + * options. The format of the string is <baud><parity><bits><flow>,
61618 + * eg: 115200n8r
61619 + */
61620 +void __init
61621 +uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
61623 + char *s = options;
61625 + *baud = simple_strtoul(s, NULL, 10);
61626 + while (*s >= '0' && *s <= '9')
61627 + s++;
61628 + if (*s)
61629 + *parity = *s++;
61630 + if (*s)
61631 + *bits = *s++ - '0';
61632 + if (*s)
61633 + *flow = *s;
61636 +struct baud_rates {
61637 + unsigned int rate;
61638 + unsigned int cflag;
61641 +static struct baud_rates baud_rates[] = {
61642 + { 921600, B921600 },
61643 + { 460800, B460800 },
61644 + { 230400, B230400 },
61645 + { 115200, B115200 },
61646 + { 57600, B57600 },
61647 + { 38400, B38400 },
61648 + { 19200, B19200 },
61649 + { 9600, B9600 },
61650 + { 4800, B4800 },
61651 + { 2400, B2400 },
61652 + { 1200, B1200 },
61653 + { 0, B38400 }
61656 +/**
61657 + * uart_set_options - setup the serial console parameters
61658 + * @port: pointer to the serial ports uart_port structure
61659 + * @co: console pointer
61660 + * @baud: baud rate
61661 + * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
61662 + * @bits: number of data bits
61663 + * @flow: flow control character - 'r' (rts)
61664 + */
61665 +int __init
61666 +uart_set_options(struct uart_port *port, struct console *co,
61667 + int baud, int parity, int bits, int flow)
61669 + struct termios termios;
61670 + unsigned int quot;
61671 + int i;
61673 + memset(&termios, 0, sizeof(struct termios));
61675 + termios.c_cflag = CREAD | HUPCL | CLOCAL;
61677 + /*
61678 + * Construct a cflag setting.
61679 + */
61680 + for (i = 0; baud_rates[i].rate; i++)
61681 + if (baud_rates[i].rate <= baud)
61682 + break;
61684 + termios.c_cflag |= baud_rates[i].cflag;
61685 + baud = baud_rates[i].rate;
61686 + if (baud == 0)
61687 + baud = 38400;
61689 + if (bits == 7)
61690 + termios.c_cflag |= CS7;
61691 + else
61692 + termios.c_cflag |= CS8;
61694 + switch (parity) {
61695 + case 'o': case 'O':
61696 + termios.c_cflag |= PARODD;
61697 + /*fall through*/
61698 + case 'e': case 'E':
61699 + termios.c_cflag |= PARENB;
61700 + break;
61703 + if (flow == 'r')
61704 + termios.c_cflag |= CRTSCTS;
61706 + quot = (port->uartclk / (16 * baud));
61707 + port->ops->change_speed(port, termios.c_cflag, 0, quot);
61708 + co->cflag = termios.c_cflag;
61710 + return 0;
61713 +extern void ambauart_console_init(void);
61714 +extern void anakin_console_init(void);
61715 +extern void clps711xuart_console_init(void);
61716 +extern void sa1100_rs_console_init(void);
61717 +extern void serial8250_console_init(void);
61718 +extern void at91_console_init(void);
61721 + * Central "initialise all serial consoles" container. Needs to be killed.
61722 + */
61723 +void __init uart_console_init(void)
61725 +#ifdef CONFIG_SERIAL_AMBA_CONSOLE
61726 + ambauart_console_init();
61727 +#endif
61728 +#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
61729 + anakin_console_init();
61730 +#endif
61731 +#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
61732 + clps711xuart_console_init();
61733 +#endif
61734 +#ifdef CONFIG_SERIAL_SA1100_CONSOLE
61735 + sa1100_rs_console_init();
61736 +#endif
61737 +#ifdef CONFIG_SERIAL_AT91_CONSOLE
61738 + at91_console_init();
61739 +#endif
61740 +#ifdef CONFIG_SERIAL_8250_CONSOLE
61741 + serial8250_console_init();
61742 +#endif
61743 +#ifdef CONFIG_SERIAL_UART00_CONSOLE
61744 + uart00_console_init();
61745 +#endif
61747 +#endif /* CONFIG_SERIAL_CORE_CONSOLE */
61749 +static void uart_change_pm(struct uart_state *state, int pm_state)
61751 + struct uart_port *port = state->port;
61752 + if (port->ops->pm)
61753 + port->ops->pm(port, pm_state, 0);
61756 +#ifdef CONFIG_PM
61757 +int uart_suspend_port(struct uart_state *state)
61759 + struct uart_port *port = state->port;
61761 + down(&state->sem);
61762 + if (port) {
61763 + /*
61764 + * Disable the console device before suspending.
61765 + */
61766 + if (uart_console(port))
61767 + port->cons->flags &= ~CON_ENABLED;
61769 + if (state->info && state->info->flags & UIF_INITIALIZED) {
61770 + struct uart_ops *ops = port->ops;
61772 + spin_lock_irq(&port->lock);
61773 + ops->stop_tx(port, 0);
61774 + ops->set_mctrl(port, 0);
61775 + ops->stop_rx(port);
61776 + spin_unlock_irq(&port->lock);
61778 + /*
61779 + * Wait for the transmitter to empty.
61780 + */
61781 + while (!ops->tx_empty(port)) {
61782 + set_current_state(TASK_UNINTERRUPTIBLE);
61783 + schedule_timeout(10*HZ/1000);
61785 + set_current_state(TASK_RUNNING);
61787 + ops->shutdown(port);
61790 + uart_change_pm(state, 3);
61793 + up(&state->sem);
61795 + return 0;
61798 +int uart_resume_port(struct uart_state *state)
61800 + struct uart_port *port = state->port;
61802 + down(&state->sem);
61803 + if (port) {
61804 + uart_change_pm(state, 0);
61806 + /*
61807 + * Re-enable the console device after suspending.
61808 + */
61809 + if (uart_console(port)) {
61810 + uart_change_speed(state, NULL);
61811 + port->cons->flags |= CON_ENABLED;
61814 + if (state->info && state->info->flags & UIF_INITIALIZED) {
61815 + struct uart_ops *ops = port->ops;
61817 + ops->set_mctrl(port, 0);
61818 + ops->startup(port);
61819 + uart_change_speed(state, NULL);
61820 + spin_lock_irq(&port->lock);
61821 + ops->set_mctrl(port, port->mctrl);
61822 + ops->start_tx(port, 0);
61823 + spin_unlock_irq(&port->lock);
61827 + up(&state->sem);
61829 + return 0;
61833 + * Wakeup support.
61834 + */
61835 +static int uart_pm_set_wakeup(struct uart_state *state, int data)
61837 + int err = 0;
61839 + if (state->port->ops->set_wake)
61840 + err = state->port->ops->set_wake(state->port, data);
61842 + return err;
61845 +static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data)
61847 + struct uart_state *state = dev->data;
61848 + int err = 0;
61850 + if (state->port && state->port->type == PORT_UNKNOWN)
61851 + return 0;
61853 + switch (rqst) {
61854 + case PM_SUSPEND:
61855 + err = uart_suspend_port(state);
61856 + break;
61858 + case PM_RESUME:
61859 + err = uart_resume_port(state);
61860 + break;
61862 + case PM_SET_WAKEUP:
61863 + err = uart_pm_set_wakeup(state, (int)data);
61864 + break;
61866 + return err;
61868 +#endif
61870 +static inline void
61871 +uart_report_port(struct uart_driver *drv, struct uart_port *port)
61873 + printk("%s%d at ", drv->normal_name, port->line);
61874 + switch (port->iotype) {
61875 + case UPIO_PORT:
61876 + printk("I/O 0x%x", port->iobase);
61877 + break;
61878 + case UPIO_HUB6:
61879 + printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
61880 + break;
61881 + case UPIO_MEM:
61882 + printk("MMIO 0x%lx", port->mapbase);
61883 + break;
61885 + printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
61888 +static void
61889 +uart_configure_port(struct uart_driver *drv, struct uart_state *state,
61890 + struct uart_port *port)
61892 + unsigned int flags;
61894 + /*
61895 + * If there isn't a port here, don't do anything further.
61896 + */
61897 + if (!port->iobase && !port->mapbase && !port->membase)
61898 + return;
61900 + /*
61901 + * Now do the auto configuration stuff. Note that config_port
61902 + * is expected to claim the resources and map the port for us.
61903 + */
61904 + flags = UART_CONFIG_TYPE;
61905 + if (port->flags & UPF_AUTO_IRQ)
61906 + flags |= UART_CONFIG_IRQ;
61907 + if (port->flags & UPF_BOOT_AUTOCONF) {
61908 + port->type = PORT_UNKNOWN;
61909 + port->ops->config_port(port, flags);
61912 + if (port->type != PORT_UNKNOWN) {
61913 + unsigned long flags;
61915 + uart_report_port(drv, port);
61917 + /*
61918 + * Ensure that the modem control lines are de-activated.
61919 + * We probably don't need a spinlock around this, but
61920 + */
61921 + spin_lock_irqsave(&port->lock, flags);
61922 + port->ops->set_mctrl(port, 0);
61923 + spin_unlock_irqrestore(&port->lock, flags);
61925 + /*
61926 + * Power down all ports by default, except the
61927 + * console if we have one.
61928 + */
61929 + if (!uart_console(port))
61930 + uart_change_pm(state, 3);
61935 + * This reverses the effects of uart_configure_port, hanging up the
61936 + * port before removal.
61937 + */
61938 +static void
61939 +uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
61941 + struct uart_port *port = state->port;
61942 + struct uart_info *info = state->info;
61944 + if (info && info->tty)
61945 + tty_vhangup(info->tty);
61947 + down(&state->sem);
61949 + state->info = NULL;
61951 + /*
61952 + * Free the port IO and memory resources, if any.
61953 + */
61954 + if (port->type != PORT_UNKNOWN)
61955 + port->ops->release_port(port);
61957 + /*
61958 + * Indicate that there isn't a port here anymore.
61959 + */
61960 + port->type = PORT_UNKNOWN;
61962 + /*
61963 + * Kill the tasklet, and free resources.
61964 + */
61965 + if (info) {
61966 + tasklet_kill(&info->tlet);
61967 + kfree(info);
61970 + up(&state->sem);
61973 +/**
61974 + * uart_register_driver - register a driver with the uart core layer
61975 + * @drv: low level driver structure
61977 + * Register a uart driver with the core driver. We in turn register
61978 + * with the tty layer, and initialise the core driver per-port state.
61980 + * We have a proc file in /proc/tty/driver which is named after the
61981 + * normal driver.
61983 + * drv->port should be NULL, and the per-port structures should be
61984 + * registered using uart_add_one_port after this call has succeeded.
61985 + */
61986 +int uart_register_driver(struct uart_driver *drv)
61988 + struct tty_driver *normal, *callout;
61989 + int i, retval;
61991 + BUG_ON(drv->state);
61993 + /*
61994 + * Maybe we should be using a slab cache for this, especially if
61995 + * we have a large number of ports to handle. Note that we also
61996 + * allocate space for an integer for reference counting.
61997 + */
61998 + drv->state = kmalloc(sizeof(struct uart_state) * drv->nr +
61999 + sizeof(int), GFP_KERNEL);
62000 + retval = -ENOMEM;
62001 + if (!drv->state)
62002 + goto out;
62004 + memset(drv->state, 0, sizeof(struct uart_state) * drv->nr +
62005 + sizeof(int));
62007 + normal = drv->normal_driver;
62008 + callout = drv->callout_driver;
62010 + normal->magic = TTY_DRIVER_MAGIC;
62011 + normal->driver_name = drv->normal_name;
62012 + normal->name = drv->normal_name;
62013 + normal->major = drv->normal_major;
62014 + normal->minor_start = drv->minor;
62015 + normal->num = drv->nr;
62016 + normal->type = TTY_DRIVER_TYPE_SERIAL;
62017 + normal->subtype = SERIAL_TYPE_NORMAL;
62018 + normal->init_termios = tty_std_termios;
62019 + normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
62020 + normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
62021 + normal->refcount = (int *)(drv->state + drv->nr);
62022 + normal->table = drv->table;
62023 + normal->termios = drv->termios;
62024 + normal->termios_locked = drv->termios_locked;
62025 + normal->driver_state = drv;
62027 + normal->open = uart_open;
62028 + normal->close = uart_close;
62029 + normal->write = uart_write;
62030 + normal->put_char = uart_put_char;
62031 + normal->flush_chars = uart_flush_chars;
62032 + normal->write_room = uart_write_room;
62033 + normal->chars_in_buffer = uart_chars_in_buffer;
62034 + normal->flush_buffer = uart_flush_buffer;
62035 + normal->ioctl = uart_ioctl;
62036 + normal->throttle = uart_throttle;
62037 + normal->unthrottle = uart_unthrottle;
62038 + normal->send_xchar = uart_send_xchar;
62039 + normal->set_termios = uart_set_termios;
62040 + normal->stop = uart_stop;
62041 + normal->start = uart_start;
62042 + normal->hangup = uart_hangup;
62043 + normal->break_ctl = uart_break_ctl;
62044 + normal->wait_until_sent = uart_wait_until_sent;
62045 +#ifdef CONFIG_PROC_FS
62046 + normal->read_proc = uart_read_proc;
62047 +#endif
62049 + /*
62050 + * The callout device is just like the normal device except for
62051 + * the major number and the subtype code.
62052 + */
62053 + *callout = *normal;
62054 + callout->name = drv->callout_name;
62055 + callout->major = drv->callout_major;
62056 + callout->subtype = SERIAL_TYPE_CALLOUT;
62057 + callout->read_proc = NULL;
62058 + callout->proc_entry = NULL;
62060 + /*
62061 + * Initialise the UART state(s).
62062 + */
62063 + for (i = 0; i < drv->nr; i++) {
62064 + struct uart_state *state = drv->state + i;
62066 + state->callout_termios = callout->init_termios;
62067 + state->normal_termios = normal->init_termios;
62068 + state->close_delay = 5 * HZ / 10;
62069 + state->closing_wait = 30 * HZ;
62071 + init_MUTEX(&state->sem);
62074 + retval = tty_register_driver(normal);
62075 + if (retval)
62076 + goto out;
62078 + retval = tty_register_driver(callout);
62079 + if (retval)
62080 + tty_unregister_driver(normal);
62082 + out:
62083 + if (retval < 0) {
62084 + kfree(drv->state);
62086 + return retval;
62089 +/**
62090 + * uart_unregister_driver - remove a driver from the uart core layer
62091 + * @drv: low level driver structure
62093 + * Remove all references to a driver from the core driver. The low
62094 + * level driver must have removed all its ports via the
62095 + * uart_remove_one_port() if it registered them with uart_add_one_port().
62096 + * (ie, drv->port == NULL)
62097 + */
62098 +void uart_unregister_driver(struct uart_driver *drv)
62100 + tty_unregister_driver(drv->normal_driver);
62101 + tty_unregister_driver(drv->callout_driver);
62103 + kfree(drv->state);
62104 + drv->state = NULL;
62107 +/**
62108 + * uart_add_one_port - attach a driver-defined port structure
62109 + * @drv: pointer to the uart low level driver structure for this port
62110 + * @port: uart port structure to use for this port.
62112 + * This allows the driver to register its own uart_port structure
62113 + * with the core driver. The main purpose is to allow the low
62114 + * level uart drivers to expand uart_port, rather than having yet
62115 + * more levels of structures.
62116 + */
62117 +int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
62119 + struct uart_state *state;
62120 + int ret = 0;
62122 + BUG_ON(in_interrupt());
62124 + if (port->line >= drv->nr)
62125 + return -EINVAL;
62127 + state = drv->state + port->line;
62129 + down(&port_sem);
62130 + if (state->port) {
62131 + ret = -EINVAL;
62132 + goto out;
62135 + state->port = port;
62137 + spin_lock_init(&port->lock);
62138 + port->cons = drv->cons;
62139 + port->info = state->info;
62141 + uart_configure_port(drv, state, port);
62143 + /*
62144 + * Register the port whether it's detected or not. This allows
62145 + * setserial to be used to alter this ports parameters.
62146 + */
62147 + tty_register_devfs(drv->normal_driver, 0, drv->minor + port->line);
62148 + tty_register_devfs(drv->callout_driver, 0, drv->minor + port->line);
62150 +#ifdef CONFIG_PM
62151 + port->cons = drv->cons;
62152 + state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
62153 + if (state->pm)
62154 + state->pm->data = state;
62155 +#endif
62157 + out:
62158 + up(&port_sem);
62160 + return ret;
62163 +/**
62164 + * uart_remove_one_port - detach a driver defined port structure
62165 + * @drv: pointer to the uart low level driver structure for this port
62166 + * @port: uart port structure for this port
62168 + * This unhooks (and hangs up) the specified port structure from the
62169 + * core driver. No further calls will be made to the low-level code
62170 + * for this port.
62171 + */
62172 +int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
62174 + struct uart_state *state = drv->state + port->line;
62176 + BUG_ON(in_interrupt());
62178 + if (state->port != port)
62179 + printk(KERN_ALERT "Removing wrong port: %p != %p\n",
62180 + state->port, port);
62182 + down(&port_sem);
62184 + pm_unregister(state->pm);
62186 + /*
62187 + * Remove the devices from devfs
62188 + */
62189 + tty_unregister_devfs(drv->normal_driver, drv->minor + port->line);
62190 + tty_unregister_devfs(drv->callout_driver, drv->minor + port->line);
62192 + uart_unconfigure_port(drv, state);
62193 + state->port = NULL;
62194 + up(&port_sem);
62196 + return 0;
62200 + * Are the two ports equivalent?
62201 + */
62202 +static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
62204 + if (port1->iotype != port2->iotype)
62205 + return 0;
62207 + switch (port1->iotype) {
62208 + case UPIO_PORT:
62209 + return (port1->iobase == port2->iobase);
62210 + case UPIO_HUB6:
62211 + return (port1->iobase == port2->iobase) &&
62212 + (port1->hub6 == port2->hub6);
62213 + case UPIO_MEM:
62214 + return (port1->membase == port2->membase);
62216 + return 0;
62220 + * Try to find an unused uart_state slot for a port.
62221 + */
62222 +static struct uart_state *
62223 +uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port)
62225 + int i;
62227 + /*
62228 + * First, find a port entry which matches. Note: if we do
62229 + * find a matching entry, and it has a non-zero use count,
62230 + * then we can't register the port.
62231 + */
62232 + for (i = 0; i < drv->nr; i++)
62233 + if (uart_match_port(drv->state[i].port, port))
62234 + return &drv->state[i];
62236 + /*
62237 + * We didn't find a matching entry, so look for the first
62238 + * free entry. We look for one which hasn't been previously
62239 + * used (indicated by zero iobase).
62240 + */
62241 + for (i = 0; i < drv->nr; i++)
62242 + if (drv->state[i].port->type == PORT_UNKNOWN &&
62243 + drv->state[i].port->iobase == 0 &&
62244 + drv->state[i].count == 0)
62245 + return &drv->state[i];
62247 + /*
62248 + * That also failed. Last resort is to find any currently
62249 + * entry which doesn't have a real port associated with it.
62250 + */
62251 + for (i = 0; i < drv->nr; i++)
62252 + if (drv->state[i].port->type == PORT_UNKNOWN &&
62253 + drv->state[i].count == 0)
62254 + return &drv->state[i];
62256 + return NULL;
62259 +/**
62260 + * uart_register_port: register uart settings with a port
62261 + * @drv: pointer to the uart low level driver structure for this port
62262 + * @port: uart port structure describing the port
62264 + * Register UART settings with the specified low level driver. Detect
62265 + * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the
62266 + * IRQ if UPF_AUTO_IRQ is set.
62268 + * We try to pick the same port for the same IO base address, so that
62269 + * when a modem is plugged in, unplugged and plugged back in, it gets
62270 + * allocated the same port.
62272 + * Returns negative error, or positive line number.
62273 + */
62274 +int uart_register_port(struct uart_driver *drv, struct uart_port *port)
62276 + struct uart_state *state;
62277 + int ret;
62279 + down(&port_sem);
62281 + state = uart_find_match_or_unused(drv, port);
62283 + if (state) {
62284 + /*
62285 + * Ok, we've found a line that we can use.
62287 + * If we find a port that matches this one, and it appears
62288 + * to be in-use (even if it doesn't have a type) we shouldn't
62289 + * alter it underneath itself - the port may be open and
62290 + * trying to do useful work.
62291 + */
62292 + if (uart_users(state) != 0) {
62293 + ret = -EBUSY;
62294 + goto out;
62297 + /*
62298 + * If the port is already initialised, don't touch it.
62299 + */
62300 + if (state->port->type == PORT_UNKNOWN) {
62301 + state->port->iobase = port->iobase;
62302 + state->port->membase = port->membase;
62303 + state->port->irq = port->irq;
62304 + state->port->uartclk = port->uartclk;
62305 + state->port->fifosize = port->fifosize;
62306 + state->port->regshift = port->regshift;
62307 + state->port->iotype = port->iotype;
62308 + state->port->flags = port->flags;
62309 + state->port->line = state - drv->state;
62310 + state->port->mapbase = port->mapbase;
62312 + uart_configure_port(drv, state, state->port);
62315 + ret = state->port->line;
62316 + } else
62317 + ret = -ENOSPC;
62318 + out:
62319 + up(&port_sem);
62320 + return ret;
62323 +/**
62324 + * uart_unregister_port - de-allocate a port
62325 + * @drv: pointer to the uart low level driver structure for this port
62326 + * @line: line index previously returned from uart_register_port()
62328 + * Hang up the specified line associated with the low level driver,
62329 + * and mark the port as unused.
62330 + */
62331 +void uart_unregister_port(struct uart_driver *drv, int line)
62333 + struct uart_state *state;
62335 + if (line < 0 || line >= drv->nr) {
62336 + printk(KERN_ERR "Attempt to unregister %s%d\n",
62337 + drv->normal_name, line);
62338 + return;
62341 + state = drv->state + line;
62343 + down(&port_sem);
62344 + uart_unconfigure_port(drv, state);
62345 + up(&port_sem);
62348 +EXPORT_SYMBOL(uart_write_wakeup);
62349 +EXPORT_SYMBOL(uart_register_driver);
62350 +EXPORT_SYMBOL(uart_unregister_driver);
62351 +EXPORT_SYMBOL(uart_register_port);
62352 +EXPORT_SYMBOL(uart_unregister_port);
62353 +EXPORT_SYMBOL(uart_add_one_port);
62354 +EXPORT_SYMBOL(uart_remove_one_port);
62356 +MODULE_DESCRIPTION("Serial driver core");
62357 +MODULE_LICENSE("GPL");
62358 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
62359 +++ linux-2.4.25/drivers/serial/omaha.c 2004-03-31 17:15:09.000000000 +0200
62360 @@ -0,0 +1,584 @@
62362 + * linux/drivers/char/omaha.c
62364 + * Driver for Omaha serial port
62366 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
62368 + * Copyright 1999-2002 ARM Limited
62369 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
62371 + * This program is free software; you can redistribute it and/or modify
62372 + * it under the terms of the GNU General Public License as published by
62373 + * the Free Software Foundation; either version 2 of the License, or
62374 + * (at your option) any later version.
62376 + * This program is distributed in the hope that it will be useful,
62377 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
62378 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62379 + * GNU General Public License for more details.
62381 + * You should have received a copy of the GNU General Public License
62382 + * along with this program; if not, write to the Free Software
62383 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
62385 + * $Id: serial_amba.c,v 1.4 2001/07/17 20:34:27 rmk Exp $
62387 + * This is a generic driver for ARM AMBA-type serial ports. They
62388 + * have a lot of 16550-like features, but are not register compatable.
62389 + * Note that although they do have CTS, DCD and DSR inputs, they do
62390 + * not have an RI input, nor do they have DTR or RTS outputs. If
62391 + * required, these have to be supplied via some other means (eg, GPIO)
62392 + * and hooked into this driver.
62393 + */
62395 +#include <linux/config.h>
62396 +#include <linux/module.h>
62397 +#include <linux/errno.h>
62398 +#include <linux/signal.h>
62399 +#include <linux/sched.h>
62400 +#include <linux/interrupt.h>
62401 +#include <linux/tty.h>
62402 +#include <linux/tty_flip.h>
62403 +#include <linux/major.h>
62404 +#include <linux/string.h>
62405 +#include <linux/fcntl.h>
62406 +#include <linux/ptrace.h>
62407 +#include <linux/ioport.h>
62408 +#include <linux/mm.h>
62409 +#include <linux/slab.h>
62410 +#include <linux/init.h>
62411 +#include <linux/circ_buf.h>
62412 +#include <linux/serial.h>
62413 +#include <linux/console.h>
62414 +#include <linux/sysrq.h>
62416 +#include <asm/system.h>
62417 +#include <asm/io.h>
62418 +#include <asm/irq.h>
62419 +#include <asm/uaccess.h>
62420 +#include <asm/bitops.h>
62422 +#if defined(CONFIG_SERIAL_OMAHA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
62423 +#define SUPPORT_SYSRQ
62424 +#endif
62426 +#include <linux/serial_core.h>
62428 +#include <asm/hardware/serial_omaha.h>
62430 +#define UART_NR 1
62432 +#define SERIAL_OMAHA_MAJOR 204
62433 +#define SERIAL_OMAHA_MINOR 32
62434 +#define SERIAL_OMAHA_NR UART_NR
62436 +#define CALLOUT_OMAHA_NAME "cuaom"
62437 +#define CALLOUT_OMAHA_MAJOR 205
62438 +#define CALLOUT_OMAHA_MINOR 32
62439 +#define CALLOUT_OMAHA_NR UART_NR
62441 +static struct tty_driver normal, callout;
62442 +static struct tty_struct *omaha_table[UART_NR];
62443 +static struct termios *omaha_termios[UART_NR], *omaha_termios_locked[UART_NR];
62444 +#ifdef SUPPORT_SYSRQ
62445 +static struct console omaha_console;
62446 +#endif
62448 +#define OMAHA_ISR_PASS_LIMIT 256
62451 + * Access macros for the Omaha UARTs
62452 + */
62454 +#define UART_GET_FR(p) readb((p)->membase + OMAHA_UTRSTAT)
62455 +#define UART_GET_CHAR(p) readb((p)->membase + OMAHA_URXH)
62456 +#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + OMAHA_UTXH)
62457 +#define UART_GET_RSR(p) readb((p)->membase + OMAHA_UERSTAT)
62458 +#define UART_FIFO_STATUS(p) (readl((p)->membase + OMAHA_UFSTAT))
62459 +#define UART_RX_DATA(s) (((s) & OMAHA_RXFF_CNT) != 0)
62460 +#define UART_TX_DATA(s) (!((s) & OMAHA_TXFF))
62461 +#define UART_TX_READY(s) (((s) & OMAHA_UTX_EMPTY))
62462 +#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & OMAHA_UTXEMPTY) != 0)
62464 +#define UART_DUMMY_RSR_RX 256
62465 +#define UART_PORT_SIZE 64
62467 +#define RX_IRQ(port) ((port)->irq)
62468 +#define TX_IRQ(port) ((port)->irq + 5)
62471 + * Our private driver data mappings.
62472 + */
62473 +#define drv_old_status driver_priv
62475 +static void omahauart_stop_tx(struct uart_port *port, u_int from_tty)
62477 + disable_irq(TX_IRQ(port));
62480 +static void omahauart_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
62482 + if (nonempty)
62483 + enable_irq(TX_IRQ(port));
62486 +static void omahauart_stop_rx(struct uart_port *port)
62488 + disable_irq(RX_IRQ(port));
62491 +static void omahauart_enable_ms(struct uart_port *port)
62493 + // Do nothing...
62496 +static void
62497 +#ifdef SUPPORT_SYSRQ
62498 +omahauart_rx_chars(struct uart_info *info, struct pt_regs *regs)
62499 +#else
62500 +omahauart_rx_chars(struct uart_info *info)
62501 +#endif
62503 + struct tty_struct *tty = info->tty;
62504 + volatile unsigned int status, data, ch, rsr, max_count = 256;
62505 + struct uart_port *port = info->port;
62507 + status = UART_FIFO_STATUS(port);
62508 + while (UART_RX_DATA(status) && max_count--) {
62509 + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
62510 + tty->flip.tqueue.routine((void *)tty);
62511 + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
62512 + printk(KERN_WARNING "TTY_DONT_FLIP set\n");
62513 + return;
62517 + ch = UART_GET_CHAR(port);
62519 + *tty->flip.char_buf_ptr = ch;
62520 + *tty->flip.flag_buf_ptr = TTY_NORMAL;
62521 + port->icount.rx++;
62523 + /*
62524 + * Note that the error handling code is
62525 + * out of the main execution path
62526 + */
62527 + rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
62528 + if (rsr & 0xf) {
62529 + if (rsr & OMAHA_UART_BREAK) {
62530 + rsr &= ~(OMAHA_UART_FRAME | OMAHA_UART_PARITY);
62531 + port->icount.brk++;
62532 + if (uart_handle_break(info, &omaha_console))
62533 + goto ignore_char;
62534 + } else if (rsr & OMAHA_UART_PARITY)
62535 + port->icount.parity++;
62536 + else if (rsr & OMAHA_UART_FRAME)
62537 + port->icount.frame++;
62538 + if (rsr & OMAHA_UART_OVERRUN)
62539 + port->icount.overrun++;
62541 + rsr &= port->read_status_mask;
62543 + if (rsr & OMAHA_UART_BREAK)
62544 + *tty->flip.flag_buf_ptr = TTY_BREAK;
62545 + else if (rsr & OMAHA_UART_PARITY)
62546 + *tty->flip.flag_buf_ptr = TTY_PARITY;
62547 + else if (rsr & OMAHA_UART_FRAME)
62548 + *tty->flip.flag_buf_ptr = TTY_FRAME;
62551 + if (uart_handle_sysrq_char(info, ch, regs))
62552 + goto ignore_char;
62554 + if ((rsr & port->ignore_status_mask) == 0) {
62555 + tty->flip.flag_buf_ptr++;
62556 + tty->flip.char_buf_ptr++;
62557 + tty->flip.count++;
62559 + if ((rsr & OMAHA_UART_OVERRUN) &&
62560 + tty->flip.count < TTY_FLIPBUF_SIZE) {
62561 + /*
62562 + * Overrun is special, since it's reported
62563 + * immediately, and doesn't affect the current
62564 + * character
62565 + */
62566 + *tty->flip.char_buf_ptr++ = 0;
62567 + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
62568 + tty->flip.count++;
62570 + ignore_char:
62571 + status = UART_FIFO_STATUS(port);
62573 + tty_flip_buffer_push(tty);
62574 + return;
62577 +static void omahauart_tx_chars(struct uart_info *info)
62579 + struct uart_port *port = info->port;
62580 + volatile unsigned int status;
62582 + if (port->x_char) {
62583 + UART_PUT_CHAR(port, port->x_char);
62584 + port->icount.tx++;
62585 + port->x_char = 0;
62586 + return;
62588 + if (info->xmit.head == info->xmit.tail
62589 + || info->tty->stopped
62590 + || info->tty->hw_stopped) {
62591 + omahauart_stop_tx(port, 0);
62592 + return;
62595 + status = UART_FIFO_STATUS(info->port);
62597 + // FIll FIFO as far as possible
62598 + while(UART_TX_DATA(UART_FIFO_STATUS(info->port)))
62600 + UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
62601 + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
62602 + port->icount.tx++;
62603 + if (info->xmit.head == info->xmit.tail)
62604 + break;
62607 + if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) <
62608 + WAKEUP_CHARS)
62609 + uart_event(info, EVT_WRITE_WAKEUP);
62611 + if (info->xmit.head == info->xmit.tail)
62612 + omahauart_stop_tx(info->port, 0);
62615 +static void omahauart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
62617 + struct uart_info *info = dev_id;
62618 + volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
62620 + status = UART_FIFO_STATUS(info->port);
62621 + do {
62622 + // TX if FIFO not full
62623 + if (UART_TX_DATA(status))
62624 + omahauart_tx_chars(info);
62626 + if (pass_counter-- == 0)
62627 + break;
62629 + status = UART_FIFO_STATUS(info->port);
62630 + } while (UART_TX_DATA(status));
62633 +static void omahauart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
62635 + struct uart_info *info = dev_id;
62636 + volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
62638 + status = UART_FIFO_STATUS(info->port);
62639 + do {
62640 + if (UART_RX_DATA(status))
62641 +#ifdef SUPPORT_SYSRQ
62642 + omahauart_rx_chars(info, regs);
62643 +#else
62644 + omahauart_rx_chars(info);
62645 +#endif
62647 + if (pass_counter-- == 0)
62648 + break;
62650 + status = UART_FIFO_STATUS(info->port);
62651 + } while (UART_RX_DATA(status));
62654 +static u_int omahauart_tx_empty(struct uart_port *port)
62656 + return UART_FIFO_STATUS(port) ? 0 : TIOCSER_TEMT;
62659 +static int omahauart_get_mctrl(struct uart_port *port)
62661 + // Report no errors.
62663 + return 0;
62666 +static void omahauart_set_mctrl(struct uart_port *port, u_int mctrl)
62668 + // Do nothing.
62671 +static void omahauart_break_ctl(struct uart_port *port, int break_state)
62673 + // Do nothing.
62676 +static int omahauart_startup(struct uart_port *port, struct uart_info *info)
62678 + unsigned int tmp;
62679 + int retval;
62681 + /*
62682 + * Allocate the IRQs
62683 + */
62684 + retval = request_irq(TX_IRQ(port), omahauart_int_tx, 0, "omaha_uart_tx", info);
62685 + if (retval)
62686 + return retval;
62688 + retval = request_irq(RX_IRQ(port), omahauart_int_rx, 0, "omaha_uart_rx", info);
62690 + if (retval)
62692 + free_irq(TX_IRQ(port), info);
62693 + return retval;
62696 + /*
62697 + * initialise the old status of the modem signals
62698 + */
62699 + info->drv_old_status = 0;
62701 + // Clear all errors
62702 + writel(0, port->membase + OMAHA_UERSTAT);
62704 + // Enable FIFO, 16-byte watermark, also do reset (auto-clearing)
62705 + writel(0xF7, port->membase + OMAHA_UFCON);
62707 + // Level driven TX/RX ints, with rx timeout enabled
62708 + tmp = readl(port->membase + OMAHA_UCON);
62709 + tmp |= 0x280; // rx is pulse driven...
62710 + writel(tmp, port->membase + OMAHA_UCON);
62712 + return 0;
62715 +static void omahauart_shutdown(struct uart_port *port, struct uart_info *info)
62717 + /*
62718 + * Free the interrupt
62719 + */
62720 + free_irq(TX_IRQ(port), info); /* TX interrupt */
62721 + free_irq(RX_IRQ(port), info); /* RX interrupt */
62725 +static void omahauart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
62727 + // Do nothing.
62730 +static const char *omahauart_type(struct uart_port *port)
62732 + return port->type == PORT_OMAHA ? "OMAHA" : NULL;
62736 + * Release the memory region(s) being used by 'port'
62737 + */
62738 +static void omahauart_release_port(struct uart_port *port)
62740 + release_mem_region(port->mapbase, UART_PORT_SIZE);
62744 + * Request the memory region(s) being used by 'port'
62745 + */
62746 +static int omahauart_request_port(struct uart_port *port)
62748 + return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_omaha")
62749 + != NULL ? 0 : -EBUSY;
62753 + * Configure/autoconfigure the port.
62754 + */
62755 +static void omahauart_config_port(struct uart_port *port, int flags)
62757 + if (flags & UART_CONFIG_TYPE) {
62758 + port->type = PORT_OMAHA;
62759 + omahauart_request_port(port);
62764 + * verify the new serial_struct (for TIOCSSERIAL).
62765 + */
62766 +static int omahauart_verify_port(struct uart_port *port, struct serial_struct *ser)
62768 + int ret = 0;
62769 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_OMAHA)
62770 + ret = -EINVAL;
62771 + if (ser->irq < 0 || ser->irq >= NR_IRQS)
62772 + ret = -EINVAL;
62773 + if (ser->baud_base < 9600)
62774 + ret = -EINVAL;
62775 + return ret;
62778 +static struct uart_ops omaha_pops = {
62779 + .tx_empty = omahauart_tx_empty,
62780 + .set_mctrl = omahauart_set_mctrl,
62781 + .get_mctrl = omahauart_get_mctrl,
62782 + .stop_tx = omahauart_stop_tx,
62783 + .start_tx = omahauart_start_tx,
62784 + .stop_rx = omahauart_stop_rx,
62785 + .enable_ms = omahauart_enable_ms,
62786 + .break_ctl = omahauart_break_ctl,
62787 + .startup = omahauart_startup,
62788 + .shutdown = omahauart_shutdown,
62789 + .change_speed = omahauart_change_speed,
62790 + .type = omahauart_type,
62791 + .release_port = omahauart_release_port,
62792 + .request_port = omahauart_request_port,
62793 + .config_port = omahauart_config_port,
62794 + .verify_port = omahauart_verify_port,
62797 +static struct uart_port omaha_ports[UART_NR] = {
62799 + .membase = (void *)IO_ADDRESS(OMAHA_UART0_BASE),
62800 + .mapbase = OMAHA_UART0_BASE,
62801 + .iotype = SERIAL_IO_MEM,
62802 + .irq = OMAHA_INT_URXD0,
62803 + .uartclk = 10000000,
62804 + .fifosize = 8,
62805 + .unused = { 4, 5 }, /*Udriver_priv: PORT_CTRLS(5, 4), */
62806 + .ops = &omaha_pops,
62807 + .flags = ASYNC_BOOT_AUTOCONF,
62811 +#ifdef CONFIG_SERIAL_OMAHA_CONSOLE
62812 +static void omahauart_console_write(struct console *co, const char *s, u_int count)
62814 + struct uart_port *port = omaha_ports + co->index;
62815 + unsigned int status;
62816 + int i;
62818 + /*
62819 + * First save the CR then disable the interrupts
62820 + */
62822 + /*
62823 + * Now, do each character
62824 + */
62825 + for (i = 0; i < count; i++) {
62826 + do {
62827 + status = UART_GET_FR(port);
62828 + } while ((status & OMAHA_UTX_EMPTY) == 0);
62829 + UART_PUT_CHAR(port, s[i]);
62830 + if (s[i] == '\n') {
62831 + do {
62832 + status = UART_GET_FR(port);
62833 + } while ((status & OMAHA_UTX_EMPTY) == 0);
62834 + UART_PUT_CHAR(port, '\r');
62838 + /*
62839 + * Finally, wait for transmitter to become empty
62840 + * and restore the TCR
62841 + */
62842 + do {
62843 + status = UART_GET_FR(port);
62844 + } while ((status & OMAHA_UTX_EMPTY) == 0);
62847 +static kdev_t omahauart_console_device(struct console *co)
62849 + return MKDEV(SERIAL_OMAHA_MAJOR, SERIAL_OMAHA_MINOR + co->index);
62852 +static int omahauart_console_wait_key(struct console *co)
62854 + struct uart_port *port = omaha_ports + co->index;
62855 + unsigned int status;
62857 + do {
62858 + status = UART_FIFO_STATUS(port);
62859 + } while (!UART_RX_DATA(status));
62860 + return UART_GET_CHAR(port);
62863 +static void __init
62864 +omahauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
62866 + // Do nothing.
62869 +static int __init omahauart_console_setup(struct console *co, char *options)
62871 + struct uart_port *port;
62872 + int baud = 38400;
62873 + int bits = 8;
62874 + int parity = 'n';
62875 + int flow = 'n';
62877 + /*
62878 + * Check whether an invalid uart number has been specified, and
62879 + * if so, search for the first available port that does have
62880 + * console support.
62881 + */
62882 + port = uart_get_console(omaha_ports, UART_NR, co);
62884 + if (options)
62885 + uart_parse_options(options, &baud, &parity, &bits, &flow);
62886 + else
62887 + omahauart_console_get_options(port, &baud, &parity, &bits);
62889 + return uart_set_options(port, co, baud, parity, bits, flow);
62892 +static struct console omaha_console = {
62893 + .write = omahauart_console_write,
62894 + .device = omahauart_console_device,
62895 + .wait_key = omahauart_console_wait_key,
62896 + .setup = omahauart_console_setup,
62897 + .flags = CON_PRINTBUFFER,
62898 + .index = -1,
62901 +void __init omahauart_console_init(void)
62903 + register_console(&omaha_console);
62906 +#define OMAHA_CONSOLE &omaha_console
62907 +#else
62908 +#define OMAHA_CONSOLE NULL
62909 +#endif
62911 +static struct uart_driver omaha_reg = {
62912 + .owner = THIS_MODULE,
62913 + .normal_major = SERIAL_OMAHA_MAJOR,
62914 +#ifdef CONFIG_DEVFS_FS
62915 + .normal_name = "ttyOM%d",
62916 + .callout_name = "cuaom%d",
62917 +#else
62918 + .normal_name = "ttyOM",
62919 + .callout_name = "cuaom",
62920 +#endif
62921 + .normal_driver = &normal,
62922 + .callout_major = CALLOUT_OMAHA_MAJOR,
62923 + .callout_driver = &callout,
62924 + .table = omaha_table,
62925 + .termios = omaha_termios,
62926 + .termios_locked = omaha_termios_locked,
62927 + .minor = SERIAL_OMAHA_MINOR,
62928 + .nr = UART_NR,
62929 + .port = omaha_ports,
62930 + .cons = OMAHA_CONSOLE,
62933 +static int __init omahauart_init(void)
62935 + return uart_register_driver(&omaha_reg);
62938 +static void __exit omahauart_exit(void)
62940 + uart_unregister_driver(&omaha_reg);
62943 +module_init(omahauart_init);
62944 +module_exit(omahauart_exit);
62945 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
62946 +++ linux-2.4.25/drivers/serial/sa1100.c 2004-03-31 17:15:09.000000000 +0200
62947 @@ -0,0 +1,904 @@
62949 + * linux/drivers/char/serial_sa1100.c
62951 + * Driver for SA11x0 serial ports
62953 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
62955 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
62957 + * This program is free software; you can redistribute it and/or modify
62958 + * it under the terms of the GNU General Public License as published by
62959 + * the Free Software Foundation; either version 2 of the License, or
62960 + * (at your option) any later version.
62962 + * This program is distributed in the hope that it will be useful,
62963 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
62964 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62965 + * GNU General Public License for more details.
62967 + * You should have received a copy of the GNU General Public License
62968 + * along with this program; if not, write to the Free Software
62969 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
62971 + * $Id: sa1100.c,v 1.14.2.4 2002/10/24 09:53:25 rmk Exp $
62973 + */
62974 +#include <linux/config.h>
62975 +#include <linux/module.h>
62976 +#include <linux/tty.h>
62977 +#include <linux/ioport.h>
62978 +#include <linux/init.h>
62979 +#include <linux/sched.h>
62980 +#include <linux/serial.h>
62981 +#include <linux/console.h>
62982 +#include <linux/sysrq.h>
62984 +#include <asm/io.h>
62985 +#include <asm/irq.h>
62986 +#include <asm/hardware.h>
62987 +#include <asm/mach/serial_sa1100.h>
62989 +#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
62990 +#define SUPPORT_SYSRQ
62991 +#endif
62993 +#include <linux/serial_core.h>
62995 +/* We've been assigned a range on the "Low-density serial ports" major */
62996 +#define SERIAL_SA1100_MAJOR 204
62997 +#define CALLOUT_SA1100_MAJOR 205
62998 +#define MINOR_START 5
63000 +#define NR_PORTS 3
63002 +#define SA1100_ISR_PASS_LIMIT 256
63005 + * Convert from ignore_status_mask or read_status_mask to UTSR[01]
63006 + */
63007 +#define SM_TO_UTSR0(x) ((x) & 0xff)
63008 +#define SM_TO_UTSR1(x) ((x) >> 8)
63009 +#define UTSR0_TO_SM(x) ((x))
63010 +#define UTSR1_TO_SM(x) ((x) << 8)
63012 +#define UART_GET_UTCR0(sport) __raw_readl((sport)->port.membase + UTCR0)
63013 +#define UART_GET_UTCR1(sport) __raw_readl((sport)->port.membase + UTCR1)
63014 +#define UART_GET_UTCR2(sport) __raw_readl((sport)->port.membase + UTCR2)
63015 +#define UART_GET_UTCR3(sport) __raw_readl((sport)->port.membase + UTCR3)
63016 +#define UART_GET_UTSR0(sport) __raw_readl((sport)->port.membase + UTSR0)
63017 +#define UART_GET_UTSR1(sport) __raw_readl((sport)->port.membase + UTSR1)
63018 +#define UART_GET_CHAR(sport) __raw_readl((sport)->port.membase + UTDR)
63020 +#define UART_PUT_UTCR0(sport,v) __raw_writel((v),(sport)->port.membase + UTCR0)
63021 +#define UART_PUT_UTCR1(sport,v) __raw_writel((v),(sport)->port.membase + UTCR1)
63022 +#define UART_PUT_UTCR2(sport,v) __raw_writel((v),(sport)->port.membase + UTCR2)
63023 +#define UART_PUT_UTCR3(sport,v) __raw_writel((v),(sport)->port.membase + UTCR3)
63024 +#define UART_PUT_UTSR0(sport,v) __raw_writel((v),(sport)->port.membase + UTSR0)
63025 +#define UART_PUT_UTSR1(sport,v) __raw_writel((v),(sport)->port.membase + UTSR1)
63026 +#define UART_PUT_CHAR(sport,v) __raw_writel((v),(sport)->port.membase + UTDR)
63029 + * This is the size of our serial port register set.
63030 + */
63031 +#define UART_PORT_SIZE 0x24
63033 +static struct tty_driver normal, callout;
63034 +static struct tty_struct *sa1100_table[NR_PORTS];
63035 +static struct termios *sa1100_termios[NR_PORTS], *sa1100_termios_locked[NR_PORTS];
63036 +static int (*sa1100_open)(struct uart_port *);
63037 +static void (*sa1100_close)(struct uart_port *);
63038 +#ifdef SUPPORT_SYSRQ
63039 +static struct console sa1100_console;
63040 +#endif
63043 + * This determines how often we check the modem status signals
63044 + * for any change. They generally aren't connected to an IRQ
63045 + * so we have to poll them. We also check immediately before
63046 + * filling the TX fifo incase CTS has been dropped.
63047 + */
63048 +#define MCTRL_TIMEOUT (250*HZ/1000)
63050 +struct sa1100_port {
63051 + struct uart_port port;
63052 + struct timer_list timer;
63053 + unsigned int old_status;
63057 + * Handle any change of modem status signal since we were last called.
63058 + */
63059 +static void sa1100_mctrl_check(struct sa1100_port *sport)
63061 + unsigned int status, changed;
63063 + status = sport->port.ops->get_mctrl(&sport->port);
63064 + changed = status ^ sport->old_status;
63066 + if (changed == 0)
63067 + return;
63069 + sport->old_status = status;
63071 + if (changed & TIOCM_RI)
63072 + sport->port.icount.rng++;
63073 + if (changed & TIOCM_DSR)
63074 + sport->port.icount.dsr++;
63075 + if (changed & TIOCM_CAR)
63076 + uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
63077 + if (changed & TIOCM_CTS)
63078 + uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
63080 + wake_up_interruptible(&sport->port.info->delta_msr_wait);
63084 + * This is our per-port timeout handler, for checking the
63085 + * modem status signals.
63086 + */
63087 +static void sa1100_timeout(unsigned long data)
63089 + struct sa1100_port *sport = (struct sa1100_port *)data;
63090 + unsigned long flags;
63092 + if (sport->port.info) {
63093 + spin_lock_irqsave(&sport->port.lock, flags);
63094 + sa1100_mctrl_check(sport);
63095 + spin_unlock_irqrestore(&sport->port.lock, flags);
63097 + mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
63102 + * interrupts disabled on entry
63103 + */
63104 +static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
63106 + struct sa1100_port *sport = (struct sa1100_port *)port;
63107 + u32 utcr3;
63109 + utcr3 = UART_GET_UTCR3(sport);
63110 + UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE);
63111 + sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
63115 + * interrupts may not be disabled on entry
63116 + */
63117 +static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
63119 + struct sa1100_port *sport = (struct sa1100_port *)port;
63120 + unsigned long flags;
63121 + u32 utcr3;
63123 + spin_lock_irqsave(&sport->port.lock, flags);
63124 + utcr3 = UART_GET_UTCR3(sport);
63125 + sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
63126 + UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
63127 + spin_unlock_irqrestore(&sport->port.lock, flags);
63131 + * Interrupts enabled
63132 + */
63133 +static void sa1100_stop_rx(struct uart_port *port)
63135 + struct sa1100_port *sport = (struct sa1100_port *)port;
63136 + u32 utcr3;
63138 + utcr3 = UART_GET_UTCR3(sport);
63139 + UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
63143 + * Set the modem control timer to fire immediately.
63144 + */
63145 +static void sa1100_enable_ms(struct uart_port *port)
63147 + struct sa1100_port *sport = (struct sa1100_port *)port;
63149 + mod_timer(&sport->timer, jiffies);
63152 +static void
63153 +sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
63155 + struct tty_struct *tty = sport->port.info->tty;
63156 + unsigned int status, ch, flg, ignored = 0;
63158 + status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
63159 + UTSR0_TO_SM(UART_GET_UTSR0(sport));
63160 + while (status & UTSR1_TO_SM(UTSR1_RNE)) {
63161 + ch = UART_GET_CHAR(sport);
63163 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
63164 + goto ignore_char;
63165 + sport->port.icount.rx++;
63167 + flg = TTY_NORMAL;
63169 + /*
63170 + * note that the error handling code is
63171 + * out of the main execution path
63172 + */
63173 + if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR))
63174 + goto handle_error;
63176 + if (uart_handle_sysrq_char(&sport->port, ch, regs))
63177 + goto ignore_char;
63179 + error_return:
63180 + *tty->flip.flag_buf_ptr++ = flg;
63181 + *tty->flip.char_buf_ptr++ = ch;
63182 + tty->flip.count++;
63183 + ignore_char:
63184 + status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
63185 + UTSR0_TO_SM(UART_GET_UTSR0(sport));
63187 + out:
63188 + tty_flip_buffer_push(tty);
63189 + return;
63191 + handle_error:
63192 + if (status & UTSR1_TO_SM(UTSR1_PRE))
63193 + sport->port.icount.parity++;
63194 + else if (status & UTSR1_TO_SM(UTSR1_FRE))
63195 + sport->port.icount.frame++;
63196 + if (status & UTSR1_TO_SM(UTSR1_ROR))
63197 + sport->port.icount.overrun++;
63199 + if (status & sport->port.ignore_status_mask) {
63200 + if (++ignored > 100)
63201 + goto out;
63202 + goto ignore_char;
63205 + status &= sport->port.read_status_mask;
63207 + if (status & UTSR1_TO_SM(UTSR1_PRE))
63208 + flg = TTY_PARITY;
63209 + else if (status & UTSR1_TO_SM(UTSR1_FRE))
63210 + flg = TTY_FRAME;
63212 + if (status & UTSR1_TO_SM(UTSR1_ROR)) {
63213 + /*
63214 + * overrun does *not* affect the character
63215 + * we read from the FIFO
63216 + */
63217 + *tty->flip.flag_buf_ptr++ = flg;
63218 + *tty->flip.char_buf_ptr++ = ch;
63219 + tty->flip.count++;
63220 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
63221 + goto ignore_char;
63222 + ch = 0;
63223 + flg = TTY_OVERRUN;
63225 +#ifdef SUPPORT_SYSRQ
63226 + sport->port.sysrq = 0;
63227 +#endif
63228 + goto error_return;
63231 +static void sa1100_tx_chars(struct sa1100_port *sport)
63233 + struct circ_buf *xmit = &sport->port.info->xmit;
63235 + if (sport->port.x_char) {
63236 + UART_PUT_CHAR(sport, sport->port.x_char);
63237 + sport->port.icount.tx++;
63238 + sport->port.x_char = 0;
63239 + return;
63242 + /*
63243 + * Check the modem control lines before
63244 + * transmitting anything.
63245 + */
63246 + sa1100_mctrl_check(sport);
63248 + if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
63249 + sa1100_stop_tx(&sport->port, 0);
63250 + return;
63253 + /*
63254 + * Tried using FIFO (not checking TNF) for fifo fill:
63255 + * still had the '4 bytes repeated' problem.
63256 + */
63257 + while (UART_GET_UTSR1(sport) & UTSR1_TNF) {
63258 + UART_PUT_CHAR(sport, xmit->buf[xmit->tail]);
63259 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
63260 + sport->port.icount.tx++;
63261 + if (uart_circ_empty(xmit))
63262 + break;
63265 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
63266 + uart_write_wakeup(&sport->port);
63268 + if (uart_circ_empty(xmit))
63269 + sa1100_stop_tx(&sport->port, 0);
63272 +static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
63274 + struct sa1100_port *sport = dev_id;
63275 + unsigned int status, pass_counter = 0;
63277 + spin_lock(&sport->port.lock);
63278 + status = UART_GET_UTSR0(sport);
63279 + status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
63280 + do {
63281 + if (status & (UTSR0_RFS | UTSR0_RID)) {
63282 + /* Clear the receiver idle bit, if set */
63283 + if (status & UTSR0_RID)
63284 + UART_PUT_UTSR0(sport, UTSR0_RID);
63285 + sa1100_rx_chars(sport, regs);
63288 + /* Clear the relevant break bits */
63289 + if (status & (UTSR0_RBB | UTSR0_REB))
63290 + UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB));
63292 + if (status & UTSR0_RBB)
63293 + sport->port.icount.brk++;
63295 + if (status & UTSR0_REB)
63296 + uart_handle_break(&sport->port);
63298 + if (status & UTSR0_TFS)
63299 + sa1100_tx_chars(sport);
63300 + if (pass_counter++ > SA1100_ISR_PASS_LIMIT)
63301 + break;
63302 + status = UART_GET_UTSR0(sport);
63303 + status &= SM_TO_UTSR0(sport->port.read_status_mask) |
63304 + ~UTSR0_TFS;
63305 + } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
63306 + spin_unlock(&sport->port.lock);
63310 + * Return TIOCSER_TEMT when transmitter is not busy.
63311 + */
63312 +static unsigned int sa1100_tx_empty(struct uart_port *port)
63314 + struct sa1100_port *sport = (struct sa1100_port *)port;
63316 + return UART_GET_UTSR1(sport) & UTSR1_TBY ? 0 : TIOCSER_TEMT;
63319 +static unsigned int sa1100_get_mctrl(struct uart_port *port)
63321 + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
63324 +static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
63329 + * Interrupts always disabled.
63330 + */
63331 +static void sa1100_break_ctl(struct uart_port *port, int break_state)
63333 + struct sa1100_port *sport = (struct sa1100_port *)port;
63334 + unsigned long flags;
63335 + unsigned int utcr3;
63337 + spin_lock_irqsave(&sport->port.lock, flags);
63338 + utcr3 = UART_GET_UTCR3(sport);
63339 + if (break_state == -1)
63340 + utcr3 |= UTCR3_BRK;
63341 + else
63342 + utcr3 &= ~UTCR3_BRK;
63343 + UART_PUT_UTCR3(sport, utcr3);
63344 + spin_unlock_irqrestore(&sport->port.lock, flags);
63347 +static int sa1100_startup(struct uart_port *port)
63349 + struct sa1100_port *sport = (struct sa1100_port *)port;
63350 + int retval;
63352 + /*
63353 + * Allocate the IRQ
63354 + */
63355 + retval = request_irq(sport->port.irq, sa1100_int, 0,
63356 + "sa11x0-uart", sport);
63357 + if (retval)
63358 + return retval;
63360 + /*
63361 + * If there is a specific "open" function
63362 + * (to register control line interrupts)
63363 + */
63364 + if (sa1100_open) {
63365 + retval = sa1100_open(port);
63366 + if (retval) {
63367 + free_irq(sport->port.irq, sport);
63368 + return retval;
63372 + /*
63373 + * Finally, clear and enable interrupts
63374 + */
63375 + UART_PUT_UTSR0(sport, -1);
63376 + UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);
63378 + return 0;
63381 +static void sa1100_shutdown(struct uart_port *port)
63383 + struct sa1100_port *sport = (struct sa1100_port *)port;
63385 + /*
63386 + * Stop our timer.
63387 + */
63388 + del_timer_sync(&sport->timer);
63390 + /*
63391 + * Free the interrupt
63392 + */
63393 + free_irq(sport->port.irq, sport);
63395 + /*
63396 + * If there is a specific "close" function (to unregister
63397 + * control line interrupts)
63398 + */
63399 + if (sa1100_close)
63400 + sa1100_close(port);
63402 + /*
63403 + * Disable all interrupts, port and break condition.
63404 + */
63405 + UART_PUT_UTCR3(sport, 0);
63408 +static void sa1100_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
63410 + struct sa1100_port *sport = (struct sa1100_port *)port;
63411 + unsigned long flags;
63412 + unsigned int utcr0, old_utcr3;
63414 + if ((cflag & CSIZE) == CS8)
63415 + utcr0 = UTCR0_DSS;
63416 + else
63417 + utcr0 = 0;
63419 + if (cflag & CSTOPB)
63420 + utcr0 |= UTCR0_SBS;
63421 + if (cflag & PARENB) {
63422 + utcr0 |= UTCR0_PE;
63423 + if (!(cflag & PARODD))
63424 + utcr0 |= UTCR0_OES;
63427 + spin_lock_irqsave(&sport->port.lock, flags);
63429 + sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
63430 + sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
63431 + if (iflag & INPCK)
63432 + sport->port.read_status_mask |=
63433 + UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
63434 + if (iflag & (BRKINT | PARMRK))
63435 + sport->port.read_status_mask |=
63436 + UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
63438 + /*
63439 + * Characters to ignore
63440 + */
63441 + sport->port.ignore_status_mask = 0;
63442 + if (iflag & IGNPAR)
63443 + sport->port.ignore_status_mask |=
63444 + UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
63445 + if (iflag & IGNBRK) {
63446 + sport->port.ignore_status_mask |=
63447 + UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
63448 + /*
63449 + * If we're ignoring parity and break indicators,
63450 + * ignore overruns too (for real raw support).
63451 + */
63452 + if (iflag & IGNPAR)
63453 + sport->port.ignore_status_mask |=
63454 + UTSR1_TO_SM(UTSR1_ROR);
63457 + del_timer_sync(&sport->timer);
63459 + /*
63460 + * disable interrupts and drain transmitter
63461 + */
63462 + old_utcr3 = UART_GET_UTCR3(sport);
63463 + UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
63465 + while (UART_GET_UTSR1(sport) & UTSR1_TBY)
63466 + barrier();
63468 + /* then, disable everything */
63469 + UART_PUT_UTCR3(sport, 0);
63471 + /* set the parity, stop bits and data size */
63472 + UART_PUT_UTCR0(sport, utcr0);
63474 + /* set the baud rate */
63475 + quot -= 1;
63476 + UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
63477 + UART_PUT_UTCR2(sport, (quot & 0xff));
63479 + UART_PUT_UTSR0(sport, -1);
63481 + UART_PUT_UTCR3(sport, old_utcr3);
63483 + if (UART_ENABLE_MS(&sport->port, cflag))
63484 + sa1100_enable_ms(&sport->port);
63486 + spin_unlock_irqrestore(&sport->port.lock, flags);
63489 +static const char *sa1100_type(struct uart_port *port)
63491 + struct sa1100_port *sport = (struct sa1100_port *)port;
63493 + return sport->port.type == PORT_SA1100 ? "SA1100" : NULL;
63497 + * Release the memory region(s) being used by 'port'.
63498 + */
63499 +static void sa1100_release_port(struct uart_port *port)
63501 + struct sa1100_port *sport = (struct sa1100_port *)port;
63503 + release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
63507 + * Request the memory region(s) being used by 'port'.
63508 + */
63509 +static int sa1100_request_port(struct uart_port *port)
63511 + struct sa1100_port *sport = (struct sa1100_port *)port;
63513 + return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
63514 + "sa11x0-uart") != NULL ? 0 : -EBUSY;
63518 + * Configure/autoconfigure the port.
63519 + */
63520 +static void sa1100_config_port(struct uart_port *port, int flags)
63522 + struct sa1100_port *sport = (struct sa1100_port *)port;
63524 + if (flags & UART_CONFIG_TYPE &&
63525 + sa1100_request_port(&sport->port) == 0)
63526 + sport->port.type = PORT_SA1100;
63530 + * Verify the new serial_struct (for TIOCSSERIAL).
63531 + * The only change we allow are to the flags and type, and
63532 + * even then only between PORT_SA1100 and PORT_UNKNOWN
63533 + */
63534 +static int sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
63536 + struct sa1100_port *sport = (struct sa1100_port *)port;
63537 + int ret = 0;
63539 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_SA1100)
63540 + ret = -EINVAL;
63541 + if (sport->port.irq != ser->irq)
63542 + ret = -EINVAL;
63543 + if (ser->io_type != SERIAL_IO_MEM)
63544 + ret = -EINVAL;
63545 + if (sport->port.uartclk / 16 != ser->baud_base)
63546 + ret = -EINVAL;
63547 + if ((void *)sport->port.mapbase != ser->iomem_base)
63548 + ret = -EINVAL;
63549 + if (sport->port.iobase != ser->port)
63550 + ret = -EINVAL;
63551 + if (ser->hub6 != 0)
63552 + ret = -EINVAL;
63553 + return ret;
63556 +static struct uart_ops sa1100_pops = {
63557 + .tx_empty = sa1100_tx_empty,
63558 + .set_mctrl = sa1100_set_mctrl,
63559 + .get_mctrl = sa1100_get_mctrl,
63560 + .stop_tx = sa1100_stop_tx,
63561 + .start_tx = sa1100_start_tx,
63562 + .stop_rx = sa1100_stop_rx,
63563 + .enable_ms = sa1100_enable_ms,
63564 + .break_ctl = sa1100_break_ctl,
63565 + .startup = sa1100_startup,
63566 + .shutdown = sa1100_shutdown,
63567 + .change_speed = sa1100_change_speed,
63568 + .type = sa1100_type,
63569 + .release_port = sa1100_release_port,
63570 + .request_port = sa1100_request_port,
63571 + .config_port = sa1100_config_port,
63572 + .verify_port = sa1100_verify_port,
63575 +static struct sa1100_port sa1100_ports[NR_PORTS];
63578 + * Setup the SA1100 serial ports. Note that we don't include the IrDA
63579 + * port here since we have our own SIR/FIR driver (see drivers/net/irda)
63581 + * Note also that we support "console=ttySAx" where "x" is either 0 or 1.
63582 + * Which serial port this ends up being depends on the machine you're
63583 + * running this kernel on. I'm not convinced that this is a good idea,
63584 + * but that's the way it traditionally works.
63586 + * Note that NanoEngine UART3 becomes UART2, and UART2 is no longer
63587 + * used here.
63588 + */
63589 +static void __init sa1100_init_ports(void)
63591 + static int first = 1;
63592 + int i;
63594 + if (!first)
63595 + return;
63596 + first = 0;
63598 + for (i = 0; i < NR_PORTS; i++) {
63599 + sa1100_ports[i].port.uartclk = 3686400;
63600 + sa1100_ports[i].port.ops = &sa1100_pops;
63601 + sa1100_ports[i].port.fifosize = 8;
63602 + sa1100_ports[i].port.line = i;
63603 + sa1100_ports[i].port.iotype = SERIAL_IO_MEM;
63604 + init_timer(&sa1100_ports[i].timer);
63605 + sa1100_ports[i].timer.function = sa1100_timeout;
63606 + sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
63609 + /*
63610 + * make transmit lines outputs, so that when the port
63611 + * is closed, the output is in the MARK state.
63612 + */
63613 + PPDR |= PPC_TXD1 | PPC_TXD3;
63614 + PPSR |= PPC_TXD1 | PPC_TXD3;
63617 +void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
63619 + if (fns->enable_ms)
63620 + sa1100_pops.enable_ms = fns->enable_ms;
63621 + if (fns->get_mctrl)
63622 + sa1100_pops.get_mctrl = fns->get_mctrl;
63623 + if (fns->set_mctrl)
63624 + sa1100_pops.set_mctrl = fns->set_mctrl;
63625 + sa1100_open = fns->open;
63626 + sa1100_close = fns->close;
63627 + sa1100_pops.pm = fns->pm;
63628 + sa1100_pops.set_wake = fns->set_wake;
63631 +void __init sa1100_register_uart(int idx, int port)
63633 + if (idx >= NR_PORTS) {
63634 + printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
63635 + return;
63638 + switch (port) {
63639 + case 1:
63640 + sa1100_ports[idx].port.membase = (void *)&Ser1UTCR0;
63641 + sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
63642 + sa1100_ports[idx].port.irq = IRQ_Ser1UART;
63643 + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
63644 + break;
63646 + case 2:
63647 + sa1100_ports[idx].port.membase = (void *)&Ser2UTCR0;
63648 + sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
63649 + sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
63650 + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
63651 + break;
63653 + case 3:
63654 + sa1100_ports[idx].port.membase = (void *)&Ser3UTCR0;
63655 + sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
63656 + sa1100_ports[idx].port.irq = IRQ_Ser3UART;
63657 + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
63658 + break;
63660 + default:
63661 + printk(KERN_ERR "%s: bad port number %d\n", __FUNCTION__, port);
63666 +#ifdef CONFIG_SERIAL_SA1100_CONSOLE
63669 + * Interrupts are disabled on entering
63670 + */
63671 +static void
63672 +sa1100_console_write(struct console *co, const char *s, unsigned int count)
63674 + struct sa1100_port *sport = &sa1100_ports[co->index];
63675 + unsigned int old_utcr3, status, i;
63677 + /*
63678 + * First, save UTCR3 and then disable interrupts
63679 + */
63680 + old_utcr3 = UART_GET_UTCR3(sport);
63681 + UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
63682 + UTCR3_TXE);
63684 + /*
63685 + * Now, do each character
63686 + */
63687 + for (i = 0; i < count; i++) {
63688 + do {
63689 + status = UART_GET_UTSR1(sport);
63690 + } while (!(status & UTSR1_TNF));
63691 + UART_PUT_CHAR(sport, s[i]);
63692 + if (s[i] == '\n') {
63693 + do {
63694 + status = UART_GET_UTSR1(sport);
63695 + } while (!(status & UTSR1_TNF));
63696 + UART_PUT_CHAR(sport, '\r');
63700 + /*
63701 + * Finally, wait for transmitter to become empty
63702 + * and restore UTCR3
63703 + */
63704 + do {
63705 + status = UART_GET_UTSR1(sport);
63706 + } while (status & UTSR1_TBY);
63707 + UART_PUT_UTCR3(sport, old_utcr3);
63710 +static kdev_t sa1100_console_device(struct console *co)
63712 + return MKDEV(SERIAL_SA1100_MAJOR, MINOR_START + co->index);
63716 + * If the port was already initialised (eg, by a boot loader), try to determine
63717 + * the current setup.
63718 + */
63719 +static void __init
63720 +sa1100_console_get_options(struct sa1100_port *sport, int *baud,
63721 + int *parity, int *bits)
63723 + unsigned int utcr3;
63725 + utcr3 = UART_GET_UTCR3(sport) & (UTCR3_RXE | UTCR3_TXE);
63726 + if (utcr3 == (UTCR3_RXE | UTCR3_TXE)) {
63727 + /* ok, the port was enabled */
63728 + unsigned int utcr0, quot;
63730 + utcr0 = UART_GET_UTCR0(sport);
63732 + *parity = 'n';
63733 + if (utcr0 & UTCR0_PE) {
63734 + if (utcr0 & UTCR0_OES)
63735 + *parity = 'e';
63736 + else
63737 + *parity = 'o';
63740 + if (utcr0 & UTCR0_DSS)
63741 + *bits = 8;
63742 + else
63743 + *bits = 7;
63745 + quot = UART_GET_UTCR2(sport) | UART_GET_UTCR1(sport) << 8;
63746 + quot &= 0xfff;
63747 + *baud = sport->port.uartclk / (16 * (quot + 1));
63751 +static int __init
63752 +sa1100_console_setup(struct console *co, char *options)
63754 + struct sa1100_port *sport;
63755 + int baud = CONFIG_SA1100_DEFAULT_BAUDRATE;
63756 + int bits = 8;
63757 + int parity = 'n';
63758 + int flow = 'n';
63760 + /*
63761 + * Check whether an invalid uart number has been specified, and
63762 + * if so, search for the first available port that does have
63763 + * console support.
63764 + */
63765 + if (co->index == -1 || co->index >= NR_PORTS)
63766 + co->index = 0;
63767 + sport = &sa1100_ports[co->index];
63769 + if (options)
63770 + uart_parse_options(options, &baud, &parity, &bits, &flow);
63771 + else
63772 + sa1100_console_get_options(sport, &baud, &parity, &bits);
63774 + return uart_set_options(&sport->port, co, baud, parity, bits, flow);
63777 +static struct console sa1100_console = {
63778 + .name = "ttySA",
63779 + .write = sa1100_console_write,
63780 + .device = sa1100_console_device,
63781 + .setup = sa1100_console_setup,
63782 + .flags = CON_PRINTBUFFER,
63783 + .index = -1,
63786 +void __init sa1100_rs_console_init(void)
63788 + sa1100_init_ports();
63789 + register_console(&sa1100_console);
63792 +#define SA1100_CONSOLE &sa1100_console
63793 +#else
63794 +#define SA1100_CONSOLE NULL
63795 +#endif
63797 +static struct uart_driver sa1100_reg = {
63798 + .owner = THIS_MODULE,
63799 + .normal_major = SERIAL_SA1100_MAJOR,
63800 +#ifdef CONFIG_DEVFS_FS
63801 + .normal_name = "ttySA%d",
63802 + .callout_name = "cusa%d",
63803 +#else
63804 + .normal_name = "ttySA",
63805 + .callout_name = "cusa",
63806 +#endif
63807 + .normal_driver = &normal,
63808 + .callout_major = CALLOUT_SA1100_MAJOR,
63809 + .callout_driver = &callout,
63810 + .table = sa1100_table,
63811 + .termios = sa1100_termios,
63812 + .termios_locked = sa1100_termios_locked,
63813 + .minor = MINOR_START,
63814 + .nr = NR_PORTS,
63815 + .cons = SA1100_CONSOLE,
63818 +static int __init sa1100_serial_init(void)
63820 + int i, ret;
63822 + sa1100_init_ports();
63824 + ret = uart_register_driver(&sa1100_reg);
63825 + if (ret)
63826 + return ret;
63828 + for (i = 0; i < NR_PORTS; i++)
63829 + uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
63831 + return 0;
63834 +static void __exit sa1100_serial_exit(void)
63836 + int i;
63838 + for (i = 0; i < NR_PORTS; i++)
63839 + uart_remove_one_port(&sa1100_reg, &sa1100_ports[i].port);
63841 + uart_unregister_driver(&sa1100_reg);
63844 +module_init(sa1100_serial_init);
63845 +module_exit(sa1100_serial_exit);
63847 +EXPORT_NO_SYMBOLS;
63849 +MODULE_AUTHOR("Deep Blue Solutions Ltd");
63850 +MODULE_DESCRIPTION("SA1100 generic serial port driver");
63851 +MODULE_LICENSE("GPL");
63852 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
63853 +++ linux-2.4.25/drivers/serial/uart00.c 2004-03-31 17:15:09.000000000 +0200
63854 @@ -0,0 +1,903 @@
63856 + * linux/drivers/serial/uart00.c
63858 + * Driver for UART00 serial ports
63860 + * Based on drivers/char/serial_amba.c, by ARM Limited &
63861 + * Deep Blue Solutions Ltd.
63862 + * Copyright 2001 Altera Corporation
63864 + * This program is free software; you can redistribute it and/or modify
63865 + * it under the terms of the GNU General Public License as published by
63866 + * the Free Software Foundation; either version 2 of the License, or
63867 + * (at your option) any later version.
63869 + * This program is distributed in the hope that it will be useful,
63870 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
63871 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63872 + * GNU General Public License for more details.
63874 + * You should have received a copy of the GNU General Public License
63875 + * along with this program; if not, write to the Free Software
63876 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
63878 + * $Id: uart00.c,v 1.3.2.5 2002/10/24 09:53:26 rmk Exp $
63880 + */
63881 +#include <linux/config.h>
63882 +#include <linux/module.h>
63884 +#include <linux/errno.h>
63885 +#include <linux/signal.h>
63886 +#include <linux/sched.h>
63887 +#include <linux/interrupt.h>
63888 +#include <linux/tty.h>
63889 +#include <linux/tty_flip.h>
63890 +#include <linux/major.h>
63891 +#include <linux/string.h>
63892 +#include <linux/fcntl.h>
63893 +#include <linux/ptrace.h>
63894 +#include <linux/ioport.h>
63895 +#include <linux/mm.h>
63896 +#include <linux/slab.h>
63897 +#include <linux/init.h>
63898 +#include <linux/circ_buf.h>
63899 +#include <linux/serial.h>
63900 +#include <linux/console.h>
63901 +#include <linux/sysrq.h>
63902 +#include <linux/pld/pld_hotswap.h>
63903 +#include <linux/proc_fs.h>
63905 +#include <asm/system.h>
63906 +#include <asm/io.h>
63907 +#include <asm/irq.h>
63908 +#include <asm/uaccess.h>
63909 +#include <asm/bitops.h>
63910 +#include <asm/sizes.h>
63912 +#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
63913 +#define SUPPORT_SYSRQ
63914 +#endif
63916 +#include <linux/serial_core.h>
63917 +#include <asm/arch/excalibur.h>
63918 +#define UART00_TYPE (volatile unsigned int*)
63919 +#include <asm/arch/uart00.h>
63920 +#include <asm/arch/int_ctrl00.h>
63922 +#undef DEBUG
63923 +#define UART_NR 2
63925 +#define SERIAL_UART00_NAME "ttyUA"
63926 +#define SERIAL_UART00_MAJOR 204
63927 +#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
63928 +#define SERIAL_UART00_NR UART_NR
63929 +#define UART_PORT_SIZE 0x50
63931 +#define CALLOUT_UART00_NAME "cuaua"
63932 +#define CALLOUT_UART00_MAJOR 205
63933 +#define CALLOUT_UART00_MINOR 16 /* Temporary - will change in future */
63934 +#define CALLOUT_UART00_NR UART_NR
63936 +static struct tty_driver normal, callout;
63937 +static struct tty_struct *uart00_table[UART_NR];
63938 +static struct termios *uart00_termios[UART_NR], *uart00_termios_locked[UART_NR];
63939 +static struct console uart00_console;
63940 +static struct uart_driver uart00_reg;
63943 +#define UART00_ISR_PASS_LIMIT 256
63946 + * Access macros for the UART00 UARTs
63947 + */
63948 +#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
63949 +#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
63950 +#define UART_GET_IES(p) inl(UART_IES((p)->membase))
63951 +#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
63952 +#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
63953 +#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
63954 +#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
63955 +#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
63956 +#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
63957 +#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
63958 +#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
63959 +#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
63960 +#define UART_GET_MC(p) inl(UART_MC((p)->membase))
63961 +#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
63962 +#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
63963 +#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
63964 +#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
63965 +#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
63966 +#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
63967 +#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
63968 +#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
63969 +//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
63971 +static void uart00_stop_tx(struct uart_port *port, u_int from_tty)
63974 + UART_PUT_IEC(port, UART_IEC_TIE_MSK);
63977 +static void uart00_stop_rx(struct uart_port *port)
63980 + UART_PUT_IEC(port, UART_IEC_RE_MSK);
63983 +static void uart00_enable_ms(struct uart_port *port)
63986 + UART_PUT_IES(port, UART_IES_ME_MSK);
63989 +static void
63990 +uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
63992 + struct uart_info *info = port->info;
63993 + struct tty_struct *tty = info->tty;
63994 + unsigned int status, ch, rds, flg, ignored = 0;
63997 + status = UART_GET_RSR(port);
63998 + while (UART_RX_DATA(status)) {
64000 + /*
64001 + * We need to read rds before reading the
64002 + * character from the fifo
64003 + */
64004 + rds = UART_GET_RDS(port);
64005 + ch = UART_GET_CHAR(port);
64006 + port->icount.rx++;
64008 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
64009 + goto ignore_char;
64011 + flg = TTY_NORMAL;
64013 + /*
64014 + * Note that the error handling code is
64015 + * out of the main execution path
64016 + */
64017 + if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|UART_RDS_PE_MSK))
64018 + goto handle_error;
64019 + if (uart_handle_sysrq_char(port, ch, regs))
64020 + goto ignore_char;
64022 + error_return:
64023 + *tty->flip.flag_buf_ptr++ = flg;
64024 + *tty->flip.char_buf_ptr++ = ch;
64025 + tty->flip.count++;
64026 + ignore_char:
64027 + status = UART_GET_RSR(port);
64029 +out:
64030 + tty_flip_buffer_push(tty);
64031 + return;
64033 +handle_error:
64034 + if (rds & UART_RDS_BI_MSK) {
64035 + status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
64036 + port->icount.brk++;
64038 +#ifdef SUPPORT_SYSRQ
64039 + if (uart_handle_break(port))
64040 + goto ignore_char;
64041 +#endif
64042 + } else if (rds & UART_RDS_PE_MSK)
64043 + port->icount.parity++;
64044 + else if (rds & UART_RDS_FE_MSK)
64045 + port->icount.frame++;
64046 + if (rds & UART_RDS_OE_MSK)
64047 + port->icount.overrun++;
64049 + if (rds & port->ignore_status_mask) {
64050 + if (++ignored > 100)
64051 + goto out;
64052 + goto ignore_char;
64054 + rds &= port->read_status_mask;
64056 + if (rds & UART_RDS_BI_MSK)
64057 + flg = TTY_BREAK;
64058 + else if (rds & UART_RDS_PE_MSK)
64059 + flg = TTY_PARITY;
64060 + else if (rds & UART_RDS_FE_MSK)
64061 + flg = TTY_FRAME;
64063 + if (rds & UART_RDS_OE_MSK) {
64064 + /*
64065 + * CHECK: does overrun affect the current character?
64066 + * ASSUMPTION: it does not.
64067 + */
64068 + *tty->flip.flag_buf_ptr++ = flg;
64069 + *tty->flip.char_buf_ptr++ = ch;
64070 + tty->flip.count++;
64071 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
64072 + goto ignore_char;
64073 + ch = 0;
64074 + flg = TTY_OVERRUN;
64076 +#ifdef SUPPORT_SYSRQ
64077 + port->sysrq = 0;
64078 +#endif
64079 + goto error_return;
64082 +static void uart00_tx_chars(struct uart_port *port)
64084 + int count;
64085 + struct uart_info *info = port->info;
64087 + if (port->x_char) {
64088 + while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
64089 + UART_PUT_CHAR(port, port->x_char);
64090 + port->icount.tx++;
64091 + port->x_char = 0;
64093 + return;
64095 + if (info->xmit.head == info->xmit.tail
64096 + || info->tty->stopped
64097 + || info->tty->hw_stopped) {
64098 + uart00_stop_tx(port, 0);
64099 + return;
64102 + count = port->fifosize >> 1;
64103 + do {
64104 + while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
64105 + UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
64106 + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
64107 + port->icount.tx++;
64108 + if (info->xmit.head == info->xmit.tail)
64109 + break;
64110 + } while (--count > 0);
64112 + if (CIRC_CNT(info->xmit.head,
64113 + info->xmit.tail,
64114 + UART_XMIT_SIZE) < WAKEUP_CHARS)
64115 + uart_write_wakeup(port);
64117 + if (info->xmit.head == info->xmit.tail)
64118 + uart00_stop_tx(port, 0);
64121 +static void uart00_start_tx(struct uart_port *port, u_int from_tty)
64123 + UART_PUT_IES(port,UART_IES_TIE_MSK );
64124 + uart00_tx_chars(port);
64127 +static void uart00_modem_status(struct uart_port *port)
64129 + unsigned int status;
64130 + struct uart_icount *icount = &port->icount;
64131 + struct uart_info *info = port->info;
64133 + status = UART_GET_MSR(port);
64135 + if (!status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
64136 + UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK))
64137 + return;
64139 + if (status & UART_MSR_DDCD_MSK) {
64140 + icount->dcd++;
64141 +#ifdef CONFIG_HARD_PPS
64142 + if ((port->flags & ASYNC_HARDPPS_CD) &&
64143 + (status & UART_MSR_DCD_MSK))
64144 + hardpps();
64145 +#endif
64146 + if (info->flags & ASYNC_CHECK_CD) {
64147 + if (status & UART_MSR_DCD_MSK)
64148 + wake_up_interruptible(&info->open_wait);
64149 + else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
64150 + (port->flags & ASYNC_CALLOUT_NOHUP))) {
64151 + if (info->tty)
64152 + tty_hangup(info->tty);
64157 + if (status & UART_MSR_DDSR_MSK)
64158 + icount->dsr++;
64160 + if (status & UART_MSR_DCTS_MSK) {
64161 + icount->cts++;
64163 + if (info->flags & ASYNC_CTS_FLOW) {
64164 + status &= UART_MSR_CTS_MSK;
64166 + if (info->tty->hw_stopped) {
64167 + if (status) {
64168 + info->tty->hw_stopped = 0;
64169 + port->ops->start_tx(port, 0);
64170 + uart_write_wakeup(port);
64172 + } else {
64173 + if (!status) {
64174 + info->tty->hw_stopped = 1;
64175 + port->ops->stop_tx(port, 0);
64180 + wake_up_interruptible(&info->delta_msr_wait);
64184 +static void uart00_int(int irq, void *dev_id, struct pt_regs *regs)
64186 + struct uart_port *port = dev_id;
64187 + unsigned int status, pass_counter = 0;
64189 + status = UART_GET_INT_STATUS(port);
64190 + do {
64192 + if (status & UART_ISR_RI_MSK)
64193 + uart00_rx_chars(port, regs);
64194 + if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
64195 + uart00_tx_chars(port);
64196 + if (status & UART_ISR_MI_MSK)
64197 + uart00_modem_status(port);
64198 + if (pass_counter++ > UART00_ISR_PASS_LIMIT)
64199 + break;
64201 + status = UART_GET_INT_STATUS(port);
64202 + } while (status);
64205 +static u_int uart00_tx_empty(struct uart_port *port)
64207 + return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
64210 +static u_int uart00_get_mctrl(struct uart_port *port)
64212 + unsigned int result = 0;
64213 + unsigned int status;
64215 + status = UART_GET_MSR(port);
64216 + if (status & UART_MSR_DCD_MSK)
64217 + result |= TIOCM_CAR;
64218 + if (status & UART_MSR_DSR_MSK)
64219 + result |= TIOCM_DSR;
64220 + if (status & UART_MSR_CTS_MSK)
64221 + result |= TIOCM_CTS;
64222 + if (status & UART_MCR_RI_MSK)
64223 + result |= TIOCM_RNG;
64225 + return result;
64228 +static void uart00_set_mctrl(struct uart_port *port, u_int mctrl)
64230 + unsigned char mcr = 0;
64232 + if (mctrl & TIOCM_RTS)
64233 + mcr |= UART_MCR_RTS_MSK;
64234 + if (mctrl & TIOCM_DTR)
64235 + mcr |= UART_MCR_DTR_MSK;
64236 + if (mctrl & TIOCM_LOOP)
64237 + mcr |= UART_MCR_LB_MSK;
64239 + UART_PUT_MCR(port, mcr);
64242 +static void uart00_break_ctl(struct uart_port *port, int break_state)
64244 + unsigned int mcr;
64246 + mcr = UART_GET_MCR(port);
64247 + if (break_state == -1)
64248 + mcr |= UART_MCR_BR_MSK;
64249 + else
64250 + mcr &= ~UART_MCR_BR_MSK;
64251 + UART_PUT_MCR(port, mcr);
64254 +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
64256 + u_int quot;
64258 + /* Special case: B0 rate */
64259 + if (!baud)
64260 + baud = 9600;
64262 + quot = (port->uartclk / (16 * baud)-1) ;
64264 + return quot;
64266 +static void uart00_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
64268 + u_int uart_mc=0, old_ies;
64269 + unsigned long flags;
64271 +#ifdef DEBUG
64272 + printk("uart00_set_cflag(0x%x) called\n", cflag);
64273 +#endif
64274 + /* byte size and parity */
64275 + switch (cflag & CSIZE) {
64276 + case CS5: uart_mc = UART_MC_CLS_CHARLEN_5; break;
64277 + case CS6: uart_mc = UART_MC_CLS_CHARLEN_6; break;
64278 + case CS7: uart_mc = UART_MC_CLS_CHARLEN_7; break;
64279 + default: uart_mc = UART_MC_CLS_CHARLEN_8; break; // CS8
64281 + if (cflag & CSTOPB)
64282 + uart_mc|= UART_MC_ST_TWO;
64283 + if (cflag & PARENB) {
64284 + uart_mc |= UART_MC_PE_MSK;
64285 + if (!(cflag & PARODD))
64286 + uart_mc |= UART_MC_EP_MSK;
64289 + port->read_status_mask = UART_RDS_OE_MSK;
64290 + if (iflag & INPCK)
64291 + port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
64292 + if (iflag & (BRKINT | PARMRK))
64293 + port->read_status_mask |= UART_RDS_BI_MSK;
64295 + /*
64296 + * Characters to ignore
64297 + */
64298 + port->ignore_status_mask = 0;
64299 + if (iflag & IGNPAR)
64300 + port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
64301 + if (iflag & IGNBRK) {
64302 + port->ignore_status_mask |= UART_RDS_BI_MSK;
64303 + /*
64304 + * If we're ignoring parity and break indicators,
64305 + * ignore overruns to (for real raw support).
64306 + */
64307 + if (iflag & IGNPAR)
64308 + port->ignore_status_mask |= UART_RDS_OE_MSK;
64311 + /* first, disable everything */
64312 + save_flags(flags); cli();
64313 + old_ies = UART_GET_IES(port);
64315 + if ((port->flags & ASYNC_HARDPPS_CD) ||
64316 + (cflag & CRTSCTS) || !(cflag & CLOCAL))
64317 + old_ies |= UART_IES_ME_MSK;
64320 + /* Set baud rate */
64321 + UART_PUT_DIV_LO(port, (quot & 0xff));
64322 + UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
64325 + UART_PUT_MC(port, uart_mc);
64326 + UART_PUT_IES(port, old_ies);
64328 + restore_flags(flags);
64331 +static int uart00_startup(struct uart_port *port)
64333 + int retval;
64335 + /*
64336 + * Allocate the IRQ
64337 + */
64338 + retval = request_irq(port->irq, uart00_int, 0, "uart00", port);
64339 + if (retval)
64340 + return retval;
64342 + /*
64343 + * Finally, enable interrupts. Use the TII interrupt to minimise
64344 + * the number of interrupts generated. If higher performance is
64345 + * needed, consider using the TI interrupt with a suitable FIFO
64346 + * threshold
64347 + */
64348 + UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
64350 + return 0;
64353 +static void uart00_shutdown(struct uart_port *port)
64355 + /*
64356 + * disable all interrupts, disable the port
64357 + */
64358 + UART_PUT_IEC(port, 0xff);
64360 + /* disable break condition and fifos */
64361 + UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
64363 + /*
64364 + * Free the interrupt
64365 + */
64366 + free_irq(port->irq, port);
64369 +static const char *uart00_type(struct uart_port *port)
64371 + return port->type == PORT_UART00 ? "Altera UART00" : NULL;
64375 + * Release the memory region(s) being used by 'port'
64376 + */
64377 +static void uart00_release_port(struct uart_port *port)
64379 + release_mem_region(port->mapbase, UART_PORT_SIZE);
64381 +#ifdef CONFIG_ARCH_CAMELOT
64382 + if(port->membase!=(void*)IO_ADDRESS(EXC_UART00_BASE)){
64383 + iounmap(port->membase);
64385 +#endif
64389 + * Request the memory region(s) being used by 'port'
64390 + */
64391 +static int uart00_request_port(struct uart_port *port)
64393 + int result;
64395 + result = request_mem_region(port->mapbase, UART_PORT_SIZE,
64396 + "serial_uart00") != NULL ? 0 : -EBUSY;
64397 + if (result)
64398 + return result;
64400 + port->membase = ioremap(port->mapbase, SZ_4K);
64401 + if (!port->membase) {
64402 + printk(KERN_ERR "serial00: cannot map io memory\n");
64403 + release_mem_region(port->mapbase, UART_PORT_SIZE);
64406 + return port->membase ? 0 : -ENOMEM;
64410 + * Configure/autoconfigure the port.
64411 + */
64412 +static void uart00_config_port(struct uart_port *port, int flags)
64414 + if (flags & UART_CONFIG_TYPE) {
64415 + if (uart00_request_port(port) == 0)
64416 + port->type = PORT_UART00;
64421 + * verify the new serial_struct (for TIOCSSERIAL).
64422 + */
64423 +static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
64425 + int ret = 0;
64426 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
64427 + ret = -EINVAL;
64428 + if (ser->irq < 0 || ser->irq >= NR_IRQS)
64429 + ret = -EINVAL;
64430 + if (ser->baud_base < 9600)
64431 + ret = -EINVAL;
64432 + return ret;
64435 +static struct uart_ops uart00_pops = {
64436 + tx_empty: uart00_tx_empty,
64437 + set_mctrl: uart00_set_mctrl,
64438 + get_mctrl: uart00_get_mctrl,
64439 + stop_tx: uart00_stop_tx,
64440 + start_tx: uart00_start_tx,
64441 + stop_rx: uart00_stop_rx,
64442 + enable_ms: uart00_enable_ms,
64443 + break_ctl: uart00_break_ctl,
64444 + startup: uart00_startup,
64445 + shutdown: uart00_shutdown,
64446 + change_speed: uart00_change_speed,
64447 + type: uart00_type,
64448 + release_port: uart00_release_port,
64449 + request_port: uart00_request_port,
64450 + config_port: uart00_config_port,
64451 + verify_port: uart00_verify_port,
64454 +static struct uart_port uart00_ports[UART_NR] = {
64456 +#ifdef CONFIG_ARCH_CAMELOT
64458 + .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
64459 + .mapbase = EXC_UART00_BASE,
64460 + .iotype = SERIAL_IO_MEM,
64461 + .irq = IRQ_UART,
64462 + .uartclk = EXC_AHB2_CLK_FREQUENCY,
64463 + .fifosize = 16,
64464 + .ops = &uart00_pops,
64465 + .flags = ASYNC_BOOT_AUTOCONF,
64467 +#endif
64470 +#ifdef CONFIG_SERIAL_UART00_CONSOLE
64471 +static void uart00_console_write(struct console *co, const char *s, unsigned count)
64473 +#ifdef CONFIG_ARCH_CAMELOT
64474 + struct uart_port *port = &uart00_ports[0];
64475 + unsigned int status, old_ies;
64476 + int i;
64478 + /*
64479 + * First save the CR then disable the interrupts
64480 + */
64481 + old_ies = UART_GET_IES(port);
64482 + UART_PUT_IEC(port,0xff);
64484 + /*
64485 + * Now, do each character
64486 + */
64487 + for (i = 0; i < count; i++) {
64488 + do {
64489 + status = UART_GET_TSR(port);
64490 + } while (!UART_TX_READY(status));
64491 + UART_PUT_CHAR(port, s[i]);
64492 + if (s[i] == '\n') {
64493 + do {
64494 + status = UART_GET_TSR(port);
64495 + } while (!UART_TX_READY(status));
64496 + UART_PUT_CHAR(port, '\r');
64500 + /*
64501 + * Finally, wait for transmitter to become empty
64502 + * and restore the IES
64503 + */
64504 + do {
64505 + status = UART_GET_TSR(port);
64506 + } while (status & UART_TSR_TX_LEVEL_MSK);
64507 + UART_PUT_IES(port, old_ies);
64508 +#endif
64511 +static kdev_t uart00_console_device(struct console *co)
64513 + return MKDEV(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index);
64516 +static void /*__init*/ uart00_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
64518 + u_int uart_mc, quot;
64519 + uart_mc= UART_GET_MC(port);
64521 + *parity = 'n';
64522 + if (uart_mc & UART_MC_PE_MSK) {
64523 + if (uart_mc & UART_MC_EP_MSK)
64524 + *parity = 'e';
64525 + else
64526 + *parity = 'o';
64529 + switch (uart_mc & UART_MC_CLS_MSK){
64531 + case UART_MC_CLS_CHARLEN_5:
64532 + *bits = 5;
64533 + break;
64534 + case UART_MC_CLS_CHARLEN_6:
64535 + *bits = 6;
64536 + break;
64537 + case UART_MC_CLS_CHARLEN_7:
64538 + *bits = 7;
64539 + break;
64540 + case UART_MC_CLS_CHARLEN_8:
64541 + *bits = 8;
64542 + break;
64544 + quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
64545 + *baud = port->uartclk / (16 *quot );
64548 +static int __init uart00_console_setup(struct console *co, char *options)
64550 + struct uart_port *port;
64551 + int baud = 38400;
64552 + int bits = 8;
64553 + int parity = 'n';
64554 + int flow= 'n';
64556 +#ifdef CONFIG_ARCH_CAMELOT
64557 + /*
64558 + * Check whether an invalid uart number has been specified, and
64559 + * if so, search for the first available port that does have
64560 + * console support.
64561 + */
64562 + port = &uart00_ports[0];
64563 + co->index = 0;
64564 +#else
64565 + return -ENODEV;
64566 +#endif
64568 + if (options)
64569 + uart_parse_options(options, &baud, &parity, &bits, &flow);
64570 + else
64571 + uart00_console_get_options(port, &baud, &parity, &bits);
64573 + return uart_set_options(port, co, baud, parity, bits, flow);
64576 +static struct console uart00_console = {
64577 + .name = SERIAL_UART00_NAME,
64578 + .write = uart00_console_write,
64579 + .device = uart00_console_device,
64580 + .setup = uart00_console_setup,
64581 + .flags = CON_PRINTBUFFER,
64582 + .index = 0,
64585 +void __init uart00_console_init(void)
64587 + register_console(&uart00_console);
64590 +#define UART00_CONSOLE &uart00_console
64591 +#else
64592 +#define UART00_CONSOLE NULL
64593 +#endif
64595 +static struct uart_driver uart00_reg = {
64596 + .owner = NULL,
64597 + .normal_major = SERIAL_UART00_MAJOR,
64598 + .normal_name = SERIAL_UART00_NAME,
64599 + .normal_driver = &normal,
64600 + .callout_major = CALLOUT_UART00_MAJOR,
64601 + .callout_name = CALLOUT_UART00_NAME,
64602 + .callout_driver = &callout,
64603 + .table = uart00_table,
64604 + .termios = uart00_termios,
64605 + .termios_locked = uart00_termios_locked,
64606 + .minor = SERIAL_UART00_MINOR,
64607 + .nr = UART_NR,
64608 + .state = NULL,
64609 + .cons = UART00_CONSOLE,
64612 +struct dev_port_entry{
64613 + struct uart_port *port;
64616 +static struct dev_port_entry dev_port_map[UART_NR];
64618 +#ifdef CONFIG_PLD_HOTSWAP
64620 + * Keep a mapping of dev_info addresses -> port lines to use when
64621 + * removing ports dev==NULL indicates unused entry
64622 + */
64624 +struct uart00_ps_data{
64625 + unsigned int clk;
64626 + unsigned int fifosize;
64629 +int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
64631 + struct uart00_ps_data* dev_ps=dev_ps_data;
64632 + struct uart_port * port;
64633 + int i,result;
64635 + i=0;
64636 + while(dev_port_map[i].port)
64637 + i++;
64639 + if(i==UART_NR){
64640 + printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
64641 + return 0;
64644 + port=&uart00_ports[i];
64646 + printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
64647 + port->membase=0;
64648 + port->mapbase=dev_info->base_addr;
64649 + port->iotype=SERIAL_IO_MEM;
64650 + port->irq=dev_info->irq;
64651 + port->uartclk=dev_ps->clk;
64652 + port->fifosize=dev_ps->fifosize;
64653 + port->ops=&uart00_pops;
64654 + port->line=i;
64655 + port->flags=ASYNC_BOOT_AUTOCONF;
64657 + result=uart_register_port(&uart00_reg, port);
64658 + if(result<0){
64659 + printk("uart_register_port returned %d\n",result);
64660 + return result;
64662 + dev_port_map[i].port=port;
64663 + printk("uart00: added device at %lx as ttyUA%d\n",dev_port_map[i].port->mapbase,i);
64664 + return 0;
64668 +int uart00_remove_devices(void)
64670 + int i,result;
64673 + result=0;
64674 + for(i=1;i<UART_NR;i++){
64675 + if(dev_port_map[i].port){
64676 + uart_unregister_port(&uart00_reg,i);
64677 + dev_port_map[i].port=NULL;
64680 + return 0;
64684 +#ifdef CONFIG_PROC_FS
64687 +int uart00_proc_read(char* buf,char** start,off_t offset,int count,int *eof,void *data){
64689 + int i,len=0;
64690 + struct uart_port *port;
64691 + int limit = count - 80;
64692 + char ps_data[80];
64693 + if(*start)
64694 + buf=*start;
64695 + for(i=0;(i<UART_NR)&&(len<limit);i++){
64696 + if(dev_port_map[i].port){
64697 + port=dev_port_map[i].port;
64698 + sprintf(ps_data,"clk, %dHz, fifo size, %dbytes",
64699 + port->uartclk,port->fifosize);
64700 + len+=PLDHS_READ_PROC_DATA(buf+len,"uart00",i,
64701 + port->mapbase,port->irq,ps_data);
64705 + *eof=1;
64706 + return len;
64711 +#endif
64712 +struct pld_hotswap_ops uart00_pldhs_ops={
64713 + .name = "uart00",
64714 + .add_device = uart00_add_device,
64715 + .remove_devices = uart00_remove_devices,
64716 + .proc_read = uart00_proc_read
64719 +#endif
64721 +static int __init uart00_init(void)
64723 + int ret;
64724 + int i;
64726 + ret = uart_register_driver(&uart00_reg);
64727 + if (ret) {
64728 + printk(KERN_ERR "uart00: Couldn't register driver\n");
64729 + return ret;
64732 + unregister_console(&uart00_console);
64734 + for(i=0;i<UART_NR;i++){
64735 + uart00_ports[i].ops=&uart00_pops;
64738 + printk(KERN_WARNING "uart00:Using temporary major/minor pairs - these WILL change in the future\n");
64740 +#ifdef CONFIG_PLD_HOTSWAP
64741 + pldhs_register_driver(&uart00_pldhs_ops);
64742 +#endif
64743 + for (i=0; i<UART_NR; i++)
64744 + uart_add_one_port(&uart00_reg,&uart00_ports[i]);
64746 + uart00_console.flags = 0;
64747 + register_console(&uart00_console);
64748 +#ifdef CONFIG_ARCH_CAMELOT
64749 + dev_port_map[0].port=uart00_ports;
64750 +#endif
64751 + return ret;
64755 +__initcall(uart00_init);
64758 --- linux-2.4.25/drivers/sound/.version~2.4.25-vrs2.patch
64759 +++ linux-2.4.25/drivers/sound/.version
64760 -3.8s
64761 -0x030804
64762 --- linux-2.4.25/drivers/sound/Config.in~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
64763 +++ linux-2.4.25/drivers/sound/Config.in 2004-03-31 17:15:09.000000000 +0200
64764 @@ -131,6 +131,17 @@
64765 dep_tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_PCI
64766 dep_mbool ' VIA 82C686 MIDI' CONFIG_MIDI_VIA82CXXX $CONFIG_SOUND_VIA82CXXX
64768 +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
64769 + dep_tristate ' StrongARM-11x0 Sound Drivers' CONFIG_SOUND_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_SOUND
64770 + dep_tristate ' UDA1341 Stereo Codec' CONFIG_SOUND_UDA1341 $CONFIG_L3 $CONFIG_SOUND_SA1100 $CONFIG_SOUND
64771 + dep_tristate ' Assabet audio support' CONFIG_SOUND_ASSABET_UDA1341 $CONFIG_SA1100_ASSABET $CONFIG_SOUND_UDA1341
64772 + dep_tristate ' Compaq iPAQ audio support' CONFIG_SOUND_H3600_UDA1341 $CONFIG_SA1100_H3600 $CONFIG_SOUND_UDA1341
64773 + dep_tristate ' Pangolin audio support' CONFIG_SOUND_PANGOLIN_UDA1341 $CONFIG_SA1100_PANGOLIN $CONFIG_SOUND_UDA1341
64774 + dep_tristate ' SA1111 audio support' CONFIG_SOUND_SA1111_UDA1341 $CONFIG_SA1111 $CONFIG_SOUND_UDA1341
64775 + dep_tristate ' SA1111 AC97 Sound' CONFIG_SOUND_SA1111_AC97 $CONFIG_SA1111 $CONFIG_SOUND_SA1100
64776 + dep_tristate ' Generic DAC on the SA11x0 SSP port' CONFIG_SOUND_SA1100SSP $CONFIG_SOUND_SA1100
64779 dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
64781 if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
64782 @@ -220,14 +231,14 @@
64783 bool ' Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
64789 - if [ "$CONFIG_ARM" = "y" ]; then
64790 - if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
64791 - dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
64792 - fi
64793 - dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
64794 +if [ "$CONFIG_ARM" = "y" ]; then
64795 + if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" -o "$CONFIG_ARCH_RISCSTATION" ]; then
64796 + dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
64799 + dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
64802 dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
64803 --- linux-2.4.25/drivers/sound/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
64804 +++ linux-2.4.25/drivers/sound/Makefile 2004-03-31 17:15:09.000000000 +0200
64805 @@ -10,7 +10,8 @@
64806 export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
64807 msnd.o opl3.o sb_common.o sequencer_syms.o \
64808 sound_core.o sound_syms.o uart401.o \
64809 - nm256_audio.o ac97.o ac97_codec.o aci.o
64810 + nm256_audio.o ac97.o ac97_codec.o aci.o \
64811 + sa1100-audio.o
64813 # Each configuration option enables a list of files.
64815 @@ -76,6 +77,14 @@
64816 obj-$(CONFIG_SOUND_FORTE) += forte.o ac97_codec.o
64817 obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
64818 obj-$(CONFIG_SOUND_HARMONY) += harmony.o
64819 +obj-$(CONFIG_SOUND_SA1100) += sa1100-audio.o
64820 +obj-$(CONFIG_SOUND_UDA1341) += uda1341.o
64821 +obj-$(CONFIG_SOUND_ASSABET_UDA1341) += assabet-uda1341.o
64822 +obj-$(CONFIG_SOUND_PANGOLIN_UDA1341) += pangolin-uda1341.o
64823 +obj-$(CONFIG_SOUND_H3600_UDA1341) += h3600-uda1341.o
64824 +obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o
64825 +obj-$(CONFIG_SOUND_SA1111_AC97) += sa1111-ac97.o ac97_codec.o
64826 +obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o
64827 obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
64828 obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
64829 obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
64830 @@ -105,7 +114,6 @@
64831 obj-y += dmasound/dmasound.o
64832 endif
64835 # Declare multi-part drivers.
64837 list-multi := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \
64838 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
64839 +++ linux-2.4.25/drivers/sound/assabet-uda1341.c 2004-03-31 17:15:09.000000000 +0200
64840 @@ -0,0 +1,404 @@
64842 + * Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.
64844 + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
64846 + * This program is free software; you can redistribute it and/or
64847 + * modify it under the terms of the GNU General Public License.
64849 + * This is the machine specific part of the Assabet/UDA1341 support.
64850 + * This driver makes use of the UDA1341 and the sa1100-audio modules.
64852 + * History:
64854 + * 2000-05-21 Nicolas Pitre Initial release.
64856 + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
64857 + * the former sa1100-uda1341.c driver.
64859 + * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
64861 + * 2001-08-03 Russell King Fix left/right channel swap.
64862 + * Attempt to reduce power consumption when idle.
64864 + * 2001-09-23 Russell King Remove old L3 bus driver.
64866 + * Please note that fiddling too much with MDREFR results in oopses, so we don't
64867 + * touch MDREFR unnecessarily, which means we don't touch it on close.
64868 + */
64870 +#include <linux/module.h>
64871 +#include <linux/init.h>
64872 +#include <linux/types.h>
64873 +#include <linux/fs.h>
64874 +#include <linux/delay.h>
64875 +#include <linux/pm.h>
64876 +#include <linux/errno.h>
64877 +#include <linux/sound.h>
64878 +#include <linux/soundcard.h>
64879 +#include <linux/cpufreq.h>
64880 +#include <linux/l3/l3.h>
64881 +#include <linux/l3/uda1341.h>
64883 +#include <asm/semaphore.h>
64884 +#include <asm/uaccess.h>
64885 +#include <asm/hardware.h>
64886 +#include <asm/dma.h>
64887 +#include <asm/arch/assabet.h>
64889 +#include "sa1100-audio.h"
64892 + * Define this to fix the power drain on early Assabets
64893 + */
64894 +#define FIX_POWER_DRAIN
64897 + * Debugging?
64898 + */
64899 +#undef DEBUG
64902 +#ifdef DEBUG
64903 +#define DPRINTK( x... ) printk( ##x )
64904 +#else
64905 +#define DPRINTK( x... )
64906 +#endif
64909 +#define AUDIO_RATE_DEFAULT 44100
64912 + * Mixer (UDA1341) interface
64913 + */
64915 +static struct l3_client uda1341;
64917 +static int
64918 +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
64920 + /*
64921 + * We only accept mixer (type 'M') ioctls.
64922 + */
64923 + if (_IOC_TYPE(cmd) != 'M')
64924 + return -EINVAL;
64926 + return l3_command(&uda1341, cmd, (void *)arg);
64929 +static struct file_operations assabet_mixer_fops = {
64930 + ioctl: mixer_ioctl,
64931 + owner: THIS_MODULE
64936 + * Audio interface
64937 + */
64938 +static long audio_samplerate = AUDIO_RATE_DEFAULT;
64941 + * FIXME: what about SFRM going high when SSP is disabled?
64942 + */
64943 +static void assabet_set_samplerate(long val)
64945 + struct uda1341_cfg cfg;
64946 + u_int clk_ref, clk_div;
64948 + /* We don't want to mess with clocks when frames are in flight */
64949 + Ser4SSCR0 &= ~SSCR0_SSE;
64950 + /* wait for any frame to complete */
64951 + udelay(125);
64953 + /*
64954 + * Our clock source is derived from the CPLD on which we don't have
64955 + * much control unfortunately. This was intended for a fixed 48000 Hz
64956 + * samplerate assuming a core clock of 221.2 MHz. The CPLD appears
64957 + * to divide the memory clock so there is a ratio of 4608 between
64958 + * the core clock and the resulting samplerate (obtained by
64959 + * measurements, the CPLD equations should confirm that).
64961 + * Still we can play with the SA1110's clock divisor for the SSP port
64962 + * to get half the samplerate as well.
64964 + * Apparently the clock sent to the SA1110 for the SSP port is further
64965 + * more divided from the clock sent to the UDA1341 (some people tried
64966 + * to be too clever in their design, or simply failed to read the
64967 + * SA1110 manual). If it was the same clock we would have been able
64968 + * to support a third samplerate with the UDA1341's 384FS mode.
64970 + * At least it would have been a minimum acceptable solution to be
64971 + * able to set the CPLD divisor by software. The iPAQ design is
64972 + * certainly a better example to follow for a new design.
64973 + */
64974 + clk_ref = cpufreq_get(0) * 1000 / 4608;
64975 + if (val > clk_ref*4/7) {
64976 + audio_samplerate = clk_ref;
64977 + cfg.fs = 256;
64978 + clk_div = SSCR0_SerClkDiv(2);
64979 + } else {
64980 + audio_samplerate = clk_ref/2;
64981 + cfg.fs = 512;
64982 + clk_div = SSCR0_SerClkDiv(4);
64985 + cfg.format = FMT_LSB16;
64986 + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
64988 + Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
64992 + * Initialise the Assabet audio driver.
64994 + * Note that we have to be careful with the order that we do things here;
64995 + * there is a D-type flip flop which is clocked from the SFRM line which
64996 + * indicates whether the same is for the left or right channel to the
64997 + * UDA1341.
64999 + * When you disable the SSP (by clearing SSCR0_SSE) it appears that the
65000 + * SFRM signal can float high. When you re-enable the SSP, you clock the
65001 + * flip flop once, and end up swapping the left and right channels.
65003 + * The ASSABET_BCR_CODEC_RST line will force this flip flop into a known
65004 + * state, but this line resets other devices as well!
65006 + * In addition to the above, it appears that powering down the UDA1341 on
65007 + * early Assabets leaves the UDA_WS actively driving a logic '1' into the
65008 + * chip, wasting power! (you can tell this by D11 being half-on). We
65009 + * attempt to correct this by kicking the flip flop on init/open/close.
65010 + * We should probably do this on PM resume as well.
65012 + * (Note the ordering of ASSABET_BCR_AUDIO_ON, SFRM and ASSABET_BCR_CODEC_RST
65013 + * is important).
65014 + */
65015 +static void assabet_audio_init(void *dummy)
65017 + unsigned long flags;
65018 + unsigned int mdrefr;
65020 + local_irq_save(flags);
65022 + /*
65023 + * Enable the power for the UDA1341 before driving any signals.
65024 + * We leave the audio amp (LM4880) disabled for now.
65025 + */
65026 + ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON);
65028 +#ifdef FIX_POWER_DRAIN
65029 + GPSR = GPIO_SSP_SFRM;
65030 + GPCR = GPIO_SSP_SFRM;
65031 +#endif
65033 + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
65034 + ASSABET_BCR_clear(ASSABET_BCR_STEREO_LB);
65036 + /*
65037 + * Setup the SSP uart.
65038 + */
65039 + PPAR |= PPAR_SPR;
65040 + Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
65041 + Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
65042 + GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK;
65043 + GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
65044 + GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
65045 + Ser4SSCR0 |= SSCR0_SSE;
65047 + /*
65048 + * Only give SFRM to the SSP after it has been enabled.
65049 + */
65050 + GAFR |= GPIO_SSP_SFRM;
65052 + /*
65053 + * The assabet board uses the SDRAM clock as the source clock for
65054 + * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
65055 + * At 206MHz we need to run the audio clock (SDRAM bank 2)
65056 + * at half speed. This clock will scale with core frequency so
65057 + * the audio sample rate will also scale. The CPLD on Assabet
65058 + * will need to be programmed to match the core frequency.
65059 + */
65060 + mdrefr = MDREFR;
65061 + if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
65062 + MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
65063 + mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
65064 + mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
65065 + MDREFR = mdrefr;
65066 + (void) MDREFR;
65068 + local_irq_restore(flags);
65070 + /* Wait for the UDA1341 to wake up */
65071 + mdelay(1);
65073 + l3_open(&uda1341);
65075 + assabet_set_samplerate(audio_samplerate);
65077 + /* Enable the audio power */
65078 + ASSABET_BCR_clear(ASSABET_BCR_QMUTE | ASSABET_BCR_SPK_OFF);
65082 + * Shutdown the Assabet audio driver.
65084 + * We have to be careful about the SFRM line here for the same reasons
65085 + * described in the initialisation comments above. This basically means
65086 + * that we must hand the SSP pins back to the GPIO module before disabling
65087 + * the SSP.
65089 + * In addition, to reduce power drain, we toggle the SFRM line once so
65090 + * that the UDA_WS line is at logic 0.
65092 + * We can't clear ASSABET_BCR_CODEC_RST without knowing if the UCB1300 or
65093 + * ADV7171 driver is still active. If it is, then we still need to play
65094 + * games, so we might as well leave ASSABET_BCR_CODEC_RST set.
65095 + */
65096 +static void assabet_audio_shutdown(void *dummy)
65098 + ASSABET_BCR_set(ASSABET_BCR_STEREO_LB | ASSABET_BCR_QMUTE |
65099 + ASSABET_BCR_SPK_OFF);
65101 + l3_close(&uda1341);
65103 + GAFR &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM);
65104 + Ser4SSCR0 = 0;
65106 +#ifdef FIX_POWER_DRAIN
65107 + GPSR = GPIO_SSP_SFRM;
65108 + GPCR = GPIO_SSP_SFRM;
65109 +#endif
65111 + /* disable the audio power */
65112 + ASSABET_BCR_clear(ASSABET_BCR_AUDIO_ON);
65115 +static int assabet_audio_ioctl( struct inode *inode, struct file *file,
65116 + uint cmd, ulong arg)
65118 + long val;
65119 + int ret = 0;
65121 + /*
65122 + * These are platform dependent ioctls which are not handled by the
65123 + * generic sa1100-audio module.
65124 + */
65125 + switch (cmd) {
65126 + case SNDCTL_DSP_STEREO:
65127 + ret = get_user(val, (int *) arg);
65128 + if (ret)
65129 + return ret;
65130 + /* the UDA1341 is stereo only */
65131 + ret = (val == 0) ? -EINVAL : 1;
65132 + return put_user(ret, (int *) arg);
65134 + case SNDCTL_DSP_CHANNELS:
65135 + case SOUND_PCM_READ_CHANNELS:
65136 + /* the UDA1341 is stereo only */
65137 + return put_user(2, (long *) arg);
65139 + case SNDCTL_DSP_SPEED:
65140 + ret = get_user(val, (long *) arg);
65141 + if (ret) break;
65142 + assabet_set_samplerate(val);
65143 + /* fall through */
65145 + case SOUND_PCM_READ_RATE:
65146 + return put_user(audio_samplerate, (long *) arg);
65148 + case SNDCTL_DSP_SETFMT:
65149 + case SNDCTL_DSP_GETFMTS:
65150 + /* we can do signed 16-bit only */
65151 + return put_user(AFMT_S16_LE, (long *) arg);
65153 + default:
65154 + /* Maybe this is meant for the mixer (As per OSS Docs) */
65155 + return mixer_ioctl(inode, file, cmd, arg);
65158 + return ret;
65161 +static audio_stream_t output_stream, input_stream;
65163 +static audio_state_t audio_state = {
65164 + output_stream: &output_stream,
65165 + output_dma: DMA_Ser4SSPWr,
65166 + output_id: "Assabet UDA1341 out",
65167 + input_stream: &input_stream,
65168 + input_dma: DMA_Ser4SSPRd,
65169 + input_id: "Assabet UDA1341 in",
65170 + need_tx_for_rx: 1,
65171 + hw_init: assabet_audio_init,
65172 + hw_shutdown: assabet_audio_shutdown,
65173 + client_ioctl: assabet_audio_ioctl,
65174 + sem: __MUTEX_INITIALIZER(audio_state.sem),
65177 +static int assabet_audio_open(struct inode *inode, struct file *file)
65179 + return sa1100_audio_attach(inode, file, &audio_state);
65183 + * Missing fields of this structure will be patched with the call
65184 + * to sa1100_audio_attach().
65185 + */
65186 +static struct file_operations assabet_audio_fops = {
65187 + open: assabet_audio_open,
65188 + owner: THIS_MODULE
65192 +static int audio_dev_id, mixer_dev_id;
65194 +static int __init assabet_uda1341_init(void)
65196 + int ret;
65198 + if (!machine_is_assabet())
65199 + return -ENODEV;
65201 + ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
65202 + if (ret)
65203 + goto out;
65205 + /* register devices */
65206 + audio_dev_id = register_sound_dsp(&assabet_audio_fops, -1);
65207 + mixer_dev_id = register_sound_mixer(&assabet_mixer_fops, -1);
65209 +#ifdef FIX_POWER_DRAIN
65211 + unsigned long flags;
65212 + local_irq_save(flags);
65213 + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
65214 + GPSR = GPIO_SSP_SFRM;
65215 + GPDR |= GPIO_SSP_SFRM;
65216 + GPCR = GPIO_SSP_SFRM;
65217 + local_irq_restore(flags);
65219 +#endif
65221 + printk(KERN_INFO "Sound: Assabet UDA1341: dsp id %d mixer id %d\n",
65222 + audio_dev_id, mixer_dev_id);
65223 + return 0;
65225 +release_l3:
65226 + l3_detach_client(&uda1341);
65227 +out:
65228 + return ret;
65231 +static void __exit assabet_uda1341_exit(void)
65233 + unregister_sound_dsp(audio_dev_id);
65234 + unregister_sound_mixer(mixer_dev_id);
65235 + l3_detach_client(&uda1341);
65238 +module_init(assabet_uda1341_init);
65239 +module_exit(assabet_uda1341_exit);
65241 +MODULE_AUTHOR("Nicolas Pitre");
65242 +MODULE_DESCRIPTION("Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.");
65244 +EXPORT_NO_SYMBOLS;
65245 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
65246 +++ linux-2.4.25/drivers/sound/h3600-uda1341.c 2004-03-31 17:15:09.000000000 +0200
65247 @@ -0,0 +1,352 @@
65249 + * Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.
65251 + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
65253 + * This program is free software; you can redistribute it and/or
65254 + * modify it under the terms of the GNU General Public License.
65256 + * This is the machine specific part of the Compaq iPAQ (aka Bitsy) support.
65257 + * This driver makes use of the UDA1341 and the sa1100-audio modules.
65259 + * History:
65261 + * 2000-05-21 Nicolas Pitre Initial UDA1341 driver release.
65263 + * 2000-07-?? George France Bitsy support.
65265 + * 2000-12-13 Deborah Wallach Fixed power handling for iPAQ/h3600
65267 + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
65268 + * the former sa1100-uda1341.c driver.
65270 + * 2001-07-13 Nicolas Pitre Fixes for all supported samplerates.
65272 + */
65274 +#include <linux/module.h>
65275 +#include <linux/init.h>
65276 +#include <linux/types.h>
65277 +#include <linux/fs.h>
65278 +#include <linux/delay.h>
65279 +#include <linux/pm.h>
65280 +#include <linux/errno.h>
65281 +#include <linux/sound.h>
65282 +#include <linux/soundcard.h>
65283 +#include <linux/l3/l3.h>
65284 +#include <linux/l3/uda1341.h>
65286 +#include <asm/semaphore.h>
65287 +#include <asm/uaccess.h>
65288 +#include <asm/hardware.h>
65289 +#include <asm/dma.h>
65290 +//#include <asm/arch/h3600_hal.h>
65292 +#include "sa1100-audio.h"
65295 +#undef DEBUG
65296 +#ifdef DEBUG
65297 +#define DPRINTK( x... ) printk( ##x )
65298 +#else
65299 +#define DPRINTK( x... )
65300 +#endif
65303 +#define AUDIO_NAME "Bitsy_UDA1341"
65305 +#define AUDIO_RATE_DEFAULT 44100
65308 +static struct l3_client uda1341;
65310 +static int
65311 +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
65313 + /*
65314 + * We only accept mixer (type 'M') ioctls.
65315 + */
65316 + if (_IOC_TYPE(cmd) != 'M')
65317 + return -EINVAL;
65319 + return l3_command(&uda1341, cmd, (void *)arg);
65322 +static struct file_operations h3600_mixer_fops = {
65323 + ioctl: mixer_ioctl,
65324 + owner: THIS_MODULE
65329 + * Audio interface
65330 + */
65332 +static long audio_samplerate = AUDIO_RATE_DEFAULT;
65335 + * Stop-gap solution until rest of hh.org HAL stuff is merged.
65336 + */
65337 +#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12)
65338 +#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13)
65339 +static void h3600_set_audio_clock(long val)
65341 + switch (val) {
65342 + case 24000: case 32000: case 48000: /* 00: 12.288 MHz */
65343 + GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
65344 + break;
65346 + case 22050: case 29400: case 44100: /* 01: 11.2896 MHz */
65347 + GPSR = GPIO_H3600_CLK_SET0;
65348 + GPCR = GPIO_H3600_CLK_SET1;
65349 + break;
65351 + case 8000: case 10666: case 16000: /* 10: 4.096 MHz */
65352 + GPCR = GPIO_H3600_CLK_SET0;
65353 + GPSR = GPIO_H3600_CLK_SET1;
65354 + break;
65356 + case 10985: case 14647: case 21970: /* 11: 5.6245 MHz */
65357 + GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
65358 + break;
65362 +static void h3600_set_samplerate(long val)
65364 + struct uda1341_cfg cfg;
65365 + int clk_div = 0;
65367 + /* We don't want to mess with clocks when frames are in flight */
65368 + Ser4SSCR0 &= ~SSCR0_SSE;
65369 + /* wait for any frame to complete */
65370 + udelay(125);
65372 + /*
65373 + * We have the following clock sources:
65374 + * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz
65375 + * Those can be divided either by 256, 384 or 512.
65376 + * This makes up 12 combinations for the following samplerates...
65377 + */
65378 + if (val >= 48000)
65379 + val = 48000;
65380 + else if (val >= 44100)
65381 + val = 44100;
65382 + else if (val >= 32000)
65383 + val = 32000;
65384 + else if (val >= 29400)
65385 + val = 29400;
65386 + else if (val >= 24000)
65387 + val = 24000;
65388 + else if (val >= 22050)
65389 + val = 22050;
65390 + else if (val >= 21970)
65391 + val = 21970;
65392 + else if (val >= 16000)
65393 + val = 16000;
65394 + else if (val >= 14647)
65395 + val = 14647;
65396 + else if (val >= 10985)
65397 + val = 10985;
65398 + else if (val >= 10666)
65399 + val = 10666;
65400 + else
65401 + val = 8000;
65403 + /* Set the external clock generator */
65404 + h3600_set_audio_clock(val);
65406 + /* Select the clock divisor */
65407 + switch (val) {
65408 + case 8000:
65409 + case 10985:
65410 + case 22050:
65411 + case 24000:
65412 + cfg.fs = 512;
65413 + clk_div = SSCR0_SerClkDiv(16);
65414 + break;
65415 + case 16000:
65416 + case 21970:
65417 + case 44100:
65418 + case 48000:
65419 + cfg.fs = 256;
65420 + clk_div = SSCR0_SerClkDiv(8);
65421 + break;
65422 + case 10666:
65423 + case 14647:
65424 + case 29400:
65425 + case 32000:
65426 + cfg.fs = 384;
65427 + clk_div = SSCR0_SerClkDiv(12);
65428 + break;
65431 + cfg.format = FMT_LSB16;
65432 + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
65433 + Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
65434 + audio_samplerate = val;
65437 +static void h3600_audio_init(void *dummy)
65439 + unsigned long flags;
65441 + /* Setup the uarts */
65442 + local_irq_save(flags);
65443 + GAFR |= (GPIO_SSP_CLK);
65444 + GPDR &= ~(GPIO_SSP_CLK);
65445 + Ser4SSCR0 = 0;
65446 + Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);
65447 + Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
65448 + Ser4SSCR0 |= SSCR0_SSE;
65450 + /* Enable the audio power */
65452 + clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
65453 + set_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
65454 + set_h3600_egpio(IPAQ_EGPIO_QMUTE);
65455 + local_irq_restore(flags);
65457 + /* external clock configuration */
65458 + h3600_set_samplerate(audio_samplerate);
65460 + /* Wait for the UDA1341 to wake up */
65461 + set_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
65462 + mdelay(1);
65464 + /* make the left and right channels unswapped (flip the WS latch ) */
65465 + Ser4SSDR = 0;
65467 + /* Initialize the UDA1341 internal state */
65468 + l3_open(&uda1341);
65470 + clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
65473 +static void h3600_audio_shutdown(void *dummy)
65475 + /* disable the audio power and all signals leading to the audio chip */
65476 + l3_close(&uda1341);
65477 + Ser4SSCR0 = 0;
65478 + clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
65479 + clr_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
65480 + clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
65483 +static int h3600_audio_ioctl(struct inode *inode, struct file *file,
65484 + uint cmd, ulong arg)
65486 + long val;
65487 + int ret = 0;
65489 + /*
65490 + * These are platform dependent ioctls which are not handled by the
65491 + * generic sa1100-audio module.
65492 + */
65493 + switch (cmd) {
65494 + case SNDCTL_DSP_STEREO:
65495 + ret = get_user(val, (int *) arg);
65496 + if (ret)
65497 + return ret;
65498 + /* the UDA1341 is stereo only */
65499 + ret = (val == 0) ? -EINVAL : 1;
65500 + return put_user(ret, (int *) arg);
65502 + case SNDCTL_DSP_CHANNELS:
65503 + case SOUND_PCM_READ_CHANNELS:
65504 + /* the UDA1341 is stereo only */
65505 + return put_user(2, (long *) arg);
65507 + case SNDCTL_DSP_SPEED:
65508 + ret = get_user(val, (long *) arg);
65509 + if (ret) break;
65510 + h3600_set_samplerate(val);
65511 + /* fall through */
65513 + case SOUND_PCM_READ_RATE:
65514 + return put_user(audio_samplerate, (long *) arg);
65516 + case SNDCTL_DSP_SETFMT:
65517 + case SNDCTL_DSP_GETFMTS:
65518 + /* we can do 16-bit only */
65519 + return put_user(AFMT_S16_LE, (long *) arg);
65521 + default:
65522 + /* Maybe this is meant for the mixer (As per OSS Docs) */
65523 + return mixer_ioctl(inode, file, cmd, arg);
65526 + return ret;
65529 +static audio_stream_t output_stream, input_stream;
65531 +static audio_state_t audio_state = {
65532 + output_stream: &output_stream,
65533 + output_dma: DMA_Ser4SSPWr,
65534 + output_id: "UDA1341 out",
65535 + input_stream: &input_stream,
65536 + input_dma: DMA_Ser4SSPRd,
65537 + input_id: "UDA1341 in",
65538 + need_tx_for_rx: 1,
65539 + hw_init: h3600_audio_init,
65540 + hw_shutdown: h3600_audio_shutdown,
65541 + client_ioctl: h3600_audio_ioctl,
65542 + sem: __MUTEX_INITIALIZER(audio_state.sem),
65545 +static int h3600_audio_open(struct inode *inode, struct file *file)
65547 + return sa1100_audio_attach(inode, file, &audio_state);
65551 + * Missing fields of this structure will be patched with the call
65552 + * to sa1100_audio_attach().
65553 + */
65554 +static struct file_operations h3600_audio_fops = {
65555 + open: h3600_audio_open,
65556 + owner: THIS_MODULE
65560 +static int audio_dev_id, mixer_dev_id;
65562 +static int __init h3600_uda1341_init(void)
65564 + int ret;
65566 + if (!machine_is_h3xxx())
65567 + return -ENODEV;
65569 + ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
65570 + if (ret)
65571 + goto out;
65573 + /* register devices */
65574 + audio_dev_id = register_sound_dsp(&h3600_audio_fops, -1);
65575 + mixer_dev_id = register_sound_mixer(&h3600_mixer_fops, -1);
65577 + printk( KERN_INFO "iPAQ audio support initialized\n" );
65578 + return 0;
65580 +release_l3:
65581 + l3_detach_client(&uda1341);
65582 +out:
65583 + return ret;
65586 +static void __exit h3600_uda1341_exit(void)
65588 + unregister_sound_dsp(audio_dev_id);
65589 + unregister_sound_mixer(mixer_dev_id);
65590 + l3_detach_client(&uda1341);
65593 +module_init(h3600_uda1341_init);
65594 +module_exit(h3600_uda1341_exit);
65596 +MODULE_AUTHOR("Nicolas Pitre, George France");
65597 +MODULE_DESCRIPTION("Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.");
65599 +EXPORT_NO_SYMBOLS;
65600 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
65601 +++ linux-2.4.25/drivers/sound/pangolin-uda1341.c 2004-03-31 17:15:09.000000000 +0200
65602 @@ -0,0 +1,322 @@
65604 + * Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.
65606 + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
65608 + * This program is free software; you can redistribute it and/or
65609 + * modify it under the terms of the GNU General Public License.
65611 + * This is the machine specific part of the Pangolin/UDA1341 support.
65612 + * This driver makes use of the UDA1341 and the sa1100-audio modules.
65614 + * History:
65616 + * 2000-05-21 Nicolas Pitre Initial release.
65618 + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
65619 + * the former sa1100-uda1341.c driver.
65621 + * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
65623 + * 2001-08-06 Richard Fan Pangolin Support
65625 + * 2001-09-23 Russell King Update inline with Assabet driver
65626 + * Remove old L3 bus driver
65628 + * Note: this should probably be merged with the Assabet audio driver,
65629 + * and become the "SDRAM-clock driven" SA1100 audio driver.
65630 + */
65632 +#include <linux/module.h>
65633 +#include <linux/init.h>
65634 +#include <linux/types.h>
65635 +#include <linux/fs.h>
65636 +#include <linux/delay.h>
65637 +#include <linux/pm.h>
65638 +#include <linux/errno.h>
65639 +#include <linux/sound.h>
65640 +#include <linux/soundcard.h>
65641 +#include <linux/l3/l3.h>
65642 +#include <linux/l3/uda1341.h>
65644 +#include <asm/semaphore.h>
65645 +#include <asm/uaccess.h>
65646 +#include <asm/hardware.h>
65647 +#include <asm/dma.h>
65649 +#include "sa1100-audio.h"
65652 + * Debugging?
65653 + */
65654 +#undef DEBUG
65657 +#ifdef DEBUG
65658 +#define DPRINTK( x... ) printk( ##x )
65659 +#else
65660 +#define DPRINTK( x... )
65661 +#endif
65664 +#define AUDIO_RATE_DEFAULT 44100
65666 +#define QmutePin GPIO_GPIO(4)
65667 +#define SpeakerOffPin GPIO_GPIO(5)
65670 + * Mixer (UDA1341) interface
65671 + */
65673 +static struct l3_client uda1341;
65675 +static int
65676 +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
65678 + /*
65679 + * We only accept mixer (type 'M') ioctls.
65680 + */
65681 + if (_IOC_TYPE(cmd) != 'M')
65682 + return -EINVAL;
65684 + return l3_command(&uda1341, cmd, (void *)arg);
65687 +static struct file_operations pangolin_mixer_fops = {
65688 + ioctl: mixer_ioctl,
65689 + owner: THIS_MODULE
65694 + * Audio interface
65695 + */
65696 +static long audio_samplerate = AUDIO_RATE_DEFAULT;
65698 +static void pangolin_set_samplerate(long val)
65700 + struct uda1341_cfg cfg;
65701 + int clk_div;
65703 + /* We don't want to mess with clocks when frames are in flight */
65704 + Ser4SSCR0 &= ~SSCR0_SSE;
65705 + /* wait for any frame to complete */
65706 + udelay(125);
65708 + /*
65709 + * Our clock source is derived from the CPLD on which we don't have
65710 + * much control unfortunately. This was intended for a fixed 44100Hz
65711 + * samplerate assuming a core clock of 206 MHz. Still we can play
65712 + * with the SA1110's clock divisor for the SSP port to get a 22050Hz
65713 + * samplerate.
65715 + * Apparently the clock sent to the SA1110 for the SSP port is
65716 + * divided from the clock sent to the UDA1341 (some people tried to
65717 + * be too clever in their design, or simply failed to read the SA1110
65718 + * manual). If it was the same source we would have been able to
65719 + * support a third samplerate.
65721 + * At least it would have been a minimum acceptable solution to be
65722 + * able to set the CPLD divisor by software. The iPAQ design is
65723 + * certainly a better example to follow for a new design.
65724 + */
65725 + if (val >= 44100) {
65726 + audio_samplerate = 44100;
65727 + cfg.fs = 256;
65728 + clk_div = SSCR0_SerClkDiv(2);
65729 + } else {
65730 + audio_samplerate = 22050;
65731 + cfg.fs = 512;
65732 + clk_div = SSCR0_SerClkDiv(4);
65735 + cfg.format = FMT_LSB16;
65736 + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
65738 + Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
65741 +static void pangolin_audio_init(void *dummy)
65743 + unsigned long flags;
65744 + unsigned int mdrefr;
65746 + local_irq_save(flags);
65748 + /*
65749 + * Setup the SSP uart.
65750 + */
65751 + PPAR |= PPAR_SPR;
65752 + Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
65753 + Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
65754 + GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK |
65755 + GPIO_SSP_SFRM;
65756 + GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
65757 + GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
65758 + Ser4SSCR0 |= SSCR0_SSE;
65760 + GAFR &= ~(SpeakerOffPin | QmutePin);
65761 + GPDR |= (SpeakerOffPin | QmutePin);
65762 + GPCR = SpeakerOffPin;
65764 + /*
65765 + * The assabet board uses the SDRAM clock as the source clock for
65766 + * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
65767 + * At 206MHz we need to run the audio clock (SDRAM bank 2)
65768 + * at half speed. This clock will scale with core frequency so
65769 + * the audio sample rate will also scale. The CPLD on Assabet
65770 + * will need to be programmed to match the core frequency.
65771 + */
65772 + mdrefr = MDREFR;
65773 + if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
65774 + MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
65775 + mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
65776 + mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
65777 + MDREFR = mdrefr;
65778 + (void) MDREFR;
65780 + local_irq_restore(flags);
65782 + /* Wait for the UDA1341 to wake up */
65783 + mdelay(100);
65785 + l3_open(&uda1341);
65787 + pangolin_set_samplerate(audio_samplerate);
65789 + GPCR = QmutePin;
65792 +static void pangolin_audio_shutdown(void *dummy)
65794 + GPSR = QmutePin;
65796 + l3_close(&uda1341);
65798 + Ser4SSCR0 = 0;
65799 + MDREFR &= ~(MDREFR_K2DB2 | MDREFR_K2RUN);
65802 +static int pangolin_audio_ioctl( struct inode *inode, struct file *file,
65803 + uint cmd, ulong arg)
65805 + long val;
65806 + int ret = 0;
65808 + /*
65809 + * These are platform dependent ioctls which are not handled by the
65810 + * generic sa1100-audio module.
65811 + */
65812 + switch (cmd) {
65813 + case SNDCTL_DSP_STEREO:
65814 + ret = get_user(val, (int *) arg);
65815 + if (ret)
65816 + return ret;
65817 + /* the UDA1341 is stereo only */
65818 + ret = (val == 0) ? -EINVAL : 1;
65819 + return put_user(ret, (int *) arg);
65821 + case SNDCTL_DSP_CHANNELS:
65822 + case SOUND_PCM_READ_CHANNELS:
65823 + /* the UDA1341 is stereo only */
65824 + return put_user(2, (long *) arg);
65826 + case SNDCTL_DSP_SPEED:
65827 + ret = get_user(val, (long *) arg);
65828 + if (ret) break;
65829 + pangolin_set_samplerate(val);
65830 + /* fall through */
65832 + case SOUND_PCM_READ_RATE:
65833 + return put_user(audio_samplerate, (long *) arg);
65835 + case SNDCTL_DSP_SETFMT:
65836 + case SNDCTL_DSP_GETFMTS:
65837 + /* we can do signed 16-bit only */
65838 + return put_user(AFMT_S16_LE, (long *) arg);
65840 + default:
65841 + /* Maybe this is meant for the mixer (As per OSS Docs) */
65842 + return mixer_ioctl(inode, file, cmd, arg);
65845 + return ret;
65848 +static audio_stream_t output_stream, input_stream;
65850 +static audio_state_t audio_state = {
65851 + output_stream: &output_stream,
65852 + output_dma: DMA_Ser4SSPWr,
65853 + output_id: "Pangolin UDA1341 out",
65854 + input_stream: &input_stream,
65855 + input_dma: DMA_Ser4SSPRd,
65856 + input_id: "Pangolin UDA1341 in",
65857 + need_tx_for_rx: 1,
65858 + hw_init: pangolin_audio_init,
65859 + hw_shutdown: pangolin_audio_shutdown,
65860 + client_ioctl: pangolin_audio_ioctl,
65861 + sem: __MUTEX_INITIALIZER(audio_state.sem),
65864 +static int pangolin_audio_open(struct inode *inode, struct file *file)
65866 + return sa1100_audio_attach(inode, file, &audio_state);
65870 + * Missing fields of this structure will be patched with the call
65871 + * to sa1100_audio_attach().
65872 + */
65873 +static struct file_operations pangolin_audio_fops = {
65874 + open: pangolin_audio_open,
65875 + owner: THIS_MODULE
65879 +static int audio_dev_id, mixer_dev_id;
65881 +static int __init pangolin_uda1341_init(void)
65883 + unsigned long flags;
65884 + int ret;
65886 + if (!machine_is_pangolin())
65887 + return -ENODEV;
65889 + ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
65890 + if (ret)
65891 + goto out;
65893 + /* register devices */
65894 + audio_dev_id = register_sound_dsp(&pangolin_audio_fops, -1);
65895 + mixer_dev_id = register_sound_mixer(&pangolin_mixer_fops, -1);
65897 + local_irq_save(flags);
65898 + GAFR &= ~(SpeakerOffPin | QmutePin);
65899 + GPDR |= (SpeakerOffPin | QmutePin);
65900 + local_irq_restore(flags);
65902 + printk(KERN_INFO "Pangolin UDA1341 audio driver initialized\n");
65903 + return 0;
65905 +release_l3:
65906 + l3_detach_client(&uda1341);
65907 +out:
65908 + return ret;
65911 +static void __exit pangolin_uda1341_exit(void)
65913 + unregister_sound_dsp(audio_dev_id);
65914 + unregister_sound_mixer(mixer_dev_id);
65915 + l3_detach_client(&uda1341);
65918 +module_init(pangolin_uda1341_init);
65919 +module_exit(pangolin_uda1341_exit);
65921 +MODULE_AUTHOR("Nicolas Pitre");
65922 +MODULE_DESCRIPTION("Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.");
65924 +EXPORT_NO_SYMBOLS;
65925 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
65926 +++ linux-2.4.25/drivers/sound/sa1100-audio.c 2004-03-31 17:15:09.000000000 +0200
65927 @@ -0,0 +1,976 @@
65929 + * Common audio handling for the SA11x0 processor
65931 + * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
65933 + * This program is free software; you can redistribute it and/or
65934 + * modify it under the terms of the GNU General Public License.
65937 + * This module handles the generic buffering/DMA/mmap audio interface for
65938 + * codecs connected to the SA1100 chip. All features depending on specific
65939 + * hardware implementations like supported audio formats or samplerates are
65940 + * relegated to separate specific modules.
65943 + * History:
65945 + * 2000-05-21 Nicolas Pitre Initial release.
65947 + * 2000-06-10 Erik Bunce Add initial poll support.
65949 + * 2000-08-22 Nicolas Pitre Removed all DMA stuff. Now using the
65950 + * generic SA1100 DMA interface.
65952 + * 2000-11-30 Nicolas Pitre - Validation of opened instances;
65953 + * - Power handling at open/release time instead
65954 + * of driver load/unload;
65956 + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
65957 + * the former sa1100-uda1341.c driver.
65959 + * 2001-07-22 Nicolas Pitre - added mmap() and realtime support
65960 + * - corrected many details to better comply
65961 + * with the OSS API
65963 + * 2001-10-19 Nicolas Pitre - brought DMA registration processing
65964 + * into this module for better ressource
65965 + * management. This also fixes a bug
65966 + * with the suspend/resume logic.
65967 + */
65969 +#include <linux/module.h>
65970 +#include <linux/init.h>
65971 +#include <linux/types.h>
65972 +#include <linux/fs.h>
65973 +#include <linux/mm.h>
65974 +#include <linux/slab.h>
65975 +#include <linux/sched.h>
65976 +#include <linux/poll.h>
65977 +#include <linux/pm.h>
65978 +#include <linux/errno.h>
65979 +#include <linux/sound.h>
65980 +#include <linux/soundcard.h>
65981 +#include <linux/sysrq.h>
65983 +#include <asm/uaccess.h>
65984 +#include <asm/io.h>
65985 +#include <asm/hardware.h>
65986 +#include <asm/semaphore.h>
65987 +#include <asm/dma.h>
65989 +#include "sa1100-audio.h"
65992 +#undef DEBUG
65993 +/* #define DEBUG 1 */
65994 +#ifdef DEBUG
65995 +#define DPRINTK( x... ) printk( ##x )
65996 +#else
65997 +#define DPRINTK( x... )
65998 +#endif
66001 +#define AUDIO_NAME "sa1100-audio"
66002 +#define AUDIO_NBFRAGS_DEFAULT 8
66003 +#define AUDIO_FRAGSIZE_DEFAULT 8192
66005 +#define NEXT_BUF(_s_,_b_) { \
66006 + (_s_)->_b_##_idx++; \
66007 + (_s_)->_b_##_idx %= (_s_)->nbfrags; \
66008 + (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; }
66010 +#define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref)
66013 + * This function frees all buffers
66014 + */
66016 +static void audio_clear_buf(audio_stream_t * s)
66018 + DPRINTK("audio_clear_buf\n");
66020 + /* ensure DMA won't run anymore */
66021 + s->active = 0;
66022 + s->stopped = 0;
66023 + sa1100_dma_flush_all(s->dma_ch);
66025 + if (s->buffers) {
66026 + int frag;
66027 + for (frag = 0; frag < s->nbfrags; frag++) {
66028 + if (!s->buffers[frag].master)
66029 + continue;
66030 + consistent_free(s->buffers[frag].start,
66031 + s->buffers[frag].master,
66032 + s->buffers[frag].dma_addr);
66034 + kfree(s->buffers);
66035 + s->buffers = NULL;
66038 + s->buf_idx = 0;
66039 + s->buf = NULL;
66044 + * This function allocates the buffer structure array and buffer data space
66045 + * according to the current number of fragments and fragment size.
66046 + */
66048 +static int audio_setup_buf(audio_stream_t * s)
66050 + int frag;
66051 + int dmasize = 0;
66052 + char *dmabuf = NULL;
66053 + dma_addr_t dmaphys = 0;
66055 + if (s->buffers)
66056 + return -EBUSY;
66058 + s->buffers = (audio_buf_t *)
66059 + kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
66060 + if (!s->buffers)
66061 + goto err;
66062 + memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
66064 + for (frag = 0; frag < s->nbfrags; frag++) {
66065 + audio_buf_t *b = &s->buffers[frag];
66067 + /*
66068 + * Let's allocate non-cached memory for DMA buffers.
66069 + * We try to allocate all memory at once.
66070 + * If this fails (a common reason is memory fragmentation),
66071 + * then we allocate more smaller buffers.
66072 + */
66073 + if (!dmasize) {
66074 + dmasize = (s->nbfrags - frag) * s->fragsize;
66075 + do {
66076 + dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
66077 + dmasize,
66078 + &dmaphys);
66079 + if (!dmabuf)
66080 + dmasize -= s->fragsize;
66081 + } while (!dmabuf && dmasize);
66082 + if (!dmabuf)
66083 + goto err;
66084 + b->master = dmasize;
66085 + memzero(dmabuf, dmasize);
66088 + b->start = dmabuf;
66089 + b->dma_addr = dmaphys;
66090 + b->stream = s;
66091 + sema_init(&b->sem, 1);
66092 + DPRINTK("buf %d: start %p dma %p\n", frag, b->start,
66093 + b->dma_addr);
66095 + dmabuf += s->fragsize;
66096 + dmaphys += s->fragsize;
66097 + dmasize -= s->fragsize;
66100 + s->buf_idx = 0;
66101 + s->buf = &s->buffers[0];
66102 + s->bytecount = 0;
66103 + s->getptrCount = 0;
66104 + s->fragcount = 0;
66106 + return 0;
66108 +err:
66109 + printk(AUDIO_NAME ": unable to allocate audio memory\n ");
66110 + audio_clear_buf(s);
66111 + return -ENOMEM;
66116 + * This function yanks all buffers from the DMA code's control and
66117 + * resets them ready to be used again.
66118 + */
66120 +static void audio_reset_buf(audio_stream_t * s)
66122 + int frag;
66124 + s->active = 0;
66125 + s->stopped = 0;
66126 + sa1100_dma_flush_all(s->dma_ch);
66127 + if (s->buffers) {
66128 + for (frag = 0; frag < s->nbfrags; frag++) {
66129 + audio_buf_t *b = &s->buffers[frag];
66130 + b->size = 0;
66131 + sema_init(&b->sem, 1);
66134 + s->bytecount = 0;
66135 + s->getptrCount = 0;
66136 + s->fragcount = 0;
66141 + * DMA callback functions
66142 + */
66144 +static void audio_dmaout_done_callback(void *buf_id, int size)
66146 + audio_buf_t *b = (audio_buf_t *) buf_id;
66147 + audio_stream_t *s = b->stream;
66149 + /* Accounting */
66150 + s->bytecount += size;
66151 + s->fragcount++;
66153 + /* Recycle buffer */
66154 + if (s->mapped)
66155 + sa1100_dma_queue_buffer(s->dma_ch, buf_id,
66156 + b->dma_addr, s->fragsize);
66157 + else
66158 + up(&b->sem);
66160 + /* And any process polling on write. */
66161 + wake_up(&s->wq);
66164 +static void audio_dmain_done_callback(void *buf_id, int size)
66166 + audio_buf_t *b = (audio_buf_t *) buf_id;
66167 + audio_stream_t *s = b->stream;
66169 + /* Accounting */
66170 + s->bytecount += size;
66171 + s->fragcount++;
66173 + /* Recycle buffer */
66174 + if (s->mapped) {
66175 + sa1100_dma_queue_buffer(s->dma_ch, buf_id,
66176 + b->dma_addr, s->fragsize);
66177 + } else {
66178 + b->size = size;
66179 + up(&b->sem);
66182 + /* And any process polling on write. */
66183 + wake_up(&s->wq);
66186 +static int audio_sync(struct file *file)
66188 + audio_state_t *state = (audio_state_t *)file->private_data;
66189 + audio_stream_t *s = state->output_stream;
66190 + audio_buf_t *b;
66192 + DPRINTK("audio_sync\n");
66194 + if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
66195 + return 0;
66197 + /*
66198 + * Send current buffer if it contains data. Be sure to send
66199 + * a full sample count.
66200 + */
66201 + b = s->buf;
66202 + if (b->size &= ~3) {
66203 + down(&b->sem);
66204 + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
66205 + b->dma_addr, b->size);
66206 + b->size = 0;
66207 + NEXT_BUF(s, buf);
66210 + /*
66211 + * Let's wait for the last buffer we sent i.e. the one before the
66212 + * current buf_idx. When we acquire the semaphore, this means either:
66213 + * - DMA on the buffer completed or
66214 + * - the buffer was already free thus nothing else to sync.
66215 + */
66216 + b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags);
66217 + if (down_interruptible(&b->sem))
66218 + return -EINTR;
66219 + up(&b->sem);
66220 + return 0;
66224 +static int audio_write(struct file *file, const char *buffer,
66225 + size_t count, loff_t * ppos)
66227 + const char *buffer0 = buffer;
66228 + audio_state_t *state = (audio_state_t *)file->private_data;
66229 + audio_stream_t *s = state->output_stream;
66230 + int chunksize, ret = 0;
66232 + DPRINTK("audio_write: count=%d\n", count);
66234 + if (ppos != &file->f_pos)
66235 + return -ESPIPE;
66236 + if (s->mapped)
66237 + return -ENXIO;
66238 + if (!s->buffers && audio_setup_buf(s))
66239 + return -ENOMEM;
66241 + while (count > 0) {
66242 + audio_buf_t *b = s->buf;
66244 + /* Wait for a buffer to become free */
66245 + if (file->f_flags & O_NONBLOCK) {
66246 + ret = -EAGAIN;
66247 + if (down_trylock(&b->sem))
66248 + break;
66249 + } else {
66250 + ret = -ERESTARTSYS;
66251 + if (down_interruptible(&b->sem))
66252 + break;
66255 + /* Feed the current buffer */
66256 + chunksize = s->fragsize - b->size;
66257 + if (chunksize > count)
66258 + chunksize = count;
66259 + DPRINTK("write %d to %d\n", chunksize, s->buf_idx);
66260 + if (copy_from_user(b->start + b->size, buffer, chunksize)) {
66261 + up(&b->sem);
66262 + return -EFAULT;
66264 + b->size += chunksize;
66265 + buffer += chunksize;
66266 + count -= chunksize;
66267 + if (b->size < s->fragsize) {
66268 + up(&b->sem);
66269 + break;
66272 + /* Send current buffer to dma */
66273 + s->active = 1;
66274 + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
66275 + b->dma_addr, b->size);
66276 + b->size = 0; /* indicate that the buffer has been sent */
66277 + NEXT_BUF(s, buf);
66280 + if ((buffer - buffer0))
66281 + ret = buffer - buffer0;
66282 + DPRINTK("audio_write: return=%d\n", ret);
66283 + return ret;
66287 +static inline void audio_check_tx_spin(audio_state_t *state)
66289 + /*
66290 + * With some codecs like the Philips UDA1341 we must ensure
66291 + * there is an output stream at any time while recording since
66292 + * this is how the UDA1341 gets its clock from the SA1100.
66293 + * So while there is no playback data to send, the output DMA
66294 + * will spin with all zeroes. We use the cache flush special
66295 + * area for that.
66296 + */
66297 + if (state->need_tx_for_rx && !state->tx_spinning) {
66298 + sa1100_dma_set_spin(state->output_stream->dma_ch,
66299 + (dma_addr_t)FLUSH_BASE_PHYS, 2048);
66300 + state->tx_spinning = 1;
66305 +static void audio_prime_dma(audio_stream_t *s)
66307 + int i;
66309 + s->active = 1;
66310 + for (i = 0; i < s->nbfrags; i++) {
66311 + audio_buf_t *b = s->buf;
66312 + down(&b->sem);
66313 + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
66314 + b->dma_addr, s->fragsize);
66315 + NEXT_BUF(s, buf);
66320 +static int audio_read(struct file *file, char *buffer,
66321 + size_t count, loff_t * ppos)
66323 + char *buffer0 = buffer;
66324 + audio_state_t *state = (audio_state_t *)file->private_data;
66325 + audio_stream_t *s = state->input_stream;
66326 + int chunksize, ret = 0;
66328 + DPRINTK("audio_read: count=%d\n", count);
66330 + if (ppos != &file->f_pos)
66331 + return -ESPIPE;
66332 + if (s->mapped)
66333 + return -ENXIO;
66335 + if (!s->active) {
66336 + if (!s->buffers && audio_setup_buf(s))
66337 + return -ENOMEM;
66338 + audio_check_tx_spin(state);
66339 + audio_prime_dma(s);
66342 + while (count > 0) {
66343 + audio_buf_t *b = s->buf;
66345 + /* Wait for a buffer to become full */
66346 + if (file->f_flags & O_NONBLOCK) {
66347 + ret = -EAGAIN;
66348 + if (down_trylock(&b->sem))
66349 + break;
66350 + } else {
66351 + ret = -ERESTARTSYS;
66352 + if (down_interruptible(&b->sem))
66353 + break;
66356 + /* Grab data from the current buffer */
66357 + chunksize = b->size;
66358 + if (chunksize > count)
66359 + chunksize = count;
66360 + DPRINTK("read %d from %d\n", chunksize, s->buf_idx);
66361 + if (copy_to_user(buffer,
66362 + b->start + s->fragsize - b->size,
66363 + chunksize)) {
66364 + up(&b->sem);
66365 + return -EFAULT;
66367 + b->size -= chunksize;
66368 + buffer += chunksize;
66369 + count -= chunksize;
66370 + if (b->size > 0) {
66371 + up(&b->sem);
66372 + break;
66375 + /* Make current buffer available for DMA again */
66376 + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
66377 + b->dma_addr, s->fragsize);
66378 + NEXT_BUF(s, buf);
66381 + if ((buffer - buffer0))
66382 + ret = buffer - buffer0;
66383 + DPRINTK("audio_read: return=%d\n", ret);
66384 + return ret;
66388 +static int audio_mmap(struct file *file, struct vm_area_struct *vma)
66390 + audio_state_t *state = (audio_state_t *)file->private_data;
66391 + audio_stream_t *s;
66392 + unsigned long size, vma_addr;
66393 + int i, ret;
66395 + if (vma->vm_pgoff != 0)
66396 + return -EINVAL;
66398 + if (vma->vm_flags & VM_WRITE) {
66399 + if (!state->wr_ref)
66400 + return -EINVAL;;
66401 + s = state->output_stream;
66402 + } else if (vma->vm_flags & VM_READ) {
66403 + if (!state->rd_ref)
66404 + return -EINVAL;
66405 + s = state->input_stream;
66406 + } else return -EINVAL;
66408 + if (s->mapped)
66409 + return -EINVAL;
66410 + size = vma->vm_end - vma->vm_start;
66411 + if (size != s->fragsize * s->nbfrags)
66412 + return -EINVAL;
66413 + if (!s->buffers && audio_setup_buf(s))
66414 + return -ENOMEM;
66415 + vma_addr = vma->vm_start;
66416 + for (i = 0; i < s->nbfrags; i++) {
66417 + audio_buf_t *buf = &s->buffers[i];
66418 + if (!buf->master)
66419 + continue;
66420 + ret = remap_page_range(vma_addr, buf->dma_addr, buf->master, vma->vm_page_prot);
66421 + if (ret)
66422 + return ret;
66423 + vma_addr += buf->master;
66425 + s->mapped = 1;
66427 + return 0;
66431 +static unsigned int audio_poll(struct file *file,
66432 + struct poll_table_struct *wait)
66434 + audio_state_t *state = (audio_state_t *)file->private_data;
66435 + audio_stream_t *is = state->input_stream;
66436 + audio_stream_t *os = state->output_stream;
66437 + unsigned int mask = 0;
66438 + int i;
66440 + DPRINTK("audio_poll(): mode=%s%s\n",
66441 + (file->f_mode & FMODE_READ) ? "r" : "",
66442 + (file->f_mode & FMODE_WRITE) ? "w" : "");
66444 + if (file->f_mode & FMODE_READ) {
66445 + /* Start audio input if not already active */
66446 + if (!is->active) {
66447 + if (!is->buffers && audio_setup_buf(is))
66448 + return -ENOMEM;
66449 + audio_check_tx_spin(state);
66450 + audio_prime_dma(is);
66452 + poll_wait(file, &is->wq, wait);
66455 + if (file->f_mode & FMODE_WRITE) {
66456 + if (!os->buffers && audio_setup_buf(os))
66457 + return -ENOMEM;
66458 + poll_wait(file, &os->wq, wait);
66461 + if (file->f_mode & FMODE_READ) {
66462 + if (is->mapped) {
66463 +/* if the buffer is mapped assume we care that there are more bytes available than
66464 + when we last asked using SNDCTL_DSP_GETxPTR */
66465 + if (is->bytecount != is->getptrCount)
66466 + mask |= POLLIN | POLLRDNORM;
66467 + } else {
66468 + for (i = 0; i < is->nbfrags; i++) {
66469 + if (atomic_read(&is->buffers[i].sem.count) > 0) {
66470 + mask |= POLLIN | POLLRDNORM;
66471 + break;
66476 + if (file->f_mode & FMODE_WRITE) {
66477 + if (os->mapped) {
66478 + if (os->bytecount != os->getptrCount)
66479 + mask |= POLLOUT | POLLWRNORM;
66480 + } else {
66481 + for (i = 0; i < os->nbfrags; i++) {
66482 + if (atomic_read(&os->buffers[i].sem.count) > 0) {
66483 + mask |= POLLOUT | POLLWRNORM;
66484 + break;
66490 + DPRINTK("audio_poll() returned mask of %s%s\n",
66491 + (mask & POLLIN) ? "r" : "",
66492 + (mask & POLLOUT) ? "w" : "");
66494 + return mask;
66498 +static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
66500 + return -ESPIPE;
66504 +static int audio_set_fragments(audio_stream_t *s, int val)
66506 + if (s->active)
66507 + return -EBUSY;
66508 + if (s->buffers)
66509 + audio_clear_buf(s);
66510 + s->nbfrags = (val >> 16) & 0x7FFF;
66511 + val &= 0xffff;
66512 + if (val < 4)
66513 + val = 4;
66514 + if (val > 15)
66515 + val = 15;
66516 + s->fragsize = 1 << val;
66517 + if (s->nbfrags < 2)
66518 + s->nbfrags = 2;
66519 + if (s->nbfrags * s->fragsize > 128 * 1024)
66520 + s->nbfrags = 128 * 1024 / s->fragsize;
66521 + if (audio_setup_buf(s))
66522 + return -ENOMEM;
66523 + return val|(s->nbfrags << 16);
66526 +static int audio_ioctl(struct inode *inode, struct file *file,
66527 + uint cmd, ulong arg)
66529 + audio_state_t *state = (audio_state_t *)file->private_data;
66530 + audio_stream_t *os = state->output_stream;
66531 + audio_stream_t *is = state->input_stream;
66532 + long val;
66534 + /* dispatch based on command */
66535 + switch (cmd) {
66536 + case OSS_GETVERSION:
66537 + return put_user(SOUND_VERSION, (int *)arg);
66539 + case SNDCTL_DSP_GETBLKSIZE:
66540 + if (file->f_mode & FMODE_WRITE)
66541 + return put_user(os->fragsize, (int *)arg);
66542 + else
66543 + return put_user(is->fragsize, (int *)arg);
66545 + case SNDCTL_DSP_GETCAPS:
66546 + val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
66547 + if (is && os)
66548 + val |= DSP_CAP_DUPLEX;
66549 + return put_user(val, (int *)arg);
66551 + case SNDCTL_DSP_SETFRAGMENT:
66552 + if (get_user(val, (long *) arg))
66553 + return -EFAULT;
66554 + if (file->f_mode & FMODE_READ) {
66555 + int ret = audio_set_fragments(is, val);
66556 + if (ret < 0)
66557 + return ret;
66558 + ret = put_user(ret, (int *)arg);
66559 + if (ret)
66560 + return ret;
66562 + if (file->f_mode & FMODE_WRITE) {
66563 + int ret = audio_set_fragments(os, val);
66564 + if (ret < 0)
66565 + return ret;
66566 + ret = put_user(ret, (int *)arg);
66567 + if (ret)
66568 + return ret;
66570 + return 0;
66572 + case SNDCTL_DSP_SYNC:
66573 + return audio_sync(file);
66575 + case SNDCTL_DSP_SETDUPLEX:
66576 + return 0;
66578 + case SNDCTL_DSP_POST:
66579 + return 0;
66581 + case SNDCTL_DSP_GETTRIGGER:
66582 + val = 0;
66583 + if (file->f_mode & FMODE_READ && is->active && !is->stopped)
66584 + val |= PCM_ENABLE_INPUT;
66585 + if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
66586 + val |= PCM_ENABLE_OUTPUT;
66587 + return put_user(val, (int *)arg);
66589 + case SNDCTL_DSP_SETTRIGGER:
66590 + if (get_user(val, (int *)arg))
66591 + return -EFAULT;
66592 + if (file->f_mode & FMODE_READ) {
66593 + if (val & PCM_ENABLE_INPUT) {
66594 + if (!is->active) {
66595 + if (!is->buffers && audio_setup_buf(is))
66596 + return -ENOMEM;
66597 + audio_prime_dma(is);
66599 + audio_check_tx_spin(state);
66600 + if (is->stopped) {
66601 + is->stopped = 0;
66602 + sa1100_dma_resume(is->dma_ch);
66604 + } else {
66605 + sa1100_dma_stop(is->dma_ch);
66606 + is->stopped = 1;
66609 + if (file->f_mode & FMODE_WRITE) {
66610 + if (val & PCM_ENABLE_OUTPUT) {
66611 + if (!os->active) {
66612 + if (!os->buffers && audio_setup_buf(os))
66613 + return -ENOMEM;
66614 + if (os->mapped)
66615 + audio_prime_dma(os);
66617 + if (os->stopped) {
66618 + os->stopped = 0;
66619 + sa1100_dma_resume(os->dma_ch);
66621 + } else {
66622 + sa1100_dma_stop(os->dma_ch);
66623 + os->stopped = 1;
66626 + return 0;
66628 + case SNDCTL_DSP_GETOPTR:
66629 + case SNDCTL_DSP_GETIPTR:
66631 + count_info inf = { 0, };
66632 + audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
66633 + audio_buf_t *b;
66634 + dma_addr_t ptr;
66635 + int bytecount, offset, flags;
66637 + if ((s == is && !(file->f_mode & FMODE_READ)) ||
66638 + (s == os && !(file->f_mode & FMODE_WRITE)))
66639 + return -EINVAL;
66640 + if (s->active) {
66641 + save_flags_cli(flags);
66642 + if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) {
66643 + offset = ptr - b->dma_addr;
66644 + inf.ptr = (b - s->buffers) * s->fragsize + offset;
66645 + } else offset = 0;
66646 + bytecount = s->bytecount + offset;
66647 + s->getptrCount = s->bytecount; /* so poll can tell if it changes */
66648 + inf.blocks = s->fragcount;
66649 + s->fragcount = 0;
66650 + restore_flags(flags);
66651 + if (bytecount < 0)
66652 + bytecount = 0;
66653 + inf.bytes = bytecount;
66655 + return copy_to_user((void *)arg, &inf, sizeof(inf));
66658 + case SNDCTL_DSP_GETOSPACE:
66660 + audio_buf_info inf = { 0, };
66661 + int i;
66663 + if (!(file->f_mode & FMODE_WRITE))
66664 + return -EINVAL;
66665 + if (!os->buffers && audio_setup_buf(os))
66666 + return -ENOMEM;
66667 + for (i = 0; i < os->nbfrags; i++) {
66668 + if (atomic_read(&os->buffers[i].sem.count) > 0) {
66669 + if (os->buffers[i].size == 0)
66670 + inf.fragments++;
66671 + inf.bytes += os->fragsize - os->buffers[i].size;
66674 + inf.fragstotal = os->nbfrags;
66675 + inf.fragsize = os->fragsize;
66676 + return copy_to_user((void *)arg, &inf, sizeof(inf));
66679 + case SNDCTL_DSP_GETISPACE:
66681 + audio_buf_info inf = { 0, };
66682 + int i;
66684 + if (!(file->f_mode & FMODE_READ))
66685 + return -EINVAL;
66686 + if (!is->buffers && audio_setup_buf(is))
66687 + return -ENOMEM;
66688 + for (i = 0; i < is->nbfrags; i++) {
66689 + if (atomic_read(&is->buffers[i].sem.count) > 0) {
66690 + if (is->buffers[i].size == is->fragsize)
66691 + inf.fragments++;
66692 + inf.bytes += is->buffers[i].size;
66695 + inf.fragstotal = is->nbfrags;
66696 + inf.fragsize = is->fragsize;
66697 + return copy_to_user((void *)arg, &inf, sizeof(inf));
66700 + case SNDCTL_DSP_NONBLOCK:
66701 + file->f_flags |= O_NONBLOCK;
66702 + return 0;
66704 + case SNDCTL_DSP_RESET:
66705 + if (file->f_mode & FMODE_READ) {
66706 + if (state->tx_spinning) {
66707 + sa1100_dma_set_spin(os->dma_ch, 0, 0);
66708 + state->tx_spinning = 0;
66710 + audio_reset_buf(is);
66712 + if (file->f_mode & FMODE_WRITE) {
66713 + audio_reset_buf(os);
66715 + return 0;
66717 + default:
66718 + /*
66719 + * Let the client of this module handle the
66720 + * non generic ioctls
66721 + */
66722 + return state->client_ioctl(inode, file, cmd, arg);
66725 + return 0;
66729 +static int audio_release(struct inode *inode, struct file *file)
66731 + audio_state_t *state = (audio_state_t *)file->private_data;
66732 + DPRINTK("audio_release\n");
66734 + down(&state->sem);
66736 + if (file->f_mode & FMODE_READ) {
66737 + if (state->tx_spinning) {
66738 + sa1100_dma_set_spin(state->output_stream->dma_ch, 0, 0);
66739 + state->tx_spinning = 0;
66741 + audio_clear_buf(state->input_stream);
66742 + if (!state->skip_dma_init) {
66743 + sa1100_free_dma(state->input_stream->dma_ch);
66744 + if (state->need_tx_for_rx && !state->wr_ref)
66745 + sa1100_free_dma(state->output_stream->dma_ch);
66747 + state->rd_ref = 0;
66750 + if (file->f_mode & FMODE_WRITE) {
66751 + audio_sync(file);
66752 + audio_clear_buf(state->output_stream);
66753 + if (!state->skip_dma_init)
66754 + if (!state->need_tx_for_rx || !state->rd_ref)
66755 + sa1100_free_dma(state->output_stream->dma_ch);
66756 + state->wr_ref = 0;
66759 + if (!AUDIO_ACTIVE(state)) {
66760 + if (state->hw_shutdown)
66761 + state->hw_shutdown(state->data);
66762 +#ifdef CONFIG_PM
66763 + pm_unregister(state->pm_dev);
66764 +#endif
66767 + up(&state->sem);
66768 + return 0;
66772 +#ifdef CONFIG_PM
66774 +static int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
66776 + audio_state_t *state = (audio_state_t *)pm_dev->data;
66778 + switch (req) {
66779 + case PM_SUSPEND: /* enter D1-D3 */
66780 + if (state->output_stream)
66781 + sa1100_dma_sleep(state->output_stream->dma_ch);
66782 + if (state->input_stream)
66783 + sa1100_dma_sleep(state->input_stream->dma_ch);
66784 + if (AUDIO_ACTIVE(state) && state->hw_shutdown)
66785 + state->hw_shutdown(state->data);
66786 + break;
66787 + case PM_RESUME: /* enter D0 */
66788 + if (AUDIO_ACTIVE(state) && state->hw_init)
66789 + state->hw_init(state->data);
66790 + if (state->input_stream)
66791 + sa1100_dma_wakeup(state->input_stream->dma_ch);
66792 + if (state->output_stream)
66793 + sa1100_dma_wakeup(state->output_stream->dma_ch);
66794 + break;
66796 + return 0;
66799 +#endif
66802 +int sa1100_audio_attach(struct inode *inode, struct file *file,
66803 + audio_state_t *state)
66805 + int err, need_tx_dma;
66807 + DPRINTK("audio_open\n");
66809 + down(&state->sem);
66811 + /* access control */
66812 + err = -ENODEV;
66813 + if ((file->f_mode & FMODE_WRITE) && !state->output_stream)
66814 + goto out;
66815 + if ((file->f_mode & FMODE_READ) && !state->input_stream)
66816 + goto out;
66817 + err = -EBUSY;
66818 + if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
66819 + goto out;
66820 + if ((file->f_mode & FMODE_READ) && state->rd_ref)
66821 + goto out;
66822 + err = -EINVAL;
66823 + if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !state->output_stream)
66824 + goto out;
66826 + /* request DMA channels */
66827 + if (state->skip_dma_init)
66828 + goto skip_dma;
66829 + need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
66830 + ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
66831 + if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
66832 + need_tx_dma = 0;
66833 + if (need_tx_dma) {
66834 + err = sa1100_request_dma(&state->output_stream->dma_ch,
66835 + state->output_id,
66836 + state->output_dma);
66837 + if (err)
66838 + goto out;
66840 + if (file->f_mode & FMODE_READ) {
66841 + err = sa1100_request_dma(&state->input_stream->dma_ch,
66842 + state->input_id,
66843 + state->input_dma);
66844 + if (err) {
66845 + if (need_tx_dma)
66846 + sa1100_free_dma(state->output_stream->dma_ch);
66847 + goto out;
66850 +skip_dma:
66852 + /* now complete initialisation */
66853 + if (!AUDIO_ACTIVE(state)) {
66854 + if (state->hw_init)
66855 + state->hw_init(state->data);
66856 +#ifdef CONFIG_PM
66857 + state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback);
66858 + if (state->pm_dev)
66859 + state->pm_dev->data = state;
66860 +#endif
66863 + if ((file->f_mode & FMODE_WRITE)) {
66864 + state->wr_ref = 1;
66865 + audio_clear_buf(state->output_stream);
66866 + state->output_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
66867 + state->output_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
66868 + state->output_stream->mapped = 0;
66869 + sa1100_dma_set_callback(state->output_stream->dma_ch,
66870 + audio_dmaout_done_callback);
66871 + init_waitqueue_head(&state->output_stream->wq);
66873 + if (file->f_mode & FMODE_READ) {
66874 + state->rd_ref = 1;
66875 + audio_clear_buf(state->input_stream);
66876 + state->input_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
66877 + state->input_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
66878 + state->input_stream->mapped = 0;
66879 + sa1100_dma_set_callback(state->input_stream->dma_ch,
66880 + audio_dmain_done_callback);
66881 + init_waitqueue_head(&state->input_stream->wq);
66884 + file->private_data = state;
66885 + file->f_op->release = audio_release;
66886 + file->f_op->write = audio_write;
66887 + file->f_op->read = audio_read;
66888 + file->f_op->mmap = audio_mmap;
66889 + file->f_op->poll = audio_poll;
66890 + file->f_op->ioctl = audio_ioctl;
66891 + file->f_op->llseek = audio_llseek;
66892 + err = 0;
66894 +out:
66895 + up(&state->sem);
66896 + return err;
66899 +EXPORT_SYMBOL(sa1100_audio_attach);
66901 +MODULE_AUTHOR("Nicolas Pitre");
66902 +MODULE_DESCRIPTION("Common audio handling for the SA11x0 processor");
66903 +MODULE_LICENSE("GPL");
66904 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
66905 +++ linux-2.4.25/drivers/sound/sa1100-audio.h 2004-03-31 17:15:09.000000000 +0200
66906 @@ -0,0 +1,68 @@
66908 + * Common audio handling for the SA11x0
66910 + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
66912 + * This program is free software; you can redistribute it and/or
66913 + * modify it under the terms of the GNU General Public License.
66914 + */
66918 + * Buffer Management
66919 + */
66921 +typedef struct {
66922 + int size; /* buffer size */
66923 + char *start; /* points to actual buffer */
66924 + dma_addr_t dma_addr; /* physical buffer address */
66925 + struct semaphore sem; /* down before touching the buffer */
66926 + int master; /* owner for buffer allocation, contain size when true */
66927 + struct audio_stream_s *stream; /* owning stream */
66928 +} audio_buf_t;
66930 +typedef struct audio_stream_s {
66931 + audio_buf_t *buffers; /* pointer to audio buffer structures */
66932 + audio_buf_t *buf; /* current buffer used by read/write */
66933 + u_int buf_idx; /* index for the pointer above... */
66934 + u_int fragsize; /* fragment i.e. buffer size */
66935 + u_int nbfrags; /* nbr of fragments i.e. buffers */
66936 + int bytecount; /* nbr of processed bytes */
66937 + int getptrCount; /* value of bytecount last time anyone asked via GETxPTR */
66938 + int fragcount; /* nbr of fragment transitions */
66939 + dmach_t dma_ch; /* DMA channel ID */
66940 + wait_queue_head_t wq; /* for poll */
66941 + int mapped:1; /* mmap()'ed buffers */
66942 + int active:1; /* actually in progress */
66943 + int stopped:1; /* might be active but stopped */
66944 +} audio_stream_t;
66947 + * State structure for one instance
66948 + */
66950 +typedef struct {
66951 + audio_stream_t *output_stream;
66952 + audio_stream_t *input_stream;
66953 + dma_device_t output_dma;
66954 + dma_device_t input_dma;
66955 + char *output_id;
66956 + char *input_id;
66957 + int rd_ref:1; /* open reference for recording */
66958 + int wr_ref:1; /* open reference for playback */
66959 + int need_tx_for_rx:1; /* if data must be sent while receiving */
66960 + int tx_spinning:1; /* tx spinning active */
66961 + int skip_dma_init:1; /* hack for the SA1111 */
66962 + void *data;
66963 + void (*hw_init)(void *);
66964 + void (*hw_shutdown)(void *);
66965 + int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
66966 + struct pm_dev *pm_dev;
66967 + struct semaphore sem; /* to protect against races in attach() */
66968 +} audio_state_t;
66971 + * Functions exported by this module
66972 + */
66973 +extern int sa1100_audio_attach( struct inode *inode, struct file *file,
66974 + audio_state_t *state);
66975 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
66976 +++ linux-2.4.25/drivers/sound/sa1100ssp.c 2004-03-31 17:15:09.000000000 +0200
66977 @@ -0,0 +1,182 @@
66979 + * Glue audio driver for a simple DAC on the SA1100's SSP port
66981 + * Copyright (c) 2001 Nicolas Pitre <nico@cam.org>
66983 + * This program is free software; you can redistribute it and/or
66984 + * modify it under the terms of the GNU General Public License.
66986 + * History:
66988 + * 2001-06-04 Nicolas Pitre Initial release.
66990 + */
66992 +#include <linux/module.h>
66993 +#include <linux/init.h>
66994 +#include <linux/types.h>
66995 +#include <linux/fs.h>
66996 +#include <linux/delay.h>
66997 +#include <linux/pm.h>
66998 +#include <linux/errno.h>
66999 +#include <linux/sound.h>
67000 +#include <linux/soundcard.h>
67002 +#include <asm/semaphore.h>
67003 +#include <asm/uaccess.h>
67004 +#include <asm/hardware.h>
67005 +#include <asm/dma.h>
67007 +#include "sa1100-audio.h"
67010 +#undef DEBUG
67011 +#ifdef DEBUG
67012 +#define DPRINTK( x... ) printk( ##x )
67013 +#else
67014 +#define DPRINTK( x... )
67015 +#endif
67018 +#define AUDIO_NAME "SA1100 SSP audio"
67020 +#define AUDIO_FMT AFMT_S16_LE
67021 +#define AUDIO_CHANNELS 2
67023 +static int sample_rate = 44100;
67026 +static void ssp_audio_init(void)
67028 + if (machine_is_lart()) {
67029 + unsigned long flags;
67030 + local_irq_save(flags);
67032 + /* LART has the SSP port rewired to GPIO 10-13, 19 */
67033 + /* alternate functions for the GPIOs */
67034 + GAFR |= ( GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK |
67035 + GPIO_SSP_SFRM | GPIO_SSP_CLK );
67037 + /* Set the direction: 10, 12, 13 output; 11, 19 input */
67038 + GPDR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM );
67039 + GPDR &= ~( GPIO_SSP_RXD | GPIO_SSP_CLK );
67041 + /* enable SSP pin swap */
67042 + PPAR |= PPAR_SPR;
67044 + local_irq_restore(flags);
67047 + /* turn on the SSP */
67048 + Ser4SSCR0 = 0;
67049 + Ser4SSCR0 = (SSCR0_DataSize(16) | SSCR0_TI | SSCR0_SerClkDiv(2) |
67050 + SSCR0_SSE);
67051 + Ser4SSCR1 = (SSCR1_SClkIactL | SSCR1_SClk1P | SSCR1_ExtClk);
67054 +static void ssp_audio_shutdown(void)
67056 + Ser4SSCR0 = 0;
67059 +static int ssp_audio_ioctl( struct inode *inode, struct file *file,
67060 + uint cmd, ulong arg)
67062 + long val;
67063 + int ret = 0;
67065 + /*
67066 + * These are platform dependent ioctls which are not handled by the
67067 + * generic sa1100-audio module.
67068 + */
67069 + switch (cmd) {
67070 + case SNDCTL_DSP_STEREO:
67071 + ret = get_user(val, (int *) arg);
67072 + if (ret)
67073 + return ret;
67074 + /* Simple standard DACs are stereo only */
67075 + ret = (val == 0) ? -EINVAL : 1;
67076 + return put_user(ret, (int *) arg);
67078 + case SNDCTL_DSP_CHANNELS:
67079 + case SOUND_PCM_READ_CHANNELS:
67080 + /* Simple standard DACs are stereo only */
67081 + return put_user(AUDIO_CHANNELS, (long *) arg);
67083 + case SNDCTL_DSP_SPEED:
67084 + case SOUND_PCM_READ_RATE:
67085 + /* We assume the clock doesn't change */
67086 + return put_user(sample_rate, (long *) arg);
67088 + case SNDCTL_DSP_SETFMT:
67089 + case SNDCTL_DSP_GETFMTS:
67090 + /* Simple standard DACs are 16-bit only */
67091 + return put_user(AUDIO_FMT, (long *) arg);
67093 + default:
67094 + return -EINVAL;
67097 + return ret;
67100 +static audio_stream_t output_stream;
67102 +static audio_state_t audio_state = {
67103 + output_stream: &output_stream,
67104 + output_dma: DMA_Ser4SSPWr,
67105 + output_id: "Generic SSP sound",
67106 + hw_init: ssp_audio_init,
67107 + hw_shutdown: ssp_audio_shutdown,
67108 + client_ioctl: ssp_audio_ioctl,
67109 + sem: __MUTEX_INITIALIZER(audio_state.sem),
67112 +static int ssp_audio_open(struct inode *inode, struct file *file)
67114 + return sa1100_audio_attach(inode, file, &audio_state);
67118 + * Missing fields of this structure will be patched with the call
67119 + * to sa1100_audio_attach().
67120 + */
67121 +static struct file_operations ssp_audio_fops = {
67122 + open: ssp_audio_open,
67123 + owner: THIS_MODULE
67126 +static int audio_dev_id;
67128 +static int __init sa1100ssp_audio_init(void)
67130 + int ret;
67132 + if (!machine_is_lart()) {
67133 + printk(KERN_ERR AUDIO_NAME ": no support for this SA-1100 design!\n");
67134 + /* look at ssp_audio_init() for specific initialisations */
67135 + return -ENODEV;
67138 + /* register devices */
67139 + audio_dev_id = register_sound_dsp(&ssp_audio_fops, -1);
67141 + printk( KERN_INFO AUDIO_NAME " initialized\n" );
67142 + return 0;
67145 +static void __exit sa1100ssp_audio_exit(void)
67147 + unregister_sound_dsp(audio_dev_id);
67150 +module_init(sa1100ssp_audio_init);
67151 +module_exit(sa1100ssp_audio_exit);
67153 +MODULE_AUTHOR("Nicolas Pitre");
67154 +MODULE_DESCRIPTION("Glue audio driver for a simple DAC on the SA1100's SSP port");
67156 +MODULE_PARM(sample_rate, "i");
67157 +MODULE_PARM_DESC(sample_rate, "Sample rate of the audio DAC, default is 44100");
67159 +EXPORT_NO_SYMBOLS;
67160 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
67161 +++ linux-2.4.25/drivers/sound/sa1111-ac97.c 2004-03-31 17:15:09.000000000 +0200
67162 @@ -0,0 +1,518 @@
67164 + * Glue audio driver for the CS4205 and CS4201 AC'97 codecs.
67165 + * largely based on the framework provided by sa1111-uda1341.c.
67167 + * Copyright (c) 2002 Bertrik Sikken (bertrik.sikken@technolution.nl)
67168 + * Copyright (c) 2002 Robert Whaley (rwhaley@applieddata.net)
67170 + * This program is free software; you can redistribute it and/or
67171 + * modify it under the terms of the GNU General Public License.
67173 + * This driver makes use of the ac97_codec module (for mixer registers)
67174 + * and the sa1100-audio module (for DMA).
67176 + * History:
67178 + * 2002-04-04 Initial version.
67179 + * 2002-04-10 Updated mtd_audio_init to improve choppy sound
67180 + * and hanging sound issue.
67181 + * 2002-05-16 Updated for ADS Bitsy+ Robert Whaley
67182 + * 2002-06-28 Cleanup and added retry for read register timeouts
67183 + * 2002-08-14 Updated for ADS AGC Robert Whaley
67184 + * 2002-12-26 Cleanup, remove CONFIG_PM (it's handled by sa1100-audio.c)
67186 + */
67188 +#include <linux/module.h>
67189 +#include <linux/init.h>
67190 +#include <linux/types.h>
67191 +#include <linux/fs.h>
67192 +#include <linux/delay.h>
67193 +#include <linux/pm.h>
67194 +#include <linux/errno.h>
67195 +#include <linux/proc_fs.h>
67196 +#include <linux/sound.h>
67197 +#include <linux/soundcard.h>
67198 +#include <linux/ac97_codec.h>
67200 +#include <asm/semaphore.h>
67201 +#include <asm/uaccess.h>
67202 +#include <asm/dma.h>
67203 +#include <asm/hardware/sa1111.h>
67205 +#include "sa1100-audio.h"
67207 +/* SAC FIFO depth, low nibble is transmit fifo, high nibble is receive FIFO */
67208 +#define SAC_FIFO_DEPTH 0x77
67210 +// #define DEBUG
67212 +#ifdef DEBUG
67213 +#define DPRINTK( x... ) printk( ##x )
67214 +#else
67215 +#define DPRINTK( x... )
67216 +#endif
67219 + Our codec data
67221 +static struct ac97_codec ac97codec;
67222 +static int audio_dev_id, mixer_dev_id;
67223 +static audio_stream_t output_stream, input_stream;
67225 +/* proc info */
67227 +struct proc_dir_entry *ac97_ps;
67229 +static int sa1111_ac97_set_adc_rate(long rate);
67230 +static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val);
67231 +static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg);
67233 +static int
67234 +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
67236 + /*
67237 + * We only accept mixer (type 'M') ioctls.
67238 + */
67239 + if (_IOC_TYPE(cmd) != 'M') {
67240 + return -EINVAL;
67243 + /* pass the ioctl to the ac97 mixer */
67244 + return ac97codec.mixer_ioctl(&ac97codec, cmd, arg);
67248 +static struct file_operations sa1111_ac97_mixer_fops = {
67249 + ioctl: mixer_ioctl,
67250 + owner: THIS_MODULE
67253 +static void sa1111_ac97_power_off(void *dummy)
67255 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
67256 + /* turn off audio and audio amp */
67257 + ADS_CPLD_PCON |= (ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
67259 + /* make GPIO11 high impeadence */
67260 + GPDR &= ~GPIO_GPIO11;
67262 + /* disable SACR0 so we can make these pins high impeadence */
67263 + SACR0 &= ~SACR0_ENB;
67265 + /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
67266 + PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
67268 +#endif
67270 +#ifdef CONFIG_SA1100_ADSAGC
67271 + /* turn off audio and audio amp */
67272 + ADS_CR1 &= ~(ADS_CR1_CODEC | ADS_CR1_AMP);
67274 + /* disable SACR0 so we can make these pins high impeadence */
67275 + SACR0 &= ~SACR0_ENB;
67277 + /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
67278 + PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
67280 +#endif
67284 +static void sa1111_ac97_power_on(void *dummy)
67286 + int ret, i;
67288 + /* disable L3 */
67289 + SACR1 = 0;
67291 + SKPCR |= (SKPCR_ACCLKEN); /* enable ac97 clock */
67292 + udelay(50);
67294 + /* BIT_CLK is input to SA1111, DMA thresholds 9 (both dirs) */
67295 + SACR0 |= SACR0_BCKD | (SAC_FIFO_DEPTH << 8);
67297 + /* reset SAC registers */
67298 + SACR0 &= ~SACR0_RST;
67299 + udelay(50);
67300 + SACR0 |= SACR0_RST;
67301 + udelay(50);
67302 + SACR0 &= ~SACR0_RST;
67304 + /* setup SA1111 to use AC'97 */
67305 + SBI_SKCR |= SKCR_SELAC; /* select ac97 */
67306 + udelay(50);
67308 + /* issue a cold AC97 reset */
67309 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
67311 + /* initialize reset line */
67312 + GAFR &= ~GPIO_GPIO11;
67313 + GPDR |= GPIO_GPIO11;
67314 + GPSR = GPIO_GPIO11;
67316 + /* turn on audio and audio amp */
67317 + ADS_CPLD_PCON &= ~(ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
67318 + mdelay(5);
67320 + /* reset by lowering the reset pin momentarily */
67321 + DPRINTK("reseting codec via GPIO11\n");
67322 + GPCR = GPIO_GPIO11;
67323 + udelay(5);
67324 + GPSR = GPIO_GPIO11;
67325 + udelay(10);
67327 +#endif
67328 +#ifdef CONFIG_SA1100_ADSAGC
67330 + /* turn on audio and audio amp */
67331 + DPRINTK("before turning on power. ADS_CR1: %x\n", ADS_CR1);
67332 + ADS_CR1 |= (ADS_CR1_AMP | ADS_CR1_CODEC);
67333 + DPRINTK("after turnning on power. ADS_CR1: %x\n", ADS_CR1);
67334 + mdelay(5);
67336 + /* reset by lowering the reset pin momentarily */
67337 + DPRINTK("reseting codec via CPLD\n");
67338 + ADS_CR1 |= ADS_CR1_AUDIO_RST;
67339 + DPRINTK("after reset1. ADS_CR1: %x\n", ADS_CR1);
67340 + udelay(5);
67341 + ADS_CR1 &= ~ADS_CR1_AUDIO_RST;
67342 + DPRINTK("after reset2. ADS_CR1: %x\n", ADS_CR1);
67343 + udelay(10);
67345 +#endif
67346 + SACR2 = 0;
67347 + udelay(50);
67349 + DPRINTK("before SW reset: SACR2: %x\n", SACR2);
67350 + SACR2 = SACR2_RESET;
67351 + DPRINTK("after SW reset: SACR2: %x\n", SACR2);
67352 + udelay(50);
67354 + /* set AC97 slot 3 and 4 (PCM out) to valid */
67355 + SACR2 = (SACR2_RESET | SACR2_TS3V | SACR2_TS4V);
67357 + /* enable SAC */
67358 + SACR0 |= SACR0_ENB;
67360 + i = 100;
67361 + while (!(SASR1 & SASR1_CRDY)) {
67362 + if (!i--) {
67363 + printk("Didn't get CRDY. SASR1=%x SKID=%x\n", SASR1, SBI_SKID);
67364 + break;
67366 + udelay(50);
67369 + if (!(ret = ac97_probe_codec(&ac97codec))) {
67370 + printk("ac97_probe_codec failed (%d)\n", ret);
67371 + return;
67374 + /* mic ADC on, disable VRA, disable VRM */
67375 + sa1111_ac97_write_reg(&ac97codec, AC97_EXTENDED_STATUS, 0x0200);
67380 + * Audio interface
67381 + */
67384 +static int sa1111_ac97_audio_ioctl(struct inode *inode, struct file *file,
67385 + uint cmd, ulong arg)
67387 + long val;
67388 + int ret = 0;
67390 + DPRINTK("sa1111_ac97_audio_ioctl\n");
67392 + /*
67393 + * These are platform dependent ioctls which are not handled by the
67394 + * generic sa1100-audio module.
67395 + */
67396 + switch (cmd) {
67397 + case SNDCTL_DSP_STEREO:
67398 + ret = get_user(val, (int *) arg);
67399 + if (ret) {
67400 + return ret;
67402 + /* the cs42xx is stereo only */
67403 + ret = (val == 0) ? -EINVAL : 1;
67404 + return put_user(ret, (int *) arg);
67406 + case SNDCTL_DSP_CHANNELS:
67407 + case SOUND_PCM_READ_CHANNELS:
67408 + /* the cs42xx is stereo only */
67409 + return put_user(2, (long *) arg);
67411 +#define SA1100_AC97_IOCTL_EXTRAS
67413 +#ifdef SA1100_AC97_IOCTL_EXTRAS
67415 +#define SNDCTL_DSP_AC97_CMD _SIOWR('P', 99, int)
67416 +#define SNDCTL_DSP_INPUT_SPEED _SIOWR('P', 98, int)
67417 +#define SOUND_PCM_READ_INPUT_RATE _SIOWR('P', 97, int)
67419 + case SNDCTL_DSP_AC97_CMD:
67421 + ret = get_user(val, (long *) arg);
67422 + if (ret) {
67423 + break;
67425 + sa1111_ac97_write_reg(&ac97codec, (u8) ((val & 0xff000000) >> 24), (u16) (val & 0xffff));
67426 + return 0;
67429 + case SNDCTL_DSP_INPUT_SPEED:
67430 + ret = get_user(val, (long *) arg);
67431 + // acc code here to set the speed
67432 + if (ret) {
67433 + break;
67435 + // note that this only changes the ADC rate, not the
67436 + // rate of the DAC.
67437 + ret = sa1111_ac97_set_adc_rate(val);
67438 + if (ret)
67439 + break;
67440 + return put_user(val, (long *) arg);
67442 + case SOUND_PCM_READ_INPUT_RATE:
67444 + return put_user((long) sa1111_ac97_read_reg(&ac97codec, 0x32), (long *) arg);
67447 +#endif
67449 + case SNDCTL_DSP_SPEED:
67450 + ret = get_user(val, (long *) arg);
67451 + if (ret) {
67452 + break;
67455 + case SOUND_PCM_READ_RATE:
67456 + /* only 48 kHz playback is supported by the SA1111 */
67457 + return put_user(48000L, (long *) arg);
67459 + case SNDCTL_DSP_SETFMT:
67460 + case SNDCTL_DSP_GETFMTS:
67461 + /* we can do 16-bit only */
67462 + return put_user(AFMT_S16_LE, (long *) arg);
67464 + default:
67465 + /* Maybe this is meant for the mixer (As per OSS Docs) */
67466 + return mixer_ioctl(inode, file, cmd, arg);
67469 + return ret;
67473 +static audio_state_t audio_state = {
67474 + output_stream: &output_stream,
67475 + input_stream: &input_stream,
67476 + skip_dma_init: 1, /* done locally */
67477 + hw_init: sa1111_ac97_power_on,
67478 + hw_shutdown: sa1111_ac97_power_off,
67479 + client_ioctl: sa1111_ac97_audio_ioctl,
67480 + sem: __MUTEX_INITIALIZER(audio_state.sem),
67484 +static int sa1111_ac97_audio_open(struct inode *inode, struct file *file)
67486 + return sa1100_audio_attach(inode, file, &audio_state);
67491 + * Missing fields of this structure will be patched with the call
67492 + * to sa1100_audio_attach().
67493 + */
67494 +static struct file_operations sa1111_ac97_audio_fops = {
67495 + open: sa1111_ac97_audio_open,
67496 + owner: THIS_MODULE
67500 +static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val)
67502 + int i;
67504 + /* reset status bits */
67505 + SASCR = SASCR_DTS;
67507 + /* write command and data registers */
67508 + ACCAR = reg << 12;
67509 + ACCDR = val << 4;
67511 + /* wait for data to be transmitted */
67512 + i = 0;
67513 + while ((SASR1 & SASR1_CADT) == 0) {
67514 + udelay(50);
67515 + if (++i > 10) {
67516 + DPRINTK("sa1111_ac97_write_reg failed (data not transmitted. SASR1: %x)\n", SASR1);
67517 + break;
67521 + DPRINTK("<%03d> sa1111_ac97_write_reg, [%02X]=%04X\n", i, reg, val);
67525 +static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg)
67527 + u16 val;
67528 + int i;
67529 + int retry = 10;
67531 + do {
67532 + /* reset status bits */
67533 + SASCR = SASCR_RDD | SASCR_STO;
67535 + /* write command register */
67536 + ACCAR = (reg | 0x80) << 12;
67537 + ACCDR = 0;
67539 + /* wait for SADR bit in SASR1 */
67540 + i = 0;
67541 + while ((SASR1 & SASR1_SADR) == 0) {
67542 + udelay(50);
67543 + if (++i > 10) {
67544 + DPRINTK("<---> sa1111_ac97_read_reg failed\n");
67545 + retry--;
67546 + break;
67548 + if ((SASR1 & SASR1_RSTO) != 0) {
67549 + DPRINTK("sa1111_ac97_read_reg *timeout*\n");
67550 + retry--;
67551 + break;
67555 + } while ((SASR1 & SASR1_SADR) == 0 && retry > 0);
67557 + val = ACSDR >> 4;
67559 + DPRINTK("<%03d> sa1111_ac97_read_reg, [%02X]=%04X\n", i, reg, val);
67560 + return val;
67564 +/* wait for codec ready */
67565 +static void sa1111_ac97_ready(struct ac97_codec *dev)
67567 + int i;
67568 + u16 val;
67570 + i = 0;
67571 + while ((SASR1 & SASR1_CRDY) == 0) {
67572 + udelay(50);
67573 + if (++i > 10) {
67574 + DPRINTK("sa1111_ac97_ready failed\n");
67575 + return;
67578 + DPRINTK("codec_ready bit took %d cycles\n", i);
67580 + /* Wait for analog parts of codec to initialise */
67581 + i = 0;
67582 + do {
67583 + val = sa1111_ac97_read_reg(&ac97codec, AC97_POWER_CONTROL);
67584 + if (++i > 100) {
67585 + break;
67587 + mdelay(10);
67588 + } while ((val & 0xF) != 0xF || val == 0xFFFF);
67590 + /* the cs42xx typically takes 150 ms to initialise */
67592 + DPRINTK("analog init took %d cycles\n", i);
67596 +static int __init sa1111_ac97_init(void)
67598 + int ret;
67600 + // SBI_SKCR |= SKCR_RCLKEN;
67602 + DPRINTK("sa1111_ac97_init\n");
67604 + /* install the ac97 mixer module */
67605 + ac97codec.codec_read = sa1111_ac97_read_reg;
67606 + ac97codec.codec_write = sa1111_ac97_write_reg;
67607 + ac97codec.codec_wait = sa1111_ac97_ready;
67609 + /* Acquire and initialize DMA */
67610 + ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
67611 + SA1111_SAC_XMT_CHANNEL);
67612 + if (ret < 0) {
67613 + printk("DMA request for SAC output failed\n");
67614 + return ret;
67617 + ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
67618 + SA1111_SAC_RCV_CHANNEL);
67619 + if (ret < 0) {
67620 + printk("DMA request for SAC input failed\n");
67621 + sa1100_free_dma(output_stream.dma_ch);
67622 + return ret;
67624 + /* register devices */
67625 + audio_dev_id = register_sound_dsp(&sa1111_ac97_audio_fops, -1);
67626 + mixer_dev_id = register_sound_mixer(&sa1111_ac97_mixer_fops, -1);
67629 + /* setup proc entry */
67630 + ac97_ps = create_proc_read_entry ("driver/sa1111-ac97", 0, NULL,
67631 + ac97_read_proc, &ac97codec);
67633 + return 0;
67637 +static void __exit sa1111_ac97_exit(void)
67639 + SKPCR &= ~SKPCR_ACCLKEN; /* disable ac97 clock */
67640 + SBI_SKCR &= ~SKCR_SELAC; /* deselect ac97 */
67642 + unregister_sound_dsp(audio_dev_id);
67643 + unregister_sound_mixer(mixer_dev_id);
67644 + sa1100_free_dma(output_stream.dma_ch);
67645 + sa1100_free_dma(input_stream.dma_ch);
67648 +static int sa1111_ac97_set_adc_rate(long rate)
67651 + // note this only changes the rate of the ADC, the DAC is fixed at 48K.
67652 + // this is due to limitations of the SA1111 chip
67654 + u16 code = rate;
67656 + switch (rate) {
67657 + case 8000:
67658 + case 11025:
67659 + case 16000:
67660 + case 22050:
67661 + case 32000:
67662 + case 44100:
67663 + case 48000:
67664 + break;
67665 + default:
67666 + return -1;
67668 + sa1111_ac97_write_reg(&ac97codec, 0x2A, 0x0001);
67669 + sa1111_ac97_write_reg(&ac97codec, 0x32, code);
67670 + return 0;
67673 +module_init(sa1111_ac97_init);
67674 +module_exit(sa1111_ac97_exit);
67676 +MODULE_AUTHOR("Bertrik Sikken, Technolution B.V., Netherlands");
67677 +MODULE_DESCRIPTION("Glue audio driver for AC'97 codec");
67678 +MODULE_LICENSE("GPL");
67680 +EXPORT_NO_SYMBOLS;
67681 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
67682 +++ linux-2.4.25/drivers/sound/sa1111-uda1341.c 2004-03-31 17:15:09.000000000 +0200
67683 @@ -0,0 +1,282 @@
67685 + * Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.
67687 + * Copyright (c) 2000 John Dorsey
67689 + * This program is free software; you can redistribute it and/or
67690 + * modify it under the terms of the GNU General Public License.
67692 + * History:
67694 + * 2000-09-04 John Dorsey SA-1111 Serial Audio Controller support
67695 + * was initially added to the sa1100-uda1341.c
67696 + * driver.
67698 + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
67699 + * the former sa1100-uda1341.c driver.
67701 + * 2001-09-23 Russell King Remove old L3 bus driver.
67702 + */
67704 +#include <linux/config.h>
67705 +#include <linux/module.h>
67706 +#include <linux/init.h>
67707 +#include <linux/types.h>
67708 +#include <linux/fs.h>
67709 +#include <linux/delay.h>
67710 +#include <linux/sched.h>
67711 +#include <linux/errno.h>
67712 +#include <linux/sound.h>
67713 +#include <linux/soundcard.h>
67714 +#include <linux/ioport.h>
67715 +#include <linux/pm.h>
67716 +#include <linux/l3/l3.h>
67717 +#include <linux/l3/uda1341.h>
67719 +#include <asm/semaphore.h>
67720 +#include <asm/mach-types.h>
67721 +#include <asm/uaccess.h>
67722 +#include <asm/hardware.h>
67723 +#include <asm/dma.h>
67724 +#include <asm/arch/assabet.h>
67725 +#include <asm/hardware/sa1111.h>
67727 +#include "sa1100-audio.h"
67729 +#undef DEBUG
67730 +#ifdef DEBUG
67731 +#define DPRINTK( x... ) printk( ##x )
67732 +#else
67733 +#define DPRINTK( x... )
67734 +#endif
67738 + * Definitions
67739 + */
67741 +#define AUDIO_RATE_DEFAULT 22050
67743 +#define AUDIO_CLK_BASE 561600
67748 + * Mixer interface
67749 + */
67751 +static struct l3_client uda1341;
67753 +static int
67754 +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
67756 + /*
67757 + * We only accept mixer (type 'M') ioctls.
67758 + */
67759 + if (_IOC_TYPE(cmd) != 'M')
67760 + return -EINVAL;
67762 + return l3_command(&uda1341, cmd, (void *)arg);
67765 +static struct file_operations uda1341_mixer_fops = {
67766 + ioctl: mixer_ioctl,
67767 + owner: THIS_MODULE
67772 + * Audio interface
67773 + */
67775 +static int audio_clk_div = (AUDIO_CLK_BASE + AUDIO_RATE_DEFAULT/2)/AUDIO_RATE_DEFAULT;
67777 +static void sa1111_audio_init(void *dummy)
67779 +#ifdef CONFIG_ASSABET_NEPONSET
67780 + if (machine_is_assabet()) {
67781 + /* Select I2S audio (instead of AC-Link) */
67782 + AUD_CTL = AUD_SEL_1341;
67784 +#endif
67785 +#ifdef CONFIG_SA1100_JORNADA720
67786 + if (machine_is_jornada720()) {
67787 + /* LDD4 is speaker, LDD3 is microphone */
67788 + PPSR &= ~(PPC_LDD3 | PPC_LDD4);
67789 + PPDR |= PPC_LDD3 | PPC_LDD4;
67790 + PPSR |= PPC_LDD4; /* enable speaker */
67791 + PPSR |= PPC_LDD3; /* enable microphone */
67793 +#endif
67795 + SBI_SKCR &= ~SKCR_SELAC;
67797 + /* Enable the I2S clock and L3 bus clock: */
67798 + SKPCR |= (SKPCR_I2SCLKEN | SKPCR_L3CLKEN);
67800 + /* Activate and reset the Serial Audio Controller */
67801 + SACR0 |= (SACR0_ENB | SACR0_RST);
67802 + mdelay(5);
67803 + SACR0 &= ~SACR0_RST;
67805 + /* For I2S, BIT_CLK is supplied internally. The "SA-1111
67806 + * Specification Update" mentions that the BCKD bit should
67807 + * be interpreted as "0 = output". Default clock divider
67808 + * is 22.05kHz.
67810 + * Select I2S, L3 bus. "Recording" and "Replaying"
67811 + * (receive and transmit) are enabled.
67812 + */
67813 + SACR1 = SACR1_L3EN;
67814 + SKAUD = audio_clk_div - 1;
67816 + /* Initialize the UDA1341 internal state */
67817 + l3_open(&uda1341);
67820 +static void sa1111_audio_shutdown(void *dummy)
67822 + l3_close(&uda1341);
67823 + SACR0 &= ~SACR0_ENB;
67826 +static int sa1111_audio_ioctl( struct inode *inode, struct file *file,
67827 + uint cmd, ulong arg)
67829 + long val;
67830 + int ret = 0;
67832 + switch (cmd) {
67833 + case SNDCTL_DSP_STEREO:
67834 + ret = get_user(val, (int *) arg);
67835 + if (ret)
67836 + return ret;
67837 + /* the UDA1341 is stereo only */
67838 + ret = (val == 0) ? -EINVAL : 1;
67839 + return put_user(ret, (int *) arg);
67841 + case SNDCTL_DSP_CHANNELS:
67842 + case SOUND_PCM_READ_CHANNELS:
67843 + /* the UDA1341 is stereo only */
67844 + return put_user(2, (long *) arg);
67846 + case SNDCTL_DSP_SPEED:
67847 + ret = get_user(val, (long *) arg);
67848 + if (ret) break;
67849 + if (val < 8000) val = 8000;
67850 + if (val > 48000) val = 48000;
67851 + audio_clk_div = (AUDIO_CLK_BASE + val/2)/val;
67852 + SKAUD = audio_clk_div - 1;
67853 + /* fall through */
67855 + case SOUND_PCM_READ_RATE:
67856 + return put_user(AUDIO_CLK_BASE/audio_clk_div, (long *) arg);
67858 + case SNDCTL_DSP_SETFMT:
67859 + case SNDCTL_DSP_GETFMTS:
67860 + /* we can do 16-bit only */
67861 + return put_user(AFMT_S16_LE, (long *) arg);
67863 + default:
67864 + /* Maybe this is meant for the mixer (as per OSS Docs) */
67865 + return mixer_ioctl(inode, file, cmd, arg);
67868 + return ret;
67871 +static audio_stream_t output_stream, input_stream;
67873 +static audio_state_t audio_state = {
67874 + output_stream: &output_stream,
67875 + input_stream: &input_stream,
67876 + skip_dma_init: 1, /* done locally */
67877 + hw_init: sa1111_audio_init,
67878 + hw_shutdown: sa1111_audio_shutdown,
67879 + client_ioctl: sa1111_audio_ioctl,
67880 + sem: __MUTEX_INITIALIZER(audio_state.sem),
67883 +static int sa1111_audio_open(struct inode *inode, struct file *file)
67885 + return sa1100_audio_attach(inode, file, &audio_state);
67889 + * Missing fields of this structure will be patched with the call
67890 + * to sa1100_audio_attach().
67891 + */
67892 +static struct file_operations sa1111_audio_fops = {
67893 + open: sa1111_audio_open,
67894 + owner: THIS_MODULE
67897 +static int audio_dev_id, mixer_dev_id;
67899 +static int __init sa1111_uda1341_init(void)
67901 + struct uda1341_cfg cfg;
67902 + int ret;
67904 + if ( !( (machine_is_assabet() && machine_has_neponset()) ||
67905 + machine_is_jornada720() ||
67906 + machine_is_badge4() ))
67907 + return -ENODEV;
67909 + if (!request_mem_region(_SACR0, 512, "sound"))
67910 + return -EBUSY;
67912 + ret = l3_attach_client(&uda1341, "l3-sa1111", "uda1341");
67913 + if (ret)
67914 + goto out;
67916 + /* Acquire and initialize DMA */
67917 + ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
67918 + SA1111_SAC_XMT_CHANNEL);
67919 + if (ret < 0)
67920 + goto release_l3;
67922 + ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
67923 + SA1111_SAC_RCV_CHANNEL);
67924 + if (ret < 0)
67925 + goto release_dma;
67927 + cfg.fs = 256;
67928 + cfg.format = FMT_I2S;
67929 + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
67931 + /* register devices */
67932 + audio_dev_id = register_sound_dsp(&sa1111_audio_fops, -1);
67933 + mixer_dev_id = register_sound_mixer(&uda1341_mixer_fops, -1);
67935 + printk(KERN_INFO "Sound: SA1111 UDA1341: dsp id %d mixer id %d\n",
67936 + audio_dev_id, mixer_dev_id);
67937 + return 0;
67939 +release_dma:
67940 + sa1100_free_dma(output_stream.dma_ch);
67941 +release_l3:
67942 + l3_detach_client(&uda1341);
67943 +out:
67944 + release_mem_region(_SACR0, 512);
67945 + return ret;
67948 +static void __exit sa1111_uda1341_exit(void)
67950 + unregister_sound_dsp(audio_dev_id);
67951 + unregister_sound_mixer(mixer_dev_id);
67952 + sa1100_free_dma(output_stream.dma_ch);
67953 + sa1100_free_dma(input_stream.dma_ch);
67954 + l3_detach_client(&uda1341);
67956 + release_mem_region(_SACR0, 512);
67959 +module_init(sa1111_uda1341_init);
67960 +module_exit(sa1111_uda1341_exit);
67962 +MODULE_AUTHOR("John Dorsey, Nicolas Pitre");
67963 +MODULE_DESCRIPTION("Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.");
67965 +EXPORT_NO_SYMBOLS;
67966 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
67967 +++ linux-2.4.25/drivers/sound/uda1341.c 2004-03-31 17:15:09.000000000 +0200
67968 @@ -0,0 +1,511 @@
67970 + * Philips UDA1341 mixer device driver
67972 + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
67974 + * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V.
67976 + * This program is free software; you can redistribute it and/or
67977 + * modify it under the terms of the GNU General Public License.
67979 + * History:
67981 + * 2000-05-21 Nicolas Pitre Initial release.
67983 + * 2000-08-19 Erik Bunce More inline w/ OSS API and UDA1341 docs
67984 + * including fixed AGC and audio source handling
67986 + * 2000-11-30 Nicolas Pitre - More mixer functionalities.
67988 + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
67989 + * the former sa1100-uda1341.c driver.
67991 + * 2001-08-13 Russell King Re-written as part of the L3 interface
67992 + */
67994 +#include <linux/module.h>
67995 +#include <linux/init.h>
67996 +#include <linux/types.h>
67997 +#include <linux/slab.h>
67998 +#include <linux/errno.h>
67999 +#include <linux/ioctl.h>
68000 +#include <linux/soundcard.h>
68001 +#include <linux/l3/l3.h>
68002 +#include <linux/l3/uda1341.h>
68004 +#include <asm/uaccess.h>
68006 +#define DEF_VOLUME 65
68009 + * UDA1341 L3 address and command types
68010 + */
68011 +#define UDA1341_L3ADDR 5
68012 +#define UDA1341_DATA0 (UDA1341_L3ADDR << 2 | 0)
68013 +#define UDA1341_DATA1 (UDA1341_L3ADDR << 2 | 1)
68014 +#define UDA1341_STATUS (UDA1341_L3ADDR << 2 | 2)
68016 +struct uda1341_regs {
68017 + unsigned char stat0;
68018 +#define STAT0 0x00
68019 +#define STAT0_RST (1 << 6)
68020 +#define STAT0_SC_MASK (3 << 4)
68021 +#define STAT0_SC_512FS (0 << 4)
68022 +#define STAT0_SC_384FS (1 << 4)
68023 +#define STAT0_SC_256FS (2 << 4)
68024 +#define STAT0_IF_MASK (7 << 1)
68025 +#define STAT0_IF_I2S (0 << 1)
68026 +#define STAT0_IF_LSB16 (1 << 1)
68027 +#define STAT0_IF_LSB18 (2 << 1)
68028 +#define STAT0_IF_LSB20 (3 << 1)
68029 +#define STAT0_IF_MSB (4 << 1)
68030 +#define STAT0_IF_LSB16MSB (5 << 1)
68031 +#define STAT0_IF_LSB18MSB (6 << 1)
68032 +#define STAT0_IF_LSB20MSB (7 << 1)
68033 +#define STAT0_DC_FILTER (1 << 0)
68035 + unsigned char stat1;
68036 +#define STAT1 0x80
68037 +#define STAT1_DAC_GAIN (1 << 6) /* gain of DAC */
68038 +#define STAT1_ADC_GAIN (1 << 5) /* gain of ADC */
68039 +#define STAT1_ADC_POL (1 << 4) /* polarity of ADC */
68040 +#define STAT1_DAC_POL (1 << 3) /* polarity of DAC */
68041 +#define STAT1_DBL_SPD (1 << 2) /* double speed playback */
68042 +#define STAT1_ADC_ON (1 << 1) /* ADC powered */
68043 +#define STAT1_DAC_ON (1 << 0) /* DAC powered */
68045 + unsigned char data0_0;
68046 +#define DATA0 0x00
68047 +#define DATA0_VOLUME_MASK 0x3f
68048 +#define DATA0_VOLUME(x) (x)
68050 + unsigned char data0_1;
68051 +#define DATA1 0x40
68052 +#define DATA1_BASS(x) ((x) << 2)
68053 +#define DATA1_BASS_MASK (15 << 2)
68054 +#define DATA1_TREBLE(x) ((x))
68055 +#define DATA1_TREBLE_MASK (3)
68057 + unsigned char data0_2;
68058 +#define DATA2 0x80
68059 +#define DATA2_PEAKAFTER (1 << 5)
68060 +#define DATA2_DEEMP_NONE (0 << 3)
68061 +#define DATA2_DEEMP_32KHz (1 << 3)
68062 +#define DATA2_DEEMP_44KHz (2 << 3)
68063 +#define DATA2_DEEMP_48KHz (3 << 3)
68064 +#define DATA2_MUTE (1 << 2)
68065 +#define DATA2_FILTER_FLAT (0 << 0)
68066 +#define DATA2_FILTER_MIN (1 << 0)
68067 +#define DATA2_FILTER_MAX (3 << 0)
68069 +#define EXTADDR(n) (0xc0 | (n))
68070 +#define EXTDATA(d) (0xe0 | (d))
68072 + unsigned char ext0;
68073 +#define EXT0 0
68074 +#define EXT0_CH1_GAIN(x) (x)
68076 + unsigned char ext1;
68077 +#define EXT1 1
68078 +#define EXT1_CH2_GAIN(x) (x)
68080 + unsigned char ext2;
68081 +#define EXT2 2
68082 +#define EXT2_MIC_GAIN_MASK (7 << 2)
68083 +#define EXT2_MIC_GAIN(x) ((x) << 2)
68084 +#define EXT2_MIXMODE_DOUBLEDIFF (0)
68085 +#define EXT2_MIXMODE_CH1 (1)
68086 +#define EXT2_MIXMODE_CH2 (2)
68087 +#define EXT2_MIXMODE_MIX (3)
68089 + unsigned char ext4;
68090 +#define EXT4 4
68091 +#define EXT4_AGC_ENABLE (1 << 4)
68092 +#define EXT4_INPUT_GAIN_MASK (3)
68093 +#define EXT4_INPUT_GAIN(x) ((x) & 3)
68095 + unsigned char ext5;
68096 +#define EXT5 5
68097 +#define EXT5_INPUT_GAIN(x) ((x) >> 2)
68099 + unsigned char ext6;
68100 +#define EXT6 6
68101 +#define EXT6_AGC_CONSTANT_MASK (7 << 2)
68102 +#define EXT6_AGC_CONSTANT(x) ((x) << 2)
68103 +#define EXT6_AGC_LEVEL_MASK (3)
68104 +#define EXT6_AGC_LEVEL(x) (x)
68107 +#define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)
68108 +#define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
68110 +struct uda1341 {
68111 + struct uda1341_regs regs;
68112 + int active;
68113 + unsigned short volume;
68114 + unsigned short bass;
68115 + unsigned short treble;
68116 + unsigned short line;
68117 + unsigned short mic;
68118 + int mod_cnt;
68121 +#define ADD_FIELD(reg,field) \
68122 + *p++ = reg | uda->regs.field
68124 +#define ADD_EXTFIELD(reg,field) \
68125 + *p++ = EXTADDR(reg); \
68126 + *p++ = EXTDATA(uda->regs.field);
68128 +static void uda1341_sync(struct l3_client *clnt)
68130 + struct uda1341 *uda = clnt->driver_data;
68131 + char buf[24], *p = buf;
68133 + ADD_FIELD(STAT0, stat0);
68134 + ADD_FIELD(STAT1, stat1);
68136 + if (p != buf)
68137 + l3_write(clnt, UDA1341_STATUS, buf, p - buf);
68139 + p = buf;
68140 + ADD_FIELD(DATA0, data0_0);
68141 + ADD_FIELD(DATA1, data0_1);
68142 + ADD_FIELD(DATA2, data0_2);
68143 + ADD_EXTFIELD(EXT0, ext0);
68144 + ADD_EXTFIELD(EXT1, ext1);
68145 + ADD_EXTFIELD(EXT2, ext2);
68146 + ADD_EXTFIELD(EXT4, ext4);
68147 + ADD_EXTFIELD(EXT5, ext5);
68148 + ADD_EXTFIELD(EXT6, ext6);
68150 + if (p != buf)
68151 + l3_write(clnt, UDA1341_DATA0, buf, p - buf);
68154 +static void uda1341_cmd_init(struct l3_client *clnt)
68156 + struct uda1341 *uda = clnt->driver_data;
68157 + char buf[2];
68159 + uda->active = 1;
68161 + buf[0] = uda->regs.stat0 | STAT0_RST;
68162 + buf[1] = uda->regs.stat0;
68164 + l3_write(clnt, UDA1341_STATUS, buf, 2);
68166 + /* resend all parameters */
68167 + uda1341_sync(clnt);
68170 +static int uda1341_configure(struct l3_client *clnt, struct uda1341_cfg *conf)
68172 + struct uda1341 *uda = clnt->driver_data;
68173 + int ret = 0;
68175 + uda->regs.stat0 &= ~(STAT0_SC_MASK | STAT0_IF_MASK);
68177 + switch (conf->fs) {
68178 + case 512: uda->regs.stat0 |= STAT0_SC_512FS; break;
68179 + case 384: uda->regs.stat0 |= STAT0_SC_384FS; break;
68180 + case 256: uda->regs.stat0 |= STAT0_SC_256FS; break;
68181 + default: ret = -EINVAL; break;
68184 + switch (conf->format) {
68185 + case FMT_I2S: uda->regs.stat0 |= STAT0_IF_I2S; break;
68186 + case FMT_LSB16: uda->regs.stat0 |= STAT0_IF_LSB16; break;
68187 + case FMT_LSB18: uda->regs.stat0 |= STAT0_IF_LSB18; break;
68188 + case FMT_LSB20: uda->regs.stat0 |= STAT0_IF_LSB20; break;
68189 + case FMT_MSB: uda->regs.stat0 |= STAT0_IF_MSB; break;
68190 + case FMT_LSB16MSB: uda->regs.stat0 |= STAT0_IF_LSB16MSB; break;
68191 + case FMT_LSB18MSB: uda->regs.stat0 |= STAT0_IF_LSB18MSB; break;
68192 + case FMT_LSB20MSB: uda->regs.stat0 |= STAT0_IF_LSB20MSB; break;
68195 + if (ret == 0 && uda->active) {
68196 + char buf = uda->regs.stat0 | STAT0;
68197 + l3_write(clnt, UDA1341_STATUS, &buf, 1);
68199 + return ret;
68202 +static int uda1341_update_direct(struct l3_client *clnt, int cmd, void *arg)
68204 + struct uda1341 *uda = clnt->driver_data;
68205 + struct l3_gain *v = arg;
68206 + char newreg;
68207 + int val;
68209 + switch (cmd) {
68210 + case L3_SET_VOLUME: /* set volume. val = 0 to 100 => 62 to 1 */
68211 + uda->regs.data0_0 = DATA0_VOLUME(62 - ((v->left * 61) / 100));
68212 + newreg = uda->regs.data0_0 | DATA0;
68213 + break;
68215 + case L3_SET_BASS: /* set bass. val = 50 to 100 => 0 to 12 */
68216 + val = v->left - 50;
68217 + if (val < 0)
68218 + val = 0;
68219 + uda->regs.data0_1 &= ~DATA1_BASS_MASK;
68220 + uda->regs.data0_1 |= DATA1_BASS((val * 12) / 50);
68221 + newreg = uda->regs.data0_1 | DATA1;
68222 + break;
68224 + case L3_SET_TREBLE: /* set treble. val = 50 to 100 => 0 to 3 */
68225 + val = v->left - 50;
68226 + if (val < 0)
68227 + val = 0;
68228 + uda->regs.data0_1 &= ~DATA1_TREBLE_MASK;
68229 + uda->regs.data0_1 |= DATA1_TREBLE((val * 3) / 50);
68230 + newreg = uda->regs.data0_1 | DATA1;
68231 + break;
68233 + default:
68234 + return -EINVAL;
68235 + }
68237 + if (uda->active)
68238 + l3_write(clnt, UDA1341_DATA0, &newreg, 1);
68239 + return 0;
68242 +static int uda1341_update_indirect(struct l3_client *clnt, int cmd, void *arg)
68244 + struct uda1341 *uda = clnt->driver_data;
68245 + struct l3_gain *gain = arg;
68246 + struct l3_agc *agc = arg;
68247 + char buf[8], *p = buf;
68248 + int val, ret = 0;
68250 + switch (cmd) {
68251 + case L3_SET_GAIN:
68252 + val = 31 - (gain->left * 31 / 100);
68253 + switch (gain->channel) {
68254 + case 1:
68255 + uda->regs.ext0 = EXT0_CH1_GAIN(val);
68256 + ADD_EXTFIELD(EXT0, ext0);
68257 + break;
68259 + case 2:
68260 + uda->regs.ext1 = EXT1_CH2_GAIN(val);
68261 + ADD_EXTFIELD(EXT1, ext1);
68262 + break;
68264 + default:
68265 + ret = -EINVAL;
68267 + break;
68269 + case L3_INPUT_AGC:
68270 + if (agc->channel == 2) {
68271 + if (agc->enable)
68272 + uda->regs.ext4 |= EXT4_AGC_ENABLE;
68273 + else
68274 + uda->regs.ext4 &= ~EXT4_AGC_ENABLE;
68275 +#if 0
68276 + agc->level
68277 + agc->attack
68278 + agc->decay
68279 +#endif
68280 + ADD_EXTFIELD(EXT4, ext4);
68281 + } else
68282 + ret = -EINVAL;
68283 + break;
68285 + default:
68286 + ret = -EINVAL;
68287 + break;
68290 + if (ret == 0 && uda->active)
68291 + l3_write(clnt, UDA1341_DATA0, buf, p - buf);
68293 + return ret;
68296 +static int uda1341_mixer_ioctl(struct l3_client *clnt, int cmd, void *arg)
68298 + struct uda1341 *uda = clnt->driver_data;
68299 + struct l3_gain gain;
68300 + int val, nr = _IOC_NR(cmd), ret = 0;
68302 + if (cmd == SOUND_MIXER_INFO) {
68303 + struct mixer_info mi;
68305 + strncpy(mi.id, "UDA1341", sizeof(mi.id));
68306 + strncpy(mi.name, "Philips UDA1341", sizeof(mi.name));
68307 + mi.modify_counter = uda->mod_cnt;
68308 + return copy_to_user(arg, &mi, sizeof(mi));
68311 + if (_IOC_DIR(cmd) & _IOC_WRITE) {
68312 + ret = get_user(val, (int *)arg);
68313 + if (ret)
68314 + goto out;
68316 + gain.left = val & 255;
68317 + gain.right = val >> 8;
68318 + gain.channel = 0;
68320 + switch (nr) {
68321 + case SOUND_MIXER_VOLUME:
68322 + uda->volume = val;
68323 + uda->mod_cnt++;
68324 + uda1341_update_direct(clnt, L3_SET_VOLUME, &gain);
68325 + break;
68327 + case SOUND_MIXER_BASS:
68328 + uda->bass = val;
68329 + uda->mod_cnt++;
68330 + uda1341_update_direct(clnt, L3_SET_BASS, &gain);
68331 + break;
68333 + case SOUND_MIXER_TREBLE:
68334 + uda->treble = val;
68335 + uda->mod_cnt++;
68336 + uda1341_update_direct(clnt, L3_SET_TREBLE, &gain);
68337 + break;
68339 + case SOUND_MIXER_LINE:
68340 + uda->line = val;
68341 + gain.channel = 1;
68342 + uda->mod_cnt++;
68343 + uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
68344 + break;
68346 + case SOUND_MIXER_MIC:
68347 + uda->mic = val;
68348 + gain.channel = 2;
68349 + uda->mod_cnt++;
68350 + uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
68351 + break;
68353 + case SOUND_MIXER_RECSRC:
68354 + break;
68356 + default:
68357 + ret = -EINVAL;
68361 + if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
68362 + int nr = _IOC_NR(cmd);
68363 + ret = 0;
68365 + switch (nr) {
68366 + case SOUND_MIXER_VOLUME: val = uda->volume; break;
68367 + case SOUND_MIXER_BASS: val = uda->bass; break;
68368 + case SOUND_MIXER_TREBLE: val = uda->treble; break;
68369 + case SOUND_MIXER_LINE: val = uda->line; break;
68370 + case SOUND_MIXER_MIC: val = uda->mic; break;
68371 + case SOUND_MIXER_RECSRC: val = REC_MASK; break;
68372 + case SOUND_MIXER_RECMASK: val = REC_MASK; break;
68373 + case SOUND_MIXER_DEVMASK: val = DEV_MASK; break;
68374 + case SOUND_MIXER_CAPS: val = 0; break;
68375 + case SOUND_MIXER_STEREODEVS: val = 0; break;
68376 + default: val = 0; ret = -EINVAL; break;
68379 + if (ret == 0)
68380 + ret = put_user(val, (int *)arg);
68382 +out:
68383 + return ret;
68386 +static int uda1341_attach(struct l3_client *clnt)
68388 + struct uda1341 *uda;
68390 + uda = kmalloc(sizeof(*uda), GFP_KERNEL);
68391 + if (!uda)
68392 + return -ENOMEM;
68394 + memset(uda, 0, sizeof(*uda));
68396 + uda->volume = DEF_VOLUME | DEF_VOLUME << 8;
68397 + uda->bass = 50 | 50 << 8;
68398 + uda->treble = 50 | 50 << 8;
68399 + uda->line = 88 | 88 << 8;
68400 + uda->mic = 88 | 88 << 8;
68402 + uda->regs.stat0 = STAT0_SC_256FS | STAT0_IF_LSB16;
68403 + uda->regs.stat1 = STAT1_DAC_GAIN | STAT1_ADC_GAIN |
68404 + STAT1_ADC_ON | STAT1_DAC_ON;
68405 + uda->regs.data0_0 = DATA0_VOLUME(62 - ((DEF_VOLUME * 61) / 100));
68406 + uda->regs.data0_1 = DATA1_BASS(0) | DATA1_TREBLE(0);
68407 + uda->regs.data0_2 = DATA2_PEAKAFTER | DATA2_DEEMP_NONE |
68408 + DATA2_FILTER_MAX;
68409 + uda->regs.ext0 = EXT0_CH1_GAIN(4);
68410 + uda->regs.ext1 = EXT1_CH2_GAIN(4);
68411 + uda->regs.ext2 = EXT2_MIXMODE_MIX | EXT2_MIC_GAIN(4);
68412 + uda->regs.ext4 = EXT4_AGC_ENABLE | EXT4_INPUT_GAIN(0);
68413 + uda->regs.ext5 = EXT5_INPUT_GAIN(0);
68414 + uda->regs.ext6 = EXT6_AGC_CONSTANT(3) | EXT6_AGC_LEVEL(0);
68416 + clnt->driver_data = uda;
68418 + return 0;
68421 +static void uda1341_detach(struct l3_client *clnt)
68423 + kfree(clnt->driver_data);
68426 +static int
68427 +uda1341_command(struct l3_client *clnt, int cmd, void *arg)
68429 + int ret = -EINVAL;
68431 + if (_IOC_TYPE(cmd) == 'M')
68432 + ret = uda1341_mixer_ioctl(clnt, cmd, arg);
68433 + else if (cmd == L3_UDA1341_CONFIGURE)
68434 + ret = uda1341_configure(clnt, arg);
68436 + return ret;
68439 +static int uda1341_open(struct l3_client *clnt)
68441 + uda1341_cmd_init(clnt);
68442 + return 0;
68445 +static void uda1341_close(struct l3_client *clnt)
68447 + struct uda1341 *uda = clnt->driver_data;
68448 + uda->active = 0;
68451 +static struct l3_ops uda1341_ops = {
68452 + open: uda1341_open,
68453 + command: uda1341_command,
68454 + close: uda1341_close,
68457 +static struct l3_driver uda1341 = {
68458 + name: UDA1341_NAME,
68459 + attach_client: uda1341_attach,
68460 + detach_client: uda1341_detach,
68461 + ops: &uda1341_ops,
68462 + owner: THIS_MODULE,
68465 +static int __init uda1341_init(void)
68467 + return l3_add_driver(&uda1341);
68470 +static void __exit uda1341_exit(void)
68472 + l3_del_driver(&uda1341);
68475 +module_init(uda1341_init);
68476 +module_exit(uda1341_exit);
68478 +MODULE_AUTHOR("Nicolas Pitre");
68479 +MODULE_DESCRIPTION("Philips UDA1341 CODEC driver");
68480 --- linux-2.4.25/drivers/sound/vidc.c~2.4.25-vrs2.patch 2001-10-11 18:43:30.000000000 +0200
68481 +++ linux-2.4.25/drivers/sound/vidc.c 2004-03-31 17:15:09.000000000 +0200
68482 @@ -40,6 +40,7 @@
68483 #endif
68485 #define VIDC_SOUND_CLOCK (250000)
68486 +#define VIDC_SOUND_CLOCK_EXT (176400)
68489 * When using SERIAL SOUND mode (external DAC), the number of physical
68490 @@ -192,28 +193,43 @@
68491 return vidc_audio_format;
68494 +#define my_abs(i) ((i)<0 ? -(i) : (i))
68496 static int vidc_audio_set_speed(int dev, int rate)
68498 if (rate) {
68499 - unsigned int hwctrl, hwrate;
68500 + unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext;
68501 unsigned int newsize, new2size;
68503 - /*
68504 - * If we have selected 44.1kHz, use the DAC clock.
68505 - */
68506 - if (0 && rate == 44100) {
68507 - hwctrl = 0x00000002;
68508 + hwctrl = 0x00000003;
68510 + /* Using internal clock */
68511 + hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
68512 + if (hwrate < 3)
68513 hwrate = 3;
68514 - } else {
68515 - hwctrl = 0x00000003;
68516 + if (hwrate > 255)
68517 + hwrate = 255;
68519 - hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
68520 - if (hwrate < 3)
68521 - hwrate = 3;
68522 - if (hwrate > 255)
68523 - hwrate = 255;
68524 + /* Using exernal clock */
68525 + hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1;
68526 + if (hwrate_ext < 3)
68527 + hwrate_ext = 3;
68528 + if (hwrate_ext > 255)
68529 + hwrate_ext = 255;
68531 - rate = VIDC_SOUND_CLOCK / hwrate;
68532 + rate_int = VIDC_SOUND_CLOCK / hwrate;
68533 + rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext;
68535 + /* Chose between external and internal clock */
68536 + if (my_abs(rate_ext-rate) < my_abs(rate_int-rate)) {
68537 + /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
68538 + hwrate=hwrate_ext;
68539 + hwctrl=0x00000002;
68540 + rate=rate_ext;
68541 + } else {
68542 + /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
68543 + hwctrl=0x00000003;
68544 + rate=rate_int;
68547 vidc_writel(0xb0000000 | (hwrate - 2));
68548 @@ -225,13 +241,14 @@
68549 if (newsize > 4096)
68550 newsize = 4096;
68551 for (new2size = 128; new2size < newsize; new2size <<= 1);
68552 - if (new2size - newsize > newsize - (new2size >> 1))
68553 - new2size >>= 1;
68554 + if (new2size - newsize > newsize - (new2size >> 1))
68555 + new2size >>= 1;
68556 if (new2size > 4096) {
68557 printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n",
68558 newsize, new2size);
68559 new2size = 4096;
68561 + /*printk("VIDC: dma size %d\n", new2size);*/
68562 dma_bufsize = new2size;
68563 vidc_audio_rate = rate;
68565 --- linux-2.4.25/drivers/sound/waveartist.c~2.4.25-vrs2.patch 2001-10-25 22:53:52.000000000 +0200
68566 +++ linux-2.4.25/drivers/sound/waveartist.c 2004-03-31 17:15:09.000000000 +0200
68567 @@ -247,17 +247,15 @@
68568 printk("\n");
68571 - if (inb(io_base + STATR) & CMD_RF) {
68572 - int old_data;
68574 - /* flush the port
68575 - */
68576 + /*
68577 + * flush any stale command data from the port.
68578 + */
68579 + while (inb(io_base + STATR) & CMD_RF) {
68580 + unsigned int old_data;
68582 old_data = inw(io_base + CMDR);
68584 - if (debug_flg & DEBUG_CMD)
68585 - printk("flushed %04X...", old_data);
68587 + printk("waveartist: flushing stale command data: 0x%04x pc=%p\n",
68588 + old_data, __builtin_return_address(0));
68589 udelay(10);
68592 @@ -287,16 +285,19 @@
68593 resp[i] = inw(io_base + CMDR);
68596 - if (debug_flg & DEBUG_CMD) {
68597 - if (!timed_out) {
68598 - printk("waveartist_cmd: resp=");
68599 + if (debug_flg & DEBUG_CMD && !timed_out) {
68600 + printk("waveartist_cmd: resp=");
68602 - for (i = 0; i < nr_resp; i++)
68603 - printk("%04X ", resp[i]);
68604 + for (i = 0; i < nr_resp; i++)
68605 + printk("%04X ", resp[i]);
68606 + printk("\n");
68609 - printk("\n");
68610 - } else
68611 - printk("waveartist_cmd: timed out\n");
68612 + if (timed_out) {
68613 + printk(KERN_ERR "waveartist_cmd: command timed out:");
68614 + for (i = 0; i < nr_cmd; i++)
68615 + printk(" %04x", cmd[i]);
68616 + printk("\n");
68619 return timed_out ? 1 : 0;
68620 @@ -495,7 +496,6 @@
68621 audio_devs[dev]->flags & DMA_AUTOMODE &&
68622 intrflag &&
68623 count == devc->xfer_count) {
68624 - devc->audio_mode |= PCM_ENABLE_INPUT;
68625 return; /*
68626 * Auto DMA mode on. No need to react
68628 @@ -571,9 +571,6 @@
68629 wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
68630 unsigned int speed, bits;
68632 - if (devc->audio_mode)
68633 - return 0;
68635 speed = waveartist_get_speed(portc);
68636 bits = waveartist_get_bits(portc);
68638 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
68639 +++ linux-2.4.25/drivers/ssi/Config.in 2004-03-31 17:15:09.000000000 +0200
68640 @@ -0,0 +1,11 @@
68642 +mainmenu_option next_comment
68643 +comment 'Synchronous Serial Interface'
68644 +tristate 'Synchronous Serial Interface Support' CONFIG_SSI
68646 +comment 'SSI Bus Drivers'
68647 +dep_tristate ' CLPS711X SSI support' CONFIG_SSI_CLPS711X $CONFIG_SSI $CONFIG_ARCH_CLPS711X
68649 +comment 'SSI Device Drivers'
68650 +dep_tristate ' JUNO keyboard support' CONFIG_SSI_JUNO $CONFIG_SSI
68651 +endmenu
68652 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
68653 +++ linux-2.4.25/drivers/ssi/Makefile 2004-03-31 17:15:09.000000000 +0200
68654 @@ -0,0 +1,50 @@
68656 +# Makefile for the SSI drivers
68658 +# Note! Dependencies are done automagically by 'make dep', which also
68659 +# removes any old dependencies. DON'T put your own dependencies here
68660 +# unless it's something special (ie not a .c file).
68662 +# Note 2! The CFLAGS definition is now inherited from the
68663 +# parent makefile.
68666 +O_TARGET := ssi.o
68668 +obj-y :=
68669 +obj-m :=
68670 +obj-n :=
68671 +obj- :=
68673 +export-objs :=
68674 +list-multi :=
68676 +obj-$(CONFIG_SSI) += ssi_core.o
68677 +obj-$(CONFIG_SSI_CLPS711X) += clps711x_ssi1.o
68678 +obj-y += juno.o
68680 +# Extract lists of the multi-part drivers.
68681 +# The 'int-*' lists are intermediate files used to build the multi's.
68683 +multi-y := $(filter $(list-multi), $(obj-y))
68684 +multi-m := $(filter $(list-multi), $(obj-m))
68685 +int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
68686 +int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
68688 +# Files that are both resident and modular; remove from modular.
68690 +obj-m := $(filter-out $(obj-y), $(obj-m))
68691 +int-m := $(filter-out $(int-y), $(int-m))
68693 +# Take multi-part drivers out of obj-y and put components in.
68695 +obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
68697 +# Translate to Rules.make lists.
68699 +O_OBJS := $(filter-out $(export-objs), $(obj-y))
68700 +OX_OBJS := $(filter $(export-objs), $(obj-y))
68701 +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
68702 +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
68704 +include $(TOPDIR)/Rules.make
68705 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
68706 +++ linux-2.4.25/drivers/ssi/README 2004-03-31 17:15:09.000000000 +0200
68707 @@ -0,0 +1,86 @@
68708 + Synchronous Serial Interface bus driver
68709 + ---------------------------------------
68711 + EEEEE X X PPPP EEEEE RRRR IIIII M M EEEEE N N TTTTT AAA L
68712 + E X X P P E R R I MM MM E NN N T A A L
68713 + EEEE X PPPP EEEE RRRR I M M M EEEE N N N T AAAAA L
68714 + E X X P E R R I M M E N NN T A A L
68715 + EEEEE X X P EEEEE R R IIIII M M EEEEE N N T A A LLLLL
68717 +This directory holds the SSI bus drivers. Basically, a SSI bus consists
68718 +of the following signals:
68720 + stxd Transmit data
68721 + srxd Receive data
68722 + sclk Clock
68723 + sfrm Frame
68724 + Chip selects (1 - n)
68726 +There may be more than one device on a SSI bus, and each device can
68727 +have different timing requirements. There are several frame formats:
68729 +1. Texas Instruments Synchronous Serial Frame format
68731 + sclk ____~_~_~_~_~_~_~_~____
68732 + sfrm ____~~_________________
68733 + stxd ------bn..........b0---
68734 + srxd ------bn..........b0---
68736 + - data latched in on the falling edge of the clock
68737 + - data shifted out on the rising edge of the clock
68739 +2. Motorola SPI frame format
68741 + sclk ______~_~_~_~_~_~_~____
68742 + sfrm ~~~~________________~~~
68743 + stxd -----bn..........b0----
68744 + srxd ----.bn..........b0----
68746 + - data latched in on the rising edge of the clock
68747 + - data shifted out on the falling edge of the clock, or falling edge
68748 + of sfrm
68750 +3. National Microwire format
68752 + sclk ______~_~_~_~_~_~_~_~_~_~_~_~_~_____
68753 + sfrm ~~~~_____________________________~~~
68754 + stxd -----bn......b0---------------------
68755 + srxd -----------------bn..........b0.----
68757 + - data latched in on the rising edge of the clock
68758 + - data shifted out on the falling edge of the clock
68759 + - half duplex, one clock between transmission and reception
68761 +Types of devices
68762 +----------------
68764 +The following types of devices can be found on a SSP bus:
68766 + Sound chips
68767 + Keyboard devices
68768 + Touch screen devices
68770 +Keyboard
68771 +--------
68773 +TX:
68774 +0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
68775 +1. select device
68776 +2. keyboard responds asserting key_atn
68777 +3. wait 0.1ms to 5ms
68778 +4. transmit data byte
68779 +5. wait >= 150us
68780 +6. repeat step 4 until all data sent
68781 +7. deselect device
68782 +8. keyboard responds de-asserting key_atn
68783 +9. wait >= 120us
68785 +RX:
68786 +0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
68787 +1. keyboard asserts key_atn
68788 +2. select device after 0.1ms < 5ms
68789 +3. read data byte
68790 +4. wait 150us
68791 +5. if key_atn still asserted, goto 3
68792 +6. deselect device
68793 +7. wait >= 120us
68794 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
68795 +++ linux-2.4.25/drivers/ssi/clps711x_ssi1.c 2004-03-31 17:15:09.000000000 +0200
68796 @@ -0,0 +1,237 @@
68798 + * linux/drivers/ssi/clps711x_ssi1.c
68800 + * SSI bus driver for the CLPS711x SSI1 bus. We support EP7212
68801 + * extensions as well.
68803 + * Frame sizes can be between 4 and 24 bits.
68804 + * Config sizes can be between 4 and 16 bits.
68805 + */
68806 +#include <linux/init.h>
68807 +#include <linux/sched.h>
68808 +#include <linux/delay.h>
68810 +#include <asm/mach-types.h>
68811 +#include <asm/io.h>
68812 +#include <asm/irq.h>
68814 +#include <asm/hardware/ep7212.h>
68816 +#include "ssi_bus.h"
68817 +#include "ssi_dev.h"
68819 +#define EP7212
68822 + * Port E on the P720T is used for the SPI bus chip selects
68823 + * 0 - Keyboard
68824 + * 1 - Touch screen
68825 + * 2 - CS4224 ADC/DAC
68826 + * 7 - idle
68827 + */
68829 +#if 0
68831 + * we place in the transmit buffer:
68832 + * <control>
68833 + * received data (binary):
68834 + * 0xxxxxxxxxxxx000
68835 + * where 'x' is the value
68836 + */
68837 +struct ssi_dev ads7846_dev = {
68838 + name: "ADS7846",
68839 + id: 1,
68840 + proto: SSI_SPI,
68841 + cfglen: 8,
68842 + framelen: 24,
68843 + clkpol: 0,
68844 + clkfreq: 2500000,
68848 + * we place in the transmit buffer:
68849 + * write: <20> <map> <data>...
68850 + * received data discarded
68851 + */
68852 +struct ssi_dev cs4224_dev = {
68853 + name: "CS4224",
68854 + id: 2,
68855 + proto: SSI_SPI,
68856 + cfglen: 8,
68857 + framelen: 8,
68858 + clkpol: 0,
68859 + clkfreq: 6000000,
68861 +#endif
68864 + * Supplement with whatever method your board requires
68865 + */
68866 +static void ssi1_select_id(int id)
68868 + if (machine_is_p720t()) {
68869 + clps_writel(7, PEDDR);
68870 + clps_writel(id, PEDR);
68875 + * Select the specified device. The upper layers will have already
68876 + * checked that the bus transmit queue is idle. We need to make sure
68877 + * that the interface itself is idle.
68878 + */
68879 +static int ssi1_select(struct ssi_bus *bus, struct ssi_dev *dev)
68881 + u_int id = dev ? dev->id : 7;
68882 + u_int val;
68884 + /*
68885 + * Make sure that the interface is idle
68886 + */
68887 + do {
68888 + val = clps_readl(SYSFLG1);
68889 + } while (val & SYSFLG1_SSIBUSY);
68891 + ssi1_select_id(7);
68893 + if (dev) {
68894 + /*
68895 + * Select clock frequency. This is very rough,
68896 + * and assumes that we're operating in PLL mode.
68897 + */
68898 + val = clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK;
68899 +// if (dev->clkfreq <= 16000) /* <16kHz */
68900 +// val |= SYSCON1_ADCKSEL(0);
68901 +// else if (dev->clkfreq < 64000) /* <64kHz */
68902 +// val |= SYSCON1_ADCKSEL(1);
68903 +// else if (dev->clkfreq < 128000) /* <128kHz */
68904 + val |= SYSCON1_ADCKSEL(2);
68905 +// else /* >= 128kHz */
68906 +// val |= SYSCON1_ADCKSEL(3);
68907 + clps_writel(val, SYSCON1);
68909 + bus->cfglen = dev->cfglen;
68910 + bus->framelen = dev->framelen;
68911 + bus->clkpol = dev->clkpol;
68912 + bus->proto = dev->proto;
68914 +#ifdef EP7212
68915 + /*
68916 + * Set the clock edge according to the device.
68917 + * (set clkpol if the device reads data on the
68918 + * falling edge of the clock signal).
68919 + */
68920 + val = ep_readl(SYSCON3) & ~SYSCON3_ADCCKNSEN;
68921 + if (bus->clkpol && dev->proto != SSI_USAR)
68922 + val |= SYSCON3_ADCCKNSEN;
68923 + ep_writel(val, SYSCON3);
68924 +#endif
68926 + /*
68927 + * Select the device
68928 + */
68929 + ssi1_select_id(id);
68931 +#ifdef EP7212
68932 + /*
68933 + * If we are doing USAR, wait 30us, then set
68934 + * the clock line low.
68935 + */
68936 + if (dev->proto == SSI_USAR) {
68937 + udelay(150);
68939 + val |= SYSCON3_ADCCKNSEN;
68940 + ep_writel(val, SYSCON3);
68942 +#endif
68945 + return 0;
68948 +static void ssi1_int(int irq, void *dev_id, struct pt_regs *regs)
68950 + struct ssi_bus *bus = (struct ssi_bus *)dev_id;
68952 + /*
68953 + * Read the data word and queue it.
68954 + */
68955 + ssi_core_rcv(bus, clps_readl(SYNCIO));
68959 + * Enable transmission and/or of some bytes
68960 + */
68961 +static int ssi1_trans(struct ssi_bus *bus, u_int data)
68963 + u_int syncio;
68965 +#ifdef EP7212
68966 + data <<= 32 - bus->cfglen;
68967 + syncio = bus->cfglen | bus->framelen << 7 | data;
68968 +#else
68969 + syncio = data | bus->framelen << 8;
68970 +#endif
68972 + clps_writel(syncio, SYNCIO);
68973 + clps_writel(syncio | SYNCIO_TXFRMEN, SYNCIO);
68974 + return 0;
68978 + * Initialise the SSI bus.
68979 + */
68980 +static int ssi1_bus_init(struct ssi_bus *bus)
68982 + int retval, val;
68984 + retval = request_irq(IRQ_SSEOTI, ssi1_int, 0, "ssi1", bus);
68985 + if (retval)
68986 + return retval;
68988 +#ifdef EP7212
68989 + /*
68990 + * EP7212 only! Set the configuration command length.
68991 + * On the CLPS711x chips, it is fixed at 8 bits.
68992 + */
68993 + val = ep_readl(SYSCON3);
68994 + val |= SYSCON3_ADCCON;
68995 + ep_writel(val, SYSCON3);
68996 +#endif
68998 + ssi1_select(bus, NULL);
69000 + PLD_SPI |= PLD_SPI_EN;
69002 + return 0;
69005 +static void ssi1_bus_exit(struct ssi_bus *bus)
69007 + ssi1_select(bus, NULL);
69009 + PLD_SPI &= ~PLD_SPI_EN;
69011 + free_irq(IRQ_SSEOTI, bus);
69014 +struct ssi_bus clps711x_ssi1_bus = {
69015 + name: "clps711x_ssi1",
69016 + init: ssi1_bus_init,
69017 + exit: ssi1_bus_exit,
69018 + select: ssi1_select,
69019 + trans: ssi1_trans,
69022 +static int __init clps711x_ssi1_init(void)
69024 + return ssi_register_bus(&clps711x_ssi1_bus);
69027 +static void __exit clps711x_ssi1_exit(void)
69029 + ssi_unregister_bus(&clps711x_ssi1_bus);
69032 +module_init(clps711x_ssi1_init);
69033 +module_exit(clps711x_ssi1_exit);
69034 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
69035 +++ linux-2.4.25/drivers/ssi/juno.c 2004-03-31 17:15:09.000000000 +0200
69036 @@ -0,0 +1,131 @@
69037 +#include <linux/module.h>
69038 +#include <linux/types.h>
69039 +#include <linux/init.h>
69040 +#include <linux/sched.h>
69041 +#include <linux/delay.h>
69043 +#include <asm/io.h>
69044 +#include <asm/irq.h>
69046 +#include <asm/arch/syspld.h>
69048 +#include "ssi_bus.h"
69049 +#include "ssi_dev.h"
69051 +extern struct ssi_bus clps711x_ssi1_bus;
69053 +static u_int recvbuf[16];
69054 +static volatile u_int ptr, rxed;
69056 +static inline void juno_enable_irq(void)
69058 + enable_irq(IRQ_EINT1);
69061 +static inline void juno_disable_irq(void)
69063 + disable_irq(IRQ_EINT1);
69066 +static void juno_rcv(struct ssi_dev *dev, u_int data)
69068 + if (ptr < 16) {
69069 + recvbuf[ptr] = data;
69070 + ptr++;
69071 + } else
69072 + printk("juno_rcv: %04x\n", data);
69073 + rxed = 1;
69076 +static void juno_irq(int irq, void *dev_id, struct pt_regs *regs)
69078 + struct ssi_dev *dev = dev_id;
69080 + printk("juno_irq\n");
69082 + ssi_select_device(dev->bus, dev);
69084 + ptr = 0;
69085 + do {
69086 + rxed = 0;
69087 + ssi_transmit_data(dev, 0xff);
69088 + while (rxed == 0);
69089 + udelay(150);
69090 + } while (PLD_INT & PLD_INT_KBD_ATN);
69092 + ssi_select_device(dev->bus, NULL);
69094 + { int i;
69095 + printk("juno_rcv: ");
69096 + for (i = 0; i < ptr; i++)
69097 + printk("%04x ", recvbuf[i]);
69098 + printk("\n");
69102 +static void juno_command(struct ssi_dev *dev, int cmd, int data)
69104 + ssi_transmit_data(dev, cmd);
69105 + mdelay(1);
69106 + ssi_transmit_data(dev, data);
69107 + mdelay(1);
69108 + ssi_transmit_data(dev, 0xa0 ^ 0xc0);
69109 + mdelay(1);
69112 +static int juno_dev_init(struct ssi_dev *dev)
69114 + int retval;
69116 + PLD_KBD |= PLD_KBD_EN;
69117 + ptr = 16;
69119 + mdelay(20);
69121 + retval = request_irq(IRQ_EINT1, juno_irq, 0, dev->name, dev);
69122 + if (retval)
69123 + return retval;
69125 + juno_disable_irq();
69127 + if (ssi_select_device(dev->bus, dev) != 0) {
69128 + printk("juno: ssi_select_dev failed\n");
69129 + return -EBUSY;
69132 + mdelay(1);
69134 + juno_command(dev, 0x80, 0x20);
69136 + ssi_select_device(dev->bus, NULL);
69138 + juno_enable_irq();
69140 + return 0;
69143 +static struct ssi_dev juno_dev = {
69144 + name: "Juno",
69145 + id: 0,
69146 + proto: SSI_USAR,
69147 + cfglen: 8,
69148 + framelen: 8,
69149 + clkpol: 1,
69150 + clkfreq: 250000,
69151 + rcv: juno_rcv,
69152 + init: juno_dev_init,
69155 +static int __init juno_init(void)
69157 + return ssi_register_device(&clps711x_ssi1_bus, &juno_dev);
69160 +static void __exit juno_exit(void)
69162 + ssi_unregister_device(&juno_dev);
69165 +module_init(juno_init);
69166 +module_exit(juno_exit);
69168 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
69169 +++ linux-2.4.25/drivers/ssi/ssi_bus.h 2004-03-31 17:15:09.000000000 +0200
69170 @@ -0,0 +1,21 @@
69171 +#include <linux/circ_buf.h>
69173 +struct ssi_dev;
69175 +struct ssi_bus {
69176 + u_char cfglen;
69177 + u_char framelen;
69178 + u_char clkpol;
69179 + u_char proto;
69180 + struct ssi_dev *dev; /* current device */
69181 + int (*select)(struct ssi_bus *, struct ssi_dev *);
69182 + int (*trans)(struct ssi_bus *, u_int data);
69183 + int (*init)(struct ssi_bus *);
69184 + void (*exit)(struct ssi_bus *);
69185 + char *name;
69186 + u_int devices;
69189 +extern int ssi_core_rcv(struct ssi_bus *bus, u_int data);
69190 +extern int ssi_register_bus(struct ssi_bus *bus);
69191 +extern int ssi_unregister_bus(struct ssi_bus *bus);
69192 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
69193 +++ linux-2.4.25/drivers/ssi/ssi_core.c 2004-03-31 17:15:09.000000000 +0200
69194 @@ -0,0 +1,175 @@
69196 + * linux/drivers/ssi/ssi_core.c
69198 + * This file provides a common framework to allow multiple SSI devices
69199 + * to work together on a single SSI bus.
69201 + * You can use this in two ways:
69202 + * 1. select the device, queue up data, flush the data to the device,
69203 + * (optionally) purge the received data, deselect the device.
69204 + * 2. select the device, queue up one data word, flush to the device
69205 + * read data word, queue up next data word, flush to the device...
69206 + * deselect the device.
69207 + */
69208 +#include <linux/module.h>
69209 +#include <linux/types.h>
69210 +#include <linux/kernel.h>
69211 +#include <linux/malloc.h>
69212 +#include <linux/init.h>
69214 +#include <asm/errno.h>
69216 +#include "ssi_bus.h"
69217 +#include "ssi_dev.h"
69219 +#define DEBUG
69221 +/**
69222 + * ssi_core_rcv - pass received SSI data to the device
69223 + * @bus: the bus that the data was received from
69224 + * @data: the data word that was received
69226 + * This function is intended to be called by SSI bus device
69227 + * drivers to pass received data to the device driver.
69228 + */
69229 +int ssi_core_rcv(struct ssi_bus *bus, u_int data)
69231 + struct ssi_dev *dev = bus->dev;
69233 + if (dev && dev->rcv)
69234 + dev->rcv(dev, data);
69236 + return 0;
69239 +/**
69240 + * ssi_transmit_data - queue SSI data for later transmission
69241 + * @dev: device requesting data to be transmitted
69242 + * @data: data word to be transmitted.
69244 + * Queue one data word of SSI data for later transmission.
69245 + */
69246 +int ssi_transmit_data(struct ssi_dev *dev, u_int data)
69248 + struct ssi_bus *bus = dev->bus;
69250 + /*
69251 + * Make sure that we currently own the bus
69252 + */
69253 + if (bus->dev != dev)
69254 + BUG();
69256 + bus->trans(bus, data);
69257 + return 0;
69260 +/**
69261 + * ssi_select_device - select a SSI device for later transactions
69262 + * @dev: device to be selected
69263 + */
69264 +int ssi_select_device(struct ssi_bus *bus, struct ssi_dev *dev)
69266 + int retval;
69268 +#ifdef DEBUG
69269 + printk("SSI: selecting device %s on bus %s\n",
69270 + dev ? dev->name : "<none>", bus->name);
69271 +#endif
69273 + /*
69274 + * Select the device if it wasn't already selected.
69275 + */
69276 + retval = 0;
69277 + if (bus->dev != dev) {
69278 + retval = bus->select(bus, dev);
69279 + bus->dev = dev;
69282 + return retval;
69285 +/**
69286 + * ssi_register_device - register a SSI device with a SSI bus
69287 + * @bus: bus
69288 + * @dev: SSI device
69289 + */
69290 +int ssi_register_device(struct ssi_bus *bus, struct ssi_dev *dev)
69292 + int retval;
69294 + dev->bus = bus;
69295 + bus->devices++;
69296 + retval = dev->init(dev);
69297 + if (retval != 0) {
69298 + dev->bus = NULL;
69299 + bus->devices--;
69300 + } else {
69301 +#ifdef DEBUG
69302 + printk("SSI: registered new device %s on bus %s\n", dev->name, bus->name);
69303 +#endif
69305 + return retval;
69308 +/**
69309 + * ssi_unregister_device - unregister a SSI device from a SSI bus
69310 + * @dev: SSI device
69311 + */
69312 +int ssi_unregister_device(struct ssi_dev *dev)
69314 + struct ssi_bus *bus = dev->bus;
69316 + if (bus->dev == dev)
69317 + bus->dev = NULL;
69319 + dev->bus = NULL;
69320 + bus->devices--;
69321 +#ifdef DEBUG
69322 + printk("SSI: unregistered device %s on bus %s\n", dev->name, bus->name);
69323 +#endif
69324 + return 0;
69327 +/**
69328 + * ssi_register_bus - register a SSI bus driver
69329 + * @bus: bus
69330 + */
69331 +int ssi_register_bus(struct ssi_bus *bus)
69333 + int retval;
69335 + retval = bus->init(bus);
69336 + if (retval == 0) {
69337 + bus->devices = 0;
69338 +#ifdef DEBUG
69339 + printk("SSI: registered new bus %s\n", bus->name);
69340 +#endif
69343 + return retval;
69346 +/**
69347 + * ssi_unregister_bus - unregister a SSI bus driver
69348 + * @bus: bus
69349 + */
69350 +int ssi_unregister_bus(struct ssi_bus *bus)
69352 + int retval = -EBUSY;
69353 + if (bus->devices == 0) {
69354 + retval = 0;
69356 + return retval;
69359 +static int __init ssi_init(void)
69361 + return 0;
69364 +static void __exit ssi_exit(void)
69368 +module_init(ssi_init);
69369 +module_exit(ssi_exit);
69370 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
69371 +++ linux-2.4.25/drivers/ssi/ssi_dev.h 2004-03-31 17:15:09.000000000 +0200
69372 @@ -0,0 +1,21 @@
69373 +struct ssi_bus;
69375 +#define SSI_SPI 1
69376 +#define SSI_MICROWIRE 2
69377 +#define SSI_TISSF 3
69378 +#define SSI_USAR 4
69380 +struct ssi_dev {
69381 + char *name;
69382 + u_int id;
69383 + u_int clkfreq;
69384 + u_char cfglen;
69385 + u_char framelen;
69386 + u_char clkpol;
69387 + u_char proto;
69388 + void (*rcv)(struct ssi_dev *, u_int);
69389 + int (*init)(struct ssi_dev *);
69390 + struct ssi_bus *bus;
69394 --- linux-2.4.25/drivers/usb/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
69395 +++ linux-2.4.25/drivers/usb/Config.in 2004-03-31 17:15:09.000000000 +0200
69396 @@ -4,7 +4,13 @@
69397 mainmenu_option next_comment
69398 comment 'USB support'
69400 -dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
69401 +# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
69402 +if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
69403 + tristate 'Support for USB' CONFIG_USB
69404 +else
69405 + define_bool CONFIG_USB n
69408 if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
69409 bool ' USB verbose debug messages' CONFIG_USB_DEBUG
69411 --- linux-2.4.25/drivers/usb/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
69412 +++ linux-2.4.25/drivers/usb/Makefile 2004-03-31 17:15:09.000000000 +0200
69413 @@ -74,6 +74,14 @@
69415 subdir-$(CONFIG_USB_OHCI) += host
69416 ifeq ($(CONFIG_USB_OHCI),y)
69417 + obj-y += host/usb-ohci.o host/usb-ohci-pci.o
69418 +endif
69419 +subdir-$(CONFIG_USB_OHCI_SA1111)+= host
69420 +ifeq ($(CONFIG_USB_OHCI),y)
69421 + obj-y += host/usb-ohci.o host/usb-ohci-sa1111.o
69422 +endif
69423 +subdir-$(CONFIG_USB_OHCI_AT91) += host
69424 +ifeq ($(CONFIG_USB_OHCI_AT91),y)
69425 obj-y += host/usb-ohci.o
69426 endif
69428 @@ -85,8 +93,6 @@
69429 obj-$(CONFIG_USB_KBD) += usbkbd.o
69430 obj-$(CONFIG_USB_AIPTEK) += aiptek.o
69431 obj-$(CONFIG_USB_WACOM) += wacom.o
69432 -obj-$(CONFIG_USB_KBTAB) += kbtab.o
69433 -obj-$(CONFIG_USB_POWERMATE) += powermate.o
69435 obj-$(CONFIG_USB_SCANNER) += scanner.o
69436 obj-$(CONFIG_USB_ACM) += acm.o
69437 --- linux-2.4.25/drivers/usb/hcd.c~2.4.25-vrs2.patch 2003-06-13 16:51:36.000000000 +0200
69438 +++ linux-2.4.25/drivers/usb/hcd.c 2004-03-31 17:15:09.000000000 +0200
69439 @@ -96,7 +96,7 @@
69440 /* used when updating hcd data */
69441 static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
69443 -static struct usb_operations hcd_operations;
69444 +/*static*/ struct usb_operations hcd_operations;
69446 /*-------------------------------------------------------------------------*/
69448 @@ -1203,13 +1203,21 @@
69449 // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag
69450 if (usb_pipecontrol (urb->pipe))
69451 urb->setup_dma = pci_map_single (
69452 +#ifdef CONFIG_PCI
69453 hcd->pdev,
69454 +#else
69455 + NULL,
69456 +#endif
69457 urb->setup_packet,
69458 sizeof (struct usb_ctrlrequest),
69459 PCI_DMA_TODEVICE);
69460 if (urb->transfer_buffer_length != 0)
69461 urb->transfer_dma = pci_map_single (
69462 +#ifdef CONFIG_PCI
69463 hcd->pdev,
69464 +#else
69465 + NULL,
69466 +#endif
69467 urb->transfer_buffer,
69468 urb->transfer_buffer_length,
69469 usb_pipein (urb->pipe)
69470 @@ -1422,7 +1430,7 @@
69471 return 0;
69474 -static struct usb_operations hcd_operations = {
69475 +/*static*/ struct usb_operations hcd_operations = {
69476 allocate: hcd_alloc_dev,
69477 get_frame_number: hcd_get_frame_number,
69478 submit_urb: hcd_submit_urb,
69479 @@ -1432,7 +1440,7 @@
69481 /*-------------------------------------------------------------------------*/
69483 -static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
69484 +/*static*/ void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
69486 struct usb_hcd *hcd = __hcd;
69487 int start = hcd->state;
69488 @@ -1481,11 +1489,23 @@
69490 // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag
69491 if (usb_pipecontrol (urb->pipe))
69492 - pci_unmap_single (hcd->pdev, urb->setup_dma,
69493 + pci_unmap_single (
69494 +#ifdef CONFIG_PCI
69495 + hcd->pdev,
69496 +#else
69497 + NULL,
69498 +#endif
69499 + urb->setup_dma,
69500 sizeof (struct usb_ctrlrequest),
69501 PCI_DMA_TODEVICE);
69502 if (urb->transfer_buffer_length != 0)
69503 - pci_unmap_single (hcd->pdev, urb->transfer_dma,
69504 + pci_unmap_single (
69505 +#ifdef CONFIG_PCI
69506 + hcd->pdev,
69507 +#else
69508 + NULL,
69509 +#endif
69510 + urb->transfer_dma,
69511 urb->transfer_buffer_length,
69512 usb_pipein (urb->pipe)
69513 ? PCI_DMA_FROMDEVICE
69514 --- linux-2.4.25/drivers/usb/host/Config.in~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
69515 +++ linux-2.4.25/drivers/usb/host/Config.in 2004-03-31 17:15:09.000000000 +0200
69516 @@ -12,8 +12,13 @@
69517 define_bool CONFIG_USB_UHCI_ALT n
69519 dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
69520 +dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
69521 if [ "$CONFIG_ARM" = "y" -o "$CONFIG_X86" = "y" -a "$CONFIG_X86_64" != "y" ]; then
69522 # Cypress embedded USB controller on StrongARM or on x86 in PC/104
69523 dep_tristate ' SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL
69524 dep_tristate ' SL811HS (x86, StrongARM) support, old driver' CONFIG_USB_SL811HS $CONFIG_USB $CONFIG_EXPERIMENTAL
69526 +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
69527 + dep_tristate ' AT91RM9200 OHCI-compatible host interface support' CONFIG_USB_OHCI_AT91 $CONFIG_USB
69530 --- linux-2.4.25/drivers/usb/host/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
69531 +++ linux-2.4.25/drivers/usb/host/Makefile 2004-03-31 17:15:09.000000000 +0200
69532 @@ -8,9 +8,11 @@
69533 obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
69534 obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
69535 obj-$(CONFIG_USB_UHCI) += usb-uhci.o
69536 -obj-$(CONFIG_USB_OHCI) += usb-ohci.o
69537 +obj-$(CONFIG_USB_OHCI) += usb-ohci.o usb-ohci-pci.o
69538 obj-$(CONFIG_USB_SL811HS_ALT) += sl811.o
69539 obj-$(CONFIG_USB_SL811HS) += hc_sl811.o
69540 +obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci.o usb-ohci-sa1111.o
69541 +obj-$(CONFIG_USB_OHCI_AT91) += usb-ohci.o
69543 # Extract lists of the multi-part drivers.
69544 # The 'int-*' lists are the intermediate files used to build the multi's.
69545 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
69546 +++ linux-2.4.25/drivers/usb/host/usb-ohci-pci.c 2004-03-31 17:15:09.000000000 +0200
69547 @@ -0,0 +1,436 @@
69548 +#include <linux/module.h>
69549 +#include <linux/init.h>
69550 +#include <linux/pci.h>
69551 +#include <linux/kernel.h>
69552 +#include <linux/slab.h>
69553 +#include <linux/delay.h>
69554 +#include <linux/interrupt.h> /* for in_interrupt() */
69555 +#undef DEBUG
69556 +#include <linux/usb.h>
69558 +#include "usb-ohci.h"
69560 +#ifdef CONFIG_PMAC_PBOOK
69561 +#include <asm/machdep.h>
69562 +#include <asm/pmac_feature.h>
69563 +#include <asm/pci-bridge.h>
69564 +#ifndef CONFIG_PM
69565 +#define CONFIG_PM
69566 +#endif
69567 +#endif
69570 +/*-------------------------------------------------------------------------*/
69572 +/* Increment the module usage count, start the control thread and
69573 + * return success. */
69575 +static struct pci_driver ohci_pci_driver;
69576 +extern spinlock_t usb_ed_lock;
69577 +int __devinit
69578 +hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
69579 + const char *name, const char *slot_name);
69580 +extern void hc_remove_ohci(ohci_t *ohci);
69582 +static int __devinit
69583 +hc_found_ohci (struct pci_dev *dev, int irq,
69584 + void *mem_base, const struct pci_device_id *id)
69586 + unsigned long flags = id->driver_data;
69588 + printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
69590 + /* Check for NSC87560. We have to look at the bridge (fn1) to identify
69591 + the USB (fn2). This quirk might apply to more or even all NSC stuff
69592 + I don't know.. */
69594 + if(dev->vendor == PCI_VENDOR_ID_NS)
69596 + struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
69597 + if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
69598 + flags |= OHCI_QUIRK_SUCKYIO;
69602 + if (flags & OHCI_QUIRK_SUCKYIO)
69603 + printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
69604 + if (flags & OHCI_QUIRK_AMD756)
69605 + printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
69607 + return hc_add_ohci(dev, irq, mem_base, flags,
69608 + ohci_pci_driver.name, dev->slot_name);
69611 +/*-------------------------------------------------------------------------*/
69613 +#ifdef CONFIG_PM
69615 +/* controller died; cleanup debris, then restart */
69616 +/* must not be called from interrupt context */
69618 +static void hc_restart (ohci_t *ohci)
69620 + int temp;
69621 + int i;
69623 + if (ohci->pci_latency)
69624 + pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
69626 + ohci->disabled = 1;
69627 + ohci->sleeping = 0;
69628 + if (ohci->bus->root_hub)
69629 + usb_disconnect (&ohci->bus->root_hub);
69631 + /* empty the interrupt branches */
69632 + for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
69633 + for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
69635 + /* no EDs to remove */
69636 + ohci->ed_rm_list [0] = NULL;
69637 + ohci->ed_rm_list [1] = NULL;
69639 + /* empty control and bulk lists */
69640 + ohci->ed_isotail = NULL;
69641 + ohci->ed_controltail = NULL;
69642 + ohci->ed_bulktail = NULL;
69644 + if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
69645 + err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
69646 + } else
69647 + dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
69650 +#endif /* CONFIG_PM */
69652 +/*-------------------------------------------------------------------------*/
69654 +/* configured so that an OHCI device is always provided */
69655 +/* always called with process context; sleeping is OK */
69657 +static int __devinit
69658 +ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
69660 + unsigned long mem_resource, mem_len;
69661 + void *mem_base;
69662 + int status;
69664 + if (pci_enable_device(dev) < 0)
69665 + return -ENODEV;
69667 + if (!dev->irq) {
69668 + err("found OHCI device with no IRQ assigned. check BIOS settings!");
69669 + pci_disable_device (dev);
69670 + return -ENODEV;
69673 + /* we read its hardware registers as memory */
69674 + mem_resource = pci_resource_start(dev, 0);
69675 + mem_len = pci_resource_len(dev, 0);
69676 + if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
69677 + dbg ("controller already in use");
69678 + pci_disable_device (dev);
69679 + return -EBUSY;
69682 + mem_base = ioremap_nocache (mem_resource, mem_len);
69683 + if (!mem_base) {
69684 + err("Error mapping OHCI memory");
69685 + release_mem_region (mem_resource, mem_len);
69686 + pci_disable_device (dev);
69687 + return -EFAULT;
69690 + /* controller writes into our memory */
69691 + pci_set_master (dev);
69693 + status = hc_found_ohci (dev, dev->irq, mem_base, id);
69694 + if (status < 0) {
69695 + iounmap (mem_base);
69696 + release_mem_region (mem_resource, mem_len);
69697 + pci_disable_device (dev);
69699 + return status;
69702 +/*-------------------------------------------------------------------------*/
69704 +/* may be called from interrupt context [interface spec] */
69705 +/* may be called without controller present */
69706 +/* may be called with controller, bus, and devices active */
69708 +static void __devexit
69709 +ohci_pci_remove (struct pci_dev *dev)
69711 + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
69713 + dbg ("remove %s controller usb-%s%s%s",
69714 + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
69715 + dev->slot_name,
69716 + ohci->disabled ? " (disabled)" : "",
69717 + in_interrupt () ? " in interrupt" : ""
69718 + );
69720 + hc_remove_ohci(ohci);
69722 + release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
69723 + pci_disable_device (dev);
69727 +#ifdef CONFIG_PM
69729 +/*-------------------------------------------------------------------------*/
69731 +static int
69732 +ohci_pci_suspend (struct pci_dev *dev, u32 state)
69734 + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
69735 + unsigned long flags;
69736 + u16 cmd;
69738 + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
69739 + dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
69740 + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
69741 + return -EIO;
69744 + /* act as if usb suspend can always be used */
69745 + info ("USB suspend: usb-%s", dev->slot_name);
69746 + ohci->sleeping = 1;
69748 + /* First stop processing */
69749 + spin_lock_irqsave (&usb_ed_lock, flags);
69750 + ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
69751 + writel (ohci->hc_control, &ohci->regs->control);
69752 + writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
69753 + (void) readl (&ohci->regs->intrstatus);
69754 + spin_unlock_irqrestore (&usb_ed_lock, flags);
69756 + /* Wait a frame or two */
69757 + mdelay(1);
69758 + if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
69759 + mdelay (1);
69761 +#ifdef CONFIG_PMAC_PBOOK
69762 + if (_machine == _MACH_Pmac)
69763 + disable_irq (ohci->irq);
69764 + /* else, 2.4 assumes shared irqs -- don't disable */
69765 +#endif
69766 + /* Enable remote wakeup */
69767 + writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
69769 + /* Suspend chip and let things settle down a bit */
69770 + ohci->hc_control = OHCI_USB_SUSPEND;
69771 + writel (ohci->hc_control, &ohci->regs->control);
69772 + (void) readl (&ohci->regs->control);
69773 + mdelay (500); /* No schedule here ! */
69774 + switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
69775 + case OHCI_USB_RESET:
69776 + dbg("Bus in reset phase ???");
69777 + break;
69778 + case OHCI_USB_RESUME:
69779 + dbg("Bus in resume phase ???");
69780 + break;
69781 + case OHCI_USB_OPER:
69782 + dbg("Bus in operational phase ???");
69783 + break;
69784 + case OHCI_USB_SUSPEND:
69785 + dbg("Bus suspended");
69786 + break;
69788 + /* In some rare situations, Apple's OHCI have happily trashed
69789 + * memory during sleep. We disable it's bus master bit during
69790 + * suspend
69791 + */
69792 + pci_read_config_word (dev, PCI_COMMAND, &cmd);
69793 + cmd &= ~PCI_COMMAND_MASTER;
69794 + pci_write_config_word (dev, PCI_COMMAND, cmd);
69795 +#ifdef CONFIG_PMAC_PBOOK
69797 + struct device_node *of_node;
69799 + /* Disable USB PAD & cell clock */
69800 + of_node = pci_device_to_OF_node (ohci->ohci_dev);
69801 + if (of_node)
69802 + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
69804 +#endif
69805 + return 0;
69808 +/*-------------------------------------------------------------------------*/
69810 +static int
69811 +ohci_pci_resume (struct pci_dev *dev)
69813 + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
69814 + int temp;
69815 + unsigned long flags;
69817 + /* guard against multiple resumes */
69818 + atomic_inc (&ohci->resume_count);
69819 + if (atomic_read (&ohci->resume_count) != 1) {
69820 + err ("concurrent PCI resumes for usb-%s", dev->slot_name);
69821 + atomic_dec (&ohci->resume_count);
69822 + return 0;
69825 +#ifdef CONFIG_PMAC_PBOOK
69827 + struct device_node *of_node;
69829 + /* Re-enable USB PAD & cell clock */
69830 + of_node = pci_device_to_OF_node (ohci->ohci_dev);
69831 + if (of_node)
69832 + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
69834 +#endif
69836 + /* did we suspend, or were we powered off? */
69837 + ohci->hc_control = readl (&ohci->regs->control);
69838 + temp = ohci->hc_control & OHCI_CTRL_HCFS;
69840 +#ifdef DEBUG
69841 + /* the registers may look crazy here */
69842 + ohci_dump_status (ohci);
69843 +#endif
69845 + /* Re-enable bus mastering */
69846 + pci_set_master(ohci->ohci_dev);
69848 + switch (temp) {
69850 + case OHCI_USB_RESET: // lost power
69851 + info ("USB restart: usb-%s", dev->slot_name);
69852 + hc_restart (ohci);
69853 + break;
69855 + case OHCI_USB_SUSPEND: // host wakeup
69856 + case OHCI_USB_RESUME: // remote wakeup
69857 + info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
69858 + (temp == OHCI_USB_SUSPEND)
69859 + ? "host" : "remote");
69860 + ohci->hc_control = OHCI_USB_RESUME;
69861 + writel (ohci->hc_control, &ohci->regs->control);
69862 + (void) readl (&ohci->regs->control);
69863 + mdelay (20); /* no schedule here ! */
69864 + /* Some controllers (lucent) need a longer delay here */
69865 + mdelay (15);
69866 + temp = readl (&ohci->regs->control);
69867 + temp = ohci->hc_control & OHCI_CTRL_HCFS;
69868 + if (temp != OHCI_USB_RESUME) {
69869 + err ("controller usb-%s won't resume", dev->slot_name);
69870 + ohci->disabled = 1;
69871 + return -EIO;
69874 + /* Some chips likes being resumed first */
69875 + writel (OHCI_USB_OPER, &ohci->regs->control);
69876 + (void) readl (&ohci->regs->control);
69877 + mdelay (3);
69879 + /* Then re-enable operations */
69880 + spin_lock_irqsave (&usb_ed_lock, flags);
69881 + ohci->disabled = 0;
69882 + ohci->sleeping = 0;
69883 + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
69884 + if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
69885 + if (ohci->ed_controltail)
69886 + ohci->hc_control |= OHCI_CTRL_CLE;
69887 + if (ohci->ed_bulktail)
69888 + ohci->hc_control |= OHCI_CTRL_BLE;
69890 + writel (ohci->hc_control, &ohci->regs->control);
69891 + writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
69892 + writel (OHCI_INTR_SF, &ohci->regs->intrenable);
69893 + /* Check for a pending done list */
69894 + writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
69895 + (void) readl (&ohci->regs->intrdisable);
69896 + spin_unlock_irqrestore (&usb_ed_lock, flags);
69897 +#ifdef CONFIG_PMAC_PBOOK
69898 + if (_machine == _MACH_Pmac)
69899 + enable_irq (ohci->irq);
69900 +#endif
69901 + if (ohci->hcca->done_head)
69902 + dl_done_list (ohci, dl_reverse_done_list (ohci));
69903 + writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
69904 + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
69905 + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
69906 + break;
69908 + default:
69909 + warn ("odd PCI resume for usb-%s", dev->slot_name);
69912 + /* controller is operational, extra resumes are harmless */
69913 + atomic_dec (&ohci->resume_count);
69915 + return 0;
69918 +#endif /* CONFIG_PM */
69921 +/*-------------------------------------------------------------------------*/
69923 +static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
69925 + /*
69926 + * AMD-756 [Viper] USB has a serious erratum when used with
69927 + * lowspeed devices like mice.
69928 + */
69929 + vendor: 0x1022,
69930 + device: 0x740c,
69931 + subvendor: PCI_ANY_ID,
69932 + subdevice: PCI_ANY_ID,
69934 + driver_data: OHCI_QUIRK_AMD756,
69936 +} , {
69938 + /* handle any USB OHCI controller */
69939 + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
69940 + class_mask: ~0,
69942 + /* no matter who makes it */
69943 + vendor: PCI_ANY_ID,
69944 + device: PCI_ANY_ID,
69945 + subvendor: PCI_ANY_ID,
69946 + subdevice: PCI_ANY_ID,
69948 + }, { /* end: all zeroes */ }
69951 +MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
69953 +static struct pci_driver ohci_pci_driver = {
69954 + name: "usb-ohci",
69955 + id_table: &ohci_pci_ids [0],
69957 + probe: ohci_pci_probe,
69958 + remove: __devexit_p(ohci_pci_remove),
69960 +#ifdef CONFIG_PM
69961 + suspend: ohci_pci_suspend,
69962 + resume: ohci_pci_resume,
69963 +#endif /* PM */
69967 +/*-------------------------------------------------------------------------*/
69969 +static int __init ohci_hcd_init (void)
69971 + return pci_module_init (&ohci_pci_driver);
69974 +/*-------------------------------------------------------------------------*/
69976 +static void __exit ohci_hcd_cleanup (void)
69978 + pci_unregister_driver (&ohci_pci_driver);
69981 +module_init (ohci_hcd_init);
69982 +module_exit (ohci_hcd_cleanup);
69984 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
69985 +++ linux-2.4.25/drivers/usb/host/usb-ohci-sa1111.c 2004-03-31 17:15:09.000000000 +0200
69986 @@ -0,0 +1,118 @@
69988 + * linux/drivers/usb/usb-ohci-sa1111.c
69990 + * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
69991 + * original OHCI driver modifications, and reworked into a cleaner form
69992 + * by Russell King <rmk@arm.linux.org.uk>.
69993 + */
69994 +#include <linux/module.h>
69995 +#include <linux/init.h>
69996 +#include <linux/sched.h>
69997 +#include <linux/ioport.h>
69998 +#include <linux/interrupt.h>
69999 +#include <linux/slab.h>
70000 +#include <linux/usb.h>
70002 +#include <asm/hardware.h>
70003 +#include <asm/irq.h>
70004 +#include <asm/io.h>
70005 +#include <asm/pci.h>
70006 +#include <asm/arch/assabet.h>
70007 +#include <asm/arch/badge4.h>
70008 +#include <asm/hardware/sa1111.h>
70010 +#include "usb-ohci.h"
70012 +int __devinit
70013 +hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
70014 + const char *name, const char *slot_name);
70015 +extern void hc_remove_ohci(ohci_t *ohci);
70017 +static ohci_t *sa1111_ohci;
70019 +static void __init sa1111_ohci_configure(void)
70021 + unsigned int usb_rst = 0;
70023 + if (machine_is_xp860() ||
70024 + machine_has_neponset() ||
70025 + machine_is_accelent_sa() ||
70026 + machine_is_pfs168() ||
70027 + machine_is_badge4())
70028 + usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
70030 + /*
70031 + * Configure the power sense and control lines. Place the USB
70032 + * host controller in reset.
70033 + */
70034 + USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
70036 + /*
70037 + * Now, carefully enable the USB clock, and take
70038 + * the USB host controller out of reset.
70039 + */
70040 + SKPCR |= SKPCR_UCLKEN;
70041 + udelay(11);
70042 + USB_RESET = usb_rst;
70045 +static int __init sa1111_ohci_init(void)
70047 + int ret;
70049 + /*
70050 + * Request memory resources.
70051 + */
70052 +// if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci"))
70053 +// return -EBUSY;
70055 + sa1111_ohci_configure();
70057 + /*
70058 + * Initialise the generic OHCI driver.
70059 + */
70060 + ret = hc_add_ohci(SA1111_FAKE_PCIDEV, NIRQHCIM,
70061 + (void *)&USB_OHCI_OP_BASE, 0, &sa1111_ohci,
70062 + "usb-ohci", "sa1111");
70064 +// if (ret)
70065 +// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
70067 +#ifdef CONFIG_SA1100_BADGE4
70068 + if (machine_is_badge4() && (!ret)) {
70069 + /* found the controller, so now power the bus */
70070 + badge4_set_5V(BADGE4_5V_USB, 1);
70072 +#endif
70074 + return ret;
70077 +static void __exit sa1111_ohci_exit(void)
70079 + hc_remove_ohci(sa1111_ohci);
70081 + /*
70082 + * Put the USB host controller into reset.
70083 + */
70084 + USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
70086 + /*
70087 + * Stop the USB clock.
70088 + */
70089 + SKPCR &= ~SKPCR_UCLKEN;
70091 + /*
70092 + * Release memory resources.
70093 + */
70094 +// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
70096 +#ifdef CONFIG_SA1100_BADGE4
70097 + if (machine_is_badge4()) {
70098 + badge4_set_5V(BADGE4_5V_USB, 0);
70100 +#endif
70103 +module_init(sa1111_ohci_init);
70104 +module_exit(sa1111_ohci_exit);
70105 --- linux-2.4.25/drivers/usb/host/usb-ohci.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
70106 +++ linux-2.4.25/drivers/usb/host/usb-ohci.c 2004-03-31 17:15:09.000000000 +0200
70107 @@ -12,7 +12,6 @@
70109 * History:
70111 - * 2002/10/22 OHCI_USB_OPER for ALi lockup in IBM i1200 (ALEX <thchou@ali>)
70112 * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on
70113 * load failure (Matthew Frederickson)
70114 * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and
70115 @@ -81,16 +80,6 @@
70117 #include "../hcd.h"
70119 -#ifdef CONFIG_PMAC_PBOOK
70120 -#include <asm/machdep.h>
70121 -#include <asm/pmac_feature.h>
70122 -#include <asm/pci-bridge.h>
70123 -#ifndef CONFIG_PM
70124 -#define CONFIG_PM
70125 -#endif
70126 -#endif
70130 * Version Information
70132 @@ -98,14 +87,10 @@
70133 #define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
70134 #define DRIVER_DESC "USB OHCI Host Controller Driver"
70136 -/* For initializing controller (mask in an HCFS mode too) */
70137 -#define OHCI_CONTROL_INIT \
70138 - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
70140 #define OHCI_UNLINK_TIMEOUT (HZ / 10)
70142 static LIST_HEAD (ohci_hcd_list);
70143 -static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
70144 +spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
70147 /*-------------------------------------------------------------------------*/
70148 @@ -443,7 +428,7 @@
70150 static void ohci_dump (ohci_t *controller, int verbose)
70152 - dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name);
70153 + dbg ("OHCI controller usb-%s state", controller->slot_name);
70155 // dumps some of the state we know about
70156 ohci_dump_status (controller);
70157 @@ -557,7 +542,7 @@
70158 int i, size = 0;
70159 unsigned long flags;
70160 int bustime = 0;
70161 - int mem_flags = GFP_ATOMIC;
70162 + int mem_flags = ALLOC_FLAGS;
70164 if (!urb->dev || !urb->dev->bus)
70165 return -ENODEV;
70166 @@ -702,6 +687,9 @@
70167 if (urb->timeout) {
70168 struct list_head *entry;
70170 + // FIXME: usb-uhci uses relative timeouts (like this),
70171 + // while uhci uses absolute ones (probably better).
70172 + // Pick one solution and change the affected drivers.
70173 urb->timeout += jiffies;
70175 list_for_each (entry, &ohci->timeout_list) {
70176 @@ -715,7 +703,6 @@
70178 /* drive timeouts by SF (messy, but works) */
70179 writel (OHCI_INTR_SF, &ohci->regs->intrenable);
70180 - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
70182 #endif
70184 @@ -790,10 +777,8 @@
70186 /* wait until all TDs are deleted */
70187 set_current_state(TASK_UNINTERRUPTIBLE);
70188 - while (timeout && (urb->status == USB_ST_URB_PENDING)) {
70189 + while (timeout && (urb->status == USB_ST_URB_PENDING))
70190 timeout = schedule_timeout (timeout);
70191 - set_current_state(TASK_UNINTERRUPTIBLE);
70193 set_current_state(TASK_RUNNING);
70194 remove_wait_queue (&unlink_wakeup, &wait);
70195 if (urb->status == USB_ST_URB_PENDING) {
70196 @@ -864,7 +849,7 @@
70197 if (ed->state == ED_OPER) {
70198 /* driver on that interface didn't unlink an urb */
70199 dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
70200 - ohci->ohci_dev->slot_name, usb_dev->devnum, i);
70201 + ohci->slot_name, usb_dev->devnum, i);
70202 ep_unlink (ohci, ed);
70204 ep_rm_ed (usb_dev, ed);
70205 @@ -909,7 +894,7 @@
70206 } else {
70207 /* likely some interface's driver has a refcount bug */
70208 err ("bus %s devnum %d deletion in interrupt",
70209 - ohci->ohci_dev->slot_name, usb_dev->devnum);
70210 + ohci->slot_name, usb_dev->devnum);
70211 BUG ();
70214 @@ -1294,7 +1279,6 @@
70215 /* enable SOF interrupt */
70216 writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
70217 writel (OHCI_INTR_SF, &ohci->regs->intrenable);
70218 - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
70222 @@ -1316,7 +1300,11 @@
70223 err("internal OHCI error: TD index > length");
70224 return;
70227 +#ifdef CONFIG_SA1111
70228 + if (data & (1 << 20))
70229 + panic("td_fill: A20 = 1: %08x\n", data);
70230 +#endif
70232 /* use this td as the next dummy */
70233 td_pt = urb_priv->td [index];
70234 td_pt->hwNextTD = 0;
70235 @@ -1415,7 +1403,6 @@
70236 if (!ohci->sleeping) {
70237 wmb();
70238 writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
70239 - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
70241 break;
70243 @@ -1444,7 +1431,6 @@
70244 if (!ohci->sleeping) {
70245 wmb();
70246 writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
70247 - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
70249 break;
70251 @@ -1826,7 +1812,7 @@
70252 num_ports = roothub_a (ohci) & RH_A_NDP;
70253 if (num_ports > MAX_ROOT_PORTS) {
70254 err ("bogus NDP=%d for OHCI usb-%s", num_ports,
70255 - ohci->ohci_dev->slot_name);
70256 + ohci->slot_name);
70257 err ("rereads as NDP=%d",
70258 readl (&ohci->regs->roothub.a) & RH_A_NDP);
70259 /* retry later; "should not happen" */
70260 @@ -2174,16 +2160,12 @@
70261 writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
70263 dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;",
70264 - ohci->ohci_dev->slot_name,
70265 + ohci->slot_name,
70266 readl (&ohci->regs->control));
70268 /* Reset USB (needed by some controllers) */
70269 writel (0, &ohci->regs->control);
70271 - /* Force a state change from USBRESET to USBOPERATIONAL for ALi */
70272 - (void) readl (&ohci->regs->control); /* PCI posting */
70273 - writel (ohci->hc_control = OHCI_USB_OPER, &ohci->regs->control);
70276 /* HC Reset requires max 10 ms delay */
70277 writel (OHCI_HCR, &ohci->regs->cmdstatus);
70278 while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
70279 @@ -2252,8 +2234,6 @@
70280 writel (RH_HS_LPSC, &ohci->regs->roothub.status);
70281 #endif /* OHCI_USE_NPS */
70283 - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
70285 // POTPGT delay is bits 24-31, in 2 ms units.
70286 mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
70288 @@ -2332,14 +2312,14 @@
70289 /* interrupt for some other device? */
70290 } else if ((ints &= readl (&regs->intrenable)) == 0) {
70291 return;
70292 - }
70295 // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
70297 if (ints & OHCI_INTR_UE) {
70298 ohci->disabled++;
70299 err ("OHCI Unrecoverable Error, controller usb-%s disabled",
70300 - ohci->ohci_dev->slot_name);
70301 + ohci->slot_name);
70302 // e.g. due to PCI Master/Target Abort
70304 #ifdef DEBUG
70305 @@ -2355,30 +2335,24 @@
70307 if (ints & OHCI_INTR_WDH) {
70308 writel (OHCI_INTR_WDH, &regs->intrdisable);
70309 - (void)readl (&regs->intrdisable); /* PCI posting flush */
70310 dl_done_list (ohci, dl_reverse_done_list (ohci));
70311 writel (OHCI_INTR_WDH, &regs->intrenable);
70312 - (void)readl (&regs->intrdisable); /* PCI posting flush */
70315 if (ints & OHCI_INTR_SO) {
70316 dbg("USB Schedule overrun");
70317 writel (OHCI_INTR_SO, &regs->intrenable);
70318 - (void)readl (&regs->intrdisable); /* PCI posting flush */
70321 // FIXME: this assumes SOF (1/ms) interrupts don't get lost...
70322 if (ints & OHCI_INTR_SF) {
70323 unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
70324 writel (OHCI_INTR_SF, &regs->intrdisable);
70325 - (void)readl (&regs->intrdisable); /* PCI posting flush */
70326 if (ohci->ed_rm_list[!frame] != NULL) {
70327 dl_del_list (ohci, !frame);
70329 - if (ohci->ed_rm_list[frame] != NULL) {
70330 + if (ohci->ed_rm_list[frame] != NULL)
70331 writel (OHCI_INTR_SF, &regs->intrenable);
70332 - (void)readl (&regs->intrdisable); /* PCI posting flush */
70336 if (!list_empty (&ohci->timeout_list)) {
70337 @@ -2392,7 +2366,6 @@
70339 writel (ints, &regs->intrstatus);
70340 writel (OHCI_INTR_MIE, &regs->intrenable);
70341 - (void)readl (&regs->intrdisable); /* PCI posting flush */
70344 /*-------------------------------------------------------------------------*/
70345 @@ -2423,7 +2396,9 @@
70346 ohci->regs = mem_base;
70348 ohci->ohci_dev = dev;
70349 +#ifdef CONFIG_PCI
70350 pci_set_drvdata(dev, ohci);
70351 +#endif
70353 INIT_LIST_HEAD (&ohci->ohci_hcd_list);
70354 list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
70355 @@ -2451,7 +2426,7 @@
70357 static void hc_release_ohci (ohci_t * ohci)
70359 - dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
70360 + dbg ("USB HC release ohci usb-%s", ohci->slot_name);
70362 /* disconnect all devices */
70363 if (ohci->bus->root_hub)
70364 @@ -2464,7 +2439,9 @@
70365 free_irq (ohci->irq, ohci);
70366 ohci->irq = -1;
70368 - pci_set_drvdata(ohci->ohci_dev, NULL);
70369 +#ifdef CONFIG_PCI
70370 + pci_set_drvdata(ohci->ohci_dev, 0);
70371 +#endif
70372 if (ohci->bus) {
70373 if (ohci->bus->busnum != -1)
70374 usb_deregister_bus (ohci->bus);
70375 @@ -2487,17 +2464,15 @@
70377 /*-------------------------------------------------------------------------*/
70379 -/* Increment the module usage count, start the control thread and
70380 - * return success. */
70382 -static struct pci_driver ohci_pci_driver;
70384 -static int __devinit
70385 -hc_found_ohci (struct pci_dev *dev, int irq,
70386 - void *mem_base, const struct pci_device_id *id)
70388 + * Host bus independent add one OHCI host controller.
70389 + */
70390 +int __devinit
70391 +hc_add_ohci(struct pci_dev *dev, int irq, void *mem_base, unsigned long flags,
70392 + const char *name, const char *slot_name)
70394 - ohci_t * ohci;
70395 char buf[8], *bufp = buf;
70396 + ohci_t * ohci;
70397 int ret;
70399 #ifndef __sparc__
70400 @@ -2507,34 +2482,17 @@
70401 #endif
70402 printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
70403 (unsigned long) mem_base, bufp);
70404 - printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
70407 ohci = hc_alloc_ohci (dev, mem_base);
70408 if (!ohci) {
70409 return -ENOMEM;
70411 + ohci->slot_name = slot_name;
70412 if ((ret = ohci_mem_init (ohci)) < 0) {
70413 hc_release_ohci (ohci);
70414 return ret;
70416 - ohci->flags = id->driver_data;
70418 - /* Check for NSC87560. We have to look at the bridge (fn1) to identify
70419 - the USB (fn2). This quirk might apply to more or even all NSC stuff
70420 - I don't know.. */
70422 - if(dev->vendor == PCI_VENDOR_ID_NS)
70424 - struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
70425 - if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
70426 - ohci->flags |= OHCI_QUIRK_SUCKYIO;
70430 - if (ohci->flags & OHCI_QUIRK_SUCKYIO)
70431 - printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
70432 - if (ohci->flags & OHCI_QUIRK_AMD756)
70433 - printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
70434 + ohci->flags = flags;
70436 if (hc_reset (ohci) < 0) {
70437 hc_release_ohci (ohci);
70438 @@ -2543,13 +2501,11 @@
70440 /* FIXME this is a second HC reset; why?? */
70441 writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
70442 - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
70443 wait_ms (10);
70445 usb_register_bus (ohci->bus);
70447 - if (request_irq (irq, hc_interrupt, SA_SHIRQ,
70448 - ohci_pci_driver.name, ohci) != 0) {
70449 + if (request_irq (irq, hc_interrupt, SA_SHIRQ, name, ohci) != 0) {
70450 err ("request interrupt %s failed", bufp);
70451 hc_release_ohci (ohci);
70452 return -EBUSY;
70453 @@ -2557,7 +2513,7 @@
70454 ohci->irq = irq;
70456 if (hc_start (ohci) < 0) {
70457 - err ("can't start usb-%s", dev->slot_name);
70458 + err ("can't start usb-%s", ohci->slot_name);
70459 hc_release_ohci (ohci);
70460 return -EBUSY;
70462 @@ -2568,114 +2524,11 @@
70463 return 0;
70466 -/*-------------------------------------------------------------------------*/
70468 -#ifdef CONFIG_PM
70470 -/* controller died; cleanup debris, then restart */
70471 -/* must not be called from interrupt context */
70473 -static void hc_restart (ohci_t *ohci)
70475 - int temp;
70476 - int i;
70478 - if (ohci->pci_latency)
70479 - pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
70481 - ohci->disabled = 1;
70482 - ohci->sleeping = 0;
70483 - if (ohci->bus->root_hub)
70484 - usb_disconnect (&ohci->bus->root_hub);
70486 - /* empty the interrupt branches */
70487 - for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
70488 - for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
70490 - /* no EDs to remove */
70491 - ohci->ed_rm_list [0] = NULL;
70492 - ohci->ed_rm_list [1] = NULL;
70494 - /* empty control and bulk lists */
70495 - ohci->ed_isotail = NULL;
70496 - ohci->ed_controltail = NULL;
70497 - ohci->ed_bulktail = NULL;
70499 - if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
70500 - err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
70501 - } else
70502 - dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
70505 -#endif /* CONFIG_PM */
70507 -/*-------------------------------------------------------------------------*/
70509 -/* configured so that an OHCI device is always provided */
70510 -/* always called with process context; sleeping is OK */
70512 -static int __devinit
70513 -ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
70515 - unsigned long mem_resource, mem_len;
70516 - void *mem_base;
70517 - int status;
70519 - if (pci_enable_device(dev) < 0)
70520 - return -ENODEV;
70522 - if (!dev->irq) {
70523 - err("found OHCI device with no IRQ assigned. check BIOS settings!");
70524 - pci_disable_device (dev);
70525 - return -ENODEV;
70528 - /* we read its hardware registers as memory */
70529 - mem_resource = pci_resource_start(dev, 0);
70530 - mem_len = pci_resource_len(dev, 0);
70531 - if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
70532 - dbg ("controller already in use");
70533 - pci_disable_device (dev);
70534 - return -EBUSY;
70537 - mem_base = ioremap_nocache (mem_resource, mem_len);
70538 - if (!mem_base) {
70539 - err("Error mapping OHCI memory");
70540 - release_mem_region (mem_resource, mem_len);
70541 - pci_disable_device (dev);
70542 - return -EFAULT;
70545 - /* controller writes into our memory */
70546 - pci_set_master (dev);
70548 - status = hc_found_ohci (dev, dev->irq, mem_base, id);
70549 - if (status < 0) {
70550 - iounmap (mem_base);
70551 - release_mem_region (mem_resource, mem_len);
70552 - pci_disable_device (dev);
70554 - return status;
70557 -/*-------------------------------------------------------------------------*/
70559 -/* may be called from interrupt context [interface spec] */
70560 -/* may be called without controller present */
70561 -/* may be called with controller, bus, and devices active */
70563 -static void __devexit
70564 -ohci_pci_remove (struct pci_dev *dev)
70566 + * Host bus independent remove one OHCI host controller.
70567 + */
70568 +void __devexit hc_remove_ohci(ohci_t *ohci)
70570 - ohci_t *ohci = pci_get_drvdata(dev);
70572 - dbg ("remove %s controller usb-%s%s%s",
70573 - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
70574 - dev->slot_name,
70575 - ohci->disabled ? " (disabled)" : "",
70576 - in_interrupt () ? " in interrupt" : ""
70577 - );
70578 #ifdef DEBUG
70579 ohci_dump (ohci, 1);
70580 #endif
70581 @@ -2692,270 +2545,8 @@
70582 &ohci->regs->control);
70584 hc_release_ohci (ohci);
70586 - release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
70587 - pci_disable_device (dev);
70591 -#ifdef CONFIG_PM
70593 -/*-------------------------------------------------------------------------*/
70595 -static int
70596 -ohci_pci_suspend (struct pci_dev *dev, u32 state)
70598 - ohci_t *ohci = pci_get_drvdata(dev);
70599 - unsigned long flags;
70600 - u16 cmd;
70602 - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
70603 - dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
70604 - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
70605 - return -EIO;
70608 - /* act as if usb suspend can always be used */
70609 - info ("USB suspend: usb-%s", dev->slot_name);
70610 - ohci->sleeping = 1;
70612 - /* First stop processing */
70613 - spin_lock_irqsave (&usb_ed_lock, flags);
70614 - ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
70615 - writel (ohci->hc_control, &ohci->regs->control);
70616 - writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
70617 - (void) readl (&ohci->regs->intrstatus);
70618 - spin_unlock_irqrestore (&usb_ed_lock, flags);
70620 - /* Wait a frame or two */
70621 - mdelay(1);
70622 - if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
70623 - mdelay (1);
70625 -#ifdef CONFIG_PMAC_PBOOK
70626 - if (_machine == _MACH_Pmac)
70627 - disable_irq (ohci->irq);
70628 - /* else, 2.4 assumes shared irqs -- don't disable */
70629 -#endif
70630 - /* Enable remote wakeup */
70631 - writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
70633 - /* Suspend chip and let things settle down a bit */
70634 - ohci->hc_control = OHCI_USB_SUSPEND;
70635 - writel (ohci->hc_control, &ohci->regs->control);
70636 - (void) readl (&ohci->regs->control);
70637 - mdelay (500); /* No schedule here ! */
70638 - switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
70639 - case OHCI_USB_RESET:
70640 - dbg("Bus in reset phase ???");
70641 - break;
70642 - case OHCI_USB_RESUME:
70643 - dbg("Bus in resume phase ???");
70644 - break;
70645 - case OHCI_USB_OPER:
70646 - dbg("Bus in operational phase ???");
70647 - break;
70648 - case OHCI_USB_SUSPEND:
70649 - dbg("Bus suspended");
70650 - break;
70652 - /* In some rare situations, Apple's OHCI have happily trashed
70653 - * memory during sleep. We disable it's bus master bit during
70654 - * suspend
70655 - */
70656 - pci_read_config_word (dev, PCI_COMMAND, &cmd);
70657 - cmd &= ~PCI_COMMAND_MASTER;
70658 - pci_write_config_word (dev, PCI_COMMAND, cmd);
70659 -#ifdef CONFIG_PMAC_PBOOK
70661 - struct device_node *of_node;
70663 - /* Disable USB PAD & cell clock */
70664 - of_node = pci_device_to_OF_node (ohci->ohci_dev);
70665 - if (of_node)
70666 - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
70668 -#endif
70669 - return 0;
70672 -/*-------------------------------------------------------------------------*/
70674 -static int
70675 -ohci_pci_resume (struct pci_dev *dev)
70677 - ohci_t *ohci = pci_get_drvdata(dev);
70678 - int temp;
70679 - unsigned long flags;
70681 - /* guard against multiple resumes */
70682 - atomic_inc (&ohci->resume_count);
70683 - if (atomic_read (&ohci->resume_count) != 1) {
70684 - err ("concurrent PCI resumes for usb-%s", dev->slot_name);
70685 - atomic_dec (&ohci->resume_count);
70686 - return 0;
70689 -#ifdef CONFIG_PMAC_PBOOK
70691 - struct device_node *of_node;
70693 - /* Re-enable USB PAD & cell clock */
70694 - of_node = pci_device_to_OF_node (ohci->ohci_dev);
70695 - if (of_node)
70696 - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
70698 -#endif
70700 - /* did we suspend, or were we powered off? */
70701 - ohci->hc_control = readl (&ohci->regs->control);
70702 - temp = ohci->hc_control & OHCI_CTRL_HCFS;
70704 -#ifdef DEBUG
70705 - /* the registers may look crazy here */
70706 - ohci_dump_status (ohci);
70707 -#endif
70709 - /* Re-enable bus mastering */
70710 - pci_set_master(ohci->ohci_dev);
70712 - switch (temp) {
70714 - case OHCI_USB_RESET: // lost power
70715 - info ("USB restart: usb-%s", dev->slot_name);
70716 - hc_restart (ohci);
70717 - break;
70719 - case OHCI_USB_SUSPEND: // host wakeup
70720 - case OHCI_USB_RESUME: // remote wakeup
70721 - info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
70722 - (temp == OHCI_USB_SUSPEND)
70723 - ? "host" : "remote");
70724 - ohci->hc_control = OHCI_USB_RESUME;
70725 - writel (ohci->hc_control, &ohci->regs->control);
70726 - (void) readl (&ohci->regs->control);
70727 - mdelay (20); /* no schedule here ! */
70728 - /* Some controllers (lucent) need a longer delay here */
70729 - mdelay (15);
70730 - temp = readl (&ohci->regs->control);
70731 - temp = ohci->hc_control & OHCI_CTRL_HCFS;
70732 - if (temp != OHCI_USB_RESUME) {
70733 - err ("controller usb-%s won't resume", dev->slot_name);
70734 - ohci->disabled = 1;
70735 - return -EIO;
70738 - /* Some chips likes being resumed first */
70739 - writel (OHCI_USB_OPER, &ohci->regs->control);
70740 - (void) readl (&ohci->regs->control);
70741 - mdelay (3);
70743 - /* Then re-enable operations */
70744 - spin_lock_irqsave (&usb_ed_lock, flags);
70745 - ohci->disabled = 0;
70746 - ohci->sleeping = 0;
70747 - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
70748 - if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
70749 - if (ohci->ed_controltail)
70750 - ohci->hc_control |= OHCI_CTRL_CLE;
70751 - if (ohci->ed_bulktail)
70752 - ohci->hc_control |= OHCI_CTRL_BLE;
70754 - writel (ohci->hc_control, &ohci->regs->control);
70755 - writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
70756 - writel (OHCI_INTR_SF, &ohci->regs->intrenable);
70757 - /* Check for a pending done list */
70758 - writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
70759 - (void) readl (&ohci->regs->intrdisable);
70760 - spin_unlock_irqrestore (&usb_ed_lock, flags);
70761 -#ifdef CONFIG_PMAC_PBOOK
70762 - if (_machine == _MACH_Pmac)
70763 - enable_irq (ohci->irq);
70764 -#endif
70765 - if (ohci->hcca->done_head)
70766 - dl_done_list (ohci, dl_reverse_done_list (ohci));
70767 - writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
70768 - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
70769 - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
70770 - break;
70772 - default:
70773 - warn ("odd PCI resume for usb-%s", dev->slot_name);
70776 - /* controller is operational, extra resumes are harmless */
70777 - atomic_dec (&ohci->resume_count);
70779 - return 0;
70782 -#endif /* CONFIG_PM */
70785 -/*-------------------------------------------------------------------------*/
70787 -static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
70789 - /*
70790 - * AMD-756 [Viper] USB has a serious erratum when used with
70791 - * lowspeed devices like mice.
70792 - */
70793 - vendor: 0x1022,
70794 - device: 0x740c,
70795 - subvendor: PCI_ANY_ID,
70796 - subdevice: PCI_ANY_ID,
70798 - driver_data: OHCI_QUIRK_AMD756,
70800 -} , {
70802 - /* handle any USB OHCI controller */
70803 - class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
70804 - class_mask: ~0,
70806 - /* no matter who makes it */
70807 - vendor: PCI_ANY_ID,
70808 - device: PCI_ANY_ID,
70809 - subvendor: PCI_ANY_ID,
70810 - subdevice: PCI_ANY_ID,
70812 - }, { /* end: all zeroes */ }
70815 -MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
70817 -static struct pci_driver ohci_pci_driver = {
70818 - name: "usb-ohci",
70819 - id_table: &ohci_pci_ids [0],
70821 - probe: ohci_pci_probe,
70822 - remove: __devexit_p(ohci_pci_remove),
70824 -#ifdef CONFIG_PM
70825 - suspend: ohci_pci_suspend,
70826 - resume: ohci_pci_resume,
70827 -#endif /* PM */
70831 -/*-------------------------------------------------------------------------*/
70833 -static int __init ohci_hcd_init (void)
70835 - return pci_module_init (&ohci_pci_driver);
70838 -/*-------------------------------------------------------------------------*/
70840 -static void __exit ohci_hcd_cleanup (void)
70842 - pci_unregister_driver (&ohci_pci_driver);
70845 -module_init (ohci_hcd_init);
70846 -module_exit (ohci_hcd_cleanup);
70849 MODULE_AUTHOR( DRIVER_AUTHOR );
70850 MODULE_DESCRIPTION( DRIVER_DESC );
70851 MODULE_LICENSE("GPL");
70852 --- linux-2.4.25/drivers/usb/host/usb-ohci.h~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
70853 +++ linux-2.4.25/drivers/usb/host/usb-ohci.h 2004-03-31 17:15:09.000000000 +0200
70854 @@ -386,6 +386,7 @@
70855 struct ohci_regs * regs; /* OHCI controller's memory */
70856 struct list_head ohci_hcd_list; /* list of all ohci_hcd */
70858 + struct ohci * next; // chain of ohci device contexts
70859 struct list_head timeout_list;
70860 // struct list_head urb_list; // list of all pending urbs
70861 // spinlock_t urb_list_lock; // lock to keep consistency
70862 @@ -403,6 +404,7 @@
70864 /* PCI device handle, settings, ... */
70865 struct pci_dev *ohci_dev;
70866 + const char *slot_name;
70867 u8 pci_latency;
70868 struct pci_pool *td_cache;
70869 struct pci_pool *dev_cache;
70870 @@ -448,7 +450,7 @@
70871 #endif
70873 #ifndef CONFIG_PCI
70874 -# error "usb-ohci currently requires PCI-based controllers"
70875 +//# error "usb-ohci currently requires PCI-based controllers"
70876 /* to support non-PCI OHCIs, you need custom bus/mem/... glue */
70877 #endif
70879 @@ -641,3 +643,6 @@
70880 pci_pool_free (hc->dev_cache, dev, dev->dma);
70883 +/* For initializing controller (mask in an HCFS mode too) */
70884 +#define OHCI_CONTROL_INIT \
70885 + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
70886 --- linux-2.4.25/drivers/video/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
70887 +++ linux-2.4.25/drivers/video/Config.in 2004-03-31 17:15:09.000000000 +0200
70888 @@ -30,13 +30,28 @@
70889 tristate ' Permedia3 support (EXPERIMENTAL)' CONFIG_FB_PM3
70892 - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
70893 - bool ' Acorn VIDC support' CONFIG_FB_ACORN
70894 - fi
70895 - dep_tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
70896 - if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
70897 - bool ' SA-1100 LCD support' CONFIG_FB_SA1100
70898 + if [ "$CONFIG_ARM" = "y" ]; then
70899 + if [ "$CONFIG_ARCH_ACORN" -o "$CONFIG_ARCH_RISCSTATION" ]; then
70900 + bool ' Acorn VIDC support' CONFIG_FB_ACORN
70901 + else
70902 + define_bool CONFIG_FB_ACORN n
70903 + fi
70904 + dep_bool ' Anakin LCD support' CONFIG_FB_ANAKIN $CONFIG_ARCH_ANAKIN
70905 + dep_bool ' CLPS711X LCD support' CONFIG_FB_CLPS711X $CONFIG_ARCH_CLPS711X
70906 + dep_bool ' SA-1100 LCD support' CONFIG_FB_SA1100 $CONFIG_ARCH_SA1100
70907 + dep_bool ' MX1ADS LCD support' CONFIG_FB_DBMX1 $CONFIG_ARCH_MX1ADS
70908 + if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF" = "y" ]; then
70909 + choice 'CerfBoard LCD Display Size' \
70910 + "3.8_Color CONFIG_CERF_LCD_38_A \
70911 + 3.8_Mono CONFIG_CERF_LCD_38_B \
70912 + 5.7 CONFIG_CERF_LCD_57_A \
70913 + 7.2 CONFIG_CERF_LCD_72_A" 5.7
70914 + fi
70915 + if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
70916 + bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
70917 + fi
70919 + dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
70920 if [ "$CONFIG_APOLLO" = "y" ]; then
70921 define_bool CONFIG_FB_APOLLO y
70923 @@ -265,7 +280,7 @@
70924 "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \
70925 "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
70926 "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
70927 - "$CONFIG_FB_TX3912" = "y" ]; then
70928 + "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" ]; then
70929 define_tristate CONFIG_FBCON_MFB y
70930 else
70931 if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \
70932 @@ -273,19 +288,20 @@
70933 "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \
70934 "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
70935 "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
70936 - "$CONFIG_FB_TX3912" = "m" ]; then
70937 + "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
70938 define_tristate CONFIG_FBCON_MFB m
70941 if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
70942 "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
70943 - "$CONFIG_FB_TX3912" = "y" ]; then
70944 + "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
70945 + "$CONFIG_FB_DBMX1" = "y" ]; then
70946 define_tristate CONFIG_FBCON_CFB2 y
70947 define_tristate CONFIG_FBCON_CFB4 y
70948 else
70949 if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
70950 "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
70951 - "$CONFIG_FB_TX3912" = "m" ]; then
70952 + "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
70953 define_tristate CONFIG_FBCON_CFB2 m
70954 define_tristate CONFIG_FBCON_CFB4 m
70956 @@ -312,7 +328,8 @@
70957 "$CONFIG_FB_TX3912" = "y" -o \
70958 "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
70959 "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \
70960 - "$CONFIG_FB_INTEL" = "y" ]; then
70961 + "$CONFIG_FB_INTEL" = "y" -o \
70962 + "$CONFIG_FB_DBMX1" = "y" ]; then
70963 define_tristate CONFIG_FBCON_CFB8 y
70964 else
70965 if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
70966 @@ -354,7 +371,9 @@
70967 "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
70968 "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
70969 "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
70970 - "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" ]; then
70971 + "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \
70972 + "$CONFIG_FB_ANAKIN" = "y" -o \
70973 + "$CONFIG_FB_DBMX1" = "y" ]; then
70974 define_tristate CONFIG_FBCON_CFB16 y
70975 else
70976 if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
70977 @@ -509,6 +528,9 @@
70978 if [ "$CONFIG_AMIGA" = "y" ]; then
70979 define_bool CONFIG_FONT_PEARL_8x8 y
70981 + if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
70982 + define_bool CONFIG_FONT_ACORN_8x8 y
70983 + fi
70984 if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then
70985 define_bool CONFIG_FONT_ACORN_8x8 y
70987 --- linux-2.4.25/drivers/video/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
70988 +++ linux-2.4.25/drivers/video/Makefile 2004-03-31 17:15:09.000000000 +0200
70989 @@ -55,6 +55,7 @@
70990 obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
70991 obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
70992 obj-$(CONFIG_FB_CT65550) += chipsfb.o
70993 +obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
70994 obj-$(CONFIG_FB_CYBER) += cyberfb.o
70995 obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
70996 obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
70997 @@ -68,7 +69,7 @@
70998 obj-$(CONFIG_FB_TRIDENT) += tridentfb.o fbgen.o
70999 obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
71000 obj-$(CONFIG_FB_TGA) += tgafb.o fbgen.o
71001 -obj-$(CONFIG_FB_VESA) += vesafb.o
71002 +obj-$(CONFIG_FB_VESA) += vesafb.o
71003 obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o
71004 obj-$(CONFIG_FB_VIRGE) += virgefb.o
71005 obj-$(CONFIG_FB_G364) += g364fb.o
71006 @@ -126,14 +127,16 @@
71008 obj-$(CONFIG_FB_SUN3) += sun3fb.o
71009 obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
71010 -obj-$(CONFIG_FB_HGA) += hgafb.o
71011 +obj-$(CONFIG_FB_HGA) += hgafb.o
71012 obj-$(CONFIG_FB_SA1100) += sa1100fb.o
71013 -obj-$(CONFIG_FB_VIRTUAL) += vfb.o
71014 +obj-$(CONFIG_FB_DBMX1) += dbmx1fb.o
71015 +obj-$(CONFIG_FB_VIRTUAL) += vfb.o
71016 obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o
71017 obj-$(CONFIG_FB_E1355) += epson1355fb.o fbgen.o
71018 obj-$(CONFIG_FB_E1356) += epson1356fb.o
71019 obj-$(CONFIG_FB_PVR2) += pvr2fb.o
71020 obj-$(CONFIG_FB_VOODOO1) += sstfb.o
71021 +obj-$(CONFIG_FB_ANAKIN) += anakinfb.o
71023 # Generic Low Level Drivers
71025 @@ -169,4 +172,3 @@
71026 -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c
71028 promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h
71030 --- linux-2.4.25/drivers/video/acornfb.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
71031 +++ linux-2.4.25/drivers/video/acornfb.c 2004-03-31 17:15:09.000000000 +0200
71032 @@ -752,11 +752,12 @@
71034 #endif
71035 #ifdef FBCON_HAS_CFB16
71036 - if (bpp == 16 && regno < 16) {
71037 + if (bpp == 16) {
71038 int i;
71040 - current_par.cmap.cfb16[regno] =
71041 - regno | regno << 5 | regno << 10;
71042 + if (regno < 16)
71043 + current_par.cmap.cfb16[regno] =
71044 + regno | regno << 5 | regno << 10;
71046 pal.p = 0;
71047 vidc_writel(0x10000000);
71048 @@ -1215,7 +1216,7 @@
71049 p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
71050 p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
71052 - acornfb_palette_write(i, current_par.palette[i]);
71053 + acornfb_palette_write(i, p);
71055 } else
71056 #endif
71057 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
71058 +++ linux-2.4.25/drivers/video/anakinfb.c 2004-03-31 17:15:09.000000000 +0200
71059 @@ -0,0 +1,221 @@
71061 + * linux/drivers/video/anakinfb.c
71063 + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
71065 + * This program is free software; you can redistribute it and/or modify
71066 + * it under the terms of the GNU General Public License version 2 as
71067 + * published by the Free Software Foundation.
71069 + * Changelog:
71070 + * 23-Apr-2001 TTC Created
71071 + */
71073 +#include <linux/types.h>
71074 +#include <linux/fb.h>
71075 +#include <linux/string.h>
71076 +#include <linux/errno.h>
71077 +#include <linux/init.h>
71078 +#include <linux/module.h>
71080 +#include <asm/io.h>
71082 +#include <video/fbcon.h>
71083 +#include <video/fbcon-cfb16.h>
71085 +static u16 colreg[16];
71086 +static int currcon = 0;
71087 +static struct fb_info fb_info;
71088 +static struct display display;
71090 +static int
71091 +anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
71092 + u_int *transp, struct fb_info *info)
71094 + if (regno > 15)
71095 + return 1;
71097 + *red = colreg[regno] & 0xf800;
71098 + *green = colreg[regno] & 0x7e0 << 5;
71099 + *blue = colreg[regno] & 0x1f << 11;
71100 + *transp = 0;
71101 + return 0;
71104 +static int
71105 +anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
71106 + u_int transp, struct fb_info *info)
71108 + if (regno > 15)
71109 + return 1;
71111 + colreg[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) |
71112 + (blue & 0xf800 >> 11);
71113 + return 0;
71116 +static int
71117 +anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
71119 + memset(fix, 0, sizeof(struct fb_fix_screeninfo));
71120 + strcpy(fix->id, "AnakinFB");
71121 + fix->smem_start = VGA_START;
71122 + fix->smem_len = VGA_SIZE;
71123 + fix->type = FB_TYPE_PACKED_PIXELS;
71124 + fix->type_aux = 0;
71125 + fix->visual = FB_VISUAL_TRUECOLOR;
71126 + fix->xpanstep = 0;
71127 + fix->ypanstep = 0;
71128 + fix->ywrapstep = 0;
71129 + fix->line_length = 400 * 2;
71130 + fix->accel = FB_ACCEL_NONE;
71131 + return 0;
71134 +static int
71135 +anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
71137 + memset(var, 0, sizeof(struct fb_var_screeninfo));
71138 + var->xres = 400;
71139 + var->yres = 234;
71140 + var->xres_virtual = 400;
71141 + var->yres_virtual = 234;
71142 + var->xoffset = 0;
71143 + var->yoffset = 0;
71144 + var->bits_per_pixel = 16;
71145 + var->grayscale = 0;
71146 + var->red.offset = 11;
71147 + var->red.length = 5;
71148 + var->green.offset = 5;
71149 + var->green.length = 6;
71150 + var->blue.offset = 0;
71151 + var->blue.length = 5;
71152 + var->transp.offset = 0;
71153 + var->transp.length = 0;
71154 + var->nonstd = 0;
71155 + var->activate = FB_ACTIVATE_NOW;
71156 + var->height = -1;
71157 + var->width = -1;
71158 + var->pixclock = 0;
71159 + var->left_margin = 0;
71160 + var->right_margin = 0;
71161 + var->upper_margin = 0;
71162 + var->lower_margin = 0;
71163 + var->hsync_len = 0;
71164 + var->vsync_len = 0;
71165 + var->sync = 0;
71166 + var->vmode = FB_VMODE_NONINTERLACED;
71167 + return 0;
71170 +static int
71171 +anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
71173 + return -EINVAL;
71176 +static int
71177 +anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
71178 + struct fb_info *info)
71180 + if (con == currcon)
71181 + return fb_get_cmap(cmap, kspc, anakinfb_getcolreg, info);
71182 + else if (fb_display[con].cmap.len)
71183 + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
71184 + else
71185 + fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);
71186 + return 0;
71189 +static int
71190 +anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
71191 + struct fb_info *info)
71193 + int err;
71195 + if (!fb_display[con].cmap.len) {
71196 + if ((err = fb_alloc_cmap(&fb_display[con].cmap, 16, 0)))
71197 + return err;
71199 + if (con == currcon)
71200 + return fb_set_cmap(cmap, kspc, anakinfb_setcolreg, info);
71201 + else
71202 + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
71203 + return 0;
71206 +static int
71207 +anakinfb_switch_con(int con, struct fb_info *info)
71209 + currcon = con;
71210 + return 0;
71214 +static int
71215 +anakinfb_updatevar(int con, struct fb_info *info)
71217 + return 0;
71220 +static void
71221 +anakinfb_blank(int blank, struct fb_info *info)
71223 + /*
71224 + * TODO: use I2C to blank/unblank the screen
71225 + */
71228 +static struct fb_ops anakinfb_ops = {
71229 + owner: THIS_MODULE,
71230 + fb_get_fix: anakinfb_get_fix,
71231 + fb_get_var: anakinfb_get_var,
71232 + fb_set_var: anakinfb_set_var,
71233 + fb_get_cmap: anakinfb_get_cmap,
71234 + fb_set_cmap: anakinfb_set_cmap,
71237 +int __init
71238 +anakinfb_init(void)
71240 + memset(&fb_info, 0, sizeof(struct fb_info));
71241 + strcpy(fb_info.modename, "AnakinFB");
71242 + fb_info.node = -1;
71243 + fb_info.flags = FBINFO_FLAG_DEFAULT;
71244 + fb_info.fbops = &anakinfb_ops;
71245 + fb_info.disp = &display;
71246 + strcpy(fb_info.fontname, "VGA8x16");
71247 + fb_info.changevar = NULL;
71248 + fb_info.switch_con = &anakinfb_switch_con;
71249 + fb_info.updatevar = &anakinfb_updatevar;
71250 + fb_info.blank = &anakinfb_blank;
71252 + memset(&display, 0, sizeof(struct display));
71253 + anakinfb_get_var(&display.var, 0, &fb_info);
71254 + display.screen_base = ioremap(VGA_START, VGA_SIZE);
71255 + display.visual = FB_VISUAL_TRUECOLOR;
71256 + display.type = FB_TYPE_PACKED_PIXELS;
71257 + display.type_aux = 0;
71258 + display.ypanstep = 0;
71259 + display.ywrapstep = 0;
71260 + display.line_length = 400 * 2;
71261 + display.can_soft_blank = 1;
71262 + display.inverse = 0;
71264 +#ifdef FBCON_HAS_CFB16
71265 + display.dispsw = &fbcon_cfb16;
71266 + display.dispsw_data = colreg;
71267 +#else
71268 + display.dispsw = &fbcon_dummy;
71269 +#endif
71271 + if (register_framebuffer(&fb_info) < 0)
71272 + return -EINVAL;
71274 + MOD_INC_USE_COUNT;
71275 + return 0;
71278 +MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
71279 +MODULE_DESCRIPTION("Anakin framebuffer driver");
71280 +MODULE_SUPPORTED_DEVICE("fb");
71281 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
71282 +++ linux-2.4.25/drivers/video/clps711xfb.c 2004-03-31 17:15:09.000000000 +0200
71283 @@ -0,0 +1,677 @@
71285 + * linux/drivers/video/clps711xfb.c
71287 + * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
71289 + * This program is free software; you can redistribute it and/or modify
71290 + * it under the terms of the GNU General Public License as published by
71291 + * the Free Software Foundation; either version 2 of the License, or
71292 + * (at your option) any later version.
71294 + * This program is distributed in the hope that it will be useful,
71295 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
71296 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71297 + * GNU General Public License for more details.
71299 + * You should have received a copy of the GNU General Public License
71300 + * along with this program; if not, write to the Free Software
71301 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
71303 + * Framebuffer driver for the CLPS7111 and EP7212 processors.
71304 + */
71305 +#include <linux/module.h>
71306 +#include <linux/kernel.h>
71307 +#include <linux/slab.h>
71308 +#include <linux/fb.h>
71309 +#include <linux/init.h>
71310 +#include <linux/proc_fs.h>
71311 +#include <linux/delay.h>
71313 +#include <video/fbcon.h>
71314 +#include <video/fbcon-cfb4.h>
71315 +#include <video/fbcon-cfb2.h>
71316 +#include <video/fbcon-mfb.h>
71318 +#include <asm/hardware.h>
71319 +#include <asm/mach-types.h>
71320 +#include <asm/uaccess.h>
71322 +#include <asm/hardware/clps7111.h>
71323 +#include <asm/arch/syspld.h>
71325 +static struct clps7111fb_info {
71326 + struct fb_info fb;
71327 + int currcon;
71328 +} *cfb;
71330 +#define CMAP_MAX_SIZE 16
71332 +/* The /proc entry for the backlight. */
71333 +static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
71335 +static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
71336 + int count, int *eof, void *data);
71337 +static int clps7111fb_proc_backlight_write(struct file *file,
71338 + const char *buffer, unsigned long count, void *data);
71341 + * LCD AC Prescale. This comes from the LCD panel manufacturers specifications.
71342 + * This determines how many clocks + 1 of CL1 before the M signal toggles.
71343 + * The number of lines on the display must not be divisible by this number.
71344 + */
71345 +static unsigned int lcd_ac_prescale = 13;
71348 + * Set a single color register. Return != 0 for invalid regno.
71349 + */
71350 +static int
71351 +clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
71352 + u_int transp, struct fb_info *info)
71354 + unsigned int level, mask, shift, pal;
71356 + if (regno >= (1 << info->var.bits_per_pixel))
71357 + return 1;
71359 + /* gray = 0.30*R + 0.58*G + 0.11*B */
71360 + level = (red * 77 + green * 151 + blue * 28) >> 20;
71362 + /*
71363 + * On an LCD, a high value is dark, while a low value is light.
71364 + * So we invert the level.
71366 + * This isn't true on all machines, so we only do it on EDB7211.
71367 + * --rmk
71368 + */
71369 + if (machine_is_edb7211() || machine_is_guidea07()) {
71370 + level = 15 - level;
71373 + shift = 4 * (regno & 7);
71374 + level <<= shift;
71375 + mask = 15 << shift;
71376 + level &= mask;
71378 + regno = regno < 8 ? PALLSW : PALMSW;
71380 + pal = clps_readl(regno);
71381 + pal = (pal & ~mask) | level;
71382 + clps_writel(pal, regno);
71384 + return 0;
71388 + * Set the colormap
71389 + */
71390 +static int
71391 +clps7111fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
71392 + struct fb_info *info)
71394 + struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
71395 + struct fb_cmap *dcmap = &fb_display[con].cmap;
71396 + int err = 0;
71398 + /* no colormap allocated? */
71399 + if (!dcmap->len)
71400 + err = fb_alloc_cmap(dcmap, CMAP_MAX_SIZE, 0);
71402 + if (!err && con == cfb->currcon) {
71403 + err = fb_set_cmap(cmap, kspc, clps7111fb_setcolreg, &cfb->fb);
71404 + dcmap = &cfb->fb.cmap;
71407 + if (!err)
71408 + fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
71410 + return err;
71414 + * Set the User Defined Part of the Display
71415 + */
71416 +static int
71417 +clps7111fb_set_var(struct fb_var_screeninfo *var, int con,
71418 + struct fb_info *info)
71420 + struct display *display;
71421 + unsigned int lcdcon, syscon, pixclock;
71422 + int chgvar = 0;
71424 + if (var->activate & FB_ACTIVATE_TEST)
71425 + return 0;
71427 + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
71428 + return -EINVAL;
71430 + if (cfb->fb.var.xres != var->xres)
71431 + chgvar = 1;
71432 + if (cfb->fb.var.yres != var->yres)
71433 + chgvar = 1;
71434 + if (cfb->fb.var.xres_virtual != var->xres_virtual)
71435 + chgvar = 1;
71436 + if (cfb->fb.var.yres_virtual != var->yres_virtual)
71437 + chgvar = 1;
71438 + if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
71439 + chgvar = 1;
71441 + if (con < 0) {
71442 + display = cfb->fb.disp;
71443 + chgvar = 0;
71444 + } else {
71445 + display = fb_display + con;
71448 + var->transp.msb_right = 0;
71449 + var->transp.offset = 0;
71450 + var->transp.length = 0;
71451 + var->red.msb_right = 0;
71452 + var->red.offset = 0;
71453 + var->red.length = var->bits_per_pixel;
71454 + var->green = var->red;
71455 + var->blue = var->red;
71457 + switch (var->bits_per_pixel) {
71458 +#ifdef FBCON_HAS_MFB
71459 + case 1:
71460 + cfb->fb.fix.visual = FB_VISUAL_MONO01;
71461 + display->dispsw = &fbcon_mfb;
71462 + display->dispsw_data = NULL;
71463 + break;
71464 +#endif
71465 +#ifdef FBCON_HAS_CFB2
71466 + case 2:
71467 + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
71468 + display->dispsw = &fbcon_cfb2;
71469 + display->dispsw_data = NULL;
71470 + break;
71471 +#endif
71472 +#ifdef FBCON_HAS_CFB4
71473 + case 4:
71474 + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
71475 + display->dispsw = &fbcon_cfb4;
71476 + display->dispsw_data = NULL;
71477 + break;
71478 +#endif
71479 + default:
71480 + return -EINVAL;
71483 + display->next_line = var->xres_virtual * var->bits_per_pixel / 8;
71485 + cfb->fb.fix.line_length = display->next_line;
71487 + display->screen_base = cfb->fb.screen_base;
71488 + display->line_length = cfb->fb.fix.line_length;
71489 + display->visual = cfb->fb.fix.visual;
71490 + display->type = cfb->fb.fix.type;
71491 + display->type_aux = cfb->fb.fix.type_aux;
71492 + display->ypanstep = cfb->fb.fix.ypanstep;
71493 + display->ywrapstep = cfb->fb.fix.ywrapstep;
71494 + display->can_soft_blank = 1;
71495 + display->inverse = 0;
71497 + cfb->fb.var = *var;
71498 + cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
71500 + /*
71501 + * Update the old var. The fbcon drivers still use this.
71502 + * Once they are using cfb->fb.var, this can be dropped.
71503 + * --rmk
71504 + */
71505 + display->var = cfb->fb.var;
71507 + /*
71508 + * If we are setting all the virtual consoles, also set the
71509 + * defaults used to create new consoles.
71510 + */
71511 + if (var->activate & FB_ACTIVATE_ALL)
71512 + cfb->fb.disp->var = cfb->fb.var;
71514 + if (chgvar && info && cfb->fb.changevar)
71515 + cfb->fb.changevar(con);
71517 + lcdcon = (var->xres_virtual * var->yres_virtual * var->bits_per_pixel) / 128 - 1;
71518 + lcdcon |= ((var->xres_virtual / 16) - 1) << 13;
71519 + lcdcon |= lcd_ac_prescale << 25;
71521 + /*
71522 + * Calculate pixel prescale value from the pixclock. This is:
71523 + * 36.864MHz / pixclock_mhz - 1.
71524 + * However, pixclock is in picoseconds, so this ends up being:
71525 + * 36864000 * pixclock_ps / 10^12 - 1
71526 + * and this will overflow the 32-bit math. We perform this as
71527 + * (9 * 4096000 == 36864000):
71528 + * pixclock_ps * 9 * (4096000 / 10^12) - 1
71529 + */
71530 + pixclock = 9 * info->var.pixclock / 244140 - 1;
71531 + lcdcon |= pixclock << 19;
71533 + if (info->var.bits_per_pixel == 4)
71534 + lcdcon |= LCDCON_GSMD;
71535 + if (info->var.bits_per_pixel >= 2)
71536 + lcdcon |= LCDCON_GSEN;
71538 + /*
71539 + * LCDCON must only be changed while the LCD is disabled
71540 + */
71541 + syscon = clps_readl(SYSCON1);
71542 + clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
71543 + clps_writel(lcdcon, LCDCON);
71544 + clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
71546 + fb_set_cmap(&cfb->fb.cmap, 1, clps7111fb_setcolreg, &cfb->fb);
71548 + return 0;
71552 + * Get the currently displayed virtual consoles colormap.
71553 + */
71554 +static int
71555 +gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
71557 + fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
71558 + return 0;
71562 + * Get the currently displayed virtual consoles fixed part of the display.
71563 + */
71564 +static int
71565 +gen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
71567 + *fix = info->fix;
71568 + return 0;
71572 + * Get the current user defined part of the display.
71573 + */
71574 +static int
71575 +gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
71577 + *var = info->var;
71578 + return 0;
71581 +static struct fb_ops clps7111fb_ops = {
71582 + owner: THIS_MODULE,
71583 + fb_set_var: clps7111fb_set_var,
71584 + fb_set_cmap: clps7111fb_set_cmap,
71585 + fb_get_fix: gen_get_fix,
71586 + fb_get_var: gen_get_var,
71587 + fb_get_cmap: gen_get_cmap,
71590 +static int clps7111fb_switch(int con, struct fb_info *info)
71592 + struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
71593 + struct display *disp;
71594 + struct fb_cmap *cmap;
71596 + if (cfb->currcon >= 0) {
71597 + disp = fb_display + cfb->currcon;
71599 + /*
71600 + * Save the old colormap and video mode.
71601 + */
71602 + disp->var = cfb->fb.var;
71603 + if (disp->cmap.len)
71604 + fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
71607 + cfb->currcon = con;
71608 + disp = fb_display + con;
71610 + /*
71611 + * Install the new colormap and change the video mode. By default,
71612 + * fbcon sets all the colormaps and video modes to the default
71613 + * values at bootup.
71614 + */
71615 + if (disp->cmap.len)
71616 + cmap = &disp->cmap;
71617 + else
71618 + cmap = fb_default_cmap(CMAP_MAX_SIZE);
71620 + fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
71622 + cfb->fb.var = disp->var;
71623 + cfb->fb.var.activate = FB_ACTIVATE_NOW;
71625 + clps7111fb_set_var(&cfb->fb.var, con, &cfb->fb);
71627 + return 0;
71630 +static int clps7111fb_updatevar(int con, struct fb_info *info)
71632 + return -EINVAL;
71635 +static void clps7111fb_blank(int blank, struct fb_info *info)
71637 + if (blank) {
71638 + if (machine_is_edb7211()) {
71639 + /* Turn off the LCD backlight. */
71640 + clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
71642 + /* Power off the LCD DC-DC converter. */
71643 + clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
71645 + /* Delay for a little while (half a second). */
71646 + udelay(100);
71648 + /* Power off the LCD panel. */
71649 + clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
71651 + /* Power off the LCD controller. */
71652 + clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
71653 + SYSCON1);
71655 + } else {
71656 + if (machine_is_edb7211()) {
71657 + /* Power up the LCD controller. */
71658 + clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
71659 + SYSCON1);
71661 + /* Power up the LCD panel. */
71662 + clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
71664 + /* Delay for a little while. */
71665 + udelay(100);
71667 + /* Power up the LCD DC-DC converter. */
71668 + clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
71669 + PDDR);
71671 + /* Turn on the LCD backlight. */
71672 + clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
71677 +static int
71678 +clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
71679 + int count, int *eof, void *data)
71681 + /* We need at least two characters, one for the digit, and one for
71682 + * the terminating NULL. */
71683 + if (count < 2)
71684 + return -EINVAL;
71686 + if (machine_is_edb7211()) {
71687 + return sprintf(page, "%d\n",
71688 + (clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
71691 + return 0;
71694 +static int
71695 +clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
71696 + unsigned long count, void *data)
71698 + unsigned char char_value;
71699 + int value;
71701 + if (count < 1) {
71702 + return -EINVAL;
71705 + if (copy_from_user(&char_value, buffer, 1))
71706 + return -EFAULT;
71708 + value = char_value - '0';
71710 + if (machine_is_edb7211()) {
71711 + unsigned char port_d;
71713 + port_d = clps_readb(PDDR);
71715 + if (value) {
71716 + port_d |= EDB_PD3_LCDBL;
71717 + } else {
71718 + port_d &= ~EDB_PD3_LCDBL;
71721 + clps_writeb(port_d, PDDR);
71724 + return count;
71727 +static void __init clps711x_guess_lcd_params(struct fb_info *info)
71729 + unsigned int lcdcon, syscon, size;
71730 + unsigned long phys_base = PHYS_OFFSET;
71731 + void *virt_base = (void *)PAGE_OFFSET;
71733 + info->var.xres_virtual = 640;
71734 + info->var.yres_virtual = 240;
71735 + info->var.bits_per_pixel = 4;
71736 + info->var.activate = FB_ACTIVATE_NOW;
71737 + info->var.height = -1;
71738 + info->var.width = -1;
71739 + info->var.pixclock = 93006; /* 10.752MHz pixel clock */
71741 + /*
71742 + * If the LCD controller is already running, decode the values
71743 + * in LCDCON to xres/yres/bpp/pixclock/acprescale
71744 + */
71745 + syscon = clps_readl(SYSCON1);
71746 + if (syscon & SYSCON1_LCDEN) {
71747 + lcdcon = clps_readl(LCDCON);
71749 + /*
71750 + * Decode GSMD and GSEN bits to bits per pixel
71751 + * (in cs89712 docs, GSEN is GSMD1, GSMD is GSMD2)
71752 + */
71753 + switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
71754 + case LCDCON_GSMD | LCDCON_GSEN:
71755 + info->var.bits_per_pixel = 4;
71756 + break;
71758 + case LCDCON_GSEN:
71759 + info->var.bits_per_pixel = 2;
71760 + break;
71762 + default:
71763 + info->var.bits_per_pixel = 1;
71764 + break;
71767 + /*
71768 + * Decode xres/yres
71769 + */
71770 + info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
71771 + info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
71772 + (info->var.xres_virtual *
71773 + info->var.bits_per_pixel);
71775 + /*
71776 + * Calculate pixclock
71777 + */
71778 + info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
71780 + /*
71781 + * Grab AC prescale
71782 + */
71783 + lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
71786 + info->var.xres = info->var.xres_virtual;
71787 + info->var.yres = info->var.yres_virtual;
71788 + info->var.grayscale = info->var.bits_per_pixel > 1;
71790 + size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
71792 + /*
71793 + * Might be worth checking to see if we can use the on-board
71794 + * RAM if size here...
71795 + * CLPS7110 - no on-board SRAM
71796 + * EP7212 - 38400 bytes
71797 + */
71798 + if (size <= 38400) {
71799 + printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
71802 + if ((syscon & SYSCON1_LCDEN) == 0) {
71803 + /*
71804 + * The display isn't running. Ensure that
71805 + * the display memory is empty.
71806 + */
71807 + memset(virt_base, 0, size);
71810 + info->screen_base = virt_base;
71811 + info->fix.smem_start = phys_base;
71812 + info->fix.smem_len = PAGE_ALIGN(size);
71813 + info->fix.type = FB_TYPE_PACKED_PIXELS;
71816 +/* this function initializes the LCD registers as required by the Guide A07
71818 +int __init clps711xfb_guidea07_init(void)
71820 + unsigned long videomem, videosize;
71821 + unsigned int lcdcon, syscon;
71823 + //LCDCON must only be changed while the LCD is disabled
71824 + syscon = clps_readl(SYSCON1);
71825 + clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
71827 + printk(KERN_INFO "CLPS711xFB: setting up cs89712 SRAM as QVGA video framebuffer\n");
71828 + clps_writel(0x6, FBADDR); //internal SRAM location
71829 + videomem = (unsigned long)ioremap(SRAM_START, SRAM_SIZE);
71830 + if (!videomem) {
71831 + printk("ioremap failed!\n");
71832 + kfree(cfb);
71833 + return -EIO;
71836 + videosize = (320*240 * 4 / 8); //ie. 38400 or 0x9600
71837 + memset((void *)videomem, 0, videosize); //clear the vid memory
71839 + cfb->fb.screen_base = (void *)videomem;
71840 + cfb->fb.fix.smem_start = SRAM_START; //must be physical address
71841 + cfb->fb.fix.smem_len = videosize;
71843 + cfb->fb.var.grayscale = 1;
71844 + cfb->fb.var.bits_per_pixel = 4;
71845 + cfb->fb.var.xres_virtual = 320;
71846 + cfb->fb.var.activate = FB_ACTIVATE_NOW;
71848 + // change to 4bpp mode
71849 + lcdcon = clps_readl(LCDCON);
71850 + lcdcon |= LCDCON_GSMD | LCDCON_GSEN; //4bpp
71851 + //lcdcon |= 5 << 19; //pixel prescale value (pixclock)
71852 + //lcdcon |= 13 << 25; //AC prescale value
71853 + clps_writel(lcdcon, LCDCON);
71855 + //reenable LCD
71856 + clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
71858 + return 0;
71861 +int __init clps711xfb_init(void)
71863 + int err = -ENOMEM;
71865 + cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
71866 + if (!cfb)
71867 + goto out;
71869 + memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
71870 + strcpy(cfb->fb.fix.id, "clps7111");
71872 + cfb->currcon = -1;
71873 + cfb->fb.screen_base = (void *)PAGE_OFFSET;
71874 + cfb->fb.fix.smem_start = PAGE_OFFSET;
71875 + cfb->fb.fix.smem_len = 0x14000;
71876 + cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
71878 + cfb->fb.fbops = &clps7111fb_ops;
71879 + cfb->fb.changevar = NULL;
71880 + cfb->fb.switch_con = clps7111fb_switch;
71881 + cfb->fb.updatevar = clps7111fb_updatevar;
71882 + cfb->fb.blank = clps7111fb_blank;
71883 + cfb->fb.flags = FBINFO_FLAG_DEFAULT;
71884 + cfb->fb.disp = (struct display *)(cfb + 1);
71886 + clps711x_guess_lcd_params(&cfb->fb);
71888 + if (machine_is_guidea07()) {
71889 + clps711xfb_guidea07_init();
71892 + if (machine_is_fortunet()) {
71893 + cfb->fb.fix.smem_len = 0x20000;
71896 + fb_alloc_cmap(&cfb->fb.cmap, CMAP_MAX_SIZE, 0);
71898 + /* Register the /proc entries. */
71899 + clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
71900 + &proc_root);
71901 + if (clps7111fb_backlight_proc_entry == NULL) {
71902 + printk("Couldn't create the /proc entry for the backlight.\n");
71903 + return -EINVAL;
71906 + clps7111fb_backlight_proc_entry->read_proc =
71907 + &clps7111fb_proc_backlight_read;
71908 + clps7111fb_backlight_proc_entry->write_proc =
71909 + &clps7111fb_proc_backlight_write;
71911 + /*
71912 + * Power up the LCD
71913 + */
71914 + if (machine_is_p720t()) {
71915 + PLD_LCDEN = PLD_LCDEN_EN;
71916 + PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
71919 + if (machine_is_edb7211()) {
71920 + /* Power up the LCD panel. */
71921 + clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
71923 + /* Delay for a little while. */
71924 + udelay(100);
71926 + /* Power up the LCD DC-DC converter. */
71927 + clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
71929 + /* Turn on the LCD backlight. */
71930 + clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
71933 + clps7111fb_set_var(&cfb->fb.var, -1, &cfb->fb);
71934 + err = register_framebuffer(&cfb->fb);
71936 +out: return err;
71939 +static void __exit clps711xfb_exit(void)
71941 + unregister_framebuffer(&cfb->fb);
71942 + kfree(cfb);
71944 + /*
71945 + * Power down the LCD
71946 + */
71947 + if (machine_is_p720t()) {
71948 + PLD_LCDEN = 0;
71949 + PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
71953 +#ifdef MODULE
71954 +module_init(clps711xfb_init);
71955 +#endif
71956 +module_exit(clps711xfb_exit);
71958 +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
71959 +MODULE_DESCRIPTION("CLPS711x framebuffer driver");
71960 +MODULE_LICENSE("GPL");
71961 --- linux-2.4.25/drivers/video/cyber2000fb.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
71962 +++ linux-2.4.25/drivers/video/cyber2000fb.c 2004-03-31 17:15:09.000000000 +0200
71963 @@ -1,7 +1,7 @@
71965 * linux/drivers/video/cyber2000fb.c
71967 - * Copyright (C) 1998-2000 Russell King
71968 + * Copyright (C) 1998-2002 Russell King
71970 * MIPS and 50xx clock support
71971 * Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
71972 @@ -13,22 +13,28 @@
71973 * it under the terms of the GNU General Public License version 2 as
71974 * published by the Free Software Foundation.
71976 - * Intergraphics CyberPro 2000, 2010 and 5000 frame buffer device
71977 + * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
71979 * Based on cyberfb.c.
71981 - * Note that we now use the new fbcon fix, var and cmap scheme. We do still
71982 - * have to check which console is the currently displayed one however, since
71983 - * especially for the colourmap stuff. Once fbcon has been fully migrated,
71984 - * we can kill the last 5 references to cfb->currcon.
71985 + * Note that we now use the new fbcon fix, var and cmap scheme. We do
71986 + * still have to check which console is the currently displayed one
71987 + * however, especially for the colourmap stuff.
71989 - * We also use the new hotplug PCI subsystem. I'm not sure if there are any
71990 - * such cards, but I'm erring on the side of caution. We don't want to go
71991 - * pop just because someone does have one.
71992 + * We also use the new hotplug PCI subsystem. I'm not sure if there
71993 + * are any such cards, but I'm erring on the side of caution. We don't
71994 + * want to go pop just because someone does have one.
71996 - * Note that this doesn't work fully in the case of multiple CyberPro cards
71997 - * with grabbers. We currently can only attach to the first CyberPro card
71998 - * found.
71999 + * Note that this doesn't work fully in the case of multiple CyberPro
72000 + * cards with grabbers. We currently can only attach to the first
72001 + * CyberPro card found.
72003 + * When we're in truecolour mode, we power down the LUT RAM as a power
72004 + * saving feature. Also, when we enter any of the powersaving modes
72005 + * (except soft blanking) we power down the RAMDACs. This saves about
72006 + * 1W, which is roughly 8% of the power consumption of a NetWinder
72007 + * (which, incidentally, is about the same saving as a 2.5in hard disk
72008 + * entering standby mode.)
72010 #include <linux/config.h>
72011 #include <linux/module.h>
72012 @@ -55,20 +61,16 @@
72013 #include <video/fbcon-cfb24.h>
72014 #include <video/fbcon-cfb32.h>
72017 - * Define this if you don't want RGB565, but RGB555 for 16bpp displays.
72018 - */
72019 -/*#define CFB16_IS_CFB15*/
72021 #include "cyber2000fb.h"
72023 struct cfb_info {
72024 struct fb_info fb;
72025 struct display_switch *dispsw;
72026 + struct display *display;
72027 struct pci_dev *dev;
72028 unsigned char *region;
72029 unsigned char *regs;
72030 - signed int currcon;
72031 + u_int id;
72032 int func_use_count;
72033 u_long ref_ps;
72035 @@ -81,10 +83,16 @@
72036 u8 red, green, blue;
72037 } palette[NR_PALETTE];
72039 + u_char mem_ctl0;
72040 u_char mem_ctl1;
72041 u_char mem_ctl2;
72042 u_char mclk_mult;
72043 u_char mclk_div;
72044 + /*
72045 + * RAMDAC control register is both of these or'ed together
72046 + */
72047 + u_char ramdac_ctrl;
72048 + u_char ramdac_powerdown;
72051 static char default_font_storage[40];
72052 @@ -144,7 +152,7 @@
72054 int count = 100000;
72056 - while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & 0x80) {
72057 + while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
72058 if (!count--) {
72059 debug_printf("accel_wait timed out\n");
72060 cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
72061 @@ -154,24 +162,23 @@
72065 -static void cyber2000_accel_setup(struct display *p)
72066 +static void cyber2000_accel_setup(struct display *display)
72068 - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
72069 + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
72071 - cfb->dispsw->setup(p);
72072 + cfb->dispsw->setup(display);
72075 static void
72076 -cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
72077 +cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
72078 int height, int width)
72080 - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
72081 - struct fb_var_screeninfo *var = &p->fb_info->var;
72082 + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
72083 + struct fb_var_screeninfo *var = &display->var;
72084 u_long src, dst;
72085 - u_int fh, fw;
72086 - int cmd = CO_CMD_L_PATTERN_FGCOL;
72087 + u_int fh, fw, cmd = CO_CMD_L_PATTERN_FGCOL;
72089 - fw = fontwidth(p);
72090 + fw = fontwidth(display);
72091 sx *= fw;
72092 dx *= fw;
72093 width *= fw;
72094 @@ -183,7 +190,7 @@
72095 cmd |= CO_CMD_L_INC_LEFT;
72098 - fh = fontheight(p);
72099 + fh = fontheight(display);
72100 sy *= fh;
72101 dy *= fh;
72102 height *= fh;
72103 @@ -199,227 +206,265 @@
72104 dst = dx + dy * var->xres_virtual;
72106 cyber2000_accel_wait(cfb);
72107 - cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
72108 - cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
72109 - cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
72110 + cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
72111 + cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
72112 + cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
72114 - if (var->bits_per_pixel != 24) {
72115 - cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
72116 - cyber2000fb_writel(src, CO_REG_SRC_PTR, cfb);
72117 - } else {
72118 - cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
72119 - cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
72120 - cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
72121 + if (var->bits_per_pixel == 24) {
72122 + cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
72123 + dst *= 3;
72124 + src *= 3;
72127 - cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
72128 - cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
72129 - cyber2000fb_writew(0x2800, CO_REG_CMD_H, cfb);
72130 + cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
72131 + cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
72132 + cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
72133 + cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
72134 + cyber2000fb_writew(CO_CMD_H_FGSRCMAP|CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
72137 static void
72138 -cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
72139 - int height, int width)
72140 +cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
72141 + int sx, int height, int width)
72143 - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
72144 - struct fb_var_screeninfo *var = &p->fb_info->var;
72145 + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
72146 + struct fb_var_screeninfo *var = &display->var;
72147 u_long dst;
72148 u_int fw, fh;
72149 - u32 bgx = attr_bgcol_ec(p, conp);
72150 + u32 bgx = attr_bgcol_ec(display, conp);
72152 - fw = fontwidth(p);
72153 - fh = fontheight(p);
72154 + fw = fontwidth(display);
72155 + fh = fontheight(display);
72157 dst = sx * fw + sy * var->xres_virtual * fh;
72158 width = width * fw - 1;
72159 height = height * fh - 1;
72161 cyber2000_accel_wait(cfb);
72162 - cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
72163 - cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
72164 - cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
72165 - cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
72167 - switch (var->bits_per_pixel) {
72168 - case 15:
72169 - case 16:
72170 - bgx = ((u16 *)p->dispsw_data)[bgx];
72171 - case 8:
72172 - cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
72173 - break;
72174 + cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
72175 + cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
72176 + cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
72178 - case 24:
72179 - cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
72180 + if (var->bits_per_pixel == 24) {
72181 cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
72182 - bgx = ((u32 *)p->dispsw_data)[bgx];
72183 - break;
72185 - case 32:
72186 - bgx = ((u32 *)p->dispsw_data)[bgx];
72187 - cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
72188 - break;
72189 + dst *= 3;
72192 - cyber2000fb_writel(bgx, CO_REG_FOREGROUND, cfb);
72193 + if (var->bits_per_pixel == 16)
72194 + bgx = ((u16 *)display->dispsw_data)[bgx];
72195 + else if (var->bits_per_pixel >= 24)
72196 + bgx = ((u32 *)display->dispsw_data)[bgx];
72198 + cyber2000fb_writel(bgx, CO_REG_FGCOLOUR, cfb);
72199 + cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
72200 + cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
72201 cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
72202 - cyber2000fb_writew(0x0800, CO_REG_CMD_H, cfb);
72203 + cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
72206 static void
72207 -cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c,
72208 +cyber2000_accel_putc(struct vc_data *conp, struct display *display, int c,
72209 int yy, int xx)
72211 - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
72212 + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
72214 cyber2000_accel_wait(cfb);
72215 - cfb->dispsw->putc(conp, p, c, yy, xx);
72216 + cfb->dispsw->putc(conp, display, c, yy, xx);
72219 static void
72220 -cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
72221 +cyber2000_accel_putcs(struct vc_data *conp, struct display *display,
72222 const unsigned short *s, int count, int yy, int xx)
72224 - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
72225 + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
72227 cyber2000_accel_wait(cfb);
72228 - cfb->dispsw->putcs(conp, p, s, count, yy, xx);
72229 + cfb->dispsw->putcs(conp, display, s, count, yy, xx);
72232 -static void cyber2000_accel_revc(struct display *p, int xx, int yy)
72233 +static void cyber2000_accel_revc(struct display *display, int xx, int yy)
72235 - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
72236 + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
72238 cyber2000_accel_wait(cfb);
72239 - cfb->dispsw->revc(p, xx, yy);
72240 + cfb->dispsw->revc(display, xx, yy);
72243 static void
72244 -cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p,
72245 +cyber2000_accel_clear_margins(struct vc_data *conp, struct display *display,
72246 int bottom_only)
72248 - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
72249 + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
72251 - cfb->dispsw->clear_margins(conp, p, bottom_only);
72252 + cfb->dispsw->clear_margins(conp, display, bottom_only);
72255 static struct display_switch fbcon_cyber_accel = {
72256 - setup: cyber2000_accel_setup,
72257 - bmove: cyber2000_accel_bmove,
72258 - clear: cyber2000_accel_clear,
72259 - putc: cyber2000_accel_putc,
72260 - putcs: cyber2000_accel_putcs,
72261 - revc: cyber2000_accel_revc,
72262 - clear_margins: cyber2000_accel_clear_margins,
72263 - fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16)
72264 + .setup = cyber2000_accel_setup,
72265 + .bmove = cyber2000_accel_bmove,
72266 + .clear = cyber2000_accel_clear,
72267 + .putc = cyber2000_accel_putc,
72268 + .putcs = cyber2000_accel_putcs,
72269 + .revc = cyber2000_accel_revc,
72270 + .clear_margins = cyber2000_accel_clear_margins,
72271 + .fontwidthmask = FONTWIDTH(8)|FONTWIDTH(16)
72274 +static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
72276 + u_int mask = (1 << bf->length) - 1;
72278 + return (val >> (16 - bf->length) & mask) << bf->offset;
72282 * Set a single color register. Return != 0 for invalid regno.
72284 static int
72285 -cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
72286 - u_int transp, struct fb_info *info)
72287 +cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
72288 + u_int transp, struct fb_info *info)
72290 struct cfb_info *cfb = (struct cfb_info *)info;
72291 + struct fb_var_screeninfo *var = &cfb->display->var;
72292 + u32 pseudo_val;
72293 + int ret = 1;
72295 - u_int alpha = transp ^ 0xFFFF;
72297 - if (regno >= NR_PALETTE)
72298 + switch (cfb->fb.fix.visual) {
72299 + default:
72300 return 1;
72302 - red >>= 8;
72303 - green >>= 8;
72304 - blue >>= 8;
72305 - alpha >>= 8;
72306 +#ifdef FBCON_HAS_CFB8
72307 + /*
72308 + * Pseudocolour:
72309 + * 8 8
72310 + * pixel --/--+--/--> red lut --> red dac
72311 + * | 8
72312 + * +--/--> green lut --> green dac
72313 + * | 8
72314 + * +--/--> blue lut --> blue dac
72315 + */
72316 + case FB_VISUAL_PSEUDOCOLOR:
72317 + if (regno >= NR_PALETTE)
72318 + return 1;
72320 - cfb->palette[regno].red = red;
72321 - cfb->palette[regno].green = green;
72322 - cfb->palette[regno].blue = blue;
72323 + red >>= 8;
72324 + green >>= 8;
72325 + blue >>= 8;
72327 + cfb->palette[regno].red = red;
72328 + cfb->palette[regno].green = green;
72329 + cfb->palette[regno].blue = blue;
72331 - switch (cfb->fb.var.bits_per_pixel) {
72332 -#ifdef FBCON_HAS_CFB8
72333 - case 8:
72334 cyber2000fb_writeb(regno, 0x3c8, cfb);
72335 - cyber2000fb_writeb(red, 0x3c9, cfb);
72336 + cyber2000fb_writeb(red, 0x3c9, cfb);
72337 cyber2000fb_writeb(green, 0x3c9, cfb);
72338 - cyber2000fb_writeb(blue, 0x3c9, cfb);
72339 - break;
72340 + cyber2000fb_writeb(blue, 0x3c9, cfb);
72341 + return 0;
72342 #endif
72344 -#ifdef FBCON_HAS_CFB16
72345 - case 16:
72346 -#ifndef CFB16_IS_CFB15
72347 - if (regno < 64) {
72348 - /* write green */
72349 + /*
72350 + * Direct colour:
72351 + * n rl
72352 + * pixel --/--+--/--> red lut --> red dac
72353 + * | gl
72354 + * +--/--> green lut --> green dac
72355 + * | bl
72356 + * +--/--> blue lut --> blue dac
72357 + * n = bpp, rl = red length, gl = green length, bl = blue length
72358 + */
72359 + case FB_VISUAL_DIRECTCOLOR:
72360 + red >>= 8;
72361 + green >>= 8;
72362 + blue >>= 8;
72364 + if (var->green.length == 6 && regno < 64) {
72365 + cfb->palette[regno << 2].green = green;
72367 + /*
72368 + * The 6 bits of the green component are applied
72369 + * to the high 6 bits of the LUT.
72370 + */
72371 cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
72372 cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
72373 cyber2000fb_writeb(green, 0x3c9, cfb);
72374 cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
72376 + green = cfb->palette[regno << 3].green;
72378 + ret = 0;
72381 - if (regno < 32) {
72382 - /* write red,blue */
72383 + if (var->green.length >= 5 && regno < 32) {
72384 + cfb->palette[regno << 3].red = red;
72385 + cfb->palette[regno << 3].green = green;
72386 + cfb->palette[regno << 3].blue = blue;
72388 + /*
72389 + * The 5 bits of each colour component are
72390 + * applied to the high 5 bits of the LUT.
72391 + */
72392 cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
72393 cyber2000fb_writeb(red, 0x3c9, cfb);
72394 - cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
72395 + cyber2000fb_writeb(green, 0x3c9, cfb);
72396 cyber2000fb_writeb(blue, 0x3c9, cfb);
72397 + ret = 0;
72400 - if (regno < 16)
72401 - ((u16 *)cfb->fb.pseudo_palette)[regno] =
72402 - ((red << 8) & 0xf800) |
72403 - ((green << 3) & 0x07e0) |
72404 - ((blue >> 3));
72405 - break;
72406 -#endif
72407 + if (var->green.length == 4 && regno < 16) {
72408 + cfb->palette[regno << 4].red = red;
72409 + cfb->palette[regno << 4].green = green;
72410 + cfb->palette[regno << 4].blue = blue;
72412 - case 15:
72413 - if (regno < 32) {
72414 - cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
72415 + /*
72416 + * The 5 bits of each colour component are
72417 + * applied to the high 5 bits of the LUT.
72418 + */
72419 + cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
72420 cyber2000fb_writeb(red, 0x3c9, cfb);
72421 cyber2000fb_writeb(green, 0x3c9, cfb);
72422 cyber2000fb_writeb(blue, 0x3c9, cfb);
72423 + ret = 0;
72425 - if (regno < 16)
72426 - ((u16 *)cfb->fb.pseudo_palette)[regno] =
72427 - ((red << 7) & 0x7c00) |
72428 - ((green << 2) & 0x03e0) |
72429 - ((blue >> 3));
72430 - break;
72432 -#endif
72434 -#ifdef FBCON_HAS_CFB24
72435 - case 24:
72436 - cyber2000fb_writeb(regno, 0x3c8, cfb);
72437 - cyber2000fb_writeb(red, 0x3c9, cfb);
72438 - cyber2000fb_writeb(green, 0x3c9, cfb);
72439 - cyber2000fb_writeb(blue, 0x3c9, cfb);
72441 - if (regno < 16)
72442 - ((u32 *)cfb->fb.pseudo_palette)[regno] =
72443 - (red << 16) | (green << 8) | blue;
72444 + /*
72445 + * Since this is only used for the first 16 colours, we
72446 + * don't have to care about overflowing for regno >= 32
72447 + */
72448 + pseudo_val = regno << var->red.offset |
72449 + regno << var->green.offset |
72450 + regno << var->blue.offset;
72451 break;
72452 -#endif
72454 -#ifdef FBCON_HAS_CFB32
72455 - case 32:
72456 - cyber2000fb_writeb(regno, 0x3c8, cfb);
72457 - cyber2000fb_writeb(red, 0x3c9, cfb);
72458 - cyber2000fb_writeb(green, 0x3c9, cfb);
72459 - cyber2000fb_writeb(blue, 0x3c9, cfb);
72461 - if (regno < 16)
72462 - ((u32 *)cfb->fb.pseudo_palette)[regno] =
72463 - (alpha << 24) | (red << 16) | (green << 8) | blue;
72464 + /*
72465 + * True colour:
72466 + * n rl
72467 + * pixel --/--+--/--> red dac
72468 + * | gl
72469 + * +--/--> green dac
72470 + * | bl
72471 + * +--/--> blue dac
72472 + * n = bpp, rl = red length, gl = green length, bl = blue length
72473 + */
72474 + case FB_VISUAL_TRUECOLOR:
72475 + pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
72476 + pseudo_val |= convert_bitfield(red, &var->red);
72477 + pseudo_val |= convert_bitfield(green, &var->green);
72478 + pseudo_val |= convert_bitfield(blue, &var->blue);
72479 break;
72480 -#endif
72483 - default:
72484 - return 1;
72485 + /*
72486 + * Now set our pseudo palette for the CFB16/24/32 drivers.
72487 + */
72488 + if (regno < 16) {
72489 + if (var->bits_per_pixel == 16)
72490 + ((u16 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
72491 + else
72492 + ((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
72493 + ret = 0;
72496 - return 0;
72497 + return ret;
72500 struct par_info {
72501 @@ -428,8 +473,8 @@
72503 u_char clock_mult;
72504 u_char clock_div;
72505 - u_char visualid;
72506 - u_char pixformat;
72507 + u_char extseqmisc;
72508 + u_char co_pixfmt;
72509 u_char crtc_ofl;
72510 u_char crtc[19];
72511 u_int width;
72512 @@ -439,8 +484,7 @@
72514 * Other
72516 - u_char palette_ctrl;
72517 - u_int vmode;
72518 + u_char ramdac;
72521 static const u_char crtc_idx[] = {
72522 @@ -449,6 +493,18 @@
72523 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
72526 +static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
72528 + unsigned int i;
72529 + unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
72531 + cyber2000fb_writeb(0x56, 0x3ce, cfb);
72532 + i = cyber2000fb_readb(0x3cf, cfb);
72533 + cyber2000fb_writeb(i | 4, 0x3cf, cfb);
72534 + cyber2000fb_writeb(val, 0x3c6, cfb);
72535 + cyber2000fb_writeb(i, 0x3cf, cfb);
72538 static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
72540 u_int i;
72541 @@ -480,7 +536,7 @@
72542 for (i = 0x0a; i < 0x10; i++)
72543 cyber2000_crtcw(i, 0, cfb);
72545 - cyber2000_grphw(0x11, hw->crtc_ofl, cfb);
72546 + cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
72547 cyber2000_grphw(0x00, 0x00, cfb);
72548 cyber2000_grphw(0x01, 0x00, cfb);
72549 cyber2000_grphw(0x02, 0x00, cfb);
72550 @@ -501,30 +557,17 @@
72551 cyber2000_attrw(0x13, 0x00, cfb);
72552 cyber2000_attrw(0x14, 0x00, cfb);
72554 - /* woody: set the interlaced bit... */
72555 - /* FIXME: what about doublescan? */
72556 - cyber2000fb_writeb(0x11, 0x3ce, cfb);
72557 - i = cyber2000fb_readb(0x3cf, cfb);
72558 - if (hw->vmode == FB_VMODE_INTERLACED)
72559 - i |= 0x20;
72560 - else
72561 - i &= ~0x20;
72562 - cyber2000fb_writeb(i, 0x3cf, cfb);
72564 /* PLL registers */
72565 - cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
72566 - cyber2000_grphw(DCLK_DIV, hw->clock_div, cfb);
72567 - cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
72568 - cyber2000_grphw(MCLK_DIV, cfb->mclk_div, cfb);
72569 + cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
72570 + cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
72571 + cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
72572 + cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
72573 cyber2000_grphw(0x90, 0x01, cfb);
72574 cyber2000_grphw(0xb9, 0x80, cfb);
72575 cyber2000_grphw(0xb9, 0x00, cfb);
72577 - cyber2000fb_writeb(0x56, 0x3ce, cfb);
72578 - i = cyber2000fb_readb(0x3cf, cfb);
72579 - cyber2000fb_writeb(i | 4, 0x3cf, cfb);
72580 - cyber2000fb_writeb(hw->palette_ctrl, 0x3c6, cfb);
72581 - cyber2000fb_writeb(i, 0x3cf, cfb);
72582 + cfb->ramdac_ctrl = hw->ramdac;
72583 + cyber2000fb_write_ramdac_ctrl(cfb);
72585 cyber2000fb_writeb(0x20, 0x3c0, cfb);
72586 cyber2000fb_writeb(0xff, 0x3c6, cfb);
72587 @@ -532,31 +575,32 @@
72588 cyber2000_grphw(0x14, hw->fetch, cfb);
72589 cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
72590 ((hw->pitch >> 4) & 0x30), cfb);
72591 - cyber2000_grphw(0x77, hw->visualid, cfb);
72592 + cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
72594 - /* make sure we stay in linear mode */
72595 - cyber2000_grphw(0x33, 0x0d, cfb);
72596 +// cyber2000_grphw(EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
72597 +// EXT_BIU_MISC_COP_ENABLE |
72598 +// EXT_BIU_MISC_COP_BFC, cfb);
72601 * Set up accelerator registers
72603 cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
72604 cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
72605 - cyber2000fb_writeb(hw->pixformat, CO_REG_PIX_FORMAT, cfb);
72606 + cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
72609 static inline int
72610 cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
72612 - u_int base;
72614 - base = var->yoffset * var->xres_virtual + var->xoffset;
72615 + u_int base = var->yoffset * var->xres_virtual + var->xoffset;
72617 - /* have to be careful, because bits_per_pixel might be 15
72618 - in this version of the driver -- dok@directfb.org 2002/06/13 */
72619 - base *= (var->bits_per_pixel + 7) >> 3;
72620 + base *= var->bits_per_pixel;
72622 - base >>= 2;
72623 + /*
72624 + * Convert to bytes and shift two extra bits because DAC
72625 + * can only start on 4 byte aligned data.
72626 + */
72627 + base >>= 5;
72629 if (base >= 1 << 20)
72630 return -EINVAL;
72631 @@ -576,27 +620,20 @@
72632 struct fb_info *info)
72634 struct cfb_info *cfb = (struct cfb_info *)info;
72635 - struct fb_cmap *dcmap = &fb_display[con].cmap;
72636 + struct display *display = fb_display + con;
72637 + struct fb_cmap *dcmap = &display->cmap;
72638 int err = 0;
72640 /* no colormap allocated? */
72641 - if (!dcmap->len) {
72642 - int size;
72644 - if (cfb->fb.var.bits_per_pixel == 16)
72645 - size = 32;
72646 - else
72647 - size = 256;
72649 - err = fb_alloc_cmap(dcmap, size, 0);
72651 + if (!dcmap->len)
72652 + err = fb_alloc_cmap(dcmap, 256, 0);
72655 * we should be able to remove this test once fbcon has been
72656 * "improved" --rmk
72658 - if (!err && con == cfb->currcon) {
72659 - err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, &cfb->fb);
72660 + if (!err && display == cfb->display) {
72661 + err = fb_set_cmap(cmap, kspc, cyber2000fb_setcolreg, &cfb->fb);
72662 dcmap = &cfb->fb.cmap;
72665 @@ -672,8 +709,9 @@
72666 hw->crtc[16] = Vblankend;
72667 hw->crtc[18] = 0xff;
72669 - /* overflow - graphics reg 0x11 */
72670 - /* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
72671 + /*
72672 + * overflow - graphics reg 0x11
72673 + * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
72674 * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
72676 hw->crtc_ofl =
72677 @@ -681,7 +719,12 @@
72678 BIT(Vdispend, 10, 0x01, 1) |
72679 BIT(Vsyncstart, 10, 0x01, 2) |
72680 BIT(Vblankstart,10, 0x01, 3) |
72681 - 1 << 4;
72682 + EXT_CRT_VRTOFL_LINECOMP10;
72684 + /* woody: set the interlaced bit... */
72685 + /* FIXME: what about doublescan? */
72686 + if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
72687 + hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
72689 return 0;
72691 @@ -787,7 +830,7 @@
72692 vco = ref_ps * best_div1 / best_mult;
72693 if ((ref_ps == 40690) && (vco < 5556))
72694 /* Set VFSEL when VCO > 180MHz (5.556 ps). */
72695 - hw->clock_div |= DCLK_DIV_VFSEL;
72696 + hw->clock_div |= EXT_DCLK_DIV_VFSEL;
72698 return 0;
72700 @@ -801,58 +844,131 @@
72701 cyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb,
72702 struct par_info *hw)
72704 + unsigned int mem;
72705 int err;
72707 hw->width = var->xres_virtual;
72708 - hw->palette_ctrl = 0x06;
72709 - hw->vmode = var->vmode;
72710 + hw->ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
72712 + var->transp.msb_right = 0;
72713 + var->red.msb_right = 0;
72714 + var->green.msb_right = 0;
72715 + var->blue.msb_right = 0;
72717 switch (var->bits_per_pixel) {
72718 #ifdef FBCON_HAS_CFB8
72719 case 8: /* PSEUDOCOLOUR, 256 */
72720 - hw->pixformat = PIXFORMAT_8BPP;
72721 - hw->visualid = VISUALID_256;
72722 + hw->co_pixfmt = CO_PIXFMT_8BPP;
72723 hw->pitch = hw->width >> 3;
72724 + hw->extseqmisc = EXT_SEQ_MISC_8;
72726 + var->transp.offset = 0;
72727 + var->transp.length = 0;
72728 + var->red.offset = 0;
72729 + var->red.length = 8;
72730 + var->green.offset = 0;
72731 + var->green.length = 8;
72732 + var->blue.offset = 0;
72733 + var->blue.length = 8;
72734 break;
72735 #endif
72736 #ifdef FBCON_HAS_CFB16
72737 - case 16:/* DIRECTCOLOUR, 64k */
72738 -#ifndef CFB16_IS_CFB15
72739 - hw->pixformat = PIXFORMAT_16BPP;
72740 - hw->visualid = VISUALID_64K;
72741 - hw->pitch = hw->width >> 2;
72742 - hw->palette_ctrl |= 0x10;
72743 - break;
72744 -#endif
72745 - case 15:/* DIRECTCOLOUR, 32k */
72746 - hw->pixformat = PIXFORMAT_16BPP;
72747 - hw->visualid = VISUALID_32K;
72748 + case 16:/* DIRECTCOLOUR, 64k or 32k */
72749 + hw->co_pixfmt = CO_PIXFMT_16BPP;
72750 hw->pitch = hw->width >> 2;
72751 - hw->palette_ctrl |= 0x10;
72752 - break;
72754 + switch (var->green.length) {
72755 + case 6: /* RGB565, 64k */
72756 + hw->extseqmisc = EXT_SEQ_MISC_16_RGB565;
72758 + var->transp.offset = 0;
72759 + var->transp.length = 0;
72760 + var->red.offset = 11;
72761 + var->red.length = 5;
72762 + var->green.offset = 5;
72763 + var->green.length = 6;
72764 + var->blue.offset = 0;
72765 + var->blue.length = 5;
72766 + break;
72768 + default:
72769 + case 5: /* RGB555, 32k */
72770 + hw->extseqmisc = EXT_SEQ_MISC_16_RGB555;
72772 + var->transp.offset = 0;
72773 + var->transp.length = 0;
72774 + var->red.offset = 10;
72775 + var->red.length = 5;
72776 + var->green.offset = 5;
72777 + var->green.length = 5;
72778 + var->blue.offset = 0;
72779 + var->blue.length = 5;
72780 + break;
72782 + case 4: /* RGB444, 4k + transparency? */
72783 + hw->extseqmisc = EXT_SEQ_MISC_16_RGB444;
72785 + var->transp.offset = 12;
72786 + var->transp.length = 4;
72787 + var->red.offset = 8;
72788 + var->red.length = 4;
72789 + var->green.offset = 4;
72790 + var->green.length = 4;
72791 + var->blue.offset = 0;
72792 + var->blue.length = 4;
72793 + break;
72795 + break;
72796 #endif
72797 #ifdef FBCON_HAS_CFB24
72798 case 24:/* TRUECOLOUR, 16m */
72799 - hw->pixformat = PIXFORMAT_24BPP;
72800 - hw->visualid = VISUALID_16M;
72801 + hw->co_pixfmt = CO_PIXFMT_24BPP;
72802 hw->width *= 3;
72803 hw->pitch = hw->width >> 3;
72804 - hw->palette_ctrl |= 0x10;
72805 + hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
72806 + hw->extseqmisc = EXT_SEQ_MISC_24_RGB888;
72808 + var->transp.offset = 0;
72809 + var->transp.length = 0;
72810 + var->red.offset = 16;
72811 + var->red.length = 8;
72812 + var->green.offset = 8;
72813 + var->green.length = 8;
72814 + var->blue.offset = 0;
72815 + var->blue.length = 8;
72816 break;
72817 #endif
72818 #ifdef FBCON_HAS_CFB32
72819 case 32:/* TRUECOLOUR, 16m */
72820 - hw->pixformat = PIXFORMAT_32BPP;
72821 - hw->visualid = VISUALID_16M_32;
72822 + hw->co_pixfmt = CO_PIXFMT_32BPP;
72823 hw->pitch = hw->width >> 1;
72824 - hw->palette_ctrl |= 0x10;
72825 + hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
72826 + hw->extseqmisc = EXT_SEQ_MISC_32;
72828 + var->transp.offset = 24;
72829 + var->transp.length = 8;
72830 + var->red.offset = 16;
72831 + var->red.length = 8;
72832 + var->green.offset = 8;
72833 + var->green.length = 8;
72834 + var->blue.offset = 0;
72835 + var->blue.length = 8;
72836 break;
72837 #endif
72838 default:
72839 return -EINVAL;
72842 + mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
72843 + if (mem > cfb->fb.fix.smem_len)
72844 + var->yres_virtual = cfb->fb.fix.smem_len * 8 /
72845 + (var->bits_per_pixel * var->xres_virtual);
72847 + if (var->yres > var->yres_virtual)
72848 + var->yres = var->yres_virtual;
72849 + if (var->xres > var->xres_virtual)
72850 + var->xres = var->xres_virtual;
72852 err = cyber2000fb_decode_clock(hw, cfb, var);
72853 if (err)
72854 return err;
72855 @@ -880,7 +996,7 @@
72856 struct cfb_info *cfb = (struct cfb_info *)info;
72857 struct display *display;
72858 struct par_info hw;
72859 - int err, chgvar = 0;
72860 + int err, chgvar;
72863 * CONUPDATE and SMOOTH_XPAN are equal. However,
72864 @@ -888,11 +1004,11 @@
72866 if (var->vmode & FB_VMODE_CONUPDATE) {
72867 var->vmode |= FB_VMODE_YWRAP;
72868 - var->xoffset = cfb->fb.var.xoffset;
72869 - var->yoffset = cfb->fb.var.yoffset;
72870 + var->xoffset = cfb->display->var.xoffset;
72871 + var->yoffset = cfb->display->var.yoffset;
72874 - err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);
72875 + err = cyber2000fb_decode_var(var, cfb, &hw);
72876 if (err)
72877 return err;
72879 @@ -902,105 +1018,61 @@
72880 if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
72881 return -EINVAL;
72883 - if (cfb->fb.var.xres != var->xres)
72884 - chgvar = 1;
72885 - if (cfb->fb.var.yres != var->yres)
72886 - chgvar = 1;
72887 - if (cfb->fb.var.xres_virtual != var->xres_virtual)
72888 - chgvar = 1;
72889 - if (cfb->fb.var.yres_virtual != var->yres_virtual)
72890 - chgvar = 1;
72891 - if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
72892 - chgvar = 1;
72894 if (con < 0) {
72895 display = cfb->fb.disp;
72896 - chgvar = 0;
72897 } else {
72898 display = fb_display + con;
72901 - var->red.msb_right = 0;
72902 - var->green.msb_right = 0;
72903 - var->blue.msb_right = 0;
72904 + chgvar = cfb->fb.var.xres != var->xres ||
72905 + cfb->fb.var.yres != var->yres ||
72906 + cfb->fb.var.xres_virtual != var->xres_virtual ||
72907 + cfb->fb.var.yres_virtual != var->yres_virtual ||
72908 + cfb->fb.var.bits_per_pixel != var->bits_per_pixel;
72910 + if (memcmp(&cfb->fb.var.red, &var->red, sizeof(var->red)) ||
72911 + memcmp(&cfb->fb.var.green, &var->green, sizeof(var->green)) ||
72912 + memcmp(&cfb->fb.var.blue, &var->blue, sizeof(var->blue)))
72913 + chgvar = 1;
72915 + if (con < 0)
72916 + chgvar = 0;
72918 + /*
72919 + * If we are setting all the virtual consoles, also set the
72920 + * defaults used to create new consoles.
72921 + */
72922 + err = var->activate;
72923 + var->activate = FB_ACTIVATE_NOW;
72924 + if (err & FB_ACTIVATE_ALL)
72925 + cfb->fb.disp->var = *var;
72927 + cfb->fb.var = *var;
72928 + cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
72930 switch (var->bits_per_pixel) {
72931 #ifdef FBCON_HAS_CFB8
72932 case 8: /* PSEUDOCOLOUR, 256 */
72933 - var->red.offset = 0;
72934 - var->red.length = 8;
72935 - var->green.offset = 0;
72936 - var->green.length = 8;
72937 - var->blue.offset = 0;
72938 - var->blue.length = 8;
72940 - cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
72941 cfb->dispsw = &fbcon_cfb8;
72942 display->dispsw_data = NULL;
72943 - display->next_line = var->xres_virtual;
72944 break;
72945 #endif
72946 #ifdef FBCON_HAS_CFB16
72947 - case 16:/* DIRECTCOLOUR, 64k */
72948 -#ifndef CFB16_IS_CFB15
72949 - var->red.offset = 11;
72950 - var->red.length = 5;
72951 - var->green.offset = 5;
72952 - var->green.length = 6;
72953 - var->blue.offset = 0;
72954 - var->blue.length = 5;
72956 - cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
72957 + case 16:/* DIRECTCOLOUR */
72958 cfb->dispsw = &fbcon_cfb16;
72959 display->dispsw_data = cfb->fb.pseudo_palette;
72960 - display->next_line = var->xres_virtual * 2;
72961 - break;
72962 -#endif
72963 - case 15:/* DIRECTCOLOUR, 32k */
72964 - var->bits_per_pixel = 15;
72965 - var->red.offset = 10;
72966 - var->red.length = 5;
72967 - var->green.offset = 5;
72968 - var->green.length = 5;
72969 - var->blue.offset = 0;
72970 - var->blue.length = 5;
72972 - cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
72973 - cfb->dispsw = &fbcon_cfb16;
72974 - display->dispsw_data = cfb->fb.pseudo_palette;
72975 - display->next_line = var->xres_virtual * 2;
72976 break;
72977 #endif
72978 #ifdef FBCON_HAS_CFB24
72979 case 24:/* TRUECOLOUR, 16m */
72980 - var->red.offset = 16;
72981 - var->red.length = 8;
72982 - var->green.offset = 8;
72983 - var->green.length = 8;
72984 - var->blue.offset = 0;
72985 - var->blue.length = 8;
72987 - cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
72988 cfb->dispsw = &fbcon_cfb24;
72989 display->dispsw_data = cfb->fb.pseudo_palette;
72990 - display->next_line = var->xres_virtual * 3;
72991 break;
72992 #endif
72993 #ifdef FBCON_HAS_CFB32
72994 case 32:/* TRUECOLOUR, 16m */
72995 - var->transp.offset = 24;
72996 - var->transp.length = 8;
72997 - var->red.offset = 16;
72998 - var->red.length = 8;
72999 - var->green.offset = 8;
73000 - var->green.length = 8;
73001 - var->blue.offset = 0;
73002 - var->blue.length = 8;
73004 - cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
73005 cfb->dispsw = &fbcon_cfb32;
73006 display->dispsw_data = cfb->fb.pseudo_palette;
73007 - display->next_line = var->xres_virtual * 4;
73008 break;
73009 #endif
73010 default:/* in theory this should never happen */
73011 @@ -1010,15 +1082,27 @@
73012 break;
73015 + /*
73016 + * 8bpp displays are always pseudo colour.
73017 + * 16bpp and above are direct colour or true colour, depending
73018 + * on whether the RAMDAC palettes are bypassed. (Direct colour
73019 + * has palettes, true colour does not.)
73020 + */
73021 + if (var->bits_per_pixel == 8)
73022 + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
73023 + else if (hw.ramdac & RAMDAC_BYPASS)
73024 + cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
73025 + else
73026 + cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
73028 if (var->accel_flags & FB_ACCELF_TEXT && cfb->dispsw != &fbcon_dummy)
73029 display->dispsw = &fbcon_cyber_accel;
73030 else
73031 display->dispsw = cfb->dispsw;
73033 - cfb->fb.fix.line_length = display->next_line;
73035 display->screen_base = cfb->fb.screen_base;
73036 display->line_length = cfb->fb.fix.line_length;
73037 + display->next_line = cfb->fb.fix.line_length;
73038 display->visual = cfb->fb.fix.visual;
73039 display->type = cfb->fb.fix.type;
73040 display->type_aux = cfb->fb.fix.type_aux;
73041 @@ -1026,31 +1110,15 @@
73042 display->ywrapstep = cfb->fb.fix.ywrapstep;
73043 display->can_soft_blank = 1;
73044 display->inverse = 0;
73045 + display->var = *var;
73047 - cfb->fb.var = *var;
73048 - cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
73050 - /*
73051 - * Update the old var. The fbcon drivers still use this.
73052 - * Once they are using cfb->fb.var, this can be dropped.
73053 - * --rmk
73054 - */
73055 - display->var = cfb->fb.var;
73057 - /*
73058 - * If we are setting all the virtual consoles, also set the
73059 - * defaults used to create new consoles.
73060 - */
73061 - if (var->activate & FB_ACTIVATE_ALL)
73062 - cfb->fb.disp->var = cfb->fb.var;
73063 + cyber2000fb_set_timing(cfb, &hw);
73064 + cyber2000fb_update_start(cfb, var);
73065 + fb_set_cmap(&cfb->fb.cmap, 1, cyber2000fb_setcolreg, &cfb->fb);
73067 - if (chgvar && info && cfb->fb.changevar)
73068 + if (chgvar && cfb->fb.changevar)
73069 cfb->fb.changevar(con);
73071 - cyber2000fb_update_start(cfb, var);
73072 - cyber2000fb_set_timing(cfb, &hw);
73073 - fb_set_cmap(&cfb->fb.cmap, 1, cyber2000_setcolreg, &cfb->fb);
73075 return 0;
73078 @@ -1072,18 +1140,18 @@
73080 if (var->xoffset > (var->xres_virtual - var->xres))
73081 return -EINVAL;
73082 - if (y_bottom > cfb->fb.var.yres_virtual)
73083 + if (y_bottom > cfb->display->var.yres_virtual)
73084 return -EINVAL;
73086 if (cyber2000fb_update_start(cfb, var))
73087 return -EINVAL;
73089 - cfb->fb.var.xoffset = var->xoffset;
73090 - cfb->fb.var.yoffset = var->yoffset;
73091 + cfb->display->var.xoffset = var->xoffset;
73092 + cfb->display->var.yoffset = var->yoffset;
73093 if (var->vmode & FB_VMODE_YWRAP) {
73094 - cfb->fb.var.vmode |= FB_VMODE_YWRAP;
73095 + cfb->display->var.vmode |= FB_VMODE_YWRAP;
73096 } else {
73097 - cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
73098 + cfb->display->var.vmode &= ~FB_VMODE_YWRAP;
73101 return 0;
73102 @@ -1106,22 +1174,18 @@
73103 static int cyber2000fb_switch(int con, struct fb_info *info)
73105 struct cfb_info *cfb = (struct cfb_info *)info;
73106 - struct display *disp;
73107 + struct display *display = cfb->display;
73108 struct fb_cmap *cmap;
73110 - if (cfb->currcon >= 0) {
73111 - disp = fb_display + cfb->currcon;
73113 + if (display) {
73115 * Save the old colormap and video mode.
73117 - disp->var = cfb->fb.var;
73118 - if (disp->cmap.len)
73119 - fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
73120 + if (display->cmap.len)
73121 + fb_copy_cmap(&cfb->fb.cmap, &display->cmap, 0);
73124 - cfb->currcon = con;
73125 - disp = fb_display + con;
73126 + cfb->display = display = fb_display + con;
73129 * Install the new colormap and change the video mode. By default,
73130 @@ -1132,73 +1196,88 @@
73131 * depth of the new video mode. For now, we leave it at its
73132 * default 256 entry.
73134 - if (disp->cmap.len)
73135 - cmap = &disp->cmap;
73136 + if (display->cmap.len)
73137 + cmap = &display->cmap;
73138 else
73139 - cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
73140 + cmap = fb_default_cmap(1 << display->var.bits_per_pixel);
73142 fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
73144 - cfb->fb.var = disp->var;
73145 - cfb->fb.var.activate = FB_ACTIVATE_NOW;
73147 - cyber2000fb_set_var(&cfb->fb.var, con, &cfb->fb);
73148 + display->var.activate = FB_ACTIVATE_NOW;
73149 + cyber2000fb_set_var(&display->var, con, &cfb->fb);
73151 return 0;
73155 * (Un)Blank the display.
73157 + * Blank the screen if blank_mode != 0, else unblank. If
73158 + * blank == NULL then the caller blanks by setting the CLUT
73159 + * (Color Look Up Table) to all black. Return 0 if blanking
73160 + * succeeded, != 0 if un-/blanking failed due to e.g. a
73161 + * video mode which doesn't support it. Implements VESA
73162 + * suspend and powerdown modes on hardware that supports
73163 + * disabling hsync/vsync:
73164 + * blank_mode == 2: suspend vsync
73165 + * blank_mode == 3: suspend hsync
73166 + * blank_mode == 4: powerdown
73168 + * wms...Enable VESA DMPS compatible powerdown mode
73169 + * run "setterm -powersave powerdown" to take advantage
73171 static void cyber2000fb_blank(int blank, struct fb_info *info)
73173 struct cfb_info *cfb = (struct cfb_info *)info;
73174 + unsigned int sync = 0;
73175 int i;
73177 - /*
73178 - * Blank the screen if blank_mode != 0, else unblank. If
73179 - * blank == NULL then the caller blanks by setting the CLUT
73180 - * (Color Look Up Table) to all black. Return 0 if blanking
73181 - * succeeded, != 0 if un-/blanking failed due to e.g. a
73182 - * video mode which doesn't support it. Implements VESA
73183 - * suspend and powerdown modes on hardware that supports
73184 - * disabling hsync/vsync:
73185 - * blank_mode == 2: suspend vsync
73186 - * blank_mode == 3: suspend hsync
73187 - * blank_mode == 4: powerdown
73189 - * wms...Enable VESA DMPS compatible powerdown mode
73190 - * run "setterm -powersave powerdown" to take advantage
73191 - */
73193 switch (blank) {
73194 case 4: /* powerdown - both sync lines down */
73195 - cyber2000_grphw(0x16, 0x05, cfb);
73196 + sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
73197 break;
73198 case 3: /* hsync off */
73199 - cyber2000_grphw(0x16, 0x01, cfb);
73200 + sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
73201 break;
73202 case 2: /* vsync off */
73203 - cyber2000_grphw(0x16, 0x04, cfb);
73204 - break;
73205 + sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
73206 + break;
73207 case 1: /* soft blank */
73208 - cyber2000_grphw(0x16, 0x00, cfb);
73209 + default: /* unblank */
73210 + break;
73213 + cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
73215 + if (blank <= 1) {
73216 + /* turn on ramdacs */
73217 + cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
73218 + cyber2000fb_write_ramdac_ctrl(cfb);
73221 + /*
73222 + * Soft blank/unblank the display.
73223 + */
73224 + if (blank) { /* soft blank */
73225 for (i = 0; i < NR_PALETTE; i++) {
73226 cyber2000fb_writeb(i, 0x3c8, cfb);
73227 cyber2000fb_writeb(0, 0x3c9, cfb);
73228 cyber2000fb_writeb(0, 0x3c9, cfb);
73229 cyber2000fb_writeb(0, 0x3c9, cfb);
73231 - break;
73232 - default: /* unblank */
73233 - cyber2000_grphw(0x16, 0x00, cfb);
73234 + } else { /* unblank */
73235 for (i = 0; i < NR_PALETTE; i++) {
73236 cyber2000fb_writeb(i, 0x3c8, cfb);
73237 cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
73238 cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
73239 cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
73241 - break;
73244 + if (blank >= 2) {
73245 + /* turn off ramdacs */
73246 + cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN;
73247 + cyber2000fb_write_ramdac_ctrl(cfb);
73251 @@ -1233,51 +1312,61 @@
73254 static struct fb_ops cyber2000fb_ops = {
73255 - owner: THIS_MODULE,
73256 - fb_set_var: cyber2000fb_set_var,
73257 - fb_set_cmap: cyber2000fb_set_cmap,
73258 - fb_pan_display: cyber2000fb_pan_display,
73259 - fb_get_fix: gen_get_fix,
73260 - fb_get_var: gen_get_var,
73261 - fb_get_cmap: gen_get_cmap,
73262 + .owner = THIS_MODULE,
73263 + .fb_set_var = cyber2000fb_set_var,
73264 + .fb_set_cmap = cyber2000fb_set_cmap,
73265 + .fb_pan_display = cyber2000fb_pan_display,
73266 + .fb_get_fix = gen_get_fix,
73267 + .fb_get_var = gen_get_var,
73268 + .fb_get_cmap = gen_get_cmap,
73272 + * This is the only "static" reference to the internal data structures
73273 + * of this driver. It is here solely at the moment to support the other
73274 + * CyberPro modules external to this driver.
73275 + */
73276 +static struct cfb_info *int_cfb_info;
73279 * Enable access to the extended registers
73281 -static void cyber2000fb_enable_extregs(struct cfb_info *cfb)
73282 +void cyber2000fb_enable_extregs(struct cfb_info *cfb)
73284 cfb->func_use_count += 1;
73286 if (cfb->func_use_count == 1) {
73287 int old;
73289 - old = cyber2000_grphr(FUNC_CTL, cfb);
73290 - cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
73291 + old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
73292 + old |= EXT_FUNC_CTL_EXTREGENBL;
73293 + cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
73298 * Disable access to the extended registers
73300 -static void cyber2000fb_disable_extregs(struct cfb_info *cfb)
73301 +void cyber2000fb_disable_extregs(struct cfb_info *cfb)
73303 if (cfb->func_use_count == 1) {
73304 int old;
73306 - old = cyber2000_grphr(FUNC_CTL, cfb);
73307 - cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
73308 + old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
73309 + old &= ~EXT_FUNC_CTL_EXTREGENBL;
73310 + cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
73313 - cfb->func_use_count -= 1;
73314 + if (cfb->func_use_count == 0)
73315 + printk(KERN_ERR "disable_extregs: count = 0\n");
73316 + else
73317 + cfb->func_use_count -= 1;
73321 - * This is the only "static" reference to the internal data structures
73322 - * of this driver. It is here solely at the moment to support the other
73323 - * CyberPro modules external to this driver.
73324 - */
73325 -static struct cfb_info *int_cfb_info;
73326 +void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
73328 + memcpy(var, &cfb->display->var, sizeof(struct fb_var_screeninfo));
73332 * Attach a capture/tv driver to the core CyberX0X0 driver.
73333 @@ -1311,164 +1400,102 @@
73335 EXPORT_SYMBOL(cyber2000fb_attach);
73336 EXPORT_SYMBOL(cyber2000fb_detach);
73337 +EXPORT_SYMBOL(cyber2000fb_enable_extregs);
73338 +EXPORT_SYMBOL(cyber2000fb_disable_extregs);
73339 +EXPORT_SYMBOL(cyber2000fb_get_fb_var);
73342 * These parameters give
73343 * 640x480, hsync 31.5kHz, vsync 60Hz
73345 static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
73346 - refresh: 60,
73347 - xres: 640,
73348 - yres: 480,
73349 - pixclock: 39722,
73350 - left_margin: 56,
73351 - right_margin: 16,
73352 - upper_margin: 34,
73353 - lower_margin: 9,
73354 - hsync_len: 88,
73355 - vsync_len: 2,
73356 - sync: FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
73357 - vmode: FB_VMODE_NONINTERLACED
73358 + .refresh = 60,
73359 + .xres = 640,
73360 + .yres = 480,
73361 + .pixclock = 39722,
73362 + .left_margin = 56,
73363 + .right_margin = 16,
73364 + .upper_margin = 34,
73365 + .lower_margin = 9,
73366 + .hsync_len = 88,
73367 + .vsync_len = 2,
73368 + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
73369 + .vmode = FB_VMODE_NONINTERLACED
73372 +/* static register programming for all chips */
73373 static char igs_regs[] __devinitdata = {
73374 - 0x12, 0x00, 0x13, 0x00,
73375 - 0x16, 0x00,
73376 - 0x31, 0x00, 0x32, 0x00,
73377 - 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
73378 - 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01,
73379 - 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00,
73380 - 0x70, 0x0b, 0x73, 0x30,
73381 - 0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8
73382 + EXT_CRT_IRQ, 0,
73383 + EXT_CRT_TEST, 0,
73384 + EXT_SYNC_CTL, 0,
73385 + EXT_SEG_WRITE_PTR, 0,
73386 + EXT_SEG_READ_PTR, 0,
73387 + EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
73388 + EXT_BIU_MISC_COP_ENABLE |
73389 + EXT_BIU_MISC_COP_BFC,
73390 + EXT_FUNC_CTL, 0,
73391 + CURS_H_START, 0,
73392 + CURS_H_START + 1, 0,
73393 + CURS_H_PRESET, 0,
73394 + CURS_V_START, 0,
73395 + CURS_V_START + 1, 0,
73396 + CURS_V_PRESET, 0,
73397 + CURS_CTL, 0,
73398 + EXT_ATTRIB_CTL, EXT_ATTRIB_CTL_EXT,
73399 + EXT_OVERSCAN_RED, 0,
73400 + EXT_OVERSCAN_GREEN, 0,
73401 + EXT_OVERSCAN_BLUE, 0,
73404 +/* specific register setting for the 2000 series */
73405 +static char igs_2000_regs[] __devinitdata = {
73406 + /* some of these are questionable when we have a BIOS */
73407 + EXT_MEM_CTL0, EXT_MEM_CTL0_7CLK |
73408 + EXT_MEM_CTL0_RAS_1 |
73409 + EXT_MEM_CTL0_MULTCAS,
73410 + EXT_HIDDEN_CTL1, 0x30,
73411 + EXT_FIFO_CTL, 0x0b,
73412 + EXT_FIFO_CTL + 1, 0x17,
73413 + 0x76, 0x00,
73414 + EXT_HIDDEN_CTL4, 0xc8
73418 - * We need to wake up the CyberPro, and make sure its in linear memory
73419 - * mode. Unfortunately, this is specific to the platform and card that
73420 - * we are running on.
73422 - * On x86 and ARM, should we be initialising the CyberPro first via the
73423 - * IO registers, and then the MMIO registers to catch all cases? Can we
73424 - * end up in the situation where the chip is in MMIO mode, but not awake
73425 - * on an x86 system?
73427 - * Note that on the NetWinder, the firmware automatically detects the
73428 - * type, width and size, and leaves this in extended registers 0x71 and
73429 - * 0x72 for us.
73430 + * Initialise the CyberPro hardware.
73432 -static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
73433 +static void cyberpro_init_hw(struct cfb_info *cfb)
73435 int i;
73437 - /*
73438 - * Wake up the CyberPro.
73439 - */
73440 -#ifdef __sparc__
73441 -#ifdef __sparc_v9__
73442 -#error "You loose, consult DaveM."
73443 -#else
73444 - /*
73445 - * SPARC does not have an "outb" instruction, so we generate
73446 - * I/O cycles storing into a reserved memory space at
73447 - * physical address 0x3000000
73448 - */
73450 - unsigned char *iop;
73452 - iop = ioremap(0x3000000, 0x5000);
73453 - if (iop == NULL) {
73454 - prom_printf("iga5000: cannot map I/O\n");
73455 - return -ENOMEM;
73458 - writeb(0x18, iop + 0x46e8);
73459 - writeb(0x01, iop + 0x102);
73460 - writeb(0x08, iop + 0x46e8);
73461 - writeb(0x33, iop + 0x3ce);
73462 - writeb(0x01, iop + 0x3cf);
73464 - iounmap((void *)iop);
73466 -#endif
73468 - if (at_boot) {
73469 - /*
73470 - * Use mclk from BIOS. Only read this if we're
73471 - * initialising this card for the first time.
73472 - * FIXME: what about hotplug?
73473 - */
73474 - cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
73475 - cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
73477 -#endif
73478 -#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
73479 - /*
73480 - * x86 and MIPS are simple, we just do regular
73481 - * outb's instead of cyber2000fb_writeb.
73482 - */
73483 - outb(0x18, 0x46e8);
73484 - outb(0x01, 0x102);
73485 - outb(0x08, 0x46e8);
73486 - outb(0x33, 0x3ce);
73487 - outb(0x01, 0x3cf);
73489 - if (at_boot) {
73490 - /*
73491 - * Use mclk from BIOS. Only read this if we're
73492 - * initialising this card for the first time.
73493 - * FIXME: what about hotplug?
73494 - */
73495 - cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
73496 - cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
73498 -#endif
73499 -#ifdef __arm__
73500 - cyber2000fb_writeb(0x18, 0x46e8, cfb);
73501 - cyber2000fb_writeb(0x01, 0x102, cfb);
73502 - cyber2000fb_writeb(0x08, 0x46e8, cfb);
73503 - cyber2000fb_writeb(0x33, 0x3ce, cfb);
73504 - cyber2000fb_writeb(0x01, 0x3cf, cfb);
73506 - /*
73507 - * MCLK on the NetWinder and the Shark is fixed at 75MHz
73508 - */
73509 - cfb->mclk_mult = 0xdb;
73510 - cfb->mclk_div = 0x54;
73511 -#endif
73513 - /*
73514 - * Initialise the CyberPro
73515 - */
73516 for (i = 0; i < sizeof(igs_regs); i += 2)
73517 cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
73519 - if (at_boot) {
73520 + if (cfb->id == ID_CYBERPRO_5000) {
73522 - * get the video RAM size and width from the VGA register.
73523 - * This should have been already initialised by the BIOS,
73524 - * but if it's garbage, claim default 1MB VRAM (woody)
73525 + * On the CyberPro5XXXX, ensure that we're using the correct
73526 + * PLL (5XXX's may be programmed to use an additional set of
73527 + * PLLs.)
73529 - cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
73530 - cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
73531 + unsigned char val;
73532 + cyber2000fb_writeb(0xba, 0x3ce, cfb);
73533 + val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
73534 + cyber2000fb_writeb(val, 0x3cf, cfb);
73535 + cyber2000fb_ops.fb_pan_display = NULL; /* FIXME: panning broken */
73536 } else {
73538 - * Reprogram the MEM_CTL1 and MEM_CTL2 registers
73539 + * Other supported chips (2000 series) appear to need
73540 + * these registers programming
73542 - cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
73543 - cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
73544 + for (i = 0; i < sizeof(igs_2000_regs); i += 2)
73545 + cyber2000_grphw(igs_2000_regs[i],
73546 + igs_2000_regs[i+1],
73547 + cfb);
73550 - /*
73551 - * Ensure thatwe are using the correct PLL.
73552 - * (CyberPro 5000's may be programmed to use
73553 - * an additional set of PLLs.
73554 - */
73555 - cyber2000fb_writeb(0xba, 0x3ce, cfb);
73556 - cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
73559 static struct cfb_info * __devinit
73560 -cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name)
73561 +cyberpro_alloc_fb_info(unsigned int id, char *name)
73563 struct cfb_info *cfb;
73565 @@ -1480,10 +1507,9 @@
73567 memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));
73569 - cfb->currcon = -1;
73570 - cfb->dev = dev;
73571 + cfb->id = id;
73573 - if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
73574 + if (id == ID_CYBERPRO_5000)
73575 cfb->ref_ps = 40690; // 24.576 MHz
73576 else
73577 cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
73578 @@ -1492,7 +1518,7 @@
73579 cfb->divisors[1] = 2;
73580 cfb->divisors[2] = 4;
73582 - if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
73583 + if (id == ID_CYBERPRO_2000)
73584 cfb->divisors[3] = 8;
73585 else
73586 cfb->divisors[3] = 6;
73587 @@ -1504,7 +1530,24 @@
73588 cfb->fb.fix.xpanstep = 0;
73589 cfb->fb.fix.ypanstep = 1;
73590 cfb->fb.fix.ywrapstep = 0;
73591 - cfb->fb.fix.accel = id->driver_data;
73593 + switch (id) {
73594 + case ID_IGA_1682:
73595 + cfb->fb.fix.accel = 0;
73596 + break;
73598 + case ID_CYBERPRO_2000:
73599 + cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
73600 + break;
73602 + case ID_CYBERPRO_2010:
73603 + cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
73604 + break;
73606 + case ID_CYBERPRO_5000:
73607 + cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
73608 + break;
73611 cfb->fb.var.nonstd = 0;
73612 cfb->fb.var.activate = FB_ACTIVATE_NOW;
73613 @@ -1569,55 +1612,46 @@
73614 return 0;
73617 -static int __devinit
73618 -cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
73620 + * The CyberPro chips can be placed on many different bus types.
73621 + * This probe function is common to all bus types. The bus-specific
73622 + * probe function is expected to have:
73623 + * - enabled access to the linear memory region
73624 + * - memory mapped access to the registers
73625 + * - initialised mem_ctl1 and mem_ctl2 appropriately.
73626 + */
73627 +static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
73629 - struct cfb_info *cfb;
73630 - u_int h_sync, v_sync;
73631 u_long smem_size;
73632 - char name[16];
73633 + u_int h_sync, v_sync;
73634 int err;
73636 - sprintf(name, "CyberPro%4X", id->device);
73638 - err = pci_enable_device(dev);
73639 - if (err)
73640 - return err;
73642 - err = pci_request_regions(dev, name);
73643 - if (err)
73644 - return err;
73646 - err = -ENOMEM;
73647 - cfb = cyberpro_alloc_fb_info(dev, id, name);
73648 - if (!cfb)
73649 - goto failed_release;
73651 - cfb->region = ioremap(pci_resource_start(dev, 0),
73652 - pci_resource_len(dev, 0));
73653 - if (!cfb->region)
73654 - goto failed_ioremap;
73656 - cfb->regs = cfb->region + MMIO_OFFSET;
73657 + cyberpro_init_hw(cfb);
73659 - cyberpro_init_hw(cfb, 1);
73660 + /*
73661 + * Get the video RAM size and width from the VGA register.
73662 + * This should have been already initialised by the BIOS,
73663 + * but if it's garbage, claim default 1MB VRAM (woody)
73664 + */
73665 + cfb->mem_ctl0 = cyber2000_grphr(EXT_MEM_CTL0, cfb);
73666 + cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
73667 + cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
73669 + /*
73670 + * Determine the size of the memory.
73671 + */
73672 switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
73673 case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break;
73674 case MEM_CTL2_SIZE_2MB: smem_size = 0x00200000; break;
73675 + case MEM_CTL2_SIZE_1MB: smem_size = 0x00100000; break;
73676 default: smem_size = 0x00100000; break;
73679 - /*
73680 - * Hmm, we _need_ a portable way of finding the address for
73681 - * the remap stuff, both for mmio and for smem.
73682 - */
73683 - cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
73684 - cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
73685 - cfb->fb.fix.mmio_len = MMIO_SIZE;
73686 cfb->fb.fix.smem_len = smem_size;
73687 + cfb->fb.fix.mmio_len = MMIO_SIZE;
73688 cfb->fb.screen_base = cfb->region;
73690 + err = -EINVAL;
73691 if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
73692 &cyber2000fb_default_mode, 8)) {
73693 printk("%s: no valid mode found\n", cfb->fb.fix.id);
73694 @@ -1644,13 +1678,181 @@
73695 v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
73696 cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
73698 - printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
73699 + printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
73700 cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
73701 cfb->fb.var.xres, cfb->fb.var.yres,
73702 h_sync / 1000, h_sync % 1000, v_sync);
73704 err = register_framebuffer(&cfb->fb);
73705 - if (err < 0)
73707 +failed:
73708 + return err;
73711 +static void cyberpro_common_resume(struct cfb_info *cfb)
73713 + cyberpro_init_hw(cfb);
73715 + /*
73716 + * Reprogram the MEM_CTL0, 1 and 2 registers
73717 + */
73718 + cyber2000_grphw(EXT_MEM_CTL0, cfb->mem_ctl0, cfb);
73719 + cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
73720 + cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
73722 + /*
73723 + * Restore the old video mode and the palette.
73724 + * We also need to tell fbcon to redraw the console.
73725 + */
73726 + cfb->fb.var.activate = FB_ACTIVATE_NOW;
73727 + cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
73734 + * PCI specific support.
73735 + */
73738 + * We need to wake up the CyberPro, and make sure its in linear memory
73739 + * mode. Unfortunately, this is specific to the platform and card that
73740 + * we are running on.
73742 + * On x86 and ARM, should we be initialising the CyberPro first via the
73743 + * IO registers, and then the MMIO registers to catch all cases? Can we
73744 + * end up in the situation where the chip is in MMIO mode, but not awake
73745 + * on an x86 system?
73746 + */
73747 +static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
73749 + unsigned char val;
73751 +#if defined(__sparc_v9__)
73752 +#error "You loose, consult DaveM."
73753 +#elif defined(__sparc__)
73754 + /*
73755 + * SPARC does not have an "outb" instruction, so we generate
73756 + * I/O cycles storing into a reserved memory space at
73757 + * physical address 0x3000000
73758 + */
73759 + unsigned char *iop;
73761 + iop = ioremap(0x3000000, 0x5000);
73762 + if (iop == NULL) {
73763 + prom_printf("iga5000: cannot map I/O\n");
73764 + return -ENOMEM;
73767 + writeb(0x18, iop + 0x46e8);
73768 + writeb(0x01, iop + 0x102);
73769 + writeb(0x08, iop + 0x46e8);
73770 + writeb(EXT_BIU_MISC, iop + 0x3ce);
73771 + writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
73773 + iounmap((void *)iop);
73774 +#elif defined(CONFIG_ARCH_SHARK)
73775 + /*
73776 + * Shark probably needs to do it this way rather than use the
73777 + * IO method below. Since the CyberPro on the Shark isn't a
73778 + * PCI device, we probably want to move this to a bus-specific
73779 + * probe function. Do we even need to do this?
73780 + */
73781 + cyber2000fb_writeb(0x18, 0x46e8, cfb);
73782 + cyber2000fb_writeb(0x01, 0x102, cfb);
73783 + cyber2000fb_writeb(0x08, 0x46e8, cfb);
73784 + cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
73785 + cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
73786 +#else
73787 + /*
73788 + * Most other machine types are "normal", so
73789 + * we use the standard IO-based wakeup.
73790 + */
73791 + outb(0x18, 0x46e8);
73792 + outb(0x01, 0x102);
73793 + outb(0x08, 0x46e8);
73794 + outb(EXT_BIU_MISC, 0x3ce);
73795 + outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
73796 +#endif
73798 + /*
73799 + * Allow the CyberPro to accept PCI burst accesses
73800 + */
73801 + val = cyber2000_grphr(EXT_BUS_CTL, cfb);
73802 + if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
73803 + printk(KERN_INFO "%s: enabling PCI bursts\n", cfb->fb.fix.id);
73805 + val |= EXT_BUS_CTL_PCIBURST_WRITE;
73807 + if (cfb->id == ID_CYBERPRO_5000)
73808 + val |= EXT_BUS_CTL_PCIBURST_READ;
73810 + cyber2000_grphw(EXT_BUS_CTL, val, cfb);
73813 + return 0;
73816 +static int __devinit
73817 +cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
73819 + struct cfb_info *cfb;
73820 + char name[16];
73821 + int err;
73823 + sprintf(name, "CyberPro%4X", id->device);
73825 + err = pci_enable_device(dev);
73826 + if (err)
73827 + return err;
73829 + err = pci_request_regions(dev, name);
73830 + if (err)
73831 + return err;
73833 + err = -ENOMEM;
73834 + cfb = cyberpro_alloc_fb_info(id->driver_data, name);
73835 + if (!cfb)
73836 + goto failed_release;
73838 + cfb->dev = dev;
73839 + cfb->region = ioremap(pci_resource_start(dev, 0),
73840 + pci_resource_len(dev, 0));
73841 + if (!cfb->region)
73842 + goto failed_ioremap;
73844 + cfb->regs = cfb->region + MMIO_OFFSET;
73845 + cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
73846 + cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
73848 + /*
73849 + * Bring up the hardware. This is expected to enable access
73850 + * to the linear memory region, and allow access to the memory
73851 + * mapped registers. Also, mem_ctl1 and mem_ctl2 must be
73852 + * initialised.
73853 + */
73854 + err = cyberpro_pci_enable_mmio(cfb);
73855 + if (err)
73856 + goto failed;
73858 + /*
73859 + * Use MCLK from BIOS. FIXME: what about hotplug?
73860 + */
73861 + cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
73862 + cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb);
73863 +#ifdef __arm__
73864 + if (machine_is_netwinder() || machine_is_shark()) {
73865 + /*
73866 + * MCLK on the NetWinder and the Shark is fixed at 75MHz
73867 + */
73868 + cfb->mclk_mult = 0xdb;
73869 + cfb->mclk_div = 0x54;
73871 +#endif
73873 + err = cyberpro_common_probe(cfb);
73874 + if (err)
73875 goto failed;
73878 @@ -1672,7 +1874,7 @@
73879 return err;
73882 -static void __devexit cyberpro_remove(struct pci_dev *dev)
73883 +static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
73885 struct cfb_info *cfb = pci_get_drvdata(dev);
73887 @@ -1701,7 +1903,7 @@
73891 -static int cyberpro_suspend(struct pci_dev *dev, u32 state)
73892 +static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
73894 return 0;
73896 @@ -1709,41 +1911,44 @@
73898 * Re-initialise the CyberPro hardware
73900 -static int cyberpro_resume(struct pci_dev *dev)
73901 +static int cyberpro_pci_resume(struct pci_dev *dev)
73903 struct cfb_info *cfb = pci_get_drvdata(dev);
73905 if (cfb) {
73906 - cyberpro_init_hw(cfb, 0);
73908 - /*
73909 - * Restore the old video mode and the palette.
73910 - * We also need to tell fbcon to redraw the console.
73911 - */
73912 - cfb->fb.var.activate = FB_ACTIVATE_NOW;
73913 - cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
73914 + cyberpro_pci_enable_mmio(cfb);
73915 + cyberpro_common_resume(cfb);
73918 return 0;
73921 static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
73922 +// Not yet
73923 +// { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
73924 +// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
73925 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
73926 - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 },
73927 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
73928 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
73929 - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 },
73930 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
73931 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
73932 - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 },
73933 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
73934 { 0, }
73937 +MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
73939 +#ifndef __devexit_p
73940 +#define __devexit_p(x) (x)
73941 +#endif
73943 static struct pci_driver cyberpro_driver = {
73944 - name: "CyberPro",
73945 - probe: cyberpro_probe,
73946 - remove: __devexit_p(cyberpro_remove),
73947 - suspend: cyberpro_suspend,
73948 - resume: cyberpro_resume,
73949 - id_table: cyberpro_pci_table
73950 + .name = "CyberPro",
73951 + .probe = cyberpro_pci_probe,
73952 + .remove = __devexit_p(cyberpro_pci_remove),
73953 + .suspend = cyberpro_pci_suspend,
73954 + .resume = cyberpro_pci_resume,
73955 + .id_table = cyberpro_pci_table
73959 @@ -1768,5 +1973,4 @@
73961 MODULE_AUTHOR("Russell King");
73962 MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
73963 -MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
73964 MODULE_LICENSE("GPL");
73965 --- linux-2.4.25/drivers/video/cyber2000fb.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
73966 +++ linux-2.4.25/drivers/video/cyber2000fb.h 2004-03-31 17:15:09.000000000 +0200
73967 @@ -36,24 +36,55 @@
73968 #define debug_printf(x...) do { } while (0)
73969 #endif
73971 -#define PIXFORMAT_8BPP 0
73972 -#define PIXFORMAT_16BPP 1
73973 -#define PIXFORMAT_24BPP 2
73974 -#define PIXFORMAT_32BPP 3
73975 +#define RAMDAC_RAMPWRDN 0x01
73976 +#define RAMDAC_DAC8BIT 0x02
73977 +#define RAMDAC_VREFEN 0x04
73978 +#define RAMDAC_BYPASS 0x10
73979 +#define RAMDAC_DACPWRDN 0x40
73981 -#define VISUALID_256 1
73982 -#define VISUALID_64K 2
73983 -#define VISUALID_16M_32 3
73984 -#define VISUALID_16M 4
73985 -#define VISUALID_32K 6
73986 +#define EXT_CRT_VRTOFL 0x11
73987 +#define EXT_CRT_VRTOFL_LINECOMP10 0x10
73988 +#define EXT_CRT_VRTOFL_INTERLACE 0x20
73990 -#define FUNC_CTL 0x3c
73991 -#define FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
73992 +#define EXT_CRT_IRQ 0x12
73993 +#define EXT_CRT_IRQ_ENABLE 0x01
73994 +#define EXT_CRT_IRQ_ACT_HIGH 0x04
73996 -#define BIU_BM_CONTROL 0x3e
73997 -#define BIU_BM_CONTROL_ENABLE 0x01 /* enable bus-master */
73998 -#define BIU_BM_CONTROL_BURST 0x02 /* enable burst */
73999 -#define BIU_BM_CONTROL_BACK2BACK 0x04 /* enable back to back */
74000 +#define EXT_CRT_TEST 0x13
74002 +#define EXT_SYNC_CTL 0x16
74003 +#define EXT_SYNC_CTL_HS_NORMAL 0x00
74004 +#define EXT_SYNC_CTL_HS_0 0x01
74005 +#define EXT_SYNC_CTL_HS_1 0x02
74006 +#define EXT_SYNC_CTL_HS_HSVS 0x03
74007 +#define EXT_SYNC_CTL_VS_NORMAL 0x00
74008 +#define EXT_SYNC_CTL_VS_0 0x04
74009 +#define EXT_SYNC_CTL_VS_1 0x08
74010 +#define EXT_SYNC_CTL_VS_COMP 0x0c
74012 +#define EXT_BUS_CTL 0x30
74013 +#define EXT_BUS_CTL_LIN_1MB 0x00
74014 +#define EXT_BUS_CTL_LIN_2MB 0x01
74015 +#define EXT_BUS_CTL_LIN_4MB 0x02
74016 +#define EXT_BUS_CTL_ZEROWAIT 0x04
74017 +#define EXT_BUS_CTL_PCIBURST_WRITE 0x20
74018 +#define EXT_BUS_CTL_PCIBURST_READ 0x80 /* CyberPro 5000 only */
74020 +#define EXT_SEG_WRITE_PTR 0x31
74021 +#define EXT_SEG_READ_PTR 0x32
74022 +#define EXT_BIU_MISC 0x33
74023 +#define EXT_BIU_MISC_LIN_ENABLE 0x01
74024 +#define EXT_BIU_MISC_COP_ENABLE 0x04
74025 +#define EXT_BIU_MISC_COP_BFC 0x08
74027 +#define EXT_FUNC_CTL 0x3c
74028 +#define EXT_FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
74030 +#define PCI_BM_CTL 0x3e
74031 +#define PCI_BM_CTL_ENABLE 0x01 /* enable bus-master */
74032 +#define PCI_BM_CTL_BURST 0x02 /* enable burst */
74033 +#define PCI_BM_CTL_BACK2BACK 0x04 /* enable back to back */
74034 +#define PCI_BM_CTL_DUMMY 0x08 /* insert dummy cycle */
74036 #define X_V2_VID_MEM_START 0x40
74037 #define X_V2_VID_SRC_WIDTH 0x43
74038 @@ -87,6 +118,19 @@
74040 #define K_CAP_X2_CTL1 0x49
74042 +#define CURS_H_START 0x50
74043 +#define CURS_H_PRESET 0x52
74044 +#define CURS_V_START 0x53
74045 +#define CURS_V_PRESET 0x55
74046 +#define CURS_CTL 0x56
74048 +#define EXT_ATTRIB_CTL 0x57
74049 +#define EXT_ATTRIB_CTL_EXT 0x01
74051 +#define EXT_OVERSCAN_RED 0x58
74052 +#define EXT_OVERSCAN_GREEN 0x59
74053 +#define EXT_OVERSCAN_BLUE 0x5a
74055 #define CAP_X_START 0x60
74056 #define CAP_X_END 0x62
74057 #define CAP_Y_START 0x64
74058 @@ -96,46 +140,112 @@
74059 #define CAP_DDA_Y_INIT 0x6c
74060 #define CAP_DDA_Y_INC 0x6e
74062 -#define MEM_CTL1 0x71
74063 +#define EXT_MEM_CTL0 0x70
74064 +#define EXT_MEM_CTL0_7CLK 0x01
74065 +#define EXT_MEM_CTL0_RAS_1 0x02
74066 +#define EXT_MEM_CTL0_RAS2CAS_1 0x04
74067 +#define EXT_MEM_CTL0_MULTCAS 0x08
74068 +#define EXT_MEM_CTL0_ASYM 0x10
74069 +#define EXT_MEM_CTL0_CAS1ON 0x20
74070 +#define EXT_MEM_CTL0_FIFOFLUSH 0x40
74071 +#define EXT_MEM_CTL0_SEQRESET 0x80
74073 -#define MEM_CTL2 0x72
74074 +#define EXT_MEM_CTL1 0x71
74075 +#define EXT_MEM_CTL1_PAR 0x00
74076 +#define EXT_MEM_CTL1_SERPAR 0x01
74077 +#define EXT_MEM_CTL1_SER 0x03
74078 +#define EXT_MEM_CTL1_SYNC 0x04
74079 +#define EXT_MEM_CTL1_VRAM 0x08
74080 +#define EXT_MEM_CTL1_4K_REFRESH 0x10
74081 +#define EXT_MEM_CTL1_256Kx4 0x00
74082 +#define EXT_MEM_CTL1_512Kx8 0x40
74083 +#define EXT_MEM_CTL1_1Mx16 0x60
74085 +#define EXT_MEM_CTL2 0x72
74086 +#define MEM_CTL2_SIZE_1MB 0x00
74087 #define MEM_CTL2_SIZE_2MB 0x01
74088 #define MEM_CTL2_SIZE_4MB 0x02
74089 #define MEM_CTL2_SIZE_MASK 0x03
74090 #define MEM_CTL2_64BIT 0x04
74092 +#define EXT_HIDDEN_CTL1 0x73
74094 #define EXT_FIFO_CTL 0x74
74096 +#define EXT_SEQ_MISC 0x77
74097 +#define EXT_SEQ_MISC_8 0x01
74098 +#define EXT_SEQ_MISC_16_RGB565 0x02
74099 +#define EXT_SEQ_MISC_32 0x03
74100 +#define EXT_SEQ_MISC_24_RGB888 0x04
74101 +#define EXT_SEQ_MISC_16_RGB555 0x06
74102 +#define EXT_SEQ_MISC_8_RGB332 0x09
74103 +#define EXT_SEQ_MISC_16_RGB444 0x0a
74105 +#define EXT_HIDDEN_CTL4 0x7a
74107 +#define CURS_MEM_START 0x7e /* bits 23..12 */
74109 #define CAP_PIP_X_START 0x80
74110 #define CAP_PIP_X_END 0x82
74111 #define CAP_PIP_Y_START 0x84
74112 #define CAP_PIP_Y_END 0x86
74114 -#define CAP_NEW_CTL1 0x88
74115 +#define EXT_CAP_CTL1 0x88
74117 -#define CAP_NEW_CTL2 0x89
74118 +#define EXT_CAP_CTL2 0x89
74119 +#define EXT_CAP_CTL2_ODDFRAMEIRQ 0x01
74120 +#define EXT_CAP_CTL2_ANYFRAMEIRQ 0x02
74122 #define BM_CTRL0 0x9c
74123 #define BM_CTRL1 0x9d
74125 -#define CAP_MODE1 0xa4
74126 -#define CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
74127 -#define CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
74128 -#define CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
74129 -#define CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
74130 -#define CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
74131 -#define CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
74132 -#define CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
74133 +#define EXT_CAP_MODE1 0xa4
74134 +#define EXT_CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
74135 +#define EXT_CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
74136 +#define EXT_CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
74137 +#define EXT_CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
74138 +#define EXT_CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
74139 +#define EXT_CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
74140 +#define EXT_CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
74142 -#define DCLK_MULT 0xb0
74143 -#define DCLK_DIV 0xb1
74144 -#define DCLK_DIV_VFSEL 0x20
74145 -#define MCLK_MULT 0xb2
74146 -#define MCLK_DIV 0xb3
74147 +#define EXT_CAP_MODE2 0xa5
74148 +#define EXT_CAP_MODE2_CCIRINVOE 0x01
74149 +#define EXT_CAP_MODE2_CCIRINVVGT 0x02
74150 +#define EXT_CAP_MODE2_CCIRINVHGT 0x04
74151 +#define EXT_CAP_MODE2_CCIRINVDG 0x08
74152 +#define EXT_CAP_MODE2_DATEND 0x10
74153 +#define EXT_CAP_MODE2_CCIRDGH 0x20
74154 +#define EXT_CAP_MODE2_FIXSONY 0x40
74155 +#define EXT_CAP_MODE2_SYNCFREEZE 0x80
74157 -#define CAP_MODE2 0xa5
74158 +#define EXT_TV_CTL 0xae
74160 -#define Y_TV_CTL 0xae
74161 +#define EXT_DCLK_MULT 0xb0
74162 +#define EXT_DCLK_DIV 0xb1
74163 +#define EXT_DCLK_DIV_VFSEL 0x20
74164 +#define EXT_MCLK_MULT 0xb2
74165 +#define EXT_MCLK_DIV 0xb3
74167 +#define EXT_LATCH1 0xb5
74168 +#define EXT_LATCH1_VAFC_EN 0x01 /* enable VAFC */
74170 +#define EXT_FEATURE 0xb7
74171 +#define EXT_FEATURE_BUS_MASK 0x07 /* host bus mask */
74172 +#define EXT_FEATURE_BUS_PCI 0x00
74173 +#define EXT_FEATURE_BUS_VL_STD 0x04
74174 +#define EXT_FEATURE_BUS_VL_LINEAR 0x05
74175 +#define EXT_FEATURE_1682 0x20 /* IGS 1682 compatibility */
74177 +#define EXT_LATCH2 0xb6
74178 +#define EXT_LATCH2_I2C_CLKEN 0x10
74179 +#define EXT_LATCH2_I2C_CLK 0x20
74180 +#define EXT_LATCH2_I2C_DATEN 0x40
74181 +#define EXT_LATCH2_I2C_DAT 0x80
74183 +#define EXT_XT_CTL 0xbe
74184 +#define EXT_XT_CAP16 0x04
74185 +#define EXT_XT_LINEARFB 0x08
74186 +#define EXT_XT_PAL 0x10
74188 #define EXT_MEM_START 0xc0 /* ext start address 21 bits */
74189 #define HOR_PHASE_SHIFT 0xc2 /* high 3 bits */
74190 @@ -160,25 +270,37 @@
74191 #define EXT_VID_FMT_RGB565 0x02
74192 #define EXT_VID_FMT_RGB888_24 0x03
74193 #define EXT_VID_FMT_RGB888_32 0x04
74194 +#define EXT_VID_FMT_RGB8 0x05
74195 +#define EXT_VID_FMT_RGB4444 0x06
74196 +#define EXT_VID_FMT_RGB8T 0x07
74197 #define EXT_VID_FMT_DUP_PIX_ZOON 0x08 /* duplicate pixel zoom */
74198 #define EXT_VID_FMT_MOD_3RD_PIX 0x20 /* modify 3rd duplicated pixel */
74199 #define EXT_VID_FMT_DBL_H_PIX 0x40 /* double horiz pixels */
74200 -#define EXT_VID_FMT_UV128 0x80 /* UV data offset by 128 */
74201 +#define EXT_VID_FMT_YUV128 0x80 /* YUV data offset by 128 */
74203 #define EXT_VID_DISP_CTL1 0xdc
74204 #define EXT_VID_DISP_CTL1_INTRAM 0x01 /* video pixels go to internal RAM */
74205 #define EXT_VID_DISP_CTL1_IGNORE_CCOMP 0x02 /* ignore colour compare registers */
74206 #define EXT_VID_DISP_CTL1_NOCLIP 0x04 /* do not clip to 16235,16240 */
74207 #define EXT_VID_DISP_CTL1_UV_AVG 0x08 /* U/V data is averaged */
74208 -#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 */
74209 -#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* vertical interpolation off */
74210 +#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 (if YUV128 set) */
74211 +#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* disable vertical interpolation */
74212 #define EXT_VID_DISP_CTL1_FULL_WIN 0x40 /* video out window full */
74213 #define EXT_VID_DISP_CTL1_ENABLE_WINDOW 0x80 /* enable video window */
74215 #define EXT_VID_FIFO_CTL1 0xdd
74216 +#define EXT_VID_FIFO_CTL1_OE_HIGH 0x02
74217 +#define EXT_VID_FIFO_CTL1_INTERLEAVE 0x04 /* enable interleaved memory read */
74219 +#define EXT_ROM_UCB4GH 0xe5
74220 +#define EXT_ROM_UCB4GH_FREEZE 0x02 /* capture frozen */
74221 +#define EXT_ROM_UCB4GH_ODDFRAME 0x04 /* 1 = odd frame captured */
74222 +#define EXT_ROM_UCB4GH_1HL 0x08 /* first horizonal line after VGT falling edge */
74223 +#define EXT_ROM_UCB4GH_ODD 0x10 /* odd frame indicator */
74224 +#define EXT_ROM_UCB4GH_INTSTAT 0x20 /* video interrupt */
74226 #define VFAC_CTL1 0xe8
74227 -#define VFAC_CTL1_CAPTURE 0x01 /* capture enable */
74228 +#define VFAC_CTL1_CAPTURE 0x01 /* capture enable (only when VSYNC high)*/
74229 #define VFAC_CTL1_VFAC_ENABLE 0x02 /* vfac enable */
74230 #define VFAC_CTL1_FREEZE_CAPTURE 0x04 /* freeze capture */
74231 #define VFAC_CTL1_FREEZE_CAPTURE_SYNC 0x08 /* sync freeze capture */
74232 @@ -197,6 +319,13 @@
74233 #define VFAC_CTL2_INVERT_OVSYNC 0x80 /* invert other vsync input */
74235 #define VFAC_CTL3 0xea
74236 +#define VFAC_CTL3_CAP_LARGE_FIFO 0x01 /* large capture fifo */
74237 +#define VFAC_CTL3_CAP_INTERLACE 0x02 /* capture odd and even fields */
74238 +#define VFAC_CTL3_CAP_HOLD_4NS 0x00 /* hold capture data for 4ns */
74239 +#define VFAC_CTL3_CAP_HOLD_2NS 0x04 /* hold capture data for 2ns */
74240 +#define VFAC_CTL3_CAP_HOLD_6NS 0x08 /* hold capture data for 6ns */
74241 +#define VFAC_CTL3_CAP_HOLD_0NS 0x0c /* hold capture data for 0ns */
74242 +#define VFAC_CTL3_CHROMAKEY 0x20 /* capture data will be chromakeyed */
74243 #define VFAC_CTL3_CAP_IRQ 0x40 /* enable capture interrupt */
74245 #define CAP_MEM_START 0xeb /* 18 bits */
74246 @@ -235,26 +364,98 @@
74247 #define BM_COUNT 0xbc090 /* read-only */
74250 - * Graphics Co-processor
74251 + * TV registers
74253 -#define CO_CMD_L_PATTERN_FGCOL 0x8000
74254 -#define CO_CMD_L_INC_LEFT 0x0004
74255 -#define CO_CMD_L_INC_UP 0x0002
74257 -#define CO_CMD_H_SRC_PIXMAP 0x2000
74258 -#define CO_CMD_H_BLITTER 0x0800
74259 +#define TV_VBLANK_EVEN_START 0xbe43c
74260 +#define TV_VBLANK_EVEN_END 0xbe440
74261 +#define TV_VBLANK_ODD_START 0xbe444
74262 +#define TV_VBLANK_ODD_END 0xbe448
74263 +#define TV_SYNC_YGAIN 0xbe44c
74264 +#define TV_UV_GAIN 0xbe450
74265 +#define TV_PED_UVDET 0xbe454
74266 +#define TV_UV_BURST_AMP 0xbe458
74267 +#define TV_HSYNC_START 0xbe45c
74268 +#define TV_HSYNC_END 0xbe460
74269 +#define TV_Y_DELAY1 0xbe464
74270 +#define TV_Y_DELAY2 0xbe468
74271 +#define TV_UV_DELAY1 0xbe46c
74272 +#define TV_BURST_START 0xbe470
74273 +#define TV_BURST_END 0xbe474
74274 +#define TV_HBLANK_START 0xbe478
74275 +#define TV_HBLANK_END 0xbe47c
74276 +#define TV_PED_EVEN_START 0xbe480
74277 +#define TV_PED_EVEN_END 0xbe484
74278 +#define TV_PED_ODD_START 0xbe488
74279 +#define TV_PED_ODD_END 0xbe48c
74280 +#define TV_VSYNC_EVEN_START 0xbe490
74281 +#define TV_VSYNC_EVEN_END 0xbe494
74282 +#define TV_VSYNC_ODD_START 0xbe498
74283 +#define TV_VSYNC_ODD_END 0xbe49c
74284 +#define TV_SCFL 0xbe4a0
74285 +#define TV_SCFH 0xbe4a4
74286 +#define TV_SCP 0xbe4a8
74287 +#define TV_DELAYBYPASS 0xbe4b4
74288 +#define TV_EQL_END 0xbe4bc
74289 +#define TV_SERR_START 0xbe4c0
74290 +#define TV_SERR_END 0xbe4c4
74291 +#define TV_CTL 0xbe4dc /* reflects a previous register- MVFCLR, MVPCLR etc P241*/
74292 +#define TV_VSYNC_VGA_HS 0xbe4e8
74293 +#define TV_FLICK_XMIN 0xbe514
74294 +#define TV_FLICK_XMAX 0xbe518
74295 +#define TV_FLICK_YMIN 0xbe51c
74296 +#define TV_FLICK_YMAX 0xbe520
74299 + * Graphics Co-processor
74300 + */
74301 #define CO_REG_CONTROL 0xbf011
74302 +#define CO_CTRL_BUSY 0x80
74303 +#define CO_CTRL_CMDFULL 0x04
74304 +#define CO_CTRL_FIFOEMPTY 0x02
74305 +#define CO_CTRL_READY 0x01
74307 #define CO_REG_SRC_WIDTH 0xbf018
74308 -#define CO_REG_PIX_FORMAT 0xbf01c
74309 -#define CO_REG_FORE_MIX 0xbf048
74310 -#define CO_REG_FOREGROUND 0xbf058
74311 -#define CO_REG_WIDTH 0xbf060
74312 -#define CO_REG_HEIGHT 0xbf062
74313 +#define CO_REG_PIXFMT 0xbf01c
74314 +#define CO_PIXFMT_32BPP 0x03
74315 +#define CO_PIXFMT_24BPP 0x02
74316 +#define CO_PIXFMT_16BPP 0x01
74317 +#define CO_PIXFMT_8BPP 0x00
74319 +#define CO_REG_FGMIX 0xbf048
74320 +#define CO_FG_MIX_ZERO 0x00
74321 +#define CO_FG_MIX_SRC_AND_DST 0x01
74322 +#define CO_FG_MIX_SRC_AND_NDST 0x02
74323 +#define CO_FG_MIX_SRC 0x03
74324 +#define CO_FG_MIX_NSRC_AND_DST 0x04
74325 +#define CO_FG_MIX_DST 0x05
74326 +#define CO_FG_MIX_SRC_XOR_DST 0x06
74327 +#define CO_FG_MIX_SRC_OR_DST 0x07
74328 +#define CO_FG_MIX_NSRC_AND_NDST 0x08
74329 +#define CO_FG_MIX_SRC_XOR_NDST 0x09
74330 +#define CO_FG_MIX_NDST 0x0a
74331 +#define CO_FG_MIX_SRC_OR_NDST 0x0b
74332 +#define CO_FG_MIX_NSRC 0x0c
74333 +#define CO_FG_MIX_NSRC_OR_DST 0x0d
74334 +#define CO_FG_MIX_NSRC_OR_NDST 0x0e
74335 +#define CO_FG_MIX_ONES 0x0f
74337 +#define CO_REG_FGCOLOUR 0xbf058
74338 +#define CO_REG_BGCOLOUR 0xbf05c
74339 +#define CO_REG_PIXWIDTH 0xbf060
74340 +#define CO_REG_PIXHEIGHT 0xbf062
74341 #define CO_REG_X_PHASE 0xbf078
74342 #define CO_REG_CMD_L 0xbf07c
74343 +#define CO_CMD_L_PATTERN_FGCOL 0x8000
74344 +#define CO_CMD_L_INC_LEFT 0x0004
74345 +#define CO_CMD_L_INC_UP 0x0002
74347 #define CO_REG_CMD_H 0xbf07e
74348 -#define CO_REG_SRC_PTR 0xbf170
74349 +#define CO_CMD_H_BGSRCMAP 0x8000 /* otherwise bg colour */
74350 +#define CO_CMD_H_FGSRCMAP 0x2000 /* otherwise fg colour */
74351 +#define CO_CMD_H_BLITTER 0x0800
74353 +#define CO_REG_SRC1_PTR 0xbf170
74354 +#define CO_REG_SRC2_PTR 0xbf174
74355 #define CO_REG_DEST_PTR 0xbf178
74356 #define CO_REG_DEST_WIDTH 0xbf218
74358 @@ -269,6 +470,7 @@
74359 char *fb;
74360 char dev_name[32];
74361 unsigned int fb_size;
74362 + unsigned int chip_id;
74365 * The following is a pointer to be passed into the
74366 @@ -288,10 +490,19 @@
74367 void (*disable_extregs)(struct cfb_info *);
74370 +#define ID_IGA_1682 0
74371 +#define ID_CYBERPRO_2000 1
74372 +#define ID_CYBERPRO_2010 2
74373 +#define ID_CYBERPRO_5000 3
74375 +struct fb_var_screeninfo;
74378 * Note! Writing to the Cyber20x0 registers from an interrupt
74379 * routine is definitely a bad idea atm.
74381 int cyber2000fb_attach(struct cyberpro_info *info, int idx);
74382 void cyber2000fb_detach(int idx);
74384 +void cyber2000fb_enable_extregs(struct cfb_info *cfb);
74385 +void cyber2000fb_disable_extregs(struct cfb_info *cfb);
74386 +void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
74387 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
74388 +++ linux-2.4.25/drivers/video/dbmx1fb.c 2004-03-31 17:15:09.000000000 +0200
74389 @@ -0,0 +1,2002 @@
74390 +/******************************************************************************
74391 + Copyright (C) 2002 Motorola GSG-China
74393 + This program is free software; you can redistribute it and/or
74394 + modify it under the terms of the GNU General Public License
74395 + as published by the Free Software Foundation; either version 2
74396 + of the License, or (at your option) any later version.
74398 + This program is distributed in the hope that it will be useful,
74399 + but WITHOUT ANY WARRANTY; without even the implied warranty of
74400 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
74401 + GNU General Public License for more details.
74403 + You should have received a copy of the GNU General Public License
74404 + along with this program; if not, write to the Free Software
74405 + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
74406 +*******************************************************************************/
74407 +/*****************************************************************************
74408 + * File Name: dbmx1fb.c
74410 + * Progammers: Chen Ning, Zhang Juan
74412 + * Date of Creations: 10 DEC,2001
74414 + * Synopsis:
74416 + * Descirption: DB-MX1 LCD controller Linux frame buffer driver
74417 + * This file is subject to the terms and conditions of the
74418 + * GNU General Public License. See the file COPYING in the main
74419 + * directory of this archive for more details.
74421 + * Modification History:
74422 + * 10 DEC, 2001, initialization version, frame work for frame buffer driver
74424 +*******************************************************************************/
74425 +#include <linux/config.h>
74426 +#include <linux/module.h>
74427 +#include <linux/kernel.h>
74428 +#include <linux/sched.h>
74429 +#include <linux/errno.h>
74430 +#include <linux/string.h>
74431 +#include <linux/ctype.h>
74432 +#include <linux/mm.h>
74433 +#include <linux/tty.h>
74434 +#include <linux/slab.h>
74435 +#include <linux/init.h>
74436 +#include <linux/fb.h>
74437 +#include <linux/delay.h>
74438 +#include <linux/wrapper.h>
74439 +#include <linux/selection.h>
74440 +#include <linux/console.h>
74441 +#include <linux/kd.h>
74442 +#include <linux/vt_kern.h>
74444 +#include <asm/hardware.h>
74445 +#include <asm/io.h>
74446 +#include <asm/irq.h>
74447 +#include <asm/mach-types.h>
74448 +#include <asm/uaccess.h>
74449 +#include <asm/proc/pgtable.h>
74451 +#include <video/fbcon.h>
74452 +#include <video/fbcon-mfb.h>
74453 +#include <video/fbcon-cfb4.h>
74454 +#include <video/fbcon-cfb8.h>
74455 +#include <video/fbcon-cfb16.h>
74457 +#include "asm/arch/hardware.h"
74458 +#include "asm/arch/platform.h"
74459 +#include "asm/arch/memory.h"
74461 +#include "dbmx1fb.h"
74463 +#undef SUP_TTY0
74465 +#define LCD_PM
74466 +#ifdef LCD_PM
74467 +#include <linux/pm.h>
74468 +struct pm_dev *pm;
74469 +#endif
74471 +// PLAM - make sure fbmem.c also has this defined for full screen frame
74472 +// buffer support in SDRAM
74473 +#define FULL_SCREEN
74475 +#undef HARDWARE_CURSOR
74476 +// #undef HARDWARE_CURSOR
74477 +#undef DEBUG
74480 +/********************************************************************************/
74481 +#ifdef DEBUG
74482 +# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
74483 +#define FUNC_START DPRINTK(KERN_ERR"start\n");
74484 +#define FUNC_END DPRINTK(KERN_ERR"end\n");
74485 +#else
74486 +# define DPRINTK(fmt, args...)
74487 +#define FUNC_START
74488 +#define FUNC_END
74489 +#endif
74491 +#define _IO_ADDRESS(r) ((r)+0xf0000000)
74492 +unsigned int READREG(unsigned int r)
74494 + volatile unsigned int * reg;
74495 + reg = (volatile unsigned int*) _IO_ADDRESS(r);
74496 + return *reg;
74498 +void WRITEREG(unsigned int r, unsigned int val)
74500 + volatile unsigned int *reg;
74501 + reg = (volatile unsigned int*) _IO_ADDRESS(r);
74502 + *reg = val;
74503 + return;
74506 +#define FONT_DATA ((unsigned char *)font->data)
74507 +struct fbcon_font_desc *font;
74509 +/* Local LCD controller parameters */
74510 +struct dbmx1fb_par{
74511 + u_char *screen_start_address; /* Screen Start Address */
74512 + u_char *v_screen_start_address;/* Virtul Screen Start Address */
74513 + unsigned long screen_memory_size; /* screen memory size */
74514 + unsigned int palette_size;
74515 + unsigned int max_xres;
74516 + unsigned int max_yres;
74517 + unsigned int xres;
74518 + unsigned int yres;
74519 + unsigned int xres_virtual;
74520 + unsigned int yres_virtual;
74521 + unsigned int max_bpp;
74522 + unsigned int bits_per_pixel;
74523 + unsigned int currcon;
74524 + unsigned int visual;
74525 + unsigned int TFT :1;
74526 + unsigned int color :1 ;
74527 + unsigned int sharp :1 ;
74529 + unsigned short cfb16[16];
74532 +#ifdef HARDWARE_CURSOR
74533 +/* hardware cursor parameters */
74534 +struct dbmx1fb_cursor{
74535 + // int enable;
74536 + int startx;
74537 + int starty;
74538 + int blinkenable;
74539 + int blink_rate;
74540 + int width;
74541 + int height;
74542 + int color[3];
74543 + int state;
74546 +/* Frame buffer of LCD information */
74547 +struct dbmx1fb_info{
74548 + struct display_switch dispsw;
74549 + struct dbmx1fb_cursor cursor;
74551 +#endif // HARDWARE_CURSOR
74553 +static u_char* p_framebuffer_memory_address;
74554 +static u_char* v_framebuffer_memory_address;
74556 +/* Fake monspecs to fill in fbinfo structure */
74557 +static struct fb_monspecs monspecs __initdata = {
74558 + 30000, 70000, 50, 65, 0 /* Generic */
74561 +/* color map initial */
74562 +static unsigned short __attribute__((unused)) color4map[16] = {
74563 + 0x0000, 0x000f, 0x00f0, 0x0f2a, 0x0f00, 0x0f0f, 0x0f88, 0x0ccc,
74564 + 0x0888, 0x00ff, 0x00f8, 0x0f44, 0x0fa6, 0x0f22, 0x0ff0, 0x0fff
74567 +static unsigned short gray4map[16] = {
74568 + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
74569 + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f
74572 +static struct display global_disp; /* Initial (default) Display Settings */
74573 +static struct fb_info fb_info;
74574 +static struct fb_var_screeninfo init_var = {};
74575 +static struct dbmx1fb_par current_par={ };
74577 +/* Frame buffer device API */
74578 +static int dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con,
74579 + struct fb_info *info);
74580 +static int dbmx1fb_get_var(struct fb_var_screeninfo *var, int con,
74581 + struct fb_info *info);
74582 +static int dbmx1fb_set_var(struct fb_var_screeninfo *var, int con,
74583 + struct fb_info *info);
74584 +static int dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
74585 + struct fb_info *info);
74586 +static int dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
74587 + struct fb_info *info);
74589 +/* Interface to the low level driver */
74590 +static int dbmx1fb_switch(int con, struct fb_info *info);
74591 +static void dbmx1fb_blank(int blank, struct fb_info *info);
74592 +static int dbmx1fb_updatevar(int con, struct fb_info *info);
74594 +/* Internal routines */
74595 +static int _reserve_fb_memory(void);
74596 +static void _install_cmap(int con, struct fb_info *info);
74597 +static void _enable_lcd_controller(void);
74598 +static void _disable_lcd_controller(void);
74599 +static int _encode_var(struct fb_var_screeninfo *var,
74600 + struct dbmx1fb_par *par);
74601 +static int _decode_var(struct fb_var_screeninfo *var,
74602 + struct dbmx1fb_par *par);
74604 +/* initialization routines */
74605 +static void __init _init_lcd_system(void);
74606 +static int __init _init_lcd(void);
74607 +static void __init _init_fbinfo(void);
74608 +static int __init _reserve_fb_memory(void);
74610 +/* frame buffer ops */
74611 +static struct fb_ops dbmx1fb_ops = {
74612 + owner: THIS_MODULE,
74613 + fb_get_fix: dbmx1fb_get_fix,
74614 + fb_get_var: dbmx1fb_get_var,
74615 + fb_set_var: dbmx1fb_set_var,
74616 + fb_get_cmap: dbmx1fb_get_cmap,
74617 + fb_set_cmap: dbmx1fb_set_cmap,
74620 +#ifdef HARDWARE_CURSOR
74621 +/* Hardware Cursor */
74622 +static void dbmx1fb_cursor(struct display *p, int mode, int x, int y);
74623 +static int dbmx1fb_set_font(struct display *d, int width, int height);
74624 +static UINT8 cursor_color_map[] = {0xf8};
74625 +static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state);
74626 +static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb);
74627 +static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink);
74629 +struct display_switch dbmx1fb_cfb4 = {
74630 + setup: fbcon_cfb4_setup,
74631 + bmove: fbcon_cfb4_bmove,
74632 + clear: fbcon_cfb4_clear,
74633 + putc: fbcon_cfb4_putc,
74634 + putcs: fbcon_cfb4_putcs,
74635 + revc: fbcon_cfb4_revc,
74636 + cursor: dbmx1fb_cursor,
74637 + set_font: dbmx1fb_set_font,
74638 + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
74641 +struct display_switch dbmx1fb_cfb8 = {
74642 + setup: fbcon_cfb8_setup,
74643 + bmove: fbcon_cfb8_bmove,
74644 + clear: fbcon_cfb8_clear,
74645 + putc: fbcon_cfb8_putc,
74646 + putcs: fbcon_cfb8_putcs,
74647 + revc: fbcon_cfb8_revc,
74648 + cursor: dbmx1fb_cursor,
74649 + set_font: dbmx1fb_set_font,
74650 + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
74653 +struct display_switch dbmx1fb_cfb16 = {
74654 + setup: fbcon_cfb16_setup,
74655 + bmove: fbcon_cfb16_bmove,
74656 + clear: fbcon_cfb16_clear,
74657 + putc: fbcon_cfb16_putc,
74658 + putcs: fbcon_cfb16_putcs,
74659 + revc: fbcon_cfb16_revc,
74660 + cursor: dbmx1fb_cursor,
74661 + set_font: dbmx1fb_set_font,
74662 + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
74664 +#endif // HARDWARE_CURSOR
74667 +/*****************************************************************************
74668 + * Function Name: dbmx1fb_getcolreg()
74670 + * Input: regno : Color register ID
74671 + * red : Color map red[]
74672 + * green : Color map green[]
74673 + * blue : Color map blue[]
74674 + * transparent : Flag
74675 + * info : Fb_info database
74677 + * Value Returned: int : Return status.If no error, return 0.
74679 + * Description: Transfer to fb_xxx_cmap handlers as parameters to
74680 + * control color registers
74682 + * Modification History:
74683 + * 10 DEC,2001, Chen Ning
74684 +******************************************************************************/
74685 +#define RED 0xf00
74686 +#define GREEN 0xf0
74687 +#define BLUE 0x0f
74688 +static int dbmx1fb_getcolreg(u_int regno, u_int *red, u_int *green,
74689 + u_int *blue, u_int *trans, struct fb_info *info)
74691 + unsigned int val;
74693 + FUNC_START;
74695 + if(regno >= current_par.palette_size)
74696 + return 1;
74698 + val = READREG(DBMX1_LCD_MAPRAM+regno);
74700 + if((current_par.bits_per_pixel == 4)&&(!current_par.color))
74702 + *red = *green = *blue = (val & BLUE) << 4;//TODO:
74703 + *trans = 0;
74705 + else
74707 + *red = (val & RED) << 4;
74708 + *green = (val & GREEN) << 8;
74709 + *blue = (val & BLUE) << 12;
74710 + *trans = 0;
74713 + FUNC_END;
74714 + return 0;
74717 +/*****************************************************************************
74718 + * Function Name: dbmx1fb_setcolreg()
74720 + * Input: regno : Color register ID
74721 + * red : Color map red[]
74722 + * green : Color map green[]
74723 + * blue : Color map blue[]
74724 + * transparent : Flag
74725 + * info : Fb_info database
74727 + * Value Returned: int : Return status.If no error, return 0.
74729 + * Description: Transfer to fb_xxx_cmap handlers as parameters to
74730 + * control color registers
74732 + * Modification History:
74733 + * 10 DEC,2001, Chen Ning
74734 + *****************************************************************************/
74735 +static int
74736 +dbmx1fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
74737 + u_int trans, struct fb_info *info)
74739 + unsigned int val=0;
74740 + FUNC_START
74741 + if(regno >= current_par.palette_size)
74742 + return 1;
74744 + if((current_par.bits_per_pixel == 4)&&(!current_par.color))
74745 + val = (blue & 0x00f) << 12;//TODO:
74746 + else
74748 + val = (blue >> 12 ) & BLUE;
74749 + val |= (green >> 8) & GREEN;
74750 + val |= (red >> 4) & RED;
74753 + if (regno < 16) {
74754 + current_par.cfb16[regno] =
74755 + regno | regno << 5 | regno << 10;
74758 + WRITEREG(DBMX1_LCD_MAPRAM+regno, val);
74759 + FUNC_END;
74760 + return 0;
74763 +/*****************************************************************************
74764 + * Function Name: dbmx1fb_get_cmap()
74766 + * Input: cmap : Ouput data pointer
74767 + * kspc : Kernel space flag
74768 + * con : Console ID
74769 + * info : Frame buffer information
74771 + * Value Returned: int : Return status.If no error, return 0.
74773 + * Description: Data is copied from hardware or local or system DISPAY,
74774 + * and copied to cmap.
74776 + * Modification History:
74777 + * 10 DEC,2001, Chen Ning
74778 +******************************************************************************/
74779 +static int
74780 +dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
74781 + struct fb_info *info)
74783 + int err = 0;
74785 + FUNC_START;
74786 + DPRINTK("current_par.visual=%d\n", current_par.visual);
74787 + if (con == current_par.currcon)
74788 + err = fb_get_cmap(cmap, kspc, dbmx1fb_getcolreg, info);
74789 + else if (fb_display[con].cmap.len)
74790 + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
74791 + else
74792 + fb_copy_cmap(fb_default_cmap(current_par.palette_size),
74793 + cmap, kspc ? 0 : 2);
74794 + FUNC_END;
74795 + return err;
74798 +/*****************************************************************************
74799 + * Function Name: dbmx1fb_set_cmap()
74801 + * Input: cmap : Ouput data pointer
74802 + * kspc : Kernel space flag
74803 + * con : Console ID
74804 + * info : Frame buffer information
74806 + * Value Returned: int : Return status.If no error, return 0.
74808 + * Description: Copy data from cmap and copy to DISPLAY. If DISPLAy has no cmap,
74809 + * allocate memory for it. If DISPLAY is current console and visible,
74810 + * then hardware color map shall be set.
74812 + * Modification History:
74813 + * 10 DEC,2001, Chen Ning
74814 +******************************************************************************/
74815 +static int
74816 +dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
74818 + int err = 0;
74820 + FUNC_START;
74821 + DPRINTK("current_par.visual=%d\n", current_par.visual);
74822 + if (!fb_display[con].cmap.len)
74823 + err = fb_alloc_cmap(&fb_display[con].cmap,
74824 + current_par.palette_size, 0);
74826 + if (!err) {
74827 + if (con == current_par.currcon)
74828 + err = fb_set_cmap(cmap, kspc, dbmx1fb_setcolreg,
74829 + info);
74830 + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
74832 + FUNC_END;
74833 + return err;
74835 +/*****************************************************************************
74836 + * Function Name: dbmx1fb_get_var()
74838 + * Input: var : Iuput data pointer
74839 + * con : Console ID
74840 + * info : Frame buffer information
74842 + * Value Returned: int : Return status.If no error, return 0.
74844 + * Functions Called: _encode_var()
74846 + * Description: Get color map from current, or global display[console]
74847 + * used by ioctl
74849 + * Modification History:
74850 + * 10 DEC,2001, Chen Ning
74851 +******************************************************************************/
74852 +static int
74853 +dbmx1fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
74855 + if (con == -1) {
74856 + _encode_var(var, &current_par);
74857 + } else
74858 + *var = fb_display[con].var;
74859 + return 0;
74863 +/*****************************************************************************
74864 + * Function Name: dbmx1fb_updatevar()
74866 + * Value Returned: VOID
74868 + * Functions Called: VOID
74870 + * Description: Fill in display switch with LCD information,
74872 + * Modification History:
74873 + * 10 DEC,2001, Chen Ning
74874 +******************************************************************************/
74875 +static int dbmx1fb_updatevar(int con, struct fb_info *info)
74877 + DPRINTK("entered\n");
74878 + return 0;
74882 +/*****************************************************************************
74883 + * Function Name: dbmx1fb_set_dispsw()
74885 + * Input: display : Iuput data pointer
74886 + * dbmx1fb_info : Frame buffer of LCD information
74888 + * Value Returned: VOID
74890 + * Functions Called: VOID
74892 + * Description: Fill in display switch with LCD information,
74894 + * Modification History:
74895 + * 10 DEC,2001, Chen Ning
74896 +******************************************************************************/
74897 +static void dbmx1fb_set_dispsw(struct display *disp
74898 +#ifdef HARDWARE_CURSOR
74899 + ,struct dbmx1fb_info *info
74900 +#endif
74903 + FUNC_START;
74904 + switch (disp->var.bits_per_pixel) {
74905 +#ifdef HARDWARE_CURSOR
74906 +#ifdef FBCON_HAS_CFB4
74907 + case 4:
74908 + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
74909 + info->dispsw = dbmx1fb_cfb4;
74910 + disp->dispsw = &info->dispsw;
74911 + disp->dispsw_data = NULL;
74912 + break;
74913 +#endif
74914 +#ifdef FBCON_HAS_CFB8
74915 + case 8:
74916 + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
74917 + info->dispsw = dbmx1fb_cfb8;
74918 + disp->dispsw = &info->dispsw;
74919 + disp->dispsw_data = NULL;
74920 + break;
74921 +#endif
74922 +#ifdef FBCON_HAS_CFB16
74923 + case 12:
74924 + case 16:
74925 + fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
74926 + info->dispsw = dbmx1fb_cfb16;
74927 + disp->dispsw = &info->dispsw;
74928 + disp->dispsw_data = current_par.cfb16;
74929 + break;
74930 +#endif
74931 +#else //!HARDWARE_CURSOR
74932 + /* first step disable the hardware cursor */
74933 +#ifdef FBCON_HAS_CFB4
74934 + case 4:
74935 + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
74936 + disp->dispsw = &fbcon_cfb4;
74937 + disp->dispsw_data = NULL;
74938 + break;
74939 +#endif
74940 +#ifdef FBCON_HAS_CFB8
74941 + case 8:
74942 + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
74943 + disp->dispsw = &fbcon_cfb8;
74944 + disp->dispsw_data = NULL;
74945 + break;
74946 +#endif
74947 +#ifdef FBCON_HAS_CFB16
74948 + case 12:
74949 + case 16:
74950 + fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
74951 + disp->dispsw = &fbcon_cfb16;
74952 + disp->dispsw_data = current_par.cfb16;
74953 + break;
74954 +#endif
74956 +#endif // HARDWARE_CURSOR
74957 + default:
74958 + disp->dispsw = &fbcon_dummy;
74959 + disp->dispsw_data = NULL;
74961 +#ifdef HARDWARE_CURSOR
74962 + if (&info->cursor)
74964 + info->dispsw.cursor = dbmx1fb_cursor;
74965 + info->dispsw.set_font = dbmx1fb_set_font;
74967 +#endif // HARDWARE_CURSOR
74968 + FUNC_END;
74971 +/*****************************************************************************
74972 + * Function Name: dbmx1fb_set_var()
74974 + * Input: var : Iuput data pointer
74975 + * con : Console ID
74976 + * info : Frame buffer information
74978 + * Value Returned: int : Return status.If no error, return 0.
74980 + * Functions Called: dbmx1fb_decode_var()
74981 + * dbmx1fb_encode_var()
74982 + * dbmx1fb_set_dispsw()
74984 + * Description: set current_par by var, also set display data, specially the console
74985 + * related fileops, then enable the lcd controller, and set cmap to
74986 + * hardware.
74988 + * Modification History:
74989 + * 10 DEC,2001, Chen Ning
74990 +******************************************************************************/
74991 +static int
74992 +dbmx1fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
74994 + struct display *display;
74995 + int err, chgvar = 0;
74996 + struct dbmx1fb_par par;
74998 + FUNC_START;
74999 + if (con >= 0)
75000 + display = &fb_display[con]; /* Display settings for console */
75001 + else
75002 + display = &global_disp; /* Default display settings */
75004 + /* Decode var contents into a par structure, adjusting any */
75005 + /* out of range values. */
75006 + if ((err = _decode_var(var, &par))){
75007 + DPRINTK("decode var error!");
75008 + return err;
75011 + // Store adjusted par values into var structure
75012 + _encode_var(var, &par);
75014 + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
75015 + return 0;
75017 + else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) &&
75018 + ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
75019 + return -EINVAL;
75021 + if (con >= 0) {
75022 + if ((display->var.xres != var->xres) ||
75023 + (display->var.yres != var->yres) ||
75024 + (display->var.xres_virtual != var->xres_virtual) ||
75025 + (display->var.yres_virtual != var->yres_virtual) ||
75026 + (display->var.sync != var->sync) ||
75027 + (display->var.bits_per_pixel != var->bits_per_pixel) ||
75028 + (memcmp(&display->var.red, &var->red, sizeof(var->red))) ||
75029 + (memcmp(&display->var.green, &var->green, sizeof(var->green)
75030 + )) ||
75031 + (memcmp(&display->var.blue, &var->blue, sizeof(var->blue))))
75032 + chgvar = 1;
75035 + display->var = *var;
75036 + display->screen_base = par.v_screen_start_address;
75037 + display->visual = par.visual;
75038 + display->type = FB_TYPE_PACKED_PIXELS;
75039 + display->type_aux = 0;
75040 + display->ypanstep = 0;
75041 + display->ywrapstep = 0;
75042 + display->line_length =
75043 + display->next_line = (var->xres * 16) / 8;
75045 + display->can_soft_blank = 1;
75046 + display->inverse = 0;
75048 + dbmx1fb_set_dispsw(display
75049 +#ifdef HARDWARE_CURSOR
75050 + , (struct dbmx1fb_info *)info
75051 +#endif // HARDWARE_CURSOR
75052 + );
75054 + /* If the console has changed and the console has defined */
75055 + /* a changevar function, call that function. */
75056 + if (chgvar && info && info->changevar)
75057 + info->changevar(con); // TODO:
75059 + /* If the current console is selected and it's not truecolor,
75060 + * update the palette
75061 + */
75062 + if ((con == current_par.currcon) &&
75063 + (current_par.visual != FB_VISUAL_TRUECOLOR)) {
75064 + struct fb_cmap *cmap;
75066 + current_par = par; // TODO ?
75067 + if (display->cmap.len)
75068 + cmap = &display->cmap;
75069 + else
75070 + cmap = fb_default_cmap(current_par.palette_size);
75072 + fb_set_cmap(cmap, 1, dbmx1fb_setcolreg, info);
75075 + /* If the current console is selected, activate the new var. */
75076 + if (con == current_par.currcon){
75077 + init_var = *var; // TODO:gcc support structure copy?
75078 + _enable_lcd_controller();
75081 + FUNC_END;
75082 + return 0;
75085 +/*****************************************************************************
75086 + * Function Name: dbmx1fb_get_fix()
75088 + * Input: fix : Ouput data pointer
75089 + * con : Console ID
75090 + * info : Frame buffer information
75092 + * Value Returned: int : Return status.If no error, return 0.
75094 + * Functions Called: VOID
75096 + * Description: get fix from display data, current_par data
75097 + * used by ioctl
75099 + * Modification History:
75100 + * 10 DEC,2001, Chen Ning
75101 +******************************************************************************/
75102 +static int
75103 +dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
75105 + struct display *display;
75107 + FUNC_START;
75108 + memset(fix, 0, sizeof(struct fb_fix_screeninfo));
75109 + strcpy(fix->id, DBMX1_NAME);
75111 + if (con >= 0)
75113 + DPRINTK("Using console specific display for con=%d\n",con);
75114 + display = &fb_display[con]; /* Display settings for console */
75116 + else
75117 + display = &global_disp; /* Default display settings */
75119 + fix->smem_start = (unsigned long)current_par.screen_start_address;
75120 + fix->smem_len = current_par.screen_memory_size;
75121 +//printk("dbmx1fb_get_fix, pointer fix: 0x%08x, smem_len: 0x%08x\n",fix,fix->smem_len);
75122 + fix->type = display->type;
75123 + fix->type_aux = display->type_aux;
75124 + fix->xpanstep = 0;
75125 + fix->ypanstep = display->ypanstep;
75126 + fix->ywrapstep = display->ywrapstep;
75127 + fix->visual = display->visual;
75128 + fix->line_length = display->line_length;
75129 + fix->accel = FB_ACCEL_NONE;
75131 + FUNC_END;
75132 + return 0;
75135 +/*****************************************************************************
75136 + * Function Name: dbmx1fb_inter_handler()
75138 + * Input:
75140 + * Value Returned: VOID
75142 + * Functions Called: VOID
75144 + * Description: Interrupt handler
75146 + * Modification History:
75147 + * 10 DEC,2001, Chen Ning
75148 +******************************************************************************/
75149 +static void dbmx1fb_inter_handler(int irq, void *dev_id, struct pt_regs *regs)
75151 + unsigned int intsr;
75152 + FUNC_START;
75153 + intsr = READREG(DBMX1_LCD_INTSR); // read to clear status
75154 + printk(KERN_ERR"lcd interrupt!\n");
75155 + FUNC_END;
75156 + // handle
75159 +#ifdef LCD_PM
75160 +#define PM_OPT " [pm]"
75161 +#define LCD_PMST_RESUME 0
75162 +#define LCD_PMST_SUSPEND 1
75163 +static unsigned int lcd_pm_status = LCD_PMST_RESUME;
75165 +void lcd_pm_resume(void)
75167 + if(lcd_pm_status == LCD_PMST_RESUME)
75168 + return;
75169 + WRITEREG(0x21c21c, 0x10000); // light on
75170 + WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
75171 + WRITEREG(DBMX1_LCD_PWMR, 0x00a9008a);
75172 + lcd_pm_status = LCD_PMST_RESUME;
75173 +// printk(KERN_ERR"lcd resumed\n");
75176 +void lcd_pm_suspend(void)
75178 + unsigned val;
75179 + if(lcd_pm_status == LCD_PMST_SUSPEND)
75180 + return;
75181 + val = READREG(0x20502c);
75182 + val |= 0x8000;
75183 + WRITEREG(0x20502c, val);
75184 + //To produce enough dealy time before trun off the LCDC.
75185 + for(val=0;val<=600000;val++);
75186 + val = READREG(0x21c21c);
75187 + val &= ~0x10000;
75188 + WRITEREG(0x21c21c, val); // light off
75189 + WRITEREG(DBMX1_LCD_REFMCR, 0x0);
75190 + lcd_pm_status = LCD_PMST_SUSPEND;
75191 +// printk(KERN_ERR"lcd suspended\n");
75194 +int lcd_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data)
75196 + switch(rqst){
75197 + case PM_RESUME:
75198 + lcd_pm_resume();
75199 + break;
75200 + case PM_SUSPEND:
75201 + lcd_pm_suspend();
75202 + break;
75203 + default:
75204 + break;
75206 + return 0;
75208 +#endif // LCD_PM
75210 +/*****************************************************************************
75211 + * Function Name: dbmx1fb_init()
75213 + * Input: VOID
75215 + * Value Returned: int : Return status.If no error, return 0.
75217 + * Functions Called: _init_fbinfo()
75218 + * disable_irq()
75219 + * enable_irq()
75220 + * _init_lcd()
75221 + * dbmx1fb_init_cursor()
75223 + * Description: initialization module, all of init routine's entry point
75224 + * initialize fb_info, init_var, current_par
75225 + * and setup interrupt, memory, lcd controller
75227 + * Modification History:
75228 + * 10 DEC,2001, Chen Ning
75229 +******************************************************************************/
75230 +int __init dbmx1fb_init(void)
75232 + int ret;
75233 +#ifdef HARDWARE_CURSOR
75234 + struct dbmx1fb_info *info;
75235 +#endif // HARDWARE_CURSOR
75237 + _init_lcd_system();
75239 + _init_fbinfo();
75241 + if ((ret = _reserve_fb_memory()) != 0){
75242 + printk(KERN_ERR"failed for reserved DBMX frame buffer memory\n");
75243 + return ret;
75246 +#if 0
75247 + if (request_irq(IRQ_LCD,
75248 + dbmx1fb_inter_handler,
75249 + SA_INTERRUPT,
75250 + DEV_NAME,
75251 + NULL) != 0) {
75252 + printk(KERN_ERR "dbmx1fb: failed in request_irq\n");
75253 + return -EBUSY;
75256 + disable_irq(IRQ_LCD);
75257 +#endif
75258 + if (dbmx1fb_set_var(&init_var, -1, &fb_info))
75259 + ; //current_par.allow_modeset = 0;
75261 + _init_lcd();
75262 + _enable_lcd_controller();
75264 +#ifdef HARDWARE_CURSOR
75265 + info = kmalloc(sizeof(struct dbmx1fb_info), GFP_KERNEL);
75266 + if(info == NULL){
75267 + printk(KERN_ERR"can not kmalloc dbmx1fb_info memory\n");
75268 + return -1;
75271 + memset(info,0,sizeof(struct dbmx1fb_info));
75273 + info->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
75274 + info->cursor.blinkenable = 0;
75275 + info->cursor.state = LCD_CURSOR_OFF;
75276 + WRITEREG(DBMX1_LCD_LCXYP,0x90010001);
75277 + WRITEREG(DBMX1_LCD_CURBLKCR,0x1F1F0000);
75278 + WRITEREG(DBMX1_LCD_LCHCC,0x0000F800);
75280 + DPRINTK(KERN_ERR"LCXYP = %x\n",READREG(DBMX1_LCD_LCXYP));
75281 + DPRINTK(KERN_ERR"CURBLICR = %x\n",READREG(DBMX1_LCD_CURBLKCR));
75282 + DPRINTK(KERN_ERR"LCHCC = %x\n",READREG(DBMX1_LCD_LCHCC));
75284 + //dbmx1fb_set_cursor(info);
75285 + //info->cursor = dbmx1fb_init_cursor(info);
75286 +#endif // HARDWARE_CURSOR
75288 + register_framebuffer(&fb_info);
75290 +#ifdef LCD_PM
75291 + pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, lcd_pm_handler);
75292 + printk("register LCD power management successfully.\n");
75293 +#endif
75294 +#if 0
75295 + enable_irq(IRQ_LCD); // TODO:
75296 +#endif
75297 + /* This driver cannot be unloaded at the moment */
75298 + MOD_INC_USE_COUNT;
75300 + return 0;
75303 +/*****************************************************************************
75304 + * Function Name: dbmx1fb_setup()
75306 + * Input: info : VOID
75308 + * Value Returned: int : Return status.If no error, return 0.
75310 + * Functions Called: VOID
75312 + * Description: basically, this routine used to parse command line parameters, which
75313 + * is initialization parameters for lcd controller, such as freq, xres,
75314 + * yres, and so on
75316 + * Modification History:
75317 + * 10 DEC,2001, Chen Ning
75318 +******************************************************************************/
75319 +int __init dbmx1fb_setup(char *options)
75321 + FUNC_START;
75322 + FUNC_END;
75323 + return 0;
75326 +/*****************************************************************************
75327 + * Function Name: _init_fbinfo()
75329 + * Input: VOID
75331 + * Value Returned: VOID
75333 + * Functions Called: VOID
75335 + * Description: while 16bpp is used to store a 12 bits pixels packet, but
75336 + * it is not a really 16bpp system. maybe in-compatiable with
75337 + * other system or GUI.There are some field in var which specify
75338 + * the red/green/blue offset in a 16bit word, just little endian is
75339 + * concerned
75341 + * Modification History:
75342 + * 10 DEC,2001, Chen Ning
75343 +******************************************************************************/
75344 +static void __init _init_fbinfo(void)
75346 +// Thomas Wong add this for debugging
75347 +// *((unsigned char *)0xF5000008) = '&';
75349 + FUNC_START;
75350 + strcpy(fb_info.modename, DBMX1_NAME);
75351 + strcpy(fb_info.fontname, "Acorn8x8");
75353 + fb_info.node = -1;
75354 + fb_info.flags = FBINFO_FLAG_DEFAULT; // Low-level driver is not a module
75355 + fb_info.fbops = &dbmx1fb_ops;
75356 + fb_info.monspecs = monspecs;
75357 + fb_info.disp = &global_disp;
75358 + fb_info.changevar = NULL;
75359 + fb_info.switch_con = dbmx1fb_switch;
75360 + fb_info.updatevar = dbmx1fb_updatevar;
75361 + fb_info.blank = dbmx1fb_blank;
75364 + * * setup initial parameters
75365 + * */
75366 + memset(&init_var, 0, sizeof(init_var));
75368 + init_var.transp.length = 0;
75369 + init_var.nonstd = 0;
75370 + init_var.activate = FB_ACTIVATE_NOW;
75371 + init_var.xoffset = 0;
75372 + init_var.yoffset = 0;
75373 + init_var.height = -1;
75374 + init_var.width = -1;
75375 + init_var.vmode = FB_VMODE_NONINTERLACED;
75377 + if (1) {
75378 + current_par.max_xres = LCD_MAXX;
75379 + current_par.max_yres = LCD_MAXY;
75380 + current_par.max_bpp = LCD_MAX_BPP; // 12
75381 + init_var.red.length = 5; // 5;
75382 + init_var.green.length = 6; // 6;
75383 + init_var.blue.length = 5; // 5;
75384 +#ifdef __LITTLE_ENDIAN
75385 + init_var.red.offset = 11;
75386 + init_var.green.offset = 5;
75387 + init_var.blue.offset = 0;
75388 +#endif //__LITTLE_ENDIAN
75389 + init_var.grayscale = 16; // i suppose, TODO
75390 + init_var.sync = 0;
75391 + init_var.pixclock = 171521; // TODO
75394 + current_par.screen_start_address = NULL;
75395 + current_par.v_screen_start_address = NULL;
75396 + current_par.screen_memory_size = MAX_PIXEL_MEM_SIZE;
75397 +// Thomas Wong add this for debugging
75398 +//printk("_init_fbinfo, pointer to current_par: 0x%08x, screen_memory_size: 0x%08x\n", &current_par,current_par.screen_memory_size);
75399 + current_par.currcon = -1; // TODO
75401 + init_var.xres = current_par.max_xres;
75402 + init_var.yres = current_par.max_yres;
75403 + init_var.xres_virtual = init_var.xres;
75404 + init_var.yres_virtual = init_var.yres;
75405 + init_var.bits_per_pixel = current_par.max_bpp;
75407 + FUNC_END;
75410 +/*****************************************************************************
75411 + * Function Name: dbmx1fb_blank()
75413 + * Input: blank : Blank flag
75414 + * info : Frame buffer database
75416 + * Value Returned: VOID
75418 + * Functions Called: _enable_lcd_controller()
75419 + * _disable_lcd_controller()
75421 + * Description: blank the screen, if blank, disable lcd controller, while if no blank
75422 + * set cmap and enable lcd controller
75424 + * Modification History:
75425 + * 10 DEC,2001, Chen Ning
75426 +******************************************************************************/
75427 +static void
75428 +dbmx1fb_blank(int blank, struct fb_info *info)
75430 +#ifdef SUP_TTY0
75431 + int i;
75433 + FUNC_START;
75434 + DPRINTK("blank=%d info->modename=%s\n", blank, info->modename);
75435 + if (blank) {
75436 + if (current_par.visual != FB_VISUAL_TRUECOLOR)
75437 + for (i = 0; i < current_par.palette_size; i++)
75438 + ; // TODO
75439 +//printk("Disable LCD\n");
75440 + _disable_lcd_controller();
75442 + else {
75443 + if (current_par.visual != FB_VISUAL_TRUECOLOR)
75444 + dbmx1fb_set_cmap(&fb_display[current_par.currcon].cmap,
75445 + 1,
75446 + current_par.currcon, info);
75447 +//printk("Enable LCD\n");
75448 + _enable_lcd_controller();
75450 + FUNC_END;
75451 +#endif //SUP_TTY0
75454 +/*****************************************************************************
75455 + * Function Name: dbmx1fb_switch()
75457 + * Input: info : Frame buffer database
75459 + * Value Returned: VOID
75461 + * Functions Called:
75463 + * Description: Switch to another console
75465 + * Modification History:
75466 + * 10 DEC,2001, Chen Ning
75467 +******************************************************************************/
75468 +static int dbmx1fb_switch(int con, struct fb_info *info)
75470 + FUNC_START;
75471 + if (current_par.visual != FB_VISUAL_TRUECOLOR) {
75472 + struct fb_cmap *cmap;
75473 + if (current_par.currcon >= 0) {
75474 + // Get the colormap for the selected console
75475 + cmap = &fb_display[current_par.currcon].cmap;
75477 + if (cmap->len)
75478 + fb_get_cmap(cmap, 1, dbmx1fb_getcolreg, info);
75482 + current_par.currcon = con;
75483 + fb_display[con].var.activate = FB_ACTIVATE_NOW;
75484 + dbmx1fb_set_var(&fb_display[con].var, con, info);
75485 + FUNC_END;
75486 + return 0;
75489 +/*****************************************************************************
75490 + * Function Name: _encode_par()
75492 + * Input: var : Input var data
75493 + * par : LCD controller parameters
75495 + * Value Returned: VOID
75497 + * Functions Called:
75499 + * Description: use current_par to set a var structure
75501 + * Modification History:
75502 + * 10 DEC,2001, Chen Ning
75503 +******************************************************************************/
75504 +static int _encode_var(struct fb_var_screeninfo *var,
75505 + struct dbmx1fb_par *par)
75507 + // Don't know if really want to zero var on entry.
75508 + // Look at set_var to see. If so, may need to add extra params to par
75510 + // memset(var, 0, sizeof(struct fb_var_screeninfo));
75512 + var->xres = par->xres;
75513 + var->yres = par->yres;
75514 + var->xres_virtual = par->xres_virtual;
75515 + var->yres_virtual = par->yres_virtual;
75517 + var->bits_per_pixel = par->bits_per_pixel;
75519 + DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
75520 + switch(var->bits_per_pixel) {
75521 + case 2:
75522 + case 4:
75523 + case 8:
75524 + var->red.length = 4;
75525 + var->green = var->red;
75526 + var->blue = var->red;
75527 + var->transp.length = 0;
75528 + break;
75529 + case 12: // This case should differ for Active/Passive mode
75530 + case 16:
75531 + if (1) {
75532 + var->red.length = 4;
75533 + var->blue.length = 4;
75534 + var->green.length = 4;
75535 + var->transp.length = 0;
75536 +#ifdef __LITTLE_ENDIAN
75537 + var->red.offset = 8;
75538 + var->green.offset = 4;
75539 + var->blue.offset = 0;
75540 + var->transp.offset = 0;
75541 +#endif // __LITTLE_ENDIAN
75543 + else
75545 + var->red.length = 5;
75546 + var->blue.length = 5;
75547 + var->green.length = 6;
75548 + var->transp.length = 0;
75549 + var->red.offset = 11;
75550 + var->green.offset = 5;
75551 + var->blue.offset = 0;
75552 + var->transp.offset = 0;
75554 + break;
75557 + return 0;
75560 +/*****************************************************************************
75561 + * Function Name: _decode_var
75563 + * Input: var : Input var data
75564 + * par : LCD controller parameters
75566 + * Value Returned: VOID
75568 + * Functions Called: VOID
75570 + * Description: Get the video params out of 'var'. If a value doesn't fit,
75571 + * round it up,if it's too big, return -EINVAL.
75573 + * Cautions: Round up in the following order: bits_per_pixel, xres,
75574 + * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
75575 + * bitfields, horizontal timing, vertical timing.
75577 + * Modification History:
75578 + * 10 DEC,2001, Chen Ning
75579 +******************************************************************************/
75580 +static int _decode_var(struct fb_var_screeninfo *var,
75581 + struct dbmx1fb_par *par)
75583 + *par = current_par;
75585 + if ((par->xres = var->xres) < MIN_XRES)
75586 + par->xres = MIN_XRES;
75587 + if ((par->yres = var->yres) < MIN_YRES)
75588 + par->yres = MIN_YRES;
75589 + if (par->xres > current_par.max_xres)
75590 + par->xres = current_par.max_xres;
75591 + if (par->yres > current_par.max_yres)
75592 + par->yres = current_par.max_yres;
75593 + par->xres_virtual =
75594 + var->xres_virtual < par->xres ? par->xres : var->xres_virtual;
75595 + par->yres_virtual =
75596 + var->yres_virtual < par->yres ? par->yres : var->yres_virtual;
75597 + par->bits_per_pixel = var->bits_per_pixel;
75599 + switch (par->bits_per_pixel) {
75600 +#ifdef FBCON_HAS_CFB4
75601 + case 4:
75602 + par->visual = FB_VISUAL_PSEUDOCOLOR;
75603 + par->palette_size = 16;
75604 + break;
75605 +#endif
75606 +#ifdef FBCON_HAS_CFB8
75607 + case 8:
75608 + par->visual = FB_VISUAL_PSEUDOCOLOR;
75609 + par->palette_size = 256;
75610 + break;
75611 +#endif
75612 +#ifdef FBCON_HAS_CFB16
75613 + case 12: // RGB 444
75614 + case 16: /* RGB 565 */
75615 + par->visual = FB_VISUAL_TRUECOLOR;
75616 + par->palette_size = 0;
75617 + break;
75618 +#endif
75619 + default:
75620 + return -EINVAL;
75623 + par->screen_start_address =(u_char*)(
75624 + (u_long)p_framebuffer_memory_address+PAGE_SIZE);
75625 + par->v_screen_start_address =(u_char*)(
75626 + (u_long)v_framebuffer_memory_address+PAGE_SIZE);
75628 +// Thomas Wong - try to change start address here (map to SRAM, instead of SDRAM)
75629 +#ifndef FULL_SCREEN
75630 + par->screen_start_address =(u_char*)(0x00300000);
75631 + par->v_screen_start_address =(u_char*)(0xF0300000);
75632 +#endif
75634 +// par->screen_start_address =(u_char*)(0x0BE00000);
75635 +// par->v_screen_start_address =(u_char*)(0xFBE00000);
75637 +// par->screen_start_address =(u_char*)(0x12000000);
75638 +// par->v_screen_start_address =(u_char*)(0xF2000000);
75640 + return 0;
75644 +/*****************************************************************************
75645 + * Function Name: _reserve_fb_memory()
75647 + * Input: VOID
75649 + * Value Returned: VOID
75651 + * Functions Called:
75653 + * Description: get data out of var structure and set related LCD controller registers
75655 + * Modification History:
75656 + * 10 DEC,2001, Chen Ning
75657 +******************************************************************************/
75658 +static int __init _reserve_fb_memory(void)
75660 + u_int required_pages;
75661 + u_int extra_pages;
75662 + u_int order;
75663 + struct page *page;
75664 + char *allocated_region;
75666 + DPRINTK("frame buffer memory size = %x\n", (unsigned int)ALLOCATED_FB_MEM_SIZE);
75667 + if (v_framebuffer_memory_address != NULL)
75668 + return -EINVAL;
75670 + /* Find order required to allocate enough memory for framebuffer */
75671 + required_pages = ALLOCATED_FB_MEM_SIZE >> PAGE_SHIFT;
75672 + for (order = 0 ; required_pages >> order ; order++) {;}
75673 + extra_pages = (1 << order) - required_pages;
75675 + if ((allocated_region =
75676 + (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)) == NULL){
75678 + DPRINTK("can not allocated memory\n");
75679 + return -ENOMEM;
75683 + v_framebuffer_memory_address = (u_char *)allocated_region +
75684 + (extra_pages << PAGE_SHIFT);
75685 + p_framebuffer_memory_address = (u_char *)__virt_to_phys(
75686 + (u_long)v_framebuffer_memory_address);
75687 +#if 0
75688 + printk(KERN_ERR"Frame buffer __get_free_pages vd:= %x, pd= %x",
75689 + (unsigned int)v_framebuffer_memory_address,
75690 + (unsigned int)p_framebuffer_memory_address);
75691 +#endif
75692 + /* Free all pages that we don't need but were given to us because */
75693 + /* __get_free_pages() works on powers of 2. */
75694 + for (;extra_pages;extra_pages--)
75695 + free_page((u_int)allocated_region + ((extra_pages-1) << PAGE_SHIFT));
75697 + /* Set reserved flag for fb memory to allow it to be remapped into */
75698 + /* user space by the common fbmem driver using remap_page_range(). */
75699 + for(page = virt_to_page(v_framebuffer_memory_address);
75700 + page < virt_to_page(v_framebuffer_memory_address
75701 + + ALLOCATED_FB_MEM_SIZE);
75702 + page++)
75703 + mem_map_reserve(page);
75704 +#if 0
75705 + /* Remap the fb memory to a non-buffered, non-cached region */
75706 + v_framebuffer_memory_address = (u_char *)__ioremap(
75707 + (u_long)p_framebuffer_memory_address,
75708 + ALLOCATED_FB_MEM_SIZE,
75709 + L_PTE_PRESENT |
75710 + L_PTE_YOUNG |
75711 + L_PTE_DIRTY |
75712 + L_PTE_WRITE);
75713 +#endif
75714 + current_par.screen_start_address =(u_char*)(
75715 + (u_long)p_framebuffer_memory_address+PAGE_SIZE);
75716 + current_par.v_screen_start_address =(u_char*)(
75717 + (u_long)v_framebuffer_memory_address+PAGE_SIZE);
75719 + DPRINTK("physical screen start addres: %x\n",
75720 + (u_long)p_framebuffer_memory_address+PAGE_SIZE);
75722 +#ifndef FULL_SCREEN
75723 +// Thomas Wong - we'll try to change the screen start address here
75724 +// printk("\n\rMap LCD screen to SDRAM.\n\r");
75726 + printk("\n\rMap LCD screen to embedded SRAM.\n\r");
75727 + current_par.screen_start_address =(u_char*)(0x00300000);
75728 + current_par.v_screen_start_address =(u_char*)(0xF0300000);
75729 +#endif
75731 +// printk("\n\rMap LCD screen to SDRAM 0xFBE00000.\n\r");
75732 +// current_par.screen_start_address =(u_char*)(0x0BE00000);
75733 +// current_par.v_screen_start_address =(u_char*)(0xFBE00000);
75735 +// printk("\n\rMap LCD screen to SRAM 0x12000000.\n\r");
75736 +// current_par.screen_start_address =(u_char*)(0x12000000);
75737 +// current_par.v_screen_start_address =(u_char*)(0xF2000000);
75739 + return (v_framebuffer_memory_address == NULL ? -EINVAL : 0);
75742 +/*****************************************************************************
75743 + * Function Name: _enable_lcd_controller()
75745 + * Input: VOID
75747 + * Value Returned: VOID
75749 + * Functions Called:
75751 + * Description: enable Lcd controller, setup registers,
75752 + * base on current_par value
75754 + * Modification History:
75755 + * 10 DEC,2001, Chen Ning
75756 +******************************************************************************/
75757 +static void _enable_lcd_controller(void)
75759 + unsigned int val;
75760 +#if 0
75761 + int i;
75762 + val =0;
75764 + FUNC_START;
75765 + _decode_var(&init_var, &current_par);
75767 + val = current_par.xres/16;
75768 + val <<= 20;
75769 + val += current_par.yres;
75770 + WRITEREG(DBMX1_LCD_XYMAX, val);
75772 + val=0;
75773 + val=current_par.xres_virtual /2;
75774 + WRITEREG(DBMX1_LCD_VPW, val);
75776 + switch(current_par.bits_per_pixel ){
75777 + case 4: // for gray only
75778 + for(i=0; i<16; i++){
75779 + WRITEREG(DBMX1_LCD_MAPRAM+i, gray4map[i]);
75781 + WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_4);
75782 + WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_4);
75783 + WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_4);
75784 + WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_4); // no interrupt
75785 + WRITEREG(DBMX1_LCD_REFMCR, REFMCR_VAL_4);
75786 + WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_4);
75787 + WRITEREG(DBMX1_LCD_PWMR, PWMR_VAL);
75788 + break;
75789 + case 12:
75790 + case 16:
75791 + WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_12);
75792 + WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_12);
75793 + WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_12);
75794 + WRITEREG(DBMX1_LCD_REFMCR, 0x0);
75795 + WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
75796 + WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
75797 + WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002);
75798 + WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
75800 + break;
75802 +#else
75803 + val = READREG(0x21c21c);
75804 + val |= 0x0010000;
75805 + WRITEREG(0x21c21c, val);
75807 + WRITEREG(DBMX1_LCD_PWMR, 0x8200);
75808 + WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
75810 + // Thomas Wong - we want 0x8A not 0x200
75811 +// WRITEREG(DBMX1_LCD_PWMR, 0x200);
75812 +// PLAM -- for rev2 (endian bit)
75813 +// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
75814 + WRITEREG(DBMX1_LCD_PWMR, 0x00A9008A);
75815 +// end PLAM
75816 +#endif
75818 + FUNC_END;
75821 +/*****************************************************************************
75822 + * Function Name: _disable_lcd_controller()
75824 + * Input: VOID
75826 + * Value Returned: VOID
75828 + * Functions Called: VOID
75830 + * Description: just disable the LCD controller
75831 + * disable lcd interrupt. others, i have no ideas
75833 + * Modification History:
75834 + * 10 DEC,2001, Chen Ning
75835 +******************************************************************************/
75836 +static void _disable_lcd_controller(void)
75838 + unsigned int val;
75839 + val = READREG(0x21c21c);
75840 + val &= ~0x0010000;
75841 + WRITEREG(0x21c21c, val);
75843 + WRITEREG(DBMX1_LCD_PWMR, 0x8200);
75844 +// WRITEREG(DBMX1_LCD_REFMCR, DISABLELCD_VAL);
75845 + WRITEREG(0x205034, 0x0);
75848 +/*****************************************************************************
75849 + * Function Name: _install_cmap
75851 + * Input: VOID
75853 + * Value Returned: VOID
75855 + * Functions Called:
75857 + * Description: set color map to hardware
75859 + * Modification History:
75860 + * 10 DEC,2001, Chen Ning
75861 +******************************************************************************/
75862 +static void _install_cmap(int con, struct fb_info *info)
75864 + if (con != current_par.currcon)
75865 + return ;
75866 + if (fb_display[con].cmap.len)
75867 + fb_set_cmap(&fb_display[con].cmap, 1, dbmx1fb_setcolreg, info);
75868 + else
75869 + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
75870 + 1,
75871 + dbmx1fb_setcolreg,
75872 + info);
75873 + return ;
75876 +/*****************************************************************************
75877 + * Function Name: _init_lcd_system
75879 + * Input: VOID
75881 + * Value Returned: VOID
75883 + * Functions Called:
75885 + * Description: initialize the gpio port C and port D with DMA enable
75887 + * Modification History:
75888 + * 10 DEC,2001, Chen Ning
75889 +******************************************************************************/
75890 +static void __init _init_lcd_system(void)
75892 +unsigned int val;
75894 +/* Thomas Wong - we don't need DMA here
75895 + // dma reset & enable
75896 + val = READREG(0x209000);
75897 + val |= 0x02;
75898 + WRITEREG(0x209000, val);
75899 + val = READREG(0x209000);
75900 + val |= 0x01;
75901 + WRITEREG(0x209000, val);
75903 + // gpio
75904 + //clear port D for LCD signal
75905 + WRITEREG(0x21c320, 0x0);
75906 + WRITEREG(0x21c338, 0x0);
75908 + val = READREG(0x21c220);
75909 + val |= 0x10000;
75910 + WRITEREG(0x21c220, val);
75911 + val = READREG(0x21c208);
75912 + val |= 0x03;
75913 + WRITEREG(0x21c208, val);
75914 + val = READREG(0x21c200);
75915 + val |= 0x10000;
75916 + WRITEREG(0x21c200, val);
75917 + val = READREG(0x21c238);
75918 + val |= 0x10000;
75919 + WRITEREG(0x21c238, val);
75920 + val = READREG(0x21c21c);
75921 + val |= 0x10000;
75922 + WRITEREG(0x21c21c, val);
75926 +static void set_pclk(unsigned int fmhz)
75928 + unsigned int div= 96/fmhz;
75929 + unsigned int reg;
75930 + reg = READREG(0x21b020);
75931 + reg &= ~0xf0;
75932 + WRITEREG(0x21b020, reg);
75933 + reg |= ((div-1)<<4) &0xf0;
75934 + WRITEREG(0x21b020, reg);
75937 +/*****************************************************************************
75938 + * Function Name: _init_lcd
75940 + * Input: VOID
75942 + * Value Returned: VOID
75944 + * Functions Called: _decode_var()
75946 + * Description: initialize the LCD controller, use current_par for 12bpp
75948 + * Modification History:
75949 + * 10 DEC,2001, Chen Ning
75950 +******************************************************************************/
75951 +static int __init _init_lcd()
75954 + unsigned int val, rate;
75955 + int i;
75956 + unsigned char * pscr;
75957 + //unsigned long pclk,temp,PCLKDIV2;
75958 + //unsigned long MFI,MFN,PD,MFD,tempReg,MCUPLLCLK;
75961 + _decode_var(&init_var, &current_par);
75963 + // gpio begin
75964 + val = READREG(0x21c21c);
75965 + val &= ~0x00010000;
75966 + WRITEREG(0x21c21c, val);
75967 + DPRINTK(KERN_ERR"DR=%x\n", READREG(0x21c21c));
75969 + // LCD regs
75970 + DPRINTK(KERN_ERR"write SSA by %x\n",
75971 + (unsigned int)current_par.screen_start_address);
75972 + WRITEREG(DBMX1_LCD_SSA, (unsigned int)current_par.screen_start_address);
75973 + DPRINTK(KERN_ERR"SSA=%x\n", READREG(DBMX1_LCD_SSA));
75975 + val =0;
75976 + val = current_par.xres/16;
75977 + val = val<<20;
75978 + val += current_par.yres;
75979 + DPRINTK(KERN_ERR"par.x=%x, y=%x\n",
75980 + current_par.xres,
75981 + current_par.yres);
75982 + WRITEREG(DBMX1_LCD_XYMAX, val);
75983 + DPRINTK(KERN_ERR"XYMAX=%x\n", READREG(DBMX1_LCD_XYMAX));
75985 + val=0;
75986 + val=current_par.xres_virtual/2;
75987 + WRITEREG(DBMX1_LCD_VPW, val);
75988 + DPRINTK(KERN_ERR"VPW=%x\n", READREG(DBMX1_LCD_VPW));
75990 + set_pclk(4);
75992 + DPRINTK(KERN_ERR"DBMX1_LCD_PANELCFG=%x\n",
75993 + READREG(DBMX1_LCD_PANELCFG));
75995 + WRITEREG(DBMX1_LCD_HCFG, 0x04000f06);
75996 + DPRINTK(KERN_ERR"DBMX1_LCD_HCFG=%x\n",
75997 + READREG(DBMX1_LCD_HCFG));
75999 + WRITEREG(DBMX1_LCD_VCFG, 0x04000907);
76000 + DPRINTK(KERN_ERR"DBMX1_LCD_VCFG=%x\n",
76001 + READREG(DBMX1_LCD_VCFG));
76003 + WRITEREG(DBMX1_LCD_REFMCR, 0x0);
76004 + DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
76005 + READREG(DBMX1_LCD_REFMCR));
76007 + WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
76008 + DPRINTK(KERN_ERR"DBMX1_LCD_DMACR=%x\n",
76009 + READREG(DBMX1_LCD_DMACR));
76011 + WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
76012 + DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
76013 + READREG(DBMX1_LCD_PWMR));
76015 + // Thomas Wong - we don't want to turn it on here
76016 + /*
76017 + WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002)
76018 + DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
76019 + READREG(DBMX1_LCD_REFMCR));
76020 + */
76022 + WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
76023 + DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
76024 + READREG(DBMX1_LCD_PWMR));
76026 + // Thomas Wong
76027 + WRITEREG(0x21B020, 0x000B005B);
76028 +// PLAM -- for rev2 (new register and endian bits)
76029 + WRITEREG(DBMX1_LCD_PANELCFG, 0xF8008B42); // little endian
76030 +// WRITEREG(DBMX1_LCD_PANELCFG, 0xF8048B42); // big endian
76031 + WRITEREG(DBMX1_LCD_LGPMR, 0x00090300);
76032 +// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
76033 + WRITEREG (DBMX1_LCD_PWMR, 0x009A008A);
76034 +// end PLAM
76036 +// PLAM -- for rev2 (new DMACR setting)
76037 +// WRITEREG(DBMX1_LCD_DMACR, 0x800C0002);
76038 + WRITEREG(DBMX1_LCD_DMACR, 0x00040008);
76039 +//end PLAM
76042 +#define DMACR_VAL_12 0x800C0002
76045 +// WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_12);
76046 +// DPRINTK(KERN_ERR"DBMX1_LCD_INTCR=%x\n",
76047 +// READREG(DBMX1_LCD_INTCR));
76049 + // warm up LCD
76050 + for(i=0;i<10000000;i++) ;
76052 + // gpio end
76053 + val = READREG(0x21c21c);
76054 + val |= 0x00010000;
76055 + WRITEREG(0x21c21c, val);
76056 + DPRINTK(KERN_ERR"DR=%x\n",
76057 + READREG(0x21c21c));
76058 +#if 0
76059 + // clear screen
76060 + pscr = current_par.v_screen_start_address;
76061 + for(i=0; i< (current_par.screen_memory_size - 2*PAGE_SIZE); i++){
76062 + *pscr++ = 0xff;
76064 +#endif
76065 + DPRINTK(KERN_ERR"_init_lcd end \n");
76067 + return 0;
76070 +#ifdef HARDWARE_CURSOR
76073 + * Hardware cursor support
76074 + */
76075 + /*****************************************************************************
76076 + * Function Name: dbmx1fb_set_cursor_color()
76078 + * Input: fb : frame buffer database
76079 + * red : red component level in the cursor
76080 + * green : green component level in the cursor
76081 + * blue : blue component level in the cursor
76083 + * Value Returned: VOID
76085 + * Functions Called: VOID
76087 + * Description: Set color of hardware cursor
76089 + * Modification History:
76090 + * 10 DEC,2001, Zhang Juan
76091 +******************************************************************************/
76092 +static void dbmx1fb_set_cursor_color(struct dbmx1fb_info *fb, UINT8 *red, UINT8 *green, UINT8 *blue)
76094 + struct dbmx1fb_cursor *c = &fb->cursor;
76095 + UINT32 color;
76097 + FUNC_START;
76098 + c->color[0] = *red;
76099 + c->color[1] = *green;
76100 + c->color[2] = *blue;
76101 + color = (UINT32)*red;
76102 + color |= (UINT32)(*green>>5);
76103 + color |= (UINT32)(*blue>>11);
76105 + WRITEREG(DBMX1_LCD_LCHCC, color);
76106 + FUNC_END;
76109 + /*****************************************************************************
76110 + * Function Name: dbmx1fb_set_cursor()
76112 + * Input: fb : frame buffer database
76114 + * Value Returned: VOID
76116 + * Functions Called: VOID
76118 + * Description: Load information of hardware cursor
76120 + * Modification History:
76121 + * 10 DEC,2001, Zhang Juan
76122 +******************************************************************************/
76123 +static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb)
76125 + struct dbmx1fb_cursor *c = &fb->cursor;
76126 + UINT32 temp,tempReg,x,y;
76128 + FUNC_START;
76129 + //DPRINTK(KERN_ERR"BLINK_RATE=%x\n",c->blink_rate);
76130 +// DPRINTK(KERN_ERR"width=%x\n",c->width);
76131 +// DPRINTK(KERN_ERR"height=%x\n",c->height);
76133 + x = c->startx << 16;
76134 + if (c->state == LCD_CURSOR_ON)
76135 + x |= CURSOR_ON_MASK;
76137 +#ifdef FBCON_HAS_CFB4
76138 + else if(c->state == LCD_CURSOR_REVERSED)
76139 + x |= CURSOR_REVERSED_MASK;
76140 + else if(c->state == LCD_CURSOR_ON_WHITE)
76141 + x |= CURSOR_WHITE_MASK;
76142 +#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
76143 + else if(c->state == LCD_CURSOR_INVERT_BGD)
76144 + x |= CURSOR_INVERT_MASK;
76145 + else if(c->state == LCD_CURSOR_AND_BGD)
76146 + x |= CURSOR_AND_BGD_MASK;
76147 + else if(c->state == LCD_CURSOR_OR_BGD)
76148 + x |= CURSOR_OR_BGD_MASK;
76149 + else if(c->state == LCD_CURSOR_XOR_BGD)
76150 + x |= CURSOR_XOR_BGD_MASK;
76151 +#endif
76152 + else
76153 + x = c->startx;
76155 + y = c->starty;
76157 + temp = (UINT32)x | (UINT32)y;
76158 + WRITEREG(DBMX1_LCD_LCXYP, temp);
76159 + //DPRINTK(KERN_ERR"lcxyp=%x\n",READREG(DBMX1_LCD_LCXYP));
76161 + temp = (UINT32)((c->width<<8) | (c->height));
76162 + tempReg = (UINT32)((temp<<16) | c->blink_rate);
76164 + WRITEREG(DBMX1_LCD_CURBLKCR, tempReg);
76166 + //c->blink_rate = 10;
76167 + if (c->blinkenable)
76168 + dbmx1fb_set_cursor_blink(fb,c->blink_rate);
76169 + DPRINTK(KERN_ERR"CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
76170 + FUNC_END;
76173 + /*****************************************************************************
76174 + * Function Name: dbmx1fb_set_cursor_blink()
76176 + * Input: fb : frame buffer database
76177 + * blink : input blink frequency of cursor
76179 + * Value Returned: VOID
76181 + * Functions Called: VOID
76183 + * Description: Set blink frequency of hardware cursor
76185 + * Modification History:
76186 + * 10 DEC,2001, Zhang Juan
76187 +******************************************************************************/
76188 +static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink)
76190 + struct dbmx1fb_cursor *c = &fb->cursor;
76192 + unsigned long temp,tempReg;
76193 + unsigned long PCD, XMAX, YMAX, PCLKDIV2;
76194 + unsigned long tempMicroPeriod;
76196 + FUNC_START;
76197 + DPRINTK(KERN_ERR"dbmx1fb_set_cursor_blink\n");
76199 + if(!c){
76200 + DPRINTK(KERN_ERR"dangerouts, for c == null\n");
76202 + c->blink_rate = blink;
76204 + tempReg = READREG(DBMX1_LCD_XYMAX);
76205 + XMAX = (tempReg & XMAX_MASK) >> 20;
76206 + YMAX = tempReg & YMAX_MASK;
76207 + //XMAX = 240;
76208 + //YMAX = 320;
76209 + tempReg = READREG(PCDR);
76210 + PCLKDIV2 = (tempReg & PCLKDIV2_MASK) >> 4;
76211 + tempReg = READREG(DBMX1_LCD_PANELCFG);
76212 + PCD = tempReg & PCD_MASK;
76214 + temp = (PCLKDIV2 + 1);
76216 + if (!blink)
76218 + /* disable the blinking cursor function when frequency is 0 */
76219 + tempReg = READREG(DBMX1_LCD_CURBLKCR);
76220 + tempReg &= CURSORBLINK_DIS_MASK;
76221 + WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
76223 + else
76226 + tempMicroPeriod = temp * XMAX * YMAX * (PCD + 1);
76227 + temp = 96*10000000/(blink * tempMicroPeriod);
76228 + tempReg = READREG(DBMX1_LCD_CURBLKCR);
76229 + tempReg |= CURSORBLINK_EN_MASK;
76230 + tempReg |= temp;
76231 + WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
76232 + DPRINTK(KERN_ERR"Inter_CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
76235 + FUNC_END;
76238 + /*****************************************************************************
76239 + * Function Name: dbmx1fb_set_cursor_state()
76241 + * Input: fb : frame buffer database
76242 + * state : The status of the cursor to be set. e.g.
76243 + * LCD_CURSOR_OFF
76244 + * LCD_CURSOR_ON
76245 + * LCD_CURSOR_REVERSED
76246 + * LCD_CURSOR_ON_WHITE
76247 + * LCD_CURSOR_OR_BGD
76248 + * LCD_CURSOR_XOR_BGD
76249 + * LCD_CURSOR_AND_BGD
76251 + * Value Returned: VOID
76253 + * Functions Called: VOID
76255 + * Description: Set state of cursor
76257 + * Modification History:
76258 + * 10 DEC,2001, Zhang Juan
76259 +******************************************************************************/
76260 +static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state)
76262 + struct dbmx1fb_cursor *c = &fb->cursor;
76263 + UINT32 temp;
76265 + FUNC_START;
76266 + c->state = state;
76267 + temp = READREG(DBMX1_LCD_LCXYP);
76268 + temp &= CURSOR_OFF_MASK;
76270 + if (state == LCD_CURSOR_OFF)
76271 + temp = temp;
76272 + else if (state == LCD_CURSOR_ON)
76273 + temp |= CURSOR_ON_MASK;
76274 +#ifdef FBCON_HAS_CFB4
76275 + else if (state == LCD_CURSOR_REVERSED)
76276 + temp |= CURSOR_REVERSED_MASK;
76277 + else if (state == LCD_CURSOR_ON_WHITE)
76278 + temp |= CURSOR_WHITE_MASK;
76279 +#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
76280 + else if(state == LCD_CURSOR_INVERT_BGD)
76281 + temp |= CURSOR_INVERT_MASK;
76282 + else if (state == LCD_CURSOR_OR_BGD)
76283 + temp |= CURSOR_OR_BGD_MASK;
76284 + else if (state == LCD_CURSOR_XOR_BGD)
76285 + temp |= CURSOR_XOR_BGD_MASK;
76286 + else if (state == LCD_CURSOR_AND_BGD)
76287 + temp |= CURSOR_AND_BGD_MASK;
76288 +#endif
76289 + WRITEREG(DBMX1_LCD_LCXYP,temp);
76290 + DPRINTK(KERN_ERR"LCDXYP=%x\n",READREG(DBMX1_LCD_LCXYP));
76291 + FUNC_END;
76295 +/*****************************************************************************
76296 + * Function Name: dbmx1fb_cursor()
76298 + * Input: fb : frame buffer database
76300 + * Value Returned: cursor : The structure of hardware cursor
76302 + * Functions Called: dbmx1fb_set_cursor()
76303 + * dbmx1fb_set_cursor_state()
76305 + * Description: The entry for display switch to operate hardware cursor
76307 + * Modification History:
76308 + * 10 DEC,2001, Zhang Juan
76309 +******************************************************************************/
76310 +static void dbmx1fb_cursor(struct display *p, int mode, int x, int y)
76312 + struct dbmx1fb_info *fb = (struct dbmx1fb_info *)p->fb_info;
76313 + struct dbmx1fb_cursor *c = &fb->cursor;
76315 + FUNC_START;
76316 + if (c==0) return;
76319 + x *= fontwidth(p);
76320 + y *= fontheight(p);
76322 + c->startx = x;
76323 + c->starty = y;
76325 + switch (mode) {
76326 + case CM_ERASE:
76327 + dbmx1fb_set_cursor_state(fb,LCD_CURSOR_OFF);
76328 + break;
76330 + case CM_DRAW:
76331 + case CM_MOVE:
76332 + c->state = LCD_CURSOR_ON;
76333 + dbmx1fb_set_cursor(fb);
76334 + dbmx1fb_set_cursor_state(fb, c->state);
76335 + break;
76337 + FUNC_END;
76340 +/*****************************************************************************
76341 + * Function Name: dbmx1fb_set_font()
76343 + * Input: display : console datebase
76344 + * width : The new width of cursor to be set.
76345 + * height : The new height of cursor position to be set
76347 + * Value Returned: int : Return status.If no error, return 0.
76349 + * Functions Called: dbmx1fb_set_cursor()
76350 + * dbmx1fb_set_cursor_color()
76352 + * Description: Set font for cursor
76354 + * Modification History:
76355 + * 10 DEC,2001, Zhang Juan
76356 +******************************************************************************/
76357 +static int dbmx1fb_set_font(struct display *d, int width, int height)
76359 + struct dbmx1fb_info *fb=(struct dbmx1fb_info *)d->fb_info;
76360 + struct dbmx1fb_cursor *c = &fb->cursor;
76362 + FUNC_START;
76363 + if(!d){
76364 + printk(KERN_ERR"dbmx1fb_set_font d=null\n");
76365 + return -1;
76368 + if (c) {
76369 + if (!width || !height) {
76370 + width = 16;
76371 + height = 16;
76374 + c->width = width;
76375 + c->height = height;
76377 + DPRINTK(KERN_ERR"set cursor\n");
76378 + dbmx1fb_set_cursor(fb);
76379 + DPRINTK(KERN_ERR"set color cursor\n");
76380 + dbmx1fb_set_cursor_color(fb, cursor_color_map,
76381 + cursor_color_map, cursor_color_map);
76382 + }else{
76383 + DPRINTK(KERN_ERR"set cursor failed, cursor == null\n");
76386 + FUNC_END;
76387 + return 1;
76389 +#endif // HARDWARE_CURSOR
76390 +/* end of file */
76392 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
76393 +++ linux-2.4.25/drivers/video/dbmx1fb.h 2004-03-31 17:15:09.000000000 +0200
76394 @@ -0,0 +1,213 @@
76395 +/****************************************************************************
76397 + * Copyright (C) 2001, Chen Ning All Rights Reserved
76399 + * File Name: dbmx1fb.h
76401 + * Progammers: Chen Ning, Zhang Juan
76403 + * Date of Creations: 10 DEC,2001
76405 + * Synopsis:
76407 + * Descirption:
76409 + * Modification History:
76410 + * 10 DEC, 2001, initialization version, frame work for frame buffer driver
76412 +*******************************************************************************/
76414 +#ifndef LCDFB_H
76415 +#define LCDFB_H
76416 +#include "asm/arch/hardware.h"
76417 +#include "asm/arch/platform.h"
76419 +typedef signed char BOOLEAN;
76420 +typedef unsigned char UINT8; /* Unsigned 8 bit quantity */
76421 +typedef signed char SINT8; /* Signed 8 bit quantity */
76422 +typedef unsigned short UINT16; /* Unsigned 16 bit quantity */
76423 +typedef signed short SINT16; /* Signed 16 bit quantity */
76424 +typedef unsigned long UINT32; /* Unsigned 32 bit quantity */
76425 +typedef signed long SINT32; /* Signed 32 bit quantity */
76427 +typedef volatile BOOLEAN VBOOLEAN;
76428 +typedef volatile UINT8 VUINT8; /* Unsigned 8 bit quantity */
76429 +typedef volatile SINT8 VSINT8; /* Signed 8 bit quantity */
76430 +typedef volatile UINT16 VUINT16; /* Unsigned 16 bit quantity */
76431 +typedef volatile SINT16 VSINT16; /* Signed 16 bit quantity */
76432 +typedef volatile UINT32 VUINT32; /* Unsigned 32 bit quantity */
76433 +typedef volatile SINT32 VSINT32; /* Signed 32 bit quantity */
76435 +#define LCDBASE 0x00205000
76436 +#define LCD_REGIONSIZE 0xc00
76438 +#define DBMX1_LCD_SSA 0x00205000
76439 +#define DBMX1_LCD_XYMAX 0x00205004
76440 +#define DBMX1_LCD_VPW 0x00205008
76441 +#define DBMX1_LCD_LCXYP 0x0020500c
76442 +#define DBMX1_LCD_CURBLKCR 0x00205010
76443 +#define DBMX1_LCD_LCHCC 0x00205014
76444 +#define DBMX1_LCD_PANELCFG 0x00205018
76445 +#define DBMX1_LCD_HCFG 0x0020501c
76446 +#define DBMX1_LCD_VCFG 0x00205020
76447 +#define DBMX1_LCD_POS 0x00205024
76448 +#define DBMX1_LCD_LGPMR 0x00205028
76449 +#define DBMX1_LCD_PWMR 0x0020502c
76450 +#define DBMX1_LCD_DMACR 0x00205030
76451 +#define DBMX1_LCD_REFMCR 0x00205034
76452 +#define DBMX1_LCD_INTCR 0x00205038
76453 +#define DBMX1_LCD_INTSR 0x00205040
76454 +#define DBMX1_LCD_MAPRAM 0x00205800
76456 +#define MPCTL0 0x0021B004
76457 +#define PCDR 0X0021B020
76459 +#define SSA DBMX1_LCD_SSA
76460 +#define XYMAX DBMX1_LCD_XYMAX
76461 +#define VPW DBMX1_LCD_VPW
76462 +#define LCXYP DBMX1_LCD_LCXYP
76463 +#define CURBLKCR DBMX1_LCD_CURBLKCR
76464 +#define LCHCC DBMX1_LCD_LCHCC
76465 +#define PANELCFG DBMX1_LCD_PANELCFG
76466 +#define VCFG DBMX1_LCD_VCFG
76467 +#define HCFG DBMX1_LCD_HCFG
76468 +#define POS DBMX1_LCD_POS
76469 +#define LGPMR DBMX1_LCD_LGPMR
76470 +#define PWMR DBMX1_LCD_PWMR
76471 +#define DMACR DBMX1_LCD_DMACR
76472 +#define REFMCR DBMX1_LCD_REFMCR
76473 +#define INTCR DBMX1_LCD_INTCR
76474 +#define INTSR DBMX1_LCD_INTSR
76475 +#define MAPRAM DBMX1_LCD_MAPRAM
76476 +// default value
76477 +#define SHARP_TFT_240x320
76479 +#ifdef SHARP_TFT_240x320
76480 +#define PANELCFG_VAL_12 0xf8008b48
76481 +#define HCFG_VAL_12 0x04000f06
76482 +#define VCFG_VAL_12 0x04000907
76483 +#define PWMR_VAL 0x0000008a
76484 +#define LCD_MAXX 240
76485 +#define LCD_MAXY 320
76486 +#else //SHARP_TFT_240x320
76488 +#define PANELCFG_VAL_12 0xf8088c6b
76489 +#define HCFG_VAL_12 0x04000f06
76490 +#define VCFG_VAL_12 0x04010c03
76491 +#define PWMR_VAL 0x00000200
76492 +#define LCD_MAXX 320
76493 +#define LCD_MAXY 240
76494 +#endif // SHARP_TFT_240x320
76496 +#define PANELCFG_VAL_4 0x20008c09
76497 +#define PANELCFG_VAL_4C 0x60008c09
76499 +#define HCFG_VAL_4 0x04000f07
76501 +#define VCFG_VAL_4 0x04010c03
76504 +#define REFMCR_VAL_4 0x00000003
76505 +#define REFMCR_VAL_12 0x00000003
76506 +#define DISABLELCD_VAL 0x00000000
76508 +#define DMACR_VAL_4 0x800c0003 // 12 & 3 TRIGGER
76509 +#define DMACR_VAL_12 0x00020008
76511 +#define INTCR_VAL_4 0x00000000
76512 +#define INTCR_VAL_12 0x00000000
76514 +#define INTSR_UDRERR 0x00000008
76515 +#define INTSR_ERRRESP 0x00000004
76516 +#define INTSR_EOF 0x00000002
76517 +#define INTSR_BOF 0x00000001
76519 +#define MIN_XRES 64
76520 +#define MIN_YRES 64
76522 +#define LCD_MAX_BPP 16
76524 +#if 0
76525 +#define READREG(r) \
76526 + inl(IO_ADDRESS(r))
76528 +#define WRITEREG(r, val) \
76529 + outl(val, IO_ADDRESS(r))
76530 +#else
76531 +#endif // 0
76533 +#define MAX_PALETTE_NUM_ENTRIES 256
76534 +#define MAX_PIXEL_MEM_SIZE \
76535 + ((current_par.max_xres * current_par.max_yres * current_par.max_bpp)/8)
76536 +#define MAX_FRAMEBUFFER_MEM_SIZE \
76537 + (MAX_PIXEL_MEM_SIZE + 32)
76538 +#define ALLOCATED_FB_MEM_SIZE \
76539 + (PAGE_ALIGN(MAX_FRAMEBUFFER_MEM_SIZE + PAGE_SIZE * 2))
76541 + // TODO:
76542 +#define FBCON_HAS_CFB4
76543 +#define FBCON_HAS_CFB8
76544 +#define FBCON_HAS_CFB16
76546 +#define IRQ_LCD 12 // TODO: which irq?
76547 +#define DBMX1_NAME "DBMX1FB"
76548 +#define DEV_NAME DBMX1_NAME
76549 +#define MAX_PALETTE_NUM_ENTRIES 256
76550 +#define DEFAULT_CURSOR_BLINK_RATE (20)
76551 +#define CURSOR_DRAW_DELAY (2)
76552 +/*cursor status*/
76553 +#define LCD_CURSOR_OFF 0
76554 +#define LCD_CURSOR_ON 1
76556 +#ifdef FBCON_HAS_CFB4
76557 + #define LCD_CURSOR_REVERSED 2
76558 + #define LCD_CURSOR_ON_WHITE 3
76559 +#elif defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16)
76560 + #define LCD_CURSOR_INVERT_BGD 2
76561 + #define LCD_CURSOR_AND_BGD 3
76562 + #define LCD_CURSOR_OR_BGD 4
76563 + #define LCD_CURSOR_XOR_BGD 5
76564 +#endif //FBCON_HAS_CFB4
76566 +/* MASK use for caculating MCDUPLLCLK */
76567 +#define MFI_MASK 0x00003C00
76568 +#define MFN_MASK 0x000003FF
76569 +#define PD_MASK 0x3C000000
76570 +#define MFD_MASK 0x03FF0000
76571 +#define PCLKDIV2_MASK 0x000000F0
76572 +#define PCD_MASK 0x0000003F
76573 +#define XMAX_MASK 0xF3F00000
76574 +#define YMAX_MASK 0x000001FF
76575 +#define HWAIT1_MASK 0x0000FF00
76576 +#define HWAIT2_MASK 0x000000FF
76577 +#define HWIDTH_MASK 0xFC000000
76578 +#define PASSDIV_MASK 0x00FF0000
76579 +#define VWAIT1_MASK 0x0000FF00
76580 +#define VWAIT2_MASK 0x000000FF
76581 +#define VWIDTH_MASK 0xFC000000
76582 +#define CURSORBLINK_DIS_MASK 0x80000000
76584 +#define DISPLAY_MODE_MASK 0x80000000
76586 +#define MCU_FREQUENCE 32768
76587 +#define COLOR_MASK 0x40000000
76589 +/* MASK use for indicating the cursor status */
76590 +#define CURSOR_ON_MASK 0x40000000
76591 +#define CURSOR_OFF_MASK 0x0FFFFFFF
76592 +#define MAX_CURSOR_WIDTH 31
76593 +#define MAX_CURSOR_HEIGHT 31
76594 +#define CURSORBLINK_EN_MASK 0x80000000
76596 +#ifdef FBCON_HAS_CFB4
76597 +#define CURSOR_REVERSED_MASK 0x80000000
76598 +#define CURSOR_WHITE_MASK 0xC0000000
76599 +#else
76600 +#define CURSOR_INVERT_MASK 0x80000000
76601 +#define CURSOR_AND_BGD_MASK 0xC0000000
76602 +#define CURSOR_OR_BGD_MASK 0x50000000
76603 +#define CURSOR_XOR_BGD_MASK 0x90000000
76604 +#endif // FBCON_HAS_CFB4
76606 +#endif //LCDFB_H
76608 --- linux-2.4.25/drivers/video/fbmem.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
76609 +++ linux-2.4.25/drivers/video/fbmem.c 2004-03-31 17:15:09.000000000 +0200
76610 @@ -61,7 +61,9 @@
76611 extern int pm2fb_setup(char*);
76612 extern int pm3fb_init(void);
76613 extern int pm3fb_setup(char*);
76614 +extern int clps711xfb_init(void);
76615 extern int cyber2000fb_init(void);
76616 +extern int cyber2000fb_setup(char*);
76617 extern int retz3fb_init(void);
76618 extern int retz3fb_setup(char*);
76619 extern int clgenfb_init(void);
76620 @@ -145,6 +147,8 @@
76621 extern int sstfb_setup(char*);
76622 extern int it8181fb_init(void);
76623 extern int it8181fb_setup(char*);
76624 +extern int anakinfb_init(void);
76625 +extern int dbmx1fb_init(void);
76627 static struct {
76628 const char *name;
76629 @@ -170,11 +174,14 @@
76630 #ifdef CONFIG_FB_AMIGA
76631 { "amifb", amifb_init, amifb_setup },
76632 #endif
76633 +#ifdef CONFIG_FB_CLPS711X
76634 + { "clps711xfb", clps711xfb_init, NULL },
76635 +#endif
76636 #ifdef CONFIG_FB_CYBER
76637 { "cyber", cyberfb_init, cyberfb_setup },
76638 #endif
76639 #ifdef CONFIG_FB_CYBER2000
76640 - { "cyber2000", cyber2000fb_init, NULL },
76641 + { "cyber2000", cyber2000fb_init, cyber2000fb_setup },
76642 #endif
76643 #ifdef CONFIG_FB_PM2
76644 { "pm2fb", pm2fb_init, pm2fb_setup },
76645 @@ -226,10 +233,10 @@
76646 #endif
76647 #ifdef CONFIG_FB_S3TRIO
76648 { "s3trio", s3triofb_init, NULL },
76649 -#endif
76650 +#endif
76651 #ifdef CONFIG_FB_FM2
76652 { "fm2fb", fm2fb_init, fm2fb_setup },
76653 -#endif
76654 +#endif
76655 #ifdef CONFIG_FB_SIS
76656 { "sisfb", sisfb_init, sisfb_setup },
76657 #endif
76658 @@ -242,7 +249,7 @@
76661 * Generic drivers that are used as fallbacks
76662 - *
76664 * These depend on resource management and must be initialized
76665 * _after_ all other frame buffer devices that use resource
76666 * management!
76667 @@ -253,7 +260,7 @@
76668 #endif
76669 #ifdef CONFIG_FB_VESA
76670 { "vesa", vesafb_init, vesafb_setup },
76671 -#endif
76672 +#endif
76675 * Chipset specific drivers that don't use resource management (yet)
76676 @@ -276,7 +283,7 @@
76677 #endif
76678 #ifdef CONFIG_FB_HGA
76679 { "hga", hgafb_init, hgafb_setup },
76680 -#endif
76681 +#endif
76682 #ifdef CONFIG_FB_IGA
76683 { "igafb", igafb_init, igafb_setup },
76684 #endif
76685 @@ -291,7 +298,7 @@
76686 #endif
76687 #ifdef CONFIG_FB_HP300
76688 { "hpfb", hpfb_init, NULL },
76689 -#endif
76690 +#endif
76691 #ifdef CONFIG_FB_G364
76692 { "g364", g364fb_init, NULL },
76693 #endif
76694 @@ -307,6 +314,9 @@
76695 #ifdef CONFIG_FB_TX3912
76696 { "tx3912", tx3912fb_init, NULL },
76697 #endif
76698 +#ifdef CONFIG_FB_ANAKIN
76699 + { "anakinfb", anakinfb_init, NULL },
76700 +#endif
76701 #ifdef CONFIG_FB_E1355
76702 { "e1355fb", e1355fb_init, e1355fb_setup },
76703 #endif
76704 @@ -330,10 +340,13 @@
76705 #endif
76706 #ifdef CONFIG_FB_AU1100
76707 { "au1100fb", au1100fb_init, au1100fb_setup },
76708 -#endif
76709 +#endif
76710 #ifdef CONFIG_FB_IT8181
76711 { "it8181fb", it8181fb_init, it8181fb_setup },
76712 #endif
76713 +#ifdef CONFIG_FB_DBMX1
76714 + { "dbmx1fb", dbmx1fb_init, NULL },
76715 +#endif
76719 @@ -342,7 +355,7 @@
76721 #ifdef CONFIG_FB_VGA16
76722 { "vga16", vga16fb_init, vga16fb_setup },
76723 -#endif
76724 +#endif
76725 #ifdef CONFIG_FB_STI
76726 { "stifb", stifb_init, stifb_setup },
76727 #endif
76728 @@ -371,7 +384,7 @@
76730 struct fb_info *registered_fb[FB_MAX];
76731 int num_registered_fb;
76732 -extern int fbcon_softback_size;
76733 +extern int fbcon_softback_size;
76735 static int first_fb_vc;
76736 static int last_fb_vc = MAX_NR_CONSOLES-1;
76737 @@ -480,7 +493,7 @@
76739 #endif /* CONFIG_KMOD */
76741 -static int
76742 +static int
76743 fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
76744 unsigned long arg)
76746 @@ -492,7 +505,7 @@
76747 struct fb_fix_screeninfo fix;
76748 struct fb_con2fbmap con2fb;
76749 int i;
76752 if (! fb)
76753 return -ENODEV;
76754 switch (cmd) {
76755 @@ -576,7 +589,7 @@
76759 -static int
76760 +static int
76761 fb_mmap(struct file *file, struct vm_area_struct * vma)
76763 int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
76764 @@ -667,11 +680,11 @@
76765 #elif defined(__sh__)
76766 pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
76767 #elif defined(__hppa__)
76768 - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
76769 + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
76770 #elif defined(__ia64__)
76771 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
76772 #elif defined(__hppa__)
76773 - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
76774 + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
76775 #else
76776 #warning What do we have to do here??
76777 #endif
76778 @@ -724,7 +737,7 @@
76779 return res;
76782 -static int
76783 +static int
76784 fb_release(struct inode *inode, struct file *file)
76786 int fbidx = GET_FB_IDX(inode->i_rdev);
76787 @@ -856,7 +869,7 @@
76791 -void __init
76792 +void __init
76793 fbmem_init(void)
76795 int i;
76796 @@ -904,7 +917,7 @@
76798 if (!options || !*options)
76799 return 0;
76802 if (!strncmp(options, "scrollback:", 11)) {
76803 options += 11;
76804 if (*options) {
76805 @@ -930,7 +943,7 @@
76807 return 0;
76811 if (!strncmp(options, "vc:", 3)) {
76812 options += 3;
76813 if (*options)
76814 --- linux-2.4.25/drivers/video/font_acorn_8x8.c~2.4.25-vrs2.patch 1998-09-30 05:56:33.000000000 +0200
76815 +++ linux-2.4.25/drivers/video/font_acorn_8x8.c 2004-03-31 17:15:09.000000000 +0200
76816 @@ -11,33 +11,33 @@
76817 /* 03 */ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^C */
76818 /* 04 */ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^D */
76819 /* 05 */ 0x00, 0x18, 0x3c, 0xe7, 0xe7, 0x3c, 0x18, 0x00, /* ^E */
76820 -/* 06 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76821 -/* 07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76822 -/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76823 -/* 09 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76824 -/* 0A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76825 -/* 0B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76826 -/* 0C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76827 -/* 0D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76828 -/* 0E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76829 -/* 0F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76830 +/* 06 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76831 +/* 07 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76832 +/* 08 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76833 +/* 09 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76834 +/* 0A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76835 +/* 0B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76836 +/* 0C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76837 +/* 0D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76838 +/* 0E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76839 +/* 0F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76840 /* 10 */ 0x00, 0x60, 0x78, 0x7e, 0x7e, 0x78, 0x60, 0x00, /* |> */
76841 /* 11 */ 0x00, 0x06, 0x1e, 0x7e, 0x7e, 0x1e, 0x06, 0x00, /* <| */
76842 -/* 12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76843 -/* 13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76844 -/* 14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76845 -/* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76846 -/* 16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76847 -/* 17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76848 -/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76849 -/* 19 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76850 -/* 1A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76851 -/* 1B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76852 -/* 1C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76853 -/* 1D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76854 +/* 12 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76855 +/* 13 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76856 +/* 14 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76857 +/* 15 */ 0x3c, 0x60, 0x3c, 0x66, 0x3c, 0x06, 0x3c, 0x00,
76858 +/* 16 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76859 +/* 17 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76860 +/* 18 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76861 +/* 19 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76862 +/* 1A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76863 +/* 1B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76864 +/* 1C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76865 +/* 1D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76866 /* 1E */ 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x00, /* /\ */
76867 /* 1F */ 0x00, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, 0x00, /* \/ */
76868 -/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
76869 +/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
76870 /* 21 */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, /* ! */
76871 /* 22 */ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, /* " */
76872 /* 23 */ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, /* # */
76873 @@ -132,55 +132,55 @@
76874 /* 7C */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* | */
76875 /* 7D */ 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, /* } */
76876 /* 7E */ 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, /* ~ */
76877 -/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* \x7f */
76878 -/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76879 -/* 81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76880 -/* 82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76881 -/* 83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76882 -/* 84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76883 -/* 85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76884 -/* 86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76885 -/* 87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76886 -/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76887 -/* 89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76888 -/* 8A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76889 -/* 8B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76890 -/* 8C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76891 -/* 8D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76892 -/* 8E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76893 -/* 8F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76894 -/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76895 -/* 91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76896 -/* 92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76897 -/* 93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76898 -/* 94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76899 -/* 95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76900 -/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76901 -/* 97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76902 -/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76903 -/* 99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76904 -/* 9A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76905 -/* 9B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76906 -/* 9C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76907 -/* 9D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76908 -/* 9E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76909 -/* 9F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76910 -/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76911 -/* A1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76912 -/* A2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76913 -/* A3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76914 -/* A4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76915 -/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76916 -/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76917 -/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76918 -/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76919 -/* A9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76920 -/* AA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76921 -/* AB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76922 -/* AC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76923 -/* AD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76924 -/* AE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76925 -/* AF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76926 +/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* \x7f */
76927 +/* 80 */ 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x30, 0x60,
76928 +/* 81 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00,
76929 +/* 82 */ 0x0c, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
76930 +/* 83 */ 0x18, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
76931 +/* 84 */ 0x66, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
76932 +/* 85 */ 0x30, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
76933 +/* 86 */ 0x3c, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
76934 +/* 87 */ 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x60,
76935 +/* 88 */ 0x3c, 0x66, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
76936 +/* 89 */ 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
76937 +/* 8A */ 0x30, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
76938 +/* 8B */ 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
76939 +/* 8C */ 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
76940 +/* 8D */ 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
76941 +/* 8E */ 0x66, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
76942 +/* 8F */ 0x18, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
76943 +/* 90 */ 0x0c, 0x18, 0x7e, 0x60, 0x7c, 0x60, 0x7e, 0x00,
76944 +/* 91 */ 0x00, 0x00, 0x3f, 0x0d, 0x3f, 0x6c, 0x3f, 0x00,
76945 +/* 92 */ 0x3f, 0x66, 0x66, 0x7f, 0x66, 0x66, 0x67, 0x00,
76946 +/* 93 */ 0x3c, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
76947 +/* 94 */ 0x66, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
76948 +/* 95 */ 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
76949 +/* 96 */ 0x3c, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
76950 +/* 97 */ 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
76951 +/* 98 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c,
76952 +/* 99 */ 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00,
76953 +/* 9A */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
76954 +/* 9B */ 0x08, 0x3e, 0x6b, 0x68, 0x6b, 0x3e, 0x08, 0x00,
76955 +/* 9C */ 0x1c, 0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00,
76956 +/* 9D */ 0x66, 0x3c, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00,
76957 +/* 9E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76958 +/* 9F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
76959 +/* A0 */ 0x0c, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
76960 +/* A1 */ 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
76961 +/* A2 */ 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
76962 +/* A3 */ 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
76963 +/* A4 */ 0x36, 0x6c, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x00,
76964 +/* A5 */ 0x36, 0x6c, 0x00, 0x66, 0x76, 0x6e, 0x66, 0x00,
76965 +/* A6 */ 0x1c, 0x06, 0x1e, 0x36, 0x1e, 0x00, 0x3e, 0x00,
76966 +/* A7 */ 0x1c, 0x36, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00,
76967 +/* A8 */ 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3c, 0x00,
76968 +/* A9 */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76969 +/* AA */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76970 +/* AB */ 0x40, 0xc0, 0x40, 0x4f, 0x41, 0x0f, 0x08, 0x0f,
76971 +/* AC */ 0x40, 0xc0, 0x40, 0x48, 0x48, 0x0a, 0x0f, 0x02,
76972 +/* AD */ 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
76973 +/* AE */ 0x00, 0x33, 0x66, 0xcc, 0xcc, 0x66, 0x33, 0x00,
76974 +/* AF */ 0x00, 0xcc, 0x66, 0x33, 0x33, 0x66, 0xcc, 0x00,
76975 /* B0 */ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
76976 /* B1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
76977 /* B2 */ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
76978 @@ -229,37 +229,37 @@
76979 /* DD */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
76980 /* DE */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
76981 /* DF */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
76982 -/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76983 -/* E1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76984 -/* E2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76985 -/* E3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76986 -/* E4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76987 -/* E5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76988 -/* E6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76989 -/* E7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76990 -/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76991 -/* E9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76992 -/* EA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76993 -/* EB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76994 -/* EC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76995 -/* ED */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76996 -/* EE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76997 -/* EF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76998 -/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76999 -/* F1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77000 -/* F2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77001 -/* F3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77002 -/* F4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77003 -/* F5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77004 -/* F6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77005 -/* F7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77006 -/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77007 -/* F9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77008 -/* FA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77009 -/* FB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77010 -/* FC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77011 -/* FD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77012 -/* FE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77013 +/* E0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77014 +/* E1 */ 0x3c, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x6c, 0xc0,
77015 +/* E2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77016 +/* E3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77017 +/* E4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77018 +/* E5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77019 +/* E6 */ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x60,
77020 +/* E7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77021 +/* E8 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77022 +/* E9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77023 +/* EA */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77024 +/* EB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77025 +/* EC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77026 +/* ED */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77027 +/* EE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77028 +/* EF */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77029 +/* F0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77030 +/* F1 */ 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
77031 +/* F2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77032 +/* F3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77033 +/* F4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77034 +/* F5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77035 +/* F6 */ 0x00, 0x18, 0x00, 0xff, 0x00, 0x18, 0x00, 0x00,
77036 +/* F7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77037 +/* F8 */ 0x3c, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
77038 +/* F9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77039 +/* FA */ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
77040 +/* FB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77041 +/* FC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77042 +/* FD */ 0x38, 0x04, 0x18, 0x20, 0x3c, 0x00, 0x00, 0x00,
77043 +/* FE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
77044 /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
77047 --- linux-2.4.25/drivers/video/pm3fb.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
77048 +++ linux-2.4.25/drivers/video/pm3fb.c 2004-03-31 17:15:09.000000000 +0200
77049 @@ -5,7 +5,6 @@
77050 * Based on code written by:
77051 * Sven Luther, <luther@dpt-info.u-strasbg.fr>
77052 * Alan Hourihane, <alanh@fairlite.demon.co.uk>
77053 - * Russel King, <rmk@arm.linux.org.uk>
77054 * Based on linux/drivers/video/skeletonfb.c:
77055 * Copyright (C) 1997 Geert Uytterhoeven
77056 * Based on linux/driver/video/pm2fb.c:
77057 @@ -16,13 +15,9 @@
77058 * License. See the file COPYING in the main directory of this archive for
77059 * more details.
77061 - * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
77062 + * $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $
77064 * CHANGELOG:
77065 - * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
77066 - * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
77067 - * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
77068 - * Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings.
77069 * Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes.
77070 * Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix.
77071 * Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG.
77072 @@ -53,8 +48,8 @@
77075 #include <linux/config.h>
77076 -#include <linux/module.h>
77077 #include <linux/version.h>
77078 +#include <linux/module.h>
77079 #include <linux/kernel.h>
77080 #include <linux/errno.h>
77081 #include <linux/string.h>
77082 @@ -80,7 +75,6 @@
77084 #include <asm/io.h>
77085 #include <asm/uaccess.h>
77087 #ifdef CONFIG_FB_OF
77088 #include <asm/prom.h>
77089 #endif
77090 @@ -128,7 +122,6 @@
77091 unsigned long refresh;
77092 unsigned long powerdown;
77094 -typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result;
77095 #define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1)
77096 #define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE }
77098 @@ -191,21 +184,13 @@
77099 PM3VideoControl_VSYNC_ACTIVE_HIGH
77100 | PM3VideoControl_PIXELSIZE_8BIT}}, {
77101 "1024x768-74-32", {
77102 - 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
77103 - 806, 1024, 0, 32,
77104 - PM3VideoControl_ENABLE |
77105 - PM3VideoControl_HSYNC_ACTIVE_HIGH
77107 - PM3VideoControl_VSYNC_ACTIVE_HIGH
77108 - | PM3VideoControl_PIXELSIZE_32BIT}},
77109 -/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/
77111 - "SGI1600SW", {
77112 - 108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32,
77113 - 1056, 1600, 0, 8,
77114 - PM3VideoControl_ENABLE|
77115 - PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW|
77116 - PM3VideoControl_PIXELSIZE_32BIT}},
77117 + 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
77118 + 806, 1024, 0, 32,
77119 + PM3VideoControl_ENABLE |
77120 + PM3VideoControl_HSYNC_ACTIVE_HIGH
77122 + PM3VideoControl_VSYNC_ACTIVE_HIGH
77123 + | PM3VideoControl_PIXELSIZE_32BIT}},
77124 /* ##### auto-generated mode, by fbtimings2pm3 */
77125 /* Generated mode : "640x480-60" */
77127 @@ -554,11 +539,9 @@
77128 short noaccel[PM3_MAX_BOARD];
77129 char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE];
77130 short depth[PM3_MAX_BOARD];
77131 -short flatpanel[PM3_MAX_BOARD];
77132 static struct display disp[PM3_MAX_BOARD];
77133 static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy";
77134 short printtimings = 0;
77135 -short forcesize[PM3_MAX_BOARD];
77137 /* ********************* */
77138 /* ***** prototype ***** */
77139 @@ -566,8 +549,7 @@
77140 /* card-specific */
77141 static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info);
77142 /* permedia3-specific */
77143 -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
77144 -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info);
77145 +static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
77146 static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info);
77147 static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
77148 unsigned long r);
77149 @@ -683,7 +665,7 @@
77150 NULL, NULL
77152 #endif /* KERNEL_2_2 */
77153 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77154 +#ifdef KERNEL_2_4
77155 struct fbgen_hwswitch pm3fb_switch = {
77156 pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
77157 pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, pm3fb_setcolreg,
77158 @@ -696,7 +678,7 @@
77159 fbgen_get_fix, fbgen_get_var, fbgen_set_var,
77160 fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display, pm3fb_ioctl, NULL, NULL
77162 -#endif /* KERNEL_2_4 or KERNEL_2_5 */
77163 +#endif /* KERNEL_2_4 */
77164 #ifdef PM3FB_USE_ACCEL
77165 #ifdef FBCON_HAS_CFB32
77166 static struct display_switch pm3fb_cfb32 = {
77167 @@ -727,75 +709,52 @@
77168 #endif /* FBCON_HAS_CFB8 */
77169 #endif /* PM3FB_USE_ACCEL */
77171 -/* ****************************** */
77172 -/* ***** card-specific data ***** */
77173 -/* ****************************** */
77174 -struct pm3fb_card_timings {
77175 - unsigned long memsize; /* 0 for last value (i.e. default) */
77176 - struct pm3fb_timings memt;
77179 -static struct pm3fb_card_timings t_FormacProFormance3[] = {
77180 - { 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} },
77181 - { 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */
77184 -static struct pm3fb_card_timings t_AppianJeronimo2000[] = {
77185 - { 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} },
77186 - { 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */
77189 -static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = {
77190 - { 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} },
77191 - { 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */
77194 +/* ********************************** */
77195 +/* ***** card-specific function ***** */
77196 +/* ********************************** */
77197 static struct {
77198 char cardname[32]; /* recognized card name */
77199 u16 subvendor; /* subvendor of the card */
77200 u16 subdevice; /* subdevice of the card */
77201 u8 func; /* function of the card to which the extra init apply */
77202 void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */
77203 - struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */
77204 + struct pm3fb_timings memt; /* default timing for the board WARNING : might be *card* - specific */
77205 } cardbase[] = {
77206 - { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL },
77207 - { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL,
77208 - t_AppianJeronimo2000
77209 - },
77210 + { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, PM3FB_UNKNOWN_TIMINGS },
77211 + { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL, PM3FB_UNKNOWN_TIMINGS },
77212 { "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup,
77213 - t_AppianJeronimo2000
77214 + {0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} /* also in pm3fb_j2000_setup */
77216 { "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */
77217 - t_FormacProFormance3
77218 + { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} /* from the 16Mb ProFormance 3 */
77220 - { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL },
77221 + { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
77222 { "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL,
77223 - t_3DLabsOxygenVX1
77224 + { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000 }
77226 - { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL },
77227 - { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL },
77228 - { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL },
77229 - { "\0", 0x0, 0x0, 0, NULL, NULL }
77230 + { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
77231 + { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
77232 + { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
77233 + { "\0", 0x0, 0x0, 0, NULL, PM3FB_UNKNOWN_TIMINGS }
77236 -/* ********************************** */
77237 -/* ***** card-specific function ***** */
77238 -/* ********************************** */
77239 static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info)
77240 { /* the appian j2000 require more initialization of the second head */
77241 /* l_fb_info must point to the _second_ head of the J2000 */
77243 DTRACE;
77245 - l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */
77247 + /* Memory timings for the Appian J2000 board. also in cardbase */
77248 + l_fb_info->memt.caps = 0x02e311B8;
77249 + l_fb_info->memt.timings = 0x07424905;
77250 + l_fb_info->memt.control = 0x0c000003;
77251 + l_fb_info->memt.refresh = 0x00000061;
77252 + l_fb_info->memt.powerdown = 0x00000000;
77254 pm3fb_write_memory_timings(l_fb_info);
77257 -/* *************************************** */
77258 -/* ***** permedia3-specific function ***** */
77259 -/* *************************************** */
77260 -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
77261 +static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
77263 l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps);
77264 l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings);
77265 @@ -810,35 +769,20 @@
77266 (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE))
77268 printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num);
77269 - return(pm3fb_try_memory_timings(l_fb_info));
77271 - return(pm3fb_timing_ok);
77274 -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info)
77276 - if (cardbase[l_fb_info->board_type].c_memt)
77278 - int i = 0, done = 0;
77279 - while (!done)
77280 + if ((cardbase[l_fb_info->board_type].memt.caps != PM3FB_UNKNOWN_TIMING_VALUE) &&
77281 + (cardbase[l_fb_info->board_type].memt.timings != PM3FB_UNKNOWN_TIMING_VALUE) &&
77282 + (cardbase[l_fb_info->board_type].memt.control != PM3FB_UNKNOWN_TIMING_VALUE) &&
77283 + (cardbase[l_fb_info->board_type].memt.refresh != PM3FB_UNKNOWN_TIMING_VALUE) &&
77284 + (cardbase[l_fb_info->board_type].memt.powerdown != PM3FB_UNKNOWN_TIMING_VALUE))
77286 - if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size)
77287 - || !(cardbase[l_fb_info->board_type].c_memt[i].memsize))
77288 - { /* will use the 0-sized timings by default */
77289 - done = 1;
77290 - l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt;
77291 - printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n",
77292 - l_fb_info->board_num,
77293 - cardbase[l_fb_info->board_type].cardname,
77294 - cardbase[l_fb_info->board_type].c_memt[i].memsize);
77295 - pm3fb_write_memory_timings(l_fb_info);
77296 - return(pm3fb_timing_retry);
77298 - i++;
77299 + l_fb_info->memt = cardbase[l_fb_info->board_type].memt;
77300 + printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s)\n", l_fb_info->board_num, cardbase[l_fb_info->board_type].cardname);
77301 + pm3fb_write_memory_timings(l_fb_info);
77303 - } else
77304 - return(pm3fb_timing_problem);
77305 - return(pm3fb_timing_ok);
77306 + else
77307 + return(1);
77309 + return(0);
77312 static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info)
77313 @@ -873,6 +817,10 @@
77314 PM3RD_SClkControl_ENABLE);
77317 +/* *************************************** */
77318 +/* ***** permedia3-specific function ***** */
77319 +/* *************************************** */
77321 static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
77322 unsigned long r)
77324 @@ -1067,7 +1015,6 @@
77325 /* write the mode to registers */
77326 static void pm3fb_write_mode(struct pm3fb_info *l_fb_info)
77328 - char tempsync = 0x00, tempmisc = 0x00;
77329 DTRACE;
77331 PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff);
77332 @@ -1197,26 +1144,22 @@
77334 PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00);
77336 - if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) ==
77337 - PM3VideoControl_HSYNC_ACTIVE_HIGH)
77338 - tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
77339 - if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) ==
77340 - PM3VideoControl_VSYNC_ACTIVE_HIGH)
77341 - tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
77343 - PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
77344 - DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
77346 - if (flatpanel[l_fb_info->board_num])
77348 - PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE);
77349 - PM3_WAIT(2);
77350 - PM3_WRITE_REG(PM3VSConfiguration, 0x06);
77351 - PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */
77352 - tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE;
77353 + char tempsync = 0x00;
77355 + if ((l_fb_info->current_par->
77356 + video & PM3VideoControl_HSYNC_MASK) ==
77357 + PM3VideoControl_HSYNC_ACTIVE_HIGH)
77358 + tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
77359 + if ((l_fb_info->current_par->
77360 + video & PM3VideoControl_VSYNC_MASK) ==
77361 + PM3VideoControl_VSYNC_ACTIVE_HIGH)
77362 + tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
77364 + PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
77365 + DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
77367 - else
77368 - PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
77369 + PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
77371 switch (l_fb_info->current_par->depth) {
77372 case 8:
77373 @@ -1225,7 +1168,8 @@
77374 PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
77375 PM3RD_ColorFormat_CI8_COLOR |
77376 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
77377 - tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
77378 + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
77379 + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
77380 break;
77381 case 12:
77382 PM3_WRITE_DAC_REG(PM3RD_PixelSize,
77383 @@ -1234,8 +1178,9 @@
77384 PM3RD_ColorFormat_4444_COLOR |
77385 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
77386 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
77387 - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77388 - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
77389 + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
77390 + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77391 + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
77392 break;
77393 case 15:
77394 PM3_WRITE_DAC_REG(PM3RD_PixelSize,
77395 @@ -1244,8 +1189,9 @@
77396 PM3RD_ColorFormat_5551_FRONT_COLOR |
77397 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
77398 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
77399 - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77400 - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
77401 + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
77402 + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77403 + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
77404 break;
77405 case 16:
77406 PM3_WRITE_DAC_REG(PM3RD_PixelSize,
77407 @@ -1254,8 +1200,9 @@
77408 PM3RD_ColorFormat_565_FRONT_COLOR |
77409 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
77410 PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
77411 - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77412 - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
77413 + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
77414 + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77415 + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
77416 break;
77417 case 32:
77418 PM3_WRITE_DAC_REG(PM3RD_PixelSize,
77419 @@ -1263,12 +1210,12 @@
77420 PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
77421 PM3RD_ColorFormat_8888_COLOR |
77422 PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
77423 - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77424 - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
77425 + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
77426 + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
77427 + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
77428 break;
77430 - PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc);
77433 PM3_SHOW_CUR_MODE;
77436 @@ -1390,9 +1337,8 @@
77438 static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
77440 - unsigned long memsize = 0, tempBypass, i, temp1, temp2;
77441 + unsigned long memsize, tempBypass, i, temp1, temp2;
77442 u16 subvendor, subdevice;
77443 - pm3fb_timing_result ptr;
77445 DTRACE;
77447 @@ -1438,7 +1384,7 @@
77449 /* card-specific setup is done, we preserve the final
77450 memory timing for future reference */
77451 - if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */
77452 + if (pm3fb_preserve_memory_timings(l_fb_info)) { /* memory timings were wrong ! oops.... */
77453 return(0);
77456 @@ -1464,12 +1410,12 @@
77457 temp1 = readl((l_fb_info->v_fb + (i * 1048576)));
77458 #endif
77459 #endif /* KERNEL_2_2 */
77460 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77461 +#ifdef KERNEL_2_4
77462 fb_writel(i * 0x00345678,
77463 (l_fb_info->v_fb + (i * 1048576)));
77464 mb();
77465 temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576)));
77466 -#endif /* KERNEL_2_4 or KERNEL_2_5 */
77467 +#endif /* KERNEL_2_4 */
77468 /* Let's check for wrapover, write will fail at 16MB boundary */
77469 if (temp1 == (i * 0x00345678))
77470 memsize = i;
77471 @@ -1512,7 +1458,7 @@
77472 ((i - 32) * 1048576)));
77473 #endif
77474 #endif /* KERNEL_2_2 */
77475 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77476 +#ifdef KERNEL_2_4
77477 fb_writel(i * 0x00345678,
77478 (l_fb_info->v_fb + (i * 1048576)));
77479 mb();
77480 @@ -1521,7 +1467,7 @@
77481 temp2 =
77482 fb_readl((l_fb_info->v_fb +
77483 ((i - 32) * 1048576)));
77484 -#endif /* KERNEL_2_4 or KERNEL_2_5 */
77485 +#endif /* KERNEL_2_4 */
77486 if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */
77487 memsize = i;
77488 else
77489 @@ -1538,21 +1484,8 @@
77491 DPRINTK(2, "Returning 0x%08lx bytes\n", memsize);
77493 - if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize))
77495 - printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]);
77496 - memsize = 1048576 * forcesize[l_fb_info->board_num];
77499 l_fb_info->fb_size = memsize;
77501 - if (ptr == pm3fb_timing_retry)
77503 - printk(KERN_WARNING "pm3fb: retrying memory timings check");
77504 - if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem)
77505 - return(0);
77509 return (memsize);
77512 @@ -1571,7 +1504,7 @@
77513 writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
77514 #endif
77515 #endif
77516 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77517 +#ifdef KERNEL_2_4
77518 fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
77519 #endif
77521 @@ -1600,7 +1533,7 @@
77522 disp[l_fb_info->board_num].scrollmode = 0; /* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */
77523 l_fb_info->gen.parsize = sizeof(struct pm3fb_par);
77524 l_fb_info->gen.info.changevar = NULL;
77525 - l_fb_info->gen.info.node = B_FREE;
77526 + l_fb_info->gen.info.node = -1;
77527 l_fb_info->gen.info.fbops = &pm3fb_ops;
77528 l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]);
77529 if (fontn[l_fb_info->board_num][0])
77530 @@ -1765,7 +1698,6 @@
77533 PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff);
77534 - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
77535 PM3_SLOW_WRITE_REG(PM3FBWriteMode,
77536 PM3FBWriteMode_WriteEnable |
77537 PM3FBWriteMode_OpaqueSpan |
77538 @@ -1786,7 +1718,9 @@
77539 PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095);
77540 else
77541 PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb);
77544 + PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
77546 switch (l_fb_info->current_par->depth) {
77547 case 8:
77548 PM3_SLOW_WRITE_REG(PM3DitherMode,
77549 @@ -1842,10 +1776,7 @@
77550 height = height * fontheight(p);
77551 c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
77553 - /* block fills in 32bpp are hard, but in low res (width <= 1600 :-)
77554 - we can use 16bpp operations, but not if NoWriteMask is on (SDRAM) */
77555 - if ((l_fb_info->current_par->width > 1600) ||
77556 - (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) {
77557 + if (l_fb_info->current_par->width > 1600) {
77558 PM3_WAIT(4);
77560 PM3_WRITE_REG(PM3Config2D,
77561 @@ -1867,7 +1798,7 @@
77562 PM3Render2D_SpanOperation |
77563 (PM3Render2D_Width(width)) |
77564 (PM3Render2D_Height(height)));
77565 - } else {
77566 + } else { /* block fills in 32bpp are hard, but in low res (width <= 1600 :-) we can use 16bpp operations */
77567 PM3_WAIT(8);
77569 PM3_WRITE_REG(PM3FBBlockColor, c);
77570 @@ -1992,10 +1923,7 @@
77572 PM3_WAIT(4);
77574 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77575 - PM3_WRITE_REG(PM3ForegroundColor, c);
77576 - else
77577 - PM3_WRITE_REG(PM3FBBlockColor, c);
77578 + PM3_WRITE_REG(PM3FBBlockColor, c);
77580 PM3_WRITE_REG(PM3Config2D,
77581 PM3Config2D_UseConstantSource |
77582 @@ -2006,23 +1934,14 @@
77583 PM3_WRITE_REG(PM3RectanglePosition,
77584 (PM3RectanglePosition_XOffset(sx)) |
77585 (PM3RectanglePosition_YOffset(sy)));
77587 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77588 - PM3_WRITE_REG(PM3Render2D,
77589 - PM3Render2D_XPositive |
77590 - PM3Render2D_YPositive |
77591 - PM3Render2D_Operation_Normal |
77592 - PM3Render2D_SpanOperation |
77593 - (PM3Render2D_Width(width)) |
77594 - (PM3Render2D_Height(height)));
77595 - else
77596 - PM3_WRITE_REG(PM3Render2D,
77597 - PM3Render2D_XPositive |
77598 - PM3Render2D_YPositive |
77599 - PM3Render2D_Operation_Normal |
77600 - (PM3Render2D_Width(width)) |
77601 - (PM3Render2D_Height(height)));
77604 + PM3_WRITE_REG(PM3Render2D,
77605 + PM3Render2D_XPositive |
77606 + PM3Render2D_YPositive |
77607 + PM3Render2D_Operation_Normal |
77608 + (PM3Render2D_Width(width)) |
77609 + (PM3Render2D_Height(height)));
77611 pm3fb_wait_pm3(l_fb_info);
77614 @@ -2048,69 +1967,45 @@
77615 PM3Config2D_ForegroundROPEnable |
77616 (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
77617 PM3Config2D_FBWriteEnable);
77619 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77620 - PM3_WRITE_REG(PM3ForegroundColor, c);
77621 - else
77622 - PM3_WRITE_REG(PM3FBBlockColor, c);
77625 + PM3_WRITE_REG(PM3FBBlockColor, c);
77627 PM3_WRITE_REG(PM3RectanglePosition,
77628 (PM3RectanglePosition_XOffset
77629 (p->var.xoffset +
77630 sx)) | (PM3RectanglePosition_YOffset(p->
77631 var.
77632 yoffset)));
77633 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77634 - PM3_WRITE_REG(PM3Render2D,
77635 - PM3Render2D_XPositive |
77636 - PM3Render2D_YPositive |
77637 - PM3Render2D_Operation_Normal |
77638 - PM3Render2D_SpanOperation |
77639 - (PM3Render2D_Width(p->var.xres - sx)) |
77640 - (PM3Render2D_Height(p->var.yres)));
77641 - else
77642 - PM3_WRITE_REG(PM3Render2D,
77643 - PM3Render2D_XPositive |
77644 - PM3Render2D_YPositive |
77645 - PM3Render2D_Operation_Normal |
77646 - (PM3Render2D_Width(p->var.xres - sx)) |
77647 - (PM3Render2D_Height(p->var.yres)));
77649 + PM3_WRITE_REG(PM3Render2D,
77650 + PM3Render2D_XPositive |
77651 + PM3Render2D_YPositive |
77652 + PM3Render2D_Operation_Normal |
77653 + (PM3Render2D_Width(p->var.xres - sx)) |
77654 + (PM3Render2D_Height(p->var.yres)));
77658 /* bottom margin left -> right */
77659 PM3_WAIT(4);
77662 PM3_WRITE_REG(PM3Config2D,
77663 - PM3Config2D_UseConstantSource |
77664 - PM3Config2D_ForegroundROPEnable |
77665 - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
77666 - PM3Config2D_FBWriteEnable);
77668 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77669 - PM3_WRITE_REG(PM3ForegroundColor, c);
77670 - else
77671 - PM3_WRITE_REG(PM3FBBlockColor, c);
77674 + PM3Config2D_UseConstantSource |
77675 + PM3Config2D_ForegroundROPEnable |
77676 + (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
77677 + PM3Config2D_FBWriteEnable);
77679 + PM3_WRITE_REG(PM3FBBlockColor, c);
77681 PM3_WRITE_REG(PM3RectanglePosition,
77682 (PM3RectanglePosition_XOffset(p->var.xoffset)) |
77683 (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
77685 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77686 - PM3_WRITE_REG(PM3Render2D,
77687 - PM3Render2D_XPositive |
77688 - PM3Render2D_YPositive |
77689 - PM3Render2D_Operation_Normal |
77690 - PM3Render2D_SpanOperation |
77691 - (PM3Render2D_Width(p->var.xres)) |
77692 - (PM3Render2D_Height(p->var.yres - sy)));
77693 - else
77694 - PM3_WRITE_REG(PM3Render2D,
77695 - PM3Render2D_XPositive |
77696 - PM3Render2D_YPositive |
77697 - PM3Render2D_Operation_Normal |
77698 - (PM3Render2D_Width(p->var.xres)) |
77699 - (PM3Render2D_Height(p->var.yres - sy)));
77701 + PM3_WRITE_REG(PM3Render2D,
77702 + PM3Render2D_XPositive |
77703 + PM3Render2D_YPositive |
77704 + PM3Render2D_Operation_Normal |
77705 + (PM3Render2D_Width(p->var.xres)) |
77706 + (PM3Render2D_Height(p->var.yres - sy)));
77708 pm3fb_wait_pm3(l_fb_info);
77710 @@ -2288,7 +2183,7 @@
77711 int c, int yy, int xx)
77713 struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
77714 - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
77715 + u8 *cdat, asx = 0, asy = 0, o_x, o_y;
77716 u32 fgx, bgx, ldat;
77717 int sx, sy, i;
77719 @@ -2398,7 +2293,7 @@
77720 int xx)
77722 struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
77723 - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
77724 + u8 *cdat, asx = 0, asy = 0, o_x, o_y;
77725 u32 fgx, bgx, ldat;
77726 int sx, sy, i, j;
77727 u16 sc;
77728 @@ -2516,12 +2411,7 @@
77729 yy = yy * fontheight(p);
77731 if (l_fb_info->current_par->depth == 8)
77733 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77734 - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F);
77735 - else
77736 - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
77738 + PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
77740 PM3_WAIT(3);
77742 @@ -2547,12 +2437,7 @@
77743 pm3fb_wait_pm3(l_fb_info);
77745 if (l_fb_info->current_par->depth == 8)
77747 - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
77748 - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF);
77749 - else
77750 - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
77752 + PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
77755 #endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
77756 @@ -2640,25 +2525,12 @@
77757 unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
77759 if (!(depth_supported(bd))) {
77760 - printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n",
77761 - bds, board_num);
77762 + DPRINTK(1, "Invalid depth: %s\n", bds);
77763 return;
77765 depth[board_num] = bd;
77768 -static void pm3fb_forcesize_setup(char *bds, unsigned long board_num)
77770 - unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
77772 - if (bd > 64) {
77773 - printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n",
77774 - bds, board_num);
77775 - return;
77777 - forcesize[board_num] = bd;
77780 static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
77782 char *next;
77783 @@ -2752,12 +2624,6 @@
77784 pm3fb_bootdepth_setup(options, bn);
77785 } else if (!strncmp(options, "printtimings", 12)) {
77786 printtimings = 1;
77787 - } else if (!strncmp(options, "flatpanel:", 10)) {
77788 - options = pm3fb_boardnum_setup(options + 10, &bn);
77789 - flatpanel[bn] = 1;
77790 - } else if (!strncmp(options, "forcesize:", 10)) {
77791 - options = pm3fb_boardnum_setup(options + 10, &bn);
77792 - pm3fb_forcesize_setup(options, bn);
77794 options = next;
77796 @@ -3495,7 +3361,7 @@
77797 pci_resource_start(l_fb_info->dev, 1);
77798 l_fb_info->v_fb = (unsigned char *) -1;
77800 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* full resource management, new in linux-2.4.x */
77801 +#ifdef KERNEL_2_4 /* full resource management, new in linux-2.4.x */
77802 if (!request_mem_region
77803 ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
77804 "pm3fb")) {
77805 @@ -3512,10 +3378,8 @@
77806 l_fb_info->board_num);
77807 continue;
77809 -#endif /* KERNEL_2_4 or KERNEL_2_5 */
77810 - if (forcesize[l_fb_info->board_num])
77811 - l_fb_info->fb_size = forcesize[l_fb_info->board_num];
77813 +#endif /* KERNEL_2_4 */
77815 l_fb_info->fb_size =
77816 pm3fb_size_memory(l_fb_info);
77818 @@ -3611,7 +3475,7 @@
77819 /* ***** standard FB API init functions ***** */
77820 /* ****************************************** */
77822 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77823 +#ifdef KERNEL_2_4
77824 int __init pm3fb_setup(char *options)
77825 #endif
77826 #ifdef KERNEL_2_2
77827 @@ -3627,12 +3491,12 @@
77828 PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1));
77829 g_options[PM3_OPTIONS_SIZE - 1] = 0;
77831 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77832 +#ifdef KERNEL_2_4
77833 return (0);
77834 #endif
77837 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77838 +#ifdef KERNEL_2_4
77839 int __init pm3fb_init(void)
77840 #endif
77841 #ifdef KERNEL_2_2
77842 @@ -3641,7 +3505,7 @@
77844 DTRACE;
77846 - DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $");
77847 + DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $");
77849 pm3fb_real_setup(g_options);
77851 @@ -3650,7 +3514,7 @@
77852 if (!fb_info[0].dev) { /* not even one board ??? */
77853 DPRINTK(1, "No PCI Permedia3 board detected\n");
77855 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77856 +#ifdef KERNEL_2_4
77857 return (0);
77858 #endif
77860 @@ -3753,9 +3617,7 @@
77861 MODULE_PARM(depth,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
77862 MODULE_PARM_DESC(depth,"boot-time depth");
77863 MODULE_PARM(printtimings, "h");
77864 -MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
77865 -MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
77866 -MODULE_PARM_DESC(forcesize, "force specified memory size");
77867 +MODULE_PARM_DESC(printtimings, "print the memory timngs of the card(s)");
77869 MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
77870 MODULE_GENERIC_TABLE(gtype,name)
77871 @@ -3829,14 +3691,14 @@
77872 if (l_fb_info->vIOBase !=
77873 (unsigned char *) -1) {
77874 pm3fb_unmapIO(l_fb_info);
77875 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
77876 +#ifdef KERNEL_2_4
77877 release_mem_region(l_fb_info->p_fb,
77878 l_fb_info->
77879 fb_size);
77880 release_mem_region(l_fb_info->
77881 pIOBase,
77882 PM3_REGS_SIZE);
77883 -#endif /* KERNEL_2_4 or KERNEL_2_5 */
77884 +#endif /* KERNEL_2_4 */
77886 unregister_framebuffer(&l_fb_info->gen.
77887 info);
77888 --- linux-2.4.25/drivers/video/pm3fb.h~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
77889 +++ linux-2.4.25/drivers/video/pm3fb.h 2004-03-31 17:15:09.000000000 +0200
77890 @@ -8,7 +8,7 @@
77891 * License. See the file COPYING in the main directory of this archive for
77892 * more details.
77894 - * $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $
77895 + * $Header: /home/pm3fb/pm3fb/pm3fb.h,v 1.30 2001/08/22 09:13:46 dolbeau Exp $
77899 @@ -92,7 +92,6 @@
77900 #define PM3MemBypassWriteMask 0x1008
77901 #define PM3MemScratch 0x1010
77902 #define PM3LocalMemCaps 0x1018
77903 - #define PM3LocalMemCaps_NoWriteMask (1 << 28)
77904 #define PM3LocalMemTimings 0x1020
77905 #define PM3LocalMemControl 0x1028
77906 #define PM3LocalMemRefresh 0x1030
77907 @@ -1121,10 +1120,6 @@
77909 /* kernel -specific definitions */
77910 /* what kernel is this ? */
77911 -#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)))
77912 -#define KERNEL_2_5
77913 -#endif
77915 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)))
77916 #define KERNEL_2_4
77917 #endif
77918 @@ -1138,8 +1133,8 @@
77919 #endif
77920 #endif
77922 -#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4)) && (!defined(KERNEL_2_5))
77923 -#error "Only kernel 2.2.x, kernel 2.4.y and kernel 2.5.z might work"
77924 +#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4))
77925 +#error "Only kernel 2.2.x and kernel 2.4.y might work"
77926 #endif
77928 /* not sure if/why it's needed. doesn't work without on my PowerMac... */
77929 @@ -1147,11 +1142,6 @@
77930 #define MUST_BYTESWAP
77931 #endif
77933 -/* for compatibility between 2.5, 2.4 and 2.2 */
77934 -#ifndef B_FREE
77935 -#define B_FREE -1
77936 -#endif
77938 /* permedia3 -specific definitions */
77939 #define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
77940 #define PICOS2KHZ(a) (1000000000UL/(a))
77941 @@ -1219,10 +1209,10 @@
77942 #define PM3_READ_REG(r) readl((l_fb_info->vIOBase + r))
77943 #endif /* MUST_BYTESWAP */
77944 #endif /* KERNEL_2_2 */
77945 -#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* native-endian access */
77946 +#ifdef KERNEL_2_4 /* native-endian access */
77947 #define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
77948 #define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
77949 -#endif /* KERNEL_2_4 or KERNEL_2_5 */
77950 +#endif /* KERNEL_2_4 */
77953 #define depth2bpp(d) ((d + 7L) & ~7L)
77954 --- linux-2.4.25/drivers/video/sa1100fb.c~2.4.25-vrs2.patch 2001-11-14 23:52:20.000000000 +0100
77955 +++ linux-2.4.25/drivers/video/sa1100fb.c 2004-03-31 17:15:09.000000000 +0200
77956 @@ -23,11 +23,11 @@
77957 * Thank you.
77959 * Known problems:
77960 - * - With the Neponset plugged into an Assabet, LCD powerdown
77961 - * doesn't work (LCD stays powered up). Therefore we shouldn't
77962 - * blank the screen.
77963 - * - We don't limit the CPU clock rate nor the mode selection
77964 - * according to the available SDRAM bandwidth.
77965 + * - With the Neponset plugged into an Assabet, LCD powerdown
77966 + * doesn't work (LCD stays powered up). Therefore we shouldn't
77967 + * blank the screen.
77968 + * - We don't limit the CPU clock rate nor the mode selection
77969 + * according to the available SDRAM bandwidth.
77971 * Other notes:
77972 * - Linear grayscale palettes and the kernel.
77973 @@ -41,6 +41,17 @@
77974 * David Neuer. It's around 8 lines of C code, plus another 4 to
77975 * detect if we are using grayscale.
77977 + * - The following must never be specified in a panel definition:
77978 + * LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
77980 + * - The following should be specified:
77981 + * either LCCR0_Color or LCCR0_Mono
77982 + * either LCCR0_Sngl or LCCR0_Dual
77983 + * either LCCR0_Act or LCCR0_Pas
77984 + * either LCCR3_OutEnH or LCCD3_OutEnL
77985 + * either LCCR3_PixRsEdg or LCCR3_PixFlEdg
77986 + * either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
77988 * Code Status:
77989 * 1999/04/01:
77990 * - Driver appears to be working for Brutus 320x200x8bpp mode. Other
77991 @@ -147,6 +158,10 @@
77993 * 2001/10/12: <rmk@arm.linux.org.uk>
77994 * - Add patch 681/1 and clean up stork definitions.
77996 + * 2002/02/21: <abraham@2d3d.co.za>
77997 + * - Added support for ICP LCD-Kit01 on Frodo.
77998 + * - Added support for backlight via CPLDs on Frodo.
78001 #include <linux/config.h>
78002 @@ -169,6 +184,7 @@
78003 #include <asm/mach-types.h>
78004 #include <asm/uaccess.h>
78005 #include <asm/arch/assabet.h>
78006 +#include <asm/arch/shannon.h>
78008 #include <video/fbcon.h>
78009 #include <video/fbcon-mfb.h>
78010 @@ -177,11 +193,6 @@
78011 #include <video/fbcon-cfb16.h>
78014 - * enable this if your panel appears to have broken
78015 - */
78016 -#undef CHECK_COMPAT
78019 * debugging?
78021 #define DEBUG 0
78022 @@ -197,243 +208,6 @@
78023 void (*sa1100fb_blank_helper)(int blank);
78024 EXPORT_SYMBOL(sa1100fb_blank_helper);
78027 -#ifdef CHECK_COMPAT
78028 -static void
78029 -sa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs,
78030 - struct fb_var_screeninfo *var, u_int pcd)
78032 - struct sa1100fb_lcd_reg shadow;
78033 - int different = 0;
78035 - /*
78036 - * These machines are good machines!
78037 - */
78038 - if (machine_is_assabet() || machine_is_h3600())
78039 - return;
78041 - /*
78042 - * The following ones are bad, bad, bad.
78043 - * Please make yours good!
78044 - */
78045 - if (machine_is_pangolin()) {
78046 - DPRINTK("Configuring Pangolin LCD\n");
78047 - shadow.lccr0 =
78048 - LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
78049 - LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
78050 - LCCR0_LtlEnd + LCCR0_DMADel(0);
78051 - shadow.lccr1 =
78052 - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) +
78053 - LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24);
78054 - shadow.lccr2 =
78055 - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) +
78056 - LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1);
78057 - shadow.lccr3 =
78058 - LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
78059 - LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH;
78061 - DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n",
78062 - pcd, LCCR3_PixClkDiv(pcd));
78064 - if (machine_is_freebird()) {
78065 - DPRINTK("Configuring Freebird LCD\n");
78066 -#if 1
78067 - shadow.lccr0 = 0x00000038;
78068 - shadow.lccr1 = 0x010108e0;
78069 - shadow.lccr2 = 0x0000053f;
78070 - shadow.lccr3 = 0x00000c20;
78071 -#else
78072 - shadow.lccr0 =
78073 - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
78074 - LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
78075 - LCCR0_LtlEnd + LCCR0_DMADel(0);
78076 - /* Check ,Chester */
78077 - shadow.lccr1 =
78078 - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
78079 - LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
78080 - /* Check ,Chester */
78081 - shadow.lccr2 =
78082 - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
78083 - LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
78084 - /* Check ,Chester */
78085 - shadow.lccr3 =
78086 - LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH +
78087 - LCCR3_HorSnchH + LCCR3_ACBsCntOff +
78088 - LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
78089 -#endif
78091 - if (machine_is_brutus()) {
78092 - DPRINTK("Configuring Brutus LCD\n");
78093 - shadow.lccr0 =
78094 - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas +
78095 - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
78096 - LCCR0_DMADel(0);
78097 - shadow.lccr1 =
78098 - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) +
78099 - LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
78100 - shadow.lccr2 =
78101 - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
78102 - LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
78103 - shadow.lccr3 =
78104 - LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
78105 - LCCR3_HorSnchH + LCCR3_ACBsCntOff +
78106 - LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
78108 - if (machine_is_huw_webpanel()) {
78109 - DPRINTK("Configuring HuW LCD\n");
78110 - shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM;
78111 - shadow.lccr1 = LCCR1_DisWdth(var->xres) +
78112 - LCCR1_HorSnchWdth(3) +
78113 - LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
78114 - shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1);
78115 - shadow.lccr3 = 8 + LCCR3_OutEnH +
78116 - LCCR3_PixRsEdg + LCCR3_VrtSnchH +
78117 - LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2);
78119 - if (machine_is_lart()) {
78120 - DPRINTK("Configuring LART LCD\n");
78121 -#if defined LART_GREY_LCD
78122 - shadow.lccr0 =
78123 - LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
78124 - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
78125 - LCCR0_DMADel(0);
78126 - shadow.lccr1 =
78127 - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) +
78128 - LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
78129 - shadow.lccr2 =
78130 - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
78131 - LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
78132 - shadow.lccr3 =
78133 - LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
78134 - LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
78135 -#endif
78136 -#if defined LART_COLOR_LCD
78137 - shadow.lccr0 =
78138 - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
78139 - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
78140 - LCCR0_DMADel(0);
78141 - shadow.lccr1 =
78142 - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
78143 - LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8);
78144 - shadow.lccr2 =
78145 - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) +
78146 - LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4);
78147 - shadow.lccr3 =
78148 - LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
78149 - LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL +
78150 - LCCR3_PixFlEdg;
78151 -#endif
78152 -#if defined LART_VIDEO_OUT
78153 - shadow.lccr0 =
78154 - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
78155 - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
78156 - LCCR0_DMADel(0);
78157 - shadow.lccr1 =
78158 - LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) +
78159 - LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24);
78160 - shadow.lccr2 =
78161 - LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) +
78162 - LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11);
78163 - shadow.lccr3 =
78164 - LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) +
78165 - LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH +
78166 - LCCR3_PixFlEdg + LCCR3_OutEnL;
78167 -#endif
78169 - if (machine_is_graphicsclient()) {
78170 - DPRINTK("Configuring GraphicsClient LCD\n");
78171 - shadow.lccr0 =
78172 - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
78173 - shadow.lccr1 =
78174 - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) +
78175 - LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54);
78176 - shadow.lccr2 =
78177 - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) +
78178 - LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24);
78179 - shadow.lccr3 =
78180 - LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) +
78181 - LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
78183 - if (machine_is_omnimeter()) {
78184 - DPRINTK("Configuring OMNI LCD\n");
78185 - shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD;
78186 - shadow.lccr1 =
78187 - LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) +
78188 - LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres);
78189 - shadow.lccr2 = LCCR2_DisHght(var->yres);
78190 - shadow.lccr3 =
78191 - LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);
78192 -//jca (GetPCD(25) << LCD3_V_PCD);
78194 - if (machine_is_xp860()) {
78195 - DPRINTK("Configuring XP860 LCD\n");
78196 - shadow.lccr0 =
78197 - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
78198 - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0);
78199 - shadow.lccr1 =
78200 - LCCR1_DisWdth(var->xres) +
78201 - LCCR1_HorSnchWdth(var->hsync_len) +
78202 - LCCR1_BegLnDel(var->left_margin) +
78203 - LCCR1_EndLnDel(var->right_margin);
78204 - shadow.lccr2 =
78205 - LCCR2_DisHght(var->yres) +
78206 - LCCR2_VrtSnchWdth(var->vsync_len) +
78207 - LCCR2_BegFrmDel(var->upper_margin) +
78208 - LCCR2_EndFrmDel(var->lower_margin);
78209 - shadow.lccr3 =
78210 - LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL;
78213 - /*
78214 - * Ok, since we're calculating these values, we want to know
78215 - * if the calculation is correct. If you see any of these
78216 - * messages _PLEASE_ report the incident to me for diagnosis,
78217 - * including details about what was happening when the
78218 - * messages appeared. --rmk, 30 March 2001
78219 - */
78220 - if (shadow.lccr0 != new_regs->lccr0) {
78221 - printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
78222 - shadow.lccr1, new_regs->lccr1);
78223 - different = 1;
78225 - if (shadow.lccr1 != new_regs->lccr1) {
78226 - printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
78227 - shadow.lccr1, new_regs->lccr1);
78228 - different = 1;
78230 - if (shadow.lccr2 != new_regs->lccr2) {
78231 - printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n",
78232 - shadow.lccr2, new_regs->lccr2);
78233 - different = 1;
78235 - if (shadow.lccr3 != new_regs->lccr3) {
78236 - printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n",
78237 - shadow.lccr3, new_regs->lccr3);
78238 - different = 1;
78240 - if (different) {
78241 - printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n",
78242 - var->xres, var->hsync_len,
78243 - var->left_margin, var->right_margin);
78244 - printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n",
78245 - var->yres, var->vsync_len,
78246 - var->upper_margin, var->lower_margin);
78248 - printk(KERN_ERR "Please report this to Russell King "
78249 - "<rmk@arm.linux.org.uk>\n");
78252 - DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0);
78253 - DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1);
78254 - DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2);
78255 - DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);
78257 -#else
78258 -#define sa1100fb_check_shadow(regs,var,pcd)
78259 -#endif
78264 * IMHO this looks wrong. In 8BPP, length should be 8.
78266 @@ -488,42 +262,56 @@
78267 #endif
78268 #endif
78270 -#ifdef CONFIG_SA1100_H3600
78271 -static struct sa1100fb_mach_info h3600_info __initdata = {
78272 -#ifdef CONFIG_IPAQ_H3100
78273 - pixclock: 407766, bpp: 4,
78274 +#ifdef CONFIG_SA1100_H3XXX
78275 +static struct sa1100fb_mach_info h3800_info __initdata = {
78276 + pixclock: 174757, bpp: 16,
78277 xres: 320, yres: 240,
78279 - hsync_len: 26, vsync_len: 41,
78280 - left_margin: 4, upper_margin: 0,
78281 - right_margin: 4, lower_margin: 0,
78282 + hsync_len: 3, vsync_len: 3,
78283 + left_margin: 12, upper_margin: 10,
78284 + right_margin: 17, lower_margin: 1,
78286 - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
78287 - cmap_greyscale: 1, cmap_static: 1,
78288 - cmap_inverse: 1,
78289 + sync: 0, cmap_static: 1,
78291 - lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
78292 - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
78293 -#else
78294 - pixclock: 174757, bpp: 16,
78295 + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
78296 + lccr3: LCCR3_ACBsCntOff | LCCR3_PixFlEdg | LCCR3_OutEnH,
78299 +static struct sa1100fb_mach_info h3600_info __initdata = {
78300 + pixclock: 174757, bpp: 16,
78301 xres: 320, yres: 240,
78303 hsync_len: 3, vsync_len: 3,
78304 left_margin: 12, upper_margin: 10,
78305 right_margin: 17, lower_margin: 1,
78307 - sync: 0,
78308 + sync: 0, cmap_static: 1,
78310 lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
78311 - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
78312 -#endif
78313 + lccr3: LCCR3_ACBsCntOff | LCCR3_OutEnH | LCCR3_PixFlEdg,
78316 static struct sa1100fb_rgb h3600_rgb_16 = {
78317 red: { offset: 12, length: 4, },
78318 green: { offset: 7, length: 4, },
78319 blue: { offset: 1, length: 4, },
78320 - transp: { offset: 0, length: 0, },
78321 + transp: { offset: 0, length: 0, },
78324 +static struct sa1100fb_mach_info h3100_info __initdata = {
78325 + pixclock: 406977, bpp: 4,
78326 + xres: 320, yres: 240,
78328 + hsync_len: 26, vsync_len: 41,
78329 + left_margin: 4, upper_margin: 0,
78330 + right_margin: 4, lower_margin: 0,
78332 + sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
78333 + cmap_greyscale: 1,
78334 + cmap_inverse: 1,
78336 + lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
78337 + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
78339 #endif
78341 @@ -618,6 +406,58 @@
78343 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
78344 static struct sa1100fb_mach_info graphicsclient_info __initdata = {
78345 +// for LQ64D343
78346 + pixclock: 53500, bpp: 8,
78347 + xres: 640, yres: 480,
78349 + hsync_len: 9, vsync_len: 9,
78350 + left_margin: 54, upper_margin: 24,
78351 + right_margin: 54, lower_margin: 32,
78353 + sync: 0,
78355 + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
78356 + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
78358 +#endif
78360 +#ifdef CONFIG_SA1100_GRAPHICSMASTER
78361 +static struct sa1100fb_mach_info graphicsmaster_info __initdata = {
78362 +// for LQ64D343
78363 + pixclock: 53500, bpp: 8,
78364 + xres: 640, yres: 480,
78366 + hsync_len: 9, vsync_len: 9,
78367 + left_margin: 54, upper_margin: 24,
78368 + right_margin: 54, lower_margin: 32,
78370 + sync: 0,
78372 + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
78373 + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
78375 +#endif
78377 +#ifdef CONFIG_SA1100_ADSBITSY
78378 +static struct sa1100fb_mach_info adsbitsy_info __initdata = {
78379 +// for LQ64D343
78380 + pixclock: 53500, bpp: 8,
78381 + xres: 640, yres: 480,
78383 + hsync_len: 9, vsync_len: 9,
78384 + left_margin: 54, upper_margin: 24,
78385 + right_margin: 54, lower_margin: 32,
78387 + sync: 0,
78389 + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
78390 + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
78392 +#endif
78394 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
78395 +static struct sa1100fb_mach_info adsbitsyplus_info __initdata = {
78396 +// for LQ64D343
78397 pixclock: 53500, bpp: 8,
78398 xres: 640, yres: 480,
78400 @@ -699,7 +539,6 @@
78401 lccr3: LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
78403 #endif
78405 #ifdef LART_KIT01_LCD
78406 static struct sa1100fb_mach_info lart_kit01_info __initdata =
78408 @@ -707,7 +546,7 @@
78409 xres: 640, yres: 480,
78411 hsync_len: 64, vsync_len: 3,
78412 - left_margin: 122, upper_margin: 45,
78413 + left_margin: 122, upper_margin: 45,
78414 right_margin: 10, lower_margin: 10,
78416 sync: 0,
78417 @@ -717,6 +556,40 @@
78419 #endif
78421 +#ifdef CONFIG_SA1100_FRODO
78422 +static struct sa1100fb_mach_info frodo_kit01_info __initdata =
78424 + /* best would be 41731 (25.8mhz), but we can only do 14.743mhz at 191.7mhz clock speed */
78425 + pixclock: 73030, bpp: 16,
78426 + xres: 640, yres: 480,
78428 + hsync_len: 32, vsync_len: 19,
78429 + left_margin: 120, upper_margin: 33,
78430 + right_margin: 17, lower_margin: 12,
78432 + sync: 0,
78434 + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
78435 + lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg
78437 +#endif
78439 +#ifdef CONFIG_SA1100_SHANNON
78440 +static struct sa1100fb_mach_info shannon_info __initdata = {
78441 + pixclock: 152500, bpp: 8,
78442 + xres: 640, yres: 480,
78444 + hsync_len: 4, vsync_len: 3,
78445 + left_margin: 2, upper_margin: 0,
78446 + right_margin: 1, lower_margin: 0,
78448 + sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
78450 + lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
78451 + lccr3: LCCR3_ACBsDiv(512),
78453 +#endif
78455 #ifdef CONFIG_SA1100_OMNIMETER
78456 static struct sa1100fb_mach_info omnimeter_info __initdata = {
78457 pixclock: 0, bpp: 4,
78458 @@ -752,7 +625,24 @@
78459 sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
78461 lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
78462 - lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg,
78463 + lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
78465 +#endif
78467 +#ifdef CONFIG_SA1100_SIMPUTER
78468 +static struct sa1100fb_mach_info simputer_info __initdata = {
78469 + pixclock: 70000, bpp: 4,
78470 + xres: 320, yres: 240,
78472 + hsync_len: 9, vsync_len: 2,
78473 + left_margin: 9, upper_margin: 0,
78474 + right_margin: 2, lower_margin: 0,
78476 + cmap_greyscale: 1,
78477 + sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT ,
78479 + lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
78480 + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(202),
78482 #endif
78484 @@ -828,7 +718,6 @@
78485 #endif
78489 static struct sa1100fb_mach_info * __init
78490 sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
78492 @@ -849,11 +738,17 @@
78493 #endif
78495 #endif
78496 -#ifdef CONFIG_SA1100_H3600
78497 +#ifdef CONFIG_SA1100_H3XXX
78498 if (machine_is_h3600()) {
78499 inf = &h3600_info;
78500 fbi->rgb[RGB_16] = &h3600_rgb_16;
78502 + if (machine_is_h3100()) {
78503 + inf = &h3100_info;
78505 + if (machine_is_h3800()) {
78506 + inf = &h3800_info;
78508 #endif
78509 #ifdef CONFIG_SA1100_BRUTUS
78510 if (machine_is_brutus()) {
78511 @@ -876,6 +771,22 @@
78512 inf = &graphicsclient_info;
78514 #endif
78515 +#ifdef CONFIG_SA1100_GRAPHICSMASTER
78516 + if (machine_is_graphicsmaster()) {
78517 + inf = &graphicsmaster_info;
78519 +#endif
78520 +#ifdef CONFIG_SA1100_ADSBITSY
78521 + if (machine_is_adsbitsy()) {
78522 + inf = &adsbitsy_info;
78524 +#endif
78525 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
78526 + if (machine_is_adsbitsyplus()) {
78527 + inf = &adsbitsyplus_info;
78530 +#endif
78531 #ifdef CONFIG_SA1100_HUW_WEBPANEL
78532 if (machine_is_huw_webpanel()) {
78533 inf = &huw_webpanel_info;
78534 @@ -897,6 +808,21 @@
78535 #endif
78537 #endif
78538 +#ifdef CONFIG_SA1100_FRODO
78539 + if (machine_is_frodo()) {
78540 + inf = &frodo_kit01_info;
78542 +#endif
78543 +#ifdef CONFIG_SA1100_SHANNON
78544 + if (machine_is_shannon()) {
78545 + inf = &shannon_info;
78547 +#endif
78548 +#ifdef CONFIG_SA1100_SIMPUTER
78549 + if (machine_is_simputer()) {
78550 + inf = &simputer_info;
78552 +#endif
78553 #ifdef CONFIG_SA1100_OMNIMETER
78554 if (machine_is_omnimeter()) {
78555 inf = &omnimeter_info;
78556 @@ -1556,7 +1482,8 @@
78557 unsigned int pcd;
78559 if (pixclock) {
78560 - pcd = get_cclk_frequency() * pixclock;
78561 + pcd = cpufreq_get(0) / 100;
78562 + pcd *= pixclock;
78563 pcd /= 10000000;
78564 pcd += 1; /* make up for integer math truncations */
78565 } else {
78566 @@ -1580,6 +1507,7 @@
78567 return pcd;
78572 * sa1100fb_activate_var():
78573 * Configures LCD Controller based on entries in var parameter. Settings are
78574 @@ -1659,8 +1587,6 @@
78575 if (pcd)
78576 new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
78578 - sa1100fb_check_shadow(&new_regs, var, pcd);
78580 DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
78581 DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
78582 DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
78583 @@ -1733,6 +1659,10 @@
78584 if (machine_is_omnimeter())
78585 LEDBacklightOn();
78586 #endif
78587 +#ifdef CONFIG_SA1100_FRODO
78588 + if (machine_is_frodo())
78589 + frodo_cpld_set (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
78590 +#endif
78594 @@ -1755,6 +1685,10 @@
78595 if (machine_is_omnimeter())
78596 LEDBacklightOff();
78597 #endif
78598 +#ifdef CONFIG_SA1100_FRODO
78599 + if (machine_is_frodo())
78600 + frodo_cpld_clear (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
78601 +#endif
78604 static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
78605 @@ -1773,20 +1707,25 @@
78606 if (machine_is_omnimeter())
78607 LCDPowerOn();
78608 #endif
78609 -#ifdef CONFIG_SA1100_H3600
78610 - if (machine_is_h3600()) {
78611 - set_h3600_egpio(EGPIO_H3600_LCD_ON |
78612 - EGPIO_H3600_LCD_PCI |
78613 - EGPIO_H3600_LCD_5V_ON |
78614 - EGPIO_H3600_LVDD_ON);
78616 -#endif
78617 + if (machine_is_h3xxx())
78618 + set_h3600_egpio( IPAQ_EGPIO_LCD_ON ); /* Turn on power to the LCD */
78619 #ifdef CONFIG_SA1100_STORK
78620 if (machine_is_stork()) {
78621 storkSetLCDCPLD(0, 1);
78622 storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
78624 #endif
78625 +#ifdef CONFIG_SA1100_FRODO
78626 + if (machine_is_frodo())
78627 + sa1100fb_backlight_on(fbi);
78628 +#endif
78629 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
78630 + if (machine_is_adsbitsyplus()) {
78631 + ADS_CPLD_PCON &= ~ADS_PCON_PANEL_ON;
78632 + ADS_CPLD_SUPPC |= ADS_SUPPC_VEE_ON;
78634 +#endif
78638 static void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
78639 @@ -1802,20 +1741,24 @@
78640 if (machine_is_huw_webpanel())
78641 BCR_set(BCR_TFT_NPWR);
78642 #endif
78643 -#ifdef CONFIG_SA1100_H3600
78644 - if (machine_is_h3600()) {
78645 - clr_h3600_egpio(EGPIO_H3600_LCD_ON |
78646 - EGPIO_H3600_LCD_PCI |
78647 - EGPIO_H3600_LCD_5V_ON |
78648 - EGPIO_H3600_LVDD_ON);
78650 -#endif
78651 + if (machine_is_h3xxx())
78652 + clr_h3600_egpio( IPAQ_EGPIO_LCD_ON );
78653 #ifdef CONFIG_SA1100_STORK
78654 if (machine_is_stork()) {
78655 storkSetLCDCPLD(0, 0);
78656 storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
78658 #endif
78659 +#ifdef CONFIG_SA1100_FRODO
78660 + if (machine_is_frodo())
78661 + sa1100fb_backlight_off(fbi);
78662 +#endif
78663 +#ifdef CONFIG_SA1100_ADSBITSYPLUS
78664 + if (machine_is_adsbitsyplus()) {
78665 + ADS_CPLD_PCON |= ADS_PCON_PANEL_ON;
78666 + ADS_CPLD_SUPPC &= ~ADS_SUPPC_VEE_ON;
78668 +#endif
78671 static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
78672 @@ -1911,15 +1854,29 @@
78673 LCCR0 |= LCCR0_LEN;
78675 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
78676 -#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
78677 if (machine_is_graphicsclient()) {
78678 // From ADS doc again...same as disable
78679 set_current_state(TASK_UNINTERRUPTIBLE);
78680 schedule_timeout(20 * HZ / 1000);
78681 - GPSR |= GPIO_GPIO24;
78682 + GPDR |= GPIO_GPIO24;
78683 + GPSR = GPIO_GPIO24;
78685 +#endif
78686 +#ifdef CONFIG_SA1100_GRAPHICSMASTER
78687 + if (machine_is_graphicsmaster()) {
78688 + // From ADS doc again...same as disable
78689 + set_current_state(TASK_UNINTERRUPTIBLE);
78690 + schedule_timeout(20 * HZ / 1000);
78691 + GPDR |= GPIO_GPIO24;
78692 + GPSR = GPIO_GPIO24;
78694 #endif
78696 + if (machine_is_shannon()) {
78697 + GPDR |= SHANNON_GPIO_DISP_EN;
78698 + GPSR |= SHANNON_GPIO_DISP_EN;
78699 + }
78701 DPRINTK("DBAR1 = %p\n", DBAR1);
78702 DPRINTK("DBAR2 = %p\n", DBAR2);
78703 DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
78704 @@ -1935,7 +1892,6 @@
78705 DPRINTK("Disabling LCD controller\n");
78707 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
78708 -#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
78709 if (machine_is_graphicsclient()) {
78711 * From ADS internal document:
78712 @@ -1944,6 +1900,22 @@
78714 * We'll wait 20msec.
78716 + GPDR |= GPIO_GPIO24;
78717 + GPCR |= GPIO_GPIO24;
78718 + set_current_state(TASK_UNINTERRUPTIBLE);
78719 + schedule_timeout(20 * HZ / 1000);
78721 +#endif
78722 +#ifdef CONFIG_SA1100_GRAPHICSMASTER
78723 + if (machine_is_graphicsmaster()) {
78724 + /*
78725 + * From ADS internal document:
78726 + * GPIO24 should be LOW at least 10msec prior to disabling
78727 + * the LCD interface.
78729 + * We'll wait 20msec.
78730 + */
78731 + GPDR |= GPIO_GPIO24;
78732 GPCR |= GPIO_GPIO24;
78733 set_current_state(TASK_UNINTERRUPTIBLE);
78734 schedule_timeout(20 * HZ / 1000);
78735 @@ -1958,12 +1930,15 @@
78737 #endif
78739 + if (machine_is_shannon()) {
78740 + GPCR |= SHANNON_GPIO_DISP_EN;
78741 + }
78743 add_wait_queue(&fbi->ctrlr_wait, &wait);
78744 set_current_state(TASK_UNINTERRUPTIBLE);
78746 LCSR = 0xffffffff; /* Clear LCD Status Register */
78747 LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
78748 - enable_irq(IRQ_LCD); /* Enable LCD IRQ */
78749 LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */
78751 schedule_timeout(20 * HZ / 1000);
78752 @@ -2006,12 +1981,13 @@
78753 * Disable controller for clock change. If the
78754 * controller is already disabled, then do nothing.
78756 - if (old_state != C_DISABLE) {
78757 + if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
78758 fbi->state = state;
78759 sa1100fb_disable_controller(fbi);
78761 break;
78763 + case C_DISABLE_PM:
78764 case C_DISABLE:
78766 * Disable controller
78767 @@ -2050,6 +2026,16 @@
78769 break;
78771 + case C_ENABLE_PM:
78772 + /*
78773 + * Re-enable the controller after PM. This is not
78774 + * perfect - think about the case where we were doing
78775 + * a clock change, and we suspended half-way through.
78776 + */
78777 + if (old_state != C_DISABLE_PM)
78778 + break;
78779 + /* fall through */
78781 case C_ENABLE:
78783 * Power up the LCD screen, enable controller, and
78784 @@ -2162,10 +2148,10 @@
78786 if (state == 0) {
78787 /* Enter D0. */
78788 - set_ctrlr_state(fbi, C_ENABLE);
78789 + set_ctrlr_state(fbi, C_ENABLE_PM);
78790 } else {
78791 /* Enter D1-D3. Disable the LCD controller. */
78792 - set_ctrlr_state(fbi, C_DISABLE);
78793 + set_ctrlr_state(fbi, C_DISABLE_PM);
78796 DPRINTK("done\n");
78797 @@ -2304,7 +2290,7 @@
78798 goto failed;
78800 ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
78801 - fbi->fb.fix.id, fbi);
78802 + "LCD", fbi);
78803 if (ret) {
78804 printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
78805 goto failed;
78806 --- linux-2.4.25/drivers/video/sa1100fb.h~2.4.25-vrs2.patch 2001-10-25 22:53:52.000000000 +0200
78807 +++ linux-2.4.25/drivers/video/sa1100fb.h 2004-03-31 17:15:09.000000000 +0200
78808 @@ -127,6 +127,8 @@
78809 #define C_DISABLE_CLKCHANGE (2)
78810 #define C_ENABLE_CLKCHANGE (3)
78811 #define C_REENABLE (4)
78812 +#define C_DISABLE_PM (5)
78813 +#define C_ENABLE_PM (6)
78815 #define SA1100_NAME "SA1100"
78817 --- linux-2.4.25/fs/adfs/dir.c~2.4.25-vrs2.patch 2000-09-19 00:14:06.000000000 +0200
78818 +++ linux-2.4.25/fs/adfs/dir.c 2004-03-31 17:15:09.000000000 +0200
78819 @@ -23,7 +23,7 @@
78821 * For future. This should probably be per-directory.
78823 -static rwlock_t adfs_dir_lock;
78824 +static rwlock_t adfs_dir_lock = RW_LOCK_UNLOCKED;
78826 static int
78827 adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
78828 --- linux-2.4.25/fs/adfs/map.c~2.4.25-vrs2.patch 2001-10-25 22:53:53.000000000 +0200
78829 +++ linux-2.4.25/fs/adfs/map.c 2004-03-31 17:15:09.000000000 +0200
78830 @@ -13,24 +13,27 @@
78831 #include <linux/adfs_fs.h>
78832 #include <linux/spinlock.h>
78834 +#include <asm/unaligned.h>
78836 #include "adfs.h"
78839 * For the future...
78841 -static rwlock_t adfs_map_lock;
78842 +static rwlock_t adfs_map_lock = RW_LOCK_UNLOCKED;
78845 + * This is fun. We need to load up to 19 bits from the map at an
78846 + * arbitary bit alignment. (We're limited to 19 bits by F+ version
78847 + * 2).
78848 + */
78849 #define GET_FRAG_ID(_map,_start,_idmask) \
78850 ({ \
78851 - unsigned long _v2, _frag; \
78852 - unsigned int _tmp; \
78853 - _tmp = _start >> 5; \
78854 - _frag = le32_to_cpu(_map[_tmp]); \
78855 - _v2 = le32_to_cpu(_map[_tmp + 1]); \
78856 - _tmp = start & 31; \
78857 - _frag = (_frag >> _tmp) | (_v2 << (32 - _tmp)); \
78858 + unsigned char *_m = _map + (_start >> 3); \
78859 + u32 _frag = get_unaligned((u32 *)_m); \
78860 + _frag >>= (_start & 7); \
78861 _frag & _idmask; \
78862 - })
78863 + })
78866 * return the map bit offset of the fragment frag_id in
78867 @@ -44,14 +47,13 @@
78868 const unsigned int frag_id, unsigned int *offset)
78870 const unsigned int mapsize = dm->dm_endbit;
78871 - const unsigned int idmask = (1 << idlen) - 1;
78872 - unsigned long *map = ((unsigned long *)dm->dm_bh->b_data) + 1;
78873 + const u32 idmask = (1 << idlen) - 1;
78874 + unsigned char *map = dm->dm_bh->b_data + 4;
78875 unsigned int start = dm->dm_startbit;
78876 unsigned int mapptr;
78877 + u32 frag;
78879 do {
78880 - unsigned long frag;
78882 frag = GET_FRAG_ID(map, start, idmask);
78883 mapptr = start + idlen;
78885 @@ -59,15 +61,17 @@
78886 * find end of fragment
78889 - unsigned long v2;
78890 + u32 v, *_map = (u32 *)map;
78892 - while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
78893 + v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
78894 + while (v == 0) {
78895 mapptr = (mapptr & ~31) + 32;
78896 if (mapptr >= mapsize)
78897 goto error;
78898 + v = le32_to_cpu(_map[mapptr >> 5]);
78901 - mapptr += 1 + ffz(~v2);
78902 + mapptr += 1 + ffz(~v);
78905 if (frag == frag_id)
78906 @@ -75,8 +79,11 @@
78907 again:
78908 start = mapptr;
78909 } while (mapptr < mapsize);
78910 + return -1;
78912 error:
78913 + printk(KERN_ERR "adfs: oversized fragment 0x%x at 0x%x-0x%x\n",
78914 + frag, start, mapptr);
78915 return -1;
78917 found:
78918 @@ -102,10 +109,10 @@
78919 const unsigned int mapsize = dm->dm_endbit + 32;
78920 const unsigned int idlen = asb->s_idlen;
78921 const unsigned int frag_idlen = idlen <= 15 ? idlen : 15;
78922 - const unsigned int idmask = (1 << frag_idlen) - 1;
78923 - unsigned long *map = (unsigned long *)dm->dm_bh->b_data;
78924 + const u32 idmask = (1 << frag_idlen) - 1;
78925 + unsigned char *map = dm->dm_bh->b_data;
78926 unsigned int start = 8, mapptr;
78927 - unsigned long frag;
78928 + u32 frag;
78929 unsigned long total = 0;
78932 @@ -133,15 +140,17 @@
78933 * find end of fragment
78936 - unsigned long v2;
78937 + u32 v, *_map = (u32 *)map;
78939 - while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
78940 + v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
78941 + while (v == 0) {
78942 mapptr = (mapptr & ~31) + 32;
78943 if (mapptr >= mapsize)
78944 goto error;
78945 + v = le32_to_cpu(_map[mapptr >> 5]);
78948 - mapptr += 1 + ffz(~v2);
78949 + mapptr += 1 + ffz(~v);
78952 total += mapptr - start;
78953 --- linux-2.4.25/fs/adfs/super.c~2.4.25-vrs2.patch 2002-02-25 20:38:07.000000000 +0100
78954 +++ linux-2.4.25/fs/adfs/super.c 2004-03-31 17:15:09.000000000 +0200
78955 @@ -386,6 +386,14 @@
78956 sb->u.adfs_sb.s_size = adfs_discsize(dr, sb->s_blocksize_bits);
78957 sb->u.adfs_sb.s_version = dr->format_version;
78958 sb->u.adfs_sb.s_log2sharesize = dr->log2sharesize;
78960 + printk(KERN_DEBUG "ADFS: idlen %d map bit size %d sector size %d\n",
78961 + dr->idlen, 1 << dr->log2bpmb, 1 << dr->log2secsize);
78962 + printk(KERN_DEBUG "ADFS: map size %d map2blk %d version %d share size %d\n",
78963 + sb->u.adfs_sb.s_map_size,
78964 + sb->u.adfs_sb.s_map2blk,
78965 + sb->u.adfs_sb.s_version,
78966 + 1 << sb->u.adfs_sb.s_log2sharesize);
78968 sb->u.adfs_sb.s_map = adfs_read_map(sb, dr);
78969 if (!sb->u.adfs_sb.s_map)
78970 @@ -393,6 +401,8 @@
78972 brelse(bh);
78974 + printk(KERN_DEBUG "ADFS: ids per zone %d\n", sb->u.adfs_sb.s_ids_per_zone);
78977 * set up enough so that we can read an inode
78979 --- linux-2.4.25/fs/binfmt_aout.c~2.4.25-vrs2.patch 2001-11-03 02:39:20.000000000 +0100
78980 +++ linux-2.4.25/fs/binfmt_aout.c 2004-03-31 17:15:09.000000000 +0200
78981 @@ -422,7 +422,11 @@
78982 start_thread(regs, ex.a_entry, current->mm->start_stack);
78983 if (current->ptrace & PT_PTRACED)
78984 send_sig(SIGTRAP, current, 0);
78985 +#ifndef __arm__
78986 return 0;
78987 +#else
78988 + return regs->ARM_r0;
78989 +#endif
78992 static int load_aout_library(struct file *file)
78993 @@ -452,8 +456,11 @@
78995 /* For QMAGIC, the starting address is 0x20 into the page. We mask
78996 this off to get the starting address for the page */
78998 - start_addr = ex.a_entry & 0xfffff000;
78999 +#ifndef __arm__
79000 + start_addr = ex.a_entry & 0xfffff000;
79001 +#else
79002 + start_addr = ex.a_entry & 0xffff8000;
79003 +#endif
79005 if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
79006 static unsigned long error_time;
79007 --- linux-2.4.25/fs/binfmt_elf.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
79008 +++ linux-2.4.25/fs/binfmt_elf.c 2004-03-31 17:15:09.000000000 +0200
79009 @@ -635,7 +635,6 @@
79012 current->mm->start_stack = bprm->p;
79014 /* Now we do a little grungy work by mmaping the ELF image into
79015 the correct location in memory. At this point, we assume that
79016 the image should be loaded at fixed address, not at a variable
79017 --- linux-2.4.25/fs/exec.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
79018 +++ linux-2.4.25/fs/exec.c 2004-03-31 17:15:09.000000000 +0200
79019 @@ -315,6 +315,7 @@
79020 spin_unlock(&tsk->mm->page_table_lock);
79022 /* no need for flush_tlb */
79023 + memc_update_addr(tsk->mm, *pte, address);
79024 return;
79025 out:
79026 spin_unlock(&tsk->mm->page_table_lock);
79027 --- linux-2.4.25/fs/jffs/inode-v23.c~2.4.25-vrs2.patch 2001-10-05 00:14:35.000000000 +0200
79028 +++ linux-2.4.25/fs/jffs/inode-v23.c 2004-03-31 17:15:09.000000000 +0200
79029 @@ -10,7 +10,7 @@
79030 * the Free Software Foundation; either version 2 of the License, or
79031 * (at your option) any later version.
79033 - * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
79034 + * $Id: inode-v23.c,v 1.72 2002/01/31 11:42:57 cdavies Exp $
79036 * Ported to Linux 2.3.x and MTD:
79037 * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
79038 @@ -48,6 +48,7 @@
79039 #include <linux/stat.h>
79040 #include <linux/blkdev.h>
79041 #include <linux/quotaops.h>
79042 +#include <linux/compatmac.h>
79043 #include <asm/semaphore.h>
79044 #include <asm/byteorder.h>
79045 #include <asm/uaccess.h>
79046 @@ -58,6 +59,11 @@
79047 #include "jffs_proc.h"
79048 #endif
79050 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
79051 +#define minor(x) MINOR(x)
79052 +#define major(x) MAJOR(x)
79053 +#endif
79055 static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
79057 static struct super_operations jffs_ops;
79058 @@ -81,7 +87,7 @@
79059 D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
79060 kdevname(dev)));
79062 - if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
79063 + if (major(dev) != MTD_BLOCK_MAJOR) {
79064 printk(KERN_WARNING "JFFS: Trying to mount a "
79065 "non-mtd device.\n");
79066 return 0;
79067 @@ -358,7 +364,7 @@
79068 inode->i_nlink = raw_inode->nlink;
79069 inode->i_uid = raw_inode->uid;
79070 inode->i_gid = raw_inode->gid;
79071 - inode->i_rdev = 0;
79072 + inode->i_rdev = NODEV;
79073 inode->i_size = raw_inode->dsize;
79074 inode->i_atime = raw_inode->atime;
79075 inode->i_mtime = raw_inode->mtime;
79076 --- linux-2.4.25/fs/jffs/intrep.c~2.4.25-vrs2.patch 2003-06-13 16:51:37.000000000 +0200
79077 +++ linux-2.4.25/fs/jffs/intrep.c 2004-03-31 17:15:09.000000000 +0200
79078 @@ -10,7 +10,7 @@
79079 * the Free Software Foundation; either version 2 of the License, or
79080 * (at your option) any later version.
79082 - * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $
79083 + * $Id: intrep.c,v 1.104 2002/03/05 14:07:39 dwmw2 Exp $
79085 * Ported to Linux 2.3.x and MTD:
79086 * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
79087 @@ -772,6 +772,9 @@
79088 __u32 free_chunk_size1;
79089 __u32 free_chunk_size2;
79091 + __u32 largest_hole = 0;
79092 + __u32 hole_end_offset = 0;
79093 + __u32 head_offset;
79095 #define NUMFREEALLOWED 2 /* 2 chunks of at least erase size space allowed */
79096 int num_free_space = 0; /* Flag err if more than TWO
79097 @@ -884,6 +887,21 @@
79098 (unsigned int) start,
79099 (unsigned int)(test_start - start)));
79101 + D1(printk("Reducing start to 0x%x from 0x%x\n",
79102 + test_start, start));
79103 + if (largest_hole < test_start - start){
79105 + D3(printk("was hole = %x end_offset = %x\n",
79106 + largest_hole, hole_end_offset));
79107 + if (fmc->head) {
79108 + largest_hole = test_start - start;
79109 + hole_end_offset = test_start;
79113 + D3(printk("now = %x end_offset = %x\n",
79114 + largest_hole, hole_end_offset));
79116 /* below, space from "start" to "pos" will be marked dirty. */
79117 start = test_start;
79119 @@ -956,6 +974,19 @@
79120 num_free_space++;
79121 D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
79122 (unsigned int) start, (unsigned int) (pos - start)));
79124 + if (largest_hole < pos - start) {
79126 + D3(printk("was hole = %x end_offset = %x\n",
79127 + largest_hole, hole_end_offset));
79128 + if (fmc->head){
79129 + largest_hole = pos - start;
79130 + hole_end_offset = pos;
79133 + D3(printk("now = %x end_offset = %x\n",
79134 + largest_hole, hole_end_offset));
79136 }else{
79137 num_free_spc_not_accp++;
79138 D1(printk("Free space (#%i) found but *Not* accepted: Starting "
79139 @@ -968,7 +999,7 @@
79140 (unsigned int) start, (unsigned int) (pos - start)));
79141 jffs_fmalloced(fmc, (__u32) start,
79142 (__u32) (pos - start), 0);
79147 if(num_free_space > NUMFREEALLOWED){
79148 @@ -1002,9 +1033,11 @@
79149 to scan for the magic pattern. */
79150 D1(printk("*************** Dirty flash memory or "
79151 "bad inode: "
79152 - "hexdump(pos = 0x%lx, len = 128):\n",
79153 - (long)pos));
79154 - D1(jffs_hexdump(fmc->mtd, pos, 128));
79155 + "hexdump(pos = 0x%lx, len = %d):\n",
79156 + (long)pos,
79157 + end - pos > 128 ? 128 : end - pos));
79158 + D1(jffs_hexdump(fmc->mtd, pos,
79159 + end - pos > 128 ? 128 : end - pos));
79161 for (pos += 4; pos < end; pos += 4) {
79162 switch (flash_read_u32(fmc->mtd, pos)) {
79163 @@ -1197,12 +1230,6 @@
79165 return -ENOMEM;
79167 - if ((err = jffs_insert_node(c, 0, &raw_inode,
79168 - name, node)) < 0) {
79169 - printk("JFFS: Failed to handle raw inode. "
79170 - "(err = %d)\n", err);
79171 - break;
79173 if (raw_inode.rename) {
79174 struct jffs_delete_list *dl
79175 = (struct jffs_delete_list *)
79176 @@ -1226,6 +1253,12 @@
79177 c->delete_list = dl;
79178 node->data_size = 0;
79180 + if ((err = jffs_insert_node(c, 0, &raw_inode,
79181 + name, node)) < 0) {
79182 + printk("JFFS: Failed to handle raw inode. "
79183 + "(err = %d)\n", err);
79184 + break;
79186 D3(jffs_print_node(node));
79187 node = 0; /* Don't free the node! */
79189 @@ -1242,7 +1275,19 @@
79190 jffs_free_node(node);
79191 DJM(no_jffs_node--);
79193 - jffs_build_end(fmc);
79194 + if (fmc->head && fmc->tail_extra &&
79195 + fmc->head->offset + fmc->flash_size -
79196 + fmc->tail_extra->offset - fmc->tail_extra->size > largest_hole) {
79197 + head_offset = fmc->head->offset;
79199 + else {
79200 + head_offset = hole_end_offset;
79203 + if (jffs_build_end(fmc, head_offset) < 0) {
79204 + D(printk("jffs_build_end() failed\n"));
79205 + return -ENOMEM;
79208 /* Free read buffer */
79209 kfree (read_buf);
79210 --- linux-2.4.25/fs/jffs/jffs_fm.c~2.4.25-vrs2.patch 2001-10-05 00:13:18.000000000 +0200
79211 +++ linux-2.4.25/fs/jffs/jffs_fm.c 2004-03-31 17:15:09.000000000 +0200
79212 @@ -10,7 +10,7 @@
79213 * the Free Software Foundation; either version 2 of the License, or
79214 * (at your option) any later version.
79216 - * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
79217 + * $Id: jffs_fm.c,v 1.29 2002/01/22 09:48:16 cdavies Exp $
79219 * Ported to Linux 2.3.x and MTD:
79220 * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
79221 @@ -20,8 +20,14 @@
79222 #include <linux/slab.h>
79223 #include <linux/blkdev.h>
79224 #include <linux/jffs.h>
79225 +#include <linux/compatmac.h>
79226 #include "jffs_fm.h"
79228 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
79229 +#define minor(x) MINOR(x)
79230 +#define major(x) MAJOR(x)
79231 +#endif
79233 #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
79234 static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
79235 #endif
79236 @@ -46,7 +52,7 @@
79238 DJM(no_jffs_fmcontrol++);
79240 - mtd = get_mtd_device(NULL, MINOR(dev));
79241 + mtd = get_mtd_device(NULL, minor(dev));
79243 if (!mtd) {
79244 kfree(fmc);
79245 @@ -89,8 +95,8 @@
79247 /* When the flash memory scan has completed, this function should be called
79248 before use of the control structure. */
79249 -void
79250 -jffs_build_end(struct jffs_fmcontrol *fmc)
79251 +int
79252 +jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset)
79254 D3(printk("jffs_build_end()\n"));
79256 @@ -99,13 +105,100 @@
79257 fmc->tail = fmc->tail_extra;
79259 else if (fmc->head_extra) {
79260 - fmc->tail_extra->next = fmc->head;
79261 - fmc->head->prev = fmc->tail_extra;
79262 - fmc->head = fmc->head_extra;
79263 + struct jffs_fm *fm, *cur;
79265 + if (head_offset == fmc->head->offset){
79266 + fmc->tail->next = fmc->head_extra;
79267 + fmc->head_extra->prev = fmc->tail;
79268 + fmc->tail = fmc->tail_extra;
79270 + else {
79271 + fmc->tail_extra->next = fmc->head;
79272 + fmc->head->prev = fmc->tail_extra;
79273 + fmc->head = fmc->head_extra;
79274 + while (fmc->head->offset != head_offset){
79275 + fmc->tail->next = fmc->head;
79276 + fmc->head = fmc->head->next;
79277 + fmc->head->prev = 0;
79278 + fmc->tail->next->prev = fmc->tail;
79279 + fmc->tail = fmc->tail->next;
79280 + fmc->tail->next = 0;
79283 + /* Make sure the only free space we have is between tail and head.
79284 + */
79285 + for (cur = fmc->head; cur && cur != fmc->tail;) {
79286 + if (cur->offset + cur->size < cur->next->offset) {
79287 + if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
79288 + D(printk("jffs_buid_end(): kmalloc failed!\n"));
79289 + return -ENOMEM;
79291 + DJM(no_jffs_fm++);
79292 + fm->size = cur->next->offset - cur->offset - cur->size;
79293 + fm->offset = cur->offset + cur->size;
79294 + fm->nodes = 0;
79295 + fm->next = cur->next;
79296 + fm->prev = cur;
79297 + cur->next->prev = fm;
79298 + cur->next = fm;
79299 + cur = fm->next;
79300 + fmc->free_size -= fm->size;
79301 + fmc->dirty_size += fm->size;
79303 + else if (cur->offset > cur->next->offset) {
79304 + if (cur->offset + cur->size < fmc->flash_size){
79305 + if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))){
79307 + D(printk("jffs_buid_end(): kmalloc failed!\n"));
79308 + return -ENOMEM;
79310 + DJM(no_jffs_fm++);
79311 + fm->size = fmc->flash_size -
79312 + cur->offset - cur->size;
79313 + fm->nodes = 0;
79314 + fm->offset = cur->offset + cur->size;
79315 + fm->next = cur->next;
79316 + fm->prev = cur;
79317 + cur->next->prev = fm;
79318 + cur->next = fm;
79319 + cur = fm->next;
79320 + fmc->free_size -= fm->size;
79321 + fmc->dirty_size += fm->size;
79323 + else {
79324 + cur = cur->next;
79326 + if (cur->offset > 0) {
79328 + if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
79329 + D(printk("jffs_buid_end(): kmalloc failed!\n"));
79330 + return -ENOMEM;
79332 + DJM(no_jffs_fm++);
79333 + fm->size = cur->offset;
79334 + fm->nodes = 0;
79335 + fm->offset = 0;
79336 + fm->next = cur;
79337 + fm->prev = cur->prev;
79338 + cur->prev->next = fm;
79339 + cur->prev = fm;
79340 + fmc->free_size -= fm->size;
79341 + fmc->dirty_size += fm->size;
79344 + else if (cur->offset + cur->size != cur->next->offset) {
79345 + printk("jffs_build_end(): Internal error.\n");
79346 + return -EINVAL;
79348 + else {
79349 + cur = cur->next;
79353 fmc->head_extra = 0; /* These two instructions should be omitted. */
79354 fmc->tail_extra = 0;
79355 D3(jffs_print_fmcontrol(fmc));
79356 + return 0;
79360 --- linux-2.4.25/fs/jffs/jffs_fm.h~2.4.25-vrs2.patch 2001-10-05 00:13:18.000000000 +0200
79361 +++ linux-2.4.25/fs/jffs/jffs_fm.h 2004-03-31 17:15:09.000000000 +0200
79362 @@ -10,7 +10,7 @@
79363 * the Free Software Foundation; either version 2 of the License, or
79364 * (at your option) any later version.
79366 - * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
79367 + * $Id: jffs_fm.h,v 1.14 2001/12/10 17:37:12 asanochkin Exp $
79369 * Ported to Linux 2.3.x and MTD:
79370 * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
79371 @@ -123,7 +123,7 @@
79374 struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, kdev_t dev);
79375 -void jffs_build_end(struct jffs_fmcontrol *fmc);
79376 +int jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset);
79377 void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
79379 int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
79380 --- linux-2.4.25/fs/partitions/Config.in~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
79381 +++ linux-2.4.25/fs/partitions/Config.in 2004-03-31 17:15:09.000000000 +0200
79382 @@ -6,6 +6,7 @@
79383 bool ' Acorn partition support' CONFIG_ACORN_PARTITION
79384 if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
79385 # bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
79386 + bool ' EESOX partition support' CONFIG_ACORN_PARTITION_EESOX
79387 bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS
79388 bool ' Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
79389 bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
79390 @@ -52,6 +53,7 @@
79391 define_bool CONFIG_ACORN_PARTITION y
79392 define_bool CONFIG_ACORN_PARTITION_ADFS y
79393 # define_bool CONFIG_ACORN_PARTITION_CUMANA y
79394 + define_bool CONFIG_ACORN_PARTITION_EESOX y
79395 define_bool CONFIG_ACORN_PARTITION_ICS y
79396 define_bool CONFIG_ACORN_PARTITION_POWERTEC y
79397 define_bool CONFIG_ACORN_PARTITION_RISCIX y
79398 --- linux-2.4.25/fs/partitions/acorn.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
79399 +++ linux-2.4.25/fs/partitions/acorn.c 2004-03-31 17:15:09.000000000 +0200
79400 @@ -7,7 +7,10 @@
79401 * it under the terms of the GNU General Public License version 2 as
79402 * published by the Free Software Foundation.
79404 - * Scan ADFS partitions on hard disk drives.
79405 + * Scan ADFS partitions on hard disk drives. Unfortunately, there
79406 + * isn't a standard for partitioning drives on Acorn machines, so
79407 + * every single manufacturer of SCSI and IDE cards created their own
79408 + * method.
79410 #include <linux/config.h>
79411 #include <linux/kernel.h>
79412 @@ -18,10 +21,18 @@
79413 #include <linux/genhd.h>
79414 #include <linux/fs.h>
79415 #include <linux/pagemap.h>
79416 +#include <linux/adfs_fs.h>
79418 #include "check.h"
79419 #include "acorn.h"
79422 + * Partition types. (Oh for reusability)
79423 + */
79424 +#define PARTITION_RISCIX_MFM 1
79425 +#define PARTITION_RISCIX_SCSI 2
79426 +#define PARTITION_LINUX 9
79428 static void
79429 adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
79431 @@ -61,6 +72,21 @@
79434 #ifdef CONFIG_ACORN_PARTITION_RISCIX
79436 +struct riscix_part {
79437 + __u32 start;
79438 + __u32 length;
79439 + __u32 one;
79440 + char name[16];
79443 +struct riscix_record {
79444 + __u32 magic;
79445 +#define RISCIX_MAGIC (0x4a657320)
79446 + __u32 date;
79447 + struct riscix_part part[8];
79450 static int
79451 riscix_partition(struct gendisk *hd, struct block_device *bdev,
79452 unsigned long first_sect, int minor, unsigned long nr_sects)
79453 @@ -102,6 +128,15 @@
79455 #endif
79457 +#define LINUX_NATIVE_MAGIC 0xdeafa1de
79458 +#define LINUX_SWAP_MAGIC 0xdeafab1e
79460 +struct linux_part {
79461 + __u32 magic;
79462 + __u32 start_sect;
79463 + __u32 nr_sects;
79466 static int
79467 linux_partition(struct gendisk *hd, struct block_device *bdev,
79468 unsigned long first_sect, int minor, unsigned long nr_sects)
79469 @@ -136,7 +171,7 @@
79472 #ifdef CONFIG_ACORN_PARTITION_CUMANA
79473 -static int
79474 +int
79475 adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
79476 unsigned long first_sector, int minor)
79478 @@ -147,7 +182,7 @@
79479 int first = 1;
79482 - * Try Cumana style partitions - sector 3 contains ADFS boot block
79483 + * Try Cumana style partitions - sector 6 contains ADFS boot block
79484 * with pointer to next 'drive'.
79486 * There are unknowns in this code - is the 'cylinder number' of the
79487 @@ -163,13 +198,13 @@
79488 struct adfs_discrecord *dr;
79489 unsigned int nr_sects;
79491 - if (!(minor & mask))
79492 - break;
79494 data = read_dev_sector(bdev, start_blk * 2 + 6, &sect);
79495 if (!data)
79496 return -1;
79498 + if (!(minor & mask))
79499 + break;
79501 dr = adfs_partition(hd, name, data, first_sector, minor++);
79502 if (!dr)
79503 break;
79504 @@ -229,7 +264,7 @@
79505 * hda1 = ADFS partition on first drive.
79506 * hda2 = non-ADFS partition.
79508 -static int
79509 +int
79510 adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
79511 unsigned long first_sector, int minor)
79513 @@ -282,11 +317,18 @@
79514 break;
79517 + printk("\n");
79518 return 1;
79520 #endif
79522 #ifdef CONFIG_ACORN_PARTITION_ICS
79524 +struct ics_part {
79525 + __u32 start;
79526 + __s32 size;
79529 static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
79531 Sector sect;
79532 @@ -303,6 +345,22 @@
79536 + * Check for a valid ICS partition using the checksum.
79537 + */
79538 +static inline int valid_ics_sector(const unsigned char *data)
79540 + unsigned long sum;
79541 + int i;
79543 + for (i = 0, sum = 0x50617274; i < 508; i++)
79544 + sum += data[i];
79546 + sum -= le32_to_cpu(*(__u32 *)(&data[508]));
79548 + return sum == 0;
79552 * Purpose: allocate ICS partitions.
79553 * Params : hd - pointer to gendisk structure to store partition info.
79554 * dev - device number to access.
79555 @@ -314,15 +372,14 @@
79556 * hda2 = ADFS partition 1 on first drive.
79557 * ..etc..
79559 -static int
79560 +int
79561 adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
79562 unsigned long first_sector, int minor)
79564 + const unsigned char *data;
79565 + const struct ics_part *p;
79566 + unsigned int mask = (1 << hd->minor_shift) - 1;
79567 Sector sect;
79568 - unsigned char *data;
79569 - unsigned long sum;
79570 - unsigned int i, mask = (1 << hd->minor_shift) - 1;
79571 - struct ics_part *p;
79574 * Try ICS style partitions - sector 0 contains partition info.
79575 @@ -331,21 +388,14 @@
79576 if (!data)
79577 return -1;
79579 - /*
79580 - * check for a valid checksum
79581 - */
79582 - for (i = 0, sum = 0x50617274; i < 508; i++)
79583 - sum += data[i];
79585 - sum -= le32_to_cpu(*(__u32 *)(&data[508]));
79586 - if (sum) {
79587 - put_dev_sector(sect);
79588 - return 0; /* not ICS partition table */
79589 + if (!valid_ics_sector(data)) {
79590 + put_dev_sector(sect);
79591 + return 0;
79594 printk(" [ICS]");
79596 - for (p = (struct ics_part *)data; p->size; p++) {
79597 + for (p = (const struct ics_part *)data; p->size; p++) {
79598 unsigned long start;
79599 long size;
79601 @@ -355,12 +405,19 @@
79602 start = le32_to_cpu(p->start);
79603 size = le32_to_cpu(p->size);
79605 + /*
79606 + * Negative sizes tell the RISC OS ICS driver to ignore
79607 + * this partition - in effect it says that this does not
79608 + * contain an ADFS filesystem.
79609 + */
79610 if (size < 0) {
79611 size = -size;
79614 - * We use the first sector to identify what type
79615 - * this partition is...
79616 + * Our own extension - We use the first sector
79617 + * of the partition to identify what type this
79618 + * partition is. We must not make this visible
79619 + * to the filesystem.
79621 if (size > 1 && adfspart_check_ICSLinux(bdev, start)) {
79622 start += 1;
79623 @@ -375,10 +432,32 @@
79626 put_dev_sector(sect);
79627 + printk("\n");
79628 return 1;
79630 #endif
79632 +#ifdef CONFIG_ACORN_PARTITION_POWERTEC
79633 +struct ptec_part {
79634 + __u32 unused1;
79635 + __u32 unused2;
79636 + __u32 start;
79637 + __u32 size;
79638 + __u32 unused5;
79639 + char type[8];
79642 +static inline int valid_ptec_sector(const unsigned char *data)
79644 + unsigned char checksum = 0x2a;
79645 + int i;
79647 + for (i = 0; i < 511; i++)
79648 + checksum += data[i];
79650 + return checksum == data[511];
79654 * Purpose: allocate ICS partitions.
79655 * Params : hd - pointer to gendisk structure to store partition info.
79656 @@ -391,32 +470,27 @@
79657 * hda2 = ADFS partition 1 on first drive.
79658 * ..etc..
79660 -#ifdef CONFIG_ACORN_PARTITION_POWERTEC
79661 -static int
79662 +int
79663 adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
79664 unsigned long first_sector, int minor)
79666 Sector sect;
79667 - unsigned char *data;
79668 - struct ptec_partition *p;
79669 - unsigned char checksum;
79670 + const unsigned char *data;
79671 + const struct ptec_part *p;
79672 int i;
79674 data = read_dev_sector(bdev, 0, &sect);
79675 if (!data)
79676 return -1;
79678 - for (checksum = 0x2a, i = 0; i < 511; i++)
79679 - checksum += data[i];
79681 - if (checksum != data[511]) {
79682 + if (!valid_ptec_sector(data)) {
79683 put_dev_sector(sect);
79684 return 0;
79687 printk(" [POWERTEC]");
79689 - for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
79690 + for (i = 0, p = (const struct ptec_part *)data; i < 12; i++, p++) {
79691 unsigned long start;
79692 unsigned long size;
79694 @@ -430,49 +504,82 @@
79697 put_dev_sector(sect);
79698 + printk("\n");
79699 return 1;
79701 #endif
79703 -static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, int) = {
79704 -#ifdef CONFIG_ACORN_PARTITION_ICS
79705 - adfspart_check_ICS,
79706 -#endif
79707 -#ifdef CONFIG_ACORN_PARTITION_POWERTEC
79708 - adfspart_check_POWERTEC,
79709 -#endif
79710 -#ifdef CONFIG_ACORN_PARTITION_CUMANA
79711 - adfspart_check_CUMANA,
79712 -#endif
79713 -#ifdef CONFIG_ACORN_PARTITION_ADFS
79714 - adfspart_check_ADFS,
79715 -#endif
79716 - NULL
79717 +#ifdef CONFIG_ACORN_PARTITION_EESOX
79718 +struct eesox_part {
79719 + char magic[6];
79720 + char name[10];
79721 + u32 start;
79722 + u32 unused6;
79723 + u32 unused7;
79724 + u32 unused8;
79728 - * Purpose: initialise all the partitions on an ADFS drive.
79729 - * These may be other ADFS partitions or a Linux/RiscBSD/RISCiX
79730 - * partition.
79731 + * Guess who created this format?
79732 + */
79733 +static const char eesox_name[] = {
79734 + 'N', 'e', 'i', 'l', ' ',
79735 + 'C', 'r', 'i', 't', 'c', 'h', 'e', 'l', 'l', ' ', ' '
79739 + * EESOX SCSI partition format.
79741 - * Params : hd - pointer to gendisk structure
79742 - * dev - device number to access
79743 - * first_sect - first available sector on the disk.
79744 - * first_minor - first available minor on this device.
79745 + * This is a goddamned awful partition format. We don't seem to store
79746 + * the size of the partition in this table, only the start addresses.
79748 - * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
79749 + * There are two possibilities where the size comes from:
79750 + * 1. The individual ADFS boot block entries that are placed on the disk.
79751 + * 2. The start address of the next entry.
79753 -int acorn_partition(struct gendisk *hd, struct block_device *bdev,
79754 - unsigned long first_sect, int first_minor)
79755 +int
79756 +adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
79757 + unsigned long first_sector, int minor)
79759 + Sector sect;
79760 + const unsigned char *data;
79761 + unsigned char buffer[256];
79762 + struct eesox_part *p;
79763 + u32 start = first_sector;
79764 int i;
79766 - for (i = 0; partfn[i]; i++) {
79767 - int r = partfn[i](hd, bdev, first_sect, first_minor);
79768 - if (r) {
79769 - if (r > 0)
79770 - printk("\n");
79771 - return r;
79773 + data = read_dev_sector(bdev, 7, &sect);
79774 + if (!data)
79775 + return -1;
79777 + /*
79778 + * "Decrypt" the partition table. God knows why...
79779 + */
79780 + for (i = 0; i < 256; i++)
79781 + buffer[i] = data[i] ^ eesox_name[i & 15];
79783 + put_dev_sector(sect);
79785 + for (i = 0, p = (struct eesox_part *)buffer; i < 8; i++, p++) {
79786 + u32 next;
79788 + if (memcmp(p->magic, "Eesox", 6))
79789 + break;
79791 + next = le32_to_cpu(p->start) + first_sector;
79792 + if (i)
79793 + add_gd_partition(hd, minor++, start, next - start);
79794 + start = next;
79796 - return 0;
79798 + if (i != 0) {
79799 + unsigned long size;
79801 + size = hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects;
79802 + add_gd_partition(hd, minor++, start, size - start);
79803 + printk("\n");
79806 + return i ? 1 : 0;
79808 +#endif
79809 --- linux-2.4.25/fs/partitions/acorn.h~2.4.25-vrs2.patch 2001-11-22 20:48:07.000000000 +0100
79810 +++ linux-2.4.25/fs/partitions/acorn.h 2004-03-31 17:15:09.000000000 +0200
79811 @@ -1,55 +1,28 @@
79813 - * fs/partitions/acorn.h
79814 + * linux/fs/partitions/acorn.h
79816 - * Copyright (C) 1996-1998 Russell King
79817 - */
79818 -#include <linux/adfs_fs.h>
79821 - * Partition types. (Oh for reusability)
79822 + * Copyright (C) 1996-2001 Russell King.
79824 + * I _hate_ this partitioning mess - why can't we have one defined
79825 + * format, and everyone stick to it?
79827 -#define PARTITION_RISCIX_MFM 1
79828 -#define PARTITION_RISCIX_SCSI 2
79829 -#define PARTITION_LINUX 9
79831 -struct riscix_part {
79832 - __u32 start;
79833 - __u32 length;
79834 - __u32 one;
79835 - char name[16];
79838 -struct riscix_record {
79839 - __u32 magic;
79840 -#define RISCIX_MAGIC (0x4a657320)
79841 - __u32 date;
79842 - struct riscix_part part[8];
79845 -#define LINUX_NATIVE_MAGIC 0xdeafa1de
79846 -#define LINUX_SWAP_MAGIC 0xdeafab1e
79848 -struct linux_part {
79849 - __u32 magic;
79850 - __u32 start_sect;
79851 - __u32 nr_sects;
79853 +int
79854 +adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
79855 + unsigned long first_sector, int minor);
79857 -struct ics_part {
79858 - __u32 start;
79859 - __s32 size;
79861 +int
79862 +adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
79863 + unsigned long first_sector, int minor);
79865 -struct ptec_partition {
79866 - __u32 unused1;
79867 - __u32 unused2;
79868 - __u32 start;
79869 - __u32 size;
79870 - __u32 unused5;
79871 - char type[8];
79874 +int
79875 +adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
79876 + unsigned long first_sector, int minor);
79878 -int acorn_partition(struct gendisk *hd, struct block_device *bdev,
79879 - unsigned long first_sect, int first_minor);
79880 +int
79881 +adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
79882 + unsigned long first_sector, int minor);
79884 +int
79885 +adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
79886 + unsigned long first_sector, int minor);
79887 --- linux-2.4.25/fs/partitions/check.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
79888 +++ linux-2.4.25/fs/partitions/check.c 2004-03-31 17:15:09.000000000 +0200
79889 @@ -40,8 +40,30 @@
79890 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
79892 static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
79893 -#ifdef CONFIG_ACORN_PARTITION
79894 - acorn_partition,
79895 + /*
79896 + * Probe partition formats with tables at disk address 0
79897 + * that also have an ADFS boot block at 0xdc0.
79898 + */
79899 +#ifdef CONFIG_ACORN_PARTITION_ICS
79900 + adfspart_check_ICS,
79901 +#endif
79902 +#ifdef CONFIG_ACORN_PARTITION_POWERTEC
79903 + adfspart_check_POWERTEC,
79904 +#endif
79905 +#ifdef CONFIG_ACORN_PARTITION_EESOX
79906 + adfspart_check_EESOX,
79907 +#endif
79909 + /*
79910 + * Now move on to formats that only have partition info at
79911 + * disk address 0xdc0. These should come before MSDOS
79912 + * partition tables.
79913 + */
79914 +#ifdef CONFIG_ACORN_PARTITION_CUMANA
79915 + adfspart_check_CUMANA,
79916 +#endif
79917 +#ifdef CONFIG_ACORN_PARTITION_ADFS
79918 + adfspart_check_ADFS,
79919 #endif
79920 #ifdef CONFIG_SGI_PARTITION
79921 sgi_partition,
79922 @@ -79,13 +101,25 @@
79923 NULL
79926 +static char *raid_name (struct gendisk *hd, unsigned int unit, unsigned int part,
79927 + int major_base, char *buf)
79929 + int ctlr = hd->major - major_base;
79930 + if (part == 0)
79931 + sprintf(buf, "%s/c%dd%d", hd->major_name, ctlr, unit);
79932 + else
79933 + sprintf(buf, "%s/c%dd%dp%d", hd->major_name, ctlr, unit,
79934 + part);
79935 + return buf;
79939 * This is ucking fugly but its probably the best thing for 2.4.x
79940 * Take it as a clear reminder that: 1) we should put the device name
79941 * generation in the object kdev_t points to in 2.5.
79942 * and 2) ioctls better work on half-opened devices.
79946 #ifdef CONFIG_ARCH_S390
79947 int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
79948 int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
79949 @@ -104,10 +138,11 @@
79950 char *disk_name (struct gendisk *hd, int minor, char *buf)
79952 const char *maj = hd->major_name;
79953 - unsigned int unit = (minor >> hd->minor_shift);
79954 - unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
79955 + unsigned int unit = minor >> hd->minor_shift;
79956 + unsigned int part = minor & (( 1 << hd->minor_shift) - 1);
79957 + char *p;
79959 - if ((unit < hd->nr_real) && hd->part[minor].de) {
79960 + if (unit < hd->nr_real && hd->part[minor].de) {
79961 int pos;
79963 pos = devfs_generate_path (hd->part[minor].de, buf, 64);
79964 @@ -153,51 +188,32 @@
79966 if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
79967 unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
79968 - if (unit+'a' > 'z') {
79969 - unit -= 26;
79970 - sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
79971 - if (part)
79972 - sprintf(buf + 4, "%d", part);
79973 - return buf;
79976 if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
79977 - int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
79978 - if (part == 0)
79979 - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
79980 - else
79981 - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
79982 - return buf;
79984 + return raid_name(hd, unit, part, COMPAQ_SMART2_MAJOR, buf);
79986 if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
79987 - int ctlr = hd->major - COMPAQ_CISS_MAJOR;
79988 - if (part == 0)
79989 - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
79990 - else
79991 - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
79992 - return buf;
79993 + return raid_name(hd, unit, part, COMPAQ_CISS_MAJOR, buf);
79995 if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
79996 - int ctlr = hd->major - DAC960_MAJOR;
79997 + return raid_name(hd, unit, part, DAC960_MAJOR, buf);
79999 + if (hd->major == ATARAID_MAJOR) {
80000 + int disk = minor >> hd->minor_shift;
80001 + int part = minor & (( 1 << hd->minor_shift) - 1);
80002 if (part == 0)
80003 - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
80004 + sprintf(buf, "%s/d%d", maj, disk);
80005 else
80006 - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
80007 + sprintf(buf, "%s/d%dp%d", maj, disk, part);
80008 return buf;
80010 - if (hd->major == ATARAID_MAJOR) {
80011 - int disk = minor >> hd->minor_shift;
80012 - int part = minor & (( 1 << hd->minor_shift) - 1);
80013 - if (part == 0)
80014 - sprintf(buf, "%s/d%d", maj, disk);
80015 - else
80016 - sprintf(buf, "%s/d%dp%d", maj, disk, part);
80017 - return buf;
80019 - if (part)
80020 - sprintf(buf, "%s%c%d", maj, unit+'a', part);
80021 + p = buf;
80022 + if (unit <= 26)
80023 + p += sprintf(buf, "%s%c", maj, 'a' + unit);
80024 else
80025 - sprintf(buf, "%s%c", maj, unit+'a');
80026 + p += sprintf(buf, "%s%c%c", maj, 'a' + unit / 26, 'a' + unit % 26);
80027 + if (part)
80028 + sprintf(p, "%d", part);
80029 return buf;
80032 @@ -207,7 +223,7 @@
80033 void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
80035 #ifndef CONFIG_DEVFS_FS
80036 - char buf[40];
80037 + char buf[MAX_DISKNAME_LEN];
80038 #endif
80040 hd->part[minor].start_sect = start;
80041 @@ -229,7 +245,7 @@
80042 static int first_time = 1;
80043 unsigned long first_sector;
80044 struct block_device *bdev;
80045 - char buf[64];
80046 + char buf[MAX_DISKNAME_LEN];
80047 int i;
80049 if (first_time)
80050 --- linux-2.4.25/fs/proc/array.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
80051 +++ linux-2.4.25/fs/proc/array.c 2004-03-31 17:15:09.000000000 +0200
80052 @@ -362,15 +362,15 @@
80053 task->cmin_flt,
80054 task->maj_flt,
80055 task->cmaj_flt,
80056 - task->times.tms_utime,
80057 - task->times.tms_stime,
80058 - task->times.tms_cutime,
80059 - task->times.tms_cstime,
80060 + hz_to_std(task->times.tms_utime),
80061 + hz_to_std(task->times.tms_stime),
80062 + hz_to_std(task->times.tms_cutime),
80063 + hz_to_std(task->times.tms_cstime),
80064 priority,
80065 nice,
80066 0UL /* removed */,
80067 task->it_real_value,
80068 - task->start_time,
80069 + hz_to_std(task->start_time),
80070 vsize,
80071 mm ? mm->rss : 0, /* you might want to shift this left 3 */
80072 task->rlim[RLIMIT_RSS].rlim_cur,
80073 @@ -417,6 +417,7 @@
80074 end = PMD_SIZE;
80075 do {
80076 pte_t page = *pte;
80077 + unsigned long pfn;
80078 struct page *ptpage;
80080 address += PAGE_SIZE;
80081 @@ -426,8 +427,11 @@
80082 ++*total;
80083 if (!pte_present(page))
80084 continue;
80085 - ptpage = pte_page(page);
80086 - if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage))
80087 + pfn = pte_pfn(page);
80088 + if (!pfn_valid(pfn))
80089 + continue;
80090 + ptpage = pfn_to_page(pfn);
80091 + if (PageReserved(ptpage))
80092 continue;
80093 ++*pages;
80094 if (pte_dirty(page))
80095 @@ -609,14 +613,14 @@
80097 len = sprintf(buffer,
80098 "cpu %lu %lu\n",
80099 - task->times.tms_utime,
80100 - task->times.tms_stime);
80101 + hz_to_std(task->times.tms_utime),
80102 + hz_to_std(task->times.tms_stime));
80104 for (i = 0 ; i < smp_num_cpus; i++)
80105 len += sprintf(buffer + len, "cpu%d %lu %lu\n",
80107 - task->per_cpu_utime[cpu_logical_map(i)],
80108 - task->per_cpu_stime[cpu_logical_map(i)]);
80109 + hz_to_std(task->per_cpu_utime[cpu_logical_map(i)]),
80110 + hz_to_std(task->per_cpu_stime[cpu_logical_map(i)]));
80112 return len;
80114 --- linux-2.4.25/fs/proc/proc_misc.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
80115 +++ linux-2.4.25/fs/proc/proc_misc.c 2004-03-31 17:15:09.000000000 +0200
80116 @@ -308,16 +308,16 @@
80118 int i, len = 0;
80119 extern unsigned long total_forks;
80120 - unsigned long jif = jiffies;
80121 + unsigned long jif = hz_to_std(jiffies);
80122 unsigned int sum = 0, user = 0, nice = 0, system = 0;
80123 int major, disk;
80125 for (i = 0 ; i < smp_num_cpus; i++) {
80126 int cpu = cpu_logical_map(i), j;
80128 - user += kstat.per_cpu_user[cpu];
80129 - nice += kstat.per_cpu_nice[cpu];
80130 - system += kstat.per_cpu_system[cpu];
80131 + user += hz_to_std(kstat.per_cpu_user[cpu]);
80132 + nice += hz_to_std(kstat.per_cpu_nice[cpu]);
80133 + system += hz_to_std(kstat.per_cpu_system[cpu]);
80134 #if !defined(CONFIG_ARCH_S390)
80135 for (j = 0 ; j < NR_IRQS ; j++)
80136 sum += kstat.irqs[cpu][j];
80137 @@ -331,10 +331,10 @@
80138 proc_sprintf(page, &off, &len,
80139 "cpu%d %u %u %u %lu\n",
80141 - kstat.per_cpu_user[cpu_logical_map(i)],
80142 - kstat.per_cpu_nice[cpu_logical_map(i)],
80143 - kstat.per_cpu_system[cpu_logical_map(i)],
80144 - jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
80145 + hz_to_std(kstat.per_cpu_user[cpu_logical_map(i)]),
80146 + hz_to_std(kstat.per_cpu_nice[cpu_logical_map(i)]),
80147 + hz_to_std(kstat.per_cpu_system[cpu_logical_map(i)]),
80148 + jif - hz_to_std( kstat.per_cpu_user[cpu_logical_map(i)] \
80149 + kstat.per_cpu_nice[cpu_logical_map(i)] \
80150 + kstat.per_cpu_system[cpu_logical_map(i)]));
80151 proc_sprintf(page, &off, &len,
80152 @@ -440,12 +440,14 @@
80153 return proc_calc_metrics(page, start, off, count, eof, len);
80156 +#ifdef CONFIG_GENERIC_ISA_DMA
80157 static int dma_read_proc(char *page, char **start, off_t off,
80158 int count, int *eof, void *data)
80160 int len = get_dma_list(page);
80161 return proc_calc_metrics(page, start, off, count, eof, len);
80163 +#endif
80165 static int cmdline_read_proc(char *page, char **start, off_t off,
80166 int count, int *eof, void *data)
80167 @@ -613,7 +615,9 @@
80168 {"interrupts", interrupts_read_proc},
80169 #endif
80170 {"filesystems", filesystems_read_proc},
80171 +#ifdef CONFIG_GENERIC_ISA_DMA
80172 {"dma", dma_read_proc},
80173 +#endif
80174 {"cmdline", cmdline_read_proc},
80175 #ifdef CONFIG_SGI_DS1286
80176 {"rtc", ds1286_read_proc},
80177 --- linux-2.4.25/fs/stat.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
80178 +++ linux-2.4.25/fs/stat.c 2004-03-31 17:15:09.000000000 +0200
80179 @@ -26,7 +26,9 @@
80183 -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
80184 +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
80185 + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
80186 + !defined(__x86_64__) && !defined(__mips__)
80189 * For backward compatibility? Maybe this should be moved
80190 @@ -38,7 +40,7 @@
80191 struct __old_kernel_stat tmp;
80193 memset(&tmp, 0, sizeof(struct __old_kernel_stat));
80196 if (warncount > 0) {
80197 warncount--;
80198 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
80199 @@ -58,7 +60,7 @@
80200 #if BITS_PER_LONG == 32
80201 if (inode->i_size > MAX_NON_LFS)
80202 return -EOVERFLOW;
80203 -#endif
80204 +#endif
80205 tmp.st_size = inode->i_size;
80206 tmp.st_atime = inode->i_atime;
80207 tmp.st_mtime = inode->i_mtime;
80208 @@ -84,7 +86,7 @@
80209 #if BITS_PER_LONG == 32
80210 if (inode->i_size > MAX_NON_LFS)
80211 return -EOVERFLOW;
80212 -#endif
80213 +#endif
80214 tmp.st_size = inode->i_size;
80215 tmp.st_atime = inode->i_atime;
80216 tmp.st_mtime = inode->i_mtime;
80217 @@ -129,7 +131,9 @@
80221 -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
80222 +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
80223 + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
80224 + !defined(__x86_64__) && !defined(__mips__)
80226 * For backward compatibility? Maybe this should be moved
80227 * into arch/i386 instead?
80228 @@ -165,7 +169,9 @@
80229 return error;
80232 -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
80233 +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
80234 + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
80235 + !defined(__x86_64__) && !defined(__mips__)
80238 * For backward compatibility? Maybe this should be moved
80239 @@ -203,7 +209,9 @@
80240 return error;
80243 -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
80244 +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
80245 + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
80246 + !defined(__x86_64__) && !defined(__mips__)
80249 * For backward compatibility? Maybe this should be moved
80250 --- linux-2.4.25/include/asm-alpha/ide.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
80251 +++ linux-2.4.25/include/asm-alpha/ide.h 2004-03-31 17:15:09.000000000 +0200
80252 @@ -19,35 +19,15 @@
80253 #define MAX_HWIFS 4
80254 #endif
80256 -static __inline__ int ide_default_irq(ide_ioreg_t base)
80258 - switch (base) {
80259 - case 0x1f0: return 14;
80260 - case 0x170: return 15;
80261 - case 0x1e8: return 11;
80262 - case 0x168: return 10;
80263 - default:
80264 - return 0;
80268 -static __inline__ ide_ioreg_t ide_default_io_base(int index)
80270 - switch (index) {
80271 - case 0: return 0x1f0;
80272 - case 1: return 0x170;
80273 - case 2: return 0x1e8;
80274 - case 3: return 0x168;
80275 - default:
80276 - return 0;
80279 +#define ide_default_io_base(i) ((ide_ioreg_t)0)
80280 +#define ide_default_irq(b) (0)
80282 static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
80284 ide_ioreg_t reg = data_port;
80285 int i;
80287 + memset(hw, 0, sizeof(*hw));
80288 for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
80289 hw->io_ports[i] = reg;
80290 reg += 1;
80291 @@ -55,7 +35,7 @@
80292 if (ctrl_port) {
80293 hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
80294 } else {
80295 - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
80296 + hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
80298 if (irq != NULL)
80299 *irq = 0;
80300 @@ -70,13 +50,19 @@
80302 #ifndef CONFIG_BLK_DEV_IDEPCI
80303 hw_regs_t hw;
80304 - int index;
80306 - for (index = 0; index < MAX_HWIFS; index++) {
80307 - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
80308 - hw.irq = ide_default_irq(ide_default_io_base(index));
80309 - ide_register_hw(&hw, NULL);
80311 + ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
80312 + hw.irq = 14;
80313 + ide_register_hw(&hw, NULL);
80314 + ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
80315 + hw.irq = 15;
80316 + ide_register_hw(&hw, NULL);
80317 + ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
80318 + hw.irq = 11;
80319 + ide_register_hw(&hw, NULL);
80320 + ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
80321 + hw.irq = 10;
80322 + ide_register_hw(&hw, NULL);
80323 #endif /* CONFIG_BLK_DEV_IDEPCI */
80326 --- linux-2.4.25/include/asm-alpha/param.h~2.4.25-vrs2.patch 2000-11-08 08:37:31.000000000 +0100
80327 +++ linux-2.4.25/include/asm-alpha/param.h 2004-03-31 17:15:09.000000000 +0200
80328 @@ -13,6 +13,9 @@
80329 # else
80330 # define HZ 1200
80331 # endif
80332 +#ifdef __KERNEL__
80333 +# define hz_to_std(a) (a)
80334 +#endif
80335 #endif
80337 #define EXEC_PAGESIZE 8192
80338 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
80339 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/AT91RM9200_MCI.h 2004-03-31 17:15:09.000000000 +0200
80340 @@ -0,0 +1,127 @@
80341 +// ----------------------------------------------------------------------------
80342 +// ATMEL Microcontroller Software Support - ROUSSET -
80343 +// ----------------------------------------------------------------------------
80344 +// The software is delivered "AS IS" without warranty or condition of any
80345 +// kind, either express, implied or statutory. This includes without
80346 +// limitation any warranty or condition with respect to merchantability or
80347 +// fitness for any particular purpose, or against the infringements of
80348 +// intellectual property rights of others.
80349 +// ----------------------------------------------------------------------------
80350 +// File Name : AT91RM9200.h
80351 +// Object : AT91RM9200 / MCI definitions
80352 +// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
80353 +//
80354 +// ----------------------------------------------------------------------------
80356 +#ifndef AT91RM9200_MCI_H
80357 +#define AT91RM9200_MCI_H
80359 +// *****************************************************************************
80360 +// SOFTWARE API DEFINITION FOR Multimedia Card Interface
80361 +// *****************************************************************************
80362 +#ifndef __ASSEMBLY__
80364 +typedef struct _AT91S_MCI {
80365 + AT91_REG MCI_CR; // MCI Control Register
80366 + AT91_REG MCI_MR; // MCI Mode Register
80367 + AT91_REG MCI_DTOR; // MCI Data Timeout Register
80368 + AT91_REG MCI_SDCR; // MCI SD Card Register
80369 + AT91_REG MCI_ARGR; // MCI Argument Register
80370 + AT91_REG MCI_CMDR; // MCI Command Register
80371 + AT91_REG Reserved0[2]; //
80372 + AT91_REG MCI_RSPR[4]; // MCI Response Register
80373 + AT91_REG MCI_RDR; // MCI Receive Data Register
80374 + AT91_REG MCI_TDR; // MCI Transmit Data Register
80375 + AT91_REG Reserved1[2]; //
80376 + AT91_REG MCI_SR; // MCI Status Register
80377 + AT91_REG MCI_IER; // MCI Interrupt Enable Register
80378 + AT91_REG MCI_IDR; // MCI Interrupt Disable Register
80379 + AT91_REG MCI_IMR; // MCI Interrupt Mask Register
80380 + AT91_REG Reserved2[44]; //
80381 + AT91_REG MCI_RPR; // Receive Pointer Register
80382 + AT91_REG MCI_RCR; // Receive Counter Register
80383 + AT91_REG MCI_TPR; // Transmit Pointer Register
80384 + AT91_REG MCI_TCR; // Transmit Counter Register
80385 + AT91_REG MCI_RNPR; // Receive Next Pointer Register
80386 + AT91_REG MCI_RNCR; // Receive Next Counter Register
80387 + AT91_REG MCI_TNPR; // Transmit Next Pointer Register
80388 + AT91_REG MCI_TNCR; // Transmit Next Counter Register
80389 + AT91_REG MCI_PTCR; // PDC Transfer Control Register
80390 + AT91_REG MCI_PTSR; // PDC Transfer Status Register
80391 +} AT91S_MCI, *AT91PS_MCI;
80393 +#endif
80395 +// -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register --------
80396 +#define AT91C_MCI_MCIEN ((unsigned int) 0x1 << 0) // (MCI) Multimedia Interface Enable
80397 +#define AT91C_MCI_MCIDIS ((unsigned int) 0x1 << 1) // (MCI) Multimedia Interface Disable
80398 +#define AT91C_MCI_PWSEN ((unsigned int) 0x1 << 2) // (MCI) Power Save Mode Enable
80399 +#define AT91C_MCI_PWSDIS ((unsigned int) 0x1 << 3) // (MCI) Power Save Mode Disable
80400 +// -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register --------
80401 +#define AT91C_MCI_CLKDIV ((unsigned int) 0x1 << 0) // (MCI) Clock Divider
80402 +#define AT91C_MCI_PWSDIV ((unsigned int) 0x1 << 8) // (MCI) Power Saving Divider
80403 +#define AT91C_MCI_PDCPADV ((unsigned int) 0x1 << 14) // (MCI) PDC Padding Value
80404 +#define AT91C_MCI_PDCMODE ((unsigned int) 0x1 << 15) // (MCI) PDC Oriented Mode
80405 +#define AT91C_MCI_BLKLEN ((unsigned int) 0x1 << 18) // (MCI) Data Block Length
80406 +// -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register --------
80407 +#define AT91C_MCI_DTOCYC ((unsigned int) 0x1 << 0) // (MCI) Data Timeout Cycle Number
80408 +#define AT91C_MCI_DTOMUL ((unsigned int) 0x7 << 4) // (MCI) Data Timeout Multiplier
80409 +#define AT91C_MCI_DTOMUL_1 ((unsigned int) 0x0 << 4) // (MCI) DTOCYC x 1
80410 +#define AT91C_MCI_DTOMUL_16 ((unsigned int) 0x1 << 4) // (MCI) DTOCYC x 16
80411 +#define AT91C_MCI_DTOMUL_128 ((unsigned int) 0x2 << 4) // (MCI) DTOCYC x 128
80412 +#define AT91C_MCI_DTOMUL_256 ((unsigned int) 0x3 << 4) // (MCI) DTOCYC x 256
80413 +#define AT91C_MCI_DTOMUL_1024 ((unsigned int) 0x4 << 4) // (MCI) DTOCYC x 1024
80414 +#define AT91C_MCI_DTOMUL_4096 ((unsigned int) 0x5 << 4) // (MCI) DTOCYC x 4096
80415 +#define AT91C_MCI_DTOMUL_65536 ((unsigned int) 0x6 << 4) // (MCI) DTOCYC x 65536
80416 +#define AT91C_MCI_DTOMUL_1048576 ((unsigned int) 0x7 << 4) // (MCI) DTOCYC x 1048576
80417 +// -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register --------
80418 +#define AT91C_MCI_SCDSEL ((unsigned int) 0x1 << 0) // (MCI) SD Card Selector
80419 +#define AT91C_MCI_SCDBUS ((unsigned int) 0x1 << 7) // (MCI) SD Card Bus Width
80420 +// -------- MCI_CMDR : (MCI Offset: 0x14) MCI Command Register --------
80421 +#define AT91C_MCI_CMDNB ((unsigned int) 0x1F << 0) // (MCI) Command Number
80422 +#define AT91C_MCI_RSPTYP ((unsigned int) 0x3 << 6) // (MCI) Response Type
80423 +#define AT91C_MCI_RSPTYP_NO ((unsigned int) 0x0 << 6) // (MCI) No response
80424 +#define AT91C_MCI_RSPTYP_48 ((unsigned int) 0x1 << 6) // (MCI) 48-bit response
80425 +#define AT91C_MCI_RSPTYP_136 ((unsigned int) 0x2 << 6) // (MCI) 136-bit response
80426 +#define AT91C_MCI_SPCMD ((unsigned int) 0x7 << 8) // (MCI) Special CMD
80427 +#define AT91C_MCI_SPCMD_NONE ((unsigned int) 0x0 << 8) // (MCI) Not a special CMD
80428 +#define AT91C_MCI_SPCMD_INIT ((unsigned int) 0x1 << 8) // (MCI) Initialization CMD
80429 +#define AT91C_MCI_SPCMD_SYNC ((unsigned int) 0x2 << 8) // (MCI) Synchronized CMD
80430 +#define AT91C_MCI_SPCMD_IT_CMD ((unsigned int) 0x4 << 8) // (MCI) Interrupt command
80431 +#define AT91C_MCI_SPCMD_IT_REP ((unsigned int) 0x5 << 8) // (MCI) Interrupt response
80432 +#define AT91C_MCI_OPDCMD ((unsigned int) 0x1 << 11) // (MCI) Open Drain Command
80433 +#define AT91C_MCI_MAXLAT ((unsigned int) 0x1 << 12) // (MCI) Maximum Latency for Command to respond
80434 +#define AT91C_MCI_TRCMD ((unsigned int) 0x3 << 16) // (MCI) Transfer CMD
80435 +#define AT91C_MCI_TRCMD_NO ((unsigned int) 0x0 << 16) // (MCI) No transfer
80436 +#define AT91C_MCI_TRCMD_START ((unsigned int) 0x1 << 16) // (MCI) Start transfer
80437 +#define AT91C_MCI_TRCMD_STOP ((unsigned int) 0x2 << 16) // (MCI) Stop transfer
80438 +#define AT91C_MCI_TRDIR ((unsigned int) 0x1 << 18) // (MCI) Transfer Direction
80439 +#define AT91C_MCI_TRTYP ((unsigned int) 0x3 << 19) // (MCI) Transfer Type
80440 +#define AT91C_MCI_TRTYP_BLOCK ((unsigned int) 0x0 << 19) // (MCI) Block Transfer type
80441 +#define AT91C_MCI_TRTYP_MULTIPLE ((unsigned int) 0x1 << 19) // (MCI) Multiple Block transfer type
80442 +#define AT91C_MCI_TRTYP_STREAM ((unsigned int) 0x2 << 19) // (MCI) Stream transfer type
80443 +// -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register --------
80444 +#define AT91C_MCI_CMDRDY ((unsigned int) 0x1 << 0) // (MCI) Command Ready flag
80445 +#define AT91C_MCI_RXRDY ((unsigned int) 0x1 << 1) // (MCI) RX Ready flag
80446 +#define AT91C_MCI_TXRDY ((unsigned int) 0x1 << 2) // (MCI) TX Ready flag
80447 +#define AT91C_MCI_BLKE ((unsigned int) 0x1 << 3) // (MCI) Data Block Transfer Ended flag
80448 +#define AT91C_MCI_DTIP ((unsigned int) 0x1 << 4) // (MCI) Data Transfer in Progress flag
80449 +#define AT91C_MCI_NOTBUSY ((unsigned int) 0x1 << 5) // (MCI) Data Line Not Busy flag
80450 +#define AT91C_MCI_ENDRX ((unsigned int) 0x1 << 6) // (MCI) End of RX Buffer flag
80451 +#define AT91C_MCI_ENDTX ((unsigned int) 0x1 << 7) // (MCI) End of TX Buffer flag
80452 +#define AT91C_MCI_RXBUFF ((unsigned int) 0x1 << 14) // (MCI) RX Buffer Full flag
80453 +#define AT91C_MCI_TXBUFE ((unsigned int) 0x1 << 15) // (MCI) TX Buffer Empty flag
80454 +#define AT91C_MCI_RINDE ((unsigned int) 0x1 << 16) // (MCI) Response Index Error flag
80455 +#define AT91C_MCI_RDIRE ((unsigned int) 0x1 << 17) // (MCI) Response Direction Error flag
80456 +#define AT91C_MCI_RCRCE ((unsigned int) 0x1 << 18) // (MCI) Response CRC Error flag
80457 +#define AT91C_MCI_RENDE ((unsigned int) 0x1 << 19) // (MCI) Response End Bit Error flag
80458 +#define AT91C_MCI_RTOE ((unsigned int) 0x1 << 20) // (MCI) Response Time-out Error flag
80459 +#define AT91C_MCI_DCRCE ((unsigned int) 0x1 << 21) // (MCI) data CRC Error flag
80460 +#define AT91C_MCI_DTOE ((unsigned int) 0x1 << 22) // (MCI) Data timeout Error flag
80461 +#define AT91C_MCI_OVRE ((unsigned int) 0x1 << 30) // (MCI) Overrun flag
80462 +#define AT91C_MCI_UNRE ((unsigned int) 0x1 << 31) // (MCI) Underrun flag
80463 +// -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register --------
80464 +// -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register --------
80465 +// -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register --------
80467 +#endif
80468 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
80469 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/AT91RM9200_SSC.h 2004-03-31 17:15:09.000000000 +0200
80470 @@ -0,0 +1,129 @@
80471 +// ----------------------------------------------------------------------------
80472 +// ATMEL Microcontroller Software Support - ROUSSET -
80473 +// ----------------------------------------------------------------------------
80474 +// The software is delivered "AS IS" without warranty or condition of any
80475 +// kind, either express, implied or statutory. This includes without
80476 +// limitation any warranty or condition with respect to merchantability or
80477 +// fitness for any particular purpose, or against the infringements of
80478 +// intellectual property rights of others.
80479 +// ----------------------------------------------------------------------------
80480 +// File Name : AT91RM9200.h
80481 +// Object : AT91RM9200 / SSC definitions
80482 +// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
80483 +//
80484 +// ----------------------------------------------------------------------------
80486 +#ifndef AT91RM9200_SSC_H
80487 +#define AT91RM9200_SSC_H
80489 +// *****************************************************************************
80490 +// SOFTWARE API DEFINITION FOR Synchronous Serial Controller Interface
80491 +// *****************************************************************************
80492 +#ifndef __ASSEMBLY__
80494 +typedef struct _AT91S_SSC {
80495 + AT91_REG SSC_CR; // Control Register
80496 + AT91_REG SSC_CMR; // Clock Mode Register
80497 + AT91_REG Reserved0[2]; //
80498 + AT91_REG SSC_RCMR; // Receive Clock ModeRegister
80499 + AT91_REG SSC_RFMR; // Receive Frame Mode Register
80500 + AT91_REG SSC_TCMR; // Transmit Clock Mode Register
80501 + AT91_REG SSC_TFMR; // Transmit Frame Mode Register
80502 + AT91_REG SSC_RHR; // Receive Holding Register
80503 + AT91_REG SSC_THR; // Transmit Holding Register
80504 + AT91_REG Reserved1[2]; //
80505 + AT91_REG SSC_RSHR; // Receive Sync Holding Register
80506 + AT91_REG SSC_TSHR; // Transmit Sync Holding Register
80507 + AT91_REG SSC_RC0R; // Receive Compare 0 Register
80508 + AT91_REG SSC_RC1R; // Receive Compare 1 Register
80509 + AT91_REG SSC_SR; // Status Register
80510 + AT91_REG SSC_IER; // Interrupt Enable Register
80511 + AT91_REG SSC_IDR; // Interrupt Disable Register
80512 + AT91_REG SSC_IMR; // Interrupt Mask Register
80513 + AT91_REG Reserved2[44]; //
80514 + AT91_REG SSC_RPR; // Receive Pointer Register
80515 + AT91_REG SSC_RCR; // Receive Counter Register
80516 + AT91_REG SSC_TPR; // Transmit Pointer Register
80517 + AT91_REG SSC_TCR; // Transmit Counter Register
80518 + AT91_REG SSC_RNPR; // Receive Next Pointer Register
80519 + AT91_REG SSC_RNCR; // Receive Next Counter Register
80520 + AT91_REG SSC_TNPR; // Transmit Next Pointer Register
80521 + AT91_REG SSC_TNCR; // Transmit Next Counter Register
80522 + AT91_REG SSC_PTCR; // PDC Transfer Control Register
80523 + AT91_REG SSC_PTSR; // PDC Transfer Status Register
80524 +} AT91S_SSC, *AT91PS_SSC;
80526 +#endif
80528 +// -------- SSC_CR : (SSC Offset: 0x0) SSC Control Register --------
80529 +#define AT91C_SSC_RXEN ( 0x1 << 0) // (SSC) Receive Enable
80530 +#define AT91C_SSC_RXDIS ( 0x1 << 1) // (SSC) Receive Disable
80531 +#define AT91C_SSC_TXEN ( 0x1 << 8) // (SSC) Transmit Enable
80532 +#define AT91C_SSC_TXDIS ( 0x1 << 9) // (SSC) Transmit Disable
80533 +#define AT91C_SSC_SWRST ( 0x1 << 15) // (SSC) Software Reset
80534 +// -------- SSC_RCMR : (SSC Offset: 0x10) SSC Receive Clock Mode Register --------
80535 +#define AT91C_SSC_CKS ( 0x3 << 0) // (SSC) Receive/Transmit Clock Selection
80536 +#define AT91C_SSC_CKS_DIV ( 0x0) // (SSC) Divided Clock
80537 +#define AT91C_SSC_CKS_TK ( 0x1) // (SSC) TK Clock signal
80538 +#define AT91C_SSC_CKS_RK ( 0x2) // (SSC) RK pin
80539 +#define AT91C_SSC_CKO ( 0x7 << 2) // (SSC) Receive/Transmit Clock Output Mode Selection
80540 +#define AT91C_SSC_CKO_NONE ( 0x0 << 2) // (SSC) Receive/Transmit Clock Output Mode: None RK pin: Input-only
80541 +#define AT91C_SSC_CKO_CONTINOUS ( 0x1 << 2) // (SSC) Continuous Receive/Transmit Clock RK pin: Output
80542 +#define AT91C_SSC_CKO_DATA_TX ( 0x2 << 2) // (SSC) Receive/Transmit Clock only during data transfers RK pin: Output
80543 +#define AT91C_SSC_CKI ( 0x1 << 5) // (SSC) Receive/Transmit Clock Inversion
80544 +#define AT91C_SSC_CKG ( 0x3 << 6) // (SSC) Receive/Transmit Clock Gating Selection
80545 +#define AT91C_SSC_CKG_NONE ( 0x0 << 6) // (SSC) Receive/Transmit Clock Gating: None, continuous clock
80546 +#define AT91C_SSC_CKG_LOW ( 0x1 << 6) // (SSC) Receive/Transmit Clock enabled only if RF Low
80547 +#define AT91C_SSC_CKG_HIGH ( 0x2 << 6) // (SSC) Receive/Transmit Clock enabled only if RF High
80548 +#define AT91C_SSC_START ( 0xF << 8) // (SSC) Receive/Transmit Start Selection
80549 +#define AT91C_SSC_START_CONTINOUS ( 0x0 << 8) // (SSC) Continuous, as soon as the receiver is enabled, and immediately after the end of transfer of the previous data.
80550 +#define AT91C_SSC_START_TX ( 0x1 << 8) // (SSC) Transmit/Receive start
80551 +#define AT91C_SSC_START_LOW_RF ( 0x2 << 8) // (SSC) Detection of a low level on RF input
80552 +#define AT91C_SSC_START_HIGH_RF ( 0x3 << 8) // (SSC) Detection of a high level on RF input
80553 +#define AT91C_SSC_START_FALL_RF ( 0x4 << 8) // (SSC) Detection of a falling edge on RF input
80554 +#define AT91C_SSC_START_RISE_RF ( 0x5 << 8) // (SSC) Detection of a rising edge on RF input
80555 +#define AT91C_SSC_START_LEVEL_RF ( 0x6 << 8) // (SSC) Detection of any level change on RF input
80556 +#define AT91C_SSC_START_EDGE_RF ( 0x7 << 8) // (SSC) Detection of any edge on RF input
80557 +#define AT91C_SSC_START_0 ( 0x8 << 8) // (SSC) Compare 0
80558 +#define AT91C_SSC_STOP ( 0x1 << 12) // (SSC) Receive Stop Selection
80559 +#define AT91C_SSC_STTOUT ( 0x1 << 15) // (SSC) Receive/Transmit Start Output Selection
80560 +#define AT91C_SSC_STTDLY ( 0xFF << 16) // (SSC) Receive/Transmit Start Delay
80561 +#define AT91C_SSC_PERIOD ( 0xFF << 24) // (SSC) Receive/Transmit Period Divider Selection
80562 +// -------- SSC_RFMR : (SSC Offset: 0x14) SSC Receive Frame Mode Register --------
80563 +#define AT91C_SSC_DATLEN ( 0x1F << 0) // (SSC) Data Length
80564 +#define AT91C_SSC_LOOP ( 0x1 << 5) // (SSC) Loop Mode
80565 +#define AT91C_SSC_MSBF ( 0x1 << 7) // (SSC) Most Significant Bit First
80566 +#define AT91C_SSC_DATNB ( 0xF << 8) // (SSC) Data Number per Frame
80567 +#define AT91C_SSC_FSLEN ( 0xF << 16) // (SSC) Receive/Transmit Frame Sync length
80568 +#define AT91C_SSC_FSOS ( 0x7 << 20) // (SSC) Receive/Transmit Frame Sync Output Selection
80569 +#define AT91C_SSC_FSOS_NONE ( 0x0 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: None RK pin Input-only
80570 +#define AT91C_SSC_FSOS_NEGATIVE ( 0x1 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Negative Pulse
80571 +#define AT91C_SSC_FSOS_POSITIVE ( 0x2 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Positive Pulse
80572 +#define AT91C_SSC_FSOS_LOW ( 0x3 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver Low during data transfer
80573 +#define AT91C_SSC_FSOS_HIGH ( 0x4 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver High during data transfer
80574 +#define AT91C_SSC_FSOS_TOGGLE ( 0x5 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Toggling at each start of data transfer
80575 +#define AT91C_SSC_FSEDGE ( 0x1 << 24) // (SSC) Frame Sync Edge Detection
80576 +// -------- SSC_TCMR : (SSC Offset: 0x18) SSC Transmit Clock Mode Register --------
80577 +// -------- SSC_TFMR : (SSC Offset: 0x1c) SSC Transmit Frame Mode Register --------
80578 +#define AT91C_SSC_DATDEF ( 0x1 << 5) // (SSC) Data Default Value
80579 +#define AT91C_SSC_FSDEN ( 0x1 << 23) // (SSC) Frame Sync Data Enable
80580 +// -------- SSC_SR : (SSC Offset: 0x40) SSC Status Register --------
80581 +#define AT91C_SSC_TXRDY ( 0x1 << 0) // (SSC) Transmit Ready
80582 +#define AT91C_SSC_TXEMPTY ( 0x1 << 1) // (SSC) Transmit Empty
80583 +#define AT91C_SSC_ENDTX ( 0x1 << 2) // (SSC) End Of Transmission
80584 +#define AT91C_SSC_TXBUFE ( 0x1 << 3) // (SSC) Transmit Buffer Empty
80585 +#define AT91C_SSC_RXRDY ( 0x1 << 4) // (SSC) Receive Ready
80586 +#define AT91C_SSC_OVRUN ( 0x1 << 5) // (SSC) Receive Overrun
80587 +#define AT91C_SSC_ENDRX ( 0x1 << 6) // (SSC) End of Reception
80588 +#define AT91C_SSC_RXBUFF ( 0x1 << 7) // (SSC) Receive Buffer Full
80589 +#define AT91C_SSC_CP0 ( 0x1 << 8) // (SSC) Compare 0
80590 +#define AT91C_SSC_CP1 ( 0x1 << 9) // (SSC) Compare 1
80591 +#define AT91C_SSC_TXSYN ( 0x1 << 10) // (SSC) Transmit Sync
80592 +#define AT91C_SSC_RXSYN ( 0x1 << 11) // (SSC) Receive Sync
80593 +#define AT91C_SSC_TXENA ( 0x1 << 16) // (SSC) Transmit Enable
80594 +#define AT91C_SSC_RXENA ( 0x1 << 17) // (SSC) Receive Enable
80595 +// -------- SSC_IER : (SSC Offset: 0x44) SSC Interrupt Enable Register --------
80596 +// -------- SSC_IDR : (SSC Offset: 0x48) SSC Interrupt Disable Register --------
80597 +// -------- SSC_IMR : (SSC Offset: 0x4c) SSC Interrupt Mask Register --------
80599 +#endif
80600 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
80601 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/AT91RM9200_TC.h 2004-03-31 17:15:09.000000000 +0200
80602 @@ -0,0 +1,165 @@
80603 +// ----------------------------------------------------------------------------
80604 +// ATMEL Microcontroller Software Support - ROUSSET -
80605 +// ----------------------------------------------------------------------------
80606 +// The software is delivered "AS IS" without warranty or condition of any
80607 +// kind, either express, implied or statutory. This includes without
80608 +// limitation any warranty or condition with respect to merchantability or
80609 +// fitness for any particular purpose, or against the infringements of
80610 +// intellectual property rights of others.
80611 +// ----------------------------------------------------------------------------
80612 +// File Name : AT91RM9200.h
80613 +// Object : AT91RM9200 definitions
80614 +// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
80615 +//
80616 +// ----------------------------------------------------------------------------
80618 +#ifndef AT91RM9200_TC_H
80619 +#define AT91RM9200_TC_H
80621 +// *****************************************************************************
80622 +// SOFTWARE API DEFINITION FOR Timer Counter Channel Interface
80623 +// *****************************************************************************
80624 +#ifndef __ASSEMBLY__
80626 +typedef struct _AT91S_TC {
80627 + AT91_REG TC_CCR; // Channel Control Register
80628 + AT91_REG TC_CMR; // Channel Mode Register
80629 + AT91_REG Reserved0[2]; //
80630 + AT91_REG TC_CV; // Counter Value
80631 + AT91_REG TC_RA; // Register A
80632 + AT91_REG TC_RB; // Register B
80633 + AT91_REG TC_RC; // Register C
80634 + AT91_REG TC_SR; // Status Register
80635 + AT91_REG TC_IER; // Interrupt Enable Register
80636 + AT91_REG TC_IDR; // Interrupt Disable Register
80637 + AT91_REG TC_IMR; // Interrupt Mask Register
80638 +} AT91S_TC, *AT91PS_TC;
80640 +typedef struct _AT91S_TCB {
80641 + AT91S_TC TCB_TC0; // TC Channel 0
80642 + AT91_REG Reserved0[4]; //
80643 + AT91S_TC TCB_TC1; // TC Channel 1
80644 + AT91_REG Reserved1[4]; //
80645 + AT91S_TC TCB_TC2; // TC Channel 2
80646 + AT91_REG Reserved2[4]; //
80647 + AT91_REG TCB_BCR; // TC Block Control Register
80648 + AT91_REG TCB_BMR; // TC Block Mode Register
80649 +} AT91S_TCB, *AT91PS_TCB;
80651 +#endif
80653 +// -------- TC_CCR : (TC Offset: 0x0) TC Channel Control Register --------
80654 +#define AT91C_TC_CLKEN ( 0x1 << 0) // (TC) Counter Clock Enable Command
80655 +#define AT91C_TC_CLKDIS ( 0x1 << 1) // (TC) Counter Clock Disable Command
80656 +#define AT91C_TC_SWTRG ( 0x1 << 2) // (TC) Software Trigger Command
80657 +// -------- TC_CMR : (TC Offset: 0x4) TC Channel Mode Register: Capture Mode / Waveform Mode --------
80658 +#define AT91C_TC_TCCLKS ( 0x7 << 0) // (TC) Clock Selection
80659 +#define AT91C_TC_TIMER_DIV1_CLOCK ( 0x0 << 0) // (TC) MCK/2
80660 +#define AT91C_TC_TIMER_DIV2_CLOCK ( 0x1 << 0) // (TC) MCK/8
80661 +#define AT91C_TC_TIMER_DIV3_CLOCK ( 0x2 << 0) // (TC) MCK/32
80662 +#define AT91C_TC_TIMER_DIV4_CLOCK ( 0x3 << 0) // (TC) MCK/128
80663 +#define AT91C_TC_TIMER_DIV5_CLOCK ( 0x4 << 0) // (TC) MCK/256 = SLOW CLOCK
80664 +#define AT91C_TC_TIMER_XC0 ( 0x5 << 0) // (TC) XC0
80665 +#define AT91C_TC_TIMER_XC1 ( 0x6 << 0) // (TC) XC1
80666 +#define AT91C_TC_TIMER_XC2 ( 0x7 << 0) // (TC) XC2
80667 +#define AT91C_TC_CLKI ( 0x1 << 3) // (TC) Clock Invert
80668 +#define AT91C_TC_BURST ( 0x3 << 4) // (TC) Burst Signal Selection
80669 +#define AT91C_TC_CPCSTOP ( 0x1 << 6) // (TC) Counter Clock Stopped with RC Compare
80670 +#define AT91C_TC_CPCDIS ( 0x1 << 7) // (TC) Counter Clock Disable with RC Compare
80671 +#define AT91C_TC_EEVTEDG ( 0x3 << 8) // (TC) External Event Edge Selection
80672 +#define AT91C_TC_EEVTEDG_NONE ( 0x0 << 8) // (TC) Edge: None
80673 +#define AT91C_TC_EEVTEDG_RISING ( 0x1 << 8) // (TC) Edge: rising edge
80674 +#define AT91C_TC_EEVTEDG_FALLING ( 0x2 << 8) // (TC) Edge: falling edge
80675 +#define AT91C_TC_EEVTEDG_BOTH ( 0x3 << 8) // (TC) Edge: each edge
80676 +#define AT91C_TC_EEVT ( 0x3 << 10) // (TC) External Event Selection
80677 +#define AT91C_TC_EEVT_NONE ( 0x0 << 10) // (TC) Signal selected as external event: TIOB TIOB direction: input
80678 +#define AT91C_TC_EEVT_RISING ( 0x1 << 10) // (TC) Signal selected as external event: XC0 TIOB direction: output
80679 +#define AT91C_TC_EEVT_FALLING ( 0x2 << 10) // (TC) Signal selected as external event: XC1 TIOB direction: output
80680 +#define AT91C_TC_EEVT_BOTH ( 0x3 << 10) // (TC) Signal selected as external event: XC2 TIOB direction: output
80681 +#define AT91C_TC_ENETRG ( 0x1 << 12) // (TC) External Event Trigger enable
80682 +#define AT91C_TC_WAVESEL ( 0x3 << 13) // (TC) Waveform Selection
80683 +#define AT91C_TC_WAVESEL_UP ( 0x0 << 13) // (TC) UP mode without atomatic trigger on RC Compare
80684 +#define AT91C_TC_WAVESEL_UP_AUTO ( 0x1 << 13) // (TC) UP mode with automatic trigger on RC Compare
80685 +#define AT91C_TC_WAVESEL_UPDOWN ( 0x2 << 13) // (TC) UPDOWN mode without automatic trigger on RC Compare
80686 +#define AT91C_TC_WAVESEL_UPDOWN_AUTO ( 0x3 << 13) // (TC) UPDOWN mode with automatic trigger on RC Compare
80687 +#define AT91C_TC_CPCTRG ( 0x1 << 14) // (TC) RC Compare Trigger Enable
80688 +#define AT91C_TC_WAVE ( 0x1 << 15) // (TC)
80689 +#define AT91C_TC_ACPA ( 0x3 << 16) // (TC) RA Compare Effect on TIOA
80690 +#define AT91C_TC_ACPA_NONE ( 0x0 << 16) // (TC) Effect: none
80691 +#define AT91C_TC_ACPA_SET ( 0x1 << 16) // (TC) Effect: set
80692 +#define AT91C_TC_ACPA_CLEAR ( 0x2 << 16) // (TC) Effect: clear
80693 +#define AT91C_TC_ACPA_TOGGLE ( 0x3 << 16) // (TC) Effect: toggle
80694 +#define AT91C_TC_ACPC ( 0x3 << 18) // (TC) RC Compare Effect on TIOA
80695 +#define AT91C_TC_ACPC_NONE ( 0x0 << 18) // (TC) Effect: none
80696 +#define AT91C_TC_ACPC_SET ( 0x1 << 18) // (TC) Effect: set
80697 +#define AT91C_TC_ACPC_CLEAR ( 0x2 << 18) // (TC) Effect: clear
80698 +#define AT91C_TC_ACPC_TOGGLE ( 0x3 << 18) // (TC) Effect: toggle
80699 +#define AT91C_TC_AEEVT ( 0x3 << 20) // (TC) External Event Effect on TIOA
80700 +#define AT91C_TC_AEEVT_NONE ( 0x0 << 20) // (TC) Effect: none
80701 +#define AT91C_TC_AEEVT_SET ( 0x1 << 20) // (TC) Effect: set
80702 +#define AT91C_TC_AEEVT_CLEAR ( 0x2 << 20) // (TC) Effect: clear
80703 +#define AT91C_TC_AEEVT_TOGGLE ( 0x3 << 20) // (TC) Effect: toggle
80704 +#define AT91C_TC_ASWTRG ( 0x3 << 22) // (TC) Software Trigger Effect on TIOA
80705 +#define AT91C_TC_ASWTRG_NONE ( 0x0 << 22) // (TC) Effect: none
80706 +#define AT91C_TC_ASWTRG_SET ( 0x1 << 22) // (TC) Effect: set
80707 +#define AT91C_TC_ASWTRG_CLEAR ( 0x2 << 22) // (TC) Effect: clear
80708 +#define AT91C_TC_ASWTRG_TOGGLE ( 0x3 << 22) // (TC) Effect: toggle
80709 +#define AT91C_TC_BCPB ( 0x3 << 24) // (TC) RB Compare Effect on TIOB
80710 +#define AT91C_TC_BCPB_NONE ( 0x0 << 24) // (TC) Effect: none
80711 +#define AT91C_TC_BCPB_SET ( 0x1 << 24) // (TC) Effect: set
80712 +#define AT91C_TC_BCPB_CLEAR ( 0x2 << 24) // (TC) Effect: clear
80713 +#define AT91C_TC_BCPB_TOGGLE ( 0x3 << 24) // (TC) Effect: toggle
80714 +#define AT91C_TC_BCPC ( 0x3 << 26) // (TC) RC Compare Effect on TIOB
80715 +#define AT91C_TC_BCPC_NONE ( 0x0 << 26) // (TC) Effect: none
80716 +#define AT91C_TC_BCPC_SET ( 0x1 << 26) // (TC) Effect: set
80717 +#define AT91C_TC_BCPC_CLEAR ( 0x2 << 26) // (TC) Effect: clear
80718 +#define AT91C_TC_BCPC_TOGGLE ( 0x3 << 26) // (TC) Effect: toggle
80719 +#define AT91C_TC_BEEVT ( 0x3 << 28) // (TC) External Event Effect on TIOB
80720 +#define AT91C_TC_BEEVT_NONE ( 0x0 << 28) // (TC) Effect: none
80721 +#define AT91C_TC_BEEVT_SET ( 0x1 << 28) // (TC) Effect: set
80722 +#define AT91C_TC_BEEVT_CLEAR ( 0x2 << 28) // (TC) Effect: clear
80723 +#define AT91C_TC_BEEVT_TOGGLE ( 0x3 << 28) // (TC) Effect: toggle
80724 +#define AT91C_TC_BSWTRG ( 0x3 << 30) // (TC) Software Trigger Effect on TIOB
80725 +#define AT91C_TC_BSWTRG_NONE ( 0x0 << 30) // (TC) Effect: none
80726 +#define AT91C_TC_BSWTRG_SET ( 0x1 << 30) // (TC) Effect: set
80727 +#define AT91C_TC_BSWTRG_CLEAR ( 0x2 << 30) // (TC) Effect: clear
80728 +#define AT91C_TC_BSWTRG_TOGGLE ( 0x3 << 30) // (TC) Effect: toggle
80729 +// -------- TC_SR : (TC Offset: 0x20) TC Channel Status Register --------
80730 +#define AT91C_TC_COVFS ( 0x1 << 0) // (TC) Counter Overflow
80731 +#define AT91C_TC_LOVRS ( 0x1 << 1) // (TC) Load Overrun
80732 +#define AT91C_TC_CPAS ( 0x1 << 2) // (TC) RA Compare
80733 +#define AT91C_TC_CPBS ( 0x1 << 3) // (TC) RB Compare
80734 +#define AT91C_TC_CPCS ( 0x1 << 4) // (TC) RC Compare
80735 +#define AT91C_TC_LDRAS ( 0x1 << 5) // (TC) RA Loading
80736 +#define AT91C_TC_LDRBS ( 0x1 << 6) // (TC) RB Loading
80737 +#define AT91C_TC_ETRCS ( 0x1 << 7) // (TC) External Trigger
80738 +#define AT91C_TC_ETRGS ( 0x1 << 16) // (TC) Clock Enabling
80739 +#define AT91C_TC_MTIOA ( 0x1 << 17) // (TC) TIOA Mirror
80740 +#define AT91C_TC_MTIOB ( 0x1 << 18) // (TC) TIOA Mirror
80741 +// -------- TC_IER : (TC Offset: 0x24) TC Channel Interrupt Enable Register --------
80742 +// -------- TC_IDR : (TC Offset: 0x28) TC Channel Interrupt Disable Register --------
80743 +// -------- TC_IMR : (TC Offset: 0x2c) TC Channel Interrupt Mask Register --------
80745 +// *****************************************************************************
80746 +// SOFTWARE API DEFINITION FOR Timer Counter Interface
80747 +// *****************************************************************************
80748 +// -------- TCB_BCR : (TCB Offset: 0xc0) TC Block Control Register --------
80749 +#define AT91C_TCB_SYNC ( 0x1 << 0) // (TCB) Synchro Command
80750 +// -------- TCB_BMR : (TCB Offset: 0xc4) TC Block Mode Register --------
80751 +#define AT91C_TCB_TC0XC0S ( 0x1 << 0) // (TCB) External Clock Signal 0 Selection
80752 +#define AT91C_TCB_TC0XC0S_TCLK0 ( 0x0) // (TCB) TCLK0 connected to XC0
80753 +#define AT91C_TCB_TC0XC0S_NONE ( 0x1) // (TCB) None signal connected to XC0
80754 +#define AT91C_TCB_TC0XC0S_TIOA1 ( 0x2) // (TCB) TIOA1 connected to XC0
80755 +#define AT91C_TCB_TC0XC0S_TIOA2 ( 0x3) // (TCB) TIOA2 connected to XC0
80756 +#define AT91C_TCB_TC1XC1S ( 0x1 << 2) // (TCB) External Clock Signal 1 Selection
80757 +#define AT91C_TCB_TC1XC1S_TCLK1 ( 0x0 << 2) // (TCB) TCLK1 connected to XC1
80758 +#define AT91C_TCB_TC1XC1S_NONE ( 0x1 << 2) // (TCB) None signal connected to XC1
80759 +#define AT91C_TCB_TC1XC1S_TIOA0 ( 0x2 << 2) // (TCB) TIOA0 connected to XC1
80760 +#define AT91C_TCB_TC1XC1S_TIOA2 ( 0x3 << 2) // (TCB) TIOA2 connected to XC1
80761 +#define AT91C_TCB_TC2XC2S ( 0x1 << 4) // (TCB) External Clock Signal 2 Selection
80762 +#define AT91C_TCB_TC2XC2S_TCLK2 ( 0x0 << 4) // (TCB) TCLK2 connected to XC2
80763 +#define AT91C_TCB_TC2XC2S_NONE ( 0x1 << 4) // (TCB) None signal connected to XC2
80764 +#define AT91C_TCB_TC2XC2S_TIOA0 ( 0x2 << 4) // (TCB) TIOA0 connected to XC2
80765 +#define AT91C_TCB_TC2XC2S_TIOA2 ( 0x3 << 4) // (TCB) TIOA2 connected to XC2
80767 +#endif
80768 --- linux-2.4.25/include/asm-arm/arch-at91rm9200/at91rm9200dk.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
80769 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/at91rm9200dk.h 2004-03-31 17:15:09.000000000 +0200
80770 @@ -68,6 +68,7 @@
80771 #define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
80772 #define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
80774 +#define AT91C_CONSOLE_DEFAULT_BAUDRATE 115200 /* default serial console baud-rate */
80777 * Serial port configuration.
80778 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
80779 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/csb337.h 2004-03-31 17:15:09.000000000 +0200
80780 @@ -0,0 +1,82 @@
80782 + * linux/include/asm-arm/arch-at91rm9200/csb337.h
80784 + * Copyright (c) 2003 Christopher Bahns & David Knickerbocker
80785 + * Polaroid Corporation
80787 + * This program is free software; you can redistribute it and/or modify
80788 + * it under the terms of the GNU General Public License as published by
80789 + * the Free Software Foundation; either version 2 of the License, or
80790 + * (at your option) any later version.
80792 + */
80794 +#ifndef __ASM_ARCH_HARDWARE_CSB337_H
80795 +#define __ASM_ARCH_HARDWARE_CSB337_H
80798 +/* AT91RM92000 clocks on CSB337 */
80799 +#define AT91C_MAIN_CLOCK 184320000
80800 +#define AT91C_MASTER_CLOCK 46080000 /* peripheral clock (AT91C_MAIN_CLOCK / 4) */
80801 +#define AT91C_SLOW_CLOCK 32768 /* slow clock */
80804 +/* FLASH */
80805 +#define AT91_FLASH_BASE 0x10000000 // NCS0: Flash physical base address
80807 +/* SDRAM */
80808 +#define AT91_SDRAM_BASE 0x20000000 // NCS1: SDRAM physical base address
80810 +/* SmartMedia */
80811 +#define AT91_SMARTMEDIA_BASE 0x40000000 // NCS3: Smartmedia physical base address
80813 +/* Multi-Master Memory controller */
80814 +#define AT91_UHP_BASE 0x00300000 // USB Host controller
80817 +/* Peripheral interrupt configuration */
80818 +#define AT91_SMR_FIQ (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (FIQ)
80819 +#define AT91_SMR_SYS (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // System Peripheral
80820 +#define AT91_SMR_PIOA (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller A
80821 +#define AT91_SMR_PIOB (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller B
80822 +#define AT91_SMR_PIOC (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller C
80823 +#define AT91_SMR_PIOD (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller D
80824 +#define AT91_SMR_US0 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 0
80825 +#define AT91_SMR_US1 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 1
80826 +#define AT91_SMR_US2 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 2
80827 +#define AT91_SMR_US3 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 3
80828 +#define AT91_SMR_MCI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Multimedia Card Interface
80829 +#define AT91_SMR_UDP (AT91C_AIC_PRIOR_4 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Device Port
80830 +#define AT91_SMR_TWI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Two-Wire Interface
80831 +#define AT91_SMR_SPI (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Peripheral Interface
80832 +#define AT91_SMR_SSC0 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 0
80833 +#define AT91_SMR_SSC1 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 1
80834 +#define AT91_SMR_SSC2 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 2
80835 +#define AT91_SMR_TC0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 0
80836 +#define AT91_SMR_TC1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 1
80837 +#define AT91_SMR_TC2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 2
80838 +#define AT91_SMR_TC3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 3
80839 +#define AT91_SMR_TC4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 4
80840 +#define AT91_SMR_TC5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 5
80841 +#define AT91_SMR_UHP (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Host port
80842 +#define AT91_SMR_EMAC (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Ethernet MAC
80843 +#define AT91_SMR_IRQ0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ0)
80844 +#define AT91_SMR_IRQ1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ1)
80845 +#define AT91_SMR_IRQ2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ2)
80846 +#define AT91_SMR_IRQ3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ3)
80847 +#define AT91_SMR_IRQ4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ4)
80848 +#define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
80849 +#define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
80852 +#define AT91C_CONSOLE_DEFAULT_BAUDRATE 38400
80855 + * Serial port configuration.
80856 + * 0 .. 3 = USART0 .. USART3
80857 + * 4 = DBGU
80858 + */
80859 +#define AT91C_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
80860 +#define AT91C_CONSOLE 0 /* ttyS0 */
80862 +#endif
80863 --- linux-2.4.25/include/asm-arm/arch-at91rm9200/hardware.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
80864 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/hardware.h 2004-03-31 17:15:09.000000000 +0200
80865 @@ -82,5 +82,8 @@
80866 #include <asm/arch/at91rm9200dk.h>
80867 #endif
80869 +#ifdef CONFIG_MACH_CSB337
80870 +#include <asm/arch/csb337.h>
80871 +#endif
80873 #endif
80874 --- linux-2.4.25/include/asm-arm/arch-at91rm9200/pio.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
80875 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/pio.h 2004-03-31 17:15:09.000000000 +0200
80876 @@ -66,6 +66,18 @@
80880 + * Configure interrupt from Ethernet PHY.
80881 + */
80882 +static inline void AT91_CfgPIO_EMAC_PHY(void) {
80883 + AT91_SYS->PMC_PCER = 1 << AT91C_ID_PIOC; /* enable peripheral clock */
80884 +#ifdef CONFIG_MACH_CSB337
80885 + AT91_SYS->PIOC_ODR = AT91C_PIO_PC2;
80886 +#else
80887 + AT91_SYS->PIOC_ODR = AT91C_PIO_PC4;
80888 +#endif
80892 * Enable the Two-Wire interface.
80894 static inline void AT91_CfgPIO_TWI(void) {
80895 --- linux-2.4.25/include/asm-arm/arch-at91rm9200/time.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
80896 +++ linux-2.4.25/include/asm-arm/arch-at91rm9200/time.h 2004-03-31 17:15:09.000000000 +0200
80897 @@ -27,6 +27,21 @@
80898 extern unsigned long (*gettimeoffset)(void);
80901 + * The ST_CRTR is updated asynchronously to the master clock. It is therefore
80902 + * necessary to read it twice (with the same value) to ensure accuracy.
80903 + */
80904 +static inline unsigned long read_CRTR(void) {
80905 + unsigned long x1, x2;
80907 + do {
80908 + x1 = AT91_SYS->ST_CRTR;
80909 + x2 = AT91_SYS->ST_CRTR;
80910 + } while (x1 != x2);
80912 + return x1;
80916 * Returns number of microseconds since last timer interrupt. Note that interrupts
80917 * will have been disabled by do_gettimeofday()
80918 * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
80919 @@ -36,7 +51,7 @@
80921 unsigned long elapsed;
80923 - elapsed = (AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
80924 + elapsed = (read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
80926 return (unsigned long)(elapsed * tick) / LATCH;
80928 @@ -52,7 +67,7 @@
80930 AT91_SYS->ST_RTAR = (AT91_SYS->ST_RTAR + LATCH) & AT91C_ST_ALMV;
80932 - } while (((AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
80933 + } while (((read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
80935 do_profile(regs);
80937 --- linux-2.4.25/include/asm-arm/arch-clps711x/system.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
80938 +++ linux-2.4.25/include/asm-arm/arch-clps711x/system.h 2004-03-31 17:15:09.000000000 +0200
80939 @@ -28,8 +28,8 @@
80941 clps_writel(1, HALT);
80942 __asm__ __volatile__(
80943 - "mov r0, r0
80944 - mov r0, r0");
80945 + "mov r0, r0\n\t"
80946 + "mov r0, r0");
80949 static inline void arch_reset(char mode)
80950 --- linux-2.4.25/include/asm-arm/arch-integrator/uncompress.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
80951 +++ linux-2.4.25/include/asm-arm/arch-integrator/uncompress.h 2004-03-31 17:15:09.000000000 +0200
80952 @@ -18,6 +18,8 @@
80953 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
80956 +#include <asm/hardware/serial_amba.h>
80958 #define AMBA_UART_DR (*(volatile unsigned char *)0x16000000)
80959 #define AMBA_UART_LCRH (*(volatile unsigned char *)0x16000008)
80960 #define AMBA_UART_LCRM (*(volatile unsigned char *)0x1600000c)
80961 @@ -30,21 +32,25 @@
80963 static void puts(const char *s)
80965 + /* Do nothing if the UART is not enabled. */
80966 + if (!(AMBA_UART_CR & AMBA_UARTCR_UARTEN))
80967 + return;
80969 while (*s) {
80970 - while (AMBA_UART_FR & (1 << 5))
80971 + while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
80972 barrier();
80974 AMBA_UART_DR = *s;
80976 if (*s == '\n') {
80977 - while (AMBA_UART_FR & (1 << 5))
80978 + while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
80979 barrier();
80981 AMBA_UART_DR = '\r';
80983 s++;
80985 - while (AMBA_UART_FR & (1 << 3));
80986 + while (AMBA_UART_FR & AMBA_UARTFR_BUSY);
80990 --- linux-2.4.25/include/asm-arm/arch-riscstation/system.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
80991 +++ linux-2.4.25/include/asm-arm/arch-riscstation/system.h 2004-03-31 17:15:09.000000000 +0200
80992 @@ -1,5 +1,5 @@
80994 - * linux/include/asm-arm/arch-rpc/system.h
80995 + * linux/include/asm-arm/arch-riscstation/system.h
80997 * Copyright (C) 1996-1999 Russell King.
80999 @@ -18,7 +18,7 @@
81001 static inline void arch_reset(char mode)
81003 - iomd_writeb(0, IOMD_ROMCR0);
81004 + iomd_writeb(0x40, IOMD_ROMCR0);
81007 * Jump into the ROM
81008 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
81009 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-clock.h 2004-03-31 17:15:09.000000000 +0200
81010 @@ -0,0 +1,76 @@
81011 +/* linux/include/asm-arm/arch-s3c2410/S3C2410-clock.h
81013 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
81014 + * http://www.simtec.co.uk/products/SWLINUX/
81016 + * This program is free software; you can redistribute it and/or modify
81017 + * it under the terms of the GNU General Public License version 2 as
81018 + * published by the Free Software Foundation.
81020 + * S3C2410 clock register definitions
81022 + * Changelog:
81023 + * 19-06-2003 BJD Created file
81024 + */
81026 +#ifndef ASMARM_ARCH_S3C2410_CLOCK_H
81027 +#define ASMARM_ARCH_S3C2410_CLOCK_H
81029 +#define S3C2410_CLKREG(x) ((x) + S3C2410_VA_CLKPWR)
81031 +#define S3C2410_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s)))
81033 +#define S3C2410_LOCKTIME S3C2410_CLKREG(0x00)
81034 +#define S3C2410_MPLLCON S3C2410_CLKREG(0x04)
81035 +#define S3C2410_UPLLCON S3C2410_CLKREG(0x08)
81036 +#define S3C2410_CLKCON S3C2410_CLKREG(0x0C)
81037 +#define S3C2410_CLKSLOW S3C2410_CLKREG(0x10)
81038 +#define S3C2410_CLKDIVN S3C2410_CLKREG(0x14)
81040 +#define S3C2410_PLLCON_MDIVSHIFT 12
81041 +#define S3C2410_PLLCON_PDIVSHIFT 4
81042 +#define S3C2410_PLLCON_SDIVSHIFT 0
81043 +#define S3C2410_PLLCON_MDIVMASK ((1<<(1+(19-12)))-1)
81044 +#define S3C2410_PLLCON_PDIVMASK ((1<<5)-1)
81045 +#define S3C2410_PLLCON_SDIVMASK 3
81047 +/* DCLKCON register addresses in gpio.h */
81049 +#define S3C2410_DCLKCON_DCLK0EN (1<<0)
81050 +#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1)
81051 +#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1)
81052 +#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4)
81053 +#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8)
81055 +#define S3C2410_DCLKCON_DCLK1EN (1<<16)
81056 +#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17)
81057 +#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17)
81058 +#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20)
81060 +#define S3C2410_CLKDIVN_PDIVN (1<<0)
81061 +#define S3C2410_CLKDIVN_HDIVN (1<<1)
81063 +static inline unsigned int
81064 +s3c2410_get_pll(int pllval, int baseclk)
81066 + int mdiv, pdiv, sdiv;
81068 + mdiv = pllval >> S3C2410_PLLCON_MDIVSHIFT;
81069 + pdiv = pllval >> S3C2410_PLLCON_PDIVSHIFT;
81070 + sdiv = pllval >> S3C2410_PLLCON_SDIVSHIFT;
81072 + mdiv &= S3C2410_PLLCON_MDIVMASK;
81073 + pdiv &= S3C2410_PLLCON_PDIVMASK;
81074 + sdiv &= S3C2410_PLLCON_SDIVMASK;
81076 + return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
81079 +#endif /* ASMARM_ARCH_S3C2410_CLOCK_H */
81087 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
81088 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-gpio.h 2004-03-31 17:15:09.000000000 +0200
81089 @@ -0,0 +1,602 @@
81090 +/* linux/include/asm-arm/arch-s3c2410/S3C2410-gpio.h
81092 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
81093 + * http://www.simtec.co.uk/products/SWLINUX/
81095 + * This program is free software; you can redistribute it and/or modify
81096 + * it under the terms of the GNU General Public License version 2 as
81097 + * published by the Free Software Foundation.
81099 + * S3C2410 GPIO register definitions
81101 + * Changelog:
81102 + * 19-06-2003 BJD Created file
81103 + * 23-06-2003 BJD Updated GSTATUS registers
81104 + */
81106 +#ifndef ASMARM_ARCH_S3C2410_GPIO_H
81107 +#define ASMARM_ARCH_S3C2410_GPIO_H
81109 +/* configure GPIO ports A..G */
81111 +#define S3C2410_GPIOREG(x) ((x) + S3C2410_VA_GPIO)
81113 +/* port A - 22bits, zero in bit X makes pin X output
81114 + * 1 makes port special function, this is default
81116 +#define S3C2410_GPACON S3C2410_GPIOREG(0x00)
81117 +#define S3C2410_GPADAT S3C2410_GPIOREG(0x04)
81119 +/* 0x08 and 0x0c are reserved */
81121 +/* GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
81122 + * 00 = input, 01 = output, 10=special function, 11=reserved
81123 + * bit 0,1 = pin 0, 2,3= pin 1...
81125 + * CPBUP = pull up resistor control, 1=disabled, 0=enabled
81128 +#define S3C2410_GPBCON S3C2410_GPIOREG(0x10)
81129 +#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)
81130 +#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)
81132 +/* no i/o pin in port b can have value 3! */
81134 +#define S3C2410_GPB0_INP (0x00 << 0)
81135 +#define S3C2410_GPB0_OUTP (0x01 << 0)
81136 +#define S3C2410_GPB0_TOUT0 (0x02 << 0)
81138 +#define S3C2410_GPB1_INP (0x00 << 2)
81139 +#define S3C2410_GPB1_OUTP (0x01 << 2)
81140 +#define S3C2410_GPB1_TOUT1 (0x02 << 2)
81142 +#define S3C2410_GPB2_INP (0x00 << 4)
81143 +#define S3C2410_GPB2_OUTP (0x01 << 4)
81144 +#define S3C2410_GPB2_TOUT2 (0x02 << 4)
81146 +#define S3C2410_GPB3_INP (0x00 << 6)
81147 +#define S3C2410_GPB3_OUTP (0x01 << 6)
81148 +#define S3C2410_GPB3_TOUT3 (0x02 << 6)
81150 +#define S3C2410_GPB4_INP (0x00 << 8)
81151 +#define S3C2410_GPB4_OUTP (0x01 << 8)
81152 +#define S3C2410_GPB4_TCLK0 (0x02 << 8)
81153 +#define S3C2410_GPB4_MASK (0x03 << 8)
81155 +#define S3C2410_GPB5_INP (0x00 << 10)
81156 +#define S3C2410_GPB5_OUTP (0x01 << 10)
81157 +#define S3C2410_GPB5_nXBACK (0x02 << 10)
81159 +#define S3C2410_GPB6_INP (0x00 << 12)
81160 +#define S3C2410_GPB6_OUTP (0x01 << 12)
81161 +#define S3C2410_GPB6_nXBREQ (0x02 << 12)
81163 +#define S3C2410_GPB7_INP (0x00 << 14)
81164 +#define S3C2410_GPB7_OUTP (0x01 << 14)
81165 +#define S3C2410_GPB7_nXDACK1 (0x02 << 14)
81167 +#define S3C2410_GPB8_INP (0x00 << 16)
81168 +#define S3C2410_GPB8_OUTP (0x01 << 16)
81169 +#define S3C2410_GPB8_nXDREQ1 (0x02 << 16)
81171 +#define S3C2410_GPB9_INP (0x00 << 18)
81172 +#define S3C2410_GPB9_OUTP (0x01 << 18)
81173 +#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
81175 +#define S3C2410_GPB10_INP (0x00 << 18)
81176 +#define S3C2410_GPB10_OUTP (0x01 << 18)
81177 +#define S3C2410_GPB10_nXDRE0 (0x02 << 18)
81179 +/* Port C consits of 16 GPIO/Special function
81181 + * almost identical setup to port b, but the special functions are mostly
81182 + * to do with the video system's sync/etc.
81185 +#define S3C2410_GPCCON S3C2410_GPIOREG(0x20)
81186 +#define S3C2410_GPCDAT S3C2410_GPIOREG(0x24)
81187 +#define S3C2410_GPCUP S3C2410_GPIOREG(0x28)
81189 +#define S3C2410_GPC0_INP (0x00 << 0)
81190 +#define S3C2410_GPC0_OUTP (0x01 << 0)
81191 +#define S3C2410_GPC0_LEND (0x02 << 0)
81193 +#define S3C2410_GPC1_INP (0x00 << 2)
81194 +#define S3C2410_GPC1_OUTP (0x01 << 2)
81195 +#define S3C2410_GPC1_VCLK (0x02 << 2)
81197 +#define S3C2410_GPC2_INP (0x00 << 4)
81198 +#define S3C2410_GPC2_OUTP (0x01 << 4)
81199 +#define S3C2410_GPC2_VLINE (0x02 << 4)
81201 +#define S3C2410_GPC3_INP (0x00 << 6)
81202 +#define S3C2410_GPC3_OUTP (0x01 << 6)
81203 +#define S3C2410_GPC3_VFRAME (0x02 << 6)
81205 +#define S3C2410_GPC4_INP (0x00 << 8)
81206 +#define S3C2410_GPC4_OUTP (0x01 << 8)
81207 +#define S3C2410_GPC4_VM (0x02 << 8)
81209 +#define S3C2410_GPC5_INP (0x00 << 10)
81210 +#define S3C2410_GPC5_OUTP (0x01 << 10)
81211 +#define S3C2410_GPC5_LCDVF0 (0x02 << 10)
81213 +#define S3C2410_GPC6_INP (0x00 << 12)
81214 +#define S3C2410_GPC6_OUTP (0x01 << 12)
81215 +#define S3C2410_GPC6_LCDVF1 (0x02 << 12)
81217 +#define S3C2410_GPC7_INP (0x00 << 14)
81218 +#define S3C2410_GPC7_OUTP (0x01 << 14)
81219 +#define S3C2410_GPC7_LCDVF2 (0x02 << 14)
81221 +#define S3C2410_GPC8_INP (0x00 << 16)
81222 +#define S3C2410_GPC8_OUTP (0x01 << 16)
81223 +#define S3C2410_GPC8_VD0 (0x02 << 16)
81225 +#define S3C2410_GPC9_INP (0x00 << 18)
81226 +#define S3C2410_GPC9_OUTP (0x01 << 18)
81227 +#define S3C2410_GPC9_VD1 (0x02 << 18)
81229 +#define S3C2410_GPC10_INP (0x00 << 20)
81230 +#define S3C2410_GPC10_OUTP (0x01 << 20)
81231 +#define S3C2410_GPC10_VD2 (0x02 << 20)
81233 +#define S3C2410_GPC11_INP (0x00 << 22)
81234 +#define S3C2410_GPC11_OUTP (0x01 << 22)
81235 +#define S3C2410_GPC11_VD3 (0x02 << 22)
81237 +#define S3C2410_GPC12_INP (0x00 << 24)
81238 +#define S3C2410_GPC12_OUTP (0x01 << 24)
81239 +#define S3C2410_GPC12_VD4 (0x02 << 24)
81241 +#define S3C2410_GPC13_INP (0x00 << 26)
81242 +#define S3C2410_GPC13_OUTP (0x01 << 26)
81243 +#define S3C2410_GPC13_VD5 (0x02 << 26)
81245 +#define S3C2410_GPC14_INP (0x00 << 28)
81246 +#define S3C2410_GPC14_OUTP (0x01 << 28)
81247 +#define S3C2410_GPC14_VD6 (0x02 << 28)
81249 +#define S3C2410_GPC15_INP (0x00 << 30)
81250 +#define S3C2410_GPC15_OUTP (0x01 << 30)
81251 +#define S3C2410_GPC15_VD7 (0x02 << 30)
81253 +/* Port D consists of 16 GPIO/Special function
81255 + * almost identical setup to port b, but the special functions are mostly
81256 + * to do with the video system's data.
81259 +#define S3C2410_GPDCON S3C2410_GPIOREG(0x30)
81260 +#define S3C2410_GPDDAT S3C2410_GPIOREG(0x34)
81261 +#define S3C2410_GPDUP S3C2410_GPIOREG(0x38)
81263 +#define S3C2410_GPD0_INP (0x00 << 0)
81264 +#define S3C2410_GPD0_OUTP (0x01 << 0)
81265 +#define S3C2410_GPD0_VD8 (0x02 << 0)
81267 +#define S3C2410_GPD1_INP (0x00 << 2)
81268 +#define S3C2410_GPD1_OUTP (0x01 << 2)
81269 +#define S3C2410_GPD1_VD9 (0x02 << 2)
81271 +#define S3C2410_GPD2_INP (0x00 << 4)
81272 +#define S3C2410_GPD2_OUTP (0x01 << 4)
81273 +#define S3C2410_GPD2_VD10 (0x02 << 4)
81275 +#define S3C2410_GPD3_INP (0x00 << 6)
81276 +#define S3C2410_GPD3_OUTP (0x01 << 6)
81277 +#define S3C2410_GPD3_VD11 (0x02 << 6)
81279 +#define S3C2410_GPD4_INP (0x00 << 8)
81280 +#define S3C2410_GPD4_OUTP (0x01 << 8)
81281 +#define S3C2410_GPD4_VD12 (0x02 << 8)
81283 +#define S3C2410_GPD5_INP (0x00 << 10)
81284 +#define S3C2410_GPD5_OUTP (0x01 << 10)
81285 +#define S3C2410_GPD5_VD13 (0x02 << 10)
81287 +#define S3C2410_GPD6_INP (0x00 << 12)
81288 +#define S3C2410_GPD6_OUTP (0x01 << 12)
81289 +#define S3C2410_GPD6_VD14 (0x02 << 12)
81291 +#define S3C2410_GPD7_INP (0x00 << 14)
81292 +#define S3C2410_GPD7_OUTP (0x01 << 14)
81293 +#define S3C2410_GPD7_VD15 (0x02 << 14)
81295 +#define S3C2410_GPD8_INP (0x00 << 16)
81296 +#define S3C2410_GPD8_OUTP (0x01 << 16)
81297 +#define S3C2410_GPD8_VD16 (0x02 << 16)
81299 +#define S3C2410_GPD9_INP (0x00 << 18)
81300 +#define S3C2410_GPD9_OUTP (0x01 << 18)
81301 +#define S3C2410_GPD9_VD17 (0x02 << 18)
81303 +#define S3C2410_GPD10_INP (0x00 << 20)
81304 +#define S3C2410_GPD10_OUTP (0x01 << 20)
81305 +#define S3C2410_GPD10_VD18 (0x02 << 20)
81307 +#define S3C2410_GPD11_INP (0x00 << 22)
81308 +#define S3C2410_GPD11_OUTP (0x01 << 22)
81309 +#define S3C2410_GPD11_VD19 (0x02 << 22)
81311 +#define S3C2410_GPD12_INP (0x00 << 24)
81312 +#define S3C2410_GPD12_OUTP (0x01 << 24)
81313 +#define S3C2410_GPD12_VD20 (0x02 << 24)
81315 +#define S3C2410_GPD13_INP (0x00 << 26)
81316 +#define S3C2410_GPD13_OUTP (0x01 << 26)
81317 +#define S3C2410_GPD13_VD21 (0x02 << 26)
81319 +#define S3C2410_GPD14_INP (0x00 << 28)
81320 +#define S3C2410_GPD14_OUTP (0x01 << 28)
81321 +#define S3C2410_GPD14_VD22 (0x02 << 28)
81323 +#define S3C2410_GPD15_INP (0x00 << 30)
81324 +#define S3C2410_GPD15_OUTP (0x01 << 30)
81325 +#define S3C2410_GPD15_VD23 (0x02 << 30)
81327 +/* Port E consists of 16 GPIO/Special function
81329 + * again, the same as port B, but dealing with I2S, SDI, and
81330 + * more miscellaneous functions
81333 +#define S3C2410_GPECON S3C2410_GPIOREG(0x40)
81334 +#define S3C2410_GPEDAT S3C2410_GPIOREG(0x44)
81335 +#define S3C2410_GPEUP S3C2410_GPIOREG(0x48)
81337 +#define S3C2410_GPE0_INP (0x00 << 0)
81338 +#define S3C2410_GPE0_OUTP (0x01 << 0)
81339 +#define S3C2410_GPE0_I2SLRCK (0x02 << 0)
81340 +#define S3C2410_GPE0_MASK (0x03 << 0)
81342 +#define S3C2410_GPE1_INP (0x00 << 2)
81343 +#define S3C2410_GPE1_OUTP (0x01 << 2)
81344 +#define S3C2410_GPE1_I2SSCLK (0x02 << 2)
81345 +#define S3C2410_GPE1_MASK (0x03 << 2)
81347 +#define S3C2410_GPE2_INP (0x00 << 4)
81348 +#define S3C2410_GPE2_OUTP (0x01 << 4)
81349 +#define S3C2410_GPE2_CDCLK (0x02 << 4)
81351 +#define S3C2410_GPE3_INP (0x00 << 6)
81352 +#define S3C2410_GPE3_OUTP (0x01 << 6)
81353 +#define S3C2410_GPE3_I2SSDI (0x02 << 6)
81354 +#define S3C2410_GPE3_MASK (0x03 << 6)
81356 +#define S3C2410_GPE4_INP (0x00 << 8)
81357 +#define S3C2410_GPE4_OUTP (0x01 << 8)
81358 +#define S3C2410_GPE4_I2SSDO (0x02 << 8)
81359 +#define S3C2410_GPE4_MASK (0x03 << 8)
81361 +#define S3C2410_GPE5_INP (0x00 << 10)
81362 +#define S3C2410_GPE5_OUTP (0x01 << 10)
81363 +#define S3C2410_GPE5_SDCLK (0x02 << 10)
81365 +#define S3C2410_GPE6_INP (0x00 << 12)
81366 +#define S3C2410_GPE6_OUTP (0x01 << 12)
81367 +#define S3C2410_GPE6_SDCLK (0x02 << 12)
81369 +#define S3C2410_GPE7_INP (0x00 << 14)
81370 +#define S3C2410_GPE7_OUTP (0x01 << 14)
81371 +#define S3C2410_GPE7_SDCMD (0x02 << 14)
81373 +#define S3C2410_GPE8_INP (0x00 << 16)
81374 +#define S3C2410_GPE8_OUTP (0x01 << 16)
81375 +#define S3C2410_GPE8_SDDAT1 (0x02 << 16)
81377 +#define S3C2410_GPE9_INP (0x00 << 18)
81378 +#define S3C2410_GPE9_OUTP (0x01 << 18)
81379 +#define S3C2410_GPE9_SDDAT2 (0x02 << 18)
81381 +#define S3C2410_GPE10_INP (0x00 << 20)
81382 +#define S3C2410_GPE10_OUTP (0x01 << 20)
81383 +#define S3C2410_GPE10_SDDAT3 (0x02 << 20)
81385 +#define S3C2410_GPE11_INP (0x00 << 22)
81386 +#define S3C2410_GPE11_OUTP (0x01 << 22)
81387 +#define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
81389 +#define S3C2410_GPE12_INP (0x00 << 24)
81390 +#define S3C2410_GPE12_OUTP (0x01 << 24)
81391 +#define S3C2410_GPE12_SPIMOSI0 (0x02 << 24)
81393 +#define S3C2410_GPE13_INP (0x00 << 26)
81394 +#define S3C2410_GPE13_OUTP (0x01 << 26)
81395 +#define S3C2410_GPE13_SPICLK0 (0x02 << 26)
81397 +#define S3C2410_GPE14_INP (0x00 << 28)
81398 +#define S3C2410_GPE14_OUTP (0x01 << 28)
81399 +#define S3C2410_GPE14_IICSCL (0x02 << 28)
81400 +#define S3C2410_GPE14_MASK (0x03 << 28)
81402 +#define S3C2410_GPE15_INP (0x00 << 30)
81403 +#define S3C2410_GPE15_OUTP (0x01 << 30)
81404 +#define S3C2410_GPE15_IICSDA (0x02 << 30)
81405 +#define S3C2410_GPE15_MASK (0x03 << 30)
81407 +#define S3C2410_GPE_PUPDIS(x) (1<<(x))
81409 +/* Port F consists of 8 GPIO/Special function
81411 + * GPIO / interrupt inputs
81413 + * GPFCON has 2 bits for each of the input pins on port F
81414 + * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 undefined
81416 + * pull up works like all other ports.
81419 +#define S3C2410_GPFCON S3C2410_GPIOREG(0x50)
81420 +#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)
81421 +#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)
81424 +#define S3C2410_GPF0_INP (0x00 << 0)
81425 +#define S3C2410_GPF0_OUTP (0x01 << 0)
81426 +#define S3C2410_GPF0_EINT0 (0x02 << 0)
81428 +#define S3C2410_GPF1_INP (0x00 << 2)
81429 +#define S3C2410_GPF1_OUTP (0x01 << 2)
81430 +#define S3C2410_GPF1_EINT1 (0x02 << 2)
81432 +#define S3C2410_GPF2_INP (0x00 << 4)
81433 +#define S3C2410_GPF2_OUTP (0x01 << 4)
81434 +#define S3C2410_GPF2_EINT2 (0x02 << 4)
81436 +#define S3C2410_GPF3_INP (0x00 << 6)
81437 +#define S3C2410_GPF3_OUTP (0x01 << 6)
81438 +#define S3C2410_GPF3_EINT3 (0x02 << 6)
81440 +#define S3C2410_GPF4_INP (0x00 << 8)
81441 +#define S3C2410_GPF4_OUTP (0x01 << 8)
81442 +#define S3C2410_GPF4_EINT4 (0x02 << 8)
81444 +#define S3C2410_GPF5_INP (0x00 << 10)
81445 +#define S3C2410_GPF5_OUTP (0x01 << 10)
81446 +#define S3C2410_GPF5_EINT5 (0x02 << 10)
81448 +#define S3C2410_GPF6_INP (0x00 << 12)
81449 +#define S3C2410_GPF6_OUTP (0x01 << 12)
81450 +#define S3C2410_GPF6_EINT6 (0x02 << 12)
81452 +#define S3C2410_GPF7_INP (0x00 << 14)
81453 +#define S3C2410_GPF7_OUTP (0x01 << 14)
81454 +#define S3C2410_GPF7_EINT7 (0x02 << 14)
81456 +/* Port G consists of 8 GPIO/IRQ/Special function
81458 + * GPGCON has 2 bits for each of the input pins on port F
81459 + * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
81461 + * pull up works like all other ports.
81464 +#define S3C2410_GPGCON S3C2410_GPIOREG(0x60)
81465 +#define S3C2410_GPGDAT S3C2410_GPIOREG(0x64)
81466 +#define S3C2410_GPGUP S3C2410_GPIOREG(0x68)
81468 +#define S3C2410_GPG0_INP (0x00 << 0)
81469 +#define S3C2410_GPG0_OUTP (0x01 << 0)
81470 +#define S3C2410_GPG0_EINT8 (0x02 << 0)
81472 +#define S3C2410_GPG1_INP (0x00 << 2)
81473 +#define S3C2410_GPG1_OUTP (0x01 << 2)
81474 +#define S3C2410_GPG1_EINT9 (0x02 << 2)
81476 +#define S3C2410_GPG2_INP (0x00 << 4)
81477 +#define S3C2410_GPG2_OUTP (0x01 << 4)
81478 +#define S3C2410_GPG2_EINT10 (0x02 << 4)
81480 +#define S3C2410_GPG3_INP (0x00 << 6)
81481 +#define S3C2410_GPG3_OUTP (0x01 << 6)
81482 +#define S3C2410_GPG3_EINT11 (0x02 << 6)
81484 +#define S3C2410_GPG4_INP (0x00 << 8)
81485 +#define S3C2410_GPG4_OUTP (0x01 << 8)
81486 +#define S3C2410_GPG4_EINT12 (0x02 << 8)
81487 +#define S3C2410_GPG4_LCDPWREN (0x03 << 8)
81489 +#define S3C2410_GPG5_INP (0x00 << 10)
81490 +#define S3C2410_GPG5_OUTP (0x01 << 10)
81491 +#define S3C2410_GPG5_EINT13 (0x02 << 10)
81492 +#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)
81494 +#define S3C2410_GPG6_INP (0x00 << 12)
81495 +#define S3C2410_GPG6_OUTP (0x01 << 12)
81496 +#define S3C2410_GPG6_EINT14 (0x02 << 12)
81497 +#define S3C2410_GPG6_SPIMOSI1 (0x03 << 12)
81499 +#define S3C2410_GPG7_INP (0x00 << 14)
81500 +#define S3C2410_GPG7_OUTP (0x01 << 14)
81501 +#define S3C2410_GPG7_EINT15 (0x02 << 14)
81502 +#define S3C2410_GPG7_SPICLK1 (0x03 << 14)
81504 +#define S3C2410_GPG8_INP (0x00 << 16)
81505 +#define S3C2410_GPG8_OUTP (0x01 << 16)
81506 +#define S3C2410_GPG8_EINT16 (0x02 << 16)
81508 +#define S3C2410_GPG9_INP (0x00 << 18)
81509 +#define S3C2410_GPG9_OUTP (0x01 << 18)
81510 +#define S3C2410_GPG9_EINT17 (0x02 << 18)
81512 +#define S3C2410_GPG10_INP (0x00 << 20)
81513 +#define S3C2410_GPG10_OUTP (0x01 << 20)
81514 +#define S3C2410_GPG10_EINT18 (0x02 << 20)
81516 +#define S3C2410_GPG11_INP (0x00 << 22)
81517 +#define S3C2410_GPG11_OUTP (0x01 << 22)
81518 +#define S3C2410_GPG11_EINT19 (0x02 << 22)
81519 +#define S3C2410_GPG11_TCLK1 (0x03 << 22)
81521 +#define S3C2410_GPG12_INP (0x00 << 24)
81522 +#define S3C2410_GPG12_OUTP (0x01 << 24)
81523 +#define S3C2410_GPG12_EINT18 (0x02 << 24)
81524 +#define S3C2410_GPG12_XMON (0x03 << 24)
81526 +#define S3C2410_GPG13_INP (0x00 << 26)
81527 +#define S3C2410_GPG13_OUTP (0x01 << 26)
81528 +#define S3C2410_GPG13_EINT18 (0x02 << 26)
81529 +#define S3C2410_GPG13_nXPON (0x03 << 26)
81531 +#define S3C2410_GPG14_INP (0x00 << 28)
81532 +#define S3C2410_GPG14_OUTP (0x01 << 28)
81533 +#define S3C2410_GPG14_EINT18 (0x02 << 28)
81534 +#define S3C2410_GPG14_YMON (0x03 << 28)
81536 +#define S3C2410_GPG15_INP (0x00 << 30)
81537 +#define S3C2410_GPG15_OUTP (0x01 << 30)
81538 +#define S3C2410_GPG15_EINT18 (0x02 << 30)
81539 +#define S3C2410_GPG15_nYPON (0x03 << 30)
81542 +#define S3C2410_GPG_PUPDIS(x) (1<<(x))
81544 +/* Port H consists of11 GPIO/serial/Misc pins
81546 + * GPGCON has 2 bits for each of the input pins on port F
81547 + * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
81549 + * pull up works like all other ports.
81552 +#define S3C2410_GPHCON S3C2410_GPIOREG(0x70)
81553 +#define S3C2410_GPHDAT S3C2410_GPIOREG(0x74)
81554 +#define S3C2410_GPHUP S3C2410_GPIOREG(0x78)
81556 +#define S3C2410_GPH0_INP (0x00 << 0)
81557 +#define S3C2410_GPH0_OUTP (0x01 << 0)
81558 +#define S3C2410_GPH0_nCTS0 (0x02 << 0)
81560 +#define S3C2410_GPH1_INP (0x00 << 2)
81561 +#define S3C2410_GPH1_OUTP (0x01 << 2)
81562 +#define S3C2410_GPH1_nRTS0 (0x02 << 2)
81564 +#define S3C2410_GPH2_INP (0x00 << 4)
81565 +#define S3C2410_GPH2_OUTP (0x01 << 4)
81566 +#define S3C2410_GPH2_TXD0 (0x02 << 4)
81568 +#define S3C2410_GPH3_INP (0x00 << 6)
81569 +#define S3C2410_GPH3_OUTP (0x01 << 6)
81570 +#define S3C2410_GPH3_RXD0 (0x02 << 6)
81572 +#define S3C2410_GPH4_INP (0x00 << 8)
81573 +#define S3C2410_GPH4_OUTP (0x01 << 8)
81574 +#define S3C2410_GPH4_TXD1 (0x02 << 8)
81576 +#define S3C2410_GPH5_INP (0x00 << 10)
81577 +#define S3C2410_GPH5_OUTP (0x01 << 10)
81578 +#define S3C2410_GPH5_RXD1 (0x02 << 10)
81580 +#define S3C2410_GPH6_INP (0x00 << 12)
81581 +#define S3C2410_GPH6_OUTP (0x01 << 12)
81582 +#define S3C2410_GPH6_TXD2 (0x02 << 12)
81583 +#define S3C2410_GPH6_nRTS1 (0x03 << 12)
81585 +#define S3C2410_GPH7_INP (0x00 << 14)
81586 +#define S3C2410_GPH7_OUTP (0x01 << 14)
81587 +#define S3C2410_GPH7_RXD2 (0x02 << 14)
81588 +#define S3C2410_GPH7_nCTS1 (0x03 << 14)
81590 +#define S3C2410_GPH8_INP (0x00 << 16)
81591 +#define S3C2410_GPH8_OUTP (0x01 << 16)
81592 +#define S3C2410_GPH8_UCLK (0x02 << 16)
81594 +#define S3C2410_GPH9_INP (0x00 << 18)
81595 +#define S3C2410_GPH9_OUTP (0x01 << 18)
81596 +#define S3C2410_GPH9_CLKOUT0 (0x02 << 18)
81598 +#define S3C2410_GPH10_INP (0x00 << 20)
81599 +#define S3C2410_GPH10_OUTP (0x01 << 20)
81600 +#define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
81602 +/* miscellaneous control */
81604 +#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
81605 +#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
81607 +/* see clock.h for dclk definitions */
81609 +/* pullup control on databus */
81610 +#define S3C2410_MISCCR_SPUCR_HEN (0)
81611 +#define S3C2410_MISCCR_SPUCR_HDIS (1<<0)
81612 +#define S3C2410_MISCCR_SPUCR_LEN (0)
81613 +#define S3C2410_MISCCR_SPUCR_LDIS (1<<1)
81615 +#define S3C2410_MISCCR_USBDEV (0)
81616 +#define S3C2410_MISCCR_USBHOST (1<<3)
81618 +#define S3C2410_MISCCR_CLK0_MPLL (0<<4)
81619 +#define S3C2410_MISCCR_CLK0_UPLL (1<<4)
81620 +#define S3C2410_MISCCR_CLK0_FCLK (2<<4)
81621 +#define S3C2410_MISCCR_CLK0_HCLK (3<<4)
81622 +#define S3C2410_MISCCR_CLK0_PCLK (4<<4)
81623 +#define S3C2410_MISCCR_CLK0_DCLK0 (5<<4)
81625 +#define S3C2410_MISCCR_CLK1_MPLL (0<<8)
81626 +#define S3C2410_MISCCR_CLK1_UPLL (1<<8)
81627 +#define S3C2410_MISCCR_CLK1_FCLK (2<<8)
81628 +#define S3C2410_MISCCR_CLK1_HCLK (3<<8)
81629 +#define S3C2410_MISCCR_CLK1_PCLK (4<<8)
81630 +#define S3C2410_MISCCR_CLK1_DCLK1 (5<<8)
81632 +#define S3C2410_MISCCR_USBSUSPND0 (1<<12)
81633 +#define S3C2410_MISCCR_USBSUSPND1 (1<<13)
81635 +#define S3C2410_MISCCR_nRSTCON (1<<16)
81637 +/* external interrupt control... */
81638 +/* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
81639 + * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
81640 + * S3C2410_EXTINT2 -> irq sense control for EINT16..EINT23
81642 + * note S3C2410_EXTINT2 has filtering options for EINT16..EINT23
81644 + * Samsung datasheet p9-25
81647 +#define S3C2410_EXTINT0 S3C2410_GPIOREG(0x88)
81648 +#define S3C2410_EXTINT1 S3C2410_GPIOREG(0x8C)
81649 +#define S3C2410_EXTINT2 S3C2410_GPIOREG(0x90)
81651 +/* values for S3C2410_EXTINT0/1/2 */
81652 +#define S3C2410_EXTINT_LOWLEV (0x00)
81653 +#define S3C2410_EXTINT_HILEV (0x01)
81654 +#define S3C2410_EXTINT_FALLEDGE (0x02)
81655 +#define S3C2410_EXTINT_RISEEDGE (0x04)
81656 +#define S3C2410_EXTINT_BOTHEDGE (0x06)
81658 +/* interrupt filtering conrrol for EINT16..EINT23 */
81659 +#define S3C2410_EINFLT0 S3C2410_GPIOREG(0x94)
81660 +#define S3C2410_EINFLT1 S3C2410_GPIOREG(0x98)
81661 +#define S3C2410_EINFLT2 S3C2410_GPIOREG(0x9C)
81662 +#define S3C2410_EINFLT3 S3C2410_GPIOREG(0xA0)
81664 +/* mask: 0=enable, 1=disable
81665 + * 1 bit EINT, 4=EINT4, 23=EINT23
81666 + * EINT0,1,2,3 are not handled here.
81668 +#define S3C2410_EINTMASK S3C2410_GPIOREG(0xA4)
81669 +#define S3C2410_EINTPEND S3C2410_GPIOREG(0xA8)
81671 +/* GSTATUS have miscellaneous information in them
81673 + */
81675 +#define S3C2410_GSTATUS0 S3C2410_GPIOREG(0x0AC)
81676 +#define S3C2410_GSTATUS1 S3C2410_GPIOREG(0x0B0)
81677 +#define S3C2410_GSTATUS2 S3C2410_GPIOREG(0x0B4)
81678 +#define S3C2410_GSTATUS3 S3C2410_GPIOREG(0x0B8)
81679 +#define S3C2410_GSTATUS4 S3C2410_GPIOREG(0x0BC)
81681 +#define S3C2410_GSTATUS0_nWAIT (1<<3)
81682 +#define S3C2410_GSTATUS0_NCON (1<<2)
81683 +#define S3C2410_GSTATUS0_RnB (1<<1)
81684 +#define S3C2410_GSTATUS0_nBATTFLT (1<<0)
81686 +#define S3C2410_GSTATUS2_WTRESET (1<<2)
81687 +#define S3C2410_GSTATUs2_OFFRESET (1<<1)
81688 +#define S3C2410_GSTATUS2_PONRESET (1<<0)
81690 +#endif /* ASMARM_ARCH_S3C2410_GPIO_H */
81692 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
81693 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-iis.h 2004-03-31 17:15:09.000000000 +0200
81694 @@ -0,0 +1,61 @@
81695 +/* linux/include/asm/hardware/s3c2410/iis.h
81697 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
81698 + * http://www.simtec.co.uk/products/SWLINUX/
81700 + * This program is free software; you can redistribute it and/or modify
81701 + * it under the terms of the GNU General Public License version 2 as
81702 + * published by the Free Software Foundation.
81704 + * S3C2410 IIS register definition
81706 + * Changelog:
81707 + * 19-06-2003 BJD Created file
81708 + * 26-06-2003 BJD Finished off definitions for register addresses
81709 + */
81711 +#ifndef ASMARM_ARCH_S3C2410_IIS_H
81712 +#define ASMARM_ARCH_S3C2410_IIS_H
81714 +#define S3C2410_IISCON (S3C2410_VA_IIS + 0x00)
81716 +#define S3C2410_IISCON_LRINDEX (1<<8)
81717 +#define S3C2410_IISCON_TXFIFORDY (1<<7)
81718 +#define S3C2410_IISCON_RXFIFORDY (1<<6)
81719 +#define S3C2410_IISCON_TXDMAEN (1<<5)
81720 +#define S3C2410_IISCON_RXDMAEN (1<<4)
81721 +#define S3C2410_IISCON_TXIDLE (1<<3)
81722 +#define S3C2410_IISCON_RXIDLE (1<<2)
81723 +#define S3C2410_IISCON_IISEN (1<<0)
81725 +#define S3C2410_IISMOD (S3C2410_VA_IIS + 0x04)
81727 +#define S3C2410_IISMOD_SLAVE (1<<8)
81728 +#define S3C2410_IISMOD_NOXFER (0<<6)
81729 +#define S3C2410_IISMOD_RXMODE (1<<6)
81730 +#define S3C2410_IISMOD_TXMODE (2<<6)
81731 +#define S3C2410_IISMOD_TXRXMODE (3<<6)
81732 +#define S3C2410_IISMOD_LR_LLOW (0<<5)
81733 +#define S3C2410_IISMOD_LR_RLOW (1<<5)
81734 +#define S3C2410_IISMOD_IIS (0<<4)
81735 +#define S3C2410_IISMOD_MSB (1<<4)
81736 +#define S3C2410_IISMOD_8BIT (0<<3)
81737 +#define S3C2410_IISMOD_16BIT (1<<3)
81738 +#define S3C2410_IISMOD_256FS (0<<1)
81739 +#define S3C2410_IISMOD_384FS (1<<1)
81740 +#define S3C2410_IISMOD_16FS (0<<0)
81741 +#define S3C2410_IISMOD_32FS (1<<0)
81742 +#define S3C2410_IISMOD_48FS (2<<0)
81744 +#define S3C2410_IISPSR (S3C2410_VA_IIS + 0x08)
81746 +#define S3C2410_IISFCON (S3C2410_VA_IIS + 0x0c)
81748 +#define S3C2410_IISFCON_TXDMA (1<<15)
81749 +#define S3C2410_IISFCON_RXDMA (1<<14)
81750 +#define S3C2410_IISFCON_TXENABLE (1<<13)
81751 +#define S3C2410_IISFCON_RXENABLE (1<<12)
81753 +#define S3C2410_IISFIFO (S3C2410_VA_IIS + 0x10)
81755 +#endif /* ASMARM_ARCH_S3C2410_IIS_H */
81756 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
81757 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-irq.h 2004-03-31 17:15:09.000000000 +0200
81758 @@ -0,0 +1,34 @@
81759 +/* linux/include/asm-arm/arch-s3c2410/S3C2410-irq.h
81761 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
81762 + * http://www.simtec.co.uk/products/SWLINUX/
81764 + * This program is free software; you can redistribute it and/or modify
81765 + * it under the terms of the GNU General Public License version 2 as
81766 + * published by the Free Software Foundation.
81768 + * Changelog:
81769 + * 19-06-2003 BJD Created file
81770 + */
81772 +#ifndef ASMARM_ARCH_S3C2410_IRQ_H
81773 +#define ASMARM_ARCH_S3C2410_IRQ_H
81775 +/* interrupt controller */
81777 +#define S3C2410_IRQREG(x) ((x) + S3C2410_VA_IRQ)
81778 +#define S3C2410_EINTREG(x) ((x) + S3C2410_VA_GPIO)
81780 +#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
81781 +#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
81782 +#define S3C2410_INTMSK S3C2410_IRQREG(0x008)
81783 +#define S3C2410_PRIORITY S3C2410_IRQREG(0x00C)
81784 +#define S3C2410_INTPND S3C2410_IRQREG(0x010)
81785 +#define S3C2410_INTOFFSET S3C2410_IRQREG(0x014)
81786 +#define S3C2410_SUBSRCPND S3C2410_IRQREG(0x018)
81787 +#define S3C2410_INTSUBMSK S3C2410_IRQREG(0x01C)
81789 +#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4)
81790 +#define S3C2410_EINTPEND S3C2410_EINTREG(0X0A8)
81792 +#endif /* ASMARM_ARCH_S3C2410_IRQ_H */
81793 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
81794 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-lcd.h 2004-03-31 17:15:09.000000000 +0200
81795 @@ -0,0 +1,107 @@
81796 +/* linux/include/asm-arm/arch-s3c2410/S3C2410-lcd.h
81798 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
81799 + * http://www.simtec.co.uk/products/SWLINUX/
81801 + * This program is free software; you can redistribute it and/or modify
81802 + * it under the terms of the GNU General Public License version 2 as
81803 + * published by the Free Software Foundation.
81807 + * Changelog:
81808 + * 12-06-2003 BJD Created file
81809 + * 26-06-2003 BJD Updated LCDCON register definitions
81812 +#ifndef ASMARM_ARCH_S3C2410_LCD_H
81813 +#define ASMARM_ARCH_S3C2410_LCD_H
81815 +#define S3C2410_LCDREG(x) ((x) + S3C2410_VA_LCD)
81817 +/* LCD control registers */
81818 +#define S3C2410_LCDCON1 S3C2410_LCDREG(0x00)
81819 +#define S3C2410_LCDCON2 S3C2410_LCDREG(0x04)
81820 +#define S3C2410_LCDCON3 S3C2410_LCDREG(0x08)
81821 +#define S3C2410_LCDCON4 S3C2410_LCDREG(0x0C)
81822 +#define S3C2410_LCDCON5 S3C2410_LCDREG(0x10)
81824 +#define S3C2410_LCDCON1_CLKVAL(x) ((x) << 8)
81825 +#define S3C2410_LCDCON1_MMODE (1<<7)
81826 +#define S3C2410_LCDCON1_DSCAN4 (0<<5)
81827 +#define S3C2410_LCDCON1_STN4 (1<<5)
81828 +#define S3C2410_LCDCON1_STN8 (2<<5)
81829 +#define S3C2410_LCDCON1_TFT (3<<5)
81831 +#define S3C2410_LCDCON1_STN1BPP (0<<1)
81832 +#define S3C2410_LCDCON1_STN2GREY (1<<1)
81833 +#define S3C2410_LCDCON1_STN4GREY (2<<1)
81834 +#define S3C2410_LCDCON1_STN8BPP (3<<1)
81835 +#define S3C2410_LCDCON1_STN12BPP (4<<1)
81837 +#define S3C2410_LCDCON1_TFT1BPP (8<<1)
81838 +#define S3C2410_LCDCON1_TFT2BPP (9<<1)
81839 +#define S3C2410_LCDCON1_TFT4BPP (10<<1)
81840 +#define S3C2410_LCDCON1_TFT8BPP (11<<1)
81841 +#define S3C2410_LCDCON1_TFT16BPP (12<<1)
81842 +#define S3C2410_LCDCON1_TFT24BPP (13<<1)
81844 +#define S3C2410_LCDCON1_ENVDI (1)
81846 +#define S3C2410_LCDCON2_VBPD(x) ((x) << 24)
81847 +#define S3C2410_LCDCON2_LINEVAL(x) ((x) << 14)
81848 +#define S3C2410_LCDCON2_VFPD(x) ((x) << 6)
81849 +#define S3C2410_LCDCON2_VSPW(x) ((x) << 0)
81851 +#define S3C2410_LCDCON3_HBPD(x) ((x) << 19)
81852 +#define S3C2410_LCDCON3_WDLY(x) ((x) << 19)
81853 +#define S3C2410_LCDCON3_HOZVAL(x) ((x) << 8)
81854 +#define S3C2410_LCDCON3_HFPD(x) ((x) << 0)
81855 +#define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
81857 +#define S3C2410_LCDCON4_MVAL(x) ((x) << 8)
81858 +#define S3C2410_LCDCON4_HSPW(x) ((x) << 0)
81859 +#define S3C2410_LCDCON4_WLH(x) ((x) << 0)
81861 +#define S3C2410_LCDCON5_BPP24BL (1<<12)
81862 +#define S3C2410_LCDCON5_FRM565 (1<<11)
81863 +#define S3C2410_LCDCON5_INVVCLK (1<<10)
81864 +#define S3C2410_LCDCON5_INVVLINE (1<<9)
81865 +#define S3C2410_LCDCON5_INVVFRAME (1<<8)
81866 +#define S3C2410_LCDCON5_INVVD (1<<7)
81867 +#define S3C2410_LCDCON5_INVVSYNC (1<<8)
81868 +#define S3C2410_LCDCON5_INVHSYNC (1<<9)
81869 +#define S3C2410_LCDCON5_INVVDEN (1<<6)
81870 +#define S3C2410_LCDCON5_INVPWREN (1<<5)
81871 +#define S3C2410_LCDCON5_INVLEND (1<<4)
81872 +#define S3C2410_LCDCON5_PWREN (1<<3)
81873 +#define S3C2410_LCDCON5_ENLEND (1<<2)
81874 +#define S3C2410_LCDCON5_BSWP (1<<1)
81875 +#define S3C2410_LCDCON5_HWSWP (1<<0)
81877 +/* framebuffer start addressed */
81878 +#define S3C2410_LCDSADDR1 S3C2410_LCDREG(0x14)
81879 +#define S3C2410_LCDSADDR2 S3C2410_LCDREG(0x18)
81880 +#define S3C2410_LCDSADDR3 S3C2410_LCDREG(0x1C)
81882 +/* colour lookup and miscellaneous controls */
81884 +#define S3C2410_REDLUT S3C2410_LCDREG(0x20)
81885 +#define S3C2410_GREENLUT S3C2410_LCDREG(0x24)
81886 +#define S3C2410_BLUELUT S3C2410_LCDREG(0x28)
81888 +#define S3C2410_DITHMODE S3C2410_LCDREG(0x4C)
81889 +#define S3C2410_TPAL S3C2410_LCDREG(0x50)
81891 +/* interrupt info */
81892 +#define S3C2410_LCDINTPND S3C2410_LCDREG(0x54)
81893 +#define S3C2410_LCDSRCPND S3C2410_LCDREG(0x58)
81894 +#define S3C2410_LCDINTMSK S3C2410_LCDREG(0x5C)
81895 +#define S3C2410_LPCSEL S3C2410_LCDREG(0x60)
81897 +#define S3C2410_TFTPAL(x) S3C2410_LCDREG((0x400 + (x)*4))
81899 +#endif /* ASMARM_ARCH_S3C2410_LCD_H */
81903 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
81904 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-rtc.h 2004-03-31 17:15:09.000000000 +0200
81905 @@ -0,0 +1,61 @@
81906 +/* linux/include/asm-arm/arch-s3c2410/S3C2410-rtc.h
81908 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
81909 + * http://www.simtec.co.uk/products/SWLINUX/
81911 + * This program is free software; you can redistribute it and/or modify
81912 + * it under the terms of the GNU General Public License version 2 as
81913 + * published by the Free Software Foundation.
81915 + * S3C2410 Timer configuration
81917 + * Changelog:
81918 + * 05-06-2003 BJD Created file
81919 + */
81921 +#ifndef ASMARM_ARCH_S3C2410_RTC_H
81922 +#define ASMARM_ARCH_S3C2410_RTC_H
81924 +#define S3C2410_RTCREG(x) ((x) + S3C2410_VA_RTC)
81926 +#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
81927 +#define S3C2410_RTCCON_RTCEN (1<<0)
81928 +#define S3C2410_RTCCON_CLKRST (1<<3)
81930 +#define S3C2410_TICNT S3C2410_RTCREG(0x44)
81931 +#define S3C2410_TICNT_ENABLE (1<<7)
81933 +#define S3C2410_RTCALM S3C2410_RTCREG(0x50)
81934 +#define S3C2410_RTCALM_ALMEN (1<<6)
81935 +#define S3C2410_RTCALM_YEAREN (1<<5)
81936 +#define S3C2410_RTCALM_MONEN (1<<4)
81937 +#define S3C2410_RTCALM_DAYEN (1<<3)
81938 +#define S3C2410_RTCALM_HOUREN (1<<2)
81939 +#define S3C2410_RTCALM_MINEN (1<<1)
81940 +#define S3C2410_RTCALM_SECEN (1<<0)
81942 +#define S3C2410_RTCALM_ALL \
81943 + S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\
81944 + S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\
81945 + S3C2410_RTCALM_SECEN
81948 +#define S3C2410_ALMSEC S3C2410_RTCREG(0x54)
81949 +#define S3C2410_ALMMIN S3C2410_RTCREG(0x58)
81950 +#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c)
81952 +#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
81953 +#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
81954 +#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
81956 +#define S3C2410_RTCRST S3C2410_RTCREG(0x6c)
81958 +#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
81959 +#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
81960 +#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
81961 +#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
81962 +#define S3C2410_RTCDAY S3C2410_RTCREG(0x80)
81963 +#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
81964 +#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
81966 +#endif /* ASMARM_ARCH_S3C2410_RTC_H */
81967 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
81968 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-serial.h 2004-03-31 17:15:09.000000000 +0200
81969 @@ -0,0 +1,98 @@
81971 + * linux/include/asm-arm/arch-s3c2410/S3C2410-serial.h
81973 + * Internal header file for Samsung S3C2410 serial ports (UART0-2)
81975 + * Copyright (C) 2002 Shane Nay (shane@minirl.com)
81977 + * Additional defines, (c) 2003 Simtec Electronics (linux@simtec.co.uk)
81979 + * Adapted from:
81981 + * Internal header file for MX1ADS serial ports (UART1 & 2)
81983 + * Copyright (C) 2002 Shane Nay (shane@minirl.com)
81985 + * This program is free software; you can redistribute it and/or modify
81986 + * it under the terms of the GNU General Public License as published by
81987 + * the Free Software Foundation; either version 2 of the License, or
81988 + * (at your option) any later version.
81990 + * This program is distributed in the hope that it will be useful,
81991 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
81992 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81993 + * GNU General Public License for more details.
81995 + * You should have received a copy of the GNU General Public License
81996 + * along with this program; if not, write to the Free Software
81997 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
81998 + */
82000 +#ifndef ASMARM_ARCH_S3C2410_SERIAL_H
82001 +#define ASMARM_ARCH_S3C2410_SERIAL_H
82003 +#define S3C2410_UARTRXH0_OFF (0x24)
82004 +#define S3C2410_UARTTXH0_OFF (0x20)
82005 +#define S3C2410_UARTLCON_OFF (0x00)
82006 +#define S3C2410_UARTCON_OFF (0x04)
82007 +#define S3C2410_UARTFCON_OFF (0x08)
82008 +#define S3C2410_UARTMCON_OFF (0x0C)
82009 +#define S3C2410_UARTBRDIV_OFF (0x28)
82010 +#define S3C2410_UARTTRSTAT_OFF (0x10)
82011 +#define S3C2410_UARTERSTAT_OFF (0x14)
82012 +#define S3C2410_UARTFSTAT_OFF (0x18)
82013 +#define S3C2410_UARTMSTAT_OFF (0x1C)
82016 +#define S3C2410_UART1_OFF (0x4000)
82017 +#define S3C2410_UART2_OFF (0x8000)
82019 +#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
82021 +#define S3C2410_LCON_CS5 (0x0)
82022 +#define S3C2410_LCON_CS6 (0x1)
82023 +#define S3C2410_LCON_CS7 (0x2)
82024 +#define S3C2410_LCON_CS8 (0x3)
82026 +#define S3C2410_LCON_PNONE (0x0)
82027 +#define S3C2410_LCON_PEVEN ((0x5)<<3)
82028 +#define S3C2410_LCON_PODD ((0x4)<<3)
82030 +#define S3C2410_UMCON_AFC (0x10)
82031 +#define S3C2410_UMCON_RTS (0x1)
82033 +#define S3C2410_UMSTAT_CTS (0x1)
82035 +#define S3C2410_UCON_SBREAK (1<<4)
82037 +#define S3C2410_UCON_TXILEVEL (1<<9)
82038 +#define S3C2410_UCON_RXILEVEL (1<<8)
82039 +#define S3C2410_UCON_TXIRQMODE (1<<2)
82040 +#define S3C2410_UCON_RXIRQMODE (1<<0)
82041 +#define S3C2410_UCON_RXFIFO_TOI (1<<7)
82043 +#define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL \
82044 + | S3C2410_UCON_TXIRQMODE | S3C2410_UCON_RXIRQMODE \
82045 + | S3C2410_UCON_RXFIFO_TOI)
82047 +#define S3C2410_UFCON_FIFOMODE (1<<0)
82048 +#define S3C2410_UFCON_TXTRIG0 (0<<6)
82049 +#define S3C2410_UFCON_RXTRIG8 (1<<4)
82050 +#define S3C2410_UFCON_RXTRIG12 (2<<4)
82052 +#define S3C2410_UFCON_RESETBOTH (3<<1)
82054 +#define S3C2410_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | S3C2410_UFCON_TXTRIG0 \
82055 + | S3C2410_UFCON_RXTRIG8 )
82057 +#define S3C2410_UFSTAT_TXFULL (1<<9)
82058 +#define S3C2410_UFSTAT_RXFULL (1<<8)
82059 +#define S3C2410_UFSTAT_TXMASK (15<<4)
82060 +#define S3C2410_UFSTAT_TXSHIFT (4)
82061 +#define S3C2410_UFSTAT_RXMASK (15<<0)
82062 +#define S3C2410_UFSTAT_RXSHIFT (0)
82064 +#define S3C2410_UTRSTAT_TXFE (1<<1)
82065 +#define S3C2410_UTRSTAT_RXDR (1<<0)
82067 +#endif /* ASMARM_ARCH_S3C2410_SERIAL_H */
82068 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
82069 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-timer.h 2004-03-31 17:15:09.000000000 +0200
82070 @@ -0,0 +1,81 @@
82071 +/* linux/include/asm-arm/arch-s3c2410/S3C2410-timer.h
82073 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
82074 + * http://www.simtec.co.uk/products/SWLINUX/
82076 + * This program is free software; you can redistribute it and/or modify
82077 + * it under the terms of the GNU General Public License version 2 as
82078 + * published by the Free Software Foundation.
82080 + * S3C2410 Timer configuration
82082 + * Changelog:
82083 + * 05-06-2003 BJD Created file
82084 + * 26-06-2003 BJD Added more timer definitions to mux / control
82085 + */
82087 +#ifndef ASMARM_ARCH_S3C2410_TIMER_H
82088 +#define ASMARM_ARCH_S3C2410_TIMER_H
82090 +#define S3C2410_TIMERREG(x) (S3C2410_VA_TIMER + (x))
82091 +#define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))
82093 +#define S3C2410_TCFG0 S3C2410_TIMERREG(0x00)
82094 +#define S3C2410_TCFG1 S3C2410_TIMERREG(0x04)
82095 +#define S3C2410_TCON S3C2410_TIMERREG(0x08)
82098 +#define S3C2410_TCFG1_MUX4_TCLK1 (4<<16)
82099 +#define S3C2410_TCFG1_MUX4_MASK (15<<16)
82101 +#define S3C2410_TCFG1_MUX3_TCLK1 (4<<12)
82102 +#define S3C2410_TCFG1_MUX3_MASK (15<<12)
82104 +#define S3C2410_TCFG1_MUX2_TCLK1 (4<<8)
82105 +#define S3C2410_TCFG1_MUX2_MASK (15<<8)
82107 +#define S3C2410_TCFG1_MUX1_TCLK0 (4<<4)
82108 +#define S3C2410_TCFG1_MUX1_MASK (15<<4)
82110 +#define S3C2410_TCFG1_MUX0_TCLK0 (4<<0)
82111 +#define S3C2410_TCFG1_MUX0_MASK (15<<0)
82113 +/* for each timer, we have an count buffer, an compare buffer and an
82114 + * observation buffer
82115 + */
82117 +/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
82119 +#define S3C2410_TCNTB(tmr) S3C2410_TIMERREG2(tmr, 0x00)
82120 +#define S3C2410_TCMPB(tmr) S3C2410_TIMERREG2(tmr, 0x04)
82121 +#define S3C2410_TCNTO(tmr) S3C2410_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08))
82123 +#define S3C2410_TCON_T4RELOAD (1<<22)
82124 +#define S3C2410_TCON_T4MANUALUPD (1<<21)
82125 +#define S3C2410_TCON_T4START (1<<20)
82127 +#define S3C2410_TCON_T3RELOAD (1<<19)
82128 +#define S3C2410_TCON_T3INVERT (1<<18)
82129 +#define S3C2410_TCON_T3MANUALUPD (1<<17)
82130 +#define S3C2410_TCON_T3START (1<<16)
82132 +#define S3C2410_TCON_T2RELOAD (1<<15)
82133 +#define S3C2410_TCON_T2INVERT (1<<14)
82134 +#define S3C2410_TCON_T2MANUALUPD (1<<13)
82135 +#define S3C2410_TCON_T2START (1<<12)
82137 +#define S3C2410_TCON_T1RELOAD (1<<11)
82138 +#define S3C2410_TCON_T1INVERT (1<<10)
82139 +#define S3C2410_TCON_T1MANUALUPD (1<<9)
82140 +#define S3C2410_TCON_T1START (1<<8)
82142 +#define S3C2410_TCON_T0DEADZONE (1<<4)
82143 +#define S3C2410_TCON_T0RELOAD (1<<3)
82144 +#define S3C2410_TCON_T0INVERT (1<<2)
82145 +#define S3C2410_TCON_T0MANUALUPD (1<<1)
82146 +#define S3C2410_TCON_T0START (1<<0)
82148 +#endif /* ASMARM_ARCH_S3C2410_TIMER_H */
82152 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
82153 +++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h 2004-03-31 17:15:09.000000000 +0200
82154 @@ -0,0 +1,40 @@
82155 +/* linux/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h
82157 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
82158 + * http://www.simtec.co.uk/products/SWLINUX/
82160 + * This program is free software; you can redistribute it and/or modify
82161 + * it under the terms of the GNU General Public License version 2 as
82162 + * published by the Free Software Foundation.
82164 + * S3C2410 Watchdog timer control
82166 + * Changelog:
82167 + * 21-06-2003 BJD Created file
82170 +#ifndef ASMARM_ARCH_S3C2410_WATCHDOG_H
82171 +#define ASMARM_ARCH_S3C2410_WATCHDOG_H
82173 +#define S3C2410_WDOGREG(x) ((x) + S3C2410_VA_WATCHDOG)
82175 +#define S3C2410_WTCON S3C2410_WDOGREG(0x00)
82176 +#define S3C2410_WTDAT S3C2410_WDOGREG(0x04)
82177 +#define S3C2410_WTCNT S3C2410_WDOGREG(0x08)
82179 +/* the watchdog can either generate a reset pulse, or an interrupt. */
82181 +#define S3C2410_WTCON_RSTEN (0x01)
82182 +#define S3C2410_WTCON_INTEN (1<<2)
82183 +#define S3C2410_WTCON_ENABLE (1<<5)
82185 +#define S3C2410_WTCON_DIV16 (0<<3)
82186 +#define S3C2410_WTCON_DIV32 (1<<3)
82187 +#define S3C2410_WTCON_DIV64 (2<<3)
82188 +#define S3C2410_WTCON_DIV128 (3<<3)
82190 +#define S3C2410_WTCON_PRESCALE(x) ((x) << 8)
82192 +#endif /* ASMARM_ARCH_S3C2410_WATCHDOG_H */
82195 --- linux-2.4.25/include/asm-arm/bugs.h~2.4.25-vrs2.patch 2000-09-19 00:15:23.000000000 +0200
82196 +++ linux-2.4.25/include/asm-arm/bugs.h 2004-03-31 17:15:09.000000000 +0200
82197 @@ -10,8 +10,17 @@
82198 #ifndef __ASM_BUGS_H
82199 #define __ASM_BUGS_H
82201 +#include <linux/config.h>
82202 #include <asm/proc-fns.h>
82204 -#define check_bugs() cpu_check_bugs()
82205 +extern void check_writebuffer_bugs(void);
82207 +static inline void check_bugs(void)
82209 +#ifdef CONFIG_CPU_32
82210 + check_writebuffer_bugs();
82211 +#endif
82212 + cpu_check_bugs();
82215 #endif
82216 --- linux-2.4.25/include/asm-arm/div64.h~2.4.25-vrs2.patch 2000-01-13 22:30:31.000000000 +0100
82217 +++ linux-2.4.25/include/asm-arm/div64.h 2004-03-31 17:15:09.000000000 +0200
82218 @@ -4,9 +4,13 @@
82219 /* We're not 64-bit, but... */
82220 #define do_div(n,base) \
82221 ({ \
82222 - int __res; \
82223 - __res = ((unsigned long)n) % (unsigned int)base; \
82224 - n = ((unsigned long)n) / (unsigned int)base; \
82225 + register int __res asm("r2") = base; \
82226 + register unsigned long long __n asm("r0") = n; \
82227 + asm("bl do_div64" \
82228 + : "=r" (__n), "=r" (__res) \
82229 + : "0" (__n), "1" (__res) \
82230 + : "r3", "ip", "lr", "cc"); \
82231 + n = __n; \
82232 __res; \
82235 --- linux-2.4.25/include/asm-arm/elf.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
82236 +++ linux-2.4.25/include/asm-arm/elf.h 2004-03-31 17:15:09.000000000 +0200
82237 @@ -45,8 +45,8 @@
82239 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
82241 -/* When the program starts, a1 contains a pointer to a function to be
82242 - registered with atexit, as per the SVR4 ABI. A value of 0 means we
82243 +/* When the program starts, a1 contains a pointer to a function to be
82244 + registered with atexit, as per the SVR4 ABI. A value of 0 means we
82245 have no such handler. */
82246 #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0
82248 --- linux-2.4.25/include/asm-arm/mach/dma.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
82249 +++ linux-2.4.25/include/asm-arm/mach/dma.h 2004-03-31 17:15:09.000000000 +0200
82250 @@ -41,6 +41,7 @@
82251 unsigned int dma_base; /* Controller base address */
82252 int dma_irq; /* Controller IRQ */
82253 struct scatterlist cur_sg; /* Current controller buffer */
82254 + unsigned int state; /* RiscPC DMA status */
82256 struct dma_ops *d_ops;
82258 --- linux-2.4.25/include/asm-arm/mach/serial_at91rm9200.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
82259 +++ linux-2.4.25/include/asm-arm/mach/serial_at91rm9200.h 2004-03-31 17:15:09.000000000 +0200
82260 @@ -10,7 +10,6 @@
82261 #include <linux/config.h>
82263 struct uart_port;
82264 -struct uart_info;
82267 * This is a temporary structure for registering these
82268 @@ -22,11 +21,11 @@
82269 void (*enable_ms)(struct uart_port *);
82270 void (*pm)(struct uart_port *, u_int, u_int);
82271 int (*set_wake)(struct uart_port *, u_int);
82272 - int (*open)(struct uart_port *, struct uart_info *);
82273 - void (*close)(struct uart_port *, struct uart_info *);
82274 + int (*open)(struct uart_port *);
82275 + void (*close)(struct uart_port *);
82278 -#if defined(CONFIG_SERIAL_AT91RM9200)
82279 +#if defined(CONFIG_SERIAL_AT91)
82280 void at91rm9200_register_uart_fns(struct at91rm9200_port_fns *fns);
82281 void at91rm9200_register_uart(int idx, int port);
82282 #else
82283 --- linux-2.4.25/include/asm-arm/proc-armv/processor.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
82284 +++ linux-2.4.25/include/asm-arm/proc-armv/processor.h 2004-03-31 17:15:09.000000000 +0200
82285 @@ -54,7 +54,9 @@
82286 regs->ARM_cpsr = USR_MODE; \
82287 else \
82288 regs->ARM_cpsr = USR26_MODE; \
82289 - regs->ARM_pc = pc; /* pc */ \
82290 + if (elf_hwcap & HWCAP_THUMB && pc & 1) \
82291 + regs->ARM_cpsr |= PSR_T_BIT; \
82292 + regs->ARM_pc = pc & ~1; /* pc */ \
82293 regs->ARM_sp = sp; /* sp */ \
82294 regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
82295 regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
82296 --- linux-2.4.25/include/asm-arm/proc-armv/ptrace.h~2.4.25-vrs2.patch 2000-11-28 02:07:59.000000000 +0100
82297 +++ linux-2.4.25/include/asm-arm/proc-armv/ptrace.h 2004-03-31 17:15:09.000000000 +0200
82298 @@ -33,6 +33,16 @@
82299 #define CC_N_BIT (1 << 31)
82300 #define PCMASK 0
82302 +/* 2.5 versions */
82303 +#define PSR_T_BIT 0x00000020
82304 +#define PSR_F_BIT 0x00000040
82305 +#define PSR_I_BIT 0x00000080
82306 +#define PSR_J_BIT 0x01000000
82307 +#define PSR_V_BIT 0x10000000
82308 +#define PSR_C_BIT 0x20000000
82309 +#define PSR_Z_BIT 0x40000000
82310 +#define PSR_N_BIT 0x80000000
82312 #ifndef __ASSEMBLY__
82314 /* this struct defines the way the registers are stored on the
82315 --- linux-2.4.25/include/asm-arm/proc-armv/uaccess.h~2.4.25-vrs2.patch 2001-10-25 22:53:55.000000000 +0200
82316 +++ linux-2.4.25/include/asm-arm/proc-armv/uaccess.h 2004-03-31 17:15:09.000000000 +0200
82317 @@ -12,12 +12,11 @@
82318 * Note that this is actually 0x1,0000,0000
82320 #define KERNEL_DS 0x00000000
82321 -#define USER_DS PAGE_OFFSET
82322 +#define USER_DS TASK_SIZE
82324 static inline void set_fs (mm_segment_t fs)
82326 current->addr_limit = fs;
82328 modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
82331 @@ -38,7 +37,7 @@
82332 : "cc"); \
82333 (flag == 0); })
82335 -#define __put_user_asm_byte(x,addr,err) \
82336 +#define __put_user_asm_byte(x,__pu_addr,err) \
82337 __asm__ __volatile__( \
82338 "1: strbt %1,[%2],#0\n" \
82339 "2:\n" \
82340 @@ -51,18 +50,18 @@
82341 " .align 3\n" \
82342 " .long 1b, 3b\n" \
82343 " .previous" \
82344 - : "=r" (err) \
82345 - : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
82346 + : "+r" (err) \
82347 + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
82348 + : "cc")
82350 -#define __put_user_asm_half(x,addr,err) \
82351 +#define __put_user_asm_half(x,__pu_addr,err) \
82352 ({ \
82353 unsigned long __temp = (unsigned long)(x); \
82354 - unsigned long __ptr = (unsigned long)(addr); \
82355 - __put_user_asm_byte(__temp, __ptr, err); \
82356 - __put_user_asm_byte(__temp >> 8, __ptr + 1, err); \
82357 + __put_user_asm_byte(__temp, __pu_addr, err); \
82358 + __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \
82361 -#define __put_user_asm_word(x,addr,err) \
82362 +#define __put_user_asm_word(x,__pu_addr,err) \
82363 __asm__ __volatile__( \
82364 "1: strt %1,[%2],#0\n" \
82365 "2:\n" \
82366 @@ -75,8 +74,28 @@
82367 " .align 3\n" \
82368 " .long 1b, 3b\n" \
82369 " .previous" \
82370 - : "=r" (err) \
82371 - : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
82372 + : "+r" (err) \
82373 + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
82374 + : "cc")
82376 +#define __put_user_asm_dword(x,__pu_addr,err) \
82377 + __asm__ __volatile__( \
82378 + "1: strt %R2, [%1], #4\n" \
82379 + "2: strt %Q2, [%1], #0\n" \
82380 + "3:\n" \
82381 + " .section .fixup,\"ax\"\n" \
82382 + " .align 2\n" \
82383 + "4: mov %0, %3\n" \
82384 + " b 3b\n" \
82385 + " .previous\n" \
82386 + " .section __ex_table,\"a\"\n" \
82387 + " .align 3\n" \
82388 + " .long 1b, 4b\n" \
82389 + " .long 2b, 4b\n" \
82390 + " .previous" \
82391 + : "+r" (err), "+r" (__pu_addr) \
82392 + : "r" (x), "i" (-EFAULT) \
82393 + : "cc")
82395 #define __get_user_asm_byte(x,addr,err) \
82396 __asm__ __volatile__( \
82397 @@ -92,18 +111,18 @@
82398 " .align 3\n" \
82399 " .long 1b, 3b\n" \
82400 " .previous" \
82401 - : "=r" (err), "=&r" (x) \
82402 - : "r" (addr), "i" (-EFAULT), "0" (err))
82403 + : "+r" (err), "=&r" (x) \
82404 + : "r" (addr), "i" (-EFAULT) \
82405 + : "cc")
82407 -#define __get_user_asm_half(x,addr,err) \
82408 +#define __get_user_asm_half(x,__gu_addr,err) \
82409 ({ \
82410 - unsigned long __b1, __b2, __ptr = (unsigned long)addr; \
82411 - __get_user_asm_byte(__b1, __ptr, err); \
82412 - __get_user_asm_byte(__b2, __ptr + 1, err); \
82413 + unsigned long __b1, __b2; \
82414 + __get_user_asm_byte(__b1, __gu_addr, err); \
82415 + __get_user_asm_byte(__b2, __gu_addr + 1, err); \
82416 (x) = __b1 | (__b2 << 8); \
82420 #define __get_user_asm_word(x,addr,err) \
82421 __asm__ __volatile__( \
82422 "1: ldrt %1,[%2],#0\n" \
82423 @@ -118,8 +137,9 @@
82424 " .align 3\n" \
82425 " .long 1b, 3b\n" \
82426 " .previous" \
82427 - : "=r" (err), "=&r" (x) \
82428 - : "r" (addr), "i" (-EFAULT), "0" (err))
82429 + : "+r" (err), "=&r" (x) \
82430 + : "r" (addr), "i" (-EFAULT) \
82431 + : "cc")
82433 extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n);
82434 #define __do_copy_from_user(to,from,n) \
82435 --- linux-2.4.25/include/asm-arm/proc-fns.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
82436 +++ linux-2.4.25/include/asm-arm/proc-fns.h 2004-03-31 17:15:09.000000000 +0200
82437 @@ -76,6 +76,30 @@
82438 # define CPU_NAME arm926
82439 # endif
82440 # endif
82441 +# ifdef CONFIG_CPU_ARM1020
82442 +# ifdef CPU_NAME
82443 +# undef MULTI_CPU
82444 +# define MULTI_CPU
82445 +# else
82446 +# define CPU_NAME arm1020
82447 +# endif
82448 +# endif
82449 +# ifdef CONFIG_CPU_ARM1020E
82450 +# ifdef CPU_NAME
82451 +# undef MULTI_CPU
82452 +# define MULTI_CPU
82453 +# else
82454 +# define CPU_NAME arm1020E
82455 +# endif
82456 +# endif
82457 +# ifdef CONFIG_CPU_ARM1022
82458 +# ifdef CPU_NAME
82459 +# undef MULTI_CPU
82460 +# define MULTI_CPU
82461 +# else
82462 +# define CPU_NAME arm1022
82463 +# endif
82464 +# endif
82465 # ifdef CONFIG_CPU_ARM1026
82466 # ifdef CPU_NAME
82467 # undef MULTI_CPU
82468 --- linux-2.4.25/include/asm-arm/processor.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
82469 +++ linux-2.4.25/include/asm-arm/processor.h 2004-03-31 17:15:09.000000000 +0200
82470 @@ -43,6 +43,7 @@
82471 #include <asm/atomic.h>
82472 #include <asm/ptrace.h>
82473 #include <asm/arch/memory.h>
82474 +#include <asm/elf.h>
82475 #include <asm/proc/processor.h>
82476 #include <asm/types.h>
82478 --- linux-2.4.25/include/asm-arm/system.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
82479 +++ linux-2.4.25/include/asm-arm/system.h 2004-03-31 17:15:09.000000000 +0200
82480 @@ -29,6 +29,10 @@
82482 void die_if_kernel(const char *str, struct pt_regs *regs, int err);
82484 +void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
82485 + struct pt_regs *),
82486 + int sig, const char *name);
82488 #include <asm/proc-fns.h>
82490 #define xchg(ptr,x) \
82491 @@ -89,6 +93,14 @@
82492 #define sti() local_irq_enable()
82493 #define clf() __clf()
82494 #define stf() __stf()
82496 +#define irqs_disabled() \
82497 +({ \
82498 + unsigned long flags; \
82499 + local_save_flags(flags); \
82500 + flags & PSR_I_BIT; \
82503 #define save_flags(x) local_save_flags(x)
82504 #define restore_flags(x) local_irq_restore(x)
82505 #define save_flags_cli(x) local_irq_save(x)
82506 --- linux-2.4.25/include/asm-arm/termios.h~2.4.25-vrs2.patch 2001-06-12 04:15:27.000000000 +0200
82507 +++ linux-2.4.25/include/asm-arm/termios.h 2004-03-31 17:15:09.000000000 +0200
82508 @@ -47,6 +47,8 @@
82509 #define TIOCM_OUT2 0x4000
82510 #define TIOCM_LOOP 0x8000
82512 +#define TIOCM_MODEM_BITS TIOCM_OUT2 /* IRDA support */
82514 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
82516 /* line disciplines */
82517 --- linux-2.4.25/include/asm-arm/uaccess.h~2.4.25-vrs2.patch 2001-10-25 22:53:55.000000000 +0200
82518 +++ linux-2.4.25/include/asm-arm/uaccess.h 2004-03-31 17:15:09.000000000 +0200
82519 @@ -74,14 +74,14 @@
82520 __asm__ __volatile__ ("bl __get_user_" #__s \
82521 : "=&r" (__e), "=r" (__r1) \
82522 : "0" (__p) \
82523 - : __i)
82524 + : __i, "cc")
82526 #define get_user(x,p) \
82527 ({ \
82528 const register typeof(*(p)) *__p asm("r0") = (p); \
82529 register typeof(*(p)) __r1 asm("r1"); \
82530 register int __e asm("r0"); \
82531 - switch (sizeof(*(p))) { \
82532 + switch (sizeof(*(__p))) { \
82533 case 1: \
82534 __get_user_x(__r1, __p, __e, 1, "lr"); \
82535 break; \
82536 @@ -100,8 +100,31 @@
82537 __e; \
82540 -#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p)))
82541 -#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
82542 +#define __get_user(x,ptr) \
82543 +({ \
82544 + long __gu_err = 0; \
82545 + __get_user_err((x),(ptr),__gu_err); \
82546 + __gu_err; \
82549 +#define __get_user_error(x,ptr,err) \
82550 +({ \
82551 + __get_user_err((x),(ptr),err); \
82552 + (void) 0; \
82555 +#define __get_user_err(x,ptr,err) \
82556 +do { \
82557 + unsigned long __gu_addr = (unsigned long)(ptr); \
82558 + unsigned long __gu_val; \
82559 + switch (sizeof(*(ptr))) { \
82560 + case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
82561 + case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
82562 + case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \
82563 + default: (__gu_val) = __get_user_bad(); \
82564 + } \
82565 + (x) = (__typeof__(*(ptr)))__gu_val; \
82566 +} while (0)
82568 extern int __put_user_1(void *, unsigned int);
82569 extern int __put_user_2(void *, unsigned int);
82570 @@ -113,22 +136,22 @@
82571 __asm__ __volatile__ ("bl __put_user_" #__s \
82572 : "=&r" (__e) \
82573 : "0" (__p), "r" (__r1) \
82574 - : __i)
82575 + : __i, "cc")
82577 #define put_user(x,p) \
82578 ({ \
82579 const register typeof(*(p)) __r1 asm("r1") = (x); \
82580 const register typeof(*(p)) *__p asm("r0") = (p); \
82581 register int __e asm("r0"); \
82582 - switch (sizeof(*(p))) { \
82583 + switch (sizeof(*(__p))) { \
82584 case 1: \
82585 - __put_user_x(__r1, __p, __e, 1, "r2", "lr"); \
82586 + __put_user_x(__r1, __p, __e, 1, "ip", "lr"); \
82587 break; \
82588 case 2: \
82589 - __put_user_x(__r1, __p, __e, 2, "r2", "lr"); \
82590 + __put_user_x(__r1, __p, __e, 2, "ip", "lr"); \
82591 break; \
82592 case 4: \
82593 - __put_user_x(__r1, __p, __e, 4, "r2", "lr"); \
82594 + __put_user_x(__r1, __p, __e, 4, "ip", "lr"); \
82595 break; \
82596 case 8: \
82597 __put_user_x(__r1, __p, __e, 8, "ip", "lr"); \
82598 @@ -138,8 +161,31 @@
82599 __e; \
82602 -#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
82603 -#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
82604 +#define __put_user(x,ptr) \
82605 +({ \
82606 + long __pu_err = 0; \
82607 + __put_user_err((x),(ptr),__pu_err); \
82608 + __pu_err; \
82611 +#define __put_user_error(x,ptr,err) \
82612 +({ \
82613 + __put_user_err((x),(ptr),err); \
82614 + (void) 0; \
82617 +#define __put_user_err(x,ptr,err) \
82618 +do { \
82619 + unsigned long __pu_addr = (unsigned long)(ptr); \
82620 + __typeof__(*(ptr)) __pu_val = (x); \
82621 + switch (sizeof(*(ptr))) { \
82622 + case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
82623 + case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
82624 + case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \
82625 + case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \
82626 + default: __put_user_bad(); \
82627 + } \
82628 +} while (0)
82630 static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
82632 @@ -209,82 +255,4 @@
82633 return res;
82637 - * These are the work horses of the get/put_user functions
82638 - */
82639 -#if 0
82640 -#define __get_user_check(x,ptr,size) \
82641 -({ \
82642 - long __gu_err = -EFAULT, __gu_val = 0; \
82643 - const __typeof__(*(ptr)) *__gu_addr = (ptr); \
82644 - if (access_ok(VERIFY_READ,__gu_addr,size)) { \
82645 - __gu_err = 0; \
82646 - __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
82647 - } \
82648 - (x) = (__typeof__(*(ptr)))__gu_val; \
82649 - __gu_err; \
82651 -#endif
82653 -#define __get_user_nocheck(x,ptr,size) \
82654 -({ \
82655 - long __gu_err = 0, __gu_val; \
82656 - __get_user_size(__gu_val,(ptr),(size),__gu_err); \
82657 - (x) = (__typeof__(*(ptr)))__gu_val; \
82658 - __gu_err; \
82661 -#define __get_user_nocheck_error(x,ptr,size,err) \
82662 -({ \
82663 - long __gu_val; \
82664 - __get_user_size(__gu_val,(ptr),(size),(err)); \
82665 - (x) = (__typeof__(*(ptr)))__gu_val; \
82666 - (void) 0; \
82669 -#define __put_user_check(x,ptr,size) \
82670 -({ \
82671 - long __pu_err = -EFAULT; \
82672 - __typeof__(*(ptr)) *__pu_addr = (ptr); \
82673 - if (access_ok(VERIFY_WRITE,__pu_addr,size)) { \
82674 - __pu_err = 0; \
82675 - __put_user_size((x),__pu_addr,(size),__pu_err); \
82676 - } \
82677 - __pu_err; \
82680 -#define __put_user_nocheck(x,ptr,size) \
82681 -({ \
82682 - long __pu_err = 0; \
82683 - __typeof__(*(ptr)) *__pu_addr = (ptr); \
82684 - __put_user_size((x),__pu_addr,(size),__pu_err); \
82685 - __pu_err; \
82688 -#define __put_user_nocheck_error(x,ptr,size,err) \
82689 -({ \
82690 - __put_user_size((x),(ptr),(size),err); \
82691 - (void) 0; \
82694 -#define __get_user_size(x,ptr,size,retval) \
82695 -do { \
82696 - switch (size) { \
82697 - case 1: __get_user_asm_byte(x,ptr,retval); break; \
82698 - case 2: __get_user_asm_half(x,ptr,retval); break; \
82699 - case 4: __get_user_asm_word(x,ptr,retval); break; \
82700 - default: (x) = __get_user_bad(); \
82701 - } \
82702 -} while (0)
82704 -#define __put_user_size(x,ptr,size,retval) \
82705 -do { \
82706 - switch (size) { \
82707 - case 1: __put_user_asm_byte(x,ptr,retval); break; \
82708 - case 2: __put_user_asm_half(x,ptr,retval); break; \
82709 - case 4: __put_user_asm_word(x,ptr,retval); break; \
82710 - default: __put_user_bad(); \
82711 - } \
82712 -} while (0)
82714 #endif /* _ASMARM_UACCESS_H */
82715 --- linux-2.4.25/include/asm-arm/unistd.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
82716 +++ linux-2.4.25/include/asm-arm/unistd.h 2004-03-31 17:15:09.000000000 +0200
82717 @@ -31,7 +31,7 @@
82718 #define __NR_write (__NR_SYSCALL_BASE+ 4)
82719 #define __NR_open (__NR_SYSCALL_BASE+ 5)
82720 #define __NR_close (__NR_SYSCALL_BASE+ 6)
82721 -#define __NR_waitpid (__NR_SYSCALL_BASE+ 7)
82722 + /* 7 was sys_waitpid */
82723 #define __NR_creat (__NR_SYSCALL_BASE+ 8)
82724 #define __NR_link (__NR_SYSCALL_BASE+ 9)
82725 #define __NR_unlink (__NR_SYSCALL_BASE+ 10)
82726 @@ -41,8 +41,8 @@
82727 #define __NR_mknod (__NR_SYSCALL_BASE+ 14)
82728 #define __NR_chmod (__NR_SYSCALL_BASE+ 15)
82729 #define __NR_lchown (__NR_SYSCALL_BASE+ 16)
82730 -#define __NR_break (__NR_SYSCALL_BASE+ 17)
82732 + /* 17 was sys_break */
82733 + /* 18 was sys_stat */
82734 #define __NR_lseek (__NR_SYSCALL_BASE+ 19)
82735 #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
82736 #define __NR_mount (__NR_SYSCALL_BASE+ 21)
82737 @@ -52,14 +52,14 @@
82738 #define __NR_stime (__NR_SYSCALL_BASE+ 25)
82739 #define __NR_ptrace (__NR_SYSCALL_BASE+ 26)
82740 #define __NR_alarm (__NR_SYSCALL_BASE+ 27)
82742 + /* 28 was sys_fstat */
82743 #define __NR_pause (__NR_SYSCALL_BASE+ 29)
82744 #define __NR_utime (__NR_SYSCALL_BASE+ 30)
82745 -#define __NR_stty (__NR_SYSCALL_BASE+ 31)
82746 -#define __NR_gtty (__NR_SYSCALL_BASE+ 32)
82747 + /* 31 was sys_stty */
82748 + /* 32 was sys_gtty */
82749 #define __NR_access (__NR_SYSCALL_BASE+ 33)
82750 #define __NR_nice (__NR_SYSCALL_BASE+ 34)
82751 -#define __NR_ftime (__NR_SYSCALL_BASE+ 35)
82752 + /* 35 was sys_ftime */
82753 #define __NR_sync (__NR_SYSCALL_BASE+ 36)
82754 #define __NR_kill (__NR_SYSCALL_BASE+ 37)
82755 #define __NR_rename (__NR_SYSCALL_BASE+ 38)
82756 @@ -68,22 +68,23 @@
82757 #define __NR_dup (__NR_SYSCALL_BASE+ 41)
82758 #define __NR_pipe (__NR_SYSCALL_BASE+ 42)
82759 #define __NR_times (__NR_SYSCALL_BASE+ 43)
82760 -#define __NR_prof (__NR_SYSCALL_BASE+ 44)
82761 + /* 44 was sys_prof */
82762 #define __NR_brk (__NR_SYSCALL_BASE+ 45)
82763 #define __NR_setgid (__NR_SYSCALL_BASE+ 46)
82764 #define __NR_getgid (__NR_SYSCALL_BASE+ 47)
82765 -#define __NR_signal (__NR_SYSCALL_BASE+ 48)
82766 + /* 48 was sys_signal */
82767 #define __NR_geteuid (__NR_SYSCALL_BASE+ 49)
82768 #define __NR_getegid (__NR_SYSCALL_BASE+ 50)
82769 #define __NR_acct (__NR_SYSCALL_BASE+ 51)
82770 #define __NR_umount2 (__NR_SYSCALL_BASE+ 52)
82771 -#define __NR_lock (__NR_SYSCALL_BASE+ 53)
82772 + /* 53 was sys_lock */
82773 #define __NR_ioctl (__NR_SYSCALL_BASE+ 54)
82774 #define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
82775 -#define __NR_mpx (__NR_SYSCALL_BASE+ 56)
82776 + /* 56 was sys_mpx */
82777 #define __NR_setpgid (__NR_SYSCALL_BASE+ 57)
82778 #define __NR_ulimit (__NR_SYSCALL_BASE+ 58)
82780 + /* 58 was sys_ulimit */
82781 + /* 59 was sys_olduname */
82782 #define __NR_umask (__NR_SYSCALL_BASE+ 60)
82783 #define __NR_chroot (__NR_SYSCALL_BASE+ 61)
82784 #define __NR_ustat (__NR_SYSCALL_BASE+ 62)
82785 @@ -92,8 +93,8 @@
82786 #define __NR_getpgrp (__NR_SYSCALL_BASE+ 65)
82787 #define __NR_setsid (__NR_SYSCALL_BASE+ 66)
82788 #define __NR_sigaction (__NR_SYSCALL_BASE+ 67)
82789 -#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68)
82790 -#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69)
82791 + /* 68 was sys_sgetmask */
82792 + /* 69 was sys_ssetmask */
82793 #define __NR_setreuid (__NR_SYSCALL_BASE+ 70)
82794 #define __NR_setregid (__NR_SYSCALL_BASE+ 71)
82795 #define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72)
82796 @@ -108,7 +109,7 @@
82797 #define __NR_setgroups (__NR_SYSCALL_BASE+ 81)
82798 #define __NR_select (__NR_SYSCALL_BASE+ 82)
82799 #define __NR_symlink (__NR_SYSCALL_BASE+ 83)
82801 + /* 84 was sys_lstat */
82802 #define __NR_readlink (__NR_SYSCALL_BASE+ 85)
82803 #define __NR_uselib (__NR_SYSCALL_BASE+ 86)
82804 #define __NR_swapon (__NR_SYSCALL_BASE+ 87)
82805 @@ -122,10 +123,10 @@
82806 #define __NR_fchown (__NR_SYSCALL_BASE+ 95)
82807 #define __NR_getpriority (__NR_SYSCALL_BASE+ 96)
82808 #define __NR_setpriority (__NR_SYSCALL_BASE+ 97)
82809 -#define __NR_profil (__NR_SYSCALL_BASE+ 98)
82810 + /* 98 was sys_profil */
82811 #define __NR_statfs (__NR_SYSCALL_BASE+ 99)
82812 #define __NR_fstatfs (__NR_SYSCALL_BASE+100)
82813 -#define __NR_ioperm (__NR_SYSCALL_BASE+101)
82814 + /* 101 was sys_ioperm */
82815 #define __NR_socketcall (__NR_SYSCALL_BASE+102)
82816 #define __NR_syslog (__NR_SYSCALL_BASE+103)
82817 #define __NR_setitimer (__NR_SYSCALL_BASE+104)
82818 @@ -133,10 +134,10 @@
82819 #define __NR_stat (__NR_SYSCALL_BASE+106)
82820 #define __NR_lstat (__NR_SYSCALL_BASE+107)
82821 #define __NR_fstat (__NR_SYSCALL_BASE+108)
82824 + /* 109 was sys_uname */
82825 + /* 110 was sys_iopl */
82826 #define __NR_vhangup (__NR_SYSCALL_BASE+111)
82827 -#define __NR_idle (__NR_SYSCALL_BASE+112)
82828 + /* 112 was sys_idle */
82829 #define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
82830 #define __NR_wait4 (__NR_SYSCALL_BASE+114)
82831 #define __NR_swapoff (__NR_SYSCALL_BASE+115)
82832 @@ -147,7 +148,7 @@
82833 #define __NR_clone (__NR_SYSCALL_BASE+120)
82834 #define __NR_setdomainname (__NR_SYSCALL_BASE+121)
82835 #define __NR_uname (__NR_SYSCALL_BASE+122)
82836 -#define __NR_modify_ldt (__NR_SYSCALL_BASE+123)
82837 + /* 123 was sys_modify_ldt */
82838 #define __NR_adjtimex (__NR_SYSCALL_BASE+124)
82839 #define __NR_mprotect (__NR_SYSCALL_BASE+125)
82840 #define __NR_sigprocmask (__NR_SYSCALL_BASE+126)
82841 @@ -161,7 +162,7 @@
82842 #define __NR_bdflush (__NR_SYSCALL_BASE+134)
82843 #define __NR_sysfs (__NR_SYSCALL_BASE+135)
82844 #define __NR_personality (__NR_SYSCALL_BASE+136)
82845 -#define __NR_afs_syscall (__NR_SYSCALL_BASE+137) /* Syscall for Andrew File System */
82846 + /* 137 was sys_afs_syscall */
82847 #define __NR_setfsuid (__NR_SYSCALL_BASE+138)
82848 #define __NR_setfsgid (__NR_SYSCALL_BASE+139)
82849 #define __NR__llseek (__NR_SYSCALL_BASE+140)
82850 @@ -190,7 +191,7 @@
82851 #define __NR_mremap (__NR_SYSCALL_BASE+163)
82852 #define __NR_setresuid (__NR_SYSCALL_BASE+164)
82853 #define __NR_getresuid (__NR_SYSCALL_BASE+165)
82854 -#define __NR_vm86 (__NR_SYSCALL_BASE+166)
82855 + /* 166 was sys_vm86 */
82856 #define __NR_query_module (__NR_SYSCALL_BASE+167)
82857 #define __NR_poll (__NR_SYSCALL_BASE+168)
82858 #define __NR_nfsservctl (__NR_SYSCALL_BASE+169)
82859 --- linux-2.4.25/include/asm-i386/ide.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
82860 +++ linux-2.4.25/include/asm-i386/ide.h 2004-03-31 17:15:09.000000000 +0200
82861 @@ -23,39 +23,15 @@
82862 # endif
82863 #endif
82865 -static __inline__ int ide_default_irq(ide_ioreg_t base)
82867 - switch (base) {
82868 - case 0x1f0: return 14;
82869 - case 0x170: return 15;
82870 - case 0x1e8: return 11;
82871 - case 0x168: return 10;
82872 - case 0x1e0: return 8;
82873 - case 0x160: return 12;
82874 - default:
82875 - return 0;
82879 -static __inline__ ide_ioreg_t ide_default_io_base(int index)
82881 - switch (index) {
82882 - case 0: return 0x1f0;
82883 - case 1: return 0x170;
82884 - case 2: return 0x1e8;
82885 - case 3: return 0x168;
82886 - case 4: return 0x1e0;
82887 - case 5: return 0x160;
82888 - default:
82889 - return 0;
82892 +#define ide_default_io_base(i) ((ide_ioreg_t)0)
82893 +#define ide_default_irq(b) (0)
82895 static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
82897 ide_ioreg_t reg = data_port;
82898 int i;
82900 + memset(hw, 0, sizeof(*hw));
82901 for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
82902 hw->io_ports[i] = reg;
82903 reg += 1;
82904 @@ -63,7 +39,7 @@
82905 if (ctrl_port) {
82906 hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
82907 } else {
82908 - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
82909 + hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
82911 if (irq != NULL)
82912 *irq = 0;
82913 @@ -74,14 +50,25 @@
82915 #ifndef CONFIG_BLK_DEV_IDEPCI
82916 hw_regs_t hw;
82917 - int index;
82919 - for(index = 0; index < MAX_HWIFS; index++) {
82920 - memset(&hw, 0, sizeof hw);
82921 - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
82922 - hw.irq = ide_default_irq(ide_default_io_base(index));
82923 - ide_register_hw(&hw, NULL);
82925 + ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
82926 + hw.irq = 14;
82927 + ide_register_hw(&hw, NULL);
82928 + ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
82929 + hw.irq = 15;
82930 + ide_register_hw(&hw, NULL);
82931 + ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
82932 + hw.irq = 11;
82933 + ide_register_hw(&hw, NULL);
82934 + ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
82935 + hw.irq = 10;
82936 + ide_register_hw(&hw, NULL);
82937 + ide_init_hwif_ports(&hw, 0x1e0, 0x3e6, NULL);
82938 + hw.irq = 8;
82939 + ide_register_hw(&hw, NULL);
82940 + ide_init_hwif_ports(&hw, 0x160, 0x366, NULL);
82941 + hw.irq = 12;
82942 + ide_register_hw(&hw, NULL);
82943 #endif /* CONFIG_BLK_DEV_IDEPCI */
82946 --- linux-2.4.25/include/asm-i386/param.h~2.4.25-vrs2.patch 2000-10-27 20:04:43.000000000 +0200
82947 +++ linux-2.4.25/include/asm-i386/param.h 2004-03-31 17:15:09.000000000 +0200
82948 @@ -3,6 +3,16 @@
82950 #ifndef HZ
82951 #define HZ 100
82952 +#ifdef __KERNEL__
82953 +#if HZ == 100
82954 +/* X86 is defined to provide userspace with a world where HZ=100
82955 + We have to do this, (x*const)/const2 isnt optimised out because its not
82956 + a null operation as it might overflow.. */
82957 +#define hz_to_std(a) (a)
82958 +#else
82959 +#define hz_to_std(a) ((a)*(100/HZ)+((a)*(100%HZ))/HZ)
82960 +#endif
82961 +#endif
82962 #endif
82964 #define EXEC_PAGESIZE 4096
82965 --- linux-2.4.25/include/asm-i386/pgtable.h~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
82966 +++ linux-2.4.25/include/asm-i386/pgtable.h 2004-03-31 17:15:09.000000000 +0200
82967 @@ -361,7 +361,6 @@
82968 #endif /* !__ASSEMBLY__ */
82970 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
82971 -#define PageSkip(page) (0)
82972 #define kern_addr_valid(addr) (1)
82974 #define io_remap_page_range remap_page_range
82975 --- linux-2.4.25/include/asm-ia64/param.h~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
82976 +++ linux-2.4.25/include/asm-ia64/param.h 2004-03-31 17:15:09.000000000 +0200
82977 @@ -8,6 +8,10 @@
82978 * David Mosberger-Tang <davidm@hpl.hp.com>
82981 +#ifdef __KERNEL__
82982 +#define hz_to_std(a) (a)
82983 +#endif
82985 #define EXEC_PAGESIZE 65536
82987 #ifndef NGROUPS
82988 --- linux-2.4.25/include/asm-m68k/param.h~2.4.25-vrs2.patch 2001-01-04 22:00:55.000000000 +0100
82989 +++ linux-2.4.25/include/asm-m68k/param.h 2004-03-31 17:15:09.000000000 +0200
82990 @@ -3,6 +3,9 @@
82992 #ifndef HZ
82993 #define HZ 100
82994 +#ifdef __KERNEL__
82995 +#define hz_to_std(a) (a)
82996 +#endif
82997 #endif
82999 #define EXEC_PAGESIZE 8192
83000 --- linux-2.4.25/include/asm-mips/ide.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
83001 +++ linux-2.4.25/include/asm-mips/ide.h 2004-03-31 17:15:09.000000000 +0200
83002 @@ -27,7 +27,7 @@
83003 int (*ide_default_irq)(ide_ioreg_t base);
83004 ide_ioreg_t (*ide_default_io_base)(int index);
83005 void (*ide_init_hwif_ports)(hw_regs_t *hw, ide_ioreg_t data_port,
83006 - ide_ioreg_t ctrl_port, int *irq);
83007 + ide_ioreg_t ctrl_port, int *irq);
83010 extern struct ide_ops *ide_ops;
83011 --- linux-2.4.25/include/asm-ppc/param.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
83012 +++ linux-2.4.25/include/asm-ppc/param.h 2004-03-31 17:15:09.000000000 +0200
83013 @@ -3,6 +3,9 @@
83015 #ifndef HZ
83016 #define HZ 100
83017 +#ifdef __KERNEL__
83018 +#define hz_to_std(a) (a)
83019 +#endif
83020 #endif
83022 #define EXEC_PAGESIZE 4096
83023 --- linux-2.4.25/include/asm-s390/param.h~2.4.25-vrs2.patch 2001-02-13 23:13:44.000000000 +0100
83024 +++ linux-2.4.25/include/asm-s390/param.h 2004-03-31 17:15:09.000000000 +0200
83025 @@ -11,6 +11,9 @@
83027 #ifndef HZ
83028 #define HZ 100
83029 +#ifdef __KERNEL__
83030 +#define hz_to_std(a) (a)
83031 +#endif
83032 #endif
83034 #define EXEC_PAGESIZE 4096
83035 --- linux-2.4.25/include/asm-sh/param.h~2.4.25-vrs2.patch 2001-01-04 22:19:13.000000000 +0100
83036 +++ linux-2.4.25/include/asm-sh/param.h 2004-03-31 17:15:09.000000000 +0200
83037 @@ -3,6 +3,9 @@
83039 #ifndef HZ
83040 #define HZ 100
83041 +#ifdef __KERNEL__
83042 +#define hz_to_std(a) (a)
83043 +#endif
83044 #endif
83046 #define EXEC_PAGESIZE 4096
83047 --- linux-2.4.25/include/asm-sparc/param.h~2.4.25-vrs2.patch 2000-10-30 23:34:12.000000000 +0100
83048 +++ linux-2.4.25/include/asm-sparc/param.h 2004-03-31 17:15:09.000000000 +0200
83049 @@ -4,6 +4,9 @@
83051 #ifndef HZ
83052 #define HZ 100
83053 +#ifdef __KERNEL__
83054 +#define hz_to_std(a) (a)
83055 +#endif
83056 #endif
83058 #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
83059 --- linux-2.4.25/include/asm-sparc64/ide.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
83060 +++ linux-2.4.25/include/asm-sparc64/ide.h 2004-03-31 17:15:09.000000000 +0200
83061 @@ -25,21 +25,12 @@
83062 # endif
83063 #endif
83065 -static __inline__ int ide_default_irq(ide_ioreg_t base)
83067 - return 0;
83070 -static __inline__ ide_ioreg_t ide_default_io_base(int index)
83072 - return 0;
83075 static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
83077 - ide_ioreg_t reg = data_port;
83078 + ide_ioreg_t reg = data_port;
83079 int i;
83081 + memset(&hw, 0, sizeof(hw));
83082 for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
83083 hw->io_ports[i] = reg;
83084 reg += 1;
83085 @@ -60,16 +51,6 @@
83087 static __inline__ void ide_init_default_hwifs(void)
83089 -#ifndef CONFIG_BLK_DEV_IDEPCI
83090 - hw_regs_t hw;
83091 - int index;
83093 - for (index = 0; index < MAX_HWIFS; index++) {
83094 - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
83095 - hw.irq = ide_default_irq(ide_default_io_base(index));
83096 - ide_register_hw(&hw, NULL);
83098 -#endif /* CONFIG_BLK_DEV_IDEPCI */
83101 #undef SUPPORT_SLOW_DATA_PORTS
83102 --- linux-2.4.25/include/asm-sparc64/param.h~2.4.25-vrs2.patch 2000-10-30 23:34:12.000000000 +0100
83103 +++ linux-2.4.25/include/asm-sparc64/param.h 2004-03-31 17:15:09.000000000 +0200
83104 @@ -4,6 +4,9 @@
83106 #ifndef HZ
83107 #define HZ 100
83108 +#ifdef __KERNEL__
83109 +#define hz_to_std(a) (a)
83110 +#endif
83111 #endif
83113 #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
83114 --- linux-2.4.25/include/linux/console_struct.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
83115 +++ linux-2.4.25/include/linux/console_struct.h 2004-03-31 17:15:09.000000000 +0200
83116 @@ -7,6 +7,8 @@
83117 * Fields marked with [#] must be set by the low-level driver.
83118 * Fields marked with [!] can be changed by the low-level driver
83119 * to achieve effects such as fast scrolling by changing the origin.
83121 + * 11/07/1998 RMK Changed vc_state to be a function pointer
83124 #ifndef _LINUX_CONSOLE_STRUCT_H_
83125 @@ -34,7 +36,11 @@
83126 unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
83127 unsigned int vc_x, vc_y; /* Cursor position */
83128 unsigned int vc_top, vc_bottom; /* Scrolling region */
83129 +#ifdef CONSOLE_WIP
83130 + int (*vc_state)(int currcons, struct tty_struct *tty, unsigned int c);
83131 +#else
83132 unsigned int vc_state; /* Escape sequence parser state */
83133 +#endif
83134 unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
83135 unsigned long vc_origin; /* [!] Start of real screen */
83136 unsigned long vc_scr_end; /* [!] End of real screen */
83137 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
83138 +++ linux-2.4.25/include/linux/cpufreq.h 2004-03-31 17:15:09.000000000 +0200
83139 @@ -0,0 +1,94 @@
83141 + * linux/include/linux/cpufreq.h
83143 + * Copyright (C) 2001 Russell King
83145 + * $Id: cpufreq.h,v 1.5.2.1 2002/05/03 13:26:27 rmk Exp $
83147 + * This program is free software; you can redistribute it and/or modify
83148 + * it under the terms of the GNU General Public License version 2 as
83149 + * published by the Free Software Foundation.
83150 + */
83151 +#ifndef _LINUX_CPUFREQ_H
83152 +#define _LINUX_CPUFREQ_H
83154 +#include <linux/config.h>
83155 +#include <linux/notifier.h>
83157 +#ifndef CONFIG_SMP
83158 +#define cpufreq_current(cpu) ((void)(cpu), __cpufreq_cur)
83159 +#define cpufreq_max(cpu) ((void)(cpu), __cpufreq_max)
83160 +#define cpufreq_min(cpu) ((void)(cpu), __cpufreq_min)
83161 +#else
83163 + * Should be something like:
83165 + * typedef struct {
83166 + * u_int current;
83167 + * u_int max;
83168 + * u_int min;
83169 + * } __cacheline_aligned cpufreq_info_t;
83171 + * static cpufreq_info_t cpufreq_info;
83173 + * #define cpufreq_current(cpu) (cpufreq_info[cpu].current)
83174 + * #define cpufreq_max(cpu) (cpufreq_info[cpu].max)
83175 + * #define cpufreq_min(cpu) (cpufreq_info[cpu].min)
83177 + * Maybe we should find some other per-cpu structure to
83178 + * bury this in?
83179 + */
83180 +#error fill in SMP version
83181 +#endif
83183 +struct cpufreq_info {
83184 + unsigned int old_freq;
83185 + unsigned int new_freq;
83189 + * The max and min frequency rates that the registered device
83190 + * can tolerate. Never set any element this structure directly -
83191 + * always use cpu_updateminmax.
83192 + */
83193 +struct cpufreq_minmax {
83194 + unsigned int min_freq;
83195 + unsigned int max_freq;
83196 + unsigned int cur_freq;
83197 + unsigned int new_freq;
83200 +static inline
83201 +void cpufreq_updateminmax(void *arg, unsigned int min, unsigned int max)
83203 + struct cpufreq_minmax *minmax = arg;
83205 + if (minmax->min_freq < min)
83206 + minmax->min_freq = min;
83207 + if (minmax->max_freq > max)
83208 + minmax->max_freq = max;
83211 +#define CPUFREQ_MINMAX (0)
83212 +#define CPUFREQ_PRECHANGE (1)
83213 +#define CPUFREQ_POSTCHANGE (2)
83215 +int cpufreq_register_notifier(struct notifier_block *nb);
83216 +int cpufreq_unregister_notifier(struct notifier_block *nb);
83218 +int cpufreq_setmax(void);
83219 +int cpufreq_restore(void);
83220 +int cpufreq_set(unsigned int khz);
83221 +unsigned int cpufreq_get(int cpu);
83224 + * These two functions are only available at init time.
83225 + */
83226 +void cpufreq_init(unsigned int khz,
83227 + unsigned int min_freq,
83228 + unsigned int max_freq);
83230 +void cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
83231 + void (*setspeed)(unsigned int));
83233 +#endif
83234 --- linux-2.4.25/include/linux/i2c-id.h~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
83235 +++ linux-2.4.25/include/linux/i2c-id.h 2004-03-31 17:15:09.000000000 +0200
83236 @@ -20,16 +20,16 @@
83237 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
83238 /* ------------------------------------------------------------------------- */
83240 -/* $Id: i2c-id.h,v 1.35 2001/08/12 17:22:20 mds Exp $ */
83241 +/* $Id: i2c-id.h,v 1.52 2002/07/10 13:28:44 abz Exp $ */
83243 #ifndef I2C_ID_H
83244 #define I2C_ID_H
83246 * This file is part of the i2c-bus package and contains the identifier
83247 * values for drivers, adapters and other folk populating these serial
83248 - * worlds.
83249 + * worlds.
83251 - * These will change often (i.e. additions) , therefore this has been
83252 + * These will change often (i.e. additions) , therefore this has been
83253 * separated from the functional interface definitions of the i2c api.
83256 @@ -38,10 +38,10 @@
83257 * ---- Driver types -----------------------------------------------------
83258 * device id name + number function description, i2c address(es)
83260 - * Range 1000-1999 range is defined in sensors/sensors.h
83261 - * Range 0x100 - 0x1ff is for V4L2 Common Components
83262 + * Range 1000-1999 range is defined in sensors/sensors.h
83263 + * Range 0x100 - 0x1ff is for V4L2 Common Components
83264 * Range 0xf000 - 0xffff is reserved for local experimentation, and should
83265 - * never be used in official drivers
83266 + * never be used in official drivers
83269 #define I2C_DRIVERID_MSP3400 1
83270 @@ -90,7 +90,12 @@
83271 #define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */
83272 #define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
83273 #define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
83274 +#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */
83275 +#define I2C_DRIVERID_DS1307 47 /* DS1307 real time clock */
83276 #define I2C_DRIVERID_ADV7175 48 /* ADV 7175/7176 video encoder */
83277 +#define I2C_DRIVERID_ZR36067 49 /* Zoran 36067 video encoder */
83278 +#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
83279 +#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
83280 #define I2C_DRIVERID_MAX1617 56 /* temp sensor */
83281 #define I2C_DRIVERID_SAA7191 57 /* video decoder */
83282 #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
83283 @@ -102,8 +107,10 @@
83285 #define I2C_DRIVERID_I2CDEV 900
83286 #define I2C_DRIVERID_I2CPROC 901
83287 +#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
83288 +#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */
83290 -/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
83291 +/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
83292 These were originally in sensors.h in the lm_sensors package */
83293 #define I2C_DRIVERID_LM78 1002
83294 #define I2C_DRIVERID_LM75 1003
83295 @@ -131,6 +138,12 @@
83296 #define I2C_DRIVERID_ADM1024 1025
83297 #define I2C_DRIVERID_IT87 1026
83298 #define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
83299 +#define I2C_DRIVERID_FSCPOS 1028
83300 +#define I2C_DRIVERID_FSCSCY 1029
83301 +#define I2C_DRIVERID_PCF8591 1030
83302 +#define I2C_DRIVERID_SMSC47M1 1031
83303 +#define I2C_DRIVERID_VT1211 1032
83304 +#define I2C_DRIVERID_LM92 1033
83307 * ---- Adapter types ----------------------------------------------------
83308 @@ -147,7 +160,8 @@
83309 #define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */
83310 #define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */
83311 #define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */
83313 +#define I2C_ALGO_IIC 0x080000 /* ITE IIC bus */
83314 +#define I2C_ALGO_SAA7134 0x090000
83315 #define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
83317 #define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
83318 @@ -156,13 +170,15 @@
83320 #define I2C_ALGO_SGI 0x130000 /* SGI algorithm */
83322 +#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
83324 #define I2C_ALGO_EXP 0x800000 /* experimental */
83326 #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
83327 #define I2C_ALGO_SHIFT 0x10 /* right shift to get index values */
83329 #define I2C_HW_ADAPS 0x10000 /* # adapter types */
83330 -#define I2C_HW_MASK 0xffff
83331 +#define I2C_HW_MASK 0xffff
83334 /* hw specific modules that are defined per algorithm layer
83335 @@ -182,9 +198,13 @@
83336 #define I2C_HW_B_I810 0x0a /* Intel I810 */
83337 #define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
83338 #define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
83339 +#define I2C_HW_B_SAVG 0x0d /* Savage 4 */
83340 #define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
83341 #define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
83342 #define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
83343 +#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */
83344 +#define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface */
83345 +#define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */
83347 /* --- PCF 8584 based algorithms */
83348 #define I2C_HW_P_LP 0x00 /* Parallel port interface */
83349 @@ -197,6 +217,12 @@
83350 /* --- MPC8xx PowerPC adapters */
83351 #define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */
83353 +/* --- ITE based algorithms */
83354 +#define I2C_HW_I_IIC 0x00 /* controller on the ITE */
83356 +/* --- PowerPC on-chip adapters */
83357 +#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
83359 /* --- Broadcom SiByte adapters */
83360 #define I2C_HW_SIBYTE 0x00
83362 --- linux-2.4.25/include/linux/ide.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
83363 +++ linux-2.4.25/include/linux/ide.h 2004-03-31 17:15:09.000000000 +0200
83364 @@ -287,7 +287,9 @@
83365 * Check for an interrupt and acknowledge the interrupt status
83367 struct hwif_s;
83368 +struct ide_drive_s;
83369 typedef int (ide_ack_intr_t)(struct hwif_s *);
83370 +typedef void (ide_xfer_data_t)(struct ide_drive_s *, void *, unsigned int);
83372 #ifndef NO_DMA
83373 #define NO_DMA 255
83374 @@ -311,10 +313,14 @@
83375 typedef struct hw_regs_s {
83376 ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
83377 int irq; /* our irq number */
83378 - int dma; /* our dma entry */
83379 + int dma; /* our dma number */
83380 ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
83381 + ide_xfer_data_t *ide_output_data; /* write data to i/face */
83382 + ide_xfer_data_t *ide_input_data; /* read data from i/face */
83383 + ide_xfer_data_t *atapi_output_bytes; /* write bytes to i/face */
83384 + ide_xfer_data_t *atapi_input_bytes; /* read bytes from i/face */
83385 void *priv; /* interface specific data */
83386 - hwif_chipset_t chipset;
83387 + hwif_chipset_t chipset;
83388 sata_ioreg_t sata_scr[SATA_NR_PORTS];
83389 sata_ioreg_t sata_misc[SATA_NR_PORTS];
83390 } hw_regs_t;
83391 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
83392 +++ linux-2.4.25/include/linux/l3/algo-bit.h 2004-03-31 17:15:09.000000000 +0200
83393 @@ -0,0 +1,39 @@
83395 + * linux/include/linux/l3/algo-bit.h
83397 + * Copyright (C) 2001 Russell King, All Rights Reserved.
83399 + * This program is free software; you can redistribute it and/or modify
83400 + * it under the terms of the GNU General Public License as published by
83401 + * the Free Software Foundation; either version 2 of the License.
83403 + * L3 Bus bit-banging algorithm. Derived from i2c-algo-bit.h by
83404 + * Simon G. Vogl.
83405 + */
83406 +#ifndef L3_ALGO_BIT_H
83407 +#define L3_ALGO_BIT_H 1
83409 +#include <linux/l3/l3.h>
83411 +struct l3_algo_bit_data {
83412 + void (*setdat) (void *data, int state);
83413 + void (*setclk) (void *data, int state);
83414 + void (*setmode)(void *data, int state);
83415 + void (*setdir) (void *data, int in); /* set data direction */
83416 + int (*getdat) (void *data);
83418 + void *data;
83420 + /* bus timings (us) */
83421 + int data_hold;
83422 + int data_setup;
83423 + int clock_high;
83424 + int mode_hold;
83425 + int mode_setup;
83426 + int mode;
83429 +int l3_bit_add_bus(struct l3_adapter *);
83430 +int l3_bit_del_bus(struct l3_adapter *);
83432 +#endif
83433 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
83434 +++ linux-2.4.25/include/linux/l3/l3.h 2004-03-31 17:15:09.000000000 +0200
83435 @@ -0,0 +1,208 @@
83437 + * linux/include/linux/l3/l3.h
83439 + * Copyright (C) 2001 Russell King, All Rights Reserved.
83441 + * This program is free software; you can redistribute it and/or modify
83442 + * it under the terms of the GNU General Public License as published by
83443 + * the Free Software Foundation; either version 2 of the License.
83445 + * Derived from i2c.h by Simon G. Vogl
83446 + */
83447 +#ifndef L3_H
83448 +#define L3_H
83450 +struct l3_msg {
83451 + unsigned char addr; /* slave address */
83452 + unsigned char flags;
83453 +#define L3_M_RD 0x01
83454 +#define L3_M_NOADDR 0x02
83455 + unsigned short len; /* msg length */
83456 + unsigned char *buf; /* pointer to msg data */
83459 +#ifdef __KERNEL__
83461 +#include <linux/types.h>
83462 +#include <linux/list.h>
83464 +struct l3_client;
83466 +struct l3_ops {
83467 + int (*open)(struct l3_client *);
83468 + int (*command)(struct l3_client *, int cmd, void *arg);
83469 + void (*close)(struct l3_client *);
83473 + * A driver is capable of handling one or more physical devices present on
83474 + * L3 adapters. This information is used to inform the driver of adapter
83475 + * events.
83476 + */
83477 +struct l3_driver {
83478 + /*
83479 + * This name is used to uniquely identify the driver.
83480 + * It should be the same as the module name.
83481 + */
83482 + char name[32];
83484 + /*
83485 + * Notifies the driver that a new client wishes to use its
83486 + * services. Note that the module use count will be increased
83487 + * prior to this function being called. In addition, the
83488 + * clients driver and adapter fields will have been setup.
83489 + */
83490 + int (*attach_client)(struct l3_client *);
83492 + /*
83493 + * Notifies the driver that the client has finished with its
83494 + * services, and any memory that it allocated for this client
83495 + * should be cleaned up. In addition the chip should be
83496 + * shut down.
83497 + */
83498 + void (*detach_client)(struct l3_client *);
83500 + /*
83501 + * Possible operations on the driver.
83502 + */
83503 + struct l3_ops *ops;
83505 + /*
83506 + * Module structure, if any.
83507 + */
83508 + struct module *owner;
83510 + /*
83511 + * drivers list
83512 + */
83513 + struct list_head drivers;
83516 +struct l3_adapter;
83518 +struct l3_algorithm {
83519 + /* textual description */
83520 + char name[32];
83522 + /* perform bus transactions */
83523 + int (*xfer)(struct l3_adapter *, struct l3_msg msgs[], int num);
83526 +struct semaphore;
83529 + * l3_adapter is the structure used to identify a physical L3 bus along
83530 + * with the access algorithms necessary to access it.
83531 + */
83532 +struct l3_adapter {
83533 + /*
83534 + * This name is used to uniquely identify the adapter.
83535 + * It should be the same as the module name.
83536 + */
83537 + char name[32];
83539 + /*
83540 + * the algorithm to access the bus
83541 + */
83542 + struct l3_algorithm *algo;
83544 + /*
83545 + * Algorithm specific data
83546 + */
83547 + void *algo_data;
83549 + /*
83550 + * This may be NULL, or should point to the module struct
83551 + */
83552 + struct module *owner;
83554 + /*
83555 + * private data for the adapter
83556 + */
83557 + void *data;
83559 + /*
83560 + * Our lock. Unlike the i2c layer, we allow this to be used for
83561 + * other stuff, like the i2c layer lock. Some people implement
83562 + * i2c stuff using the same signals as the l3 bus.
83563 + */
83564 + struct semaphore *lock;
83566 + /*
83567 + * List of attached clients.
83568 + */
83569 + struct list_head clients;
83571 + /*
83572 + * List of all adapters.
83573 + */
83574 + struct list_head adapters;
83578 + * l3_client identifies a single device (i.e. chip) that is connected to an
83579 + * L3 bus. The behaviour is defined by the routines of the driver. This
83580 + * function is mainly used for lookup & other admin. functions.
83581 + */
83582 +struct l3_client {
83583 + struct l3_adapter *adapter; /* the adapter we sit on */
83584 + struct l3_driver *driver; /* and our access routines */
83585 + void *driver_data; /* private driver data */
83586 + struct list_head __adap;
83590 +extern int l3_add_adapter(struct l3_adapter *);
83591 +extern int l3_del_adapter(struct l3_adapter *);
83593 +extern int l3_add_driver(struct l3_driver *);
83594 +extern int l3_del_driver(struct l3_driver *);
83596 +extern int l3_attach_client(struct l3_client *, const char *, const char *);
83597 +extern int l3_detach_client(struct l3_client *);
83599 +extern int l3_transfer(struct l3_adapter *, struct l3_msg msgs[], int);
83600 +extern int l3_write(struct l3_client *, int, const char *, int);
83601 +extern int l3_read(struct l3_client *, int, char *, int);
83603 +/**
83604 + * l3_command - send a command to a L3 device driver
83605 + * @client: registered client structure
83606 + * @cmd: device driver command
83607 + * @arg: device driver arguments
83609 + * Ask the L3 device driver to perform some function. Further information
83610 + * should be sought from the device driver in question.
83612 + * Returns negative error code on failure.
83613 + */
83614 +static inline int l3_command(struct l3_client *clnt, int cmd, void *arg)
83616 + struct l3_ops *ops = clnt->driver->ops;
83617 + int ret = -EINVAL;
83619 + if (ops && ops->command)
83620 + ret = ops->command(clnt, cmd, arg);
83622 + return ret;
83625 +static inline int l3_open(struct l3_client *clnt)
83627 + struct l3_ops *ops = clnt->driver->ops;
83628 + int ret = 0;
83630 + if (ops && ops->open)
83631 + ret = ops->open(clnt);
83632 + return ret;
83635 +static inline void l3_close(struct l3_client *clnt)
83637 + struct l3_ops *ops = clnt->driver->ops;
83638 + if (ops && ops->close)
83639 + ops->close(clnt);
83641 +#endif
83643 +#endif /* L3_H */
83644 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
83645 +++ linux-2.4.25/include/linux/l3/uda1341.h 2004-03-31 17:15:09.000000000 +0200
83646 @@ -0,0 +1,50 @@
83648 + * linux/include/linux/l3/uda1341.h
83650 + * Philips UDA1341 mixer device driver
83652 + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
83654 + * This program is free software; you can redistribute it and/or
83655 + * modify it under the terms of the GNU General Public License.
83656 + */
83658 +#define UDA1341_NAME "uda1341"
83660 +struct uda1341_cfg {
83661 + unsigned int fs:16;
83662 + unsigned int format:3;
83665 +#define FMT_I2S 0
83666 +#define FMT_LSB16 1
83667 +#define FMT_LSB18 2
83668 +#define FMT_LSB20 3
83669 +#define FMT_MSB 4
83670 +#define FMT_LSB16MSB 5
83671 +#define FMT_LSB18MSB 6
83672 +#define FMT_LSB20MSB 7
83674 +#define L3_UDA1341_CONFIGURE 0x13410001
83676 +struct l3_gain {
83677 + unsigned int left:8;
83678 + unsigned int right:8;
83679 + unsigned int unused:8;
83680 + unsigned int channel:8;
83683 +#define L3_SET_VOLUME 0x13410002
83684 +#define L3_SET_TREBLE 0x13410003
83685 +#define L3_SET_BASS 0x13410004
83686 +#define L3_SET_GAIN 0x13410005
83688 +struct l3_agc {
83689 + unsigned int level:8;
83690 + unsigned int enable:1;
83691 + unsigned int attack:7;
83692 + unsigned int decay:8;
83693 + unsigned int channel:8;
83696 +#define L3_INPUT_AGC 0x13410006
83697 --- linux-2.4.25/include/linux/mm.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
83698 +++ linux-2.4.25/include/linux/mm.h 2004-03-31 17:15:09.000000000 +0200
83699 @@ -685,6 +685,12 @@
83701 extern struct page * vmalloc_to_page(void *addr);
83703 +#ifndef __arm__
83704 +#define memc_update_addr(x,y,z)
83705 +#define memc_update_mm(x)
83706 +#define memc_clear(x,y)
83707 +#endif
83709 #endif /* __KERNEL__ */
83711 #endif
83712 --- linux-2.4.25/include/linux/pci.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
83713 +++ linux-2.4.25/include/linux/pci.h 2004-03-31 17:15:09.000000000 +0200
83714 @@ -410,6 +410,7 @@
83716 char name[90]; /* device name */
83717 char slot_name[8]; /* slot name */
83718 + u32 saved_state[16]; /* for saving the config space before suspend */
83719 int active; /* ISAPnP: device is active */
83720 int ro; /* ISAPnP: read only */
83721 unsigned short regs; /* ISAPnP: supported registers */
83722 @@ -496,6 +497,8 @@
83724 struct pbus_set_ranges_data
83726 + int found_vga:1;
83727 + int prefetch_valid:1;
83728 unsigned long io_start, io_end;
83729 unsigned long mem_start, mem_end;
83730 unsigned long prefetch_start, prefetch_end;
83731 @@ -637,6 +640,8 @@
83732 int pci_restore_state(struct pci_dev *dev, u32 *buffer);
83733 int pci_set_power_state(struct pci_dev *dev, int state);
83734 int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
83735 +int pci_generic_suspend_save(struct pci_dev *pdev, u32 state);
83736 +int pci_generic_resume_restore(struct pci_dev *pdev);
83738 /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
83740 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
83741 +++ linux-2.4.25/include/linux/pld/pld_epxa.h 2004-03-31 17:15:09.000000000 +0200
83742 @@ -0,0 +1,35 @@
83743 +#ifndef __LINUX_EPXAPLD_H
83744 +#define __LINUX_EPXAPLD_H
83747 + * linux/drivers/char/pld/epxapld.h
83749 + * Pld driver for Altera EPXA Excalibur devices
83751 + * Copyright 2001 Altera Corporation
83753 + * This program is free software; you can redistribute it and/or modify
83754 + * it under the terms of the GNU General Public License as published by
83755 + * the Free Software Foundation; either version 2 of the License, or
83756 + * (at your option) any later version.
83758 + * This program is distributed in the hope that it will be useful,
83759 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
83760 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83761 + * GNU General Public License for more details.
83763 + * You should have received a copy of the GNU General Public License
83764 + * along with this program; if not, write to the Free Software
83765 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
83767 + * $Id: $
83769 + */
83770 +#define PLD_IOC_MAGIC 'p'
83771 +#if !defined(KERNEL) || defined(CONFIG_PLD_HOTSWAP)
83772 +#define PLD_IOC_ADD_PLD_DEV _IOW(PLD_IOC_MAGIC, 0xa0, struct pldhs_dev_desc)
83773 +#define PLD_IOC_REMOVE_PLD_DEVS _IO(PLD_IOC_MAGIC, 0xa1)
83774 +#define PLD_IOC_SET_INT_MODE _IOW(PLD_IOC_MAGIC, 0xa2, int)
83775 +#endif
83777 +#endif
83778 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
83779 +++ linux-2.4.25/include/linux/pld/pld_hotswap.h 2004-03-31 17:15:09.000000000 +0200
83780 @@ -0,0 +1,87 @@
83781 +#ifndef __LINUX_PLD_HOTSWAP_H
83782 +#define __LINUX_PLD_HOTSWAP_H
83784 + * linux/drivers/char/pld/pld_hotswap.h
83786 + * Pld driver for Altera EPXA Excalibur devices
83788 + * Copyright 2001 Altera Corporation
83790 + * This program is free software; you can redistribute it and/or modify
83791 + * it under the terms of the GNU General Public License as published by
83792 + * the Free Software Foundation; either version 2 of the License, or
83793 + * (at your option) any later version.
83795 + * This program is distributed in the hope that it will be useful,
83796 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
83797 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83798 + * GNU General Public License for more details.
83800 + * You should have received a copy of the GNU General Public License
83801 + * along with this program; if not, write to the Free Software
83802 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
83804 + * $Id: $
83806 + */
83809 + * The pld_hotswap ops contain the basic operation required for adding
83810 + * and removing devices from the system.
83811 + */
83813 +struct pldhs_dev_info{
83814 + unsigned int size;
83815 + unsigned short vendor_id;
83816 + unsigned short product_id;
83817 + unsigned char fsize;
83818 + unsigned char nsize;
83819 + unsigned short pssize;
83820 + unsigned short cmdsize;
83821 + unsigned char irq;
83822 + unsigned char version;
83823 + unsigned int base_addr;
83824 + unsigned int reg_size;
83827 +struct pldhs_dev_desc{
83828 + struct pldhs_dev_info* info;
83829 + char* name;
83830 + void* data;
83833 +#include <linux/pld/pld_epxa.h>
83836 +#ifdef __KERNEL__
83837 +struct pld_hotswap_ops{
83838 + struct list_head list;
83839 + char* name;
83840 + int (*add_device)(struct pldhs_dev_info *dev_info, void* dev_ps_data);
83841 + int (*remove_devices)(void);
83842 + int (*proc_read)(char* buf,char** start,off_t offset,int count,int *eof,void *data);
83846 + * These functions are called by the device drivers to register functions
83847 + * which should be called when devices are added and removed
83848 + */
83849 +extern int pldhs_register_driver(struct pld_hotswap_ops *drv);
83850 +extern int pldhs_unregister_driver(char *driver);
83853 + * These functions are called by the pld loader to add and remove
83854 + * device instances from the system. The call the functions regsistered
83855 + * the the particular deriver for this purpose
83856 + */
83857 +extern int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data);
83858 +extern int pldhs_remove_devices(void);
83860 +/* Macro for formatting data to appear in the proc/pld file */
83861 +#define PLDHS_READ_PROC_DATA(buf,name,index,base,irq,ps_string) \
83862 + sprintf(buf,":%s:%d Base Address, %#lx, IRQ, %d#\n%s\n",\
83863 + name,index,base,irq,ps_string)
83865 +#endif
83867 +#endif
83868 --- linux-2.4.25/include/linux/serial.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
83869 +++ linux-2.4.25/include/linux/serial.h 2004-03-31 17:15:09.000000000 +0200
83870 @@ -48,7 +48,7 @@
83871 unsigned char *iomem_base;
83872 unsigned short iomem_reg_shift;
83873 unsigned int port_high;
83874 - int reserved[1];
83875 + unsigned long iomap_base; /* cookie passed into ioremap */
83879 --- linux-2.4.25/include/linux/serialP.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
83880 +++ linux-2.4.25/include/linux/serialP.h 2004-03-31 17:15:09.000000000 +0200
83881 @@ -157,8 +157,8 @@
83882 struct pci_dev *dev;
83885 -extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
83886 -extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
83887 +//extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
83888 +//extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
83890 #ifndef PCI_ANY_ID
83891 #define PCI_ANY_ID (~0)
83892 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
83893 +++ linux-2.4.25/include/linux/serial_core.h 2004-03-31 17:15:09.000000000 +0200
83894 @@ -0,0 +1,441 @@
83896 + * linux/drivers/char/serial_core.h
83898 + * Copyright (C) 2000 Deep Blue Solutions Ltd.
83900 + * This program is free software; you can redistribute it and/or modify
83901 + * it under the terms of the GNU General Public License as published by
83902 + * the Free Software Foundation; either version 2 of the License, or
83903 + * (at your option) any later version.
83905 + * This program is distributed in the hope that it will be useful,
83906 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
83907 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83908 + * GNU General Public License for more details.
83910 + * You should have received a copy of the GNU General Public License
83911 + * along with this program; if not, write to the Free Software
83912 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
83914 + * $Id: serial_core.h,v 1.9.2.3 2001/11/26 22:32:45 rmk Exp $
83915 + */
83918 + * The type definitions. These are from Ted Ts'o's serial.h
83919 + */
83920 +#define PORT_UNKNOWN 0
83921 +#define PORT_8250 1
83922 +#define PORT_16450 2
83923 +#define PORT_16550 3
83924 +#define PORT_16550A 4
83925 +#define PORT_CIRRUS 5
83926 +#define PORT_16650 6
83927 +#define PORT_16650V2 7
83928 +#define PORT_16750 8
83929 +#define PORT_STARTECH 9
83930 +#define PORT_16C950 10
83931 +#define PORT_16654 11
83932 +#define PORT_16850 12
83933 +#define PORT_RSA 13
83934 +#define PORT_NS16550A 14
83935 +#define PORT_MAX_8250 14 /* max port ID */
83938 + * ARM specific type numbers. These are not currently guaranteed
83939 + * to be implemented, and will change in the future. These are
83940 + * separate so any additions to the old serial.c that occur before
83941 + * we are merged can be easily merged here.
83942 + */
83943 +#define PORT_AMBA 32
83944 +#define PORT_CLPS711X 33
83945 +#define PORT_SA1100 34
83946 +#define PORT_UART00 35
83947 +#define PORT_21285 37
83949 +/* Sparc type numbers. */
83950 +#define PORT_SUNZILOG 38
83951 +#define PORT_SUNSAB 39
83953 +/* NEC v850. */
83954 +#define PORT_NB85E_UART 40
83956 +/* NEC PC-9800 */
83957 +#define PORT_8251_PC98 41
83958 +#define PORT_19K_PC98 42
83959 +#define PORT_FIFO_PC98 43
83960 +#define PORT_VFAST_PC98 44
83961 +#define PORT_PC9861 45
83962 +#define PORT_PC9801_101 46
83964 +/* DZ */
83965 +#define PORT_DZ 47
83967 +#define PORT_OMAHA 48
83968 +#define PORT_AT91RM9200 49
83971 +#ifdef __KERNEL__
83973 +#include <linux/config.h>
83974 +#include <linux/interrupt.h>
83975 +#include <linux/circ_buf.h>
83976 +#include <linux/serial.h>
83977 +#include <linux/spinlock.h>
83979 +struct uart_port;
83980 +struct uart_info;
83981 +struct serial_struct;
83984 + * This structure describes all the operations that can be
83985 + * done on the physical hardware.
83986 + */
83987 +struct uart_ops {
83988 + unsigned int (*tx_empty)(struct uart_port *);
83989 + void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
83990 + unsigned int (*get_mctrl)(struct uart_port *);
83991 + void (*stop_tx)(struct uart_port *, unsigned int tty_stop);
83992 + void (*start_tx)(struct uart_port *, unsigned int tty_start);
83993 + void (*send_xchar)(struct uart_port *, char ch);
83994 + void (*stop_rx)(struct uart_port *);
83995 + void (*enable_ms)(struct uart_port *);
83996 + void (*break_ctl)(struct uart_port *, int ctl);
83997 + int (*startup)(struct uart_port *);
83998 + void (*shutdown)(struct uart_port *);
83999 + void (*change_speed)(struct uart_port *, unsigned int cflag, unsigned int iflag, unsigned int quot);
84000 + void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate);
84001 + int (*set_wake)(struct uart_port *, unsigned int state);
84003 + /*
84004 + * Return a string describing the type of the port
84005 + */
84006 + const char *(*type)(struct uart_port *);
84008 + /*
84009 + * Release IO and memory resources used by the port.
84010 + * This includes iounmap if necessary.
84011 + */
84012 + void (*release_port)(struct uart_port *);
84014 + /*
84015 + * Request IO and memory resources used by the port.
84016 + * This includes iomapping the port if necessary.
84017 + */
84018 + int (*request_port)(struct uart_port *);
84019 + void (*config_port)(struct uart_port *, int);
84020 + int (*verify_port)(struct uart_port *, struct serial_struct *);
84021 + int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
84024 +#define UART_CONFIG_TYPE (1 << 0)
84025 +#define UART_CONFIG_IRQ (1 << 1)
84027 +struct uart_icount {
84028 + __u32 cts;
84029 + __u32 dsr;
84030 + __u32 rng;
84031 + __u32 dcd;
84032 + __u32 rx;
84033 + __u32 tx;
84034 + __u32 frame;
84035 + __u32 overrun;
84036 + __u32 parity;
84037 + __u32 brk;
84038 + __u32 buf_overrun;
84041 +struct uart_port {
84042 + spinlock_t lock; /* port lock */
84043 + unsigned int iobase; /* in/out[bwl] */
84044 + char *membase; /* read/write[bwl] */
84045 + unsigned char fifosize; /* tx fifo size */
84046 + unsigned char x_char; /* xon/xoff char */
84047 + unsigned char regshift; /* reg offset shift */
84048 + unsigned char iotype; /* io access style */
84050 +#define UPIO_PORT (0)
84051 +#define UPIO_HUB6 (1)
84052 +#define UPIO_MEM (2)
84054 + unsigned int read_status_mask; /* driver specific */
84055 + unsigned int ignore_status_mask; /* driver specific */
84057 + struct uart_info *info; /* pointer to parent info */
84058 + struct uart_icount icount; /* statistics */
84060 + struct console *cons; /* struct console, if any */
84061 + unsigned long sysrq; /* sysrq timeout */
84063 + unsigned int flags;
84065 +#define UPF_HUP_NOTIFY ASYNC_HUP_NOTIFY
84066 +#define UPF_FOURPORT ASYNC_FOURPORT
84067 +#define UPF_SAK ASYNC_SAK
84068 +#define UPF_SPLIT_TERMIOS ASYNC_SPLIT_TERMIOS
84069 +#define UPF_SPD_MASK (0x1030)
84070 +#define UPF_SPD_HI (0x0010)
84071 +#define UPF_SPD_VHI (0x0020)
84072 +#define UPF_SPD_CUST (0x0030)
84073 +#define UPF_SPD_SHI (0x1000)
84074 +#define UPF_SPD_WARP (0x1010)
84075 +#define UPF_SKIP_TEST ASYNC_SKIP_TEST
84076 +#define UPF_AUTO_IRQ ASYNC_AUTO_IRQ
84077 +#define UPF_SESSION_LOCKOUT ASYNC_SESSION_LOCKOUT
84078 +#define UPF_PGRP_LOCKOUT ASYNCPGRP_LOCKOUT
84079 +#define UPF_CALLOUT_NOHUP ASYNC_CALLOUT_NOHUP
84080 +#define UPF_HARDPPS_CD ASYNC_HARDPPS_CD
84081 + /* 12 */
84082 +#define UPF_LOW_LATENCY ASYNC_LOW_LATENCY
84083 +#define UPF_BUGGY_UART ASYNC_BUGGY_UART
84084 +#define UPF_AUTOPROBE ASYNC_AUTOPROBE
84085 +#define UPF_MAGIC_MULTIPLIER (1 << 16)
84086 +#define UPF_BOOT_ONLYMCA ASYNC_BOOT_ONLYMCA
84087 +#define UPF_CONS_FLOW ASYNC_CONS_FLOW
84088 +#define UPF_SHARE_IRQ ASYNC_SHARE_IRQ
84089 +#define UPF_BOOT_AUTOCONF ASYNC_BOOT_AUTOCONF
84090 +#define UPF_RESOURCES (1 << 30)
84091 +#define UPF_IOREMAP (1 << 31)
84093 +#define UPF_CHANGE_MASK (0x17fff)
84094 +#define UPF_USR_MASK (UPF_SPD_MASK|UPF_LOW_LATENCY)
84096 + unsigned int mctrl; /* current modem ctrl settings */
84097 + unsigned int timeout; /* character-based timeout */
84098 + unsigned int type; /* port type */
84099 + struct uart_ops *ops;
84100 + unsigned int uartclk; /* base uart clock */
84101 + unsigned int custom_divisor;
84102 + unsigned int irq; /* irq number */
84103 + unsigned int line; /* port index */
84104 + unsigned long mapbase; /* for ioremap */
84105 + unsigned char hub6; /* this should be in the 8250 driver */
84106 + unsigned char unused[7];
84110 + * This is the state information which is persistent across opens.
84111 + * The low level driver must not to touch any elements contained
84112 + * within.
84113 + */
84114 +struct uart_state {
84115 + unsigned int close_delay;
84116 + unsigned int closing_wait;
84118 +#define USF_CLOSING_WAIT_INF (0)
84119 +#define USF_CLOSING_WAIT_NONE (65535)
84121 + struct termios normal_termios;
84122 + struct termios callout_termios;
84124 + int count;
84125 + struct uart_info *info;
84126 + struct uart_port *port;
84128 + struct semaphore sem;
84129 +#ifdef CONFIG_PM
84130 + struct pm_dev *pm;
84131 +#endif
84134 +#define UART_XMIT_SIZE 1024
84136 + * This is the state information which is only valid when the port
84137 + * is open; it may be freed by the core driver once the device has
84138 + * been closed. Either the low level driver or the core can modify
84139 + * stuff here.
84140 + */
84141 +struct uart_info {
84142 + struct tty_struct *tty;
84143 + struct circ_buf xmit;
84144 + unsigned int flags;
84147 + * These are the flags that specific to info->flags, and reflect our
84148 + * internal state. They can not be accessed via port->flags. Low
84149 + * level drivers must not change these, but may query them instead.
84150 + */
84151 +#define UIF_CHECK_CD ASYNC_CHECK_CD
84152 +#define UIF_CTS_FLOW ASYNC_CTS_FLOW
84153 +#define UIF_CALLOUT_ACTIVE ASYNC_CALLOUT_ACTIVE
84154 +#define UIF_NORMAL_ACTIVE ASYNC_NORMAL_ACTIVE
84155 +#define UIF_INITIALIZED ASYNC_INITIALIZED
84157 + unsigned char *tmpbuf;
84158 + struct semaphore tmpbuf_sem;
84160 + unsigned int driver_priv;
84161 + int blocked_open;
84162 + pid_t session;
84163 + pid_t pgrp;
84165 + struct tasklet_struct tlet;
84167 + wait_queue_head_t open_wait;
84168 + wait_queue_head_t delta_msr_wait;
84171 +/* number of characters left in xmit buffer before we ask for more */
84172 +#define WAKEUP_CHARS 256
84174 +struct module;
84175 +struct tty_driver;
84177 +struct uart_driver {
84178 + struct module *owner;
84179 + int normal_major;
84180 + const char *normal_name;
84181 + struct tty_driver *normal_driver;
84182 + int callout_major;
84183 + const char *callout_name;
84184 + struct tty_driver *callout_driver;
84185 + struct tty_struct **table;
84186 + struct termios **termios;
84187 + struct termios **termios_locked;
84188 + int minor;
84189 + int nr;
84190 + struct console *cons;
84192 + /*
84193 + * these are private; the low level driver should not
84194 + * touch these; they should be initialised to NULL
84195 + */
84196 + struct uart_state *state;
84199 +void uart_write_wakeup(struct uart_port *port);
84200 +struct uart_port *uart_get_console(struct uart_port *ports, int nr,
84201 + struct console *c);
84202 +void uart_parse_options(char *options, int *baud, int *parity, int *bits,
84203 + int *flow);
84204 +int uart_set_options(struct uart_port *port, struct console *co, int baud,
84205 + int parity, int bits, int flow);
84208 + * Port/driver registration/removal
84209 + */
84210 +int uart_register_driver(struct uart_driver *uart);
84211 +void uart_unregister_driver(struct uart_driver *uart);
84212 +void uart_unregister_port(struct uart_driver *reg, int line);
84213 +int uart_register_port(struct uart_driver *reg, struct uart_port *port);
84214 +int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
84215 +int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
84217 +#define uart_circ_empty(circ) ((circ)->head == (circ)->tail)
84218 +#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
84220 +#define uart_circ_chars_pending(circ) \
84221 + (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
84223 +#define uart_circ_chars_free(circ) \
84224 + (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
84226 +#define uart_tx_stopped(port) \
84227 + ((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
84230 + * The following are helper functions for the low level drivers.
84231 + */
84232 +#ifdef SUPPORT_SYSRQ
84233 +static inline int
84234 +uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
84235 + struct pt_regs *regs)
84237 + if (port->sysrq) {
84238 + if (ch && time_before(jiffies, port->sysrq)) {
84239 + handle_sysrq(ch, regs, NULL, NULL);
84240 + port->sysrq = 0;
84241 + return 1;
84243 + port->sysrq = 0;
84245 + return 0;
84247 +#else
84248 +#define uart_handle_sysrq_char(port,ch,regs) (0)
84249 +#endif
84252 + * We do the SysRQ and SAK checking like this...
84253 + */
84254 +static inline int uart_handle_break(struct uart_port *port)
84256 + struct uart_info *info = port->info;
84257 +#ifdef SUPPORT_SYSRQ
84258 + if (port->cons && port->cons->index == port->line) {
84259 + if (!port->sysrq) {
84260 + port->sysrq = jiffies + HZ*5;
84261 + return 1;
84263 + port->sysrq = 0;
84265 +#endif
84266 + if (port->flags & UPF_SAK)
84267 + do_SAK(info->tty);
84268 + return 0;
84271 +/**
84272 + * uart_handle_dcd_change - handle a change of carrier detect state
84273 + * @port: uart_port structure for the open port
84274 + * @status: new carrier detect status, nonzero if active
84275 + */
84276 +static inline void
84277 +uart_handle_dcd_change(struct uart_port *port, unsigned int status)
84279 + struct uart_info *info = port->info;
84281 + port->icount.dcd++;
84283 +#ifdef CONFIG_HARD_PPS
84284 + if ((port->flags & UPF_HARDPPS_CD) && status)
84285 + hardpps();
84286 +#endif
84288 + if (info->flags & UIF_CHECK_CD) {
84289 + if (status)
84290 + wake_up_interruptible(&info->open_wait);
84291 + else if (!((info->flags & UIF_CALLOUT_ACTIVE) &&
84292 + (port->flags & UPF_CALLOUT_NOHUP))) {
84293 + if (info->tty)
84294 + tty_hangup(info->tty);
84299 +/**
84300 + * uart_handle_cts_change - handle a change of clear-to-send state
84301 + * @port: uart_port structure for the open port
84302 + * @status: new clear to send status, nonzero if active
84303 + */
84304 +static inline void
84305 +uart_handle_cts_change(struct uart_port *port, unsigned int status)
84307 + struct uart_info *info = port->info;
84308 + struct tty_struct *tty = info->tty;
84310 + port->icount.cts++;
84312 + if (info->flags & UIF_CTS_FLOW) {
84313 + if (tty->hw_stopped) {
84314 + if (status) {
84315 + tty->hw_stopped = 0;
84316 + port->ops->start_tx(port, 0);
84317 + uart_write_wakeup(port);
84319 + } else {
84320 + if (!status) {
84321 + tty->hw_stopped = 1;
84322 + port->ops->stop_tx(port, 0);
84329 + * UART_ENABLE_MS - determine if port should enable modem status irqs
84330 + */
84331 +#define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \
84332 + (cflag) & CRTSCTS || \
84333 + !((cflag) & CLOCAL))
84335 +#endif
84336 --- linux-2.4.25/include/linux/serial_reg.h~2.4.25-vrs2.patch 2001-05-02 01:05:00.000000000 +0200
84337 +++ linux-2.4.25/include/linux/serial_reg.h 2004-03-31 17:15:09.000000000 +0200
84338 @@ -121,6 +121,7 @@
84340 * These are the definitions for the Modem Control Register
84342 +#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */
84343 #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
84344 #define UART_MCR_OUT2 0x08 /* Out2 complement */
84345 #define UART_MCR_OUT1 0x04 /* Out1 complement */
84346 --- linux-2.4.25/include/linux/zlib.h~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
84347 +++ linux-2.4.25/include/linux/zlib.h 2004-03-31 17:15:09.000000000 +0200
84348 @@ -31,7 +31,7 @@
84349 #ifndef _ZLIB_H
84350 #define _ZLIB_H
84352 -#include <linux/zconf.h>
84353 +#include "zconf.h"
84355 #ifdef __cplusplus
84356 extern "C" {
84357 --- linux-2.4.25/init/do_mounts.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
84358 +++ linux-2.4.25/init/do_mounts.c 2004-03-31 17:15:09.000000000 +0200
84359 @@ -888,7 +888,7 @@
84361 void prepare_namespace(void)
84363 - int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
84364 + int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31;
84365 #ifdef CONFIG_ALL_PPC
84366 extern void arch_discover_root(void);
84367 arch_discover_root();
84368 @@ -951,6 +951,7 @@
84369 static unsigned inptr; /* index of next byte to be processed in inbuf */
84370 static unsigned outcnt; /* bytes in output buffer */
84371 static int exit_code;
84372 +static int unzip_error;
84373 static long bytes_out;
84374 static int crd_infd, crd_outfd;
84376 @@ -998,13 +999,17 @@
84377 /* ===========================================================================
84378 * Fill the input buffer. This is called only when the buffer is empty
84379 * and at least one byte is really needed.
84380 + * Returning -1 does not guarantee that gunzip() will ever return.
84382 static int __init fill_inbuf(void)
84384 if (exit_code) return -1;
84386 insize = read(crd_infd, inbuf, INBUFSIZ);
84387 - if (insize == 0) return -1;
84388 + if (insize == 0) {
84389 + error("RAMDISK: ran out of compressed data\n");
84390 + return -1;
84393 inptr = 1;
84395 @@ -1018,10 +1023,15 @@
84396 static void __init flush_window(void)
84398 ulg c = crc; /* temporary variable */
84399 - unsigned n;
84400 + unsigned n, written;
84401 uch *in, ch;
84403 - write(crd_outfd, window, outcnt);
84404 + written = write(crd_outfd, window, outcnt);
84405 + if (written != outcnt && unzip_error == 0) {
84406 + printk(KERN_ERR "RAMDISK: incomplete write (%d != %d), "
84407 + "only wrote %ld\n", written, outcnt, bytes_out);
84408 + unzip_error = 1;
84410 in = window;
84411 for (n = 0; n < outcnt; n++) {
84412 ch = *in++;
84413 @@ -1036,6 +1046,7 @@
84415 printk(KERN_ERR "%s", x);
84416 exit_code = 1;
84417 + unzip_error = 1;
84420 static int __init crd_load(int in_fd, int out_fd)
84421 @@ -1064,6 +1075,8 @@
84423 makecrc();
84424 result = gunzip();
84425 + if (unzip_error)
84426 + result = 1;
84427 kfree(inbuf);
84428 kfree(window);
84429 return result;
84430 --- linux-2.4.25/kernel/Makefile~2.4.25-vrs2.patch 2001-09-17 06:22:40.000000000 +0200
84431 +++ linux-2.4.25/kernel/Makefile 2004-03-31 17:15:09.000000000 +0200
84432 @@ -9,16 +9,19 @@
84434 O_TARGET := kernel.o
84436 -export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
84437 +export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
84438 + printk.o fork.o cpufreq.o
84440 -obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
84441 +obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
84442 module.o exit.o itimer.o info.o time.o softirq.o resource.o \
84443 sysctl.o acct.o capability.o ptrace.o timer.o user.o \
84444 signal.o sys.o kmod.o context.o
84446 +obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
84447 obj-$(CONFIG_UID16) += uid16.o
84448 obj-$(CONFIG_MODULES) += ksyms.o
84449 obj-$(CONFIG_PM) += pm.o
84450 +obj-$(CONFIG_CPU_FREQ) += cpufreq.o
84452 ifneq ($(CONFIG_IA64),y)
84453 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
84454 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
84455 +++ linux-2.4.25/kernel/cpufreq.c 2004-03-31 17:15:09.000000000 +0200
84456 @@ -0,0 +1,536 @@
84458 + * linux/kernel/cpufreq.c
84460 + * Copyright (C) 2001 Russell King
84462 + * $Id: cpufreq.c,v 1.17.2.2 2002/05/03 13:26:27 rmk Exp $
84464 + * This program is free software; you can redistribute it and/or modify
84465 + * it under the terms of the GNU General Public License version 2 as
84466 + * published by the Free Software Foundation.
84468 + * CPU speed changing core functionality. We provide the following
84469 + * services to the system:
84470 + * - notifier lists to inform other code of the freq change both
84471 + * before and after the freq change.
84472 + * - the ability to change the freq speed
84474 + * ** You'll need to add CTL_CPU = 10 to include/linux/sysctl.h if
84475 + * it's not already present.
84477 + * When this appears in the kernel, the sysctl enums will move to
84478 + * include/linux/sysctl.h
84479 + */
84480 +#include <linux/config.h>
84481 +#include <linux/types.h>
84482 +#include <linux/module.h>
84483 +#include <linux/notifier.h>
84484 +#include <linux/cpufreq.h>
84485 +#include <linux/kernel.h>
84486 +#include <linux/delay.h>
84487 +#include <linux/init.h>
84488 +#include <linux/smp.h>
84489 +#include <linux/fs.h>
84490 +#include <linux/sysctl.h>
84492 +#include <asm/semaphore.h>
84493 +#include <asm/system.h>
84494 +#include <asm/uaccess.h>
84495 +#include <linux/interrupt.h> /* requires system.h */
84498 + * This list is for kernel code that needs to handle
84499 + * changes to devices when the CPU clock speed changes.
84500 + */
84501 +static struct notifier_block *cpufreq_notifier_list;
84502 +static DECLARE_MUTEX_LOCKED(cpufreq_sem);
84503 +static unsigned long cpufreq_ref_loops;
84504 +static unsigned int cpufreq_ref_freq;
84505 +static int cpufreq_initialised;
84506 +static unsigned int (*cpufreq_validatespeed)(unsigned int);
84507 +static void (*cpufreq_setspeed)(unsigned int);
84509 +#ifndef CONFIG_SMP
84510 +static unsigned int __cpufreq_max;
84511 +static unsigned int __cpufreq_min;
84512 +static unsigned int __cpufreq_cur;
84513 +#endif
84515 +static unsigned long scale(unsigned long ref, u_int div, u_int mult)
84517 + unsigned long new_jiffy_l, new_jiffy_h;
84519 + /*
84520 + * Recalculate loops_per_jiffy. We do it this way to
84521 + * avoid math overflow on 32-bit machines. Maybe we
84522 + * should make this architecture dependent? If you have
84523 + * a better way of doing this, please replace!
84525 + * new = old * mult / div
84526 + */
84527 + new_jiffy_h = ref / div;
84528 + new_jiffy_l = (ref % div) / 100;
84529 + new_jiffy_h *= mult;
84530 + new_jiffy_l = new_jiffy_l * mult / div;
84532 + return new_jiffy_h + new_jiffy_l * 100;
84536 + * cpufreq_max command line parameter. Use:
84537 + * cpufreq=59000-221000
84538 + * to set the CPU frequency to 59 to 221MHz.
84539 + */
84540 +static int __init cpufreq_setup(char *str)
84542 + unsigned int min, max;
84543 + int i;
84545 + min = 0;
84546 + max = simple_strtoul(str, &str, 0);
84547 + if (*str == '-') {
84548 + min = max;
84549 + max = simple_strtoul(str + 1, NULL, 0);
84552 + for (i = 0; i < smp_num_cpus; i++) {
84553 + cpufreq_max(i) = max;
84554 + cpufreq_min(i) = min;
84557 + return 1;
84560 +__setup("cpufreq=", cpufreq_setup);
84562 +/**
84563 + * cpufreq_register_notifier - register a driver with cpufreq
84564 + * @nb: notifier function to register
84566 + * Add a driver to the list of drivers that which to be notified about
84567 + * CPU clock rate changes. The driver will be called three times on
84568 + * clock change.
84570 + * This function may sleep, and has the same return conditions as
84571 + * notifier_chain_register.
84572 + */
84573 +int cpufreq_register_notifier(struct notifier_block *nb)
84575 + int ret;
84577 + down(&cpufreq_sem);
84578 + ret = notifier_chain_register(&cpufreq_notifier_list, nb);
84579 + up(&cpufreq_sem);
84581 + return ret;
84584 +EXPORT_SYMBOL(cpufreq_register_notifier);
84586 +/**
84587 + * cpufreq_unregister_notifier - unregister a driver with cpufreq
84588 + * @nb: notifier block to be unregistered
84590 + * Remove a driver from the CPU frequency notifier lists.
84592 + * This function may sleep, and has the same return conditions as
84593 + * notifier_chain_unregister.
84594 + */
84595 +int cpufreq_unregister_notifier(struct notifier_block *nb)
84597 + int ret;
84599 + down(&cpufreq_sem);
84600 + ret = notifier_chain_unregister(&cpufreq_notifier_list, nb);
84601 + up(&cpufreq_sem);
84603 + return ret;
84606 +EXPORT_SYMBOL(cpufreq_unregister_notifier);
84609 + * This notifier alters the system "loops_per_jiffy" for the clock
84610 + * speed change. We ignore CPUFREQ_MINMAX here.
84611 + */
84612 +static void adjust_jiffies(unsigned long val, struct cpufreq_info *ci)
84614 + if ((val == CPUFREQ_PRECHANGE && ci->old_freq < ci->new_freq) ||
84615 + (val == CPUFREQ_POSTCHANGE && ci->old_freq > ci->new_freq))
84616 + loops_per_jiffy = scale(cpufreq_ref_loops, cpufreq_ref_freq,
84617 + ci->new_freq);
84620 +#ifdef CONFIG_PM
84621 +/**
84622 + * cpufreq_restore - restore the CPU clock frequency after resume
84624 + * Restore the CPU clock frequency so that our idea of the current
84625 + * frequency reflects the actual hardware.
84626 + */
84627 +int cpufreq_restore(void)
84629 + unsigned long old_cpus;
84630 + int cpu = smp_processor_id();
84631 + int ret;
84633 + if (!cpufreq_initialised)
84634 + panic("cpufreq_restore() called before initialisation!");
84635 + if (in_interrupt())
84636 + panic("cpufreq_restore() called from interrupt context!");
84638 + /*
84639 + * Bind to the current CPU.
84640 + */
84641 + old_cpus = current->cpus_allowed;
84642 + current->cpus_allowed = 1UL << cpu_logical_map(cpu);
84644 + down(&cpufreq_sem);
84646 + ret = -ENXIO;
84647 + if (cpufreq_setspeed) {
84648 + cpufreq_setspeed(cpufreq_current(cpu));
84649 + ret = 0;
84652 + up(&cpufreq_sem);
84654 + current->cpus_allowed = old_cpus;
84656 + return ret;
84659 +EXPORT_SYMBOL_GPL(cpufreq_restore);
84660 +#endif
84662 +/**
84663 + * cpu_setfreq - change the CPU clock frequency.
84664 + * @freq: frequency (in kHz) at which we should run.
84666 + * Set the CPU clock frequency, informing all registered users of
84667 + * the change. We bound the frequency according to the cpufreq_max
84668 + * command line parameter, and the parameters the registered users
84669 + * will allow.
84671 + * This function must be called from process context, and on the
84672 + * cpu that we wish to change the frequency of.
84674 + * We return 0 if successful. (we are currently always successful).
84675 + */
84676 +int cpufreq_set(unsigned int freq)
84678 + unsigned long old_cpus;
84679 + struct cpufreq_info clkinfo;
84680 + struct cpufreq_minmax minmax;
84681 + int cpu = smp_processor_id();
84682 + int ret;
84684 + if (!cpufreq_initialised)
84685 + panic("cpufreq_set() called before initialisation!");
84686 + if (in_interrupt())
84687 + panic("cpufreq_set() called from interrupt context!");
84689 + /*
84690 + * Bind to the current CPU.
84691 + */
84692 + old_cpus = current->cpus_allowed;
84693 + current->cpus_allowed = 1UL << cpu_logical_map(cpu);
84695 + down(&cpufreq_sem);
84696 + ret = -ENXIO;
84697 + if (!cpufreq_setspeed || !cpufreq_validatespeed)
84698 + goto out;
84700 + /*
84701 + * Don't allow the CPU to be clocked over the limit.
84702 + */
84703 + minmax.min_freq = cpufreq_min(cpu);
84704 + minmax.max_freq = cpufreq_max(cpu);
84705 + minmax.cur_freq = cpufreq_current(cpu);
84706 + minmax.new_freq = freq;
84708 + /*
84709 + * Find out what the registered devices will currently tolerate,
84710 + * and limit the requested clock rate to these values. Drivers
84711 + * must not rely on the 'new_freq' value - it is only a guide.
84712 + */
84713 + notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_MINMAX, &minmax);
84714 + if (freq < minmax.min_freq)
84715 + freq = minmax.min_freq;
84716 + if (freq > minmax.max_freq)
84717 + freq = minmax.max_freq;
84719 + /*
84720 + * Ask the CPU specific code to validate the speed. If the speed
84721 + * is not acceptable, make it acceptable. Current policy is to
84722 + * round the frequency down to the value the processor actually
84723 + * supports.
84724 + */
84725 + freq = cpufreq_validatespeed(freq);
84727 + if (cpufreq_current(cpu) != freq) {
84728 + clkinfo.old_freq = cpufreq_current(cpu);
84729 + clkinfo.new_freq = freq;
84731 + notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_PRECHANGE,
84732 + &clkinfo);
84734 + adjust_jiffies(CPUFREQ_PRECHANGE, &clkinfo);
84736 + /*
84737 + * Actually set the CPU frequency.
84738 + */
84739 + cpufreq_setspeed(freq);
84740 + cpufreq_current(cpu) = freq;
84741 + adjust_jiffies(CPUFREQ_POSTCHANGE, &clkinfo);
84743 + notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_POSTCHANGE,
84744 + &clkinfo);
84747 + ret = 0;
84749 + out:
84750 + up(&cpufreq_sem);
84752 + current->cpus_allowed = old_cpus;
84754 + return ret;
84757 +EXPORT_SYMBOL_GPL(cpufreq_set);
84759 +/**
84760 + * cpufreq_setmax - set the CPU to maximum frequency
84762 + * Sets the CPU this function is executed on to maximum frequency.
84763 + */
84764 +int cpufreq_setmax(void)
84766 + return cpufreq_set(cpufreq_max(smp_processor_id()));
84769 +EXPORT_SYMBOL_GPL(cpufreq_setmax);
84771 +/**
84772 + * cpufreq_get - return the current CPU clock frequency in 1kHz
84773 + * @cpu: cpu number to obtain frequency for
84775 + * Returns the specified CPUs frequency in kHz.
84776 + */
84777 +unsigned int cpufreq_get(int cpu)
84779 + if (!cpufreq_initialised)
84780 + panic("cpufreq_get() called before initialisation!");
84781 + return cpufreq_current(cpu);
84784 +EXPORT_SYMBOL(cpufreq_get);
84786 +#ifdef CONFIG_SYSCTL
84788 +static int
84789 +cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
84790 + void *buffer, size_t *lenp)
84792 + char buf[16], *p;
84793 + int cpu = 0, len, left = *lenp;
84795 + if (!left || (filp->f_pos && !write)) {
84796 + *lenp = 0;
84797 + return 0;
84800 + if (write) {
84801 + unsigned int freq;
84803 + len = left;
84804 + if (left > sizeof(buf))
84805 + left = sizeof(buf);
84806 + if (copy_from_user(buf, buffer, left))
84807 + return -EFAULT;
84808 + buf[sizeof(buf) - 1] = '\0';
84810 + freq = simple_strtoul(buf, &p, 0);
84811 + cpufreq_set(freq);
84812 + } else {
84813 + len = sprintf(buf, "%d\n", cpufreq_get(cpu));
84814 + if (len > left)
84815 + len = left;
84816 + if (copy_to_user(buffer, buf, len))
84817 + return -EFAULT;
84820 + *lenp = len;
84821 + filp->f_pos += len;
84822 + return 0;
84825 +static int
84826 +cpufreq_sysctl(ctl_table *table, int *name, int nlen,
84827 + void *oldval, size_t *oldlenp,
84828 + void *newval, size_t newlen, void **context)
84830 + int cpu = 0;
84832 + if (oldval && oldlenp) {
84833 + size_t oldlen;
84835 + if (get_user(oldlen, oldlenp))
84836 + return -EFAULT;
84838 + if (oldlen != sizeof(unsigned int))
84839 + return -EINVAL;
84841 + if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
84842 + put_user(sizeof(unsigned int), oldlenp))
84843 + return -EFAULT;
84845 + if (newval && newlen) {
84846 + unsigned int freq;
84848 + if (newlen != sizeof(unsigned int))
84849 + return -EINVAL;
84851 + if (get_user(freq, (unsigned int *)newval))
84852 + return -EFAULT;
84854 + cpufreq_set(freq);
84856 + return 1;
84859 +enum {
84860 + CPU_NR_FREQ_MAX = 1,
84861 + CPU_NR_FREQ_MIN = 2,
84862 + CPU_NR_FREQ = 3
84865 +static ctl_table ctl_cpu_vars[4] = {
84867 + ctl_name: CPU_NR_FREQ_MAX,
84868 + procname: "speed-max",
84869 + data: &cpufreq_max(0),
84870 + maxlen: sizeof(cpufreq_max(0)),
84871 + mode: 0444,
84872 + proc_handler: proc_dointvec,
84873 + },
84875 + ctl_name: CPU_NR_FREQ_MIN,
84876 + procname: "speed-min",
84877 + data: &cpufreq_min(0),
84878 + maxlen: sizeof(cpufreq_min(0)),
84879 + mode: 0444,
84880 + proc_handler: proc_dointvec,
84881 + },
84883 + ctl_name: CPU_NR_FREQ,
84884 + procname: "speed",
84885 + mode: 0644,
84886 + proc_handler: cpufreq_procctl,
84887 + strategy: cpufreq_sysctl,
84888 + },
84890 + ctl_name: 0,
84894 +enum {
84895 + CPU_NR = 1,
84898 +static ctl_table ctl_cpu_nr[2] = {
84900 + ctl_name: CPU_NR,
84901 + procname: "0",
84902 + mode: 0555,
84903 + child: ctl_cpu_vars,
84904 + },
84906 + ctl_name: 0,
84910 +static ctl_table ctl_cpu[2] = {
84912 + ctl_name: CTL_CPU,
84913 + procname: "cpu",
84914 + mode: 0555,
84915 + child: ctl_cpu_nr,
84916 + },
84918 + ctl_name: 0,
84922 +static inline void cpufreq_sysctl_init(void)
84924 + register_sysctl_table(ctl_cpu, 0);
84927 +#else
84928 +#define cpufreq_sysctl_init()
84929 +#endif
84931 +/**
84932 + * cpufreq_setfunctions - Set CPU clock functions
84933 + * @validate: pointer to validation function
84934 + * @setspeed: pointer to setspeed function
84935 + */
84936 +void
84937 +cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
84938 + void (*setspeed)(unsigned int))
84940 + down(&cpufreq_sem);
84941 + cpufreq_validatespeed = validate;
84942 + cpufreq_setspeed = setspeed;
84943 + up(&cpufreq_sem);
84946 +EXPORT_SYMBOL_GPL(cpufreq_setfunctions);
84948 +/**
84949 + * cpufreq_init - Initialise the cpufreq core
84950 + * @freq: current CPU clock speed.
84951 + * @min_freq: minimum CPU clock speed.
84952 + * @max_freq: maximum CPU clock speed.
84954 + * Initialise the cpufreq core. If the cpufreq_max command line
84955 + * parameter has not been specified, we set the maximum clock rate
84956 + * to the current CPU clock rate.
84957 + */
84958 +void cpufreq_init(unsigned int freq,
84959 + unsigned int min_freq,
84960 + unsigned int max_freq)
84962 + /*
84963 + * If the user doesn't tell us their maximum frequency,
84964 + * or if it is invalid, use the values determined
84965 + * by the cpufreq-arch-specific initialization functions.
84966 + * The validatespeed code is responsible for limiting
84967 + * this further.
84968 + */
84969 + if (max_freq && ((cpufreq_max(0) == 0) || (cpufreq_max(0) > max_freq)))
84970 + cpufreq_max(0) = max_freq;
84971 + if (min_freq && ((cpufreq_min(0) == 0) || (cpufreq_min(0) < min_freq)))
84972 + cpufreq_min(0) = min_freq;
84974 + if (cpufreq_max(0) == 0)
84975 + cpufreq_max(0) = freq;
84977 + printk(KERN_INFO "CPU clock: %d.%03d MHz (%d.%03d-%d.%03d MHz)\n",
84978 + freq / 1000, freq % 1000,
84979 + cpufreq_min(0) / 1000, cpufreq_min(0) % 1000,
84980 + cpufreq_max(0) / 1000, cpufreq_max(0) % 1000);
84982 + cpufreq_ref_loops = loops_per_jiffy;
84983 + cpufreq_ref_freq = freq;
84984 + cpufreq_current(smp_processor_id()) = freq;
84986 + cpufreq_initialised = 1;
84987 + up(&cpufreq_sem);
84989 + cpufreq_sysctl_init();
84992 +EXPORT_SYMBOL_GPL(cpufreq_init);
84993 --- linux-2.4.25/kernel/exit.c~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
84994 +++ linux-2.4.25/kernel/exit.c 2004-03-31 17:15:09.000000000 +0200
84995 @@ -587,7 +587,7 @@
84996 return retval;
84999 -#if !defined(__alpha__) && !defined(__ia64__)
85000 +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
85003 * sys_waitpid() remains for compatibility. waitpid() should be
85004 --- linux-2.4.25/kernel/fork.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
85005 +++ linux-2.4.25/kernel/fork.c 2004-03-31 17:15:09.000000000 +0200
85006 @@ -75,7 +75,11 @@
85007 * value: the thread structures can take up at most half
85008 * of memory.
85010 +#if THREAD_SIZE > PAGE_SIZE
85011 max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8;
85012 +#else
85013 + max_threads = (mempages * PAGE_SIZE) / (8 * THREAD_SIZE);
85014 +#endif
85016 init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
85017 init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
85018 @@ -220,6 +224,7 @@
85020 fail_nomem:
85021 flush_tlb_mm(current->mm);
85022 + memc_update_mm(mm);
85023 return retval;
85026 --- linux-2.4.25/kernel/ksyms.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
85027 +++ linux-2.4.25/kernel/ksyms.c 2004-03-31 17:15:09.000000000 +0200
85028 @@ -345,6 +345,7 @@
85030 /* tty routines */
85031 EXPORT_SYMBOL(tty_hangup);
85032 +EXPORT_SYMBOL(tty_vhangup);
85033 EXPORT_SYMBOL(tty_wait_until_sent);
85034 EXPORT_SYMBOL(tty_check_change);
85035 EXPORT_SYMBOL(tty_hung_up_p);
85036 @@ -439,9 +440,11 @@
85037 EXPORT_SYMBOL(kiobuf_wait_for_io);
85039 /* dma handling */
85040 +#ifdef CONFIG_GENERIC_ISA_DMA
85041 EXPORT_SYMBOL(request_dma);
85042 EXPORT_SYMBOL(free_dma);
85043 EXPORT_SYMBOL(dma_spin_lock);
85044 +#endif
85045 #ifdef HAVE_DISABLE_HLT
85046 EXPORT_SYMBOL(disable_hlt);
85047 EXPORT_SYMBOL(enable_hlt);
85048 --- linux-2.4.25/kernel/signal.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
85049 +++ linux-2.4.25/kernel/signal.c 2004-03-31 17:15:09.000000000 +0200
85050 @@ -778,8 +778,8 @@
85051 info.si_uid = tsk->uid;
85053 /* FIXME: find out whether or not this is supposed to be c*time. */
85054 - info.si_utime = tsk->times.tms_utime;
85055 - info.si_stime = tsk->times.tms_stime;
85056 + info.si_utime = hz_to_std(tsk->times.tms_utime);
85057 + info.si_stime = hz_to_std(tsk->times.tms_stime);
85059 status = tsk->exit_code & 0x7f;
85060 why = SI_KERNEL; /* shouldn't happen */
85061 @@ -1277,7 +1277,7 @@
85062 #endif /* __sparc__ */
85063 #endif
85065 -#if !defined(__alpha__) && !defined(__ia64__)
85066 +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
85068 * For backwards compatibility. Functionality superseded by sigprocmask.
85070 @@ -1305,7 +1305,8 @@
85072 #endif /* !defined(__alpha__) */
85074 -#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__)
85075 +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && \
85076 + !defined(__arm__)
85078 * For backwards compatibility. Functionality superseded by sigaction.
85080 @@ -1322,4 +1323,4 @@
85082 return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
85084 -#endif /* !alpha && !__ia64__ && !defined(__mips__) */
85085 +#endif /* !alpha && !__ia64__ && !defined(__mips__) && !defined(__arm__) */
85086 --- linux-2.4.25/kernel/sys.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
85087 +++ linux-2.4.25/kernel/sys.c 2004-03-31 17:15:09.000000000 +0200
85088 @@ -801,16 +801,23 @@
85090 asmlinkage long sys_times(struct tms * tbuf)
85092 + struct tms temp;
85095 * In the SMP world we might just be unlucky and have one of
85096 * the times increment as we use it. Since the value is an
85097 * atomically safe type this is just fine. Conceptually its
85098 * as if the syscall took an instant longer to occur.
85100 - if (tbuf)
85101 - if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
85102 + if (tbuf) {
85103 + temp.tms_utime = hz_to_std(current->times.tms_utime);
85104 + temp.tms_stime = hz_to_std(current->times.tms_stime);
85105 + temp.tms_cutime = hz_to_std(current->times.tms_cutime);
85106 + temp.tms_cstime = hz_to_std(current->times.tms_cstime);
85107 + if (copy_to_user(tbuf, &temp, sizeof(struct tms)))
85108 return -EFAULT;
85109 - return jiffies;
85111 + return hz_to_std(jiffies);
85115 --- linux-2.4.25/lib/string.c~2.4.25-vrs2.patch 2002-08-03 02:39:46.000000000 +0200
85116 +++ linux-2.4.25/lib/string.c 2004-03-31 17:15:09.000000000 +0200
85117 @@ -188,10 +188,10 @@
85119 char * strchr(const char * s, int c)
85121 - for(; *s != (char) c; ++s)
85122 - if (*s == '\0')
85123 - return NULL;
85124 - return (char *) s;
85125 + for(; *s != '\0'; ++s)
85126 + if (*s == (char) c)
85127 + return (char *) s;
85128 + return NULL;
85130 #endif
85132 --- linux-2.4.25/mm/Makefile~2.4.25-vrs2.patch 2002-08-03 02:39:46.000000000 +0200
85133 +++ linux-2.4.25/mm/Makefile 2004-03-31 17:15:09.000000000 +0200
85134 @@ -18,4 +18,5 @@
85136 obj-$(CONFIG_HIGHMEM) += highmem.o
85138 +obj-y += debug.o
85139 include $(TOPDIR)/Rules.make
85140 --- /dev/null 2003-09-23 19:59:22.000000000 +0200
85141 +++ linux-2.4.25/mm/debug.c 2004-03-31 17:15:09.000000000 +0200
85142 @@ -0,0 +1,159 @@
85144 + * linux/mm/debug.c
85146 + * Copyright (C) 2001 Russell King.
85148 + * This program is free software; you can redistribute it and/or modify
85149 + * it under the terms of the GNU General Public License version 2 as
85150 + * published by the Free Software Foundation.
85152 + * Dump out page information on SysRQ-G, and provide show_page_info()
85154 + * You are advised to use a serial console with this patch - it
85155 + * saturates a 38400baud link for 1 minute on a 32MB machine.
85156 + */
85157 +#include <linux/kernel.h>
85158 +#include <linux/mm.h>
85159 +#include <linux/pagemap.h>
85160 +#include <linux/sysrq.h>
85161 +#include <linux/init.h>
85164 + * We print out the following information for each page in the system:
85165 + * address: use count, age, mapping, [RSsr] rD [acd]
85167 + * The flags are:
85168 + * R - reserved
85169 + * S - in swapcache
85170 + * s - slab page
85172 + * r - referenced
85173 + * D - dirty
85175 + * a - active page
85176 + */
85177 +static void page_detail(struct page *page)
85179 + if (!page)
85180 + return;
85182 + printk("%p: %2d %p [%c%c%c] %c%c [%c]\n",
85183 + page_address(page),
85184 + page_count(page),
85185 + page->mapping,
85187 + PageReserved(page) ? 'R' : '-',
85188 + PageSwapCache(page) ? 'S' : '-',
85189 + PageSlab(page) ? 's' : '-',
85191 + PageReferenced(page) ? 'r' : '-',
85192 + PageDirty(page) ? 'D' : '-',
85194 + PageActive(page) ? 'a' : '-');
85198 + * This version collects statistics
85199 + */
85200 +static int anon_pages, slab_pages, resvd_pages, unused_pages;
85202 +static void page_statistics(struct page *page)
85204 + if (page) {
85205 + if (PageReserved(page))
85206 + resvd_pages++;
85207 + else if (PageSlab(page))
85208 + slab_pages++;
85209 + else if (!page_count(page))
85210 + unused_pages ++;
85211 + else if (!page->mapping)
85212 + anon_pages ++;
85213 + return;
85216 + printk(" anon: %d, slab: %d, reserved: %d, free: %d\n",
85217 + anon_pages, slab_pages, resvd_pages, unused_pages);
85220 +static void show_zone_info(zone_t *zone, void (*fn)(struct page *))
85222 + int i;
85224 + printk(" total %ld, free %ld\n",
85225 + zone->size, zone->free_pages);
85227 + anon_pages = 0;
85228 + slab_pages = 0;
85229 + resvd_pages = 0;
85230 + unused_pages = 0;
85232 + for (i = 0; i < zone->size; i++) {
85233 + struct page *page = zone->zone_mem_map + i;
85235 + fn(page);
85238 + fn(NULL);
85241 +static void show_node_info(pg_data_t *pg, void (*fn)(struct page *))
85243 + int type;
85245 + for (type = 0; type < MAX_NR_ZONES; type++) {
85246 + zone_t *zone = pg->node_zones + type;
85248 + if (zone->size == 0)
85249 + continue;
85251 + printk("----- Zone %d ------\n", type);
85253 + show_zone_info(zone, fn);
85257 +static void __show_page_info(void (*fn)(struct page *))
85259 + pg_data_t *pg;
85260 + int pgdat = 0;
85262 + for (pg = pgdat_list; pg; pg = pg->node_next) {
85264 + printk("===== Node %d =====\n", pgdat++);
85266 + show_node_info(pg, fn);
85267 + }
85270 +void show_page_info(void)
85272 + __show_page_info(page_detail);
85275 +static void
85276 +show_pg_info(int key, struct pt_regs *regs, struct kbd_struct *kd,
85277 + struct tty_struct *tty)
85279 + void (*fn)(struct page *);
85280 + show_mem();
85281 + if (key == 'g')
85282 + fn = page_detail;
85283 + else
85284 + fn = page_statistics;
85285 + __show_page_info(fn);
85288 +static struct sysrq_key_op page_info_op = {
85289 + handler: show_pg_info,
85290 + help_msg: "paGeinfo",
85291 + action_msg: "Page Info",
85294 +static int __init debug_mm_init(void)
85296 + register_sysrq_key('g', &page_info_op);
85297 + register_sysrq_key('h', &page_info_op);
85298 + return 0;
85301 +__initcall(debug_mm_init);
85302 --- linux-2.4.25/mm/filemap.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
85303 +++ linux-2.4.25/mm/filemap.c 2004-03-31 17:15:09.000000000 +0200
85304 @@ -2210,10 +2210,14 @@
85305 pte_t pte = *ptep;
85307 if (pte_present(pte)) {
85308 - struct page *page = pte_page(pte);
85309 - if (VALID_PAGE(page) && !PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
85310 - flush_tlb_page(vma, address);
85311 - set_page_dirty(page);
85312 + unsigned long pfn = pte_pfn(pte);
85314 + if (pfn_valid(pfn)) {
85315 + struct page *page = pfn_to_page(pfn);
85316 + if (!PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
85317 + flush_tlb_page(vma, address);
85318 + set_page_dirty(page);
85322 return 0;
85323 --- linux-2.4.25/mm/memory.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
85324 +++ linux-2.4.25/mm/memory.c 2004-03-31 17:15:09.000000000 +0200
85325 @@ -77,8 +77,13 @@
85327 void __free_pte(pte_t pte)
85329 - struct page *page = pte_page(pte);
85330 - if ((!VALID_PAGE(page)) || PageReserved(page))
85331 + unsigned long pfn = pte_pfn(pte);
85332 + struct page *page;
85334 + if (!pfn_valid(pfn))
85335 + return;
85336 + page = pfn_to_page(pfn);
85337 + if (PageReserved(page))
85338 return;
85339 if (pte_dirty(pte))
85340 set_page_dirty(page);
85341 @@ -232,6 +237,7 @@
85342 do {
85343 pte_t pte = *src_pte;
85344 struct page *ptepage;
85345 + unsigned long pfn;
85347 /* copy_one_pte */
85349 @@ -241,9 +247,11 @@
85350 swap_duplicate(pte_to_swp_entry(pte));
85351 goto cont_copy_pte_range;
85353 - ptepage = pte_page(pte);
85354 - if ((!VALID_PAGE(ptepage)) ||
85355 - PageReserved(ptepage))
85356 + pfn = pte_pfn(pte);
85357 + if (!pfn_valid(pfn))
85358 + goto cont_copy_pte_range;
85359 + ptepage = pfn_to_page(pfn);
85360 + if (PageReserved(ptepage))
85361 goto cont_copy_pte_range;
85363 /* If it's a COW mapping, write protect it both in the parent and the child */
85364 @@ -314,9 +322,13 @@
85365 if (pte_none(pte))
85366 continue;
85367 if (pte_present(pte)) {
85368 - struct page *page = pte_page(pte);
85369 - if (VALID_PAGE(page) && !PageReserved(page))
85370 - freed ++;
85371 + unsigned long pfn = pte_pfn(pte);
85373 + if (pfn_valid(pfn)) {
85374 + struct page *page = pfn_to_page(pfn);
85375 + if (!PageReserved(page))
85376 + freed ++;
85378 /* This will eventually call __free_pte on the pte. */
85379 tlb_remove_page(tlb, ptep, address + offset);
85380 } else {
85381 @@ -354,17 +366,37 @@
85382 return freed;
85385 +void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long address, unsigned long end)
85387 + int freed = 0;
85388 + pgd_t * dir;
85390 + if (address >= end)
85391 + BUG();
85392 + dir = pgd_offset(mm, address);
85393 + do {
85394 + freed += zap_pmd_range(tlb, dir, address, end - address);
85395 + address = (address + PGDIR_SIZE) & PGDIR_MASK;
85396 + dir++;
85397 + } while (address && (address < end));
85399 + /*
85400 + * Update rss for the mm_struct (not necessarily current->mm)
85401 + * Notice that rss is an unsigned long.
85402 + */
85403 + if (mm->rss > freed)
85404 + mm->rss -= freed;
85405 + else
85406 + mm->rss = 0;
85410 * remove user pages in a given range.
85412 void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
85414 - mmu_gather_t *tlb;
85415 - pgd_t * dir;
85416 unsigned long start = address, end = address + size;
85417 - int freed = 0;
85419 - dir = pgd_offset(mm, address);
85420 + mmu_gather_t *tlb;
85423 * This is a long-lived spinlock. That's fine.
85424 @@ -377,25 +409,10 @@
85425 BUG();
85426 spin_lock(&mm->page_table_lock);
85427 flush_cache_range(mm, address, end);
85428 - tlb = tlb_gather_mmu(mm);
85430 - do {
85431 - freed += zap_pmd_range(tlb, dir, address, end - address);
85432 - address = (address + PGDIR_SIZE) & PGDIR_MASK;
85433 - dir++;
85434 - } while (address && (address < end));
85436 - /* this will flush any remaining tlb entries */
85437 + tlb = tlb_gather_mmu(mm);
85438 + unmap_page_range(tlb, mm, address, end);
85439 tlb_finish_mmu(tlb, start, end);
85441 - /*
85442 - * Update rss for the mm_struct (not necessarily current->mm)
85443 - * Notice that rss is an unsigned long.
85444 - */
85445 - if (mm->rss > freed)
85446 - mm->rss -= freed;
85447 - else
85448 - mm->rss = 0;
85449 spin_unlock(&mm->page_table_lock);
85452 @@ -407,6 +424,7 @@
85453 pgd_t *pgd;
85454 pmd_t *pmd;
85455 pte_t *ptep, pte;
85456 + unsigned long pfn;
85458 pgd = pgd_offset(mm, address);
85459 if (pgd_none(*pgd) || pgd_bad(*pgd))
85460 @@ -423,8 +441,11 @@
85461 pte = *ptep;
85462 if (pte_present(pte)) {
85463 if (!write ||
85464 - (pte_write(pte) && pte_dirty(pte)))
85465 - return pte_page(pte);
85466 + (pte_write(pte) && pte_dirty(pte))) {
85467 + pfn = pte_pfn(pte);
85468 + if (pfn_valid(pfn))
85469 + return pfn_to_page(pfn);
85473 out:
85474 @@ -439,7 +460,8 @@
85476 static inline struct page * get_page_map(struct page *page)
85478 - if (!VALID_PAGE(page))
85479 + unsigned long pfn = page_to_pfn(page);
85480 + if (!pfn_valid(pfn))
85481 return 0;
85482 return page;
85484 @@ -826,22 +848,22 @@
85485 unsigned long phys_addr, pgprot_t prot)
85487 unsigned long end;
85488 + unsigned long pfn;
85490 address &= ~PMD_MASK;
85491 end = address + size;
85492 if (end > PMD_SIZE)
85493 end = PMD_SIZE;
85494 + pfn = phys_addr >> PAGE_SHIFT;
85495 do {
85496 - struct page *page;
85497 pte_t oldpage;
85498 oldpage = ptep_get_and_clear(pte);
85500 - page = virt_to_page(__va(phys_addr));
85501 - if ((!VALID_PAGE(page)) || PageReserved(page))
85502 - set_pte(pte, mk_pte_phys(phys_addr, prot));
85503 + if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
85504 + set_pte(pte, pfn_pte(pfn, prot));
85505 forget_pte(oldpage);
85506 address += PAGE_SIZE;
85507 - phys_addr += PAGE_SIZE;
85508 + pfn++;
85509 pte++;
85510 } while (address && (address < end));
85512 @@ -949,10 +971,11 @@
85513 unsigned long address, pte_t *page_table, pte_t pte)
85515 struct page *old_page, *new_page;
85516 + unsigned long pfn = pte_pfn(pte);
85518 - old_page = pte_page(pte);
85519 - if (!VALID_PAGE(old_page))
85520 + if (!pfn_valid(pfn))
85521 goto bad_wp_page;
85522 + old_page = pte_page(pte);
85524 if (!TryLockPage(old_page)) {
85525 int reuse = can_share_swap_page(old_page);
85526 @@ -996,7 +1019,7 @@
85528 bad_wp_page:
85529 spin_unlock(&mm->page_table_lock);
85530 - printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
85531 + printk("do_wp_page: bogus page at address %08lx\n", address);
85532 return -1;
85533 no_mem:
85534 page_cache_release(old_page);
85535 --- linux-2.4.25/mm/mmap.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
85536 +++ linux-2.4.25/mm/mmap.c 2004-03-31 17:15:09.000000000 +0200
85537 @@ -18,6 +18,9 @@
85539 #include <asm/uaccess.h>
85540 #include <asm/pgalloc.h>
85541 +#include <asm/tlb.h>
85543 +extern void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long start, unsigned long end);
85546 * WARNING: the debugging will use recursive algorithms so never enable this
85547 @@ -915,6 +918,8 @@
85548 * old method of shifting the VA >> by PGDIR_SHIFT doesn't work.
85550 start_index = pgd_index(first);
85551 + if (start_index < FIRST_USER_PGD_NR)
85552 + start_index = FIRST_USER_PGD_NR;
85553 end_index = pgd_index(last);
85554 if (end_index > start_index) {
85555 clear_page_tables(mm, start_index, end_index - start_index);
85556 @@ -1046,7 +1051,6 @@
85557 len = PAGE_ALIGN(len);
85558 if (!len)
85559 return addr;
85561 if ((addr + len) > TASK_SIZE || (addr + len) < addr)
85562 return -EINVAL;
85564 @@ -1135,45 +1139,58 @@
85565 /* Release all mmaps. */
85566 void exit_mmap(struct mm_struct * mm)
85568 + mmu_gather_t *tlb;
85569 struct vm_area_struct * mpnt;
85571 release_segments(mm);
85572 spin_lock(&mm->page_table_lock);
85574 + tlb = tlb_gather_mmu(mm);
85576 + flush_cache_mm(mm);
85577 + mpnt = mm->mmap;
85578 + while (mpnt) {
85579 + unsigned long start = mpnt->vm_start;
85580 + unsigned long end = mpnt->vm_end;
85582 + mm->map_count--;
85583 + remove_shared_vm_struct(mpnt);
85584 + unmap_page_range(tlb, mm, start, end);
85585 + mpnt = mpnt->vm_next;
85588 + /* This is just debugging */
85589 + if (mm->map_count)
85590 + BUG();
85592 + tlb_finish_mmu(tlb, 0, TASK_SIZE);
85594 mpnt = mm->mmap;
85595 mm->mmap = mm->mmap_cache = NULL;
85596 mm->mm_rb = RB_ROOT;
85597 mm->rss = 0;
85598 - spin_unlock(&mm->page_table_lock);
85599 mm->total_vm = 0;
85600 mm->locked_vm = 0;
85602 - flush_cache_mm(mm);
85603 + spin_unlock(&mm->page_table_lock);
85605 + clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
85607 + /*
85608 + * Walk the list again, actually closing and freeing it
85609 + * without holding any MM locks.
85610 + */
85611 while (mpnt) {
85612 struct vm_area_struct * next = mpnt->vm_next;
85613 - unsigned long start = mpnt->vm_start;
85614 - unsigned long end = mpnt->vm_end;
85615 - unsigned long size = end - start;
85617 if (mpnt->vm_ops) {
85618 if (mpnt->vm_ops->close)
85619 mpnt->vm_ops->close(mpnt);
85621 - mm->map_count--;
85622 - remove_shared_vm_struct(mpnt);
85623 - zap_page_range(mm, start, size);
85624 if (mpnt->vm_file)
85625 fput(mpnt->vm_file);
85626 kmem_cache_free(vm_area_cachep, mpnt);
85627 mpnt = next;
85630 - /* This is just debugging */
85631 - if (mm->map_count)
85632 - BUG();
85634 - clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
85636 - flush_tlb_mm(mm);
85639 /* Insert vm structure into process list sorted by address
85640 --- linux-2.4.25/mm/slab.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
85641 +++ linux-2.4.25/mm/slab.c 2004-03-31 17:15:09.000000000 +0200
85642 @@ -1391,7 +1391,7 @@
85643 #if DEBUG
85644 # define CHECK_NR(pg) \
85645 do { \
85646 - if (!VALID_PAGE(pg)) { \
85647 + if (!virt_addr_valid(pg)) { \
85648 printk(KERN_ERR "kfree: out of range ptr %lxh.\n", \
85649 (unsigned long)objp); \
85650 BUG(); \
85651 @@ -1950,12 +1950,12 @@
85652 name = cachep->name;
85654 char tmp;
85655 - mm_segment_t old_fs;
85656 + mm_segment_t old_fs;
85657 old_fs = get_fs();
85658 set_fs(KERNEL_DS);
85659 if (__get_user(tmp, name))
85660 name = "broken";
85661 - set_fs(old_fs);
85662 + set_fs (old_fs);
85665 seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
85666 --- linux-2.4.25/mm/vmalloc.c~2.4.25-vrs2.patch 2003-08-25 13:44:44.000000000 +0200
85667 +++ linux-2.4.25/mm/vmalloc.c 2004-03-31 17:15:09.000000000 +0200
85668 @@ -44,8 +44,13 @@
85669 if (pte_none(page))
85670 continue;
85671 if (pte_present(page)) {
85672 - struct page *ptpage = pte_page(page);
85673 - if (VALID_PAGE(ptpage) && (!PageReserved(ptpage)))
85674 + unsigned long pfn = pte_pfn(page);
85675 + struct page *ptpage;
85677 + if (!pfn_valid(pfn))
85678 + continue;
85679 + ptpage = pfn_to_page(pfn);
85680 + if (!PageReserved(ptpage))
85681 __free_page(ptpage);
85682 continue;
85684 --- linux-2.4.25/mm/vmscan.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
85685 +++ linux-2.4.25/mm/vmscan.c 2004-03-31 17:15:09.000000000 +0200
85686 @@ -121,6 +121,7 @@
85687 drop_pte:
85688 mm->rss--;
85689 UnlockPage(page);
85690 + memc_clear(vma->vm_mm, page);
85692 int freeable = page_count(page) - !!page->buffers <= 2;
85693 page_cache_release(page);
85694 @@ -206,13 +207,16 @@
85696 do {
85697 if (pte_present(*pte)) {
85698 - struct page *page = pte_page(*pte);
85699 + unsigned long pfn = pte_pfn(*pte);
85701 - if (VALID_PAGE(page) && !PageReserved(page)) {
85702 - count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
85703 - if (!count) {
85704 - address += PAGE_SIZE;
85705 - break;
85706 + if (pfn_valid(pfn)) {
85707 + struct page *page = pfn_to_page(pfn);
85708 + if (!PageReserved(page)) {
85709 + count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
85710 + if (!count) {
85711 + address += PAGE_SIZE;
85712 + break;
85717 --- linux-2.4.25/net/irda/af_irda.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
85718 +++ linux-2.4.25/net/irda/af_irda.c 2004-03-31 17:15:09.000000000 +0200
85719 @@ -1176,7 +1176,7 @@
85720 #endif /* CONFIG_IRDA_ULTRA */
85721 kfree(self);
85722 MOD_DEC_USE_COUNT;
85725 return;
85728 @@ -2571,19 +2571,15 @@
85729 sock_register(&irda_family_ops);
85731 irda_packet_type.type = htons(ETH_P_IRDA);
85732 - dev_add_pack(&irda_packet_type);
85733 + dev_add_pack(&irda_packet_type);
85735 register_netdevice_notifier(&irda_dev_notifier);
85737 irda_init();
85738 #ifdef MODULE
85739 - irda_device_init(); /* Called by init/main.c when non-modular */
85740 + irda_device_init(); /* Called by init/main.c when non-modular */
85741 #endif
85742 return 0;
85744 -#ifdef MODULE
85745 -module_init(irda_proto_init); /* If non-module, called from init/main.c */
85746 -#endif
85749 * Function irda_proto_cleanup (void)
85750 @@ -2591,25 +2587,27 @@
85751 * Remove IrDA protocol layer
85754 -#ifdef MODULE
85755 -void irda_proto_cleanup(void)
85756 +static void __exit irda_proto_cleanup(void)
85758 irda_packet_type.type = htons(ETH_P_IRDA);
85759 - dev_remove_pack(&irda_packet_type);
85760 + dev_remove_pack(&irda_packet_type);
85762 + unregister_netdevice_notifier(&irda_dev_notifier);
85764 - unregister_netdevice_notifier(&irda_dev_notifier);
85766 sock_unregister(PF_IRDA);
85768 irda_cleanup();
85770 - return;
85773 +#ifdef MODULE
85774 +module_init(irda_proto_init);
85775 module_exit(irda_proto_cleanup);
85778 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
85779 -MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
85780 +MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
85781 MODULE_LICENSE("GPL");
85782 #ifdef CONFIG_IRDA_DEBUG
85783 MODULE_PARM(irda_debug, "1l");
85784 #endif
85785 -#endif /* MODULE */
85786 +#endif
85788 --- linux-2.4.25/net/irda/iriap.c~2.4.25-vrs2.patch 2002-11-29 00:53:16.000000000 +0100
85789 +++ linux-2.4.25/net/irda/iriap.c 2004-03-31 17:15:09.000000000 +0200
85790 @@ -1004,18 +1004,20 @@
85792 switch (attrib->value->type) {
85793 case IAS_INTEGER:
85794 - len += sprintf(buf+len, "%d\n",
85795 + len += sprintf(buf+len, "%d",
85796 attrib->value->t.integer);
85797 break;
85798 case IAS_STRING:
85799 - len += sprintf(buf+len, "\"%s\"\n",
85800 + len += sprintf(buf+len, "\"%s\"",
85801 attrib->value->t.string);
85802 break;
85803 case IAS_OCT_SEQ:
85804 - len += sprintf(buf+len, "octet sequence (%d bytes)\n", attrib->value->len);
85805 + len += sprintf(buf+len,
85806 + "octet sequence (%d bytes)",
85807 + attrib->value->len);
85808 break;
85809 case IAS_MISSING:
85810 - len += sprintf(buf+len, "missing\n");
85811 + len += sprintf(buf+len, "missing");
85812 break;
85813 default:
85814 IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
85815 @@ -1027,6 +1029,7 @@
85816 hashbin_get_next(obj->attribs);
85818 obj = (struct ias_object *) hashbin_get_next(objects);
85819 + len += sprintf(buf+len, "\n");
85821 restore_flags(flags);
85823 --- linux-2.4.25/net/irda/irlan/irlan_common.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
85824 +++ linux-2.4.25/net/irda/irlan/irlan_common.c 2004-03-31 17:15:09.000000000 +0200
85825 @@ -317,6 +317,9 @@
85827 del_timer(&self->watchdog_timer);
85829 + /* since irlan_do_*_event gobble the skb, we must get it once -- rmk */
85830 + skb_get(skb);
85832 /* If you want to pass the skb to *both* state machines, you will
85833 * need to skb_clone() it, so that you don't free it twice.
85834 * As the state machines don't need it, git rid of it here...
85835 --- linux-2.4.25/net/irda/irlap_event.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
85836 +++ linux-2.4.25/net/irda/irlap_event.c 2004-03-31 17:15:09.000000000 +0200
85837 @@ -532,7 +532,7 @@
85838 #endif /* CONFIG_IRDA_ULTRA */
85839 case RECV_TEST_CMD:
85840 /* Remove test frame header */
85841 - skb_pull(skb, sizeof(struct test_frame));
85842 + skb_pull(skb, 10 /*sizeof(struct test_frame)*/);
85845 * Send response. This skb will not be sent out again, and
85846 @@ -740,7 +740,7 @@
85848 switch (event) {
85849 case CONNECT_RESPONSE:
85850 - skb_pull(skb, sizeof(struct snrm_frame));
85851 + skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
85853 ASSERT(self->netdev != NULL, return -1;);
85855 @@ -870,7 +870,7 @@
85857 ASSERT(self->netdev != NULL, return -1;);
85859 - skb_pull(skb, sizeof(struct snrm_frame));
85860 + skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
85862 irlap_qos_negotiate(self, skb);
85864 @@ -902,7 +902,7 @@
85865 /* Negotiate connection parameters */
85866 ASSERT(skb->len > 10, return -1;);
85868 - skb_pull(skb, sizeof(struct ua_frame));
85869 + skb_pull(skb, 10 /*sizeof(struct ua_frame)*/);
85871 ASSERT(self->netdev != NULL, return -1;);
85873 --- linux-2.4.25/net/irda/irlap_frame.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
85874 +++ linux-2.4.25/net/irda/irlap_frame.c 2004-03-31 17:15:09.000000000 +0200
85875 @@ -1,5 +1,5 @@
85876 /*********************************************************************
85877 - *
85879 * Filename: irlap_frame.c
85880 * Version: 1.0
85881 * Description: Build and transmit IrLAP frames
85882 @@ -8,18 +8,18 @@
85883 * Created at: Tue Aug 19 10:27:26 1997
85884 * Modified at: Wed Jan 5 08:59:04 2000
85885 * Modified by: Dag Brattli <dagb@cs.uit.no>
85886 - *
85887 - * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
85889 + * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
85890 * All Rights Reserved.
85891 * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
85892 - *
85893 - * This program is free software; you can redistribute it and/or
85894 - * modify it under the terms of the GNU General Public License as
85895 - * published by the Free Software Foundation; either version 2 of
85897 + * This program is free software; you can redistribute it and/or
85898 + * modify it under the terms of the GNU General Public License as
85899 + * published by the Free Software Foundation; either version 2 of
85900 * the License, or (at your option) any later version.
85902 * Neither Dag Brattli nor University of TromsĆø admit liability nor
85903 - * provide warranty for any of this software. This material is
85904 + * provide warranty for any of this software. This material is
85905 * provided "AS-IS" and at no charge.
85907 ********************************************************************/
85908 @@ -29,11 +29,12 @@
85909 #include <linux/if_ether.h>
85910 #include <linux/netdevice.h>
85911 #include <linux/irda.h>
85914 #include <net/pkt_sched.h>
85915 #include <net/sock.h>
85918 #include <asm/byteorder.h>
85919 +#include <asm/unaligned.h>
85921 #include <net/irda/irda.h>
85922 #include <net/irda/irda_device.h>
85923 @@ -46,18 +47,18 @@
85925 * Function irlap_insert_info (self, skb)
85927 - * Insert minimum turnaround time and speed information into the skb. We
85928 + * Insert minimum turnaround time and speed information into the skb. We
85929 * need to do this since it's per packet relevant information. Safe to
85930 * have this function inlined since it's only called from one place
85932 -static inline void irlap_insert_info(struct irlap_cb *self,
85933 +static inline void irlap_insert_info(struct irlap_cb *self,
85934 struct sk_buff *skb)
85936 struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
85938 - /*
85939 + /*
85940 * Insert MTT (min. turn time) and speed into skb, so that the
85941 - * device driver knows which settings to use
85942 + * device driver knows which settings to use
85944 cb->magic = LAP_MAGIC;
85945 cb->mtt = self->mtt_required;
85946 @@ -65,15 +66,15 @@
85948 /* Reset */
85949 self->mtt_required = 0;
85951 - /*
85952 - * Delay equals negotiated BOFs count, plus the number of BOFs to
85953 - * force the negotiated minimum turnaround time
85955 + /*
85956 + * Delay equals negotiated BOFs count, plus the number of BOFs to
85957 + * force the negotiated minimum turnaround time
85959 cb->xbofs = self->bofs_count;
85960 cb->next_xbofs = self->next_bofs;
85961 cb->xbofs_delay = self->xbofs_delay;
85964 /* Reset XBOF's delay (used only for getting min turn time) */
85965 self->xbofs_delay = 0;
85966 /* Put the correct xbofs value for the next packet */
85967 @@ -104,7 +105,7 @@
85969 * Transmits a connect SNRM command frame
85971 -void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
85972 +void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
85974 struct sk_buff *skb;
85975 struct snrm_frame *frame;
85976 @@ -118,7 +119,7 @@
85977 if (!skb)
85978 return;
85980 - frame = (struct snrm_frame *) skb_put(skb, 2);
85981 + frame = (struct snrm_frame *) skb_put(skb, 2);
85983 /* Insert connection address field */
85984 if (qos)
85985 @@ -128,17 +129,17 @@
85987 /* Insert control field */
85988 frame->control = SNRM_CMD | PF_BIT;
85992 - * If we are establishing a connection then insert QoS paramerters
85993 + * If we are establishing a connection then insert QoS paramerters
85995 if (qos) {
85996 skb_put(skb, 9); /* 21 left */
85997 - frame->saddr = cpu_to_le32(self->saddr);
85998 - frame->daddr = cpu_to_le32(self->daddr);
85999 + put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
86000 + put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
86002 frame->ncaddr = self->caddr;
86005 ret = irlap_insert_qos_negotiation_params(self, skb);
86006 if (ret < 0) {
86007 dev_kfree_skb(skb);
86008 @@ -154,13 +155,13 @@
86009 * Received SNRM (Set Normal Response Mode) command frame
86012 -static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
86013 - struct irlap_info *info)
86014 +static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
86015 + struct irlap_info *info)
86017 struct snrm_frame *frame;
86019 frame = (struct snrm_frame *) skb->data;
86022 if (skb->len >= sizeof(struct snrm_frame)) {
86023 /* Copy the new connection address ignoring the C/R bit */
86024 info->caddr = frame->ncaddr & 0xFE;
86025 @@ -170,11 +171,11 @@
86026 IRDA_DEBUG(3, "%s(), invalid connection address!\n", __FUNCTION__);
86027 return;
86031 /* Copy peer device address */
86032 - info->daddr = le32_to_cpu(frame->saddr);
86033 - info->saddr = le32_to_cpu(frame->daddr);
86035 + info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
86036 + info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
86038 /* Only accept if addressed directly to us */
86039 if (info->saddr != self->saddr) {
86040 IRDA_DEBUG(2, "%s(), not addressed to us!\n", __FUNCTION__);
86041 @@ -198,9 +199,9 @@
86042 struct sk_buff *skb;
86043 struct ua_frame *frame;
86044 int ret;
86047 IRDA_DEBUG(2, "%s() <%ld>\n", __FUNCTION__, jiffies);
86050 ASSERT(self != NULL, return;);
86051 ASSERT(self->magic == LAP_MAGIC, return;);
86053 @@ -212,13 +213,13 @@
86054 return;
86056 frame = (struct ua_frame *) skb_put(skb, 10);
86059 /* Build UA response */
86060 frame->caddr = self->caddr;
86061 frame->control = UA_RSP | PF_BIT;
86063 - frame->saddr = cpu_to_le32(self->saddr);
86064 - frame->daddr = cpu_to_le32(self->daddr);
86065 + put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
86066 + put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
86068 /* Should we send QoS negotiation parameters? */
86069 if (qos) {
86070 @@ -243,7 +244,7 @@
86072 struct sk_buff *skb = NULL;
86073 __u8 *frame;
86076 ASSERT(self != NULL, return;);
86077 ASSERT(self->magic == LAP_MAGIC, return;);
86079 @@ -252,7 +253,7 @@
86080 return;
86082 frame = skb_put( skb, 2);
86085 if (self->state == LAP_NDM)
86086 frame[0] = CBROADCAST;
86087 else
86088 @@ -260,7 +261,7 @@
86090 frame[1] = DM_RSP | PF_BIT;
86092 - irlap_queue_xmit(self, skb);
86093 + irlap_queue_xmit(self, skb);
86097 @@ -269,11 +270,11 @@
86098 * Send disconnect (DISC) frame
86101 -void irlap_send_disc_frame(struct irlap_cb *self)
86102 +void irlap_send_disc_frame(struct irlap_cb *self)
86104 struct sk_buff *skb = NULL;
86105 __u8 *frame;
86108 IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
86110 ASSERT(self != NULL, return;);
86111 @@ -284,7 +285,7 @@
86112 return;
86114 frame = skb_put(skb, 2);
86117 frame[0] = self->caddr | CMD_FRAME;
86118 frame[1] = DISC_CMD | PF_BIT;
86120 @@ -295,17 +296,17 @@
86121 * Function irlap_send_discovery_xid_frame (S, s, command)
86123 * Build and transmit a XID (eXchange station IDentifier) discovery
86124 - * frame.
86125 + * frame.
86127 -void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
86128 - __u8 command, discovery_t *discovery)
86129 +void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
86130 + __u8 command, discovery_t *discovery)
86132 struct sk_buff *skb = NULL;
86133 struct xid_frame *frame;
86134 - __u32 bcast = BROADCAST;
86135 + __u32 bcast = BROADCAST, daddr;
86136 __u8 *info;
86138 - IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
86139 + IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
86140 command);
86142 ASSERT(self != NULL, return;);
86143 @@ -328,13 +329,14 @@
86145 frame->ident = XID_FORMAT;
86147 - frame->saddr = cpu_to_le32(self->saddr);
86149 if (command)
86150 - frame->daddr = cpu_to_le32(bcast);
86151 + daddr = bcast;
86152 else
86153 - frame->daddr = cpu_to_le32(discovery->daddr);
86155 + daddr = discovery->daddr;
86157 + put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
86158 + put_unaligned(cpu_to_le32(daddr), &frame->daddr);
86160 switch (S) {
86161 case 1:
86162 frame->flags = 0x00;
86163 @@ -353,10 +355,10 @@
86164 break;
86167 - frame->slotnr = s;
86168 + frame->slotnr = s;
86169 frame->version = 0x00;
86171 - /*
86172 + /*
86173 * Provide info for final slot only in commands, and for all
86174 * responses. Send the second byte of the hint only if the
86175 * EXTENSION bit is set in the first byte.
86176 @@ -365,7 +367,7 @@
86177 int len;
86179 if (discovery->hints.byte[0] & HINT_EXTENSION) {
86180 - info = skb_put(skb, 2);
86181 + info = skb_put(skb, 2);
86182 info[0] = discovery->hints.byte[0];
86183 info[1] = discovery->hints.byte[1];
86184 } else {
86185 @@ -378,7 +380,7 @@
86186 len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
86187 info = skb_put(skb, len);
86188 memcpy(info, discovery->nickname, len);
86189 - }
86191 irlap_queue_xmit(self, skb);
86194 @@ -388,9 +390,9 @@
86195 * Received a XID discovery response
86198 -static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
86199 - struct sk_buff *skb,
86200 - struct irlap_info *info)
86201 +static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
86202 + struct sk_buff *skb,
86203 + struct irlap_info *info)
86205 struct xid_frame *xid;
86206 discovery_t *discovery = NULL;
86207 @@ -404,8 +406,8 @@
86209 xid = (struct xid_frame *) skb->data;
86211 - info->daddr = le32_to_cpu(xid->saddr);
86212 - info->saddr = le32_to_cpu(xid->daddr);
86213 + info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
86214 + info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
86216 /* Make sure frame is addressed to us */
86217 if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
86218 @@ -439,11 +441,11 @@
86219 discovery->charset = discovery_info[1];
86220 text = (char *) &discovery_info[2];
86222 - /*
86223 - * Terminate info string, should be safe since this is where the
86224 + /*
86225 + * Terminate info string, should be safe since this is where the
86226 * FCS bytes resides.
86228 - skb->data[skb->len] = '\0';
86229 + skb->data[skb->len] = '\0';
86230 strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
86231 discovery->name_len = strlen(discovery->nickname);
86233 @@ -458,9 +460,9 @@
86234 * Received a XID discovery command
86237 -static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
86238 - struct sk_buff *skb,
86239 - struct irlap_info *info)
86240 +static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
86241 + struct sk_buff *skb,
86242 + struct irlap_info *info)
86244 struct xid_frame *xid;
86245 discovery_t *discovery = NULL;
86246 @@ -469,8 +471,8 @@
86248 xid = (struct xid_frame *) skb->data;
86250 - info->daddr = le32_to_cpu(xid->saddr);
86251 - info->saddr = le32_to_cpu(xid->daddr);
86252 + info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
86253 + info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
86255 /* Make sure frame is addressed to us */
86256 if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
86257 @@ -497,11 +499,11 @@
86258 return;
86260 info->s = xid->slotnr;
86263 discovery_info = skb_pull(skb, sizeof(struct xid_frame));
86265 - /*
86266 - * Check if last frame
86267 + /*
86268 + * Check if last frame
86270 if (info->s == 0xff) {
86271 /* Check if things are sane at this point... */
86272 @@ -518,7 +520,7 @@
86273 WARNING("%s(), unable to malloc!\n", __FUNCTION__);
86274 return;
86278 discovery->daddr = info->daddr;
86279 discovery->saddr = self->saddr;
86280 discovery->timestamp = jiffies;
86281 @@ -533,11 +535,11 @@
86282 discovery->charset = discovery_info[1];
86283 text = (char *) &discovery_info[2];
86285 - /*
86286 - * Terminate string, should be safe since this is where the
86287 + /*
86288 + * Terminate string, should be safe since this is where the
86289 * FCS bytes resides.
86291 - skb->data[skb->len] = '\0';
86292 + skb->data[skb->len] = '\0';
86293 strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
86294 discovery->name_len = strlen(discovery->nickname);
86296 @@ -554,7 +556,7 @@
86297 * Build and transmit RR (Receive Ready) frame. Notice that it is currently
86298 * only possible to send RR frames with the poll bit set.
86300 -void irlap_send_rr_frame(struct irlap_cb *self, int command)
86301 +void irlap_send_rr_frame(struct irlap_cb *self, int command)
86303 struct sk_buff *skb;
86304 __u8 *frame;
86305 @@ -562,9 +564,9 @@
86306 skb = dev_alloc_skb(16);
86307 if (!skb)
86308 return;
86311 frame = skb_put(skb, 2);
86314 frame[0] = self->caddr;
86315 frame[0] |= (command) ? CMD_FRAME : 0;
86317 @@ -576,7 +578,7 @@
86319 * Function irlap_send_rd_frame (self)
86321 - * Request disconnect. Used by a secondary station to request the
86322 + * Request disconnect. Used by a secondary station to request the
86323 * disconnection of the link.
86325 void irlap_send_rd_frame(struct irlap_cb *self)
86326 @@ -587,9 +589,9 @@
86327 skb = dev_alloc_skb(16);
86328 if (!skb)
86329 return;
86332 frame = skb_put(skb, 2);
86335 frame[0] = self->caddr;
86336 frame[1] = RD_RSP | PF_BIT;
86338 @@ -603,8 +605,8 @@
86339 * making it inline since its called only from one single place
86340 * (irlap_driver_rcv).
86342 -static inline void irlap_recv_rr_frame(struct irlap_cb *self,
86343 - struct sk_buff *skb,
86344 +static inline void irlap_recv_rr_frame(struct irlap_cb *self,
86345 + struct sk_buff *skb,
86346 struct irlap_info *info, int command)
86348 info->nr = skb->data[1] >> 5;
86349 @@ -620,7 +622,7 @@
86351 struct sk_buff *skb = NULL;
86352 __u8 *frame;
86355 ASSERT( self != NULL, return;);
86356 ASSERT( self->magic == LAP_MAGIC, return;);
86358 @@ -629,7 +631,7 @@
86359 return;
86361 frame = skb_put( skb, 2);
86364 frame[0] = self->caddr;
86365 frame[0] |= (command) ? CMD_FRAME : 0;
86367 @@ -639,7 +641,7 @@
86369 frame[2] = 0;
86371 - IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
86372 + IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
86374 irlap_queue_xmit(self, skb);
86376 @@ -650,8 +652,8 @@
86377 * Received RNR (Receive Not Ready) frame from peer station
86380 -static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
86381 - struct irlap_info *info, int command)
86382 +static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
86383 + struct irlap_info *info, int command)
86385 info->nr = skb->data[1] >> 5;
86387 @@ -663,13 +665,13 @@
86388 irlap_do_event(self, RECV_RNR_RSP, skb, info);
86391 -static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
86392 +static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
86393 struct irlap_info *info, int command)
86395 IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
86397 info->nr = skb->data[1] >> 5;
86400 /* Check if this is a command or a response frame */
86401 if (command)
86402 irlap_do_event(self, RECV_REJ_CMD, skb, info);
86403 @@ -677,13 +679,13 @@
86404 irlap_do_event(self, RECV_REJ_RSP, skb, info);
86407 -static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
86408 +static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
86409 struct irlap_info *info, int command)
86411 IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
86413 info->nr = skb->data[1] >> 5;
86416 /* Check if this is a command or a response frame */
86417 if (command)
86418 irlap_do_event(self, RECV_SREJ_CMD, skb, info);
86419 @@ -691,7 +693,7 @@
86420 irlap_do_event(self, RECV_SREJ_RSP, skb, info);
86423 -static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
86424 +static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
86425 struct irlap_info *info, int command)
86427 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
86428 @@ -709,9 +711,9 @@
86429 * Received UA (Unnumbered Acknowledgement) frame
86432 -static inline void irlap_recv_ua_frame(struct irlap_cb *self,
86433 - struct sk_buff *skb,
86434 - struct irlap_info *info)
86435 +static inline void irlap_recv_ua_frame(struct irlap_cb *self,
86436 + struct sk_buff *skb,
86437 + struct irlap_info *info)
86439 irlap_do_event(self, RECV_UA_RSP, skb, info);
86441 @@ -728,25 +730,25 @@
86443 if (skb->data[1] == I_FRAME) {
86445 - /*
86446 + /*
86447 * Insert frame sequence number (Vs) in control field before
86448 * inserting into transmit window queue.
86450 skb->data[1] = I_FRAME | (self->vs << 1);
86453 /* Copy buffer */
86454 tx_skb = skb_clone(skb, GFP_ATOMIC);
86455 if (tx_skb == NULL) {
86456 return;
86459 - /*
86460 - * Insert frame in store, in case of retransmissions
86462 + /*
86463 + * Insert frame in store, in case of retransmissions
86465 skb_queue_tail(&self->wx_list, skb_get(skb));
86468 self->vs = (self->vs + 1) % 8;
86469 - self->ack_required = FALSE;
86470 + self->ack_required = FALSE;
86471 self->window -= 1;
86473 irlap_send_i_frame( self, tx_skb, CMD_FRAME);
86474 @@ -761,40 +763,40 @@
86476 * Send I(nformation) frame as primary with poll bit set
86478 -void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
86479 +void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
86481 struct sk_buff *tx_skb;
86483 /* Stop P timer */
86484 del_timer(&self->poll_timer);
86487 /* Is this reliable or unreliable data? */
86488 if (skb->data[1] == I_FRAME) {
86490 - /*
86492 + /*
86493 * Insert frame sequence number (Vs) in control field before
86494 * inserting into transmit window queue.
86496 skb->data[1] = I_FRAME | (self->vs << 1);
86499 /* Copy buffer */
86500 tx_skb = skb_clone(skb, GFP_ATOMIC);
86501 if (tx_skb == NULL) {
86502 return;
86505 - /*
86506 - * Insert frame in store, in case of retransmissions
86508 + /*
86509 + * Insert frame in store, in case of retransmissions
86511 skb_queue_tail(&self->wx_list, skb_get(skb));
86513 - /*
86515 + /*
86516 * Set poll bit if necessary. We do this to the copied
86517 * skb, since retransmitted need to set or clear the poll
86518 - * bit depending on when they are sent.
86519 + * bit depending on when they are sent.
86521 tx_skb->data[1] |= PF_BIT;
86524 self->vs = (self->vs + 1) % 8;
86525 self->ack_required = FALSE;
86527 @@ -827,8 +829,8 @@
86528 * Send I(nformation) frame as secondary with final bit set
86531 -void irlap_send_data_secondary_final(struct irlap_cb *self,
86532 - struct sk_buff *skb)
86533 +void irlap_send_data_secondary_final(struct irlap_cb *self,
86534 + struct sk_buff *skb)
86536 struct sk_buff *tx_skb = NULL;
86538 @@ -839,26 +841,26 @@
86539 /* Is this reliable or unreliable data? */
86540 if (skb->data[1] == I_FRAME) {
86542 - /*
86543 + /*
86544 * Insert frame sequence number (Vs) in control field before
86545 * inserting into transmit window queue.
86547 skb->data[1] = I_FRAME | (self->vs << 1);
86550 tx_skb = skb_clone(skb, GFP_ATOMIC);
86551 if (tx_skb == NULL) {
86552 return;
86553 - }
86556 /* Insert frame in store */
86557 skb_queue_tail(&self->wx_list, skb_get(skb));
86560 tx_skb->data[1] |= PF_BIT;
86562 - self->vs = (self->vs + 1) % 8;
86564 + self->vs = (self->vs + 1) % 8;
86565 self->ack_required = FALSE;
86567 - irlap_send_i_frame(self, tx_skb, RSP_FRAME);
86569 + irlap_send_i_frame(self, tx_skb, RSP_FRAME);
86570 } else {
86571 if (self->ack_required) {
86572 irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
86573 @@ -885,32 +887,32 @@
86574 * Send I(nformation) frame as secondary without final bit set
86577 -void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
86578 +void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
86580 struct sk_buff *tx_skb = NULL;
86582 /* Is this reliable or unreliable data? */
86583 if (skb->data[1] == I_FRAME) {
86585 - /*
86587 + /*
86588 * Insert frame sequence number (Vs) in control field before
86589 * inserting into transmit window queue.
86591 skb->data[1] = I_FRAME | (self->vs << 1);
86594 tx_skb = skb_clone(skb, GFP_ATOMIC);
86595 if (tx_skb == NULL) {
86596 return;
86597 - }
86601 /* Insert frame in store */
86602 skb_queue_tail(&self->wx_list, skb_get(skb));
86605 self->vs = (self->vs + 1) % 8;
86606 - self->ack_required = FALSE;
86607 + self->ack_required = FALSE;
86608 self->window -= 1;
86610 - irlap_send_i_frame(self, tx_skb, RSP_FRAME);
86611 + irlap_send_i_frame(self, tx_skb, RSP_FRAME);
86612 } else {
86613 irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
86614 self->window -= 1;
86615 @@ -920,8 +922,8 @@
86617 * Function irlap_resend_rejected_frames (nr)
86619 - * Resend frames which has not been acknowledged. Should be safe to
86620 - * traverse the list without locking it since this function will only be
86621 + * Resend frames which has not been acknowledged. Should be safe to
86622 + * traverse the list without locking it since this function will only be
86623 * called from interrupt context (BH)
86625 void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
86626 @@ -943,8 +945,8 @@
86627 while (skb != NULL) {
86628 irlap_wait_min_turn_around(self, &self->qos_tx);
86630 - /* We copy the skb to be retransmitted since we will have to
86631 - * modify it. Cloning will confuse packet sniffers
86632 + /* We copy the skb to be retransmitted since we will have to
86633 + * modify it. Cloning will confuse packet sniffers
86635 /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
86636 tx_skb = skb_copy(skb, GFP_ATOMIC);
86637 @@ -959,17 +961,17 @@
86638 /* Clear old Nr field + poll bit */
86639 tx_skb->data[1] &= 0x0f;
86641 - /*
86642 + /*
86643 * Set poll bit on the last frame retransmitted
86645 if (count-- == 1)
86646 tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
86647 else
86648 tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */
86651 irlap_send_i_frame(self, tx_skb, command);
86653 - /*
86654 + /*
86655 * If our skb is the last buffer in the list, then
86656 * we are finished, if not, move to the next sk-buffer
86658 @@ -979,23 +981,23 @@
86659 skb = skb->next;
86661 #if 0 /* Not yet */
86662 - /*
86663 + /*
86664 * We can now fill the window with additinal data frames
86666 while (skb_queue_len( &self->txq) > 0) {
86669 IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);
86670 - if ((skb_queue_len( &self->txq) > 0) &&
86671 + if ((skb_queue_len( &self->txq) > 0) &&
86672 (self->window > 0)) {
86673 - skb = skb_dequeue( &self->txq);
86674 + skb = skb_dequeue( &self->txq);
86675 ASSERT(skb != NULL, return;);
86678 - * If send window > 1 then send frame with pf
86679 + * If send window > 1 then send frame with pf
86680 * bit cleared
86681 - */
86682 - if ((self->window > 1) &&
86683 - skb_queue_len(&self->txq) > 0)
86684 + */
86685 + if ((self->window > 1) &&
86686 + skb_queue_len(&self->txq) > 0)
86688 irlap_send_data_primary(self, skb);
86689 } else {
86690 @@ -1023,14 +1025,14 @@
86691 if (skb != NULL) {
86692 irlap_wait_min_turn_around(self, &self->qos_tx);
86694 - /* We copy the skb to be retransmitted since we will have to
86695 - * modify it. Cloning will confuse packet sniffers
86696 + /* We copy the skb to be retransmitted since we will have to
86697 + * modify it. Cloning will confuse packet sniffers
86699 /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
86700 tx_skb = skb_copy(skb, GFP_ATOMIC);
86701 if (!tx_skb) {
86702 IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
86703 - return;
86704 + return;
86706 /* Unlink tx_skb from list */
86707 tx_skb->next = tx_skb->prev = NULL;
86708 @@ -1041,7 +1043,7 @@
86710 /* Set poll/final bit */
86711 tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
86714 irlap_send_i_frame(self, tx_skb, command);
86717 @@ -1052,15 +1054,15 @@
86718 * Contruct and transmit an Unnumbered Information (UI) frame
86721 -void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
86722 +void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
86723 __u8 caddr, int command)
86725 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
86728 ASSERT(self != NULL, return;);
86729 ASSERT(self->magic == LAP_MAGIC, return;);
86730 ASSERT(skb != NULL, return;);
86733 /* Insert connection address */
86734 skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);
86736 @@ -1072,13 +1074,13 @@
86738 * Contruct and transmit Information (I) frame
86740 -void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
86741 - int command)
86742 +void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
86743 + int command)
86745 /* Insert connection address */
86746 skb->data[0] = self->caddr;
86747 skb->data[0] |= (command) ? CMD_FRAME : 0;
86750 /* Insert next to receive (Vr) */
86751 skb->data[1] |= (self->vr << 5); /* insert nr */
86753 @@ -1091,9 +1093,9 @@
86754 * Receive and parse an I (Information) frame, no harm in making it inline
86755 * since it's called only from one single place (irlap_driver_rcv).
86757 -static inline void irlap_recv_i_frame(struct irlap_cb *self,
86758 - struct sk_buff *skb,
86759 - struct irlap_info *info, int command)
86760 +static inline void irlap_recv_i_frame(struct irlap_cb *self,
86761 + struct sk_buff *skb,
86762 + struct irlap_info *info, int command)
86764 info->nr = skb->data[1] >> 5; /* Next to receive */
86765 info->pf = skb->data[1] & PF_BIT; /* Final bit */
86766 @@ -1112,7 +1114,7 @@
86767 * Receive and parse an Unnumbered Information (UI) frame
86770 -static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
86771 +static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
86772 struct irlap_info *info)
86774 IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
86775 @@ -1128,19 +1130,19 @@
86776 * Received Frame Reject response.
86779 -static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
86780 - struct irlap_info *info)
86781 +static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
86782 + struct irlap_info *info)
86784 __u8 *frame;
86785 int w, x, y, z;
86787 IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
86790 ASSERT(self != NULL, return;);
86791 ASSERT(self->magic == LAP_MAGIC, return;);
86792 ASSERT(skb != NULL, return;);
86793 ASSERT(info != NULL, return;);
86796 frame = skb->data;
86798 info->nr = frame[2] >> 5; /* Next to receive */
86799 @@ -1151,11 +1153,11 @@
86800 x = frame[3] & 0x02;
86801 y = frame[3] & 0x04;
86802 z = frame[3] & 0x08;
86805 if (w) {
86806 IRDA_DEBUG(0, "Rejected control field is undefined or not "
86807 "implemented.\n");
86808 - }
86810 if (x) {
86811 IRDA_DEBUG(0, "Rejected control field was invalid because it "
86812 "contained a non permitted I field.\n");
86813 @@ -1178,7 +1180,7 @@
86814 * Send a test frame response
86817 -void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
86818 +void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
86819 struct sk_buff *cmd)
86821 struct sk_buff *skb;
86822 @@ -1191,7 +1193,7 @@
86824 /* Broadcast frames must include saddr and daddr fields */
86825 if (caddr == CBROADCAST) {
86826 - frame = (struct test_frame *)
86827 + frame = (struct test_frame *)
86828 skb_put(skb, sizeof(struct test_frame));
86830 /* Insert the swapped addresses */
86831 @@ -1218,28 +1220,28 @@
86832 * Receive a test frame
86835 -static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
86836 +static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
86837 struct irlap_info *info, int command)
86839 struct test_frame *frame;
86841 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
86844 frame = (struct test_frame *) skb->data;
86847 /* Broadcast frames must carry saddr and daddr fields */
86848 if (info->caddr == CBROADCAST) {
86849 if (skb->len < sizeof(struct test_frame)) {
86850 IRDA_DEBUG(0, "%s() test frame to short!\n", __FUNCTION__);
86851 return;
86855 /* Read and swap addresses */
86856 - info->daddr = le32_to_cpu(frame->saddr);
86857 - info->saddr = le32_to_cpu(frame->daddr);
86858 + info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
86859 + info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
86861 /* Make sure frame is addressed to us */
86862 - if ((info->saddr != self->saddr) &&
86863 + if ((info->saddr != self->saddr) &&
86864 (info->saddr != BROADCAST)) {
86865 return;
86867 @@ -1254,18 +1256,18 @@
86869 * Function irlap_driver_rcv (skb, netdev, ptype)
86871 - * Called when a frame is received. Dispatches the right receive function
86872 + * Called when a frame is received. Dispatches the right receive function
86873 * for processing of the frame.
86876 -int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
86877 +int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
86878 struct packet_type *ptype)
86880 struct irlap_info info;
86881 struct irlap_cb *self;
86882 int command;
86883 __u8 control;
86886 /* FIXME: should we get our own field? */
86887 self = (struct irlap_cb *) dev->atalk_ptr;
86889 @@ -1281,10 +1283,10 @@
86890 dev_kfree_skb(skb);
86891 return -1;
86895 command = skb->data[0] & CMD_FRAME;
86896 info.caddr = skb->data[0] & CBROADCAST;
86899 info.pf = skb->data[1] & PF_BIT;
86900 info.control = skb->data[1] & ~PF_BIT; /* Mask away poll/final bit */
86902 @@ -1295,7 +1297,7 @@
86903 IRDA_DEBUG(0, "%s(), wrong connection address!\n", __FUNCTION__);
86904 goto out;
86906 - /*
86907 + /*
86908 * Optimize for the common case and check if the frame is an
86909 * I(nformation) frame. Only I-frames have bit 0 set to 0
86911 @@ -1304,11 +1306,11 @@
86912 goto out;
86915 - * We now check is the frame is an S(upervisory) frame. Only
86916 + * We now check is the frame is an S(upervisory) frame. Only
86917 * S-frames have bit 0 set to 1 and bit 1 set to 0
86919 if (~control & 0x02) {
86920 - /*
86921 + /*
86922 * Received S(upervisory) frame, check which frame type it is
86923 * only the first nibble is of interest
86925 @@ -1332,8 +1334,8 @@
86927 goto out;
86929 - /*
86930 - * This must be a C(ontrol) frame
86931 + /*
86932 + * This must be a C(ontrol) frame
86934 switch (control) {
86935 case XID_RSP:
86936 @@ -1369,6 +1371,6 @@
86937 break;
86939 out:
86940 - dev_kfree_skb(skb);
86941 + dev_kfree_skb(skb);
86942 return 0;
86944 --- linux-2.4.25/net/irda/irttp.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
86945 +++ linux-2.4.25/net/irda/irttp.c 2004-03-31 17:15:09.000000000 +0200
86946 @@ -1665,8 +1665,8 @@
86948 self->rx_sdu_size = 0;
86951 - /*
86953 + /*
86954 * It's not trivial to keep track of how many credits are available
86955 * by incrementing at each packet, because delivery may fail
86956 * (irttp_do_data_indication() may requeue the frame) and because
86957 @@ -1676,7 +1676,7 @@
86958 * to send remote_credit.
86959 * No need to spinlock, write is atomic and self correcting...
86960 * Jean II
86961 - */
86962 + */
86963 self->avail_credit = (self->initial_credit -
86964 (self->remote_credit +
86965 skb_queue_len(&self->rx_queue) +
86966 --- linux-2.4.25/net/sched/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
86967 +++ linux-2.4.25/net/sched/Config.in 2004-03-31 17:15:09.000000000 +0200
86968 @@ -3,9 +3,9 @@
86970 tristate ' CBQ packet scheduler' CONFIG_NET_SCH_CBQ
86971 tristate ' HTB packet scheduler' CONFIG_NET_SCH_HTB
86972 -tristate ' CSZ packet scheduler' CONFIG_NET_SCH_CSZ
86973 +dep_tristate ' CSZ packet scheduler (experimental)' CONFIG_NET_SCH_CSZ $CONFIG_EXPERIMENTAL
86974 #tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
86975 -tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFSC
86976 +tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
86977 if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then
86978 dep_tristate ' ATM pseudo-scheduler' CONFIG_NET_SCH_ATM $CONFIG_ATM