summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/cris/Kconfig457
-rw-r--r--arch/cris/Makefile74
-rw-r--r--arch/cris/arch-v10/Kconfig422
-rw-r--r--arch/cris/arch-v10/README.mm (renamed from arch/cris/README.mm)4
-rw-r--r--arch/cris/arch-v10/boot/Makefile (renamed from arch/cris/boot/Makefile)0
-rw-r--r--arch/cris/arch-v10/boot/compressed/Makefile (renamed from arch/cris/boot/compressed/Makefile)0
-rw-r--r--arch/cris/arch-v10/boot/compressed/README (renamed from arch/cris/boot/compressed/README)2
-rw-r--r--arch/cris/arch-v10/boot/compressed/decompress.ld (renamed from arch/cris/boot/compressed/decompress.ld)1
-rw-r--r--arch/cris/arch-v10/boot/compressed/head.S (renamed from arch/cris/boot/compressed/head.S)2
-rw-r--r--arch/cris/arch-v10/boot/compressed/misc.c (renamed from arch/cris/boot/compressed/misc.c)8
-rw-r--r--arch/cris/arch-v10/boot/rescue/Makefile (renamed from arch/cris/boot/rescue/Makefile)0
-rw-r--r--arch/cris/arch-v10/boot/rescue/head.S (renamed from arch/cris/boot/rescue/head.S)10
-rw-r--r--arch/cris/arch-v10/boot/rescue/kimagerescue.S (renamed from arch/cris/boot/rescue/kimagerescue.S)2
-rw-r--r--arch/cris/arch-v10/boot/rescue/rescue.ld (renamed from arch/cris/boot/rescue/rescue.ld)0
-rw-r--r--arch/cris/arch-v10/boot/rescue/testrescue.S (renamed from arch/cris/boot/rescue/testrescue.S)2
-rw-r--r--arch/cris/arch-v10/boot/tools/build.c (renamed from arch/cris/boot/tools/build.c)0
-rw-r--r--arch/cris/arch-v10/defconfig506
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig (renamed from arch/cris/drivers/Kconfig)749
-rw-r--r--arch/cris/arch-v10/drivers/Makefile (renamed from arch/cris/drivers/Makefile)8
-rw-r--r--arch/cris/arch-v10/drivers/axisflashmap.c541
-rw-r--r--arch/cris/arch-v10/drivers/ds1302.c (renamed from arch/cris/drivers/ds1302.c)177
-rw-r--r--arch/cris/arch-v10/drivers/eeprom.c (renamed from arch/cris/drivers/eeprom.c)57
-rw-r--r--arch/cris/arch-v10/drivers/ethernet.c (renamed from arch/cris/drivers/ethernet.c)686
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c907
-rw-r--r--arch/cris/arch-v10/drivers/i2c.c (renamed from arch/cris/drivers/i2c.c)204
-rw-r--r--arch/cris/arch-v10/drivers/i2c.h (renamed from arch/cris/drivers/i2c.h)2
-rw-r--r--arch/cris/arch-v10/drivers/pcf8563.c287
-rw-r--r--arch/cris/arch-v10/drivers/serial.c (renamed from arch/cris/drivers/serial.c)1597
-rw-r--r--arch/cris/arch-v10/drivers/serial.h (renamed from arch/cris/drivers/serial.h)19
-rw-r--r--arch/cris/arch-v10/kernel/Makefile16
-rw-r--r--arch/cris/arch-v10/kernel/asm-offsets.c47
-rw-r--r--arch/cris/arch-v10/kernel/debugport.c (renamed from arch/cris/kernel/debugport.c)137
-rw-r--r--arch/cris/arch-v10/kernel/entry.S (renamed from arch/cris/kernel/entry.S)453
-rw-r--r--arch/cris/arch-v10/kernel/fasttimer.c996
-rw-r--r--arch/cris/arch-v10/kernel/head.S (renamed from arch/cris/kernel/head.S)40
-rw-r--r--arch/cris/arch-v10/kernel/irq.c219
-rw-r--r--arch/cris/arch-v10/kernel/kgdb.c (renamed from arch/cris/kernel/kgdb.c)20
-rw-r--r--arch/cris/arch-v10/kernel/process.c252
-rw-r--r--arch/cris/arch-v10/kernel/ptrace.c308
-rw-r--r--arch/cris/arch-v10/kernel/setup.c96
-rw-r--r--arch/cris/arch-v10/kernel/shadows.c (renamed from arch/cris/kernel/shadows.c)2
-rw-r--r--arch/cris/arch-v10/kernel/signal.c (renamed from arch/cris/kernel/signal.c)52
-rw-r--r--arch/cris/arch-v10/kernel/time.c359
-rw-r--r--arch/cris/arch-v10/kernel/traps.c132
-rw-r--r--arch/cris/arch-v10/lib/Makefile (renamed from arch/cris/lib/Makefile)2
-rw-r--r--arch/cris/arch-v10/lib/checksum.S (renamed from arch/cris/lib/checksum.S)2
-rw-r--r--arch/cris/arch-v10/lib/checksumcopy.S (renamed from arch/cris/lib/checksumcopy.S)2
-rw-r--r--arch/cris/arch-v10/lib/csumcpfruser.S (renamed from arch/cris/lib/csumcpfruser.S)0
-rw-r--r--arch/cris/arch-v10/lib/dmacopy.c (renamed from arch/cris/lib/dmacopy.c)2
-rw-r--r--arch/cris/arch-v10/lib/dram_init.S (renamed from arch/cris/lib/dram_init.S)35
-rw-r--r--arch/cris/arch-v10/lib/hw_settings.S (renamed from arch/cris/lib/hw_settings.S)2
-rw-r--r--arch/cris/arch-v10/lib/memset.c (renamed from arch/cris/lib/memset.c)0
-rw-r--r--arch/cris/arch-v10/lib/old_checksum.c (renamed from arch/cris/lib/old_checksum.c)4
-rw-r--r--arch/cris/arch-v10/lib/string.c (renamed from arch/cris/lib/string.c)0
-rw-r--r--arch/cris/arch-v10/lib/usercopy.c (renamed from arch/cris/lib/usercopy.c)166
-rw-r--r--arch/cris/arch-v10/mm/Makefile6
-rw-r--r--arch/cris/arch-v10/mm/fault.c175
-rw-r--r--arch/cris/arch-v10/mm/init.c265
-rw-r--r--arch/cris/arch-v10/mm/tlb.c236
-rw-r--r--arch/cris/arch-v10/output_arch.ld2
-rw-r--r--arch/cris/arch-v10/vmlinux.lds.S (renamed from arch/cris/vmlinux.lds.S)36
-rw-r--r--arch/cris/defconfig80
-rw-r--r--arch/cris/drivers/axisflashmap.c361
-rw-r--r--arch/cris/drivers/bluetooth/Makefile25
-rw-r--r--arch/cris/drivers/gpio.c460
-rw-r--r--arch/cris/drivers/ide.c877
-rw-r--r--arch/cris/drivers/lpslave/Makefile15
-rw-r--r--arch/cris/drivers/lpslave/bintocarr.pl30
-rw-r--r--arch/cris/drivers/lpslave/e100lpslave.README54
-rw-r--r--arch/cris/drivers/lpslave/e100lpslave.S429
-rw-r--r--arch/cris/drivers/lpslave/e100lpslave.h2
-rw-r--r--arch/cris/drivers/lpslave/e100lpslaveld22
-rw-r--r--arch/cris/drivers/lpslave/e100lpslavenet.c1012
-rw-r--r--arch/cris/drivers/parport.c572
-rw-r--r--arch/cris/drivers/sync_serial.c900
-rw-r--r--arch/cris/drivers/usb-host.c2516
-rw-r--r--arch/cris/drivers/usb-host.h243
-rw-r--r--arch/cris/kernel/Makefile18
-rw-r--r--arch/cris/kernel/entryoffsets.c62
-rw-r--r--arch/cris/kernel/irq.c284
-rw-r--r--arch/cris/kernel/ksyms.c19
-rw-r--r--arch/cris/kernel/module.c106
-rw-r--r--arch/cris/kernel/process.c304
-rw-r--r--arch/cris/kernel/ptrace.c279
-rw-r--r--arch/cris/kernel/setup.c132
-rw-r--r--arch/cris/kernel/sys_cris.c34
-rw-r--r--arch/cris/kernel/time.c386
-rw-r--r--arch/cris/kernel/traps.c143
-rw-r--r--arch/cris/mm/Makefile1
-rw-r--r--arch/cris/mm/extable.c53
-rw-r--r--arch/cris/mm/fault.c174
-rw-r--r--arch/cris/mm/init.c298
-rw-r--r--arch/cris/mm/ioremap.c18
-rw-r--r--arch/cris/mm/tlb.c223
-rw-r--r--include/asm-cris/arch-v10/bitops.h73
-rw-r--r--include/asm-cris/arch-v10/byteorder.h25
-rw-r--r--include/asm-cris/arch-v10/cache.h8
-rw-r--r--include/asm-cris/arch-v10/checksum.h29
-rw-r--r--include/asm-cris/arch-v10/delay.h20
-rw-r--r--include/asm-cris/arch-v10/dma.h46
-rw-r--r--include/asm-cris/arch-v10/elf.h71
-rw-r--r--include/asm-cris/arch-v10/io.h193
-rw-r--r--include/asm-cris/arch-v10/irq.h176
-rw-r--r--include/asm-cris/arch-v10/mmu.h106
-rw-r--r--include/asm-cris/arch-v10/offset.h33
-rw-r--r--include/asm-cris/arch-v10/page.h31
-rw-r--r--include/asm-cris/arch-v10/pgtable.h19
-rw-r--r--include/asm-cris/arch-v10/processor.h62
-rw-r--r--include/asm-cris/arch-v10/ptrace.h114
-rw-r--r--include/asm-cris/arch-v10/sv_addr.agh (renamed from include/asm-cris/sv_addr.agh)40
-rw-r--r--include/asm-cris/arch-v10/sv_addr_ag.h (renamed from include/asm-cris/sv_addr_ag.h)30
-rw-r--r--include/asm-cris/arch-v10/svinto.h (renamed from include/asm-cris/svinto.h)3
-rw-r--r--include/asm-cris/arch-v10/system.h62
-rw-r--r--include/asm-cris/arch-v10/thread_info.h12
-rw-r--r--include/asm-cris/arch-v10/timex.h30
-rw-r--r--include/asm-cris/arch-v10/tlb.h13
-rw-r--r--include/asm-cris/arch-v10/uaccess.h660
-rw-r--r--include/asm-cris/arch-v10/unistd.h148
-rw-r--r--include/asm-cris/arch-v10/user.h46
-rw-r--r--include/asm-cris/atomic.h88
-rw-r--r--include/asm-cris/axisflashmap.h19
-rw-r--r--include/asm-cris/bitops.h176
-rw-r--r--include/asm-cris/byteorder.h23
-rw-r--r--include/asm-cris/cache.h8
-rw-r--r--include/asm-cris/cacheflush.h23
-rw-r--r--include/asm-cris/checksum.h35
-rw-r--r--include/asm-cris/current.h10
-rw-r--r--include/asm-cris/delay.h25
-rw-r--r--include/asm-cris/dma.h52
-rw-r--r--include/asm-cris/elf.h64
-rw-r--r--include/asm-cris/etraxgpio.h69
-rw-r--r--include/asm-cris/fasttimer.h42
-rw-r--r--include/asm-cris/hardirq.h82
-rw-r--r--include/asm-cris/hdreg.h11
-rw-r--r--include/asm-cris/ide.h103
-rw-r--r--include/asm-cris/io.h205
-rw-r--r--include/asm-cris/ioctls.h3
-rw-r--r--include/asm-cris/ipc.h1
-rw-r--r--include/asm-cris/irq.h186
-rw-r--r--include/asm-cris/kmap_types.h25
-rw-r--r--include/asm-cris/mman.h3
-rw-r--r--include/asm-cris/mmu.h54
-rw-r--r--include/asm-cris/mmu_context.h2
-rw-r--r--include/asm-cris/module.h13
-rw-r--r--include/asm-cris/page.h90
-rw-r--r--include/asm-cris/param.h11
-rw-r--r--include/asm-cris/percpu.h6
-rw-r--r--include/asm-cris/pgalloc.h104
-rw-r--r--include/asm-cris/pgtable.h279
-rw-r--r--include/asm-cris/poll.h1
-rw-r--r--include/asm-cris/posix_types.h4
-rw-r--r--include/asm-cris/processor.h91
-rw-r--r--include/asm-cris/ptrace.h112
-rw-r--r--include/asm-cris/rs485.h20
-rw-r--r--include/asm-cris/rtc.h117
-rw-r--r--include/asm-cris/scatterlist.h2
-rw-r--r--include/asm-cris/semaphore-helper.h24
-rw-r--r--include/asm-cris/semaphore.h28
-rw-r--r--include/asm-cris/setup.h406
-rw-r--r--include/asm-cris/signal.h14
-rw-r--r--include/asm-cris/smp_lock.h73
-rw-r--r--include/asm-cris/sync_serial.h97
-rw-r--r--include/asm-cris/system.h164
-rw-r--r--include/asm-cris/termbits.h41
-rw-r--r--include/asm-cris/termios.h1
-rw-r--r--include/asm-cris/thread_info.h100
-rw-r--r--include/asm-cris/timex.h18
-rw-r--r--include/asm-cris/tlb.h16
-rw-r--r--include/asm-cris/tlbflush.h43
-rw-r--r--include/asm-cris/uaccess.h748
-rw-r--r--include/asm-cris/unistd.h198
-rw-r--r--include/asm-cris/user.h44
172 files changed, 12012 insertions, 15132 deletions
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index b092fb53d4cb..05fb1fe7620f 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -42,9 +42,9 @@ config ETRAX_KGDB
this option is turned on!
config ETRAX_WATCHDOG
- bool "Enable Etrax100 watchdog"
+ bool "Enable ETRAX watchdog"
help
- Enable the built-in watchdog timer support on Etrax100 embedded
+ Enable the built-in watchdog timer support on ETRAX based embedded
network computers.
config ETRAX_WATCHDOG_NICE_DOGGY
@@ -55,6 +55,26 @@ config ETRAX_WATCHDOG_NICE_DOGGY
printing oopses. Recommended for development systems but not for
production releases.
+config ETRAX_FAST_TIMER
+ bool "Enable ETRAX fast timer API"
+ help
+ This options enables the API to a fast timer implementation using
+ timer1 to get sub jiffie resolution timers (primarily one-shot
+ timers).
+ This is needed if CONFIG_ETRAX_SERIAL_FAST_TIMER is enabled.
+
+config PREEMPT
+ bool "Preemptible Kernel"
+ help
+ This option reduces the latency of the kernel when reacting to
+ real-time or interactive events by allowing a low priority process to
+ be preempted even if it is in kernel mode executing a system call.
+ This allows applications to run more reliably even when the system is
+ under load.
+
+ Say Y here if you are building a kernel for a desktop, embedded
+ or real-time system. Say N if you are unsure.
+
endmenu
@@ -65,32 +85,36 @@ choice
default ETRAX100LX
config ETRAX100LX
- bool "Etrax-100-LX-v1"
+ bool "ETRAX-100LX-v1"
help
- Support version 1 of the Etrax 100LX.
+ Support version 1 of the ETRAX 100LX.
config ETRAX100LX_V2
- bool "Etrax-100-LX-v2"
+ bool "ETRAX-100LX-v2"
help
- Support version 2 of the Etrax 100LX.
+ Support version 2 of the ETRAX 100LX.
config SVINTO_SIM
- bool "Etrax-100-LX-for-xsim-simulator"
+ bool "ETRAX-100LX-for-xsim-simulator"
help
Support the xsim ETRAX Simulator.
+config ETRAX200LX
+ bool "ETRAX-200LX-V32"
+ help
+ Support CRIS V32.
+
endchoice
-# Etrax100 LX v1 has a MMU "feature" requiring a low mapping
-config CRIS_LOW_MAP
- bool
- depends on ETRAX100LX
- default y
+config ETRAX_ARCH_V10
+ bool
+ default y if ETRAX100LX || ETRAX100LX_V2
+ default n if !(ETRAX100LX || ETRAX100LX_V2)
-config ETRAX_DRAM_VIRTUAL_BASE
- hex
- default "c0000000" if !ETRAX100LX
- default "60000000" if ETRAX100LX
+config ETRAX_ARCH_V32
+ bool
+ default y if ETRAX200LX
+ default n if !(ETRAX200LX)
config ETRAX_DRAM_SIZE
int "DRAM size (dec, in MB)"
@@ -114,404 +138,17 @@ config ETRAX_ROOT_DEVICE
should normally be the mtdblock device for the partition after the
last partition in the partition table.
-choice
- prompt "Product LED port"
- default ETRAX_PA_LEDS
-
-config ETRAX_PA_LEDS
- bool "Port-PA-LEDs"
- help
- The Etrax network driver is responsible for flashing LED's when
- packets arrive and are sent. It uses macros defined in
- <file:include/asm-cris/io.h>, and those macros are defined after what
- YOU choose in this option. The actual bits used are configured
- separately. Select this if the LEDs are on port PA. Some products
- put the leds on PB or a memory-mapped latch (CSP0) instead.
-
-config ETRAX_PB_LEDS
- bool "Port-PB-LEDs"
- help
- The Etrax network driver is responsible for flashing LED's when
- packets arrive and are sent. It uses macros defined in
- <file:include/asm-cris/io.h>, and those macros are defined after what
- YOU choose in this option. The actual bits used are configured
- separately. Select this if the LEDs are on port PB. Some products
- put the leds on PA or a memory-mapped latch (CSP0) instead.
-
-config ETRAX_CSP0_LEDS
- bool "Port-CSP0-LEDs"
- help
- The Etrax network driver is responsible for flashing LED's when
- packets arrive and are sent. It uses macros defined in
- <file:include/asm-cris/io.h>, and those macros are defined after what
- YOU choose in this option. The actual bits used are configured
- separately. Select this if the LEDs are on a memory-mapped latch
- using chip select CSP0, this is mapped at 0x90000000.
- Some products put the leds on PA or PB instead.
-
-config ETRAX_NO_LEDS
- bool "None"
- help
- Select this option if you don't have any LED at all.
-
-endchoice
-
-config ETRAX_LED1G
- int "First green LED bit"
- depends on !ETRAX_NO_LEDS
- default "2"
- help
- Bit to use for the first green LED.
- Most Axis products use bit 2 here.
-
-config ETRAX_LED1R
- int "First red LED bit"
- depends on !ETRAX_NO_LEDS
- default "3"
- help
- Bit to use for the first red LED.
- Most Axis products use bit 3 here.
- For products with only one controllable LED,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED2G
- int "Second green LED bit"
- depends on !ETRAX_NO_LEDS
- default "4"
- help
- Bit to use for the second green LED. The "Active" LED.
- Most Axis products use bit 4 here.
- For products with only one controllable LED,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED2R
- int "Second red LED bit"
- depends on !ETRAX_NO_LEDS
- default "5"
- help
- Bit to use for the second red LED.
- Most Axis products use bit 5 here.
- For products with only one controllable LED,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED3G
- int "Third green LED bit"
- depends on !ETRAX_NO_LEDS
- default "2"
- help
- Bit to use for the third green LED. The "Drive" LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED3R
- int "Third red LED bit"
- depends on !ETRAX_NO_LEDS
- default "2"
- help
- Bit to use for the third red LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED4R
- int "Fourth red LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the fourth red LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED4G
- int "Fourth green LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the fourth green LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
+# duplicate choice configs are not yet supported, so the followinguse
+# doesn't work:
-config ETRAX_LED5R
- int "Fifth red LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the fifth red LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
+source arch/cris/arch-v10/Kconfig
-config ETRAX_LED5G
- int "Fifth green LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the fifth green LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED6R
- int "Sixth red LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the sixth red LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED6G
- int "Sixth green LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the sixth green LED. The "Drive" LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED7R
- int "Seventh red LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the seventh red LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED7G
- int "Seventh green LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the seventh green LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED8Y
- int "Eigth yellow LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the eighth yellow LED. The "Drive" LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED9Y
- int "Ninth yellow LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the ninth yellow LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED10Y
- int "Tenth yellow LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the tenth yellow LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED11Y
- int "Eleventh yellow LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the eleventh yellow LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-config ETRAX_LED12R
- int "Twelfth red LED bit"
- depends on ETRAX_CSP0_LEDS
- default "2"
- help
- Bit to use for the twelfth red LED.
- For products with only one or two controllable LEDs,
- set this to same as CONFIG_ETRAX_LED1G (normally 2).
-
-choice
- prompt "Product debug-port"
- default ETRAX_DEBUG_PORT0
-
-config ETRAX_DEBUG_PORT0
- bool "Serial-0"
- help
- Choose a serial port for the ETRAX debug console. Default to
- port 0.
-
-config ETRAX_DEBUG_PORT1
- bool "Serial-1"
- help
- Use serial port 1 for the console.
-
-config ETRAX_DEBUG_PORT2
- bool "Serial-2"
- help
- Use serial port 2 for the console.
-
-config ETRAX_DEBUG_PORT3
- bool "Serial-3"
- help
- Use serial port 3 for the console.
-
-config ETRAX_DEBUG_PORT_NULL
- bool "disabled"
- help
- Disable serial-port debugging.
-
-endchoice
-
-choice
- prompt "Product rescue-port"
- default ETRAX_RESCUE_SER0
-
-config ETRAX_RESCUE_SER0
- bool "Serial-0"
- help
- Select one of the four serial ports as a rescue port. The default
- is port 0.
-
-config ETRAX_RESCUE_SER1
- bool "Serial-1"
- help
- Use serial port 1 as the rescue port.
-
-config ETRAX_RESCUE_SER2
- bool "Serial-2"
- help
- Use serial port 2 as the rescue port.
-
-config ETRAX_RESCUE_SER3
- bool "Serial-3"
- help
- Use serial port 3 as the rescue port.
-
-endchoice
-
-config ETRAX_DEF_R_WAITSTATES
- hex "R_WAITSTATES"
- default "95a6"
- help
- Waitstates for SRAM, Flash and peripherials (not DRAM). 95f8 is a
- good choice for most Axis products...
-
-config ETRAX_DEF_R_BUS_CONFIG
- hex "R_BUS_CONFIG"
- default "104"
- help
- Assorted bits controlling write mode, DMA burst length etc. 104 is
- a good choice for most Axis products...
-
-config ETRAX_SDRAM
- bool "SDRAM support"
- help
- Enable this if you use SDRAM chips and configure
- R_SDRAM_CONFIG and R_SDRAM_TIMING as well.
-
-config ETRAX_DEF_R_DRAM_CONFIG
- hex "R_DRAM_CONFIG"
- depends on !ETRAX_SDRAM
- default "1a200040"
- help
- The R_DRAM_CONFIG register specifies everything on how the DRAM
- chips in the system are connected to the Etrax CPU. This is
- different depending on the manufacturer, chip type and number of
- chips. So this value often needs to be different for each Axis
- product.
-
-config ETRAX_DEF_R_DRAM_TIMING
- hex "R_DRAM_TIMING"
- depends on !ETRAX_SDRAM
- default "5611"
- help
- Different DRAM chips have different speeds. Current Axis products
- use 50ns DRAM chips which can use the timing: 5611.
-
-config ETRAX_DEF_R_SDRAM_CONFIG
- hex "R_SDRAM_CONFIG"
- depends on ETRAX_SDRAM
- default "d2fa7878"
- help
- The R_SDRAM_CONFIG register specifies everything on how the SDRAM
- chips in the system are connected to the Etrax CPU. This is
- different depending on the manufacturer, chip type and number of
- chips. So this value often needs to be different for each Axis
- product.
-
-config ETRAX_DEF_R_SDRAM_TIMING
- hex "R_SDRAM_TIMING"
- depends on ETRAX_SDRAM
- default "80004801"
- help
- Different SDRAM chips have different timing.
-
-config ETRAX_DEF_R_PORT_PA_DIR
- hex "R_PORT_PA_DIR"
- default "1c"
- help
- Configures the direction of general port A bits. 1 is out, 0 is in.
- This is often totally different depending on the product used.
- There are some guidelines though - if you know that only LED's are
- connected to port PA, then they are usually connected to bits 2-4
- and you can therefore use 1c. On other boards which don't have the
- LED's at the general ports, these bits are used for all kinds of
- stuff. If you don't know what to use, it is always safe to put all
- as inputs, although floating inputs isn't good.
-
-config ETRAX_DEF_R_PORT_PA_DATA
- hex "R_PORT_PA_DATA"
- default "00"
- help
- Configures the initial data for the general port A bits. Most
- products should use 00 here.
-
-config ETRAX_DEF_R_PORT_PB_CONFIG
- hex "R_PORT_PB_CONFIG"
- default "00"
- help
- Configures the type of the general port B bits. 1 is chip select,
- 0 is port. Most products should use 00 here.
+endmenu
-config ETRAX_DEF_R_PORT_PB_DIR
- hex "R_PORT_PB_DIR"
- default "00"
- help
- Configures the direction of general port B bits. 1 is out, 0 is in.
- This is often totally different depending on the product used. Bits
- 0 and 1 on port PB are usually used for I2C communication, but the
- kernel I2C driver sets the appropriate directions itself so you
- don't need to take that into consideration when setting this option.
- If you don't know what to use, it is always safe to put all as
- inputs.
-
-config ETRAX_DEF_R_PORT_PB_DATA
- hex "R_PORT_PB_DATA"
- default "ff"
- help
- Configures the initial data for the general port A bits. Most
- products should use FF here.
+# bring in ETRAX built-in drivers
+menu "Drivers for built-in interfaces"
-config ETRAX_SOFT_SHUTDOWN
- bool "Software Shutdown Support"
- help
- Enable this if Etrax is used with a power-supply that can be turned
- off and on with PS_ON signal. Gives the possibility to detect
- powerbutton and then do a power off after unmounting disks.
-
-config ETRAX_SHUTDOWN_BIT
- int "Shutdown bit on port CSP0"
- depends on ETRAX_SOFT_SHUTDOWN
- default "12"
- help
- Configure what pin on CSPO-port that is used for controlling power
- supply.
-
-config ETRAX_POWERBUTTON_BIT
- int "Power button bit on port G"
- depends on ETRAX_SOFT_SHUTDOWN
- default "25"
- help
- Configure where power button is connected.
+source arch/cris/arch-v10/drivers/Kconfig
endmenu
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index 94c3671bdf5c..3a1a7d919725 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 2002/01/21 15:21:23 bjornw Exp $
+# $Id: Makefile,v 1.15 2003/07/04 12:47:53 tobiasa Exp $
# cris/Makefile
#
# This file is included by the global makefile so that you can add your own
@@ -13,37 +13,40 @@
# A bug in ld prevents us from having a (constant-value) symbol in a
# "ORIGIN =" or "LENGTH =" expression.
-LD = $(CROSS_COMPILE)ld -mcrislinux
+arch-y := v10
+arch-$(CONFIG_ETRAX_ARCH_V10) := v10
+
+# No config avaiable for make clean etc
+ifneq ($(arch-y),)
+SARCH := arch-$(arch-y)
+else
+SARCH :=
+endif
-# objcopy is used to make binary images from the resulting linked file
+LD = $(CROSS_COMPILE)ld -mcrislinux
+LDFLAGS_BLOB := --format binary --oformat elf32-cris \
+ -T arch/cris/$(SARCH)/output_arch.ld
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
-# -mlinux enables -march=v10, -fno-underscores, -D__linux__ among others
+AFLAGS_vmlinux.lds.o = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
+AFLAGS += -mlinux
-CFLAGS := $(CFLAGS) -mlinux -pipe
+CFLAGS := $(CFLAGS) -mlinux -march=$(arch-y) -pipe
ifdef CONFIG_ETRAX_KGDB
CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
CFLAGS += -fno-omit-frame-pointer
endif
-AFLAGS += -mlinux
+HEAD := arch/$(ARCH)/$(SARCH)/kernel/head.o
-HEAD := arch/cris/kernel/head.o
-
-ifdef CONFIG_ETRAX_AXISFLASHMAP
-# only build this if axis flash map is used, because they depend on
-# each others config options
-SUBDIRS += arch/cris/boot/rescue
-endif
LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a)
-core-y += arch/cris/kernel/ arch/cris/mm/
-drivers-y += arch/cris/drivers/
-libs-y += arch/cris/lib/lib.a $(LIBGCC)
-
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
+core-y += arch/$(ARCH)/$(SARCH)/kernel/ arch/$(ARCH)/$(SARCH)/mm/
+drivers-y += arch/$(ARCH)/$(SARCH)/drivers/
+libs-y += arch/$(ARCH)/$(SARCH)/lib/ $(LIBGCC)
vmlinux.bin: vmlinux
$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux.bin
@@ -65,20 +68,43 @@ cramfs:
clinux: vmlinux.bin decompress.bin rescue.bin
decompress.bin: FORCE
- @make -C arch/cris/boot/compressed decompress.bin
+ @make -C arch/$(ARCH)/boot/compressed decompress.bin
rescue.bin: FORCE
- @make -C arch/cris/boot/rescue rescue.bin
+ @make -C arch/$(ARCH)/boot/rescue rescue.bin
-zImage: vmlinux.bin
+zImage: vmlinux.bin rescue.bin
## zImage - Compressed kernel (gzip)
- @$(MAKEBOOT) zImage
+ @make -C arch/$(ARCH)/boot/ zImage
compressed: zImage
+archmrproper:
archclean:
- @$(MAKEBOOT) clean
+ $(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/$(ARCH)/boot
rm -f timage vmlinux.bin cramfs.img
rm -rf $(LD_SCRIPT).tmp
-archmrproper:
+prepare: arch/$(ARCH)/.links include/asm-$(ARCH)/.arch \
+ include/asm-$(ARCH)/$(SARCH)/offset.h
+
+# Create some links to make all tools happy
+arch/$(ARCH)/.links:
+ @ln -sfn $(SARCH)/drivers arch/$(ARCH)/drivers
+ @ln -sfn $(SARCH)/boot arch/$(ARCH)/boot
+ @ln -sfn $(SARCH)/lib arch/$(ARCH)/lib
+ @ln -sfn $(SARCH)/vmlinux.lds.S arch/$(ARCH)/vmlinux.lds.S
+ @touch $@
+
+# Create link to sub arch includes
+include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
+ @echo ' Making asm-$(ARCH)/arch -> asm-$(ARCH)/$(SARCH) symlink'
+ @rm -f include/asm-$(ARCH)/arch
+ @ln -sf $(SARCH) include/asm-$(ARCH)/arch
+ @touch $@
+
+arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
+ include/config/MARKER
+
+include/asm-$(ARCH)/$(SARCH)/offset.h: arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s
+ $(call filechk,gen-asm-offsets)
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
new file mode 100644
index 000000000000..2ca64cc40c63
--- /dev/null
+++ b/arch/cris/arch-v10/Kconfig
@@ -0,0 +1,422 @@
+# ETRAX 100LX v1 has a MMU "feature" requiring a low mapping
+config CRIS_LOW_MAP
+ bool
+ depends on ETRAX_ARCH_V10 && ETRAX100LX
+ default y
+
+config ETRAX_DRAM_VIRTUAL_BASE
+ hex
+ depends on ETRAX_ARCH_V10
+ default "c0000000" if !ETRAX100LX
+ default "60000000" if ETRAX100LX
+
+choice
+ prompt "Product LED port"
+ depends on ETRAX_ARCH_V10
+ default ETRAX_PA_LEDS
+
+config ETRAX_PA_LEDS
+ bool "Port-PA-LEDs"
+ help
+ The ETRAX network driver is responsible for flashing LED's when
+ packets arrive and are sent. It uses macros defined in
+ <file:include/asm-cris/io.h>, and those macros are defined after what
+ YOU choose in this option. The actual bits used are configured
+ separately. Select this if the LEDs are on port PA. Some products
+ put the leds on PB or a memory-mapped latch (CSP0) instead.
+
+config ETRAX_PB_LEDS
+ bool "Port-PB-LEDs"
+ help
+ The ETRAX network driver is responsible for flashing LED's when
+ packets arrive and are sent. It uses macros defined in
+ <file:include/asm-cris/io.h>, and those macros are defined after what
+ YOU choose in this option. The actual bits used are configured
+ separately. Select this if the LEDs are on port PB. Some products
+ put the leds on PA or a memory-mapped latch (CSP0) instead.
+
+config ETRAX_CSP0_LEDS
+ bool "Port-CSP0-LEDs"
+ help
+ The ETRAX network driver is responsible for flashing LED's when
+ packets arrive and are sent. It uses macros defined in
+ <file:include/asm-cris/io.h>, and those macros are defined after what
+ YOU choose in this option. The actual bits used are configured
+ separately. Select this if the LEDs are on a memory-mapped latch
+ using chip select CSP0, this is mapped at 0x90000000.
+ Some products put the leds on PA or PB instead.
+
+config ETRAX_NO_LEDS
+ bool "None"
+ help
+ Select this option if you don't have any LED at all.
+
+endchoice
+
+config ETRAX_LED1G
+ int "First green LED bit"
+ depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS
+ default "2"
+ help
+ Bit to use for the first green LED.
+ Most Axis products use bit 2 here.
+
+config ETRAX_LED1R
+ int "First red LED bit"
+ depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS
+ default "3"
+ help
+ Bit to use for the first red LED.
+ Most Axis products use bit 3 here.
+ For products with only one controllable LED,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED2G
+ int "Second green LED bit"
+ depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS
+ default "4"
+ help
+ Bit to use for the second green LED. The "Active" LED.
+ Most Axis products use bit 4 here.
+ For products with only one controllable LED,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED2R
+ int "Second red LED bit"
+ depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS
+ default "5"
+ help
+ Bit to use for the second red LED.
+ Most Axis products use bit 5 here.
+ For products with only one controllable LED,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED3G
+ int "Third green LED bit"
+ depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS
+ default "2"
+ help
+ Bit to use for the third green LED. The "Drive" LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED3R
+ int "Third red LED bit"
+ depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS
+ default "2"
+ help
+ Bit to use for the third red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED4R
+ int "Fourth red LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the fourth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED4G
+ int "Fourth green LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the fourth green LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED5R
+ int "Fifth red LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the fifth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED5G
+ int "Fifth green LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the fifth green LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED6R
+ int "Sixth red LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the sixth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED6G
+ int "Sixth green LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the sixth green LED. The "Drive" LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED7R
+ int "Seventh red LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the seventh red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED7G
+ int "Seventh green LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the seventh green LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED8Y
+ int "Eigth yellow LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the eighth yellow LED. The "Drive" LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED9Y
+ int "Ninth yellow LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the ninth yellow LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED10Y
+ int "Tenth yellow LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the tenth yellow LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED11Y
+ int "Eleventh yellow LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the eleventh yellow LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+config ETRAX_LED12R
+ int "Twelfth red LED bit"
+ depends on ETRAX_CSP0_LEDS
+ default "2"
+ help
+ Bit to use for the twelfth red LED.
+ For products with only one or two controllable LEDs,
+ set this to same as CONFIG_ETRAX_LED1G (normally 2).
+
+choice
+ prompt "Product debug-port"
+ depends on ETRAX_ARCH_V10
+ default ETRAX_DEBUG_PORT0
+
+config ETRAX_DEBUG_PORT0
+ bool "Serial-0"
+ help
+ Choose a serial port for the ETRAX debug console. Default to
+ port 0.
+
+config ETRAX_DEBUG_PORT1
+ bool "Serial-1"
+ help
+ Use serial port 1 for the console.
+
+config ETRAX_DEBUG_PORT2
+ bool "Serial-2"
+ help
+ Use serial port 2 for the console.
+
+config ETRAX_DEBUG_PORT3
+ bool "Serial-3"
+ help
+ Use serial port 3 for the console.
+
+config ETRAX_DEBUG_PORT_NULL
+ bool "disabled"
+ help
+ Disable serial-port debugging.
+
+endchoice
+
+choice
+ prompt "Product rescue-port"
+ depends on ETRAX_ARCH_V10
+ default ETRAX_RESCUE_SER0
+
+config ETRAX_RESCUE_SER0
+ bool "Serial-0"
+ help
+ Select one of the four serial ports as a rescue port. The default
+ is port 0.
+
+config ETRAX_RESCUE_SER1
+ bool "Serial-1"
+ help
+ Use serial port 1 as the rescue port.
+
+config ETRAX_RESCUE_SER2
+ bool "Serial-2"
+ help
+ Use serial port 2 as the rescue port.
+
+config ETRAX_RESCUE_SER3
+ bool "Serial-3"
+ help
+ Use serial port 3 as the rescue port.
+
+endchoice
+
+config ETRAX_DEF_R_WAITSTATES
+ hex "R_WAITSTATES"
+ depends on ETRAX_ARCH_V10
+ default "95a6"
+ help
+ Waitstates for SRAM, Flash and peripherials (not DRAM). 95f8 is a
+ good choice for most Axis products...
+
+config ETRAX_DEF_R_BUS_CONFIG
+ hex "R_BUS_CONFIG"
+ depends on ETRAX_ARCH_V10
+ default "104"
+ help
+ Assorted bits controlling write mode, DMA burst length etc. 104 is
+ a good choice for most Axis products...
+
+config ETRAX_SDRAM
+ bool "SDRAM support"
+ depends on ETRAX_ARCH_V10
+ help
+ Enable this if you use SDRAM chips and configure
+ R_SDRAM_CONFIG and R_SDRAM_TIMING as well.
+
+config ETRAX_DEF_R_DRAM_CONFIG
+ hex "R_DRAM_CONFIG"
+ depends on ETRAX_ARCH_V10 && !ETRAX_SDRAM
+ default "1a200040"
+ help
+ The R_DRAM_CONFIG register specifies everything on how the DRAM
+ chips in the system are connected to the ETRAX CPU. This is
+ different depending on the manufacturer, chip type and number of
+ chips. So this value often needs to be different for each Axis
+ product.
+
+config ETRAX_DEF_R_DRAM_TIMING
+ hex "R_DRAM_TIMING"
+ depends on ETRAX_ARCH_V10 && !ETRAX_SDRAM
+ default "5611"
+ help
+ Different DRAM chips have different speeds. Current Axis products
+ use 50ns DRAM chips which can use the timing: 5611.
+
+config ETRAX_DEF_R_SDRAM_CONFIG
+ hex "R_SDRAM_CONFIG"
+ depends on ETRAX_ARCH_V10 && ETRAX_SDRAM
+ default "d2fa7878"
+ help
+ The R_SDRAM_CONFIG register specifies everything on how the SDRAM
+ chips in the system are connected to the ETRAX CPU. This is
+ different depending on the manufacturer, chip type and number of
+ chips. So this value often needs to be different for each Axis
+ product.
+
+config ETRAX_DEF_R_SDRAM_TIMING
+ hex "R_SDRAM_TIMING"
+ depends on ETRAX_ARCH_V10 && ETRAX_SDRAM
+ default "80004801"
+ help
+ Different SDRAM chips have different timing.
+
+config ETRAX_DEF_R_PORT_PA_DIR
+ hex "R_PORT_PA_DIR"
+ depends on ETRAX_ARCH_V10
+ default "1c"
+ help
+ Configures the direction of general port A bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_R_PORT_PA_DATA
+ hex "R_PORT_PA_DATA"
+ depends on ETRAX_ARCH_V10
+ default "00"
+ help
+ Configures the initial data for the general port A bits. Most
+ products should use 00 here.
+
+config ETRAX_DEF_R_PORT_PB_CONFIG
+ hex "R_PORT_PB_CONFIG"
+ depends on ETRAX_ARCH_V10
+ default "00"
+ help
+ Configures the type of the general port B bits. 1 is chip select,
+ 0 is port. Most products should use 00 here.
+
+config ETRAX_DEF_R_PORT_PB_DIR
+ hex "R_PORT_PB_DIR"
+ depends on ETRAX_ARCH_V10
+ default "00"
+ help
+ Configures the direction of general port B bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used. Bits
+ 0 and 1 on port PB are usually used for I2C communication, but the
+ kernel I2C driver sets the appropriate directions itself so you
+ don't need to take that into consideration when setting this option.
+ If you don't know what to use, it is always safe to put all as
+ inputs.
+
+config ETRAX_DEF_R_PORT_PB_DATA
+ hex "R_PORT_PB_DATA"
+ depends on ETRAX_ARCH_V10
+ default "ff"
+ help
+ Configures the initial data for the general port A bits. Most
+ products should use FF here.
+
+config ETRAX_SOFT_SHUTDOWN
+ bool "Software Shutdown Support"
+ depends on ETRAX_ARCH_V10
+ help
+ Enable this if ETRAX is used with a power-supply that can be turned
+ off and on with PS_ON signal. Gives the possibility to detect
+ powerbutton and then do a power off after unmounting disks.
+
+config ETRAX_SHUTDOWN_BIT
+ int "Shutdown bit on port CSP0"
+ depends on ETRAX_SOFT_SHUTDOWN
+ default "12"
+ help
+ Configure what pin on CSPO-port that is used for controlling power
+ supply.
+
+config ETRAX_POWERBUTTON_BIT
+ int "Power button bit on port G"
+ depends on ETRAX_SOFT_SHUTDOWN
+ default "25"
+ help
+ Configure where power button is connected.
diff --git a/arch/cris/README.mm b/arch/cris/arch-v10/README.mm
index 195ca898b55b..6f08903f3139 100644
--- a/arch/cris/README.mm
+++ b/arch/cris/arch-v10/README.mm
@@ -3,8 +3,8 @@ Memory management for CRIS/MMU
HISTORY:
$Log: README.mm,v $
-Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
-Import of Linux 2.5.1
+Revision 1.1 2001/12/17 13:59:27 bjornw
+Initial revision
Revision 1.1 2000/07/10 16:25:21 bjornw
Initial revision
diff --git a/arch/cris/boot/Makefile b/arch/cris/arch-v10/boot/Makefile
index fe6650368e6a..fe6650368e6a 100644
--- a/arch/cris/boot/Makefile
+++ b/arch/cris/arch-v10/boot/Makefile
diff --git a/arch/cris/boot/compressed/Makefile b/arch/cris/arch-v10/boot/compressed/Makefile
index 5f71c2c819e6..5f71c2c819e6 100644
--- a/arch/cris/boot/compressed/Makefile
+++ b/arch/cris/arch-v10/boot/compressed/Makefile
diff --git a/arch/cris/boot/compressed/README b/arch/cris/arch-v10/boot/compressed/README
index 349eb2ab4663..48b3db9924b9 100644
--- a/arch/cris/boot/compressed/README
+++ b/arch/cris/arch-v10/boot/compressed/README
@@ -1,6 +1,6 @@
Creation of the self-extracting compressed kernel image (vmlinuz)
-----------------------------------------------------------------
-$Id: README,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+$Id: README,v 1.1 2001/12/17 13:59:27 bjornw Exp $
This can be slightly confusing because it's a process with many steps.
diff --git a/arch/cris/boot/compressed/decompress.ld b/arch/cris/arch-v10/boot/compressed/decompress.ld
index 24be54924970..0b0a14fe6177 100644
--- a/arch/cris/boot/compressed/decompress.ld
+++ b/arch/cris/arch-v10/boot/compressed/decompress.ld
@@ -13,6 +13,7 @@ SECTIONS
_stext = . ;
*(.text)
*(.rodata)
+ *(.rodata.*)
_etext = . ;
} > dram
.data :
diff --git a/arch/cris/boot/compressed/head.S b/arch/cris/arch-v10/boot/compressed/head.S
index 84719ff14401..4cbdd4b1d9d6 100644
--- a/arch/cris/boot/compressed/head.S
+++ b/arch/cris/arch-v10/boot/compressed/head.S
@@ -10,7 +10,7 @@
#include <linux/config.h>
#define ASSEMBLER_MACROS_ONLY
-#include <asm/sv_addr_ag.h>
+#include <asm/arch/sv_addr_ag.h>
#define RAM_INIT_MAGIC 0x56902387
diff --git a/arch/cris/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c
index 906610b45625..9969c6242f75 100644
--- a/arch/cris/boot/compressed/misc.c
+++ b/arch/cris/arch-v10/boot/compressed/misc.c
@@ -1,7 +1,7 @@
/*
* misc.c
*
- * $Id: misc.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+ * $Id: misc.c,v 1.4 2003/04/09 05:20:45 starvik Exp $
*
* This is a collection of several routines from gzip-1.0.3
* adapted for Linux.
@@ -15,7 +15,7 @@
/* where the piggybacked kernel image expects itself to live.
* it is the same address we use when we network load an uncompressed
* image into DRAM, and it is the address the kernel is linked to live
- * at by etrax100.ld.
+ * at by vmlinux.lds.S
*/
#define KERNEL_LOAD_ADR 0x40004000
@@ -23,7 +23,7 @@
#include <linux/config.h>
#include <linux/types.h>
-#include <asm/svinto.h>
+#include <asm/arch/svinto.h>
/*
* gzip declarations
@@ -109,7 +109,7 @@ static void puts(const char *);
extern int end;
static long free_mem_ptr = (long)&end;
-#include "../../../../lib/inflate.c"
+#include "../../../../../lib/inflate.c"
static void *malloc(int size)
{
diff --git a/arch/cris/boot/rescue/Makefile b/arch/cris/arch-v10/boot/rescue/Makefile
index e9f2ba2ad02c..e9f2ba2ad02c 100644
--- a/arch/cris/boot/rescue/Makefile
+++ b/arch/cris/arch-v10/boot/rescue/Makefile
diff --git a/arch/cris/boot/rescue/head.S b/arch/cris/arch-v10/boot/rescue/head.S
index 52881742da43..8689ea972c46 100644
--- a/arch/cris/boot/rescue/head.S
+++ b/arch/cris/arch-v10/boot/rescue/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.2 2001/12/18 13:35:12 bjornw Exp $
+/* $Id: head.S,v 1.6 2003/04/09 08:12:43 pkj Exp $
*
* Rescue code, made to reside at the beginning of the
* flash-memory. when it starts, it checks a partition
@@ -52,7 +52,7 @@
*
* Bit 0 in flags signifies RW or RO. The rescue code only bothers
* to check the checksum for RO partitions, since the others will
- * change its data without updating the checksums. A 1 in bit 0
+ * change their data without updating the checksums. A 1 in bit 0
* means RO, 0 means RW. That way, it is possible to set a partition
* in RO mode initially, and later mark it as RW, since you can always
* write 0's to the flash.
@@ -60,12 +60,12 @@
* During the wait for serial input, the status LED will flash so the
* user knows something went wrong.
*
- * Copyright (C) 1999,2001 Axis Communications AB
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Axis Communications AB
*/
#include <linux/config.h>
#define ASSEMBLER_MACROS_ONLY
-#include <asm/sv_addr_ag.h>
+#include <asm/arch/sv_addr_ag.h>
;; The partitiontable is looked for at the first sector after the boot
;; sector. Sector size is 65536 bytes in all flashes we use.
@@ -192,7 +192,7 @@ no_newjump:
moveq -1, $r7
ploop: move.d [$r3+], $r1 ; partition offset (from ptable start)
- bne notfirst ; check if its the partition containing ptable
+ bne notfirst ; check if it is the partition containing ptable
nop ; yes..
move.d $r8, $r1 ; for its checksum check, skip the ptable
move.d [$r3+], $r2 ; partition length
diff --git a/arch/cris/boot/rescue/kimagerescue.S b/arch/cris/arch-v10/boot/rescue/kimagerescue.S
index 270774108b7e..264bf7afc9ad 100644
--- a/arch/cris/boot/rescue/kimagerescue.S
+++ b/arch/cris/arch-v10/boot/rescue/kimagerescue.S
@@ -1,4 +1,4 @@
-/* $Id: kimagerescue.S,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: kimagerescue.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
*
* Rescue code to be prepended on a kimage and copied to the
* rescue serial port.
diff --git a/arch/cris/boot/rescue/rescue.ld b/arch/cris/arch-v10/boot/rescue/rescue.ld
index 0b52a9490db6..0b52a9490db6 100644
--- a/arch/cris/boot/rescue/rescue.ld
+++ b/arch/cris/arch-v10/boot/rescue/rescue.ld
diff --git a/arch/cris/boot/rescue/testrescue.S b/arch/cris/arch-v10/boot/rescue/testrescue.S
index f39c69e26483..566a9f341254 100644
--- a/arch/cris/boot/rescue/testrescue.S
+++ b/arch/cris/arch-v10/boot/rescue/testrescue.S
@@ -1,4 +1,4 @@
-/* $Id: testrescue.S,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: testrescue.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
*
* Simple testcode to download by the rescue block.
* Just lits some LEDs to show it was downloaded correctly.
diff --git a/arch/cris/boot/tools/build.c b/arch/cris/arch-v10/boot/tools/build.c
index 2f9bbb26d603..2f9bbb26d603 100644
--- a/arch/cris/boot/tools/build.c
+++ b/arch/cris/arch-v10/boot/tools/build.c
diff --git a/arch/cris/arch-v10/defconfig b/arch/cris/arch-v10/defconfig
new file mode 100644
index 000000000000..9d40dd316576
--- /dev/null
+++ b/arch/cris/arch-v10/defconfig
@@ -0,0 +1,506 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_ETRAX_KGDB is not set
+# CONFIG_ETRAX_WATCHDOG is not set
+
+#
+# Hardware setup
+#
+CONFIG_ETRAX100LX=y
+# CONFIG_ETRAX100LX_V2 is not set
+# CONFIG_SVINTO_SIM is not set
+CONFIG_CRIS_LOW_MAP=y
+CONFIG_ETRAX_DRAM_VIRTUAL_BASE=60000000
+CONFIG_ETRAX_DRAM_SIZE=8
+CONFIG_ETRAX_FLASH_BUSWIDTH=2
+CONFIG_ETRAX_ROOT_DEVICE="/dev/mtdblock3"
+CONFIG_ETRAX_PA_LEDS=y
+# CONFIG_ETRAX_PB_LEDS is not set
+# CONFIG_ETRAX_CSP0_LEDS is not set
+# CONFIG_ETRAX_NO_LEDS is not set
+CONFIG_ETRAX_LED1G=2
+CONFIG_ETRAX_LED1R=2
+CONFIG_ETRAX_LED2G=2
+CONFIG_ETRAX_LED2R=2
+CONFIG_ETRAX_LED3R=2
+CONFIG_ETRAX_LED3G=2
+CONFIG_ETRAX_LED4R=2
+CONFIG_ETRAX_LED4G=2
+CONFIG_ETRAX_LED5R=2
+CONFIG_ETRAX_LED5G=2
+CONFIG_ETRAX_LED6R=2
+CONFIG_ETRAX_LED6G=2
+CONFIG_ETRAX_LED7R=2
+CONFIG_ETRAX_LED7G=2
+CONFIG_ETRAX_LED8Y=2
+CONFIG_ETRAX_LED9Y=2
+CONFIG_ETRAX_LED10Y=2
+CONFIG_ETRAX_LED11Y=2
+CONFIG_ETRAX_LED12R=2
+CONFIG_ETRAX_DEBUG_PORT0=y
+# CONFIG_ETRAX_DEBUG_PORT1 is not set
+# CONFIG_ETRAX_DEBUG_PORT2 is not set
+# CONFIG_ETRAX_DEBUG_PORT3 is not set
+CONFIG_ETRAX_RESCUE_SER0=y
+# CONFIG_ETRAX_RESCUE_SER1 is not set
+# CONFIG_ETRAX_RESCUE_SER2 is not set
+# CONFIG_ETRAX_RESCUE_SER3 is not set
+CONFIG_ETRAX_DEF_R_WAITSTATES=95a6
+CONFIG_ETRAX_DEF_R_BUS_CONFIG=104
+# CONFIG_ETRAX_SDRAM is not set
+CONFIG_ETRAX_DEF_R_DRAM_CONFIG=1a200040
+CONFIG_ETRAX_DEF_R_DRAM_TIMING=5611
+CONFIG_ETRAX_DEF_R_PORT_PA_DIR=1d
+CONFIG_ETRAX_DEF_R_PORT_PA_DATA=f0
+CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=00
+CONFIG_ETRAX_DEF_R_PORT_PB_DIR=1e
+CONFIG_ETRAX_DEF_R_PORT_PB_DATA=f3
+# CONFIG_ETRAX_SOFT_SHUTDOWN is not set
+
+#
+# Drivers for ETRAX 100LX built-in interfaces
+#
+CONFIG_ETRAX_ETHERNET=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set
+CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y
+# CONFIG_ETRAX_ETHERNET_LPSLAVE is not set
+CONFIG_ETRAX_SERIAL=y
+CONFIG_ETRAX_SERIAL_PORT0=y
+# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB is not set
+CONFIG_ETRAX_SERIAL_PORT1=y
+# CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB is not set
+# CONFIG_ETRAX_SERIAL_PORT2 is not set
+# CONFIG_ETRAX_SERIAL_PORT3 is not set
+# CONFIG_ETRAX_RS485 is not set
+# CONFIG_ETRAX_SYNCHRONOUS_SERIAL is not set
+# CONFIG_ETRAX_IDE is not set
+CONFIG_ETRAX_AXISFLASHMAP=y
+CONFIG_ETRAX_PTABLE_SECTOR=65536
+CONFIG_MTD=y
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_AMDSTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_ETRAX_I2C=y
+CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C=y
+# CONFIG_ETRAX_I2C_EEPROM is not set
+CONFIG_ETRAX_GPIO=y
+CONFIG_ETRAX_PA_BUTTON_BITMASK=02
+CONFIG_ETRAX_PA_CHANGEABLE_DIR=00
+CONFIG_ETRAX_PA_CHANGEABLE_BITS=FF
+CONFIG_ETRAX_PB_CHANGEABLE_DIR=00
+CONFIG_ETRAX_PB_CHANGEABLE_BITS=FF
+# CONFIG_ETRAX_USB_HOST is not set
+# CONFIG_USB is not set
+# CONFIG_ETRAX_DS1302 is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# RAM/ROM Device Drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_MTDRAM is not set
+
+#
+# Linearly Mapped Flash Device Drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_CFI_GEOMETRY is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_AMDSTD=y
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_SC520CDP is not set
+# CONFIG_MTD_SBC_MEDIAGX is not set
+# CONFIG_MTD_ELAN_104NC is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_CSTM_CFI_JEDEC is not set
+# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_VMAX is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_NAND_SPIA is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+# CONFIG_BLK_DEV_IDE is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_CRAMFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PROFILE is not set
diff --git a/arch/cris/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index fef010d37227..7b0684d07fcf 100644
--- a/arch/cris/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -1,8 +1,6 @@
-
-menu "Drivers for ETRAX 100LX built-in interfaces"
-
config ETRAX_ETHERNET
bool "Ethernet support"
+ depends on ETRAX_ARCH_V10
help
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
controller.
@@ -45,51 +43,39 @@ choice
config ETRAX_NETWORK_LED_ON_WHEN_LINK
bool "LED_on_when_link"
help
- Selecting LED_on_when_link will light the LED when there is a
- connection and will flash off when there is activity.
+ Selecting LED_on_when_link will light the LED when there is a
+ connection and will flash off when there is activity.
- Selecting LED_on_when_activity will light the LED only when
+ Selecting LED_on_when_activity will light the LED only when
there is activity.
- This setting will also affect the behaviour of other activity LEDs
- e.g. Bluetooth.
+ This setting will also affect the behaviour of other activity LEDs
+ e.g. Bluetooth.
config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
bool "LED_on_when_activity"
help
- Selecting LED_on_when_link will light the LED when there is a
- connection and will flash off when there is activity.
+ Selecting LED_on_when_link will light the LED when there is a
+ connection and will flash off when there is activity.
- Selecting LED_on_when_activity will light the LED only when
+ Selecting LED_on_when_activity will light the LED only when
there is activity.
- This setting will also affect the behaviour of other activity LEDs
- e.g. Bluetooth.
+ This setting will also affect the behaviour of other activity LEDs
+ e.g. Bluetooth.
endchoice
-config ETRAX_ETHERNET_LPSLAVE
- bool "Etrax Ethernet slave support (over lp0/1)"
- help
- This option enables a slave ETRAX 100 or ETRAX 100LX, connected to a
- master ETRAX 100 or ETRAX 100LX through par0 and par1, to act as an
- Ethernet controller.
-
-config ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
- bool "Slave has its own LEDs"
- depends on ETRAX_ETHERNET_LPSLAVE
- help
- Enable if the slave has it's own LEDs.
-
config ETRAX_SERIAL
bool "Serial-port support"
+ depends on ETRAX_ARCH_V10
help
Enables the ETRAX 100 serial driver for ser0 (ttyS0)
You probably want this enabled.
-# bool ' Use fast timers for DMA flush and RS-485 timing' CONFIG_ETRAX_SERIAL_FAST_TIMER n
config ETRAX_SERIAL_FAST_TIMER
- bool
+ bool "Use fast timers for serial DMA flush (experimental)"
+ depends on ETRAX_SERIAL
help
Select this to have the serial DMAs flushed at a higher rate than
normally, possible by using the fast timer API, the timeout is
@@ -107,7 +93,7 @@ config ETRAX_SERIAL_FLUSH_DMA_FAST
config ETRAX_SERIAL_RX_TIMEOUT_TICKS
int "Receive flush timeout (ticks) "
- depends on ETRAX_SERIAL && !ETRAX_SERIAL_FAST_TIMER && !ETRAX100_SERIAL_FLUSH_DMA_FAST
+ depends on ETRAX_SERIAL && !ETRAX_SERIAL_FAST_TIMER && !ETRAX_SERIAL_FLUSH_DMA_FAST
default "5"
help
Number of timer ticks between flush of receive fifo (1 tick = 10ms).
@@ -123,41 +109,84 @@ config ETRAX_SERIAL_PORT0
Normally you want this on, unless you use external DMA 1 that uses
the same DMA channels.
-config ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
- bool "Ser0 DTR, RI, DSR, CD on PB"
+choice
+ prompt "Ser0 DTR, RI, DSR and CD assignment"
depends on ETRAX_SERIAL_PORT0
+ default ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE
+
+config ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE
+ bool "No_DTR_RI_DSR_CD"
+
+config ETRAX_SER0_DTR_RI_DSR_CD_ON_PA
+ bool "DTR_RI_DSR_CD_on_PA"
+
+config ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
+ bool "DTR_RI_DSR_CD_on_PB"
help
Enables the status and control signals DTR, RI, DSR and CD on PB for
ser0.
+config ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB"
+
+endchoice
+
+config ETRAX_SER0_DTR_ON_PA_BIT
+ int "Ser0 DTR on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "4" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER0_RI_ON_PA_BIT
+ int "Ser0 RI on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "5" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER0_DSR_ON_PA_BIT
+ int "Ser0 DSR on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "6" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER0_CD_ON_PA_BIT
+ int "Ser0 CD on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "7" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+
config ETRAX_SER0_DTR_ON_PB_BIT
- int "Ser0 DTR on PB bit"
- depends on ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
- default "4"
+ int "Ser0 DTR on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "4" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the DTR signal for serial
port 0.
config ETRAX_SER0_RI_ON_PB_BIT
- int "Ser0 RI on PB bit"
- depends on ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
- default "5"
+ int "Ser0 RI on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "5" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the RI signal for serial
port 0.
config ETRAX_SER0_DSR_ON_PB_BIT
- int "Ser0 DSR on PB bit"
- depends on ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
- default "6"
+ int "Ser0 DSR on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "6" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the DSR signal for serial
port 0.
config ETRAX_SER0_CD_ON_PB_BIT
- int "Ser0 CD on PB bit"
- depends on ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
- default "7"
+ int "Ser0 CD on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT0
+ default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+ default "7" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the CD signal for serial
port 0.
@@ -168,41 +197,84 @@ config ETRAX_SERIAL_PORT1
help
Enables the ETRAX 100 serial driver for ser1 (ttyS1).
-config ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
- bool "Ser1 DTR, RI, DSR, CD on PB"
+choice
+ prompt "Ser1 DTR, RI, DSR and CD assignment"
depends on ETRAX_SERIAL_PORT1
+ default ETRAX_SER1_DTR_RI_DSR_CD_ON_NONE
+
+config ETRAX_SER1_DTR_RI_DSR_CD_ON_NONE
+ bool "No_DTR_RI_DSR_CD"
+
+config ETRAX_SER1_DTR_RI_DSR_CD_ON_PA
+ bool "DTR_RI_DSR_CD_on_PA"
+
+config ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
+ bool "DTR_RI_DSR_CD_on_PB"
help
Enables the status and control signals DTR, RI, DSR and CD on PB for
ser1.
+config ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB"
+
+endchoice
+
+config ETRAX_SER1_DTR_ON_PA_BIT
+ int "Ser1 DTR on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "4" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER1_RI_ON_PA_BIT
+ int "Ser1 RI on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "5" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER1_DSR_ON_PA_BIT
+ int "Ser1 DSR on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "6" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER1_CD_ON_PA_BIT
+ int "Ser1 CD on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "7" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+
config ETRAX_SER1_DTR_ON_PB_BIT
- int "Ser1 DTR on PB bit"
- depends on ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
- default "4"
+ int "Ser1 DTR on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "4" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the DTR signal for serial
port 1.
config ETRAX_SER1_RI_ON_PB_BIT
- int "Ser1 RI on PB bit"
- depends on ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
- default "5"
+ int "Ser1 RI on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "5" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the RI signal for serial
port 1.
config ETRAX_SER1_DSR_ON_PB_BIT
- int "Ser1 DSR on PB bit"
- depends on ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
- default "6"
+ int "Ser1 DSR on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "6" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the DSR signal for serial
port 1.
config ETRAX_SER1_CD_ON_PB_BIT
- int "Ser1 CD on PB bit"
- depends on ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
- default "7"
+ int "Ser1 CD on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT1
+ default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+ default "7" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PB port to carry the CD signal for serial
port 1.
@@ -216,51 +288,153 @@ config ETRAX_SERIAL_PORT2
help
Enables the ETRAX 100 serial driver for ser2 (ttyS2).
-config ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
- bool "Ser2 DTR, RI, DSR, CD on PA"
+choice
+ prompt "Ser2 DTR, RI, DSR and CD assignment"
depends on ETRAX_SERIAL_PORT2
+ default ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE
+
+config ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE
+ bool "No_DTR_RI_DSR_CD"
+
+config ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
+ bool "DTR_RI_DSR_CD_on_PA"
help
Enables the status and control signals DTR, RI, DSR and CD on PA for
ser2.
+config ETRAX_SER2_DTR_RI_DSR_CD_ON_PB
+ bool "DTR_RI_DSR_CD_on_PB"
+
+config ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB"
+
+endchoice
+
config ETRAX_SER2_DTR_ON_PA_BIT
- int "Ser2 DTR on PA bit"
- depends on ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
- default "4"
+ int "Ser2 DTR on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "4" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PA port to carry the DTR signal for serial
port 2.
config ETRAX_SER2_RI_ON_PA_BIT
- int "Ser2 RI on PA bit"
- depends on ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
- default "5"
+ int "Ser2 RI on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "5" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PA port to carry the RI signal for serial
port 2.
config ETRAX_SER2_DSR_ON_PA_BIT
- int "Ser2 DSR on PA bit"
- depends on ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
- default "6"
+ int "Ser2 DSR on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "6" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PA port to carry the DTR signal for serial
port 2.
config ETRAX_SER2_CD_ON_PA_BIT
- int "Ser2 CD on PA bit"
- depends on ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
- default "7"
+ int "Ser2 CD on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "7" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
help
Specify the pin of the PA port to carry the CD signal for serial
port 2.
+config ETRAX_SER2_DTR_ON_PB_BIT
+ int "Ser2 DTR on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "4" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER2_RI_ON_PB_BIT
+ int "Ser2 RI on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "5" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER2_DSR_ON_PB_BIT
+ int "Ser2 DSR on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "6" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+
+config ETRAX_SER2_CD_ON_PB_BIT
+ int "Ser2 CD on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT2
+ default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+ default "7" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+
config ETRAX_SERIAL_PORT3
bool "Serial port 3 enabled"
depends on ETRAX_SERIAL
help
Enables the ETRAX 100 serial driver for ser3 (ttyS3).
+choice
+ prompt "Ser3 DTR, RI, DSR and CD assignment"
+ depends on ETRAX_SERIAL_PORT3
+ default ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE
+
+config ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE
+ bool "No_DTR_RI_DSR_CD"
+
+config ETRAX_SER3_DTR_RI_DSR_CD_ON_PA
+ bool "DTR_RI_DSR_CD_on_PA"
+
+config ETRAX_SER3_DTR_RI_DSR_CD_ON_PB
+ bool "DTR_RI_DSR_CD_on_PB"
+
+config ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB"
+
+endchoice
+
+config ETRAX_SER3_DTR_ON_PA_BIT
+ int "Ser3 DTR on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
+config ETRAX_SER3_RI_ON_PA_BIT
+ int "Ser3 RI on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
+config ETRAX_SER3_DSR_ON_PA_BIT
+ int "Ser3 DSR on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
+config ETRAX_SER3_CD_ON_PA_BIT
+ int "Ser3 CD on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
+config ETRAX_SER3_DTR_ON_PB_BIT
+ int "Ser3 DTR on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
+config ETRAX_SER3_RI_ON_PB_BIT
+ int "Ser3 RI on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
+config ETRAX_SER3_DSR_ON_PB_BIT
+ int "Ser3 DSR on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
+config ETRAX_SER3_CD_ON_PB_BIT
+ int "Ser3 CD on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+ depends on ETRAX_SERIAL_PORT3
+ default "-1"
+
config ETRAX_RS485
bool "RS-485 support"
depends on ETRAX_SERIAL
@@ -272,7 +446,7 @@ config ETRAX_RS485_ON_PA
bool "RS-485 mode on PA"
depends on ETRAX_RS485
help
- Control Driver Output Enable on RS485 tranceiver using a pin on PA
+ Control Driver Output Enable on RS485 transceiver using a pin on PA
port:
Axis 2400/2401 uses PA 3.
@@ -281,7 +455,7 @@ config ETRAX_RS485_ON_PA_BIT
depends on ETRAX_RS485_ON_PA
default "3"
help
- Control Driver Output Enable on RS485 tranceiver using a this bit
+ Control Driver Output Enable on RS485 transceiver using a this bit
on PA port.
config ETRAX_RS485_DISABLE_RECEIVER
@@ -292,299 +466,9 @@ config ETRAX_RS485_DISABLE_RECEIVER
loopback. Not all products are able to do this in software only.
Axis 2400/2401 must disable receiver.
-config ETRAX_SYNCHRONOUS_SERIAL
- bool "Synchronous serial port support"
- help
- This option enables support for the ETRAX 100LX built-in
- synchronous serial ports. These ports are used for continuous
- streamed data like audio. The default setting is compatible
- with the STA 013 MP3 decoder, but can easily be tuned to fit
- any other audio encoder/decoder and SPI.
-
-config ETRAX_SYNCHRONOUS_SERIAL_PORT0
- bool "Synchronous serial port 0 enabled"
- depends on ETRAX_SYNCHRONOUS_SERIAL
- help
- Enables the ETRAX 100LX synchronous serial port 0 (syncser0).
-
-config ETRAX_SYNCHRONOUS_SERIAL0_DMA
- bool "Synchronous serial port 0 uses DMA"
- depends on ETRAX_SYNCHRONOUS_SERIAL_PORT0
- help
- Makes synchronous serial port 0 use DMA.
-
-config ETRAX_SYNCHRONOUS_SERIAL_PORT1
- bool "Synchronous serial port 1 enabled"
- depends on ETRAX_SYNCHRONOUS_SERIAL
- help
- Enables the ETRAX 100LX synchronous serial port 1 (syncser1).
-
-config ETRAX_SYNCHRONOUS_SERIAL1_DMA
- bool "Synchronous serial port 1 uses DMA"
- depends on ETRAX_SYNCHRONOUS_SERIAL_PORT1
- help
- Makes synchronous serial port 1 use DMA.
-
-config ETRAX_PARPORT
- bool "Parallel port support"
- help
- Say Y here to enable the ETRAX on-board parallel ports.
-
-config ETRAX_PARALLEL_PORT0
- bool "Parallel port 0 enabled"
- depends on ETRAX_PARPORT
- help
- Say Y here to enable parallel port 0.
-
-config ETRAX_PARALLEL_PORT1
- bool "Parallel port 1 enabled"
- depends on ETRAX_PARPORT
- help
- Say Y here to enable parallel port 1.
-
-# here we define the CONFIG_'s necessary to enable parallel port support
-config PARPORT
- tristate
- depends on ETRAX_PARPORT
- default y
- ---help---
- If you want to use devices connected to your machine's parallel port
- (the connector at the computer with 25 holes), e.g. printer, ZIP
- drive, PLIP link (Parallel Line Internet Protocol is mainly used to
- create a mini network by connecting the parallel ports of two local
- machines) etc., then you need to say Y here; please read
- <file:Documentation/parport.txt> and
- <file:drivers/parport/BUGS-parport>.
-
- For extensive information about drivers for many devices attaching
- to the parallel port see <http://www.torque.net/linux-pp.html> on
- the WWW.
-
- It is possible to share a single parallel port among several devices
- and it is safe to compile all the corresponding drivers into the
- kernel. If you want to compile parallel port support as a module
- ( = code which can be inserted in and removed from the running
- kernel whenever you want), say M here and read
- <file:Documentation/modules.txt>. The module will be called
- parport. If you have more than one parallel port and want to
- specify which port and IRQ to be used by this driver at module load
- time, take a look at <file:Documentation/parport.txt>.
-
- If unsure, say Y.
-
-config PARPORT_1284
- bool
- depends on ETRAX_PARPORT
- default y
- help
- If you have a printer that supports status readback or device ID, or
- want to use a device that uses enhanced parallel port transfer modes
- such as EPP and ECP, say Y here to enable advanced IEEE 1284
- transfer modes. Also say Y if you want device ID information to
- appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N.
-
-config PRINTER
- tristate
- depends on ETRAX_PARPORT
- default y
- ---help---
- If you intend to attach a printer to the parallel port of your Linux
- box (as opposed to using a serial printer; if the connector at the
- printer has 9 or 25 holes ["female"], then it's serial), say Y.
- Also read the Printing-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- It is possible to share one parallel port among several devices
- (e.g. printer and ZIP drive) and it is safe to compile the
- corresponding drivers into the kernel. If you want to compile this
- driver as a module however ( = code which can be inserted in and
- removed from the running kernel whenever you want), say M here and
- read <file:Documentation/modules.txt> and
- <file:Documentation/parport.txt>. The module will be called lp.
-
- If you have several parallel ports, you can specify which ports to
- use with the "lp" kernel command line option. (Try "man bootparam"
- or see the documentation of your boot loader (lilo or loadlin) about
- how to pass options to the kernel at boot time.) The syntax of the
- "lp" command line option can be found in <file:drivers/char/lp.c>.
-
- If you have more than 8 printers, you need to increase the LP_NO
- macro in lp.c and the PARPORT_MAX macro in parport.h.
-
-config ETRAX_IDE
- bool "ATA/IDE support"
- help
- Enable this to get support for ATA/IDE. You can't use parallel
- ports or SCSI ports at the same time.
-
-# here we should add the CONFIG_'s necessary to enable the basic
-# general ide drivers so the common case does not need to go
-# into that config submenu. enable disk and CD support. others
-# need to go fiddle in the submenu..
-config IDE
- tristate
- depends on ETRAX_IDE
- default y
- ---help---
- If you say Y here, your kernel will be able to manage low cost mass
- storage units such as ATA/(E)IDE and ATAPI units. The most common
- cases are IDE hard drives and ATAPI CD-ROM drives.
-
- If your system is pure SCSI and doesn't use these interfaces, you
- can say N here.
-
- Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard
- for mass storage units such as hard disks. It was designed by
- Western Digital and Compaq Computer in 1984. It was then named
- ST506. Quite a number of disks use the IDE interface.
-
- AT Attachment (ATA) is the superset of the IDE specifications.
- ST506 was also called ATA-1.
-
- Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is
- ATA-3. It provides support for larger disks (up to 8.4GB by means of
- the LBA standard), more disks (4 instead of 2) and for other mass
- storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is
- ATA-4 and provides faster (and more CPU friendly) transfer modes
- than previous PIO (Programmed processor Input/Output) from previous
- ATA/IDE standards by means of fast DMA controllers.
-
- ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and
- CD-ROM drives, similar in many respects to the SCSI protocol.
-
- SMART IDE (Self Monitoring, Analysis and Reporting Technology) was
- designed in order to prevent data corruption and disk crash by
- detecting pre hardware failure conditions (heat, access time, and
- the like...). Disks built since June 1995 may follow this standard.
- The kernel itself don't manage this; however there are quite a
- number of user programs such as smart that can query the status of
- SMART parameters disk.
-
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called ide.
-
- For further information, please read <file:Documentation/ide.txt>.
-
- If unsure, say Y.
-
-config BLK_DEV_IDE
- tristate
- depends on ETRAX_IDE
- default y
- ---help---
- If you say Y here, you will use the full-featured IDE driver to
- control up to ten ATA/IDE interfaces, each being able to serve a
- "master" and a "slave" device, for a total of up to twenty ATA/IDE
- disk/cdrom/tape/floppy drives.
-
- Useful information about large (>540 MB) IDE disks, multiple
- interfaces, what to do if ATA/IDE devices are not automatically
- detected, sound card ATA/IDE ports, module support, and other
- topics, is contained in <file:Documentation/ide.txt>. For detailed
- information about hard drives, consult the Disk-HOWTO and the
- Multi-Disk-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To fine-tune ATA/IDE drive/interface parameters for improved
- performance, look for the hdparm package at
- <ftp://ibiblio.org/pub/Linux/system/hardware/>.
-
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt> and
- <file:Documentation/ide.txt>. The module will be called ide-mod.
- Do not compile this driver as a module if your root file system (the
- one containing the directory /) is located on an IDE device.
-
- If you have one or more IDE drives, say Y or M here. If your system
- has no IDE drives, or if memory requirements are really tight, you
- could say N here, and select the "Old hard disk driver" below
- instead to save about 13 KB of memory in the kernel.
-
-config BLK_DEV_IDEDISK
- tristate
- depends on ETRAX_IDE
- default y
- ---help---
- This will include enhanced support for MFM/RLL/IDE hard disks. If
- you have a MFM/RLL/IDE disk, and there is no special reason to use
- the old hard disk driver instead, say Y. If you have an SCSI-only
- system, you can say N here.
-
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called ide-disk. Do not compile this driver as a module
- if your root file system (the one containing the directory /) is
- located on the IDE disk. If unsure, say Y.
-
-config BLK_DEV_IDECD
- tristate
- depends on ETRAX_IDE
- default y
- ---help---
- If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is
- a newer protocol used by IDE CD-ROM and TAPE drives, similar to the
- SCSI protocol. Most new CD-ROM drives use ATAPI, including the
- NEC-260, Mitsumi FX400, Sony 55E, and just about all non-SCSI
- double(2X) or better speed drives.
-
- If you say Y here, the CD-ROM drive will be identified at boot time
- along with other IDE devices, as "hdb" or "hdc", or something
- similar (check the boot messages with dmesg). If this is your only
- CD-ROM drive, you can say N to all other CD-ROM options, but be sure
- to say Y or M to "ISO 9660 CD-ROM file system support".
-
- Note that older versions of LILO (LInux LOader) cannot properly deal
- with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from
- <ftp://brun.dyndns.org/pub/linux/lilo/>.
-
- If you want to compile the driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called ide-cd.
-
-config BLK_DEV_IDEDMA
- bool
- depends on ETRAX_IDE
- default y
-
-config ETRAX_IDE_DELAY
- int "Delay for drives to regain consciousness"
- depends on ETRAX_IDE
- default "15"
- help
- Sets the time to wait for disks to regain consciousness after reset.
-
-choice
- prompt "IDE reset pin"
- depends on ETRAX_IDE
- default ETRAX_IDE_PB7_RESET
-
-config ETRAX_IDE_PB7_RESET
- bool "Port_PB_Bit_7"
- help
- Configures the pin used to reset the IDE bus.
-
-config ETRAX_IDE_G27_RESET
- bool "Port_G_Bit_27"
- help
- Configures the pin used to reset the IDE bus.
-
-config ETRAX_IDE_CSE1_16_RESET
- bool "Port_CSE1_Bit_16"
-
-config ETRAX_IDE_CSP0_8_RESET
- bool "Port_CSP0_Bit_08"
- help
- Configures the pin used to reset the IDE bus.
-
-endchoice
-
config ETRAX_AXISFLASHMAP
bool "Axis flash-map support"
+ depends on ETRAX_ARCH_V10
help
This option enables MTD mapping of flash devices. Needed to use
flash memories. If unsure, say Y.
@@ -637,6 +521,19 @@ config MTD_CFI_AMDSTD
provides support for one of those command sets, used on chips
chips including the AMD Am29LV320.
+config MTD_OBSOLETE_CHIPS
+ bool
+ depends on ETRAX_AXISFLASHMAP
+ default y
+ help
+ This option does not enable any code directly, but will allow you to
+ select some other chip drivers which are now considered obsolete,
+ because the generic CONFIG_JEDEC_PROBE code above should now detect
+ the chips which are supported by these drivers, and allow the generic
+ CFI-compatible drivers to drive the chips. Say 'N' here unless you have
+ already tried the CONFIG_JEDEC_PROBE method and reported its failure
+ to the MTD mailing list at <linux-mtd@lists.infradead.org>
+
config MTD_AMDSTD
tristate
depends on ETRAX_AXISFLASHMAP
@@ -695,10 +592,16 @@ config MTD_PARTITIONS
devices. Partitioning on NFTL 'devices' is a different - that's the
'normal' form of partitioning used on a block device.
+config MTD_CONCAT
+ tristate
+ depends on ETRAX_AXISFLASHMAP
+ default y
+
config ETRAX_I2C
bool "I2C support"
+ depends on ETRAX_ARCH_V10
help
- Enables an I2C driver on PB0 and PB1 on ETRAX100.
+ Enables an I2C driver on ETRAX100.
EXAMPLE usage:
i2c_arg = I2C_WRITEARG(STA013_WRITE_ADDR, reg, val);
ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_WRITEREG), i2c_arg);
@@ -717,8 +620,23 @@ config ETRAX_I2C_USES_PB_NOT_PB_I2C
I2C driver, like the DS1302 realtime-clock driver. If you are
uncertain, choose Y here.
+config ETRAX_I2C_DATA_PORT
+ int "I2C SDA bit number"
+ depends on ETRAX_I2C_USES_PB_NOT_PB_I2C
+ default "0"
+ help
+ Selects the pin on Port B where the data pin is connected
+
+config ETRAX_I2C_CLK_PORT
+ int "I2C SCL bit number"
+ depends on ETRAX_I2C_USES_PB_NOT_PB_I2C
+ default "1"
+ help
+ Select the pin on Port B where the clock pin is connected
+
config ETRAX_I2C_EEPROM
bool "I2C EEPROM (non-volatile RAM) support"
+ depends on ETRAX_I2C
help
Enables I2C EEPROM (non-volatile RAM) on PB0 and PB1 using the I2C
driver. Select size option: Probed, 2k, 8k, 16k.
@@ -755,8 +673,9 @@ endchoice
config ETRAX_GPIO
bool "GPIO support"
+ depends on ETRAX_ARCH_V10
---help---
- Enables the Etrax general port device (major 120, minors 0 and 1).
+ Enables the ETRAX general port device (major 120, minors 0 and 1).
You can use this driver to access the general port bits. It supports
these ioctl's:
#include <linux/etraxgpio.h>
@@ -778,7 +697,7 @@ config ETRAX_PA_BUTTON_BITMASK
use 02 here.
Use 00 if there are no buttons on PA.
If the bitmask is <> 00 a button driver will be included in the gpio
- driver. Etrax general I/O support must be enabled.
+ driver. ETRAX general I/O support must be enabled.
config ETRAX_PA_CHANGEABLE_DIR
hex "PA user changeable dir mask"
@@ -820,71 +739,37 @@ config ETRAX_PB_CHANGEABLE_BITS
Bit set = changeable.
You probably want 00 here.
-#bool 'ARTPEC-1 support' CONFIG_JULIETTE
-#
-#if [ "$CONFIG_JULIETTE" = "y" ]; then
-# source arch/cris/drivers/juliette/Config.in
-#fi
-config ETRAX_USB_HOST
- bool "USB host"
+config ETRAX_RTC
+ bool "Real Time Clock support"
+ depends on ETRAX_ARCH_V10
help
- This option enables the host functionality of the ETRAX 100LX
- built-in USB controller. In host mode the controller is designed
- for CTRL and BULK traffic only, INTR traffic may work as well
- however (depending on the requirements of timeliness).
-
-config USB
- tristate
- depends on ETRAX_USB_HOST
- default y
- ---help---
- Universal Serial Bus (USB) is a specification for a serial bus
- subsystem which offers higher speeds and more features than the
- traditional PC serial port. The bus supplies power to peripherals
- and allows for hot swapping. Up to 127 USB peripherals can be
- connected to a single USB port in a tree structure. The USB port is
- the root of the tree, the peripherals are the leaves and the inner
- nodes are special USB devices called hubs. Many newer PC's have USB
- ports and newer peripherals such as scanners, keyboards, mice,
- modems, and printers support the USB protocol and can be connected
- to the PC via those ports.
-
- Say Y here if your computer has a USB port and you want to use USB
- devices. You then need to say Y to at least one of "UHCI support"
- or "OHCI support" below (the type of interface that the USB hardware
- in your computer provides to the operating system) and then choose
- from among the drivers for USB peripherals. You may want to check
- out the information provided in <file:Documentation/usb/> and
- especially the links given in <file:Documentation/usb/usb-help.txt>.
-
- This code is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called usbcore. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt>.
-
-config ETRAX_USB_HOST_PORT1
- bool "USB port 1 enabled"
- depends on ETRAX_USB_HOST
- help
- This option enables port 1 of the ETRAX 100LX USB root hub (RH).
-
-config ETRAX_USB_HOST_PORT2
- bool "USB port 2 enabled"
- depends on ETRAX_USB_HOST
- help
- This option enables port 2 of the ETRAX 100LX USB root hub (RH).
-
-config ETRAX_DS1302
- bool "DS1302 Real Time Clock support"
- help
- Enables the driver for the DS1302 Real-Time Clock battery-backed
- chip on some products. The kernel reads the time when booting, and
+ Enables drivers for the Real-Time Clock battery-backed chips on
+ some products. The kernel reads the time when booting, and
the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
device, major 121. You can check the time with cat /proc/rtc, but
normal time reading should be done using libc function time and
friends.
+choice
+ prompt "RTC chip"
+ depends on ETRAX_RTC
+ default ETRAX_DS1302
+
+config ETRAX_DS1302
+ bool "DS1302"
+ help
+ Enables the driver for the DS1302 Real-Time Clock battery-backed
+ chip on some products.
+
+config ETRAX_PCF8563
+ bool "PCF8563"
+ help
+ Enables the driver for the PCF8563 Real-Time Clock battery-backed
+ chip on some products.
+
+endchoice
+
config ETRAX_DS1302_RST_ON_GENERIC_PORT
bool "DS1302 RST on Generic Port"
depends on ETRAX_DS1302
@@ -919,5 +804,17 @@ config ETRAX_DS1302_SDABIT
This is the bit number for the SDA signal line of the DS1302 RTC on
Port PB. This is probably best left at 2.
-endmenu
+config ETRAX_DS1302_TRICKLE_CHARGE
+ int "DS1302 Trickle charger value"
+ depends on ETRAX_DS1302
+ default "0"
+ help
+ This controls the initial value of the trickle charge register.
+ 0 = disabled (use this if you are unsure or have a non rechargable battery)
+ Otherwise the following values can be OR:ed together to control the
+ charge current:
+ 1 = 2kohm, 2 = 4kohm, 3 = 4kohm
+ 4 = 1 diode, 8 = 2 diodes
+ Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
+
diff --git a/arch/cris/drivers/Makefile b/arch/cris/arch-v10/drivers/Makefile
index 50da6d18d529..7160cdd7bdd1 100644
--- a/arch/cris/drivers/Makefile
+++ b/arch/cris/arch-v10/drivers/Makefile
@@ -4,13 +4,11 @@
obj-$(CONFIG_ETRAX_ETHERNET) += ethernet.o
obj-$(CONFIG_ETRAX_SERIAL) += serial.o
-obj-$(CONFIG_ETRAX_IDE) += ide.o
obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
obj-$(CONFIG_ETRAX_I2C) += i2c.o
obj-$(CONFIG_ETRAX_I2C_EEPROM) += eeprom.o
obj-$(CONFIG_ETRAX_GPIO) += gpio.o
-obj-$(CONFIG_ETRAX_USB_HOST) += usb-host.o
-obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
-obj-$(CONFIG_ETRAX_PARPORT) += parport.o
obj-$(CONFIG_ETRAX_DS1302) += ds1302.o
-obj-$(CONFIG_ETRAX_ETHERNET_LPSLAVE) += lpslave
+obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o
+
+
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
new file mode 100644
index 000000000000..c6f90bdcf07c
--- /dev/null
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -0,0 +1,541 @@
+/*
+ * Physical mapping layer for MTD using the Axis partitiontable format
+ *
+ * Copyright (c) 2001, 2002 Axis Communications AB
+ *
+ * This file is under the GPL.
+ *
+ * First partition is always sector 0 regardless of if we find a partitiontable
+ * or not. In the start of the next sector, there can be a partitiontable that
+ * tells us what other partitions to define. If there isn't, we use a default
+ * partition split defined below.
+ *
+ * $Log: axisflashmap.c,v $
+ * Revision 1.6 2003/07/04 08:27:37 starvik
+ * Merge of Linux 2.5.74
+ *
+ * Revision 1.5 2002/12/11 13:13:57 starvik
+ * Added arch/ to v10 specific includes
+ * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
+ *
+ * Revision 1.4 2002/11/20 11:56:10 starvik
+ * Merge of Linux 2.5.48
+ *
+ * Revision 1.3 2002/11/13 14:54:13 starvik
+ * Copied from linux 2.4
+ *
+ * Revision 1.28 2002/10/01 08:08:43 jonashg
+ * The first partition ends at the start of the partition table.
+ *
+ * Revision 1.27 2002/08/21 09:23:13 jonashg
+ * Speling.
+ *
+ * Revision 1.26 2002/08/21 08:35:20 jonashg
+ * Cosmetic change to printouts.
+ *
+ * Revision 1.25 2002/08/21 08:15:42 jonashg
+ * Made it compile even without CONFIG_MTD_CONCAT defined.
+ *
+ * Revision 1.24 2002/08/20 13:12:35 jonashg
+ * * New approach to probing. Probe cse0 and cse1 separately and (mtd)concat
+ * the results.
+ * * Removed compile time tests concerning how the mtdram driver has been
+ * configured. The user will know about the misconfiguration at runtime
+ * instead. (The old approach made it impossible to use mtdram for anything
+ * else than RAM boot).
+ *
+ * Revision 1.23 2002/05/13 12:12:28 johana
+ * Allow compile without CONFIG_MTD_MTDRAM but warn at compiletime and
+ * be informative at runtime.
+ *
+ * Revision 1.22 2002/05/13 10:24:44 johana
+ * Added #if checks on MTDRAM CONFIG
+ *
+ * Revision 1.21 2002/05/06 16:05:20 johana
+ * Removed debug printout.
+ *
+ * Revision 1.20 2002/05/06 16:03:00 johana
+ * No more cramfs as root hack in generic code.
+ * It's handled by axisflashmap using mtdram.
+ *
+ * Revision 1.19 2002/03/15 17:10:28 bjornw
+ * Changed comment about cached access since we changed this before
+ *
+ * Revision 1.18 2002/03/05 17:06:15 jonashg
+ * Try amd_flash probe before cfi_probe since amd_flash driver can handle two
+ * (or more) flash chips of different model and the cfi driver cannot.
+ *
+ * Revision 1.17 2001/11/12 19:42:38 pkj
+ * Fixed compiler warnings.
+ *
+ * Revision 1.16 2001/11/08 11:18:58 jonashg
+ * Always read from uncached address to avoid problems with flushing
+ * cachelines after write and MTD-erase. No performance loss have been
+ * seen yet.
+ *
+ * Revision 1.15 2001/10/19 12:41:04 jonashg
+ * Name of probe has changed in MTD.
+ *
+ * Revision 1.14 2001/09/21 07:14:10 jonashg
+ * Made root filesystem (cramfs) use mtdblock driver when booting from flash.
+ *
+ * Revision 1.13 2001/08/15 13:57:35 jonashg
+ * Entire MTD updated to the linux 2.4.7 version.
+ *
+ * Revision 1.12 2001/06/11 09:50:30 jonashg
+ * Oops, 2MB is 0x200000 bytes.
+ *
+ * Revision 1.11 2001/06/08 11:39:44 jonashg
+ * Changed sizes and offsets in axis_default_partitions to use
+ * CONFIG_ETRAX_PTABLE_SECTOR.
+ *
+ * Revision 1.10 2001/05/29 09:42:03 jonashg
+ * Use macro for end marker length instead of sizeof.
+ *
+ * Revision 1.9 2001/05/29 08:52:52 jonashg
+ * Gave names to the magic fours (size of the ptable end marker).
+ *
+ * Revision 1.8 2001/05/28 15:36:20 jonashg
+ * * Removed old comment about ptable location in flash (it's a CONFIG_ option).
+ * * Variable ptable was initialized twice to the same value.
+ *
+ * Revision 1.7 2001/04/05 13:41:46 markusl
+ * Updated according to review remarks
+ *
+ * Revision 1.6 2001/03/07 09:21:21 bjornw
+ * No need to waste .data
+ *
+ * Revision 1.5 2001/03/06 16:27:01 jonashg
+ * Probe the entire flash area for flash devices.
+ *
+ * Revision 1.4 2001/02/23 12:47:15 bjornw
+ * Uncached flash in LOW_MAP moved from 0xe to 0x8
+ *
+ * Revision 1.3 2001/02/16 12:11:45 jonashg
+ * MTD driver amd_flash is now included in MTD CVS repository.
+ * (It's now in drivers/mtd).
+ *
+ * Revision 1.2 2001/02/09 11:12:22 jonashg
+ * Support for AMD compatible non-CFI flash chips.
+ * Only tested with Toshiba TC58FVT160 so far.
+ *
+ * Revision 1.1 2001/01/12 17:01:18 bjornw
+ * * Added axisflashmap.c, a physical mapping for MTD that reads and understands
+ * Axis partition-table format.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/mtd/concat.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/mtdram.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/axisflashmap.h>
+#include <asm/mmu.h>
+#include <asm/arch/sv_addr_ag.h>
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define FLASH_UNCACHED_ADDR KSEG_8
+#define FLASH_CACHED_ADDR KSEG_5
+#else
+#define FLASH_UNCACHED_ADDR KSEG_E
+#define FLASH_CACHED_ADDR KSEG_F
+#endif
+
+/* From head.S */
+extern unsigned long romfs_start, romfs_length, romfs_in_flash;
+
+/* Map driver functions. */
+
+static __u8 flash_read8(struct map_info *map, unsigned long ofs)
+{
+ return *(__u8 *)(map->map_priv_1 + ofs);
+}
+
+static __u16 flash_read16(struct map_info *map, unsigned long ofs)
+{
+ return *(__u16 *)(map->map_priv_1 + ofs);
+}
+
+static __u32 flash_read32(struct map_info *map, unsigned long ofs)
+{
+ return *(volatile unsigned int *)(map->map_priv_1 + ofs);
+}
+
+static void flash_copy_from(struct map_info *map, void *to,
+ unsigned long from, ssize_t len)
+{
+ memcpy(to, (void *)(map->map_priv_1 + from), len);
+}
+
+static void flash_write8(struct map_info *map, __u8 d, unsigned long adr)
+{
+ *(__u8 *)(map->map_priv_1 + adr) = d;
+}
+
+static void flash_write16(struct map_info *map, __u16 d, unsigned long adr)
+{
+ *(__u16 *)(map->map_priv_1 + adr) = d;
+}
+
+static void flash_write32(struct map_info *map, __u32 d, unsigned long adr)
+{
+ *(__u32 *)(map->map_priv_1 + adr) = d;
+}
+
+/*
+ * The map for chip select e0.
+ *
+ * We run into tricky coherence situations if we mix cached with uncached
+ * accesses to we only use the uncached version here.
+ *
+ * The size field is the total size where the flash chips may be mapped on the
+ * chip select. MTD probes should find all devices there and it does not matter
+ * if there are unmapped gaps or aliases (mirrors of flash devices). The MTD
+ * probes will ignore them.
+ *
+ * The start address in map_priv_1 is in virtual memory so we cannot use
+ * MEM_CSE0_START but must rely on that FLASH_UNCACHED_ADDR is the start
+ * address of cse0.
+ */
+static struct map_info map_cse0 = {
+ .name = "cse0",
+ .size = MEM_CSE0_SIZE,
+ .buswidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
+ .read8 = flash_read8,
+ .read16 = flash_read16,
+ .read32 = flash_read32,
+ .copy_from = flash_copy_from,
+ .write8 = flash_write8,
+ .write16 = flash_write16,
+ .write32 = flash_write32,
+ .map_priv_1 = FLASH_UNCACHED_ADDR
+};
+
+/*
+ * The map for chip select e1.
+ *
+ * If there was a gap between cse0 and cse1, map_priv_1 would get the wrong
+ * address, but there isn't.
+ */
+static struct map_info map_cse1 = {
+ .name = "cse1",
+ .size = MEM_CSE1_SIZE,
+ .buswidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
+ .read8 = flash_read8,
+ .read16 = flash_read16,
+ .read32 = flash_read32,
+ .copy_from = flash_copy_from,
+ .write8 = flash_write8,
+ .write16 = flash_write16,
+ .write32 = flash_write32,
+ .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE
+};
+
+/* If no partition-table was found, we use this default-set. */
+#define MAX_PARTITIONS 7
+#define NUM_DEFAULT_PARTITIONS 3
+
+/*
+ * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the
+ * size of one flash block and "filesystem"-partition needs 5 blocks to be able
+ * to use JFFS.
+ */
+static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
+ {
+ .name = "boot firmware",
+ .size = CONFIG_ETRAX_PTABLE_SECTOR,
+ .offset = 0
+ },
+ {
+ .name = "kernel",
+ .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
+ .offset = CONFIG_ETRAX_PTABLE_SECTOR
+ },
+ {
+ .name = "filesystem",
+ .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,
+ .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
+ }
+};
+
+/* Initialize the ones normally used. */
+static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
+ {
+ .name = "part0",
+ .size = CONFIG_ETRAX_PTABLE_SECTOR,
+ .offset = 0
+ },
+ {
+ .name = "part1",
+ .size = 0,
+ .offset = 0
+ },
+ {
+ .name = "part2",
+ .size = 0,
+ .offset = 0
+ },
+ {
+ .name = "part3",
+ .size = 0,
+ .offset = 0
+ },
+ {
+ .name = "part4",
+ .size = 0,
+ .offset = 0
+ },
+ {
+ .name = "part5",
+ .size = 0,
+ .offset = 0
+ },
+ {
+ .name = "part6",
+ .size = 0,
+ .offset = 0
+ },
+};
+
+/*
+ * Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash
+ * chips in that order (because the amd_flash-driver is faster).
+ */
+static struct mtd_info *probe_cs(struct map_info *map_cs)
+{
+ struct mtd_info *mtd_cs = NULL;
+
+ printk("%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
+ map_cs->name, map_cs->size, map_cs->map_priv_1);
+
+#ifdef CONFIG_MTD_AMDSTD
+ mtd_cs = do_map_probe("amd_flash", map_cs);
+#endif
+#ifdef CONFIG_MTD_CFI
+ if (!mtd_cs) {
+ mtd_cs = do_map_probe("cfi_probe", map_cs);
+ }
+#endif
+
+ return mtd_cs;
+}
+
+/*
+ * Probe each chip select individually for flash chips. If there are chips on
+ * both cse0 and cse1, the mtd_info structs will be concatenated to one struct
+ * so that MTD partitions can cross chip boundries.
+ *
+ * The only known restriction to how you can mount your chips is that each
+ * chip select must hold similar flash chips. But you need external hardware
+ * to do that anyway and you can put totally different chips on cse0 and cse1
+ * so it isn't really much of a restriction.
+ */
+static struct mtd_info *flash_probe(void)
+{
+ struct mtd_info *mtd_cse0;
+ struct mtd_info *mtd_cse1;
+ struct mtd_info *mtd_cse;
+
+ mtd_cse0 = probe_cs(&map_cse0);
+ mtd_cse1 = probe_cs(&map_cse1);
+
+ if (!mtd_cse0 && !mtd_cse1) {
+ /* No chip found. */
+ return NULL;
+ }
+
+ if (mtd_cse0 && mtd_cse1) {
+#ifdef CONFIG_MTD_CONCAT
+ struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 };
+
+ /* Since the concatenation layer adds a small overhead we
+ * could try to figure out if the chips in cse0 and cse1 are
+ * identical and reprobe the whole cse0+cse1 window. But since
+ * flash chips are slow, the overhead is relatively small.
+ * So we use the MTD concatenation layer instead of further
+ * complicating the probing procedure.
+ */
+ mtd_cse = mtd_concat_create(mtds,
+ sizeof(mtds) / sizeof(mtds[0]),
+ "cse0+cse1");
+#else
+ printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
+ "(mis)configuration!\n", map_cse0.name, map_cse1.name);
+ mtd_cse = NULL;
+#endif
+ if (!mtd_cse) {
+ printk(KERN_ERR "%s and %s: Concatenation failed!\n",
+ map_cse0.name, map_cse1.name);
+
+ /* The best we can do now is to only use what we found
+ * at cse0.
+ */
+ mtd_cse = mtd_cse0;
+ map_destroy(mtd_cse1);
+ }
+ } else {
+ mtd_cse = mtd_cse0? mtd_cse0 : mtd_cse1;
+ }
+
+ return mtd_cse;
+}
+
+/*
+ * Probe the flash chip(s) and, if it succeeds, read the partition-table
+ * and register the partitions with MTD.
+ */
+static int __init init_axis_flash(void)
+{
+ struct mtd_info *mymtd;
+ int err = 0;
+ int pidx = 0;
+ struct partitiontable_head *ptable_head;
+ struct partitiontable_entry *ptable;
+ int use_default_ptable = 1; /* Until proven otherwise. */
+ const char *pmsg = " /dev/flash%d at 0x%08x, size 0x%08x\n";
+
+ if (!(mymtd = flash_probe())) {
+ /* There's no reason to use this module if no flash chip can
+ * be identified. Make sure that's understood.
+ */
+ panic("axisflashmap found no flash chip!\n");
+ }
+
+ printk("%s: 0x%08x bytes of flash memory.\n",
+ mymtd->name, mymtd->size);
+
+ mymtd->owner = THIS_MODULE;
+
+ ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
+ CONFIG_ETRAX_PTABLE_SECTOR + PARTITION_TABLE_OFFSET);
+ pidx++; /* First partition is always set to the default. */
+
+ if ((ptable_head->magic == PARTITION_TABLE_MAGIC)
+ && (ptable_head->size <
+ (MAX_PARTITIONS * sizeof(struct partitiontable_entry) +
+ PARTITIONTABLE_END_MARKER_SIZE))
+ && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) +
+ ptable_head->size -
+ PARTITIONTABLE_END_MARKER_SIZE)
+ == PARTITIONTABLE_END_MARKER)) {
+ /* Looks like a start, sane length and end of a
+ * partition table, lets check csum etc.
+ */
+ int ptable_ok = 0;
+ struct partitiontable_entry *max_addr =
+ (struct partitiontable_entry *)
+ ((unsigned long)ptable_head + sizeof(*ptable_head) +
+ ptable_head->size);
+ unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
+ unsigned char *p;
+ unsigned long csum = 0;
+
+ ptable = (struct partitiontable_entry *)
+ ((unsigned long)ptable_head + sizeof(*ptable_head));
+
+ /* Lets be PARANOID, and check the checksum. */
+ p = (unsigned char*) ptable;
+
+ while (p <= (unsigned char*)max_addr) {
+ csum += *p++;
+ csum += *p++;
+ csum += *p++;
+ csum += *p++;
+ }
+ ptable_ok = (csum == ptable_head->checksum);
+
+ /* Read the entries and use/show the info. */
+ printk(" Found a%s partition table at 0x%p-0x%p.\n",
+ (ptable_ok ? " valid" : "n invalid"), ptable_head,
+ max_addr);
+
+ /* We have found a working bootblock. Now read the
+ * partition table. Scan the table. It ends when
+ * there is 0xffffffff, that is, empty flash.
+ */
+ while (ptable_ok
+ && ptable->offset != 0xffffffff
+ && ptable < max_addr
+ && pidx < MAX_PARTITIONS) {
+
+ axis_partitions[pidx].offset = offset + ptable->offset;
+ axis_partitions[pidx].size = ptable->size;
+
+ printk(pmsg, pidx, axis_partitions[pidx].offset,
+ axis_partitions[pidx].size);
+ pidx++;
+ ptable++;
+ }
+ use_default_ptable = !ptable_ok;
+ }
+
+ if (romfs_in_flash) {
+ /* Add an overlapping device for the root partition (romfs). */
+
+ axis_partitions[pidx].name = "romfs";
+ axis_partitions[pidx].size = romfs_length;
+ axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
+ axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
+
+ printk(" Adding readonly flash partition for romfs image:\n");
+ printk(pmsg, pidx, axis_partitions[pidx].offset,
+ axis_partitions[pidx].size);
+ pidx++;
+ }
+
+ if (use_default_ptable) {
+ printk(" Using default partition table.\n");
+ err = add_mtd_partitions(mymtd, axis_default_partitions,
+ NUM_DEFAULT_PARTITIONS);
+ } else {
+ err = add_mtd_partitions(mymtd, axis_partitions, pidx);
+ }
+
+ if (err) {
+ panic("axisflashmap could not add MTD partitions!\n");
+ }
+
+ if (!romfs_in_flash) {
+ /* Create an RAM device for the root partition (romfs). */
+
+#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
+ /* No use trying to boot this kernel from RAM. Panic! */
+ printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "
+ "device due to kernel (mis)configuration!\n");
+ panic("This kernel cannot boot from RAM!\n");
+#else
+ struct mtd_info *mtd_ram;
+
+ mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
+ GFP_KERNEL);
+ if (!mtd_ram) {
+ panic("axisflashmap couldn't allocate memory for "
+ "mtd_info!\n");
+ }
+
+ printk(" Adding RAM partition for romfs image:\n");
+ printk(pmsg, pidx, romfs_start, romfs_length);
+
+ err = mtdram_init_device(mtd_ram, (void*)romfs_start,
+ romfs_length, "romfs");
+ if (err) {
+ panic("axisflashmap could not initialize MTD RAM "
+ "device!\n");
+ }
+#endif
+ }
+
+ return err;
+}
+
+/* This adds the above to the kernels init-call chain. */
+module_init(init_axis_flash);
diff --git a/arch/cris/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 23814c3843d3..175062133724 100644
--- a/arch/cris/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -7,8 +7,37 @@
*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init, get_rtc_status
*!
*! $Log: ds1302.c,v $
-*! Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
-*! Import of Linux 2.5.1
+*! Revision 1.9 2003/07/04 08:27:37 starvik
+*! Merge of Linux 2.5.74
+*!
+*! Revision 1.8 2003/04/09 05:20:47 starvik
+*! Merge of Linux 2.5.67
+*!
+*! Revision 1.6 2003/01/09 14:42:51 starvik
+*! Merge of Linux 2.5.55
+*!
+*! Revision 1.4 2002/12/11 13:13:57 starvik
+*! Added arch/ to v10 specific includes
+*! Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
+*!
+*! Revision 1.3 2002/11/20 11:56:10 starvik
+*! Merge of Linux 2.5.48
+*!
+*! Revision 1.2 2002/11/18 13:16:06 starvik
+*! Linux 2.5 port of latest 2.4 drivers
+*!
+*! Revision 1.15 2002/10/11 16:14:33 johana
+*! Added CONFIG_ETRAX_DS1302_TRICKLE_CHARGE and initial setting of the
+*! trcklecharge register.
+*!
+*! Revision 1.14 2002/10/10 12:15:38 magnusmn
+*! Added support for having the RST signal on bit g0
+*!
+*! Revision 1.13 2002/05/29 15:16:08 johana
+*! Removed unused variables.
+*!
+*! Revision 1.12 2002/04/10 15:35:25 johana
+*! Moved probe function closer to init function and marked it __init.
*!
*! Revision 1.11 2001/06/14 12:35:52 jonashg
*! The ATA hack is back. It is unfortunately the only way to set g27 to output.
@@ -85,7 +114,7 @@
*!
*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
*!
-*! $Id: ds1302.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+*! $Id: ds1302.c,v 1.9 2003/07/04 08:27:37 starvik Exp $
*!
*!***************************************************************************/
@@ -101,7 +130,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/svinto.h>
+#include <asm/arch/svinto.h>
#include <asm/io.h>
#include <asm/rtc.h>
@@ -232,54 +261,6 @@ ds1302_wdisable(void)
stop();
}
-/* Probe for the chip by writing something to its RAM and try reading it back. */
-
-#define MAGIC_PATTERN 0x42
-
-static int
-ds1302_probe(void)
-{
- int retval, res;
-
- TK_RST_DIR(1);
- TK_SCL_DIR(1);
- TK_SDA_DIR(0);
-
- /* Try to talk to timekeeper. */
-
- ds1302_wenable();
- start();
- out_byte(0xc0); /* write RAM byte 0 */
- out_byte(MAGIC_PATTERN); /* write something magic */
- start();
- out_byte(0xc1); /* read RAM byte 0 */
-
- if((res = in_byte()) == MAGIC_PATTERN) {
- char buf[100];
- stop();
- ds1302_wdisable();
- printk("%s: RTC found.\n", ds1302_name);
- printk("%s: SDA, SCL, RST on PB%i, PB%i, %s%i\n",
- ds1302_name,
- CONFIG_ETRAX_DS1302_SDABIT,
- CONFIG_ETRAX_DS1302_SCLBIT,
-#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
- "GENIO",
-#else
- "PB",
-#endif
- CONFIG_ETRAX_DS1302_RSTBIT);
- get_rtc_status(buf);
- printk(buf);
- retval = 1;
- } else {
- stop();
- printk("%s: RTC not found.\n", ds1302_name);
- retval = 0;
- }
-
- return retval;
-}
/* Read a byte from the selected register in the DS1302. */
@@ -315,8 +296,8 @@ get_rtc_time(struct rtc_time *rtc_tm)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
+ local_irq_disable();
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
@@ -325,7 +306,7 @@ get_rtc_time(struct rtc_time *rtc_tm)
rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
- restore_flags(flags);
+ local_irq_restore(flags);
BCD_TO_BIN(rtc_tm->tm_sec);
BCD_TO_BIN(rtc_tm->tm_min);
@@ -371,7 +352,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
{
struct rtc_time rtc_tm;
unsigned char mon, day, hrs, min, sec, leap_yr;
- unsigned char save_control, save_freq_select;
unsigned int yrs;
if (!capable(CAP_SYS_TIME))
@@ -414,15 +394,15 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
BIN_TO_BCD(mon);
BIN_TO_BCD(yrs);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
+ local_irq_disable();
CMOS_WRITE(yrs, RTC_YEAR);
CMOS_WRITE(mon, RTC_MONTH);
CMOS_WRITE(day, RTC_DAY_OF_MONTH);
CMOS_WRITE(hrs, RTC_HOURS);
CMOS_WRITE(min, RTC_MINUTES);
CMOS_WRITE(sec, RTC_SECONDS);
- restore_flags(flags);
+ local_irq_restore(flags);
/* Notice that at this point, the RTC is updated but
* the kernel is still running with the old time.
@@ -435,7 +415,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */
{
int tcs_val;
- unsigned char save_control, save_freq_select;
if (!capable(CAP_SYS_TIME))
return -EPERM;
@@ -484,6 +463,56 @@ static struct file_operations rtc_fops = {
.ioctl = rtc_ioctl,
};
+/* Probe for the chip by writing something to its RAM and try reading it back. */
+
+#define MAGIC_PATTERN 0x42
+
+static int __init
+ds1302_probe(void)
+{
+ int retval, res;
+
+ TK_RST_DIR(1);
+ TK_SCL_DIR(1);
+ TK_SDA_DIR(0);
+
+ /* Try to talk to timekeeper. */
+
+ ds1302_wenable();
+ start();
+ out_byte(0xc0); /* write RAM byte 0 */
+ out_byte(MAGIC_PATTERN); /* write something magic */
+ start();
+ out_byte(0xc1); /* read RAM byte 0 */
+
+ if((res = in_byte()) == MAGIC_PATTERN) {
+ char buf[100];
+ stop();
+ ds1302_wdisable();
+ printk("%s: RTC found.\n", ds1302_name);
+ printk("%s: SDA, SCL, RST on PB%i, PB%i, %s%i\n",
+ ds1302_name,
+ CONFIG_ETRAX_DS1302_SDABIT,
+ CONFIG_ETRAX_DS1302_SCLBIT,
+#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
+ "GENIO",
+#else
+ "PB",
+#endif
+ CONFIG_ETRAX_DS1302_RSTBIT);
+ get_rtc_status(buf);
+ printk(buf);
+ retval = 1;
+ } else {
+ stop();
+ printk("%s: RTC not found.\n", ds1302_name);
+ retval = 0;
+ }
+
+ return retval;
+}
+
+
/* Just probe for the RTC and register the device to handle the ioctl needed. */
int __init
@@ -491,27 +520,47 @@ ds1302_init(void)
{
if (!ds1302_probe()) {
#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
+#if CONFIG_ETRAX_DS1302_RSTBIT == 27
/*
* The only way to set g27 to output is to enable ATA.
*
* Make sure that R_GEN_CONFIG is setup correct.
*/
genconfig_shadow = ((genconfig_shadow &
- ~IO_MASK(R_GEN_CONFIG, ata))
- |
+ ~IO_MASK(R_GEN_CONFIG, ata)) |
(IO_STATE(R_GEN_CONFIG, ata, select)));
*R_GEN_CONFIG = genconfig_shadow;
- if (!ds1302_probe())
+#elif CONFIG_ETRAX_DS1302_RSTBIT == 0
+
+ /* Set the direction of this bit to out. */
+ genconfig_shadow = ((genconfig_shadow &
+ ~IO_MASK(R_GEN_CONFIG, g0dir)) |
+ (IO_STATE(R_GEN_CONFIG, g0dir, out)));
+ *R_GEN_CONFIG = genconfig_shadow;
+#endif
+ if (!ds1302_probe())
return -1;
#else
return -1;
#endif
}
+ /* Initialise trickle charger */
+ ds1302_writereg(RTC_TRICKLECHARGER,
+ RTC_TCR_PATTERN |(CONFIG_ETRAX_DS1302_TRICKLE_CHARGE & 0x0F));
+ return 0;
+}
+
+static int __init ds1302_register(void)
+{
+ ds1302_init();
if (register_chrdev(RTC_MAJOR_NR, ds1302_name, &rtc_fops)) {
printk(KERN_INFO "%s: unable to get major %d for rtc\n",
ds1302_name, RTC_MAJOR_NR);
return -1;
}
- return 0;
+ return 0;
+
}
+
+module_init(ds1302_register);
diff --git a/arch/cris/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c
index ae3c37886721..67523549dd96 100644
--- a/arch/cris/drivers/eeprom.c
+++ b/arch/cris/arch-v10/drivers/eeprom.c
@@ -20,8 +20,24 @@
*! in the spin-lock.
*!
*! $Log: eeprom.c,v $
-*! Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
-*! Import of Linux 2.5.1
+*! Revision 1.9 2003/07/04 08:27:37 starvik
+*! Merge of Linux 2.5.74
+*!
+*! Revision 1.8 2003/04/09 05:20:47 starvik
+*! Merge of Linux 2.5.67
+*!
+*! Revision 1.6 2003/02/10 07:19:28 starvik
+*! Removed misplaced ;
+*!
+*! Revision 1.5 2002/12/11 13:13:57 starvik
+*! Added arch/ to v10 specific includes
+*! Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
+*!
+*! Revision 1.4 2002/11/20 11:56:10 starvik
+*! Merge of Linux 2.5.48
+*!
+*! Revision 1.3 2002/11/18 13:16:06 starvik
+*! Linux 2.5 port of latest 2.4 drivers
*!
*! Revision 1.8 2001/06/15 13:24:29 jonashg
*! * Added verification of pointers from userspace in read and write.
@@ -74,7 +90,7 @@
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include "i2c.h"
@@ -425,9 +441,9 @@ int __init eeprom_init(void)
static int eeprom_open(struct inode * inode, struct file * file)
{
- if(MINOR(inode->i_rdev) != EEPROM_MINOR_NR)
+ if(minor(inode->i_rdev) != EEPROM_MINOR_NR)
return -ENXIO;
- if(MAJOR(inode->i_rdev) != EEPROM_MAJOR_NR)
+ if(major(inode->i_rdev) != EEPROM_MAJOR_NR)
return -ENXIO;
if( eeprom.size > 0 )
@@ -449,39 +465,36 @@ static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig)
* orig 1: relative from current position
* orig 2: position from last eeprom address
*/
- loff_t ret;
-
- lock_kernel();
+
switch (orig)
{
case 0:
- ret = file->f_pos = offset;
+ file->f_pos = offset;
break;
case 1:
- ret = file->f_pos += offset;
+ file->f_pos += offset;
break;
case 2:
- ret = file->f_pos = eeprom.size - offset;
+ file->f_pos = eeprom.size - offset;
break;
default:
- ret = -EINVAL;
+ return -EINVAL;
}
/* truncate position */
if (file->f_pos < 0)
{
- file->f_pos = 0;
- ret = -EOVERFLOW;
+ file->f_pos = 0;
+ return(-EOVERFLOW);
}
-
+
if (file->f_pos >= eeprom.size)
{
file->f_pos = eeprom.size - 1;
- ret = -EOVERFLOW;
+ return(-EOVERFLOW);
}
- unlock_kernel();
- return ( ret );
+ return ( file->f_pos );
}
/* Reads data from eeprom. */
@@ -500,7 +513,7 @@ static int eeprom_read_buf(loff_t addr, char * buf, int count)
static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t *off)
{
- int i, read=0;
+ int read=0;
unsigned long p = file->f_pos;
unsigned char page;
@@ -526,7 +539,7 @@ static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t
if(!eeprom_address(p))
{
printk(KERN_INFO "%s: Read failed to address the eeprom: "
- "0x%08X (%i) page: %i\n", eeprom_name, p, p, page);
+ "0x%08X (%i) page: %i\n", eeprom_name, (int)p, (int)p, page);
i2c_stop();
/* don't forget to wake them up */
@@ -609,7 +622,7 @@ static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,
if(!eeprom_address(p))
{
printk(KERN_INFO "%s: Write failed to address the eeprom: "
- "0x%08X (%i) \n", eeprom_name, p, p);
+ "0x%08X (%i) \n", eeprom_name, (int)p, (int)p);
i2c_stop();
/* don't forget to wake them up */
@@ -747,7 +760,7 @@ static int eeprom_close(struct inode * inode, struct file * file)
static int eeprom_address(unsigned long addr)
{
- int i, j;
+ int i;
unsigned char page, offset;
page = (unsigned char) (addr >> 8);
diff --git a/arch/cris/drivers/ethernet.c b/arch/cris/arch-v10/drivers/ethernet.c
index 9b72037ea030..6b9b40634da9 100644
--- a/arch/cris/drivers/ethernet.c
+++ b/arch/cris/arch-v10/drivers/ethernet.c
@@ -1,14 +1,109 @@
-/* $Id: ethernet.c,v 1.2 2001/12/18 13:35:15 bjornw Exp $
+/* $Id: ethernet.c,v 1.17 2003/07/04 08:27:37 starvik Exp $
*
* e100net.c: A network driver for the ETRAX 100LX network controller.
*
- * Copyright (c) 1998-2001 Axis Communications AB.
+ * Copyright (c) 1998-2002 Axis Communications AB.
*
* The outline of this driver comes from skeleton.c.
*
* $Log: ethernet.c,v $
- * Revision 1.2 2001/12/18 13:35:15 bjornw
- * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
+ * Revision 1.17 2003/07/04 08:27:37 starvik
+ * Merge of Linux 2.5.74
+ *
+ * Revision 1.16 2003/04/24 08:28:22 starvik
+ * New LED behaviour: LED off when no link
+ *
+ * Revision 1.15 2003/04/09 05:20:47 starvik
+ * Merge of Linux 2.5.67
+ *
+ * Revision 1.13 2003/03/06 16:11:01 henriken
+ * Off by one error in group address register setting.
+ *
+ * Revision 1.12 2003/02/27 17:24:19 starvik
+ * Corrected Rev to Revision
+ *
+ * Revision 1.11 2003/01/24 09:53:21 starvik
+ * Oops. Initialize GA to 0, not to 1
+ *
+ * Revision 1.10 2003/01/24 09:50:55 starvik
+ * Initialize GA_0 and GA_1 to 0 to avoid matching of unwanted packets
+ *
+ * Revision 1.9 2002/12/13 07:40:58 starvik
+ * Added basic ethtool interface
+ * Handled out of memory when allocating new buffers
+ *
+ * Revision 1.8 2002/12/11 13:13:57 starvik
+ * Added arch/ to v10 specific includes
+ * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
+ *
+ * Revision 1.7 2002/11/26 09:41:42 starvik
+ * Added e100_set_config (standard interface to set media type)
+ * Added protection against preemptive scheduling
+ * Added standard MII ioctls
+ *
+ * Revision 1.6 2002/11/21 07:18:18 starvik
+ * Timers must be initialized in 2.5.48
+ *
+ * Revision 1.5 2002/11/20 11:56:11 starvik
+ * Merge of Linux 2.5.48
+ *
+ * Revision 1.4 2002/11/18 07:26:46 starvik
+ * Linux 2.5 port of latest Linux 2.4 ethernet driver
+ *
+ * Revision 1.33 2002/10/02 20:16:17 hp
+ * SETF, SETS: Use underscored IO_x_ macros rather than incorrect token concatenation
+ *
+ * Revision 1.32 2002/09/16 06:05:58 starvik
+ * Align memory returned by dev_alloc_skb
+ * Moved handling of sent packets to interrupt to avoid reference counting problem
+ *
+ * Revision 1.31 2002/09/10 13:28:23 larsv
+ * Return -EINVAL for unknown ioctls to avoid confusing tools that tests
+ * for supported functionality by issuing special ioctls, i.e. wireless
+ * extensions.
+ *
+ * Revision 1.30 2002/05/07 18:50:08 johana
+ * Correct spelling in comments.
+ *
+ * Revision 1.29 2002/05/06 05:38:49 starvik
+ * Performance improvements:
+ * Large packets are not copied (breakpoint set to 256 bytes)
+ * The cache bug workaround is delayed until half of the receive list
+ * has been used
+ * Added transmit list
+ * Transmit interrupts are only enabled when transmit queue is full
+ *
+ * Revision 1.28.2.1 2002/04/30 08:15:51 starvik
+ * Performance improvements:
+ * Large packets are not copied (breakpoint set to 256 bytes)
+ * The cache bug workaround is delayed until half of the receive list
+ * has been used.
+ * Added transmit list
+ * Transmit interrupts are only enabled when transmit queue is full
+ *
+ * Revision 1.28 2002/04/22 11:47:21 johana
+ * Fix according to 2.4.19-pre7. time_after/time_before and
+ * missing end of comment.
+ * The patch has a typo for ethernet.c in e100_clear_network_leds(),
+ * that is fixed here.
+ *
+ * Revision 1.27 2002/04/12 11:55:11 bjornw
+ * Added TODO
+ *
+ * Revision 1.26 2002/03/15 17:11:02 bjornw
+ * Use prepare_rx_descriptor after the CPU has touched the receiving descs
+ *
+ * Revision 1.25 2002/03/08 13:07:53 bjornw
+ * Unnecessary spinlock removed
+ *
+ * Revision 1.24 2002/02/20 12:57:43 fredriks
+ * Replaced MIN() with min().
+ *
+ * Revision 1.23 2002/02/20 10:58:14 fredriks
+ * Strip the Ethernet checksum (4 bytes) before forwarding a frame to upper layers.
+ *
+ * Revision 1.22 2002/01/30 07:48:22 matsfg
+ * Initiate R_NETWORK_TR_CTRL
*
* Revision 1.21 2001/11/23 11:54:49 starvik
* Added IFF_PROMISC and IFF_ALLMULTI handling in set_multicast_list
@@ -112,22 +207,25 @@
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/ethtool.h>
-#include <asm/svinto.h> /* DMA and register descriptions */
+#include <asm/arch/svinto.h>/* DMA and register descriptions */
#include <asm/io.h> /* LED_* I/O functions */
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/ethernet.h>
+#include <asm/cache.h>
//#define ETHDEBUG
#define D(x)
-
/*
* The name of the card. Is used for messages and in the requests for
* io regions, irqs and dma channels
@@ -154,6 +252,11 @@ struct net_local {
spinlock_t lock;
};
+typedef struct etrax_eth_descr
+{
+ etrax_dma_descr descr;
+ struct sk_buff* skb;
+} etrax_eth_descr;
/* Duplex settings */
enum duplex
@@ -165,8 +268,6 @@ enum duplex
/* Dma descriptors etc. */
-#define RX_BUF_SIZE 32768
-
#define MAX_MEDIA_DATA_SIZE 1518
#define MIN_PACKET_LEN 46
@@ -207,29 +308,37 @@ enum duplex
#define NO_NETWORK_ACTIVITY 0
#define NETWORK_ACTIVITY 1
-#define RX_DESC_BUF_SIZE 256
-#define NBR_OF_RX_DESC (RX_BUF_SIZE / \
- RX_DESC_BUF_SIZE)
+#define NBR_OF_RX_DESC 64
+#define NBR_OF_TX_DESC 256
+
+/* Large packets are sent directly to upper layers while small packets are */
+/* copied (to reduce memory waste). The following constant decides the breakpoint */
+#define RX_COPYBREAK 256
+
+/* Due to a chip bug we need to flush the cache when descriptors are returned */
+/* to the DMA. To decrease performance impact we return descriptors in chunks. */
+/* The following constant determines the number of descriptors to return. */
+#define RX_QUEUE_THRESHOLD NBR_OF_RX_DESC/2
#define GET_BIT(bit,val) (((val) >> (bit)) & 0x01)
/* Define some macros to access ETRAX 100 registers */
-#define SETF(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
- IO_FIELD(##reg##, field, val)
-#define SETS(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
- IO_STATE(##reg##, field, val)
+#define SETF(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
+ IO_FIELD_(reg##_, field##_, val)
+#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
+ IO_STATE_(reg##_, field##_, _##val)
-static etrax_dma_descr *myNextRxDesc; /* Points to the next descriptor to
+static etrax_eth_descr *myNextRxDesc; /* Points to the next descriptor to
to be processed */
-static etrax_dma_descr *myLastRxDesc; /* The last processed descriptor */
-static etrax_dma_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */
-
-static unsigned char RxBuf[RX_BUF_SIZE];
+static etrax_eth_descr *myLastRxDesc; /* The last processed descriptor */
+static etrax_eth_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */
-static etrax_dma_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(4)));
-static etrax_dma_descr TxDesc __attribute__ ((aligned(4)));
+static etrax_eth_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(32)));
-static struct sk_buff *tx_skb;
+static etrax_eth_descr* myFirstTxDesc; /* First packet not yet sent */
+static etrax_eth_descr* myLastTxDesc; /* End of send queue */
+static etrax_eth_descr* myNextTxDesc; /* Next descriptor to use */
+static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32)));
static unsigned int network_rec_config_shadow = 0;
@@ -238,27 +347,29 @@ static struct timer_list speed_timer = TIMER_INITIALIZER(NULL, 0, 0);
static struct timer_list clear_led_timer = TIMER_INITIALIZER(NULL, 0, 0);
static int current_speed; /* Speed read from transceiver */
static int current_speed_selection; /* Speed selected by user */
-static int led_next_time;
+static unsigned long led_next_time;
static int led_active;
+static int rx_queue_len;
/* Duplex */
-static struct timer_list duplex_timer;
+static struct timer_list duplex_timer = TIMER_INITIALIZER(NULL, 0, 0);
static int full_duplex;
static enum duplex current_duplex;
/* Index to functions, as function prototypes. */
-static int etrax_ethernet_init(struct net_device *dev);
+static int etrax_ethernet_init(void);
static int e100_open(struct net_device *dev);
static int e100_set_mac_address(struct net_device *dev, void *addr);
static int e100_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void e100rx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void e100tx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void e100nw_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t e100rxtx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t e100nw_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void e100_rx(struct net_device *dev);
static int e100_close(struct net_device *dev);
static int e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int e100_ethtool_ioctl(struct net_device* dev, struct ifreq *ifr);
+static int e100_set_config(struct net_device* dev, struct ifmap* map);
static void e100_tx_timeout(struct net_device *dev);
static struct net_device_stats *e100_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@@ -273,6 +384,7 @@ static void e100_set_duplex(enum duplex);
static void e100_negotiate(void);
static unsigned short e100_get_mdio_reg(unsigned char reg_num);
+static void e100_set_mdio_reg(unsigned char reg, unsigned short data);
static void e100_send_mdio_cmd(unsigned short cmd, int write_cmd);
static void e100_send_mdio_bit(unsigned char bit);
static unsigned char e100_receive_mdio_bit(void);
@@ -296,15 +408,14 @@ etrax_ethernet_init(void)
{
struct net_device *dev;
int i, err;
- int anOffset = 0;
- printk("ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2001 Axis Communications AB\n");
+ printk("ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n");
dev = alloc_etherdev(sizeof(struct net_local));
if (!dev)
return -ENOMEM;
- dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
+ dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
/* now setup our etrax specific stuff */
@@ -320,35 +431,55 @@ etrax_ethernet_init(void)
dev->set_multicast_list = set_multicast_list;
dev->set_mac_address = e100_set_mac_address;
dev->do_ioctl = e100_ioctl;
+ dev->set_config = e100_set_config;
dev->tx_timeout = e100_tx_timeout;
/* Initialise the list of Etrax DMA-descriptors */
/* Initialise receive descriptors */
- for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) {
- RxDescList[i].ctrl = 0;
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);
- RxDescList[i].buf = virt_to_phys(RxBuf + anOffset);
- RxDescList[i].status = 0;
- RxDescList[i].hw_len = 0;
- anOffset += RX_DESC_BUF_SIZE;
+ for (i = 0; i < NBR_OF_RX_DESC; i++) {
+ /* Allocate two extra cachelines to make sure that buffer used by DMA
+ * does not share cacheline with any other data (to avoid cache bug)
+ */
+ RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
+ RxDescList[i].descr.ctrl = 0;
+ RxDescList[i].descr.sw_len = MAX_MEDIA_DATA_SIZE;
+ RxDescList[i].descr.next = virt_to_phys(&RxDescList[i + 1]);
+ RxDescList[i].descr.buf = L1_CACHE_ALIGN(virt_to_phys(RxDescList[i].skb->data));
+ RxDescList[i].descr.status = 0;
+ RxDescList[i].descr.hw_len = 0;
+ prepare_rx_descriptor(&RxDescList[i].descr);
}
- RxDescList[i].ctrl = d_eol;
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].next = virt_to_phys(&RxDescList[0]);
- RxDescList[i].buf = virt_to_phys(RxBuf + anOffset);
- RxDescList[i].status = 0;
- RxDescList[i].hw_len = 0;
+ RxDescList[NBR_OF_RX_DESC - 1].descr.ctrl = d_eol;
+ RxDescList[NBR_OF_RX_DESC - 1].descr.next = virt_to_phys(&RxDescList[0]);
+ rx_queue_len = 0;
+
+ /* Initialize transmit descriptors */
+ for (i = 0; i < NBR_OF_TX_DESC; i++) {
+ TxDescList[i].descr.ctrl = 0;
+ TxDescList[i].descr.sw_len = 0;
+ TxDescList[i].descr.next = virt_to_phys(&TxDescList[i + 1].descr);
+ TxDescList[i].descr.buf = 0;
+ TxDescList[i].descr.status = 0;
+ TxDescList[i].descr.hw_len = 0;
+ TxDescList[i].skb = 0;
+ }
+ TxDescList[NBR_OF_TX_DESC - 1].descr.ctrl = d_eol;
+ TxDescList[NBR_OF_TX_DESC - 1].descr.next = virt_to_phys(&TxDescList[0].descr);
+
/* Initialise initial pointers */
- myNextRxDesc = &RxDescList[0];
- myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
- myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+ myNextRxDesc = &RxDescList[0];
+ myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+ myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+ myFirstTxDesc = &TxDescList[0];
+ myNextTxDesc = &TxDescList[0];
+ myLastTxDesc = &TxDescList[NBR_OF_TX_DESC - 1];
+ /* Register device */
err = register_netdev(dev);
if (err) {
kfree(dev);
@@ -375,6 +506,10 @@ etrax_ethernet_init(void)
duplex_timer.function = e100_check_duplex;
add_timer(&duplex_timer);
+ /* Initialize group address registers to make sure that no */
+ /* unwanted addresses are matched */
+ *R_NETWORK_GA_0 = 0x00000000;
+ *R_NETWORK_GA_1 = 0x00000000;
return 0;
}
@@ -385,9 +520,12 @@ etrax_ethernet_init(void)
static int
e100_set_mac_address(struct net_device *dev, void *p)
{
+ struct net_local *np = (struct net_local *)dev->priv;
struct sockaddr *addr = p;
int i;
+ spin_lock(&np->lock); /* preemption protection */
+
/* remember it */
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -412,6 +550,8 @@ e100_set_mac_address(struct net_device *dev, void *p)
printk("%02X\n", dev->dev_addr[i]);
+ spin_unlock(&np->lock);
+
return 0;
}
@@ -462,14 +602,14 @@ e100_open(struct net_device *dev)
/* allocate the irq corresponding to the receiving DMA */
- if (request_irq(NETWORK_DMA_RX_IRQ_NBR, e100rx_interrupt, 0,
+ if (request_irq(NETWORK_DMA_RX_IRQ_NBR, e100rxtx_interrupt, 0,
cardname, (void *)dev)) {
goto grace_exit0;
}
/* allocate the irq corresponding to the transmitting DMA */
- if (request_irq(NETWORK_DMA_TX_IRQ_NBR, e100tx_interrupt, 0,
+ if (request_irq(NETWORK_DMA_TX_IRQ_NBR, e100rxtx_interrupt, 0,
cardname, (void *)dev)) {
goto grace_exit1;
}
@@ -481,19 +621,6 @@ e100_open(struct net_device *dev)
goto grace_exit2;
}
- /*
- * Always allocate the DMA channels after the IRQ,
- * and clean up on failure.
- */
-
- if (request_dma(NETWORK_TX_DMA_NBR, cardname)) {
- goto grace_exit3;
- }
-
- if (request_dma(NETWORK_RX_DMA_NBR, cardname)) {
- goto grace_exit4;
- }
-
/* give the HW an idea of what MAC address we want */
*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |
@@ -518,22 +645,28 @@ e100_open(struct net_device *dev)
IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) |
IO_STATE(R_NETWORK_GEN_CONFIG, enable, on);
+ *R_NETWORK_TR_CTRL =
+ IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr) |
+ IO_STATE(R_NETWORK_TR_CTRL, delay, none) |
+ IO_STATE(R_NETWORK_TR_CTRL, cancel, dont) |
+ IO_STATE(R_NETWORK_TR_CTRL, cd, enable) |
+ IO_STATE(R_NETWORK_TR_CTRL, retry, enable) |
+ IO_STATE(R_NETWORK_TR_CTRL, pad, enable) |
+ IO_STATE(R_NETWORK_TR_CTRL, crc, enable);
+
save_flags(flags);
cli();
/* enable the irq's for ethernet DMA */
*R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set);
+ IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set);
*R_IRQ_MASK0_SET =
IO_STATE(R_IRQ_MASK0_SET, overrun, set) |
IO_STATE(R_IRQ_MASK0_SET, underrun, set) |
IO_STATE(R_IRQ_MASK0_SET, excessive_col, set);
- tx_skb = 0;
-
/* make sure the irqs are cleared */
*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
@@ -549,6 +682,11 @@ e100_open(struct net_device *dev)
*R_DMA_CH1_FIRST = virt_to_phys(myNextRxDesc);
*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, start);
+ /* Set up transmit DMA channel so it can be restarted later */
+
+ *R_DMA_CH0_FIRST = 0;
+ *R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc);
+
restore_flags(flags);
/* We are now ready to accept transmit requeusts from
@@ -558,10 +696,6 @@ e100_open(struct net_device *dev)
return 0;
-grace_exit4:
- free_dma(NETWORK_TX_DMA_NBR);
-grace_exit3:
- free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
grace_exit2:
free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev);
grace_exit1:
@@ -596,9 +730,7 @@ e100_check_speed(unsigned long dummy)
static void
e100_negotiate(void)
{
- unsigned short cmd;
unsigned short data = e100_get_mdio_reg(MDIO_ADVERTISMENT_REG);
- int bitCounter;
/* Discard old speed and duplex settings */
data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD |
@@ -637,29 +769,13 @@ e100_negotiate(void)
MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;
}
- cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) |
- (MDIO_ADVERTISMENT_REG<< 2);
-
- e100_send_mdio_cmd(cmd, 1);
-
- /* Data... */
- for (bitCounter=15; bitCounter>=0 ; bitCounter--) {
- e100_send_mdio_bit(GET_BIT(bitCounter, data));
- }
+ e100_set_mdio_reg(MDIO_ADVERTISMENT_REG, data);
/* Renegotiate with link partner */
data = e100_get_mdio_reg(MDIO_BASE_CONTROL_REG);
data |= MDIO_BC_NEGOTIATE;
- cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) |
- (MDIO_BASE_CONTROL_REG<< 2);
-
- e100_send_mdio_cmd(cmd, 1);
-
- /* Data... */
- for (bitCounter=15; bitCounter>=0 ; bitCounter--) {
- e100_send_mdio_bit(GET_BIT(bitCounter, data));
- }
+ e100_set_mdio_reg(MDIO_BASE_CONTROL_REG, data);
}
static void
@@ -727,6 +843,24 @@ e100_get_mdio_reg(unsigned char reg_num)
}
static void
+e100_set_mdio_reg(unsigned char reg, unsigned short data)
+{
+ int bitCounter;
+ unsigned short cmd;
+
+ cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) |
+ (reg << 2);
+
+ e100_send_mdio_cmd(cmd, 1);
+
+ /* Data... */
+ for (bitCounter=15; bitCounter>=0 ; bitCounter--) {
+ e100_send_mdio_bit(GET_BIT(bitCounter, data));
+ }
+
+}
+
+static void
e100_send_mdio_cmd(unsigned short cmd, int write_cmd)
{
int bitCounter;
@@ -801,6 +935,9 @@ static void
e100_tx_timeout(struct net_device *dev)
{
struct net_local *np = (struct net_local *)dev->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&np->lock, flags);
printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
tx_done(dev) ? "IRQ problem" : "network cable problem");
@@ -818,14 +955,22 @@ e100_tx_timeout(struct net_device *dev)
e100_reset_transceiver();
- /* and get rid of the packet that never got an interrupt */
-
- dev_kfree_skb(tx_skb);
- tx_skb = 0;
-
+ /* and get rid of the packets that never got an interrupt */
+ while (myFirstTxDesc != myNextTxDesc)
+ {
+ dev_kfree_skb(myFirstTxDesc->skb);
+ myFirstTxDesc->skb = 0;
+ myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
+ }
+
+ /* Set up transmit DMA channel so it can be restarted later */
+ *R_DMA_CH0_FIRST = 0;
+ *R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc);
+
/* tell the upper layers we're ok again */
netif_wake_queue(dev);
+ spin_unlock_irqrestore(&np->lock, flags);
}
@@ -841,25 +986,30 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev)
struct net_local *np = (struct net_local *)dev->priv;
int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
+ unsigned long flags;
#ifdef ETHDEBUG
printk("send packet len %d\n", length);
#endif
- spin_lock_irq(&np->lock); /* protect from tx_interrupt */
+ spin_lock_irqsave(&np->lock, flags); /* protect from tx_interrupt and ourself */
+
+ myNextTxDesc->skb = skb;
- tx_skb = skb; /* remember it so we can free it in the tx irq handler later */
dev->trans_start = jiffies;
e100_hardware_send_packet(buf, length);
- /* this simple TX driver has only one send-descriptor so we're full
- * directly. If this had a send-ring instead, we would only do this if
- * the ring got full.
- */
+ myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next);
- netif_stop_queue(dev);
+ /* Stop queue if full */
+ if (myNextTxDesc == myFirstTxDesc) {
+ /* Enable transmit interrupt to wake up queue */
+ *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
+ *R_IRQ_MASK2_SET = IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set);
+ netif_stop_queue(dev);
+ }
- spin_unlock_irq(&np->lock);
+ spin_unlock_irqrestore(&np->lock, flags);
return 0;
}
@@ -869,12 +1019,14 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev)
* Handle the network interface interrupts.
*/
-static void
-e100rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t
+e100rxtx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = (struct net_device *)dev_id;
+ struct net_local *np = (struct net_local *)dev->priv;
unsigned long irqbits = *R_IRQ_MASK2_RD;
+ /* Handle received packets */
if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) {
/* acknowledge the eop interrupt */
@@ -899,51 +1051,31 @@ e100rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
so we have to loop back and check if so */
}
}
-}
-
-/* the transmit dma channel interrupt
- *
- * this is supposed to free the skbuff which was pending during transmission,
- * and inform the kernel that we can send one more buffer
- */
-static void
-e100tx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- struct net_device *dev = (struct net_device *)dev_id;
- unsigned long irqbits = *R_IRQ_MASK2_RD;
- struct net_local *np = (struct net_local *)dev->priv;
-
- /* check for a dma0_eop interrupt */
- if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) {
- /* This protects us from concurrent execution of
- * our dev->hard_start_xmit function above.
- */
-
- spin_lock(&np->lock);
-
- /* acknowledge the eop interrupt */
+ /* Report any packets that have been sent */
+ while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) &&
+ myFirstTxDesc != myNextTxDesc)
+ {
+ np->stats.tx_bytes += myFirstTxDesc->skb->len;
+ np->stats.tx_packets++;
+
+ /* dma is ready with the transmission of the data in tx_skb, so now
+ we can release the skb memory */
+ dev_kfree_skb_irq(myFirstTxDesc->skb);
+ myFirstTxDesc->skb = 0;
+ myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
+ }
+ if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) {
+ /* acknowledge the eop interrupt and wake up queue */
*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
-
- if (*R_DMA_CH0_FIRST == 0 && tx_skb) {
- np->stats.tx_bytes += tx_skb->len;
- np->stats.tx_packets++;
- /* dma is ready with the transmission of the data in tx_skb, so now
- we can release the skb memory */
- dev_kfree_skb_irq(tx_skb);
- tx_skb = 0;
- netif_wake_queue(dev);
- } else {
- printk(KERN_WARNING "%s: tx weird interrupt\n",
- cardname);
- }
-
- spin_unlock(&np->lock);
+ *R_IRQ_MASK2_CLR = IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr);
+ netif_wake_queue(dev);
}
+ return IRQ_HANDLED;
}
-static void
+static irqreturn_t
e100nw_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = (struct net_device *)dev_id;
@@ -968,7 +1100,7 @@ e100nw_interrupt(int irq, void *dev_id, struct pt_regs * regs)
np->stats.tx_errors++;
D(printk("ethernet excessive collisions!\n"));
}
-
+ return IRQ_HANDLED;
}
/* We have a good packet(s), get it/them out of the buffers. */
@@ -978,7 +1110,6 @@ e100_rx(struct net_device *dev)
struct sk_buff *skb;
int length = 0;
struct net_local *np = (struct net_local *)dev->priv;
- struct etrax_dma_descr *mySaveRxDesc = myNextRxDesc;
unsigned char *skb_data_ptr;
#ifdef ETHDEBUG
int i;
@@ -994,24 +1125,13 @@ e100_rx(struct net_device *dev)
mod_timer(&clear_led_timer, jiffies + HZ/10);
}
- /* If the packet is broken down in many small packages then merge
- * count how much space we will need to alloc with skb_alloc() for
- * it to fit.
- */
-
- while (!(myNextRxDesc->status & d_eop)) {
- length += myNextRxDesc->sw_len; /* use sw_len for the first descs */
- myNextRxDesc->status = 0;
- myNextRxDesc = phys_to_virt(myNextRxDesc->next);
- }
-
- length += myNextRxDesc->hw_len; /* use hw_len for the last descr */
+ length = myNextRxDesc->descr.hw_len - 4;
((struct net_local *)dev->priv)->stats.rx_bytes += length;
#ifdef ETHDEBUG
printk("Got a packet of length %d:\n", length);
/* dump the first bytes in the packet */
- skb_data_ptr = (unsigned char *)phys_to_virt(mySaveRxDesc->buf);
+ skb_data_ptr = (unsigned char *)phys_to_virt(myNextRxDesc->descr.buf);
for (i = 0; i < 8; i++) {
printk("%d: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", i * 8,
skb_data_ptr[0],skb_data_ptr[1],skb_data_ptr[2],skb_data_ptr[3],
@@ -1020,53 +1140,68 @@ e100_rx(struct net_device *dev)
}
#endif
- skb = dev_alloc_skb(length - ETHER_HEAD_LEN);
- if (!skb) {
- np->stats.rx_errors++;
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
- dev->name);
- return;
- }
+ if (length < RX_COPYBREAK) {
+ /* Small packet, copy data */
+ skb = dev_alloc_skb(length - ETHER_HEAD_LEN);
+ if (!skb) {
+ np->stats.rx_errors++;
+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+ return;
+ }
- skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */
- skb_data_ptr = skb_push(skb, ETHER_HEAD_LEN); /* allocate room for the header */
+ skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */
+ skb_data_ptr = skb_push(skb, ETHER_HEAD_LEN); /* allocate room for the header */
#ifdef ETHDEBUG
- printk("head = 0x%x, data = 0x%x, tail = 0x%x, end = 0x%x\n",
- skb->head, skb->data, skb->tail, skb->end);
- printk("copying packet to 0x%x.\n", skb_data_ptr);
+ printk("head = 0x%x, data = 0x%x, tail = 0x%x, end = 0x%x\n",
+ skb->head, skb->data, skb->tail, skb->end);
+ printk("copying packet to 0x%x.\n", skb_data_ptr);
#endif
-
- /* this loop can be made using max two memcpy's if optimized */
-
- while (mySaveRxDesc != myNextRxDesc) {
- memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),
- mySaveRxDesc->sw_len);
- skb_data_ptr += mySaveRxDesc->sw_len;
- mySaveRxDesc = phys_to_virt(mySaveRxDesc->next);
+
+ memcpy(skb_data_ptr, phys_to_virt(myNextRxDesc->descr.buf), length);
+ }
+ else {
+ /* Large packet, send directly to upper layers and allocate new
+ * memory (aligned to cache line boundary to avoid bug).
+ * Before sending the skb to upper layers we must make sure that
+ * skb->data points to the aligned start of the packet.
+ */
+ int align;
+ struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
+ if (!new_skb) {
+ np->stats.rx_errors++;
+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+ return;
+ }
+ skb = myNextRxDesc->skb;
+ align = (int)phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data;
+ skb_put(skb, length + align);
+ skb_pull(skb, align); /* Remove alignment bytes */
+ myNextRxDesc->skb = new_skb;
+ myNextRxDesc->descr.buf = L1_CACHE_ALIGN(virt_to_phys(myNextRxDesc->skb->data));
}
-
- memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),
- mySaveRxDesc->hw_len);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
/* Send the packet to the upper layers */
-
netif_rx(skb);
/* Prepare for next packet */
-
- myNextRxDesc->status = 0;
+ myNextRxDesc->descr.status = 0;
myPrevRxDesc = myNextRxDesc;
- myNextRxDesc = phys_to_virt(myNextRxDesc->next);
+ myNextRxDesc = phys_to_virt(myNextRxDesc->descr.next);
- myPrevRxDesc->ctrl |= d_eol;
- myLastRxDesc->ctrl &= ~d_eol;
- myLastRxDesc = myPrevRxDesc;
+ rx_queue_len++;
- return;
+ /* Check if descriptors should be returned */
+ if (rx_queue_len == RX_QUEUE_THRESHOLD) {
+ flush_etrax_cache();
+ myPrevRxDesc->descr.ctrl |= d_eol;
+ myLastRxDesc->descr.ctrl &= ~d_eol;
+ myLastRxDesc = myPrevRxDesc;
+ rx_queue_len = 0;
+ }
}
/* The inverse routine to net_open(). */
@@ -1105,9 +1240,6 @@ e100_close(struct net_device *dev)
free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev);
free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
- free_dma(NETWORK_TX_DMA_NBR);
- free_dma(NETWORK_RX_DMA_NBR);
-
/* Update the statistics here. */
update_rx_stats(&np->stats);
@@ -1119,8 +1251,24 @@ e100_close(struct net_device *dev)
static int
e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- /* Maybe default should return -EINVAL instead? */
+ struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
+ struct net_local *np = (struct net_local *)dev->priv;
+
+ spin_lock(&np->lock); /* Preempt protection */
switch (cmd) {
+ case SIOCETHTOOL:
+ return e100_ethtool_ioctl(dev,ifr);
+ case SIOCGMIIPHY: /* Get PHY address */
+ data->phy_id = MDIO_PHYS_ADDR;
+ break;
+ case SIOCGMIIREG: /* Read MII register */
+ data->val_out = e100_get_mdio_reg(data->reg_num);
+ break;
+ case SIOCSMIIREG: /* Write MII register */
+ e100_set_mdio_reg(data->reg_num, data->val_in);
+ break;
+ /* The ioctls below should be considered obsolete but are */
+ /* still present for compatability with old scripts/apps */
case SET_ETH_SPEED_10: /* 10 Mbps */
e100_set_speed(10);
break;
@@ -1139,11 +1287,128 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex*/
e100_set_duplex(autoneg);
break;
- default: /* Auto neg */
+ default:
+ return -EINVAL;
+ }
+ spin_unlock(&np->lock);
+ return 0;
+}
+
+static int
+e100_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
+{
+ struct ethtool_cmd ecmd;
+
+ if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
+ return -EFAULT;
+
+ switch (ecmd.cmd) {
+ case ETHTOOL_GSET:
+ {
+ memset((void *) &ecmd, 0, sizeof (ecmd));
+ ecmd.supported =
+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
+ SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
+ ecmd.port = PORT_TP;
+ ecmd.transceiver = XCVR_EXTERNAL;
+ ecmd.phy_address = MDIO_PHYS_ADDR;
+ ecmd.speed = current_speed;
+ ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+ ecmd.advertising = ADVERTISED_TP;
+ if (current_duplex == autoneg && current_speed_selection == 0)
+ ecmd.advertising = ADVERTISED_Autoneg;
+ else {
+ ecmd.advertising |=
+ ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+ if (current_speed_selection == 10)
+ ecmd.advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full);
+ else if (current_speed_selection == 100)
+ ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full);
+ if (current_duplex == half)
+ ecmd.advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full);
+ else if (current_duplex == full)
+ ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half);
+ }
+ ecmd.autoneg = AUTONEG_ENABLE;
+ if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
+ return -EFAULT;
+ }
+ break;
+ case ETHTOOL_SSET:
+ {
+ if (!capable(CAP_NET_ADMIN)) {
+ return -EPERM;
+ }
+ if (ecmd.autoneg == AUTONEG_ENABLE) {
+ e100_set_duplex(autoneg);
+ e100_set_speed(0);
+ } else {
+ e100_set_duplex(ecmd.duplex == DUPLEX_HALF ? half : full);
+ e100_set_speed(ecmd.speed == SPEED_10 ? 10: 100);
+ }
+ }
+ break;
+ case ETHTOOL_GDRVINFO:
+ {
+ struct ethtool_drvinfo info;
+ memset((void *) &info, 0, sizeof (info));
+ strncpy(info.driver, "ETRAX 100LX", sizeof(info.driver) - 1);
+ strncpy(info.version, "$Revision: 1.17 $", sizeof(info.version) - 1);
+ strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1);
+ strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1);
+ info.regdump_len = 0;
+ info.eedump_len = 0;
+ info.testinfo_len = 0;
+ if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
+ return -EFAULT;
+ }
+ break;
+ case ETHTOOL_NWAY_RST:
+ if (current_duplex == autoneg && current_speed_selection == 0)
+ e100_negotiate();
+ break;
+ default:
+ return -EOPNOTSUPP;
+ break;
+ }
+ return 0;
+}
+
+static int
+e100_set_config(struct net_device *dev, struct ifmap *map)
+{
+ struct net_local *np = (struct net_local *)dev->priv;
+ spin_lock(&np->lock); /* Preempt protection */
+
+ switch(map->port) {
+ case IF_PORT_UNKNOWN:
+ /* Use autoneg */
e100_set_speed(0);
e100_set_duplex(autoneg);
break;
+ case IF_PORT_10BASET:
+ e100_set_speed(10);
+ e100_set_duplex(autoneg);
+ break;
+ case IF_PORT_100BASET:
+ case IF_PORT_100BASETX:
+ e100_set_speed(100);
+ e100_set_duplex(autoneg);
+ break;
+ case IF_PORT_100BASEFX:
+ case IF_PORT_10BASE2:
+ case IF_PORT_AUI:
+ spin_unlock(&np->lock);
+ return -EOPNOTSUPP;
+ break;
+ default:
+ printk(KERN_ERR "%s: Invalid media selected", dev->name);
+ spin_unlock(&np->lock);
+ return -EINVAL;
}
+ spin_unlock(&np->lock);
return 0;
}
@@ -1177,10 +1442,13 @@ static struct net_device_stats *
e100_get_stats(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
+ unsigned long flags;
+ spin_lock_irqsave(&lp->lock, flags);
update_rx_stats(&lp->stats);
update_tx_stats(&lp->stats);
-
+
+ spin_unlock_irqrestore(&lp->lock, flags);
return &lp->stats;
}
@@ -1194,9 +1462,11 @@ e100_get_stats(struct net_device *dev)
static void
set_multicast_list(struct net_device *dev)
{
+ struct net_local *lp = (struct net_local *)dev->priv;
int num_addr = dev->mc_count;
unsigned long int lo_bits;
unsigned long int hi_bits;
+ spin_lock(&lp->lock);
if (dev->flags & IFF_PROMISC)
{
/* promiscuous mode */
@@ -1255,7 +1525,7 @@ set_multicast_list(struct net_device *dev)
hash_ix &= 0x3f;
- if (hash_ix > 32) {
+ if (hash_ix >= 32) {
hi_bits |= (1 << (hash_ix-32));
}
else {
@@ -1269,6 +1539,7 @@ set_multicast_list(struct net_device *dev)
}
*R_NETWORK_GA_0 = lo_bits;
*R_NETWORK_GA_1 = hi_bits;
+ spin_unlock(&lp->lock);
}
void
@@ -1287,15 +1558,16 @@ e100_hardware_send_packet(char *buf, int length)
}
/* configure the tx dma descriptor */
+ myNextTxDesc->descr.sw_len = length;
+ myNextTxDesc->descr.ctrl = d_eop | d_eol | d_wait;
+ myNextTxDesc->descr.buf = virt_to_phys(buf);
- TxDesc.sw_len = length;
- TxDesc.ctrl = d_eop | d_eol | d_wait;
- TxDesc.buf = virt_to_phys(buf);
+ /* Move end of list */
+ myLastTxDesc->descr.ctrl &= ~d_eol;
+ myLastTxDesc = myNextTxDesc;
- /* setup the dma channel and start it */
-
- *R_DMA_CH0_FIRST = virt_to_phys(&TxDesc);
- *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, start);
+ /* Restart DMA channel */
+ *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, restart);
}
static void
@@ -1323,7 +1595,7 @@ e100_set_network_leds(int active)
if (!current_speed) {
/* Make LED red, link is down */
- LED_NETWORK_SET(LED_RED);
+ LED_NETWORK_SET(LED_OFF);
}
else if (light_leds) {
if (current_speed == 10) {
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
new file mode 100644
index 000000000000..a105cadaeed1
--- /dev/null
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -0,0 +1,907 @@
+/* $Id: gpio.c,v 1.8 2003/07/04 08:27:37 starvik Exp $
+ *
+ * Etrax general port I/O device
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen (initial version)
+ * Ola Knutsson (LED handling)
+ * Johan Adolfsson (read/set directions, write, port G)
+ *
+ * $Log: gpio.c,v $
+ * Revision 1.8 2003/07/04 08:27:37 starvik
+ * Merge of Linux 2.5.74
+ *
+ * Revision 1.7 2003/01/10 07:44:07 starvik
+ * init_ioremap is now called by kernel before drivers are initialized
+ *
+ * Revision 1.6 2002/12/11 13:13:57 starvik
+ * Added arch/ to v10 specific includes
+ * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
+ *
+ * Revision 1.5 2002/11/20 11:56:11 starvik
+ * Merge of Linux 2.5.48
+ *
+ * Revision 1.4 2002/11/18 10:10:05 starvik
+ * Linux 2.5 port of latest gpio.c from Linux 2.4
+ *
+ * Revision 1.20 2002/10/16 21:16:24 johana
+ * Added support for PA high level interrupt.
+ * That gives 2ms response time with iodtest for high levels and 2-12 ms
+ * response time on low levels if the check is not made in
+ * process.c:cpu_idle() as well.
+ *
+ * Revision 1.19 2002/10/14 18:27:33 johana
+ * Implemented alarm handling so select() now works.
+ * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in
+ * cpu_idle().
+ * Otherwise I get 15-18 ms (same as doing the poll in userspace -
+ * but less overhead).
+ * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
+ * is in 2.4) as well?
+ * TODO? Perhaps call request_irq()/free_irq() only when needed?
+ * Increased version to 2.5
+ *
+ * Revision 1.18 2002/10/11 15:02:00 johana
+ * Mask inverted 8 bit value in setget_input().
+ *
+ * Revision 1.17 2002/06/17 15:53:01 johana
+ * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT
+ * that take a pointer as argument and thus can handle 32 bit ports (G)
+ * correctly.
+ * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
+ * (especially if Port G bit 31 is used)
+ *
+ * Revision 1.16 2002/06/17 09:59:51 johana
+ * Returning 32 bit values in the ioctl return value doesn't work if bit
+ * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.
+ * A new set of ioctl's will be added.
+ *
+ * Revision 1.15 2002/05/06 13:19:13 johana
+ * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well.
+ *
+ * Revision 1.14 2002/04/12 12:01:53 johana
+ * Use global r_port_g_data_shadow.
+ * Moved gpio_init_port_g() closer to gpio_init() and marked it __init.
+ *
+ * Revision 1.13 2002/04/10 12:03:55 johana
+ * Added support for port G /dev/gpiog (minor 3).
+ * Changed indentation on switch cases.
+ * Fixed other spaces to tabs.
+ *
+ * Revision 1.12 2001/11/12 19:42:15 pkj
+ * * Corrected return values from gpio_leds_ioctl().
+ * * Fixed compiler warnings.
+ *
+ * Revision 1.11 2001/10/30 14:39:12 johana
+ * Added D() around gpio_write printk.
+ *
+ * Revision 1.10 2001/10/25 10:24:42 johana
+ * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
+ * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
+ * from ~60 seconds to 4 seconds).
+ * Added save_flags/cli/restore_flags in ioctl.
+ *
+ * Revision 1.9 2001/05/04 14:16:07 matsfg
+ * Corrected spelling error
+ *
+ * Revision 1.8 2001/04/27 13:55:26 matsfg
+ * Moved initioremap.
+ * Turns off all LEDS on init.
+ * Added support for shutdown and powerbutton.
+ *
+ * Revision 1.7 2001/04/04 13:30:08 matsfg
+ * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
+ *
+ * Revision 1.6 2001/03/26 16:03:06 bjornw
+ * Needs linux/config.h
+ *
+ * Revision 1.5 2001/03/26 14:22:03 bjornw
+ * Namechange of some config options
+ *
+ * Revision 1.4 2001/02/27 13:52:48 bjornw
+ * malloc.h -> slab.h
+ *
+ * Revision 1.3 2001/01/24 15:06:48 bjornw
+ * gpio_wq correct type
+ *
+ * Revision 1.2 2001/01/18 16:07:30 bjornw
+ * 2.4 port
+ *
+ * Revision 1.1 2001/01/18 15:55:16 bjornw
+ * Verbatim copy of etraxgpio.c from elinux 2.0 added
+ *
+ *
+ */
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/etraxgpio.h>
+#include <asm/arch/svinto.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#define GPIO_MAJOR 120 /* experimental MAJOR number */
+
+#define D(x)
+
+#if 0
+static int dp_cnt;
+#define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
+#else
+#define DP(x)
+#endif
+
+static char gpio_name[] = "etrax gpio";
+
+#if 0
+static wait_queue_head_t *gpio_wq;
+#endif
+
+static int gpio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
+ loff_t *off);
+static int gpio_open(struct inode *inode, struct file *filp);
+static int gpio_release(struct inode *inode, struct file *filp);
+static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
+
+/* private data per open() of this driver */
+
+struct gpio_private {
+ struct gpio_private *next;
+ /* These fields are for PA and PB only */
+ volatile unsigned char *port, *shadow;
+ volatile unsigned char *dir, *dir_shadow;
+ unsigned char changeable_dir;
+ unsigned char changeable_bits;
+ unsigned char clk_mask;
+ unsigned char data_mask;
+ unsigned char write_msb;
+ unsigned char pad1, pad2, pad3;
+ /* These fields are generic */
+ unsigned long highalarm, lowalarm;
+ wait_queue_head_t alarm_wq;
+ int minor;
+};
+
+/* linked list of alarms to check for */
+
+static struct gpio_private *alarmlist = 0;
+
+static int gpio_some_alarms = 0; /* Set if someone uses alarm */
+
+/* Port A and B use 8 bit access, but Port G is 32 bit */
+#define NUM_PORTS (GPIO_MINOR_B+1)
+
+static volatile unsigned char *ports[NUM_PORTS] = {
+ R_PORT_PA_DATA,
+ R_PORT_PB_DATA,
+};
+static volatile unsigned char *shads[NUM_PORTS] = {
+ &port_pa_data_shadow,
+ &port_pb_data_shadow
+};
+
+/* What direction bits that are user changeable 1=changeable*/
+#ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
+#define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
+#endif
+#ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
+#define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
+#endif
+
+#ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
+#define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
+#endif
+#ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
+#define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
+#endif
+
+
+static unsigned char changeable_dir[NUM_PORTS] = {
+ CONFIG_ETRAX_PA_CHANGEABLE_DIR,
+ CONFIG_ETRAX_PB_CHANGEABLE_DIR
+};
+static unsigned char changeable_bits[NUM_PORTS] = {
+ CONFIG_ETRAX_PA_CHANGEABLE_BITS,
+ CONFIG_ETRAX_PB_CHANGEABLE_BITS
+};
+
+static volatile unsigned char *dir[NUM_PORTS] = {
+ R_PORT_PA_DIR,
+ R_PORT_PB_DIR
+};
+
+static volatile unsigned char *dir_shadow[NUM_PORTS] = {
+ &port_pa_dir_shadow,
+ &port_pb_dir_shadow
+};
+
+/* Port G is 32 bit, handle it special, some bits are both inputs
+ and outputs at the same time, only some of the bits can change direction
+ and some of them in groups of 8 bit. */
+static unsigned long changeable_dir_g;
+static unsigned long dir_g_in_bits;
+static unsigned long dir_g_out_bits;
+static unsigned long dir_g_shadow; /* 1=output */
+
+#define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
+
+
+
+static unsigned int
+gpio_poll(struct file *file,
+ poll_table *wait)
+{
+ unsigned int mask = 0;
+ struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ unsigned long data;
+ poll_wait(file, &priv->alarm_wq, wait);
+ if (priv->minor == GPIO_MINOR_A) {
+ unsigned long tmp;
+ data = *R_PORT_PA_DATA;
+ /* PA has support for high level interrupt -
+ * lets activate for those low and with highalarm set
+ */
+ tmp = ~data & priv->highalarm & 0xFF;
+ *R_IRQ_MASK1_SET = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
+ } else if (priv->minor == GPIO_MINOR_B)
+ data = *R_PORT_PB_DATA;
+ else if (priv->minor == GPIO_MINOR_G)
+ data = *R_PORT_G_DATA;
+ else
+ return 0;
+
+ if ((data & priv->highalarm) ||
+ (~data & priv->lowalarm)) {
+ mask = POLLIN|POLLRDNORM;
+ }
+
+ DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
+ return mask;
+}
+
+int etrax_gpio_wake_up_check(void)
+{
+ struct gpio_private *priv = alarmlist;
+ unsigned long data = 0;
+ int ret = 0;
+ while (priv) {
+ if (USE_PORTS(priv)) {
+ data = *priv->port;
+ } else if (priv->minor == GPIO_MINOR_G) {
+ data = *R_PORT_G_DATA;
+ }
+ if ((data & priv->highalarm) ||
+ (~data & priv->lowalarm)) {
+ DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
+ wake_up_interruptible(&priv->alarm_wq);
+ ret = 1;
+ }
+ priv = priv->next;
+ }
+ return ret;
+}
+
+static irqreturn_t
+gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (gpio_some_alarms) {
+ etrax_gpio_wake_up_check();
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static irqreturn_t
+gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long tmp;
+ /* Find what PA interrupts are active */
+ tmp = (*R_IRQ_READ1 >> R_IRQ_READ1__pa0__BITNR) & 0xFF;
+ /* Clear them.. */
+ /* NOTE: Maybe we need to be more careful here if some other
+ * driver uses PA interrupt as well?
+ */
+ *R_IRQ_MASK1_CLR = (tmp << R_IRQ_MASK1_CLR__pa0__BITNR);
+ if (gpio_some_alarms) {
+ return IRQ_RETVAL(etrax_gpio_wake_up_check());
+ }
+ return IRQ_NONE;
+}
+
+
+static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
+ loff_t *off)
+{
+ struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ unsigned char data, clk_mask, data_mask, write_msb;
+ unsigned long flags;
+ ssize_t retval = count;
+ if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
+ return -EFAULT;
+ }
+
+ if (verify_area(VERIFY_READ, buf, count)) {
+ return -EFAULT;
+ }
+ clk_mask = priv->clk_mask;
+ data_mask = priv->data_mask;
+ /* It must have been configured using the IO_CFG_WRITE_MODE */
+ /* Perhaps a better error code? */
+ if (clk_mask == 0 || data_mask == 0) {
+ return -EPERM;
+ }
+ write_msb = priv->write_msb;
+ D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
+ while (count--) {
+ int i;
+ data = *buf++;
+ if (priv->write_msb) {
+ for (i = 7; i >= 0;i--) {
+ local_irq_save(flags); local_irq_disable();
+ *priv->port = *priv->shadow &= ~clk_mask;
+ if (data & 1<<i)
+ *priv->port = *priv->shadow |= data_mask;
+ else
+ *priv->port = *priv->shadow &= ~data_mask;
+ /* For FPGA: min 5.0ns (DCC) before CCLK high */
+ *priv->port = *priv->shadow |= clk_mask;
+ local_irq_restore(flags);
+ }
+ } else {
+ for (i = 0; i <= 7;i++) {
+ local_irq_save(flags); local_irq_disable();
+ *priv->port = *priv->shadow &= ~clk_mask;
+ if (data & 1<<i)
+ *priv->port = *priv->shadow |= data_mask;
+ else
+ *priv->port = *priv->shadow &= ~data_mask;
+ /* For FPGA: min 5.0ns (DCC) before CCLK high */
+ *priv->port = *priv->shadow |= clk_mask;
+ local_irq_restore(flags);
+ }
+ }
+ }
+ return retval;
+}
+
+
+
+static int
+gpio_open(struct inode *inode, struct file *filp)
+{
+ struct gpio_private *priv;
+ int p = minor(inode->i_rdev);
+
+ if (p > GPIO_MINOR_LAST)
+ return -EINVAL;
+
+ priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
+ GFP_KERNEL);
+
+ if (!priv)
+ return -ENOMEM;
+
+ priv->minor = p;
+
+ /* initialize the io/alarm struct and link it into our alarmlist */
+
+ priv->next = alarmlist;
+ alarmlist = priv;
+ if (USE_PORTS(priv)) { /* A and B */
+ priv->port = ports[p];
+ priv->shadow = shads[p];
+ priv->dir = dir[p];
+ priv->dir_shadow = dir_shadow[p];
+ priv->changeable_dir = changeable_dir[p];
+ priv->changeable_bits = changeable_bits[p];
+ } else {
+ priv->port = NULL;
+ priv->shadow = NULL;
+ priv->dir = NULL;
+ priv->dir_shadow = NULL;
+ priv->changeable_dir = 0;
+ priv->changeable_bits = 0;
+ }
+
+ priv->highalarm = 0;
+ priv->lowalarm = 0;
+ priv->clk_mask = 0;
+ priv->data_mask = 0;
+ init_waitqueue_head(&priv->alarm_wq);
+
+ filp->private_data = (void *)priv;
+
+ return 0;
+}
+
+static int
+gpio_release(struct inode *inode, struct file *filp)
+{
+ struct gpio_private *p = alarmlist;
+ struct gpio_private *todel = (struct gpio_private *)filp->private_data;
+
+ /* unlink from alarmlist and free the private structure */
+
+ if (p == todel) {
+ alarmlist = todel->next;
+ } else {
+ while (p->next != todel)
+ p = p->next;
+ p->next = todel->next;
+ }
+
+ kfree(todel);
+ /* Check if there are still any alarms set */
+ p = alarmlist;
+ while (p) {
+ if (p->highalarm | p->lowalarm) {
+ gpio_some_alarms = 1;
+ return 0;
+ }
+ p = p->next;
+ }
+ gpio_some_alarms = 0;
+
+ return 0;
+}
+
+/* Main device API. ioctl's to read/set/clear bits, as well as to
+ * set alarms to wait for using a subsequent select().
+ */
+
+unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
+{
+ /* Set direction 0=unchanged 1=input,
+ * return mask with 1=input
+ */
+ unsigned long flags;
+ if (USE_PORTS(priv)) {
+ local_irq_save(flags); local_irq_disable();
+ *priv->dir = *priv->dir_shadow &=
+ ~((unsigned char)arg & priv->changeable_dir);
+ local_irq_restore(flags);
+ return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
+ } else if (priv->minor == GPIO_MINOR_G) {
+ /* We must fiddle with R_GEN_CONFIG to change dir */
+ if (((arg & dir_g_in_bits) != arg) &&
+ (arg & changeable_dir_g)) {
+ arg &= changeable_dir_g;
+ /* Clear bits in genconfig to set to input */
+ if (arg & (1<<0)) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
+ dir_g_in_bits |= (1<<0);
+ dir_g_out_bits &= ~(1<<0);
+ }
+ if ((arg & 0x0000FF00) == 0x0000FF00) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);
+ dir_g_in_bits |= 0x0000FF00;
+ dir_g_out_bits &= ~0x0000FF00;
+ }
+ if ((arg & 0x00FF0000) == 0x00FF0000) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);
+ dir_g_in_bits |= 0x00FF0000;
+ dir_g_out_bits &= ~0x00FF0000;
+ }
+ if (arg & (1<<24)) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
+ dir_g_in_bits |= (1<<24);
+ dir_g_out_bits &= ~(1<<24);
+ }
+ printk("gpio: SETINPUT on port G set "
+ "genconfig to 0x%08lX "
+ "in_bits: 0x%08lX "
+ "out_bits: 0x%08lX\n",
+ (unsigned long)genconfig_shadow,
+ dir_g_in_bits, dir_g_out_bits);
+ *R_GEN_CONFIG = genconfig_shadow;
+ /* Must be a >120 ns delay before writing this again */
+
+ }
+ return dir_g_in_bits;
+ }
+ return 0;
+} /* setget_input */
+
+unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
+{
+ unsigned long flags;
+ if (USE_PORTS(priv)) {
+ local_irq_save(flags); local_irq_disable();
+ *priv->dir = *priv->dir_shadow |=
+ ((unsigned char)arg & priv->changeable_dir);
+ local_irq_restore(flags);
+ return *priv->dir_shadow;
+ } else if (priv->minor == GPIO_MINOR_G) {
+ /* We must fiddle with R_GEN_CONFIG to change dir */
+ if (((arg & dir_g_out_bits) != arg) &&
+ (arg & changeable_dir_g)) {
+ /* Set bits in genconfig to set to output */
+ if (arg & (1<<0)) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
+ dir_g_out_bits |= (1<<0);
+ dir_g_in_bits &= ~(1<<0);
+ }
+ if ((arg & 0x0000FF00) == 0x0000FF00) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);
+ dir_g_out_bits |= 0x0000FF00;
+ dir_g_in_bits &= ~0x0000FF00;
+ }
+ if ((arg & 0x00FF0000) == 0x00FF0000) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);
+ dir_g_out_bits |= 0x00FF0000;
+ dir_g_in_bits &= ~0x00FF0000;
+ }
+ if (arg & (1<<24)) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
+ dir_g_out_bits |= (1<<24);
+ dir_g_in_bits &= ~(1<<24);
+ }
+ printk("gpio: SETOUTPUT on port G set "
+ "genconfig to 0x%08lX "
+ "in_bits: 0x%08lX "
+ "out_bits: 0x%08lX\n",
+ (unsigned long)genconfig_shadow,
+ dir_g_in_bits, dir_g_out_bits);
+ *R_GEN_CONFIG = genconfig_shadow;
+ /* Must be a >120 ns delay before writing this again */
+ }
+ return dir_g_out_bits & 0x7FFFFFFF;
+ }
+ return 0;
+} /* setget_output */
+
+static int
+gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
+
+static int
+gpio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned long flags;
+ unsigned long val;
+ struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
+ return -EINVAL;
+ }
+
+ switch (_IOC_NR(cmd)) {
+ case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
+ // read the port
+ if (USE_PORTS(priv)) {
+ return *priv->port;
+ } else if (priv->minor == GPIO_MINOR_G) {
+ return (*R_PORT_G_DATA) & 0x7FFFFFFF;
+ }
+ break;
+ case IO_SETBITS:
+ local_irq_save(flags); local_irq_disable();
+ // set changeable bits with a 1 in arg
+ if (USE_PORTS(priv)) {
+ *priv->port = *priv->shadow |=
+ ((unsigned char)arg & priv->changeable_bits);
+ } else if (priv->minor == GPIO_MINOR_G) {
+ *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
+ }
+ local_irq_restore(flags);
+ break;
+ case IO_CLRBITS:
+ local_irq_save(flags); local_irq_disable();
+ // clear changeable bits with a 1 in arg
+ if (USE_PORTS(priv)) {
+ *priv->port = *priv->shadow &=
+ ~((unsigned char)arg & priv->changeable_bits);
+ } else if (priv->minor == GPIO_MINOR_G) {
+ *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
+ }
+ local_irq_restore(flags);
+ break;
+ case IO_HIGHALARM:
+ // set alarm when bits with 1 in arg go high
+ priv->highalarm |= arg;
+ gpio_some_alarms = 1;
+ break;
+ case IO_LOWALARM:
+ // set alarm when bits with 1 in arg go low
+ priv->lowalarm |= arg;
+ gpio_some_alarms = 1;
+ break;
+ case IO_CLRALARM:
+ // clear alarm for bits with 1 in arg
+ priv->highalarm &= ~arg;
+ priv->lowalarm &= ~arg;
+ break;
+ case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
+ /* Read direction 0=input 1=output */
+ if (USE_PORTS(priv)) {
+ return *priv->dir_shadow;
+ } else if (priv->minor == GPIO_MINOR_G) {
+ /* Note: Some bits are both in and out,
+ * Those that are dual is set here as well.
+ */
+ return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
+ }
+ case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
+ /* Set direction 0=unchanged 1=input,
+ * return mask with 1=input
+ */
+ return setget_input(priv, arg) & 0x7FFFFFFF;
+ break;
+ case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
+ /* Set direction 0=unchanged 1=output,
+ * return mask with 1=output
+ */
+ return setget_output(priv, arg) & 0x7FFFFFFF;
+
+ case IO_SHUTDOWN:
+ SOFT_SHUTDOWN();
+ break;
+ case IO_GET_PWR_BT:
+#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
+ return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
+#else
+ return 0;
+#endif
+ break;
+ case IO_CFG_WRITE_MODE:
+ priv->clk_mask = arg & 0xFF;
+ priv->data_mask = (arg >> 8) & 0xFF;
+ priv->write_msb = (arg >> 16) & 0x01;
+ /* Check if we're allowed to change the bits and
+ * the direction is correct
+ */
+ if (!((priv->clk_mask & priv->changeable_bits) &&
+ (priv->data_mask & priv->changeable_bits) &&
+ (priv->clk_mask & *priv->dir_shadow) &&
+ (priv->data_mask & *priv->dir_shadow)))
+ {
+ priv->clk_mask = 0;
+ priv->data_mask = 0;
+ return -EPERM;
+ }
+ break;
+ case IO_READ_INBITS:
+ /* *arg is result of reading the input pins */
+ if (USE_PORTS(priv)) {
+ val = *priv->port;
+ } else if (priv->minor == GPIO_MINOR_G) {
+ val = *R_PORT_G_DATA;
+ }
+ if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ return -EFAULT;
+ return 0;
+ break;
+ case IO_READ_OUTBITS:
+ /* *arg is result of reading the output shadow */
+ if (USE_PORTS(priv)) {
+ val = *priv->shadow;
+ } else if (priv->minor == GPIO_MINOR_G) {
+ val = port_g_data_shadow;
+ }
+ if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ case IO_SETGET_INPUT:
+ /* bits set in *arg is set to input,
+ * *arg updated with current input pins.
+ */
+ if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_input(priv, val);
+ if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ case IO_SETGET_OUTPUT:
+ /* bits set in *arg is set to output,
+ * *arg updated with current output pins.
+ */
+ if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_output(priv, val);
+ if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ default:
+ if (priv->minor == GPIO_MINOR_LEDS)
+ return gpio_leds_ioctl(cmd, arg);
+ else
+ return -EINVAL;
+ } /* switch */
+
+ return 0;
+}
+
+static int
+gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
+{
+ unsigned char green;
+ unsigned char red;
+
+ switch (_IOC_NR(cmd)) {
+ case IO_LEDACTIVE_SET:
+ green = ((unsigned char) arg) & 1;
+ red = (((unsigned char) arg) >> 1) & 1;
+ LED_ACTIVE_SET_G(green);
+ LED_ACTIVE_SET_R(red);
+ break;
+
+ case IO_LED_SETBIT:
+ LED_BIT_SET(arg);
+ break;
+
+ case IO_LED_CLRBIT:
+ LED_BIT_CLR(arg);
+ break;
+
+ default:
+ return -EINVAL;
+ } /* switch */
+
+ return 0;
+}
+
+struct file_operations gpio_fops = {
+ .owner = THIS_MODULE,
+ .poll = gpio_poll,
+ .ioctl = gpio_ioctl,
+ .write = gpio_write,
+ .open = gpio_open,
+ .release = gpio_release,
+};
+
+
+static void __init gpio_init_port_g(void)
+{
+#define GROUPA (0x0000FF3F)
+#define GROUPB (1<<6 | 1<<7)
+#define GROUPC (1<<30 | 1<<31)
+#define GROUPD (0x3FFF0000)
+#define GROUPD_LOW (0x00FF0000)
+ unsigned long used_in_bits = 0;
+ unsigned long used_out_bits = 0;
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){
+ used_in_bits |= GROUPA | GROUPB | 0 | 0;
+ used_out_bits |= GROUPA | GROUPB | 0 | 0;
+ }
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {
+ used_in_bits |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));
+ used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;
+ }
+
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {
+ used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
+ used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
+ }
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {
+ used_in_bits |= 0 | GROUPB | 0 | 0;
+ used_out_bits |= 0 | GROUPB | 0 | 0;
+ }
+ /* mio same as shared RAM ? */
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {
+ used_in_bits |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;
+ used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;
+ }
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {
+ used_in_bits |= 0 | 0 | GROUPC | GROUPD;
+ used_out_bits |= 0 | 0 | GROUPC | GROUPD;
+ }
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {
+ used_in_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);
+ used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);
+ }
+
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {
+ used_in_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
+ used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
+ }
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {
+ used_in_bits |= 0 | 0 | GROUPC | 0;
+ used_out_bits |= 0 | 0 | GROUPC | 0;
+ }
+ /* mio same as shared RAM-W? */
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {
+ used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;
+ used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;
+ }
+ /* TODO: USB p2, parw, sync ser3? */
+
+ /* Initialise the dir_g_shadow etc. depending on genconfig */
+ /* 0=input 1=output */
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out))
+ dir_g_shadow |= (1 << 0);
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))
+ dir_g_shadow |= 0x0000FF00;
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out))
+ dir_g_shadow |= 0x00FF0000;
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
+ dir_g_shadow |= (1 << 24);
+
+ dir_g_in_bits = ~used_in_bits;
+ dir_g_out_bits = ~used_out_bits;
+
+ changeable_dir_g = 0x01FFFF01; /* all that can change dir */
+ changeable_dir_g &= dir_g_out_bits;
+ changeable_dir_g &= dir_g_in_bits;
+ /* Correct the bits that can change direction */
+ dir_g_out_bits &= ~changeable_dir_g;
+ dir_g_out_bits |= dir_g_shadow;
+ dir_g_in_bits &= ~changeable_dir_g;
+ dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
+
+
+ printk("GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
+ dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
+ printk("GPIO port G: dir: %08lX changeable: %08lX\n",
+ dir_g_shadow, changeable_dir_g);
+}
+
+/* main driver initialization routine, called from mem.c */
+
+static __init int
+gpio_init(void)
+{
+ int res;
+#if defined (CONFIG_ETRAX_CSP0_LEDS)
+ int i;
+#endif
+
+ /* do the formalities */
+
+ res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
+ if (res < 0) {
+ printk(KERN_ERR "gpio: couldn't get a major number.\n");
+ return res;
+ }
+
+ /* Clear all leds */
+#if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
+ LED_NETWORK_SET(0);
+ LED_ACTIVE_SET(0);
+ LED_DISK_READ(0);
+ LED_DISK_WRITE(0);
+
+#if defined (CONFIG_ETRAX_CSP0_LEDS)
+ for (i = 0; i < 32; i++) {
+ LED_BIT_SET(i);
+ }
+#endif
+
+#endif
+ gpio_init_port_g();
+ printk("ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
+ /* We call etrax_gpio_wake_up_check() from timer interrupt and
+ * from cpu_idle() in kernel/process.c
+ * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
+ * in some tests.
+ */
+ if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
+ SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) {
+ printk("err: timer0 irq for gpio\n");
+ }
+ if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
+ SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) {
+ printk("err: PA irq for gpio\n");
+ }
+
+
+ return res;
+}
+
+/* this makes sure that gpio_init is called during kernel boot */
+
+module_init(gpio_init);
diff --git a/arch/cris/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index 093c5d5dac13..7731f7d22f91 100644
--- a/arch/cris/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -12,8 +12,25 @@
*! don't use PB_I2C if DS1302 uses same bits,
*! use PB.
*! $Log: i2c.c,v $
-*! Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
-*! Import of Linux 2.5.1
+*! Revision 1.4 2002/12/11 13:13:57 starvik
+*! Added arch/ to v10 specific includes
+*! Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
+*!
+*! Revision 1.3 2002/11/20 11:56:11 starvik
+*! Merge of Linux 2.5.48
+*!
+*! Revision 1.2 2002/11/18 13:16:06 starvik
+*! Linux 2.5 port of latest 2.4 drivers
+*!
+*! Revision 1.9 2002/10/31 15:32:26 starvik
+*! Update Port B register and shadow even when running with hardware support
+*! to avoid glitches when reading bits
+*! Never set direction to out in i2c_inbyte
+*! Removed incorrect clock togling at end of i2c_inbyte
+*!
+*! Revision 1.8 2002/08/13 06:31:53 starvik
+*! Made SDA and SCL line configurable
+*! Modified i2c_inbyte to work with PCF8563
*!
*! Revision 1.7 2001/04/04 13:11:36 markusl
*! Updated according to review remarks
@@ -43,10 +60,11 @@
*!
*! ---------------------------------------------------------------------------
*!
-*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
+*! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
*!
*!***************************************************************************/
-/* $Id: i2c.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $ */
+/* $Id: i2c.c,v 1.4 2002/12/11 13:13:57 starvik Exp $ */
+
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/module.h>
@@ -62,7 +80,7 @@
#include <asm/etraxi2c.h>
#include <asm/system.h>
-#include <asm/svinto.h>
+#include <asm/arch/svinto.h>
#include <asm/io.h>
#include <asm/delay.h>
@@ -96,8 +114,15 @@ static const char i2c_name[] = "i2c";
#ifdef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
/* Use PB and not PB_I2C */
-#define SDABIT 0
-#define SCLBIT 1
+#ifndef CONFIG_ETRAX_I2C_DATA_PORT
+#define CONFIG_ETRAX_I2C_DATA_PORT 0
+#endif
+#ifndef CONFIG_ETRAX_I2C_CLK_PORT
+#define CONFIG_ETRAX_I2C_CLK_PORT 1
+#endif
+
+#define SDABIT CONFIG_ETRAX_I2C_DATA_PORT
+#define SCLBIT CONFIG_ETRAX_I2C_CLK_PORT
#define i2c_enable()
#define i2c_disable()
@@ -117,7 +142,7 @@ static const char i2c_name[] = "i2c";
/* read a bit from the i2c interface */
-#define i2c_getbit() (*R_PORT_PB_READ & (1 << SDABIT))
+#define i2c_getbit() (((*R_PORT_PB_READ & (1 << SDABIT))) >> SDABIT)
#else
/* enable or disable the i2c interface */
@@ -127,16 +152,24 @@ static const char i2c_name[] = "i2c";
/* enable or disable output-enable, to select output or input on the i2c bus */
-#define i2c_dir_out() *R_PORT_PB_I2C = (port_pb_i2c_shadow &= ~IO_MASK(R_PORT_PB_I2C, i2c_oe_))
-#define i2c_dir_in() *R_PORT_PB_I2C = (port_pb_i2c_shadow |= IO_MASK(R_PORT_PB_I2C, i2c_oe_))
+#define i2c_dir_out() \
+ *R_PORT_PB_I2C = (port_pb_i2c_shadow &= ~IO_MASK(R_PORT_PB_I2C, i2c_oe_)); \
+ REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, 0, 1);
+#define i2c_dir_in() \
+ *R_PORT_PB_I2C = (port_pb_i2c_shadow |= IO_MASK(R_PORT_PB_I2C, i2c_oe_)); \
+ REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, 0, 0);
/* control the i2c clock and data signals */
-#define i2c_clk(x) *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \
- ~IO_MASK(R_PORT_PB_I2C, i2c_clk)) | IO_FIELD(R_PORT_PB_I2C, i2c_clk, (x)))
+#define i2c_clk(x) \
+ *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \
+ ~IO_MASK(R_PORT_PB_I2C, i2c_clk)) | IO_FIELD(R_PORT_PB_I2C, i2c_clk, (x))); \
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 1, x);
-#define i2c_data(x) *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \
- ~IO_MASK(R_PORT_PB_I2C, i2c_d)) | IO_FIELD(R_PORT_PB_I2C, i2c_d, (x)))
+#define i2c_data(x) \
+ *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \
+ ~IO_MASK(R_PORT_PB_I2C, i2c_d)) | IO_FIELD(R_PORT_PB_I2C, i2c_d, (x))); \
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 0, x);
/* read a bit from the i2c interface */
@@ -209,14 +242,15 @@ void
i2c_outbyte(unsigned char x)
{
int i;
-
+
i2c_dir_out();
for (i = 0; i < 8; i++) {
- if (x & 0x80)
+ if (x & 0x80) {
i2c_data(I2C_DATA_HIGH);
- else
+ } else {
i2c_data(I2C_DATA_LOW);
+ }
i2c_delay(CLOCK_LOW_TIME/2);
i2c_clk(I2C_CLOCK_HIGH);
@@ -241,65 +275,41 @@ i2c_inbyte(void)
{
unsigned char aBitByte = 0;
int i;
- int iaa;
- /*
- * enable output
- */
- i2c_dir_out();
- /*
- * Release data bus by setting
- * data high
- */
- i2c_data(I2C_DATA_HIGH);
- /*
- * enable input
- */
+ /* Switch off I2C to get bit */
+ i2c_disable();
i2c_dir_in();
- /*
- * Use PORT PB instead of I2C
- * for input. (I2C not working)
- */
- i2c_clk(1);
- i2c_data(1);
- /*
- * get bits
- */
- for (i = 0; i < 8; i++) {
- i2c_delay(CLOCK_LOW_TIME/2);
- /*
- * low clock period
- */
+ i2c_delay(CLOCK_HIGH_TIME/2);
+
+ /* Get bit */
+ aBitByte |= i2c_getbit();
+
+ /* Enable I2C */
+ i2c_enable();
+ i2c_delay(CLOCK_LOW_TIME/2);
+
+ for (i = 1; i < 8; i++) {
+ aBitByte <<= 1;
+ /* Clock pulse */
i2c_clk(I2C_CLOCK_HIGH);
- /*
- * switch off I2C
- */
- i2c_data(1);
+ i2c_delay(CLOCK_HIGH_TIME);
+ i2c_clk(I2C_CLOCK_LOW);
+ i2c_delay(CLOCK_LOW_TIME);
+
+ /* Switch off I2C to get bit */
i2c_disable();
i2c_dir_in();
- /*
- * wait before getting bit
- */
- i2c_delay(CLOCK_HIGH_TIME/2);
- aBitByte = (aBitByte << 1);
- iaa = i2c_getbit();
- aBitByte = aBitByte | iaa ;
- /*
- * wait
- */
i2c_delay(CLOCK_HIGH_TIME/2);
- /*
- * end clock puls
- */
+
+ /* Get bit */
+ aBitByte |= i2c_getbit();
+
+ /* Enable I2C */
i2c_enable();
- i2c_dir_out();
- i2c_clk(I2C_CLOCK_LOW);
- /*
- * low clock period
- */
i2c_delay(CLOCK_LOW_TIME/2);
}
- i2c_dir_out();
+ i2c_clk(I2C_CLOCK_HIGH);
+ i2c_delay(CLOCK_HIGH_TIME);
return aBitByte;
}
@@ -424,44 +434,25 @@ i2c_sendack(void)
*#
*#--------------------------------------------------------------------------*/
int
-i2c_writereg(unsigned char theSlave, unsigned char theReg,
+i2c_writereg(unsigned char theSlave, unsigned char theReg,
unsigned char theValue)
{
int error, cntr = 3;
unsigned long flags;
-
+
do {
error = 0;
/*
* we don't like to be interrupted
*/
- save_flags(flags);
- cli();
- /*
- * generate start condition
- */
- i2c_start();
- /*
- * dummy preamble
- */
- i2c_outbyte(0x01);
- i2c_data(I2C_DATA_HIGH);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME); /* Dummy Acknowledge */
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_LOW_TIME); /* Repeated Start Condition */
- i2c_data(I2C_DATA_LOW);
- i2c_delay(CLOCK_HIGH_TIME);
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME);
+ local_irq_save(flags);
+ local_irq_disable();
i2c_start();
/*
* send slave address
*/
- i2c_outbyte(theSlave);
+ i2c_outbyte((theSlave & 0xfe));
/*
* wait for ack
*/
@@ -493,10 +484,10 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
/*
* enable interrupt again
*/
- restore_flags(flags);
+ local_irq_restore(flags);
} while(error && cntr--);
-
+
i2c_delay(CLOCK_LOW_TIME);
return -error;
@@ -515,40 +506,23 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
unsigned char b = 0;
int error, cntr = 3;
unsigned long flags;
-
+
do {
error = 0;
/*
* we don't like to be interrupted
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
+ local_irq_disable();
/*
* generate start condition
*/
i2c_start();
- /*
- * dummy preamble
- */
- i2c_outbyte(0x01);
- i2c_data(I2C_DATA_HIGH);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME); /* Dummy Acknowledge */
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_LOW_TIME); /* Repeated Start Condition */
- i2c_data(I2C_DATA_LOW);
- i2c_delay(CLOCK_HIGH_TIME);
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME);
-
- i2c_start();
/*
* send slave address
*/
- i2c_outbyte(theSlave);
+ i2c_outbyte((theSlave & 0xfe));
/*
* wait for ack
*/
@@ -593,7 +567,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
/*
* enable interrupt again
*/
- restore_flags(flags);
+ local_irq_restore(flags);
} while(error && cntr--);
diff --git a/arch/cris/drivers/i2c.h b/arch/cris/arch-v10/drivers/i2c.h
index d789274adc71..d0caa9ff883e 100644
--- a/arch/cris/drivers/i2c.h
+++ b/arch/cris/arch-v10/drivers/i2c.h
@@ -1,4 +1,4 @@
-/* $Id: i2c.h,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $ */
+/* $Id: i2c.h,v 1.2 2002/11/18 13:16:06 starvik Exp $ */
/* High level I2C actions */
int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue);
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
new file mode 100644
index 000000000000..6a677bce6f14
--- /dev/null
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -0,0 +1,287 @@
+/*
+ * PCF8563 RTC
+ *
+ * From Phillips' datasheet:
+ *
+ * The PCF8563 is a CMOS real-time clock/calendar optimized for low power
+ * consumption. A programmable clock output, interupt output and voltage
+ * low detector are also provided. All address and data are transferred
+ * serially via two-line bidirectional I2C-bus. Maximum bus speed is
+ * 400 kbits/s. The built-in word address register is incremented
+ * automatically after each written or read bute.
+ *
+ * Copyright (c) 2002, Axis Communications AB
+ * All rights reserved.
+ *
+ * Author: Tobias Anderberg <tobiasa@axis.com>.
+ *
+ * $Id: pcf8563.c,v 1.1 2002/12/12 08:27:26 starvik Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/arch/svinto.h>
+#include <asm/rtc.h>
+#include "i2c.h"
+
+#define PCF8563_MAJOR 121 /* Local major number. */
+#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
+#define PCF8563_NAME "PCF8563"
+#define DRIVER_VERSION "$Revision: 1.1 $"
+
+/* I2C bus slave registers. */
+#define RTC_I2C_READ 0xa3
+#define RTC_I2C_WRITE 0xa2
+
+/* Two simple wrapper macros, saves a few keystrokes. */
+#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
+#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
+
+static const unsigned char days_in_month[] =
+ { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+int pcf8563_open(struct inode *, struct file *);
+int pcf8563_release(struct inode *, struct file *);
+
+static struct file_operations pcf8563_fops = {
+ owner: THIS_MODULE,
+ ioctl: pcf8563_ioctl,
+ open: pcf8563_open,
+ release: pcf8563_release,
+};
+
+unsigned char
+pcf8563_readreg(int reg)
+{
+ unsigned char res = i2c_readreg(RTC_I2C_READ, reg);
+
+ /* The PCF8563 does not return 0 for unimplemented bits */
+ switch(reg)
+ {
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ res &= 0x7f;
+ break;
+ case RTC_HOURS:
+ case RTC_DAY_OF_MONTH:
+ res &= 0x3f;
+ break;
+ case RTC_MONTH:
+ res = (res & 0x1f) - 1; /* PCF8563 returns month in range 1-12 */
+ break;
+ }
+ return res;
+}
+
+void
+pcf8563_writereg(int reg, unsigned char val)
+{
+ i2c_writereg(RTC_I2C_WRITE,reg,val);
+}
+
+void
+get_rtc_time(struct rtc_time *tm)
+{
+ tm->tm_sec = rtc_read(RTC_SECONDS);
+ tm->tm_min = rtc_read(RTC_MINUTES);
+ tm->tm_hour = rtc_read(RTC_HOURS);
+ tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
+ tm->tm_mon = rtc_read(RTC_MONTH);
+ tm->tm_year = rtc_read(RTC_YEAR);
+
+ if (tm->tm_sec & 0x80)
+ printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME);
+
+ tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0);
+ tm->tm_sec &= 0x7f;
+ tm->tm_min &= 0x7f;
+ tm->tm_hour &= 0x3f;
+ tm->tm_mday &= 0x3f;
+ tm->tm_mon &= 0x1f;
+
+ BCD_TO_BIN(tm->tm_sec);
+ BCD_TO_BIN(tm->tm_min);
+ BCD_TO_BIN(tm->tm_hour);
+ BCD_TO_BIN(tm->tm_mday);
+ BCD_TO_BIN(tm->tm_mon);
+ tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
+}
+
+int __init
+pcf8563_init(void)
+{
+ unsigned char ret;
+ /*
+ * First of all we need to reset the chip. This is done by
+ * clearing control1, control2 and clk freq, clear the
+ * Voltage Low bit, and resetting all alarms.
+ */
+ if (rtc_write(RTC_CONTROL1, 0x00) < 0)
+ goto err;
+
+ if (rtc_write(RTC_CONTROL2, 0x00) < 0)
+ goto err;
+
+ if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
+ goto err;
+
+ /* Clear the VL bit in the seconds register. */
+ ret = rtc_read(RTC_SECONDS);
+
+ if (rtc_write(RTC_SECONDS, (ret & 0x7f)) < 0)
+ goto err;
+
+ /* Reset the alarms. */
+ if (rtc_write(RTC_MINUTE_ALARM, 0x00) < 0)
+ goto err;
+
+ if (rtc_write(RTC_HOUR_ALARM, 0x00) < 0)
+ goto err;
+
+ if (rtc_write(RTC_DAY_ALARM, 0x00) < 0)
+ goto err;
+
+ if (rtc_write(RTC_WEEKDAY_ALARM, 0x00) < 0)
+ goto err;
+
+ if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
+ printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
+ PCF8563_NAME, PCF8563_MAJOR);
+ return -1;
+ }
+
+ printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
+
+ /* Check for low voltage, and warn about it.. */
+ if (rtc_read(RTC_SECONDS) & 0x80)
+ printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME);
+
+ return 0;
+
+err:
+ printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
+ return -1;
+}
+
+void __exit
+pcf8563_exit(void)
+{
+ if (unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME) < 0) {
+ printk(KERN_INFO "%s: Unable to unregister device.\n", PCF8563_NAME);
+ }
+}
+
+/*
+ * ioctl calls for this driver. Why return -ENOTTY upon error? Because
+ * POSIX says so!
+ */
+int
+pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ /* Some sanity checks. */
+ if (_IOC_TYPE(cmd) != RTC_MAGIC)
+ return -ENOTTY;
+
+ if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
+ return -ENOTTY;
+
+ switch (cmd) {
+ case RTC_RD_TIME:
+ {
+ struct rtc_time tm;
+
+ get_rtc_time(&tm);
+
+ if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
+ return -EFAULT;
+ }
+
+ return 0;
+ }
+ break;
+ case RTC_SET_TIME:
+ {
+ int leap;
+ int century;
+ unsigned long flags;
+ struct rtc_time tm;
+
+ if (!capable(CAP_SYS_TIME))
+ return -EPERM;
+
+ if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time)))
+ return -EFAULT;
+
+ /* Convert from struct tm to struct rtc_time. */
+ tm.tm_year += 1900;
+ tm.tm_mon += 1;
+
+ leap = ((tm.tm_mon == 2) && ((tm.tm_year % 4) == 0)) ? 1 : 0;
+
+ /* Perform some sanity checks. */
+ if ((tm.tm_year < 1970) ||
+ (tm.tm_mon > 12) ||
+ (tm.tm_mday == 0) ||
+ (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
+ (tm.tm_hour >= 24) ||
+ (tm.tm_min >= 60) ||
+ (tm.tm_sec >= 60))
+ return -EINVAL;
+
+ century = (tm.tm_year >= 2000) ? 0x80 : 0;
+ tm.tm_year = tm.tm_year % 100;
+
+ BIN_TO_BCD(tm.tm_year);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_sec);
+ tm.tm_mon |= century;
+
+ rtc_write(RTC_YEAR, tm.tm_year);
+ rtc_write(RTC_MONTH, tm.tm_mon);
+ rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
+ rtc_write(RTC_HOURS, tm.tm_hour);
+ rtc_write(RTC_MINUTES, tm.tm_min);
+ rtc_write(RTC_SECONDS, tm.tm_sec);
+
+ return 0;
+ }
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+int
+pcf8563_open(struct inode *inode, struct file *filp)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+int
+pcf8563_release(struct inode *inode, struct file *filp)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+EXPORT_NO_SYMBOLS;
+module_init(pcf8563_init);
+module_exit(pcf8563_exit);
diff --git a/arch/cris/drivers/serial.c b/arch/cris/arch-v10/drivers/serial.c
index 1a47d686061f..2822ffb812cc 100644
--- a/arch/cris/drivers/serial.c
+++ b/arch/cris/arch-v10/drivers/serial.c
@@ -1,13 +1,129 @@
-/* $Id: serial.c,v 1.3 2001/12/19 10:32:35 johana Exp $
+/* $Id: serial.c,v 1.17 2003/07/04 08:27:37 starvik Exp $
*
* Serial port driver for the ETRAX 100LX chip
*
- * Copyright (C) 1998, 1999, 2000, 2001 Axis Communications AB
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Axis Communications AB
*
- * Many, many authors. Based once upon a time on serial.c for 16x50.
+ * Many, many authors. Based once upon a time on serial.c for 16x50.
*
* $Log: serial.c,v $
- * Revision 1.3 2001/12/19 10:32:35 johana
+ * Revision 1.17 2003/07/04 08:27:37 starvik
+ * Merge of Linux 2.5.74
+ *
+ * Revision 1.16 2003/06/13 10:05:19 johana
+ * Help the user to avoid trouble by:
+ * Forcing mixed mode for status/control lines if not all pins are used.
+ *
+ * Revision 1.15 2003/06/13 09:43:01 johana
+ * Merged in the following changes from os/linux/arch/cris/drivers/serial.c
+ * + some minor changes to reduce diff.
+ *
+ * Revision 1.49 2003/05/30 11:31:54 johana
+ * Merged in change-branch--serial9bit that adds CMSPAR support for sticky
+ * parity (mark/space)
+ *
+ * Revision 1.48 2003/05/30 11:03:57 johana
+ * Implemented rs_send_xchar() by disabling the DMA and writing manually.
+ * Added e100_disable_txdma_channel() and e100_enable_txdma_channel().
+ * Fixed rs_throttle() and rs_unthrottle() to properly call rs_send_xchar
+ * instead of setting info->x_char and check the CRTSCTS flag before
+ * controlling the rts pin.
+ *
+ * Revision 1.14 2003/04/09 08:12:44 pkj
+ * Corrected typo changes made upstream.
+ *
+ * Revision 1.13 2003/04/09 05:20:47 starvik
+ * Merge of Linux 2.5.67
+ *
+ * Revision 1.11 2003/01/22 06:48:37 starvik
+ * Fixed warnings issued by GCC 3.2.1
+ *
+ * Revision 1.9 2002/12/13 09:07:47 starvik
+ * Alert user that RX_TIMEOUT_TICKS==0 doesn't work
+ *
+ * Revision 1.8 2002/12/11 13:13:57 starvik
+ * Added arch/ to v10 specific includes
+ * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
+ *
+ * Revision 1.7 2002/12/06 07:13:57 starvik
+ * Corrected work queue stuff
+ * Removed CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
+ *
+ * Revision 1.6 2002/11/21 07:17:46 starvik
+ * Change static inline to extern inline where otherwise outlined with gcc-3.2
+ *
+ * Revision 1.5 2002/11/14 15:59:49 starvik
+ * Linux 2.5 port of the latest serial driver from 2.4. The work queue stuff
+ * probably doesn't work yet.
+ *
+ * Revision 1.42 2002/11/05 09:08:47 johana
+ * Better implementation of rs_stop() and rs_start() that uses the XOFF
+ * register to start/stop transmission.
+ * change_speed() also initilises XOFF register correctly so that
+ * auto_xoff is enabled when IXON flag is set by user.
+ * This gives fast XOFF response times.
+ *
+ * Revision 1.41 2002/11/04 18:40:57 johana
+ * Implemented rs_stop() and rs_start().
+ * Simple tests using hwtestserial indicates that this should be enough
+ * to make it work.
+ *
+ * Revision 1.40 2002/10/14 05:33:18 starvik
+ * RS-485 uses fast timers even if SERIAL_FAST_TIMER is disabled
+ *
+ * Revision 1.39 2002/09/30 21:00:57 johana
+ * Support for CONFIG_ETRAX_SERx_DTR_RI_DSR_CD_MIXED where the status and
+ * control pins can be mixed between PA and PB.
+ * If no serial port uses MIXED old solution is used
+ * (saves a few bytes and cycles).
+ * control_pins struct uses masks instead of bit numbers.
+ * Corrected dummy values and polarity in line_info() so
+ * /proc/tty/driver/serial is now correct.
+ * (the E100_xxx_GET() macros is really active low - perhaps not obvious)
+ *
+ * Revision 1.38 2002/08/23 11:01:36 starvik
+ * Check that serial port is enabled in all interrupt handlers to avoid
+ * restarts of DMA channels not assigned to serial ports
+ *
+ * Revision 1.37 2002/08/13 13:02:37 bjornw
+ * Removed some warnings because of unused code
+ *
+ * Revision 1.36 2002/08/08 12:50:01 starvik
+ * Serial interrupt is shared with synchronous serial port driver
+ *
+ * Revision 1.35 2002/06/03 10:40:49 starvik
+ * Increased RS-485 RTS toggle timer to 2 characters
+ *
+ * Revision 1.34 2002/05/28 18:59:36 johana
+ * Whitespace and comment fixing to be more like etrax100ser.c 1.71.
+ *
+ * Revision 1.33 2002/05/28 17:55:43 johana
+ * RS-485 uses FAST_TIMER if enabled, and starts a short (one char time)
+ * timer from tranismit_chars (interrupt context).
+ * The timer toggles RTS in interrupt context when expired giving minimum
+ * latencies.
+ *
+ * Revision 1.32 2002/05/22 13:58:00 johana
+ * Renamed rs_write() to raw_write() and made it inline.
+ * New rs_write() handles RS-485 if configured and enabled
+ * (moved code from e100_write_rs485()).
+ * RS-485 ioctl's uses copy_from_user() instead of verify_area().
+ *
+ * Revision 1.31 2002/04/22 11:20:03 johana
+ * Updated copyright years.
+ *
+ * Revision 1.30 2002/04/22 09:39:12 johana
+ * RS-485 support compiles.
+ *
+ * Revision 1.29 2002/01/14 16:10:01 pkj
+ * Allocate the receive buffers dynamically. The static 4kB buffer was
+ * too small for the peaks. This means that we can get rid of the extra
+ * buffer and the copying to it. It also means we require less memory
+ * under normal operations, but can use more when needed (there is a
+ * cap at 64kB for safety reasons). If there is no memory available
+ * we panic(), and die a horrible death...
+ *
+ * Revision 1.28 2001/12/18 15:04:53 johana
* Cleaned up write_rs485() - now it works correctly without padding extra
* char.
* Added sane default initialisation of rs485.
@@ -283,7 +399,7 @@
*
*/
-static char *serial_version = "$Revision: 1.3 $";
+static char *serial_version = "$Revision: 1.17 $";
#include <linux/config.h>
#include <linux/version.h>
@@ -301,12 +417,8 @@ static char *serial_version = "$Revision: 1.3 $";
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#if (LINUX_VERSION_CODE >= 131343)
#include <linux/init.h>
-#endif
-#if (LINUX_VERSION_CODE >= 131336)
#include <asm/uaccess.h>
-#endif
#include <linux/kernel.h>
#include <asm/io.h>
@@ -314,28 +426,38 @@ static char *serial_version = "$Revision: 1.3 $";
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>
-#include <asm/delay.h>
+#include <linux/delay.h>
-#include <asm/svinto.h>
+#include <asm/arch/svinto.h>
/* non-arch dependent serial structures are in linux/serial.h */
#include <linux/serial.h>
/* while we keep our own stuff (struct e100_serial) in a local .h file */
#include "serial.h"
+#include <asm/fasttimer.h>
+
+#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
+#ifndef CONFIG_ETRAX_FAST_TIMER
+#error "Enable FAST_TIMER to use SERIAL_FAST_TIMER"
+#endif
+#endif
+
+#if defined(CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS) && \
+ (CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS == 0)
+#error "RX_TIMEOUT_TICKS == 0 not allowed, use 1"
+#endif
/*
* All of the compatibilty code so we can compile serial.c against
* older kernels is hidden in serial_compat.h
*/
-#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */
+#if defined(LOCAL_HEADERS)
#include "serial_compat.h"
#endif
#define _INLINE_ inline
-static DECLARE_TASK_QUEUE(tq_serial);
-
-static struct tty_driver *serial_driver;
+struct tty_driver *serial_driver;
/* serial subtype definitions */
#ifndef SERIAL_TYPE_NORMAL
@@ -361,8 +483,7 @@ static struct tty_driver *serial_driver;
#define TTY_THROTTLE_LIMIT (TTY_FLIPBUF_SIZE/10)
-#define SERIAL_RECV_SIZE 4096
-#define SERIAL_DESCR_BUF_SIZE 512
+#define SERIAL_DESCR_BUF_SIZE 256
/* Add an x here to log a lot of timer stuff */
#define TIMERD(x)
@@ -381,6 +502,14 @@ static void change_speed(struct e100_serial *info);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
static int rs_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count);
+static inline int raw_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count);
+#ifdef CONFIG_ETRAX_RS485
+static int e100_write_rs485(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count);
+#endif
+static int get_lsr_info(struct e100_serial * info, unsigned int *value);
+
#define DEF_BAUD 0x99 /* 115.2 kbit/s */
#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
@@ -487,6 +616,9 @@ static struct e100_serial rs_table[] = {
#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
+#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
+static struct fast_timer fast_timers[NR_PORTS];
+#endif
#ifdef CONFIG_ETRAX_SERIAL_PROC_ENTRY
#define PROCSTAT(x) x
@@ -506,7 +638,7 @@ struct ser_statistics_type {
static struct ser_statistics_type ser_stat[NR_PORTS];
-#else
+#else
#define PROCSTAT(x)
@@ -514,91 +646,440 @@ static struct ser_statistics_type ser_stat[NR_PORTS];
/* RS-485 */
#if defined(CONFIG_ETRAX_RS485)
+#ifdef CONFIG_ETRAX_FAST_TIMER
+static struct fast_timer fast_timers_rs485[NR_PORTS];
+#endif
#if defined(CONFIG_ETRAX_RS485_ON_PA)
static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT;
#endif
#endif
-
-/* For now we assume that all bits are on the same port for each serial port */
+/* Info and macros needed for each ports extra control/status signals. */
+#define E100_STRUCT_PORT(line, pinname) \
+ ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \
+ (R_PORT_PA_DATA): ( \
+ (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \
+ (R_PORT_PB_DATA):&dummy_ser[line]))
+
+#define E100_STRUCT_SHADOW(line, pinname) \
+ ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \
+ (&port_pa_data_shadow): ( \
+ (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \
+ (&port_pb_data_shadow):&dummy_ser[line]))
+#define E100_STRUCT_MASK(line, pinname) \
+ ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \
+ (1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT): ( \
+ (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \
+ (1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT):DUMMY_##pinname##_MASK))
+
+#define DUMMY_DTR_MASK 1
+#define DUMMY_RI_MASK 2
+#define DUMMY_DSR_MASK 4
+#define DUMMY_CD_MASK 8
+static unsigned char dummy_ser[NR_PORTS] = {0xFF, 0xFF, 0xFF,0xFF};
+
+/* If not all status pins are used or disabled, use mixed mode */
+#ifdef CONFIG_ETRAX_SERIAL_PORT0
-/* Dummy shadow variables */
-#if !defined(CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB)
-static unsigned char dummy_ser0 = 0x00;
-static unsigned char dummy_dir_ser0 = 0x00;
-#endif
-#if !defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB)
-static unsigned char dummy_ser1 = 0x00;
-static unsigned char dummy_dir_ser1 = 0x00;
-#endif
-#if !defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA)
-static unsigned char dummy_ser2 = 0x00;
-static unsigned char dummy_dir_ser2 = 0x00;
-#endif
+#define SER0_PA_BITSUM (CONFIG_ETRAX_SER0_DTR_ON_PA_BIT+CONFIG_ETRAX_SER0_RI_ON_PA_BIT+CONFIG_ETRAX_SER0_DSR_ON_PA_BIT+CONFIG_ETRAX_SER0_CD_ON_PA_BIT)
+
+#if SER0_PA_BITSUM != -4
+# if CONFIG_ETRAX_SER0_DTR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER0_RI_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER0_DSR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER0_CD_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#define SER0_PB_BITSUM (CONFIG_ETRAX_SER0_DTR_ON_PB_BIT+CONFIG_ETRAX_SER0_RI_ON_PB_BIT+CONFIG_ETRAX_SER0_DSR_ON_PB_BIT+CONFIG_ETRAX_SER0_CD_ON_PB_BIT)
+
+#if SER0_PB_BITSUM != -4
+# if CONFIG_ETRAX_SER0_DTR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER0_RI_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER0_DSR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER0_CD_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#endif /* PORT0 */
+
+
+#ifdef CONFIG_ETRAX_SERIAL_PORT1
+
+#define SER1_PA_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PA_BIT+CONFIG_ETRAX_SER1_RI_ON_PA_BIT+CONFIG_ETRAX_SER1_DSR_ON_PA_BIT+CONFIG_ETRAX_SER1_CD_ON_PA_BIT)
+
+#if SER1_PA_BITSUM != -4
+# if CONFIG_ETRAX_SER1_DTR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER1_RI_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER1_DSR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER1_CD_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#define SER0_PB_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PB_BIT+CONFIG_ETRAX_SER1_RI_ON_PB_BIT+CONFIG_ETRAX_SER1_DSR_ON_PB_BIT+CONFIG_ETRAX_SER1_CD_ON_PB_BIT)
+
+#if SER1_PB_BITSUM != -4
+# if CONFIG_ETRAX_SER1_DTR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER1_RI_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER1_DSR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER1_CD_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#endif /* PORT1 */
+
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+
+#define SER2_PA_BITSUM (CONFIG_ETRAX_SER2_DTR_ON_PA_BIT+CONFIG_ETRAX_SER2_RI_ON_PA_BIT+CONFIG_ETRAX_SER2_DSR_ON_PA_BIT+CONFIG_ETRAX_SER2_CD_ON_PA_BIT)
+
+#if SER2_PA_BITSUM != -4
+# if CONFIG_ETRAX_SER2_DTR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER2_RI_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER2_DSR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER2_CD_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#define SER2_PB_BITSUM (CONFIG_ETRAX_SER2_DTR_ON_PB_BIT+CONFIG_ETRAX_SER2_RI_ON_PB_BIT+CONFIG_ETRAX_SER2_DSR_ON_PB_BIT+CONFIG_ETRAX_SER2_CD_ON_PB_BIT)
+
+#if SER2_PB_BITSUM != -4
+# if CONFIG_ETRAX_SER2_DTR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER2_RI_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER2_DSR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER2_CD_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#endif /* PORT2 */
-static unsigned char dummy_ser3 = 0x00;
-static unsigned char dummy_dir_ser3 = 0x00;
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
+
+#define SER3_PA_BITSUM (CONFIG_ETRAX_SER3_DTR_ON_PA_BIT+CONFIG_ETRAX_SER3_RI_ON_PA_BIT+CONFIG_ETRAX_SER3_DSR_ON_PA_BIT+CONFIG_ETRAX_SER3_CD_ON_PA_BIT)
+
+#if SER3_PA_BITSUM != -4
+# if CONFIG_ETRAX_SER3_DTR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER3_RI_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER3_DSR_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER3_CD_ON_PA_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#define SER3_PB_BITSUM (CONFIG_ETRAX_SER3_DTR_ON_PB_BIT+CONFIG_ETRAX_SER3_RI_ON_PB_BIT+CONFIG_ETRAX_SER3_DSR_ON_PB_BIT+CONFIG_ETRAX_SER3_CD_ON_PB_BIT)
+
+#if SER3_PB_BITSUM != -4
+# if CONFIG_ETRAX_SER3_DTR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER3_RI_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER3_DSR_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+# if CONFIG_ETRAX_SER3_CD_ON_PB_BIT == -1
+# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED
+# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1
+# endif
+# endif
+#endif
+
+#endif /* PORT3 */
+
+
+#if defined(CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED) || \
+ defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED) || \
+ defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED) || \
+ defined(CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED)
+#define CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED
+#endif
+
+#ifdef CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED
+/* The pins can be mixed on PA and PB */
+#define CONTROL_PINS_PORT_NOT_USED(line) \
+ &dummy_ser[line], &dummy_ser[line], \
+ &dummy_ser[line], &dummy_ser[line], \
+ &dummy_ser[line], &dummy_ser[line], \
+ &dummy_ser[line], &dummy_ser[line], \
+ DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK
+
+
+struct control_pins
+{
+ volatile unsigned char *dtr_port;
+ unsigned char *dtr_shadow;
+ volatile unsigned char *ri_port;
+ unsigned char *ri_shadow;
+ volatile unsigned char *dsr_port;
+ unsigned char *dsr_shadow;
+ volatile unsigned char *cd_port;
+ unsigned char *cd_shadow;
+
+ unsigned char dtr_mask;
+ unsigned char ri_mask;
+ unsigned char dsr_mask;
+ unsigned char cd_mask;
+};
+
+static const struct control_pins e100_modem_pins[NR_PORTS] =
+{
+ /* Ser 0 */
+ {
+#ifdef CONFIG_ETRAX_SERIAL_PORT0
+ E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR),
+ E100_STRUCT_PORT(0,RI), E100_STRUCT_SHADOW(0,RI),
+ E100_STRUCT_PORT(0,DSR), E100_STRUCT_SHADOW(0,DSR),
+ E100_STRUCT_PORT(0,CD), E100_STRUCT_SHADOW(0,CD),
+ E100_STRUCT_MASK(0,DTR),
+ E100_STRUCT_MASK(0,RI),
+ E100_STRUCT_MASK(0,DSR),
+ E100_STRUCT_MASK(0,CD)
+#else
+ CONTROL_PINS_PORT_NOT_USED(0)
+#endif
+ },
+
+ /* Ser 1 */
+ {
+#ifdef CONFIG_ETRAX_SERIAL_PORT1
+ E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR),
+ E100_STRUCT_PORT(1,RI), E100_STRUCT_SHADOW(1,RI),
+ E100_STRUCT_PORT(1,DSR), E100_STRUCT_SHADOW(1,DSR),
+ E100_STRUCT_PORT(1,CD), E100_STRUCT_SHADOW(1,CD),
+ E100_STRUCT_MASK(1,DTR),
+ E100_STRUCT_MASK(1,RI),
+ E100_STRUCT_MASK(1,DSR),
+ E100_STRUCT_MASK(1,CD)
+#else
+ CONTROL_PINS_PORT_NOT_USED(1)
+#endif
+ },
+
+ /* Ser 2 */
+ {
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+ E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR),
+ E100_STRUCT_PORT(2,RI), E100_STRUCT_SHADOW(2,RI),
+ E100_STRUCT_PORT(2,DSR), E100_STRUCT_SHADOW(2,DSR),
+ E100_STRUCT_PORT(2,CD), E100_STRUCT_SHADOW(2,CD),
+ E100_STRUCT_MASK(2,DTR),
+ E100_STRUCT_MASK(2,RI),
+ E100_STRUCT_MASK(2,DSR),
+ E100_STRUCT_MASK(2,CD)
+#else
+ CONTROL_PINS_PORT_NOT_USED(2)
+#endif
+ },
+
+ /* Ser 3 */
+ {
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
+ E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR),
+ E100_STRUCT_PORT(3,RI), E100_STRUCT_SHADOW(3,RI),
+ E100_STRUCT_PORT(3,DSR), E100_STRUCT_SHADOW(3,DSR),
+ E100_STRUCT_PORT(3,CD), E100_STRUCT_SHADOW(3,CD),
+ E100_STRUCT_MASK(3,DTR),
+ E100_STRUCT_MASK(3,RI),
+ E100_STRUCT_MASK(3,DSR),
+ E100_STRUCT_MASK(3,CD)
+#else
+ CONTROL_PINS_PORT_NOT_USED(3)
+#endif
+ }
+};
+#else /* CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
+
+/* All pins are on either PA or PB for each serial port */
+#define CONTROL_PINS_PORT_NOT_USED(line) \
+ &dummy_ser[line], &dummy_ser[line], \
+ DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK
+
-/* Info needed for each ports extra control/status signals.
- We only supports that all pins uses same register for each port */
struct control_pins
{
volatile unsigned char *port;
- volatile unsigned char *shadow;
- volatile unsigned char *dir_shadow;
-
- unsigned char dtr_bit;
- unsigned char ri_bit;
- unsigned char dsr_bit;
- unsigned char cd_bit;
+ unsigned char *shadow;
+
+ unsigned char dtr_mask;
+ unsigned char ri_mask;
+ unsigned char dsr_mask;
+ unsigned char cd_mask;
};
+#define dtr_port port
+#define dtr_shadow shadow
+#define ri_port port
+#define ri_shadow shadow
+#define dsr_port port
+#define dsr_shadow shadow
+#define cd_port port
+#define cd_shadow shadow
+
static const struct control_pins e100_modem_pins[NR_PORTS] =
{
/* Ser 0 */
{
-#if defined(CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB)
- R_PORT_PB_DATA, &port_pb_data_shadow, &port_pb_dir_shadow,
- CONFIG_ETRAX_SER0_DTR_ON_PB_BIT,
- CONFIG_ETRAX_SER0_RI_ON_PB_BIT,
- CONFIG_ETRAX_SER0_DSR_ON_PB_BIT,
- CONFIG_ETRAX_SER0_CD_ON_PB_BIT
+#ifdef CONFIG_ETRAX_SERIAL_PORT0
+ E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR),
+ E100_STRUCT_MASK(0,DTR),
+ E100_STRUCT_MASK(0,RI),
+ E100_STRUCT_MASK(0,DSR),
+ E100_STRUCT_MASK(0,CD)
#else
- &dummy_ser0, &dummy_ser0, &dummy_dir_ser0, 0, 1, 2, 3
-#endif
+ CONTROL_PINS_PORT_NOT_USED(0)
+#endif
},
/* Ser 1 */
{
-#if defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB)
- R_PORT_PB_DATA, &port_pb_data_shadow, &port_pb_dir_shadow,
- CONFIG_ETRAX_SER1_DTR_ON_PB_BIT,
- CONFIG_ETRAX_SER1_RI_ON_PB_BIT,
- CONFIG_ETRAX_SER1_DSR_ON_PB_BIT,
- CONFIG_ETRAX_SER1_CD_ON_PB_BIT
+#ifdef CONFIG_ETRAX_SERIAL_PORT1
+ E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR),
+ E100_STRUCT_MASK(1,DTR),
+ E100_STRUCT_MASK(1,RI),
+ E100_STRUCT_MASK(1,DSR),
+ E100_STRUCT_MASK(1,CD)
#else
- &dummy_ser1, &dummy_ser1, &dummy_dir_ser1, 0, 1, 2, 3
-#endif
+ CONTROL_PINS_PORT_NOT_USED(1)
+#endif
},
/* Ser 2 */
{
-#if defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA)
- R_PORT_PA_DATA, &port_pa_data_shadow, &port_pa_dir_shadow,
- CONFIG_ETRAX_SER2_DTR_ON_PA_BIT,
- CONFIG_ETRAX_SER2_RI_ON_PA_BIT,
- CONFIG_ETRAX_SER2_DSR_ON_PA_BIT,
- CONFIG_ETRAX_SER2_CD_ON_PA_BIT
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+ E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR),
+ E100_STRUCT_MASK(2,DTR),
+ E100_STRUCT_MASK(2,RI),
+ E100_STRUCT_MASK(2,DSR),
+ E100_STRUCT_MASK(2,CD)
#else
- &dummy_ser2, &dummy_ser2, &dummy_dir_ser2, 0, 1, 2, 3
-#endif
+ CONTROL_PINS_PORT_NOT_USED(2)
+#endif
},
/* Ser 3 */
{
- &dummy_ser3, &dummy_ser3, &dummy_dir_ser3, 0, 1, 2, 3
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
+ E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR),
+ E100_STRUCT_MASK(3,DTR),
+ E100_STRUCT_MASK(3,RI),
+ E100_STRUCT_MASK(3,DSR),
+ E100_STRUCT_MASK(3,CD)
+#else
+ CONTROL_PINS_PORT_NOT_USED(3)
+#endif
}
};
+#endif /* !CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */
#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_RS485_ON_PA)
unsigned char rs485_pa_port = CONFIG_ETRAX_RS485_ON_PA_BIT;
@@ -623,20 +1104,16 @@ unsigned char rs485_pa_port = CONFIG_ETRAX_RS485_ON_PA_BIT;
/* These are typically PA or PB and 0 means 0V, 1 means 3.3V */
/* Is an output */
-#define E100_DTR_GET(info) ((*e100_modem_pins[(info)->line].shadow) & (1 << e100_modem_pins[(info)->line].dtr_bit))
+#define E100_DTR_GET(info) ((*e100_modem_pins[(info)->line].dtr_shadow) & e100_modem_pins[(info)->line].dtr_mask)
/* Normally inputs */
-#define E100_RI_GET(info) ((*e100_modem_pins[(info)->line].port) & (1 << e100_modem_pins[(info)->line].ri_bit))
-#define E100_CD_GET(info) ((*e100_modem_pins[(info)->line].port) & (1 << e100_modem_pins[(info)->line].cd_bit))
+#define E100_RI_GET(info) ((*e100_modem_pins[(info)->line].ri_port) & e100_modem_pins[(info)->line].ri_mask)
+#define E100_CD_GET(info) ((*e100_modem_pins[(info)->line].cd_port) & e100_modem_pins[(info)->line].cd_mask)
/* Input */
-#define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].port) & (1 << e100_modem_pins[(info)->line].dsr_bit))
+#define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].dsr_port) & e100_modem_pins[(info)->line].dsr_mask)
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
/*
* tmp_buf is used as a temporary buffer by serial_write. We need to
* lock it in case the memcpy_fromfs blocks while swapping in a page,
@@ -653,43 +1130,6 @@ static DECLARE_MUTEX(tmp_buf_sem);
static struct semaphore tmp_buf_sem = MUTEX;
#endif
-#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
-
-/* clock select 10 for timer 1 gives 230400 Hz */
-#define FASTTIMER_SELECT (10)
-/* we use a source of 230400 Hz and a divider of 15 => 15360 Hz */
-#define FASTTIMER_DIV (15)
-
-/* fast flush timer stuff */
-static int fast_timer_started = 0;
-static unsigned long int fast_timer_ints = 0;
-
-static void _INLINE_ start_flush_timer(void)
-{
- if (fast_timer_started)
- return;
-
- *R_TIMER_CTRL = r_timer_ctrl_shadow =
- (r_timer_ctrl_shadow &
- ~IO_MASK(R_TIMER_CTRL, timerdiv1) &
- ~IO_MASK(R_TIMER_CTRL, tm1) &
- ~IO_MASK(R_TIMER_CTRL, clksel1)) |
- IO_FIELD(R_TIMER_CTRL, timerdiv1, FASTTIMER_DIV) |
- IO_STATE(R_TIMER_CTRL, tm1, stop_ld) |
- IO_FIELD(R_TIMER_CTRL, clksel1, FASTTIMER_SELECT);
-
- *R_TIMER_CTRL = r_timer_ctrl_shadow =
- (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
- IO_STATE(R_TIMER_CTRL, tm1, run);
-
- /* enable timer1 irq */
-
- *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);
-
- fast_timer_started = 1;
-}
-#endif /* CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST */
-
/* Calculate the chartime depending on baudrate, numbor of bits etc. */
static void update_char_time(struct e100_serial * info)
{
@@ -754,7 +1194,7 @@ cflag_to_etrax_baud(unsigned int cflag)
retval = baud_table[cflag & CBAUD];
if (retval < 0) {
- printk("serdriver tried setting invalid baud rate, flags %x.\n", cflag);
+ printk(KERN_WARNING "serdriver tried setting invalid baud rate, flags %x.\n", cflag);
retval = 5; /* choose default 9600 instead */
}
@@ -770,16 +1210,17 @@ cflag_to_etrax_baud(unsigned int cflag)
* any general port.
*/
+
static inline void
e100_dtr(struct e100_serial *info, int set)
{
#ifndef CONFIG_SVINTO_SIM
- unsigned char mask = (1 << e100_modem_pins[info->line].dtr_bit);
+ unsigned char mask = e100_modem_pins[info->line].dtr_mask;
#ifdef SERIAL_DEBUG_IO
printk("ser%i dtr %i mask: 0x%02X\n", info->line, set, mask);
printk("ser%i shadow before 0x%02X get: %i\n",
- info->line, *e100_modem_pins[info->line].shadow,
+ info->line, *e100_modem_pins[info->line].dtr_shadow,
E100_DTR_GET(info));
#endif
/* DTR is active low */
@@ -788,20 +1229,15 @@ e100_dtr(struct e100_serial *info, int set)
save_flags(flags);
cli();
- *e100_modem_pins[info->line].shadow &= ~mask;
- *e100_modem_pins[info->line].shadow |= (set ? 0 : mask);
- *e100_modem_pins[info->line].port = *e100_modem_pins[info->line].shadow;
+ *e100_modem_pins[info->line].dtr_shadow &= ~mask;
+ *e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask);
+ *e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow;
restore_flags(flags);
}
-#if 0
- REG_SHADOW_SET(e100_modem_pins[info->line].port,
- *e100_modem_pins[info->line].shadow,
- e100_modem_pins[info->line].dtr_bit, !set);
-#endif
#ifdef SERIAL_DEBUG_IO
printk("ser%i shadow after 0x%02X get: %i\n",
- info->line, *e100_modem_pins[info->line].shadow,
+ info->line, *e100_modem_pins[info->line].dtr_shadow,
E100_DTR_GET(info));
#endif
#endif
@@ -814,15 +1250,16 @@ static inline void
e100_rts(struct e100_serial *info, int set)
{
#ifndef CONFIG_SVINTO_SIM
-#ifdef SERIAL_DEBUG_IO
- printk("ser%i rts %i\n", info->line, set);
-#endif
info->rx_ctrl &= ~E100_RTS_MASK;
info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */
info->port[REG_REC_CTRL] = info->rx_ctrl;
+#ifdef SERIAL_DEBUG_IO
+ printk("ser%i rts %i\n", info->line, set);
+#endif
#endif
}
+
/* If this behaves as a modem, RI and CD is an output */
static inline void
e100_ri_out(struct e100_serial *info, int set)
@@ -830,21 +1267,16 @@ e100_ri_out(struct e100_serial *info, int set)
#ifndef CONFIG_SVINTO_SIM
/* RI is active low */
{
- unsigned char mask = (1 << e100_modem_pins[info->line].ri_bit);
+ unsigned char mask = e100_modem_pins[info->line].ri_mask;
unsigned long flags;
save_flags(flags);
cli();
- *e100_modem_pins[info->line].shadow &= ~mask;
- *e100_modem_pins[info->line].shadow |= (set ? 0 : mask);
- *e100_modem_pins[info->line].port = *e100_modem_pins[info->line].shadow;
+ *e100_modem_pins[info->line].ri_shadow &= ~mask;
+ *e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask);
+ *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
restore_flags(flags);
}
-#if 0
- REG_SHADOW_SET(e100_modem_pins[info->line].port,
- *e100_modem_pins[info->line].shadow,
- e100_modem_pins[info->line].ri_bit, !set);
-#endif
#endif
}
static inline void
@@ -853,21 +1285,16 @@ e100_cd_out(struct e100_serial *info, int set)
#ifndef CONFIG_SVINTO_SIM
/* CD is active low */
{
- unsigned char mask = (1 << e100_modem_pins[info->line].cd_bit);
+ unsigned char mask = e100_modem_pins[info->line].cd_mask;
unsigned long flags;
save_flags(flags);
cli();
- *e100_modem_pins[info->line].shadow &= ~mask;
- *e100_modem_pins[info->line].shadow |= (set ? 0 : mask);
- *e100_modem_pins[info->line].port = *e100_modem_pins[info->line].shadow;
+ *e100_modem_pins[info->line].cd_shadow &= ~mask;
+ *e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask);
+ *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
restore_flags(flags);
}
-#if 0
- REG_SHADOW_SET(e100_modem_pins[info->line].port,
- *e100_modem_pins[info->line].shadow,
- e100_modem_pins[info->line].cd_bit, !set);
-#endif
#endif
}
@@ -931,6 +1358,60 @@ e100_enable_txdma_irq(struct e100_serial *info)
*R_IRQ_MASK2_SET = info->irq;
}
+static inline void
+e100_disable_txdma_channel(struct e100_serial *info)
+{
+ unsigned long flags;
+
+ /* Disable output DMA channel for the serial port in question
+ * ( set to something other then serialX)
+ */
+ save_flags(flags);
+ cli();
+ if (info->line == 0) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused);
+ } else if (info->line == 1) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb);
+ } else if (info->line == 2) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0);
+ } else if (info->line == 3) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1);
+ }
+ *R_GEN_CONFIG = genconfig_shadow;
+ restore_flags(flags);
+}
+
+
+static inline void
+e100_enable_txdma_channel(struct e100_serial *info)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ /* Enable output DMA channel for the serial port in question */
+ if (info->line == 0) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, serial0);
+ } else if (info->line == 1) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, serial1);
+ } else if (info->line == 2) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, serial2);
+ } else if (info->line == 3) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4);
+ genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3);
+ }
+ *R_GEN_CONFIG = genconfig_shadow;
+ restore_flags(flags);
+}
+
+
#ifdef SERIAL_HANDLE_EARLY_ERRORS
/* in order to detect and fix errors on the first byte
we have to use the serial interrupts as well. */
@@ -972,88 +1453,98 @@ e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r)
info->rs485.rts_after_sent = 0x01 & r->rts_after_sent;
info->rs485.delay_rts_before_send = r->delay_rts_before_send;
info->rs485.enabled = r->enabled;
-
+/* printk("rts: on send = %i, after = %i, enabled = %i",
+ info->rs485.rts_on_send,
+ info->rs485.rts_after_sent,
+ info->rs485.enabled
+ );
+*/
return 0;
}
static int
-e100_write_rs485(struct tty_struct *tty,struct rs485_write *r)
+e100_write_rs485(struct tty_struct *tty, int from_user,
+ const unsigned char *buf, int count)
{
- int total;
struct e100_serial * info = (struct e100_serial *)tty->driver_data;
+ int old_enabled = info->rs485.enabled;
- /* If we are in RS-485 mode, we need to toggle RTS and disable
- * the receiver before initiating a DMA transfer
+ /* rs485 is always implicitly enabled if we're using the ioctl()
+ * but it doesn't have to be set in the rs485_control
+ * (to be backward compatible with old apps)
+ * So we store, set and restore it.
*/
- e100_rts(info, info->rs485.rts_on_send);
-#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
- e100_disable_rx(info);
- e100_disable_rxdma_irq(info);
-#endif
-
- if (info->rs485.delay_rts_before_send > 0) {
- current->timeout = jiffies + (info->rs485.delay_rts_before_send * HZ)/1000;
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- current->timeout = 0;
- }
- total = rs_write(tty, 1, (*r).outc, (*r).outc_size);
-
- /* If we are in RS-485 mode the following things has to be done:
- * wait until DMA is ready
- * wait on transmit shift register
- * wait to toggle RTS
- * enable the receiver
- */
+ info->rs485.enabled = 1;
+ /* rs_write now deals with RS485 if enabled */
+ count = rs_write(tty, from_user, buf, count);
+ info->rs485.enabled = old_enabled;
+ return count;
+}
- /* Sleep until all sent */
- tty_wait_until_sent(tty, 0);
-#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
- /* Now sleep a little more so that shift register is empty */
- schedule_usleep(info->char_time_usec * 2);
-#else
- {
- unsigned int val;
- /* wait on transmit shift register */
- do{
- get_lsr_info(info, &val);
- }while (!(val & TIOCSER_TEMT));
- }
-#endif
+#ifdef CONFIG_ETRAX_FAST_TIMER
+/* Timer function to toggle RTS when using FAST_TIMER */
+static void rs485_toggle_rts_timer_function(unsigned long data)
+{
+ struct e100_serial *info = (struct e100_serial *)data;
+ fast_timers_rs485[info->line].function = NULL;
e100_rts(info, info->rs485.rts_after_sent);
-
#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
e100_enable_rx(info);
e100_enable_rxdma_irq(info);
#endif
-
- return total;
}
#endif
+#endif /* CONFIG_ETRAX_RS485 */
/*
* ------------------------------------------------------------
* rs_stop() and rs_start()
*
* This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
+ * They enable or disable transmitter using the XOFF registers, as necessary.
* ------------------------------------------------------------
*/
-/* FIXME - when are these used and what is the purpose ?
- * In rs_stop we probably just can block the transmit DMA ready irq
- * and in rs_start we re-enable it (and then the old one will come).
- */
-
static void
rs_stop(struct tty_struct *tty)
{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ if (info) {
+ unsigned long flags;
+ unsigned long xoff;
+
+ save_flags(flags); cli();
+ xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->tty));
+ xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop);
+ if (tty->termios->c_iflag & IXON ) {
+ xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
+ }
+
+ *((unsigned long *)&info->port[REG_XOFF]) = xoff;
+ restore_flags(flags);
+ }
}
static void
rs_start(struct tty_struct *tty)
{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ if (info) {
+ unsigned long flags;
+ unsigned long xoff;
+
+ save_flags(flags); cli();
+ xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty));
+ xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
+ if (tty->termios->c_iflag & IXON ) {
+ xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
+ }
+
+ *((unsigned long *)&info->port[REG_XOFF]) = xoff;
+
+ restore_flags(flags);
+ }
}
/*
@@ -1086,8 +1577,7 @@ rs_sched_event(struct e100_serial *info,
int event)
{
info->event |= 1 << event;
- queue_task(&info->tqueue, &tq_serial);
- mark_bh(SERIAL_BH);
+ schedule_work(&info->work);
}
/* The output DMA channel is free - use it to send as many chars as possible
@@ -1136,7 +1626,7 @@ transmit_chars(struct e100_serial *info)
#endif
if (!info->tr_running) {
/* weirdo... we shouldn't get here! */
- printk("Achtung: transmit_chars with !tr_running\n");
+ printk(KERN_WARNING "Achtung: transmit_chars with !tr_running\n");
return;
}
@@ -1173,26 +1663,16 @@ transmit_chars(struct e100_serial *info)
/* our job here is done, don't schedule any new DMA transfer */
info->tr_running = 0;
-#if defined(CONFIG_ETRAX_RS485)
- /* Check if we should toggle RTS now */
+#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_FAST_TIMER)
if (info->rs485.enabled) {
- /* Make sure fifo is empty */
- int in_fifo = 0;
-
- do {
- in_fifo = IO_EXTRACT(R_DMA_CH6_STATUS, avail,
- *info->ostatusadr);
- } while (in_fifo > 0);
- /* Any way to really check transmitter empty? (TEMT) */
- /* Control RTS to set to RX mode */
- e100_rts(info, info->rs485.rts_after_sent);
-#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
- e100_enable_rx(info);
- e100_enable_rxdma_irq(info);
-#endif
+ /* Set a short timer to toggle RTS */
+ start_one_shot_timer(&fast_timers_rs485[info->line],
+ rs485_toggle_rts_timer_function,
+ (unsigned long)info,
+ info->char_time_usec*2,
+ "RS-485");
}
#endif /* RS485 */
-
return;
}
@@ -1208,7 +1688,7 @@ transmit_chars(struct e100_serial *info)
*info->ocmdadr = 1; /* dma command start -> R_DMAx_CMD */
/* DMA is now running (hopefully) */
-}
+} /* transmit_chars */
static void
start_transmit(struct e100_serial *info)
@@ -1224,7 +1704,7 @@ start_transmit(struct e100_serial *info)
info->tr_running = 1;
transmit_chars(info);
-}
+} /* start_transmit */
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
static int serial_fast_timer_started = 0;
@@ -1254,49 +1734,91 @@ static void flush_timeout_function(unsigned long data);
#define START_FLUSH_FAST_TIMER(info, string)
#endif
+static struct etrax_recv_buffer *
+alloc_recv_buffer(unsigned int size)
+{
+ struct etrax_recv_buffer *buffer;
+
+ if (!(buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC)))
+ return NULL;
+
+ buffer->next = NULL;
+ buffer->length = 0;
+ buffer->error = TTY_NORMAL;
+
+ return buffer;
+}
+
+static void
+append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ if (!info->first_recv_buffer)
+ info->first_recv_buffer = buffer;
+ else
+ info->last_recv_buffer->next = buffer;
+
+ info->last_recv_buffer = buffer;
+
+ info->recv_cnt += buffer->length;
+ if (info->recv_cnt > info->max_recv_cnt)
+ info->max_recv_cnt = info->recv_cnt;
+
+ restore_flags(flags);
+}
+
static int
add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char flag)
{
- if (!CIRC_SPACE(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE))
+ struct etrax_recv_buffer *buffer;
+
+ if (!(buffer = alloc_recv_buffer(4)))
return 0;
- info->recv.buf[info->recv.head] = data;
- info->flag_buf[info->recv.head] = flag;
- info->recv.head = (info->recv.head + 1) & (SERIAL_RECV_SIZE - 1);
+ buffer->length = 1;
+ buffer->error = flag;
+ buffer->buffer[0] = data;
+
+ append_recv_buffer(info, buffer);
info->icount.rx++;
return 1;
}
-static _INLINE_ unsigned int
-copy_descr_data(struct e100_serial *info, unsigned int recvl, unsigned char *buf)
+extern _INLINE_ unsigned int
+handle_descr_data(struct e100_serial *info, struct etrax_dma_descr *descr, unsigned int recvl)
{
- unsigned int count = CIRC_SPACE_TO_END(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE);
- unsigned int length = 0;
+ struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer;
- while (length < recvl && count) {
- if (length + count > recvl)
- count = recvl - length;
+ if (info->recv_cnt + recvl > 65536) {
+ printk(KERN_CRIT
+ "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __FUNCTION__, recvl);
+ return 0;
+ }
- memcpy(info->recv.buf + info->recv.head, buf + length, count);
- memset(info->flag_buf + info->recv.head, '\0', count);
- info->recv.head = (info->recv.head + count) & (SERIAL_RECV_SIZE - 1);
- length += count;
+ buffer->length = recvl;
- count = CIRC_SPACE_TO_END(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE);
- }
+ if (info->errorcode == ERRCODE_SET_BREAK)
+ buffer->error = TTY_BREAK;
+ info->errorcode = 0;
- if (length != recvl) {
- printk(__FUNCTION__ ": Buffer overflow! %d byte(s) did not fit.\n", recvl - length);
- PROCSTAT(ser_stat[info->line].overrun_cnt += recvl - length);
- }
+ append_recv_buffer(info, buffer);
- return length;
+ if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
+ panic("%s: Failed to allocate memory for receive buffer!\n", __FUNCTION__);
+
+ descr->buf = virt_to_phys(buffer->buffer);
+
+ return recvl;
}
static _INLINE_ unsigned int
-copy_all_descr_data(struct e100_serial *info)
+handle_all_descr_data(struct e100_serial *info)
{
struct etrax_dma_descr *descr;
unsigned int recvl;
@@ -1330,7 +1852,7 @@ copy_all_descr_data(struct e100_serial *info)
/* update stats */
info->icount.rx += recvl;
- ret += copy_descr_data(info, recvl, phys_to_virt(descr->buf));
+ ret += handle_descr_data(info, descr, recvl);
}
return ret;
@@ -1341,7 +1863,6 @@ receive_chars(struct e100_serial *info)
{
struct tty_struct *tty;
unsigned char rstat;
- unsigned int old_head;
#ifdef CONFIG_SVINTO_SIM
/* No receive in the simulator. Will probably be when the rest of
@@ -1366,12 +1887,7 @@ receive_chars(struct e100_serial *info)
if (info->errorcode == ERRCODE_INSERT_BREAK)
add_char_and_flag(info, '\0', TTY_BREAK);
- old_head = info->recv.head;
-
- if (copy_all_descr_data(info) && info->errorcode == ERRCODE_SET_BREAK)
- info->flag_buf[old_head] = TTY_BREAK;
-
- info->errorcode = 0;
+ handle_all_descr_data(info);
/* Read the status register to detect errors */
rstat = info->port[REG_STATUS];
@@ -1394,10 +1910,6 @@ receive_chars(struct e100_serial *info)
add_char_and_flag(info, data, TTY_FRAME);
}
- if (!E100_RTS_GET(info) &&
- CIRC_SPACE(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE) < TTY_THROTTLE_LIMIT)
- info->tty->driver->throttle(info->tty);
-
START_FLUSH_FAST_TIMER(info, "receive_chars");
/* Restart the receiving DMA */
@@ -1408,19 +1920,20 @@ static _INLINE_ int
start_recv_dma(struct e100_serial *info)
{
struct etrax_dma_descr *descr = info->rec_descr;
- unsigned char *buf = info->recv.buf + 2*SERIAL_RECV_SIZE;
+ struct etrax_recv_buffer *buffer;
int i;
/* Set up the receiving descriptors */
for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
+ if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
+ panic("%s: Failed to allocate memory for receive buffer!\n", __FUNCTION__);
+
descr[i].ctrl = d_int;
- descr[i].buf = virt_to_phys(buf);
+ descr[i].buf = virt_to_phys(buffer->buffer);
descr[i].sw_len = SERIAL_DESCR_BUF_SIZE;
descr[i].hw_len = 0;
descr[i].status = 0;
descr[i].next = virt_to_phys(&descr[i+1]);
-
- buf += SERIAL_DESCR_BUF_SIZE;
}
/* Link the last descriptor to the first */
@@ -1448,7 +1961,7 @@ start_receive(struct e100_serial *info)
#endif
/* reset the input dma channel to be sure it works */
-
+
*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
@@ -1456,10 +1969,6 @@ start_receive(struct e100_serial *info)
info->tty->flip.count = 0;
start_recv_dma(info);
-
-#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- start_flush_timer();
-#endif
}
@@ -1480,13 +1989,14 @@ status_handle(struct e100_serial *info, unsigned short status)
DMA8(ser1) when they have finished a descriptor with the intr flag set.
*/
-static void
+static irqreturn_t
tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct e100_serial *info;
unsigned long ireg;
int i;
-
+ int handled = 0;
+
#ifdef CONFIG_SVINTO_SIM
/* No receive in the simulator. Will probably be when the rest of
* the serial interface works, and this piece will just be removed.
@@ -1495,7 +2005,7 @@ tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
const char *s = "What? tr_interrupt in simulator??\n";
SIMCOUT(s,strlen(s));
}
- return;
+ return IRQ_HANDLED;
#endif
/* find out the line that caused this irq and get it from rs_table */
@@ -1504,10 +2014,11 @@ tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i;
- if (!info->uses_dma)
+ if (!info->enabled || !info->uses_dma)
continue;
/* check for dma_descr (don't need to check for dma_eop in output dma for serial */
if (ireg & info->irq) {
+ handled = 1;
/* we can send a new dma bunch. make it so. */
DEBUG_LOG(info->line, "tr_interrupt %i\n", i);
/* Read jiffies_usec first,
@@ -1522,16 +2033,18 @@ tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* FIXME: here we should really check for a change in the
status lines and if so call status_handle(info) */
}
+ return IRQ_RETVAL(handled);
}
/* dma input channel interrupt handler */
-static void
+static irqreturn_t
rec_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct e100_serial *info;
unsigned long ireg;
int i;
+ int handled = 0;
#ifdef CONFIG_SVINTO_SIM
/* No receive in the simulator. Will probably be when the rest of
@@ -1550,10 +2063,11 @@ rec_interrupt(int irq, void *dev_id, struct pt_regs * regs)
for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i;
- if (!info->uses_dma)
+ if (!info->enabled || !info->uses_dma)
continue;
/* check for both dma_eop and dma_descr for the input dma channel */
if (ireg & ((info->irq << 2) | (info->irq << 3))) {
+ handled = 1;
/* we have received something */
receive_chars(info);
}
@@ -1561,6 +2075,7 @@ rec_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* FIXME: here we should really check for a change in the
status lines and if so call status_handle(info) */
}
+ return IRQ_RETVAL(handled);
}
static _INLINE_ int
@@ -1611,48 +2126,56 @@ force_eop_if_needed(struct e100_serial *info)
static _INLINE_ void
flush_to_flip_buffer(struct e100_serial *info)
{
- struct tty_struct *tty = info->tty;
- unsigned int count = CIRC_CNT_TO_END(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE);
+ struct tty_struct *tty;
+ struct etrax_recv_buffer *buffer;
unsigned int length;
unsigned long flags;
- if (!count)
+ if (!info->first_recv_buffer)
return;
save_flags(flags);
cli();
+ if (!(tty = info->tty)) {
+ restore_flags(flags);
+ return;
+ }
+
length = tty->flip.count;
-
- do {
+
+ while ((buffer = info->first_recv_buffer) && length < TTY_FLIPBUF_SIZE) {
+ unsigned int count = buffer->length;
+
if (length + count > TTY_FLIPBUF_SIZE)
count = TTY_FLIPBUF_SIZE - length;
- memcpy(tty->flip.char_buf_ptr + length, info->recv.buf + info->recv.tail, count);
- memcpy(tty->flip.flag_buf_ptr + length, info->flag_buf + info->recv.tail, count);
- info->recv.tail = ((info->recv.tail + count) & (SERIAL_RECV_SIZE-1));
+ memcpy(tty->flip.char_buf_ptr + length, buffer->buffer, count);
+ memset(tty->flip.flag_buf_ptr + length, TTY_NORMAL, count);
+ tty->flip.flag_buf_ptr[length] = buffer->error;
+
length += count;
-
- count = CIRC_CNT_TO_END(info->recv.head,
- info->recv.tail,
- SERIAL_RECV_SIZE);
- } while (length < TTY_FLIPBUF_SIZE && count);
+ info->recv_cnt -= count;
+
+ if (count == buffer->length) {
+ info->first_recv_buffer = buffer->next;
+ kfree(buffer);
+ } else {
+ buffer->length -= count;
+ memmove(buffer->buffer, buffer->buffer + count, buffer->length);
+ buffer->error = TTY_NORMAL;
+ }
+ }
+
+ if (!info->first_recv_buffer)
+ info->last_recv_buffer = NULL;
tty->flip.count = length;
restore_flags(flags);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,66)
/* this includes a check for low-latency */
tty_flip_buffer_push(tty);
-#else
- queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
-#endif
-
- /* unthrottle if we have throttled */
- if (E100_RTS_GET(info) &&
- CIRC_SPACE(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE) > TTY_THROTTLE_LIMIT)
- tty->driver->unthrottle(info->tty);
}
static _INLINE_ void
@@ -1662,7 +2185,7 @@ check_flush_timeout(struct e100_serial *info)
flush_to_flip_buffer(info);
- if (CIRC_CNT(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE))
+ if (info->first_recv_buffer)
START_FLUSH_FAST_TIMER(info, "flip");
}
@@ -1678,43 +2201,11 @@ static void flush_timeout_function(unsigned long data)
check_flush_timeout(info);
}
-#elif defined(CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST)
-
-static void
-timeout_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct e100_serial *info;
- int i;
-
-#ifdef CONFIG_SVINTO_SIM
- /* No receive in the simulator. Will probably be when the rest of
- * the serial interface works, and this piece will just be removed.
- */
- {
- const char *s = "What? timeout_interrupt in simulator??\n";
- SIMCOUT(s,strlen(s));
- }
- return;
-#endif
-
- /* acknowledge the timer1 irq */
- *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);
- PROCSTAT(fast_timer_ints++);
-
- for (i = 0; i < NR_PORTS; i++) {
- info = rs_table + i;
- if (info->uses_dma)
- check_flush_timeout(info);
- }
-} /* timeout_interrupt */
-
#else
/* dma fifo/buffer timeout handler
forces an end-of-packet for the dma input channel if no chars
have been received for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS/100 s.
- If CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is configured then this
- handler is instead run at 15360 Hz.
*/
static struct timer_list flush_timer;
@@ -1810,7 +2301,7 @@ TODO: The break will be delayed until an F or V character is received.
*/
-static void _INLINE_ handle_ser_interrupt(struct e100_serial *info)
+extern irqreturn_t _INLINE_ handle_ser_interrupt(struct e100_serial *info)
{
unsigned char rstat = info->port[REG_STATUS];
@@ -1869,7 +2360,7 @@ static void _INLINE_ handle_ser_interrupt(struct e100_serial *info)
}
info->break_detected_cnt = 0;
DEBUG_LOG(info->line, "#iERR s d %04X\n",
- ((rstat & SER_ERROR_MASK) << 8) | data);
+ ((rstat & SER_ERROR_MASK) << 8) | data);
}
PROCSTAT(ser_stat[info->line].early_errors_cnt++);
} else { /* It was a valid byte, now let the DMA do the rest */
@@ -1883,8 +2374,8 @@ static void _INLINE_ handle_ser_interrupt(struct e100_serial *info)
* previous interrupt we should discard it.
*/
long elapsed_usec =
- (curr_time - info->last_rx_active) * (1000000/HZ) +
- curr_time_u - info->last_rx_active_usec;
+ (curr_time - info->last_rx_active) * (1000000/HZ) +
+ curr_time_u - info->last_rx_active_usec;
if (elapsed_usec < 2*info->char_time_usec) {
DEBUG_LOG(info->line, "FBRK %i\n", info->line);
/* Report as BREAK (error) and let
@@ -1911,25 +2402,29 @@ static void _INLINE_ handle_ser_interrupt(struct e100_serial *info)
/* Restarting the DMA never hurts */
*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
START_FLUSH_FAST_TIMER(info, "ser_int");
+ return IRQ_HANDLED;
} /* handle_ser_interrupt */
-static void
+static irqreturn_t
ser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct e100_serial *info;
int i;
+ int handled = 0;
for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i;
- if (!info->uses_dma)
+ if (!info->enabled || !info->uses_dma)
continue;
/* Which line caused the irq? */
if (*R_IRQ_MASK1_RD & (1U << (8+2*info->line))) {
+ handled = 1;
handle_ser_interrupt(info);
}
}
+ return IRQ_RETVAL(handled);
} /* ser_interrupt */
#endif
@@ -1949,12 +2444,6 @@ ser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* them using rs_sched_event(), and they get done here.
*/
static void
-do_serial_bh(void)
-{
- run_task_queue(&tq_serial);
-}
-
-static void
do_softint(void *private_)
{
struct e100_serial *info = (struct e100_serial *) private_;
@@ -1972,53 +2461,25 @@ do_softint(void *private_)
}
}
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred. The path of
- * hangup processing is:
- *
- * serial interrupt routine -> (scheduler tqueue) ->
- * do_serial_hangup() -> tty->hangup() -> rs_hangup()
- *
- */
-static void
-do_serial_hangup(void *private_)
-{
- struct e100_serial *info = (struct e100_serial *) private_;
- struct tty_struct *tty;
-
- tty = info->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
-}
-
static int
startup(struct e100_serial * info)
{
unsigned long flags;
unsigned long xmit_page;
- unsigned char *recv_page;
+ int i;
xmit_page = get_zeroed_page(GFP_KERNEL);
if (!xmit_page)
return -ENOMEM;
- recv_page = kmalloc(2 * SERIAL_RECV_SIZE + SERIAL_RECV_DESCRIPTORS * SERIAL_DESCR_BUF_SIZE, GFP_KERNEL);
- if (!recv_page) {
- free_page(xmit_page);
- return -ENOMEM;
- }
-
- save_flags(flags); cli();
+ save_flags(flags);
+ cli();
/* if it was already initialized, skip this */
if (info->flags & ASYNC_INITIALIZED) {
restore_flags(flags);
free_page(xmit_page);
- kfree(recv_page);
return 0;
}
@@ -2027,13 +2488,6 @@ startup(struct e100_serial * info)
else
info->xmit.buf = (unsigned char *) xmit_page;
- if (info->recv.buf)
- kfree(recv_page);
- else {
- info->recv.buf = (unsigned char *) recv_page;
- info->flag_buf = info->recv.buf + SERIAL_RECV_SIZE;
- }
-
#ifdef SERIAL_DEBUG_OPEN
printk("starting up ttyS%d (xmit_buf 0x%p, recv_buf 0x%p)...\n", info->line, info->xmit.buf, info->recv.buf);
#endif
@@ -2044,8 +2498,13 @@ startup(struct e100_serial * info)
right? */
if (info->tty)
clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
info->xmit.head = info->xmit.tail = 0;
- info->recv.head = info->recv.tail = 0;
+ info->first_recv_buffer = info->last_recv_buffer = NULL;
+ info->recv_cnt = info->max_recv_cnt = 0;
+
+ for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
+ info->rec_descr[i].buf = NULL;
/* No real action in the simulator, but may set info important
to ioctl. */
@@ -2084,8 +2543,12 @@ startup(struct e100_serial * info)
clear_bit(TTY_IO_ERROR, &info->tty->flags);
info->xmit.head = info->xmit.tail = 0;
- info->recv.head = info->recv.tail = 0;
+ info->first_recv_buffer = info->last_recv_buffer = NULL;
+ info->recv_cnt = info->max_recv_cnt = 0;
+ for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
+ info->rec_descr[i].buf = 0;
+
/*
* and set the speed and other flags of the serial port
* this will start the rx/tx as well
@@ -2137,6 +2600,9 @@ static void
shutdown(struct e100_serial * info)
{
unsigned long flags;
+ struct etrax_dma_descr *descr = info->rec_descr;
+ struct etrax_recv_buffer *buffer;
+ int i;
#ifndef CONFIG_SVINTO_SIM
/* shut down the transmitter and receiver */
@@ -2173,11 +2639,12 @@ shutdown(struct e100_serial * info)
info->xmit.buf = NULL;
}
- if (info->recv.buf) {
- kfree(info->recv.buf);
- info->recv.buf = NULL;
- info->flag_buf = NULL;
- }
+ for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
+ if (descr[i].buf) {
+ buffer = phys_to_virt(descr[i].buf) - sizeof *buffer;
+ kfree(buffer);
+ descr[i].buf = 0;
+ }
if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
/* hang up DTR and RTS if HUPCL is enabled */
@@ -2199,6 +2666,7 @@ static void
change_speed(struct e100_serial *info)
{
unsigned int cflag;
+ unsigned long xoff;
/* first some safety checks */
@@ -2248,10 +2716,21 @@ change_speed(struct e100_serial *info)
info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
}
- if (cflag & PARODD) {
- /* set odd parity */
- info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
- info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
+ if (cflag & CMSPAR) {
+ /* enable stick parity */
+ info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, stick);
+ info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, stick);
+ if (!(cflag & PARODD)) {
+ /* set mark parity */
+ info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
+ info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
+ }
+ } else {
+ if (cflag & PARODD) {
+ /* set odd parity */
+ info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
+ info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
+ }
}
if (cflag & CRTSCTS) {
@@ -2268,7 +2747,13 @@ change_speed(struct e100_serial *info)
info->port[REG_TR_CTRL] = info->tx_ctrl;
info->port[REG_REC_CTRL] = info->rx_ctrl;
- *((unsigned long *)&info->port[REG_XOFF]) = 0;
+ xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->tty));
+ xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable);
+ if (info->tty->termios->c_iflag & IXON ) {
+ xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable);
+ }
+
+ *((unsigned long *)&info->port[REG_XOFF]) = xoff;
#endif /* !CONFIG_SVINTO_SIM */
update_char_time(info);
@@ -2301,9 +2786,9 @@ rs_flush_chars(struct tty_struct *tty)
restore_flags(flags);
}
-static int
-rs_write(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count)
+extern inline int
+raw_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count)
{
int c, ret = 0;
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
@@ -2316,7 +2801,7 @@ rs_write(struct tty_struct * tty, int from_user,
#ifdef SERIAL_DEBUG_DATA
if (info->line == SERIAL_DEBUG_LINE)
- printk("rs_write (%d), status %d\n",
+ printk("raw_write (%d), status %d\n",
count, info->port[REG_STATUS]);
#endif
@@ -2402,7 +2887,74 @@ rs_write(struct tty_struct * tty, int from_user,
}
return ret;
-}
+} /* raw_write() */
+
+static int
+rs_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count)
+{
+#if defined(CONFIG_ETRAX_RS485)
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+
+ if (info->rs485.enabled)
+ {
+ /* If we are in RS-485 mode, we need to toggle RTS and disable
+ * the receiver before initiating a DMA transfer
+ */
+#ifdef CONFIG_ETRAX_FAST_TIMER
+ /* Abort any started timer */
+ fast_timers_rs485[info->line].function = NULL;
+ del_fast_timer(&fast_timers_rs485[info->line]);
+#endif
+ e100_rts(info, info->rs485.rts_on_send);
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
+ e100_disable_rx(info);
+ e100_disable_rxdma_irq(info);
+#endif
+
+ if (info->rs485.delay_rts_before_send > 0) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout((info->rs485.delay_rts_before_send * HZ)/1000);
+ }
+ }
+#endif /* CONFIG_ETRAX_RS485 */
+
+ count = raw_write(tty, from_user, buf, count);
+
+#if defined(CONFIG_ETRAX_RS485)
+ if (info->rs485.enabled)
+ {
+ unsigned int val;
+ /* If we are in RS-485 mode the following has to be done:
+ * wait until DMA is ready
+ * wait on transmit shift register
+ * toggle RTS
+ * enable the receiver
+ */
+
+ /* Sleep until all sent */
+ tty_wait_until_sent(tty, 0);
+#ifdef CONFIG_ETRAX_FAST_TIMER
+ /* Now sleep a little more so that shift register is empty */
+ schedule_usleep(info->char_time_usec * 2);
+#endif
+ /* wait on transmit shift register */
+ do{
+ get_lsr_info(info, &val);
+ }while (!(val & TIOCSER_TEMT));
+
+ e100_rts(info, info->rs485.rts_after_sent);
+
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
+ e100_enable_rx(info);
+ e100_enable_rxdma_irq(info);
+#endif
+ }
+#endif /* CONFIG_ETRAX_RS485 */
+
+ return count;
+} /* rs_write */
+
/* how much space is available in the xmit buffer? */
@@ -2451,20 +3003,23 @@ rs_flush_buffer(struct tty_struct *tty)
* This function is used to send a high-priority XON/XOFF character to
* the device
*
- * Since we don't bother to check for info->x_char in transmit_chars yet,
- * we don't really implement this function yet.
+ * Since we use DMA we don't check for info->x_char in transmit_chars,
+ * just disable DMA channel and write the character when possible.
*/
static void rs_send_xchar(struct tty_struct *tty, char ch)
{
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
- printk("serial.c:rs_send_xchar not implemented!\n");
+ e100_disable_txdma_channel(info);
- info->x_char = ch;
- if (ch) {
- /* Make sure transmit interrupts are on */
- /* TODO. */
- }
+ /* Wait for tr_ready */
+ while (!(info->port[REG_STATUS] & IO_MASK(R_SERIAL0_STATUS, tr_ready)))
+ /* wait */;
+
+ /* Write the XON/XOFF char */
+ info->port[REG_TR_DATA] = ch;
+
+ e100_enable_txdma_channel(info);
}
/*
@@ -2482,20 +3037,22 @@ rs_throttle(struct tty_struct * tty)
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
-
+
printk("throttle %s: %d....\n", _tty_name(tty, buf),
tty->ldisc.chars_in_buffer(tty));
#endif
-
+
+ /* Do RTS before XOFF since XOFF might take some time */
+ if (tty->termios->c_cflag & CRTSCTS) {
+ /* Turn off RTS line (do this atomic) */
+ save_flags(flags);
+ cli();
+ e100_rts(info, 0);
+ restore_flags(flags);
+ }
if (I_IXOFF(tty))
- info->x_char = STOP_CHAR(tty);
-
- /* Turn off RTS line (do this atomic) should here be an else ?? */
-
- save_flags(flags);
- cli();
- e100_rts(info, 0);
- restore_flags(flags);
+ rs_send_xchar(tty, STOP_CHAR(tty));
+
}
static void
@@ -2505,24 +3062,27 @@ rs_unthrottle(struct tty_struct * tty)
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
-
+
printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
tty->ldisc.chars_in_buffer(tty));
#endif
-
+
+ /* Do RTS before XOFF since XOFF might take some time */
+ if (tty->termios->c_cflag & CRTSCTS) {
+ /* Assert RTS line (do this atomic) */
+ save_flags(flags);
+ cli();
+ e100_rts(info, 1);
+ restore_flags(flags);
+ }
+
if (I_IXOFF(tty)) {
if (info->x_char)
info->x_char = 0;
else
- info->x_char = START_CHAR(tty);
+ rs_send_xchar(tty, START_CHAR(tty));
}
-
- /* Assert RTS line (do this atomic) */
-
- save_flags(flags);
- cli();
- e100_rts(info, 1);
- restore_flags(flags);
+
}
/*
@@ -2594,9 +3154,7 @@ set_serial_info(struct e100_serial *info,
info->type = new_serial.type;
info->close_delay = new_serial.close_delay;
info->closing_wait = new_serial.closing_wait;
-#if (LINUX_VERSION_CODE > 0x20100)
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-#endif
check_and_exit:
if (info->flags & ASYNC_INITIALIZED) {
@@ -2641,8 +3199,8 @@ get_lsr_info(struct e100_serial * info, unsigned int *value)
#ifdef SERIAL_DEBUG_IO
struct state_str
{
- int state;
- const char *str;
+ int state;
+ const char *str;
};
const struct state_str control_state_str[] = {
@@ -2690,14 +3248,15 @@ get_modem_info(struct e100_serial * info, unsigned int *value)
E100_DSR_GET(info),
E100_CTS_GET(info));
#endif
+
result =
(!E100_RTS_GET(info) ? TIOCM_RTS : 0)
| (!E100_DTR_GET(info) ? TIOCM_DTR : 0)
- | (!E100_CD_GET(info) ? TIOCM_CAR : 0)
| (!E100_RI_GET(info) ? TIOCM_RNG : 0)
| (!E100_DSR_GET(info) ? TIOCM_DSR : 0)
+ | (!E100_CD_GET(info) ? TIOCM_CAR : 0)
| (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
-
+
#ifdef SERIAL_DEBUG_IO
printk("e100ser: modem state: %i 0x%08X\n", result, result);
{
@@ -2766,44 +3325,7 @@ set_modem_info(struct e100_serial * info, unsigned int cmd,
return 0;
}
-/*
- * This routine sends a break character out the serial port.
- */
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-static void
-send_break(struct e100_serial * info, int duration)
-{
- unsigned long flags;
-
- if (!info->port)
- return;
-
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + duration;
-
- save_flags(flags);
- cli();
-
- /* Go to manual mode and set the txd pin to 0 */
-
- info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */
- info->port[REG_TR_CTRL] = info->tx_ctrl;
-
- /* wait for "duration" jiffies */
-
- schedule();
-
- info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */
- info->port[REG_TR_CTRL] = info->tx_ctrl;
-
- /* the DMA gets awfully confused if we toggle the transceiver like this
- * so we need to reset it
- */
- *info->ocmdadr = 4;
- restore_flags(flags);
-}
-#else
static void
rs_break(struct tty_struct *tty, int break_state)
{
@@ -2824,19 +3346,12 @@ rs_break(struct tty_struct *tty, int break_state)
info->port[REG_TR_CTRL] = info->tx_ctrl;
restore_flags(flags);
}
-#endif
static int
rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct e100_serial * info = (struct e100_serial *)tty->driver_data;
-#if defined(CONFIG_ETRAX_RS485) || (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
- int error;
-#endif
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
- int retval;
-#endif
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
@@ -2846,45 +3361,6 @@ rs_ioctl(struct tty_struct *tty, struct file * file,
}
switch (cmd) {
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (signal_pending(current))
- return -EINTR;
- if (!arg) {
- send_break(info, HZ/4); /* 1/4 second */
- if (signal_pending(current))
- return -EINTR;
- }
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (signal_pending(current))
- return -EINTR;
- send_break(info, arg ? arg*(HZ/10) : HZ/4);
- if (signal_pending(current))
- return -EINTR;
- return 0;
- case TIOCGSOFTCAR:
- error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
- if (error)
- return error;
- put_fs_long(C_CLOCAL(tty) ? 1 : 0,
- (unsigned long *) arg);
- return 0;
- case TIOCSSOFTCAR:
- arg = get_fs_long((unsigned long *) arg);
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- return 0;
-#endif
case TIOCMGET:
return get_modem_info(info, (unsigned int *) arg);
case TIOCMBIS:
@@ -2908,22 +3384,22 @@ rs_ioctl(struct tty_struct *tty, struct file * file,
#if defined(CONFIG_ETRAX_RS485)
case TIOCSERSETRS485:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct rs485_control));
-
- if (error)
- return error;
-
- return e100_enable_rs485(tty, (struct rs485_control *) arg);
+ {
+ struct rs485_control rs485ctrl;
+ if (copy_from_user(&rs485ctrl, (struct rs485_control*)arg, sizeof(rs485ctrl)))
+ return -EFAULT;
+
+ return e100_enable_rs485(tty, &rs485ctrl);
+ }
case TIOCSERWRRS485:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct rs485_write));
-
- if (error)
- return error;
-
- return e100_write_rs485(tty, (struct rs485_write *) arg);
+ {
+ struct rs485_write rs485wr;
+ if (copy_from_user(&rs485wr, (struct rs485_write*)arg, sizeof(rs485wr)))
+ return -EFAULT;
+
+ return e100_write_rs485(tty, 1, rs485wr.outc, rs485wr.outc_size);
+ }
#endif
default:
@@ -2991,12 +3467,13 @@ rs_close(struct tty_struct *tty, struct file * filp)
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
- printk("rs_close: bad serial port count; tty->count is 1, "
+ printk(KERN_CRIT
+ "rs_close: bad serial port count; tty->count is 1, "
"info->count is %d\n", info->count);
info->count = 1;
}
if (--info->count < 0) {
- printk("rs_close: bad serial port count for ttyS%d: %d\n",
+ printk(KERN_CRIT "rs_close: bad serial port count for ttyS%d: %d\n",
info->line, info->count);
info->count = 0;
}
@@ -3149,7 +3626,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
return -EAGAIN;
#endif
}
-
+
/*
* If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit.
@@ -3162,7 +3639,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
if (tty->termios->c_cflag & CLOCAL)
do_clocal = 1;
-
+
/*
* Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
@@ -3187,7 +3664,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
while (1) {
save_flags(flags);
cli();
- /* assert RTS and DTR */
+ /* assert RTS and DTR */
e100_rts(info, 1);
e100_dtr(info, 1);
restore_flags(flags);
@@ -3204,7 +3681,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
#endif
break;
}
- if (!(info->flags & ASYNC_CLOSING) && do_clocal)
+ if (!(info->flags & ASYNC_CLOSING) && do_clocal)
/* && (do_clocal || DCD_IS_ASSERTED) */
break;
if (signal_pending(current)) {
@@ -3258,17 +3735,15 @@ rs_open(struct tty_struct *tty, struct file * filp)
return -ENODEV;
#ifdef SERIAL_DEBUG_OPEN
- printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name,
- info->count);
+ printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name,
+ info->count);
#endif
info->count++;
tty->driver_data = info;
info->tty = tty;
-#if (LINUX_VERSION_CODE > 0x20100)
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-#endif
if (!tmp_buf) {
page = get_zeroed_page(GFP_KERNEL);
@@ -3312,7 +3787,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
#endif
return retval;
}
-
+
#ifdef SERIAL_DEBUG_OPEN
printk("rs_open ttyS%d successful...\n", info->line);
#endif
@@ -3323,7 +3798,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
* /proc fs routines....
*/
-static inline int line_info(char *buf, struct e100_serial *info)
+extern inline int line_info(char *buf, struct e100_serial *info)
{
char stat_buf[30];
int ret;
@@ -3338,17 +3813,17 @@ static inline int line_info(char *buf, struct e100_serial *info)
stat_buf[0] = 0;
stat_buf[1] = 0;
- if (E100_RTS_GET(info))
+ if (!E100_RTS_GET(info))
strcat(stat_buf, "|RTS");
- if (E100_CTS_GET(info))
+ if (!E100_CTS_GET(info))
strcat(stat_buf, "|CTS");
- if (E100_DTR_GET(info))
+ if (!E100_DTR_GET(info))
strcat(stat_buf, "|DTR");
- if (E100_DSR_GET(info))
+ if (!E100_DSR_GET(info))
strcat(stat_buf, "|DSR");
- if (E100_CD_GET(info))
+ if (!E100_CD_GET(info))
strcat(stat_buf, "|CD");
- if (E100_RI_GET(info))
+ if (!E100_RI_GET(info))
strcat(stat_buf, "|RI");
ret += sprintf(buf+ret, " baud:%d", info->baud);
@@ -3357,6 +3832,10 @@ static inline int line_info(char *buf, struct e100_serial *info)
(unsigned long)info->icount.tx,
(unsigned long)info->icount.rx);
+ ret += sprintf(buf+ret, " rx_pend:%lu/%lu",
+ (unsigned long)info->recv_cnt,
+ (unsigned long)info->max_recv_cnt);
+
if (info->icount.frame)
ret += sprintf(buf+ret, " fe:%lu",
(unsigned long)info->icount.frame);
@@ -3413,12 +3892,13 @@ done:
static void
show_serial_version(void)
{
- printk("ETRAX 100LX serial-driver %s, (c) 2000 Axis Communications AB\r\n",
- serial_version);
+ printk(KERN_INFO
+ "ETRAX 100LX serial-driver %s, (c) 2000-2003 Axis Communications AB\r\n",
+ &serial_version[11]); /* "$Revision: x.yy" */
}
/* rs_init inits the driver at boot (using the module_init chain) */
-
+
static struct tty_operations rs_ops = {
.open = rs_open,
.close = rs_close,
@@ -3428,8 +3908,8 @@ static struct tty_operations rs_ops = {
.chars_in_buffer = rs_chars_in_buffer,
.flush_buffer = rs_flush_buffer,
.ioctl = rs_ioctl,
- .throttle = rs_throttle,
- .unthrottle = rs_unthrottle,
+ .throttle = rs_throttle,
+ .unthrottle = rs_unthrottle,
.set_termios = rs_set_termios,
.stop = rs_stop,
.start = rs_start,
@@ -3451,12 +3931,10 @@ rs_init(void)
return -ENOMEM;
show_serial_version();
-
- init_bh(SERIAL_BH, do_serial_bh);
/* Setup the timed flush handler system */
-#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) && !defined(CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST)
+#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER)
init_timer(&flush_timer);
flush_timer.function = timed_flush_handler;
mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
@@ -3477,7 +3955,7 @@ rs_init(void)
tty_set_operations(driver, &rs_ops);
if (tty_register_driver(driver))
panic("Couldn't register serial driver\n");
- serial_driver = driver;
+ serial_driver = driver;
/* do some initializing for the separate ports */
@@ -3495,15 +3973,12 @@ rs_init(void)
info->event = 0;
info->count = 0;
info->blocked_open = 0;
- info->tqueue.routine = do_softint;
- info->tqueue.data = info;
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
info->xmit.buf = NULL;
info->xmit.tail = info->xmit.head = 0;
- info->recv.buf = NULL;
- info->recv.tail = info->recv.head = 0;
- info->flag_buf = NULL;
+ info->first_recv_buffer = info->last_recv_buffer = NULL;
+ info->recv_cnt = info->max_recv_cnt = 0;
info->last_tx_active_usec = 0;
info->last_tx_active = 0;
@@ -3514,12 +3989,22 @@ rs_init(void)
info->rs485.delay_rts_before_send = 0;
info->rs485.enabled = 0;
#endif
+ INIT_WORK(&info->work, do_softint, info);
if (info->enabled) {
printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
serial_driver->name, info->line, (unsigned int)info->port);
}
}
+#ifdef CONFIG_ETRAX_FAST_TIMER
+#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
+ memset(fast_timers, 0, sizeof(fast_timers));
+#endif
+#ifdef CONFIG_ETRAX_RS485
+ memset(fast_timers_rs485, 0, sizeof(fast_timers_rs485));
+#endif
+ fast_timer_init();
+#endif
#ifndef CONFIG_SVINTO_SIM
/* Not needed in simulator. May only complicate stuff. */
@@ -3531,7 +4016,7 @@ rs_init(void)
panic("irq23");
#endif
#ifdef SERIAL_HANDLE_EARLY_ERRORS
- if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_INTERRUPT, "serial ", NULL))
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial ", NULL))
panic("irq8");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT1
@@ -3555,12 +4040,6 @@ rs_init(void)
panic("irq21");
#endif
-#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ | SA_INTERRUPT,
- "fast serial dma timeout", NULL)) {
- printk("err: timer1 irq\n");
- }
-#endif
#endif /* CONFIG_SVINTO_SIM */
return 0;
diff --git a/arch/cris/drivers/serial.h b/arch/cris/arch-v10/drivers/serial.h
index 1994228fa102..45813c657aaf 100644
--- a/arch/cris/drivers/serial.h
+++ b/arch/cris/arch-v10/drivers/serial.h
@@ -25,6 +25,15 @@
#define SERIAL_RECV_DESCRIPTORS 8
+struct etrax_recv_buffer {
+ struct etrax_recv_buffer *next;
+ unsigned short length;
+ unsigned char error;
+ unsigned char pad;
+
+ unsigned char buffer[0];
+};
+
struct e100_serial {
int baud;
volatile u8 *port; /* R_SERIALx_CTRL */
@@ -79,10 +88,12 @@ struct e100_serial {
int count; /* # of fd on device */
int blocked_open; /* # of blocked opens */
struct circ_buf xmit;
- struct circ_buf recv;
- unsigned char *flag_buf;
+ struct etrax_recv_buffer *first_recv_buffer;
+ struct etrax_recv_buffer *last_recv_buffer;
+ unsigned int recv_cnt;
+ unsigned int max_recv_cnt;
- struct tq_struct tqueue;
+ struct work_struct work;
struct async_icount icount; /* error-statistics etc.*/
#ifdef DECLARE_WAITQUEUE
wait_queue_head_t open_wait;
@@ -101,7 +112,7 @@ struct e100_serial {
int break_detected_cnt;
int errorcode;
-#ifdef CONFIG_RS485
+#ifdef CONFIG_ETRAX_RS485
struct rs485_control rs485; /* RS-485 support */
#endif
};
diff --git a/arch/cris/arch-v10/kernel/Makefile b/arch/cris/arch-v10/kernel/Makefile
new file mode 100644
index 000000000000..20a56080a8f0
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/Makefile
@@ -0,0 +1,16 @@
+# $Id: Makefile,v 1.4 2003/07/04 12:57:13 tobiasa Exp $
+#
+# Makefile for the linux kernel.
+#
+
+extra-y := head.o
+
+
+obj-y := entry.o traps.o shadows.o debugport.o irq.o \
+ process.o setup.o signal.o traps.o time.o ptrace.o
+
+obj-$(CONFIG_ETRAX_KGDB) += kgdb.o
+obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o
+
+clean:
+
diff --git a/arch/cris/arch-v10/kernel/asm-offsets.c b/arch/cris/arch-v10/kernel/asm-offsets.c
new file mode 100644
index 000000000000..1aa3cc4e7107
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/asm-offsets.c
@@ -0,0 +1,47 @@
+#include <linux/sched.h>
+#include <asm/thread_info.h>
+
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ */
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+#define ENTRY(entry) DEFINE(PT_ ## entry, offsetof(struct pt_regs, entry))
+ ENTRY(orig_r10);
+ ENTRY(r13);
+ ENTRY(r12);
+ ENTRY(r11);
+ ENTRY(r10);
+ ENTRY(r9);
+ ENTRY(mof);
+ ENTRY(dccr);
+ ENTRY(srp);
+ BLANK();
+#undef ENTRY
+#define ENTRY(entry) DEFINE(TI_ ## entry, offsetof(struct thread_info, entry))
+ ENTRY(task);
+ ENTRY(flags);
+ ENTRY(preempt_count);
+ BLANK();
+#undef ENTRY
+#define ENTRY(entry) DEFINE(THREAD_ ## entry, offsetof(struct thread_struct, entry))
+ ENTRY(ksp);
+ ENTRY(usp);
+ ENTRY(dccr);
+ BLANK();
+#undef ENTRY
+#define ENTRY(entry) DEFINE(TASK_ ## entry, offsetof(struct task_struct, entry))
+ ENTRY(pid);
+ BLANK();
+ DEFINE(LCLONE_VM, CLONE_VM);
+ DEFINE(LCLONE_UNTRACED, CLONE_UNTRACED);
+ return 0;
+}
diff --git a/arch/cris/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c
index fa20b2146adf..012c3028e5f6 100644
--- a/arch/cris/kernel/debugport.c
+++ b/arch/cris/arch-v10/kernel/debugport.c
@@ -12,6 +12,33 @@
* init_etrax_debug()
*
* $Log: debugport.c,v $
+ * Revision 1.11 2003/07/07 09:53:36 starvik
+ * Revert all the 2.5.74 merge changes to make the console work again
+ *
+ * Revision 1.9 2003/02/17 17:07:23 starvik
+ * Solved the problem with corrupted debug output (from Linux 2.4)
+ * * Wait until DMA, FIFO and pipe is empty before and after transmissions
+ * * Buffer data until a FIFO flush can be triggered.
+ *
+ * Revision 1.8 2003/01/22 06:48:36 starvik
+ * Fixed warnings issued by GCC 3.2.1
+ *
+ * Revision 1.7 2002/12/12 08:26:32 starvik
+ * Don't use C-comments inside CVS comments
+ *
+ * Revision 1.6 2002/12/11 15:42:02 starvik
+ * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/
+ *
+ * Revision 1.5 2002/11/20 06:58:03 starvik
+ * Compiles with kgdb
+ *
+ * Revision 1.4 2002/11/19 14:35:24 starvik
+ * Changes from linux 2.4
+ * Changed struct initializer syntax to the currently prefered notation
+ *
+ * Revision 1.3 2002/11/06 09:47:03 starvik
+ * Modified for new interrupt macros
+ *
* Revision 1.2 2002/01/21 15:21:50 bjornw
* Update for kdev_t changes
*
@@ -31,9 +58,10 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/major.h>
+#include <linux/delay.h>
#include <asm/system.h>
-#include <asm/svinto.h>
+#include <asm/arch/svinto.h>
#include <asm/io.h> /* Get SIMCOUT. */
/* Which serial-port is our debug port ? */
@@ -94,6 +122,8 @@
#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma4_descr, clr)
#endif
+#define MIN_SIZE 32 /* Size that triggers the FIFO to flush characters to interface */
+
/* Write a string of count length to the console (debug port) using DMA, polled
* for completion. Interrupts are disabled during the whole process. Some
* caution needs to be taken to not interfere with ttyS business on this port.
@@ -102,9 +132,13 @@
static void
console_write(struct console *co, const char *buf, unsigned int len)
{
+
static struct etrax_dma_descr descr;
+ static struct etrax_dma_descr descr2;
+ static char tmp_buf[MIN_SIZE];
+ static int tmp_size = 0;
+
unsigned long flags;
- int in_progress;
#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
/* no debug printout at all */
@@ -117,16 +151,48 @@ console_write(struct console *co, const char *buf, unsigned int len)
return;
#endif
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
#ifdef CONFIG_ETRAX_KGDB
/* kgdb needs to output debug info using the gdb protocol */
putDebugString(buf, len);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
#endif
+ /* To make this work together with the real serial port driver
+ * we have to make sure that everything is flushed when we leave
+ * here. The following steps are made to assure this:
+ * 1. Wait until DMA stops, FIFO is empty and serial port pipeline empty.
+ * 2. Write at least half the FIFO to trigger flush to serial port.
+ * 3. Wait until DMA stops, FIFO is empty and serial port pipeline empty.
+ */
+
+ /* Do we have enough characters to make the DMA/FIFO happy? */
+ if (tmp_size + len < MIN_SIZE)
+ {
+ int size = min((int)(MIN_SIZE - tmp_size),(int)len);
+ memcpy(&tmp_buf[tmp_size], buf, size);
+ tmp_size += size;
+ len -= size;
+
+ /* Pad with space if complete line */
+ if (tmp_buf[tmp_size-1] == '\n')
+ {
+ memset(&tmp_buf[tmp_size-1], ' ', MIN_SIZE - tmp_size);
+ tmp_buf[MIN_SIZE - 1] = '\n';
+ tmp_size = MIN_SIZE;
+ len = 0;
+ }
+ else
+ {
+ /* Wait for more characters */
+ local_irq_restore(flags);
+ return;
+ }
+ }
+
/* make sure the transmitter is enabled.
* NOTE: this overrides any setting done in ttySx, to 8N1, no auto-CTS.
* in the future, move the tr/rec_ctrl shadows from etrax100ser.c to
@@ -134,38 +200,37 @@ console_write(struct console *co, const char *buf, unsigned int len)
*/
*DEBUG_TR_CTRL = 0x40;
-
- /* if the tty has some ongoing business, remember it */
-
- in_progress = *DEBUG_OCMD & 7;
-
- if(in_progress) {
- /* wait until the output dma channel is ready */
-
- while(*DEBUG_OCMD & 7) /* nothing */ ;
+ while(*DEBUG_OCMD & 7); /* Until DMA is not running */
+ while(*DEBUG_STATUS & 0x7f); /* wait until output FIFO is empty as well */
+ udelay(200); /* Wait for last two characters to leave the serial transmitter */
+
+ if (tmp_size)
+ {
+ descr.ctrl = len ? 0 : d_eop | d_wait | d_eol;
+ descr.sw_len = tmp_size;
+ descr.buf = virt_to_phys(tmp_buf);
+ descr.next = virt_to_phys(&descr2);
+ descr2.ctrl = d_eop | d_wait | d_eol;
+ descr2.sw_len = len;
+ descr2.buf = virt_to_phys((char*)buf);
+ }
+ else
+ {
+ descr.ctrl = d_eop | d_wait | d_eol;
+ descr.sw_len = len;
+ descr.buf = virt_to_phys((char*)buf);
}
- descr.ctrl = d_eol;
- descr.sw_len = len;
- descr.buf = __pa(buf);
-
- *DEBUG_FIRST = __pa(&descr); /* write to R_DMAx_FIRST */
+ *DEBUG_FIRST = virt_to_phys(&descr); /* write to R_DMAx_FIRST */
*DEBUG_OCMD = 1; /* dma command start -> R_DMAx_CMD */
/* wait until the output dma channel is ready again */
+ while(*DEBUG_OCMD & 7);
+ while(*DEBUG_STATUS & 0x7f);
+ udelay(200);
- while(*DEBUG_OCMD & 7) /* nothing */;
-
- /* clear pending interrupts so we don't get a surprise below */
-
- if(in_progress)
- *DEBUG_OCLRINT = 2; /* only clear EOP, leave DESCR for the tty */
- else
- *DEBUG_OCLRINT = 3; /* clear both EOP and DESCR */
-
- while(*DEBUG_STATUS & 0x7f); /* wait until output FIFO is empty as well */
-
- restore_flags(flags);
+ tmp_size = 0;
+ local_irq_restore(flags);
}
/* legacy function */
@@ -227,11 +292,11 @@ console_setup(struct console *co, char *options)
}
static struct console sercons = {
- .name = "ttyS",
- .write = console_write,
- .read = NULL,
- .device = console_device,
- .unblank = NULL,
+ .name = "ttyS",
+ .write = console_write,
+ .read = NULL,
+ .device = console_device,
+ .unblank = NULL,
.setup = console_setup,
.flags = CON_PRINTBUFFER,
.index = DEBUG_PORT_IDX,
diff --git a/arch/cris/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index 2c0477bcdd50..5e5f5be7e139 100644
--- a/arch/cris/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -1,12 +1,55 @@
-/* $Id: entry.S,v 1.3 2002/01/21 15:22:20 bjornw Exp $
+/* $Id: entry.S,v 1.16 2003/07/04 08:27:41 starvik Exp $
*
* linux/arch/cris/entry.S
*
- * Copyright (C) 2000, 2001 Axis Communications AB
+ * Copyright (C) 2000, 2001, 2002 Axis Communications AB
*
* Authors: Bjorn Wesen (bjornw@axis.com)
*
* $Log: entry.S,v $
+ * Revision 1.16 2003/07/04 08:27:41 starvik
+ * Merge of Linux 2.5.74
+ *
+ * Revision 1.15 2003/04/09 07:32:55 starvik
+ * resume should return task_struct, not thread_info
+ *
+ * Revision 1.14 2003/04/09 05:20:44 starvik
+ * Merge of Linux 2.5.67
+ *
+ * Revision 1.13 2002/12/11 15:42:02 starvik
+ * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/*.c
+ *
+ * Revision 1.12 2002/12/10 09:00:10 starvik
+ * Merge of Linux 2.5.51
+ *
+ * Revision 1.11 2002/12/05 07:53:10 starvik
+ * Corrected constants used with btstq
+ *
+ * Revision 1.10 2002/11/27 08:45:10 starvik
+ * pid is in task_struct, not thread_info
+ *
+ * Revision 1.9 2002/11/26 09:52:05 starvik
+ * Added preemptive kernel scheduling (if CONFIG_PREEMPT)
+ *
+ * Revision 1.8 2002/11/20 11:56:11 starvik
+ * Merge of Linux 2.5.48
+ *
+ * Revision 1.7 2002/11/18 13:02:42 starvik
+ * Added fourth parameter to do_notify_resume
+ * Minor cleanup
+ *
+ * Revision 1.6 2002/11/11 10:37:50 starvik
+ * Use new asm-offset defines
+ * Modified for new location of current->work etc
+ * Removed SYMBOL_NAME from syscalls
+ * Added some new syscalls
+ *
+ * Revision 1.5 2002/11/05 06:45:11 starvik
+ * Merge of Linux 2.5.45
+ *
+ * Revision 1.4 2002/02/05 15:41:31 bjornw
+ * Rewritten to conform better to current 2.5 code (similar to arch/i386)
+ *
* Revision 1.3 2002/01/21 15:22:20 bjornw
* NICE_DOGGY fix from 2.4 arch/cris
*
@@ -185,75 +228,88 @@
#include <linux/linkage.h>
#include <linux/sys.h>
#include <asm/unistd.h>
-#include <asm/sv_addr_ag.h>
+#include <asm/arch/sv_addr_ag.h>
#include <asm/errno.h>
-
+#include <asm/thread_info.h>
+#include <asm/arch/offset.h>
+
;; functions exported from this file
.globl system_call
.globl ret_from_intr
- .globl ret_from_sys_call
+ .globl ret_from_fork
.globl resume
.globl multiple_interrupt
.globl hwbreakpoint
.globl IRQ1_interrupt
- .globl timer_interrupt
- .globl timer_shortcut
.globl spurious_interrupt
.globl hw_bp_trigs
.globl mmu_bus_fault
.globl do_sigtrap
.globl gdb_handle_breakpoint
-
.globl sys_call_table
- ;; Get values and offsets into various structs. The file isn't
- ;; suitable for consumption by the preprocessor, so don't use
- ;; #include.
- .include "entryoffsets.s"
-
- ;; process bits for ptrace. FIXME: Should be in a header file.
-
-PT_TRACESYS_BIT = 1
-
;; below are various parts of system_call which are not in the fast-path
- ;; handle software irqs
-
-_handle_softirq:
- move.d $r9, $r1
- jsr do_softirq ; call the C routine for softirq handling
- move.d $r1, $r9
-
- ;; fall-through
-
+#ifdef CONFIG_PREEMPT
+ ; Check if preemptive kernel scheduling should be done
+_resume_kernel:
+ ; Load current task struct
+ movs.w -8192, $r0 ; THREAD_SIZE = 8192
+ and.d $sp, $r0
+ move.d [$r0+TI_preempt_count], $r10 ; Preemption disabled?
+ bne _Rexit
+ nop
+_need_resched:
+ move.d [$r0+TI_flags], $r10
+ btstq TIF_NEED_RESCHED, $r10 ; Check if need_resched is set
+ bpl _Rexit
+ nop
+ ; Ok, lets's do some preemptive kernel scheduling
+ move.d PREEMPT_ACTIVE, $r10
+ move.d $r10, [$r0+TI_preempt_count] ; Mark as active
+ ei
+ jsr schedule
+ clear.d [$r0+TI_preempt_count] ; Mark as inactive
+ di
+ ; Load new task struct
+ movs.w -8192, $r0 ; THREAD_SIZE = 8192
+ and.d $sp, $r0
+ ; One more time (with new task)
+ ba _need_resched
+ nop
+#else
+#define _resume_kernel _Rexit
+#endif
+
+ ; Called at exit from fork. schedule_tail must be called to drop
+ ; spinlock if CONFIG_PREEMPT
+ret_from_fork:
+ jsr schedule_tail
+ ba ret_from_sys_call
+ nop
+
ret_from_intr:
- ;; check for resched only if we're going back to user-mode
+ ;; check for resched if preemptive kernel or if we're going back to user-mode
;; this test matches the user_regs(regs) macro
;; we cannot simply test $dccr, because that does not necessarily
;; reflect what mode we'll return into.
- move.d [$sp + LDCCR], $r0; regs->dccr
+ move.d [$sp + PT_dccr], $r0; regs->dccr
btstq 8, $r0 ; U-flag
- bpl _Rexit ; go back directly
- nop
- ba _ret_with_reschedule ; go back but check schedule and signals first
- nop
+ bpl _resume_kernel
+ ; Note that di below is in delay slot
+
+_resume_userspace:
+ di ; so need_resched and sigpending don't change
-_reschedule:
- ;; keep r9 intact
- move.d $r9, $r1
- jsr schedule
- ba ret_from_sys_call
- move.d $r1, $r9
+ movs.w -8192, $r0 ; THREAD_SIZE == 8192
+ and.d $sp, $r0
- ;; return but call do_signal first
-_signal_return:
- ei ; we can get here from an interrupt
- move.d $r9, $r10 ; do_signals syscall/irq param
- moveq 0, $r11 ; oldset param - 0 in this case
- move.d $sp, $r12 ; another argument to do_signal (the regs param)
- jsr do_signal ; arch/cris/kernel/signal.c
+ move.d [$r0+TI_flags], $r10 ; current->work
+ and.d _TIF_WORK_MASK, $r10 ; is there any work to be done on return
+ bne _work_pending
+ nop
ba _Rexit
nop
@@ -285,18 +341,20 @@ system_call:
clear.d [$sp=$sp-4] ; frametype == 0, normal stackframe
movs.w -ENOSYS, $r0
- move.d $r0, [$sp+LR10] ; put the default return value in r10 in the frame
+ move.d $r0, [$sp+PT_r10] ; put the default return value in r10 in the frame
;; check if this process is syscall-traced
movs.w -8192, $r0 ; THREAD_SIZE == 8192
and.d $sp, $r0
- move.d [$r0+LTASK_PTRACE], $r0
- btstq PT_TRACESYS_BIT, $r0
- bmi _tracesys
+ move.d [$r0+TI_flags], $r0
+ btstq TIF_SYSCALL_TRACE, $r0
+ bmi _syscall_trace_entry
nop
+_syscall_traced:
+
;; check for sanity in the requested syscall number
cmpu.w NR_syscalls, $r9
@@ -317,39 +375,26 @@ system_call:
jsr [$r9+sys_call_table] ; actually do the system call
addq 3*4, $sp ; pop the mof, srp and regs parameters
- move.d $r10, [$sp+LR10] ; save the return value
+ move.d $r10, [$sp+PT_r10] ; save the return value
moveq 1, $r9 ; "parameter" to ret_from_sys_call to show it was a sys call
;; fall through into ret_from_sys_call to return
ret_from_sys_call:
- ;; r9 is a parameter - if 1, we came from a syscall, if 0, from an irq
+ ;; r9 is a parameter - if >=1 we came from a syscall, if 0, from an irq
- ;; check if any bottom halves need service
-
- test.d [irq_stat] ; softirq_pending
- bne _handle_softirq
- nop
+ ;; get the current task-struct pointer (see top for defs)
-_ret_with_reschedule:
- ;; first get the current task-struct pointer (see top for defs)
+ movs.w -8192, $r0 ; THREAD_SIZE == 8192
+ and.d $sp, $r0
- move.d $sp, $r0
- and.d -8192, $r0 ; THREAD_SIZE == 8192
-
- ;; see if we want to reschedule into another process
-
- test.d [$r0+LTASK_NEEDRESCHED]
- bne _reschedule
+ di ; make sure need_resched and sigpending don't change
+ move.d [$r0+TI_flags],$r1
+ and.d _TIF_ALLWORK_MASK, $r1
+ bne _syscall_exit_work
nop
- ;; see if we need to run signal checks (important that r9 is intact here)
-
- test.d [$r0+LTASK_SIGPENDING]
- bne _signal_return
- nop
-
_Rexit:
;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h
pop $r10 ; frametype
@@ -375,63 +420,82 @@ _RBFexit:
pop $srp ; subroutine return pointer
rbf [$sp+] ; return by popping the CPU status
-_tracesys:
- ;; this first invocation of syscall_trace _requires_ that
- ;; LR10 in the frame contains -ENOSYS (as is set in the beginning
- ;; of system_call).
-
- jsr syscall_trace
-
- ;; now we should more or less do the same things as in the system_call
- ;; but since our argument regs got clobbered during syscall_trace and
- ;; because syscall_trace might want to alter them, we need to reload them
- ;; from the stack-frame as we use them.
-
- ;; check for sanity in the requested syscall number
-
- move.d [$sp+LR9], $r9
- movs.w -ENOSYS, $r10
- cmpu.w NR_syscalls, $r9
- bcc 1f
- lslq 2, $r9 ; multiply by 4, in the delay slot
-
- ;; read the system call vector entry into r9
+ ;; We get here after doing a syscall if extra work might need to be done
+ ;; perform syscall exit tracing if needed
- move.d [$r9+sys_call_table], $r9
-
- ;; restore r10, r11, r12, r13, mof and srp into the needed registers
-
- move.d [$sp+LORIG_R10], $r10 ; LR10 is already filled with -ENOSYS.
- move.d [$sp+LR11], $r11
- move.d [$sp+LR12], $r12
- move.d [$sp+LR13], $r13
- move [$sp+LMOF], $mof
- move [$sp+LSRP], $srp
-
- ;; as a bonus 7th parameter, we give the location on the stack
- ;; of the register structure itself. some syscalls need this.
+_syscall_exit_work:
+ ;; $r0 contains current at this point and irq's are disabled
- push $sp
+ move.d [$r0+TI_flags], $r1
+ btstq TIF_SYSCALL_TRACE, $r1
+ bpl _work_pending
+ nop
- ;; the fifth and sixth parameters needs to be put on the stack for
- ;; the system call to find them
+ ei
- push $srp
- push $mof
+ move.d $r9, $r1 ; preserve r9
+ jsr do_syscall_trace
+ move.d $r1, $r9
+
+ ba _resume_userspace
+ nop
+
+_work_pending:
+ move.d [$r0+TI_flags], $r1
+ btstq TIF_NEED_RESCHED, $r1
+ bpl _work_notifysig ; was neither trace nor sched, must be signal/notify
+ nop
+
+_work_resched:
+ move.d $r9, $r1 ; preserve r9
+ jsr schedule
+ move.d $r1, $r9
+ di
- jsr $r9 ; actually call the system-call
- addq 3*4, $sp ; pop the srp, mof and regs parameters
+ move.d [$r0+TI_flags], $r1
+ and.d _TIF_WORK_MASK, $r1; ignore the syscall trace counter
+ beq _Rexit
+ nop
+ btstq TIF_NEED_RESCHED, $r1
+ bmi _work_resched ; current->work.need_resched
+ nop
-1: move.d $r10, [$sp+LR10]; save the return value
+_work_notifysig:
+ ;; deal with pending signals and notify-resume requests
- ;; second call of syscall_trace, to let it grab the results
-
- jsr syscall_trace
+ move.d $r9, $r10 ; do_notify_resume syscall/irq param
+ moveq 0, $r11 ; oldset param - 0 in this case
+ move.d $sp, $r12 ; the regs param
+ move.d $r1, $r13 ; the thread_info_flags parameter
+ jsr do_notify_resume
+
+ ba _Rexit
+ nop
- moveq 1, $r9 ; "parameter" to ret_from_sys_call to show it was a sys call
- ba ret_from_sys_call
+ ;; We get here as a sidetrack when we've entered a syscall with the
+ ;; trace-bit set. We need to call do_syscall_trace and then continue
+ ;; with the call.
+
+_syscall_trace_entry:
+ ;; PT_r10 in the frame contains -ENOSYS as required, at this point
+
+ jsr do_syscall_trace
+
+ ;; now re-enter the syscall code to do the syscall itself
+ ;; we need to restore $r9 here to contain the wanted syscall, and
+ ;; the other parameter-bearing registers
+
+ move.d [$sp+PT_r9], $r9
+ move.d [$sp+PT_orig_r10], $r10 ; PT_r10 is already filled with -ENOSYS.
+ move.d [$sp+PT_r11], $r11
+ move.d [$sp+PT_r12], $r12
+ move.d [$sp+PT_r13], $r13
+ move [$sp+PT_mof], $mof
+ move [$sp+PT_srp], $srp
+
+ ba _syscall_traced
nop
-
+
;; resume performs the actual task-switching, by switching stack pointers
;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct
;; returns old current in r10
@@ -442,26 +506,27 @@ _tracesys:
resume:
push $srp ; we keep the old/new PC on the stack
add.d $r12, $r10 ; r10 = current tasks tss
- move $dccr, [$r10+LTHREAD_DCCR] ; save irq enable state
+ move $dccr, [$r10+THREAD_dccr]; save irq enable state
di
- move $usp, [$r10+LTHREAD_USP] ; save user-mode stackpointer
+ move $usp, [$r10+ THREAD_usp] ; save user-mode stackpointer
;; See copy_thread for the reason why register R9 is saved.
subq 10*4, $sp
movem $r9, [$sp] ; save non-scratch registers and R9.
- move.d $sp, [$r10+LTHREAD_KSP] ; save the kernel stack pointer for the old task
+ move.d $sp, [$r10+THREAD_ksp] ; save the kernel stack pointer for the old task
move.d $sp, $r10 ; return last running task in r10
- and.d -8192, $r10 ; get task ptr from stackpointer
+ and.d -8192, $r10 ; get thread_info from stackpointer
+ move.d [$r10+TI_task], $r10 ; get task
add.d $r12, $r11 ; find the new tasks tss
- move.d [$r11+LTHREAD_KSP], $sp ; switch into the new stackframe by restoring kernel sp
+ move.d [$r11+THREAD_ksp], $sp ; switch into the new stackframe by restoring kernel sp
movem [$sp+], $r9 ; restore non-scratch registers and R9.
- move [$r11+LTHREAD_USP], $usp ; restore user-mode stackpointer
+ move [$r11+THREAD_usp], $usp ; restore user-mode stackpointer
- move [$r11+LTHREAD_DCCR], $dccr ; restore irq enable status
+ move [$r11+THREAD_dccr], $dccr ; restore irq enable status
jump [$sp+] ; restore PC
;; This is the MMU bus fault handler.
@@ -689,7 +754,8 @@ do_sigtrap:
movs.w -8192,$r9 ; THREAD_SIZE == 8192
and.d $sp, $r9
- move.d [$r9+LTASK_PID], $r10 ; current->pid as arg1.
+ move.d [$r9+TI_task], $r10
+ move.d [$r10+TASK_pid], $r10 ; current->pid as arg1.
moveq 5, $r11 ; SIGTRAP as arg2.
jsr sys_kill
jump ret_from_intr ; Use the return routine for interrupts.
@@ -722,75 +788,9 @@ hw_bp_trigs:
hw_bp_trig_ptr:
.dword hw_bp_trigs
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process (i.e. the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be free'd until both the parent and the child have exited.
- *
- * This *can* be done in C with an single-asm-wrapped-in-a-function, but you
- * get more or less gross code. The safer you make the asm-constraints,
- * the grosser the code, at least with the gcc version in cris-dist-1.13.
- */
-
-/* int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */
-/* r10 r11 r12 */
-
- .text
- .global kernel_thread
-kernel_thread:
-
- /* Save ARG for later. */
- move.d $r11, $r13
-
- /* r11 is argument 2 to clone, the flags */
- move.d $r12, $r11
- or.w LCLONE_VM, $r11
- or.w LCLONE_UNTRACED, $r11
-
- /* Save FN for later. */
- move.d $r10, $r12
-
- /* r9 contains syscall number, to sys_clone */
- movu.w __NR_clone, $r9
-
- /* r10 is argument 1 to clone */
- clear.d $r10
-
- /* call sys_clone, this will fork */
- break 13
-
- /* parent or child? child returns 0 here. */
- test.d $r10
-
- /* jump if parent */
- bne 1f
- nop /* delay slot */
-
- /* set argument to function to call */
- move.d $r13, $r10
-
- /* call specified function */
- jsr $r12
- /* If we ever return from the function, something bad has happened. */
-
- /* r9 is sys_exit syscall number */
- movu.w __NR_exit, $r9
-
- /* Give a really bad exit-value */
- moveq -1, $r10
-
- /* call sys_exit, killing the child */
- break 13
-1:
- ret
- nop /* delay slot */
-
.section .rodata,"a"
sys_call_table:
- .long sys_ni_syscall /* 0 - old "setup()" system call*/
+ .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
.long sys_exit
.long sys_fork
.long sys_read
@@ -842,7 +842,7 @@ sys_call_table:
.long sys_geteuid16
.long sys_getegid16 /* 50 */
.long sys_acct
- .long sys_umount /* recycled never used phys() */
+ .long sys_umount /* recycled never used phys( */
.long sys_ni_syscall /* old lock syscall holder */
.long sys_ioctl
.long sys_fcntl /* 55 */
@@ -913,14 +913,14 @@ sys_call_table:
.long sys_clone /* 120 */
.long sys_setdomainname
.long sys_newuname
- .long sys_ni_syscall /* TODO sys_modify_ldt - do something ?*/
+ .long sys_ni_syscall /* sys_modify_ldt */
.long sys_adjtimex
.long sys_mprotect /* 125 */
.long sys_sigprocmask
- .long sys_create_module
+ .long sys_ni_syscall /* old "create_module" */
.long sys_init_module
.long sys_delete_module
- .long sys_get_kernel_syms /* 130 */
+ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
.long sys_quotactl
.long sys_getpgid
.long sys_fchdir
@@ -945,19 +945,19 @@ sys_call_table:
.long sys_mlockall
.long sys_munlockall
.long sys_sched_setparam
- .long sys_sched_getparam /* 155 */
+ .long sys_sched_getparam /* 155 */
.long sys_sched_setscheduler
.long sys_sched_getscheduler
.long sys_sched_yield
.long sys_sched_get_priority_max
- .long sys_sched_get_priority_min /* 160 */
+ .long sys_sched_get_priority_min /* 160 */
.long sys_sched_rr_get_interval
.long sys_nanosleep
.long sys_mremap
.long sys_setresuid16
.long sys_getresuid16 /* 165 */
.long sys_ni_syscall /* sys_vm86 */
- .long sys_query_module
+ .long sys_ni_syscall /* Old sys_query_module */
.long sys_poll
.long sys_nfsservctl
.long sys_setresgid16 /* 170 */
@@ -970,8 +970,8 @@ sys_call_table:
.long sys_rt_sigtimedwait
.long sys_rt_sigqueueinfo
.long sys_rt_sigsuspend
- .long sys_pread /* 180 */
- .long sys_pwrite
+ .long sys_pread64 /* 180 */
+ .long sys_pwrite64
.long sys_chown16
.long sys_getcwd
.long sys_capget
@@ -1013,11 +1013,54 @@ sys_call_table:
.long sys_getdents64 /* 220 */
.long sys_fcntl64
.long sys_ni_syscall /* reserved for TUX */
- .long sys_ni_syscall /* Reserved for Security */
+ .long sys_ni_syscall
.long sys_gettid
.long sys_readahead /* 225 */
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr
+ .long sys_getxattr
+ .long sys_lgetxattr /* 230 */
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr
+ .long sys_flistxattr
+ .long sys_removexattr /* 235 */
+ .long sys_lremovexattr
+ .long sys_fremovexattr
.long sys_tkill
-
+ .long sys_sendfile64
+ .long sys_futex /* 240 */
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_ni_syscall /* sys_set_thread_area */
+ .long sys_ni_syscall /* sys_get_thread_area */
+ .long sys_io_setup /* 245 */
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit
+ .long sys_io_cancel
+ .long sys_fadvise64 /* 250 */
+ .long sys_ni_syscall
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create
+ .long sys_epoll_ctl /* 255 */
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_set_tid_address
+ .long sys_timer_create
+ .long sys_timer_settime /* 260 */
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime /* 265 */
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64
+
/*
* NOTE!! This doesn't have to be exact - we just have
* to make sure we have _enough_ of the "sys_ni_syscall"
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c
new file mode 100644
index 000000000000..2c2cb60c4710
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/fasttimer.c
@@ -0,0 +1,996 @@
+/* $Id: fasttimer.c,v 1.4 2003/07/04 08:27:41 starvik Exp $
+ * linux/arch/cris/kernel/fasttimer.c
+ *
+ * Fast timers for ETRAX100/ETRAX100LX
+ * This may be useful in other OS than Linux so use 2 space indentation...
+ *
+ * $Log: fasttimer.c,v $
+ * Revision 1.4 2003/07/04 08:27:41 starvik
+ * Merge of Linux 2.5.74
+ *
+ * Revision 1.3 2002/12/12 08:26:32 starvik
+ * Don't use C-comments inside CVS comments
+ *
+ * Revision 1.2 2002/12/11 15:42:02 starvik
+ * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/
+ *
+ * Revision 1.1 2002/11/18 07:58:06 starvik
+ * Fast timers (from Linux 2.4)
+ *
+ * Revision 1.5 2002/10/15 06:21:39 starvik
+ * Added call to init_waitqueue_head
+ *
+ * Revision 1.4 2002/05/28 17:47:59 johana
+ * Added del_fast_timer()
+ *
+ * Revision 1.3 2002/05/28 16:16:07 johana
+ * Handle empty fast_timer_list
+ *
+ * Revision 1.2 2002/05/27 15:38:42 johana
+ * Made it compile without warnings on Linux 2.4.
+ * (includes, wait_queue, PROC_FS and snprintf)
+ *
+ * Revision 1.1 2002/05/27 15:32:25 johana
+ * arch/etrax100/kernel/fasttimer.c v1.8 from the elinux tree.
+ *
+ * Revision 1.8 2001/11/27 13:50:40 pkj
+ * Disable interrupts while stopping the timer and while modifying the
+ * list of active timers in timer1_handler() as it may be interrupted
+ * by other interrupts (e.g., the serial interrupt) which may add fast
+ * timers.
+ *
+ * Revision 1.7 2001/11/22 11:50:32 pkj
+ * * Only store information about the last 16 timers.
+ * * proc_fasttimer_read() now uses an allocated buffer, since it
+ * requires more space than just a page even for only writing the
+ * last 16 timers. The buffer is only allocated on request, so
+ * unless /proc/fasttimer is read, it is never allocated.
+ * * Renamed fast_timer_started to fast_timers_started to match
+ * fast_timers_added and fast_timers_expired.
+ * * Some clean-up.
+ *
+ * Revision 1.6 2000/12/13 14:02:08 johana
+ * Removed volatile for fast_timer_list
+ *
+ * Revision 1.5 2000/12/13 13:55:35 johana
+ * Added DEBUG_LOG, added som cli() and cleanup
+ *
+ * Revision 1.4 2000/12/05 13:48:50 johana
+ * Added range check when writing proc file, modified timer int handling
+ *
+ * Revision 1.3 2000/11/23 10:10:20 johana
+ * More debug/logging possibilities.
+ * Moved GET_JIFFIES_USEC() to timex.h and time.c
+ *
+ * Revision 1.2 2000/11/01 13:41:04 johana
+ * Clean up and bugfixes.
+ * Created new do_gettimeofday_fast() that gets a timeval struct
+ * with time based on jiffies and *R_TIMER0_DATA, uses a table
+ * for fast conversion of timer value to microseconds.
+ * (Much faster the standard do_gettimeofday() and we don't really
+ * wan't to use the true time - we wan't the "uptime" so timers don't screw up
+ * when we change the time.
+ * TODO: Add efficient support for continuous timers as well.
+ *
+ * Revision 1.1 2000/10/26 15:49:16 johana
+ * Added fasttimer, highresolution timers.
+ *
+ * Copyright (C) 2000,2001 2002 Axis Communications AB, Lund, Sweden
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/rtc.h>
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <asm/arch/svinto.h>
+#include <asm/fasttimer.h>
+#include <linux/proc_fs.h>
+
+
+#define DEBUG_LOG_INCLUDED
+#define FAST_TIMER_LOG
+//#define FAST_TIMER_TEST
+
+#define FAST_TIMER_SANITY_CHECKS
+
+#ifdef FAST_TIMER_SANITY_CHECKS
+#define SANITYCHECK(x) x
+static int sanity_failed = 0;
+#else
+#define SANITYCHECK(x)
+#endif
+
+#define D1(x)
+#define D2(x)
+#define DP(x)
+
+#define __INLINE__ inline
+
+static int fast_timer_running = 0;
+static int fast_timers_added = 0;
+static int fast_timers_started = 0;
+static int fast_timers_expired = 0;
+static int fast_timers_deleted = 0;
+static int fast_timer_is_init = 0;
+static int fast_timer_ints = 0;
+
+static struct fast_timer *fast_timer_list = NULL;
+
+#ifdef DEBUG_LOG_INCLUDED
+#define DEBUG_LOG_MAX 128
+static const char * debug_log_string[DEBUG_LOG_MAX];
+static unsigned long debug_log_value[DEBUG_LOG_MAX];
+static int debug_log_cnt = 0;
+static int debug_log_cnt_wrapped = 0;
+
+#define DEBUG_LOG(string, value) \
+{ \
+ unsigned long log_flags; \
+ save_flags(log_flags); \
+ cli(); \
+ debug_log_string[debug_log_cnt] = (string); \
+ debug_log_value[debug_log_cnt] = (unsigned long)(value); \
+ if (++debug_log_cnt >= DEBUG_LOG_MAX) \
+ { \
+ debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \
+ debug_log_cnt_wrapped = 1; \
+ } \
+ restore_flags(log_flags); \
+}
+#else
+#define DEBUG_LOG(string, value)
+#endif
+
+
+/* The frequencies for index = clkselx number in R_TIMER_CTRL */
+#define NUM_TIMER_FREQ 15
+#define MAX_USABLE_TIMER_FREQ 7
+#define MAX_DELAY_US 853333L
+const unsigned long timer_freq_100[NUM_TIMER_FREQ] =
+{
+ 3, /* 0 3333 - 853333 us */
+ 6, /* 1 1666 - 426666 us */
+ 12, /* 2 833 - 213333 us */
+ 24, /* 3 416 - 106666 us */
+ 48, /* 4 208 - 53333 us */
+ 96, /* 5 104 - 26666 us */
+ 192, /* 6 52 - 13333 us */
+ 384, /* 7 26 - 6666 us */
+ 576,
+ 1152,
+ 2304,
+ 4608,
+ 9216,
+ 18432,
+ 62500,
+ /* 15 = cascade */
+};
+#define NUM_TIMER_STATS 16
+#ifdef FAST_TIMER_LOG
+struct fast_timer timer_added_log[NUM_TIMER_STATS];
+struct fast_timer timer_started_log[NUM_TIMER_STATS];
+struct fast_timer timer_expired_log[NUM_TIMER_STATS];
+#endif
+
+int timer_div_settings[NUM_TIMER_STATS];
+int timer_freq_settings[NUM_TIMER_STATS];
+int timer_delay_settings[NUM_TIMER_STATS];
+
+/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */
+void __INLINE__ do_gettimeofday_fast(struct timeval *tv)
+{
+ unsigned long sec = jiffies;
+ unsigned long usec = GET_JIFFIES_USEC();
+
+ usec += (sec % HZ) * (1000000 / HZ);
+ sec = sec / HZ;
+
+ if (usec > 1000000)
+ {
+ usec -= 1000000;
+ sec++;
+ }
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1)
+{
+ if (t0->tv_sec < t1->tv_sec)
+ {
+ return -1;
+ }
+ else if (t0->tv_sec > t1->tv_sec)
+ {
+ return 1;
+ }
+ if (t0->tv_usec < t1->tv_usec)
+ {
+ return -1;
+ }
+ else if (t0->tv_usec > t1->tv_usec)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+void __INLINE__ start_timer1(unsigned long delay_us)
+{
+ int freq_index = 0; /* This is the lowest resolution */
+ unsigned long upper_limit = MAX_DELAY_US;
+
+ unsigned long div;
+ /* Start/Restart the timer to the new shorter value */
+ /* t = 1/freq = 1/19200 = 53us
+ * T=div*t, div = T/t = delay_us*freq/1000000
+ */
+#if 1 /* Adaptive timer settings */
+ while (delay_us < upper_limit && freq_index < MAX_USABLE_TIMER_FREQ)
+ {
+ freq_index++;
+ upper_limit >>= 1; /* Divide by 2 using shift */
+ }
+ if (freq_index > 0)
+ {
+ freq_index--;
+ }
+#else
+ freq_index = 6;
+#endif
+ div = delay_us * timer_freq_100[freq_index]/10000;
+ if (div < 2)
+ {
+ /* Maybe increase timer freq? */
+ div = 2;
+ }
+ if (div > 255)
+ {
+ div = 0; /* This means 256, the max the timer takes */
+ /* If a longer timeout than the timer can handle is used,
+ * then we must restart it when it goes off.
+ */
+ }
+
+ timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = div;
+ timer_freq_settings[fast_timers_started % NUM_TIMER_STATS] = freq_index;
+ timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us;
+
+ D1(printk("start_timer1 : %d us freq: %i div: %i\n",
+ delay_us, freq_index, div));
+ /* Clear timer1 irq */
+ *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
+
+ /* Set timer values */
+ *R_TIMER_CTRL = r_timer_ctrl_shadow =
+ (r_timer_ctrl_shadow &
+ ~IO_MASK(R_TIMER_CTRL, timerdiv1) &
+ ~IO_MASK(R_TIMER_CTRL, tm1) &
+ ~IO_MASK(R_TIMER_CTRL, clksel1)) |
+ IO_FIELD(R_TIMER_CTRL, timerdiv1, div) |
+ IO_STATE(R_TIMER_CTRL, tm1, stop_ld) |
+ IO_FIELD(R_TIMER_CTRL, clksel1, freq_index ); /* 6=c19k2Hz */
+
+ /* Ack interrupt */
+ *R_TIMER_CTRL = r_timer_ctrl_shadow |
+ IO_STATE(R_TIMER_CTRL, i1, clr);
+
+ /* Start timer */
+ *R_TIMER_CTRL = r_timer_ctrl_shadow =
+ (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
+ IO_STATE(R_TIMER_CTRL, tm1, run);
+
+ /* Enable timer1 irq */
+ *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);
+ fast_timers_started++;
+ fast_timer_running = 1;
+}
+
+/* In version 1.4 this function takes 27 - 50 us */
+void start_one_shot_timer(struct fast_timer *t,
+ fast_timer_function_type *function,
+ unsigned long data,
+ unsigned long delay_us,
+ const char *name)
+{
+ unsigned long flags;
+ struct fast_timer *tmp;
+
+ D1(printk("sft %s %d us\n", name, delay_us));
+
+ save_flags(flags);
+ cli();
+
+ do_gettimeofday_fast(&t->tv_set);
+ tmp = fast_timer_list;
+
+ SANITYCHECK({ /* Check so this is not in the list already... */
+ while (tmp != NULL)
+ {
+ if (tmp == t)
+ {
+ printk("timer name: %s data: 0x%08lX already in list!\n", name, data);
+ sanity_failed++;
+ return;
+ }
+ else
+ {
+ tmp = tmp->next;
+ }
+ }
+ tmp = fast_timer_list;
+ });
+
+ t->delay_us = delay_us;
+ t->function = function;
+ t->data = data;
+ t->name = name;
+
+ t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
+ t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000;
+ if (t->tv_expires.tv_usec > 1000000)
+ {
+ t->tv_expires.tv_usec -= 1000000;
+ t->tv_expires.tv_sec++;
+ }
+#ifdef FAST_TIMER_LOG
+ timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
+#endif
+ fast_timers_added++;
+
+ /* Check if this should timeout before anything else */
+ if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
+ {
+ /* Put first in list and modify the timer value */
+ t->prev = NULL;
+ t->next = fast_timer_list;
+ if (fast_timer_list)
+ {
+ fast_timer_list->prev = t;
+ }
+ fast_timer_list = t;
+#ifdef FAST_TIMER_LOG
+ timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
+#endif
+ start_timer1(delay_us);
+ } else {
+ /* Put in correct place in list */
+ while (tmp->next &&
+ timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
+ {
+ tmp = tmp->next;
+ }
+ /* Insert t after tmp */
+ t->prev = tmp;
+ t->next = tmp->next;
+ if (tmp->next)
+ {
+ tmp->next->prev = t;
+ }
+ tmp->next = t;
+ }
+
+ D2(printk("start_one_shot_timer: %d us done\n", delay_us));
+
+ restore_flags(flags);
+} /* start_one_shot_timer */
+
+static inline int fast_timer_pending (const struct fast_timer * t)
+{
+ return (t->next != NULL) || (t->prev != NULL) || (t == fast_timer_list);
+}
+
+static inline int detach_fast_timer (struct fast_timer *t)
+{
+ struct fast_timer *next, *prev;
+ if (!fast_timer_pending(t))
+ return 0;
+ next = t->next;
+ prev = t->prev;
+ if (next)
+ next->prev = prev;
+ if (prev)
+ prev->next = next;
+ else
+ fast_timer_list = next;
+ fast_timers_deleted++;
+ return 1;
+}
+
+int del_fast_timer(struct fast_timer * t)
+{
+ unsigned long flags;
+ int ret;
+
+ save_flags(flags);
+ cli();
+ ret = detach_fast_timer(t);
+ t->next = t->prev = NULL;
+ restore_flags(flags);
+ return ret;
+} /* del_fast_timer */
+
+
+/* Interrupt routines or functions called in interrupt context */
+
+/* Timer 1 interrupt handler */
+
+static irqreturn_t
+timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct fast_timer *t;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ /* Clear timer1 irq */
+ *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
+
+ /* First stop timer, then ack interrupt */
+ /* Stop timer */
+ *R_TIMER_CTRL = r_timer_ctrl_shadow =
+ (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
+ IO_STATE(R_TIMER_CTRL, tm1, stop_ld);
+
+ /* Ack interrupt */
+ *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);
+
+ fast_timer_running = 0;
+ fast_timer_ints++;
+
+ restore_flags(flags);
+
+ t = fast_timer_list;
+ while (t)
+ {
+ struct timeval tv;
+
+ /* Has it really expired? */
+ do_gettimeofday_fast(&tv);
+ D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec));
+
+ if (timeval_cmp(&t->tv_expires, &tv) <= 0)
+ {
+ /* Yes it has expired */
+#ifdef FAST_TIMER_LOG
+ timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
+#endif
+ fast_timers_expired++;
+
+ /* Remove this timer before call, since it may reuse the timer */
+ save_flags(flags);
+ cli();
+ if (t->prev)
+ {
+ t->prev->next = t->next;
+ }
+ else
+ {
+ fast_timer_list = t->next;
+ }
+ if (t->next)
+ {
+ t->next->prev = t->prev;
+ }
+ t->prev = NULL;
+ t->next = NULL;
+ restore_flags(flags);
+
+ if (t->function != NULL)
+ {
+ t->function(t->data);
+ }
+ else
+ {
+ DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
+ }
+ }
+ else
+ {
+ /* Timer is to early, let's set it again using the normal routines */
+ D1(printk(".\n"));
+ }
+
+ save_flags(flags);
+ cli();
+ if ((t = fast_timer_list) != NULL)
+ {
+ /* Start next timer.. */
+ long us;
+ struct timeval tv;
+
+ do_gettimeofday_fast(&tv);
+ us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 +
+ t->tv_expires.tv_usec - tv.tv_usec);
+ if (us > 0)
+ {
+ if (!fast_timer_running)
+ {
+#ifdef FAST_TIMER_LOG
+ timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
+#endif
+ start_timer1(us);
+ }
+ restore_flags(flags);
+ break;
+ }
+ else
+ {
+ /* Timer already expired, let's handle it better late than never.
+ * The normal loop handles it
+ */
+ D1(printk("e! %d\n", us));
+ }
+ }
+ restore_flags(flags);
+ }
+
+ if (!t)
+ {
+ D1(printk("t1 stop!\n"));
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void wake_up_func(unsigned long data)
+{
+#ifdef DECLARE_WAITQUEUE
+ wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data;
+#else
+ struct wait_queue **sleep_wait_p = (struct wait_queue **)data;
+#endif
+ wake_up(sleep_wait_p);
+}
+
+
+/* Useful API */
+
+void schedule_usleep(unsigned long us)
+{
+ struct fast_timer t;
+#ifdef DECLARE_WAITQUEUE
+ wait_queue_head_t sleep_wait;
+ init_waitqueue_head(&sleep_wait);
+ {
+ DECLARE_WAITQUEUE(wait, current);
+#else
+ struct wait_queue *sleep_wait = NULL;
+ struct wait_queue wait = { current, NULL };
+#endif
+
+ D1(printk("schedule_usleep(%d)\n", us));
+ add_wait_queue(&sleep_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us,
+ "usleep");
+ schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&sleep_wait, &wait);
+ D1(printk("done schedule_usleep(%d)\n", us));
+#ifdef DECLARE_WAITQUEUE
+ }
+#endif
+}
+
+#ifdef CONFIG_PROC_FS
+static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+ ,int *eof, void *data_unused
+#else
+ ,int unused
+#endif
+ );
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+static struct proc_dir_entry *fasttimer_proc_entry;
+#else
+static struct proc_dir_entry fasttimer_proc_entry =
+{
+ 0, 9, "fasttimer",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, NULL /* ops -- default to array */,
+ &proc_fasttimer_read /* get_info */,
+};
+#endif
+#endif /* CONFIG_PROC_FS */
+
+#ifdef CONFIG_PROC_FS
+
+/* This value is very much based on testing */
+#define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300)
+
+static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+ ,int *eof, void *data_unused
+#else
+ ,int unused
+#endif
+ )
+{
+ unsigned long flags;
+ int i = 0;
+ int num_to_show;
+ struct timeval tv;
+ struct fast_timer *t, *nextt;
+ static char *bigbuf = NULL;
+ static unsigned long used;
+
+ if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE)))
+ {
+ used = 0;
+ bigbuf[0] = '\0';
+ return 0;
+ }
+
+ if (!offset || !used)
+ {
+ do_gettimeofday_fast(&tv);
+
+ used = 0;
+ used += sprintf(bigbuf + used, "Fast timers added: %i\n",
+ fast_timers_added);
+ used += sprintf(bigbuf + used, "Fast timers started: %i\n",
+ fast_timers_started);
+ used += sprintf(bigbuf + used, "Fast timer interrupts: %i\n",
+ fast_timer_ints);
+ used += sprintf(bigbuf + used, "Fast timers expired: %i\n",
+ fast_timers_expired);
+ used += sprintf(bigbuf + used, "Fast timers deleted: %i\n",
+ fast_timers_deleted);
+ used += sprintf(bigbuf + used, "Fast timer running: %s\n",
+ fast_timer_running ? "yes" : "no");
+ used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n",
+ (unsigned long)tv.tv_sec,
+ (unsigned long)tv.tv_usec);
+#ifdef FAST_TIMER_SANITY_CHECKS
+ used += sprintf(bigbuf + used, "Sanity failed: %i\n",
+ sanity_failed);
+#endif
+ used += sprintf(bigbuf + used, "\n");
+
+#ifdef DEBUG_LOG_INCLUDED
+ {
+ int end_i = debug_log_cnt;
+ i = 0;
+
+ if (debug_log_cnt_wrapped)
+ {
+ i = debug_log_cnt;
+ }
+
+ while ((i != end_i || (debug_log_cnt_wrapped && !used)) &&
+ used+100 < BIG_BUF_SIZE)
+ {
+ used += sprintf(bigbuf + used, debug_log_string[i],
+ debug_log_value[i]);
+ i = (i+1) % DEBUG_LOG_MAX;
+ }
+ }
+ used += sprintf(bigbuf + used, "\n");
+#endif
+
+ num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
+ NUM_TIMER_STATS);
+ used += sprintf(bigbuf + used, "Timers started: %i\n", fast_timers_started);
+ for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE) ; i++)
+ {
+ int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;
+
+#if 1 //ndef FAST_TIMER_LOG
+ used += sprintf(bigbuf + used, "div: %i freq: %i delay: %i"
+ "\n",
+ timer_div_settings[cur],
+ timer_freq_settings[cur],
+ timer_delay_settings[cur]
+ );
+#endif
+#ifdef FAST_TIMER_LOG
+ t = &timer_started_log[cur];
+ used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+ "d: %6li us data: 0x%08lX"
+ "\n",
+ t->name,
+ (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_usec,
+ (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_usec,
+ t->delay_us,
+ t->data
+ );
+#endif
+ }
+ used += sprintf(bigbuf + used, "\n");
+
+#ifdef FAST_TIMER_LOG
+ num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
+ NUM_TIMER_STATS);
+ used += sprintf(bigbuf + used, "Timers added: %i\n", fast_timers_added);
+ for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
+ {
+ t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
+ used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+ "d: %6li us data: 0x%08lX"
+ "\n",
+ t->name,
+ (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_usec,
+ (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_usec,
+ t->delay_us,
+ t->data
+ );
+ }
+ used += sprintf(bigbuf + used, "\n");
+
+ num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
+ NUM_TIMER_STATS);
+ used += sprintf(bigbuf + used, "Timers expired: %i\n", fast_timers_expired);
+ for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
+ {
+ t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
+ used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+ "d: %6li us data: 0x%08lX"
+ "\n",
+ t->name,
+ (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_usec,
+ (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_usec,
+ t->delay_us,
+ t->data
+ );
+ }
+ used += sprintf(bigbuf + used, "\n");
+#endif
+
+ used += sprintf(bigbuf + used, "Active timers:\n");
+ save_flags(flags);
+ cli();
+ t = fast_timer_list;
+ while (t != NULL && (used+100 < BIG_BUF_SIZE))
+ {
+ nextt = t->next;
+ restore_flags(flags);
+ used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
+ "d: %6li us data: 0x%08lX"
+/* " func: 0x%08lX" */
+ "\n",
+ t->name,
+ (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_usec,
+ (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_usec,
+ t->delay_us,
+ t->data
+/* , t->function */
+ );
+ cli();
+ if (t->next != nextt)
+ {
+ printk("timer removed!\n");
+ }
+ t = nextt;
+ }
+ restore_flags(flags);
+ }
+
+ if (used - offset < len)
+ {
+ len = used - offset;
+ }
+
+ memcpy(buf, bigbuf + offset, len);
+ *start = buf;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+ *eof = 1;
+#endif
+
+ return len;
+}
+#endif /* PROC_FS */
+
+#ifdef FAST_TIMER_TEST
+static volatile unsigned long i = 0;
+static volatile int num_test_timeout = 0;
+static struct fast_timer tr[10];
+static int exp_num[10];
+
+static struct timeval tv_exp[100];
+
+static void test_timeout(unsigned long data)
+{
+ do_gettimeofday_fast(&tv_exp[data]);
+ exp_num[data] = num_test_timeout;
+
+ num_test_timeout++;
+}
+
+static void test_timeout1(unsigned long data)
+{
+ do_gettimeofday_fast(&tv_exp[data]);
+ exp_num[data] = num_test_timeout;
+ if (data < 7)
+ {
+ start_one_shot_timer(&tr[i], test_timeout1, i, 1000, "timeout1");
+ i++;
+ }
+ num_test_timeout++;
+}
+
+DP(
+static char buf0[2000];
+static char buf1[2000];
+static char buf2[2000];
+static char buf3[2000];
+static char buf4[2000];
+);
+
+static char buf5[6000];
+static int j_u[1000];
+
+static void fast_timer_test(void)
+{
+ int prev_num;
+ int j;
+
+ struct timeval tv, tv0, tv1, tv2;
+
+ printk("fast_timer_test() start\n");
+ do_gettimeofday_fast(&tv);
+
+ for (j = 0; j < 1000; j++)
+ {
+ j_u[j] = GET_JIFFIES_USEC();
+ }
+ for (j = 0; j < 100; j++)
+ {
+ do_gettimeofday_fast(&tv_exp[j]);
+ }
+ printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec);
+
+ for (j = 0; j < 1000; j++)
+ {
+ printk("%i %i %i %i %i\n",j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]);
+ j += 4;
+ }
+ for (j = 0; j < 100; j++)
+ {
+ printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n",
+ tv_exp[j].tv_sec,tv_exp[j].tv_usec,
+ tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec,
+ tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec,
+ tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec,
+ tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec);
+ j += 4;
+ }
+ do_gettimeofday_fast(&tv0);
+ start_one_shot_timer(&tr[i], test_timeout, i, 50000, "test0");
+ DP(proc_fasttimer_read(buf0, NULL, 0, 0, 0));
+ i++;
+ start_one_shot_timer(&tr[i], test_timeout, i, 70000, "test1");
+ DP(proc_fasttimer_read(buf1, NULL, 0, 0, 0));
+ i++;
+ start_one_shot_timer(&tr[i], test_timeout, i, 40000, "test2");
+ DP(proc_fasttimer_read(buf2, NULL, 0, 0, 0));
+ i++;
+ start_one_shot_timer(&tr[i], test_timeout, i, 60000, "test3");
+ DP(proc_fasttimer_read(buf3, NULL, 0, 0, 0));
+ i++;
+ start_one_shot_timer(&tr[i], test_timeout1, i, 55000, "test4xx");
+ DP(proc_fasttimer_read(buf4, NULL, 0, 0, 0));
+ i++;
+ do_gettimeofday_fast(&tv1);
+
+ proc_fasttimer_read(buf5, NULL, 0, 0, 0);
+
+ prev_num = num_test_timeout;
+ while (num_test_timeout < i)
+ {
+ if (num_test_timeout != prev_num)
+ {
+ prev_num = num_test_timeout;
+ }
+ }
+ do_gettimeofday_fast(&tv2);
+ printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec);
+ printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec);
+ printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec);
+ DP(printk("buf0:\n");
+ printk(buf0);
+ printk("buf1:\n");
+ printk(buf1);
+ printk("buf2:\n");
+ printk(buf2);
+ printk("buf3:\n");
+ printk(buf3);
+ printk("buf4:\n");
+ printk(buf4);
+ );
+ printk("buf5:\n");
+ printk(buf5);
+
+ printk("timers set:\n");
+ for(j = 0; j<i; j++)
+ {
+ struct fast_timer *t = &tr[j];
+ printk("%-10s set: %6is %06ius exp: %6is %06ius "
+ "data: 0x%08X func: 0x%08X\n",
+ t->name,
+ t->tv_set.tv_sec,
+ t->tv_set.tv_usec,
+ t->tv_expires.tv_sec,
+ t->tv_expires.tv_usec,
+ t->data,
+ t->function
+ );
+
+ printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n",
+ t->delay_us,
+ tv_exp[j].tv_sec,
+ tv_exp[j].tv_usec,
+ exp_num[j],
+ (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec);
+ }
+ proc_fasttimer_read(buf5, NULL, 0, 0, 0);
+ printk("buf5 after all done:\n");
+ printk(buf5);
+ printk("fast_timer_test() done\n");
+}
+#endif
+
+
+void fast_timer_init(void)
+{
+ /* For some reason, request_irq() hangs when called froom time_init() */
+ if (!fast_timer_is_init)
+ {
+#if 0 && defined(FAST_TIMER_TEST)
+ int i;
+#endif
+
+ printk("fast_timer_init()\n");
+
+#if 0 && defined(FAST_TIMER_TEST)
+ for (i = 0; i <= TIMER0_DIV; i++)
+ {
+ /* We must be careful not to get overflow... */
+ printk("%3i %6u\n", i, timer0_value_us[i]);
+ }
+#endif
+#ifdef CONFIG_PROC_FS
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+ if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
+ fasttimer_proc_entry->read_proc = proc_fasttimer_read;
+#else
+ proc_register_dynamic(&proc_root, &fasttimer_proc_entry);
+#endif
+#endif /* PROC_FS */
+ if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ,
+ "fast timer int", NULL))
+ {
+ printk("err: timer1 irq\n");
+ }
+ fast_timer_is_init = 1;
+#ifdef FAST_TIMER_TEST
+ printk("do test\n");
+ fast_timer_test();
+#endif
+ }
+}
diff --git a/arch/cris/kernel/head.S b/arch/cris/arch-v10/kernel/head.S
index bbd4eb3dd936..8192cd758b4f 100644
--- a/arch/cris/kernel/head.S
+++ b/arch/cris/arch-v10/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.2 2001/12/18 13:35:19 bjornw Exp $
+/* $Id: head.S,v 1.6 2003/04/28 05:31:46 starvik Exp $
*
* Head of the kernel - alter with care
*
@@ -7,6 +7,19 @@
* Authors: Bjorn Wesen (bjornw@axis.com)
*
* $Log: head.S,v $
+ * Revision 1.6 2003/04/28 05:31:46 starvik
+ * Added section attributes
+ *
+ * Revision 1.5 2002/12/11 15:42:02 starvik
+ * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/*.c
+ *
+ * Revision 1.4 2002/11/07 09:00:44 starvik
+ * Names changed for init sections
+ * init_task_union -> init_thread_union
+ *
+ * Revision 1.3 2002/02/05 15:38:23 bjornw
+ * Oops.. non-CRAMFS_MAGIC should jump over the copying, not into it...
+ *
* Revision 1.2 2001/12/18 13:35:19 bjornw
* Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
*
@@ -161,7 +174,7 @@
#define ASSEMBLER_MACROS_ONLY
/* The IO_* macros use the ## token concatenation operator, so
-traditional must not be used when assembling this file. */
-#include <asm/sv_addr_ag.h>
+#include <asm/arch/sv_addr_ag.h>
#define CRAMFS_MAGIC 0x28cd3d45
#define RAM_INIT_MAGIC 0x56902387
@@ -294,7 +307,7 @@
;;
;; arch/etrax100/etrax100.ld sets some symbols that define the start
;; and end of each segment.
-
+
;; Check if we start from DRAM or FLASH by testing PC
move.d $pc,$r0
@@ -311,7 +324,7 @@ _inflash0:
;; Put this in a suitable section where we can reclaim storage
;; after init.
- .section ".text.init"
+ .section ".init.text", "ax"
_inflash:
#ifdef CONFIG_ETRAX_ETHERNET
;; Start MII clock to make sure it is running when tranceiver is reset
@@ -379,7 +392,7 @@ _dram_init_finished:
_inram:
;; Move the ROM fs to after BSS end. This assumes that the cramfs
;; second longword contains the length of the cramfs
-
+
moveq 0, $r0
move.d $r0, [romfs_length] ; default if there is no cramfs
@@ -411,19 +424,20 @@ _inram:
moveq 1, $r0
move.d $r0, [romfs_in_flash]
-
+
jump _start_it ; enter code, cached this time
_no_romfs_in_flash:
+
;; Check if there is a cramfs (magic value).
;; Notice that we check for cramfs magic value - which is
;; the "rom fs" we'll possibly use in 2.4 if not JFFS (which does
;; not need this mechanism anyway)
-
+
move.d __vmlinux_end, $r0; the image will be after the vmlinux end address
move.d [$r0], $r1 ; cramfs assumes same endian on host/target
cmp.d CRAMFS_MAGIC, $r1; magic value in cramfs superblock
- bne 1f
+ bne 2f
nop
;; Ok. What is its size ?
@@ -453,7 +467,8 @@ _no_romfs_in_flash:
subq 1, $r2
bne 1b
nop
-
+
+2:
;; Dont worry that the BSS is tainted. It will be cleared later.
moveq 0, $r0
@@ -462,14 +477,15 @@ _no_romfs_in_flash:
jump _start_it ; better skip the additional cramfs check below
_start_it:
+
;; the kernel stack is overlayed with the task structure for each
;; task. thus the initial kernel stack is in the same page as the
;; init_task (but starts in the top of the page, size 8192)
- move.d init_task_union + 8192, $sp
+ move.d init_thread_union + 8192, $sp
move.d ibr_start,$r0 ; this symbol is set by the linker script
move $r0,$ibr
move.d $r0,[etrax_irv] ; set the interrupt base register and pointer
-
+
;; Clear BSS region, from _bss_start to _end
move.d __bss_start, $r0
@@ -839,5 +855,5 @@ swapper_pg_dir = 0x60002000
swapper_pg_dir = 0xc0002000
#endif
- .section ".data.init"
+ .section ".init.data", "aw"
#include "../lib/hw_settings.S"
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
new file mode 100644
index 000000000000..c5e6348aba1f
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -0,0 +1,219 @@
+/* $Id: irq.c,v 1.1 2002/12/11 15:42:02 starvik Exp $
+ *
+ * linux/arch/cris/kernel/irq.c
+ *
+ * Copyright (c) 2000-2002 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen (bjornw@axis.com)
+ *
+ * This file contains the interrupt vectors and some
+ * helper functions
+ *
+ */
+
+#include <asm/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/config.h>
+
+irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */
+
+/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
+ * global just so that the kernel gdb can use it.
+ */
+
+void
+set_int_vector(int n, irqvectptr addr, irqvectptr saddr)
+{
+ /* remember the shortcut entry point, after the prologue */
+
+ irq_shortcuts[n] = saddr;
+
+ etrax_irv->v[n + 0x20] = (irqvectptr)addr;
+}
+
+/* the breakpoint vector is obviously not made just like the normal irq handlers
+ * but needs to contain _code_ to jump to addr.
+ *
+ * the BREAK n instruction jumps to IBR + n * 8
+ */
+
+void
+set_break_vector(int n, irqvectptr addr)
+{
+ unsigned short *jinstr = (unsigned short *)&etrax_irv->v[n*2];
+ unsigned long *jaddr = (unsigned long *)(jinstr + 1);
+
+ /* if you don't know what this does, do not touch it! */
+
+ *jinstr = 0x0d3f;
+ *jaddr = (unsigned long)addr;
+
+ /* 00000026 <clrlop+1a> 3f0d82000000 jump 0x82 */
+}
+
+/*
+ * This builds up the IRQ handler stubs using some ugly macros in irq.h
+ *
+ * These macros create the low-level assembly IRQ routines that do all
+ * the operations that are needed. They are also written to be fast - and to
+ * disable interrupts as little as humanly possible.
+ *
+ */
+
+/* IRQ0 and 1 are special traps */
+void hwbreakpoint(void);
+void IRQ1_interrupt(void);
+BUILD_TIMER_IRQ(2, 0x04) /* the timer interrupt is somewhat special */
+BUILD_IRQ(3, 0x08)
+BUILD_IRQ(4, 0x10)
+BUILD_IRQ(5, 0x20)
+BUILD_IRQ(6, 0x40)
+BUILD_IRQ(7, 0x80)
+BUILD_IRQ(8, 0x100)
+BUILD_IRQ(9, 0x200)
+BUILD_IRQ(10, 0x400)
+BUILD_IRQ(11, 0x800)
+BUILD_IRQ(12, 0x1000)
+BUILD_IRQ(13, 0x2000)
+void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */
+void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
+BUILD_IRQ(16, 0x10000)
+BUILD_IRQ(17, 0x20000)
+BUILD_IRQ(18, 0x40000)
+BUILD_IRQ(19, 0x80000)
+BUILD_IRQ(20, 0x100000)
+BUILD_IRQ(21, 0x200000)
+BUILD_IRQ(22, 0x400000)
+BUILD_IRQ(23, 0x800000)
+BUILD_IRQ(24, 0x1000000)
+BUILD_IRQ(25, 0x2000000)
+/* IRQ 26-30 are reserved */
+BUILD_IRQ(31, 0x80000000)
+
+/*
+ * Pointers to the low-level handlers
+ */
+
+static void (*interrupt[NR_IRQS])(void) = {
+ NULL, NULL, IRQ2_interrupt, IRQ3_interrupt,
+ IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
+ IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
+ IRQ12_interrupt, IRQ13_interrupt, NULL, NULL,
+ IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,
+ IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,
+ IRQ24_interrupt, IRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
+ IRQ31_interrupt
+};
+
+static void (*sinterrupt[NR_IRQS])(void) = {
+ NULL, NULL, sIRQ2_interrupt, sIRQ3_interrupt,
+ sIRQ4_interrupt, sIRQ5_interrupt, sIRQ6_interrupt, sIRQ7_interrupt,
+ sIRQ8_interrupt, sIRQ9_interrupt, sIRQ10_interrupt, sIRQ11_interrupt,
+ sIRQ12_interrupt, sIRQ13_interrupt, NULL, NULL,
+ sIRQ16_interrupt, sIRQ17_interrupt, sIRQ18_interrupt, sIRQ19_interrupt,
+ sIRQ20_interrupt, sIRQ21_interrupt, sIRQ22_interrupt, sIRQ23_interrupt,
+ sIRQ24_interrupt, sIRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
+ sIRQ31_interrupt
+};
+
+static void (*bad_interrupt[NR_IRQS])(void) = {
+ NULL, NULL,
+ NULL, bad_IRQ3_interrupt,
+ bad_IRQ4_interrupt, bad_IRQ5_interrupt,
+ bad_IRQ6_interrupt, bad_IRQ7_interrupt,
+ bad_IRQ8_interrupt, bad_IRQ9_interrupt,
+ bad_IRQ10_interrupt, bad_IRQ11_interrupt,
+ bad_IRQ12_interrupt, bad_IRQ13_interrupt,
+ NULL, NULL,
+ bad_IRQ16_interrupt, bad_IRQ17_interrupt,
+ bad_IRQ18_interrupt, bad_IRQ19_interrupt,
+ bad_IRQ20_interrupt, bad_IRQ21_interrupt,
+ bad_IRQ22_interrupt, bad_IRQ23_interrupt,
+ bad_IRQ24_interrupt, bad_IRQ25_interrupt,
+ NULL, NULL, NULL, NULL, NULL,
+ bad_IRQ31_interrupt
+};
+
+void arch_setup_irq(int irq)
+{
+ set_int_vector(irq, interrupt[irq], sinterrupt[irq]);
+}
+
+void arch_free_irq(int irq)
+{
+ set_int_vector(irq, bad_interrupt[irq], 0);
+}
+
+void weird_irq(void);
+void system_call(void); /* from entry.S */
+void do_sigtrap(void); /* from entry.S */
+void gdb_handle_breakpoint(void); /* from entry.S */
+
+/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
+ setting the irq vector table to point to bad_interrupt ptrs.
+*/
+
+void __init
+init_IRQ(void)
+{
+ int i;
+
+ /* clear all interrupt masks */
+
+#ifndef CONFIG_SVINTO_SIM
+ *R_IRQ_MASK0_CLR = 0xffffffff;
+ *R_IRQ_MASK1_CLR = 0xffffffff;
+ *R_IRQ_MASK2_CLR = 0xffffffff;
+#endif
+
+ *R_VECT_MASK_CLR = 0xffffffff;
+
+ /* clear the shortcut entry points */
+
+ for(i = 0; i < NR_IRQS; i++)
+ irq_shortcuts[i] = NULL;
+
+ for (i = 0; i < 256; i++)
+ etrax_irv->v[i] = weird_irq;
+
+ /* the entries in the break vector contain actual code to be
+ executed by the associated break handler, rather than just a jump
+ address. therefore we need to setup a default breakpoint handler
+ for all breakpoints */
+
+ for (i = 0; i < 16; i++)
+ set_break_vector(i, do_sigtrap);
+
+ /* set all etrax irq's to the bad handlers */
+ for (i = 2; i < NR_IRQS; i++)
+ set_int_vector(i, bad_interrupt[i], 0);
+
+ /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
+
+ set_int_vector(15, multiple_interrupt, 0);
+
+ /* 0 and 1 which are special breakpoint/NMI traps */
+
+ set_int_vector(0, hwbreakpoint, 0);
+ set_int_vector(1, IRQ1_interrupt, 0);
+
+ /* and irq 14 which is the mmu bus fault handler */
+
+ set_int_vector(14, mmu_bus_fault, 0);
+
+ /* setup the system-call trap, which is reached by BREAK 13 */
+
+ set_break_vector(13, system_call);
+
+ /* setup a breakpoint handler for debugging used for both user and
+ kernel mode debugging (which is why it is not inside an ifdef
+ CONFIG_ETRAX_KGDB) */
+ set_break_vector(8, gdb_handle_breakpoint);
+
+#ifdef CONFIG_ETRAX_KGDB
+ /* setup kgdb if its enabled, and break into the debugger */
+ kgdb_init();
+ breakpoint();
+#endif
+}
diff --git a/arch/cris/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c
index 793c77575c8e..4e5d50d28de5 100644
--- a/arch/cris/kernel/kgdb.c
+++ b/arch/cris/arch-v10/kernel/kgdb.c
@@ -18,8 +18,18 @@
*! Jul 21 1999 Bjorn Wesen eLinux port
*!
*! $Log: kgdb.c,v $
-*! Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
-*! Import of Linux 2.5.1
+*! Revision 1.4 2003/04/09 05:20:44 starvik
+*! Merge of Linux 2.5.67
+*!
+*! Revision 1.3 2003/01/21 19:11:08 starvik
+*! Modified include path for new dir layout
+*!
+*! Revision 1.2 2002/11/19 14:35:24 starvik
+*! Changes from linux 2.4
+*! Changed struct initializer syntax to the currently prefered notation
+*!
+*! Revision 1.1 2001/12/17 13:59:27 bjornw
+*! Initial revision
*!
*! Revision 1.6 2001/10/09 13:10:03 matsfg
*! Added $ on registers and removed some underscores
@@ -58,7 +68,7 @@
*!
*!---------------------------------------------------------------------------
*!
-*! $Id: kgdb.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+*! $Id: kgdb.c,v 1.4 2003/04/09 05:20:44 starvik Exp $
*!
*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
*!
@@ -216,7 +226,7 @@
#include <asm/setup.h>
#include <asm/ptrace.h>
-#include <asm/svinto.h>
+#include <asm/arch/svinto.h>
#include <asm/irq.h>
static int kgdb_started = 0;
@@ -1067,7 +1077,7 @@ handle_exception (int sigval)
int regno = gdb_cris_strtol (&remcomInBuffer[1], &suffix, 16);
int status;
#ifdef PROCESS_SUPPORT
- if (current_thread_g =! executing_task)
+ if (current_thread_g != executing_task)
status = write_stack_register (current_thread_g, regno, suffix+1);
else
#endif
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
new file mode 100644
index 000000000000..62e3a4fbf33a
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -0,0 +1,252 @@
+/* $Id: process.c,v 1.3 2003/07/04 08:27:41 starvik Exp $
+ *
+ * linux/arch/cris/kernel/process.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 2000-2002 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen (bjornw@axis.com)
+ * Mikael Starvik (starvik@axis.com)
+ *
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_ETRAX_GPIO
+void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */
+#endif
+
+/*
+ * We use this if we don't have any better
+ * idle routine..
+ */
+void default_idle(void)
+{
+#ifdef CONFIG_ETRAX_GPIO
+ etrax_gpio_wake_up_check();
+#endif
+}
+
+/* if the watchdog is enabled, we can simply disable interrupts and go
+ * into an eternal loop, and the watchdog will reset the CPU after 0.1s
+ * if on the other hand the watchdog wasn't enabled, we just enable it and wait
+ */
+
+void hard_reset_now (void)
+{
+ /*
+ * Don't declare this variable elsewhere. We don't want any other
+ * code to know about it than the watchdog handler in entry.S and
+ * this code, implementing hard reset through the watchdog.
+ */
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+ extern int cause_of_death;
+#endif
+
+ printk("*** HARD RESET ***\n");
+ local_irq_disable();
+
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+ cause_of_death = 0xbedead;
+#else
+ /* Since we dont plan to keep on reseting the watchdog,
+ the key can be arbitrary hence three */
+ *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, 3) |
+ IO_STATE(R_WATCHDOG, enable, start);
+#endif
+
+ while(1) /* waiting for RETRIBUTION! */ ;
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *t)
+{
+ return (unsigned long)user_regs(t->thread_info)->irp;
+}
+
+static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
+{
+ fn(arg);
+ do_exit(-1); /* Should never be called, return bad exit value */
+}
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(regs));
+
+ /* Don't use r10 since that is set to 0 in copy_thread */
+ regs.r11 = (unsigned long)fn;
+ regs.r12 = (unsigned long)arg;
+ regs.irp = (unsigned long)kernel_thread_helper;
+
+ /* Ok, create the new process.. */
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+
+/* setup the child's kernel stack with a pt_regs and switch_stack on it.
+ * it will be un-nested during _resume and _ret_from_sys_call when the
+ * new thread is scheduled.
+ *
+ * also setup the thread switching structure which is used to keep
+ * thread-specific data during _resumes.
+ *
+ */
+asmlinkage void ret_from_fork(void);
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
+ struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs * childregs;
+ struct switch_stack *swstack;
+
+ /* put the pt_regs structure at the end of the new kernel stack page and fix it up
+ * remember that the task_struct doubles as the kernel stack for the task
+ */
+
+ childregs = user_regs(p->thread_info);
+
+ *childregs = *regs; /* struct copy of pt_regs */
+
+ p->set_child_tid = p->clear_child_tid = NULL;
+
+ childregs->r10 = 0; /* child returns 0 after a fork/clone */
+
+ /* put the switch stack right below the pt_regs */
+
+ swstack = ((struct switch_stack *)childregs) - 1;
+
+ swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */
+
+ /* we want to return into ret_from_sys_call after the _resume */
+
+ swstack->return_ip = (unsigned long) ret_from_fork; /* Will call ret_from_sys_call */
+
+ /* fix the user-mode stackpointer */
+
+ p->thread.usp = usp;
+
+ /* and the kernel-mode one */
+
+ p->thread.ksp = (unsigned long) swstack;
+
+#ifdef DEBUG
+ printk("copy_thread: new regs at 0x%p, as shown below:\n", childregs);
+ show_registers(childregs);
+#endif
+
+ return 0;
+}
+
+/*
+ * Be aware of the "magic" 7th argument in the four system-calls below.
+ * They need the latest stackframe, which is put as the 7th argument by
+ * entry.S. The previous arguments are dummies or actually used, but need
+ * to be defined to reach the 7th argument.
+ *
+ * N.B.: Another method to get the stackframe is to use current_regs(). But
+ * it returns the latest stack-frame stacked when going from _user mode_ and
+ * some of these (at least sys_clone) are called from kernel-mode sometimes
+ * (for example during kernel_thread, above) and thus cannot use it. Thus,
+ * to be sure not to get any surprises, we use the method for the other calls
+ * as well.
+ */
+
+asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
+ struct pt_regs *regs)
+{
+ return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+}
+
+/* if newusp is 0, we just grab the old usp */
+/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
+asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
+ int* parent_tid, int* child_tid, long mof, long srp,
+ struct pt_regs *regs)
+{
+ if (!newusp)
+ newusp = rdusp();
+ return do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0, parent_tid, child_tid);
+}
+
+/* vfork is a system call in i386 because of register-pressure - maybe
+ * we can remove it and handle it in libc but we put it here until then.
+ */
+
+asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
+ struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(const char *fname, char **argv, char **envp,
+ long r13, long mof, long srp,
+ struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname(fname);
+ error = PTR_ERR(filename);
+
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, argv, envp, regs);
+ putname(filename);
+ out:
+ return error;
+}
+
+/*
+ * These bracket the sleeping functions..
+ */
+
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched ((unsigned long) scheduling_functions_start_here)
+#define last_sched ((unsigned long) scheduling_functions_end_here)
+
+unsigned long get_wchan(struct task_struct *p)
+{
+#if 0
+ /* YURGH. TODO. */
+
+ unsigned long ebp, esp, eip;
+ unsigned long stack_page;
+ int count = 0;
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+ stack_page = (unsigned long)p;
+ esp = p->thread.esp;
+ if (!stack_page || esp < stack_page || esp > 8188+stack_page)
+ return 0;
+ /* include/asm-i386/system.h:switch_to() pushes ebp last. */
+ ebp = *(unsigned long *) esp;
+ do {
+ if (ebp < stack_page || ebp > 8184+stack_page)
+ return 0;
+ eip = *(unsigned long *) (ebp+4);
+ if (eip < first_sched || eip >= last_sched)
+ return eip;
+ ebp = *(unsigned long *) ebp;
+ } while (count++ < 16);
+#endif
+ return 0;
+}
+#undef last_sched
+#undef first_sched
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
new file mode 100644
index 000000000000..c83eba5d6d04
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2000-2003, Axis Communications AB.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+
+/*
+ * Determines which bits in DCCR the user has access to.
+ * 1 = access, 0 = no access.
+ */
+#define DCCR_MASK 0x0000001f /* XNZVC */
+
+extern inline long get_reg(struct task_struct *, unsigned int);
+extern inline long put_reg(struct task_struct *, unsigned int, unsigned long);
+
+/*
+ * Called by kernel/ptrace.c when detaching.
+ *
+ * Make sure the single step bit is not set.
+ */
+void
+ptrace_disable(struct task_struct *child)
+{
+ /* Todo - pending singlesteps? */
+}
+
+/*
+ * Note that this implementation of ptrace behaves differently from vanilla
+ * ptrace. Contrary to what the man page says, in the PTRACE_PEEKTEXT,
+ * PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests the data variable is not
+ * ignored. Instead, the data variable is expected to point at a location
+ * (in user space) where the result of the ptrace call is written (instead of
+ * being returned).
+ */
+asmlinkage int
+sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ int ret;
+
+ lock_kernel();
+ ret = -EPERM;
+
+ if (request == PTRACE_TRACEME) {
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+
+ if (child)
+ get_task_struct(child);
+
+ read_unlock(&tasklist_lock);
+
+ if (!child)
+ goto out;
+
+ ret = -EPERM;
+
+ if (pid == 1) /* Leave the init process alone! */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
+ ret = -ESRCH;
+
+ if (!(child->ptrace & PT_PTRACED))
+ goto out_tsk;
+
+ if (child->state != TASK_STOPPED) {
+ if (request != PTRACE_KILL)
+ goto out_tsk;
+ }
+
+ if (child->parent != current)
+ goto out_tsk;
+
+ switch (request) {
+ /* Read word at location address. */
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+
+ if (copied != sizeof(tmp))
+ break;
+
+ ret = put_user(tmp,(unsigned long *) data);
+ break;
+ }
+
+ /* Read the word at location address in the USER area. */
+ case PTRACE_PEEKUSR: {
+ unsigned long tmp;
+
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+ break;
+
+ tmp = 0; /* Default return condition */
+ ret = -EIO;
+
+ if (addr < sizeof(struct pt_regs)) {
+ tmp = get_reg(child, addr >> 2);
+ ret = put_user(tmp, (unsigned long *)data);
+ }
+
+ break;
+ }
+
+ /* Write the word at location address. */
+ case PTRACE_POKETEXT:
+ case PTRACE_POKEDATA:
+ ret = 0;
+
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ break;
+
+ ret = -EIO;
+ break;
+
+ /* Write the word at location address in the USER area. */
+ case PTRACE_POKEUSR:
+ ret = -EIO;
+
+ if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+ break;
+
+ if (addr < sizeof(struct pt_regs)) {
+ addr >>= 2;
+
+ if (addr == PT_DCCR) {
+ /*
+ * Don't allow the tracing process to
+ * change stuff like interrupt enable,
+ * kernel/user bit, etc.
+ */
+ data &= DCCR_MASK;
+ data |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
+ }
+
+ if (put_reg(child, addr, data))
+ break;
+
+ ret = 0;
+ }
+ break;
+
+ case PTRACE_SYSCALL:
+ case PTRACE_CONT:
+ ret = -EIO;
+
+ if ((unsigned long) data > _NSIG)
+ break;
+
+ if (request == PTRACE_SYSCALL) {
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+ else {
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+
+ child->exit_code = data;
+
+ /* TODO: make sure any pending breakpoint is killed */
+ wake_up_process(child);
+ ret = 0;
+
+ break;
+
+ /* Make the child exit by sending it a sigkill. */
+ case PTRACE_KILL:
+ ret = 0;
+
+ if (child->state == TASK_ZOMBIE)
+ break;
+
+ child->exit_code = SIGKILL;
+
+ /* TODO: make sure any pending breakpoint is killed */
+ wake_up_process(child);
+ break;
+
+ /* Set the trap flag. */
+ case PTRACE_SINGLESTEP:
+ ret = -EIO;
+
+ if ((unsigned long) data > _NSIG)
+ break;
+
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+ /* TODO: set some clever breakpoint mechanism... */
+
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+
+ case PTRACE_DETACH:
+ ret = ptrace_detach(child, data);
+ break;
+
+ /* Get all GP registers from the child. */
+ case PTRACE_GETREGS: {
+ int i;
+ unsigned long tmp;
+
+ for (i = 0; i <= PT_MAX; i++) {
+ tmp = get_reg(child, i);
+
+ if (put_user(tmp, (unsigned long *) data)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ data += sizeof(long);
+ }
+
+ ret = 0;
+ break;
+ }
+
+ /* Set all GP registers in the child. */
+ case PTRACE_SETREGS: {
+ int i;
+ unsigned long tmp;
+
+ for (i = 0; i <= PT_MAX; i++) {
+ if (get_user(tmp, (unsigned long *) data)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ if (i == PT_DCCR) {
+ tmp &= DCCR_MASK;
+ tmp |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
+ }
+
+ put_reg(child, i, tmp);
+ data += sizeof(long);
+ }
+
+ ret = 0;
+ break;
+ }
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+void do_syscall_trace(void)
+{
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+
+ current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0);
+
+ current->state = TASK_STOPPED;
+ notify_parent(current, SIGCHLD);
+ schedule();
+
+ /*
+ * This isn't the same as continuing with a signal, but it will do for
+ * normal use.
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/cris/arch-v10/kernel/setup.c b/arch/cris/arch-v10/kernel/setup.c
new file mode 100644
index 000000000000..d95930270a9b
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/setup.c
@@ -0,0 +1,96 @@
+/* $Id: setup.c,v 1.1 2002/12/11 15:42:02 starvik Exp $
+ *
+ * linux/arch/cris/arch-v10/kernel/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (c) 2001-2002 Axis Communications AB
+ */
+
+/*
+ * This file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/config.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_PROC_FS
+#define HAS_FPU 0x0001
+#define HAS_MMU 0x0002
+#define HAS_ETHERNET100 0x0004
+#define HAS_TOKENRING 0x0008
+#define HAS_SCSI 0x0010
+#define HAS_ATA 0x0020
+#define HAS_USB 0x0040
+#define HAS_IRQ_BUG 0x0080
+#define HAS_MMU_BUG 0x0100
+
+static struct cpu_info {
+ char *model;
+ unsigned short cache;
+ unsigned short flags;
+} cpu_info[] = {
+ /* The first four models will never ever run this code and are
+ only here for display. */
+ { "ETRAX 1", 0, 0 },
+ { "ETRAX 2", 0, 0 },
+ { "ETRAX 3", 0, HAS_TOKENRING },
+ { "ETRAX 4", 0, HAS_TOKENRING | HAS_SCSI },
+ { "Unknown", 0, 0 },
+ { "Unknown", 0, 0 },
+ { "Unknown", 0, 0 },
+ { "Simulator", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
+ { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG },
+ { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
+ { "ETRAX 100LX", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU | HAS_MMU_BUG },
+ { "ETRAX 100LX v2", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU },
+ { "Unknown", 0, 0 } /* This entry MUST be the last */
+};
+
+int show_cpuinfo(struct seq_file *m, void *v)
+{
+ unsigned long revision;
+ struct cpu_info *info;
+
+ /* read the version register in the CPU and print some stuff */
+
+ revision = rdvr();
+
+ if (revision >= sizeof cpu_info/sizeof *cpu_info)
+ info = &cpu_info[sizeof cpu_info/sizeof *cpu_info - 1];
+ else
+ info = &cpu_info[revision];
+
+ return seq_printf(m,
+ "processor\t: 0\n"
+ "cpu\t\t: CRIS\n"
+ "cpu revision\t: %lu\n"
+ "cpu model\t: %s\n"
+ "cache size\t: %d kB\n"
+ "fpu\t\t: %s\n"
+ "mmu\t\t: %s\n"
+ "mmu DMA bug\t: %s\n"
+ "ethernet\t: %s Mbps\n"
+ "token ring\t: %s\n"
+ "scsi\t\t: %s\n"
+ "ata\t\t: %s\n"
+ "usb\t\t: %s\n"
+ "bogomips\t: %lu.%02lu\n",
+
+ revision,
+ info->model,
+ info->cache,
+ info->flags & HAS_FPU ? "yes" : "no",
+ info->flags & HAS_MMU ? "yes" : "no",
+ info->flags & HAS_MMU_BUG ? "yes" : "no",
+ info->flags & HAS_ETHERNET100 ? "10/100" : "10",
+ info->flags & HAS_TOKENRING ? "4/16 Mbps" : "no",
+ info->flags & HAS_SCSI ? "yes" : "no",
+ info->flags & HAS_ATA ? "yes" : "no",
+ info->flags & HAS_USB ? "yes" : "no",
+ (loops_per_jiffy * HZ + 500) / 500000,
+ ((loops_per_jiffy * HZ + 500) / 5000) % 100);
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/cris/kernel/shadows.c b/arch/cris/arch-v10/kernel/shadows.c
index 25fac64945e4..561a890a8e4c 100644
--- a/arch/cris/kernel/shadows.c
+++ b/arch/cris/arch-v10/kernel/shadows.c
@@ -1,4 +1,4 @@
-/* $Id: shadows.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: shadows.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $
*
* Various shadow registers. Defines for these are in include/asm-etrax100/io.h
*/
diff --git a/arch/cris/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 678281dae205..6698054a576c 100644
--- a/arch/cris/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -55,11 +55,11 @@ sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
sigset_t saveset;
mask &= _BLOCKABLE;
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sighand->siglock);
regs->r10 = -EINTR;
while (1) {
@@ -94,11 +94,11 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, long r12, long r13,
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sighand->siglock);
regs->r10 = -EINTR;
while (1) {
@@ -117,7 +117,7 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, long r12, long r13,
}
int
-sys_sigaction(int sig, const struct old_sigaction *act,
+sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction *oact)
{
struct k_sigaction new_ka, old_ka;
@@ -149,7 +149,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
}
int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+sys_sigaltstack(const stack_t *uss, stack_t __user *uoss)
{
return do_sigaltstack(uss, uoss, rdusp());
}
@@ -175,7 +175,7 @@ struct rt_sigframe {
static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
unsigned int err = 0;
unsigned long old_usp;
@@ -217,7 +217,7 @@ badframe:
asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
long srp, struct pt_regs *regs)
{
- struct sigframe *frame = (struct sigframe *)rdusp();
+ struct sigframe __user *frame = (struct sigframe *)rdusp();
sigset_t set;
/*
@@ -232,15 +232,15 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
- && __copy_from_user(&set.sig[1], &frame->extramask,
+ && __copy_from_user(&set.sig[1], frame->extramask,
sizeof(frame->extramask))))
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sighand->siglock);
current->blocked = set;
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sighand->siglock);
if (restore_sigcontext(regs, &frame->sc))
goto badframe;
@@ -259,7 +259,7 @@ badframe:
asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
long mof, long srp, struct pt_regs *regs)
{
- struct rt_sigframe *frame = (struct rt_sigframe *)rdusp();
+ struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp();
sigset_t set;
stack_t st;
@@ -277,10 +277,10 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sighand->siglock);
current->blocked = set;
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sighand->siglock);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -303,7 +303,7 @@ badframe:
*/
static int
-setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask)
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask)
{
int err = 0;
unsigned long usp = rdusp();
@@ -328,7 +328,7 @@ setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask
/* figure out where we want to put the new signal frame - usually on the stack */
-static inline void *
+static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
{
unsigned long sp = rdusp();
@@ -343,7 +343,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
sp &= ~3;
- return (void *)(sp - frame_size);
+ return (void __user*)(sp - frame_size);
}
/* grab and setup a signal frame.
@@ -357,7 +357,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
static void setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs * regs)
{
- struct sigframe *frame;
+ struct sigframe __user *frame;
unsigned long return_ip;
int err = 0;
@@ -414,7 +414,7 @@ give_sigsegv:
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
- struct rt_sigframe *frame;
+ struct rt_sigframe __user *frame;
unsigned long return_ip;
int err = 0;
@@ -481,16 +481,18 @@ give_sigsegv:
* OK, we're invoking a handler
*/
-static inline void
+extern inline void
handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
- struct k_sigaction *ka = &current->sig->action[sig-1];
+ struct k_sigaction *ka = &current->sighand->action[sig-1];
/* Are we from a system call? */
if (canrestart) {
/* If so, check system call restarting.. */
switch (regs->r10) {
+ case -ERESTART_RESTARTBLOCK:
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
case -ERESTARTNOHAND:
/* ERESTARTNOHAND means that the syscall should only be
restarted if there was no handler for the signal, and since
@@ -523,11 +525,11 @@ handle_signal(int canrestart, unsigned long sig,
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
sigaddset(&current->blocked,sig);
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sighand->siglock);
}
}
@@ -575,6 +577,10 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
regs->r10 == -ERESTARTNOINTR) {
RESTART_CRIS_SYS(regs);
}
+ if (regs->r10 == -ERESTART_RESTARTBLOCK){
+ regs->r10 = __NR_restart_syscall;
+ regs->irp -= 2;
+ }
}
return 0;
}
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
new file mode 100644
index 000000000000..31e83a84e4a6
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -0,0 +1,359 @@
+/* $Id: time.c,v 1.2 2003/07/04 08:27:41 starvik Exp $
+ *
+ * linux/arch/cris/arch-v10/kernel/time.c
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Copyright (C) 1999-2002 Axis Communications AB
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/timex.h>
+#include <linux/time.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/swap.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/arch/svinto.h>
+#include <asm/types.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/rtc.h>
+
+/* define this if you need to use print_timestamp */
+/* it will make jiffies at 96 hz instead of 100 hz though */
+#undef USE_CASCADE_TIMERS
+
+extern void update_xtime_from_cmos(void);
+extern int set_rtc_mmss(unsigned long nowtime);
+extern int setup_irq(int, struct irqaction *);
+extern int have_rtc;
+
+unsigned long get_ns_in_jiffie(void)
+{
+ unsigned char timer_count, t1;
+ unsigned short presc_count;
+ unsigned long ns;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ local_irq_disable();
+ timer_count = *R_TIMER0_DATA;
+ presc_count = *R_TIM_PRESC_STATUS;
+ /* presc_count might be wrapped */
+ t1 = *R_TIMER0_DATA;
+
+ if (timer_count != t1){
+ /* it wrapped, read prescaler again... */
+ presc_count = *R_TIM_PRESC_STATUS;
+ timer_count = t1;
+ }
+ local_irq_restore(flags);
+ if (presc_count >= PRESCALE_VALUE/2 ){
+ presc_count = PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2;
+ } else {
+ presc_count = PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2;
+ }
+
+ ns = ( (TIMER0_DIV - timer_count) * ((1000000000/HZ)/TIMER0_DIV )) +
+ ( (presc_count) * (1000000000/PRESCALE_FREQ));
+ return ns;
+}
+
+unsigned long do_slow_gettimeoffset(void)
+{
+ unsigned long count, t1;
+ unsigned long usec_count = 0;
+ unsigned short presc_count;
+
+ static unsigned long count_p = TIMER0_DIV;/* for the first call after boot */
+ static unsigned long jiffies_p = 0;
+
+ /*
+ * cache volatile jiffies temporarily; we have IRQs turned off.
+ */
+ unsigned long jiffies_t;
+
+ /* The timer interrupt comes from Etrax timer 0. In order to get
+ * better precision, we check the current value. It might have
+ * underflowed already though.
+ */
+
+#ifndef CONFIG_SVINTO_SIM
+ /* Not available in the xsim simulator. */
+ count = *R_TIMER0_DATA;
+ presc_count = *R_TIM_PRESC_STATUS;
+ /* presc_count might be wrapped */
+ t1 = *R_TIMER0_DATA;
+ if (count != t1){
+ /* it wrapped, read prescaler again... */
+ presc_count = *R_TIM_PRESC_STATUS;
+ count = t1;
+ }
+#else
+ count = 0;
+ presc_count = 0;
+#endif
+
+ jiffies_t = jiffies;
+
+ /*
+ * avoiding timer inconsistencies (they are rare, but they happen)...
+ * there are one problem that must be avoided here:
+ * 1. the timer counter underflows
+ */
+ if( jiffies_t == jiffies_p ) {
+ if( count > count_p ) {
+ /* Timer wrapped, use new count and prescale
+ * increase the time corresponding to one jiffie
+ */
+ usec_count = 1000000/HZ;
+ }
+ } else
+ jiffies_p = jiffies_t;
+ count_p = count;
+ if (presc_count >= PRESCALE_VALUE/2 ){
+ presc_count = PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2;
+ } else {
+ presc_count = PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2;
+ }
+ /* Convert timer value to usec */
+ usec_count += ( (TIMER0_DIV - count) * (1000000/HZ)/TIMER0_DIV ) +
+ (( (presc_count) * (1000000000/PRESCALE_FREQ))/1000);
+
+ return usec_count;
+}
+
+/* Excerpt from the Etrax100 HSDD about the built-in watchdog:
+ *
+ * 3.10.4 Watchdog timer
+
+ * When the watchdog timer is started, it generates an NMI if the watchdog
+ * isn't restarted or stopped within 0.1 s. If it still isn't restarted or
+ * stopped after an additional 3.3 ms, the watchdog resets the chip.
+ * The watchdog timer is stopped after reset. The watchdog timer is controlled
+ * by the R_WATCHDOG register. The R_WATCHDOG register contains an enable bit
+ * and a 3-bit key value. The effect of writing to the R_WATCHDOG register is
+ * described in the table below:
+ *
+ * Watchdog Value written:
+ * state: To enable: To key: Operation:
+ * -------- ---------- ------- ----------
+ * stopped 0 X No effect.
+ * stopped 1 key_val Start watchdog with key = key_val.
+ * started 0 ~key Stop watchdog
+ * started 1 ~key Restart watchdog with key = ~key.
+ * started X new_key_val Change key to new_key_val.
+ *
+ * Note: '~' is the bitwise NOT operator.
+ *
+ */
+
+/* right now, starting the watchdog is the same as resetting it */
+#define start_watchdog reset_watchdog
+
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+static int watchdog_key = 0; /* arbitrary number */
+#endif
+
+/* number of pages to consider "out of memory". it is normal that the memory
+ * is used though, so put this really low.
+ */
+
+#define WATCHDOG_MIN_FREE_PAGES 8
+
+void
+reset_watchdog(void)
+{
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+ /* only keep watchdog happy as long as we have memory left! */
+ if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {
+ /* reset the watchdog with the inverse of the old key */
+ watchdog_key ^= 0x7; /* invert key, which is 3 bits */
+ *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
+ IO_STATE(R_WATCHDOG, enable, start);
+ }
+#endif
+}
+
+/* stop the watchdog - we still need the correct key */
+
+void
+stop_watchdog(void)
+{
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+ watchdog_key ^= 0x7; /* invert key, which is 3 bits */
+ *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
+ IO_STATE(R_WATCHDOG, enable, stop);
+#endif
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+
+//static unsigned short myjiff; /* used by our debug routine print_timestamp */
+
+static inline irqreturn_t
+timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* acknowledge the timer irq */
+
+#ifdef USE_CASCADE_TIMERS
+ *R_TIMER_CTRL =
+ IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
+ IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
+ IO_STATE( R_TIMER_CTRL, i1, clr) |
+ IO_STATE( R_TIMER_CTRL, tm1, run) |
+ IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
+ IO_STATE( R_TIMER_CTRL, i0, clr) |
+ IO_STATE( R_TIMER_CTRL, tm0, run) |
+ IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
+#else
+ *R_TIMER_CTRL = r_timer_ctrl_shadow |
+ IO_STATE(R_TIMER_CTRL, i0, clr);
+#endif
+
+ /* reset watchdog otherwise it resets us! */
+
+ reset_watchdog();
+
+ /* call the real timer interrupt handler */
+
+ do_timer(regs);
+
+ /*
+ * If we have an externally synchronized Linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ *
+ * The division here is not time critical since it will run once in
+ * 11 minutes
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ (xtime.tv_nsec / 1000) >= 500000 - (tick_nsec / 1000) / 2 &&
+ (xtime.tv_nsec / 1000) <= 500000 + (tick_nsec / 1000) / 2) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+ return IRQ_HANDLED;
+}
+
+/* timer is SA_SHIRQ so drivers can add stuff to the timer irq chain
+ * it needs to be SA_INTERRUPT to make the jiffies update work properly
+ */
+
+static struct irqaction irq2 = { timer_interrupt, SA_SHIRQ | SA_INTERRUPT,
+ 0, "timer", NULL, NULL};
+
+void __init
+time_init(void)
+{
+ /* probe for the RTC and read it if it exists
+ * Before the RTC can be probed the loops_per_usec variable needs
+ * to be initialized to make usleep work. A better value for
+ * loops_per_usec is calculated by the kernel later once the
+ * clock has started.
+ */
+ loops_per_usec = 50;
+
+ if(RTC_INIT() < 0) {
+ /* no RTC, start at 1980 */
+ xtime.tv_sec = 0;
+ xtime.tv_nsec = 0;
+ have_rtc = 0;
+ } else {
+ /* get the current time */
+ have_rtc = 1;
+ update_xtime_from_cmos();
+ }
+
+ /* Setup the etrax timers
+ * Base frequency is 25000 hz, divider 250 -> 100 HZ
+ * In normal mode, we use timer0, so timer1 is free. In cascade
+ * mode (which we sometimes use for debugging) both timers are used.
+ * Remember that linux/timex.h contains #defines that rely on the
+ * timer settings below (hz and divide factor) !!!
+ */
+
+#ifdef USE_CASCADE_TIMERS
+ *R_TIMER_CTRL =
+ IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
+ IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
+ IO_STATE( R_TIMER_CTRL, i1, nop) |
+ IO_STATE( R_TIMER_CTRL, tm1, stop_ld) |
+ IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
+ IO_STATE( R_TIMER_CTRL, i0, nop) |
+ IO_STATE( R_TIMER_CTRL, tm0, stop_ld) |
+ IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
+
+ *R_TIMER_CTRL = r_timer_ctrl_shadow =
+ IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
+ IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
+ IO_STATE( R_TIMER_CTRL, i1, nop) |
+ IO_STATE( R_TIMER_CTRL, tm1, run) |
+ IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
+ IO_STATE( R_TIMER_CTRL, i0, nop) |
+ IO_STATE( R_TIMER_CTRL, tm0, run) |
+ IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
+#else
+ *R_TIMER_CTRL =
+ IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) |
+ IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) |
+ IO_STATE(R_TIMER_CTRL, i1, nop) |
+ IO_STATE(R_TIMER_CTRL, tm1, stop_ld) |
+ IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) |
+ IO_STATE(R_TIMER_CTRL, i0, nop) |
+ IO_STATE(R_TIMER_CTRL, tm0, stop_ld) |
+ IO_STATE(R_TIMER_CTRL, clksel0, flexible);
+
+ *R_TIMER_CTRL = r_timer_ctrl_shadow =
+ IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) |
+ IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) |
+ IO_STATE(R_TIMER_CTRL, i1, nop) |
+ IO_STATE(R_TIMER_CTRL, tm1, run) |
+ IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) |
+ IO_STATE(R_TIMER_CTRL, i0, nop) |
+ IO_STATE(R_TIMER_CTRL, tm0, run) |
+ IO_STATE(R_TIMER_CTRL, clksel0, flexible);
+
+ *R_TIMER_PRESCALE = PRESCALE_VALUE;
+#endif
+
+ *R_IRQ_MASK0_SET =
+ IO_STATE(R_IRQ_MASK0_SET, timer0, set); /* unmask the timer irq */
+
+ /* now actually register the timer irq handler that calls timer_interrupt() */
+
+ setup_irq(2, &irq2); /* irq 2 is the timer0 irq in etrax */
+
+ /* enable watchdog if we should use one */
+
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+ printk("Enabling watchdog...\n");
+ start_watchdog();
+
+ /* If we use the hardware watchdog, we want to trap it as an NMI
+ and dump registers before it resets us. For this to happen, we
+ must set the "m" NMI enable flag (which once set, is unset only
+ when an NMI is taken).
+
+ The same goes for the external NMI, but that doesn't have any
+ driver or infrastructure support yet. */
+ asm ("setf m");
+
+ *R_IRQ_MASK0_SET =
+ IO_STATE(R_IRQ_MASK0_SET, watchdog_nmi, set);
+ *R_VECT_MASK_SET =
+ IO_STATE(R_VECT_MASK_SET, nmi, set);
+#endif
+}
diff --git a/arch/cris/arch-v10/kernel/traps.c b/arch/cris/arch-v10/kernel/traps.c
new file mode 100644
index 000000000000..da491f438a6e
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/traps.c
@@ -0,0 +1,132 @@
+/* $Id: traps.c,v 1.2 2003/07/04 08:27:41 starvik Exp $
+ *
+ * linux/arch/cris/arch-v10/traps.c
+ *
+ * Heler functions for trap handlers
+ *
+ * Copyright (C) 2000-2002 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen
+ * Hans-Peter Nilsson
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <asm/uaccess.h>
+#include <asm/arch/sv_addr_ag.h>
+
+void
+show_registers(struct pt_regs * regs)
+{
+ /* We either use rdusp() - the USP register, which might not
+ correspond to the current process for all cases we're called,
+ or we use the current->thread.usp, which is not up to date for
+ the current process. Experience shows we want the USP
+ register. */
+ unsigned long usp = rdusp();
+
+ printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
+ regs->irp, regs->srp, regs->dccr, usp, regs->mof );
+ printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
+ regs->r0, regs->r1, regs->r2, regs->r3);
+ printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
+ regs->r4, regs->r5, regs->r6, regs->r7);
+ printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
+ regs->r8, regs->r9, regs->r10, regs->r11);
+ printk("r12: %08lx r13: %08lx oR10: %08lx\n",
+ regs->r12, regs->r13, regs->orig_r10);
+ printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
+ current->comm, current->pid, (unsigned long)current);
+
+ /*
+ * When in-kernel, we also print out the stack and code at the
+ * time of the fault..
+ */
+ if (! user_mode(regs)) {
+ int i;
+
+ show_stack(NULL, (unsigned long*)usp);
+
+ /* Dump kernel stack if the previous dump wasn't one. */
+ if (usp != 0)
+ show_stack (NULL, NULL);
+
+ printk("\nCode: ");
+ if(regs->irp < PAGE_OFFSET)
+ goto bad;
+
+ /* Often enough the value at regs->irp does not point to
+ the interesting instruction, which is most often the
+ _previous_ instruction. So we dump at an offset large
+ enough that instruction decoding should be in sync at
+ the interesting point, but small enough to fit on a row
+ (sort of). We point out the regs->irp location in a
+ ksymoops-friendly way by wrapping the byte for that
+ address in parentheses. */
+ for(i = -12; i < 12; i++)
+ {
+ unsigned char c;
+ if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
+bad:
+ printk(" Bad IP value.");
+ break;
+ }
+
+ if (i == 0)
+ printk("(%02x) ", c);
+ else
+ printk("%02x ", c);
+ }
+ printk("\n");
+ }
+}
+
+/* Called from entry.S when the watchdog has bitten
+ * We print out something resembling an oops dump, and if
+ * we have the nice doggy development flag set, we halt here
+ * instead of rebooting.
+ */
+
+extern void reset_watchdog(void);
+extern void stop_watchdog(void);
+
+
+void
+watchdog_bite_hook(struct pt_regs *regs)
+{
+#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
+ local_irq_disable();
+ stop_watchdog();
+ show_registers(regs);
+ while(1) /* nothing */;
+#else
+ show_registers(regs);
+#endif
+}
+
+/* This is normally the 'Oops' routine */
+void
+die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+ if(user_mode(regs))
+ return;
+
+#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
+ /* This printout might take too long and trigger the
+ * watchdog normally. If we're in the nice doggy
+ * development mode, stop the watchdog during printout.
+ */
+ stop_watchdog();
+#endif
+
+ printk("%s: %04lx\n", str, err & 0xffff);
+
+ show_registers(regs);
+
+#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
+ reset_watchdog();
+#endif
+ do_exit(SIGSEGV);
+}
diff --git a/arch/cris/lib/Makefile b/arch/cris/arch-v10/lib/Makefile
index 568496a8884e..36e9a9c5239b 100644
--- a/arch/cris/lib/Makefile
+++ b/arch/cris/arch-v10/lib/Makefile
@@ -2,6 +2,8 @@
# Makefile for Etrax-specific library files..
#
+
EXTRA_AFLAGS := -traditional
lib-y = checksum.o checksumcopy.o string.o usercopy.o memset.o csumcpfruser.o
+
diff --git a/arch/cris/lib/checksum.S b/arch/cris/arch-v10/lib/checksum.S
index fd15a76f78d6..85c48f0a9ec2 100644
--- a/arch/cris/lib/checksum.S
+++ b/arch/cris/arch-v10/lib/checksum.S
@@ -1,4 +1,4 @@
-/* $Id: checksum.S,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: checksum.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
* A fast checksum routine using movem
* Copyright (c) 1998-2001 Axis Communications AB
*
diff --git a/arch/cris/lib/checksumcopy.S b/arch/cris/arch-v10/lib/checksumcopy.S
index 4d8bc348da39..35cbffb306fd 100644
--- a/arch/cris/lib/checksumcopy.S
+++ b/arch/cris/arch-v10/lib/checksumcopy.S
@@ -1,4 +1,4 @@
-/* $Id: checksumcopy.S,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: checksumcopy.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
* A fast checksum+copy routine using movem
* Copyright (c) 1998, 2001 Axis Communications AB
*
diff --git a/arch/cris/lib/csumcpfruser.S b/arch/cris/arch-v10/lib/csumcpfruser.S
index 5f41ccd62754..5f41ccd62754 100644
--- a/arch/cris/lib/csumcpfruser.S
+++ b/arch/cris/arch-v10/lib/csumcpfruser.S
diff --git a/arch/cris/lib/dmacopy.c b/arch/cris/arch-v10/lib/dmacopy.c
index fe8f091ed09c..e5fb44f505c5 100644
--- a/arch/cris/lib/dmacopy.c
+++ b/arch/cris/arch-v10/lib/dmacopy.c
@@ -1,4 +1,4 @@
-/* $Id: dmacopy.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: dmacopy.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $
*
* memcpy for large blocks, using memory-memory DMA channels 6 and 7 in Etrax
*/
diff --git a/arch/cris/lib/dram_init.S b/arch/cris/arch-v10/lib/dram_init.S
index d46efd1aef1f..4852709dc7aa 100644
--- a/arch/cris/lib/dram_init.S
+++ b/arch/cris/arch-v10/lib/dram_init.S
@@ -1,4 +1,4 @@
-/* $Id: dram_init.S,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: dram_init.S,v 1.3 2003/03/31 09:38:37 starvik Exp $
*
* DRAM/SDRAM initialization - alter with care
* This file is intended to be included from other assembler files
@@ -11,8 +11,20 @@
* Authors: Mikael Starvik (starvik@axis.com)
*
* $Log: dram_init.S,v $
- * Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
- * Import of Linux 2.5.1
+ * Revision 1.3 2003/03/31 09:38:37 starvik
+ * Corrected calculation of end of sdram init commands
+ *
+ * Revision 1.2 2002/11/19 13:33:29 starvik
+ * Changes from Linux 2.4
+ *
+ * Revision 1.13 2002/10/30 07:42:28 starvik
+ * Always read SDRAM command sequence from flash
+ *
+ * Revision 1.12 2002/08/09 11:37:37 orjanf
+ * Added double initialization work-around for Samsung SDRAMs.
+ *
+ * Revision 1.11 2002/06/04 11:43:21 starvik
+ * Check if mrs_data is specified in kernelconfig (necessary for MCM)
*
* Revision 1.10 2001/10/04 12:00:21 martinnn
* Added missing underscores.
@@ -73,7 +85,11 @@
move.d CONFIG_ETRAX_DEF_R_DRAM_TIMING, $r0
move.d $r0, [R_DRAM_TIMING]
-#else
+#else
+ ;; Samsung SDRAMs seem to require to be initialized twice to work properly.
+ moveq 2, $r6
+_sdram_init:
+
; Refer to ETRAX 100LX Designers Reference for a description of SDRAM initialization
; Bank configuration
@@ -85,6 +101,12 @@
; CAS latency = 3 && bus_width = 32 => 0x60
; CAS latency = 2 && bus_width = 16 => 0x20
; CAS latency = 3 && bus_width = 16 => 0x30
+
+ ; Check if value is already supplied in kernel config
+ move.d CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r2
+ and.d 0x00ff0000, $r2
+ bne _set_timing
+ lsrq 16, $r2
move.d 0x40, $r2 ; Assume 32 bits and CAS latency = 2
move.d CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r1
@@ -130,7 +152,9 @@ _set_timing:
; Issue initialization command sequence
move.d _sdram_commands_start, $r2
+ and.d 0x00ffffff, $r2 ; Make sure commands are read from flash
move.d _sdram_commands_end, $r3
+ and.d 0x00ffffff, $r3
1: clear.d $r4
move.b [$r2+], $r4
lslq 9, $r4 ; Command starts at bit 9
@@ -145,6 +169,9 @@ _set_timing:
bne 1b
nop
move.d $r5, [R_SDRAM_TIMING]
+ subq 1, $r6
+ bne _sdram_init
+ nop
ba _sdram_commands_end
nop
diff --git a/arch/cris/lib/hw_settings.S b/arch/cris/arch-v10/lib/hw_settings.S
index b35bb3baa5aa..56905aaa7b6e 100644
--- a/arch/cris/lib/hw_settings.S
+++ b/arch/cris/arch-v10/lib/hw_settings.S
@@ -1,5 +1,5 @@
/*
- * $Id: hw_settings.S,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+ * $Id: hw_settings.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
*
* This table is used by some tools to extract hardware parameters.
* The table should be included in the kernel and the decompressor.
diff --git a/arch/cris/lib/memset.c b/arch/cris/arch-v10/lib/memset.c
index 82bb66839171..82bb66839171 100644
--- a/arch/cris/lib/memset.c
+++ b/arch/cris/arch-v10/lib/memset.c
diff --git a/arch/cris/lib/old_checksum.c b/arch/cris/arch-v10/lib/old_checksum.c
index 5d4d9bc4b057..3b68d1a60a0a 100644
--- a/arch/cris/lib/old_checksum.c
+++ b/arch/cris/arch-v10/lib/old_checksum.c
@@ -1,4 +1,4 @@
-/* $Id: old_checksum.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: old_checksum.c,v 1.2 2002/11/05 06:45:12 starvik Exp $
*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
@@ -75,7 +75,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
sum += *((unsigned short *)buff)++;
}
if(endMarker - buff > 0) {
- sum += *buff; /* add extra byte separately */
+ sum += *buff; /* add extra byte seperately */
}
BITOFF;
return(sum);
diff --git a/arch/cris/lib/string.c b/arch/cris/arch-v10/lib/string.c
index 8ffde4901b57..8ffde4901b57 100644
--- a/arch/cris/lib/string.c
+++ b/arch/cris/arch-v10/lib/string.c
diff --git a/arch/cris/lib/usercopy.c b/arch/cris/arch-v10/lib/usercopy.c
index fc0b89cc57fe..43778d53c254 100644
--- a/arch/cris/lib/usercopy.c
+++ b/arch/cris/arch-v10/lib/usercopy.c
@@ -31,7 +31,7 @@
kernel-to-kernel copying; see "string.c". */
unsigned long
-__copy_user (void *pdst, const void *psrc, unsigned long pn)
+__copy_user (void __user *pdst, const void *psrc, unsigned long pn)
{
/* We want the parameters put in special registers.
Make sure the compiler is able to make something useful of this.
@@ -88,11 +88,11 @@ __copy_user (void *pdst, const void *psrc, unsigned long pn)
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
"r13=r13, r11=r11, r12=r12". */
- __asm__ volatile ("
- ;; Check that the following is true (same register names on
- ;; both sides of equal sign, as in r8=r8):
- ;; %0=r13, %1=r11, %2=r12 %3=r10
- ;;
+ __asm__ volatile ("\
+ .ifnc %0%1%2%3,$r13$r11$r12$r10 \n\
+ .err \n\
+ .endif \n\
+
;; Save the registers we'll use in the movem process
;; on the stack.
subq 11*4,$sp
@@ -189,10 +189,11 @@ __copy_user (void *pdst, const void *psrc, unsigned long pn)
}
/* Copy from user to kernel, zeroing the bytes that were inaccessible in
- userland. */
+ userland. The return-value is the number of bytes that were
+ inaccessible. */
unsigned long
-__copy_user_zeroing (void *pdst, const void *psrc, unsigned long pn)
+__copy_user_zeroing (void __user *pdst, const void *psrc, unsigned long pn)
{
/* We want the parameters put in special registers.
Make sure the compiler is able to make something useful of this.
@@ -207,30 +208,34 @@ __copy_user_zeroing (void *pdst, const void *psrc, unsigned long pn)
register int n __asm__ ("r12") = pn;
register int retn __asm__ ("r10") = 0;
- /* When src is aligned but not dst, this makes a few extra needless
- cycles. I believe it would take as many to check that the
- re-alignment was unnecessary. */
- if (((unsigned long) dst & 3) != 0
- /* Don't align if we wouldn't copy more than a few bytes; so we
- don't have to check further for overflows. */
- && n >= 3)
+ /* The best reason to align src is that we then know that a read-fault
+ was for aligned bytes; there's no 1..3 remaining good bytes to
+ pickle. */
+ if (((unsigned long) src & 3) != 0)
{
- if ((unsigned long) dst & 1)
+ if (((unsigned long) src & 1) && n != 0)
{
__asm_copy_from_user_1 (dst, src, retn);
n--;
}
- if ((unsigned long) dst & 2)
+ if (((unsigned long) src & 2) && n >= 2)
{
__asm_copy_from_user_2 (dst, src, retn);
n -= 2;
}
+
+ /* We only need one check after the unalignment-adjustments, because
+ if both adjustments were done, either both or neither reference
+ had an exception. */
+ if (retn != 0)
+ goto copy_exception_bytes;
}
/* Decide which copying method to use. */
if (n >= 44*2) /* Break even between movem and
- move16 is at 38.7*2, but modulo 44. */
+ move16 is at 38.7*2, but modulo 44.
+ FIXME: We use move4 now. */
{
/* For large copies we use 'movem' */
@@ -249,10 +254,10 @@ __copy_user_zeroing (void *pdst, const void *psrc, unsigned long pn)
check the equalities in the first comment. It should say
"r13=r13, r11=r11, r12=r12" */
__asm__ volatile ("
- ;; Check that the following is true (same register names on
- ;; both sides of equal sign, as in r8=r8):
- ;; %0=r13, %1=r11, %2=r12 %3=r10
- ;;
+ .ifnc %0%1%2%3,$r13$r11$r12$r10 \n\
+ .err \n\
+ .endif \n\
+
;; Save the registers we'll use in the movem process
;; on the stack.
subq 11*4,$sp
@@ -273,73 +278,30 @@ __copy_user_zeroing (void *pdst, const void *psrc, unsigned long pn)
movem $r10,[$r13+]
addq 44,$r12 ;; compensate for last loop underflowing n
-8:
+
;; Restore registers from stack
movem [$sp+],$r10
-
+4:
.section .fixup,\"ax\"
;; Do not jump back into the loop if we fail. For some uses, we get a
-;; page fault but for performance reasons we care to not get further
-;; faults. For example, fs/super.c at one time did
+;; page fault somewhere on the line. Without checking for page limits,
+;; we don't know where, but we need to copy accurately and keep an
+;; accurate count; not just clear the whole line. To do that, we fall
+;; down in the code below, proceeding with smaller amounts. It should
+;; be kept in mind that we have to cater to code like what at one time
+;; was in fs/super.c:
;; i = size - copy_from_user((void *)page, data, size);
;; which would cause repeated faults while clearing the remainder of
;; the SIZE bytes at PAGE after the first fault.
+;; A caveat here is that we must not fall through from a failing page
+;; to a valid page.
3:
- move.d [$sp],$r10
-
-;; Number of remaining bytes, cleared but not copied, is r12 + 44.
-
- add.d $r12,$r10
- addq 44,$r10
-
- move.d $r10,[$sp]
- clear.d $r0
- clear.d $r1
- clear.d $r2
- clear.d $r3
- clear.d $r4
- clear.d $r5
- clear.d $r6
- clear.d $r7
- clear.d $r8
- clear.d $r9
- clear.d $r10
-
-;; Perform clear similar to the copy-loop.
-
-4:
- subq 44,$r12
- bge 4b
- movem $r10,[$r13+]
-
-;; Clear by four for the remaining multiples.
-
- addq 40,$r12
- bmi 6f
- nop
-5:
- subq 4,$r12
- bpl 5b
- clear.d [$r13+]
-6:
- addq 4,$r12
- beq 7f
- nop
-
- subq 1,$r12
- beq 7f
- clear.b [$r13+]
-
- subq 1,$r12
- beq 7f
- clear.b [$r13+]
-
- clear.d $r12
- clear.b [$r13+]
-7:
- jump 8b
+ movem [$sp+],$r10
+ addq 44,$r12 ;; Get back count before faulting point.
+ subq 44,$r11 ;; Get back pointer to faulting movem-line.
+ jump 4b ;; Fall through, pretending the fault didn't happen.
.previous
.section __ex_table,\"a\"
@@ -354,25 +316,30 @@ __copy_user_zeroing (void *pdst, const void *psrc, unsigned long pn)
/* Either we directly start copying here, using dword copying in a loop,
or we copy as much as possible with 'movem' and then the last block
(<44 bytes) is copied here. This will work since 'movem' will have
- updated src, dst and n. */
+ updated src, dst and n. (Except with failing src.)
- while (n >= 16)
- {
- __asm_copy_from_user_16 (dst, src, retn);
- n -= 16;
- }
+ Since we want to keep src accurate, we can't use
+ __asm_copy_from_user_N with N != (1, 2, 4); it updates dst and
+ retn, but not src (by design; it's value is ignored elsewhere). */
- /* Having a separate by-four loops cuts down on cache footprint.
- FIXME: Test with and without; increasing switch to be 0..15. */
while (n >= 4)
{
__asm_copy_from_user_4 (dst, src, retn);
n -= 4;
+
+ if (retn)
+ goto copy_exception_bytes;
}
+ /* If we get here, there were no memory read faults. */
switch (n)
{
+ /* These copies are at least "naturally aligned" (so we don't have
+ to check each byte), due to the src alignment code before the
+ movem loop. The *_3 case *will* get the correct count for retn. */
case 0:
+ /* This case deliberately left in (if you have doubts check the
+ generated assembly code). */
break;
case 1:
__asm_copy_from_user_1 (dst, src, retn);
@@ -385,13 +352,28 @@ __copy_user_zeroing (void *pdst, const void *psrc, unsigned long pn)
break;
}
+ /* If we get here, retn correctly reflects the number of failing
+ bytes. */
return retn;
+
+copy_exception_bytes:
+ /* We already have "retn" bytes cleared, and need to clear the
+ remaining "n" bytes. A non-optimized simple byte-for-byte in-line
+ memset is preferred here, since this isn't speed-critical code and
+ we'd rather have this a leaf-function than calling memset. */
+ {
+ char *endp;
+ for (endp = dst + n; dst < endp; dst++)
+ *dst = 0;
+ }
+
+ return retn + n;
}
/* Zero userspace. */
unsigned long
-__do_clear_user (void *pto, unsigned long pn)
+__do_clear_user (void __user *pto, unsigned long pn)
{
/* We want the parameters put in special registers.
Make sure the compiler is able to make something useful of this.
@@ -444,10 +426,10 @@ __do_clear_user (void *pto, unsigned long pn)
check the equalities in the first comment. It should say
something like "r13=r13, r11=r11, r12=r12". */
__asm__ volatile ("
- ;; Check that the following is true (same register names on
- ;; both sides of equal sign, as in r8=r8):
- ;; %0=r13, %1=r12 %2=r10
- ;;
+ .ifnc %0%1%2,$r13$r12$r10 \n\
+ .err \n\
+ .endif \n\
+
;; Save the registers we'll clobber in the movem process
;; on the stack. Don't mention them to gcc, it will only be
;; upset.
diff --git a/arch/cris/arch-v10/mm/Makefile b/arch/cris/arch-v10/mm/Makefile
new file mode 100644
index 000000000000..588b4baee85e
--- /dev/null
+++ b/arch/cris/arch-v10/mm/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux cris-specific parts of the memory manager.
+#
+
+obj-y := fault.o init.o tlb.o
+
diff --git a/arch/cris/arch-v10/mm/fault.c b/arch/cris/arch-v10/mm/fault.c
new file mode 100644
index 000000000000..7a012adc1579
--- /dev/null
+++ b/arch/cris/arch-v10/mm/fault.c
@@ -0,0 +1,175 @@
+/*
+ * linux/arch/cris/mm/fault.c
+ *
+ * Low level bus fault handler
+ *
+ *
+ * Copyright (C) 2000, 2001 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen
+ *
+ */
+
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/arch/svinto.h>
+
+/* debug of low-level TLB reload */
+#undef DEBUG
+
+#ifdef DEBUG
+#define D(x) x
+#else
+#define D(x)
+#endif
+
+extern volatile pgd_t *current_pgd;
+
+extern const struct exception_table_entry
+ *search_exception_tables(unsigned long addr);
+
+asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs,
+ int error_code);
+
+/* fast TLB-fill fault handler
+ * this is called from entry.S with interrupts disabled
+ */
+
+void
+handle_mmu_bus_fault(struct pt_regs *regs)
+{
+ int cause, select;
+#ifdef DEBUG
+ int index;
+ int page_id;
+ int acc, inv;
+#endif
+ int miss, we, writeac;
+ pmd_t *pmd;
+ pte_t pte;
+ int errcode;
+ unsigned long address;
+
+ cause = *R_MMU_CAUSE;
+ select = *R_TLB_SELECT;
+
+ address = cause & PAGE_MASK; /* get faulting address */
+
+#ifdef DEBUG
+ page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause);
+ acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause);
+ inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause);
+ index = IO_EXTRACT(R_TLB_SELECT, index, select);
+#endif
+ miss = IO_EXTRACT(R_MMU_CAUSE, miss_excp, cause);
+ we = IO_EXTRACT(R_MMU_CAUSE, we_excp, cause);
+ writeac = IO_EXTRACT(R_MMU_CAUSE, wr_rd, cause);
+
+ /* ETRAX 100LX TR89 bugfix: if the second half of an unaligned
+ * write causes a MMU-fault, it will not be restarted correctly.
+ * This could happen if a write crosses a page-boundary and the
+ * second page is not yet COW'ed or even loaded. The workaround
+ * is to clear the unaligned bit in the CPU status record, so
+ * that the CPU will rerun both the first and second halves of
+ * the instruction. This will not have any sideeffects unless
+ * the first half goes to any device or memory that can't be
+ * written twice, and which is mapped through the MMU.
+ *
+ * We only need to do this for writes.
+ */
+
+ if(writeac)
+ regs->csrinstr &= ~(1 << 5);
+
+ /* Set errcode's R/W flag according to the mode which caused the
+ * fault
+ */
+
+ errcode = writeac << 1;
+
+ D(printk("bus_fault from IRP 0x%lx: addr 0x%lx, miss %d, inv %d, we %d, acc %d, dx %d pid %d\n",
+ regs->irp, address, miss, inv, we, acc, index, page_id));
+
+ /* for a miss, we need to reload the TLB entry */
+
+ if (miss) {
+ /* see if the pte exists at all
+ * refer through current_pgd, dont use mm->pgd
+ */
+
+ pmd = (pmd_t *)(current_pgd + pgd_index(address));
+ if (pmd_none(*pmd))
+ goto dofault;
+ if (pmd_bad(*pmd)) {
+ printk("bad pgdir entry 0x%lx at 0x%p\n", *(unsigned long*)pmd, pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = *pte_offset_kernel(pmd, address);
+ if (!pte_present(pte))
+ goto dofault;
+
+#ifdef DEBUG
+ printk(" found pte %lx pg %p ", pte_val(pte), pte_page(pte));
+ if (pte_val(pte) & _PAGE_SILENT_WRITE)
+ printk("Silent-W ");
+ if (pte_val(pte) & _PAGE_KERNEL)
+ printk("Kernel ");
+ if (pte_val(pte) & _PAGE_SILENT_READ)
+ printk("Silent-R ");
+ if (pte_val(pte) & _PAGE_GLOBAL)
+ printk("Global ");
+ if (pte_val(pte) & _PAGE_PRESENT)
+ printk("Present ");
+ if (pte_val(pte) & _PAGE_ACCESSED)
+ printk("Accessed ");
+ if (pte_val(pte) & _PAGE_MODIFIED)
+ printk("Modified ");
+ if (pte_val(pte) & _PAGE_READ)
+ printk("Readable ");
+ if (pte_val(pte) & _PAGE_WRITE)
+ printk("Writeable ");
+ printk("\n");
+#endif
+
+ /* load up the chosen TLB entry
+ * this assumes the pte format is the same as the TLB_LO layout.
+ *
+ * the write to R_TLB_LO also writes the vpn and page_id fields from
+ * R_MMU_CAUSE, which we in this case obviously want to keep
+ */
+
+ *R_TLB_LO = pte_val(pte);
+
+ return;
+ }
+
+ errcode = 1 | (we << 1);
+
+ dofault:
+ /* leave it to the MM system fault handler below */
+ D(printk("do_page_fault %lx errcode %d\n", address, errcode));
+ do_page_fault(address, regs, errcode);
+}
+
+/* Called from arch/cris/mm/fault.c to find fixup code. */
+int
+find_fixup_code(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fixup;
+
+ if ((fixup = search_exception_tables(regs->irp)) != 0) {
+ /* Adjust the instruction pointer in the stackframe. */
+ regs->irp = fixup->fixup;
+
+ /*
+ * Don't return by restoring the CPU state, so switch
+ * frame-type.
+ */
+ regs->frametype = CRIS_FRAME_NORMAL;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c
new file mode 100644
index 000000000000..df03dea5bae4
--- /dev/null
+++ b/arch/cris/arch-v10/mm/init.c
@@ -0,0 +1,265 @@
+/*
+ * linux/arch/cris/arch-v10/mm/init.c
+ *
+ */
+#include <linux/config.h>
+#include <linux/mmzone.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/types.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/arch/svinto.h>
+
+extern void tlb_init(void);
+
+/*
+ * The kernel is already mapped with a kernel segment at kseg_c so
+ * we don't need to map it with a page table. However head.S also
+ * temporarily mapped it at kseg_4 so we should set up the ksegs again,
+ * clear the TLB and do some other paging setup stuff.
+ */
+
+void __init
+paging_init(void)
+{
+ int i;
+ unsigned long zones_size[MAX_NR_ZONES];
+
+ printk("Setting up paging and the MMU.\n");
+
+ /* clear out the init_mm.pgd that will contain the kernel's mappings */
+
+ for(i = 0; i < PTRS_PER_PGD; i++)
+ swapper_pg_dir[i] = __pgd(0);
+
+ /* make sure the current pgd table points to something sane
+ * (even if it is most probably not used until the next
+ * switch_mm)
+ */
+
+ current_pgd = init_mm.pgd;
+
+ /* initialise the TLB (tlb.c) */
+
+ tlb_init();
+
+ /* see README.mm for details on the KSEG setup */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+ /* Etrax-100 LX version 1 has a bug so that we cannot map anything
+ * across the 0x80000000 boundary, so we need to shrink the user-virtual
+ * area to 0x50000000 instead of 0xb0000000 and map things slightly
+ * different. The unused areas are marked as paged so that we can catch
+ * freak kernel accesses there.
+ *
+ * The ARTPEC chip is mapped at 0xa so we pass that segment straight
+ * through. We cannot vremap it because the vmalloc area is below 0x8
+ * and Juliette needs an uncached area above 0x8.
+ *
+ * Same thing with 0xc and 0x9, which is memory-mapped I/O on some boards.
+ * We map them straight over in LOW_MAP, but use vremap in LX version 2.
+ */
+
+#define CACHED_BOOTROM (KSEG_F | 0x08000000UL)
+
+ *R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg ) | /* bootrom */
+ IO_STATE(R_MMU_KSEG, seg_e, page ) |
+ IO_STATE(R_MMU_KSEG, seg_d, page ) |
+ IO_STATE(R_MMU_KSEG, seg_c, page ) |
+ IO_STATE(R_MMU_KSEG, seg_b, seg ) | /* kernel reg area */
+#ifdef CONFIG_JULIETTE
+ IO_STATE(R_MMU_KSEG, seg_a, seg ) | /* ARTPEC etc. */
+#else
+ IO_STATE(R_MMU_KSEG, seg_a, page ) |
+#endif
+ IO_STATE(R_MMU_KSEG, seg_9, seg ) | /* LED's on some boards */
+ IO_STATE(R_MMU_KSEG, seg_8, seg ) | /* CSE0/1, flash and I/O */
+ IO_STATE(R_MMU_KSEG, seg_7, page ) | /* kernel vmalloc area */
+ IO_STATE(R_MMU_KSEG, seg_6, seg ) | /* kernel DRAM area */
+ IO_STATE(R_MMU_KSEG, seg_5, seg ) | /* cached flash */
+ IO_STATE(R_MMU_KSEG, seg_4, page ) | /* user area */
+ IO_STATE(R_MMU_KSEG, seg_3, page ) | /* user area */
+ IO_STATE(R_MMU_KSEG, seg_2, page ) | /* user area */
+ IO_STATE(R_MMU_KSEG, seg_1, page ) | /* user area */
+ IO_STATE(R_MMU_KSEG, seg_0, page ) ); /* user area */
+
+ *R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x3 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_e, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_c, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
+#ifdef CONFIG_JULIETTE
+ IO_FIELD(R_MMU_KBASE_HI, base_a, 0xa ) |
+#else
+ IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) |
+#endif
+ IO_FIELD(R_MMU_KBASE_HI, base_9, 0x9 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_8, 0x8 ) );
+
+ *R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_6, 0x4 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
+#else
+ /* This code is for the corrected Etrax-100 LX version 2... */
+
+#define CACHED_BOOTROM (KSEG_A | 0x08000000UL)
+
+ *R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg ) | /* cached flash */
+ IO_STATE(R_MMU_KSEG, seg_e, seg ) | /* uncached flash */
+ IO_STATE(R_MMU_KSEG, seg_d, page ) | /* vmalloc area */
+ IO_STATE(R_MMU_KSEG, seg_c, seg ) | /* kernel area */
+ IO_STATE(R_MMU_KSEG, seg_b, seg ) | /* kernel reg area */
+ IO_STATE(R_MMU_KSEG, seg_a, seg ) | /* bootrom */
+ IO_STATE(R_MMU_KSEG, seg_9, page ) | /* user area */
+ IO_STATE(R_MMU_KSEG, seg_8, page ) |
+ IO_STATE(R_MMU_KSEG, seg_7, page ) |
+ IO_STATE(R_MMU_KSEG, seg_6, page ) |
+ IO_STATE(R_MMU_KSEG, seg_5, page ) |
+ IO_STATE(R_MMU_KSEG, seg_4, page ) |
+ IO_STATE(R_MMU_KSEG, seg_3, page ) |
+ IO_STATE(R_MMU_KSEG, seg_2, page ) |
+ IO_STATE(R_MMU_KSEG, seg_1, page ) |
+ IO_STATE(R_MMU_KSEG, seg_0, page ) );
+
+ *R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_c, 0x4 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_a, 0x3 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) );
+
+ *R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_6, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
+ IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
+#endif
+
+ *R_MMU_CONTEXT = ( IO_FIELD(R_MMU_CONTEXT, page_id, 0 ) );
+
+ /* The MMU has been enabled ever since head.S but just to make
+ * it totally obvious we do it here as well.
+ */
+
+ *R_MMU_CTRL = ( IO_STATE(R_MMU_CTRL, inv_excp, enable ) |
+ IO_STATE(R_MMU_CTRL, acc_excp, enable ) |
+ IO_STATE(R_MMU_CTRL, we_excp, enable ) );
+
+ *R_MMU_ENABLE = IO_STATE(R_MMU_ENABLE, mmu_enable, enable);
+
+ /*
+ * initialize the bad page table and bad page to point
+ * to a couple of allocated pages
+ */
+
+ empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+ memset((void *)empty_zero_page, 0, PAGE_SIZE);
+
+ /* All pages are DMA'able in Etrax, so put all in the DMA'able zone */
+
+ zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+
+ for (i = 1; i < MAX_NR_ZONES; i++)
+ zones_size[i] = 0;
+
+ /* Use free_area_init_node instead of free_area_init, because the former
+ * is designed for systems where the DRAM starts at an address substantially
+ * higher than 0, like us (we start at PAGE_OFFSET). This saves space in the
+ * mem_map page array.
+ */
+
+ free_area_init_node(0, &contig_page_data, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+ mem_map = contig_page_data.node_mem_map;
+}
+
+/* Initialize remaps of some I/O-ports. It is important that this
+ * is called before any driver is initialized.
+ */
+
+static int
+__init init_ioremap(void)
+{
+
+ /* Give the external I/O-port addresses their values */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+ /* Simply a linear map (see the KSEG map above in paging_init) */
+ port_cse1_addr = (volatile unsigned long *)(MEM_CSE1_START |
+ MEM_NON_CACHEABLE);
+ port_csp0_addr = (volatile unsigned long *)(MEM_CSP0_START |
+ MEM_NON_CACHEABLE);
+ port_csp4_addr = (volatile unsigned long *)(MEM_CSP4_START |
+ MEM_NON_CACHEABLE);
+#else
+ /* Note that nothing blows up just because we do this remapping
+ * it's ok even if the ports are not used or connected
+ * to anything (or connected to a non-I/O thing) */
+ port_cse1_addr = (volatile unsigned long *)
+ ioremap((unsigned long)(MEM_CSE1_START | MEM_NON_CACHEABLE), 16);
+ port_csp0_addr = (volatile unsigned long *)
+ ioremap((unsigned long)(MEM_CSP0_START | MEM_NON_CACHEABLE), 16);
+ port_csp4_addr = (volatile unsigned long *)
+ ioremap((unsigned long)(MEM_CSP4_START | MEM_NON_CACHEABLE), 16);
+#endif
+ return 0;
+}
+
+__initcall(init_ioremap);
+
+/* Helper function for the two below */
+
+static inline void
+flush_etrax_cacherange(void *startadr, int length)
+{
+ /* CACHED_BOOTROM is mapped to the boot-rom area (cached) which
+ * we can use to get fast dummy-reads of cachelines
+ */
+
+ volatile short *flushadr = (volatile short *)(((unsigned long)startadr & ~PAGE_MASK) |
+ CACHED_BOOTROM);
+
+ length = length > 8192 ? 8192 : length; /* No need to flush more than cache size */
+
+ while(length > 0) {
+ *flushadr; /* dummy read to flush */
+ flushadr += (32/sizeof(short)); /* a cacheline is 32 bytes */
+ length -= 32;
+ }
+}
+
+/* Due to a bug in Etrax100(LX) all versions, receiving DMA buffers
+ * will occationally corrupt certain CPU writes if the DMA buffers
+ * happen to be hot in the cache.
+ *
+ * As a workaround, we have to flush the relevant parts of the cache
+ * before (re) inserting any receiving descriptor into the DMA HW.
+ */
+
+void
+prepare_rx_descriptor(struct etrax_dma_descr *desc)
+{
+ flush_etrax_cacherange((void *)desc->buf, desc->sw_len ? desc->sw_len : 65536);
+}
+
+/* Do the same thing but flush the entire cache */
+
+void
+flush_etrax_cache(void)
+{
+ flush_etrax_cacherange(0, 8192);
+}
diff --git a/arch/cris/arch-v10/mm/tlb.c b/arch/cris/arch-v10/mm/tlb.c
new file mode 100644
index 000000000000..2ddb0a61cdbf
--- /dev/null
+++ b/arch/cris/arch-v10/mm/tlb.c
@@ -0,0 +1,236 @@
+/*
+ * linux/arch/cris/arch-v10/mm/tlb.c
+ *
+ * Low level TLB handling
+ *
+ *
+ * Copyright (C) 2000-2002 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen (bjornw@axis.com)
+ *
+ */
+
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+#include <asm/arch/svinto.h>
+
+#define D(x)
+
+/* The TLB can host up to 64 different mm contexts at the same time.
+ * The running context is R_MMU_CONTEXT, and each TLB entry contains a
+ * page_id that has to match to give a hit. In page_id_map, we keep track
+ * of which mm's we have assigned which page_id's, so that we know when
+ * to invalidate TLB entries.
+ *
+ * The last page_id is never running - it is used as an invalid page_id
+ * so we can make TLB entries that will never match.
+ *
+ * Notice that we need to make the flushes atomic, otherwise an interrupt
+ * handler that uses vmalloced memory might cause a TLB load in the middle
+ * of a flush causing.
+ */
+
+/* invalidate all TLB entries */
+
+void
+flush_tlb_all(void)
+{
+ int i;
+ unsigned long flags;
+
+ /* the vpn of i & 0xf is so we dont write similar TLB entries
+ * in the same 4-way entry group. details..
+ */
+
+ local_save_flags(flags);
+ local_irq_disable();
+ for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+ *R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
+ *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+ IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
+
+ *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
+ IO_STATE(R_TLB_LO, valid, no ) |
+ IO_STATE(R_TLB_LO, kernel,no ) |
+ IO_STATE(R_TLB_LO, we, no ) |
+ IO_FIELD(R_TLB_LO, pfn, 0 ) );
+ }
+ local_irq_restore(flags);
+ D(printk("tlb: flushed all\n"));
+}
+
+/* invalidate the selected mm context only */
+
+void
+flush_tlb_mm(struct mm_struct *mm)
+{
+ int i;
+ int page_id = mm->context;
+ unsigned long flags;
+
+ D(printk("tlb: flush mm context %d (%p)\n", page_id, mm));
+
+ if(page_id == NO_CONTEXT)
+ return;
+
+ /* mark the TLB entries that match the page_id as invalid.
+ * here we could also check the _PAGE_GLOBAL bit and NOT flush
+ * global pages. is it worth the extra I/O ?
+ */
+
+ local_save_flags(flags);
+ local_irq_disable();
+ for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+ *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
+ if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
+ *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+ IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
+
+ *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
+ IO_STATE(R_TLB_LO, valid, no ) |
+ IO_STATE(R_TLB_LO, kernel,no ) |
+ IO_STATE(R_TLB_LO, we, no ) |
+ IO_FIELD(R_TLB_LO, pfn, 0 ) );
+ }
+ }
+ local_irq_restore(flags);
+}
+
+/* invalidate a single page */
+
+void
+flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int page_id = mm->context;
+ int i;
+ unsigned long flags;
+
+ D(printk("tlb: flush page %p in context %d (%p)\n", addr, page_id, mm));
+
+ if(page_id == NO_CONTEXT)
+ return;
+
+ addr &= PAGE_MASK; /* perhaps not necessary */
+
+ /* invalidate those TLB entries that match both the mm context
+ * and the virtual address requested
+ */
+
+ local_save_flags(flags);
+ local_irq_disable();
+ for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+ unsigned long tlb_hi;
+ *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
+ tlb_hi = *R_TLB_HI;
+ if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
+ (tlb_hi & PAGE_MASK) == addr) {
+ *R_TLB_HI = IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+ addr; /* same addr as before works. */
+
+ *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
+ IO_STATE(R_TLB_LO, valid, no ) |
+ IO_STATE(R_TLB_LO, kernel,no ) |
+ IO_STATE(R_TLB_LO, we, no ) |
+ IO_FIELD(R_TLB_LO, pfn, 0 ) );
+ }
+ }
+ local_irq_restore(flags);
+}
+
+/* invalidate a page range */
+
+void
+flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int page_id = mm->context;
+ int i;
+ unsigned long flags;
+
+ D(printk("tlb: flush range %p<->%p in context %d (%p)\n",
+ start, end, page_id, mm));
+
+ if(page_id == NO_CONTEXT)
+ return;
+
+ start &= PAGE_MASK; /* probably not necessary */
+ end &= PAGE_MASK; /* dito */
+
+ /* invalidate those TLB entries that match both the mm context
+ * and the virtual address range
+ */
+
+ local_save_flags(flags);
+ local_irq_disable();
+ for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+ unsigned long tlb_hi, vpn;
+ *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
+ tlb_hi = *R_TLB_HI;
+ vpn = tlb_hi & PAGE_MASK;
+ if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
+ vpn >= start && vpn < end) {
+ *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+ IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
+
+ *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
+ IO_STATE(R_TLB_LO, valid, no ) |
+ IO_STATE(R_TLB_LO, kernel,no ) |
+ IO_STATE(R_TLB_LO, we, no ) |
+ IO_FIELD(R_TLB_LO, pfn, 0 ) );
+ }
+ }
+ local_irq_restore(flags);
+}
+
+/* dump the entire TLB for debug purposes */
+
+#if 0
+void
+dump_tlb_all(void)
+{
+ int i;
+ unsigned long flags;
+
+ printk("TLB dump. LO is: pfn | reserved | global | valid | kernel | we |\n");
+
+ local_save_flags(flags);
+ local_irq_disable();
+ for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+ *R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
+ printk("Entry %d: HI 0x%08lx, LO 0x%08lx\n",
+ i, *R_TLB_HI, *R_TLB_LO);
+ }
+ local_irq_restore(flags);
+}
+#endif
+
+/* called in schedule() just before actually doing the switch_to */
+
+void
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk, int cpu)
+{
+ /* make sure we have a context */
+
+ get_mmu_context(next);
+
+ /* remember the pgd for the fault handlers
+ * this is similar to the pgd register in some other CPU's.
+ * we need our own copy of it because current and active_mm
+ * might be invalid at points where we still need to derefer
+ * the pgd.
+ */
+
+ current_pgd = next->pgd;
+
+ /* switch context in the MMU */
+
+ D(printk("switching mmu_context to %d (%p)\n", next->context, next));
+
+ *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context);
+}
+
diff --git a/arch/cris/arch-v10/output_arch.ld b/arch/cris/arch-v10/output_arch.ld
new file mode 100644
index 000000000000..2f3288006991
--- /dev/null
+++ b/arch/cris/arch-v10/output_arch.ld
@@ -0,0 +1,2 @@
+/* At the time of this writing, there's no equivalent ld option. */
+OUTPUT_ARCH (cris)
diff --git a/arch/cris/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S
index 3a5f1a36da38..b2c27e147f29 100644
--- a/arch/cris/vmlinux.lds.S
+++ b/arch/cris/arch-v10/vmlinux.lds.S
@@ -10,11 +10,11 @@
#include <linux/config.h>
#include <asm-generic/vmlinux.lds.h>
-
+
jiffies = jiffies_64;
SECTIONS
{
- . = 0x ## CONFIG_ETRAX_DRAM_VIRTUAL_BASE;
+ . = DRAM_VIRTUAL_BASE;
dram_start = .;
ibr_start = .;
. = . + 0x4000; /* see head.S and pages reserved at the start */
@@ -53,12 +53,19 @@ SECTIONS
. = ALIGN(8192); /* Init code and data */
__init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : { *(.data.init) }
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ .init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
- .setup.init : { *(.setup.init) }
+ .init.setup : { *(.init.setup) }
__setup_end = .;
+ __start___param = .;
+ __param : { *(__param) }
+ __stop___param = .;
.initcall.init : {
__initcall_start = .;
*(.initcall1.init);
@@ -68,24 +75,27 @@ SECTIONS
*(.initcall5.init);
*(.initcall6.init);
*(.initcall7.init);
- __initcall_end = .;
+ __initcall_end = .;
}
+
.con_initcall.init : {
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
- }
- .security_initcall.init : {
- __security_initcall_start = .;
- *(.security_initcall.init)
- __security_initcall_end = .;
-
+ }
+ SECURITY_INIT
+
+ .init.ramfs : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
/* We fill to the next page, so we can discard all init
pages without needing to consider what payload might be
appended to the kernel image. */
- FILL (0);
+ FILL (0);
. = ALIGN (8192);
}
+
__vmlinux_end = .; /* last address of the physical file */
__init_end = .;
diff --git a/arch/cris/defconfig b/arch/cris/defconfig
index 9d40dd316576..7af178b78328 100644
--- a/arch/cris/defconfig
+++ b/arch/cris/defconfig
@@ -27,93 +27,13 @@ CONFIG_BINFMT_ELF=y
CONFIG_ETRAX100LX=y
# CONFIG_ETRAX100LX_V2 is not set
# CONFIG_SVINTO_SIM is not set
-CONFIG_CRIS_LOW_MAP=y
-CONFIG_ETRAX_DRAM_VIRTUAL_BASE=60000000
CONFIG_ETRAX_DRAM_SIZE=8
CONFIG_ETRAX_FLASH_BUSWIDTH=2
CONFIG_ETRAX_ROOT_DEVICE="/dev/mtdblock3"
-CONFIG_ETRAX_PA_LEDS=y
-# CONFIG_ETRAX_PB_LEDS is not set
-# CONFIG_ETRAX_CSP0_LEDS is not set
-# CONFIG_ETRAX_NO_LEDS is not set
-CONFIG_ETRAX_LED1G=2
-CONFIG_ETRAX_LED1R=2
-CONFIG_ETRAX_LED2G=2
-CONFIG_ETRAX_LED2R=2
-CONFIG_ETRAX_LED3R=2
-CONFIG_ETRAX_LED3G=2
-CONFIG_ETRAX_LED4R=2
-CONFIG_ETRAX_LED4G=2
-CONFIG_ETRAX_LED5R=2
-CONFIG_ETRAX_LED5G=2
-CONFIG_ETRAX_LED6R=2
-CONFIG_ETRAX_LED6G=2
-CONFIG_ETRAX_LED7R=2
-CONFIG_ETRAX_LED7G=2
-CONFIG_ETRAX_LED8Y=2
-CONFIG_ETRAX_LED9Y=2
-CONFIG_ETRAX_LED10Y=2
-CONFIG_ETRAX_LED11Y=2
-CONFIG_ETRAX_LED12R=2
-CONFIG_ETRAX_DEBUG_PORT0=y
-# CONFIG_ETRAX_DEBUG_PORT1 is not set
-# CONFIG_ETRAX_DEBUG_PORT2 is not set
-# CONFIG_ETRAX_DEBUG_PORT3 is not set
-CONFIG_ETRAX_RESCUE_SER0=y
-# CONFIG_ETRAX_RESCUE_SER1 is not set
-# CONFIG_ETRAX_RESCUE_SER2 is not set
-# CONFIG_ETRAX_RESCUE_SER3 is not set
-CONFIG_ETRAX_DEF_R_WAITSTATES=95a6
-CONFIG_ETRAX_DEF_R_BUS_CONFIG=104
-# CONFIG_ETRAX_SDRAM is not set
-CONFIG_ETRAX_DEF_R_DRAM_CONFIG=1a200040
-CONFIG_ETRAX_DEF_R_DRAM_TIMING=5611
-CONFIG_ETRAX_DEF_R_PORT_PA_DIR=1d
-CONFIG_ETRAX_DEF_R_PORT_PA_DATA=f0
-CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=00
-CONFIG_ETRAX_DEF_R_PORT_PB_DIR=1e
-CONFIG_ETRAX_DEF_R_PORT_PB_DATA=f3
-# CONFIG_ETRAX_SOFT_SHUTDOWN is not set
#
# Drivers for ETRAX 100LX built-in interfaces
#
-CONFIG_ETRAX_ETHERNET=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set
-CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y
-# CONFIG_ETRAX_ETHERNET_LPSLAVE is not set
-CONFIG_ETRAX_SERIAL=y
-CONFIG_ETRAX_SERIAL_PORT0=y
-# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB is not set
-CONFIG_ETRAX_SERIAL_PORT1=y
-# CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB is not set
-# CONFIG_ETRAX_SERIAL_PORT2 is not set
-# CONFIG_ETRAX_SERIAL_PORT3 is not set
-# CONFIG_ETRAX_RS485 is not set
-# CONFIG_ETRAX_SYNCHRONOUS_SERIAL is not set
-# CONFIG_ETRAX_IDE is not set
-CONFIG_ETRAX_AXISFLASHMAP=y
-CONFIG_ETRAX_PTABLE_SECTOR=65536
-CONFIG_MTD=y
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_AMDSTD=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_ETRAX_I2C=y
-CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C=y
-# CONFIG_ETRAX_I2C_EEPROM is not set
-CONFIG_ETRAX_GPIO=y
-CONFIG_ETRAX_PA_BUTTON_BITMASK=02
-CONFIG_ETRAX_PA_CHANGEABLE_DIR=00
-CONFIG_ETRAX_PA_CHANGEABLE_BITS=FF
-CONFIG_ETRAX_PB_CHANGEABLE_DIR=00
-CONFIG_ETRAX_PB_CHANGEABLE_BITS=FF
-# CONFIG_ETRAX_USB_HOST is not set
-# CONFIG_USB is not set
-# CONFIG_ETRAX_DS1302 is not set
#
# Memory Technology Devices (MTD)
diff --git a/arch/cris/drivers/axisflashmap.c b/arch/cris/drivers/axisflashmap.c
deleted file mode 100644
index 6db4078e068b..000000000000
--- a/arch/cris/drivers/axisflashmap.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Physical mapping layer for MTD using the Axis partitiontable format
- *
- * Copyright (c) 2001 Axis Communications AB
- *
- * This file is under the GPL.
- *
- * First partition is always sector 0 regardless of if we find a partitiontable
- * or not. In the start of the next sector, there can be a partitiontable that
- * tells us what other partitions to define. If there isn't, we use a default
- * partition split defined below.
- *
- * $Log: axisflashmap.c,v $
- * Revision 1.2 2001/12/18 13:35:15 bjornw
- * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
- *
- * Revision 1.17 2001/11/12 19:42:38 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.16 2001/11/08 11:18:58 jonashg
- * Always read from uncached address to avoid problems with flushing
- * cachelines after write and MTD-erase. No performance loss have been
- * seen yet.
- *
- * Revision 1.15 2001/10/19 12:41:04 jonashg
- * Name of probe has changed in MTD.
- *
- * Revision 1.14 2001/09/21 07:14:10 jonashg
- * Made root filesystem (cramfs) use mtdblock driver when booting from flash.
- *
- * Revision 1.13 2001/08/15 13:57:35 jonashg
- * Entire MTD updated to the linux 2.4.7 version.
- *
- * Revision 1.12 2001/06/11 09:50:30 jonashg
- * Oops, 2MB is 0x200000 bytes.
- *
- * Revision 1.11 2001/06/08 11:39:44 jonashg
- * Changed sizes and offsets in axis_default_partitions to use
- * CONFIG_ETRAX_PTABLE_SECTOR.
- *
- * Revision 1.10 2001/05/29 09:42:03 jonashg
- * Use macro for end marker length instead of sizeof.
- *
- * Revision 1.9 2001/05/29 08:52:52 jonashg
- * Gave names to the magic fours (size of the ptable end marker).
- *
- * Revision 1.8 2001/05/28 15:36:20 jonashg
- * * Removed old comment about ptable location in flash (it's a CONFIG_ option).
- * * Variable ptable was initialized twice to the same value.
- *
- * Revision 1.7 2001/04/05 13:41:46 markusl
- * Updated according to review remarks
- *
- * Revision 1.6 2001/03/07 09:21:21 bjornw
- * No need to waste .data
- *
- * Revision 1.5 2001/03/06 16:27:01 jonashg
- * Probe the entire flash area for flash devices.
- *
- * Revision 1.4 2001/02/23 12:47:15 bjornw
- * Uncached flash in LOW_MAP moved from 0xe to 0x8
- *
- * Revision 1.3 2001/02/16 12:11:45 jonashg
- * MTD driver amd_flash is now included in MTD CVS repository.
- * (It's now in drivers/mtd).
- *
- * Revision 1.2 2001/02/09 11:12:22 jonashg
- * Support for AMD compatible non-CFI flash chips.
- * Only tested with Toshiba TC58FVT160 so far.
- *
- * Revision 1.1 2001/01/12 17:01:18 bjornw
- * * Added axisflashmap.c, a physical mapping for MTD that reads and understands
- * Axis partition-table format.
- *
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/config.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/axisflashmap.h>
-#include <asm/mmu.h>
-
-#ifdef CONFIG_CRIS_LOW_MAP
-#define FLASH_UNCACHED_ADDR KSEG_8
-#define FLASH_CACHED_ADDR KSEG_5
-#else
-#define FLASH_UNCACHED_ADDR KSEG_E
-#define FLASH_CACHED_ADDR KSEG_F
-#endif
-
-/*
- * WINDOW_SIZE is the total size where the flash chips may be mapped.
- * MTD probes should find all devices there and it does not matter
- * if there are unmapped gaps or aliases (mirrors of flash devices).
- * The MTD probes will ignore them.
- */
-
-#define WINDOW_SIZE (128 * 1024 * 1024)
-
-extern unsigned long romfs_start, romfs_length, romfs_in_flash; /* From head.S */
-
-/*
- * Map driver
- *
- * Ok this is the scoop - we need to access the flash both with and without
- * the cache - without when doing all the fancy flash interfacing, and with
- * when we do actual copying because otherwise it will be slow like molasses.
- */
-
-static __u8 flash_read8(struct map_info *map, unsigned long ofs)
-{
- return *(__u8 *)(FLASH_UNCACHED_ADDR + ofs);
-}
-
-static __u16 flash_read16(struct map_info *map, unsigned long ofs)
-{
- return *(__u16 *)(FLASH_UNCACHED_ADDR + ofs);
-}
-
-static __u32 flash_read32(struct map_info *map, unsigned long ofs)
-{
- return *(volatile unsigned int *)(FLASH_UNCACHED_ADDR + ofs);
-}
-
-static void flash_copy_from(struct map_info *map, void *to,
- unsigned long from, ssize_t len)
-{
- memcpy(to, (void *)(FLASH_UNCACHED_ADDR + from), len);
-}
-
-static void flash_write8(struct map_info *map, __u8 d, unsigned long adr)
-{
- *(__u8 *)(FLASH_UNCACHED_ADDR + adr) = d;
-}
-
-static void flash_write16(struct map_info *map, __u16 d, unsigned long adr)
-{
- *(__u16 *)(FLASH_UNCACHED_ADDR + adr) = d;
-}
-
-static void flash_write32(struct map_info *map, __u32 d, unsigned long adr)
-{
- *(__u32 *)(FLASH_UNCACHED_ADDR + adr) = d;
-}
-
-static struct map_info axis_map = {
- .name = "Axis flash",
- .size = WINDOW_SIZE,
- .buswidth = CONFIG_ETRAX_FLASH_BUSWIDTH,
- .read8 = flash_read8,
- .read16 = flash_read16,
- .read32 = flash_read32,
- .copy_from = flash_copy_from,
- .write8 = flash_write8,
- .write16 = flash_write16,
- .write32 = flash_write32,
-};
-
-/* If no partition-table was found, we use this default-set.
- */
-
-#define MAX_PARTITIONS 7
-#define NUM_DEFAULT_PARTITIONS 3
-
-/* Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the
- * size of one flash block and "filesystem"-partition needs 5 blocks to be able
- * to use JFFS.
- */
-static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
- {
- .name = "boot firmware",
- .size = CONFIG_ETRAX_PTABLE_SECTOR,
- .offset = 0
- },
- {
- .name = "kernel",
- .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
- .offset = CONFIG_ETRAX_PTABLE_SECTOR
- },
- {
- .name = "filesystem",
- .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,
- .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
- }
-};
-
-static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
- {
- .name = "part0",
- .size = 0,
- .offset = 0
- },
- {
- .name = "part1",
- .size = 0,
- .offset = 0
- },
- {
- .name = "part2",
- .size = 0,
- .offset = 0
- },
- {
- .name = "part3",
- .size = 0,
- .offset = 0
- },
- {
- .name = "part4",
- .size = 0,
- .offset = 0
- },
- {
- .name = "part5",
- .size = 0,
- .offset = 0
- },
- {
- .name = "part6",
- .size = 0,
- .offset = 0
- },
-};
-
-/*
- * This is the master MTD device for which all the others are just
- * auto-relocating aliases.
- */
-static struct mtd_info *mymtd;
-
-/* CFI-scan the flash, and if there was a chip, read the partition-table
- * and register the partitions with MTD.
- */
-
-static int __init
-init_axis_flash(void)
-{
- int pidx = 0;
- struct partitiontable_head *ptable_head;
- struct partitiontable_entry *ptable;
- int use_default_ptable = 1; /* Until proven otherwise */
- const char *pmsg = " /dev/flash%d at 0x%x, size 0x%x\n";
-
- printk(KERN_NOTICE "Axis flash mapping: %x at %lx\n",
- WINDOW_SIZE, FLASH_CACHED_ADDR);
-
-#ifdef CONFIG_MTD_CFI
- mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &axis_map);
-#endif
-
-#ifdef CONFIG_MTD_AMDSTD
- if (!mymtd) {
- mymtd = (struct mtd_info *)do_map_probe("amd_flash", &axis_map);
- }
-#endif
-
- if(!mymtd) {
- printk("%s: No flash chip found!\n", axis_map.name);
- return -ENXIO;
- }
-
- mymtd->module = THIS_MODULE;
-
- ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
- CONFIG_ETRAX_PTABLE_SECTOR + PARTITION_TABLE_OFFSET);
- pidx++; /* first partition is always set to the default */
-
- if ((ptable_head->magic == PARTITION_TABLE_MAGIC)
- && (ptable_head->size <
- (MAX_PARTITIONS * sizeof(struct partitiontable_entry) +
- PARTITIONTABLE_END_MARKER_SIZE))
- && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) +
- ptable_head->size -
- PARTITIONTABLE_END_MARKER_SIZE)
- == PARTITIONTABLE_END_MARKER)) {
- /* Looks like a start, sane length and end of a
- * partition table, lets check csum etc.
- */
- int ptable_ok = 0;
- struct partitiontable_entry *max_addr =
- (struct partitiontable_entry *)
- ((unsigned long)ptable_head + sizeof(*ptable_head) +
- ptable_head->size);
- unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
- unsigned char *p;
- unsigned long csum = 0;
-
- ptable = (struct partitiontable_entry *)
- ((unsigned long)ptable_head + sizeof(*ptable_head));
-
- /* Lets be PARANOID, and check the checksum. */
- p = (unsigned char*) ptable;
-
- while (p <= (unsigned char*)max_addr) {
- csum += *p++;
- csum += *p++;
- csum += *p++;
- csum += *p++;
- }
- /* printk(" total csum: 0x%08X 0x%08X\n",
- csum, ptable_head->checksum); */
- ptable_ok = (csum == ptable_head->checksum);
-
- /* Read the entries and use/show the info. */
- printk(" Found %s partition table at 0x%08lX-0x%08lX.\n",
- (ptable_ok ? "valid" : "invalid"),
- (unsigned long)ptable_head,
- (unsigned long)max_addr);
-
- /* We have found a working bootblock. Now read the
- partition table. Scan the table. It ends when
- there is 0xffffffff, that is, empty flash. */
-
- while (ptable_ok
- && ptable->offset != 0xffffffff
- && ptable < max_addr
- && pidx < MAX_PARTITIONS) {
-
- axis_partitions[pidx].offset = offset + ptable->offset;
- axis_partitions[pidx].size = ptable->size;
-
- printk(pmsg, pidx, axis_partitions[pidx].offset,
- axis_partitions[pidx].size);
- pidx++;
- ptable++;
- }
- use_default_ptable = !ptable_ok;
- }
-
- if (use_default_ptable) {
- printk(" Using default partition table\n");
- return add_mtd_partitions(mymtd, axis_default_partitions,
- NUM_DEFAULT_PARTITIONS);
- } else {
- if (romfs_in_flash) {
- axis_partitions[pidx].name = "romfs";
- axis_partitions[pidx].size = romfs_length;
- axis_partitions[pidx].offset = romfs_start -
- FLASH_CACHED_ADDR;
- axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
-
- printk(" Adding readonly partition for romfs image:\n");
- printk(pmsg, pidx, axis_partitions[pidx].offset,
- axis_partitions[pidx].size);
- pidx++;
- }
- return add_mtd_partitions(mymtd, axis_partitions, pidx);
- }
-}
-
-/* This adds the above to the kernels init-call chain */
-
-module_init(init_axis_flash);
-
diff --git a/arch/cris/drivers/bluetooth/Makefile b/arch/cris/drivers/bluetooth/Makefile
deleted file mode 100644
index b3cbffc6c1a4..000000000000
--- a/arch/cris/drivers/bluetooth/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-include $(APPS)/Rules.elinux
-
-all:
-
-install: src/bluetooth.c include/btcommon.h
- ln -sfn ../../arch/cris/drivers/bluetooth/include ../../../../include/linux/bluetooth
- if ! grep arch/cris/drivers/bluetooth/src/Config.in ../Config.in; then \
- echo '' >> ../Config.in; \
- echo 'if [ "$$CONFIG_ETRAX_SERIAL" = "y" ]; then' >> ../Config.in; \
- echo ' source arch/cris/drivers/bluetooth/src/Config.in' >> ../Config.in; \
- echo 'fi' >> ../Config.in; \
- fi
- if ! grep bluetooth/src/bt.o ../Makefile; then \
- perl -pi -e "s:include:obj-\\\$$(CONFIG_BLUETOOTH) += bluetooth/src/bt.o\nsubdir-\\\$$(CONFIG_BLUETOOTH) += bluetooth/src\n\ninclude:" ../Makefile; \
- fi
-
-clean:
-
-src/bluetooth.c:
- @echo "You must install the OpenBT src directory before install can be done here!"
- @exit 1
-
-include/btcommon.h:
- @echo "You must install the OpenBT include directory before install can be done here!"
- @exit 1
diff --git a/arch/cris/drivers/gpio.c b/arch/cris/drivers/gpio.c
deleted file mode 100644
index 533e2738c46f..000000000000
--- a/arch/cris/drivers/gpio.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/* $Id: gpio.c,v 1.2 2001/12/18 13:35:15 bjornw Exp $
- *
- * Etrax general port I/O device
- *
- * Copyright (c) 1999, 2000, 2001 Axis Communications AB
- *
- * Authors: Bjorn Wesen (initial version)
- * Ola Knutsson (LED handling)
- * Johan Adolfsson (read/set directions, write)
- *
- * $Log: gpio.c,v $
- * Revision 1.2 2001/12/18 13:35:15 bjornw
- * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
- *
- * Revision 1.12 2001/11/12 19:42:15 pkj
- * * Corrected return values from gpio_leds_ioctl().
- * * Fixed compiler warnings.
- *
- * Revision 1.11 2001/10/30 14:39:12 johana
- * Added D() around gpio_write printk.
- *
- * Revision 1.10 2001/10/25 10:24:42 johana
- * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
- * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
- * from ~60 seconds to 4 seconds).
- * Added save_flags/cli/restore_flags in ioctl.
- *
- * Revision 1.9 2001/05/04 14:16:07 matsfg
- * Corrected spelling error
- *
- * Revision 1.8 2001/04/27 13:55:26 matsfg
- * Moved initioremap.
- * Turns off all LEDS on init.
- * Added support for shutdown and powerbutton.
- *
- * Revision 1.7 2001/04/04 13:30:08 matsfg
- * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
- *
- * Revision 1.6 2001/03/26 16:03:06 bjornw
- * Needs linux/config.h
- *
- * Revision 1.5 2001/03/26 14:22:03 bjornw
- * Namechange of some config options
- *
- * Revision 1.4 2001/02/27 13:52:48 bjornw
- * malloc.h -> slab.h
- *
- * Revision 1.3 2001/01/24 15:06:48 bjornw
- * gpio_wq correct type
- *
- * Revision 1.2 2001/01/18 16:07:30 bjornw
- * 2.4 port
- *
- * Revision 1.1 2001/01/18 15:55:16 bjornw
- * Verbatim copy of etraxgpio.c from elinux 2.0 added
- *
- *
- */
-
-#include <linux/config.h>
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-
-#include <asm/etraxgpio.h>
-#include <asm/svinto.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#define GPIO_MAJOR 120 /* experimental MAJOR number */
-
-#define D(x)
-
-static char gpio_name[] = "etrax gpio";
-
-#if 0
-static wait_queue_head_t *gpio_wq;
-#endif
-
-static int gpio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
-static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
- loff_t *off);
-static int gpio_open(struct inode *inode, struct file *filp);
-static int gpio_release(struct inode *inode, struct file *filp);
-static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
-
-/* private data per open() of this driver */
-
-struct gpio_private {
- struct gpio_private *next;
- volatile unsigned char *port, *shadow;
- volatile unsigned char *dir, *dir_shadow;
- unsigned char changeable_dir;
- unsigned char changeable_bits;
- unsigned char highalarm, lowalarm;
- unsigned char clk_mask;
- unsigned char data_mask;
- unsigned char write_msb;
- wait_queue_head_t alarm_wq;
- int minor;
-};
-
-/* linked list of alarms to check for */
-
-static struct gpio_private *alarmlist = 0;
-
-#define NUM_PORTS 2
-static volatile unsigned char *ports[2] = { R_PORT_PA_DATA, R_PORT_PB_DATA };
-static volatile unsigned char *shads[2] = {
- &port_pa_data_shadow, &port_pb_data_shadow };
-
-/* What direction bits that are user changeable 1=changeable*/
-#ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
-#define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
-#endif
-#ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
-#define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
-#endif
-
-#ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
-#define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
-#endif
-#ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
-#define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
-#endif
-
-
-static unsigned char changeable_dir[2] = { CONFIG_ETRAX_PA_CHANGEABLE_DIR,
- CONFIG_ETRAX_PB_CHANGEABLE_DIR };
-static unsigned char changeable_bits[2] = { CONFIG_ETRAX_PA_CHANGEABLE_BITS,
- CONFIG_ETRAX_PB_CHANGEABLE_BITS };
-
-static volatile unsigned char *dir[2] = { R_PORT_PA_DIR, R_PORT_PB_DIR };
-
-static volatile unsigned char *dir_shadow[2] = {
- &port_pa_dir_shadow, &port_pb_dir_shadow };
-
-#define LEDS 2
-
-static unsigned int
-gpio_poll(struct file *filp,
- struct poll_table_struct *wait)
-{
- /* TODO poll on alarms! */
-#if 0
- if (!ANYTHING_WANTED) {
- D(printk("gpio_select sleeping task\n"));
- select_wait(&gpio_wq, table);
- return 0;
- }
- D(printk("gpio_select ready\n"));
-#endif
- return 1;
-}
-
-static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
- loff_t *off)
-{
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
- unsigned char data, clk_mask, data_mask, write_msb;
- unsigned long flags;
- ssize_t retval = count;
- if (verify_area(VERIFY_READ, buf, count)) {
- return -EFAULT;
- }
- clk_mask = priv->clk_mask;
- data_mask = priv->data_mask;
- /* It must have been configured using the IO_CFG_WRITE_MODE */
- /* Perhaps a better error code? */
- if (clk_mask == 0 || data_mask == 0) {
- return -EPERM;
- }
- write_msb = priv->write_msb;
- D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
- while (count--) {
- int i;
- data = *buf++;
- if (priv->write_msb) {
- for (i = 7; i >= 0;i--) {
- save_flags(flags); cli();
- *priv->port = *priv->shadow &= ~clk_mask;
- if (data & 1<<i)
- *priv->port = *priv->shadow |= data_mask;
- else
- *priv->port = *priv->shadow &= ~data_mask;
- /* For FPGA: min 5.0ns (DCC) before CCLK high */
- *priv->port = *priv->shadow |= clk_mask;
- restore_flags(flags);
- }
- } else {
- for (i = 0; i <= 7;i++) {
- save_flags(flags); cli();
- *priv->port = *priv->shadow &= ~clk_mask;
- if (data & 1<<i)
- *priv->port = *priv->shadow |= data_mask;
- else
- *priv->port = *priv->shadow &= ~data_mask;
- /* For FPGA: min 5.0ns (DCC) before CCLK high */
- *priv->port = *priv->shadow |= clk_mask;
- restore_flags(flags);
- }
- }
- }
- return retval;
-}
-
-static int
-gpio_open(struct inode *inode, struct file *filp)
-{
- struct gpio_private *priv;
- int p = minor(inode->i_rdev);
-
- if (p >= NUM_PORTS && p != LEDS)
- return -EINVAL;
-
- priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
- GFP_KERNEL);
-
- if (!priv)
- return -ENOMEM;
-
- priv->minor = p;
-
- /* initialize the io/alarm struct and link it into our alarmlist */
-
- priv->next = alarmlist;
- alarmlist = priv;
- priv->port = ports[p];
- priv->shadow = shads[p];
-
- priv->changeable_dir = changeable_dir[p];
- priv->changeable_bits = changeable_bits[p];
- priv->dir = dir[p];
- priv->dir_shadow = dir_shadow[p];
-
- priv->highalarm = 0;
- priv->lowalarm = 0;
- priv->clk_mask = 0;
- priv->data_mask = 0;
- init_waitqueue_head(&priv->alarm_wq);
-
- filp->private_data = (void *)priv;
-
- return 0;
-}
-
-static int
-gpio_release(struct inode *inode, struct file *filp)
-{
- struct gpio_private *p = alarmlist;
- struct gpio_private *todel = (struct gpio_private *)filp->private_data;
-
- /* unlink from alarmlist and free the private structure */
-
- if (p == todel) {
- alarmlist = todel->next;
- } else {
- while (p->next != todel)
- p = p->next;
- p->next = todel->next;
- }
-
- kfree(todel);
-
- return 0;
-}
-
-/* Main device API. ioctl's to read/set/clear bits, as well as to
- * set alarms to wait for using a subsequent select().
- */
-
-static int
-gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
-
-static int
-gpio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
- if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
- return -EINVAL;
- }
-
- switch (_IOC_NR(cmd)) {
- case IO_READBITS:
- // read the port
- return *priv->port;
- case IO_SETBITS:
- save_flags(flags); cli();
- // set changeable bits with a 1 in arg
- *priv->port = *priv->shadow |=
- ((unsigned char)arg & priv->changeable_bits);
- restore_flags(flags);
- break;
- case IO_CLRBITS:
- save_flags(flags); cli();
- // clear changeable bits with a 1 in arg
- *priv->port = *priv->shadow &=
- ~((unsigned char)arg & priv->changeable_bits);
- restore_flags(flags);
- break;
- case IO_HIGHALARM:
- // set alarm when bits with 1 in arg go high
- priv->highalarm |= (unsigned char)arg;
- break;
- case IO_LOWALARM:
- // set alarm when bits with 1 in arg go low
- priv->lowalarm |= (unsigned char)arg;
- break;
- case IO_CLRALARM:
- // clear alarm for bits with 1 in arg
- priv->highalarm &= ~(unsigned char)arg;
- priv->lowalarm &= ~(unsigned char)arg;
- break;
- case IO_READDIR:
- /* Read direction 0=input 1=output */
- return *priv->dir_shadow;
- case IO_SETINPUT:
- save_flags(flags); cli();
- /* Set direction 0=unchanged 1=input */
- *priv->dir = *priv->dir_shadow &=
- ~((unsigned char)arg & priv->changeable_dir);
- restore_flags(flags);
- return *priv->dir_shadow;
- case IO_SETOUTPUT:
- save_flags(flags); cli();
- /* Set direction 0=unchanged 1=output */
- *priv->dir = *priv->dir_shadow |=
- ((unsigned char)arg & priv->changeable_dir);
- restore_flags(flags);
- return *priv->dir_shadow;
- case IO_SHUTDOWN:
- SOFT_SHUTDOWN();
- break;
- case IO_GET_PWR_BT:
-#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
- return (*R_PORT_G_DATA &
- ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
-#else
- return 0;
-#endif
- break;
- case IO_CFG_WRITE_MODE:
- priv->clk_mask = arg & 0xFF;
- priv->data_mask = (arg >> 8) & 0xFF;
- priv->write_msb = (arg >> 16) & 0x01;
- /* Check if we're allowed to change the bits and
- * the direction is correct
- */
- if (!((priv->clk_mask & priv->changeable_bits) &&
- (priv->data_mask & priv->changeable_bits) &&
- (priv->clk_mask & *priv->dir_shadow) &&
- (priv->data_mask & *priv->dir_shadow)))
- {
- priv->clk_mask = 0;
- priv->data_mask = 0;
- return -EPERM;
- }
- break;
- default:
- if (priv->minor == LEDS)
- return gpio_leds_ioctl(cmd, arg);
- else
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
-{
- unsigned char green;
- unsigned char red;
-
- switch (_IOC_NR(cmd)) {
- case IO_LEDACTIVE_SET:
- green = ((unsigned char) arg) & 1;
- red = (((unsigned char) arg) >> 1) & 1;
- LED_ACTIVE_SET_G(green);
- LED_ACTIVE_SET_R(red);
- break;
-
- case IO_LED_SETBIT:
- LED_BIT_SET(arg);
- break;
-
- case IO_LED_CLRBIT:
- LED_BIT_CLR(arg);
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-struct file_operations gpio_fops = {
- .owner = THIS_MODULE,
- .poll = gpio_poll,
- .ioctl = gpio_ioctl,
- .write = gpio_write,
- .open = gpio_open,
- .release = gpio_release,
-};
-
-/* main driver initialization routine, called from mem.c */
-
-static __init int
-gpio_init(void)
-{
- extern void init_ioremap(void);
- int res;
-#if defined (CONFIG_ETRAX_CSP0_LEDS)
- int i;
-#endif
-
- /* do the formalities */
-
- res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
- if (res < 0) {
- printk(KERN_ERR "gpio: couldn't get a major number.\n");
- return res;
- }
-
- /* Clear all leds */
-#if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
- init_ioremap();
- LED_NETWORK_SET(0);
- LED_ACTIVE_SET(0);
- LED_DISK_READ(0);
- LED_DISK_WRITE(0);
-
-#if defined (CONFIG_ETRAX_CSP0_LEDS)
- for (i = 0; i < 32; i++) {
- LED_BIT_SET(i);
- }
-#endif
-
-#endif
-
- printk("ETRAX 100LX GPIO driver v2.2, (c) 2001 Axis Communications AB\n");
-
- return res;
-}
-
-/* this makes sure that gpio_init is called during kernel boot */
-
-module_init(gpio_init);
diff --git a/arch/cris/drivers/ide.c b/arch/cris/drivers/ide.c
deleted file mode 100644
index 89ae840968e8..000000000000
--- a/arch/cris/drivers/ide.c
+++ /dev/null
@@ -1,877 +0,0 @@
-/* $Id: ide.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
- *
- * Etrax specific IDE functions, like init and PIO-mode setting etc.
- * Almost the entire ide.c is used for the rest of the Etrax ATA driver.
- * Copyright (c) 2000, 2001 Axis Communications AB
- *
- * Authors: Bjorn Wesen (initial version)
- * Mikael Starvik (pio setup stuff)
- *
- * $Log: ide.c,v $
- * Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
- * Import of Linux 2.5.1
- *
- * Revision 1.19 2001/05/09 12:53:16 johana
- * Added #include <asm/dma.h>
- *
- * Revision 1.18 2001/05/09 12:37:00 johana
- * Use DMA_NBR macros from dma.h.
- *
- * Revision 1.17 2001/04/23 13:36:30 matsfg
- * Changed CONFIG_IDE_DELAY to CONFIG_ETRAX_IDE_DELAY
- *
- * Revision 1.16 2001/04/05 08:30:07 matsfg
- * Corrected cse1 and csp0 reset.
- *
- * Revision 1.15 2001/04/04 14:34:06 bjornw
- * Re-instated code that mysteriously disappeared during review updates.
- *
- * Revision 1.14 2001/04/04 13:45:12 matsfg
- * Calls REG_SHADOW_SET for cse1 reset so only the resetbit is affected
- *
- * Revision 1.13 2001/04/04 13:26:40 matsfg
- * memmapping is done in init.c
- *
- * Revision 1.12 2001/04/04 11:37:56 markusl
- * Updated according to review remarks
- *
- * Revision 1.11 2001/03/29 12:49:14 matsfg
- * Changed check for ata_tot_size from >= to >.
- * Sets sw_len to 0 if size is exactly 65536.
- *
- * Revision 1.10 2001/03/16 09:39:30 matsfg
- * Support for reset on port CSP0
- *
- * Revision 1.9 2001/03/01 13:11:18 bjornw
- * 100 -> HZ
- *
- * Revision 1.8 2001/03/01 09:32:56 matsfg
- * Moved IDE delay to a CONFIG-parameter instead
- *
- * Revision 1.7 2001/02/23 13:46:38 bjornw
- * Spellling check
- *
- * Revision 1.6 2001/02/22 15:44:30 bjornw
- * * Use ioremap when mapping the CSE1 memory-mapped reset-line for LX v2
- * * sw_len for a 65536 descriptor is 0, not 65536
- * * Express concern for G27 reset code
- *
- * Revision 1.5 2001/02/16 07:35:38 matsfg
- * Now handles DMA request blocks between 64k and 128k by split into two descriptors.
- *
- * Revision 1.4 2001/01/10 21:14:32 bjornw
- * Initialize hwif->ideproc, for the new way of handling ide_xxx_data
- *
- * Revision 1.3 2000/12/01 17:48:18 bjornw
- * - atapi_output_bytes now uses DMA
- * - dma_active check removed - the kernel does proper serializing and it had
- * a race-condition anyway
- * - ide_build_dmatable had a nameclash
- * - re-added the RESET_DMA thingys because sometimes the interface can get
- * stuck apparently
- * - added ide_release_dma
- *
- * Revision 1.2 2000/11/29 17:31:29 bjornw
- * 2.4 port
- *
- * - The "register addresses" stored in the hwif are now 32-bit fields that
- * don't need to be shifted into correct positions in R_ATA_CTRL_DATA
- * - PIO-mode detection temporarily disabled since ide-modes.c is not compiled
- * - All DMA uses virt_to_phys conversions for DMA buffers and descriptor ptrs
- * - Probably correct ide_dma_begin semantics in dmaproc now for ATAPI devices
- * - Removed RESET_DMA when starting a new transfer - why was this necessary ?
- * - Indentation fix
- *
- *
- */
-
-/* Regarding DMA:
- *
- * There are two forms of DMA - "DMA handshaking" between the interface and the drive,
- * and DMA between the memory and the interface. We can ALWAYS use the latter, since it's
- * something built-in in the Etrax. However only some drives support the DMA-mode handshaking
- * on the ATA-bus. The normal PC driver and Triton interface disables memory-if DMA when the
- * device can't do DMA handshaking for some stupid reason. We don't need to do that.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/svinto.h>
-#include <asm/dma.h>
-
-/* number of Etrax DMA descriptors */
-#define MAX_DMA_DESCRS 64
-
-#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
-/* address where the memory-mapped IDE reset bit lives, if used */
-static volatile unsigned long *reset_addr;
-#endif
-
-#define LOWDB(x)
-#define D(x)
-
-void OUT_BYTE(unsigned char data, ide_ioreg_t reg) {
- LOWDB(printk("ob: data 0x%x, reg 0x%x\n", data, reg));
- while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag */
- *R_ATA_CTRL_DATA = reg | data; /* write data to the drive's register */
- while(!(*R_ATA_STATUS_DATA &
- IO_MASK(R_ATA_STATUS_DATA, tr_rdy))); /* wait for transmitter ready */
-}
-
-unsigned char IN_BYTE(ide_ioreg_t reg) {
- int status;
- while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag */
- *R_ATA_CTRL_DATA = reg | IO_STATE(R_ATA_CTRL_DATA, rw, read); /* read data */
- while(!((status = *R_ATA_STATUS_DATA) &
- IO_MASK(R_ATA_STATUS_DATA, dav))); /* wait for available */
- LOWDB(printk("inb: 0x%x from reg 0x%x\n", status & 0xff, reg));
- return (unsigned char)status; /* data was in the lower 16 bits in the status reg */
-}
-
-/* PIO timing (in R_ATA_CONFIG)
- *
- * _____________________________
- * ADDRESS : ________/
- *
- * _______________
- * DIOR : ____________/ \__________
- *
- * _______________
- * DATA : XXXXXXXXXXXXXXXX_______________XXXXXXXX
- *
- *
- * DIOR is unbuffered while address and data is buffered.
- * This creates two problems:
- * 1. The DIOR pulse is to early (because it is unbuffered)
- * 2. The rise time of DIOR is long
- *
- * There are at least three different plausible solutions
- * 1. Use a pad capable of larger currents in Etrax
- * 2. Use an external buffer
- * 3. Make the strobe pulse longer
- *
- * Some of the strobe timings below are modified to compensate
- * for this. This implies a slight performance decrease.
- *
- * THIS SHOULD NEVER BE CHANGED!
- *
- * TODO: Is this true for the latest LX boards still ?
- */
-
-#define ATA_DMA2_STROBE 4
-#define ATA_DMA2_HOLD 0
-#define ATA_DMA1_STROBE 4
-#define ATA_DMA1_HOLD 1
-#define ATA_DMA0_STROBE 12
-#define ATA_DMA0_HOLD 9
-#define ATA_PIO4_SETUP 1
-#define ATA_PIO4_STROBE 5
-#define ATA_PIO4_HOLD 0
-#define ATA_PIO3_SETUP 1
-#define ATA_PIO3_STROBE 5
-#define ATA_PIO3_HOLD 1
-#define ATA_PIO2_SETUP 1
-#define ATA_PIO2_STROBE 6
-#define ATA_PIO2_HOLD 2
-#define ATA_PIO1_SETUP 2
-#define ATA_PIO1_STROBE 11
-#define ATA_PIO1_HOLD 4
-#define ATA_PIO0_SETUP 4
-#define ATA_PIO0_STROBE 19
-#define ATA_PIO0_HOLD 4
-
-static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq);
-static void e100_ideproc (ide_ide_action_t func, struct ata_device *drive,
- void *buffer, unsigned int length);
-
-/*
- * good_dma_drives() lists the model names (from "hdparm -i")
- * of drives which do not support mword2 DMA but which are
- * known to work fine with this interface under Linux.
- */
-
-const char *good_dma_drives[] = {"Micropolis 2112A",
- "CONNER CTMA 4000",
- "CONNER CTT8000-A",
- NULL};
-
-static void tune_e100_ide(struct ata_device *drive, byte pio)
-{
- unsigned long flags;
-
- pio = 4;
- /* pio = ide_get_best_pio_mode(drive, pio, 4, NULL); */
-
- save_flags(flags);
- cli();
-
- /* set pio mode! */
-
- switch(pio) {
- case 0:
- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) |
- IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) |
- IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO0_SETUP ) |
- IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO0_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO0_HOLD ) );
- break;
- case 1:
- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) |
- IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) |
- IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO1_SETUP ) |
- IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO1_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO1_HOLD ) );
- break;
- case 2:
- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) |
- IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) |
- IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO2_SETUP ) |
- IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO2_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO2_HOLD ) );
- break;
- case 3:
- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) |
- IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) |
- IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO3_SETUP ) |
- IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO3_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO3_HOLD ) );
- break;
- case 4:
- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) |
- IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) |
- IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO4_SETUP ) |
- IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO4_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO4_HOLD ) );
- break;
- }
- restore_flags(flags);
-}
-
-void __init
-init_e100_ide (void)
-{
- volatile unsigned int dummy;
- int h;
-
- printk("ide: ETRAX 100LX built-in ATA DMA controller\n");
-
- /* first initialize the channel interface data */
-
- for(h = 0; h < MAX_HWIFS; h++) {
- struct ata_channel *hwif = &ide_hwifs[h];
-
- hwif->chipset = ide_etrax100;
- hwif->tuneproc = &tune_e100_ide;
- hwif->udma = &e100_dmaproc;
- hwif->ata_read = e100_ide_input_data;
- hwif->ata_write = e100_ide_output_data;
- hwif->atapi_read = e100_atapi_read;
- hwif->atapi_write = e100_atapi_write;
- }
- /* actually reset and configure the etrax100 ide/ata interface */
-
- /* This is mystifying; why is not G27 SET anywhere ? It's just reset here twice. */
-
- /* de-assert bus-reset */
-#ifdef CONFIG_ETRAX_IDE_PB7_RESET
- port_pb_dir_shadow = port_pb_dir_shadow |
- IO_STATE(R_PORT_PB_DIR, dir7, output);
- *R_PORT_PB_DIR = port_pb_dir_shadow;
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 7, 1);
-#endif
-#ifdef CONFIG_ETRAX_IDE_G27_RESET
- *R_PORT_G_DATA = 0;
-#endif
-
- *R_ATA_CTRL_DATA = 0;
- *R_ATA_TRANSFER_CNT = 0;
- *R_ATA_CONFIG = 0;
-
- genconfig_shadow = (genconfig_shadow &
- ~IO_MASK(R_GEN_CONFIG, dma2) &
- ~IO_MASK(R_GEN_CONFIG, dma3) &
- ~IO_MASK(R_GEN_CONFIG, ata)) |
- ( IO_STATE( R_GEN_CONFIG, dma3, ata ) |
- IO_STATE( R_GEN_CONFIG, dma2, ata ) |
- IO_STATE( R_GEN_CONFIG, ata, select ) );
-
- *R_GEN_CONFIG = genconfig_shadow;
-
-#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
- init_ioremap();
- REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 0);
-#endif
-
-#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET
- init_ioremap();
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 0);
-#endif
-
- /* wait some */
- udelay(25);
-
-#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
- REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 1);
-#endif
-#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 1);
-#endif
-#ifdef CONFIG_ETRAX_IDE_G27_RESET
- *R_PORT_G_DATA = 0; /* de-assert bus-reset */
-#endif
-
- /* make a dummy read to set the ata controller in a proper state */
- dummy = *R_ATA_STATUS_DATA;
-
- *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) |
- IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) |
- IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO4_SETUP ) |
- IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO4_STROBE ) |
- IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO4_HOLD ) );
-
- *R_ATA_CTRL_DATA = ( IO_STATE( R_ATA_CTRL_DATA, rw, read) |
- IO_FIELD( R_ATA_CTRL_DATA, addr, 1 ) );
-
- while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag*/
-
- *R_IRQ_MASK0_SET = ( IO_STATE( R_IRQ_MASK0_SET, ata_irq0, set ) |
- IO_STATE( R_IRQ_MASK0_SET, ata_irq1, set ) |
- IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set ) |
- IO_STATE( R_IRQ_MASK0_SET, ata_irq3, set ) );
-
- printk("ide: waiting %d seconds for drives to regain consciousness\n", CONFIG_ETRAX_IDE_DELAY);
-
- h = jiffies + (CONFIG_ETRAX_IDE_DELAY * HZ);
- while(time_before(jiffies, h)) ;
-
- /* reset the dma channels we will use */
-
- RESET_DMA(ATA_TX_DMA_NBR);
- RESET_DMA(ATA_RX_DMA_NBR);
- WAIT_DMA(ATA_TX_DMA_NBR);
- WAIT_DMA(ATA_RX_DMA_NBR);
-
-}
-
-static etrax_dma_descr mydescr;
-
-/*
- * The following routines are mainly used by the ATAPI drivers.
- *
- * These routines will round up any request for an odd number of bytes,
- * so if an odd bytecount is specified, be sure that there's at least one
- * extra byte allocated for the buffer.
- */
-static void
-e100_atapi_read(struct ata_device *drive, void *buffer, unsigned int bytecount)
-{
- ide_ioreg_t data_reg = IDE_DATA_REG;
-
- D(printk("atapi_read, dreg 0x%x, buffer 0x%x, count %d\n",
- data_reg, buffer, bytecount));
-
- if(bytecount & 1) {
- printk("warning, odd bytecount in cdrom_in_bytes = %d.\n", bytecount);
- bytecount++; /* to round off */
- }
-
- /* make sure the DMA channel is available */
- RESET_DMA(ATA_RX_DMA_NBR);
- WAIT_DMA(ATA_RX_DMA_NBR);
-
- /* setup DMA descriptor */
-
- mydescr.sw_len = bytecount;
- mydescr.ctrl = d_eol;
- mydescr.buf = virt_to_phys(buffer);
-
- /* start the dma channel */
-
- *R_DMA_CH3_FIRST = virt_to_phys(&mydescr);
- *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start);
-
- /* initiate a multi word dma read using PIO handshaking */
-
- *R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1);
-
- *R_ATA_CTRL_DATA = data_reg |
- IO_STATE(R_ATA_CTRL_DATA, rw, read) |
- IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) |
- IO_STATE(R_ATA_CTRL_DATA, handsh, pio) |
- IO_STATE(R_ATA_CTRL_DATA, multi, on) |
- IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-
- /* wait for completion */
-
- LED_DISK_READ(1);
- WAIT_DMA(ATA_RX_DMA_NBR);
- LED_DISK_READ(0);
-
-#if 0
- /* old polled transfer code
- * this should be moved into a new function that can do polled
- * transfers if DMA is not available
- */
-
- /* initiate a multi word read */
-
- *R_ATA_TRANSFER_CNT = wcount << 1;
-
- *R_ATA_CTRL_DATA = data_reg |
- IO_STATE(R_ATA_CTRL_DATA, rw, read) |
- IO_STATE(R_ATA_CTRL_DATA, src_dst, register) |
- IO_STATE(R_ATA_CTRL_DATA, handsh, pio) |
- IO_STATE(R_ATA_CTRL_DATA, multi, on) |
- IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-
- /* svinto has a latency until the busy bit actually is set */
-
- nop(); nop();
- nop(); nop();
- nop(); nop();
- nop(); nop();
- nop(); nop();
-
- /* unit should be busy during multi transfer */
- while((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, busy)) {
- while(!(status & IO_MASK(R_ATA_STATUS_DATA, dav)))
- status = *R_ATA_STATUS_DATA;
- *ptr++ = (unsigned short)(status & 0xffff);
- }
-#endif
-}
-
-static void
-e100_atapi_write(struct ata_device *drive, void *buffer, unsigned int bytecount)
-{
- ide_ioreg_t data_reg = IDE_DATA_REG;
-
- D(printk("atapi_write, dreg 0x%x, buffer 0x%x, count %d\n",
- data_reg, buffer, bytecount));
-
- if(bytecount & 1) {
- printk("odd bytecount %d in atapi_out_bytes!\n", bytecount);
- bytecount++;
- }
-
- /* make sure the DMA channel is available */
- RESET_DMA(ATA_TX_DMA_NBR);
- WAIT_DMA(ATA_TX_DMA_NBR);
-
- /* setup DMA descriptor */
-
- mydescr.sw_len = bytecount;
- mydescr.ctrl = d_eol;
- mydescr.buf = virt_to_phys(buffer);
-
- /* start the dma channel */
-
- *R_DMA_CH2_FIRST = virt_to_phys(&mydescr);
- *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start);
-
- /* initiate a multi word dma write using PIO handshaking */
-
- *R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1);
-
- *R_ATA_CTRL_DATA = data_reg |
- IO_STATE(R_ATA_CTRL_DATA, rw, write) |
- IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) |
- IO_STATE(R_ATA_CTRL_DATA, handsh, pio) |
- IO_STATE(R_ATA_CTRL_DATA, multi, on) |
- IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-
- /* wait for completion */
-
- LED_DISK_WRITE(1);
- WAIT_DMA(ATA_TX_DMA_NBR);
- LED_DISK_WRITE(0);
-
-#if 0
- /* old polled write code - see comment in input_bytes */
-
- /* wait for busy flag */
- while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy));
-
- /* initiate a multi word write */
-
- *R_ATA_TRANSFER_CNT = bytecount >> 1;
-
- ctrl = data_reg |
- IO_STATE(R_ATA_CTRL_DATA, rw, write) |
- IO_STATE(R_ATA_CTRL_DATA, src_dst, register) |
- IO_STATE(R_ATA_CTRL_DATA, handsh, pio) |
- IO_STATE(R_ATA_CTRL_DATA, multi, on) |
- IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-
- LED_DISK_WRITE(1);
-
- /* Etrax will set busy = 1 until the multi pio transfer has finished
- * and tr_rdy = 1 after each succesful word transfer.
- * When the last byte has been transferred Etrax will first set tr_tdy = 1
- * and then busy = 0 (not in the same cycle). If we read busy before it
- * has been set to 0 we will think that we should transfer more bytes
- * and then tr_rdy would be 0 forever. This is solved by checking busy
- * in the inner loop.
- */
-
- do {
- *R_ATA_CTRL_DATA = ctrl | *ptr++;
- while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)) &&
- (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)));
- } while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy));
-
- LED_DISK_WRITE(0);
-#endif
-
-}
-
-/*
- * This is used for most PIO data transfers *from* the IDE interface
- */
-static void
-e100_ide_input_data (struct ata_device *drive, void *buffer, unsigned int wcount)
-{
- e100_atapi_read(drive, buffer, wcount << 2);
-}
-
-/*
- * This is used for most PIO data transfers *to* the IDE interface
- */
-static void
-e100_ide_output_data (struct ata_device *drive, void *buffer, unsigned int wcount)
-{
- e100_atapi_write(drive, buffer, wcount << 2);
-}
-
-/* we only have one DMA channel on the chip for ATA, so we can keep these statically */
-static etrax_dma_descr ata_descrs[MAX_DMA_DESCRS];
-static unsigned int ata_tot_size;
-
-
-/*
- * This prepares a dma request. Returns 0 if all went okay, returns 1
- * otherwise.
- */
-
-static int e100_udma_new_table(struct ata_channel *ch, struct request *rq)
-{
- struct buffer_head *bh = rq->bh;
- unsigned long size, addr;
- unsigned int count = 0;
-
- ata_tot_size = 0;
-
- do {
- /*
- * Determine addr and size of next buffer area. We assume that
- * individual virtual buffers are always composed linearly in
- * physical memory. For example, we assume that any 8kB buffer
- * is always composed of two adjacent physical 4kB pages rather
- * than two possibly non-adjacent physical 4kB pages.
- */
- if (bh == NULL) { /* paging and tape requests have (rq->bh == NULL) */
- addr = virt_to_phys (rq->buffer);
- size = rq->nr_sectors << 9;
- } else {
- /* group sequential buffers into one large buffer */
- addr = virt_to_phys (bh->b_data);
- size = bh->b_size;
- while ((bh = bh->b_reqnext) != NULL) {
- if ((addr + size) != virt_to_phys (bh->b_data))
- break;
- size += bh->b_size;
- }
- }
-
- /* did we run out of descriptors? */
-
- if(count >= MAX_DMA_DESCRS) {
- printk("%s: too few DMA descriptors\n", ch->name);
- return 1;
- }
-
- /* however, this case is more difficult - R_ATA_TRANSFER_CNT cannot be more
- than 65536 words per transfer, so in that case we need to either
- 1) use a DMA interrupt to re-trigger R_ATA_TRANSFER_CNT and continue with
- the descriptors, or
- 2) simply do the request here, and get dma_intr to only ide_end_request on
- those blocks that were actually set-up for transfer.
- */
-
- if(ata_tot_size + size > 131072) {
- printk("too large total ATA DMA request, %d + %d!\n", ata_tot_size, size);
- return 1;
- }
-
- /* If size > 65536 it has to be splitted into new descriptors. Since we don't handle
- size > 131072 only one split is necessary */
-
- if(size > 65536) {
- /* ok we want to do IO at addr, size bytes. set up a new descriptor entry */
- ata_descrs[count].sw_len = 0; /* 0 means 65536, this is a 16-bit field */
- ata_descrs[count].ctrl = 0;
- ata_descrs[count].buf = addr;
- ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]);
- count++;
- ata_tot_size += 65536;
- /* size and addr should refere to not handled data */
- size -= 65536;
- addr += 65536;
- }
- /* ok we want to do IO at addr, size bytes. set up a new descriptor entry */
- if(size == 65536) {
- ata_descrs[count].sw_len = 0; /* 0 means 65536, this is a 16-bit field */
- }
- else {
- ata_descrs[count].sw_len = size;
- }
- ata_descrs[count].ctrl = 0;
- ata_descrs[count].buf = addr;
- ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]);
- count++;
- ata_tot_size += size;
-
- } while (bh != NULL);
-
- if (count) {
- /* set the end-of-list flag on the last descriptor */
- ata_descrs[count - 1].ctrl |= d_eol;
- /* return and say all is ok */
- return 0;
- }
-
- printk("%s: empty DMA table?\n", ch->name);
- return 1; /* let the PIO routines handle this weirdness */
-}
-
-static int config_drive_for_dma (struct ata_device *drive)
-{
- const char **list;
- struct hd_driveid *id = drive->id;
-
- if (id && (id->capability & 1)) {
- /* Enable DMA on any drive that supports mword2 DMA */
- if ((id->field_valid & 2) && (id->dma_mword & 0x404) == 0x404) {
- drive->using_dma = 1;
- return 0; /* DMA enabled */
- }
-
- /* Consult the list of known "good" drives */
- list = good_dma_drives;
- while (*list) {
- if (!strcmp(*list++,id->model)) {
- drive->using_dma = 1;
- return 0; /* DMA enabled */
- }
- }
- }
- return 1; /* DMA not enabled */
-}
-
-/*
- * etrax_dma_intr() is the handler for disk read/write DMA interrupts
- */
-static ide_startstop_t etrax_dma_intr(struct ata_device *drive, struct request *rq)
-{
- int i, dma_stat;
-
- LED_DISK_READ(0);
- LED_DISK_WRITE(0);
-
- dma_stat = drive->channel->udma(ide_dma_end, drive, rq);
- /* get drive status */
- if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
- if (!dma_stat) {
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(drive, rq, 1);
- }
- return ATA_OP_FINISHED;
- }
- printk("%s: bad DMA status\n", drive->name);
- }
- return ata_error(drive, rq, __FUNCTION__);
-}
-
-/*
- * e100_dmaproc() initiates/aborts DMA read/write operations on a drive.
- *
- * The caller is assumed to have selected the drive and programmed the drive's
- * sector address using CHS or LBA. All that remains is to prepare for DMA
- * and then issue the actual read/write DMA/PIO command to the drive.
- *
- * For ATAPI devices, we just prepare for DMA and return. The caller should
- * then issue the packet command to the drive and call us again with
- * ide_dma_begin afterwards.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case
- * the caller should revert to PIO for the current request.
- */
-
-static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
-{
- static unsigned int reading; /* static to support ide_dma_begin semantics */
- int atapi = 0;
-
- D(printk("e100_dmaproc func %d\n", func));
-
- switch (func) {
- case ide_dma_verbose:
- return 0;
- case ide_dma_check:
- return config_drive_for_dma (drive);
- case ide_dma_off:
- case ide_dma_off_quietly:
- /* ok.. we don't really need to do anything I think. */
- return 0;
- case ide_dma_write:
- reading = 0;
- break;
- case ide_dma_read:
- reading = 1;
- break;
- case ide_dma_begin:
- /* begin DMA, used by ATAPI devices which want to issue the
- * appropriate IDE command themselves.
- *
- * they have already called ide_dma_read/write to set the
- * static reading flag, now they call ide_dma_begin to do
- * the real stuff. we tell our code below not to issue
- * any IDE commands itself and jump into it.
- */
- atapi++;
- goto dma_begin;
- case ide_dma_end: /* returns 1 on error, 0 otherwise */
- /* TODO: check if something went wrong with the DMA */
- return 0;
-
- default:
- printk("e100_dmaproc: unsupported func %d\n", func);
- return 1;
- }
-
- /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction
- * then they call ide_dma_begin after they have issued the appropriate drive command
- * themselves to actually start the chipset DMA. so we just return here if we're
- * not a diskdrive.
- */
-
- if (drive->type != ATA_DISK)
- return 0;
-
- dma_begin:
-
- if(reading) {
-
- RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */
- WAIT_DMA(ATA_RX_DMA_NBR);
-
- /* set up the Etrax DMA descriptors */
-
- if(e100_udma_new_table(drive->channel, rq))
- return 1;
-
- if(!atapi) {
- /* set the irq handler which will finish the request when DMA is done */
- ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
-
- /* issue cmd to drive */
- OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG);
- }
-
- /* begin DMA */
- *R_DMA_CH3_FIRST = virt_to_phys(ata_descrs);
- *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start);
-
- /* initiate a multi word dma read using DMA handshaking */
-
- *R_ATA_TRANSFER_CNT =
- IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1);
-
- *R_ATA_CTRL_DATA =
- IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) |
- IO_STATE(R_ATA_CTRL_DATA, rw, read) |
- IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) |
- IO_STATE(R_ATA_CTRL_DATA, handsh, dma) |
- IO_STATE(R_ATA_CTRL_DATA, multi, on) |
- IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-
- LED_DISK_READ(1);
-
- D(printk("dma read of %d bytes.\n", ata_tot_size));
-
- } else {
- /* writing */
-
- RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */
- WAIT_DMA(ATA_TX_DMA_NBR);
-
- /* set up the Etrax DMA descriptors */
-
- if(e100_udma_new_table(drive->channel, rq))
- return 1;
-
- if(!atapi) {
- /* set the irq handler which will finish the request when DMA is done */
- ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
-
- /* issue cmd to drive */
- OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG);
- }
-
- /* begin DMA */
- *R_DMA_CH2_FIRST = virt_to_phys(ata_descrs);
- *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start);
-
- /* initiate a multi word dma write using DMA handshaking */
- *R_ATA_TRANSFER_CNT =
- IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1);
-
- *R_ATA_CTRL_DATA =
- IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) |
- IO_STATE(R_ATA_CTRL_DATA, rw, write) |
- IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) |
- IO_STATE(R_ATA_CTRL_DATA, handsh, dma) |
- IO_STATE(R_ATA_CTRL_DATA, multi, on) |
- IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-
- LED_DISK_WRITE(1);
-
- D(printk("dma write of %d bytes.\n", ata_tot_size));
- }
-
- /* DMA started successfully */
- return 0;
-}
-
-/* ide.c calls this, but we don't need to do anything particular */
-
-/* Dear maintainer of this architecture please note that it would be a little
- * more clever :-) to put this up into some header as static inline, so the
- * spurious code below would just vanish.
- *
- * --- Marcin Dalecki
- */
-
-void ide_release_dma(struct ata_channel *ch)
-{
- /* empty */
-}
diff --git a/arch/cris/drivers/lpslave/Makefile b/arch/cris/drivers/lpslave/Makefile
deleted file mode 100644
index 6d7982db01e8..000000000000
--- a/arch/cris/drivers/lpslave/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Makefile for parallel port slave drivers
-#
-
-obj-y = e100lpslavenet.o e100lpslave_code.o
-
-e100lpslave_code.o: e100lpslave.o e100lpslaveld
- $(CROSS_COMPILE)ld -qmagic -Te100lpslaveld e100lpslave.o -o e100lpslave
- $(CROSS_COMPILE)objcopy -O binary --remove-section=.data --remove-section=.bss e100lpslave e100lpslave.text
- $(CROSS_COMPILE)objcopy -O binary --remove-section=.text --remove-section=.bss e100lpslave e100lpslave.data
- cat e100lpslave.text e100lpslave.data |\
- ./bintocarr.pl e100lpslaveprog |\
- $(CC) $(CFLAGS) -pipe -o e100lpslave_code.o -c -x c -
- ls -l e100lpslave.text e100lpslave.data
- rm -f e100lpslave e100lpslave.text e100lpslave.data
diff --git a/arch/cris/drivers/lpslave/bintocarr.pl b/arch/cris/drivers/lpslave/bintocarr.pl
deleted file mode 100644
index c03dd8b718b7..000000000000
--- a/arch/cris/drivers/lpslave/bintocarr.pl
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/perl -w
-# $Id: bintocarr.pl,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
-# Copy of mkjulbin.pl made by Olof
-# convert a binary stdin to a C-file containing a char array of the input
-# first argument is the symbol name
-
-$symbol = shift @ARGV;
-
-print "#include <linux/init.h>\n\n";
-#print "unsigned char $symbol", "[] __initdata = {\n";
-print "unsigned char $symbol", "[] = {\n";
-
-my $char;
-
-$bcount = 0;
-
-while(read STDIN, $char, 1) {
- printf("0x%x, ", ord($char));
- $bcount++;
- if(!($bcount % 16)) {
- print "\n";
- }
-}
-
-print "\n};\n";
-
-$lensymb = ("_" . ($symbol . "_length"));
-
-print "__asm__(\"\\t.globl $lensymb\\n$lensymb = $bcount\\n\");\n";
-
diff --git a/arch/cris/drivers/lpslave/e100lpslave.README b/arch/cris/drivers/lpslave/e100lpslave.README
deleted file mode 100644
index eb580a9d2dac..000000000000
--- a/arch/cris/drivers/lpslave/e100lpslave.README
+++ /dev/null
@@ -1,54 +0,0 @@
-***** MODIFICATIONS
-To use a 5600 as a slave device it has to somewhat modified.
-This has to be done on a 5600 (art no 16144 R2) to automatically set it to parallel port boot mode:
-
-1)
-Close to the LPT1 connector there are two resistors, between the "Pulse" inductor and
-the LS245. The one closest to the LS245 is a 4k7 pull up (R105). Remove it.
-
-2)
-Between the other "Pulse" inductor and Etrax there is a black 5-pin inverter
-(D15). Short connectors 2 and 3 with a solder blob.
-
-
-***** PINOUT
-To use this driver use cables connected like this:
-DSUB25-Male DSUB25Male
-
-1 10
-2-9 2-9
-10 1
-11 14
-12 18
-13 NC
-14 11
-15 NC
-16 NC
-17 NC
-18 12
-19 NC
-20-25 20-25
-
-Thus the cables are symmetrical with most cables straight through,
-some crossed (1-10, 11-14 and 12-18)
-and some Not connected (NC 13,15,16,17 and 19).
-
-
-******* Only for reference
-To ease the use of flat-cable connectors, here are the notes of wich wires to cross and cut with pin 1 being cable 1:
-Cross:
-1 19
-2 21
-10 23
-Cut:
-4
-6
-8
-12
-25
-
-jonas.dellenvall@axis.com
-
-
-
-
diff --git a/arch/cris/drivers/lpslave/e100lpslave.S b/arch/cris/drivers/lpslave/e100lpslave.S
deleted file mode 100644
index 44efe0771fc2..000000000000
--- a/arch/cris/drivers/lpslave/e100lpslave.S
+++ /dev/null
@@ -1,429 +0,0 @@
- ;; $Id: e100lpslave.S,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
- ;;
- ;; Etrax100 slave network<->parport forwarder
- ;;
- ;; Copyright (c) 1999 Bjorn Wesen, Axis Communications AB
- ;;
- ;; We got 784 bytes (par loader size) to do DMA forwarding
- ;; between DMA0/1 (ethernet) and DMA3/4 (par port 0 RX/1 TX)
- ;;
-
-#include <linux/config.h>
-#if 0
-#define ASSEMBLER_MACROS_ONLY
-#endif
-#include <asm/sv_addr_ag.h>
-
-#define BUFSIZE 0x600
-
- ;; R_IRQ_READ2
-
-#define DMA1EOPBIT 3
-#define DMA0EOPBIT 1
-#define DMA3EOPBIT 7
-#define DMA4DESCBIT 8
-
- ;; R_IRQ_READ0
-
-#define PAR0ECPCMDBIT 11
-
- ;; get host CMDs
-
-#include "e100lpslave.h"
-
-start:
- ;; disable interrupts. we are not going to use them at all.
-
- di
-
- ;; setup DMA connections and port configuration
-
- movu.w 0x84, r0 ; DMA2/3/4/5 to par ports
- move.d r0, [R_GEN_CONFIG]
-
- ;; setup port PA dirs and turn on the LED to show were alive
-
- movu.w 0x0cfb, r0 ; PA2-PA3 out, PA2 inactive
- move.d r0, [R_PORT_PA_SET]
-
- ;; enable MDIO output pin
- moveq IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable), r0
- move.d r0, [R_NETWORK_MGM_CTRL]
-
- ;; accept broadcast frames, and enable station address 0
- moveq IO_STATE(R_NETWORK_REC_CONFIG, broadcast, receive) | \
- IO_STATE(R_NETWORK_REC_CONFIG, ma0, enable), r0
- move.d r0, [R_NETWORK_REC_CONFIG]
-
- ;; use MII CLK mode, and enable the controller
- moveq IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | \
- IO_STATE(R_NETWORK_GEN_CONFIG, enable, on), r0
- move.d r0, [R_NETWORK_GEN_CONFIG]
-
- move.d IO_STATE(R_PAR0_CONFIG, ioe, noninv) | \
- IO_STATE(R_PAR0_CONFIG, iseli, noninv) | \
- IO_STATE(R_PAR0_CONFIG, iautofd, noninv) | \
- IO_STATE(R_PAR0_CONFIG, istrb, noninv) | \
- IO_STATE(R_PAR0_CONFIG, iinit, noninv) | \
- IO_STATE(R_PAR0_CONFIG, iperr, noninv) | \
- IO_STATE(R_PAR0_CONFIG, iack, noninv) | \
- IO_STATE(R_PAR0_CONFIG, ibusy, noninv) | \
- IO_STATE(R_PAR0_CONFIG, ifault, noninv) | \
- IO_STATE(R_PAR0_CONFIG, isel, noninv) | \
- IO_STATE(R_PAR0_CONFIG, dma, enable) | \
- IO_STATE(R_PAR0_CONFIG, rle_in, disable) | \
- IO_STATE(R_PAR0_CONFIG, rle_out, disable) | \
- IO_STATE(R_PAR0_CONFIG, enable, on) | \
- IO_STATE(R_PAR0_CONFIG, force, on) | \
- IO_STATE(R_PAR0_CONFIG, mode, ecp_rev), r0 ; Reverse ECP - PAR0 is RX
-
- move.d r0, [R_PAR0_CONFIG]
-
- move.d IO_STATE(R_PAR1_CONFIG, ioe, noninv) | \
- IO_STATE(R_PAR1_CONFIG, iseli, noninv) | \
- IO_STATE(R_PAR1_CONFIG, iautofd, noninv) | \
- IO_STATE(R_PAR1_CONFIG, istrb, noninv) | \
- IO_STATE(R_PAR1_CONFIG, iinit, noninv) | \
- IO_STATE(R_PAR1_CONFIG, iperr, inv) | \
- IO_STATE(R_PAR1_CONFIG, iack, noninv) | \
- IO_STATE(R_PAR1_CONFIG, ibusy, noninv) | \
- IO_STATE(R_PAR1_CONFIG, ifault, noninv) | \
- IO_STATE(R_PAR1_CONFIG, isel, noninv) | \
- IO_STATE(R_PAR1_CONFIG, dma, enable) | \
- IO_STATE(R_PAR1_CONFIG, rle_in, disable) | \
- IO_STATE(R_PAR1_CONFIG, rle_out, disable) | \
- IO_STATE(R_PAR1_CONFIG, enable, on) | \
- IO_STATE(R_PAR1_CONFIG, force, on) | \
- IO_STATE(R_PAR1_CONFIG, mode, ecp_fwd), r0 ; Forward ECP - PAR1 is TX
-
- move.d r0, [R_PAR1_CONFIG]
-
- moveq IO_FIELD(R_PAR1_DELAY, setup, 0), r0 ; setup time of value * 160 + 20 == 20 ns
- move.d r0, [R_PAR1_DELAY]
-
- ;; we got four descriptors, that can be active at the same time:
- ;; 1) from network
- ;; 2) to parport
- ;; 3) from parport
- ;; 4) to network
- ;;
- ;; we got four buffers, each can hold a max packet (we use 1536 bytes)
- ;; buffers 1 and 2 are used from network to parport, while
- ;; buffers 3 and 4 are used from parport to network.
- ;;
- ;; a double buffering scheme is used, so that new data can be read
- ;; into a buffer pair while the last data is written out from the
- ;; last buffer. if the read buffer is done before the write buffer,
- ;; the reading will halt until the writing is done, at which point
- ;; writing starts from the newly read and reading can start with
- ;; the newly written.
- ;;
-
- move.d R_DMA_CH0_FIRST, r1 ; we use this as base for subsequent DMA ops
- moveq IO_STATE(R_DMA_CH1_CMD, cmd, start), r6
- move.d FN1desc, r7
- move.d R_IRQ_READ0, r9
-
- ;; start receiving from network
-
- jsr startdmaFPTN
- jsr startdmaFNTP
-
-
-
- ;; ------------------- MAIN LOOP
-
- ;; IRQ bits: parport rcv is par0_ecp_cmd, then dma3_eop
- ;; network rcv is dma1_eop
- ;; parport tx is dma4_desc
- ;; network tx is dma0_eop
-
-mainloop:
-
- ;; ------- first handle the parport -> network link
-
- ;; check if we got something from the parport
-
- move.d [r9], r0 ; r0 <- *R_IRQ_READ0
- btstq PAR0ECPCMDBIT, r0
- bpl noparecp
- nop
-
- ;; ack it by reading PAR0_STATUS_DATA
-
- move.d [R_PAR0_STATUS_DATA], r0
-
- ;; trigger EOP on DMA3 (par0 incoming channel)
-
- moveq IO_STATE(R_SET_EOP, ch3_eop, set), r0
- move.d r0, [R_SET_EOP]
-
-noparecp:
-
- ;; if we simultaneously have parport rx EOP and
- ;; network TX eop, we can swap buffers and start a new RX/TX
-
- move.d [r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0
- btstq DMA3EOPBIT, r0 ; check parport rx
- bpl noswap1
- btstq DMA0EOPBIT, r0 ; check network tx
- bpl noswap1
- nop
-
- ;; prepare to swap buffer ptrs (FN3b <-> TN4b)
-
- move.d [r4 = r7 + 56], r0; FP3b
- move.d [r3 = r7 + 72], r2; TN4b
-
- ;; but first check if this was a Host Command Packet
-
- move.d [r0], r5 ; r5 <- first 4 bytes in PAR-received packet
- bne handle_command ; if non-zero, it was a host command
- addq 4, r0 ; skip command (in delay slot - handle_command requires this)
- move.d r0, [r3] ; write to To Network descriptor
- subq 4, r2 ; undo the skipping done last swap
- move.d r2, [r4] ; write to From Parport descriptor
-
- ;; clear the interrupts
-
- moveq IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do), r0
- move.b r0, [r1 + (R_DMA_CH0_CLR_INTR - R_DMA_CH0_FIRST)]
- move.b r0, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)]
-
- ;; copy received length to outgoing network length
-
- move.w [r7 + 60], r0 ; FPhlen
- subq 4, r0 ; skip command
- move.w r0, [r7 + 64] ; TN4desc
-
- ;; restart DMAs
-
- jsr startdmaFPTN
-
-#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
-#if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK)
- ;; Turn off the LED signaling an outgoing network packet
- movu.b [LEDOff], r0
-#elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY)
- ;; Light the LED signaling an outgoing network packet
- movu.b [LEDAmber], r0
-#else
-#error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY"
-#endif
- move.b r0, [R_PORT_PA_DATA]
- move.d 0x00011000, r0
- move.d r0,[LEDCount]
-#endif
-
-noswap1:
- ;; ----- now check the network -> parport link
-
-
- ;; if we simultaneously have network rx EOP and
- ;; parport TX desc, we can swap buffers and start a new RX/TX
-
- move.d [r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0
- btstq DMA1EOPBIT, r0 ; check network rx
- bpl noswap2
- btstq DMA4DESCBIT, r0 ; check parport tx
- bpl noswap2
- nop
-
- ;; prepare to swap buffer ptrs (FP1b <-> TP2b)
-
- move.d [r4 = r7 + 8], r0; FN1b
- move.d [r3 = r7 + 24], r2; TP2b
- move.d r0, [r3] ; write to To Parport descriptor
- move.d r2, [r4] ; write to From Network descriptor
-
- ;; clear the interrupts
-
- moveq IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do) | \
- IO_STATE(R_DMA_CH1_CLR_INTR, clr_descr, do), r0
- move.b r0, [r1 + (R_DMA_CH1_CLR_INTR - R_DMA_CH0_FIRST)]
- move.b r0, [r1 + (R_DMA_CH4_CLR_INTR - R_DMA_CH0_FIRST)]
-
- ;; copy received network length to outgoing parport length
-
- move.w [r7 + 12], r0 ; FNhlen
- move.w r0, [r7 + 16] ; TP2desc
-
- ;; restart DMAs
-
- jsr startdmaFNTP
-#if 0
-#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
- ;; Light the LED signaling an incoming networkpacket
- movu.b 0xFB, r0
- move.b r0, [R_PORT_PA_DATA]
- move.d 0x00010000, r0
- move.d r0,[LEDCount]
-#endif
-#endif
-
-noswap2:
-#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
-
- ;; Count down LED counter, and turn off the network LED if required
- move.d [LEDCount], r0
- beq mainloop
- nop
-
- subq 1, r0
- move.d r0, [LEDCount]
- bne mainloop
- nop
-
-#if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK)
- ;; Light the network LED , and start over the main loop
- movu.b [LEDAmber], r0
-#elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY)
- ;; Turn off the network LED, and start over the main loop
- movu.b [LEDOff], r0
-#else
-#error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY"
-#endif
- move.b r0, [R_PORT_PA_DATA]
-#endif
-
- ba mainloop
- nop
-
- ;; --- some useful subroutines.
-
-handle_command:
- ;; handle command. we also need to clear the PAR0 RX EOP IRQ, and
- ;; restart the PAR0 dma. command is in R5, packet after cmd is in R0
-
- moveq IO_STATE(R_DMA_CH3_CLR_INTR, clr_eop, do), r2
- move.b r2, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)]
-
- cmpq HOST_CMD_SETMAC, r5
- bne no_setmac
- nop
-
- ;; copy station address (6 bytes) from packet to hardware
-
- move.d [r0+], r2
- move.d R_NETWORK_SA_0, r3
- move.d r2, [r3]
- move.w [r0], r2
- move.w r2, [r3 + 4]
-
-no_setmac:
- move noswap1, SRP
- ba startdmaFP
- nop
-
- ;; start DMAs, from parport and to network
-
-startdmaFPTN:
-
- ;; start transmitting to the network (CH0)
-
- move.d TN4desc, r8
- move.d r8, [r1] ; TN4desc -> FIRST0
- move.b r6, [r1 + (R_DMA_CH0_CMD - R_DMA_CH0_FIRST)] ; start -> CMD0
-
-startdmaFP:
-
- ;; start receiving from parport (CH3)
-
- move.d FP3desc, r8
- move.d r8, [r1 + (R_DMA_CH3_FIRST - R_DMA_CH0_FIRST)] ; FP3desc -> FIRST3
- move.b r6, [r1 + (R_DMA_CH3_CMD - R_DMA_CH0_FIRST)] ; start -> CMD3
-
- ret
- nop
-
- ;; start DMAs, from network and to parport
-
-startdmaFNTP:
-
- ;; start transmitting to the parport (CH4)
-
- move.d TP2desc, r8
- move.d r8, [r1 + (R_DMA_CH4_FIRST - R_DMA_CH0_FIRST)] ; TP2desc -> FIRST4
- move.b r6, [r1 + (R_DMA_CH4_CMD - R_DMA_CH0_FIRST)] ; start -> CMD4
-
- ;; start receiving from network (CH1) (r7 already contains FN1desc)
-
- move.d r7, [r1 + (R_DMA_CH1_FIRST - R_DMA_CH0_FIRST)] ; FN1desc -> FIRST1
- move.b r6, [r1 + (R_DMA_CH1_CMD - R_DMA_CH0_FIRST)] ; start -> CMD1
-
- ret
- nop
-
- ;; --- DMA descriptors - each descriptor is 4 longwords (16 bytes)
- ;; DONT MOVE THESE AROUND. Due to the as/ld "hole-in-the-head",
- ;; we cant write stuff like (TP2b - TP2desc) but the offsets
- ;; have to be hardcoded.
-
- .data
-
- ;; 0 from network
-FN1desc:
- .word BUFSIZE ; sw_len
- .word 0x0001 ; ctrl, d_eol is only flag we need
- .dword 0 ; next
-FN1b: .dword buffers ; buffer 1 8
- .word 0 ; hw_len
- .word 0 ; status
-
- ;; 16 to parport
-TP2desc:
- .word 2 ; sw_len, filled in by code
- .word 0x0004 ; ctrl, d_wait because ecp cmd in next
- .dword TP2desc2 ; next
-TP2b: .dword buffers + BUFSIZE ; buffer 2 24
- .word 0 ; hw_len
- .word 0 ; status
-
- ;; 32 to parport second descriptor, for the ECP command
-TP2desc2:
- .word 0x0001 ; sw_len, 1 byte (ecp command)
- .word 0x0019 ; ctrl, d_ecp | d_eol | d_int
- .dword 0 ; next
- .dword TP2desc2 ; buffer, dont care
- .word 0 ; hw_len
- .word 0 ; status
-
- ;; 48 from parport
-FP3desc:
- .word BUFSIZE ; sw_len
- .word 0x0001 ; ctrl, d_eol is only flag we need
- .dword 0 ; next
-FP3b: .dword buffers + BUFSIZE * 2 ; 56 buffer 3
-FPhlen: .word 0 ; 60 hw_len
- .word 0 ; status
-
- ;; 64 to network
-TN4desc:
- .word 2 ; sw_len, filled in by code
- .word 0x0007 ; ctrl, d_eop | d_eol | d_wait
- .dword 0 ; next
-TN4b: .dword buffers + BUFSIZE * 3 + 4 ; 72 buffer 4 (the +4 is to offset the anti-skipping)
- .word 0 ; hw_len
- .word 0 ; status
-
-#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
-LEDCount:
- .dword 0
-LEDOff:
- .word 0xff
-LEDGreen:
- .word 0xfb
-LEDRed:
- .word 0xf7
-LEDAmber:
- .word 0xf3
-LED:
- .word 0xf7
-#endif
-
- ;; after the prog we put the buffers. not in the asm program, we just use
- ;; the address generated
-
-buffers:
-
- ;; END
diff --git a/arch/cris/drivers/lpslave/e100lpslave.h b/arch/cris/drivers/lpslave/e100lpslave.h
deleted file mode 100644
index 7c9cfd91e365..000000000000
--- a/arch/cris/drivers/lpslave/e100lpslave.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define HOST_CMD_SENDPACK 0
-#define HOST_CMD_SETMAC 1
diff --git a/arch/cris/drivers/lpslave/e100lpslaveld b/arch/cris/drivers/lpslave/e100lpslaveld
deleted file mode 100644
index 4d51ff40ef65..000000000000
--- a/arch/cris/drivers/lpslave/e100lpslaveld
+++ /dev/null
@@ -1,22 +0,0 @@
-MEMORY
- {
- cache : ORIGIN = 0x380000f0,
- LENGTH = 784
- }
-
-SECTIONS
-{
- .text :
- {
- *(.text)
- } > cache
- .data :
- {
- *(.data)
- *(COMMON)
- } > cache
- .bss :
- {
- *(.bss)
- } > cache
-}
diff --git a/arch/cris/drivers/lpslave/e100lpslavenet.c b/arch/cris/drivers/lpslave/e100lpslavenet.c
deleted file mode 100644
index 29e98e46c321..000000000000
--- a/arch/cris/drivers/lpslave/e100lpslavenet.c
+++ /dev/null
@@ -1,1012 +0,0 @@
-/* $Id: e100lpslavenet.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
- *
- * e100lpslavenet.c: A network driver for the ETRAX 100LX slave controller.
- *
- * Copyright (c) 1998-2001 Axis Communications AB.
- *
- * The outline of this driver comes from skeleton.c.
- *
- * $Log: e100lpslavenet.c,v $
- * Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
- * Import of Linux 2.5.1
- *
- * Revision 1.4 2001/06/21 16:55:26 olof
- * Minimized par port setup time to gain bandwidth
- *
- * Revision 1.3 2001/06/21 15:49:02 olof
- * Removed setting of default MAC address
- *
- * Revision 1.2 2001/06/11 15:39:52 olof
- * Clean up and sync with ethernet.c rev 1.16. Increased reset time of slave.
- *
- * Revision 1.1 2001/06/06 08:56:26 olof
- * Added support for slave Etrax defined by CONFIG_ETRAX_ETHERNET_LPSLAVE
- *
- */
-
-#include <linux/config.h>
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <asm/svinto.h> /* DMA and register descriptions */
-#include <asm/io.h> /* LED_* I/O functions */
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-
-#include "e100lpslave.h"
-
-/* #define ETHDEBUG */
-#define D(x)
-
-/*
- * The name of the card. Is used for messages and in the requests for
- * io regions, irqs and dma channels
- */
-
-static const char* cardname = "Etrax 100LX ethernet slave controller";
-
-/* A default ethernet address. Highlevel SW will set the real one later */
-
-static struct sockaddr default_mac = {
- 0,
- { 0x00, 0x40, 0x8C, 0xCD, 0x00, 0x00 }
-};
-
-/* Information that need to be kept for each board. */
-struct net_local {
- struct net_device_stats stats;
-
- /* Tx control lock. This protects the transmit buffer ring
- * state along with the "tx full" state of the driver. This
- * means all netif_queue flow control actions are protected
- * by this lock as well.
- */
- spinlock_t lock;
-};
-
-/* Dma descriptors etc. */
-
-#define RX_BUF_SIZE 32768
-#define ETHER_HEAD_LEN 14
-
-#define PAR0_ECP_IRQ_NBR 4
-
-#define RX_DESC_BUF_SIZE 256
-#define NBR_OF_RX_DESC (RX_BUF_SIZE / \
- RX_DESC_BUF_SIZE)
-
-/* Size of slave etrax boot image */
-#define ETRAX_PAR_BOOT_LENGTH 784
-
-static etrax_dma_descr *myNextRxDesc; /* Points to the next descriptor to
- to be processed */
-static etrax_dma_descr *myLastRxDesc; /* The last processed descriptor */
-static etrax_dma_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */
-
-static unsigned char RxBuf[RX_BUF_SIZE];
-
-static etrax_dma_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(4)));
-static etrax_dma_descr TxDescList[3] __attribute__ ((aligned(4)));
- /* host command, data, bogus ECP command */
-
-static struct sk_buff *tx_skb;
-
-/* Index to functions, as function prototypes. */
-
-static int etrax_ethernet_lpslave_init(struct net_device *dev);
-
-static int e100_open(struct net_device *dev);
-static int e100_set_mac_address(struct net_device *dev, void *addr);
-static int e100_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void e100rx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void e100tx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void ecp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void e100_rx(struct net_device *dev);
-static int e100_close(struct net_device *dev);
-static struct net_device_stats *e100_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static void e100_hardware_send_packet(unsigned long hostcmd, char *buf, int length);
-static void update_rx_stats(struct net_device_stats *);
-static void update_tx_stats(struct net_device_stats *);
-static void e100_reset_transceiver(void);
-
-static void boot_slave(unsigned char *code);
-
-#ifdef ETHDEBUG
-static void dump_parport_status(void);
-#endif
-
-#define tx_done(dev) (*R_DMA_CH0_CMD == 0)
-
-static unsigned long host_command;
-extern unsigned char e100lpslaveprog;
-
-/*
- * This driver uses PAR0 to recevice data from slave ETRAX and PAR1 to boot
- * and send data to slave ETRAX.
- * Used ETRAX100 DMAchannels with corresponding IRQ:
- * PAR0 RX : DMA3 - IRQ 19
- * PAR1 TX : DMA4 - IRQ 20
- * IRQ 4 is used to detect ECP commands from slave ETRAX
- *
- * NOTE! PAR0 and PAR1 shares DMA and IRQ numbers with SER2 and SER3
- */
-
-
-/*
- * Check for a network adaptor of this type, and return '0' if one exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- * If dev->base_addr == 2, allocate space for the device and return success
- * (detachable devices only).
- */
-static int __init
-etrax_ethernet_lpslave_init(void)
-{
- struct net_device *dev;
- int i, err;
- int anOffset = 0;
-
- printk("Etrax/100 lpslave ethernet driver v0.3, (c) 1999 Axis Communications AB\n");
-
- dev = alloc_etherdev(sizeof(struct net_lock));
- if (!dev)
- return -ENOMEM;
-
- dev->base_addr = 2;
-
- /* now setup our etrax specific stuff */
-
- dev->irq = DMA3_RX_IRQ_NBR; /* we really use DMATX as well... */
- dev->dma = PAR0_RX_DMA_NBR;
-
- /* fill in our handlers so the network layer can talk to us in the future */
-
- dev->open = e100_open;
- dev->hard_start_xmit = e100_send_packet;
- dev->stop = e100_close;
- dev->get_stats = e100_get_stats;
- dev->set_multicast_list = set_multicast_list;
- dev->set_mac_address = e100_set_mac_address;
-
- /* Initialise the list of Etrax DMA-descriptors */
-
- /* Initialise receive descriptors */
-
- for(i = 0; i < (NBR_OF_RX_DESC - 1); i++) {
- RxDescList[i].ctrl = 0;
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);
- RxDescList[i].buf = virt_to_phys(RxBuf + anOffset);
- RxDescList[i].status = 0;
- RxDescList[i].hw_len = 0;
- anOffset += RX_DESC_BUF_SIZE;
- }
-
- RxDescList[i].ctrl = d_eol;
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].next = virt_to_phys(&RxDescList[0]);
- RxDescList[i].buf = virt_to_phys(RxBuf + anOffset);
- RxDescList[i].status = 0;
- RxDescList[i].hw_len = 0;
-
- /* Initialise initial pointers */
-
- myNextRxDesc = &RxDescList[0];
- myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
- myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
-
- /* setup some TX descriptor data */
-
- TxDescList[0].sw_len = 4;
- TxDescList[0].ctrl = 0;
- TxDescList[0].buf = virt_to_phys(&host_command);
- TxDescList[0].next = virt_to_phys(&TxDescList[1]);
-
- err = register_netdev(dev);
- if (err)
- kfree(dev);
-
- return err;
-}
-
-/* set MAC address of the interface. called from the core after a
- * SIOCSIFADDR ioctl, and from the bootup above.
- */
-
-static int
-e100_set_mac_address(struct net_device *dev, void *p)
-{
- struct sockaddr *addr = p;
- int i;
-
- /* remember it */
-
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
- /* Write it to the hardware.
- * Note the way the address is wrapped:
- * *R_NETWORK_SA_0 = a0_0 | (a0_1 << 8) | (a0_2 << 16) | (a0_3 << 24);
- * *R_NETWORK_SA_1 = a0_4 | (a0_5 << 8);
- */
-
- tx_skb = 0;
- e100_hardware_send_packet(HOST_CMD_SETMAC, dev->dev_addr, 6);
-
- /* show it in the log as well */
-
- printk("%s: changed MAC to ", dev->name);
-
- for (i = 0; i < 5; i++)
- printk("%02X:", dev->dev_addr[i]);
-
- printk("%02X\n", dev->dev_addr[i]);
-
- return 0;
-}
-
-/*
- * Open/initialize the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-
-static int
-e100_open(struct net_device *dev)
-{
- unsigned long flags;
-
- /* configure the PAR0 (RX) and PAR1 (TX) ports
- *
- * perror is nAckReverse, which must be 1 at the TX side,
- * and 0 at the RX side
- *
- * select is XFlag, which must be 1 at both sides
- */
-#ifdef ETHDEBUG
- printk("Setting up PAR ports\n");
-#endif
- *R_PAR0_CONFIG =
- /* We do not have an external buffer, don't care */
- IO_STATE(R_PAR0_CONFIG, ioe, noninv) |
- /* Not connected, don't care */
- IO_STATE(R_PAR0_CONFIG, iseli, noninv) |
- /* iautofd is not inverted, noninv */
- IO_STATE(R_PAR0_CONFIG, iautofd, noninv) |
- /* Not used in reverse direction, don't care */
- IO_STATE(R_PAR0_CONFIG, istrb, noninv) |
- /* Not connected, don't care */
- IO_STATE(R_PAR0_CONFIG, iinit, noninv) |
- /* perror is GND and reverse wants 0, noninv */
- IO_STATE(R_PAR0_CONFIG, iperr, noninv) |
- /* ack is not inverted, noninv */
- IO_STATE(R_PAR0_CONFIG, iack, noninv) |
- /* busy is not inverted, noninv */
- IO_STATE(R_PAR0_CONFIG, ibusy, noninv) |
- /* fault is not inverted, noninv */
- IO_STATE(R_PAR0_CONFIG, ifault, noninv) |
- /* select is Vcc and we want 1, noninv */
- IO_STATE(R_PAR0_CONFIG, isel, noninv) |
- /* We will run dma, enable */
- IO_STATE(R_PAR0_CONFIG, dma, enable) |
- /* No run length encoding, disable */
- IO_STATE(R_PAR0_CONFIG, rle_in, disable) |
- /* No run length encoding, disable */
- IO_STATE(R_PAR0_CONFIG, rle_out, disable) |
- /* Enable parallel port */
- IO_STATE(R_PAR0_CONFIG, enable, on) |
- /* Force mode regardless of pin status */
- IO_STATE(R_PAR0_CONFIG, force, on) |
- /* We want ECP forward mode since PAR0 is RX */
- IO_STATE(R_PAR0_CONFIG, mode, ecp_rev);
-
- *R_PAR1_CONFIG =
- /* We do not have an external buffer, don't care */
- IO_STATE(R_PAR1_CONFIG, ioe, noninv) |
-
- /* Not connected, don't care */
- IO_STATE(R_PAR1_CONFIG, iseli, noninv) |
-
- /* HostAck must indicate data cycle, noninv */
- IO_STATE(R_PAR1_CONFIG, iautofd, noninv) |
-
- /* HostClk has no external inverter, noninv */
- IO_STATE(R_PAR1_CONFIG, istrb, noninv) |
-
- /* Not connected, don't care */
- IO_STATE(R_PAR1_CONFIG, iinit, noninv) |
-
- /* nAckReverse must be 1 in forward mode but is grounded, inv */
- IO_STATE(R_PAR1_CONFIG, iperr, inv) |
-
- /* PeriphClk must be 1 in forward mode, noninv */
- IO_STATE(R_PAR1_CONFIG, iack, noninv) |
-
- /* PeriphAck has no external inverter, noninv */
- IO_STATE(R_PAR1_CONFIG, ibusy, noninv) |
-
- /* nPerihpRequest has no external inverter, noniv */
- IO_STATE(R_PAR1_CONFIG, ifault, noninv) |
-
- /* Select is VCC and we want 1, noninv */
- IO_STATE(R_PAR1_CONFIG, isel, noninv) |
-
- /* No EPP mode, disable */
- IO_STATE(R_PAR1_CONFIG, ext_mode, disable) |
-
- /* We will run dma, enable */
- IO_STATE(R_PAR1_CONFIG, dma, enable) |
-
- /* No run length encoding, disable */
- IO_STATE(R_PAR1_CONFIG, rle_in, disable) |
-
- /* No run length encoding, disable */
- IO_STATE(R_PAR1_CONFIG, rle_out, disable) |
-
- /* Enable parallel port */
- IO_STATE(R_PAR1_CONFIG, enable, on) |
-
- /* Force mode regardless of pin status */
- IO_STATE(R_PAR1_CONFIG, force, on) |
-
- /* We want ECP forward mode since PAR1 is TX */
- IO_STATE(R_PAR1_CONFIG, mode, ecp_fwd);
-
- /* Setup time of value * 160 + 20 ns == 20 ns below */
- *R_PAR1_DELAY = IO_FIELD(R_PAR1_DELAY, setup, 0);
-
- *R_PAR1_CTRL = 0;
-
- while ((((*R_PAR1_STATUS)&0xE000) >> 13) != 5); /* Wait for ECP_FWD mode */
-#ifdef ETHDEBUG
- dump_parport_status();
-#endif
-
- /* make sure ECP irq is acked when we enable it below */
-
- (void)*R_PAR0_STATUS_DATA;
- (void)*R_PAR1_STATUS_DATA;
-
- /* Reset and wait for the DMA channels */
-
- RESET_DMA(4); /* PAR1_TX_DMA_NBR */
- RESET_DMA(3); /* PAR0_RX_DMA_NBR */
- WAIT_DMA(4);
- WAIT_DMA(3);
-
- /* boot the slave Etrax, by sending code on PAR1.
- * do this before we start up the IRQ handlers and stuff,
- * beacuse we simply poll for completion in boot_slave.
- */
-
- boot_slave(&e100lpslaveprog);
-
- /* allocate the irq corresponding to the receiving DMA */
-
- if (request_irq(DMA3_RX_IRQ_NBR, e100rx_interrupt, 0,
- cardname, (void *)dev)) {
- printk("Failed to allocate DMA3_RX_IRQ_NBR\n");
- goto grace_exit;
- }
-
- /* allocate the irq corresponding to the transmitting DMA */
-
- if (request_irq(DMA4_TX_IRQ_NBR, e100tx_interrupt, 0,
- cardname, (void *)dev)) {
- printk("Failed to allocate DMA4_TX_IRQ_NBR\n");
- goto grace_exit;
- }
-
- /* allocate the irq used for detecting ECP commands on the RX port (PAR0) */
-
- if (request_irq(PAR0_ECP_IRQ_NBR, ecp_interrupt, 0,
- cardname, (void *)dev)) {
- printk("Failed to allocate PAR0_ECP_IRQ_NBR\n");
- grace_exit:
- free_irq(PAR0_ECP_IRQ_NBR, (void *)dev);
- free_irq(DMA4_TX_IRQ_NBR, (void *)dev);
- free_irq(DMA3_RX_IRQ_NBR, (void *)dev);
-
- return -EAGAIN;
- }
-
-#if 0
- /* We are not allocating DMA since DMA4 is reserved for 'cascading'
- * and will always fail with the current dma.c
- */
-
- /*
- * Always allocate the DMA channels after the IRQ,
- * and clean up on failure.
- */
-
- if(request_dma(PAR0_RX_DMA_NBR, cardname)) {
- printk("Failed to allocate PAR0_RX_DMA_NBR\n");
- goto grace_exit;
- }
-
- if(request_dma(PAR1_TX_DMA_NBR, cardname)) {
- printk("Failed to allocate PAR1_TX_DMA_NBR\n");
- grace_exit:
- /* this will cause some 'trying to free free irq' but what the heck... */
-
- free_dma(PAR1_TX_DMA_NBR);
- free_dma(PAR0_RX_DMA_NBR);
- free_irq(PAR0_ECP_IRQ_NBR, (void *)dev);
- free_irq(DMA4_TX_IRQ_NBR, (void *)dev);
- free_irq(DMA3_RX_IRQ_NBR, (void *)dev);
-
- return -EAGAIN;
- }
-#endif
-
-#ifdef ETHDEBUG
- printk("Par port IRQ and DMA allocated\n");
-#endif
- save_flags(flags);
- cli();
-
- /* enable the irq's for PAR0/1 DMA */
-
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma3_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma4_descr, set);
-
- *R_IRQ_MASK0_SET =
- IO_STATE(R_IRQ_MASK0_SET, par0_ecp_cmd, set);
-
- tx_skb = 0;
-
- /* make sure the irqs are cleared */
-
- *R_DMA_CH3_CLR_INTR = IO_STATE(R_DMA_CH3_CLR_INTR, clr_eop, do);
- *R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);
-
- /* Write the MAC address to the slave HW */
- udelay(5000);
- e100_hardware_send_packet(HOST_CMD_SETMAC, dev->dev_addr, 6);
-
- /* make sure the rec and transmit error counters are cleared */
-
- (void)*R_REC_COUNTERS; /* dummy read */
- (void)*R_TR_COUNTERS; /* dummy read */
-
- /* start the receiving DMA channel so we can receive packets from now on */
-
- *R_DMA_CH3_FIRST = virt_to_phys(myNextRxDesc);
- *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start);
-
- restore_flags(flags);
-
- /* We are now ready to accept transmit requeusts from
- * the queueing layer of the networking.
- */
-#ifdef ETHDEBUG
- printk("Starting slave network transmit queue\n");
-#endif
- netif_start_queue(dev);
-
- return 0;
-}
-
-static void
-e100_reset_transceiver(void)
-{
- /* To do: Reboot and setup slave Etrax */
-}
-
-/* Called by upper layers if they decide it took too long to complete
- * sending a packet - we need to reset and stuff.
- */
-
-static void
-e100_tx_timeout(struct net_device *dev)
-{
- struct net_local *np = (struct net_local *)dev->priv;
-
- printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
- tx_done(dev) ? "IRQ problem" : "network cable problem");
-
- /* remember we got an error */
-
- np->stats.tx_errors++;
-
- /* reset the TX DMA in case it has hung on something */
-
- RESET_DMA(4);
- WAIT_DMA(4);
-
- /* Reset the transceiver. */
-
- e100_reset_transceiver();
-
- /* and get rid of the packet that never got an interrupt */
-
- dev_kfree_skb(tx_skb);
- tx_skb = 0;
-
- /* tell the upper layers we're ok again */
-
- netif_wake_queue(dev);
-}
-
-
-/* This will only be invoked if the driver is _not_ in XOFF state.
- * What this means is that we need not check it, and that this
- * invariant will hold if we make sure that the netif_*_queue()
- * calls are done at the proper times.
- */
-
-static int
-e100_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_local *np = (struct net_local *)dev->priv;
- int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
-
-#ifdef ETHDEBUG
- unsigned char *temp_data_ptr = buf;
- int i;
-
- printk("Sending a packet of length %d:\n", length);
- /* dump the first bytes in the packet */
- for(i = 0; i < 8; i++) {
- printk("%d: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", i * 8,
- temp_data_ptr[0],temp_data_ptr[1],temp_data_ptr[2],
- temp_data_ptr[3],temp_data_ptr[4],temp_data_ptr[5],
- temp_data_ptr[6],temp_data_ptr[7]);
- temp_data_ptr += 8;
- }
-#endif
- spin_lock_irq(&np->lock); /* protect from tx_interrupt */
-
- tx_skb = skb; /* remember it so we can free it in the tx irq handler later */
- dev->trans_start = jiffies;
-
- e100_hardware_send_packet(HOST_CMD_SENDPACK, buf, length);
-
- /* this simple TX driver has only one send-descriptor so we're full
- * directly. If this had a send-ring instead, we would only do this if
- * the ring got full.
- */
-
- netif_stop_queue(dev);
-
- spin_unlock_irq(&np->lock);
-
- return 0;
-}
-
-/*
- * The typical workload of the driver:
- * Handle the network interface interrupts.
- */
-
-static void
-e100rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- struct net_device *dev = (struct net_device *)dev_id;
- unsigned long irqbits = *R_IRQ_MASK2_RD;
-
- if(irqbits & IO_STATE(R_IRQ_MASK2_RD, dma3_eop, active)) {
-
- /* acknowledge the eop interrupt */
-
- *R_DMA_CH3_CLR_INTR = IO_STATE(R_DMA_CH3_CLR_INTR, clr_eop, do);
-
- /* check if one or more complete packets were indeed received */
-
- while(*R_DMA_CH3_FIRST != virt_to_phys(myNextRxDesc)) {
- /* Take out the buffer and give it to the OS, then
- * allocate a new buffer to put a packet in.
- */
- e100_rx(dev);
- ((struct net_local *)dev->priv)->stats.rx_packets++;
- /* restart/continue on the channel, for safety */
- *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, restart);
- /* clear dma channel 3 eop/descr irq bits */
- *R_DMA_CH3_CLR_INTR =
- IO_STATE(R_DMA_CH3_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH3_CLR_INTR, clr_descr, do);
-
- /* now, we might have gotten another packet
- so we have to loop back and check if so */
- }
- }
-}
-
-/* the transmit dma channel interrupt
- *
- * this is supposed to free the skbuff which was pending during transmission,
- * and inform the kernel that we can send one more buffer
- */
-
-static void
-e100tx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- struct net_device *dev = (struct net_device *)dev_id;
- unsigned long irqbits = *R_IRQ_MASK2_RD;
- struct net_local *np = (struct net_local *)dev->priv;
-
-#ifdef ETHDEBUG
- printk("We got tx interrupt\n");
-#endif
- /* check for a dma4_eop interrupt */
- if(irqbits & IO_STATE(R_IRQ_MASK2_RD, dma4_descr, active)) {
- /* This protects us from concurrent execution of
- * our dev->hard_start_xmit function above.
- */
-
- spin_lock(&np->lock);
-
- /* acknowledge the eop interrupt */
-
- *R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);
-
- /* skip *R_DMA_CH4_FIRST == 0 test since we use d_wait... */
- if(tx_skb) {
-
- np->stats.tx_bytes += tx_skb->len;
- np->stats.tx_packets++;
- /* dma is ready with the transmission of the data in tx_skb, so now we can release the skb memory */
- dev_kfree_skb_irq(tx_skb);
- tx_skb = 0;
- netif_wake_queue(dev);
- } else {
- printk(KERN_WARNING "%s: tx weird interrupt\n",
- cardname);
- }
-
- spin_unlock(&np->lock);
- }
-}
-
-static void
-ecp_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- struct net_device *dev = (struct net_device *)dev_id;
- struct net_local *lp = (struct net_local *)dev->priv;
- unsigned long temp, irqbits = *R_IRQ_MASK0_RD;
-
- /* check for ecp irq */
- if(irqbits & IO_MASK(R_IRQ_MASK0_RD, par0_ecp_cmd)) {
- /* acknowledge by reading the bit */
- temp = *R_PAR0_STATUS_DATA;
- /* force an EOP on the incoming channel, so we'll get an rx interrupt */
- *R_SET_EOP = IO_STATE(R_SET_EOP, ch3_eop, set);
- }
-}
-
-/* We have a good packet(s), get it/them out of the buffers. */
-static void
-e100_rx(struct net_device *dev)
-{
- struct sk_buff *skb;
- int length=0;
- int i;
- struct net_local *np = (struct net_local *)dev->priv;
- struct etrax_dma_descr *mySaveRxDesc = myNextRxDesc;
- unsigned char *skb_data_ptr;
-
- /* If the packet is broken down in many small packages then merge
- * count how much space we will need to alloc with skb_alloc() for
- * it to fit.
- */
-
- while (!(myNextRxDesc->status & d_eop)) {
- length += myNextRxDesc->sw_len; /* use sw_len for the first descs */
- myNextRxDesc->status = 0;
- myNextRxDesc = phys_to_virt(myNextRxDesc->next);
- }
-
- length += myNextRxDesc->hw_len; /* use hw_len for the last descr */
-
-#ifdef ETHDEBUG
- printk("Got a packet of length %d:\n", length);
- /* dump the first bytes in the packet */
- skb_data_ptr = (unsigned char *)phys_to_virt(mySaveRxDesc->buf);
- for(i = 0; i < 8; i++) {
- printk("%d: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", i * 8,
- skb_data_ptr[0],skb_data_ptr[1],skb_data_ptr[2],skb_data_ptr[3],
- skb_data_ptr[4],skb_data_ptr[5],skb_data_ptr[6],skb_data_ptr[7]);
- skb_data_ptr += 8;
- }
-#endif
-
- skb = dev_alloc_skb(length - ETHER_HEAD_LEN);
- if (!skb) {
- np->stats.rx_errors++;
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
- dev->name);
- return;
- }
-
- skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */
- skb_data_ptr = skb_push(skb, ETHER_HEAD_LEN); /* allocate room for the header */
-
-#ifdef ETHDEBUG
- printk("head = 0x%x, data = 0x%x, tail = 0x%x, end = 0x%x\n",
- skb->head, skb->data, skb->tail, skb->end);
- printk("copying packet to 0x%x.\n", skb_data_ptr);
-#endif
-
- /* this loop can be made using max two memcpy's if optimized */
-
- while(mySaveRxDesc != myNextRxDesc) {
- memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),
- mySaveRxDesc->sw_len);
- skb_data_ptr += mySaveRxDesc->sw_len;
- mySaveRxDesc = phys_to_virt(mySaveRxDesc->next);
- }
-
- memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),
- mySaveRxDesc->hw_len);
-
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
-
- /* Send the packet to the upper layers */
-
- netif_rx(skb);
-
- /* Prepare for next packet */
-
- myNextRxDesc->status = 0;
- myPrevRxDesc = myNextRxDesc;
- myNextRxDesc = phys_to_virt(myNextRxDesc->next);
-
- myPrevRxDesc->ctrl |= d_eol;
- myLastRxDesc->ctrl &= ~d_eol;
- myLastRxDesc = myPrevRxDesc;
-
- return;
-}
-
-/* The inverse routine to net_open(). */
-static int
-e100_close(struct net_device *dev)
-{
- struct net_local *np = (struct net_local *)dev->priv;
-
- printk("Closing %s.\n", dev->name);
-
- netif_stop_queue(dev);
-
- *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, par0_ecp_cmd, clr);
-
- *R_IRQ_MASK2_CLR =
- IO_STATE(R_IRQ_MASK2_CLR, dma3_eop, clr) |
- IO_STATE(R_IRQ_MASK2_CLR, dma4_descr, clr);
-
- /* Stop the receiver and the transmitter */
-
- RESET_DMA(3);
- RESET_DMA(4);
-
- /* Flush the Tx and disable Rx here. */
-
- free_irq(DMA3_RX_IRQ_NBR, (void *)dev);
- free_irq(DMA4_TX_IRQ_NBR, (void *)dev);
- free_irq(PAR0_ECP_IRQ_NBR, (void *)dev);
-
- free_dma(PAR1_TX_DMA_NBR);
- free_dma(PAR0_RX_DMA_NBR);
-
- /* Update the statistics here. */
-
- update_rx_stats(&np->stats);
- update_tx_stats(&np->stats);
-
- return 0;
-}
-
-static void
-update_rx_stats(struct net_device_stats *es)
-{
- unsigned long r = *R_REC_COUNTERS;
- /* update stats relevant to reception errors */
- es->rx_fifo_errors += r >> 24; /* fifo overrun */
- es->rx_crc_errors += r & 0xff; /* crc error */
- es->rx_frame_errors += (r >> 8) & 0xff; /* alignment error */
- es->rx_length_errors += (r >> 16) & 0xff; /* oversized frames */
-}
-
-static void
-update_tx_stats(struct net_device_stats *es)
-{
- unsigned long r = *R_TR_COUNTERS;
- /* update stats relevant to transmission errors */
- es->collisions += (r & 0xff) + ((r >> 8) & 0xff); /* single_col + multiple_col */
- es->tx_errors += (r >> 24) & 0xff; /* deferred transmit frames */
-}
-
-/*
- * Get the current statistics.
- * This may be called with the card open or closed.
- */
-static struct net_device_stats *
-e100_get_stats(struct net_device *dev)
-{
- struct net_local *lp = (struct net_local *)dev->priv;
-
- update_rx_stats(&lp->stats);
- update_tx_stats(&lp->stats);
-
- return &lp->stats;
-}
-
-/*
- * Set or clear the multicast filter for this adaptor.
- * num_addrs == -1 Promiscuous mode, receive all packets
- * num_addrs == 0 Normal mode, clear multicast list
- * num_addrs > 0 Multicast mode, receive normal and MC packets,
- * and do best-effort filtering.
- */
-static void
-set_multicast_list(struct net_device *dev)
-{
- /* To do */
-}
-
-void
-e100_hardware_send_packet(unsigned long hostcmd, char *buf, int length)
-{
- static char bogus_ecp[] = { 42, 42 };
- int i;
-
-
-#ifdef ETHDEBUG
- printk("e100 send pack, buf 0x%x len %d\n", buf, length);
-#endif
-
- host_command = hostcmd;
-
- /* Configure the tx dma descriptor. Desc 0 is already configured.*/
-
- TxDescList[1].sw_len = length;
- /* bug workaround - etrax100 needs d_wait on the descriptor _before_
- * a descriptor containing an ECP command
- */
- TxDescList[1].ctrl = d_wait;
- TxDescList[1].buf = virt_to_phys(buf);
- TxDescList[1].next = virt_to_phys(&TxDescList[2]);
-
- /* append the ecp dummy descriptor - its only purpose is to
- * make the receiver generate an irq due to the ecp command
- * so the receiver knows where packets end
- */
-
- TxDescList[2].sw_len = 1;
- TxDescList[2].ctrl = d_ecp | d_eol | d_int;
- TxDescList[2].buf = virt_to_phys(bogus_ecp);
-
-
- /* setup the dma channel and start it */
-
- *R_DMA_CH4_FIRST = virt_to_phys(TxDescList);
- *R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, start);
-
-#ifdef ETHDEBUG
- printk("done\n");
-#endif
-}
-
-/* send a chunk of code to the slave chip to boot it. */
-
-static void
-boot_slave(unsigned char *code)
-{
- int i;
-
-#ifdef ETHDEBUG
- printk(" booting slave ETRAX...\n");
-#endif
- *R_PORT_PB_DATA = 0x7F; /* Reset slave */
- udelay(15); /* Time enough to reset WAN tranciever */
- *R_PORT_PB_DATA = 0xFF; /* Reset slave */
-
- /* configure the tx dma data descriptor */
-
- TxDescList[1].sw_len = ETRAX_PAR_BOOT_LENGTH;
- TxDescList[1].ctrl = d_eol | d_int;
-
- TxDescList[1].buf = virt_to_phys(code);
- TxDescList[1].next = 0;
-
- /* setup the dma channel and start it */
- *R_DMA_CH4_FIRST = virt_to_phys(&TxDescList[1]);
- *R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, start);
-
- /* wait for completion */
- while(!(*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma4_descr)));
-
- /* ack the irq */
-
- *R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);
-
-#if 0
- /* manual transfer of boot code - requires dma turned off */
- for (i=0; i<ETRAX_PAR_BOOT_LENGTH; i++)
- {
- printk(" sending byte: %u value: %x\n",i,code[i]);
- while (((*R_PAR1_STATUS)&0x02) == 0); /* Wait while tr_rdy is busy*/
- *R_PAR1_CTRL_DATA = code[i];
- }
-#endif
-
-#ifdef ETHDEBUG
- printk(" done\n");
-#endif
-}
-
-#ifdef ETHDEBUG
-/* debug code to check the current status of PAR1 */
-static void
-dump_parport_status(void)
-{
- unsigned long temp;
-
- printk("Parport1 status:\n");
-
- temp = (*R_PAR1_STATUS)&0xE000;
- temp = temp >> 13;
- printk("Reg mode: %u (ecp_fwd(5), ecp_rev(6))\n", temp);
-
- temp = (*R_PAR1_STATUS)&0x1000;
- temp = temp >> 12;
- printk("Reg perr: %u (ecp_rev(0))\n", temp);
-
- temp = (*R_PAR1_STATUS)&0x0800;
- temp = temp >> 11;
- printk("Reg ack: %u (inactive (1), active (0))\n", temp);
-
- temp = (*R_PAR1_STATUS)&0x0400;
- temp = temp >> 10;
- printk("Reg busy: %u (inactive (0), active (1))\n", temp);
-
- temp = (*R_PAR1_STATUS)&0x0200;
- temp = temp >> 9;
- printk("Reg fault: %u (inactive (1), active (0))\n", temp);
-
- temp = (*R_PAR1_STATUS)&0x0100;
- temp = temp >> 8;
- printk("Reg sel: %u (inactive (0), active (1), xflag(1))\n", temp);
-
- temp = (*R_PAR1_STATUS)&0x02;
- temp = temp >> 1;
- printk("Reg tr_rdy: %u (busy (0), ready (1))\n", temp);
-
-}
-#endif /* ETHDEBUG */
-
-static int
-etrax_init_module(void)
-{
- return etrax_ethernet_lpslave_init();
-}
-
-module_init(etrax_init_module);
diff --git a/arch/cris/drivers/parport.c b/arch/cris/drivers/parport.c
deleted file mode 100644
index 443e51a111b8..000000000000
--- a/arch/cris/drivers/parport.c
+++ /dev/null
@@ -1,572 +0,0 @@
-/* $Id: parport.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
- *
- * Elinux parallel port driver
- * NOTE!
- * Since par0 shares DMA with ser2 and par 1 shares DMA with ser3
- * this should be handled if both are enabled at the same time.
- * THIS IS NOT HANDLED YET!
- *
- * Copyright (c) 2001 Axis Communications AB
- *
- * Author: Fredrik Hugosson
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/parport.h>
-#include <linux/ioport.h>
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include <asm/svinto.h>
-
-
-#undef DEBUG
-#ifdef DEBUG
-#define DPRINTK printk
-#else
-static inline int DPRINTK(void *nothing, ...) {return 0;}
-#endif
-
-/*
- * Etrax100 DMAchannels:
- * Par0 out : DMA2
- * Par0 in : DMA3
- * Par1 out : DMA4
- * Par1 in : DMA5
- * NOTE! par0 is shared with ser2 and par1 is shared with ser3 regarding
- * DMA and DMA irq
- */
-
-//#define CONFIG_PAR0_INT 1
-//#define CONFIG_PAR1_INT 1
-
-#define SETF(var, reg, field, val) \
- var = (var & ~IO_MASK(##reg##, field)) | IO_FIELD(##reg##, field, val)
-
-#define SETS(var, reg, field, val) \
- var = (var & ~IO_MASK(##reg##, field)) | IO_STATE(##reg##, field, val)
-
-struct etrax100par_struct {
- /* parallell port control */
- volatile u32 *reg_ctrl_data; /* R_PARx_CTRL_DATA */
- const volatile u32 *reg_status_data; /* R_PARx_STATUS_DATA */
- volatile u32 *reg_config; /* R_PARx_CONFIG */
- volatile u32 *reg_delay; /* R_PARx_DELAY */
-
- /* DMA control */
- int odma;
- unsigned long dma_irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */
-
- volatile char *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR, output */
- volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST, output */
- volatile char *ocmdadr; /* adr to R_DMA_CHx_CMD, output */
-
- volatile char *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR, input */
- volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST, input */
- volatile char *icmdadr; /* adr to R_DMA_CHx_CMD, input */
-
- /* Non DMA interrupt stuff */
- unsigned long int_irq; /* R_VECT_MASK_RD */
- const volatile u32 *irq_mask_rd; /* R_IRQ_MASKX_RD */
- volatile u32 *irq_mask_clr; /* R_IRQ_MASKX_RD */
- const volatile u32 *irq_read; /* R_IRQ_READX */
- volatile u32 *irq_mask_set; /* R_IRQ_MASKX_SET */
- unsigned long irq_mask_tx; /* bitmask in R_IRQ_ for tx (ready) int */
- unsigned long irq_mask_rx; /* bitmask in R_IRQ_ for rx (data) int */
- unsigned long irq_mask_ecp_cmd; /* mask in R_IRQ_ for ecp_cmd int */
- unsigned long irq_mask_peri; /* bitmask in R_IRQ_ for peri int */
- int portnr;
-
- /* ----- end of fields initialised in port_table[] below ----- */
-
- struct parport *port;
-
- /* Shadow registers */
- volatile unsigned long reg_ctrl_data_shadow; /* for R_PARx_CTRL_DATA */
- volatile unsigned long reg_config_shadow; /* for R_PARx_CONFIG */
- volatile unsigned long reg_delay_shadow; /* for R_PARx_DELAY */
-};
-
-/* Always have the complete structs here, even if the port is not used!
- * (that way we can index this by the port number)
- */
-static struct etrax100par_struct port_table[] = {
- {
- R_PAR0_CTRL_DATA,
- R_PAR0_STATUS_DATA,
- R_PAR0_CONFIG,
- R_PAR0_DELAY,
- /* DMA interrupt stuff */
- 2,
- 1U << 4, /* uses DMA 2 and 3 */
- R_DMA_CH2_CLR_INTR,
- R_DMA_CH2_FIRST,
- R_DMA_CH2_CMD,
- R_DMA_CH3_CLR_INTR,
- R_DMA_CH3_FIRST,
- R_DMA_CH3_CMD,
- /* Non DMA interrupt stuff */
- IO_BITNR(R_VECT_MASK_RD, par0),
- R_IRQ_MASK0_RD,
- R_IRQ_MASK0_CLR,
- R_IRQ_READ0,
- R_IRQ_MASK0_SET,
- IO_FIELD(R_IRQ_MASK0_RD, par0_ready, 1U), /* tx (ready)*/
- IO_FIELD(R_IRQ_MASK0_RD, par0_data, 1U), /* rx (data)*/
- IO_FIELD(R_IRQ_MASK0_RD, par0_ecp_cmd, 1U), /* ecp_cmd */
- IO_FIELD(R_IRQ_MASK0_RD, par0_peri, 1U), /* peri */
- 0
- },
- {
- R_PAR1_CTRL_DATA,
- R_PAR1_STATUS_DATA,
- R_PAR1_CONFIG,
- R_PAR1_DELAY,
- /* DMA interrupt stuff */
- 4,
- 1U << 8, /* uses DMA 4 and 5 */
-
- R_DMA_CH4_CLR_INTR,
- R_DMA_CH4_FIRST,
- R_DMA_CH4_CMD,
- R_DMA_CH5_CLR_INTR,
- R_DMA_CH5_FIRST,
- R_DMA_CH5_CMD,
- /* Non DMA interrupt stuff */
- IO_BITNR(R_VECT_MASK_RD, par1),
- R_IRQ_MASK1_RD,
- R_IRQ_MASK1_CLR,
- R_IRQ_READ1,
- R_IRQ_MASK1_SET,
- IO_FIELD(R_IRQ_MASK1_RD, par1_ready, 1U), /* tx (ready)*/
- IO_FIELD(R_IRQ_MASK1_RD, par1_data, 1U), /* rx (data)*/
- IO_FIELD(R_IRQ_MASK1_RD, par1_ecp_cmd, 1U), /* ecp_cmd */
- IO_FIELD(R_IRQ_MASK1_RD, par1_peri, 1U), /* peri */
- 1
- }
-};
-
-
-#define NR_PORTS (sizeof(port_table)/sizeof(struct etrax100par_struct))
-
-static void
-parport_etrax_write_data(struct parport *p, unsigned char value)
-{
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
-
- DPRINTK("* E100 PP %d: etrax_write_data %02X\n", p->portnum, value);
- SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, data, value);
- *info->reg_ctrl_data = info->reg_ctrl_data_shadow;
-}
-
-
-static unsigned char
-parport_etrax_read_data(struct parport *p)
-{
- unsigned char ret;
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
-
- ret = IO_EXTRACT(R_PAR0_STATUS_DATA, data, *info->reg_status_data);
-
- DPRINTK("* E100 PP %d: etrax_read_data %02X\n", p->portnum, ret);
- return ret;
-}
-
-
-static void
-parport_etrax_write_control(struct parport *p, unsigned char control)
-{
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
-
- DPRINTK("* E100 PP %d: etrax_write_control %02x\n", p->portnum, control);
-
- SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, strb,
- (control & PARPORT_CONTROL_STROBE) > 0);
- SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, autofd,
- (control & PARPORT_CONTROL_AUTOFD) > 0);
- SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, init,
- (control & PARPORT_CONTROL_INIT) > 0);
- SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, seli,
- (control & PARPORT_CONTROL_SELECT) > 0);
-
- *info->reg_ctrl_data = info->reg_ctrl_data_shadow;
-}
-
-
-static unsigned char
-parport_etrax_read_control( struct parport *p)
-{
- unsigned char ret = 0;
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
-
- if (IO_EXTRACT(R_PAR0_CTRL_DATA, strb, info->reg_ctrl_data_shadow))
- ret |= PARPORT_CONTROL_STROBE;
- if (IO_EXTRACT(R_PAR0_CTRL_DATA, autofd, info->reg_ctrl_data_shadow))
- ret |= PARPORT_CONTROL_AUTOFD;
- if (IO_EXTRACT(R_PAR0_CTRL_DATA, init, info->reg_ctrl_data_shadow))
- ret |= PARPORT_CONTROL_INIT;
- if (IO_EXTRACT(R_PAR0_CTRL_DATA, seli, info->reg_ctrl_data_shadow))
- ret |= PARPORT_CONTROL_SELECT;
-
- DPRINTK("* E100 PP %d: etrax_read_control %02x\n", p->portnum, ret);
- return ret;
-}
-
-
-static unsigned char
-parport_etrax_frob_control(struct parport *p, unsigned char mask,
- unsigned char val)
-{
- unsigned char old;
-
- DPRINTK("* E100 PP %d: frob_control mask %02x, value %02x\n",
- p->portnum, mask, val);
- old = parport_etrax_read_control(p);
- parport_etrax_write_control(p, (old & ~mask) ^ val);
- return old;
-}
-
-
-static unsigned char
-parport_etrax_read_status(struct parport *p)
-{
- unsigned char ret = 0;
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
-
- if (IO_EXTRACT(R_PAR0_STATUS_DATA, fault, *info->reg_status_data))
- ret |= PARPORT_STATUS_ERROR;
- if (IO_EXTRACT(R_PAR0_STATUS_DATA, sel, *info->reg_status_data))
- ret |= PARPORT_STATUS_SELECT;
- if (!IO_EXTRACT(R_PAR0_STATUS_DATA, perr, *info->reg_status_data))
- ret |= PARPORT_STATUS_PAPEROUT;
- if (IO_EXTRACT(R_PAR0_STATUS_DATA, ack, *info->reg_status_data))
- ret |= PARPORT_STATUS_ACK;
- if (!IO_EXTRACT(R_PAR0_STATUS_DATA, busy, *info->reg_status_data))
- ret |= PARPORT_STATUS_BUSY;
-
- DPRINTK("* E100 PP %d: status register %04x\n",
- p->portnum, *info->reg_status_data);
- DPRINTK("* E100 PP %d: read_status %02x\n", p->portnum, ret);
- return ret;
-}
-
-
-static void
-parport_etrax_enable_irq(struct parport *p)
-{
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
- *info->irq_mask_set = info->irq_mask_tx;
- DPRINTK("* E100 PP %d: enable irq\n", p->portnum);
-}
-
-
-static void
-parport_etrax_disable_irq(struct parport *p)
-{
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
- *info->irq_mask_clr = info->irq_mask_tx;
- DPRINTK("* E100 PP %d: disable irq\n", p->portnum);
-}
-
-
-static void
-parport_etrax_data_forward(struct parport *p)
-{
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
-
- DPRINTK("* E100 PP %d: forward mode\n", p->portnum);
- SETS(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, oe, enable);
- *info->reg_ctrl_data = info->reg_ctrl_data_shadow;
-}
-
-
-static void
-parport_etrax_data_reverse(struct parport *p)
-{
- struct etrax100par_struct *info =
- (struct etrax100par_struct *)p->private_data;
-
- DPRINTK("* E100 PP %d: reverse mode\n", p->portnum);
- SETS(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, oe, disable);
- *info->reg_ctrl_data = info->reg_ctrl_data_shadow;
-}
-
-
-static void
-parport_etrax_init_state(struct pardevice *dev, struct parport_state *s)
-{
- DPRINTK("* E100 PP: parport_etrax_init_state\n");
-}
-
-
-static void
-parport_etrax_save_state(struct parport *p, struct parport_state *s)
-{
- DPRINTK("* E100 PP: parport_etrax_save_state\n");
-}
-
-
-static void
-parport_etrax_restore_state(struct parport *p, struct parport_state *s)
-{
- DPRINTK("* E100 PP: parport_etrax_restore_state\n");
-}
-
-
-static void
-parport_etrax_inc_use_count(void)
-{
- MOD_INC_USE_COUNT;
-}
-
-
-static void
-parport_etrax_dec_use_count(void)
-{
- MOD_DEC_USE_COUNT;
-}
-
-
-static struct
-parport_operations pp_etrax_ops = {
- parport_etrax_write_data,
- parport_etrax_read_data,
-
- parport_etrax_write_control,
- parport_etrax_read_control,
- parport_etrax_frob_control,
-
- parport_etrax_read_status,
-
- parport_etrax_enable_irq,
- parport_etrax_disable_irq,
-
- parport_etrax_data_forward,
- parport_etrax_data_reverse,
-
- parport_etrax_init_state,
- parport_etrax_save_state,
- parport_etrax_restore_state,
-
- parport_etrax_inc_use_count,
- parport_etrax_dec_use_count,
-
- parport_ieee1284_epp_write_data,
- parport_ieee1284_epp_read_data,
- parport_ieee1284_epp_write_addr,
- parport_ieee1284_epp_read_addr,
-
- parport_ieee1284_ecp_write_data,
- parport_ieee1284_ecp_read_data,
- parport_ieee1284_ecp_write_addr,
-
- parport_ieee1284_write_compat,
- parport_ieee1284_read_nibble,
- parport_ieee1284_read_byte,
-};
-
-
-static void
-parport_etrax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct etrax100par_struct *info = (struct etrax100par_struct *)
- ((struct parport *)dev_id)->private_data;
- DPRINTK("* E100 PP %d: Interrupt received\n",
- ((struct parport *)dev_id)->portnum);
- *info->irq_mask_clr = info->irq_mask_tx;
- parport_generic_irq(irq, (struct parport *)dev_id, regs);
-}
-
-/* ----------- Initialisation code --------------------------------- */
-
-static void __init
-parport_etrax_show_parallel_version(void)
-{
- printk("ETRAX 100LX parallel port driver v1.0, (c) 2001 Axis Communications AB\n");
-}
-
-#ifdef CONFIG_ETRAX_PAR0_DMA
-#define PAR0_USE_DMA 1
-#else
-#define PAR0_USE_DMA 0
-#endif
-
-#ifdef CONFIG_ETRAX_PAR1_DMA
-#define PAR1_USE_DMA 1
-#else
-#define PAR1_USE_DMA 0
-#endif
-
-static void __init
-parport_etrax_init_registers(void)
-{
- struct etrax100par_struct *info;
- int i;
-
- for (i = 0, info = port_table; i < 2; i++, info++) {
-#ifndef CONFIG_ETRAX_PARALLEL_PORT0
- if (i == 0)
- continue;
-#endif
-#ifndef CONFIG_ETRAX_PARALLEL_PORT1
- if (i == 1)
- continue;
-#endif
- info->reg_config_shadow =
- IO_STATE(R_PAR0_CONFIG, iseli, inv) |
- IO_STATE(R_PAR0_CONFIG, iautofd, inv) |
- IO_STATE(R_PAR0_CONFIG, istrb, inv) |
- IO_STATE(R_PAR0_CONFIG, iinit, inv) |
- IO_STATE(R_PAR0_CONFIG, rle_in, disable) |
- IO_STATE(R_PAR0_CONFIG, rle_out, disable) |
- IO_STATE(R_PAR0_CONFIG, enable, on) |
- IO_STATE(R_PAR0_CONFIG, force, off) |
- IO_STATE(R_PAR0_CONFIG, ign_ack, wait) |
- IO_STATE(R_PAR0_CONFIG, oe_ack, wait_oe) |
- IO_STATE(R_PAR0_CONFIG, mode, manual);
-
- if ((i == 0 && PAR0_USE_DMA) || (i == 1 && PAR1_USE_DMA))
- info->reg_config_shadow |=
- IO_STATE(R_PAR0_CONFIG, dma, enable);
- else
- info->reg_config_shadow |=
- IO_STATE(R_PAR0_CONFIG, dma, disable);
-
- *info->reg_config = info->reg_config_shadow;
-
- info->reg_ctrl_data_shadow =
- IO_STATE(R_PAR0_CTRL_DATA, peri_int, nop) |
- IO_STATE(R_PAR0_CTRL_DATA, oe, enable) |
- IO_STATE(R_PAR0_CTRL_DATA, seli, inactive) |
- IO_STATE(R_PAR0_CTRL_DATA, autofd, inactive) |
- IO_STATE(R_PAR0_CTRL_DATA, strb, inactive) |
- IO_STATE(R_PAR0_CTRL_DATA, init, inactive) |
- IO_STATE(R_PAR0_CTRL_DATA, ecp_cmd, data) |
- IO_FIELD(R_PAR0_CTRL_DATA, data, 0);
- *info->reg_ctrl_data = info->reg_ctrl_data_shadow;
-
- /* Clear peri int without setting shadow */
- *info->reg_ctrl_data = info->reg_ctrl_data_shadow |
- IO_STATE(R_PAR0_CTRL_DATA, peri_int, ack);
-
- info->reg_delay_shadow =
- IO_FIELD(R_PAR0_DELAY, setup, 5) |
- IO_FIELD(R_PAR0_DELAY, strobe, 5) |
- IO_FIELD(R_PAR0_DELAY, hold, 5);
- *info->reg_delay = info->reg_delay_shadow;
- }
-
-#ifdef CONFIG_ETRAX_PARALLEL_PORT0
-#ifdef CONFIG_ETRAX_PAR0_DMA
- RESET_DMA(PAR0_TX_DMA_NBR);
- WAIT_DMA(PAR0_TX_DMA_NBR);
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
- printk(" Warning - DMA clash with ser2!\n");
-#endif /* SERIAL_PORT2 */
-#endif /* DMA */
-#endif /* PORT0 */
-
-#ifdef CONFIG_ETRAX_PARALLEL_PORT1
-#ifdef CONFIG_ETRAX_PAR1_DMA
- RESET_DMA(PAR1_TX_DMA_NBR);
- WAIT_DMA(PAR1_TX_DMA_NBR);
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
- printk(" Warning - DMA clash with ser3!\n");
-#endif /* SERIAL_PORT3 */
-#endif /* DMA */
-#endif /* PORT1 */
-}
-
-
-int __init
-parport_etrax_init(void)
-{
- struct parport *p;
- int port_exists = 0;
- int i;
- struct etrax100par_struct *info;
- const char *names[] = { "parallel 0 tx+rx", "parallel 1 tx+rx" };
-
- parport_etrax_show_parallel_version();
- parport_etrax_init_registers();
-
- for (i = 0, info = port_table; i < NR_PORTS; i++, info++) {
-#ifndef CONFIG_ETRAX_PARALLEL_PORT0
- if (i == 0)
- continue;
-#endif
-#ifndef CONFIG_ETRAX_PARALLEL_PORT1
- if (i == 1)
- continue;
-#endif
- p = parport_register_port((unsigned long)0, info->int_irq,
- PARPORT_DMA_NONE, &pp_etrax_ops);
- if (!p)
- continue;
-
- info->port = p;
- p->private_data = info;
- /* Axis FIXME: Set mode flags. */
- /* p->modes = PARPORT_MODE_TRISTATE | PARPORT_MODE_SAFEININT; */
-
- if(request_irq(info->int_irq, parport_etrax_interrupt,
- SA_SHIRQ, names[i], p)) {
- parport_unregister_port (p);
- continue;
- }
-
- printk(KERN_INFO "%s: ETRAX 100LX port %d using irq\n",
- p->name, i);
- parport_proc_register(p);
- parport_announce_port(p);
- port_exists = 1;
- }
-
- return port_exists;
-}
-
-void __exit
-parport_etrax_exit(void)
-{
- int i;
- struct etrax100par_struct *info;
-
- for (i = 0, info = port_table; i < NR_PORTS; i++, info++) {
-#ifndef CONFIG_ETRAX_PARALLEL_PORT0
- if (i == 0)
- continue;
-#endif
-#ifndef CONFIG_ETRAX_PARALLEL_PORT1
- if (i == 1)
- continue;
-#endif
- if (info->int_irq != PARPORT_IRQ_NONE)
- free_irq(info->int_irq, info->port);
- parport_proc_unregister(info->port);
- parport_unregister_port(info->port);
- }
-}
diff --git a/arch/cris/drivers/sync_serial.c b/arch/cris/drivers/sync_serial.c
deleted file mode 100644
index 59d62e01c731..000000000000
--- a/arch/cris/drivers/sync_serial.c
+++ /dev/null
@@ -1,900 +0,0 @@
-/*
- * Simple synchronous serial port driver for ETRAX 100LX.
- *
- * Synchronous serial ports are used for continous streamed data like audio.
- * The default setting for this driver is compatible with the STA 013 MP3
- * decoder. The driver can easily be tuned to fit other audio encoder/decoders
- * and SPI
- *
- * Copyright (c) 2001 Axis Communications AB
- *
- * Author: Mikael Starvik
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/svinto.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/sync_serial.h>
-
-/* The receiver is a bit tricky beacuse of the continous stream of data. */
-/* */
-/* Two DMA descriptors are linked together. Each DMA descriptor is */
-/* responsible for one half of a common buffer. */
-/* */
-/* ------------------------------ */
-/* | ---------- ---------- | */
-/* --> | Descr1 |-->| Descr2 |--- */
-/* ---------- ---------- */
-/* | | */
-/* v v */
-/* ----------------------------- */
-/* | BUFFER | */
-/* ----------------------------- */
-/* | | */
-/* readp writep */
-/* */
-/* If the application keeps up the pace readp will be right after writep.*/
-/* If the application can't keep the pace we have to throw away data. */
-/* The idea is that readp should be ready with the data pointed out by */
-/* Descr1 when the DMA has filled in Descr2. Otherwise we will discard */
-/* the rest of the data pointed out by Descr1 and set readp to the start */
-/* of Descr2 */
-
-#define SYNC_SERIAL_MAJOR 125
-
-/* IN_BUFFER_SIZE should be a multiple of 6 to make sure that 24 bit */
-/* words can be handled */
-
-#define IN_BUFFER_SIZE 12288
-#define OUT_BUFFER_SIZE 4096
-
-#define DEFAULT_FRAME_RATE 0
-#define DEFAULT_WORD_RATE 7
-
-#define DEBUG(x)
-
-/* Define some macros to access ETRAX 100 registers */
-#define SETF(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
- IO_FIELD(##reg##, field, val)
-#define SETS(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
- IO_STATE(##reg##, field, val)
-
-typedef struct sync_port
-{
- /* Etrax registers and bits*/
- volatile unsigned * const status;
- volatile unsigned * const ctrl_data;
- volatile unsigned * const output_dma_first;
- volatile unsigned char * const output_dma_cmd;
- volatile unsigned char * const output_dma_clr_irq;
- volatile unsigned * const input_dma_first;
- volatile unsigned char * const input_dma_cmd;
- volatile unsigned char * const input_dma_clr_irq;
- volatile unsigned * const data_out;
- volatile unsigned * const data_in;
- char data_avail_bit; /* In R_IRQ_MASK1_RD */
- char transmitter_ready_bit; /* In R_IRQ_MASK1_RD */
- char ready_irq_bit; /* In R_IRQ_MASK1_SET and R_IRQ_MASK1_CLR */
- char input_dma_descr_bit; /* In R_IRQ_MASK2_RD */
- char output_dma_bit; /* In R_IRQ_MASK2_RD */
-
- int enabled; /* 1 if port is enabled */
- int use_dma; /* 1 if port uses dma */
- int port_nbr; /* Port 0 or 1 */
- unsigned ctrl_data_shadow; /* Register shadow */
- char busy; /* 1 if port is busy */
- wait_queue_head_t out_wait_q;
- wait_queue_head_t in_wait_q;
- struct etrax_dma_descr out_descr;
- struct etrax_dma_descr in_descr1;
- struct etrax_dma_descr in_descr2;
- char out_buffer[OUT_BUFFER_SIZE];
- int out_count; /* Remaining bytes for current transfer */
- char* outp; /* Current position in out_buffer */
- char in_buffer[IN_BUFFER_SIZE];
- volatile char* readp; /* Next byte to be read by application */
- volatile char* writep; /* Next byte to be written by etrax */
- int odd_output; /* 1 if writing odd nible in 12 bit mode */
- int odd_input; /* 1 if reading odd nible in 12 bit mode */
-} sync_port;
-
-
-static int etrax_sync_serial_init(void);
-static void initialize_port(int portnbr);
-static int sync_serial_open(struct inode *, struct file*);
-static int sync_serial_release(struct inode*, struct file*);
-static int sync_serial_ioctl(struct inode*, struct file*,
- unsigned int cmd, unsigned long arg);
-static ssize_t sync_serial_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos);
-static ssize_t sync_serial_manual_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos);
-static ssize_t sync_serial_read(struct file *file, char *buf,
- size_t count, loff_t *ppos);
-static void send_word(sync_port* port);
-static void start_dma(struct sync_port *port, const char* data, int count);
-static void start_dma_in(sync_port* port);
-static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-
-/* The ports */
-static struct sync_port ports[]=
-{
- {
- R_SYNC_SERIAL1_STATUS, /* status */
- R_SYNC_SERIAL1_CTRL, /* ctrl_data */
- R_DMA_CH8_FIRST, /* output_dma_first */
- R_DMA_CH8_CMD, /* output_dma_cmd */
- R_DMA_CH8_CLR_INTR, /* output_dma_clr_irq */
- R_DMA_CH9_FIRST, /* input_dma_first */
- R_DMA_CH9_CMD, /* input_dma_cmd */
- R_DMA_CH9_CLR_INTR, /* input_dma_clr_irq */
- R_SYNC_SERIAL1_TR_DATA, /* data_out */
- R_SYNC_SERIAL1_REC_DATA,/* data in */
- IO_BITNR(R_IRQ_MASK1_RD, ser1_data), /* data_avail_bit */
- IO_BITNR(R_IRQ_MASK1_RD, ser1_ready), /* transmitter_ready_bit */
- IO_BITNR(R_IRQ_MASK1_SET, ser1_ready), /* ready_irq_bit */
- IO_BITNR(R_IRQ_MASK2_RD, dma9_descr), /* input_dma_descr_bit */
- IO_BITNR(R_IRQ_MASK2_RD, dma8_eop), /* output_dma_bit */
- },
- {
- R_SYNC_SERIAL3_STATUS, /* status */
- R_SYNC_SERIAL3_CTRL, /* ctrl_data */
- R_DMA_CH4_FIRST, /* output_dma_first */
- R_DMA_CH4_CMD, /* output_dma_cmd */
- R_DMA_CH4_CLR_INTR, /* output_dma_clr_irq */
- R_DMA_CH5_FIRST, /* input_dma_first */
- R_DMA_CH5_CMD, /* input_dma_cmd */
- R_DMA_CH5_CLR_INTR, /* input_dma_clr_irq */
- R_SYNC_SERIAL3_TR_DATA, /* data_out */
- R_SYNC_SERIAL3_REC_DATA,/* data in */
- IO_BITNR(R_IRQ_MASK1_RD, ser3_data), /* data_avail_bit */
- IO_BITNR(R_IRQ_MASK1_RD, ser3_ready), /* transmitter_ready_bit */
- IO_BITNR(R_IRQ_MASK1_SET, ser3_ready), /* ready_irq_bit */
- IO_BITNR(R_IRQ_MASK2_RD, dma5_descr), /* input_dma_descr_bit */
- IO_BITNR(R_IRQ_MASK2_RD, dma4_eop), /* output_dma_bit */
- }
-};
-
-/* Register shadows */
-static unsigned sync_serial_prescale_shadow = 0;
-static unsigned gen_config_ii_shadow = 0;
-
-#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
-
-static struct file_operations sync_serial_fops = {
- .owner = THIS_MODULE,
- .write = sync_serial_write,
- .read = sync_serial_read,
- .ioctl = sync_serial_ioctl,
- .open = sync_serial_open,
- .release = sync_serial_release
-};
-
-static int __init etrax_sync_serial_init(void)
-{
- ports[0].enabled = 0;
- ports[1].enabled = 0;
-
- if (register_chrdev(SYNC_SERIAL_MAJOR,"sync serial", &sync_serial_fops) <0 )
- {
- printk("unable to get major for synchronous serial port\n");
- return -EBUSY;
- }
-
- /* Deselect synchronous serial ports */
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, ser3, select);
- *R_GEN_CONFIG_II = gen_config_ii_shadow;
-
- /* Initialize Ports */
-#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0)
- ports[0].enabled = 1;
- SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser1, ss1extra);
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
-#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)
- ports[0].use_dma = 1;
- initialize_port(0);
- if(request_irq(24, tr_interrupt, 0, "synchronous serial 1 dma tr", &ports[0]))
- panic("Can't allocate sync serial port 1 IRQ");
- if(request_irq(25, rx_interrupt, 0, "synchronous serial 1 dma rx", &ports[0]))
- panic("Can't allocate sync serial port 1 IRQ");
- RESET_DMA(8); WAIT_DMA(8);
- RESET_DMA(9); WAIT_DMA(9);
- *R_DMA_CH8_CLR_INTR = IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do);
- *R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH9_CLR_INTR, clr_descr, do);
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma8_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma8_descr, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);
- start_dma_in(&ports[0]);
-#else
- ports[0].use_dma = 0;
- initialize_port(0);
- if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", &ports[0]))
- panic("Can't allocate sync serial manual irq");
- *R_IRQ_MASK1_SET = IO_STATE(R_IRQ_MASK1_SET, ser1_data, set);
-#endif
-#endif
-
-#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
- ports[1].enabled = 1;
- SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser3, ss3extra);
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);
-#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)
- ports[1].use_dma = 1;
- initialize_port(1);
- if(request_irq(20, tr_interrupt, 0, "synchronous serial 3 dma tr", &ports[1]))
- panic("Can't allocate sync serial port 1 IRQ");
- if(request_irq(21, rx_interrupt, 0, "synchronous serial 3 dma rx", &ports[1]))
- panic("Can't allocate sync serial port 1 IRQ");
- RESET_DMA(4); WAIT_DMA(4);
- RESET_DMA(5); WAIT_DMA(5);
- *R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);
- *R_DMA_CH5_CLR_INTR = IO_STATE(R_DMA_CH5_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH5_CLR_INTR, clr_descr, do);
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma4_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma4_descr, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma5_descr, set);
- start_dma_in(&ports[1]);
-#else
- ports[1].use_dma = 0;
- initialize_port(1);
- if (port[0].use_dma) /* Port 0 uses dma, we must manual allocate IRQ */
- {
- if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", &ports[1]))
- panic("Can't allocate sync serial manual irq");
- }
- *R_IRQ_MASK1_SET = IO_STATE(R_IRQ_MASK1_SET, ser3_data, set);
-#endif
-#endif
-
- *R_PORT_PB_I2C = port_pb_i2c_shadow; /* Use PB4/PB7 */
-
- /* Set up timing */
- *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow = (
- IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec) |
- IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u1, external) |
- IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec) |
- IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) |
- IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4) |
- IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, DEFAULT_FRAME_RATE) |
- IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, DEFAULT_WORD_RATE) |
- IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal));
-
- /* Select synchronous ports */
- *R_GEN_CONFIG_II = gen_config_ii_shadow;
-
- printk("ETRAX 100LX synchronous serial port driver\n");
- return 0;
-}
-
-static void initialize_port(int portnbr)
-{
- struct sync_port* port = &ports[portnbr];
-
- DEBUG(printk("Init sync serial port %d\n", portnbr));
-
- port->port_nbr = portnbr;
- port->busy = 0;
- port->readp = port->in_buffer;
- port->writep = port->in_buffer + IN_BUFFER_SIZE/2;
- port->odd_input = 0;
-
- init_waitqueue_head(&port->out_wait_q);
- init_waitqueue_head(&port->in_wait_q);
-
- port->ctrl_data_shadow =
- IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, error, ignore) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, rec_enable, disable) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, f_synctype, normal) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, word) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, normal) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, stopped) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, disable) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, clk_polarity, neg) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, frame_polarity, normal)|
- IO_STATE(R_SYNC_SERIAL1_CTRL, status_polarity, inverted)|
- IO_STATE(R_SYNC_SERIAL1_CTRL, clk_driver, normal) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, frame_driver, normal) |
- IO_STATE(R_SYNC_SERIAL1_CTRL, status_driver, normal)|
- IO_STATE(R_SYNC_SERIAL1_CTRL, def_out0, high);
-
- if (port->use_dma)
- port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, dma_enable, on);
- else
- port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, dma_enable, off);
-
- *port->ctrl_data = port->ctrl_data_shadow;
-}
-
-static int sync_serial_open(struct inode *inode, struct file *file)
-{
- int dev = MINOR(inode->i_rdev);
- DEBUG(printk("Open sync serial port %d\n", dev));
-
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
- {
- DEBUG(printk("Invalid minor %d\n", dev));
- return -ENODEV;
- }
- if (ports[dev].busy)
- {
- DEBUG(printk("Device is busy.. \n"));
- return -EBUSY;
- }
- ports[dev].busy = 1;
- return 0;
-}
-
-static int sync_serial_release(struct inode *inode, struct file *file)
-{
- int dev = MINOR(inode->i_rdev);
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
- {
- DEBUG(printk("Invalid minor %d\n", dev));
- return -ENODEV;
- }
- ports[dev].busy = 0;
- return 0;
-}
-
-static int sync_serial_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int return_val = 0;
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
- sync_port* port;
-
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
- {
- DEBUG(printk("Invalid minor %d\n", dev));
- return -1;
- }
- port = &ports[dev];
-
- /* Disable port while changing config */
- if (dev)
- {
- RESET_DMA(4); WAIT_DMA(4);
- *R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
- }
- else
- {
- RESET_DMA(8); WAIT_DMA(8);
- *R_DMA_CH8_CLR_INTR = IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do);
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
- }
- *R_GEN_CONFIG_II = gen_config_ii_shadow;
-
- switch(cmd)
- {
- case SSP_SPEED:
- if (GET_SPEED(arg) == CODEC)
- {
- if (dev)
- SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec);
- else
- SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec);
-
- SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, prescaler, GET_FREQ(arg));
- SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, frame_rate, GET_FRAME_RATE(arg));
- SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, word_rate, GET_WORD_RATE(arg));
- }
- else
- {
- SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_baud, GET_SPEED(arg));
- if (dev)
- SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, baudrate);
- else
- SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, baudrate);
- }
- break;
- case SSP_MODE:
- if (arg > 5)
- return -EINVAL;
- SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg);
- break;
- case SSP_FRAME_SYNC:
- if (arg & NORMAL_SYNC)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);
- else if (arg & EARLY_SYNC)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, early);
-
- if (arg & BIT_SYNC)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, bit);
- else if (arg & WORD_SYNC)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
- else if (arg & EXTENDED_SYNC)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, extended);
-
- if (arg & SYNC_ON)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
- else if (arg & SYNC_OFF)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, off);
-
- if (arg & WORD_SIZE_8)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
- else if (arg & WORD_SIZE_12)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size12bit);
- else if (arg & WORD_SIZE_16)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size16bit);
- else if (arg & WORD_SIZE_24)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size24bit);
- else if (arg & WORD_SIZE_32)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size32bit);
-
- if (arg & BIT_ORDER_MSB)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
- else if (arg & BIT_ORDER_LSB)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, lsb);
-
- if (arg & FLOW_CONTROL_ENABLE)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled);
- else if (arg & FLOW_CONTROL_DISABLE)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
-
- if (arg & CLOCK_NOT_GATED)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, normal);
- else if (arg & CLOCK_GATED)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, gated);
-
- break;
- case SSP_IPOLARITY:
- if (arg & CLOCK_NORMAL)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
- else if (arg & CLOCK_INVERT)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, pos);
-
- if (arg & FRAME_NORMAL)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, normal);
- else if (arg & FRAME_INVERT)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
-
- if (arg & STATUS_NORMAL)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, normal);
- else if (arg & STATUS_INVERT)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, inverted);
- break;
- case SSP_OPOLARITY:
- if (arg & CLOCK_NORMAL)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, normal);
- else if (arg & CLOCK_INVERT)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
-
- if (arg & FRAME_NORMAL)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, normal);
- else if (arg & FRAME_INVERT)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
-
- if (arg & STATUS_NORMAL)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, normal);
- else if (arg & STATUS_INVERT)
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, inverted);
- break;
- case SSP_SPI:
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);
- if (arg & SPI_SLAVE)
- {
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
- SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, SLAVE_INPUT);
- }
- else
- {
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
- SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, MASTER_OUTPUT);
- }
- break;
- default:
- return_val = -1;
- }
- /* Set config and enable port */
- *port->ctrl_data = port->ctrl_data_shadow;
- *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow;
- if (dev)
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);
- else
- SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
-
- *R_GEN_CONFIG_II = gen_config_ii_shadow;
- return return_val;
-}
-
-static ssize_t sync_serial_manual_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
- DECLARE_WAITQUEUE(wait, current);
- sync_port* port;
-
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
- {
- DEBUG(printk("Invalid minor %d\n", dev));
- return -ENODEV;
- }
-
- port = &ports[dev];
- if (copy_from_user(port->out_buffer, buf, count))
- return -EFAULT;
- port->outp = port->out_buffer;
- port->out_count = count;
- port->odd_output = 1;
- add_wait_queue(&port->out_wait_q, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- *R_IRQ_MASK1_SET = 1 << port->ready_irq_bit; /* transmitter ready IRQ on */
- send_word(port); /* Start sender by sending first word */
- schedule();
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->out_wait_q, &wait);
- if (signal_pending(current))
- {
- return -EINTR;
- }
- return count;
-}
-
-static ssize_t sync_serial_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
- DECLARE_WAITQUEUE(wait, current);
- sync_port *port;
-
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
- {
- DEBUG(printk("Invalid minor %d\n", dev));
- return -ENODEV;
- }
- port = &ports[dev];
-
- DEBUG(printk("Write dev %d count %d\n", port->port_nbr, count));
-
- count = count > OUT_BUFFER_SIZE ? OUT_BUFFER_SIZE : count;
-
- /* Make sure transmitter is running */
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, enable);
- *port->ctrl_data = port->ctrl_data_shadow;
-
- if (!port->use_dma)
- {
- return sync_serial_manual_write(file, buf, count, ppos);
- }
-
- if (copy_from_user(port->out_buffer, buf, count))
- return -EFAULT;
- add_wait_queue(&port->out_wait_q, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- start_dma(port, buf, count);
- schedule();
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->out_wait_q, &wait);
- if (signal_pending(current))
- {
- return -EINTR;
- }
- return count;
-}
-
-static ssize_t sync_serial_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
- int avail;
- sync_port *port;
- char* start;
- char* end;
- unsigned long flags;
-
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
- {
- DEBUG(printk("Invalid minor %d\n", dev));
- return -ENODEV;
- }
- port = &ports[dev];
-
- DEBUG(printk("Read dev %d count %d\n", dev, count));
-
- /* Make sure receiver is running */
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);
- SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, enable);
- *port->ctrl_data = port->ctrl_data_shadow;
-
- /* Calculate number of available bytes */
- while (port->readp == port->writep) /* No data */
- {
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
- interruptible_sleep_on(&port->in_wait_q);
- if (signal_pending(current))
- {
- return -EINTR;
- }
- }
-
- /* Save pointers to avoid that they are modified by interrupt */
- start = port->readp;
- end = port->writep;
-
- /* Lazy read, never return wrapped data. */
- if (end > start)
- avail = end - start;
- else
- avail = port->in_buffer + IN_BUFFER_SIZE - start;
-
- count = count > avail ? avail : count;
- if (copy_to_user(buf, start, count))
- return -EFAULT;
-
- /* Disable interrupts while updating readp */
- save_flags(flags);
- cli();
- port->readp += count;
- if (port->readp == port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */
- port->readp = port->in_buffer;
- restore_flags(flags);
-
- DEBUG(printk("%d bytes read\n", count));
- return count;
-}
-
-static void send_word(sync_port* port)
-{
- switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))
- {
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
- port->out_count--;
- *port->data_out = *port->outp++;
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
- port->out_count--;
- if (port->odd_output)
- *port->data_out = ((*port->outp) << 16) | (*(unsigned short *)(port->outp + 1));
- else
- *port->data_out = ((*(unsigned short *)port->outp) << 8) | (*(port->outp + 1));
- port->odd_output = !port->odd_output;
- port->outp++;
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
- port->out_count-=2;
- *port->data_out = *(unsigned short *)port->outp;
- port->outp+=2;
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
- port->out_count-=3;
- *port->data_out = *(unsigned int *)port->outp;
- port->outp+=3;
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
- port->out_count-=4;
- *port->data_out = *(unsigned int *)port->outp;
- port->outp+=4;
- break;
- }
-}
-
-static void start_dma(struct sync_port* port, const char* data, int count)
-{
- port->out_descr.hw_len = 0;
- port->out_descr.next = 0;
- port->out_descr.ctrl = d_int | d_eol | d_eop | d_wait;
- port->out_descr.sw_len = count;
- port->out_descr.buf = virt_to_phys(port->out_buffer);
- port->out_descr.status = 0;
-
- *port->output_dma_first = virt_to_phys(&port->out_descr);
- *port->output_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
-}
-
-static void start_dma_in(sync_port* port)
-{
- if (port->writep > port->in_buffer + IN_BUFFER_SIZE)
- {
- panic("Offset too large in sync serial driver\n");
- return;
- }
- port->in_descr1.hw_len = 0;
- port->in_descr1.ctrl = d_int;
- port->in_descr1.status = 0;
- port->in_descr1.next = virt_to_phys(&port->in_descr2);
- port->in_descr2.hw_len = 0;
- port->in_descr2.next = virt_to_phys(&port->in_descr1);
- port->in_descr2.ctrl = d_int;
- port->in_descr2.status = 0;
-
- /* Find out which descriptor to start */
- if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2)
- {
- /* Start descriptor 2 */
- port->in_descr1.sw_len = IN_BUFFER_SIZE/2; /* All data available in 1 */
- port->in_descr1.buf = virt_to_phys(port->in_buffer);
- port->in_descr2.sw_len = port->in_buffer + IN_BUFFER_SIZE - port->writep;
- port->in_descr2.buf = virt_to_phys(port->writep);
- *port->input_dma_first = virt_to_phys(&port->in_descr2);
- }
- else
- {
- /* Start descriptor 1 */
- port->in_descr1.sw_len = port->in_buffer + IN_BUFFER_SIZE/2 - port->writep;
- port->in_descr1.buf = virt_to_phys(port->writep);
- port->in_descr2.sw_len = IN_BUFFER_SIZE/2;
- port->in_descr2.buf = virt_to_phys(port->in_buffer + IN_BUFFER_SIZE / 2);
- *port->input_dma_first = virt_to_phys(&port->in_descr1);
- }
- *port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
-}
-
-static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- unsigned long ireg = *R_IRQ_MASK2_RD;
- int i;
-
- for (i = 0; i < NUMBER_OF_PORTS; i++)
- {
- sync_port *port = &ports[i];
- if (ireg & (1 << port->output_dma_bit)) /* IRQ active for the port? */
- {
- /* Clear IRQ */
- *port->output_dma_clr_irq =
- IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
- wake_up_interruptible(&port->out_wait_q); /* wake up the waiting process */
- }
- }
-}
-
-static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- unsigned long ireg = *R_IRQ_MASK2_RD;
- int i;
-
- for (i = 0; i < NUMBER_OF_PORTS; i++)
- {
- int update = 0;
- sync_port *port = &ports[i];
-
- if (!port->enabled)
- {
- continue;
- }
-
- if (ireg & (1 << port->input_dma_descr_bit)) /* Descriptor interrupt */
- {
- /* DMA has reached end of descriptor */
- *port->input_dma_clr_irq =
- IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) |
- IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
-
- /* Find out which descriptor that is ready */
- if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2)
- {
- /* Descr 2 was ready. Restart DMA at descriptor 1 */
- port->writep = port->in_buffer;
-
- /* Throw away data? */
- if (port->readp < port->in_buffer + IN_BUFFER_SIZE/2)
- port->readp = port->in_buffer + IN_BUFFER_SIZE/2;
- }
- else
- {
- /* Descr 1 was ready. Restart DMA at descriptor 2 */
- port->writep = port->in_buffer + IN_BUFFER_SIZE/2;
-
- /* Throw away data? */
- if (port->readp >= port->in_buffer + IN_BUFFER_SIZE/2)
- port->readp = port->in_buffer;
- }
- start_dma_in(port);
- wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */
- }
- }
-}
-
-static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- int i;
-
- for (i = 0; i < NUMBER_OF_PORTS; i++)
- {
- sync_port* port = &ports[i];
-
- if (!port->enabled)
- {
- continue;
- }
-
- if (*R_IRQ_MASK1_RD & (1 << port->data_avail_bit)) /* Data received? */
- {
- /* Read data */
- switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))
- {
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
- *port->writep++ = *(volatile char *)port->data_in;
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
- {
- int data = *(unsigned short *)port->data_in;
- if (port->odd_input)
- {
- *port->writep |= (data & 0x0f00) >> 8;
- *(port->writep + 1) = data & 0xff;
- }
- else
- {
- *port->writep = (data & 0x0ff0) >> 4;
- *(port->writep + 1) = (data & 0x0f) << 4;
- }
- port->odd_input = !port->odd_input;
- port->writep+=1;
- }
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
- *(unsigned short*)port->writep = *(volatile unsigned short *)port->data_in;
- port->writep+=2;
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
- *(unsigned int*)port->writep = *port->data_in;
- port->writep+=3;
- break;
- case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
- *(unsigned int*)port->writep = *port->data_in;
- port->writep+=4;
- break;
- }
-
- if (port->writep > port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */
- port->writep = port->in_buffer;
- wake_up_interruptible(&port->in_wait_q); /* Wake up application */
- }
-
- if (*R_IRQ_MASK1_RD & (1 << port->transmitter_ready_bit)) /* Transmitter ready? */
- {
- if (port->out_count) /* More data to send */
- send_word(port);
- else /* transmission finished */
- {
- *R_IRQ_MASK1_CLR = 1 << port->ready_irq_bit; /* Turn off IRQ */
- wake_up_interruptible(&port->out_wait_q); /* Wake up application */
- }
- }
- }
-}
-
-module_init(etrax_sync_serial_init);
diff --git a/arch/cris/drivers/usb-host.c b/arch/cris/drivers/usb-host.c
deleted file mode 100644
index 3a6326f735ae..000000000000
--- a/arch/cris/drivers/usb-host.c
+++ /dev/null
@@ -1,2516 +0,0 @@
-/*
- * usb-host.c: ETRAX 100LX USB Host Controller Driver (HCD)
- *
- * Copyright (c) 2001 Axis Communications AB.
- *
- * $Id: usb-host.c,v 1.11 2001/09/26 11:52:16 bjornw Exp $
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/version.h>
-#include <linux/list.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/svinto.h>
-
-#include <linux/usb.h>
-#include "usb-host.h"
-
-#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR
-#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR
-#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR
-
-static const char *usb_hcd_version = "$Revision: 1.11 $";
-
-#undef KERN_DEBUG
-#define KERN_DEBUG ""
-
-#undef USB_DEBUG_RH
-#undef USB_DEBUG_EP
-#undef USB_DEBUG_DESC
-#undef USB_DEBUG_TRACE
-#undef USB_DEBUG_CTRL
-#undef USB_DEBUG_BULK
-#undef USB_DEBUG_INTR
-
-#ifdef USB_DEBUG_RH
-#define dbg_rh(format, arg...) printk(KERN_DEBUG __FILE__ ": (RH) " format "\n" , ## arg)
-#else
-#define dbg_rh(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_EP
-#define dbg_ep(format, arg...) printk(KERN_DEBUG __FILE__ ": (EP) " format "\n" , ## arg)
-#else
-#define dbg_ep(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_CTRL
-#define dbg_ctrl(format, arg...) printk(KERN_DEBUG __FILE__ ": (CTRL) " format "\n" , ## arg)
-#else
-#define dbg_ctrl(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_BULK
-#define dbg_bulk(format, arg...) printk(KERN_DEBUG __FILE__ ": (BULK) " format "\n" , ## arg)
-#else
-#define dbg_bulk(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_INTR
-#define dbg_intr(format, arg...) printk(KERN_DEBUG __FILE__ ": (INTR) " format "\n" , ## arg)
-#else
-#define dbg_intr(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_TRACE
-#define DBFENTER (printk(KERN_DEBUG __FILE__ ": Entering : " __FUNCTION__ "\n"))
-#define DBFEXIT (printk(KERN_DEBUG __FILE__ ": Exiting : " __FUNCTION__ "\n"))
-#else
-#define DBFENTER (NULL)
-#define DBFEXIT (NULL)
-#endif
-
-/*-------------------------------------------------------------------
- Virtual Root Hub
- -------------------------------------------------------------------*/
-
-static __u8 root_hub_dev_des[] =
-{
- 0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
- 0x00, /* __u16 bcdUSB; v1.0 */
- 0x01,
- 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
- 0x00, /* __u8 bDeviceSubClass; */
- 0x00, /* __u8 bDeviceProtocol; */
- 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
- 0x00, /* __u16 idVendor; */
- 0x00,
- 0x00, /* __u16 idProduct; */
- 0x00,
- 0x00, /* __u16 bcdDevice; */
- 0x00,
- 0x00, /* __u8 iManufacturer; */
- 0x02, /* __u8 iProduct; */
- 0x01, /* __u8 iSerialNumber; */
- 0x01 /* __u8 bNumConfigurations; */
-};
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x02, /* __u8 bDescriptorType; Configuration */
- 0x19, /* __u16 wTotalLength; */
- 0x00,
- 0x01, /* __u8 bNumInterfaces; */
- 0x01, /* __u8 bConfigurationValue; */
- 0x00, /* __u8 iConfiguration; */
- 0x40, /* __u8 bmAttributes; Bit 7: Bus-powered */
- 0x00, /* __u8 MaxPower; */
-
- /* interface */
- 0x09, /* __u8 if_bLength; */
- 0x04, /* __u8 if_bDescriptorType; Interface */
- 0x00, /* __u8 if_bInterfaceNumber; */
- 0x00, /* __u8 if_bAlternateSetting; */
- 0x01, /* __u8 if_bNumEndpoints; */
- 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
- 0x00, /* __u8 if_bInterfaceSubClass; */
- 0x00, /* __u8 if_bInterfaceProtocol; */
- 0x00, /* __u8 if_iInterface; */
-
- /* endpoint */
- 0x07, /* __u8 ep_bLength; */
- 0x05, /* __u8 ep_bDescriptorType; Endpoint */
- 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
- 0x00,
- 0xff /* __u8 ep_bInterval; 255 ms */
-};
-
-static __u8 root_hub_hub_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x29, /* __u8 bDescriptorType; Hub-descriptor */
- 0x02, /* __u8 bNbrPorts; */
- 0x00, /* __u16 wHubCharacteristics; */
- 0x00,
- 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
- 0x00, /* __u8 bHubContrCurrent; 0 mA */
- 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
- 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
-};
-
-
-#define OK(x) len = (x); dbg_rh("OK(%d): line: %d", x, __LINE__); break
-#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \
-{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}
-
-static submit_urb_count = 0;
-
-//#define ETRAX_USB_INTR_IRQ
-//#define ETRAX_USB_INTR_ERROR_FATAL
-
-#define RX_BUF_SIZE 32768
-#define RX_DESC_BUF_SIZE 64
-#define NBR_OF_RX_DESC (RX_BUF_SIZE / RX_DESC_BUF_SIZE)
-
-#define NBR_OF_EP_DESC 32
-
-#define MAX_INTR_INTERVAL 128
-
-static __u32 ep_usage_bitmask;
-static __u32 ep_really_active;
-
-static unsigned char RxBuf[RX_BUF_SIZE];
-static USB_IN_Desc_t RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4)));
-
-static volatile USB_IN_Desc_t *myNextRxDesc;
-static volatile USB_IN_Desc_t *myLastRxDesc;
-static volatile USB_IN_Desc_t *myPrevRxDesc;
-
-static USB_EP_Desc_t TxCtrlEPList[NBR_OF_EP_DESC] __attribute__ ((aligned (4)));
-static USB_EP_Desc_t TxBulkEPList[NBR_OF_EP_DESC] __attribute__ ((aligned (4)));
-
-static USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));
-static USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));
-
-static struct urb *URB_List[NBR_OF_EP_DESC];
-static kmem_cache_t *usb_desc_cache;
-static struct usb_bus *etrax_usb_bus;
-
-static void dump_urb (struct urb *urb);
-static void init_rx_buffers(void);
-static int etrax_rh_unlink_urb (struct urb *urb);
-static void etrax_rh_send_irq(struct urb *urb);
-static void etrax_rh_init_int_timer(struct urb *urb);
-static void etrax_rh_int_timer_do(unsigned long ptr);
-
-static void etrax_usb_setup_epid(char epid, char devnum, char endpoint,
- char packsize, char slow);
-static int etrax_usb_lookup_epid(unsigned char devnum, char endpoint, char slow, int maxp);
-static int etrax_usb_allocate_epid(void);
-static void etrax_usb_free_epid(char epid);
-static void cleanup_sb(USB_SB_Desc_t *sb);
-
-static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags);
-static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags);
-
-static int etrax_usb_submit_ctrl_urb(struct urb *urb, int mem_flags);
-
-static int etrax_usb_submit_urb(struct urb *urb, int mem_flags);
-static int etrax_usb_unlink_urb(struct urb *urb);
-static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
-static int etrax_usb_allocate_dev(struct usb_device *usb_dev);
-static int etrax_usb_deallocate_dev(struct usb_device *usb_dev);
-
-static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs);
-static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);
-static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs);
-
-static int etrax_rh_submit_urb (struct urb *urb);
-
-static int etrax_usb_hc_init(void);
-static void etrax_usb_hc_cleanup(void);
-
-static struct usb_operations etrax_usb_device_operations =
-{
- etrax_usb_allocate_dev,
- etrax_usb_deallocate_dev,
- etrax_usb_get_frame_number,
- etrax_usb_submit_urb,
- etrax_usb_unlink_urb
-};
-
-#ifdef USB_DEBUG_DESC
-static void dump_urb(struct urb *urb)
-{
- printk("\nurb :0x%08X\n", urb);
- printk("next :0x%08X\n", urb->next);
- printk("dev :0x%08X\n", urb->dev);
- printk("pipe :0x%08X\n", urb->pipe);
- printk("status :%d\n", urb->status);
- printk("transfer_flags :0x%08X\n", urb->transfer_flags);
- printk("transfer_buffer :0x%08X\n", urb->transfer_buffer);
- printk("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
- printk("actual_length :%d\n", urb->actual_length);
- printk("setup_packet :0x%08X\n", urb->setup_packet);
- printk("start_frame :%d\n", urb->start_frame);
- printk("number_of_packets :%d\n", urb->number_of_packets);
- printk("interval :%d\n", urb->interval);
- printk("error_count :%d\n", urb->error_count);
- printk("context :0x%08X\n", urb->context);
- printk("complete :0x%08X\n\n", urb->complete);
-}
-
-static void dump_in_desc(USB_IN_Desc_t *in)
-{
- printk("\nUSB_IN_Desc at 0x%08X\n", in);
- printk(" sw_len : 0x%04X (%d)\n", in->sw_len, in->sw_len);
- printk(" command : 0x%04X\n", in->command);
- printk(" next : 0x%08X\n", in->next);
- printk(" buf : 0x%08X\n", in->buf);
- printk(" hw_len : 0x%04X (%d)\n", in->hw_len, in->hw_len);
- printk(" status : 0x%04X\n\n", in->status);
-}
-
-static void dump_sb_desc(USB_SB_Desc_t *sb)
-{
- printk("\nUSB_SB_Desc at 0x%08X\n", sb);
- printk(" sw_len : 0x%04X (%d)\n", sb->sw_len, sb->sw_len);
- printk(" command : 0x%04X\n", sb->command);
- printk(" next : 0x%08X\n", sb->next);
- printk(" buf : 0x%08X\n\n", sb->buf);
-}
-
-
-static void dump_ep_desc(USB_EP_Desc_t *ep)
-{
- printk("\nUSB_EP_Desc at 0x%08X\n", ep);
- printk(" hw_len : 0x%04X (%d)\n", ep->hw_len, ep->hw_len);
- printk(" command : 0x%08X\n", ep->command);
- printk(" sub : 0x%08X\n", ep->sub);
- printk(" nep : 0x%08X\n\n", ep->nep);
-}
-
-
-#else
-#define dump_urb(...) (NULL)
-#define dump_ep_desc(...) (NULL)
-#define dump_sb_desc(...) (NULL)
-#define dump_in_desc(...) (NULL)
-#endif
-
-static void init_rx_buffers(void)
-{
- int i;
-
- DBFENTER;
-
- for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) {
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].command = 0;
- RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);
- RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
- RxDescList[i].hw_len = 0;
- RxDescList[i].status = 0;
- }
-
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes);
- RxDescList[i].next = virt_to_phys(&RxDescList[0]);
- RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
- RxDescList[i].hw_len = 0;
- RxDescList[i].status = 0;
-
- myNextRxDesc = &RxDescList[0];
- myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
- myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
-
- *R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc);
- *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start);
-
- DBFEXIT;
-}
-
-static void init_tx_ctrl_ep(void)
-{
- int i;
-
- DBFENTER;
-
- for (i = 0; i < (NBR_OF_EP_DESC - 1); i++) {
- TxCtrlEPList[i].hw_len = 0;
- TxCtrlEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
- TxCtrlEPList[i].sub = 0;
- TxCtrlEPList[i].nep = virt_to_phys(&TxCtrlEPList[i + 1]);
- }
-
- TxCtrlEPList[i].hw_len = 0;
- TxCtrlEPList[i].command = IO_STATE(USB_EP_command, eol, yes) |
- IO_FIELD(USB_EP_command, epid, i);
-
- TxCtrlEPList[i].sub = 0;
- TxCtrlEPList[i].nep = virt_to_phys(&TxCtrlEPList[0]);
-
- *R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[0]);
- *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
-
- DBFEXIT;
-}
-
-static void init_tx_bulk_ep(void)
-{
- int i;
-
- DBFENTER;
-
- for (i = 0; i < (NBR_OF_EP_DESC - 1); i++) {
- TxBulkEPList[i].hw_len = 0;
- TxBulkEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
- TxBulkEPList[i].sub = 0;
- TxBulkEPList[i].nep = virt_to_phys(&TxBulkEPList[i + 1]);
- }
-
- TxBulkEPList[i].hw_len = 0;
- TxBulkEPList[i].command = IO_STATE(USB_EP_command, eol, yes) |
- IO_FIELD(USB_EP_command, epid, i);
-
- TxBulkEPList[i].sub = 0;
- TxBulkEPList[i].nep = virt_to_phys(&TxBulkEPList[0]);
-
- *R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[0]);
- *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
-
- DBFEXIT;
-}
-
-static void init_tx_intr_ep(void)
-{
- int i;
-
- DBFENTER;
-
- TxIntrSB_zout.sw_len = 0;
- TxIntrSB_zout.next = 0;
- TxIntrSB_zout.buf = 0;
- TxIntrSB_zout.command = IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, zout) |
- IO_STATE(USB_SB_command, full, yes) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes);
-
- for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) {
- TxIntrEPList[i].hw_len = 0;
- TxIntrEPList[i].command = IO_STATE(USB_EP_command, eof, yes) |
- IO_STATE(USB_EP_command, enable, yes) |
- IO_FIELD(USB_EP_command, epid, 0);
- TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
- TxIntrEPList[i].nep = virt_to_phys(&TxIntrEPList[i + 1]);
- }
-
- TxIntrEPList[i].hw_len = 0;
- TxIntrEPList[i].command =
- IO_STATE(USB_EP_command, eof, yes) |
- IO_STATE(USB_EP_command, enable, yes) |
- IO_FIELD(USB_EP_command, epid, 0);
- TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
- TxIntrEPList[i].nep = virt_to_phys(&TxIntrEPList[0]);
-
- *R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);
- *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
-
- DBFEXIT;
-}
-
-
-static int etrax_usb_unlink_intr_urb(struct urb *urb)
-{
- struct usb_device *usb_dev = urb->dev;
- etrax_hc_t *hc = usb_dev->bus->hcpriv;
-
- USB_EP_Desc_t *tmp_ep;
- USB_EP_Desc_t *first_ep;
-
- USB_EP_Desc_t *ep_desc;
- USB_SB_Desc_t *sb_desc;
-
- char epid;
- char devnum;
- char endpoint;
- char slow;
- int maxlen;
- int i;
-
- etrax_urb_priv_t *urb_priv;
- unsigned long flags;
-
- DBFENTER;
-
- devnum = usb_pipedevice(urb->pipe);
- endpoint = usb_pipeendpoint(urb->pipe);
- slow = usb_pipeslow(urb->pipe);
- maxlen = usb_maxpacket(urb->dev, urb->pipe,
- usb_pipeout(urb->pipe));
-
- epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
- if (epid == -1) {
- err("Trying to unlink urb that is not in traffic queue!!");
- return -1; /* fix this */
- }
-
- *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, stop);
- /* Somehow wait for the DMA to finish current activities */
- i = jiffies + 100;
- while (time_before(jiffies, i))
- ;
-
- first_ep = &TxIntrEPList[0];
- tmp_ep = first_ep;
-
- do {
- if (IO_EXTRACT(USB_EP_command, epid, ((USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep))->command)
- == epid) {
- /* Unlink it !!! */
- dbg_intr("Found urb to unlink for epid %d", epid);
-
- ep_desc = phys_to_virt(tmp_ep->nep);
- tmp_ep->nep = ep_desc->nep;
- kmem_cache_free(usb_desc_cache, phys_to_virt(ep_desc->sub));
- kmem_cache_free(usb_desc_cache, ep_desc);
- }
-
- tmp_ep = phys_to_virt(tmp_ep->nep);
-
- } while (tmp_ep != first_ep);
-
- /* We should really try to move the EP register to an EP that is not removed
- instead of restarting, but this will work too */
- *R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);
- *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
-
- clear_bit(epid, (void *)&ep_really_active);
- URB_List[epid] = NULL;
- etrax_usb_free_epid(epid);
-
- DBFEXIT;
-
- return 0;
-}
-
-void etrax_usb_do_intr_recover(int epid)
-{
- USB_EP_Desc_t *first_ep, *tmp_ep;
-
- first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);
- tmp_ep = first_ep;
-
- do {
- if (IO_EXTRACT(USB_EP_command, epid, tmp_ep->command) == epid &&
- !(tmp_ep->command & IO_MASK(USB_EP_command, enable))) {
- tmp_ep->command |= IO_STATE(USB_EP_command, enable, yes);
- }
-
- tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep);
-
- } while (tmp_ep != first_ep);
-}
-
-static int etrax_usb_submit_intr_urb(struct urb *urb, mem_flags)
-{
- USB_EP_Desc_t *tmp_ep;
- USB_EP_Desc_t *first_ep;
-
- USB_SB_Desc_t *sb_desc;
-
- char epid;
- char devnum;
- char endpoint;
- char maxlen;
- char slow;
- int interval;
- int i;
-
- etrax_urb_priv_t *urb_priv;
- unsigned long flags;
-
- DBFENTER;
-
- devnum = usb_pipedevice(urb->pipe);
- endpoint = usb_pipeendpoint(urb->pipe);
- maxlen = usb_maxpacket(urb->dev, urb->pipe,
- usb_pipeout(urb->pipe));
-
- slow = usb_pipeslow(urb->pipe);
- interval = urb->interval;
-
- dbg_intr("Intr traffic for dev %d, endpoint %d, maxlen %d, slow %d",
- devnum, endpoint, maxlen, slow);
-
- epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
- if (epid == -1) {
- epid = etrax_usb_allocate_epid();
- if (epid == -1) {
- /* We're out of endpoints, return some error */
- err("We're out of endpoints");
- return -ENOMEM;
- }
- /* Now we have to fill in this ep */
- etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow);
- }
- /* Ok, now we got valid endpoint, lets insert some traffic */
-
- urb_priv = (etrax_urb_priv_t *)kmalloc(sizeof(etrax_urb_priv_t), mem_flags);
- urb_priv->first_sb = 0;
- urb_priv->rx_offset = 0;
- urb_priv->eot = 0;
- INIT_LIST_HEAD(&urb_priv->ep_in_list);
- urb->hcpriv = urb_priv;
-
- /* This is safe since there cannot be any other URB's for this epid */
- URB_List[epid] = urb;
-#if 0
- first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);
-#else
- first_ep = &TxIntrEPList[0];
-#endif
-
- /* Round of the interval to 2^n, it is obvious that this code favours
- smaller numbers, but that is actually a good thing */
- for (i = 0; interval; i++) {
- interval = interval >> 1;
- }
-
- urb->interval = interval = 1 << (i - 1);
-
- dbg_intr("Interval rounded to %d", interval);
-
- tmp_ep = first_ep;
- i = 0;
- do {
- if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) {
- if ((i % interval) == 0) {
- /* Insert the traffic ep after tmp_ep */
- USB_EP_Desc_t *traffic_ep;
- USB_SB_Desc_t *traffic_sb;
-
- traffic_ep = (USB_EP_Desc_t *)
- kmem_cache_alloc(usb_desc_cache, mem_flags);
- traffic_sb = (USB_SB_Desc_t *)
- kmem_cache_alloc(usb_desc_cache, mem_flags);
-
- traffic_ep->hw_len = 0;
- traffic_ep->command = IO_FIELD(USB_EP_command, epid, epid) |
- IO_STATE(USB_EP_command, enable, yes);
- traffic_ep->sub = virt_to_phys(traffic_sb);
-
- if (usb_pipein(urb->pipe)) {
- traffic_sb->sw_len = urb->transfer_buffer_length ?
- (urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
- traffic_sb->next = 0;
- traffic_sb->buf = 0;
- traffic_sb->command = IO_FIELD(USB_SB_command, rem,
- urb->transfer_buffer_length % maxlen) |
- IO_STATE(USB_SB_command, tt, in) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes);
-
- } else if (usb_pipeout(urb->pipe)) {
- traffic_sb->sw_len = urb->transfer_buffer_length;
- traffic_sb->next = 0;
- traffic_sb->buf = virt_to_phys(urb->transfer_buffer);
- traffic_sb->command = IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, out) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes) |
- IO_STATE(USB_SB_command, full, yes);
- }
-
- traffic_ep->nep = tmp_ep->nep;
- tmp_ep->nep = virt_to_phys(traffic_ep);
- dbg_intr("One ep sucessfully inserted");
- }
- i++;
- }
- tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep);
- } while (tmp_ep != first_ep);
-
- set_bit(epid, (void *)&ep_really_active);
-
- *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
-
- DBFEXIT;
-
- return 0;
-}
-
-
-static int handle_intr_transfer_attn(char epid, int status)
-{
- struct urb *old_urb;
-
- DBFENTER;
-
- old_urb = URB_List[epid];
-
- /* if (status == 0 && IN) find data and copy to urb */
- if (status == 0 && usb_pipein(old_urb->pipe)) {
- unsigned long flags;
- etrax_urb_priv_t *urb_priv;
- struct list_head *entry;
- struct in_chunk *in;
-
- urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
-
- save_flags(flags);
- cli();
-
- list_for_each(entry, &urb_priv->ep_in_list) {
- in = list_entry(entry, struct in_chunk, list);
- memcpy(old_urb->transfer_buffer, in->data, in->length);
- old_urb->actual_length = in->length;
- old_urb->status = status;
-
- if (old_urb->complete) {
- old_urb->complete(old_urb);
- }
-
- list_del(entry);
- kfree(in->data);
- kfree(in);
- }
-
- restore_flags(flags);
-
- } else if (status != 0) {
- warn("Some sort of error for INTR EP !!!!");
-#ifdef ETRAX_USB_INTR_ERROR_FATAL
- /* This means that an INTR error is fatal for that endpoint */
- etrax_usb_unlink_intr_urb(old_urb);
- old_urb->status = status;
- if (old_urb->complete) {
- old_urb->complete(old_urb);
- }
-#else
- /* In this case we reenable the disabled endpoint(s) */
- etrax_usb_do_intr_recover(epid);
-#endif
- }
-
- DBFEXIT;
-}
-
-static int etrax_rh_unlink_urb (struct urb *urb)
-{
- etrax_hc_t *hc;
-
- DBFENTER;
-
- hc = urb->dev->bus->hcpriv;
-
- if (hc->rh.urb == urb) {
- hc->rh.send = 0;
- del_timer(&hc->rh.rh_int_timer);
- }
-
- DBFEXIT;
- return 0;
-}
-
-static void etrax_rh_send_irq(struct urb *urb)
-{
- __u16 data = 0;
- etrax_hc_t *hc = urb->dev->bus->hcpriv;
-// static prev_wPortStatus_1 = 0;
-// static prev_wPortStatus_2 = 0;
-
-/* DBFENTER; */
-
-
-/*
- dbg_rh("R_USB_FM_NUMBER : 0x%08X", *R_USB_FM_NUMBER);
- dbg_rh("R_USB_FM_REMAINING: 0x%08X", *R_USB_FM_REMAINING);
-*/
-
- data |= (hc->rh.wPortChange_1) ? (1 << 1) : 0;
- data |= (hc->rh.wPortChange_2) ? (1 << 2) : 0;
-
- *((__u16 *)urb->transfer_buffer) = cpu_to_le16(data);
- urb->actual_length = 1;
- urb->status = 0;
-
-
- if (data && hc->rh.send && urb->complete) {
- dbg_rh("wPortChange_1: 0x%04X", hc->rh.wPortChange_1);
- dbg_rh("wPortChange_2: 0x%04X", hc->rh.wPortChange_2);
-
- urb->complete(urb);
- }
-
-/* DBFEXIT; */
-}
-
-static void etrax_rh_init_int_timer(struct urb *urb)
-{
- etrax_hc_t *hc;
-
-/* DBFENTER; */
-
- hc = urb->dev->bus->hcpriv;
- hc->rh.interval = urb->interval;
- init_timer(&hc->rh.rh_int_timer);
- hc->rh.rh_int_timer.function = etrax_rh_int_timer_do;
- hc->rh.rh_int_timer.data = (unsigned long)urb;
- hc->rh.rh_int_timer.expires = jiffies + ((HZ * hc->rh.interval) / 1000);
- add_timer(&hc->rh.rh_int_timer);
-
-/* DBFEXIT; */
-}
-
-static void etrax_rh_int_timer_do(unsigned long ptr)
-{
- struct urb *urb;
- etrax_hc_t *hc;
-
-/* DBFENTER; */
-
- urb = (struct urb *)ptr;
- hc = urb->dev->bus->hcpriv;
-
- if (hc->rh.send) {
- etrax_rh_send_irq(urb);
- }
-
- etrax_rh_init_int_timer(urb);
-
-/* DBFEXIT; */
-}
-
-static void etrax_usb_setup_epid(char epid, char devnum, char endpoint, char packsize, char slow)
-{
- unsigned long flags;
-
- DBFENTER;
-
- save_flags(flags);
- cli();
-
- if (test_bit(epid, (void *)&ep_usage_bitmask)) {
- restore_flags(flags);
-
- warn("Trying to setup used epid %d", epid);
- DBFEXIT;
- return;
- }
-
- set_bit(epid, (void *)&ep_usage_bitmask);
- dbg_ep("Setting up ep_id %d with devnum %d, endpoint %d and max_len %d",
- epid, devnum, endpoint, packsize);
-
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
- nop();
- *R_USB_EPT_DATA = IO_STATE(R_USB_EPT_DATA, valid, yes) |
- IO_FIELD(R_USB_EPT_DATA, ep, endpoint) |
- IO_FIELD(R_USB_EPT_DATA, dev, devnum) |
- IO_FIELD(R_USB_EPT_DATA, max_len, packsize) |
- IO_FIELD(R_USB_EPT_DATA, low_speed, slow);
-
- restore_flags(flags);
-
- DBFEXIT;
-}
-
-static void etrax_usb_free_epid(char epid)
-{
- unsigned long flags;
-
- DBFENTER;
-
- if (!test_bit(epid, (void *)&ep_usage_bitmask)) {
- warn("Trying to free unused epid %d", epid);
- DBFEXIT;
- return;
- }
-
- save_flags(flags);
- cli();
-
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
- nop();
- while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold))
- printk("+");
- *R_USB_EPT_DATA = 0;
- clear_bit(epid, (void *)&ep_usage_bitmask);
-
- restore_flags(flags);
-
- dbg_ep("epid: %d freed", epid);
-
- DBFEXIT;
-}
-
-
-static int etrax_usb_lookup_epid(unsigned char devnum, char endpoint, char slow, int maxp)
-{
- int i;
- unsigned long flags;
- __u32 data;
-
- DBFENTER;
-
- save_flags(flags);
-
- /* Skip first ep_id since it is reserved when intr. or iso traffic is used */
- for (i = 0; i < NBR_OF_EP_DESC; i++) {
- if (test_bit(i, (void *)&ep_usage_bitmask)) {
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i);
- nop();
- data = *R_USB_EPT_DATA;
- if ((IO_MASK(R_USB_EPT_DATA, valid) & data) &&
- (IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) &&
- (IO_EXTRACT(R_USB_EPT_DATA, ep, data) == endpoint) &&
- (IO_EXTRACT(R_USB_EPT_DATA, low_speed, data) == slow) &&
- (IO_EXTRACT(R_USB_EPT_DATA, max_len, data) == maxp)) {
- restore_flags(flags);
-
- dbg_ep("Found ep_id %d for devnum %d, endpoint %d",
- i, devnum, endpoint);
- DBFEXIT;
- return i;
- }
- }
- }
-
- restore_flags(flags);
-
- dbg_ep("Found no ep_id for devnum %d, endpoint %d",
- devnum, endpoint);
- DBFEXIT;
- return -1;
-}
-
-static int etrax_usb_allocate_epid(void)
-{
- int i;
-
- DBFENTER;
-
- for (i = 0; i < NBR_OF_EP_DESC; i++) {
- if (!test_bit(i, (void *)&ep_usage_bitmask)) {
- dbg_ep("Found free ep_id at %d", i);
- DBFEXIT;
- return i;
- }
- }
-
- dbg_ep("Found no free ep_id's");
- DBFEXIT;
- return -1;
-}
-
-static int etrax_usb_submit_bulk_urb(struct urb *urb, int mem_flags)
-{
- char epid;
- char devnum;
- char endpoint;
- char maxlen;
- char slow;
-
- struct urb *tmp_urb;
-
- etrax_urb_priv_t *urb_priv;
- unsigned long flags;
-
- DBFENTER;
-
- devnum = usb_pipedevice(urb->pipe);
- endpoint = usb_pipeendpoint(urb->pipe);
- maxlen = usb_maxpacket(urb->dev, urb->pipe,
- usb_pipeout(urb->pipe));
- slow = usb_pipeslow(urb->pipe);
-
- epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
- if (epid == -1) {
- epid = etrax_usb_allocate_epid();
- if (epid == -1) {
- /* We're out of endpoints, return some error */
- err("We're out of endpoints");
- return -ENOMEM;
- }
- /* Now we have to fill in this ep */
- etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow);
- }
- /* Ok, now we got valid endpoint, lets insert some traffic */
-
- urb->status = -EINPROGRESS;
-
- save_flags(flags);
- cli();
-
- if (URB_List[epid]) {
- /* Find end of list and add */
- for (tmp_urb = URB_List[epid]; tmp_urb->next; tmp_urb = tmp_urb->next)
- dump_urb(tmp_urb);
-
- tmp_urb->next = urb;
- restore_flags(flags);
- } else {
- /* If this is the first URB, add the URB and do HW add */
- URB_List[epid] = urb;
- restore_flags(flags);
- etrax_usb_do_bulk_hw_add(urb, epid, maxlen, mem_flags);
- }
-
- DBFEXIT;
-
- return 0;
-}
-
-static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags)
-{
- USB_SB_Desc_t *sb_desc_1;
-
- etrax_urb_priv_t *urb_priv;
-
- unsigned long flags;
- __u32 r_usb_ept_data;
-
- DBFENTER;
-
- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), mem_flags);
- sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
-
- if (usb_pipeout(urb->pipe)) {
-
- dbg_bulk("Bulk transfer for epid %d is OUT", epid);
- dbg_bulk("transfer_buffer_length == %d", urb->transfer_buffer_length);
- dbg_bulk("actual_length == %d", urb->actual_length);
-
- if (urb->transfer_buffer_length > 0xffff) {
- panic(__FILE__ __FUNCTION__ ":urb->transfer_buffer_length > 0xffff\n");
- }
-
- sb_desc_1->sw_len = urb->transfer_buffer_length; /* was actual_length */
- sb_desc_1->command = IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, out) |
-
-#if 0
- IO_STATE(USB_SB_command, full, no) |
-#else
- IO_STATE(USB_SB_command, full, yes) |
-#endif
-
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes);
-
- dbg_bulk("transfer_buffer is at 0x%08X", urb->transfer_buffer);
-
- sb_desc_1->buf = virt_to_phys(urb->transfer_buffer);
- sb_desc_1->next = 0;
-
- } else if (usb_pipein(urb->pipe)) {
-
- dbg_bulk("Transfer for epid %d is IN", epid);
- dbg_bulk("transfer_buffer_length = %d", urb->transfer_buffer_length);
- dbg_bulk("rem is calculated to %d", urb->transfer_buffer_length % maxlen);
-
- sb_desc_1->sw_len = urb->transfer_buffer_length ?
- (urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
- dbg_bulk("sw_len got %d", sb_desc_1->sw_len);
- dbg_bulk("transfer_buffer is at 0x%08X", urb->transfer_buffer);
-
- sb_desc_1->command =
- IO_FIELD(USB_SB_command, rem,
- urb->transfer_buffer_length % maxlen) |
- IO_STATE(USB_SB_command, tt, in) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes);
-
- sb_desc_1->buf = 0;
- sb_desc_1->next = 0;
-
- urb_priv->rx_offset = 0;
- urb_priv->eot = 0;
- }
-
- urb_priv->first_sb = sb_desc_1;
-
- urb->hcpriv = (void *)urb_priv;
-
- /* Reset toggle bits and reset error count, remeber to di and ei */
- /* Warning: it is possible that this locking doesn't work with bottom-halves */
-
- save_flags(flags);
- cli();
-
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
- if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
- panic("Hold was set in %s\n", __FUNCTION__);
- }
-
- *R_USB_EPT_DATA &=
- ~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
- IO_MASK(R_USB_EPT_DATA, error_count_out));
-
- if (usb_pipeout(urb->pipe)) {
- char toggle =
- usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
- *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out);
- *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle);
- } else {
- char toggle =
- usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
- *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in);
- *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle);
- }
-
- /* Enable the EP descr. */
-
- set_bit(epid, (void *)&ep_really_active);
-
- TxBulkEPList[epid].sub = virt_to_phys(sb_desc_1);
- TxBulkEPList[epid].hw_len = 0;
- TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-
- restore_flags(flags);
-
- if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) {
- *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
-
- }
-
- DBFEXIT;
-}
-
-static int handle_bulk_transfer_attn(char epid, int status)
-{
- struct urb *old_urb;
- etrax_urb_priv_t *hc_priv;
- unsigned long flags;
-
- DBFENTER;
-
- clear_bit(epid, (void *)&ep_really_active);
-
- old_urb = URB_List[epid];
- URB_List[epid] = old_urb->next;
-
- /* if (status == 0 && IN) find data and copy to urb */
- if (status == 0 && usb_pipein(old_urb->pipe)) {
- etrax_urb_priv_t *urb_priv;
-
- urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
- save_flags(flags);
- cli();
- if (urb_priv->eot == 1) {
- old_urb->actual_length = urb_priv->rx_offset;
- } else {
- if (urb_priv->rx_offset == 0) {
- status = 0;
- } else {
- status = -EPROTO;
- }
-
- old_urb->actual_length = 0;
- err("(BULK) No eot set in IN data!!! rx_offset is: %d", urb_priv->rx_offset);
- }
-
- restore_flags(flags);
- }
-
- save_flags(flags);
- cli();
-
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
- if (usb_pipeout(old_urb->pipe)) {
- char toggle =
- IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA);
- usb_settoggle(old_urb->dev, usb_pipeendpoint(old_urb->pipe),
- usb_pipeout(old_urb->pipe), toggle);
- } else {
- char toggle =
- IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA);
- usb_settoggle(old_urb->dev, usb_pipeendpoint(old_urb->pipe),
- usb_pipeout(old_urb->pipe), toggle);
- }
- restore_flags(flags);
-
- /* If there are any more URB's in the list we'd better start sending */
- if (URB_List[epid]) {
- etrax_usb_do_bulk_hw_add(URB_List[epid], epid,
- usb_maxpacket(URB_List[epid]->dev, URB_List[epid]->pipe,
- usb_pipeout(URB_List[epid]->pipe)),
- GFP_KERNEL);
- }
-#if 1
- else {
- /* This means that this EP is now free, deconfigure it */
- etrax_usb_free_epid(epid);
- }
-#endif
-
- /* Remember to free the SB's */
- hc_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
- cleanup_sb(hc_priv->first_sb);
- kfree(hc_priv);
-
- old_urb->status = status;
- if (old_urb->complete) {
- old_urb->complete(old_urb);
- }
-
- DBFEXIT;
-}
-
-/* ---------------------------------------------------------------------------- */
-
-static int etrax_usb_submit_ctrl_urb(struct urb *urb, int mem_flags)
-{
- char epid;
- char devnum;
- char endpoint;
- char maxlen;
- char slow;
-
- struct urb *tmp_urb;
-
- etrax_urb_priv_t *urb_priv;
- unsigned long flags;
-
- DBFENTER;
-
- devnum = usb_pipedevice(urb->pipe);
- endpoint = usb_pipeendpoint(urb->pipe);
- maxlen = usb_maxpacket(urb->dev, urb->pipe,
- usb_pipeout(urb->pipe));
- slow = usb_pipeslow(urb->pipe);
-
- epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
- if (epid == -1) {
- epid = etrax_usb_allocate_epid();
- if (epid == -1) {
- /* We're out of endpoints, return some error */
- err("We're out of endpoints");
- return -ENOMEM;
- }
- /* Now we have to fill in this ep */
- etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow);
- }
- /* Ok, now we got valid endpoint, lets insert some traffic */
-
- urb->status = -EINPROGRESS;
-
- save_flags(flags);
- cli();
-
- if (URB_List[epid]) {
- /* Find end of list and add */
- for (tmp_urb = URB_List[epid]; tmp_urb->next; tmp_urb = tmp_urb->next)
- dump_urb(tmp_urb);
-
- tmp_urb->next = urb;
- restore_flags(flags);
- } else {
- /* If this is the first URB, add the URB and do HW add */
- URB_List[epid] = urb;
- restore_flags(flags);
- etrax_usb_do_ctrl_hw_add(urb, epid, maxlen, mem_flags);
- }
-
- DBFEXIT;
-
- return 0;
-}
-
-static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen, int mem_flags)
-{
- USB_SB_Desc_t *sb_desc_1;
- USB_SB_Desc_t *sb_desc_2;
- USB_SB_Desc_t *sb_desc_3;
-
- etrax_urb_priv_t *urb_priv;
-
- unsigned long flags;
- __u32 r_usb_ept_data;
-
-
- DBFENTER;
-
- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), mem_flags);
- sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
- sb_desc_2 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
-
- if (!(sb_desc_1 && sb_desc_2)) {
- panic("kmem_cache_alloc in ctrl_hw_add gave NULL pointers !!!\n");
- }
-
- sb_desc_1->sw_len = 8;
- sb_desc_1->command = IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, setup) |
- IO_STATE(USB_SB_command, full, yes) |
- IO_STATE(USB_SB_command, eot, yes);
-
- sb_desc_1->buf = virt_to_phys(urb->setup_packet);
- sb_desc_1->next = virt_to_phys(sb_desc_2);
- dump_sb_desc(sb_desc_1);
-
- if (usb_pipeout(urb->pipe)) {
- dbg_ctrl("Transfer for epid %d is OUT", epid);
-
- /* If this Control OUT transfer has an optional data stage we add an OUT token
- before the mandatory IN (status) token, hence the reordered SB list */
-
- if (urb->transfer_buffer) {
- dbg_ctrl("This OUT transfer has an extra data stage");
- sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
-
- sb_desc_1->next = virt_to_phys(sb_desc_3);
-
- sb_desc_3->sw_len = urb->transfer_buffer_length;
- sb_desc_3->command = IO_STATE(USB_SB_command, tt, out) |
- IO_STATE(USB_SB_command, full, yes) |
- IO_STATE(USB_SB_command, eot, yes);
- sb_desc_3->buf = virt_to_phys(urb->transfer_buffer);
- sb_desc_3->next = virt_to_phys(sb_desc_2);
- }
-
- sb_desc_2->sw_len = 1;
- sb_desc_2->command = IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, in) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes);
-
- sb_desc_2->buf = 0;
- sb_desc_2->next = 0;
- dump_sb_desc(sb_desc_2);
-
- } else if (usb_pipein(urb->pipe)) {
-
- dbg_ctrl("Transfer for epid %d is IN", epid);
- dbg_ctrl("transfer_buffer_length = %d", urb->transfer_buffer_length);
- dbg_ctrl("rem is calculated to %d", urb->transfer_buffer_length % maxlen);
-
- sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, mem_flags);
-
- sb_desc_2->sw_len = urb->transfer_buffer_length ?
- (urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
- dbg_ctrl("sw_len got %d", sb_desc_2->sw_len);
-
- sb_desc_2->command =
- IO_FIELD(USB_SB_command, rem,
- urb->transfer_buffer_length % maxlen) |
- IO_STATE(USB_SB_command, tt, in) |
- IO_STATE(USB_SB_command, eot, yes);
-
- sb_desc_2->buf = 0;
- sb_desc_2->next = virt_to_phys(sb_desc_3);
- dump_sb_desc(sb_desc_2);
-
- sb_desc_3->sw_len = 1;
- sb_desc_3->command = IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, zout) |
- IO_STATE(USB_SB_command, full, yes) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes);
-
- sb_desc_3->buf = 0;
- sb_desc_3->next = 0;
- dump_sb_desc(sb_desc_3);
-
- urb_priv->rx_offset = 0;
- urb_priv->eot = 0;
- }
-
- urb_priv->first_sb = sb_desc_1;
-
- urb->hcpriv = (void *)urb_priv;
-
- /* Reset toggle bits and reset error count, remeber to di and ei */
- /* Warning: it is possible that this locking doesn't work with bottom-halves */
-
- save_flags(flags);
- cli();
-
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
- if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
- panic("Hold was set in %s\n", __FUNCTION__);
- }
-
-
- *R_USB_EPT_DATA &=
- ~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
- IO_MASK(R_USB_EPT_DATA, error_count_out) |
- IO_MASK(R_USB_EPT_DATA, t_in) |
- IO_MASK(R_USB_EPT_DATA, t_out));
-
- /* Enable the EP descr. */
-
- set_bit(epid, (void *)&ep_really_active);
-
- TxCtrlEPList[epid].sub = virt_to_phys(sb_desc_1);
- TxCtrlEPList[epid].hw_len = 0;
- TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
-
- restore_flags(flags);
-
- dump_ep_desc(&TxCtrlEPList[epid]);
-
- if (!(*R_DMA_CH8_SUB1_CMD & IO_MASK(R_DMA_CH8_SUB1_CMD, cmd))) {
- *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
-
- }
-
- DBFEXIT;
-}
-
-static int etrax_usb_submit_urb(struct urb *urb, int mem_flags)
-{
- etrax_hc_t *hc;
- int rval = -EINVAL;
-
- DBFENTER;
-
- dump_urb(urb);
- submit_urb_count++;
-
- hc = (etrax_hc_t*) urb->dev->bus->hcpriv;
-
- if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
- /* This request if for the Virtual Root Hub */
- rval = etrax_rh_submit_urb(urb);
-
- } else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
- rval = etrax_usb_submit_ctrl_urb(urb, mem_flags);
-
- } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
- rval = etrax_usb_submit_bulk_urb(urb, mem_flags);
-
- } else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
- int bustime;
-
- if (urb->bandwidth == 0) {
- bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0) {
- rval = bustime;
- } else {
- usb_claim_bandwidth(urb->dev, urb, bustime, 0);
- rval = etrax_usb_submit_intr_urb(urb, mem_flags);
- }
-
- }
- } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
- warn("Isochronous traffic is not supported !!!");
- rval = -EINVAL;
- }
-
- DBFEXIT;
-
- return rval;
-}
-
-static int etrax_usb_unlink_urb(struct urb *urb)
-{
- etrax_hc_t *hc = urb->dev->bus->hcpriv;
- int epid;
- int pos;
- int devnum, endpoint, slow, maxlen;
- etrax_urb_priv_t *hc_priv;
- unsigned long flags;
-
- DBFENTER;
- dump_urb(urb);
- devnum = usb_pipedevice(urb->pipe);
- endpoint = usb_pipeendpoint(urb->pipe);
- slow = usb_pipeslow(urb->pipe);
- maxlen = usb_maxpacket(urb->dev, urb->pipe,
- usb_pipeout(urb->pipe));
-
- epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
-
- if (epid == -1)
- return 0;
-
-
- if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
- int ret;
- ret = etrax_rh_unlink_urb(urb);
- DBFEXIT;
- return ret;
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
- int ret;
- ret = etrax_usb_unlink_intr_urb(urb);
- urb->status = -ENOENT;
- if (urb->complete) {
- urb->complete(urb);
- }
- DBFEXIT;
- return ret;
- }
-
- info("Unlink of BULK or CTRL");
-
- save_flags(flags);
- cli();
-
- for (epid = 0; epid < 32; epid++) {
- struct urb *u = URB_List[epid];
- pos = 0;
-
- for (; u; u = u->next) {
- pos++;
- if (u == urb) {
- info("Found urb at epid %d, pos %d", epid, pos);
-
- if (pos == 1) {
- if (usb_pipetype(u->pipe) == PIPE_CONTROL) {
- if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
- /* The EP was enabled, disable it and wait */
- TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
- while (*R_DMA_CH8_SUB1_EP == virt_to_phys(&TxCtrlEPList[epid]));
- }
-
- } else if (usb_pipetype(u->pipe) == PIPE_BULK) {
- if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
- TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
- while (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[epid]));
- }
- }
-
- URB_List[epid] = u->next;
-
- } else {
- struct urb *up;
- for (up = URB_List[epid]; up->next != u; up = up->next);
- up->next = u->next;
- }
- u->status = -ENOENT;
- if (u->complete) {
- u->complete(u);
- }
-
- hc_priv = (etrax_urb_priv_t *)u->hcpriv;
- cleanup_sb(hc_priv->first_sb);
- kfree(hc_priv);
- }
- }
- }
-
- restore_flags(flags);
-
- DBFEXIT;
- return 0;
-}
-
-static int etrax_usb_get_frame_number(struct usb_device *usb_dev)
-{
- DBFENTER;
- DBFEXIT;
- return (*R_USB_FM_NUMBER);
-}
-
-static int etrax_usb_allocate_dev(struct usb_device *usb_dev)
-{
- DBFENTER;
- DBFEXIT;
- return 0;
-}
-
-static int etrax_usb_deallocate_dev(struct usb_device *usb_dev)
-{
- DBFENTER;
- DBFEXIT;
- return 0;
-}
-
-static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs)
-{
- etrax_hc_t *hc = (etrax_hc_t *)vhc;
- int epid;
- char eol;
- struct urb *urb;
- USB_EP_Desc_t *tmp_ep;
- USB_SB_Desc_t *tmp_sb;
-
- DBFENTER;
-
- if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) {
- info("dma8_sub0_descr (BULK) intr.");
- *R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do);
- }
- if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) {
- info("dma8_sub1_descr (CTRL) intr.");
- *R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do);
- }
- if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) {
- info("dma8_sub2_descr (INT) intr.");
- *R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do);
- }
- if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) {
- info("dma8_sub3_descr (ISO) intr.");
- *R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);
- }
-
- DBFEXIT;
-}
-
-static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs)
-{
- int epid = 0;
- struct urb *urb;
- etrax_urb_priv_t *urb_priv;
-
- *R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);
-
- while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) {
- if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {
-
- goto skip_out;
- }
-
- if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) {
-
- goto skip_out;
- }
-
- epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status);
-
- urb = URB_List[epid];
-
- if (urb && usb_pipein(urb->pipe)) {
- urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
-
- if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
- struct in_chunk *in;
- dbg_intr("Packet for epid %d in rx buffers", epid);
- in = kmalloc(sizeof(struct in_chunk), GFP_ATOMIC);
- in->length = myNextRxDesc->hw_len;
- in->data = kmalloc(in->length, GFP_ATOMIC);
- memcpy(in->data, phys_to_virt(myNextRxDesc->buf), in->length);
- list_add_tail(&in->list, &urb_priv->ep_in_list);
-#ifndef ETRAX_USB_INTR_IRQ
- etrax_usb_hc_intr_top_half(irq, vhc, regs);
-#endif
-
- } else {
- if ((urb_priv->rx_offset + myNextRxDesc->hw_len) >
- urb->transfer_buffer_length) {
- err("Packet (epid: %d) in RX buffer was bigger "
- "than the URB has room for !!!", epid);
- goto skip_out;
- }
-
- memcpy(urb->transfer_buffer + urb_priv->rx_offset,
- phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len);
-
- urb_priv->rx_offset += myNextRxDesc->hw_len;
- }
-
- if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) {
- urb_priv->eot = 1;
- }
-
- } else {
- err("This is almost fatal, inpacket for epid %d which does not exist "
- " or is out !!!\nURB was at 0x%08X", epid, urb);
-
- goto skip_out;
- }
-
- skip_out:
- myPrevRxDesc = myNextRxDesc;
- myPrevRxDesc->command |= IO_MASK(USB_IN_command, eol);
- myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol);
- myLastRxDesc = myPrevRxDesc;
-
- myNextRxDesc->status = 0;
- myNextRxDesc = phys_to_virt(myNextRxDesc->next);
- }
-}
-
-
-
-static void cleanup_sb(USB_SB_Desc_t *sb)
-{
- USB_SB_Desc_t *next_sb;
-
- DBFENTER;
-
- if (sb == NULL) {
- err("cleanup_sb was given a NULL pointer");
- return;
- }
-
- while (!(sb->command & IO_MASK(USB_SB_command, eol))) {
- next_sb = (USB_SB_Desc_t *)phys_to_virt(sb->next);
- kmem_cache_free(usb_desc_cache, sb);
- sb = next_sb;
- }
-
- kmem_cache_free(usb_desc_cache, sb);
-
- DBFEXIT;
-
-}
-
-static int handle_control_transfer_attn(char epid, int status)
-{
- struct urb *old_urb;
- etrax_urb_priv_t *hc_priv;
-
- DBFENTER;
-
- clear_bit(epid, (void *)&ep_really_active);
-
- old_urb = URB_List[epid];
- URB_List[epid] = old_urb->next;
-
- /* if (status == 0 && IN) find data and copy to urb */
- if (status == 0 && usb_pipein(old_urb->pipe)) {
- unsigned long flags;
- etrax_urb_priv_t *urb_priv;
-
- urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
- save_flags(flags);
- cli();
- if (urb_priv->eot == 1) {
- old_urb->actual_length = urb_priv->rx_offset;
- dbg_ctrl("urb_priv->rx_offset: %d in handle_control_attn", urb_priv->rx_offset);
- } else {
- status = -EPROTO;
- old_urb->actual_length = 0;
- err("(CTRL) No eot set in IN data!!! rx_offset: %d", urb_priv->rx_offset);
- }
-
- restore_flags(flags);
- }
-
- /* If there are any more URB's in the list we'd better start sending */
- if (URB_List[epid]) {
- etrax_usb_do_ctrl_hw_add(URB_List[epid], epid,
- usb_maxpacket(URB_List[epid]->dev, URB_List[epid]->pipe,
- usb_pipeout(URB_List[epid]->pipe)),
- GFP_KERNEL);
- }
-#if 1
- else {
- /* This means that this EP is now free, deconfigure it */
- etrax_usb_free_epid(epid);
- }
-#endif
-
- /* Remember to free the SB's */
- hc_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
- cleanup_sb(hc_priv->first_sb);
- kfree(hc_priv);
-
- old_urb->status = status;
- if (old_urb->complete) {
- old_urb->complete(old_urb);
- }
-
- DBFEXIT;
-}
-
-
-
-static void etrax_usb_hc_intr_bottom_half(void *data)
-{
- struct usb_reg_context *reg = (struct usb_reg_context *)data;
- struct urb *old_urb;
-
- int error_code;
- int epid;
-
- __u32 r_usb_ept_data;
-
- etrax_hc_t *hc = reg->hc;
- __u16 r_usb_rh_port_status_1;
- __u16 r_usb_rh_port_status_2;
-
- DBFENTER;
-
- if (reg->r_usb_irq_mask_read & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) {
-
- /*
- The Etrax RH does not include a wPortChange register, so this has
- to be handled in software. See section 11.16.2.6.2 in USB 1.1 spec
- for details.
- */
-
- r_usb_rh_port_status_1 = reg->r_usb_rh_port_status_1;
- r_usb_rh_port_status_2 = reg->r_usb_rh_port_status_2;
-
- dbg_rh("port_status pending");
- dbg_rh("r_usb_rh_port_status_1: 0x%04X", r_usb_rh_port_status_1);
- dbg_rh("r_usb_rh_port_status_2: 0x%04X", r_usb_rh_port_status_2);
-
- /* C_PORT_CONNECTION is set on any transition */
- hc->rh.wPortChange_1 |=
- ((r_usb_rh_port_status_1 & (1 << RH_PORT_CONNECTION)) !=
- (hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_CONNECTION))) ?
- (1 << RH_PORT_CONNECTION) : 0;
-
- hc->rh.wPortChange_2 |=
- ((r_usb_rh_port_status_2 & (1 << RH_PORT_CONNECTION)) !=
- (hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_CONNECTION))) ?
- (1 << RH_PORT_CONNECTION) : 0;
-
- /* C_PORT_ENABLE is _only_ set on a one to zero transition */
- hc->rh.wPortChange_1 |=
- ((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_ENABLE))
- && !(r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ?
- (1 << RH_PORT_ENABLE) : 0;
-
- hc->rh.wPortChange_2 |=
- ((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_ENABLE))
- && !(r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ?
- (1 << RH_PORT_ENABLE) : 0;
-
- /* C_PORT_SUSPEND seems difficult, lets ignore it.. (for now) */
-
- /* C_PORT_RESET is _only_ set on a transition from the resetting state
- to the enabled state */
- hc->rh.wPortChange_1 |=
- ((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_RESET))
- && (r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ?
- (1 << RH_PORT_RESET) : 0;
-
- hc->rh.wPortChange_2 |=
- ((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_RESET))
- && (r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ?
- (1 << RH_PORT_RESET) : 0;
-
- hc->rh.prev_wPortStatus_1 = r_usb_rh_port_status_1;
- hc->rh.prev_wPortStatus_2 = r_usb_rh_port_status_2;
- }
-
- for (epid = 0; epid < 32; epid++) {
-
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
- r_usb_ept_data = *R_USB_EPT_DATA;
-
- restore_flags(flags);
-
- if (r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, hold)) {
- warn("Was hold for epid %d", epid);
- continue;
- }
-
- if (!(r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, valid))) {
- continue;
- }
-
-
- if (test_bit(epid, (void *)&reg->r_usb_epid_attn)) {
-
- if (URB_List[epid] == NULL) {
- err("R_USB_EPT_DATA is 0x%08X", r_usb_ept_data);
- err("submit urb has been called %d times..", submit_urb_count);
- err("EPID_ATTN for epid %d, with NULL entry in list", epid);
- return;
- }
-
- dbg_ep("r_usb_ept_data [%d] == 0x%08X", epid,
- r_usb_ept_data);
-
- error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code,
- r_usb_ept_data);
-
- if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
- /* no_error means that this urb was sucessfully sent or that we have
- some undefinde error*/
-
- if (IO_EXTRACT(R_USB_EPT_DATA, error_count_out, r_usb_ept_data) == 3 ||
- IO_EXTRACT(R_USB_EPT_DATA, error_count_in, r_usb_ept_data) == 3) {
- /* Actually there were transmission errors */
- warn("Undefined error for endpoint %d", epid);
- if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
- handle_control_transfer_attn(epid, -EPROTO);
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
- handle_bulk_transfer_attn(epid, -EPROTO);
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
- handle_intr_transfer_attn(epid, -EPROTO);
- }
-
- } else {
-
- if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
- if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
- etrax_usb_do_intr_recover(epid);
- } else {
- panic("Epid attention for epid %d (none INTR), with no errors and no "
- "exessive retry r_usb_status is 0x%02X\n",
- epid, reg->r_usb_status);
- }
-
- } else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
- panic("Epid attention for epid %d, with no errors and no "
- "exessive retry r_usb_status is 0x%02X\n",
- epid, reg->r_usb_status);
-
- }
-
- warn("Epid attention for epid %d, with no errors and no "
- "exessive retry r_usb_status is 0x%02X",
- epid, reg->r_usb_status);
- warn("OUT error count: %d", IO_EXTRACT(R_USB_EPT_DATA, error_count_out,
- r_usb_ept_data));
- warn("IN error count: %d", IO_EXTRACT(R_USB_EPT_DATA, error_count_in,
- r_usb_ept_data));
-
-
- }
-
- } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, stall)) {
- warn("Stall for endpoint %d", epid);
- if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
- handle_control_transfer_attn(epid, -EPIPE);
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
- handle_bulk_transfer_attn(epid, -EPIPE);
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
- handle_intr_transfer_attn(epid, -EPIPE);
- }
-
-
- } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, bus_error)) {
- panic("USB bus error for endpoint %d\n", epid);
-
- } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, buffer_error)) {
- warn("Buffer error for endpoint %d", epid);
-
- if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
- handle_control_transfer_attn(epid, -EPROTO);
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
- handle_bulk_transfer_attn(epid, -EPROTO);
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
- handle_intr_transfer_attn(epid, -EPROTO);
- }
-
- }
- } else if (test_bit(epid, (void *)&ep_really_active)) {
- /* Should really be else if (testbit(really active)) */
-
- if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
-
- if (!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable))) {
- /* Now we have to verify that this CTRL endpoint got disabled
- cause it reached end of list with no error */
-
- if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==
- IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
- /*
- This means that the endpoint has no error, is disabled
- and had inserted traffic,
- i.e. transfer sucessfully completed
- */
- dbg_ctrl("Last SB for CTRL %d sent sucessfully", epid);
- handle_control_transfer_attn(epid, 0);
- }
- }
-
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
- if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable))) {
- /* Now we have to verify that this BULK endpoint go disabled
- cause it reached end of list with no error */
-
- if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==
- IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
- /*
- This means that the endpoint has no error, is disabled
- and had inserted traffic,
- i.e. transfer sucessfully completed
- */
- dbg_bulk("Last SB for BULK %d sent sucessfully", epid);
- handle_bulk_transfer_attn(epid, 0);
- }
- }
- } else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
- handle_intr_transfer_attn(epid, 0);
- }
- }
-
- }
-
- kfree(reg);
-
- DBFEXIT;
-}
-
-
-static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs)
-{
- struct usb_reg_context *reg;
-
- DBFENTER;
-
- reg = (struct usb_reg_context *)kmalloc(sizeof(struct usb_reg_context), GFP_ATOMIC);
-
- if (!(reg)) {
- panic("kmalloc failed in top_half\n");
- }
-
- reg->hc = (etrax_hc_t *)vhc;
- reg->r_usb_irq_mask_read = *R_USB_IRQ_MASK_READ;
- reg->r_usb_status = *R_USB_STATUS;
-
-#if 0
- if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
- panic("r_usb_status said perror\n");
- }
- if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
- panic("r_usb_status said ourun !!!\n");
- }
-#endif
-
- reg->r_usb_epid_attn = *R_USB_EPID_ATTN;
-
- reg->r_usb_rh_port_status_1 = *R_USB_RH_PORT_STATUS_1;
- reg->r_usb_rh_port_status_2 = *R_USB_RH_PORT_STATUS_2;
-
- reg->usb_bh.sync = 0;
- reg->usb_bh.routine = etrax_usb_hc_intr_bottom_half;
- reg->usb_bh.data = reg;
-
- queue_task(&reg->usb_bh, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
- DBFEXIT;
-}
-
-static int etrax_rh_submit_urb(struct urb *urb)
-{
- struct usb_device *usb_dev = urb->dev;
- etrax_hc_t *hc = usb_dev->bus->hcpriv;
- unsigned int pipe = urb->pipe;
- struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
- void *data = urb->transfer_buffer;
- int leni = urb->transfer_buffer_length;
- int len = 0;
- int status = 0;
- int stat = 0;
- int i;
-
- __u16 cstatus;
-
- __u16 bmRType_bReq;
- __u16 wValue;
- __u16 wIndex;
- __u16 wLength;
-
- DBFENTER;
-
- if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
- dbg_rh("Root-Hub submit IRQ: every %d ms", urb->interval);
- hc->rh.urb = urb;
- hc->rh.send = 1;
- hc->rh.interval = urb->interval;
- etrax_rh_init_int_timer(urb);
- DBFEXIT;
-
- return 0;
- }
-
- bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
- wValue = le16_to_cpu(cmd->wValue);
- wIndex = le16_to_cpu(cmd->wIndex);
- wLength = le16_to_cpu(cmd->wLength);
-
- dbg_rh("bmRType_bReq : 0x%04X (%d)", bmRType_bReq, bmRType_bReq);
- dbg_rh("wValue : 0x%04X (%d)", wValue, wValue);
- dbg_rh("wIndex : 0x%04X (%d)", wIndex, wIndex);
- dbg_rh("wLength : 0x%04X (%d)", wLength, wLength);
-
- switch (bmRType_bReq) {
-
- /* Request Destination:
- without flags: Device,
- RH_INTERFACE: interface,
- RH_ENDPOINT: endpoint,
- RH_CLASS means HUB here,
- RH_OTHER | RH_CLASS almost ever means HUB_PORT here
- */
-
- case RH_GET_STATUS:
- *(__u16 *) data = cpu_to_le16 (1);
- OK (2);
-
- case RH_GET_STATUS | RH_INTERFACE:
- *(__u16 *) data = cpu_to_le16 (0);
- OK (2);
-
- case RH_GET_STATUS | RH_ENDPOINT:
- *(__u16 *) data = cpu_to_le16 (0);
- OK (2);
-
- case RH_GET_STATUS | RH_CLASS:
- *(__u32 *) data = cpu_to_le32 (0);
- OK (4); /* hub power ** */
-
- case RH_GET_STATUS | RH_OTHER | RH_CLASS:
- if (wIndex == 1) {
- *((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_1);
- *((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_1);
- }
- else if (wIndex == 2) {
- *((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_2);
- *((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_2);
- }
- else {
- dbg_rh("RH_GET_STATUS whith invalid wIndex !!");
- OK(0);
- }
-
- OK(4);
-
- case RH_CLEAR_FEATURE | RH_ENDPOINT:
- switch (wValue) {
- case (RH_ENDPOINT_STALL):
- OK (0);
- }
- break;
-
- case RH_CLEAR_FEATURE | RH_CLASS:
- switch (wValue) {
- case (RH_C_HUB_OVER_CURRENT):
- OK (0); /* hub power over current ** */
- }
- break;
-
- case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
- switch (wValue) {
- case (RH_PORT_ENABLE):
- if (wIndex == 1) {
-
- dbg_rh("trying to do disable of port 1");
-
- *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, yes);
- while (hc->rh.prev_wPortStatus_1 &
- IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes));
- *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);
- dbg_rh("Port 1 is disabled");
-
- } else if (wIndex == 2) {
-
- dbg_rh("trying to do disable of port 2");
-
- *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, yes);
- while (hc->rh.prev_wPortStatus_2 &
- IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, yes));
- *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);
- dbg_rh("Port 2 is disabled");
-
- } else {
- dbg_rh("RH_CLEAR_FEATURE->RH_PORT_ENABLE "
- "with invalid wIndex == %d!!", wIndex);
- }
-
- OK (0);
- case (RH_PORT_SUSPEND):
- /* Opposite to suspend should be resume, so well do a resume */
- if (wIndex == 1) {
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, port_sel, port1) |
- IO_STATE(R_USB_COMMAND, port_cmd, resume)|
- IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
- } else if (wIndex == 2) {
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, port_sel, port2) |
- IO_STATE(R_USB_COMMAND, port_cmd, resume)|
- IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
- } else {
- dbg_rh("RH_CLEAR_FEATURE->RH_PORT_SUSPEND "
- "with invalid wIndex == %d!!", wIndex);
- }
-
- OK (0);
- case (RH_PORT_POWER):
- OK (0); /* port power ** */
- case (RH_C_PORT_CONNECTION):
-
- if (wIndex == 1) {
- hc->rh.wPortChange_1 &= ~(1 << RH_PORT_CONNECTION);
- }
- else if (wIndex == 2) {
- hc->rh.wPortChange_2 &= ~(1 << RH_PORT_CONNECTION);
- }
- else {
- dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_CONNECTION "
- "with invalid wIndex == %d!!", wIndex);
- }
-
- OK (0);
- case (RH_C_PORT_ENABLE):
- if (wIndex == 1) {
- hc->rh.wPortChange_1 &= ~(1 << RH_PORT_ENABLE);
- }
- else if (wIndex == 2) {
- hc->rh.wPortChange_2 &= ~(1 << RH_PORT_ENABLE);
- }
- else {
- dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_ENABLE "
- "with invalid wIndex == %d!!", wIndex);
- }
- OK (0);
- case (RH_C_PORT_SUSPEND):
-/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
- OK (0);
- case (RH_C_PORT_OVER_CURRENT):
- OK (0); /* port power over current ** */
- case (RH_C_PORT_RESET):
- if (wIndex == 1) {
- hc->rh.wPortChange_1 &= ~(1 << RH_PORT_RESET);
- }
- else if (wIndex == 2) {
- dbg_rh("This is wPortChange before clear: 0x%04X", hc->rh.wPortChange_2);
-
- hc->rh.wPortChange_2 &= ~(1 << RH_PORT_RESET);
- dbg_rh("This is wPortChange after clear: 0x%04X", hc->rh.wPortChange_2);
- } else {
- dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_RESET "
- "with invalid index == %d!!", wIndex);
- }
-
- OK (0);
-
- }
- break;
-
- case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
- switch (wValue) {
- case (RH_PORT_SUSPEND):
- if (wIndex == 1) {
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, port_sel, port1) |
- IO_STATE(R_USB_COMMAND, port_cmd, suspend) |
- IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
- } else if (wIndex == 2) {
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, port_sel, port2) |
- IO_STATE(R_USB_COMMAND, port_cmd, suspend) |
- IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
- } else {
- dbg_rh("RH_SET_FEATURE->RH_C_PORT_SUSPEND "
- "with invalid wIndex == %d!!", wIndex);
- }
-
- OK (0);
- case (RH_PORT_RESET):
- if (wIndex == 1) {
- int port1_retry;
-
- port1_redo:
- dbg_rh("Doing reset of port 1");
-
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, port_cmd, reset) |
- IO_STATE(R_USB_COMMAND, port_sel, port1);
-
- /* We must once again wait at least 10ms for the device to recover */
-
- port1_retry = 0;
- while (!((*((volatile __u16 *)&hc->rh.prev_wPortStatus_1)) &
- IO_STATE(R_USB_RH_PORT_STATUS_1,
- enabled, yes))) {
- printk(""); if (port1_retry++ >= 10000) {goto port1_redo;}
- }
-
- /* This only seems to work if we use printk,
- not even schedule() works !!! WHY ?? */
-
- udelay(15000);
- }
- else if (wIndex == 2) {
- int port2_retry;
-
- port2_redo:
- dbg_rh("Doing reset of port 2");
-
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, port_cmd, reset) |
- IO_STATE(R_USB_COMMAND, port_sel, port2);
-
- /* We must once again wait at least 10ms for the device to recover */
-
- port2_retry = 0;
- while (!((*((volatile __u16 *)&hc->rh.prev_wPortStatus_2)) &
- IO_STATE(R_USB_RH_PORT_STATUS_2,
- enabled, yes))) {
- printk(""); if (port2_retry++ >= 10000) {goto port2_redo;}
- }
-
- /* This only seems to work if we use printk,
- not even schedule() works !!! WHY ?? */
-
- udelay(15000);
- }
-
- /* Try to bring the HC into running state */
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
-
- nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
- dbg_rh("...Done");
- OK(0);
-
- case (RH_PORT_POWER):
- OK (0); /* port power ** */
- case (RH_PORT_ENABLE):
- /* There is no rh port enable command in the Etrax USB interface!!!! */
- OK (0);
-
- }
- break;
-
- case RH_SET_ADDRESS:
- hc->rh.devnum = wValue;
- dbg_rh("RH address set to: %d", hc->rh.devnum);
- OK (0);
-
- case RH_GET_DESCRIPTOR:
- switch ((wValue & 0xff00) >> 8) {
- case (0x01): /* device descriptor */
- len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_dev_des), wLength));
- memcpy (data, root_hub_dev_des, len);
- OK (len);
- case (0x02): /* configuration descriptor */
- len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_config_des), wLength));
- memcpy (data, root_hub_config_des, len);
- OK (len);
- case (0x03): /* string descriptors */
- len = usb_root_hub_string (wValue & 0xff,
- 0xff, "ETRAX 100LX",
- data, wLength);
- if (len > 0) {
- OK(min_t(int, leni, len));
- } else
- stat = -EPIPE;
- }
- break;
-
- case RH_GET_DESCRIPTOR | RH_CLASS:
- root_hub_hub_des[2] = hc->rh.numports;
- len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_hub_des), wLength));
- memcpy (data, root_hub_hub_des, len);
- OK (len);
-
- case RH_GET_CONFIGURATION:
- *(__u8 *) data = 0x01;
- OK (1);
-
- case RH_SET_CONFIGURATION:
- OK (0);
-
- default:
- stat = -EPIPE;
- }
-
- urb->actual_length = len;
- urb->status = stat;
- urb->dev=NULL;
- if (urb->complete) {
- urb->complete (urb);
- }
- DBFEXIT;
-
- return 0;
-}
-
-static int __init etrax_usb_hc_init(void)
-{
- static etrax_hc_t *hc;
- struct usb_bus *bus;
- struct usb_device *usb_rh;
-
- DBFENTER;
-
- info("ETRAX 100LX USB-HCD %s (c) 2001 Axis Communications AB\n", usb_hcd_version);
-
- hc = kmalloc(sizeof(etrax_hc_t), GFP_KERNEL);
-
- /* We use kmem_cache_* to make sure that all DMA desc. are dword aligned */
- usb_desc_cache = kmem_cache_create("usb_desc_cache", sizeof(USB_EP_Desc_t), 0, 0, 0, 0);
- if (!usb_desc_cache) {
- panic("USB Desc Cache allocation failed !!!\n");
- }
-
- etrax_usb_bus = bus = usb_alloc_bus(&etrax_usb_device_operations);
- hc->bus = bus;
- bus->hcpriv = hc;
-
- /* Initalize RH to the default address.
- And make sure that we have no status change indication */
- hc->rh.numports = 2; /* The RH has two ports */
- hc->rh.devnum = 0;
- hc->rh.wPortChange_1 = 0;
- hc->rh.wPortChange_2 = 0;
-
- /* Also initate the previous values to zero */
- hc->rh.prev_wPortStatus_1 = 0;
- hc->rh.prev_wPortStatus_2 = 0;
-
- /* Initialize the intr-traffic flags */
- hc->intr.sleeping = 0;
- hc->intr.wq = NULL;
-
- /* Initially all ep's are free except ep 0 */
- ep_usage_bitmask = 0;
- set_bit(0, (void *)&ep_usage_bitmask);
- ep_really_active = 0;
-
- memset(URB_List, 0, sizeof(URB_List));
-
- /* This code should really be moved */
-
- if (request_dma(USB_TX_DMA_NBR, "ETRAX 100LX built-in USB (Tx)")) {
- err("Could not allocate DMA ch 8 for USB");
- etrax_usb_hc_cleanup();
- DBFEXIT;
- return -1;
- }
-
- if (request_dma(USB_RX_DMA_NBR, "ETRAX 100LX built-in USB (Rx)")) {
- err("Could not allocate DMA ch 9 for USB");
- etrax_usb_hc_cleanup();
- DBFEXIT;
- return -1;
- }
-#if 0 /* Moved to head.S */
- *R_GEN_CONFIG = genconfig_shadow =
- (genconfig_shadow & ~(IO_MASK(R_GEN_CONFIG, usb1) |
- IO_MASK(R_GEN_CONFIG, usb2) |
- IO_MASK(R_GEN_CONFIG, dma8) |
- IO_MASK(R_GEN_CONFIG, dma9))) |
- IO_STATE(R_GEN_CONFIG, dma8, usb) |
- IO_STATE(R_GEN_CONFIG, dma9, usb)
-#ifdef CONFIG_ETRAX_USB_HOST_PORT1
- | IO_STATE(R_GEN_CONFIG, usb1, select)
-#endif
-#ifdef CONFIG_ETRAX_USB_HOST_PORT2
- | IO_STATE(R_GEN_CONFIG, usb2, select)
-#endif
- ;
-#endif
-
- usb_register_bus(hc->bus);
-
- /* We may have to set more bits, but these are the obvious ones */
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma8_sub0_descr, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma8_sub1_descr, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma8_sub2_descr, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma8_sub3_descr, set);
-
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);
-
- *R_USB_IRQ_MASK_SET =
- IO_STATE(R_USB_IRQ_MASK_SET, ctl_status, set) |
- IO_STATE(R_USB_IRQ_MASK_SET, ctl_eot, set) |
- IO_STATE(R_USB_IRQ_MASK_SET, bulk_eot, set) |
-#ifdef ETRAX_USB_INTR_IRQ
- IO_STATE(R_USB_IRQ_MASK_SET, intr_eot, set) |
-#endif
- IO_STATE(R_USB_IRQ_MASK_SET, epid_attn, set) |
- IO_STATE(R_USB_IRQ_MASK_SET, port_status, set);
-
- if (request_irq(ETRAX_USB_HC_IRQ, etrax_usb_hc_intr_top_half, 0,
- "ETRAX 100LX built-in USB (HC)", hc)) {
- err("Could not allocate IRQ %d for USB", ETRAX_USB_HC_IRQ);
- etrax_usb_hc_cleanup();
- DBFEXIT;
- return -1;
- }
-
- if (request_irq(ETRAX_USB_RX_IRQ, etrax_usb_rx_interrupt, 0,
- "ETRAX 100LX built-in USB (Rx)", hc)) {
- err("Could not allocate IRQ %d for USB", ETRAX_USB_RX_IRQ);
- etrax_usb_hc_cleanup();
- DBFEXIT;
- return -1;
- }
-
- if (request_irq(ETRAX_USB_TX_IRQ, etrax_usb_tx_interrupt, 0,
- "ETRAX 100LX built-in USB (Tx)", hc)) {
- err("Could not allocate IRQ %d for USB", ETRAX_USB_TX_IRQ);
- etrax_usb_hc_cleanup();
- DBFEXIT;
- return -1;
- }
-
- /* Reset the USB interface (configures as HC) */
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, ctrl_cmd, reset) |
- IO_STATE(R_USB_COMMAND, port_cmd, reset);
-
- nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-#if 1
- /* Initate PSTART to all unallocatable bit times */
- *R_USB_FM_PSTART = IO_FIELD(R_USB_FM_PSTART, value, 10000);
-#endif
-
-#ifdef CONFIG_ETRAX_USB_HOST_PORT1
- *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);
-#endif
-
-#ifdef CONFIG_ETRAX_USB_HOST_PORT2
- *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);
-#endif
-
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, ctrl_cmd, host_config) |
- IO_STATE(R_USB_COMMAND, port_cmd, reset);
-
- nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, port_sel, port1) |
- IO_STATE(R_USB_COMMAND, port_cmd, reset);
-
- nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
- /* Here we must wait at least 10ms so the device has time to recover */
- udelay(15000);
-
- init_rx_buffers();
- init_tx_bulk_ep();
- init_tx_ctrl_ep();
- init_tx_intr_ep();
-
- /* This works. It seems like the host_run command only has effect when a device is connected,
- i.e. it has to be done when a interrup */
- *R_USB_COMMAND =
- IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
-
- nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
-
- usb_rh = usb_alloc_dev(NULL, hc->bus);
- hc->bus->root_hub = usb_rh;
- usb_connect(usb_rh);
- usb_new_device(usb_rh);
-
- DBFEXIT;
-
- return 0;
-}
-
-static void etrax_usb_hc_cleanup(void)
-{
- DBFENTER;
-
- free_irq(ETRAX_USB_HC_IRQ, NULL);
- free_irq(ETRAX_USB_RX_IRQ, NULL);
- free_irq(ETRAX_USB_TX_IRQ, NULL);
-
- free_dma(USB_TX_DMA_NBR);
- free_dma(USB_RX_DMA_NBR);
- usb_deregister_bus(etrax_usb_bus);
-
- DBFEXIT;
-}
-
-module_init(etrax_usb_hc_init);
-module_exit(etrax_usb_hc_cleanup);
diff --git a/arch/cris/drivers/usb-host.h b/arch/cris/drivers/usb-host.h
deleted file mode 100644
index 434d50b26021..000000000000
--- a/arch/cris/drivers/usb-host.h
+++ /dev/null
@@ -1,243 +0,0 @@
-#ifndef __LINUX_ETRAX_USB_H
-#define __LINUX_ETRAX_USB_H
-
-#include <linux/types.h>
-#include <linux/list.h>
-
-typedef struct USB_IN_Desc {
- __u16 sw_len;
- __u16 command;
- unsigned long next;
- unsigned long buf;
- __u16 hw_len;
- __u16 status;
-} USB_IN_Desc_t;
-
-typedef struct USB_SB_Desc {
- __u16 sw_len;
- __u16 command;
- unsigned long next;
- unsigned long buf;
- __u32 dummy;
-} USB_SB_Desc_t;
-
-typedef struct USB_EP_Desc {
- __u16 hw_len;
- __u16 command;
- unsigned long sub;
- unsigned long nep;
- __u32 dummy;
-} USB_EP_Desc_t;
-
-struct virt_root_hub {
- int devnum;
- void *urb;
- void *int_addr;
- int send;
- int interval;
- int numports;
- struct timer_list rh_int_timer;
- __u16 wPortChange_1;
- __u16 wPortChange_2;
- __u16 prev_wPortStatus_1;
- __u16 prev_wPortStatus_2;
-};
-
-struct etrax_usb_intr_traffic {
- int sleeping;
- int error;
- struct wait_queue *wq;
-};
-
-typedef struct etrax_usb_hc {
- struct usb_bus *bus;
- struct virt_root_hub rh;
- struct etrax_usb_intr_traffic intr;
-} etrax_hc_t;
-
-typedef enum {idle, eot, nodata} etrax_usb_rx_state_t;
-
-typedef struct etrax_usb_urb_priv {
- USB_SB_Desc_t *first_sb;
- __u32 rx_offset;
- etrax_usb_rx_state_t rx_state;
- __u8 eot;
- struct list_head ep_in_list;
-} etrax_urb_priv_t;
-
-
-struct usb_reg_context
-{
- etrax_hc_t *hc;
- __u32 r_usb_epid_attn;
- __u8 r_usb_status;
- __u32 r_usb_rh_port_status_1;
- __u32 r_usb_rh_port_status_2;
- __u32 r_usb_irq_mask_read;
- struct tq_struct usb_bh;
-#if 0
- __u32 r_usb_ept_data[32];
-#endif
-};
-
-struct in_chunk
-{
- void *data;
- int length;
- char epid;
- struct list_head list;
-};
-
-
-/* ---------------------------------------------------------------------------
- Virtual Root HUB
- ------------------------------------------------------------------------- */
-/* destination of request */
-#define RH_INTERFACE 0x01
-#define RH_ENDPOINT 0x02
-#define RH_OTHER 0x03
-
-#define RH_CLASS 0x20
-#define RH_VENDOR 0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS 0x0080
-#define RH_CLEAR_FEATURE 0x0100
-#define RH_SET_FEATURE 0x0300
-#define RH_SET_ADDRESS 0x0500
-#define RH_GET_DESCRIPTOR 0x0680
-#define RH_SET_DESCRIPTOR 0x0700
-#define RH_GET_CONFIGURATION 0x0880
-#define RH_SET_CONFIGURATION 0x0900
-#define RH_GET_STATE 0x0280
-#define RH_GET_INTERFACE 0x0A80
-#define RH_SET_INTERFACE 0x0B00
-#define RH_SYNC_FRAME 0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP 0x2000
-
-
-/* Hub port features */
-#define RH_PORT_CONNECTION 0x00
-#define RH_PORT_ENABLE 0x01
-#define RH_PORT_SUSPEND 0x02
-#define RH_PORT_OVER_CURRENT 0x03
-#define RH_PORT_RESET 0x04
-#define RH_PORT_POWER 0x08
-#define RH_PORT_LOW_SPEED 0x09
-#define RH_C_PORT_CONNECTION 0x10
-#define RH_C_PORT_ENABLE 0x11
-#define RH_C_PORT_SUSPEND 0x12
-#define RH_C_PORT_OVER_CURRENT 0x13
-#define RH_C_PORT_RESET 0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER 0x00
-#define RH_C_HUB_OVER_CURRENT 0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP 0x00
-#define RH_ENDPOINT_STALL 0x01
-
-/* Our Vendor Specific feature */
-#define RH_REMOVE_EP 0x00
-
-
-#define RH_ACK 0x01
-#define RH_REQ_ERR -1
-#define RH_NACK 0x00
-
-/* Field definitions for */
-
-#define USB_IN_command__eol__BITNR 0 /* command macros */
-#define USB_IN_command__eol__WIDTH 1
-#define USB_IN_command__eol__no 0
-#define USB_IN_command__eol__yes 1
-
-#define USB_IN_command__intr__BITNR 3
-#define USB_IN_command__intr__WIDTH 1
-#define USB_IN_command__intr__no 0
-#define USB_IN_command__intr__yes 1
-
-#define USB_IN_status__eop__BITNR 1 /* status macros. */
-#define USB_IN_status__eop__WIDTH 1
-#define USB_IN_status__eop__no 0
-#define USB_IN_status__eop__yes 1
-
-#define USB_IN_status__eot__BITNR 5
-#define USB_IN_status__eot__WIDTH 1
-#define USB_IN_status__eot__no 0
-#define USB_IN_status__eot__yes 1
-
-#define USB_IN_status__error__BITNR 6
-#define USB_IN_status__error__WIDTH 1
-#define USB_IN_status__error__no 0
-#define USB_IN_status__error__yes 1
-
-#define USB_IN_status__nodata__BITNR 7
-#define USB_IN_status__nodata__WIDTH 1
-#define USB_IN_status__nodata__no 0
-#define USB_IN_status__nodata__yes 1
-
-#define USB_IN_status__epid__BITNR 8
-#define USB_IN_status__epid__WIDTH 5
-
-#define USB_EP_command__eol__BITNR 0
-#define USB_EP_command__eol__WIDTH 1
-#define USB_EP_command__eol__no 0
-#define USB_EP_command__eol__yes 1
-
-#define USB_EP_command__eof__BITNR 1
-#define USB_EP_command__eof__WIDTH 1
-#define USB_EP_command__eof__no 0
-#define USB_EP_command__eof__yes 1
-
-#define USB_EP_command__intr__BITNR 3
-#define USB_EP_command__intr__WIDTH 1
-#define USB_EP_command__intr__no 0
-#define USB_EP_command__intr__yes 1
-
-#define USB_EP_command__enable__BITNR 4
-#define USB_EP_command__enable__WIDTH 1
-#define USB_EP_command__enable__no 0
-#define USB_EP_command__enable__yes 1
-
-#define USB_EP_command__hw_valid__BITNR 5
-#define USB_EP_command__hw_valid__WIDTH 1
-#define USB_EP_command__hw_valid__no 0
-#define USB_EP_command__hw_valid__yes 1
-
-#define USB_EP_command__epid__BITNR 8
-#define USB_EP_command__epid__WIDTH 5
-
-#define USB_SB_command__eol__BITNR 0 /* command macros. */
-#define USB_SB_command__eol__WIDTH 1
-#define USB_SB_command__eol__no 0
-#define USB_SB_command__eol__yes 1
-
-#define USB_SB_command__eot__BITNR 1
-#define USB_SB_command__eot__WIDTH 1
-#define USB_SB_command__eot__no 0
-#define USB_SB_command__eot__yes 1
-
-#define USB_SB_command__intr__BITNR 3
-#define USB_SB_command__intr__WIDTH 1
-#define USB_SB_command__intr__no 0
-#define USB_SB_command__intr__yes 1
-
-#define USB_SB_command__tt__BITNR 4
-#define USB_SB_command__tt__WIDTH 2
-#define USB_SB_command__tt__zout 0
-#define USB_SB_command__tt__in 1
-#define USB_SB_command__tt__out 2
-#define USB_SB_command__tt__setup 3
-
-
-#define USB_SB_command__rem__BITNR 8
-#define USB_SB_command__rem__WIDTH 6
-
-#define USB_SB_command__full__BITNR 6
-#define USB_SB_command__full__WIDTH 1
-#define USB_SB_command__full__no 0
-#define USB_SB_command__full__yes 1
-
-#endif
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
index a340c8fb59fa..7f6d9b43cf1f 100644
--- a/arch/cris/kernel/Makefile
+++ b/arch/cris/kernel/Makefile
@@ -1,21 +1,13 @@
-# $Id: Makefile,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+# $Id: Makefile,v 1.8 2003/04/09 05:20:47 starvik Exp $
#
# Makefile for the linux kernel.
#
-extra-y := head.o
-
-obj-y := process.o signal.o entry.o traps.o irq.o \
- ptrace.o setup.o time.o sys_cris.o shadows.o \
- debugport.o semaphore.o
+obj-y := process.o traps.o irq.o ptrace.o setup.o \
+ time.o sys_cris.o semaphore.o
obj-$(CONFIG_MODULES) += ksyms.o
-obj-$(CONFIG_ETRAX_KGDB) += kgdb.o
-
-# This dependency isn't caught by mkdep. See entry.S.
-entry.o: entryoffsets.s
-
-entryoffsets.s: entryoffsets.c
- $(CC) $(CFLAGS) -S -c $<
+obj-$(CONFIG_MODULES) += module.o
clean:
+
diff --git a/arch/cris/kernel/entryoffsets.c b/arch/cris/kernel/entryoffsets.c
deleted file mode 100644
index f1480acd1047..000000000000
--- a/arch/cris/kernel/entryoffsets.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* linux/arch/cris/entryoffsets.c
- *
- * Copyright (C) 2001 Axis Communications AB
- *
- * Generate structure offsets for use in entry.S. No extra processing
- * needed more than compiling this file to assembly code. Horrendous
- * assembly code will be generated, so don't look at that.
- *
- * Authors: Hans-Peter Nilsson (hp@axis.com)
- */
-
-/* There can be string constants fallout from inline functions, so we'd
- better make sure we don't assemble anything emitted from inclusions. */
-__asm__ (".if 0");
-
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <asm/processor.h>
-
-/* Exclude everything except the assembly by wrapping it in ".if 0". */
-#undef VAL
-#define VAL(NAME, VALUE) \
-void NAME ## _fun (void) \
- { \
- __asm__ (".endif \n" \
- #NAME " = %0 \n" \
- ".if 0\n" \
- : : "i" (VALUE)); \
- }
-
-#undef OF
-#define OF(NAME, TYPE, MEMBER) \
- VAL (NAME, offsetof (TYPE, MEMBER))
-
-/* task_struct offsets. */
-#error OF (LTASK_SIGPENDING, struct task_struct, sigpending)
-#error OF (LTASK_NEEDRESCHED, struct task_struct, need_resched)
-#error OF (LTASK_PTRACE, struct task_struct, ptrace)
-OF (LTASK_PID, struct task_struct, pid)
-
-/* pt_regs offsets. */
-OF (LORIG_R10, struct pt_regs, orig_r10)
-OF (LR13, struct pt_regs, r13)
-OF (LR12, struct pt_regs, r12)
-OF (LR11, struct pt_regs, r11)
-OF (LR10, struct pt_regs, r10)
-OF (LR9, struct pt_regs, r9)
-OF (LMOF, struct pt_regs, mof)
-OF (LDCCR, struct pt_regs, dccr)
-OF (LSRP, struct pt_regs, srp)
-OF (LIRP, struct pt_regs, irp)
-
-/* thread_struct offsets. */
-OF (LTHREAD_KSP, struct thread_struct, ksp)
-OF (LTHREAD_USP, struct thread_struct, usp)
-OF (LTHREAD_DCCR, struct thread_struct, dccr)
-
-/* linux/sched.h values - doesn't have an #ifdef __ASSEMBLY__ for these. */
-VAL (LCLONE_VM, CLONE_VM)
-VAL (LCLONE_UNTRACED, CLONE_UNTRACED)
-
-__asm__ (".endif");
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
index c63a5f02b00d..934f8715b5af 100644
--- a/arch/cris/kernel/irq.c
+++ b/arch/cris/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.2 2001/12/18 13:35:20 bjornw Exp $
+/* $Id: irq.c,v 1.8 2003/07/04 08:27:52 starvik Exp $
*
* linux/arch/cris/kernel/irq.c
*
@@ -23,7 +23,7 @@
#include <linux/config.h>
#include <linux/ptrace.h>
-#include <linux/errno.h>
+
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -34,47 +34,34 @@
#include <linux/random.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/errno.h>
-#include <asm/system.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/bitops.h>
-#include <asm/svinto.h>
-
-char *hw_bp_msg = "BP 0x%x\n";
-
-static inline void
-mask_irq(unsigned int irq_nr)
-{
- *R_VECT_MASK_CLR = 1 << irq_nr;
-}
-
-static inline void
-unmask_irq(unsigned int irq_nr)
-{
- *R_VECT_MASK_SET = 1 << irq_nr;
-}
+/* Defined in arch specific irq.c */
+extern void arch_setup_irq(int irq);
+extern void arch_free_irq(int irq);
void
disable_irq(unsigned int irq_nr)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
mask_irq(irq_nr);
- restore_flags(flags);
+ local_irq_restore(flags);
}
void
enable_irq(unsigned int irq_nr)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
unmask_irq(irq_nr);
- restore_flags(flags);
+ local_irq_restore(flags);
}
unsigned long
@@ -89,140 +76,11 @@ probe_irq_off(unsigned long x)
return 0;
}
-irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */
-
-/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
- * global just so that the kernel gdb can use it.
- */
-
-void
-set_int_vector(int n, irqvectptr addr, irqvectptr saddr)
-{
- /* remember the shortcut entry point, after the prologue */
-
- irq_shortcuts[n] = saddr;
-
- etrax_irv->v[n + 0x20] = (irqvectptr)addr;
-}
-
-/* the breakpoint vector is obviously not made just like the normal irq handlers
- * but needs to contain _code_ to jump to addr.
- *
- * the BREAK n instruction jumps to IBR + n * 8
- */
-
-void
-set_break_vector(int n, irqvectptr addr)
-{
- unsigned short *jinstr = (unsigned short *)&etrax_irv->v[n*2];
- unsigned long *jaddr = (unsigned long *)(jinstr + 1);
-
- /* if you don't know what this does, do not touch it! */
-
- *jinstr = 0x0d3f;
- *jaddr = (unsigned long)addr;
-
- /* 00000026 <clrlop+1a> 3f0d82000000 jump 0x82 */
-}
-
-
-/*
- * This builds up the IRQ handler stubs using some ugly macros in irq.h
- *
- * These macros create the low-level assembly IRQ routines that do all
- * the operations that are needed. They are also written to be fast - and to
- * disable interrupts as little as humanly possible.
- *
- */
-
-/* IRQ0 and 1 are special traps */
-void hwbreakpoint(void);
-void IRQ1_interrupt(void);
-BUILD_TIMER_IRQ(2, 0x04) /* the timer interrupt is somewhat special */
-BUILD_IRQ(3, 0x08)
-BUILD_IRQ(4, 0x10)
-BUILD_IRQ(5, 0x20)
-BUILD_IRQ(6, 0x40)
-BUILD_IRQ(7, 0x80)
-BUILD_IRQ(8, 0x100)
-BUILD_IRQ(9, 0x200)
-BUILD_IRQ(10, 0x400)
-BUILD_IRQ(11, 0x800)
-BUILD_IRQ(12, 0x1000)
-BUILD_IRQ(13, 0x2000)
-void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */
-void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
-BUILD_IRQ(16, 0x10000)
-BUILD_IRQ(17, 0x20000)
-BUILD_IRQ(18, 0x40000)
-BUILD_IRQ(19, 0x80000)
-BUILD_IRQ(20, 0x100000)
-BUILD_IRQ(21, 0x200000)
-BUILD_IRQ(22, 0x400000)
-BUILD_IRQ(23, 0x800000)
-BUILD_IRQ(24, 0x1000000)
-BUILD_IRQ(25, 0x2000000)
-/* IRQ 26-30 are reserved */
-BUILD_IRQ(31, 0x80000000)
-
-/*
- * Pointers to the low-level handlers
- */
-
-static void (*interrupt[NR_IRQS])(void) = {
- NULL, NULL, IRQ2_interrupt, IRQ3_interrupt,
- IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
- IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
- IRQ12_interrupt, IRQ13_interrupt, NULL, NULL,
- IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,
- IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,
- IRQ24_interrupt, IRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
- IRQ31_interrupt
-};
-
-static void (*sinterrupt[NR_IRQS])(void) = {
- NULL, NULL, sIRQ2_interrupt, sIRQ3_interrupt,
- sIRQ4_interrupt, sIRQ5_interrupt, sIRQ6_interrupt, sIRQ7_interrupt,
- sIRQ8_interrupt, sIRQ9_interrupt, sIRQ10_interrupt, sIRQ11_interrupt,
- sIRQ12_interrupt, sIRQ13_interrupt, NULL, NULL,
- sIRQ16_interrupt, sIRQ17_interrupt, sIRQ18_interrupt, sIRQ19_interrupt,
- sIRQ20_interrupt, sIRQ21_interrupt, sIRQ22_interrupt, sIRQ23_interrupt,
- sIRQ24_interrupt, sIRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
- sIRQ31_interrupt
-};
-
-static void (*bad_interrupt[NR_IRQS])(void) = {
- NULL, NULL,
- NULL, bad_IRQ3_interrupt,
- bad_IRQ4_interrupt, bad_IRQ5_interrupt,
- bad_IRQ6_interrupt, bad_IRQ7_interrupt,
- bad_IRQ8_interrupt, bad_IRQ9_interrupt,
- bad_IRQ10_interrupt, bad_IRQ11_interrupt,
- bad_IRQ12_interrupt, bad_IRQ13_interrupt,
- NULL, NULL,
- bad_IRQ16_interrupt, bad_IRQ17_interrupt,
- bad_IRQ18_interrupt, bad_IRQ19_interrupt,
- bad_IRQ20_interrupt, bad_IRQ21_interrupt,
- bad_IRQ22_interrupt, bad_IRQ23_interrupt,
- bad_IRQ24_interrupt, bad_IRQ25_interrupt,
- NULL, NULL, NULL, NULL, NULL,
- bad_IRQ31_interrupt
-};
-
/*
* Initial irq handlers.
*/
-static struct irqaction *irq_action[NR_IRQS] = {
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
-};
+static struct irqaction *irq_action[NR_IRQS];
int show_interrupts(struct seq_file *p, void *v)
{
@@ -262,9 +120,10 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
struct irqaction *action;
int do_random, cpu;
+ int retval = 0;
cpu = smp_processor_id();
- irq_enter(cpu);
+ irq_enter();
kstat_cpu(cpu).irqs[irq]++;
action = irq_action[irq];
@@ -275,14 +134,24 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
do_random = 0;
do {
do_random |= action->flags;
- action->handler(irq, action->dev_id, regs);
+ retval |= action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
+
+ if (retval != 1) {
+ if (retval) {
+ printk("irq event %d: bogus retval mask %x\n",
+ irq, retval);
+ } else {
+ printk("irq %d: nobody cared\n", irq);
+ }
+ }
+
if (do_random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
- local_irq_disable();
+ local_irq_disable();
}
- irq_exit(cpu);
+ irq_exit();
if (softirq_pending(cpu))
do_softirq();
@@ -295,7 +164,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
handler is entered into the interrupt vector
*/
-int setup_etrax_irq(int irq, struct irqaction * new)
+int setup_irq(int irq, struct irqaction * new)
{
int shared = 0;
struct irqaction *old, **p;
@@ -322,19 +191,19 @@ int setup_etrax_irq(int irq, struct irqaction * new)
if (new->flags & SA_SAMPLE_RANDOM)
rand_initialize_irq(irq);
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
*p = new;
if (!shared) {
/* if the irq wasn't registred before, enter it into the vector table
and unmask it physically
*/
- set_int_vector(irq, interrupt[irq], sinterrupt[irq]);
+ arch_setup_irq(irq);
unmask_irq(irq);
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -348,7 +217,7 @@ int setup_etrax_irq(int irq, struct irqaction * new)
*/
int request_irq(unsigned int irq,
- void (*handler)(int, void *, struct pt_regs *),
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char * devname,
void *dev_id)
@@ -378,7 +247,7 @@ int request_irq(unsigned int irq,
action->next = NULL;
action->dev_id = dev_id;
- retval = setup_etrax_irq(irq, action);
+ retval = setup_irq(irq, action);
if (retval)
kfree(action);
@@ -399,14 +268,14 @@ void free_irq(unsigned int irq, void *dev_id)
continue;
/* Found it - now free it */
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
*p = action->next;
if (!irq_action[irq]) {
mask_irq(irq);
- set_int_vector(irq, bad_interrupt[irq], 0);
+ arch_free_irq(irq);
}
- restore_flags(flags);
+ local_irq_restore(flags);
kfree(action);
return;
}
@@ -415,84 +284,11 @@ void free_irq(unsigned int irq, void *dev_id)
void weird_irq(void)
{
- __asm__("di");
+ local_irq_disable();
printk("weird irq\n");
while(1);
}
-/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
- setting the irq vector table to point to bad_interrupt ptrs.
-*/
-
-void system_call(void); /* from entry.S */
-void do_sigtrap(void); /* from entry.S */
-void gdb_handle_breakpoint(void); /* from entry.S */
-
-void __init
-init_IRQ(void)
-{
- int i;
-
- /* clear all interrupt masks */
-
-#ifndef CONFIG_SVINTO_SIM
- *R_IRQ_MASK0_CLR = 0xffffffff;
- *R_IRQ_MASK1_CLR = 0xffffffff;
- *R_IRQ_MASK2_CLR = 0xffffffff;
-#endif
-
- *R_VECT_MASK_CLR = 0xffffffff;
-
- /* clear the shortcut entry points */
-
- for(i = 0; i < NR_IRQS; i++)
- irq_shortcuts[i] = NULL;
-
- for (i = 0; i < 256; i++)
- etrax_irv->v[i] = weird_irq;
-
- /* the entries in the break vector contain actual code to be
- executed by the associated break handler, rather than just a jump
- address. therefore we need to setup a default breakpoint handler
- for all breakpoints */
-
- for (i = 0; i < 16; i++)
- set_break_vector(i, do_sigtrap);
-
- /* set all etrax irq's to the bad handlers */
- for (i = 2; i < NR_IRQS; i++)
- set_int_vector(i, bad_interrupt[i], 0);
-
- /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
-
- set_int_vector(15, multiple_interrupt, 0);
-
- /* 0 and 1 which are special breakpoint/NMI traps */
-
- set_int_vector(0, hwbreakpoint, 0);
- set_int_vector(1, IRQ1_interrupt, 0);
-
- /* and irq 14 which is the mmu bus fault handler */
-
- set_int_vector(14, mmu_bus_fault, 0);
-
- /* setup the system-call trap, which is reached by BREAK 13 */
-
- set_break_vector(13, system_call);
-
- /* setup a breakpoint handler for debugging used for both user and
- kernel mode debugging (which is why it is not inside an ifdef
- CONFIG_ETRAX_KGDB) */
- set_break_vector(8, gdb_handle_breakpoint);
-
-#ifdef CONFIG_ETRAX_KGDB
- /* setup kgdb if its enabled, and break into the debugger */
- kgdb_init();
- breakpoint();
-#endif
-
-}
-
#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
/* Used by other archs to show/control IRQ steering during SMP */
void __init
diff --git a/arch/cris/kernel/ksyms.c b/arch/cris/kernel/ksyms.c
index 4d2cbc18c6a8..1161a2525254 100644
--- a/arch/cris/kernel/ksyms.c
+++ b/arch/cris/kernel/ksyms.c
@@ -24,6 +24,9 @@
extern void dump_thread(struct pt_regs *, struct user *);
extern unsigned long get_cmos_time(void);
extern void __Udiv(void);
+extern void __Umod(void);
+extern void __Div(void);
+extern void __Mod(void);
extern void __ashrdi3(void);
extern void iounmap(void *addr);
@@ -44,11 +47,16 @@ EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
/* Math functions */
EXPORT_SYMBOL(__Udiv);
+EXPORT_SYMBOL(__Umod);
+EXPORT_SYMBOL(__Div);
+EXPORT_SYMBOL(__Mod);
EXPORT_SYMBOL(__ashrdi3);
/* Memory functions */
@@ -58,6 +66,8 @@ EXPORT_SYMBOL(iounmap);
/* Semaphore functions */
EXPORT_SYMBOL(__up);
EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
/* Export shadow registers for the CPU I/O pins */
EXPORT_SYMBOL(genconfig_shadow);
@@ -69,14 +79,13 @@ EXPORT_SYMBOL(port_pb_config_shadow);
EXPORT_SYMBOL(port_g_data_shadow);
/* Userspace access functions */
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(__generic_copy_from_user);
-EXPORT_SYMBOL(__generic_copy_to_user);
-EXPORT_SYMBOL(strnlen_user);
EXPORT_SYMBOL(__copy_user_zeroing);
EXPORT_SYMBOL(__copy_user);
+/* Cache flush functions */
+EXPORT_SYMBOL(flush_etrax_cache);
+EXPORT_SYMBOL(prepare_rx_descriptor);
+
#undef memcpy
#undef memset
extern void * memset(void *, int, __kernel_size_t);
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c
new file mode 100644
index 000000000000..052c0031fa29
--- /dev/null
+++ b/arch/cris/kernel/module.c
@@ -0,0 +1,106 @@
+/* Kernel module help for i386.
+ Copyright (C) 2001 Rusty Russell.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+
+ /* TODO: This is probably not correct */
+ printk("Beware: untested code in module.c!\n");
+ /* We add the value into the location given */
+ *location += sym->st_value;
+ }
+ return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 60441877ef2f..23a5d13c18ea 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -1,13 +1,51 @@
-/* $Id: process.c,v 1.3 2002/01/21 15:22:49 bjornw Exp $
+/* $Id: process.c,v 1.14 2003/06/10 10:21:12 johana Exp $
*
* linux/arch/cris/kernel/process.c
*
* Copyright (C) 1995 Linus Torvalds
- * Copyright (C) 2000, 2001 Axis Communications AB
+ * Copyright (C) 2000-2002 Axis Communications AB
*
* Authors: Bjorn Wesen (bjornw@axis.com)
*
* $Log: process.c,v $
+ * Revision 1.14 2003/06/10 10:21:12 johana
+ * Moved thread_saved_pc() from arch/cris/kernel/process.c to
+ * subarch specific process.c.
+ *
+ * Revision 1.13 2003/04/09 05:20:47 starvik
+ * Merge of Linux 2.5.67
+ *
+ * Revision 1.12 2002/12/11 15:41:11 starvik
+ * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/kernel
+ *
+ * Revision 1.11 2002/12/10 09:00:10 starvik
+ * Merge of Linux 2.5.51
+ *
+ * Revision 1.10 2002/11/27 08:42:34 starvik
+ * Argument to user_regs() is thread_info*
+ *
+ * Revision 1.9 2002/11/26 09:44:21 starvik
+ * New threads exits through ret_from_fork (necessary for preemptive scheduling)
+ *
+ * Revision 1.8 2002/11/19 14:35:24 starvik
+ * Changes from linux 2.4
+ * Changed struct initializer syntax to the currently prefered notation
+ *
+ * Revision 1.7 2002/11/18 07:39:42 starvik
+ * thread_saved_pc moved here from processor.h
+ *
+ * Revision 1.6 2002/11/14 06:51:27 starvik
+ * Made cpu_idle more similar with other archs
+ * init_task_union -> init_thread_union
+ * Updated for new interrupt macros
+ * sys_clone and do_fork have a new argument, user_tid
+ *
+ * Revision 1.5 2002/11/05 06:45:11 starvik
+ * Merge of Linux 2.5.45
+ *
+ * Revision 1.4 2002/02/05 15:37:44 bjornw
+ * Need init_task.h
+ *
* Revision 1.3 2002/01/21 15:22:49 bjornw
* current->counter is gone
*
@@ -54,29 +92,17 @@
*/
#define __KERNEL_SYSCALLS__
-#include <stdarg.h>
-#include <linux/errno.h>
+#include <asm/atomic.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/fs_struct.h>
+#include <linux/init_task.h>
#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
+#include <linux/fs.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/elfcore.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-
-#include <linux/smp.h>
//#define DEBUG
@@ -89,20 +115,29 @@
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
/*
- * Initial task structure.
+ * Initial thread structure.
*
* We need to make sure that this is 8192-byte aligned due to the
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+
-union task_union init_task_union
- __attribute__((__section__(".data.init_task"))) =
- { INIT_TASK(init_task_union.task) };
/*
* The hlt_counter, disable_hlt and enable_hlt is just here as a hook if
@@ -125,44 +160,34 @@ void enable_hlt(void)
hlt_counter--;
}
-int cpu_idle(void *unused)
-{
- while(1) {
- schedule();
- }
-}
-
-/* if the watchdog is enabled, we can simply disable interrupts and go
- * into an eternal loop, and the watchdog will reset the CPU after 0.1s
- * if on the other hand the watchdog wasn't enabled, we just enable it and wait
+/*
+ * The following aren't currently used.
*/
+void (*pm_idle)(void);
-void hard_reset_now (void)
-{
- /*
- * Don't declare this variable elsewhere. We don't want any other
- * code to know about it than the watchdog handler in entry.S and
- * this code, implementing hard reset through the watchdog.
- */
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
- extern int cause_of_death;
-#endif
-
- printk("*** HARD RESET ***\n");
- cli();
+extern void default_idle(void);
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
- cause_of_death = 0xbedead;
-#else
- /* Since we don't plan to keep on reseting the watchdog,
- the key can be arbitrary hence three */
- *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, 3) |
- IO_STATE(R_WATCHDOG, enable, start);
-#endif
-
- while(1) /* waiting for RETRIBUTION! */ ;
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle (void)
+{
+ /* endless idle loop with no priority at all */
+ while (1) {
+ void (*idle)(void) = pm_idle;
+ if (!idle)
+ idle = default_idle;
+ while (!need_resched())
+ idle();
+ schedule();
+ }
}
+void hard_reset_now (void);
+
void machine_restart(void)
{
hard_reset_now();
@@ -194,60 +219,6 @@ void flush_thread(void)
{
}
-asmlinkage void ret_from_sys_call(void);
-
-/* setup the child's kernel stack with a pt_regs and switch_stack on it.
- * it will be un-nested during _resume and _ret_from_sys_call when the
- * new thread is scheduled.
- *
- * also setup the thread switching structure which is used to keep
- * thread-specific data during _resumes.
- *
- */
-
-int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
- unsigned long unused,
- struct task_struct *p, struct pt_regs *regs)
-{
- struct pt_regs * childregs;
- struct switch_stack *swstack;
-
- /* put the pt_regs structure at the end of the new kernel stack page and fix it up
- * remember that the task_struct doubles as the kernel stack for the task
- */
-
- childregs = user_regs(p);
-
- *childregs = *regs; /* struct copy of pt_regs */
-
- childregs->r10 = 0; /* child returns 0 after a fork/clone */
-
- /* put the switch stack right below the pt_regs */
-
- swstack = ((struct switch_stack *)childregs) - 1;
-
- swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == don't restart the syscall */
-
- /* we want to return into ret_from_sys_call after the _resume */
-
- swstack->return_ip = (unsigned long) ret_from_sys_call;
-
- /* fix the user-mode stackpointer */
-
- p->thread.usp = usp;
-
- /* and the kernel-mode one */
-
- p->thread.ksp = (unsigned long) swstack;
-
-#ifdef DEBUG
- printk("copy_thread: new regs at 0x%p, as shown below:\n", childregs);
- show_registers(childregs);
-#endif
-
- return 0;
-}
-
/*
* fill in the user structure for a core dump..
*/
@@ -281,110 +252,3 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
{
return 0;
}
-
-/*
- * Be aware of the "magic" 7th argument in the four system-calls below.
- * They need the latest stackframe, which is put as the 7th argument by
- * entry.S. The previous arguments are dummies or actually used, but need
- * to be defined to reach the 7th argument.
- *
- * N.B.: Another method to get the stackframe is to use current_regs(). But
- * it returns the latest stack-frame stacked when going from _user mode_ and
- * some of these (at least sys_clone) are called from kernel-mode sometimes
- * (for example during kernel_thread, above) and thus cannot use it. Thus,
- * to be sure not to get any surprises, we use the method for the other calls
- * as well.
- */
-
-asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
- struct pt_regs *regs)
-{
- struct task_struct *p;
- p = do_fork(SIGCHLD, rdusp(), regs, 0);
- return IS_ERR(p) ? PTR_ERR(p) : p->pid;
-}
-
-/* if newusp is 0, we just grab the old usp */
-
-asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
- long r12, long r13, long mof, long srp,
- struct pt_regs *regs)
-{
- struct task_struct *p;
- if (!newusp)
- newusp = rdusp();
- p = do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0);
- return IS_ERR(p) ? PTR_ERR(p) : p->pid;
-}
-
-/* vfork is a system call in i386 because of register-pressure - maybe
- * we can remove it and handle it in libc but we put it here until then.
- */
-
-asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
- struct pt_regs *regs)
-{
- struct task_struct *p;
- p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0);
- return IS_ERR(p) ? PTR_ERR(p) : p->pid;
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char *fname, char **argv, char **envp,
- long r13, long mof, long srp,
- struct pt_regs *regs)
-{
- int error;
- char *filename;
-
- filename = getname(fname);
- error = PTR_ERR(filename);
-
- if (IS_ERR(filename))
- goto out;
- error = do_execve(filename, argv, envp, regs);
- putname(filename);
- out:
- return error;
-}
-
-/*
- * These bracket the sleeping functions..
- */
-
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-#define first_sched ((unsigned long) scheduling_functions_start_here)
-#define last_sched ((unsigned long) scheduling_functions_end_here)
-
-unsigned long get_wchan(struct task_struct *p)
-{
-#if 0
- /* YURGH. TODO. */
-
- unsigned long ebp, esp, eip;
- unsigned long stack_page;
- int count = 0;
- if (!p || p == current || p->state == TASK_RUNNING)
- return 0;
- stack_page = (unsigned long)p;
- esp = p->thread.esp;
- if (!stack_page || esp < stack_page || esp > 8188+stack_page)
- return 0;
- /* include/asm-i386/system.h:switch_to() pushes ebp last. */
- ebp = *(unsigned long *) esp;
- do {
- if (ebp < stack_page || ebp > 8184+stack_page)
- return 0;
- eip = *(unsigned long *) (ebp+4);
- if (eip < first_sched || eip >= last_sched)
- return eip;
- ebp = *(unsigned long *) ebp;
- } while (count++ < 16);
-#endif
- return 0;
-}
-#undef last_sched
-#undef first_sched
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
index c8a066c4ee4c..e85a2fdd9acf 100644
--- a/arch/cris/kernel/ptrace.c
+++ b/arch/cris/kernel/ptrace.c
@@ -3,11 +3,35 @@
*
* Parts taken from the m68k port.
*
- * Copyright (c) 2000, 2001 Axis Communications AB
+ * Copyright (c) 2000, 2001, 2002 Axis Communications AB
*
* Authors: Bjorn Wesen
*
* $Log: ptrace.c,v $
+ * Revision 1.9 2003/07/04 12:56:11 tobiasa
+ * Moved arch-specific code to arch-specific files.
+ *
+ * Revision 1.8 2003/04/09 05:20:47 starvik
+ * Merge of Linux 2.5.67
+ *
+ * Revision 1.7 2002/11/27 08:42:34 starvik
+ * Argument to user_regs() is thread_info*
+ *
+ * Revision 1.6 2002/11/20 11:56:11 starvik
+ * Merge of Linux 2.5.48
+ *
+ * Revision 1.5 2002/11/18 07:41:19 starvik
+ * Removed warning
+ *
+ * Revision 1.4 2002/11/11 12:47:28 starvik
+ * SYSCALL_TRACE has been moved to thread flags
+ *
+ * Revision 1.3 2002/02/05 15:37:18 bjornw
+ * * Add do_notify_resume (replaces do_signal in the callchain)
+ * * syscall_trace is now do_syscall_trace
+ * * current->ptrace flag PT_TRACESYS -> PT_SYSCALLTRACE
+ * * Keep track of the current->work.syscall_trace counter
+ *
* Revision 1.2 2001/12/18 13:35:20 bjornw
* Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
*
@@ -49,18 +73,9 @@
#include <asm/processor.h>
/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- */
-
-/* determines which bits in DCCR the user has access to. */
-/* 1 = access 0 = no access */
-#define DCCR_MASK 0x0000001f /* XNZVC */
-
-/*
* Get contents of register REGNO in task TASK.
*/
-static inline long get_reg(struct task_struct *task, unsigned int regno)
+inline long get_reg(struct task_struct *task, unsigned int regno)
{
/* USP is a special case, it's not in the pt_regs struct but
* in the tasks thread struct
@@ -69,7 +84,7 @@ static inline long get_reg(struct task_struct *task, unsigned int regno)
if (regno == PT_USP)
return task->thread.usp;
else if (regno < PT_MAX)
- return ((unsigned long *)user_regs(task))[regno];
+ return ((unsigned long *)user_regs(task->thread_info))[regno];
else
return 0;
}
@@ -77,248 +92,28 @@ static inline long get_reg(struct task_struct *task, unsigned int regno)
/*
* Write contents of register REGNO in task TASK.
*/
-static inline int put_reg(struct task_struct *task, unsigned int regno,
+inline int put_reg(struct task_struct *task, unsigned int regno,
unsigned long data)
{
if (regno == PT_USP)
task->thread.usp = data;
else if (regno < PT_MAX)
- ((unsigned long *)user_regs(task))[regno] = data;
+ ((unsigned long *)user_regs(task->thread_info))[regno] = data;
else
return -1;
return 0;
}
-/*
- * Called by kernel/ptrace.c when detaching..
- *
- * Make sure the single step bit is not set.
+/* notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
*/
-void ptrace_disable(struct task_struct *child)
-{
- /* Todo - pending singlesteps? */
-}
+extern int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
-/* Note that this implementation of ptrace behaves differently from vanilla
- * ptrace. Contrary to what the man page says, in the PTRACE_PEEKTEXT,
- * PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests the data variable is not
- * ignored. Instead, the data variable is expected to point at a location
- * (in user space) where the result of the ptrace call is written (instead of
- * being returned).
- */
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+void do_notify_resume(int canrestart, sigset_t *oldset, struct pt_regs *regs,
+ __u32 thread_info_flags )
{
- struct task_struct *child;
- int ret;
-
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
- ret = -ESRCH;
- if (!(child->ptrace & PT_PTRACED))
- goto out_tsk;
- if (child->state != TASK_STOPPED) {
- if (request != PTRACE_KILL)
- goto out_tsk;
- }
- if (child->p_pptr != current)
- goto out_tsk;
-
- switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long *) data);
- break;
- }
-
- /* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR: {
- unsigned long tmp;
-
- ret = -EIO;
- if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- break;
-
- tmp = 0; /* Default return condition */
- ret = -EIO;
- if (addr < sizeof(struct pt_regs)) {
- tmp = get_reg(child, addr >> 2);
- ret = put_user(tmp, (unsigned long *)data);
- }
- break;
- }
-
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
- break;
-
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
- ret = -EIO;
- if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- break;
-
- if (addr < sizeof(struct pt_regs)) {
- addr >>= 2;
-
- if (addr == PT_DCCR) {
- /* don't allow the tracing process to change stuff like
- * interrupt enable, kernel/user bit, dma enables etc.
- */
- data &= DCCR_MASK;
- data |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
- }
- if (put_reg(child, addr, data))
- break;
- ret = 0;
- }
- break;
-
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: /* restart after signal. */
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- break;
- if (request == PTRACE_SYSCALL)
- child->ptrace |= PT_TRACESYS;
- else
- child->ptrace &= ~PT_TRACESYS;
- child->exit_code = data;
- /* TODO: make sure any pending breakpoint is killed */
- wake_up_process(child);
- ret = 0;
- break;
-
-/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL:
- ret = 0;
- if (child->state == TASK_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;
- /* TODO: make sure any pending breakpoint is killed */
- wake_up_process(child);
- break;
-
- case PTRACE_SINGLESTEP: /* set the trap flag. */
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- break;
- child->ptrace &= ~PT_TRACESYS;
-
- /* TODO: set some clever breakpoint mechanism... */
-
- child->exit_code = data;
- /* give it a chance to run. */
- wake_up_process(child);
- ret = 0;
- break;
-
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
- break;
-
- case PTRACE_GETREGS: { /* Get all gp regs from the child. */
- int i;
- unsigned long tmp;
- for (i = 0; i <= PT_MAX; i++) {
- tmp = get_reg(child, i);
- if (put_user(tmp, (unsigned long *) data)) {
- ret = -EFAULT;
- break;
- }
- data += sizeof(long);
- }
- ret = 0;
- break;
- }
-
- case PTRACE_SETREGS: { /* Set all gp regs in the child. */
- int i;
- unsigned long tmp;
- for (i = 0; i <= PT_MAX; i++) {
- if (get_user(tmp, (unsigned long *) data)) {
- ret = -EFAULT;
- break;
- }
- if (i == PT_DCCR) {
- tmp &= DCCR_MASK;
- tmp |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
- }
- put_reg(child, i, tmp);
- data += sizeof(long);
- }
- ret = 0;
- break;
- }
-
- default:
- ret = ptrace_request(child, request, addr, data);
- break;
- }
-out_tsk:
- free_task_struct(child);
-out:
- unlock_kernel();
- return ret;
-}
-
-asmlinkage void syscall_trace(void)
-{
- if ((current->ptrace & (PT_PTRACED | PT_TRACESYS)) !=
- (PT_PTRACED | PT_TRACESYS))
- return;
- current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0);
- current->state = TASK_STOPPED;
- notify_parent(current, SIGCHLD);
- schedule();
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
+ /* deal with pending signal delivery */
+ if (thread_info_flags & _TIF_SIGPENDING)
+ do_signal(canrestart,oldset,regs);
}
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 3232548a639c..fc989d2c7735 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.2 2001/12/18 13:35:20 bjornw Exp $
+/* $Id: setup.c,v 1.7 2003/07/04 08:27:52 starvik Exp $
*
* linux/arch/cris/kernel/setup.c
*
@@ -10,30 +10,12 @@
* This file handles the architecture-dependent parts of initialization
*/
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/config.h>
#include <linux/init.h>
+#include <linux/mm.h>
#include <linux/bootmem.h>
-#include <linux/seq_file.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/smp.h>
#include <asm/pgtable.h>
-#include <asm/types.h>
-#include <asm/svinto.h>
+#include <linux/seq_file.h>
+#include <linux/tty.h>
/*
* Setup options
@@ -52,6 +34,7 @@ static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
extern const unsigned long text_start, edata; /* set by the linker script */
+extern unsigned long dram_start, dram_end;
extern unsigned long romfs_start, romfs_length, romfs_in_flash; /* from head.S */
@@ -169,14 +152,14 @@ setup_arch(char **cmdline_p)
*cmdline_p = command_line;
- if (romfs_in_flash) {
- strlcpy(command_line, "root=", sizeof(command_line));
- strlcat(command_line, CONFIG_ETRAX_ROOT_DEVICE,
- sizeof(command_line));
-
- /* Save command line copy for /proc/cmdline */
- strlcpy(saved_command_line, command_line, sizeof(saved_command_line));
- }
+#ifdef CONFIG_ETRAX_CMDLINE
+ strlcpy(command_line, CONFIG_ETRAX_CMDLINE, sizeof(command_line));
+#elif defined(CONFIG_ETRAX_ROOT_DEVICE)
+ strlcpy(command_line, "root=", sizeof(command_line));
+ strlcat(command_line, CONFIG_ETRAX_ROOT_DEVICE,
+ sizeof(command_line));
+#endif
+ command_line[COMMAND_LINE_SIZE - 1] = '\0';
/* give credit for the CRIS port */
@@ -184,83 +167,6 @@ setup_arch(char **cmdline_p)
}
-#ifdef CONFIG_PROC_FS
-#define HAS_FPU 0x0001
-#define HAS_MMU 0x0002
-#define HAS_ETHERNET100 0x0004
-#define HAS_TOKENRING 0x0008
-#define HAS_SCSI 0x0010
-#define HAS_ATA 0x0020
-#define HAS_USB 0x0040
-#define HAS_IRQ_BUG 0x0080
-#define HAS_MMU_BUG 0x0100
-
-static struct cpu_info {
- char *model;
- unsigned short cache;
- unsigned short flags;
-} cpu_info[] = {
- /* The first four models will never ever run this code and are
- only here for display. */
- { "ETRAX 1", 0, 0 },
- { "ETRAX 2", 0, 0 },
- { "ETRAX 3", 0, HAS_TOKENRING },
- { "ETRAX 4", 0, HAS_TOKENRING | HAS_SCSI },
- { "Unknown", 0, 0 },
- { "Unknown", 0, 0 },
- { "Unknown", 0, 0 },
- { "Simulator", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
- { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG },
- { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
- { "ETRAX 100LX", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU | HAS_MMU_BUG },
- { "ETRAX 100LX v2", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU },
- { "Unknown", 0, 0 } /* This entry MUST be the last */
-};
-
-static int show_cpuinfo(struct seq_file *m, void *v)
-{
- unsigned long revision;
- struct cpu_info *info;
-
- /* read the version register in the CPU and print some stuff */
-
- revision = rdvr();
-
- if (revision >= sizeof cpu_info/sizeof *cpu_info)
- info = &cpu_info[sizeof cpu_info/sizeof *cpu_info - 1];
- else
- info = &cpu_info[revision];
-
- return seq_printf(m,
- "cpu\t\t: CRIS\n"
- "cpu revision\t: %lu\n"
- "cpu model\t: %s\n"
- "cache size\t: %d kB\n"
- "fpu\t\t: %s\n"
- "mmu\t\t: %s\n"
- "mmu DMA bug\t: %s\n"
- "ethernet\t: %s Mbps\n"
- "token ring\t: %s\n"
- "scsi\t\t: %s\n"
- "ata\t\t: %s\n"
- "usb\t\t: %s\n"
- "bogomips\t: %lu.%02lu\n",
-
- revision,
- info->model,
- info->cache,
- info->flags & HAS_FPU ? "yes" : "no",
- info->flags & HAS_MMU ? "yes" : "no",
- info->flags & HAS_MMU_BUG ? "yes" : "no",
- info->flags & HAS_ETHERNET100 ? "10/100" : "10",
- info->flags & HAS_TOKENRING ? "4/16 Mbps" : "no",
- info->flags & HAS_SCSI ? "yes" : "no",
- info->flags & HAS_ATA ? "yes" : "no",
- info->flags & HAS_USB ? "yes" : "no",
- (loops_per_jiffy * HZ + 500) / 500000,
- ((loops_per_jiffy * HZ + 500) / 5000) % 100);
-}
-
static void *c_start(struct seq_file *m, loff_t *pos)
{
/* We only got one CPU... */
@@ -277,11 +183,13 @@ static void c_stop(struct seq_file *m, void *v)
{
}
+extern int show_cpuinfo(struct seq_file *m, void *v);
+
struct seq_operations cpuinfo_op = {
- .start = c_start,
- .next = c_next,
- .stop = c_stop,
- .show = show_cpuinfo,
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
};
-#endif /* CONFIG_PROC_FS */
+
diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c
index 31917ab11982..e7e5c04071e5 100644
--- a/arch/cris/kernel/sys_cris.c
+++ b/arch/cris/kernel/sys_cris.c
@@ -1,4 +1,4 @@
-/* $Id: sys_cris.c,v 1.1.1.1 2001/12/17 13:59:27 bjornw Exp $
+/* $Id: sys_cris.c,v 1.5 2003/07/04 08:27:52 starvik Exp $
*
* linux/arch/cris/kernel/sys_cris.c
*
@@ -29,7 +29,7 @@
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way Unix traditionally does this, though.
*/
-asmlinkage int sys_pipe(unsigned long * fildes)
+asmlinkage int sys_pipe(unsigned long __user * fildes)
{
int fd[2];
int error;
@@ -69,7 +69,7 @@ out:
return error;
}
-asmlinkage unsigned long old_mmap(unsigned long *args)
+asmlinkage unsigned long old_mmap(unsigned long __user *args)
{
unsigned long buffer[6];
int err = -EFAULT;
@@ -101,7 +101,7 @@ sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
*/
asmlinkage int sys_ipc (uint call, int first, int second,
- int third, void *ptr, long fifth)
+ int third, void __user *ptr, long fifth)
{
int version, ret;
@@ -110,20 +110,24 @@ asmlinkage int sys_ipc (uint call, int first, int second,
switch (call) {
case SEMOP:
- return sys_semop (first, (struct sembuf *)ptr, second);
+ return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
+ (const struct timespec __user *)fifth);
+
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
union semun fourth;
if (!ptr)
return -EINVAL;
- if (get_user(fourth.__pad, (void **) ptr))
+ if (get_user(fourth.__pad, (void * __user *) ptr))
return -EFAULT;
return sys_semctl (first, second, third, fourth);
}
case MSGSND:
- return sys_msgsnd (first, (struct msgbuf *) ptr,
+ return sys_msgsnd (first, (struct msgbuf __user *) ptr,
second, third);
case MSGRCV:
switch (version) {
@@ -133,7 +137,7 @@ asmlinkage int sys_ipc (uint call, int first, int second,
return -EINVAL;
if (copy_from_user(&tmp,
- (struct ipc_kludge *) ptr,
+ (struct ipc_kludge __user *) ptr,
sizeof (tmp)))
return -EFAULT;
return sys_msgrcv (first, tmp.msgp, second,
@@ -141,29 +145,29 @@ asmlinkage int sys_ipc (uint call, int first, int second,
}
default:
return sys_msgrcv (first,
- (struct msgbuf *) ptr,
+ (struct msgbuf __user *) ptr,
second, fifth, third);
}
case MSGGET:
return sys_msgget ((key_t) first, second);
case MSGCTL:
- return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ return sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
case SHMAT: {
ulong raddr;
- ret = sys_shmat (first, (char *) ptr, second, &raddr);
+ ret = sys_shmat (first, (char __user *) ptr, second, &raddr);
if (ret)
return ret;
- return put_user (raddr, (ulong *) third);
+ return put_user (raddr, (ulong __user *) third);
}
case SHMDT:
- return sys_shmdt ((char *)ptr);
+ return sys_shmdt ((char __user *)ptr);
case SHMGET:
return sys_shmget (first, second, third);
case SHMCTL:
return sys_shmctl (first, second,
- (struct shmid_ds *) ptr);
+ (struct shmid_ds __user *) ptr);
default:
- return -EINVAL;
+ return -ENOSYS;
}
}
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 81f91df573af..caee8e4fd39b 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.2 2001/12/18 13:35:20 bjornw Exp $
+/* $Id: time.c,v 1.9 2003/07/04 08:27:52 starvik Exp $
*
* linux/arch/cris/kernel/time.c
*
@@ -22,124 +22,66 @@
*
*/
+#include <asm/rtc.h>
#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <linux/bcd.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-#include <asm/rtc.h>
-
#include <linux/timex.h>
-#include <linux/config.h>
-
-#include <asm/svinto.h>
u64 jiffies_64 = INITIAL_JIFFIES;
-static int have_rtc; /* used to remember if we have an RTC or not */
-
-/* define this if you need to use print_timestamp */
-/* it will make jiffies at 96 hz instead of 100 hz though */
-#undef USE_CASCADE_TIMERS
-
-extern int setup_etrax_irq(int, struct irqaction *);
-
-/* Lookup table to convert *R_TIMER0 to microseconds (us)
- * Timer goes from TIMER0_DIV down to 1 meaning 0-10000us in step of approx 52us
- */
-unsigned short cris_timer0_value_us[TIMER0_DIV+1];
+int have_rtc; /* used to remember if we have an RTC or not */;
#define TICK_SIZE tick
-static unsigned long do_slow_gettimeoffset(void)
-{
- unsigned long count;
- unsigned long usec_count = 0;
-
- static unsigned long count_p = LATCH; /* for the first call after boot */
- static unsigned long jiffies_p = 0;
-
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
- unsigned long jiffies_t;
-
- /* The timer interrupt comes from Etrax timer 0. In order to get
- * better precision, we check the current value. It might have
- * underflowed already though.
- */
-
-#ifndef CONFIG_SVINTO_SIM
- /* Not available in the xsim simulator. */
- count = *R_TIMER0_DATA;
-#else
- count = 0;
-#endif
-
- jiffies_t = jiffies;
-
- /*
- * avoiding timer inconsistencies (they are rare, but they happen)...
- * there are three kinds of problems that must be avoided here:
- * 1. the timer counter underflows
- * 2. we are after the timer interrupt, but the bottom half handler
- * hasn't executed yet.
- */
- if( jiffies_t == jiffies_p ) {
- if( count > count_p ) {
- /* Timer wrapped */
- count = count_p;
- usec_count = 1000000/CLOCK_TICK_RATE/2;
- }
- } else
- jiffies_p = jiffies_t;
- count_p = count;
- /* Convert timer value to usec using table lookup */
- usec_count += cris_timer0_value_us[count];
-#if 0
- count = ((LATCH-1) - count) * TICK_SIZE;
- count = (count + LATCH/2) / LATCH;
-#endif
- return usec_count;
-}
+extern unsigned long wall_jiffies;
+extern unsigned long do_slow_gettimeoffset(void);
static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
/*
* This version of gettimeofday has near microsecond resolution.
+ *
+ * Note: Division is quite slow on CRIS and do_gettimeofday is called
+ * rather often. Maybe we should do some kind of approximation here
+ * (a naive approximation would be to divide by 1024).
*/
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
+ signed long usec, sec;
+ local_irq_save(flags);
+ local_irq_disable();
+ usec = do_gettimeoffset();
+ {
+ unsigned long lost = jiffies - wall_jiffies;
+ if (lost)
+ usec += lost * (1000000 / HZ);
+ }
+ sec = xtime.tv_sec;
+ usec += xtime.tv_nsec / 1000;
+ local_irq_restore(flags);
- save_flags(flags);
- cli();
- *tv = xtime;
- tv->tv_usec += do_gettimeoffset();
- if (tv->tv_usec >= 1000000) {
- tv->tv_usec -= 1000000;
- tv->tv_sec++;
+ while (usec >= 1000000) {
+ usec -= 1000000;
+ sec++;
}
- restore_flags(flags);
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
}
int do_settimeofday(struct timespec *tv)
{
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ unsigned long flags;
+
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
- cli();
+ local_irq_save(flags);
+ local_irq_disable();
+
/* This is revolting. We need to set the xtime.tv_usec
* correctly. However, the value in this location is
* is value at the last tick.
@@ -147,19 +89,20 @@ int do_settimeofday(struct timespec *tv)
* would have done, and then undo it!
*/
tv->tv_nsec -= do_gettimeoffset() * 1000;
+ tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
- if (tv->tv_nsec < 0) {
+ while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
-
- xtime = *tv;
+ xtime.tv_sec = tv->tv_sec;
+ xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_state = TIME_ERROR; /* p. 24, (a) */
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- sti();
+ local_irq_restore(flags);
return 0;
}
@@ -169,7 +112,7 @@ int do_settimeofday(struct timespec *tv)
* sets the minutes. Usually you'll only notice that after reboot!
*/
-static int set_rtc_mmss(unsigned long nowtime)
+int set_rtc_mmss(unsigned long nowtime)
{
int retval = 0;
int real_seconds, real_minutes, cmos_minutes;
@@ -209,143 +152,6 @@ static int set_rtc_mmss(unsigned long nowtime)
return retval;
}
-/* Excerpt from the Etrax100 HSDD about the built-in watchdog:
- *
- * 3.10.4 Watchdog timer
-
- * When the watchdog timer is started, it generates an NMI if the watchdog
- * isn't restarted or stopped within 0.1 s. If it still isn't restarted or
- * stopped after an additional 3.3 ms, the watchdog resets the chip.
- * The watchdog timer is stopped after reset. The watchdog timer is controlled
- * by the R_WATCHDOG register. The R_WATCHDOG register contains an enable bit
- * and a 3-bit key value. The effect of writing to the R_WATCHDOG register is
- * described in the table below:
- *
- * Watchdog Value written:
- * state: To enable: To key: Operation:
- * -------- ---------- ------- ----------
- * stopped 0 X No effect.
- * stopped 1 key_val Start watchdog with key = key_val.
- * started 0 ~key Stop watchdog
- * started 1 ~key Restart watchdog with key = ~key.
- * started X new_key_val Change key to new_key_val.
- *
- * Note: '~' is the bitwise NOT operator.
- *
- */
-
-/* right now, starting the watchdog is the same as resetting it */
-#define start_watchdog reset_watchdog
-
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
-static int watchdog_key = 0; /* arbitrary number */
-#endif
-
-/* number of pages to consider "out of memory". it is normal that the memory
- * is used though, so put this really low.
- */
-
-#define WATCHDOG_MIN_FREE_PAGES 8
-
-void
-reset_watchdog(void)
-{
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
- /* only keep watchdog happy as long as we have memory left! */
- if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {
- /* reset the watchdog with the inverse of the old key */
- watchdog_key ^= 0x7; /* invert key, which is 3 bits */
- *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
- IO_STATE(R_WATCHDOG, enable, start);
- }
-#endif
-}
-
-/* stop the watchdog - we still need the correct key */
-
-void
-stop_watchdog(void)
-{
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
- watchdog_key ^= 0x7; /* invert key, which is 3 bits */
- *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
- IO_STATE(R_WATCHDOG, enable, stop);
-#endif
-}
-
-/* last time the cmos clock got updated */
-static long last_rtc_update = 0;
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-
-//static unsigned short myjiff; /* used by our debug routine print_timestamp */
-
-static inline void
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- /* acknowledge the timer irq */
-
-#ifdef USE_CASCADE_TIMERS
- *R_TIMER_CTRL =
- IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
- IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
- IO_STATE( R_TIMER_CTRL, i1, clr) |
- IO_STATE( R_TIMER_CTRL, tm1, run) |
- IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
- IO_STATE( R_TIMER_CTRL, i0, clr) |
- IO_STATE( R_TIMER_CTRL, tm0, run) |
- IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
-#else
- *R_TIMER_CTRL = r_timer_ctrl_shadow |
- IO_STATE(R_TIMER_CTRL, i0, clr);
-#endif
-
- /* reset watchdog otherwise it resets us! */
-
- reset_watchdog();
-
- /* call the real timer interrupt handler */
-
- do_timer(regs);
-
- /*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
-
- if ((time_status & STA_UNSYNC) == 0 &&
- xtime.tv_sec > last_rtc_update + 660 &&
- xtime.tv_usec > 500000 - (tick >> 1) &&
- xtime.tv_usec < 500000 + (tick >> 1)) {
- if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600;
- }
-}
-
-#if 0
-/* some old debug code for testing the microsecond timing of packets */
-static unsigned int lastjiff;
-
-void print_timestamp(const char *s)
-{
- unsigned long flags;
- unsigned int newjiff;
-
- save_flags(flags);
- cli();
- newjiff = (myjiff << 16) | (unsigned short)(-*R_TIMER01_DATA);
- printk("%s: %x (%x)\n", s, newjiff, newjiff - lastjiff);
- lastjiff = newjiff;
- restore_flags(flags);
-}
-#endif
-
/* grab the time from the RTC chip */
unsigned long
@@ -385,116 +191,6 @@ update_xtime_from_cmos(void)
{
if(have_rtc) {
xtime.tv_sec = get_cmos_time();
- xtime.tv_usec = 0;
- }
-}
-
-/* timer is SA_SHIRQ so drivers can add stuff to the timer irq chain
- * it needs to be SA_INTERRUPT to make the jiffies update work properly
- */
-
-static struct irqaction irq2 = { timer_interrupt, SA_SHIRQ | SA_INTERRUPT,
- 0, "timer", NULL, NULL};
-
-void __init
-time_init(void)
-{
- int i;
- /* probe for the RTC and read it if it exists */
-
- if(RTC_INIT() < 0) {
- /* no RTC, start at 1980 */
- xtime.tv_sec = 0;
- xtime.tv_usec = 0;
- have_rtc = 0;
- } else {
- /* get the current time */
- have_rtc = 1;
- update_xtime_from_cmos();
- }
-
- /* Setup the etrax timers
- * Base frequency is 19200 hz, divider 192 -> 100 hz as Linux wants
- * In normal mode, we use timer0, so timer1 is free. In cascade
- * mode (which we sometimes use for debugging) both timers are used.
- * Remember that linux/timex.h contains #defines that rely on the
- * timer settings below (hz and divide factor) !!!
- */
-
-#ifdef USE_CASCADE_TIMERS
- *R_TIMER_CTRL =
- IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
- IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
- IO_STATE( R_TIMER_CTRL, i1, nop) |
- IO_STATE( R_TIMER_CTRL, tm1, stop_ld) |
- IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
- IO_STATE( R_TIMER_CTRL, i0, nop) |
- IO_STATE( R_TIMER_CTRL, tm0, stop_ld) |
- IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
-
- *R_TIMER_CTRL = r_timer_ctrl_shadow =
- IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
- IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
- IO_STATE( R_TIMER_CTRL, i1, nop) |
- IO_STATE( R_TIMER_CTRL, tm1, run) |
- IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
- IO_STATE( R_TIMER_CTRL, i0, nop) |
- IO_STATE( R_TIMER_CTRL, tm0, run) |
- IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
-#else
- *R_TIMER_CTRL =
- IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) |
- IO_FIELD(R_TIMER_CTRL, timerdiv0, 192) |
- IO_STATE(R_TIMER_CTRL, i1, nop) |
- IO_STATE(R_TIMER_CTRL, tm1, stop_ld) |
- IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) |
- IO_STATE(R_TIMER_CTRL, i0, nop) |
- IO_STATE(R_TIMER_CTRL, tm0, stop_ld) |
- IO_STATE(R_TIMER_CTRL, clksel0, c19k2Hz);
-
- *R_TIMER_CTRL = r_timer_ctrl_shadow =
- IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) |
- IO_FIELD(R_TIMER_CTRL, timerdiv0, 192) |
- IO_STATE(R_TIMER_CTRL, i1, nop) |
- IO_STATE(R_TIMER_CTRL, tm1, run) |
- IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) |
- IO_STATE(R_TIMER_CTRL, i0, nop) |
- IO_STATE(R_TIMER_CTRL, tm0, run) |
- IO_STATE(R_TIMER_CTRL, clksel0, c19k2Hz);
-#endif
-
- for (i=0; i <= TIMER0_DIV; i++) {
- /* We must be careful not to get overflow... */
- cris_timer0_value_us[TIMER0_DIV-i] =
- (unsigned short)((unsigned long)
- ((i*(1000000/HZ))/TIMER0_DIV)&0x0000FFFFL);
+ xtime.tv_nsec = 0;
}
-
- *R_IRQ_MASK0_SET =
- IO_STATE(R_IRQ_MASK0_SET, timer0, set); /* unmask the timer irq */
-
- /* now actually register the timer irq handler that calls timer_interrupt() */
-
- setup_etrax_irq(2, &irq2); /* irq 2 is the timer0 irq in etrax */
-
- /* enable watchdog if we should use one */
-
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
- printk("Enabling watchdog...\n");
- start_watchdog();
-
- /* If we use the hardware watchdog, we want to trap it as an NMI
- and dump registers before it resets us. For this to happen, we
- must set the "m" NMI enable flag (which once set, is unset only
- when an NMI is taken).
-
- The same goes for the external NMI, but that doesn't have any
- driver or infrastructure support yet. */
- asm ("setf m");
-
- *R_IRQ_MASK0_SET =
- IO_STATE(R_IRQ_MASK0_SET, watchdog_nmi, set);
- *R_VECT_MASK_SET =
- IO_STATE(R_VECT_MASK_SET, nmi, set);
-#endif
}
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c
index 9666d32af626..5273241e072d 100644
--- a/arch/cris/kernel/traps.c
+++ b/arch/cris/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.2 2001/12/18 13:35:20 bjornw Exp $
+/* $Id: traps.c,v 1.7 2003/07/04 08:27:52 starvik Exp $
*
* linux/arch/cris/traps.c
*
@@ -6,7 +6,7 @@
* mechanism, as well as some general stack/register dumping
* things.
*
- * Copyright (C) 2000,2001 Axis Communications AB
+ * Copyright (C) 2000-2002 Axis Communications AB
*
* Authors: Bjorn Wesen
* Hans-Peter Nilsson
@@ -14,19 +14,8 @@
*/
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <asm/uaccess.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/io.h>
#include <asm/pgtable.h>
+#include <asm/uaccess.h>
static int kstack_depth_to_print = 24;
@@ -95,7 +84,7 @@ void show_trace_task(struct task_struct *tsk)
*/
void
-show_stack(unsigned long *sp)
+show_stack(struct task_struct *task, unsigned long *sp)
{
unsigned long *stack, addr;
int i;
@@ -105,8 +94,12 @@ show_stack(unsigned long *sp)
* back trace.
*/
- if(sp == NULL)
- sp = (unsigned long*)rdsp();
+ if(sp == NULL) {
+ if (task)
+ sp = (unsigned long*)task->thread.ksp;
+ else
+ sp = (unsigned long*)rdsp();
+ }
stack = sp;
@@ -144,123 +137,9 @@ show_stack()
}
#endif
-void
-show_registers(struct pt_regs * regs)
-{
- /* We either use rdusp() - the USP register, which might not
- correspond to the current process for all cases we're called,
- or we use the current->thread.usp, which is not up to date for
- the current process. Experience shows we want the USP
- register. */
- unsigned long usp = rdusp();
-
- printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
- regs->irp, regs->srp, regs->dccr, usp, regs->mof );
- printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
- regs->r0, regs->r1, regs->r2, regs->r3);
- printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
- regs->r4, regs->r5, regs->r6, regs->r7);
- printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
- regs->r8, regs->r9, regs->r10, regs->r11);
- printk("r12: %08lx r13: %08lx oR10: %08lx\n",
- regs->r12, regs->r13, regs->orig_r10);
- printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
- printk("Process %s (pid: %d, stackpage=%08lx)\n",
- current->comm, current->pid, (unsigned long)current);
-
- /*
- * When in-kernel, we also print out the stack and code at the
- * time of the fault..
- */
- if (! user_mode(regs)) {
- int i;
-
- show_stack((unsigned long*)usp);
-
- /* Dump kernel stack if the previous dump wasn't one. */
- if (usp != 0)
- show_stack (NULL);
-
- printk("\nCode: ");
- if(regs->irp < PAGE_OFFSET)
- goto bad;
-
- /* Often enough the value at regs->irp does not point to
- the interesting instruction, which is most often the
- _previous_ instruction. So we dump at an offset large
- enough that instruction decoding should be in sync at
- the interesting point, but small enough to fit on a row
- (sort of). We point out the regs->irp location in a
- ksymoops-friendly way by wrapping the byte for that
- address in parentheses. */
- for(i = -12; i < 12; i++)
- {
- unsigned char c;
- if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
-bad:
- printk(" Bad IP value.");
- break;
- }
-
- if (i == 0)
- printk("(%02x) ", c);
- else
- printk("%02x ", c);
- }
- printk("\n");
- }
-}
-
-/* Called from entry.S when the watchdog has bitten
- * We print out something resembling an oops dump, and if
- * we have the nice doggy development flag set, we halt here
- * instead of rebooting.
- */
-
-void
-watchdog_bite_hook(struct pt_regs *regs)
-{
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- cli();
- stop_watchdog();
- show_registers(regs);
- while(1) /* nothing */;
-#else
- show_registers(regs);
-#endif
-}
-
void dump_stack(void)
{
- show_stack(NULL);
-}
-
-/* This is normally the 'Oops' routine */
-void
-die_if_kernel(const char * str, struct pt_regs * regs, long err)
-{
- extern void reset_watchdog(void);
- extern void stop_watchdog(void);
-
- if(user_mode(regs))
- return;
-
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- /* This printout might take too long and trigger the
- * watchdog normally. If we're in the nice doggy
- * development mode, stop the watchdog during printout.
- */
- stop_watchdog();
-#endif
-
- printk("%s: %04lx\n", str, err & 0xffff);
-
- show_registers(regs);
-
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- reset_watchdog();
-#endif
- do_exit(SIGSEGV);
+ show_stack(NULL, NULL);
}
void __init
diff --git a/arch/cris/mm/Makefile b/arch/cris/mm/Makefile
index 5a92ec53ca3d..f3790c7e41ae 100644
--- a/arch/cris/mm/Makefile
+++ b/arch/cris/mm/Makefile
@@ -3,3 +3,4 @@
#
obj-y := init.o fault.o tlb.o extable.o ioremap.o
+
diff --git a/arch/cris/mm/extable.c b/arch/cris/mm/extable.c
index 7351f59f8bb9..7992bdb4fea1 100644
--- a/arch/cris/mm/extable.c
+++ b/arch/cris/mm/extable.c
@@ -2,8 +2,18 @@
* linux/arch/cris/mm/extable.c
*
* $Log: extable.c,v $
- * Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
- * Import of Linux 2.5.1
+ * Revision 1.4 2003/01/09 14:42:52 starvik
+ * Merge of Linux 2.5.55
+ *
+ * Revision 1.3 2002/11/21 07:24:54 starvik
+ * Made search_exception_table similar to implementation for other archs
+ * (now compiles with CONFIG_MODULES)
+ *
+ * Revision 1.2 2002/11/18 07:36:55 starvik
+ * Removed warning
+ *
+ * Revision 1.1 2001/12/17 13:59:27 bjornw
+ * Initial revision
*
* Revision 1.3 2001/09/27 13:52:40 bjornw
* Harmonize underscore-ness with other parts
@@ -15,13 +25,11 @@
#include <linux/module.h>
#include <asm/uaccess.h>
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
{
while (first <= last) {
const struct exception_table_entry *mid;
@@ -30,34 +38,11 @@ search_one_table(const struct exception_table_entry *first,
mid = (last - first) / 2 + first;
diff = mid->insn - value;
if (diff == 0)
- return mid->fixup;
+ return mid;
else if (diff < 0)
first = mid+1;
else
last = mid-1;
}
- return 0;
-}
-
-unsigned long
-search_exception_table(unsigned long addr)
-{
- unsigned long ret;
-
-#ifndef CONFIG_MODULES
- /* There is only the kernel to search. */
- return search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-#else
- /* The kernel is the last "module" -- no need to treat it special. */
- struct module *mp;
- for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->ex_table_start == NULL)
- continue;
- ret = search_one_table(mp->ex_table_start,
- mp->ex_table_end - 1, addr);
- if (ret) return ret;
- }
-#endif
-
- return 0;
+ return NULL;
}
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c
index 2e4d91e40cf9..1af6f3a49dad 100644
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -6,6 +6,25 @@
* Authors: Bjorn Wesen
*
* $Log: fault.c,v $
+ * Revision 1.8 2003/07/04 13:02:48 tobiasa
+ * Moved code snippet from arch/cris/mm/fault.c that searches for fixup code
+ * to seperate function in arch-specific files.
+ *
+ * Revision 1.7 2003/01/22 06:48:38 starvik
+ * Fixed warnings issued by GCC 3.2.1
+ *
+ * Revision 1.6 2003/01/09 14:42:52 starvik
+ * Merge of Linux 2.5.55
+ *
+ * Revision 1.5 2002/12/11 14:44:48 starvik
+ * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/mm
+ *
+ * Revision 1.4 2002/11/13 15:10:28 starvik
+ * pte_offset has been renamed to pte_offset_kernel
+ *
+ * Revision 1.3 2002/11/05 06:45:13 starvik
+ * Merge of Linux 2.5.45
+ *
* Revision 1.2 2001/12/18 13:35:22 bjornw
* Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
*
@@ -68,24 +87,13 @@
*
*/
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/pgtable.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
-#include <asm/svinto.h>
-extern void die_if_kernel(const char *,struct pt_regs *,long);
+extern int find_fixup_code(struct pt_regs *);
+extern void die_if_kernel(const char *, struct pt_regs *, long);
asmlinkage void do_invalid_op (struct pt_regs *, unsigned long);
asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs,
@@ -107,127 +115,6 @@ asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs,
volatile pgd_t *current_pgd;
-/* fast TLB-fill fault handler
- * this is called from entry.S with interrupts disabled
- */
-
-void
-handle_mmu_bus_fault(struct pt_regs *regs)
-{
- int cause, select;
-#ifdef DEBUG
- int index;
- int page_id;
- int acc, inv;
-#endif
- int miss, we, writeac;
- pmd_t *pmd;
- pte_t pte;
- int errcode;
- unsigned long address;
-
- cause = *R_MMU_CAUSE;
- select = *R_TLB_SELECT;
-
- address = cause & PAGE_MASK; /* get faulting address */
-
-#ifdef DEBUG
- page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause);
- acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause);
- inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause);
- index = IO_EXTRACT(R_TLB_SELECT, index, select);
-#endif
- miss = IO_EXTRACT(R_MMU_CAUSE, miss_excp, cause);
- we = IO_EXTRACT(R_MMU_CAUSE, we_excp, cause);
- writeac = IO_EXTRACT(R_MMU_CAUSE, wr_rd, cause);
-
- /* ETRAX 100LX TR89 bugfix: if the second half of an unaligned
- * write causes a MMU-fault, it will not be restarted correctly.
- * This could happen if a write crosses a page-boundary and the
- * second page is not yet COW'ed or even loaded. The workaround
- * is to clear the unaligned bit in the CPU status record, so
- * that the CPU will rerun both the first and second halves of
- * the instruction. This will not have any sideeffects unless
- * the first half goes to any device or memory that can't be
- * written twice, and which is mapped through the MMU.
- *
- * We only need to do this for writes.
- */
-
- if(writeac)
- regs->csrinstr &= ~(1 << 5);
-
- /* Set errcode's R/W flag according to the mode which caused the
- * fault
- */
-
- errcode = writeac << 1;
-
- D(printk("bus_fault from IRP 0x%lx: addr 0x%lx, miss %d, inv %d, we %d, acc %d, dx %d pid %d\n",
- regs->irp, address, miss, inv, we, acc, index, page_id));
-
- /* for a miss, we need to reload the TLB entry */
-
- if (miss) {
- /* see if the pte exists at all
- * refer through current_pgd, don't use mm->pgd
- */
-
- pmd = (pmd_t *)(current_pgd + pgd_index(address));
- if (pmd_none(*pmd))
- goto dofault;
- if (pmd_bad(*pmd)) {
- printk("bad pgdir entry 0x%lx at 0x%p\n", *(unsigned long*)pmd, pmd);
- pmd_clear(pmd);
- return;
- }
- pte = *pte_offset(pmd, address);
- if (!pte_present(pte))
- goto dofault;
-
-#ifdef DEBUG
- printk(" found pte %lx pg %p ", pte_val(pte), pte_page(pte));
- if (pte_val(pte) & _PAGE_SILENT_WRITE)
- printk("Silent-W ");
- if (pte_val(pte) & _PAGE_KERNEL)
- printk("Kernel ");
- if (pte_val(pte) & _PAGE_SILENT_READ)
- printk("Silent-R ");
- if (pte_val(pte) & _PAGE_GLOBAL)
- printk("Global ");
- if (pte_val(pte) & _PAGE_PRESENT)
- printk("Present ");
- if (pte_val(pte) & _PAGE_ACCESSED)
- printk("Accessed ");
- if (pte_val(pte) & _PAGE_MODIFIED)
- printk("Modified ");
- if (pte_val(pte) & _PAGE_READ)
- printk("Readable ");
- if (pte_val(pte) & _PAGE_WRITE)
- printk("Writeable ");
- printk("\n");
-#endif
-
- /* load up the chosen TLB entry
- * this assumes the pte format is the same as the TLB_LO layout.
- *
- * the write to R_TLB_LO also writes the vpn and page_id fields from
- * R_MMU_CAUSE, which we in this case obviously want to keep
- */
-
- *R_TLB_LO = pte_val(pte);
-
- return;
- }
-
- errcode = 1 | (we << 1);
-
- dofault:
- /* leave it to the MM system fault handler below */
- D(printk("do_page_fault %lx errcode %d\n", address, errcode));
- do_page_fault(address, regs, errcode);
-}
-
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
@@ -253,7 +140,6 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
struct mm_struct *mm;
struct vm_area_struct * vma;
int writeaccess;
- unsigned long fixup;
siginfo_t info;
tsk = current;
@@ -391,20 +277,8 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
* code)
*/
- if ((fixup = search_exception_table(regs->irp)) != 0) {
- /* Adjust the instruction pointer in the stackframe */
-
- regs->irp = fixup;
-
- /* We do not want to return by restoring the CPU-state
- * anymore, so switch frame-types (see ptrace.h)
- */
-
- regs->frametype = CRIS_FRAME_NORMAL;
-
- D(printk("doing fixup to 0x%lx\n", fixup));
+ if (find_fixup_code(regs))
return;
- }
/*
* Oops. The kernel tried to access some bad page. We'll have to
@@ -498,7 +372,7 @@ vmalloc_fault:
* silently loop forever.
*/
- pte_k = pte_offset(pmd_k, address);
+ pte_k = pte_offset_kernel(pmd_k, address);
if (!pte_present(*pte_k))
goto no_context;
diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c
index d9ab23bacb2b..3ff9bfcb8194 100644
--- a/arch/cris/mm/init.c
+++ b/arch/cris/mm/init.c
@@ -7,6 +7,27 @@
* Authors: Bjorn Wesen (bjornw@axis.com)
*
* $Log: init.c,v $
+ * Revision 1.9 2003/07/04 08:27:54 starvik
+ * Merge of Linux 2.5.74
+ *
+ * Revision 1.8 2003/04/09 05:20:48 starvik
+ * Merge of Linux 2.5.67
+ *
+ * Revision 1.7 2003/01/22 06:48:38 starvik
+ * Fixed warnings issued by GCC 3.2.1
+ *
+ * Revision 1.6 2002/12/11 14:44:48 starvik
+ * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/mm
+ *
+ * Revision 1.5 2002/11/18 07:37:37 starvik
+ * Added cache bug workaround (from Linux 2.4)
+ *
+ * Revision 1.4 2002/11/13 15:40:24 starvik
+ * Removed the page table cache stuff (as done in other archs)
+ *
+ * Revision 1.3 2002/11/05 06:45:13 starvik
+ * Merge of Linux 2.5.45
+ *
* Revision 1.2 2001/12/18 13:35:22 bjornw
* Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
*
@@ -91,65 +112,19 @@
*
*/
-#include <linux/config.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/smp.h>
+#include <linux/init.h>
#include <linux/bootmem.h>
+#include <asm/tlb.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/dma.h>
-#include <asm/svinto.h>
-#include <asm/io.h>
-#include <asm/mmu_context.h>
-
-struct pgtable_cache_struct quicklists; /* see asm/pgalloc.h */
-
-const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
-
-extern void die_if_kernel(char *,struct pt_regs *,long);
-extern void show_net_buffers(void);
-extern void tlb_init(void);
-
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
unsigned long empty_zero_page;
-/* trim the page-table cache if necessary */
-
-int
-do_check_pgt_cache(int low, int high)
-{
- int freed = 0;
+extern unsigned long loops_per_jiffy; /* init/main.c */
+unsigned long loops_per_usec;
- if(pgtable_cache_size > high) {
- do {
- if(pgd_quicklist) {
- free_pgd_slow(get_pgd_fast());
- freed++;
- }
- if(pmd_quicklist) {
- pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
- freed++;
- }
- if(pte_quicklist) {
- pte_free_slow(pte_alloc_one_fast(NULL, 0));
- freed++;
- }
- } while(pgtable_cache_size > low);
- }
- return freed;
-}
+extern char _stext, _edata, _etext; /* From linkerscript */
+extern char __init_begin, __init_end;
void
show_mem(void)
@@ -180,181 +155,8 @@ show_mem(void)
printk("%d pages nonshared\n",nonshared);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
- printk("%ld pages in page table cache\n",pgtable_cache_size);
}
-/*
- * The kernel is already mapped with a kernel segment at kseg_c so
- * we don't need to map it with a page table. However head.S also
- * temporarily mapped it at kseg_4 so we should set up the ksegs again,
- * clear the TLB and do some other paging setup stuff.
- */
-
-void __init
-paging_init(void)
-{
- int i;
- unsigned long zones_size[MAX_NR_ZONES];
-
- printk("Setting up paging and the MMU.\n");
-
- /* clear out the init_mm.pgd that will contain the kernel's mappings */
-
- for(i = 0; i < PTRS_PER_PGD; i++)
- swapper_pg_dir[i] = __pgd(0);
-
- /* make sure the current pgd table points to something sane
- * (even if it is most probably not used until the next
- * switch_mm)
- */
-
- current_pgd = init_mm.pgd;
-
- /* initialise the TLB (tlb.c) */
-
- tlb_init();
-
- /* see README.mm for details on the KSEG setup */
-
-#ifndef CONFIG_CRIS_LOW_MAP
- /* This code is for the corrected Etrax-100 LX version 2... */
-
- *R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg ) | /* cached flash */
- IO_STATE(R_MMU_KSEG, seg_e, seg ) | /* uncached flash */
- IO_STATE(R_MMU_KSEG, seg_d, page ) | /* vmalloc area */
- IO_STATE(R_MMU_KSEG, seg_c, seg ) | /* kernel area */
- IO_STATE(R_MMU_KSEG, seg_b, seg ) | /* kernel reg area */
- IO_STATE(R_MMU_KSEG, seg_a, page ) | /* user area */
- IO_STATE(R_MMU_KSEG, seg_9, page ) |
- IO_STATE(R_MMU_KSEG, seg_8, page ) |
- IO_STATE(R_MMU_KSEG, seg_7, page ) |
- IO_STATE(R_MMU_KSEG, seg_6, page ) |
- IO_STATE(R_MMU_KSEG, seg_5, page ) |
- IO_STATE(R_MMU_KSEG, seg_4, page ) |
- IO_STATE(R_MMU_KSEG, seg_3, page ) |
- IO_STATE(R_MMU_KSEG, seg_2, page ) |
- IO_STATE(R_MMU_KSEG, seg_1, page ) |
- IO_STATE(R_MMU_KSEG, seg_0, page ) );
-
- *R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_c, 0x4 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
- IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) );
-
- *R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_6, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
-#else
- /* Etrax-100 LX version 1 has a bug so that we cannot map anything
- * across the 0x80000000 boundary, so we need to shrink the user-virtual
- * area to 0x50000000 instead of 0xb0000000 and map things slightly
- * different. The unused areas are marked as paged so that we can catch
- * freak kernel accesses there.
- *
- * The ARTPEC chip is mapped at 0xa so we pass that segment straight
- * through. We cannot vremap it because the vmalloc area is below 0x8
- * and Juliette needs an uncached area above 0x8.
- *
- * Same thing with 0xc and 0x9, which is memory-mapped I/O on some boards.
- * We map them straight over in LOW_MAP, but use vremap in LX version 2.
- */
-
- *R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, page ) |
- IO_STATE(R_MMU_KSEG, seg_e, page ) |
- IO_STATE(R_MMU_KSEG, seg_d, page ) |
- IO_STATE(R_MMU_KSEG, seg_c, page ) |
- IO_STATE(R_MMU_KSEG, seg_b, seg ) | /* kernel reg area */
-#ifdef CONFIG_JULIETTE
- IO_STATE(R_MMU_KSEG, seg_a, seg ) | /* ARTPEC etc. */
-#else
- IO_STATE(R_MMU_KSEG, seg_a, page ) |
-#endif
- IO_STATE(R_MMU_KSEG, seg_9, seg ) | /* LED's on some boards */
- IO_STATE(R_MMU_KSEG, seg_8, seg ) | /* CSE0/1, flash and I/O */
- IO_STATE(R_MMU_KSEG, seg_7, page ) | /* kernel vmalloc area */
- IO_STATE(R_MMU_KSEG, seg_6, seg ) | /* kernel DRAM area */
- IO_STATE(R_MMU_KSEG, seg_5, seg ) | /* cached flash */
- IO_STATE(R_MMU_KSEG, seg_4, page ) | /* user area */
- IO_STATE(R_MMU_KSEG, seg_3, page ) | /* user area */
- IO_STATE(R_MMU_KSEG, seg_2, page ) | /* user area */
- IO_STATE(R_MMU_KSEG, seg_1, page ) | /* user area */
- IO_STATE(R_MMU_KSEG, seg_0, page ) ); /* user area */
-
- *R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_e, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_c, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
-#ifdef CONFIG_JULIETTE
- IO_FIELD(R_MMU_KBASE_HI, base_a, 0xa ) |
-#else
- IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) |
-#endif
- IO_FIELD(R_MMU_KBASE_HI, base_9, 0x9 ) |
- IO_FIELD(R_MMU_KBASE_HI, base_8, 0x8 ) );
-
- *R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_6, 0x4 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
- IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
-#endif
-
- *R_MMU_CONTEXT = ( IO_FIELD(R_MMU_CONTEXT, page_id, 0 ) );
-
- /* The MMU has been enabled ever since head.S but just to make
- * it totally obvious we do it here as well.
- */
-
- *R_MMU_CTRL = ( IO_STATE(R_MMU_CTRL, inv_excp, enable ) |
- IO_STATE(R_MMU_CTRL, acc_excp, enable ) |
- IO_STATE(R_MMU_CTRL, we_excp, enable ) );
-
- *R_MMU_ENABLE = IO_STATE(R_MMU_ENABLE, mmu_enable, enable);
-
- /*
- * initialize the bad page table and bad page to point
- * to a couple of allocated pages
- */
-
- empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
- memset((void *)empty_zero_page, 0, PAGE_SIZE);
-
- /* All pages are DMA'able in Etrax, so put all in the DMA'able zone */
-
- zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
-
- for (i = 1; i < MAX_NR_ZONES; i++)
- zones_size[i] = 0;
-
- /* Use free_area_init_node instead of free_area_init, because the former
- * is designed for systems where the DRAM starts at an address substantially
- * higher than 0, like us (we start at PAGE_OFFSET). This saves space in the
- * mem_map page array.
- */
-
- free_area_init_node(0, &contig_page_data, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
- mem_map = contig_page_data.node_mem_map;
-}
-
-extern unsigned long loops_per_jiffy; /* init/main.c */
-unsigned long loops_per_usec;
-
-extern char _stext, _edata, _etext;
-extern char __init_begin, __init_end;
-
void __init
mem_init(void)
{
@@ -409,48 +211,6 @@ mem_init(void)
return;
}
-/* Initialize remaps of some I/O-ports. This is designed to be callable
- * multiple times from the drivers init-sections, because we don't know
- * beforehand which driver will get initialized first.
- */
-
-void
-init_ioremap(void)
-{
-
- /* Give the external I/O-port addresses their values */
-
- static int initialized = 0;
-
- if( !initialized ) {
- initialized++;
-
-#ifdef CONFIG_CRIS_LOW_MAP
- /* Simply a linear map (see the KSEG map above in paging_init) */
- port_cse1_addr = (volatile unsigned long *)(MEM_CSE1_START |
- MEM_NON_CACHEABLE);
- port_csp0_addr = (volatile unsigned long *)(MEM_CSP0_START |
- MEM_NON_CACHEABLE);
- port_csp4_addr = (volatile unsigned long *)(MEM_CSP4_START |
- MEM_NON_CACHEABLE);
-#else
- /* Note that nothing blows up just because we do this remapping
- * it's ok even if the ports are not used or connected
- * to anything (or connected to a non-I/O thing) */
- port_cse1_addr = (volatile unsigned long *)
- ioremap((unsigned long)(MEM_CSE1_START |
- MEM_NON_CACHEABLE), 16);
- port_csp0_addr = (volatile unsigned long *)
- ioremap((unsigned long)(MEM_CSP0_START |
- MEM_NON_CACHEABLE), 16);
- port_csp4_addr = (volatile unsigned long *)
- ioremap((unsigned long)(MEM_CSP4_START |
- MEM_NON_CACHEABLE), 16);
-#endif
- }
-}
-
-
/* free the pages occupied by initialization code */
void
@@ -466,5 +226,5 @@ free_initmem(void)
totalram_pages++;
}
printk ("Freeing unused kernel memory: %luk freed\n",
- (&__init_end - &__init_begin) >> 10);
+ (unsigned long)((&__init_end - &__init_begin) >> 10));
}
diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c
index 53656f9c5dc4..14216d9668f9 100644
--- a/arch/cris/mm/ioremap.c
+++ b/arch/cris/mm/ioremap.c
@@ -12,12 +12,13 @@
#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
{
unsigned long end;
- unsigned long pfn;
address &= ~PMD_MASK;
end = address + size;
@@ -25,17 +26,16 @@ static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
end = PMD_SIZE;
if (address >= end)
BUG();
- pfn = phys_addr >> PAGE_SHIFT;
do {
if (!pte_none(*pte)) {
printk("remap_area_pte: page already exists\n");
BUG();
}
- set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | __READABLE |
- __WRITEABLE | _PAGE_GLOBAL |
- _PAGE_KERNEL | flags)));
+ set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | __READABLE |
+ __WRITEABLE | _PAGE_GLOBAL |
+ _PAGE_KERNEL | flags)));
address += PAGE_SIZE;
- pfn++;
+ phys_addr += PAGE_SIZE;
pte++;
} while (address && (address < end));
}
@@ -53,7 +53,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
if (address >= end)
BUG();
do {
- pte_t * pte = pte_alloc(&init_mm, pmd, address);
+ pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
if (!pte)
return -ENOMEM;
remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -148,7 +148,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
*/
offset = phys_addr & ~PAGE_MASK;
phys_addr &= PAGE_MASK;
- size = PAGE_ALIGN(last_addr) - phys_addr;
+ size = PAGE_ALIGN(last_addr+1) - phys_addr;
/*
* Ok, go for it..
diff --git a/arch/cris/mm/tlb.c b/arch/cris/mm/tlb.c
index f5a97c9799fd..23eca5ad7389 100644
--- a/arch/cris/mm/tlb.c
+++ b/arch/cris/mm/tlb.c
@@ -7,31 +7,11 @@
*
*/
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/pgtable.h>
-#include <asm/svinto.h>
-#include <asm/mmu_context.h>
+#include <asm/tlb.h>
#define D(x)
-/* CRIS in Etrax100LX TLB */
-
-#define NUM_TLB_ENTRIES 64
-#define NUM_PAGEID 64
-#define INVALID_PAGEID 63
-#define NO_CONTEXT -1
-
/* The TLB can host up to 64 different mm contexts at the same time.
* The running context is R_MMU_CONTEXT, and each TLB entry contains a
* page_id that has to match to give a hit. In page_id_map, we keep track
@@ -47,182 +27,8 @@
*/
struct mm_struct *page_id_map[NUM_PAGEID];
-
static int map_replace_ptr = 1; /* which page_id_map entry to replace next */
-/* invalidate all TLB entries */
-
-void
-flush_tlb_all(void)
-{
- int i;
- unsigned long flags;
-
- /* the vpn of i & 0xf is so we don't write similar TLB entries
- * in the same 4-way entry group. details..
- */
-
- save_and_cli(flags); /* flush needs to be atomic */
- for(i = 0; i < NUM_TLB_ENTRIES; i++) {
- *R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
- *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
- IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
-
- *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
- IO_STATE(R_TLB_LO, valid, no ) |
- IO_STATE(R_TLB_LO, kernel,no ) |
- IO_STATE(R_TLB_LO, we, no ) |
- IO_FIELD(R_TLB_LO, pfn, 0 ) );
- }
- restore_flags(flags);
- D(printk("tlb: flushed all\n"));
-}
-
-/* invalidate the selected mm context only */
-
-void
-flush_tlb_mm(struct mm_struct *mm)
-{
- int i;
- int page_id = mm->context;
- unsigned long flags;
-
- D(printk("tlb: flush mm context %d (%p)\n", page_id, mm));
-
- if(page_id == NO_CONTEXT)
- return;
-
- /* mark the TLB entries that match the page_id as invalid.
- * here we could also check the _PAGE_GLOBAL bit and NOT flush
- * global pages. is it worth the extra I/O ?
- */
-
- save_and_cli(flags); /* flush needs to be atomic */
- for(i = 0; i < NUM_TLB_ENTRIES; i++) {
- *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
- if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
- *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
- IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
-
- *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
- IO_STATE(R_TLB_LO, valid, no ) |
- IO_STATE(R_TLB_LO, kernel,no ) |
- IO_STATE(R_TLB_LO, we, no ) |
- IO_FIELD(R_TLB_LO, pfn, 0 ) );
- }
- }
- restore_flags(flags);
-}
-
-/* invalidate a single page */
-
-void
-flush_tlb_page(struct vm_area_struct *vma,
- unsigned long addr)
-{
- struct mm_struct *mm = vma->vm_mm;
- int page_id = mm->context;
- int i;
- unsigned long flags;
-
- D(printk("tlb: flush page %p in context %d (%p)\n", addr, page_id, mm));
-
- if(page_id == NO_CONTEXT)
- return;
-
- addr &= PAGE_MASK; /* perhaps not necessary */
-
- /* invalidate those TLB entries that match both the mm context
- * and the virtual address requested
- */
-
- save_and_cli(flags); /* flush needs to be atomic */
- for(i = 0; i < NUM_TLB_ENTRIES; i++) {
- unsigned long tlb_hi;
- *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
- tlb_hi = *R_TLB_HI;
- if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
- (tlb_hi & PAGE_MASK) == addr) {
- *R_TLB_HI = IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
- addr; /* same addr as before works. */
-
- *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
- IO_STATE(R_TLB_LO, valid, no ) |
- IO_STATE(R_TLB_LO, kernel,no ) |
- IO_STATE(R_TLB_LO, we, no ) |
- IO_FIELD(R_TLB_LO, pfn, 0 ) );
- }
- }
- restore_flags(flags);
-}
-
-/* invalidate a page range */
-
-void
-flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start,
- unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- int page_id = mm->context;
- int i;
- unsigned long flags;
-
- D(printk("tlb: flush range %p<->%p in context %d (%p)\n",
- start, end, page_id, mm));
-
- if(page_id == NO_CONTEXT)
- return;
-
- start &= PAGE_MASK; /* probably not necessary */
- end &= PAGE_MASK; /* dito */
-
- /* invalidate those TLB entries that match both the mm context
- * and the virtual address range
- */
-
- save_and_cli(flags); /* flush needs to be atomic */
- for(i = 0; i < NUM_TLB_ENTRIES; i++) {
- unsigned long tlb_hi, vpn;
- *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
- tlb_hi = *R_TLB_HI;
- vpn = tlb_hi & PAGE_MASK;
- if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
- vpn >= start && vpn < end) {
- *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
- IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
-
- *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
- IO_STATE(R_TLB_LO, valid, no ) |
- IO_STATE(R_TLB_LO, kernel,no ) |
- IO_STATE(R_TLB_LO, we, no ) |
- IO_FIELD(R_TLB_LO, pfn, 0 ) );
- }
- }
- restore_flags(flags);
-}
-
-/* dump the entire TLB for debug purposes */
-
-#if 0
-void
-dump_tlb_all(void)
-{
- int i;
- unsigned long flags;
-
- printk("TLB dump. LO is: pfn | reserved | global | valid | kernel | we |\n");
-
- save_and_cli(flags);
- for(i = 0; i < NUM_TLB_ENTRIES; i++) {
- *R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
- printk("Entry %d: HI 0x%08lx, LO 0x%08lx\n",
- i, *R_TLB_HI, *R_TLB_LO);
- }
- restore_flags(flags);
-}
-#endif
-
/*
* Initialize the context related info for a new mm_struct
* instance.
@@ -279,33 +85,6 @@ get_mmu_context(struct mm_struct *mm)
alloc_context(mm);
}
-/* called in schedule() just before actually doing the switch_to */
-
-void
-switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, int cpu)
-{
- /* make sure we have a context */
-
- get_mmu_context(next);
-
- /* remember the pgd for the fault handlers
- * this is similar to the pgd register in some other CPU's.
- * we need our own copy of it because current and active_mm
- * might be invalid at points where we still need to derefer
- * the pgd.
- */
-
- current_pgd = next->pgd;
-
- /* switch context in the MMU */
-
- D(printk("switching mmu_context to %d (%p)\n", next->context, next));
-
- *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context);
-}
-
-
/* called by __exit_mm to destroy the used MMU context if any before
* destroying the mm itself. this is only called when the last user of the mm
* drops it.
diff --git a/include/asm-cris/arch-v10/bitops.h b/include/asm-cris/arch-v10/bitops.h
new file mode 100644
index 000000000000..21b7ae8c9bb3
--- /dev/null
+++ b/include/asm-cris/arch-v10/bitops.h
@@ -0,0 +1,73 @@
+/* asm/arch/bitops.h for Linux/CRISv10 */
+
+#ifndef _CRIS_ARCH_BITOPS_H
+#define _CRIS_ARCH_BITOPS_H
+
+/*
+ * Helper functions for the core of the ff[sz] functions, wrapping the
+ * syntactically awkward asms. The asms compute the number of leading
+ * zeroes of a bits-in-byte and byte-in-word and word-in-dword-swapped
+ * number. They differ in that the first function also inverts all bits
+ * in the input.
+ */
+extern inline unsigned long cris_swapnwbrlz(unsigned long w)
+{
+ /* Let's just say we return the result in the same register as the
+ input. Saying we clobber the input but can return the result
+ in another register:
+ ! __asm__ ("swapnwbr %2\n\tlz %2,%0"
+ ! : "=r,r" (res), "=r,X" (dummy) : "1,0" (w));
+ confuses gcc (sched.c, gcc from cris-dist-1.14). */
+
+ unsigned long res;
+ __asm__ ("swapnwbr %0 \n\t"
+ "lz %0,%0"
+ : "=r" (res) : "0" (w));
+ return res;
+}
+
+extern inline unsigned long cris_swapwbrlz(unsigned long w)
+{
+ unsigned res;
+ __asm__ ("swapwbr %0 \n\t"
+ "lz %0,%0"
+ : "=r" (res)
+ : "0" (w));
+ return res;
+}
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+extern inline unsigned long ffz(unsigned long w)
+{
+ return cris_swapnwbrlz(w);
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+extern __inline__ unsigned long __ffs(unsigned long word)
+{
+ return cris_swapnwbrlz(~word);
+}
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+extern inline unsigned long kernel_ffs(unsigned long w)
+{
+ return w ? cris_swapwbrlz (w) + 1 : 0;
+}
+
+#endif
diff --git a/include/asm-cris/arch-v10/byteorder.h b/include/asm-cris/arch-v10/byteorder.h
new file mode 100644
index 000000000000..bac946459b81
--- /dev/null
+++ b/include/asm-cris/arch-v10/byteorder.h
@@ -0,0 +1,25 @@
+#ifndef _CRIS_ARCH_BYTEORDER_H
+#define _CRIS_ARCH_BYTEORDER_H
+
+#include <asm/types.h>
+
+/* we just define these two (as we can do the swap in a single
+ * asm instruction in CRIS) and the arch-independent files will put
+ * them together into ntohl etc.
+ */
+
+extern __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+ __asm__ ("swapwb %0" : "=r" (x) : "0" (x));
+
+ return(x);
+}
+
+extern __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+ __asm__ ("swapb %0" : "=r" (x) : "0" (x));
+
+ return(x);
+}
+
+#endif
diff --git a/include/asm-cris/arch-v10/cache.h b/include/asm-cris/arch-v10/cache.h
new file mode 100644
index 000000000000..1e796271ea5e
--- /dev/null
+++ b/include/asm-cris/arch-v10/cache.h
@@ -0,0 +1,8 @@
+#ifndef _ASM_ARCH_CACHE_H
+#define _ASM_ARCH_CACHE_H
+
+/* Etrax 100LX have 32-byte cache-lines. */
+#define L1_CACHE_BYTES 32
+#define L1_CACHE_SHIFT_MAX 5
+
+#endif /* _ASM_ARCH_CACHE_H */
diff --git a/include/asm-cris/arch-v10/checksum.h b/include/asm-cris/arch-v10/checksum.h
new file mode 100644
index 000000000000..fde1d00aaa90
--- /dev/null
+++ b/include/asm-cris/arch-v10/checksum.h
@@ -0,0 +1,29 @@
+#ifndef _CRIS_ARCH_CHECKSUM_H
+#define _CRIS_ARCH_CHECKSUM_H
+
+/* Checksum some values used in TCP/UDP headers.
+ *
+ * The gain by doing this in asm is that C will not generate carry-additions
+ * for the 32-bit components of the checksum, so otherwise we would have had
+ * to split all of those into 16-bit components, then add.
+ */
+
+extern inline unsigned int
+csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
+ unsigned short proto, unsigned int sum)
+{
+ int res;
+ __asm__ ("add.d %2, %0\n\t"
+ "ax\n\t"
+ "add.d %3, %0\n\t"
+ "ax\n\t"
+ "add.d %4, %0\n\t"
+ "ax\n\t"
+ "addq 0, %0\n"
+ : "=r" (res)
+ : "0" (sum), "r" (daddr), "r" (saddr), "r" ((ntohs(len) << 16) + (proto << 8)));
+
+ return res;
+}
+
+#endif
diff --git a/include/asm-cris/arch-v10/delay.h b/include/asm-cris/arch-v10/delay.h
new file mode 100644
index 000000000000..cfedae0d2f53
--- /dev/null
+++ b/include/asm-cris/arch-v10/delay.h
@@ -0,0 +1,20 @@
+#ifndef _CRIS_ARCH_DELAY_H
+#define _CRIS_ARCH_DELAY_H
+
+extern __inline__ void __delay(int loops)
+{
+ __asm__ __volatile__ (
+ "move.d %0,$r9\n\t"
+ "beq 2f\n\t"
+ "subq 1,$r9\n\t"
+ "1:\n\t"
+ "bne 1b\n\t"
+ "subq 1,$r9\n"
+ "2:"
+ : : "g" (loops) : "r9");
+}
+
+#endif /* defined(_CRIS_ARCH_DELAY_H) */
+
+
+
diff --git a/include/asm-cris/arch-v10/dma.h b/include/asm-cris/arch-v10/dma.h
new file mode 100644
index 000000000000..9e078b9bc934
--- /dev/null
+++ b/include/asm-cris/arch-v10/dma.h
@@ -0,0 +1,46 @@
+/* Defines for using and allocating dma channels. */
+
+#ifndef _ASM_ARCH_DMA_H
+#define _ASM_ARCH_DMA_H
+
+#define MAX_DMA_CHANNELS 10
+
+/* dma0 and dma1 used for network (ethernet) */
+#define NETWORK_TX_DMA_NBR 0
+#define NETWORK_RX_DMA_NBR 1
+
+/* dma2 and dma3 shared by par0, scsi0, ser2 and ata */
+#define PAR0_TX_DMA_NBR 2
+#define PAR0_RX_DMA_NBR 3
+#define SCSI0_TX_DMA_NBR 2
+#define SCSI0_RX_DMA_NBR 3
+#define SER2_TX_DMA_NBR 2
+#define SER2_RX_DMA_NBR 3
+#define ATA_TX_DMA_NBR 2
+#define ATA_RX_DMA_NBR 3
+
+/* dma4 and dma5 shared by par1, scsi1, ser3 and extdma0 */
+#define PAR1_TX_DMA_NBR 4
+#define PAR1_RX_DMA_NBR 5
+#define SCSI1_TX_DMA_NBR 4
+#define SCSI1_RX_DMA_NBR 5
+#define SER3_TX_DMA_NBR 4
+#define SER3_RX_DMA_NBR 5
+#define EXTDMA0_TX_DMA_NBR 4
+#define EXTDMA0_RX_DMA_NBR 5
+
+/* dma6 and dma7 shared by ser0, extdma1 and mem2mem */
+#define SER0_TX_DMA_NBR 6
+#define SER0_RX_DMA_NBR 7
+#define EXTDMA1_TX_DMA_NBR 6
+#define EXTDMA1_RX_DMA_NBR 7
+#define MEM2MEM_TX_DMA_NBR 6
+#define MEM2MEM_RX_DMA_NBR 7
+
+/* dma8 and dma9 shared by ser1 and usb */
+#define SER1_TX_DMA_NBR 8
+#define SER1_RX_DMA_NBR 9
+#define USB_TX_DMA_NBR 8
+#define USB_RX_DMA_NBR 9
+
+#endif
diff --git a/include/asm-cris/arch-v10/elf.h b/include/asm-cris/arch-v10/elf.h
new file mode 100644
index 000000000000..2a2201ca538e
--- /dev/null
+++ b/include/asm-cris/arch-v10/elf.h
@@ -0,0 +1,71 @@
+#ifndef __ASMCRIS_ARCH_ELF_H
+#define __ASMCRIS_ARCH_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
+ starts (a register; assume first param register for CRIS)
+ contains a pointer to a function which might be
+ registered using `atexit'. This provides a mean for the
+ dynamic linker to call DT_FINI functions for shared libraries
+ that have been loaded before the code runs.
+
+ A value of 0 tells we have no such handler. */
+
+/* Explicitly set registers to 0 to increase determinism. */
+#define ELF_PLAT_INIT(_r, load_addr) do { \
+ (_r)->r13 = 0; (_r)->r12 = 0; (_r)->r11 = 0; (_r)->r10 = 0; \
+ (_r)->r9 = 0; (_r)->r8 = 0; (_r)->r7 = 0; (_r)->r6 = 0; \
+ (_r)->r5 = 0; (_r)->r4 = 0; (_r)->r3 = 0; (_r)->r2 = 0; \
+ (_r)->r1 = 0; (_r)->r0 = 0; (_r)->mof = 0; (_r)->srp = 0; \
+} while (0)
+
+/* The additional layer below is because the stack pointer is missing in
+ the pt_regs struct, but needed in a core dump. pr_reg is a elf_gregset_t,
+ and should be filled in according to the layout of the user_regs_struct
+ struct; regs is a pt_regs struct. We dump all registers, though several are
+ obviously unnecessary. That way there's less need for intelligence at
+ the receiving end (i.e. gdb). */
+#define ELF_CORE_COPY_REGS(pr_reg, regs) \
+ pr_reg[0] = regs->r0; \
+ pr_reg[1] = regs->r1; \
+ pr_reg[2] = regs->r2; \
+ pr_reg[3] = regs->r3; \
+ pr_reg[4] = regs->r4; \
+ pr_reg[5] = regs->r5; \
+ pr_reg[6] = regs->r6; \
+ pr_reg[7] = regs->r7; \
+ pr_reg[8] = regs->r8; \
+ pr_reg[9] = regs->r9; \
+ pr_reg[10] = regs->r10; \
+ pr_reg[11] = regs->r11; \
+ pr_reg[12] = regs->r12; \
+ pr_reg[13] = regs->r13; \
+ pr_reg[14] = rdusp(); /* sp */ \
+ pr_reg[15] = regs->irp; /* pc */ \
+ pr_reg[16] = 0; /* p0 */ \
+ pr_reg[17] = rdvr(); /* vr */ \
+ pr_reg[18] = 0; /* p2 */ \
+ pr_reg[19] = 0; /* p3 */ \
+ pr_reg[20] = 0; /* p4 */ \
+ pr_reg[21] = (regs->dccr & 0xffff); /* ccr */ \
+ pr_reg[22] = 0; /* p6 */ \
+ pr_reg[23] = regs->mof; /* mof */ \
+ pr_reg[24] = 0; /* p8 */ \
+ pr_reg[25] = 0; /* ibr */ \
+ pr_reg[26] = 0; /* irp */ \
+ pr_reg[27] = regs->srp; /* srp */ \
+ pr_reg[28] = 0; /* bar */ \
+ pr_reg[29] = regs->dccr; /* dccr */ \
+ pr_reg[30] = 0; /* brp */ \
+ pr_reg[31] = rdusp(); /* usp */ \
+ pr_reg[32] = 0; /* csrinstr */ \
+ pr_reg[33] = 0; /* csraddr */ \
+ pr_reg[34] = 0; /* csrdata */
+
+
+#endif
diff --git a/include/asm-cris/arch-v10/io.h b/include/asm-cris/arch-v10/io.h
new file mode 100644
index 000000000000..0bc38a0313c1
--- /dev/null
+++ b/include/asm-cris/arch-v10/io.h
@@ -0,0 +1,193 @@
+#ifndef _ASM_ARCH_CRIS_IO_H
+#define _ASM_ARCH_CRIS_IO_H
+
+#include <asm/arch/svinto.h>
+#include <linux/config.h>
+
+/* Etrax shadow registers - which live in arch/cris/kernel/shadows.c */
+
+extern unsigned long port_g_data_shadow;
+extern unsigned char port_pa_dir_shadow;
+extern unsigned char port_pa_data_shadow;
+extern unsigned char port_pb_i2c_shadow;
+extern unsigned char port_pb_config_shadow;
+extern unsigned char port_pb_dir_shadow;
+extern unsigned char port_pb_data_shadow;
+extern unsigned long r_timer_ctrl_shadow;
+
+extern unsigned long port_cse1_shadow;
+extern unsigned long port_csp0_shadow;
+extern unsigned long port_csp4_shadow;
+
+extern volatile unsigned long *port_cse1_addr;
+extern volatile unsigned long *port_csp0_addr;
+extern volatile unsigned long *port_csp4_addr;
+
+/* macro for setting regs through a shadow -
+ * r = register name (like R_PORT_PA_DATA)
+ * s = shadow name (like port_pa_data_shadow)
+ * b = bit number
+ * v = value (0 or 1)
+ */
+
+#define REG_SHADOW_SET(r,s,b,v) *r = s = (s & ~(1 << (b))) | ((v) << (b))
+
+/* The LED's on various Etrax-based products are set differently. */
+
+#if defined(CONFIG_ETRAX_NO_LEDS) || defined(CONFIG_SVINTO_SIM)
+#undef CONFIG_ETRAX_PA_LEDS
+#undef CONFIG_ETRAX_PB_LEDS
+#undef CONFIG_ETRAX_CSP0_LEDS
+#define LED_NETWORK_SET_G(x)
+#define LED_NETWORK_SET_R(x)
+#define LED_ACTIVE_SET_G(x)
+#define LED_ACTIVE_SET_R(x)
+#define LED_DISK_WRITE(x)
+#define LED_DISK_READ(x)
+#endif
+
+#if !defined(CONFIG_ETRAX_CSP0_LEDS)
+#define LED_BIT_SET(x)
+#define LED_BIT_CLR(x)
+#endif
+
+#define LED_OFF 0x00
+#define LED_GREEN 0x01
+#define LED_RED 0x02
+#define LED_ORANGE (LED_GREEN | LED_RED)
+
+#if CONFIG_ETRAX_LED1G == CONFIG_ETRAX_LED1R
+#define LED_NETWORK_SET(x) \
+ do { \
+ LED_NETWORK_SET_G((x) & LED_GREEN); \
+ } while (0)
+#else
+#define LED_NETWORK_SET(x) \
+ do { \
+ LED_NETWORK_SET_G((x) & LED_GREEN); \
+ LED_NETWORK_SET_R((x) & LED_RED); \
+ } while (0)
+#endif
+#if CONFIG_ETRAX_LED2G == CONFIG_ETRAX_LED2R
+#define LED_ACTIVE_SET(x) \
+ do { \
+ LED_ACTIVE_SET_G((x) & LED_GREEN); \
+ } while (0)
+#else
+#define LED_ACTIVE_SET(x) \
+ do { \
+ LED_ACTIVE_SET_G((x) & LED_GREEN); \
+ LED_ACTIVE_SET_R((x) & LED_RED); \
+ } while (0)
+#endif
+
+#ifdef CONFIG_ETRAX_PA_LEDS
+#define LED_NETWORK_SET_G(x) \
+ REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1G, !(x))
+#define LED_NETWORK_SET_R(x) \
+ REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1R, !(x))
+#define LED_ACTIVE_SET_G(x) \
+ REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2G, !(x))
+#define LED_ACTIVE_SET_R(x) \
+ REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2R, !(x))
+#define LED_DISK_WRITE(x) \
+ do{\
+ REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !(x));\
+ REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !(x));\
+ }while(0)
+#define LED_DISK_READ(x) \
+ REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !(x))
+#endif
+
+#ifdef CONFIG_ETRAX_PB_LEDS
+#define LED_NETWORK_SET_G(x) \
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1G, !(x))
+#define LED_NETWORK_SET_R(x) \
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1R, !(x))
+#define LED_ACTIVE_SET_G(x) \
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2G, !(x))
+#define LED_ACTIVE_SET_R(x) \
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2R, !(x))
+#define LED_DISK_WRITE(x) \
+ do{\
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED3G, !(x));\
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED3R, !(x));\
+ }while(0)
+#define LED_DISK_READ(x) \
+ REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED3G, !(x))
+#endif
+
+#ifdef CONFIG_ETRAX_CSP0_LEDS
+#define CONFIGURABLE_LEDS\
+ ((1 << CONFIG_ETRAX_LED1G ) | (1 << CONFIG_ETRAX_LED1R ) |\
+ (1 << CONFIG_ETRAX_LED2G ) | (1 << CONFIG_ETRAX_LED2R ) |\
+ (1 << CONFIG_ETRAX_LED3G ) | (1 << CONFIG_ETRAX_LED3R ) |\
+ (1 << CONFIG_ETRAX_LED4G ) | (1 << CONFIG_ETRAX_LED4R ) |\
+ (1 << CONFIG_ETRAX_LED5G ) | (1 << CONFIG_ETRAX_LED5R ) |\
+ (1 << CONFIG_ETRAX_LED6G ) | (1 << CONFIG_ETRAX_LED6R ) |\
+ (1 << CONFIG_ETRAX_LED7G ) | (1 << CONFIG_ETRAX_LED7R ) |\
+ (1 << CONFIG_ETRAX_LED8Y ) | (1 << CONFIG_ETRAX_LED9Y ) |\
+ (1 << CONFIG_ETRAX_LED10Y ) |(1 << CONFIG_ETRAX_LED11Y )|\
+ (1 << CONFIG_ETRAX_LED12R ))
+
+#define LED_NETWORK_SET_G(x) \
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED1G, !(x))
+#define LED_NETWORK_SET_R(x) \
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED1R, !(x))
+#define LED_ACTIVE_SET_G(x) \
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED2G, !(x))
+#define LED_ACTIVE_SET_R(x) \
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED2R, !(x))
+#define LED_DISK_WRITE(x) \
+ do{\
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3G, !(x));\
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3R, !(x));\
+ }while(0)
+#define LED_DISK_READ(x) \
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3G, !(x))
+#define LED_BIT_SET(x)\
+ do{\
+ if((( 1 << x) & CONFIGURABLE_LEDS) != 0)\
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, x, 1);\
+ }while(0)
+#define LED_BIT_CLR(x)\
+ do{\
+ if((( 1 << x) & CONFIGURABLE_LEDS) != 0)\
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, x, 0);\
+ }while(0)
+#endif
+
+#
+#ifdef CONFIG_ETRAX_SOFT_SHUTDOWN
+#define SOFT_SHUTDOWN() \
+ REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_SHUTDOWN_BIT, 1)
+#else
+#define SOFT_SHUTDOWN()
+#endif
+
+/* Console I/O for simulated etrax100. Use #ifdef so erroneous
+ use will be evident. */
+#ifdef CONFIG_SVINTO_SIM
+ /* Let's use the ucsim interface since it lets us do write(2, ...) */
+#define SIMCOUT(s,len) \
+ asm ("moveq 4,$r9 \n\t" \
+ "moveq 2,$r10 \n\t" \
+ "move.d %0,$r11 \n\t" \
+ "move.d %1,$r12 \n\t" \
+ "push $irp \n\t" \
+ "move 0f,$irp \n\t" \
+ "jump -6809 \n" \
+ "0: \n\t" \
+ "pop $irp" \
+ : : "rm" (s), "rm" (len) : "r9","r10","r11","r12","memory")
+#define TRACE_ON() __extension__ \
+ ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \
+ (255)); _Foofoo; })
+
+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0)
+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0)
+#define CRIS_CYCLES() __extension__ \
+ ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;})
+#endif /* ! defined CONFIG_SVINTO_SIM */
+
+#endif
diff --git a/include/asm-cris/arch-v10/irq.h b/include/asm-cris/arch-v10/irq.h
new file mode 100644
index 000000000000..f657c75ddcfa
--- /dev/null
+++ b/include/asm-cris/arch-v10/irq.h
@@ -0,0 +1,176 @@
+/*
+ * Interrupt handling assembler and defines for Linux/CRISv10
+ */
+
+#ifndef _ASM_ARCH_IRQ_H
+#define _ASM_ARCH_IRQ_H
+
+#include <asm/arch/sv_addr_ag.h>
+
+#define NR_IRQS 32
+#define SOME_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, some) /* 0 ? */
+#define NMI_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, nmi) /* 1 */
+#define TIMER0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer0) /* 2 */
+#define TIMER1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer1) /* 3 */
+/* mio, ata, par0, scsi0 on 4 */
+/* par1, scsi1 on 5 */
+#define NETWORK_STATUS_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, network) /* 6 */
+
+#define SERIAL_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, serial) /* 8 */
+#define PA_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, pa) /* 11 */
+/* extdma0 and extdma1 is at irq 12 and 13 and/or same as dma5 and dma6 ? */
+#define EXTDMA0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma0)
+#define EXTDMA1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma1)
+
+/* dma0-9 is irq 16..25 */
+/* 16,17: network */
+#define DMA0_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma0)
+#define DMA1_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma1)
+#define NETWORK_DMA_TX_IRQ_NBR DMA0_TX_IRQ_NBR
+#define NETWORK_DMA_RX_IRQ_NBR DMA1_RX_IRQ_NBR
+
+/* 18,19: dma2 and dma3 shared by par0, scsi0, ser2 and ata */
+#define DMA2_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma2)
+#define DMA3_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma3)
+#define SER2_DMA_TX_IRQ_NBR DMA2_TX_IRQ_NBR
+#define SER2_DMA_RX_IRQ_NBR DMA3_RX_IRQ_NBR
+
+/* 20,21: dma4 and dma5 shared by par1, scsi1, ser3 and extdma0 */
+#define DMA4_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma4)
+#define DMA5_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma5)
+#define SER3_DMA_TX_IRQ_NBR DMA4_TX_IRQ_NBR
+#define SER3_DMA_RX_IRQ_NBR DMA5_RX_IRQ_NBR
+
+/* 22,23: dma6 and dma7 shared by ser0, extdma1 and mem2mem */
+#define DMA6_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma6)
+#define DMA7_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma7)
+#define SER0_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR
+#define SER0_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR
+#define MEM2MEM_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR
+#define MEM2MEM_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR
+
+/* 24,25: dma8 and dma9 shared by ser1 and usb */
+#define DMA8_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma8)
+#define DMA9_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma9)
+#define SER1_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR
+#define SER1_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR
+#define USB_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR
+#define USB_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR
+
+/* usb: controller at irq 31 + uses DMA8 and DMA9 */
+#define USB_HC_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, usb)
+
+/* our fine, global, etrax irq vector! the pointer lives in the head.S file. */
+
+typedef void (*irqvectptr)(void);
+
+struct etrax_interrupt_vector {
+ irqvectptr v[256];
+};
+
+extern struct etrax_interrupt_vector *etrax_irv;
+void set_int_vector(int n, irqvectptr addr, irqvectptr saddr);
+void set_break_vector(int n, irqvectptr addr);
+
+#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
+#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+/* SAVE_ALL saves registers so they match pt_regs */
+
+#define SAVE_ALL \
+ "move $irp,[$sp=$sp-16]\n\t" /* push instruction pointer and fake SBFS struct */ \
+ "push $srp\n\t" /* push subroutine return pointer */ \
+ "push $dccr\n\t" /* push condition codes */ \
+ "push $mof\n\t" /* push multiply overflow reg */ \
+ "di\n\t" /* need to disable irq's at this point */\
+ "subq 14*4,$sp\n\t" /* make room for r0-r13 */ \
+ "movem $r13,[$sp]\n\t" /* push the r0-r13 registers */ \
+ "push $r10\n\t" /* push orig_r10 */ \
+ "clear.d [$sp=$sp-4]\n\t" /* frametype - this is a normal stackframe */
+
+ /* BLOCK_IRQ and UNBLOCK_IRQ do the same as mask_irq and unmask_irq */
+
+#define BLOCK_IRQ(mask,nr) \
+ "move.d " #mask ",$r0\n\t" \
+ "move.d $r0,[0xb00000d8]\n\t"
+
+#define UNBLOCK_IRQ(mask) \
+ "move.d " #mask ",$r0\n\t" \
+ "move.d $r0,[0xb00000dc]\n\t"
+
+#define IRQ_NAME2(nr) nr##_interrupt(void)
+#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
+#define sIRQ_NAME(nr) IRQ_NAME2(sIRQ##nr)
+#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
+
+ /* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls
+ * do_IRQ (with irq disabled still). after that it unblocks and jumps to
+ * ret_from_intr (entry.S)
+ *
+ * The reason the IRQ is blocked is to allow an sti() before the handler which
+ * will acknowledge the interrupt is run.
+ */
+
+#define BUILD_IRQ(nr,mask) \
+void IRQ_NAME(nr); \
+void sIRQ_NAME(nr); \
+void BAD_IRQ_NAME(nr); \
+__asm__ ( \
+ ".text\n\t" \
+ "IRQ" #nr "_interrupt:\n\t" \
+ SAVE_ALL \
+ "sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
+ BLOCK_IRQ(mask,nr) /* this must be done to prevent irq loops when we ei later */ \
+ "moveq "#nr",$r10\n\t" \
+ "move.d $sp,$r11\n\t" \
+ "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
+ UNBLOCK_IRQ(mask) \
+ "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
+ "jump ret_from_intr\n\t" \
+ "bad_IRQ" #nr "_interrupt:\n\t" \
+ "push $r0\n\t" \
+ BLOCK_IRQ(mask,nr) \
+ "pop $r0\n\t" \
+ "reti\n\t" \
+ "nop\n");
+
+/* This is subtle. The timer interrupt is crucial and it should not be disabled for
+ * too long. However, if it had been a normal interrupt as per BUILD_IRQ, it would
+ * have been BLOCK'ed, and then softirq's are run before we return here to UNBLOCK.
+ * If the softirq's take too much time to run, the timer irq won't run and the
+ * watchdog will kill us.
+ *
+ * Furthermore, if a lot of other irq's occur before we return here, the multiple_irq
+ * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed
+ * it here, we would not get the multiple_irq at all.
+ *
+ * The non-blocking here is based on the knowledge that the timer interrupt is
+ * registred as a fast interrupt (SA_INTERRUPT) so that we _know_ there will not
+ * be an sti() before the timer irq handler is run to acknowledge the interrupt.
+ */
+
+#define BUILD_TIMER_IRQ(nr,mask) \
+void IRQ_NAME(nr); \
+void sIRQ_NAME(nr); \
+void BAD_IRQ_NAME(nr); \
+__asm__ ( \
+ ".text\n\t" \
+ "IRQ" #nr "_interrupt:\n\t" \
+ SAVE_ALL \
+ "sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
+ "moveq "#nr",$r10\n\t" \
+ "move.d $sp,$r11\n\t" \
+ "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
+ "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
+ "jump ret_from_intr\n\t" \
+ "bad_IRQ" #nr "_interrupt:\n\t" \
+ "push $r0\n\t" \
+ BLOCK_IRQ(mask,nr) \
+ "pop $r0\n\t" \
+ "reti\n\t" \
+ "nop\n");
+
+#endif
diff --git a/include/asm-cris/arch-v10/mmu.h b/include/asm-cris/arch-v10/mmu.h
new file mode 100644
index 000000000000..d18aa00e50bc
--- /dev/null
+++ b/include/asm-cris/arch-v10/mmu.h
@@ -0,0 +1,106 @@
+/*
+ * CRIS MMU constants and PTE layout
+ */
+
+#ifndef _CRIS_ARCH_MMU_H
+#define _CRIS_ARCH_MMU_H
+
+/* type used in struct mm to couple an MMU context to an active mm */
+
+typedef unsigned int mm_context_t;
+
+/* kernel memory segments */
+
+#define KSEG_F 0xf0000000UL
+#define KSEG_E 0xe0000000UL
+#define KSEG_D 0xd0000000UL
+#define KSEG_C 0xc0000000UL
+#define KSEG_B 0xb0000000UL
+#define KSEG_A 0xa0000000UL
+#define KSEG_9 0x90000000UL
+#define KSEG_8 0x80000000UL
+#define KSEG_7 0x70000000UL
+#define KSEG_6 0x60000000UL
+#define KSEG_5 0x50000000UL
+#define KSEG_4 0x40000000UL
+#define KSEG_3 0x30000000UL
+#define KSEG_2 0x20000000UL
+#define KSEG_1 0x10000000UL
+#define KSEG_0 0x00000000UL
+
+/* CRIS PTE bits (see R_TLB_LO in the register description)
+ *
+ * Bit: 31-13 12-------4 3 2 1 0
+ * ________________________________________________
+ * | pfn | reserved | global | valid | kernel | we |
+ * |_____|__________|________|_______|________|_____|
+ *
+ * (pfn = physical frame number)
+ */
+
+/* Real HW-based PTE bits. We use some synonym names so that
+ * things become less confusing in combination with the SW-based
+ * bits further below.
+ *
+ */
+
+#define _PAGE_WE (1<<0) /* page is write-enabled */
+#define _PAGE_SILENT_WRITE (1<<0) /* synonym */
+#define _PAGE_KERNEL (1<<1) /* page is kernel only */
+#define _PAGE_VALID (1<<2) /* page is valid */
+#define _PAGE_SILENT_READ (1<<2) /* synonym */
+#define _PAGE_GLOBAL (1<<3) /* global page - context is ignored */
+
+/* Bits the HW doesn't care about but the kernel uses them in SW */
+
+#define _PAGE_PRESENT (1<<4) /* page present in memory */
+#define _PAGE_FILE (1<<5) /* set: pagecache, unset: swap (when !PRESENT) */
+#define _PAGE_ACCESSED (1<<5) /* simulated in software using valid bit */
+#define _PAGE_MODIFIED (1<<6) /* simulated in software using we bit */
+#define _PAGE_READ (1<<7) /* read-enabled */
+#define _PAGE_WRITE (1<<8) /* write-enabled */
+
+/* Define some higher level generic page attributes. */
+
+#define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
+#define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
+
+#define _PAGE_TABLE (_PAGE_PRESENT | __READABLE | __WRITEABLE)
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED)
+
+#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
+ _PAGE_ACCESSED)
+#define PAGE_COPY __pgprot(_PAGE_PRESENT | __READABLE) // | _PAGE_COW
+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | __READABLE)
+#define PAGE_KERNEL __pgprot(_PAGE_GLOBAL | _PAGE_KERNEL | \
+ _PAGE_PRESENT | __READABLE | __WRITEABLE)
+#define _KERNPG_TABLE (_PAGE_TABLE | _PAGE_KERNEL)
+
+/*
+ * CRIS can't do page protection for execute, and considers read the same.
+ * Also, write permissions imply read permissions. This is the closest we can
+ * get..
+ */
+
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED
+
+#define PTE_FILE_MAX_BITS 26
+
+#endif
diff --git a/include/asm-cris/arch-v10/offset.h b/include/asm-cris/arch-v10/offset.h
new file mode 100644
index 000000000000..87901a752746
--- /dev/null
+++ b/include/asm-cris/arch-v10/offset.h
@@ -0,0 +1,33 @@
+#ifndef __ASM_OFFSETS_H__
+#define __ASM_OFFSETS_H__
+/*
+ * DO NOT MODIFY.
+ *
+ * This file was generated by arch/cris/Makefile
+ *
+ */
+
+#define PT_orig_r10 4 /* offsetof(struct pt_regs, orig_r10) */
+#define PT_r13 8 /* offsetof(struct pt_regs, r13) */
+#define PT_r12 12 /* offsetof(struct pt_regs, r12) */
+#define PT_r11 16 /* offsetof(struct pt_regs, r11) */
+#define PT_r10 20 /* offsetof(struct pt_regs, r10) */
+#define PT_r9 24 /* offsetof(struct pt_regs, r9) */
+#define PT_mof 64 /* offsetof(struct pt_regs, mof) */
+#define PT_dccr 68 /* offsetof(struct pt_regs, dccr) */
+#define PT_srp 72 /* offsetof(struct pt_regs, srp) */
+
+#define TI_task 0 /* offsetof(struct thread_info, task) */
+#define TI_flags 8 /* offsetof(struct thread_info, flags) */
+#define TI_preempt_count 16 /* offsetof(struct thread_info, preempt_count) */
+
+#define THREAD_ksp 0 /* offsetof(struct thread_struct, ksp) */
+#define THREAD_usp 4 /* offsetof(struct thread_struct, usp) */
+#define THREAD_dccr 8 /* offsetof(struct thread_struct, dccr) */
+
+#define TASK_pid 121 /* offsetof(struct task_struct, pid) */
+
+#define LCLONE_VM 256 /* CLONE_VM */
+#define LCLONE_UNTRACED 8388608 /* CLONE_UNTRACED */
+
+#endif
diff --git a/include/asm-cris/arch-v10/page.h b/include/asm-cris/arch-v10/page.h
new file mode 100644
index 000000000000..407e6e68f49e
--- /dev/null
+++ b/include/asm-cris/arch-v10/page.h
@@ -0,0 +1,31 @@
+#ifndef _CRIS_ARCH_PAGE_H
+#define _CRIS_ARCH_PAGE_H
+
+#include <linux/config.h>
+
+#ifdef __KERNEL__
+
+/* This handles the memory map.. */
+#ifdef CONFIG_CRIS_LOW_MAP
+#define PAGE_OFFSET KSEG_6 /* kseg_6 is mapped to physical ram */
+#else
+#define PAGE_OFFSET KSEG_C /* kseg_c is mapped to physical ram */
+#endif
+
+/* macros to convert between really physical and virtual addresses
+ * by stripping a selected bit, we can convert between KSEG_x and 0x40000000 where
+ * the DRAM really resides
+ */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+/* we have DRAM virtually at 0x6 */
+#define __pa(x) ((unsigned long)(x) & 0xdfffffff)
+#define __va(x) ((void *)((unsigned long)(x) | 0x20000000))
+#else
+/* we have DRAM virtually at 0xc */
+#define __pa(x) ((unsigned long)(x) & 0x7fffffff)
+#define __va(x) ((void *)((unsigned long)(x) | 0x80000000))
+#endif
+
+#endif
+#endif
diff --git a/include/asm-cris/arch-v10/pgtable.h b/include/asm-cris/arch-v10/pgtable.h
new file mode 100644
index 000000000000..65eecd1e6538
--- /dev/null
+++ b/include/asm-cris/arch-v10/pgtable.h
@@ -0,0 +1,19 @@
+#ifndef _CRIS_ARCH_PGTABLE_H
+#define _CRIS_ARCH_PGTABLE_H
+
+/*
+ * Kernels own virtual memory area.
+ */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define VMALLOC_START KSEG_7
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END KSEG_8
+#else
+#define VMALLOC_START KSEG_D
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END KSEG_E
+#endif
+
+#endif
+
diff --git a/include/asm-cris/arch-v10/processor.h b/include/asm-cris/arch-v10/processor.h
new file mode 100644
index 000000000000..9355d8675a58
--- /dev/null
+++ b/include/asm-cris/arch-v10/processor.h
@@ -0,0 +1,62 @@
+#ifndef __ASM_CRIS_ARCH_PROCESSOR_H
+#define __ASM_CRIS_ARCH_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({void *pc; __asm__ ("move.d $pc,%0" : "=rm" (pc)); pc; })
+
+/* CRIS has no problems with write protection */
+#define wp_works_ok 1
+
+/* CRIS thread_struct. this really has nothing to do with the processor itself, since
+ * CRIS does not do any hardware task-switching, but it's here for legacy reasons.
+ * The thread_struct here is used when task-switching using _resume defined in entry.S.
+ * The offsets here are hardcoded into _resume - if you change this struct, you need to
+ * change them as well!!!
+*/
+
+struct thread_struct {
+ unsigned long ksp; /* kernel stack pointer */
+ unsigned long usp; /* user stack pointer */
+ unsigned long dccr; /* saved flag register */
+};
+
+/*
+ * User space process size. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define TASK_SIZE (0x50000000UL) /* 1.25 GB */
+#else
+#define TASK_SIZE (0xA0000000UL) /* 2.56 GB */
+#endif
+
+#define INIT_THREAD { \
+ 0, 0, 0x20 } /* ccr = int enable, nothing else */
+
+#define KSTK_EIP(tsk) \
+({ \
+ unsigned long eip = 0; \
+ unsigned long regs = (unsigned long)user_regs(tsk); \
+ if (regs > PAGE_SIZE && \
+ virt_addr_valid(regs)) \
+ eip = ((struct pt_regs *)regs)->irp; \
+ eip; \
+})
+
+/* give the thread a program location
+ * set user-mode (The 'U' flag (User mode flag) is CCR/DCCR bit 8)
+ * switch user-stackpointer
+ */
+
+#define start_thread(regs, ip, usp) do { \
+ set_fs(USER_DS); \
+ regs->irp = ip; \
+ regs->dccr |= 1 << U_DCCR_BITNR; \
+ wrusp(usp); \
+} while(0)
+
+#endif
diff --git a/include/asm-cris/arch-v10/ptrace.h b/include/asm-cris/arch-v10/ptrace.h
new file mode 100644
index 000000000000..939d9846477e
--- /dev/null
+++ b/include/asm-cris/arch-v10/ptrace.h
@@ -0,0 +1,114 @@
+#ifndef _CRIS_ARCH_PTRACE_H
+#define _CRIS_ARCH_PTRACE_H
+
+/* Frame types */
+
+#define CRIS_FRAME_NORMAL 0 /* normal frame without SBFS stacking */
+#define CRIS_FRAME_BUSFAULT 1 /* frame stacked using SBFS, need RBF return
+ path */
+
+/* Register numbers in the ptrace system call interface */
+
+#define PT_FRAMETYPE 0
+#define PT_ORIG_R10 1
+#define PT_R13 2
+#define PT_R12 3
+#define PT_R11 4
+#define PT_R10 5
+#define PT_R9 6
+#define PT_R8 7
+#define PT_R7 8
+#define PT_R6 9
+#define PT_R5 10
+#define PT_R4 11
+#define PT_R3 12
+#define PT_R2 13
+#define PT_R1 14
+#define PT_R0 15
+#define PT_MOF 16
+#define PT_DCCR 17
+#define PT_SRP 18
+#define PT_IRP 19 /* This is actually the debugged process' PC */
+#define PT_CSRINSTR 20 /* CPU Status record remnants -
+ valid if frametype == busfault */
+#define PT_CSRADDR 21
+#define PT_CSRDATA 22
+#define PT_USP 23 /* special case - USP is not in the pt_regs */
+#define PT_MAX 23
+
+/* Condition code bit numbers. The same numbers apply to CCR of course,
+ but we use DCCR everywhere else, so let's try and be consistent. */
+#define C_DCCR_BITNR 0
+#define V_DCCR_BITNR 1
+#define Z_DCCR_BITNR 2
+#define N_DCCR_BITNR 3
+#define X_DCCR_BITNR 4
+#define I_DCCR_BITNR 5
+#define B_DCCR_BITNR 6
+#define M_DCCR_BITNR 7
+#define U_DCCR_BITNR 8
+#define P_DCCR_BITNR 9
+#define F_DCCR_BITNR 10
+
+/* pt_regs not only specifices the format in the user-struct during
+ * ptrace but is also the frame format used in the kernel prologue/epilogues
+ * themselves
+ */
+
+struct pt_regs {
+ unsigned long frametype; /* type of stackframe */
+ unsigned long orig_r10;
+ /* pushed by movem r13, [sp] in SAVE_ALL, movem pushes backwards */
+ unsigned long r13;
+ unsigned long r12;
+ unsigned long r11;
+ unsigned long r10;
+ unsigned long r9;
+ unsigned long r8;
+ unsigned long r7;
+ unsigned long r6;
+ unsigned long r5;
+ unsigned long r4;
+ unsigned long r3;
+ unsigned long r2;
+ unsigned long r1;
+ unsigned long r0;
+ unsigned long mof;
+ unsigned long dccr;
+ unsigned long srp;
+ unsigned long irp; /* This is actually the debugged process' PC */
+ unsigned long csrinstr;
+ unsigned long csraddr;
+ unsigned long csrdata;
+};
+
+/* switch_stack is the extra stuff pushed onto the stack in _resume (entry.S)
+ * when doing a context-switch. it is used (apart from in resume) when a new
+ * thread is made and we need to make _resume (which is starting it for the
+ * first time) realise what is going on.
+ *
+ * Actually, the use is very close to the thread struct (TSS) in that both the
+ * switch_stack and the TSS are used to keep thread stuff when switching in
+ * _resume.
+ */
+
+struct switch_stack {
+ unsigned long r9;
+ unsigned long r8;
+ unsigned long r7;
+ unsigned long r6;
+ unsigned long r5;
+ unsigned long r4;
+ unsigned long r3;
+ unsigned long r2;
+ unsigned long r1;
+ unsigned long r0;
+ unsigned long return_ip; /* ip that _resume will return to */
+};
+
+/* bit 8 is user-mode flag */
+#define user_mode(regs) (((regs)->dccr & 0x100) != 0)
+#define instruction_pointer(regs) ((regs)->irp)
+extern void show_regs(struct pt_regs *);
+
+#endif
diff --git a/include/asm-cris/sv_addr.agh b/include/asm-cris/arch-v10/sv_addr.agh
index ddaf91fa38cf..6ac3a7bc9760 100644
--- a/include/asm-cris/sv_addr.agh
+++ b/include/asm-cris/arch-v10/sv_addr.agh
@@ -691,10 +691,10 @@
#define R_GEN_CONFIG__g24dir__WIDTH 1
#define R_GEN_CONFIG__g24dir__in 0
#define R_GEN_CONFIG__g24dir__out 1
-#define R_GEN_CONFIG__g16_20dir__BITNR 26
-#define R_GEN_CONFIG__g16_20dir__WIDTH 1
-#define R_GEN_CONFIG__g16_20dir__in 0
-#define R_GEN_CONFIG__g16_20dir__out 1
+#define R_GEN_CONFIG__g16_23dir__BITNR 26
+#define R_GEN_CONFIG__g16_23dir__WIDTH 1
+#define R_GEN_CONFIG__g16_23dir__in 0
+#define R_GEN_CONFIG__g16_23dir__out 1
#define R_GEN_CONFIG__g8_15dir__BITNR 25
#define R_GEN_CONFIG__g8_15dir__WIDTH 1
#define R_GEN_CONFIG__g8_15dir__in 0
@@ -1142,7 +1142,7 @@
#define R_SERIAL0_CTRL__rec_stick_par__BITNR 19
#define R_SERIAL0_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL0_CTRL__rec_stick_par__normal 0
-#define R_SERIAL0_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL0_CTRL__rec_stick_par__stick 1
#define R_SERIAL0_CTRL__rec_par__BITNR 18
#define R_SERIAL0_CTRL__rec_par__WIDTH 1
#define R_SERIAL0_CTRL__rec_par__even 0
@@ -1172,7 +1172,7 @@
#define R_SERIAL0_CTRL__tr_stick_par__BITNR 11
#define R_SERIAL0_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL0_CTRL__tr_stick_par__normal 0
-#define R_SERIAL0_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL0_CTRL__tr_stick_par__stick 1
#define R_SERIAL0_CTRL__tr_par__BITNR 10
#define R_SERIAL0_CTRL__tr_par__WIDTH 1
#define R_SERIAL0_CTRL__tr_par__even 0
@@ -1246,7 +1246,7 @@
#define R_SERIAL0_REC_CTRL__rec_stick_par__BITNR 3
#define R_SERIAL0_REC_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL0_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL0_REC_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL0_REC_CTRL__rec_stick_par__stick 1
#define R_SERIAL0_REC_CTRL__rec_par__BITNR 2
#define R_SERIAL0_REC_CTRL__rec_par__WIDTH 1
#define R_SERIAL0_REC_CTRL__rec_par__even 0
@@ -1278,7 +1278,7 @@
#define R_SERIAL0_TR_CTRL__tr_stick_par__BITNR 3
#define R_SERIAL0_TR_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL0_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL0_TR_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL0_TR_CTRL__tr_stick_par__stick 1
#define R_SERIAL0_TR_CTRL__tr_par__BITNR 2
#define R_SERIAL0_TR_CTRL__tr_par__WIDTH 1
#define R_SERIAL0_TR_CTRL__tr_par__even 0
@@ -1434,7 +1434,7 @@
#define R_SERIAL1_CTRL__rec_stick_par__BITNR 19
#define R_SERIAL1_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL1_CTRL__rec_stick_par__normal 0
-#define R_SERIAL1_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL1_CTRL__rec_stick_par__stick 1
#define R_SERIAL1_CTRL__rec_par__BITNR 18
#define R_SERIAL1_CTRL__rec_par__WIDTH 1
#define R_SERIAL1_CTRL__rec_par__even 0
@@ -1464,7 +1464,7 @@
#define R_SERIAL1_CTRL__tr_stick_par__BITNR 11
#define R_SERIAL1_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL1_CTRL__tr_stick_par__normal 0
-#define R_SERIAL1_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL1_CTRL__tr_stick_par__stick 1
#define R_SERIAL1_CTRL__tr_par__BITNR 10
#define R_SERIAL1_CTRL__tr_par__WIDTH 1
#define R_SERIAL1_CTRL__tr_par__even 0
@@ -1538,7 +1538,7 @@
#define R_SERIAL1_REC_CTRL__rec_stick_par__BITNR 3
#define R_SERIAL1_REC_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL1_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL1_REC_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL1_REC_CTRL__rec_stick_par__stick 1
#define R_SERIAL1_REC_CTRL__rec_par__BITNR 2
#define R_SERIAL1_REC_CTRL__rec_par__WIDTH 1
#define R_SERIAL1_REC_CTRL__rec_par__even 0
@@ -1570,7 +1570,7 @@
#define R_SERIAL1_TR_CTRL__tr_stick_par__BITNR 3
#define R_SERIAL1_TR_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL1_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL1_TR_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL1_TR_CTRL__tr_stick_par__stick 1
#define R_SERIAL1_TR_CTRL__tr_par__BITNR 2
#define R_SERIAL1_TR_CTRL__tr_par__WIDTH 1
#define R_SERIAL1_TR_CTRL__tr_par__even 0
@@ -1726,7 +1726,7 @@
#define R_SERIAL2_CTRL__rec_stick_par__BITNR 19
#define R_SERIAL2_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL2_CTRL__rec_stick_par__normal 0
-#define R_SERIAL2_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL2_CTRL__rec_stick_par__stick 1
#define R_SERIAL2_CTRL__rec_par__BITNR 18
#define R_SERIAL2_CTRL__rec_par__WIDTH 1
#define R_SERIAL2_CTRL__rec_par__even 0
@@ -1756,7 +1756,7 @@
#define R_SERIAL2_CTRL__tr_stick_par__BITNR 11
#define R_SERIAL2_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL2_CTRL__tr_stick_par__normal 0
-#define R_SERIAL2_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL2_CTRL__tr_stick_par__stick 1
#define R_SERIAL2_CTRL__tr_par__BITNR 10
#define R_SERIAL2_CTRL__tr_par__WIDTH 1
#define R_SERIAL2_CTRL__tr_par__even 0
@@ -1830,7 +1830,7 @@
#define R_SERIAL2_REC_CTRL__rec_stick_par__BITNR 3
#define R_SERIAL2_REC_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL2_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL2_REC_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL2_REC_CTRL__rec_stick_par__stick 1
#define R_SERIAL2_REC_CTRL__rec_par__BITNR 2
#define R_SERIAL2_REC_CTRL__rec_par__WIDTH 1
#define R_SERIAL2_REC_CTRL__rec_par__even 0
@@ -1862,7 +1862,7 @@
#define R_SERIAL2_TR_CTRL__tr_stick_par__BITNR 3
#define R_SERIAL2_TR_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL2_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL2_TR_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL2_TR_CTRL__tr_stick_par__stick 1
#define R_SERIAL2_TR_CTRL__tr_par__BITNR 2
#define R_SERIAL2_TR_CTRL__tr_par__WIDTH 1
#define R_SERIAL2_TR_CTRL__tr_par__even 0
@@ -2018,7 +2018,7 @@
#define R_SERIAL3_CTRL__rec_stick_par__BITNR 19
#define R_SERIAL3_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL3_CTRL__rec_stick_par__normal 0
-#define R_SERIAL3_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL3_CTRL__rec_stick_par__stick 1
#define R_SERIAL3_CTRL__rec_par__BITNR 18
#define R_SERIAL3_CTRL__rec_par__WIDTH 1
#define R_SERIAL3_CTRL__rec_par__even 0
@@ -2048,7 +2048,7 @@
#define R_SERIAL3_CTRL__tr_stick_par__BITNR 11
#define R_SERIAL3_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL3_CTRL__tr_stick_par__normal 0
-#define R_SERIAL3_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL3_CTRL__tr_stick_par__stick 1
#define R_SERIAL3_CTRL__tr_par__BITNR 10
#define R_SERIAL3_CTRL__tr_par__WIDTH 1
#define R_SERIAL3_CTRL__tr_par__even 0
@@ -2122,7 +2122,7 @@
#define R_SERIAL3_REC_CTRL__rec_stick_par__BITNR 3
#define R_SERIAL3_REC_CTRL__rec_stick_par__WIDTH 1
#define R_SERIAL3_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL3_REC_CTRL__rec_stick_parlocal_irq_enableck 1
+#define R_SERIAL3_REC_CTRL__rec_stick_par__stick 1
#define R_SERIAL3_REC_CTRL__rec_par__BITNR 2
#define R_SERIAL3_REC_CTRL__rec_par__WIDTH 1
#define R_SERIAL3_REC_CTRL__rec_par__even 0
@@ -2154,7 +2154,7 @@
#define R_SERIAL3_TR_CTRL__tr_stick_par__BITNR 3
#define R_SERIAL3_TR_CTRL__tr_stick_par__WIDTH 1
#define R_SERIAL3_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL3_TR_CTRL__tr_stick_parlocal_irq_enableck 1
+#define R_SERIAL3_TR_CTRL__tr_stick_par__stick 1
#define R_SERIAL3_TR_CTRL__tr_par__BITNR 2
#define R_SERIAL3_TR_CTRL__tr_par__WIDTH 1
#define R_SERIAL3_TR_CTRL__tr_par__even 0
diff --git a/include/asm-cris/sv_addr_ag.h b/include/asm-cris/arch-v10/sv_addr_ag.h
index c80826bf9410..e4a6b68b8982 100644
--- a/include/asm-cris/sv_addr_ag.h
+++ b/include/asm-cris/arch-v10/sv_addr_ag.h
@@ -25,33 +25,41 @@
/* IO_MASK returns a mask for a specified bitfield in a register.
Note that this macro doesn't work when field width is 32 bits. */
-#define IO_MASK(reg,field) \
- ( ( ( 1 << reg##__##field##__WIDTH ) - 1 ) << reg##__##field##__BITNR )
+#define IO_MASK(reg, field) IO_MASK_ (reg##_, field##_)
+#define IO_MASK_(reg_, field_) \
+ ( ( ( 1 << reg_##_##field_##_WIDTH ) - 1 ) << reg_##_##field_##_BITNR )
/* IO_STATE returns a constant corresponding to a one of the symbolic
states that the bitfield can have. (Shifted to correct position) */
-#define IO_STATE(reg,field,state) \
- ( reg##__##field##__##state << reg##__##field##__BITNR )
+#define IO_STATE(reg, field, state) IO_STATE_ (reg##_, field##_, _##state)
+#define IO_STATE_(reg_, field_, _state) \
+ ( reg_##_##field_##_state << reg_##_##field_##_BITNR )
/* IO_EXTRACT returns the masked and shifted value corresponding to the
bitfield can have. */
-#define IO_EXTRACT(reg,field,val) ( (( ( ( 1 << reg##__##field##__WIDTH ) \
- - 1 ) << reg##__##field##__BITNR ) & (val)) >> reg##__##field##__BITNR )
+#define IO_EXTRACT(reg, field, val) IO_EXTRACT_ (reg##_, field##_, val)
+#define IO_EXTRACT_(reg_, field_, val) ( (( ( ( 1 << reg_##_##field_##_WIDTH ) \
+ - 1 ) << reg_##_##field_##_BITNR ) & (val)) >> reg_##_##field_##_BITNR )
/* IO_STATE_VALUE returns a constant corresponding to a one of the symbolic
states that the bitfield can have. (Not shifted) */
-#define IO_STATE_VALUE(reg,field,state) ( reg##__##field##__##state )
+#define IO_STATE_VALUE(reg, field, state) \
+ IO_STATE_VALUE_ (reg##_, field##_, _##state)
+#define IO_STATE_VALUE_(reg_, field_, _state) ( reg_##_##field_##_state )
/* IO_FIELD shifts the val parameter to be aligned with the bitfield
specified. */
-#define IO_FIELD(reg,field,val) ((val) << reg##__##field##__BITNR)
+#define IO_FIELD(reg, field, val) IO_FIELD_ (reg##_, field##_, val)
+#define IO_FIELD_(reg_, field_, val) ((val) << reg_##_##field_##_BITNR)
/* IO_BITNR returns the starting bitnumber of a bitfield. Bit 0 is
LSB and the returned bitnumber is LSB of the field. */
-#define IO_BITNR(reg,field) (reg##__##field##__BITNR)
+#define IO_BITNR(reg, field) IO_BITNR_ (reg##_, field##_)
+#define IO_BITNR_(reg_, field_) (reg_##_##field_##_BITNR)
/* IO_WIDTH returns the width, in bits, of a bitfield. */
-#define IO_WIDTH(reg,field) (reg##__##field##__WIDTH)
+#define IO_WIDTH(reg, field) IO_WIDTH_ (reg##_, field##_)
+#define IO_WIDTH_(reg_, field_) (reg_##_##field_##_WIDTH)
/*--- Obsolete. Kept for backw compatibility. ---*/
/* Reads (or writes) a byte/uword/udword from the specified mode
@@ -66,7 +74,9 @@
!*-----------------------------------------------------------*/
#define MEM_CSE0_START (0x00000000)
+#define MEM_CSE0_SIZE (0x04000000)
#define MEM_CSE1_START (0x04000000)
+#define MEM_CSE1_SIZE (0x04000000)
#define MEM_CSR0_START (0x08000000)
#define MEM_CSR1_START (0x0c000000)
#define MEM_CSP0_START (0x10000000)
diff --git a/include/asm-cris/svinto.h b/include/asm-cris/arch-v10/svinto.h
index c0a16650a20e..0881a1af7cee 100644
--- a/include/asm-cris/svinto.h
+++ b/include/asm-cris/arch-v10/svinto.h
@@ -58,4 +58,7 @@ typedef struct etrax_dma_descr {
*/
#define WAIT_DMA( n ) WAIT_DMA_NUM( n )
+extern void prepare_rx_descriptor(struct etrax_dma_descr *desc);
+extern void flush_etrax_cache(void);
+
#endif
diff --git a/include/asm-cris/arch-v10/system.h b/include/asm-cris/arch-v10/system.h
new file mode 100644
index 000000000000..781ca30229a8
--- /dev/null
+++ b/include/asm-cris/arch-v10/system.h
@@ -0,0 +1,62 @@
+#ifndef __ASM_CRIS_ARCH_SYSTEM_H
+#define __ASM_CRIS_ARCH_SYSTEM_H
+
+#include <linux/config.h>
+
+/* read the CPU version register */
+
+extern inline unsigned long rdvr(void) {
+ unsigned char vr;
+ __asm__ volatile ("move $vr,%0" : "=rm" (vr));
+ return vr;
+}
+
+/* read/write the user-mode stackpointer */
+
+extern inline unsigned long rdusp(void) {
+ unsigned long usp;
+ __asm__ __volatile__("move $usp,%0" : "=rm" (usp));
+ return usp;
+}
+
+#define wrusp(usp) \
+ __asm__ __volatile__("move %0,$usp" : /* no outputs */ : "rm" (usp))
+
+/* read the current stackpointer */
+
+extern inline unsigned long rdsp(void) {
+ unsigned long sp;
+ __asm__ __volatile__("move.d $sp,%0" : "=rm" (sp));
+ return sp;
+}
+
+extern inline unsigned long _get_base(char * addr)
+{
+ return 0;
+}
+
+#define nop() __asm__ __volatile__ ("nop");
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) (xchg((ptr),1))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+/* interrupt control.. */
+#define local_save_flags(x) __asm__ __volatile__ ("move $ccr,%0" : "=rm" (x) : : "memory");
+#define local_irq_restore(x) __asm__ __volatile__ ("move %0,$ccr" : : "rm" (x) : "memory");
+#define local_irq_disable() __asm__ __volatile__ ( "di" : : :"memory");
+#define local_irq_enable() __asm__ __volatile__ ( "ei" : : :"memory");
+
+#define irqs_disabled() \
+({ \
+ unsigned long flags; \
+ local_save_flags(flags); \
+ !(flags & (1<<5)); \
+})
+
+/* For spinlocks etc */
+#define local_irq_save(x) __asm__ __volatile__ ("move $ccr,%0\n\tdi" : "=rm" (x) : : "memory");
+
+#endif
diff --git a/include/asm-cris/arch-v10/thread_info.h b/include/asm-cris/arch-v10/thread_info.h
new file mode 100644
index 000000000000..357f5df0c907
--- /dev/null
+++ b/include/asm-cris/arch-v10/thread_info.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_ARCH_THREAD_INFO_H
+#define _ASM_ARCH_THREAD_INFO_H
+
+/* how to get the thread information struct from C */
+extern inline struct thread_info *current_thread_info(void)
+{
+ struct thread_info *ti;
+ __asm__("and.d $sp,%0; ":"=r" (ti) : "0" (~8191UL));
+ return ti;
+}
+
+#endif
diff --git a/include/asm-cris/arch-v10/timex.h b/include/asm-cris/arch-v10/timex.h
new file mode 100644
index 000000000000..ecfc553c06a5
--- /dev/null
+++ b/include/asm-cris/arch-v10/timex.h
@@ -0,0 +1,30 @@
+/*
+ * Use prescale timer at 25000 Hz instead of the baudrate timer at
+ * 19200 to get rid of the 64ppm to fast timer (and we get better
+ * resolution within a jiffie as well.
+ */
+#ifndef _ASM_CRIS_ARCH_TIMEX_H
+#define _ASM_CRIS_ARCH_TIMEX_H
+
+/* The prescaler clock runs at 25MHz, we divide it by 1000 in the prescaler */
+/* If you change anything here you must check time.c as well... */
+#define PRESCALE_FREQ 25000000
+#define PRESCALE_VALUE 1000
+#define CLOCK_TICK_RATE 25000 /* Underlying frequency of the HZ timer */
+/* The timer0 values gives 40us resolution (1/25000) but interrupts at HZ*/
+#define TIMER0_FREQ (CLOCK_TICK_RATE)
+#define TIMER0_CLKSEL flexible
+#define TIMER0_DIV (TIMER0_FREQ/(HZ))
+
+
+#define GET_JIFFIES_USEC() \
+ ( (TIMER0_DIV - *R_TIMER0_DATA) * (1000000/HZ)/TIMER0_DIV )
+
+unsigned long get_ns_in_jiffie(void);
+
+extern inline unsigned long get_us_in_jiffie_highres(void)
+{
+ return get_ns_in_jiffie()/1000;
+}
+
+#endif
diff --git a/include/asm-cris/arch-v10/tlb.h b/include/asm-cris/arch-v10/tlb.h
new file mode 100644
index 000000000000..31525bbe75c3
--- /dev/null
+++ b/include/asm-cris/arch-v10/tlb.h
@@ -0,0 +1,13 @@
+#ifndef _CRIS_ARCH_TLB_H
+#define _CRIS_ARCH_TLB_H
+
+/* The TLB can host up to 64 different mm contexts at the same time.
+ * The last page_id is never running - it is used as an invalid page_id
+ * so we can make TLB entries that will never match.
+ */
+#define NUM_TLB_ENTRIES 64
+#define NUM_PAGEID 64
+#define INVALID_PAGEID 63
+#define NO_CONTEXT -1
+
+#endif
diff --git a/include/asm-cris/arch-v10/uaccess.h b/include/asm-cris/arch-v10/uaccess.h
new file mode 100644
index 000000000000..787d2e60c83c
--- /dev/null
+++ b/include/asm-cris/arch-v10/uaccess.h
@@ -0,0 +1,660 @@
+/*
+ * Authors: Bjorn Wesen (bjornw@axis.com)
+ * Hans-Peter Nilsson (hp@axis.com)
+ *
+ */
+#ifndef _CRIS_ARCH_UACCESS_H
+#define _CRIS_ARCH_UACCESS_H
+
+/*
+ * We don't tell gcc that we are accessing memory, but this is OK
+ * because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ *
+ * Note that PC at a fault is the address *after* the faulting
+ * instruction.
+ */
+#define __put_user_asm(x, addr, err, op) \
+ __asm__ __volatile__( \
+ " "op" %1,[%2]\n" \
+ "2:\n" \
+ " .section .fixup,\"ax\"\n" \
+ "3: move.d %3,%0\n" \
+ " jump 2b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .dword 2b,3b\n" \
+ " .previous\n" \
+ : "=r" (err) \
+ : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
+
+#define __put_user_asm_64(x, addr, err) \
+ __asm__ __volatile__( \
+ " move.d %M1,[%2]\n" \
+ "2: move.d %H1,[%2+4]\n" \
+ "4:\n" \
+ " .section .fixup,\"ax\"\n" \
+ "3: move.d %3,%0\n" \
+ " jump 4b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .dword 2b,3b\n" \
+ " .dword 4b,3b\n" \
+ " .previous\n" \
+ : "=r" (err) \
+ : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
+
+/* See comment before __put_user_asm. */
+
+#define __get_user_asm(x, addr, err, op) \
+ __asm__ __volatile__( \
+ " "op" [%2],%1\n" \
+ "2:\n" \
+ " .section .fixup,\"ax\"\n" \
+ "3: move.d %3,%0\n" \
+ " moveq 0,%1\n" \
+ " jump 2b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .dword 2b,3b\n" \
+ " .previous\n" \
+ : "=r" (err), "=r" (x) \
+ : "r" (addr), "g" (-EFAULT), "0" (err))
+
+#define __get_user_asm_64(x, addr, err) \
+ __asm__ __volatile__( \
+ " move.d [%2],%M1\n" \
+ "2: move.d [%2+4],%H1\n" \
+ "4:\n" \
+ " .section .fixup,\"ax\"\n" \
+ "3: move.d %3,%0\n" \
+ " moveq 0,%1\n" \
+ " jump 4b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .dword 2b,3b\n" \
+ " .dword 4b,3b\n" \
+ " .previous\n" \
+ : "=r" (err), "=r" (x) \
+ : "r" (addr), "g" (-EFAULT), "0" (err))
+
+/*
+ * Copy a null terminated string from userspace.
+ *
+ * Must return:
+ * -EFAULT for an exception
+ * count if we hit the buffer limit
+ * bytes copied if we hit a null byte
+ * (without the null byte)
+ */
+extern inline long
+__do_strncpy_from_user(char *dst, const char *src, long count)
+{
+ long res;
+
+ if (count == 0)
+ return 0;
+
+ /*
+ * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
+ * So do we.
+ *
+ * This code is deduced from:
+ *
+ * char tmp2;
+ * long tmp1, tmp3
+ * tmp1 = count;
+ * while ((*dst++ = (tmp2 = *src++)) != 0
+ * && --tmp1)
+ * ;
+ *
+ * res = count - tmp1;
+ *
+ * with tweaks.
+ */
+
+ __asm__ __volatile__ (
+ " move.d %3,%0\n"
+ " move.b [%2+],$r9\n"
+ "1: beq 2f\n"
+ " move.b $r9,[%1+]\n"
+
+ " subq 1,%0\n"
+ " bne 1b\n"
+ " move.b [%2+],$r9\n"
+
+ "2: sub.d %3,%0\n"
+ " neg.d %0,%0\n"
+ "3:\n"
+ " .section .fixup,\"ax\"\n"
+ "4: move.d %7,%0\n"
+ " jump 3b\n"
+
+ /* There's one address for a fault at the first move, and
+ two possible PC values for a fault at the second move,
+ being a delay-slot filler. However, the branch-target
+ for the second move is the same as the first address.
+ Just so you don't get confused... */
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .dword 1b,4b\n"
+ " .dword 2b,4b\n"
+ " .previous"
+ : "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
+ : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
+ : "r9");
+
+ return res;
+}
+
+/* A few copy asms to build up the more complex ones from.
+
+ Note again, a post-increment is performed regardless of whether a bus
+ fault occurred in that instruction, and PC for a faulted insn is the
+ address *after* the insn. */
+
+#define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm__ __volatile__ ( \
+ COPY \
+ "1:\n" \
+ " .section .fixup,\"ax\"\n" \
+ FIXUP \
+ " jump 1b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ TENTRY \
+ " .previous\n" \
+ : "=r" (to), "=r" (from), "=r" (ret) \
+ : "0" (to), "1" (from), "2" (ret) \
+ : "r9", "memory")
+
+#define __asm_copy_from_user_1(to, from, ret) \
+ __asm_copy_user_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "2: move.b $r9,[%0+]\n", \
+ "3: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 2b,3b\n")
+
+#define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_user_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ "2: move.w $r9,[%0+]\n" COPY, \
+ "3: addq 2,%2\n" \
+ " clear.w [%0+]\n" FIXUP, \
+ " .dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_from_user_2(to, from, ret) \
+ __asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_3(to, from, ret) \
+ __asm_copy_from_user_2x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "4: move.b $r9,[%0+]\n", \
+ "5: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 4b,5b\n")
+
+#define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_user_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ "2: move.d $r9,[%0+]\n" COPY, \
+ "3: addq 4,%2\n" \
+ " clear.d [%0+]\n" FIXUP, \
+ " .dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_from_user_4(to, from, ret) \
+ __asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_5(to, from, ret) \
+ __asm_copy_from_user_4x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "4: move.b $r9,[%0+]\n", \
+ "5: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 4b,5b\n")
+
+#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_4x_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ "4: move.w $r9,[%0+]\n" COPY, \
+ "5: addq 2,%2\n" \
+ " clear.w [%0+]\n" FIXUP, \
+ " .dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_from_user_6(to, from, ret) \
+ __asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_7(to, from, ret) \
+ __asm_copy_from_user_6x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "6: move.b $r9,[%0+]\n", \
+ "7: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 6b,7b\n")
+
+#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_4x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ "4: move.d $r9,[%0+]\n" COPY, \
+ "5: addq 4,%2\n" \
+ " clear.d [%0+]\n" FIXUP, \
+ " .dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_from_user_8(to, from, ret) \
+ __asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_9(to, from, ret) \
+ __asm_copy_from_user_8x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "6: move.b $r9,[%0+]\n", \
+ "7: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 6b,7b\n")
+
+#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_8x_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ "6: move.w $r9,[%0+]\n" COPY, \
+ "7: addq 2,%2\n" \
+ " clear.w [%0+]\n" FIXUP, \
+ " .dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_from_user_10(to, from, ret) \
+ __asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_11(to, from, ret) \
+ __asm_copy_from_user_10x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "8: move.b $r9,[%0+]\n", \
+ "9: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 8b,9b\n")
+
+#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_8x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ "6: move.d $r9,[%0+]\n" COPY, \
+ "7: addq 4,%2\n" \
+ " clear.d [%0+]\n" FIXUP, \
+ " .dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_from_user_12(to, from, ret) \
+ __asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_13(to, from, ret) \
+ __asm_copy_from_user_12x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "8: move.b $r9,[%0+]\n", \
+ "9: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 8b,9b\n")
+
+#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_12x_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ "8: move.w $r9,[%0+]\n" COPY, \
+ "9: addq 2,%2\n" \
+ " clear.w [%0+]\n" FIXUP, \
+ " .dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_from_user_14(to, from, ret) \
+ __asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_15(to, from, ret) \
+ __asm_copy_from_user_14x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ "10: move.b $r9,[%0+]\n", \
+ "11: addq 1,%2\n" \
+ " clear.b [%0+]\n", \
+ " .dword 10b,11b\n")
+
+#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_12x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ "8: move.d $r9,[%0+]\n" COPY, \
+ "9: addq 4,%2\n" \
+ " clear.d [%0+]\n" FIXUP, \
+ " .dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_from_user_16(to, from, ret) \
+ __asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_16x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ "10: move.d $r9,[%0+]\n" COPY, \
+ "11: addq 4,%2\n" \
+ " clear.d [%0+]\n" FIXUP, \
+ " .dword 10b,11b\n" TENTRY)
+
+#define __asm_copy_from_user_20(to, from, ret) \
+ __asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_from_user_20x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ "12: move.d $r9,[%0+]\n" COPY, \
+ "13: addq 4,%2\n" \
+ " clear.d [%0+]\n" FIXUP, \
+ " .dword 12b,13b\n" TENTRY)
+
+#define __asm_copy_from_user_24(to, from, ret) \
+ __asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
+
+/* And now, the to-user ones. */
+
+#define __asm_copy_to_user_1(to, from, ret) \
+ __asm_copy_user_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n2:\n", \
+ "3: addq 1,%2\n", \
+ " .dword 2b,3b\n")
+
+#define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_user_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ " move.w $r9,[%0+]\n2:\n" COPY, \
+ "3: addq 2,%2\n" FIXUP, \
+ " .dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_to_user_2(to, from, ret) \
+ __asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_3(to, from, ret) \
+ __asm_copy_to_user_2x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n4:\n", \
+ "5: addq 1,%2\n", \
+ " .dword 4b,5b\n")
+
+#define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_user_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ " move.d $r9,[%0+]\n2:\n" COPY, \
+ "3: addq 4,%2\n" FIXUP, \
+ " .dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_to_user_4(to, from, ret) \
+ __asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_5(to, from, ret) \
+ __asm_copy_to_user_4x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n4:\n", \
+ "5: addq 1,%2\n", \
+ " .dword 4b,5b\n")
+
+#define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_4x_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ " move.w $r9,[%0+]\n4:\n" COPY, \
+ "5: addq 2,%2\n" FIXUP, \
+ " .dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_to_user_6(to, from, ret) \
+ __asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_7(to, from, ret) \
+ __asm_copy_to_user_6x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n6:\n", \
+ "7: addq 1,%2\n", \
+ " .dword 6b,7b\n")
+
+#define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_4x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ " move.d $r9,[%0+]\n4:\n" COPY, \
+ "5: addq 4,%2\n" FIXUP, \
+ " .dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_to_user_8(to, from, ret) \
+ __asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_9(to, from, ret) \
+ __asm_copy_to_user_8x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n6:\n", \
+ "7: addq 1,%2\n", \
+ " .dword 6b,7b\n")
+
+#define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_8x_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ " move.w $r9,[%0+]\n6:\n" COPY, \
+ "7: addq 2,%2\n" FIXUP, \
+ " .dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_to_user_10(to, from, ret) \
+ __asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_11(to, from, ret) \
+ __asm_copy_to_user_10x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n8:\n", \
+ "9: addq 1,%2\n", \
+ " .dword 8b,9b\n")
+
+#define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_8x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ " move.d $r9,[%0+]\n6:\n" COPY, \
+ "7: addq 4,%2\n" FIXUP, \
+ " .dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_to_user_12(to, from, ret) \
+ __asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_13(to, from, ret) \
+ __asm_copy_to_user_12x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n8:\n", \
+ "9: addq 1,%2\n", \
+ " .dword 8b,9b\n")
+
+#define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_12x_cont(to, from, ret, \
+ " move.w [%1+],$r9\n" \
+ " move.w $r9,[%0+]\n8:\n" COPY, \
+ "9: addq 2,%2\n" FIXUP, \
+ " .dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_to_user_14(to, from, ret) \
+ __asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_15(to, from, ret) \
+ __asm_copy_to_user_14x_cont(to, from, ret, \
+ " move.b [%1+],$r9\n" \
+ " move.b $r9,[%0+]\n10:\n", \
+ "11: addq 1,%2\n", \
+ " .dword 10b,11b\n")
+
+#define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_12x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ " move.d $r9,[%0+]\n8:\n" COPY, \
+ "9: addq 4,%2\n" FIXUP, \
+ " .dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_to_user_16(to, from, ret) \
+ __asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_16x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ " move.d $r9,[%0+]\n10:\n" COPY, \
+ "11: addq 4,%2\n" FIXUP, \
+ " .dword 10b,11b\n" TENTRY)
+
+#define __asm_copy_to_user_20(to, from, ret) \
+ __asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+ __asm_copy_to_user_20x_cont(to, from, ret, \
+ " move.d [%1+],$r9\n" \
+ " move.d $r9,[%0+]\n12:\n" COPY, \
+ "13: addq 4,%2\n" FIXUP, \
+ " .dword 12b,13b\n" TENTRY)
+
+#define __asm_copy_to_user_24(to, from, ret) \
+ __asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
+
+/* Define a few clearing asms with exception handlers. */
+
+/* This frame-asm is like the __asm_copy_user_cont one, but has one less
+ input. */
+
+#define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
+ __asm__ __volatile__ ( \
+ CLEAR \
+ "1:\n" \
+ " .section .fixup,\"ax\"\n" \
+ FIXUP \
+ " jump 1b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ TENTRY \
+ " .previous" \
+ : "=r" (to), "=r" (ret) \
+ : "0" (to), "1" (ret) \
+ : "memory")
+
+#define __asm_clear_1(to, ret) \
+ __asm_clear(to, ret, \
+ " clear.b [%0+]\n2:\n", \
+ "3: addq 1,%1\n", \
+ " .dword 2b,3b\n")
+
+#define __asm_clear_2(to, ret) \
+ __asm_clear(to, ret, \
+ " clear.w [%0+]\n2:\n", \
+ "3: addq 2,%1\n", \
+ " .dword 2b,3b\n")
+
+#define __asm_clear_3(to, ret) \
+ __asm_clear(to, ret, \
+ " clear.w [%0+]\n" \
+ "2: clear.b [%0+]\n3:\n", \
+ "4: addq 2,%1\n" \
+ "5: addq 1,%1\n", \
+ " .dword 2b,4b\n" \
+ " .dword 3b,5b\n")
+
+#define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+ __asm_clear(to, ret, \
+ " clear.d [%0+]\n2:\n" CLEAR, \
+ "3: addq 4,%1\n" FIXUP, \
+ " .dword 2b,3b\n" TENTRY)
+
+#define __asm_clear_4(to, ret) \
+ __asm_clear_4x_cont(to, ret, "", "", "")
+
+#define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+ __asm_clear_4x_cont(to, ret, \
+ " clear.d [%0+]\n4:\n" CLEAR, \
+ "5: addq 4,%1\n" FIXUP, \
+ " .dword 4b,5b\n" TENTRY)
+
+#define __asm_clear_8(to, ret) \
+ __asm_clear_8x_cont(to, ret, "", "", "")
+
+#define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+ __asm_clear_8x_cont(to, ret, \
+ " clear.d [%0+]\n6:\n" CLEAR, \
+ "7: addq 4,%1\n" FIXUP, \
+ " .dword 6b,7b\n" TENTRY)
+
+#define __asm_clear_12(to, ret) \
+ __asm_clear_12x_cont(to, ret, "", "", "")
+
+#define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+ __asm_clear_12x_cont(to, ret, \
+ " clear.d [%0+]\n8:\n" CLEAR, \
+ "9: addq 4,%1\n" FIXUP, \
+ " .dword 8b,9b\n" TENTRY)
+
+#define __asm_clear_16(to, ret) \
+ __asm_clear_16x_cont(to, ret, "", "", "")
+
+#define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+ __asm_clear_16x_cont(to, ret, \
+ " clear.d [%0+]\n10:\n" CLEAR, \
+ "11: addq 4,%1\n" FIXUP, \
+ " .dword 10b,11b\n" TENTRY)
+
+#define __asm_clear_20(to, ret) \
+ __asm_clear_20x_cont(to, ret, "", "", "")
+
+#define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+ __asm_clear_20x_cont(to, ret, \
+ " clear.d [%0+]\n12:\n" CLEAR, \
+ "13: addq 4,%1\n" FIXUP, \
+ " .dword 12b,13b\n" TENTRY)
+
+#define __asm_clear_24(to, ret) \
+ __asm_clear_24x_cont(to, ret, "", "", "")
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return length of string in userspace including terminating 0
+ * or 0 for error. Return a value greater than N if too long.
+ */
+
+extern inline long
+strnlen_user(const char *s, long n)
+{
+ long res, tmp1;
+
+ if (!access_ok(VERIFY_READ, s, 0))
+ return 0;
+
+ /*
+ * This code is deduced from:
+ *
+ * tmp1 = n;
+ * while (tmp1-- > 0 && *s++)
+ * ;
+ *
+ * res = n - tmp1;
+ *
+ * (with tweaks).
+ */
+
+ __asm__ __volatile__ (
+ " move.d %1,$r9\n"
+ "0:\n"
+ " ble 1f\n"
+ " subq 1,$r9\n"
+
+ " test.b [%0+]\n"
+ " bne 0b\n"
+ " test.d $r9\n"
+ "1:\n"
+ " move.d %1,%0\n"
+ " sub.d $r9,%0\n"
+ "2:\n"
+ " .section .fixup,\"ax\"\n"
+
+ "3: clear.d %0\n"
+ " jump 2b\n"
+
+ /* There's one address for a fault at the first move, and
+ two possible PC values for a fault at the second move,
+ being a delay-slot filler. However, the branch-target
+ for the second move is the same as the first address.
+ Just so you don't get confused... */
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .dword 0b,3b\n"
+ " .dword 1b,3b\n"
+ " .previous\n"
+ : "=r" (res), "=r" (tmp1)
+ : "0" (s), "1" (n)
+ : "r9");
+
+ return res;
+}
+
+#endif
diff --git a/include/asm-cris/arch-v10/unistd.h b/include/asm-cris/arch-v10/unistd.h
new file mode 100644
index 000000000000..d1a38b9e6264
--- /dev/null
+++ b/include/asm-cris/arch-v10/unistd.h
@@ -0,0 +1,148 @@
+#ifndef _ASM_CRIS_ARCH_UNISTD_H_
+#define _ASM_CRIS_ARCH_UNISTD_H_
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+/*
+ * Don't remove the .ifnc tests; they are an insurance against
+ * any hard-to-spot gcc register allocation bugs.
+ */
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+ register long __a __asm__ ("r10"); \
+ register long __n_ __asm__ ("r9") = (__NR_##name); \
+ __asm__ __volatile__ (".ifnc %0%1,$r10$r9\n\t" \
+ ".err\n\t" \
+ ".endif\n\t" \
+ "break 13" \
+ : "=r" (__a) \
+ : "r" (__n_)); \
+ if (__a >= 0) \
+ return (type) __a; \
+ errno = -__a; \
+ return (type) -1; \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+ register long __a __asm__ ("r10") = (long) arg1; \
+ register long __n_ __asm__ ("r9") = (__NR_##name); \
+ __asm__ __volatile__ (".ifnc %0%1,$r10$r9\n\t" \
+ ".err\n\t" \
+ ".endif\n\t" \
+ "break 13" \
+ : "=r" (__a) \
+ : "r" (__n_), "0" (__a)); \
+ if (__a >= 0) \
+ return (type) __a; \
+ errno = -__a; \
+ return (type) -1; \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+ register long __a __asm__ ("r10") = (long) arg1; \
+ register long __b __asm__ ("r11") = (long) arg2; \
+ register long __n_ __asm__ ("r9") = (__NR_##name); \
+ __asm__ __volatile__ (".ifnc %0%1%3,$r10$r9$r11\n\t" \
+ ".err\n\t" \
+ ".endif\n\t" \
+ "break 13" \
+ : "=r" (__a) \
+ : "r" (__n_), "0" (__a), "r" (__b)); \
+ if (__a >= 0) \
+ return (type) __a; \
+ errno = -__a; \
+ return (type) -1; \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+ register long __a __asm__ ("r10") = (long) arg1; \
+ register long __b __asm__ ("r11") = (long) arg2; \
+ register long __c __asm__ ("r12") = (long) arg3; \
+ register long __n_ __asm__ ("r9") = (__NR_##name); \
+ __asm__ __volatile__ (".ifnc %0%1%3%4,$r10$r9$r11$r12\n\t" \
+ ".err\n\t" \
+ ".endif\n\t" \
+ "break 13" \
+ : "=r" (__a) \
+ : "r" (__n_), "0" (__a), "r" (__b), "r" (__c)); \
+ if (__a >= 0) \
+ return (type) __a; \
+ errno = -__a; \
+ return (type) -1; \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+ register long __a __asm__ ("r10") = (long) arg1; \
+ register long __b __asm__ ("r11") = (long) arg2; \
+ register long __c __asm__ ("r12") = (long) arg3; \
+ register long __d __asm__ ("r13") = (long) arg4; \
+ register long __n_ __asm__ ("r9") = (__NR_##name); \
+ __asm__ __volatile__ (".ifnc %0%1%3%4%5,$r10$r9$r11$r12$r13\n\t" \
+ ".err\n\t" \
+ ".endif\n\t" \
+ "break 13" \
+ : "=r" (__a) \
+ : "r" (__n_), "0" (__a), "r" (__b), \
+ "r" (__c), "r" (__d)); \
+ if (__a >= 0) \
+ return (type) __a; \
+ errno = -__a; \
+ return (type) -1; \
+}
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+ register long __a __asm__ ("r10") = (long) arg1; \
+ register long __b __asm__ ("r11") = (long) arg2; \
+ register long __c __asm__ ("r12") = (long) arg3; \
+ register long __d __asm__ ("r13") = (long) arg4; \
+ register long __n_ __asm__ ("r9") = (__NR_##name); \
+ __asm__ __volatile__ (".ifnc %0%1%3%4%5,$r10$r9$r11$r12$r13\n\t" \
+ ".err\n\t" \
+ ".endif\n\t" \
+ "move %6,$mof\n\t" \
+ "break 13" \
+ : "=r" (__a) \
+ : "r" (__n_), "0" (__a), "r" (__b), \
+ "r" (__c), "r" (__d), "g" (arg5)); \
+ if (__a >= 0) \
+ return (type) __a; \
+ errno = -__a; \
+ return (type) -1; \
+}
+
+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
+{ \
+ register long __a __asm__ ("r10") = (long) arg1; \
+ register long __b __asm__ ("r11") = (long) arg2; \
+ register long __c __asm__ ("r12") = (long) arg3; \
+ register long __d __asm__ ("r13") = (long) arg4; \
+ register long __n_ __asm__ ("r9") = (__NR_##name); \
+ __asm__ __volatile__ (".ifnc %0%1%3%4%5,$r10$r9$r11$r12$r13\n\t" \
+ ".err\n\t" \
+ ".endif\n\t" \
+ "move %6,$mof\n\tmove %7,$srp\n\t" \
+ "break 13" \
+ : "=r" (__a) \
+ : "r" (__n_), "0" (__a), "r" (__b), \
+ "r" (__c), "r" (__d), "g" (arg5), "g" (arg6)\
+ : "srp"); \
+ if (__a >= 0) \
+ return (type) __a; \
+ errno = -__a; \
+ return (type) -1; \
+}
+
+#endif
diff --git a/include/asm-cris/arch-v10/user.h b/include/asm-cris/arch-v10/user.h
new file mode 100644
index 000000000000..9303ea77c915
--- /dev/null
+++ b/include/asm-cris/arch-v10/user.h
@@ -0,0 +1,46 @@
+#ifndef __ASM_CRIS_ARCH_USER_H
+#define __ASM_CRIS_ARCH_USER_H
+
+/* User mode registers, used for core dumps. In order to keep ELF_NGREG
+ sensible we let all registers be 32 bits. The csr registers are included
+ for future use. */
+struct user_regs_struct {
+ unsigned long r0; /* General registers. */
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long r11;
+ unsigned long r12;
+ unsigned long r13;
+ unsigned long sp; /* Stack pointer. */
+ unsigned long pc; /* Program counter. */
+ unsigned long p0; /* Constant zero (only 8 bits). */
+ unsigned long vr; /* Version register (only 8 bits). */
+ unsigned long p2; /* Reserved. */
+ unsigned long p3; /* Reserved. */
+ unsigned long p4; /* Constant zero (only 16 bits). */
+ unsigned long ccr; /* Condition code register (only 16 bits). */
+ unsigned long p6; /* Reserved. */
+ unsigned long mof; /* Multiply overflow register. */
+ unsigned long p8; /* Constant zero. */
+ unsigned long ibr; /* Not accessible. */
+ unsigned long irp; /* Not accessible. */
+ unsigned long srp; /* Subroutine return pointer. */
+ unsigned long bar; /* Not accessible. */
+ unsigned long dccr; /* Dword condition code register. */
+ unsigned long brp; /* Not accessible. */
+ unsigned long usp; /* User-mode stack pointer. Same as sp when
+ in user mode. */
+ unsigned long csrinstr; /* Internal status registers. */
+ unsigned long csraddr;
+ unsigned long csrdata;
+};
+
+#endif
diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h
index f2f51505d6dc..19ae993cb561 100644
--- a/include/asm-cris/atomic.h
+++ b/include/asm-cris/atomic.h
@@ -27,115 +27,115 @@ typedef struct { int counter; } atomic_t;
/* These should be written in asm but we do it in C for now. */
-static __inline__ void atomic_add(int i, volatile atomic_t *v)
+extern __inline__ void atomic_add(int i, volatile atomic_t *v)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
v->counter += i;
- restore_flags(flags);
+ local_irq_restore(flags);
}
-static __inline__ void atomic_sub(int i, volatile atomic_t *v)
+extern __inline__ void atomic_sub(int i, volatile atomic_t *v)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
v->counter -= i;
- restore_flags(flags);
+ local_irq_restore(flags);
}
-static __inline__ int atomic_add_return(int i, volatile atomic_t *v)
+extern __inline__ int atomic_add_return(int i, volatile atomic_t *v)
{
unsigned long flags;
int retval;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (v->counter += i);
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
-static __inline__ int atomic_sub_return(int i, volatile atomic_t *v)
+extern __inline__ int atomic_sub_return(int i, volatile atomic_t *v)
{
unsigned long flags;
int retval;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (v->counter -= i);
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
-static __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v)
+extern __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v)
{
int retval;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (v->counter -= i) == 0;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
-static __inline__ void atomic_inc(volatile atomic_t *v)
+extern __inline__ void atomic_inc(volatile atomic_t *v)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
(v->counter)++;
- restore_flags(flags);
+ local_irq_restore(flags);
}
-static __inline__ void atomic_dec(volatile atomic_t *v)
+extern __inline__ void atomic_dec(volatile atomic_t *v)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
(v->counter)--;
- restore_flags(flags);
+ local_irq_restore(flags);
}
-static __inline__ int atomic_inc_return(volatile atomic_t *v)
+extern __inline__ int atomic_inc_return(volatile atomic_t *v)
{
unsigned long flags;
int retval;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (v->counter)++;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
-static __inline__ int atomic_dec_return(volatile atomic_t *v)
+extern __inline__ int atomic_dec_return(volatile atomic_t *v)
{
unsigned long flags;
int retval;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (v->counter)--;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
-static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
+extern __inline__ int atomic_dec_and_test(volatile atomic_t *v)
{
int retval;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = --(v->counter) == 0;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
-static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
+extern __inline__ int atomic_inc_and_test(volatile atomic_t *v)
{
int retval;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = ++(v->counter) == 0;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
diff --git a/include/asm-cris/axisflashmap.h b/include/asm-cris/axisflashmap.h
index c54f65d4a4a7..600bb8715d89 100644
--- a/include/asm-cris/axisflashmap.h
+++ b/include/asm-cris/axisflashmap.h
@@ -9,25 +9,6 @@
* and it has nothing to do with the partition table.
*/
-
-/* the partitiontable consists of some "jump over" code, a head and
- * then the actual entries.
- * tools/mkptable is used to generate the ptable.
- */
-
-/* The partition table starts with code to "jump over" it. The ba
- instruction and delay-slot is modified elsewhere (for example the
- mkptable script); don't change this to fill the delay-slot. */
-#define PARTITIONTABLE_CODE_START { \
- 0x0f, 0x05, /* nop 0 */\
- 0x25, 0xf0, /* di 2 */\
- 0xed, 0xff /* ba 4 */ }
-
-/* The actual offset depend on the number of entries */
-#define PARTITIONTABLE_CODE_END { \
- 0x00, 0x00, /* ba offset 6 */\
- 0x0f, 0x05 /* nop 8 */}
-
#define PARTITION_TABLE_OFFSET 10
#define PARTITION_TABLE_MAGIC 0xbeef /* Not a good magic */
diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h
index 563cc9f6a998..10de1ccd1e01 100644
--- a/include/asm-cris/bitops.h
+++ b/include/asm-cris/bitops.h
@@ -1,9 +1,6 @@
/* asm/bitops.h for Linux/CRIS
*
* TODO: asm versions if speed is needed
- * set_bit, clear_bit and change_bit wastes cycles being only
- * macros into test_and_set_bit etc.
- * kernel-doc things (**) for macros are disabled
*
* All bit operations return 0 if the bit was cleared before the
* operation and != 0 if it was not.
@@ -17,11 +14,8 @@
/* Currently this is unsuitable for consumption outside the kernel. */
#ifdef __KERNEL__
+#include <asm/arch/bitops.h>
#include <asm/system.h>
-
-/* We use generic_ffs so get it; include guards resolve the possible
- mutually inclusion. */
-#include <linux/bitops.h>
#include <linux/compiler.h>
/*
@@ -63,7 +57,7 @@ struct __dummy { unsigned long a[100]; };
/*
* change_bit - Toggle a bit in memory
- * @nr: Bit to clear
+ * @nr: Bit to change
* @addr: Address to start counting from
*
* change_bit() is atomic and may not be reordered.
@@ -75,7 +69,7 @@ struct __dummy { unsigned long a[100]; };
/*
* __change_bit - Toggle a bit in memory
- * @nr: the bit to set
+ * @nr: the bit to change
* @addr: the address to start counting from
*
* Unlike change_bit(), this function is non-atomic and may be reordered.
@@ -94,7 +88,7 @@ struct __dummy { unsigned long a[100]; };
* It also implies a memory barrier.
*/
-static inline int test_and_set_bit(int nr, void *addr)
+extern inline int test_and_set_bit(int nr, void *addr)
{
unsigned int mask, retval;
unsigned long flags;
@@ -102,15 +96,15 @@ static inline int test_and_set_bit(int nr, void *addr)
adr += nr >> 5;
mask = 1 << (nr & 0x1f);
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (mask & *adr) != 0;
*adr |= mask;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
-static inline int __test_and_set_bit(int nr, void *addr)
+extern inline int __test_and_set_bit(int nr, void *addr)
{
unsigned int mask, retval;
unsigned int *adr = (unsigned int *)addr;
@@ -130,14 +124,14 @@ static inline int __test_and_set_bit(int nr, void *addr)
/**
* test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to set
+ * @nr: Bit to clear
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
* It also implies a memory barrier.
*/
-static inline int test_and_clear_bit(int nr, void *addr)
+extern inline int test_and_clear_bit(int nr, void *addr)
{
unsigned int mask, retval;
unsigned long flags;
@@ -145,17 +139,17 @@ static inline int test_and_clear_bit(int nr, void *addr)
adr += nr >> 5;
mask = 1 << (nr & 0x1f);
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (mask & *adr) != 0;
*adr &= ~mask;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
/**
* __test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to set
+ * @nr: Bit to clear
* @addr: Address to count from
*
* This operation is non-atomic and can be reordered.
@@ -163,7 +157,7 @@ static inline int test_and_clear_bit(int nr, void *addr)
* but actually fail. You must protect multiple accesses with a lock.
*/
-static inline int __test_and_clear_bit(int nr, void *addr)
+extern inline int __test_and_clear_bit(int nr, void *addr)
{
unsigned int mask, retval;
unsigned int *adr = (unsigned int *)addr;
@@ -176,31 +170,31 @@ static inline int __test_and_clear_bit(int nr, void *addr)
}
/**
* test_and_change_bit - Change a bit and return its new value
- * @nr: Bit to set
+ * @nr: Bit to change
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
* It also implies a memory barrier.
*/
-static inline int test_and_change_bit(int nr, void *addr)
+extern inline int test_and_change_bit(int nr, void *addr)
{
unsigned int mask, retval;
unsigned long flags;
unsigned int *adr = (unsigned int *)addr;
adr += nr >> 5;
mask = 1 << (nr & 0x1f);
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
retval = (mask & *adr) != 0;
*adr ^= mask;
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
/* WARNING: non atomic and it can be reordered! */
-static inline int __test_and_change_bit(int nr, void *addr)
+extern inline int __test_and_change_bit(int nr, void *addr)
{
unsigned int mask, retval;
unsigned int *adr = (unsigned int *)addr;
@@ -221,7 +215,7 @@ static inline int __test_and_change_bit(int nr, void *addr)
* This routine doesn't need to be atomic.
*/
-static inline int test_bit(int nr, const void *addr)
+extern inline int test_bit(int nr, const void *addr)
{
unsigned int mask;
unsigned int *adr = (unsigned int *)addr;
@@ -236,63 +230,28 @@ static inline int test_bit(int nr, const void *addr)
*/
/*
- * Helper functions for the core of the ff[sz] functions, wrapping the
- * syntactically awkward asms. The asms compute the number of leading
- * zeroes of a bits-in-byte and byte-in-word and word-in-dword-swapped
- * number. They differ in that the first function also inverts all bits
- * in the input.
+ * Since we define it "external", it collides with the built-in
+ * definition, which doesn't have the same semantics. We don't want to
+ * use -fno-builtin, so just hide the name ffs.
*/
-static inline unsigned long cris_swapnwbrlz(unsigned long w)
-{
- /* Let's just say we return the result in the same register as the
- input. Saying we clobber the input but can return the result
- in another register:
- ! __asm__ ("swapnwbr %2\n\tlz %2,%0"
- ! : "=r,r" (res), "=r,X" (dummy) : "1,0" (w));
- confuses gcc (sched.c, gcc from cris-dist-1.14). */
-
- unsigned long res;
- __asm__ ("swapnwbr %0 \n\t"
- "lz %0,%0"
- : "=r" (res) : "0" (w));
- return res;
-}
-
-static inline unsigned long cris_swapwbrlz(unsigned long w)
-{
- unsigned res;
- __asm__ ("swapwbr %0 \n\t"
- "lz %0,%0"
- : "=r" (res)
- : "0" (w));
- return res;
-}
+#define ffs kernel_ffs
/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
+ * fls: find last bit set.
*/
-static inline unsigned long ffz(unsigned long w)
-{
- /* The generic_ffs function is used to avoid the asm when the
- argument is a constant. */
- return __builtin_constant_p (w)
- ? (~w ? (unsigned long) generic_ffs ((int) ~w) - 1 : 32)
- : cris_swapnwbrlz (w);
-}
+
+#define fls(x) generic_fls(x)
/*
- * Somewhat like ffz but the equivalent of generic_ffs: in contrast to
- * ffz we return the first one-bit *plus one*.
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
*/
-static inline unsigned long ffs(unsigned long w)
-{
- /* The generic_ffs function is used to avoid the asm when the
- argument is a constant. */
- return __builtin_constant_p (w)
- ? (unsigned long) generic_ffs ((int) w)
- : w ? cris_swapwbrlz (w) + 1 : 0;
-}
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
/**
* find_next_zero_bit - find the first zero bit in a memory region
@@ -300,7 +259,7 @@ static inline unsigned long ffs(unsigned long w)
* @offset: The bitnumber to start searching at
* @size: The maximum size to search
*/
-static inline int find_next_zero_bit (void * addr, int size, int offset)
+extern inline int find_next_zero_bit (void * addr, int size, int offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
unsigned long result = offset & ~31UL;
@@ -348,17 +307,6 @@ static inline int find_next_zero_bit (void * addr, int size, int offset)
#define find_first_zero_bit(addr, size) \
find_next_zero_bit((addr), (size), 0)
-/*
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
- * The Hamming Weight of a number is the total number of bits set in it.
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
#define ext2_set_bit test_and_set_bit
#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
#define ext2_clear_bit test_and_clear_bit
@@ -373,44 +321,20 @@ static inline int find_next_zero_bit (void * addr, int size, int offset)
#define minix_test_bit(nr,addr) test_bit(nr,addr)
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-#if 0
-/* TODO: see below */
-#define sched_find_first_zero_bit(addr) find_first_zero_bit(addr, 168)
-
-#else
-/* TODO: left out pending where to put it.. (there are .h dependencies) */
-
- /*
- * Every architecture must define this function. It's the fastest
- * way of searching a 168-bit bitmap where the first 128 bits are
- * unlikely to be set. It's guaranteed that at least one of the 168
- * bits is cleared.
- */
-#if 0
-#if MAX_RT_PRIO != 128 || MAX_PRIO != 168
-# error update this function.
-#endif
-#else
-#define MAX_RT_PRIO 128
-#define MAX_PRIO 168
-#endif
-
-static inline int sched_find_first_zero_bit(char *bitmap)
+extern inline int sched_find_first_bit(unsigned long *b)
{
- unsigned int *b = (unsigned int *)bitmap;
- unsigned int rt;
-
- rt = b[0] & b[1] & b[2] & b[3];
- if (unlikely(rt != 0xffffffff))
- return find_first_zero_bit(bitmap, MAX_RT_PRIO);
-
- if (b[4] != ~0)
- return ffz(b[4]) + MAX_RT_PRIO;
- return ffz(b[5]) + 32 + MAX_RT_PRIO;
+ if (unlikely(b[0]))
+ return __ffs(b[0]);
+ if (unlikely(b[1]))
+ return __ffs(b[1]) + 32;
+ if (unlikely(b[2]))
+ return __ffs(b[2]) + 64;
+ if (unlikely(b[3]))
+ return __ffs(b[3]) + 96;
+ if (b[4])
+ return __ffs(b[4]) + 128;
+ return __ffs(b[5]) + 32 + 128;
}
-#undef MAX_PRIO
-#undef MAX_RT_PRIO
-#endif
#endif /* __KERNEL__ */
diff --git a/include/asm-cris/byteorder.h b/include/asm-cris/byteorder.h
index 64275f6045ef..a1a222adaa9f 100644
--- a/include/asm-cris/byteorder.h
+++ b/include/asm-cris/byteorder.h
@@ -1,30 +1,9 @@
-/* $Id: byteorder.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
-
#ifndef _CRIS_BYTEORDER_H
#define _CRIS_BYTEORDER_H
-#include <asm/types.h>
-
#ifdef __GNUC__
-/* we just define these two (as we can do the swap in a single
- * asm instruction in CRIS) and the arch-independent files will put
- * them together into ntohl etc.
- */
-
-static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
-{
- __asm__ ("swapwb %0" : "=r" (x) : "0" (x));
-
- return(x);
-}
-
-static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
-{
- __asm__ ("swapb %0" : "=r" (x) : "0" (x));
-
- return(x);
-}
+#include <asm/arch/byteorder.h>
/* defines are necessary because the other files detect the presence
* of a defined __arch_swab32, not an inline
diff --git a/include/asm-cris/cache.h b/include/asm-cris/cache.h
index 1899bd77461d..46a3b26e205a 100644
--- a/include/asm-cris/cache.h
+++ b/include/asm-cris/cache.h
@@ -1,12 +1,6 @@
#ifndef _ASM_CACHE_H
#define _ASM_CACHE_H
-/* Etrax 100LX have 32-byte cache-lines. When we add support for future chips
- * here should be a check for CPU type.
- */
-
-#define L1_CACHE_BYTES 32
-
-#define L1_CACHE_SHIFT_MAX 5 /* largest L1 which this arch supports */
+#include <asm/arch/cache.h>
#endif /* _ASM_CACHE_H */
diff --git a/include/asm-cris/cacheflush.h b/include/asm-cris/cacheflush.h
new file mode 100644
index 000000000000..6be38857a0ae
--- /dev/null
+++ b/include/asm-cris/cacheflush.h
@@ -0,0 +1,23 @@
+#ifndef _CRIS_CACHEFLUSH_H
+#define _CRIS_CACHEFLUSH_H
+
+/* Keep includes the same across arches. */
+#include <linux/mm.h>
+
+/* The cache doesn't need to be flushed when TLB entries change because
+ * the cache is mapped to physical memory, not virtual memory
+ */
+#define flush_cache_all() do { } while (0)
+#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_range(vma, start, end) do { } while (0)
+#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_page_to_ram(page) do { } while (0)
+#define flush_dcache_page(page) do { } while (0)
+#define flush_icache_range(start, end) do { } while (0)
+#define flush_icache_page(vma,pg) do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
+
+void global_flush_tlb(void);
+int change_page_attr(struct page *page, int numpages, pgprot_t prot);
+
+#endif /* _CRIS_CACHEFLUSH_H */
diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h
index 589eb323eba3..15ca8aec5c63 100644
--- a/include/asm-cris/checksum.h
+++ b/include/asm-cris/checksum.h
@@ -3,6 +3,8 @@
#ifndef _CRIS_CHECKSUM_H
#define _CRIS_CHECKSUM_H
+#include <asm/arch/checksum.h>
+
/*
* computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit)
@@ -32,7 +34,7 @@ unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
* Fold a partial checksum into a word
*/
-static inline unsigned int csum_fold(unsigned int sum)
+extern inline unsigned int csum_fold(unsigned int sum)
{
/* the while loop is unnecessary really, it's always enough with two
iterations */
@@ -43,31 +45,6 @@ static inline unsigned int csum_fold(unsigned int sum)
return ~sum;
}
-/* Checksum some values used in TCP/UDP headers.
- *
- * The gain by doing this in asm is that C will not generate carry-additions
- * for the 32-bit components of the checksum, so otherwise we would have had
- * to split all of those into 16-bit components, then add.
- */
-
-static inline unsigned int
-csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
- unsigned short proto, unsigned int sum)
-{
- int res;
- __asm__ ("add.d %2, %0\n\t"
- "ax\n\t"
- "add.d %3, %0\n\t"
- "ax\n\t"
- "add.d %4, %0\n\t"
- "ax\n\t"
- "addq 0, %0\n"
- : "=r" (res)
- : "0" (sum), "r" (daddr), "r" (saddr), "r" ((ntohs(len) << 16) + (proto << 8)));
-
- return res;
-}
-
extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
int len, unsigned int sum,
int *errptr);
@@ -78,7 +55,7 @@ extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
*
*/
-static inline unsigned short ip_fast_csum(unsigned char * iph,
+extern inline unsigned short ip_fast_csum(unsigned char * iph,
unsigned int ihl)
{
return csum_fold(csum_partial(iph, ihl * 4, 0));
@@ -89,7 +66,7 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
* returns a 16-bit checksum, already complemented
*/
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
@@ -103,7 +80,7 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+extern inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
return csum_fold (csum_partial(buff, len, 0));
}
diff --git a/include/asm-cris/current.h b/include/asm-cris/current.h
index c5cc44d537d6..dce69c99da39 100644
--- a/include/asm-cris/current.h
+++ b/include/asm-cris/current.h
@@ -1,14 +1,14 @@
#ifndef _CRIS_CURRENT_H
#define _CRIS_CURRENT_H
+#include <linux/thread_info.h>
+
struct task_struct;
-static inline struct task_struct * get_current(void)
+extern inline struct task_struct * get_current(void)
{
- struct task_struct *current;
- __asm__("and.d $sp,%0; ":"=r" (current) : "0" (~8191UL));
- return current;
- }
+ return current_thread_info()->task;
+}
#define current get_current()
diff --git a/include/asm-cris/delay.h b/include/asm-cris/delay.h
index 632c369c41b9..efc41aad4845 100644
--- a/include/asm-cris/delay.h
+++ b/include/asm-cris/delay.h
@@ -2,33 +2,12 @@
#define _CRIS_DELAY_H
/*
- * Copyright (C) 1998, 1999, 2000, 2001 Axis Communications AB
+ * Copyright (C) 1998-2002 Axis Communications AB
*
* Delay routines, using a pre-computed "loops_per_second" value.
*/
-#include <linux/config.h>
-#include <linux/linkage.h>
-
-#ifdef CONFIG_SMP
-#include <asm/smp.h>
-#endif
-
-extern void __do_delay(void); /* Special register call calling convention */
-
-extern __inline__ void __delay(int loops)
-{
- __asm__ __volatile__ (
- "move.d %0,$r9\n\t"
- "beq 2f\n\t"
- "subq 1,$r9\n\t"
- "1:\n\t"
- "bne 1b\n\t"
- "subq 1,$r9\n"
- "2:"
- : : "g" (loops) : "r9");
-}
-
+#include <asm/arch/delay.h>
/* Use only for very small delays ( < 1 msec). */
diff --git a/include/asm-cris/dma.h b/include/asm-cris/dma.h
index fde1cbf1a803..c229fac35cdc 100644
--- a/include/asm-cris/dma.h
+++ b/include/asm-cris/dma.h
@@ -1,59 +1,13 @@
-/* $Id: dma.h,v 1.2 2001/05/09 12:17:42 johana Exp $
- * linux/include/asm/dma.h: Defines for using and allocating dma channels.
- */
+/* $Id: dma.h,v 1.2 2001/05/09 12:17:42 johana Exp $ */
#ifndef _ASM_DMA_H
#define _ASM_DMA_H
+#include <asm/arch/dma.h>
+
/* it's useless on the Etrax, but unfortunately needed by the new
bootmem allocator (but this should do it for this) */
#define MAX_DMA_ADDRESS PAGE_OFFSET
-/* TODO: check nbr of channels on Etrax-100LX */
-
-#define MAX_DMA_CHANNELS 10
-
-/* dma0 and dma1 used for network (ethernet) */
-#define NETWORK_TX_DMA_NBR 0
-#define NETWORK_RX_DMA_NBR 1
-
-/* dma2 and dma3 shared by par0, scsi0, ser2 and ata */
-#define PAR0_TX_DMA_NBR 2
-#define PAR0_RX_DMA_NBR 3
-#define SCSI0_TX_DMA_NBR 2
-#define SCSI0_RX_DMA_NBR 3
-#define SER2_TX_DMA_NBR 2
-#define SER2_RX_DMA_NBR 3
-#define ATA_TX_DMA_NBR 2
-#define ATA_RX_DMA_NBR 3
-
-/* dma4 and dma5 shared by par1, scsi1, ser3 and extdma0 */
-#define PAR1_TX_DMA_NBR 4
-#define PAR1_RX_DMA_NBR 5
-#define SCSI1_TX_DMA_NBR 4
-#define SCSI1_RX_DMA_NBR 5
-#define SER3_TX_DMA_NBR 4
-#define SER3_RX_DMA_NBR 5
-#define EXTDMA0_TX_DMA_NBR 4
-#define EXTDMA0_RX_DMA_NBR 5
-
-/* dma6 and dma7 shared by ser0, extdma1 and mem2mem */
-#define SER0_TX_DMA_NBR 6
-#define SER0_RX_DMA_NBR 7
-#define EXTDMA1_TX_DMA_NBR 6
-#define EXTDMA1_RX_DMA_NBR 7
-#define MEM2MEM_TX_DMA_NBR 6
-#define MEM2MEM_RX_DMA_NBR 7
-
-/* dma8 and dma9 shared by ser1 and usb */
-#define SER1_TX_DMA_NBR 8
-#define SER1_RX_DMA_NBR 9
-#define USB_TX_DMA_NBR 8
-#define USB_RX_DMA_NBR 9
-
-/* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr); /* release it */
-
#endif /* _ASM_DMA_H */
diff --git a/include/asm-cris/elf.h b/include/asm-cris/elf.h
index 798aeaeaabd1..d37fd5c4a567 100644
--- a/include/asm-cris/elf.h
+++ b/include/asm-cris/elf.h
@@ -5,7 +5,8 @@
* ELF register definitions..
*/
-#include <asm/ptrace.h>
+#include <asm/arch/elf.h>
+#include <asm/user.h>
typedef unsigned long elf_greg_t;
@@ -29,69 +30,8 @@ typedef unsigned long elf_fpregset_t;
#define ELF_DATA ELFDATA2LSB;
#define ELF_ARCH EM_CRIS
- /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
- starts (a register; assume first param register for CRIS)
- contains a pointer to a function which might be
- registered using `atexit'. This provides a mean for the
- dynamic linker to call DT_FINI functions for shared libraries
- that have been loaded before the code runs.
-
- A value of 0 tells we have no such handler. */
-
- /* Explicitly set registers to 0 to increase determinism. */
-#define ELF_PLAT_INIT(_r, load_addr) do { \
- (_r)->r13 = 0; (_r)->r12 = 0; (_r)->r11 = 0; (_r)->r10 = 0; \
- (_r)->r9 = 0; (_r)->r8 = 0; (_r)->r7 = 0; (_r)->r6 = 0; \
- (_r)->r5 = 0; (_r)->r4 = 0; (_r)->r3 = 0; (_r)->r2 = 0; \
- (_r)->r1 = 0; (_r)->r0 = 0; (_r)->mof = 0; (_r)->srp = 0; \
-} while (0)
-
#define USE_ELF_CORE_DUMP
-/* The additional layer below is because the stack pointer is missing in
- the pt_regs struct, but needed in a core dump. pr_reg is a elf_gregset_t,
- and should be filled in according to the layout of the user_regs_struct
- struct; regs is a pt_regs struct. We dump all registers, though several are
- obviously unnecessary. That way there's less need for intelligence at
- the receiving end (i.e. gdb). */
-#define ELF_CORE_COPY_REGS(pr_reg, regs) \
- pr_reg[0] = regs->r0; \
- pr_reg[1] = regs->r1; \
- pr_reg[2] = regs->r2; \
- pr_reg[3] = regs->r3; \
- pr_reg[4] = regs->r4; \
- pr_reg[5] = regs->r5; \
- pr_reg[6] = regs->r6; \
- pr_reg[7] = regs->r7; \
- pr_reg[8] = regs->r8; \
- pr_reg[9] = regs->r9; \
- pr_reg[10] = regs->r10; \
- pr_reg[11] = regs->r11; \
- pr_reg[12] = regs->r12; \
- pr_reg[13] = regs->r13; \
- pr_reg[14] = rdusp(); /* sp */ \
- pr_reg[15] = regs->irp; /* pc */ \
- pr_reg[16] = 0; /* p0 */ \
- pr_reg[17] = rdvr(); /* vr */ \
- pr_reg[18] = 0; /* p2 */ \
- pr_reg[19] = 0; /* p3 */ \
- pr_reg[20] = 0; /* p4 */ \
- pr_reg[21] = (regs->dccr & 0xffff); /* ccr */ \
- pr_reg[22] = 0; /* p6 */ \
- pr_reg[23] = regs->mof; /* mof */ \
- pr_reg[24] = 0; /* p8 */ \
- pr_reg[25] = 0; /* ibr */ \
- pr_reg[26] = 0; /* irp */ \
- pr_reg[27] = regs->srp; /* srp */ \
- pr_reg[28] = 0; /* bar */ \
- pr_reg[29] = regs->dccr; /* dccr */ \
- pr_reg[30] = 0; /* brp */ \
- pr_reg[31] = rdusp(); /* usp */ \
- pr_reg[32] = 0; /* csrinstr */ \
- pr_reg[33] = 0; /* csraddr */ \
- pr_reg[34] = 0; /* csrdata */
-
-
#define ELF_EXEC_PAGESIZE 8192
/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
diff --git a/include/asm-cris/etraxgpio.h b/include/asm-cris/etraxgpio.h
index 0395953e883e..cf04af9635cc 100644
--- a/include/asm-cris/etraxgpio.h
+++ b/include/asm-cris/etraxgpio.h
@@ -1,13 +1,54 @@
+/* $Id: etraxgpio.h,v 1.8 2002/06/17 15:53:07 johana Exp $ */
+/*
+ * The following devices are accessable using this driver using
+ * GPIO_MAJOR (120) and a couple of minor numbers:
+ * For ETRAX 100LX (ARCH_V10):
+ * /dev/gpioa minor 0, 8 bit GPIO, each bit can change direction
+ * /dev/gpiob minor 1, 8 bit GPIO, each bit can change direction
+ * /dev/leds minor 2, Access to leds depending on kernelconfig
+ * /dev/gpiog minor 3
+ g0dir, g8_15dir, g16_23dir, g24 dir configurable in R_GEN_CONFIG
+ g1-g7 and g25-g31 is both input and outputs but on different pins
+ Also note that some bits change pins depending on what interfaces
+ are enabled.
+ *
+ *
+ * For ETRAX 200 (ARCH_V32):
+ * /dev/gpioa minor 0, 8 bit GPIO, each bit can change direction
+ * /dev/gpiob minor 1, 18 bit GPIO, each bit can change direction
+ * /dev/gpioc minor 2, 18 bit GPIO, each bit can change direction
+ * /dev/gpiod minor 3, 18 bit GPIO, each bit can change direction
+ * /dev/gpioe minor 4, 18 bit GPIO, each bit can change direction
+ * /dev/leds minor 5, Access to leds depending on kernelconfig
+ *
+ */
#ifndef _ASM_ETRAXGPIO_H
#define _ASM_ETRAXGPIO_H
+#include <linux/config.h>
/* etraxgpio _IOC_TYPE, bits 8 to 15 in ioctl cmd */
-
+#ifdef CONFIG_ETRAX_ARCH_V10
+#define ETRAXGPIO_IOCTYPE 43
+#define GPIO_MINOR_A 0
+#define GPIO_MINOR_B 1
+#define GPIO_MINOR_LEDS 2
+#define GPIO_MINOR_G 3
+#define GPIO_MINOR_LAST 3
+#endif
+#ifdef CONFIG_ETRAX_ARCH_V32
#define ETRAXGPIO_IOCTYPE 43
+#define GPIO_MINOR_A 0
+#define GPIO_MINOR_B 1
+#define GPIO_MINOR_C 2
+#define GPIO_MINOR_D 3
+#define GPIO_MINOR_E 4
+#define GPIO_MINOR_LEDS 5
+#define GPIO_MINOR_LAST 5
+#endif
/* supported ioctl _IOC_NR's */
-#define IO_READBITS 0x1 /* read and return current port bits */
+#define IO_READBITS 0x1 /* read and return current port bits (obsolete) */
#define IO_SETBITS 0x2 /* set the bits marked by 1 in the argument */
#define IO_CLRBITS 0x3 /* clear the bits marked by 1 in the argument */
@@ -22,11 +63,11 @@
* 0=off, 1=green, 2=red, 3=yellow */
/* GPIO direction ioctl's */
-#define IO_READDIR 0x8 /* Read direction 0=input 1=output */
-#define IO_SETINPUT 0x9 /* Set direction 0=unchanged 1=input,
- returns current dir */
-#define IO_SETOUTPUT 0xA /* Set direction 0=unchanged 1=output,
- returns current dir */
+#define IO_READDIR 0x8 /* Read direction 0=input 1=output (obsolete) */
+#define IO_SETINPUT 0x9 /* Set direction for bits set, 0=unchanged 1=input,
+ returns mask with current inputs (obsolete) */
+#define IO_SETOUTPUT 0xA /* Set direction for bits set, 0=unchanged 1=output,
+ returns mask with current outputs (obsolete)*/
/* LED ioctl extended */
#define IO_LED_SETBIT 0xB
@@ -45,5 +86,19 @@
#define IO_CFG_WRITE_MODE_VALUE(msb, data_mask, clk_mask) \
( (((msb)&1) << 16) | (((data_mask) &0xFF) << 8) | ((clk_mask) & 0xFF) )
+/* The following 4 ioctl's take a pointer as argument and handles
+ * 32 bit ports (port G) properly.
+ * These replaces IO_READBITS,IO_SETINPUT AND IO_SETOUTPUT
+ */
+#define IO_READ_INBITS 0x10 /* *arg is result of reading the input pins */
+#define IO_READ_OUTBITS 0x11 /* *arg is result of reading the output shadow */
+#define IO_SETGET_INPUT 0x12 /* bits set in *arg is set to input,
+ * *arg updated with current input pins.
+ */
+#define IO_SETGET_OUTPUT 0x13 /* bits set in *arg is set to output,
+ * *arg updated with current output pins.
+ */
+
+
#endif
diff --git a/include/asm-cris/fasttimer.h b/include/asm-cris/fasttimer.h
new file mode 100644
index 000000000000..10a770647870
--- /dev/null
+++ b/include/asm-cris/fasttimer.h
@@ -0,0 +1,42 @@
+/* $Id: fasttimer.h,v 1.2 2002/12/11 13:03:43 starvik Exp $
+ * linux/include/asm-cris/fasttimer.h
+ *
+ * Fast timers for ETRAX100LX
+ * This may be useful in other OS than Linux so use 2 space indentation...
+ * Copyright (C) 2000, 2002 Axis Communications AB
+ */
+#include <linux/config.h>
+#include <linux/time.h> /* struct timeval */
+#include <linux/timex.h>
+
+#ifdef CONFIG_ETRAX_FAST_TIMER
+
+typedef void fast_timer_function_type(unsigned long);
+
+struct fast_timer{ /* Close to timer_list */
+ struct fast_timer *next;
+ struct fast_timer *prev;
+ struct timeval tv_set;
+ struct timeval tv_expires;
+ unsigned long delay_us;
+ fast_timer_function_type *function;
+ unsigned long data;
+ const char *name;
+};
+
+void start_one_shot_timer(struct fast_timer *t,
+ fast_timer_function_type *function,
+ unsigned long data,
+ unsigned long delay_us,
+ const char *name);
+
+int del_fast_timer(struct fast_timer * t);
+/* return 1 if deleted */
+
+
+void schedule_usleep(unsigned long us);
+
+
+void fast_timer_init(void);
+
+#endif
diff --git a/include/asm-cris/hardirq.h b/include/asm-cris/hardirq.h
index 4a13a2445d5b..c75100f8359b 100644
--- a/include/asm-cris/hardirq.h
+++ b/include/asm-cris/hardirq.h
@@ -4,6 +4,7 @@
/* only non-SMP supported */
#include <linux/threads.h>
+#include <linux/cache.h>
/* entry.S is sensitive to the offsets of these fields */
typedef struct {
@@ -17,19 +18,80 @@ typedef struct {
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
/*
- * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
+ * We put the hardirq and softirq counter into the preemption
+ * counter. The bitmask has the following meaning:
+ *
+ * - bits 0-7 are the preemption count (max preemption depth: 256)
+ * - bits 8-15 are the softirq count (max # of softirqs: 256)
+ * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ *
+ * - ( bit 26 is the PREEMPT_ACTIVE flag. )
+ *
+ * PREEMPT_MASK: 0x000000ff
+ * SOFTIRQ_MASK: 0x0000ff00
+ * HARDIRQ_MASK: 0x00ff0000
*/
-#define in_interrupt() ((local_irq_count(smp_processor_id()) + \
- local_bh_count(smp_processor_id())) != 0)
-#define in_irq() (local_irq_count(smp_processor_id()) != 0)
-#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
-#define hardirq_endlock(cpu) do { (void)(cpu); } while (0)
+#define PREEMPT_BITS 8
+#define SOFTIRQ_BITS 8
+#define HARDIRQ_BITS 8
-#define irq_enter(cpu) (local_irq_count(cpu)++)
-#define irq_exit(cpu) (local_irq_count(cpu)--)
+#define PREEMPT_SHIFT 0
+#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
+#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
-#define synchronize_irq() barrier()
+#define __MASK(x) ((1UL << (x))-1)
+
+#define PREEMPT_MASK (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
+#define HARDIRQ_MASK (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
+#define SOFTIRQ_MASK (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
+
+#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
+#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
+#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
+
+#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
+#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
+#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+/*
+ * Are we doing bottom half or hardware interrupt processing?
+ * Are we in a softirq context? Interrupt context?
+ */
+#define in_irq() (hardirq_count())
+#define in_softirq() (softirq_count())
+#define in_interrupt() (irq_count())
+
+
+#define hardirq_trylock() (!in_interrupt())
+#define hardirq_endlock() do { } while (0)
+
+#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
+
+#ifdef CONFIG_PREEMPT
+# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define in_atomic() (preempt_count() != 0)
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
+#define irq_exit() \
+do { \
+ preempt_count() -= IRQ_EXIT_OFFSET; \
+ if (!in_interrupt() && softirq_pending(smp_processor_id())) \
+ do_softirq(); \
+ preempt_enable_no_resched(); \
+} while (0)
+
+#define synchronize_irq(irq) barrier()
#endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-cris/hdreg.h b/include/asm-cris/hdreg.h
deleted file mode 100644
index 382a8e64ce8b..000000000000
--- a/include/asm-cris/hdreg.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * linux/include/asm-cris/hdreg.h
- *
- */
-
-#ifndef __ASMCRIS_HDREG_H
-#define __ASMCRIS_HDREG_H
-
-typedef unsigned long ide_ioreg_t;
-
-#endif /* __ASMCRIS_HDREG_H */
diff --git a/include/asm-cris/ide.h b/include/asm-cris/ide.h
deleted file mode 100644
index 8f4bd8c131f4..000000000000
--- a/include/asm-cris/ide.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * linux/include/asm-cris/ide.h
- *
- * Copyright (C) 2000 Axis Communications AB
- *
- * Authors: Bjorn Wesen
- *
- */
-
-/*
- * This file contains the ETRAX 100LX specific IDE code.
- */
-
-#ifndef __ASMCRIS_IDE_H
-#define __ASMCRIS_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/svinto.h>
-
-/* ETRAX 100 can support 4 IDE busses on the same pins (serialized) */
-
-#define MAX_HWIFS 4
-
-static __inline__ int ide_default_irq(ide_ioreg_t base)
-{
- /* all IDE busses share the same IRQ, number 4.
- * this has the side-effect that ide-probe.c will cluster our 4 interfaces
- * together in a hwgroup, and will serialize accesses. this is good, because
- * we can't access more than one interface at the same time on ETRAX100.
- */
- return 4;
-}
-
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
-{
- /* we have no real I/O base address per interface, since all go through the
- * same register. but in a bitfield in that register, we have the i/f number.
- * so we can use the io_base to remember that bitfield.
- */
- static const unsigned long io_bases[MAX_HWIFS] = {
- IO_FIELD(R_ATA_CTRL_DATA, sel, 0),
- IO_FIELD(R_ATA_CTRL_DATA, sel, 1),
- IO_FIELD(R_ATA_CTRL_DATA, sel, 2),
- IO_FIELD(R_ATA_CTRL_DATA, sel, 3)
- };
- return io_bases[index];
-}
-
-/* this is called once for each interface, to setup the port addresses. data_port is the result
- * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us.
- */
-
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
-{
- int i;
-
- /* fill in ports for ATA addresses 0 to 7 */
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = data_port |
- IO_FIELD(R_ATA_CTRL_DATA, addr, i) |
- IO_STATE(R_ATA_CTRL_DATA, cs0, active);
- }
-
- /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
-
- hw->io_ports[IDE_CONTROL_OFFSET] = data_port |
- IO_FIELD(R_ATA_CTRL_DATA, addr, 6) |
- IO_STATE(R_ATA_CTRL_DATA, cs1, active);
-
- /* whats this for ? */
-
- hw->io_ports[IDE_IRQ_OFFSET] = 0;
-}
-
-static __inline__ void ide_init_default_hwifs(void)
-{
- hw_regs_t hw;
- int index;
-
- for(index = 0; index < MAX_HWIFS; index++) {
- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
- hw.irq = ide_default_irq(ide_default_io_base(index));
- ide_register_hw(&hw);
- }
-}
-
-/* some configuration options we don't need */
-
-#undef SUPPORT_SLOW_DATA_PORTS
-#define SUPPORT_SLOW_DATA_PORTS 0
-
-/* the drive addressing is done through a controller register on the Etrax CPU */
-void OUT_BYTE(unsigned char data, ide_ioreg_t reg);
-unsigned char IN_BYTE(ide_ioreg_t reg);
-
-/* this tells ide.h not to define the standard macros */
-#define HAVE_ARCH_IN_OUT 1
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMCRIS_IDE_H */
diff --git a/include/asm-cris/io.h b/include/asm-cris/io.h
index 82a06f841c9f..8604f0e9a69d 100644
--- a/include/asm-cris/io.h
+++ b/include/asm-cris/io.h
@@ -2,209 +2,18 @@
#define _ASM_CRIS_IO_H
#include <asm/page.h> /* for __va, __pa */
-#include <asm/svinto.h>
-#include <linux/config.h>
-
-/* Console I/O for simulated etrax100. Use #ifdef so erroneous
- use will be evident. */
-#ifdef CONFIG_SVINTO_SIM
- /* Let's use the ucsim interface since it lets us do write(2, ...) */
-#define SIMCOUT(s,len) \
- asm ("moveq 4,$r9 \n\t" \
- "moveq 2,$r10 \n\t" \
- "move.d %0,$r11 \n\t" \
- "move.d %1,$r12 \n\t" \
- "push $irp \n\t" \
- "move 0f,$irp \n\t" \
- "jump -6809 \n" \
- "0: \n\t" \
- "pop $irp" \
- : : "rm" (s), "rm" (len) : "r9","r10","r11","r12","memory")
-#define TRACE_ON() __extension__ \
- ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \
- (255)); _Foofoo; })
-
-#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0)
-#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0)
-#define CRIS_CYCLES() __extension__ \
- ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;})
-#else /* ! defined CONFIG_SVINTO_SIM */
-/* FIXME: Is there a reliable cycle counter available in some chip? Use
- that then. */
-#define CRIS_CYCLES() 0
-#endif /* ! defined CONFIG_SVINTO_SIM */
-
-/* Etrax shadow registers - which live in arch/cris/kernel/shadows.c */
-
-extern unsigned long port_g_data_shadow;
-extern unsigned char port_pa_dir_shadow;
-extern unsigned char port_pa_data_shadow;
-extern unsigned char port_pb_i2c_shadow;
-extern unsigned char port_pb_config_shadow;
-extern unsigned char port_pb_dir_shadow;
-extern unsigned char port_pb_data_shadow;
-extern unsigned long r_timer_ctrl_shadow;
-
-extern unsigned long port_cse1_shadow;
-extern unsigned long port_csp0_shadow;
-extern unsigned long port_csp4_shadow;
-
-extern volatile unsigned long *port_cse1_addr;
-extern volatile unsigned long *port_csp0_addr;
-extern volatile unsigned long *port_csp4_addr;
-
-/* macro for setting regs through a shadow -
- * r = register name (like R_PORT_PA_DATA)
- * s = shadow name (like port_pa_data_shadow)
- * b = bit number
- * v = value (0 or 1)
- */
-
-#define REG_SHADOW_SET(r,s,b,v) *r = s = (s & ~(1 << (b))) | ((v) << (b))
-
-/* The LED's on various Etrax-based products are set differently. */
-
-#if defined(CONFIG_ETRAX_NO_LEDS) || defined(CONFIG_SVINTO_SIM)
-#undef CONFIG_ETRAX_PA_LEDS
-#undef CONFIG_ETRAX_PB_LEDS
-#undef CONFIG_ETRAX_CSP0_LEDS
-#define LED_NETWORK_SET_G(x)
-#define LED_NETWORK_SET_R(x)
-#define LED_ACTIVE_SET_G(x)
-#define LED_ACTIVE_SET_R(x)
-#define LED_DISK_WRITE(x)
-#define LED_DISK_READ(x)
-#endif
-
-#if !defined(CONFIG_ETRAX_CSP0_LEDS)
-#define LED_BIT_SET(x)
-#define LED_BIT_CLR(x)
-#endif
-
-#define LED_OFF 0x00
-#define LED_GREEN 0x01
-#define LED_RED 0x02
-#define LED_ORANGE (LED_GREEN | LED_RED)
-
-#if CONFIG_ETRAX_LED1G == CONFIG_ETRAX_LED1R
-#define LED_NETWORK_SET(x) \
- do { \
- LED_NETWORK_SET_G((x) & LED_GREEN); \
- } while (0)
-#else
-#define LED_NETWORK_SET(x) \
- do { \
- LED_NETWORK_SET_G((x) & LED_GREEN); \
- LED_NETWORK_SET_R((x) & LED_RED); \
- } while (0)
-#endif
-#if CONFIG_ETRAX_LED2G == CONFIG_ETRAX_LED2R
-#define LED_ACTIVE_SET(x) \
- do { \
- LED_ACTIVE_SET_G((x) & LED_GREEN); \
- } while (0)
-#else
-#define LED_ACTIVE_SET(x) \
- do { \
- LED_ACTIVE_SET_G((x) & LED_GREEN); \
- LED_ACTIVE_SET_R((x) & LED_RED); \
- } while (0)
-#endif
-
-#ifdef CONFIG_ETRAX_PA_LEDS
-#define LED_NETWORK_SET_G(x) \
- REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1G, !(x))
-#define LED_NETWORK_SET_R(x) \
- REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1R, !(x))
-#define LED_ACTIVE_SET_G(x) \
- REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2G, !(x))
-#define LED_ACTIVE_SET_R(x) \
- REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2R, !(x))
-#define LED_DISK_WRITE(x) \
- do{\
- REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !(x));\
- REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !(x));\
- }while(0)
-#define LED_DISK_READ(x) \
- REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !(x))
-#endif
-
-#ifdef CONFIG_ETRAX_PB_LEDS
-#define LED_NETWORK_SET_G(x) \
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1G, !(x))
-#define LED_NETWORK_SET_R(x) \
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1R, !(x))
-#define LED_ACTIVE_SET_G(x) \
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2G, !(x))
-#define LED_ACTIVE_SET_R(x) \
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2R, !(x))
-#define LED_DISK_WRITE(x) \
- do{\
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED3G, !(x));\
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED3R, !(x));\
- }while(0)
-#define LED_DISK_READ(x) \
- REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED3G, !(x))
-#endif
-
-#ifdef CONFIG_ETRAX_CSP0_LEDS
-#define CONFIGURABLE_LEDS\
- ((1 << CONFIG_ETRAX_LED1G ) | (1 << CONFIG_ETRAX_LED1R ) |\
- (1 << CONFIG_ETRAX_LED2G ) | (1 << CONFIG_ETRAX_LED2R ) |\
- (1 << CONFIG_ETRAX_LED3G ) | (1 << CONFIG_ETRAX_LED3R ) |\
- (1 << CONFIG_ETRAX_LED4G ) | (1 << CONFIG_ETRAX_LED4R ) |\
- (1 << CONFIG_ETRAX_LED5G ) | (1 << CONFIG_ETRAX_LED5R ) |\
- (1 << CONFIG_ETRAX_LED6G ) | (1 << CONFIG_ETRAX_LED6R ) |\
- (1 << CONFIG_ETRAX_LED7G ) | (1 << CONFIG_ETRAX_LED7R ) |\
- (1 << CONFIG_ETRAX_LED8Y ) | (1 << CONFIG_ETRAX_LED9Y ) |\
- (1 << CONFIG_ETRAX_LED10Y ) |(1 << CONFIG_ETRAX_LED11Y )|\
- (1 << CONFIG_ETRAX_LED12R ))
-
-#define LED_NETWORK_SET_G(x) \
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED1G, !(x))
-#define LED_NETWORK_SET_R(x) \
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED1R, !(x))
-#define LED_ACTIVE_SET_G(x) \
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED2G, !(x))
-#define LED_ACTIVE_SET_R(x) \
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED2R, !(x))
-#define LED_DISK_WRITE(x) \
- do{\
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3G, !(x));\
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3R, !(x));\
- }while(0)
-#define LED_DISK_READ(x) \
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3G, !(x))
-#define LED_BIT_SET(x)\
- do{\
- if((( 1 << x) & CONFIGURABLE_LEDS) != 0)\
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, x, 1);\
- }while(0)
-#define LED_BIT_CLR(x)\
- do{\
- if((( 1 << x) & CONFIGURABLE_LEDS) != 0)\
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, x, 0);\
- }while(0)
-#endif
-
-#
-#ifdef CONFIG_ETRAX_SOFT_SHUTDOWN
-#define SOFT_SHUTDOWN() \
- REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_SHUTDOWN_BIT, 1)
-#else
-#define SOFT_SHUTDOWN()
-#endif
+#include <asm/arch/io.h>
/*
* Change virtual addresses to physical addresses and vv.
*/
-static inline unsigned long virt_to_phys(volatile void * address)
+extern inline unsigned long virt_to_phys(volatile void * address)
{
return __pa(address);
}
-static inline void * phys_to_virt(unsigned long address)
+extern inline void * phys_to_virt(unsigned long address)
{
return __va(address);
}
@@ -216,6 +25,8 @@ extern inline void * ioremap (unsigned long offset, unsigned long size)
return __ioremap(offset, size, 0);
}
+extern void iounmap(void *addr);
+
/*
* IO bus memory addresses are also 1:1 with the physical address
*/
@@ -231,10 +42,16 @@ extern inline void * ioremap (unsigned long offset, unsigned long size)
#define readb(addr) (*(volatile unsigned char *) (addr))
#define readw(addr) (*(volatile unsigned short *) (addr))
#define readl(addr) (*(volatile unsigned int *) (addr))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
#define memset_io(a,b,c) memset((void *)(a),(b),(c))
#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
diff --git a/include/asm-cris/ioctls.h b/include/asm-cris/ioctls.h
index 1628ad265a89..97787c3c575f 100644
--- a/include/asm-cris/ioctls.h
+++ b/include/asm-cris/ioctls.h
@@ -70,6 +70,9 @@
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
+#define TIOCSERSETRS485 0x5461 /* enable rs-485 */
+#define TIOCSERWRRS485 0x5462 /* write rs-485 */
+
/* Used for packet mode */
#define TIOCPKT_DATA 0
#define TIOCPKT_FLUSHREAD 1
diff --git a/include/asm-cris/ipc.h b/include/asm-cris/ipc.h
index 07e51a11d50d..f086af6fa03f 100644
--- a/include/asm-cris/ipc.h
+++ b/include/asm-cris/ipc.h
@@ -17,6 +17,7 @@ struct ipc_kludge {
#define SEMOP 1
#define SEMGET 2
#define SEMCTL 3
+#define SEMTIMEDOP 4
#define MSGSND 11
#define MSGRCV 12
#define MSGGET 13
diff --git a/include/asm-cris/irq.h b/include/asm-cris/irq.h
index 5e4fb8db6735..caa45facb1b2 100644
--- a/include/asm-cris/irq.h
+++ b/include/asm-cris/irq.h
@@ -1,78 +1,12 @@
-/*
- * Interrupt handling assembler and defines for Linux/CRIS
- *
- * Copyright (c) 2000, 2001 Axis Communications AB
- *
- */
-
#ifndef _ASM_IRQ_H
#define _ASM_IRQ_H
-/*
- * linux/include/asm-cris/irq.h
- */
-
-#include <linux/linkage.h>
-#include <asm/segment.h>
-
-#include <asm/sv_addr_ag.h>
-
-#define NR_IRQS 32
-#define SOME_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, some) /* 0 ? */
-#define NMI_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, nmi) /* 1 */
-#define TIMER0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer0) /* 2 */
-#define TIMER1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer1) /* 3 */
-/* mio, ata, par0, scsi0 on 4 */
-/* par1, scsi1 on 5 */
-#define NETWORK_STATUS_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, network) /* 6 */
-
-#define SERIAL_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, serial) /* 8 */
-#define PA_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, pa) /* 11 */
-/* extdma0 and extdma1 is at irq 12 and 13 and/or same as dma5 and dma6 ? */
-#define EXTDMA0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma0)
-#define EXTDMA1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma1)
-
-/* dma0-9 is irq 16..25 */
-/* 16,17: network */
-#define DMA0_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma0)
-#define DMA1_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma1)
-#define NETWORK_DMA_TX_IRQ_NBR DMA0_TX_IRQ_NBR
-#define NETWORK_DMA_RX_IRQ_NBR DMA1_RX_IRQ_NBR
-
-/* 18,19: dma2 and dma3 shared by par0, scsi0, ser2 and ata */
-#define DMA2_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma2)
-#define DMA3_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma3)
-#define SER2_DMA_TX_IRQ_NBR DMA2_TX_IRQ_NBR
-#define SER2_DMA_RX_IRQ_NBR DMA3_RX_IRQ_NBR
-
-/* 20,21: dma4 and dma5 shared by par1, scsi1, ser3 and extdma0 */
-#define DMA4_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma4)
-#define DMA5_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma5)
-#define SER3_DMA_TX_IRQ_NBR DMA4_TX_IRQ_NBR
-#define SER3_DMA_RX_IRQ_NBR DMA5_RX_IRQ_NBR
-
-/* 22,23: dma6 and dma7 shared by ser0, extdma1 and mem2mem */
-#define DMA6_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma6)
-#define DMA7_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma7)
-#define SER0_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR
-#define SER0_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR
-#define MEM2MEM_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR
-#define MEM2MEM_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR
-
-/* 24,25: dma8 and dma9 shared by ser1 and usb */
-#define DMA8_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma8)
-#define DMA9_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma9)
-#define SER1_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR
-#define SER1_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR
-#define USB_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR
-#define USB_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR
-
-/* usb: controller at irq 31 + uses DMA8 and DMA9 */
-#define USB_HC_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, usb)
-
-
-
+#include <asm/arch/irq.h>
+extern __inline__ int irq_canonicalize(int irq)
+{
+ return irq;
+}
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
@@ -80,116 +14,6 @@ extern void enable_irq(unsigned int);
#define disable_irq_nosync disable_irq
#define enable_irq_nosync enable_irq
-/* our fine, global, etrax irq vector! the pointer lives in the head.S file. */
-
-typedef void (*irqvectptr)(void);
-
-struct etrax_interrupt_vector {
- irqvectptr v[256];
-};
-
-extern struct etrax_interrupt_vector *etrax_irv;
-void set_int_vector(int n, irqvectptr addr, irqvectptr saddr);
-void set_break_vector(int n, irqvectptr addr);
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
-/* SAVE_ALL saves registers so they match pt_regs */
-
-#define SAVE_ALL \
- "move $irp,[$sp=$sp-16]\n\t" /* push instruction pointer and fake SBFS struct */ \
- "push $srp\n\t" /* push subroutine return pointer */ \
- "push $dccr\n\t" /* push condition codes */ \
- "push $mof\n\t" /* push multiply overflow reg */ \
- "di\n\t" /* need to disable irq's at this point */\
- "subq 14*4,$sp\n\t" /* make room for r0-r13 */ \
- "movem $r13,[$sp]\n\t" /* push the r0-r13 registers */ \
- "push $r10\n\t" /* push orig_r10 */ \
- "clear.d [$sp=$sp-4]\n\t" /* frametype - this is a normal stackframe */
-
- /* BLOCK_IRQ and UNBLOCK_IRQ do the same as mask_irq and unmask_irq in irq.c */
-
-#define BLOCK_IRQ(mask,nr) \
- "move.d " #mask ",$r0\n\t" \
- "move.d $r0,[0xb00000d8]\n\t"
-
-#define UNBLOCK_IRQ(mask) \
- "move.d " #mask ",$r0\n\t" \
- "move.d $r0,[0xb00000dc]\n\t"
-
-#define IRQ_NAME2(nr) nr##_interrupt(void)
-#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-#define sIRQ_NAME(nr) IRQ_NAME2(sIRQ##nr)
-#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
-
- /* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls
- * do_IRQ (with irq disabled still). after that it unblocks and jumps to
- * ret_from_intr (entry.S)
- *
- * The reason the IRQ is blocked is to allow an sti() before the handler which
- * will acknowledge the interrupt is run.
- */
-
-#define BUILD_IRQ(nr,mask) \
-void IRQ_NAME(nr); \
-void sIRQ_NAME(nr); \
-void BAD_IRQ_NAME(nr); \
-__asm__ ( \
- ".text\n\t" \
- "IRQ" #nr "_interrupt:\n\t" \
- SAVE_ALL \
- "sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
- BLOCK_IRQ(mask,nr) /* this must be done to prevent irq loops when we ei later */ \
- "moveq "#nr",$r10\n\t" \
- "move.d $sp,$r11\n\t" \
- "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
- UNBLOCK_IRQ(mask) \
- "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
- "jump ret_from_intr\n\t" \
- "bad_IRQ" #nr "_interrupt:\n\t" \
- "push $r0\n\t" \
- BLOCK_IRQ(mask,nr) \
- "pop $r0\n\t" \
- "reti\n\t" \
- "nop\n");
-
-/* This is subtle. The timer interrupt is crucial and it should not be disabled for
- * too long. However, if it had been a normal interrupt as per BUILD_IRQ, it would
- * have been BLOCK'ed, and then softirq's are run before we return here to UNBLOCK.
- * If the softirq's take too much time to run, the timer irq won't run and the
- * watchdog will kill us.
- *
- * Furthermore, if a lot of other irq's occur before we return here, the multiple_irq
- * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed
- * it here, we would not get the multiple_irq at all.
- *
- * The non-blocking here is based on the knowledge that the timer interrupt is
- * registred as a fast interrupt (SA_INTERRUPT) so that we _know_ there will not
- * be an sti() before the timer irq handler is run to acknowledge the interrupt.
- */
-
-#define BUILD_TIMER_IRQ(nr,mask) \
-void IRQ_NAME(nr); \
-void sIRQ_NAME(nr); \
-void BAD_IRQ_NAME(nr); \
-__asm__ ( \
- ".text\n\t" \
- "IRQ" #nr "_interrupt:\n\t" \
- SAVE_ALL \
- "sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
- "moveq "#nr",$r10\n\t" \
- "move.d $sp,$r11\n\t" \
- "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
- "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
- "jump ret_from_intr\n\t" \
- "bad_IRQ" #nr "_interrupt:\n\t" \
- "push $r0\n\t" \
- BLOCK_IRQ(mask,nr) \
- "pop $r0\n\t" \
- "reti\n\t" \
- "nop\n");
-
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-cris/kmap_types.h b/include/asm-cris/kmap_types.h
new file mode 100644
index 000000000000..eec0974c2417
--- /dev/null
+++ b/include/asm-cris/kmap_types.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+/* Dummy header just to define km_type. None of this
+ * is actually used on cris.
+ */
+
+enum km_type {
+ KM_BOUNCE_READ,
+ KM_SKB_SUNRPC_DATA,
+ KM_SKB_DATA_SOFTIRQ,
+ KM_USER0,
+ KM_USER1,
+ KM_BIO_SRC_IRQ,
+ KM_BIO_DST_IRQ,
+ KM_PTE0,
+ KM_PTE1,
+ KM_IRQ0,
+ KM_IRQ1,
+ KM_CRYPTO_USER,
+ KM_CRYPTO_SOFTIRQ,
+ KM_TYPE_NR
+};
+
+#endif
diff --git a/include/asm-cris/mman.h b/include/asm-cris/mman.h
index 827849b9f7f1..4de58ad6efa1 100644
--- a/include/asm-cris/mman.h
+++ b/include/asm-cris/mman.h
@@ -6,6 +6,7 @@
#define PROT_READ 0x1 /* page can be read */
#define PROT_WRITE 0x2 /* page can be written */
#define PROT_EXEC 0x4 /* page can be executed */
+#define PROT_SEM 0x8 /* page may be used for atomic ops */
#define PROT_NONE 0x0 /* page can not be accessed */
#define MAP_SHARED 0x01 /* Share changes */
@@ -19,6 +20,8 @@
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
#define MAP_LOCKED 0x2000 /* pages are locked */
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_INVALIDATE 2 /* invalidate the caches */
diff --git a/include/asm-cris/mmu.h b/include/asm-cris/mmu.h
index df2d5ee85c7b..c40a1bcad06c 100644
--- a/include/asm-cris/mmu.h
+++ b/include/asm-cris/mmu.h
@@ -5,58 +5,6 @@
#ifndef _CRIS_MMU_H
#define _CRIS_MMU_H
-/* type used in struct mm to couple an MMU context to an active mm */
-
-typedef unsigned int mm_context_t;
-
-/* kernel memory segments */
-
-#define KSEG_F 0xf0000000UL
-#define KSEG_E 0xe0000000UL
-#define KSEG_D 0xd0000000UL
-#define KSEG_C 0xc0000000UL
-#define KSEG_B 0xb0000000UL
-#define KSEG_A 0xa0000000UL
-#define KSEG_9 0x90000000UL
-#define KSEG_8 0x80000000UL
-#define KSEG_7 0x70000000UL
-#define KSEG_6 0x60000000UL
-#define KSEG_5 0x50000000UL
-#define KSEG_4 0x40000000UL
-#define KSEG_3 0x30000000UL
-#define KSEG_2 0x20000000UL
-#define KSEG_1 0x10000000UL
-#define KSEG_0 0x00000000UL
-
-/* CRIS PTE bits (see R_TLB_LO in the register description)
- *
- * Bit: 31-13 12-------4 3 2 1 0
- * ________________________________________________
- * | pfn | reserved | global | valid | kernel | we |
- * |_____|__________|________|_______|________|_____|
- *
- * (pfn = physical frame number)
- */
-
-/* Real HW-based PTE bits. We use some synonym names so that
- * things become less confusing in combination with the SW-based
- * bits further below.
- *
- */
-
-#define _PAGE_WE (1<<0) /* page is write-enabled */
-#define _PAGE_SILENT_WRITE (1<<0) /* synonym */
-#define _PAGE_KERNEL (1<<1) /* page is kernel only */
-#define _PAGE_VALID (1<<2) /* page is valid */
-#define _PAGE_SILENT_READ (1<<2) /* synonym */
-#define _PAGE_GLOBAL (1<<3) /* global page - context is ignored */
-
-/* Bits the HW doesn't care about but the kernel uses them in SW */
-
-#define _PAGE_PRESENT (1<<4) /* page present in memory */
-#define _PAGE_ACCESSED (1<<5) /* simulated in software using valid bit */
-#define _PAGE_MODIFIED (1<<6) /* simulated in software using we bit */
-#define _PAGE_READ (1<<7) /* read-enabled */
-#define _PAGE_WRITE (1<<8) /* write-enabled */
+#include <asm/arch/mmu.h>
#endif
diff --git a/include/asm-cris/mmu_context.h b/include/asm-cris/mmu_context.h
index 6a6ea71a85cd..dd1db4e98fcc 100644
--- a/include/asm-cris/mmu_context.h
+++ b/include/asm-cris/mmu_context.h
@@ -17,7 +17,7 @@ extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
extern volatile pgd_t *current_pgd; /* defined in arch/cris/mm/fault.c */
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+extern inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
{
}
diff --git a/include/asm-cris/module.h b/include/asm-cris/module.h
index 5853a11d6163..7ee72311bd78 100644
--- a/include/asm-cris/module.h
+++ b/include/asm-cris/module.h
@@ -1,12 +1,9 @@
#ifndef _ASM_CRIS_MODULE_H
#define _ASM_CRIS_MODULE_H
-/*
- * This file contains the CRIS architecture specific module code.
- */
-
-#define module_map(x) vmalloc(x)
-#define module_unmap(x) vfree(x)
-#define module_arch_init(x) (0)
-#define arch_init_modules(x) do { } while (0)
+/* cris is simple */
+struct mod_arch_specific { };
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
#endif /* _ASM_CRIS_MODULE_H */
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index 47c83465c2af..05dc15526aa3 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -2,7 +2,7 @@
#define _CRIS_PAGE_H
#include <linux/config.h>
-#include <asm/mmu.h>
+#include <asm/arch/page.h>
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 13
@@ -14,12 +14,9 @@
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
-#define clear_user_page(page, vaddr) clear_page(page)
-#define copy_user_page(to, from, vaddr) copy_page(to, from)
+#define clear_user_page(page, vaddr, pg) clear_page(page)
+#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
/*
* These are used to make use of C type-checking..
*/
@@ -38,52 +35,11 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-#else
-/*
- * .. while these make it easier on the compiler
- */
-typedef unsigned long pte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t;
-typedef unsigned long pgprot_t;
-
-#define pte_val(x) (x)
-#define pmd_val(x) (x)
-#define pgd_val(x) (x)
-#define pgprot_val(x) (x)
-
-#define __pte(x) (x)
-#define __pmd(x) (x)
-#define __pgd(x) (x)
-#define __pgprot(x) (x)
-
-#endif
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-/* This handles the memory map.. */
-
-#ifdef CONFIG_CRIS_LOW_MAP
-#define PAGE_OFFSET KSEG_6 /* kseg_6 is mapped to physical ram */
-#else
-#define PAGE_OFFSET KSEG_C /* kseg_c is mapped to physical ram */
-#endif
-
-/* macros to convert between really physical and virtual addresses
- * by stripping a selected bit, we can convert between KSEG_x and 0x40000000 where
- * the DRAM really resides
- */
-
-#ifdef CONFIG_CRIS_LOW_MAP
-/* we have DRAM virtually at 0x6 */
-#define __pa(x) ((unsigned long)(x) & 0xdfffffff)
-#define __va(x) ((void *)((unsigned long)(x) | 0x20000000))
-#else
-/* we have DRAM virtually at 0xc */
-#define __pa(x) ((unsigned long)(x) & 0x7fffffff)
-#define __va(x) ((void *)((unsigned long)(x) | 0x80000000))
-#endif
+/* On CRIS the PFN numbers doesn't start at 0 so we have to compensate */
+/* for that before indexing into the page table starting at mem_map */
+#define pfn_to_page(pfn) (mem_map + ((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)))
+#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + (PAGE_OFFSET >> PAGE_SHIFT))
+#define pfn_valid(pfn) (((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)) < max_mapnr)
/* to index into the page map. our pages all start at physical addr PAGE_OFFSET so
* we can let the map start there. notice that we subtract PAGE_OFFSET because
@@ -95,6 +51,7 @@ typedef unsigned long pgprot_t;
#define virt_to_page(kaddr) (mem_map + (((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT))
#define VALID_PAGE(page) (((page) - mem_map) < max_mapnr)
+#define virt_addr_valid(kaddr) pfn_valid((kaddr) >> PAGE_SHIFT)
/* convert a page (based on mem_map and forward) to a physical address
* do this by figuring out the virtual address and then use __pa
@@ -102,9 +59,34 @@ typedef unsigned long pgprot_t;
#define page_to_phys(page) __pa((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-/* from linker script */
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+#ifndef __ASSEMBLY__
+
+#define BUG() do { \
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+} while (0)
+
+#define PAGE_BUG(page) do { \
+ BUG(); \
+} while (0)
+
+#endif /* __ASSEMBLY__ */
+
+/* Pure 2^n version of get_order */
+static inline int get_order(unsigned long size)
+{
+ int order;
-extern unsigned long dram_start, dram_end;
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
diff --git a/include/asm-cris/param.h b/include/asm-cris/param.h
index 50fe5729b29e..a9f71dbedb39 100644
--- a/include/asm-cris/param.h
+++ b/include/asm-cris/param.h
@@ -1,6 +1,13 @@
#ifndef _ASMCRIS_PARAM_H
#define _ASMCRIS_PARAM_H
+/* Currently we assume that HZ=100 is good for CRIS. */
+#ifdef __KERNEL__
+# define HZ 100 /* Internal kernel timer frequency */
+# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
+# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
+#endif
+
#ifndef HZ
#define HZ 100
#endif
@@ -17,8 +24,4 @@
#define MAXHOSTNAMELEN 64 /* max length of hostname */
-#ifdef __KERNEL__
-# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */
-#endif
-
#endif
diff --git a/include/asm-cris/percpu.h b/include/asm-cris/percpu.h
new file mode 100644
index 000000000000..6db9b43cf80a
--- /dev/null
+++ b/include/asm-cris/percpu.h
@@ -0,0 +1,6 @@
+#ifndef _CRIS_PERCPU_H
+#define _CRIS_PERCPU_H
+
+#include <asm-generic/percpu.h>
+
+#endif /* _CRIS_PERCPU_H */
diff --git a/include/asm-cris/pgalloc.h b/include/asm-cris/pgalloc.h
index 75dde6f4a42f..ca769e060298 100644
--- a/include/asm-cris/pgalloc.h
+++ b/include/asm-cris/pgalloc.h
@@ -3,113 +3,65 @@
#include <asm/page.h>
#include <linux/threads.h>
+#include <linux/mm.h>
-extern struct pgtable_cache_struct {
- unsigned long *pgd_cache;
- unsigned long *pte_cache;
- unsigned long pgtable_cache_sz;
-} quicklists;
-
-#define pgd_quicklist (quicklists.pgd_cache)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist (quicklists.pte_cache)
-#define pgtable_cache_size (quicklists.pgtable_cache_sz)
-
-#define pmd_populate(mm, pmd, pte) pmd_set(pmd, pte)
+#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte)
+#define pmd_populate(mm, pmd, pte) pmd_set(pmd, page_address(pte))
/*
* Allocate and free page tables.
*/
-static inline pgd_t *get_pgd_slow(void)
-{
- pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
-
- if (ret) {
- memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
- memcpy(ret + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD,
- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
- }
- return ret;
-}
-
-static inline void free_pgd_slow(pgd_t *pgd)
+extern inline pgd_t *pgd_alloc (struct mm_struct *mm)
{
- free_page((unsigned long)pgd);
+ return (pgd_t *)get_zeroed_page(GFP_KERNEL);
}
-static inline pgd_t *get_pgd_fast(void)
+extern inline void pgd_free (pgd_t *pgd)
{
- unsigned long *ret;
-
- if ((ret = pgd_quicklist) != NULL) {
- pgd_quicklist = (unsigned long *)(*ret);
- ret[0] = 0;
- pgtable_cache_size--;
- } else
- ret = (unsigned long *)get_pgd_slow();
- return (pgd_t *)ret;
+ free_page((unsigned long)pgd);
}
-static inline void free_pgd_fast(pgd_t *pgd)
+extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
- pgd_quicklist = (unsigned long *) pgd;
- pgtable_cache_size++;
+ pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+ if (pte)
+ clear_page(pte);
+ return pte;
}
-static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+extern inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte;
-
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
- if (pte)
- clear_page(pte);
- return pte;
+ struct page *pte;
+ pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+ if (pte)
+ clear_page(page_address(pte));
+ return pte;
}
-static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
+extern inline void pte_free_kernel(pte_t *pte)
{
- unsigned long *ret;
-
- if((ret = (unsigned long *)pte_quicklist) != NULL) {
- pte_quicklist = (unsigned long *)(*ret);
- ret[0] = ret[1];
- pgtable_cache_size--;
- }
- return (pte_t *)ret;
+ free_page((unsigned long)pte);
}
-static __inline__ void pte_free_fast(pte_t *pte)
+extern inline void pte_free(struct page *pte)
{
- *(unsigned long *)pte = (unsigned long) pte_quicklist;
- pte_quicklist = (unsigned long *) pte;
- pgtable_cache_size++;
+ __free_page(pte);
}
-static __inline__ void pte_free_slow(pte_t *pte)
-{
- free_page((unsigned long)pte);
-}
-#define pte_free(pte) pte_free_slow(pte)
-#define pgd_free(pgd) free_pgd_slow(pgd)
-#define pgd_alloc(mm) get_pgd_fast()
+#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
/*
* We don't have any real pmd's, and this code never triggers because
* the pgd will always be present..
*/
-#define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); })
-#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
-#define pmd_free_slow(x) do { } while (0)
-#define pmd_free_fast(x) do { } while (0)
-#define pmd_free(x) do { } while (0)
-#define pgd_populate(mm, pmd, pte) BUG()
-
-/* other stuff */
+#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
+#define pmd_free(x) do { } while (0)
+#define __pmd_free_tlb(tlb,x) do { } while (0)
+#define pgd_populate(mm, pmd, pte) BUG()
-extern int do_check_pgt_cache(int, int);
+#define check_pgt_cache() do { } while (0)
#endif
diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
index d3ffca513750..25b2b51b55b3 100644
--- a/include/asm-cris/pgtable.h
+++ b/include/asm-cris/pgtable.h
@@ -1,104 +1,14 @@
-/* CRIS pgtable.h - macros and functions to manipulate page tables
- *
- * HISTORY:
- *
- * $Log: pgtable.h,v $
- * Revision 1.14 2001/12/10 03:08:50 bjornw
- * Added pgtable_cache_init dummy
- *
- * Revision 1.13 2001/11/12 18:05:38 pkj
- * Added declaration of paging_init().
- *
- * Revision 1.12 2001/08/11 00:28:00 bjornw
- * PAGE_CHG_MASK and PAGE_NONE had somewhat untraditional values
- *
- * Revision 1.11 2001/04/04 14:38:36 bjornw
- * Removed bad_pagetable handling and the _kernel functions
- *
- * Revision 1.10 2001/03/23 07:46:42 starvik
- * Corrected according to review remarks
- *
- * Revision 1.9 2000/11/22 14:57:53 bjornw
- * * extern inline -> static inline
- * * include asm-generic/pgtable.h
- *
- * Revision 1.8 2000/11/21 13:56:16 bjornw
- * Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
- *
- * Revision 1.7 2000/10/06 15:05:32 bjornw
- * VMALLOC area changed in memory mapping change
- *
- * Revision 1.6 2000/10/04 16:59:14 bjornw
- * Changed comments
- *
- * Revision 1.5 2000/09/13 14:39:53 bjornw
- * New macros
- *
- * Revision 1.4 2000/08/17 15:38:48 bjornw
- * 2.4.0-test6 modifications:
- * * flush_dcache_page added
- * * MAP_NR removed
- * * virt_to_page added
- *
- * Plus some comments and type-clarifications.
- *
- * Revision 1.3 2000/08/15 16:33:35 bjornw
- * pmd_bad should recognize both kernel and user page-tables
- *
- * Revision 1.2 2000/07/10 17:06:01 bjornw
- * Fixed warnings
- *
- * Revision 1.1.1.1 2000/07/10 16:32:31 bjornw
- * CRIS architecture, working draft
- *
- *
- * Revision 1.11 2000/05/29 14:55:56 bjornw
- * Small tweaks of pte_mk routines
- *
- * Revision 1.10 2000/01/27 01:49:06 bjornw
- * * Ooops. The physical frame number in a PTE entry needs to point to the
- * DRAM directly, not to what the kernel thinks is DRAM (due to KSEG mapping).
- * Hence we need to strip bit 31 so 0xcXXXXXXX -> 0x4XXXXXXX.
- *
- * Revision 1.9 2000/01/26 16:25:50 bjornw
- * Fixed PAGE_KERNEL bits
- *
- * Revision 1.8 2000/01/23 22:53:22 bjornw
- * Correct flush_tlb_* macros and externs
- *
- * Revision 1.7 2000/01/18 16:22:55 bjornw
- * Use PAGE_MASK instead of PFN_MASK.
- *
- * Revision 1.6 2000/01/17 02:42:53 bjornw
- * Added the pmd_set macro.
- *
- * Revision 1.5 2000/01/16 19:53:42 bjornw
- * Removed VMALLOC_OFFSET. Changed definitions of swapper_pg_dir and zero_page.
- *
- * Revision 1.4 2000/01/14 16:38:20 bjornw
- * PAGE_DIRTY -> PAGE_SILENT_WRITE, removed PAGE_COW from PAGE_COPY.
- *
- * Revision 1.3 1999/12/04 20:12:21 bjornw
- * * PTE bits have moved to asm/mmu.h
- * * Fixed definitions of the higher level page protection bits
- * * Added the pte_* functions, including dirty/accessed SW simulation
- * (these are exactly the same as for the MIPS port)
- *
- * Revision 1.2 1999/12/04 00:41:54 bjornw
- * * Fixed page table offsets, sizes and shifts
- * * Removed reference to i386 SMP stuff
- * * Added stray comments about Linux/CRIS mm design
- * * Include asm/mmu.h which will contain MMU details
- *
- * Revision 1.1 1999/12/03 15:04:02 bjornw
- * Copied from include/asm-etrax100. For the new CRIS architecture.
+/*
+ * CRIS pgtable.h - macros and functions to manipulate page tables.
*/
#ifndef _CRIS_PGTABLE_H
#define _CRIS_PGTABLE_H
#include <linux/config.h>
+#include <linux/sched.h>
#include <asm/mmu.h>
+#include <asm/arch/pgtable.h>
/*
* The Linux memory management assumes a three-level page table setup. On
@@ -114,49 +24,6 @@
extern void paging_init(void);
-/* The cache doesn't need to be flushed when TLB entries change because
- * the cache is mapped to physical memory, not virtual memory
- */
-#define flush_cache_all() do { } while (0)
-#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_range(vma, start, end) do { } while (0)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_dcache_page(page) do { } while (0)
-#define flush_icache_range(start, end) do { } while (0)
-#define flush_icache_page(vma,pg) do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
-
-/*
- * TLB flushing (implemented in arch/cris/mm/tlb.c):
- *
- * - flush_tlb() flushes the current mm struct TLBs
- * - flush_tlb_all() flushes all processes TLBs
- * - flush_tlb_mm(mm) flushes the specified mm context TLB's
- * - flush_tlb_page(vma, vmaddr) flushes one page
- * - flush_tlb_range(vma, start, end) flushes a range of pages
- *
- */
-
-extern void flush_tlb_all(void);
-extern void flush_tlb_mm(struct mm_struct *mm);
-extern void flush_tlb_page(struct vm_area_struct *vma,
- unsigned long addr);
-extern void flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start,
- unsigned long end);
-
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- /* CRIS does not keep any page table caches in TLB */
-}
-
-
-static inline void flush_tlb(void)
-{
- flush_tlb_mm(current->mm);
-}
-
/* Certain architectures need to do special things when pte's
* within a page table are directly modified. Thus, the following
* hook is made available.
@@ -204,63 +71,6 @@ static inline void flush_tlb(void)
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
#define FIRST_USER_PGD_NR 0
-/*
- * Kernels own virtual memory area.
- */
-
-#ifdef CONFIG_CRIS_LOW_MAP
-#define VMALLOC_START KSEG_7
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END KSEG_8
-#else
-#define VMALLOC_START KSEG_D
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END KSEG_E
-#endif
-
-/* Define some higher level generic page attributes. The PTE bits are
- * defined in asm-cris/mmu.h, and these are just combinations of those.
- */
-
-#define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
-#define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
-
-#define _PAGE_TABLE (_PAGE_PRESENT | __READABLE | __WRITEABLE)
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED)
-
-#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_SHARED __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
- _PAGE_ACCESSED)
-#define PAGE_COPY __pgprot(_PAGE_PRESENT | __READABLE) // | _PAGE_COW
-#define PAGE_READONLY __pgprot(_PAGE_PRESENT | __READABLE)
-#define PAGE_KERNEL __pgprot(_PAGE_GLOBAL | _PAGE_KERNEL | \
- _PAGE_PRESENT | __READABLE | __WRITEABLE)
-#define _KERNPG_TABLE (_PAGE_TABLE | _PAGE_KERNEL)
-
-/*
- * CRIS can't do page protection for execute, and considers read the same.
- * Also, write permissions imply read permissions. This is the closest we can
- * get..
- */
-
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
-
/* zero page used for uninitialized stuff */
extern unsigned long empty_zero_page;
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
@@ -299,53 +109,54 @@ extern unsigned long empty_zero_page;
* setup: the pgd is never bad, and a pmd always exists (as it's folded
* into the pgd entry)
*/
-static inline int pgd_none(pgd_t pgd) { return 0; }
-static inline int pgd_bad(pgd_t pgd) { return 0; }
-static inline int pgd_present(pgd_t pgd) { return 1; }
-static inline void pgd_clear(pgd_t * pgdp) { }
+extern inline int pgd_none(pgd_t pgd) { return 0; }
+extern inline int pgd_bad(pgd_t pgd) { return 0; }
+extern inline int pgd_present(pgd_t pgd) { return 1; }
+extern inline void pgd_clear(pgd_t * pgdp) { }
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
-static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
+extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
-static inline pte_t pte_wrprotect(pte_t pte)
+extern inline pte_t pte_wrprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
return pte;
}
-static inline pte_t pte_rdprotect(pte_t pte)
+extern inline pte_t pte_rdprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
return pte;
}
-static inline pte_t pte_exprotect(pte_t pte)
+extern inline pte_t pte_exprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
return pte;
}
-static inline pte_t pte_mkclean(pte_t pte)
+extern inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
return pte;
}
-static inline pte_t pte_mkold(pte_t pte)
+extern inline pte_t pte_mkold(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ);
return pte;
}
-static inline pte_t pte_mkwrite(pte_t pte)
+extern inline pte_t pte_mkwrite(pte_t pte)
{
pte_val(pte) |= _PAGE_WRITE;
if (pte_val(pte) & _PAGE_MODIFIED)
@@ -353,7 +164,7 @@ static inline pte_t pte_mkwrite(pte_t pte)
return pte;
}
-static inline pte_t pte_mkread(pte_t pte)
+extern inline pte_t pte_mkread(pte_t pte)
{
pte_val(pte) |= _PAGE_READ;
if (pte_val(pte) & _PAGE_ACCESSED)
@@ -361,7 +172,7 @@ static inline pte_t pte_mkread(pte_t pte)
return pte;
}
-static inline pte_t pte_mkexec(pte_t pte)
+extern inline pte_t pte_mkexec(pte_t pte)
{
pte_val(pte) |= _PAGE_READ;
if (pte_val(pte) & _PAGE_ACCESSED)
@@ -369,7 +180,7 @@ static inline pte_t pte_mkexec(pte_t pte)
return pte;
}
-static inline pte_t pte_mkdirty(pte_t pte)
+extern inline pte_t pte_mkdirty(pte_t pte)
{
pte_val(pte) |= _PAGE_MODIFIED;
if (pte_val(pte) & _PAGE_WRITE)
@@ -377,7 +188,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
return pte;
}
-static inline pte_t pte_mkyoung(pte_t pte)
+extern inline pte_t pte_mkyoung(pte_t pte)
{
pte_val(pte) |= _PAGE_ACCESSED;
if (pte_val(pte) & _PAGE_READ)
@@ -401,7 +212,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
* addresses (the 0xc0xxxxxx's) goes as void *'s.
*/
-static inline pte_t __mk_pte(void * page, pgprot_t pgprot)
+extern inline pte_t __mk_pte(void * page, pgprot_t pgprot)
{
pte_t pte;
/* the PTE needs a physical address */
@@ -419,7 +230,7 @@ static inline pte_t __mk_pte(void * page, pgprot_t pgprot)
__pte; \
})
-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
@@ -428,7 +239,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* pte_pagenr refers to the page-number counted starting from the virtual DRAM start
*/
-static inline unsigned long __pte_page(pte_t pte)
+extern inline unsigned long __pte_page(pte_t pte)
{
/* the PTE contains a physical address */
return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
@@ -446,17 +257,17 @@ static inline unsigned long __pte_page(pte_t pte)
* don't need the __pa and __va transformations.
*/
-static inline unsigned long pmd_page(pmd_t pmd)
-{ return pmd_val(pmd) & PAGE_MASK; }
-
-static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
{ pmd_val(*pmdp) = _PAGE_TABLE | (unsigned long) ptep; }
+#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
/* to find an entry in a page-table-directory. */
#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
/* to find an entry in a page-table-directory */
-static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
{
return mm->pgd + pgd_index(address);
}
@@ -465,16 +276,24 @@ static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
/* Find an entry in the second-level page table.. */
-static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
{
return (pmd_t *) dir;
}
-/* Find an entry in the third-level page table.. */
-static inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
-{
- return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
+/* Find an entry in the third-level page table.. */
+#define __pte_offset(address) \
+ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address) \
+ ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address))
+#define pte_offset_map(dir, address) \
+ ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
+
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
+#define pte_pfn(x) ((unsigned long)(__va((x).pte)) >> PAGE_SHIFT)
+#define pfn_pte(pfn, prot) __pte((__pa((pfn) << PAGE_SHIFT)) | pgprot_val(prot))
#define pte_ERROR(e) \
printk("%s:%d: bad pte %p(%08lx).\n", __FILE__, __LINE__, &(e), pte_val(e))
@@ -483,6 +302,7 @@ static inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
+
extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
/*
@@ -491,7 +311,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
*
* Actually I am not sure on what this could be used for.
*/
-static inline void update_mmu_cache(struct vm_area_struct * vma,
+extern inline void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t pte)
{
}
@@ -514,6 +334,9 @@ static inline void update_mmu_cache(struct vm_area_struct * vma,
*/
#define pgtable_cache_init() do { } while (0)
+#define pte_to_pgoff(x) (pte_val(x) >> 6)
+#define pgoff_to_pte(x) __pte(((x) << 6) | _PAGE_FILE)
+
typedef pte_t *pte_addr_t;
#endif /* _CRIS_PGTABLE_H */
diff --git a/include/asm-cris/poll.h b/include/asm-cris/poll.h
index 8699d59dad74..1c0efc3e4be7 100644
--- a/include/asm-cris/poll.h
+++ b/include/asm-cris/poll.h
@@ -14,6 +14,7 @@
#define POLLWRNORM 256
#define POLLWRBAND 512
#define POLLMSG 1024
+#define POLLREMOVE 4096
struct pollfd {
int fd;
diff --git a/include/asm-cris/posix_types.h b/include/asm-cris/posix_types.h
index d10e9fc65c32..d1c87c652619 100644
--- a/include/asm-cris/posix_types.h
+++ b/include/asm-cris/posix_types.h
@@ -23,12 +23,14 @@ typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
-typedef unsigned long __kernel_size_t;
+typedef __SIZE_TYPE__ __kernel_size_t;
typedef long __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t;
+typedef int __kernel_timer_t;
+typedef int __kernel_clockid_t;
typedef int __kernel_daddr_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h
index 0a8c08fa93b5..623bdf06d911 100644
--- a/include/asm-cris/processor.h
+++ b/include/asm-cris/processor.h
@@ -14,32 +14,12 @@
#include <asm/system.h>
#include <asm/page.h>
#include <asm/ptrace.h>
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({void *pc; __asm__ ("move.d $pc,%0" : "=rm" (pc)); pc; })
-
-/* CRIS has no problems with write protection */
-
-#define wp_works_ok 1
-
-/*
- * User space process size. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- */
-
-#ifdef CONFIG_CRIS_LOW_MAP
-#define TASK_SIZE (0x50000000UL) /* 1.25 GB */
-#else
-#define TASK_SIZE (0xB0000000UL) /* 2.75 GB */
-#endif
+#include <asm/arch/processor.h>
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
* normally, the stack is found by doing something like p + THREAD_SIZE
@@ -49,19 +29,6 @@
#define THREAD_SIZE PAGE_SIZE
#define KERNEL_STACK_SIZE PAGE_SIZE
-/* CRIS thread_struct. this really has nothing to do with the processor itself, since
- * CRIS does not do any hardware task-switching, but it's here for legacy reasons.
- * The thread_struct here is used when task-switching using _resume defined in entry.S.
- * The offsets here are hardcoded into _resume - if you change this struct, you need to
- * change them as well!!!
-*/
-
-struct thread_struct {
- unsigned long ksp; /* kernel stack pointer */
- unsigned long usp; /* user stack pointer */
- unsigned long dccr; /* saved flag register */
-};
-
/*
* At user->kernel entry, the pt_regs struct is stacked on the top of the kernel-stack.
* This macro allows us to find those regs for a task.
@@ -70,76 +37,42 @@ struct thread_struct {
* registers are reached by this.
*/
-#define user_regs(task) (((struct pt_regs *)((unsigned long)(task) + THREAD_SIZE)) - 1)
+#define user_regs(thread_info) (((struct pt_regs *)((unsigned long)(thread_info) + THREAD_SIZE)) - 1)
/*
* Dito but for the currently running task
*/
-#define current_regs() user_regs(current)
+#define current_regs() user_regs(current->thread_info)
-#define INIT_THREAD { \
- 0, 0, 0x20 } /* ccr = int enable, nothing else */
+extern inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-/* give the thread a program location
- * set user-mode (The 'U' flag (User mode flag) is CCR/DCCR bit 8)
- * switch user-stackpointer
- */
-
-#define start_thread(regs, ip, usp) do { \
- set_fs(USER_DS); \
- regs->irp = ip; \
- regs->dccr |= 1 << U_DCCR_BITNR; \
- wrusp(usp); \
-} while(0)
-
unsigned long get_wchan(struct task_struct *p);
-#define KSTK_EIP(tsk) \
- ({ \
- unsigned long eip = 0; \
- unsigned long regs = (unsigned long)user_regs(tsk); \
- if (regs > PAGE_SIZE && \
- virt_addr_valid(regs)) \
- eip = ((struct pt_regs *)regs)->irp; \
- eip; })
-
#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
/*
* Free current thread data structures etc..
*/
-static inline void exit_thread(void)
+extern inline void exit_thread(void)
{
/* Nothing needs to be done. */
}
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
/* Free all resources held by a thread. */
-static inline void release_thread(struct task_struct *dead_task)
+extern inline void release_thread(struct task_struct *dead_task)
{
/* Nothing needs to be done. */
}
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
-/*
- * Return saved PC of a blocked thread.
- */
-extern inline unsigned long thread_saved_pc(struct thread_struct *t)
-{
- return (unsigned long)user_regs(t)->irp;
-}
-
-#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long) (p), 1)
-#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)
-
-#define init_task (init_task_union.task)
-#define init_stack (init_task_union.stack)
+#define init_stack (init_thread_union.stack)
#define cpu_relax() barrier()
diff --git a/include/asm-cris/ptrace.h b/include/asm-cris/ptrace.h
index b7391cc079dc..79045e36d0a9 100644
--- a/include/asm-cris/ptrace.h
+++ b/include/asm-cris/ptrace.h
@@ -1,120 +1,10 @@
#ifndef _CRIS_PTRACE_H
#define _CRIS_PTRACE_H
-/* Register numbers in the ptrace system call interface */
+#include <asm/arch/ptrace.h>
-#define PT_FRAMETYPE 0
-#define PT_ORIG_R10 1
-#define PT_R13 2
-#define PT_R12 3
-#define PT_R11 4
-#define PT_R10 5
-#define PT_R9 6
-#define PT_R8 7
-#define PT_R7 8
-#define PT_R6 9
-#define PT_R5 10
-#define PT_R4 11
-#define PT_R3 12
-#define PT_R2 13
-#define PT_R1 14
-#define PT_R0 15
-#define PT_MOF 16
-#define PT_DCCR 17
-#define PT_SRP 18
-#define PT_IRP 19 /* This is actually the debugged process' PC */
-#define PT_CSRINSTR 20 /* CPU Status record remnants -
- valid if frametype == busfault */
-#define PT_CSRADDR 21
-#define PT_CSRDATA 22
-#define PT_USP 23 /* special case - USP is not in the pt_regs */
-#define PT_MAX 23
-
-/* Condition code bit numbers. The same numbers apply to CCR of course,
- but we use DCCR everywhere else, so let's try and be consistent. */
-#define C_DCCR_BITNR 0
-#define V_DCCR_BITNR 1
-#define Z_DCCR_BITNR 2
-#define N_DCCR_BITNR 3
-#define X_DCCR_BITNR 4
-#define I_DCCR_BITNR 5
-#define B_DCCR_BITNR 6
-#define M_DCCR_BITNR 7
-#define U_DCCR_BITNR 8
-#define P_DCCR_BITNR 9
-#define F_DCCR_BITNR 10
-
-/* Frame types */
-
-#define CRIS_FRAME_NORMAL 0 /* normal frame without SBFS stacking */
-#define CRIS_FRAME_BUSFAULT 1 /* frame stacked using SBFS, need RBF return
- path */
-
-/* pt_regs not only specifices the format in the user-struct during
- * ptrace but is also the frame format used in the kernel prologue/epilogues
- * themselves
- */
-
-struct pt_regs {
- unsigned long frametype; /* type of stackframe */
- unsigned long orig_r10;
- /* pushed by movem r13, [sp] in SAVE_ALL, movem pushes backwards */
- unsigned long r13;
- unsigned long r12;
- unsigned long r11;
- unsigned long r10;
- unsigned long r9;
- unsigned long r8;
- unsigned long r7;
- unsigned long r6;
- unsigned long r5;
- unsigned long r4;
- unsigned long r3;
- unsigned long r2;
- unsigned long r1;
- unsigned long r0;
- unsigned long mof;
- unsigned long dccr;
- unsigned long srp;
- unsigned long irp; /* This is actually the debugged process' PC */
- unsigned long csrinstr;
- unsigned long csraddr;
- unsigned long csrdata;
-};
-
-/* switch_stack is the extra stuff pushed onto the stack in _resume (entry.S)
- * when doing a context-switch. it is used (apart from in resume) when a new
- * thread is made and we need to make _resume (which is starting it for the
- * first time) realise what is going on.
- *
- * Actually, the use is very close to the thread struct (TSS) in that both the
- * switch_stack and the TSS are used to keep thread stuff when switching in
- * _resume.
- */
-
-struct switch_stack {
- unsigned long r9;
- unsigned long r8;
- unsigned long r7;
- unsigned long r6;
- unsigned long r5;
- unsigned long r4;
- unsigned long r3;
- unsigned long r2;
- unsigned long r1;
- unsigned long r0;
- unsigned long return_ip; /* ip that _resume will return to */
-};
-
-#ifdef __KERNEL__
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
-/* bit 8 is user-mode flag */
-#define user_mode(regs) (((regs)->dccr & 0x100) != 0)
-#define instruction_pointer(regs) ((regs)->irp)
-extern void show_regs(struct pt_regs *);
-#endif
-
#endif /* _CRIS_PTRACE_H */
diff --git a/include/asm-cris/rs485.h b/include/asm-cris/rs485.h
new file mode 100644
index 000000000000..c331c51b0c2b
--- /dev/null
+++ b/include/asm-cris/rs485.h
@@ -0,0 +1,20 @@
+/* RS-485 structures */
+
+/* RS-485 support */
+/* Used with ioctl() TIOCSERSETRS485 */
+struct rs485_control {
+ unsigned short rts_on_send;
+ unsigned short rts_after_sent;
+ unsigned long delay_rts_before_send;
+ unsigned short enabled;
+#ifdef __KERNEL__
+ int disable_serial_loopback;
+#endif
+};
+
+/* Used with ioctl() TIOCSERWRRS485 */
+struct rs485_write {
+ unsigned short outc_size;
+ unsigned char *outc;
+};
+
diff --git a/include/asm-cris/rtc.h b/include/asm-cris/rtc.h
index 72ff33a48a8d..382081c4ab52 100644
--- a/include/asm-cris/rtc.h
+++ b/include/asm-cris/rtc.h
@@ -1,42 +1,81 @@
-/* $Id: rtc.h,v 1.3 2001/03/21 09:56:31 magnusmn Exp $ */
+/* $Id: rtc.h,v 1.7 2002/11/04 07:32:09 starvik Exp $ */
+
+#ifndef __RTC_H__
+#define __RTC_H__
-#ifndef RTC_H
-#define RTC_H
#include <linux/config.h>
-/* Dallas DS1302 clock/calendar register numbers */
+#ifdef CONFIG_ETRAX_DS1302
+ /* Dallas DS1302 clock/calendar register numbers. */
+# define RTC_SECONDS 0
+# define RTC_MINUTES 1
+# define RTC_HOURS 2
+# define RTC_DAY_OF_MONTH 3
+# define RTC_MONTH 4
+# define RTC_WEEKDAY 5
+# define RTC_YEAR 6
+# define RTC_CONTROL 7
+
+ /* Bits in CONTROL register. */
+# define RTC_CONTROL_WRITEPROTECT 0x80
+# define RTC_TRICKLECHARGER 8
+
+ /* Bits in TRICKLECHARGER register TCS TCS TCS TCS DS DS RS RS. */
+# define RTC_TCR_PATTERN 0xA0 /* 1010xxxx */
+# define RTC_TCR_1DIOD 0x04 /* xxxx01xx */
+# define RTC_TCR_2DIOD 0x08 /* xxxx10xx */
+# define RTC_TCR_DISABLED 0x00 /* xxxxxx00 Disabled */
+# define RTC_TCR_2KOHM 0x01 /* xxxxxx01 2KOhm */
+# define RTC_TCR_4KOHM 0x02 /* xxxxxx10 4kOhm */
+# define RTC_TCR_8KOHM 0x03 /* xxxxxx11 8kOhm */
+
+#elif defined(CONFIG_ETRAX_PCF8563)
+ /* I2C bus slave registers. */
+# define RTC_I2C_READ 0xa3
+# define RTC_I2C_WRITE 0xa2
-#define RTC_SECONDS 0
-#define RTC_MINUTES 1
-#define RTC_HOURS 2
-#define RTC_DAY_OF_MONTH 3
-#define RTC_MONTH 4
-#define RTC_WEEKDAY 5
-#define RTC_YEAR 6
-#define RTC_CONTROL 7
+ /* Phillips PCF8563 registers. */
+# define RTC_CONTROL1 0x00 /* Control/Status register 1. */
+# define RTC_CONTROL2 0x01 /* Control/Status register 2. */
+# define RTC_CLOCKOUT_FREQ 0x0d /* CLKOUT frequency. */
+# define RTC_TIMER_CONTROL 0x0e /* Timer control. */
+# define RTC_TIMER_CNTDOWN 0x0f /* Timer countdown. */
-/* Bits in CONTROL register */
-#define RTC_CONTROL_WRITEPROTECT 0x80
-#define RTC_TRICKLECHARGER 8
-/* Bits in TRICKLECHARGER register TCS TCS TCS TCS DS DS RS RS */
-#define RTC_TCR_PATTERN 0xA0 /* 1010xxxx */
-#define RTC_TCR_1DIOD 0x04 /* xxxx01xx */
-#define RTC_TCR_2DIOD 0x08 /* xxxx10xx */
-#define RTC_TCR_DISABLED 0x00 /* xxxxxx00 Disabled */
-#define RTC_TCR_2KOHM 0x01 /* xxxxxx01 2KOhm */
-#define RTC_TCR_4KOHM 0x02 /* xxxxxx10 4kOhm */
-#define RTC_TCR_8KOHM 0x03 /* xxxxxx11 8kOhm */
+ /* BCD encoded clock registers. */
+# define RTC_SECONDS 0x02
+# define RTC_MINUTES 0x03
+# define RTC_HOURS 0x04
+# define RTC_DAY_OF_MONTH 0x05
+# define RTC_WEEKDAY 0x06 /* Not coded in BCD! */
+# define RTC_MONTH 0x07
+# define RTC_YEAR 0x08
+# define RTC_MINUTE_ALARM 0x09
+# define RTC_HOUR_ALARM 0x0a
+# define RTC_DAY_ALARM 0x0b
+# define RTC_WEEKDAY_ALARM 0x0c
+
+#endif
#ifdef CONFIG_ETRAX_DS1302
-#define CMOS_READ(x) ds1302_readreg(x)
-#define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
-#define RTC_INIT() ds1302_init()
+extern unsigned char ds1302_readreg(int reg);
+extern void ds1302_writereg(int reg, unsigned char val);
+extern int ds1302_init(void);
+# define CMOS_READ(x) ds1302_readreg(x)
+# define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
+# define RTC_INIT() ds1302_init()
+#elif defined(CONFIG_ETRAX_PCF8563)
+extern unsigned char pcf8563_readreg(int reg);
+extern void pcf8563_writereg(int reg, unsigned char val);
+extern int pcf8563_init(void);
+# define CMOS_READ(x) pcf8563_readreg(x)
+# define CMOS_WRITE(val,reg) pcf8563_writereg(reg,val)
+# define RTC_INIT() pcf8563_init()
#else
-/* no RTC configured so we shouldn't try to access any */
-#define CMOS_READ(x) 42
-#define CMOS_WRITE(x,y)
-#define RTC_INIT() (-1)
+ /* No RTC configured so we shouldn't try to access any. */
+# define CMOS_READ(x) 42
+# define CMOS_WRITE(x,y)
+# define RTC_INIT() (-1)
#endif
/*
@@ -44,7 +83,6 @@
* struct tm in <time.h>, but it needs to be here so that the kernel
* source is self contained, allowing cross-compiles, etc. etc.
*/
-
struct rtc_time {
int tm_sec;
int tm_min;
@@ -57,14 +95,11 @@ struct rtc_time {
int tm_isdst;
};
-/*
- * ioctl calls that are permitted to the /dev/rtc interface
- */
-
-#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time) /* Read RTC time */
-#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
-#define RTC_SET_CHARGE _IOW('p', 0x0b, int) /* Set CHARGE mode */
-
-#endif
-
+/* ioctl() calls that are permitted to the /dev/rtc interface. */
+#define RTC_MAGIC 'p'
+#define RTC_RD_TIME _IOR(RTC_MAGIC, 0x09, struct rtc_time) /* Read RTC time. */
+#define RTC_SET_TIME _IOW(RTC_MAGIC, 0x0a, struct rtc_time) /* Set RTC time. */
+#define RTC_SET_CHARGE _IOW(RTC_MAGIC, 0x0b, int)
+#define RTC_MAX_IOCTL 0x0b
+#endif /* __RTC_H__ */
diff --git a/include/asm-cris/scatterlist.h b/include/asm-cris/scatterlist.h
index 11a64f5fe30b..4bdc44c4ac3d 100644
--- a/include/asm-cris/scatterlist.h
+++ b/include/asm-cris/scatterlist.h
@@ -11,6 +11,8 @@ struct scatterlist {
};
+#define sg_dma_address(sg) ((sg)->address)
+#define sg_dma_len(sg) ((sg)->length)
/* i386 junk */
#define ISA_DMA_THRESHOLD (0x1fffffff)
diff --git a/include/asm-cris/semaphore-helper.h b/include/asm-cris/semaphore-helper.h
index 3453c88c2f2e..461c5e4fc7b8 100644
--- a/include/asm-cris/semaphore-helper.h
+++ b/include/asm-cris/semaphore-helper.h
@@ -9,6 +9,7 @@
#define _ASM_SEMAPHORE_HELPER_H
#include <asm/atomic.h>
+#include <linux/errno.h>
#define read(a) ((a)->counter)
#define inc(a) (((a)->counter)++)
@@ -19,32 +20,34 @@
/*
* These two _must_ execute atomically wrt each other.
*/
-static inline void wake_one_more(struct semaphore * sem)
+extern inline void wake_one_more(struct semaphore * sem)
{
atomic_inc(&sem->waking);
}
-static inline int waking_non_zero(struct semaphore *sem)
+extern inline int waking_non_zero(struct semaphore *sem)
{
unsigned long flags;
int ret = 0;
- save_and_cli(flags);
+ local_save_flags(flags);
+ local_irq_disable();
if (read(&sem->waking) > 0) {
dec(&sem->waking);
ret = 1;
}
- restore_flags(flags);
+ local_irq_restore(flags);
return ret;
}
-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+extern inline int waking_non_zero_interruptible(struct semaphore *sem,
struct task_struct *tsk)
{
int ret = 0;
unsigned long flags;
- save_and_cli(flags);
+ local_save_flags(flags);
+ local_irq_disable();
if (read(&sem->waking) > 0) {
dec(&sem->waking);
ret = 1;
@@ -52,23 +55,24 @@ static inline int waking_non_zero_interruptible(struct semaphore *sem,
count_inc(&sem->count);
ret = -EINTR;
}
- restore_flags(flags);
+ local_irq_restore(flags);
return ret;
}
-static inline int waking_non_zero_trylock(struct semaphore *sem)
+extern inline int waking_non_zero_trylock(struct semaphore *sem)
{
int ret = 1;
unsigned long flags;
- save_and_cli(flags);
+ local_save_flags(flags);
+ local_irq_disable();
if (read(&sem->waking) <= 0)
count_inc(&sem->count);
else {
dec(&sem->waking);
ret = 0;
}
- restore_flags(flags);
+ local_irq_restore(flags);
return ret;
}
diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
index f55edcd2f8d2..011a3bdc9ca7 100644
--- a/include/asm-cris/semaphore.h
+++ b/include/asm-cris/semaphore.h
@@ -54,12 +54,12 @@ extern inline void sema_init(struct semaphore *sem, int val)
*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}
-static inline void init_MUTEX (struct semaphore *sem)
+extern inline void init_MUTEX (struct semaphore *sem)
{
sema_init(sem, 1);
}
-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+extern inline void init_MUTEX_LOCKED (struct semaphore *sem)
{
sema_init(sem, 0);
}
@@ -81,10 +81,10 @@ extern inline void down(struct semaphore * sem)
#endif
/* atomically decrement the semaphores count, and if its negative, we wait */
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
failed = --(sem->count) < 0;
- restore_flags(flags);
+ local_irq_restore(flags);
if(failed) {
__down(sem);
}
@@ -106,10 +106,10 @@ extern inline int down_interruptible(struct semaphore * sem)
#endif
/* atomically decrement the semaphores count, and if its negative, we wait */
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
failed = --(sem->count) < 0;
- restore_flags(flags);
+ local_irq_restore(flags);
if(failed)
failed = __down_interruptible(sem);
return(failed);
@@ -124,10 +124,10 @@ extern inline int down_trylock(struct semaphore * sem)
CHECK_MAGIC(sem->__magic);
#endif
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
failed = --(sem->count) < 0;
- restore_flags(flags);
+ local_irq_restore(flags);
if(failed)
failed = __down_trylock(sem);
return(failed);
@@ -149,10 +149,10 @@ extern inline void up(struct semaphore * sem)
#endif
/* atomically increment the semaphores count, and if it was negative, we wake people */
- save_flags(flags);
- cli();
+ local_save_flags(flags);
+ local_irq_disable();
wakeup = ++(sem->count) <= 0;
- restore_flags(flags);
+ local_irq_restore(flags);
if(wakeup) {
__up(sem);
}
diff --git a/include/asm-cris/setup.h b/include/asm-cris/setup.h
index f382d3b4d282..832c197edf48 100644
--- a/include/asm-cris/setup.h
+++ b/include/asm-cris/setup.h
@@ -1,405 +1,3 @@
-/*
-** asm/setup.h -- Definition of the Linux/m68k boot information structure
-**
-** Copyright 1992 by Greg Harp
-**
-** This file is subject to the terms and conditions of the GNU General Public
-** License. See the file COPYING in the main directory of this archive
-** for more details.
-**
-** Created 09/29/92 by Greg Harp
-**
-** 5/2/94 Roman Hodek:
-** Added bi_atari part of the machine dependent union bi_un; for now it
-** contains just a model field to distinguish between TT and Falcon.
-** 26/7/96 Roman Zippel:
-** Renamed to setup.h; added some useful macros to allow gcc some
-** optimizations if possible.
-*/
-
-#ifndef _M68K_SETUP_H
-#define _M68K_SETUP_H
-
-#include <linux/config.h>
-
-#define CL_SIZE (256)
-
-#if 0
-
-#include <asm/zorro.h>
-
-/*
- * Amiga specific part of bootinfo structure.
- */
-
-#define NUM_AUTO 16
-
-#ifndef __ASSEMBLY__
-
-#define AMIGAHW_DECLARE(name) unsigned name : 1
-#define AMIGAHW_SET(name) (boot_info.bi_amiga.hw_present.name = 1)
-#define AMIGAHW_PRESENT(name) (boot_info.bi_amiga.hw_present.name)
-
-struct bi_Amiga {
- int model; /* Amiga Model (3000?) */
- int num_autocon; /* # of autoconfig devices found */
- struct ConfigDev autocon[NUM_AUTO]; /* up to 16 autoconfig devices */
-#ifdef HACKER_KERNEL
- void (*exit_func)(void); /* addr of function to exit kernel */
- unsigned long chip_addr; /* start of chip memory (bytes) */
+#ifndef _CRIS_SETUP_H
+#define _CRIS_SETUP_H
#endif
- unsigned long chip_size; /* size of chip memory (bytes) */
- unsigned char vblank; /* VBLANK frequency */
- unsigned char psfreq; /* power supply frequency */
- unsigned long eclock; /* EClock frequency */
- unsigned long chipset; /* native chipset present */
- struct {
- /* video hardware */
- AMIGAHW_DECLARE(AMI_VIDEO); /* Amiga Video */
- AMIGAHW_DECLARE(AMI_BLITTER); /* Amiga Blitter */
- AMIGAHW_DECLARE(AMBER_FF); /* Amber Flicker Fixer */
- /* sound hardware */
- AMIGAHW_DECLARE(AMI_AUDIO); /* Amiga Audio */
- /* disk storage interfaces */
- AMIGAHW_DECLARE(AMI_FLOPPY); /* Amiga Floppy */
- AMIGAHW_DECLARE(A3000_SCSI); /* SCSI (wd33c93, A3000 alike) */
- AMIGAHW_DECLARE(A4000_SCSI); /* SCSI (ncr53c710, A4000T alike) */
- AMIGAHW_DECLARE(A1200_IDE); /* IDE (A1200 alike) */
- AMIGAHW_DECLARE(A4000_IDE); /* IDE (A4000 alike) */
- AMIGAHW_DECLARE(CD_ROM); /* CD ROM drive */
- /* other I/O hardware */
- AMIGAHW_DECLARE(AMI_KEYBOARD); /* Amiga Keyboard */
- AMIGAHW_DECLARE(AMI_MOUSE); /* Amiga Mouse */
- AMIGAHW_DECLARE(AMI_SERIAL); /* Amiga Serial */
- AMIGAHW_DECLARE(AMI_PARALLEL); /* Amiga Parallel */
- /* real time clocks */
- AMIGAHW_DECLARE(A2000_CLK); /* Hardware Clock (A2000 alike) */
- AMIGAHW_DECLARE(A3000_CLK); /* Hardware Clock (A3000 alike) */
- /* supporting hardware */
- AMIGAHW_DECLARE(CHIP_RAM); /* Chip RAM */
- AMIGAHW_DECLARE(PAULA); /* Paula (8364) */
- AMIGAHW_DECLARE(DENISE); /* Denise (8362) */
- AMIGAHW_DECLARE(DENISE_HR); /* Denise (8373) */
- AMIGAHW_DECLARE(LISA); /* Lisa (8375) */
- AMIGAHW_DECLARE(AGNUS_PAL); /* Normal/Fat PAL Agnus (8367/8371) */
- AMIGAHW_DECLARE(AGNUS_NTSC); /* Normal/Fat NTSC Agnus (8361/8370) */
- AMIGAHW_DECLARE(AGNUS_HR_PAL); /* Fat Hires PAL Agnus (8372) */
- AMIGAHW_DECLARE(AGNUS_HR_NTSC); /* Fat Hires NTSC Agnus (8372) */
- AMIGAHW_DECLARE(ALICE_PAL); /* PAL Alice (8374) */
- AMIGAHW_DECLARE(ALICE_NTSC); /* NTSC Alice (8374) */
- AMIGAHW_DECLARE(MAGIC_REKICK); /* A3000 Magic Hard Rekick */
- AMIGAHW_DECLARE(ZORRO); /* Zorro AutoConfig */
- } hw_present;
-};
-
-#else /* __ASSEMBLY__ */
-
-BI_amiga_model = BI_un
-BI_amiga_num_autcon = BI_amiga_model+4
-BI_amiga_autocon = BI_amiga_num_autcon+4
-#ifdef HACKER_KERNEL
-BI_amiga_exit_func = BI_amiga_autocon+(CD_sizeof*NUM_AUTO)
-BI_amiga_chip_addr = BI_amiga_exit_func+4
-BI_amiga_chip_size = BI_amiga_chip_addr+4
-#else
-BI_amiga_chip_size = BI_amiga_autocon+(CD_sizeof*NUM_AUTO)
-#endif
-BI_amiga_vblank = BI_amiga_chip_size+4
-BI_amiga_psfreq = BI_amiga_vblank+1
-BI_amiga_eclock = BI_amiga_psfreq+1
-BI_amiga_chipset = BI_amiga_eclock+4
-BI_amiga_hw_present = BI_amiga_chipset+4
-
-#endif /* __ASSEMBLY__ */
-
-/* Atari specific part of bootinfo */
-
-/*
- * Define several Hardware-Chips for indication so that for the ATARI we do
- * no longer decide whether it is a Falcon or other machine . It's just
- * important what hardware the machine uses
- */
-
-/* ++roman 08/08/95: rewritten from ORing constants to a C bitfield */
-
-#ifndef __ASSEMBLY__
-
-#define ATARIHW_DECLARE(name) unsigned name : 1
-#define ATARIHW_SET(name) (boot_info.bi_atari.hw_present.name = 1)
-#define ATARIHW_PRESENT(name) (boot_info.bi_atari.hw_present.name)
-
-struct bi_Atari {
- struct {
- /* video hardware */
- ATARIHW_DECLARE(STND_SHIFTER); /* ST-Shifter - no base low ! */
- ATARIHW_DECLARE(EXTD_SHIFTER); /* STe-Shifter - 24 bit address */
- ATARIHW_DECLARE(TT_SHIFTER); /* TT-Shifter */
- ATARIHW_DECLARE(VIDEL_SHIFTER); /* Falcon-Shifter */
- /* sound hardware */
- ATARIHW_DECLARE(YM_2149); /* Yamaha YM 2149 */
- ATARIHW_DECLARE(PCM_8BIT); /* PCM-Sound in STe-ATARI */
- ATARIHW_DECLARE(CODEC); /* CODEC Sound (Falcon) */
- /* disk storage interfaces */
- ATARIHW_DECLARE(TT_SCSI); /* Directly mapped NCR5380 */
- ATARIHW_DECLARE(ST_SCSI); /* NCR5380 via ST-DMA (Falcon) */
- ATARIHW_DECLARE(ACSI); /* Standard ACSI like in STs */
- ATARIHW_DECLARE(IDE); /* IDE Interface */
- ATARIHW_DECLARE(FDCSPEED); /* 8/16 MHz switch for FDC */
- /* other I/O hardware */
- ATARIHW_DECLARE(ST_MFP); /* The ST-MFP (there should
- be no Atari without
- it... but who knows?) */
- ATARIHW_DECLARE(TT_MFP); /* 2nd MFP */
- ATARIHW_DECLARE(SCC); /* Serial Communications Contr. */
- ATARIHW_DECLARE(ST_ESCC); /* SCC Z83230 in an ST */
- ATARIHW_DECLARE(ANALOG_JOY); /* Paddle Interface for STe
- and Falcon */
- ATARIHW_DECLARE(MICROWIRE); /* Microwire Interface */
- /* DMA */
- ATARIHW_DECLARE(STND_DMA); /* 24 Bit limited ST-DMA */
- ATARIHW_DECLARE(EXTD_DMA); /* 32 Bit ST-DMA */
- ATARIHW_DECLARE(SCSI_DMA); /* DMA for the NCR5380 */
- ATARIHW_DECLARE(SCC_DMA); /* DMA for the SCC */
- /* real time clocks */
- ATARIHW_DECLARE(TT_CLK); /* TT compatible clock chip */
- ATARIHW_DECLARE(MSTE_CLK); /* Mega ST(E) clock chip */
- /* supporting hardware */
- ATARIHW_DECLARE(SCU); /* System Control Unit */
- ATARIHW_DECLARE(BLITTER); /* Blitter */
- ATARIHW_DECLARE(VME); /* VME Bus */
- } hw_present;
- unsigned long mch_cookie; /* _MCH cookie from TOS */
-};
-
-/* mch_cookie values (upper word) */
-#define ATARI_MCH_ST 0
-#define ATARI_MCH_STE 1
-#define ATARI_MCH_TT 2
-#define ATARI_MCH_FALCON 3
-
-struct mem_info {
- unsigned long addr; /* physical address of memory chunk */
- unsigned long size; /* length of memory chunk (in bytes) */
-};
-
-#else /* __ASSEMBLY__ */
-
-MI_addr = 0
-MI_size = MI_addr+4
-MI_sizeof = MI_size+4
-
-#endif /* __ASSEMBLY__ */
-
-#define NUM_MEMINFO 4
-
-#define MACH_AMIGA 1
-#define MACH_ATARI 2
-#define MACH_MAC 3
-
-/*
- * CPU and FPU types
- */
-
-#define CPUB_68020 0
-#define CPUB_68030 1
-#define CPUB_68040 2
-#define CPUB_68060 3
-#define FPUB_68881 5
-#define FPUB_68882 6
-#define FPUB_68040 7 /* Internal FPU */
-#define FPUB_68060 8 /* Internal FPU */
-
-#define CPU_68020 (1<<CPUB_68020)
-#define CPU_68030 (1<<CPUB_68030)
-#define CPU_68040 (1<<CPUB_68040)
-#define CPU_68060 (1<<CPUB_68060)
-#define CPU_MASK (31)
-#define FPU_68881 (1<<FPUB_68881)
-#define FPU_68882 (1<<FPUB_68882)
-#define FPU_68040 (1<<FPUB_68040) /* Internal FPU */
-#define FPU_68060 (1<<FPUB_68060) /* Internal FPU */
-#define FPU_MASK (0xfe0)
-
-#define CL_SIZE (256)
-
-/*
- * machine type definitions
- */
-
-#if !defined(CONFIG_AMIGA)
-# define MACH_IS_AMIGA (0)
-#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
-# define MACH_IS_AMIGA (boot_info.machtype == MACH_AMIGA)
-#else
-# define CONFIG_AMIGA_ONLY
-# define MACH_IS_AMIGA (1)
-# define MACH_TYPE (MACH_AMIGA)
-#endif
-
-#if !defined(CONFIG_ATARI)
-# define MACH_IS_ATARI (0)
-#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
-# define MACH_IS_ATARI (boot_info.machtype == MACH_ATARI)
-#else
-# define CONFIG_ATARI_ONLY
-# define MACH_IS_ATARI (1)
-# define MACH_TYPE (MACH_ATARI)
-#endif
-
-#if defined(CONFIG_MAC)
-# error Currently no Mac support!
-#endif
-
-#ifndef MACH_TYPE
-# define MACH_TYPE (boot_info.machtype)
-#endif
-
-/*
- * cpu type definitions
- */
-
-#if !defined(CONFIG_M68020)
-# define CPU_IS_020 (0)
-#elif defined(CONFIG_M68030) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
-# define CPU_IS_020 (boot_info.cputype & CPU_68020)
-#else
-# define CONFIG_M68020_ONLY
-# define CPU_IS_020 (1)
-#endif
-
-#if !defined(CONFIG_M68030)
-# define CPU_IS_030 (0)
-#elif defined(CONFIG_M68020) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
-# define CPU_IS_030 (boot_info.cputype & CPU_68030)
-#else
-# define CONFIG_M68030_ONLY
-# define CPU_IS_030 (1)
-#endif
-
-#if !defined(CONFIG_M68040)
-# define CPU_IS_040 (0)
-#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68060)
-# define CPU_IS_040 (boot_info.cputype & CPU_68040)
-#else
-# define CONFIG_M68040_ONLY
-# define CPU_IS_040 (1)
-#endif
-
-#if !defined(CONFIG_M68060)
-# define CPU_IS_060 (0)
-#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68040)
-# define CPU_IS_060 (boot_info.cputype & CPU_68060)
-#else
-# define CONFIG_M68060_ONLY
-# define CPU_IS_060 (1)
-#endif
-
-#if !defined(CONFIG_M68020) && !defined(CONFIG_M68030)
-# define CPU_IS_020_OR_030 (0)
-#else
-# define CONFIG_M68020_OR_M68030
-# if defined(CONFIG_M68040) || defined(CONFIG_M68060)
-# define CPU_IS_020_OR_030 (!m68k_is040or060)
-# else
-# define CONFIG_M68020_OR_M68030_ONLY
-# define CPU_IS_020_OR_030 (1)
-# endif
-#endif
-
-#if !defined(CONFIG_M68040) && !defined(CONFIG_M68060)
-# define CPU_IS_040_OR_060 (0)
-#else
-# define CONFIG_M68040_OR_M68060
-# if defined(CONFIG_M68020) || defined(CONFIG_M68030)
-# define CPU_IS_040_OR_060 (m68k_is040or060)
-# else
-# define CONFIG_M68040_OR_M68060_ONLY
-# define CPU_IS_040_OR_060 (1)
-# endif
-#endif
-
-#define CPU_TYPE (boot_info.cputype)
-
-#ifndef __ASSEMBLY__
-#ifdef __KERNEL__
- /*
- * m68k_is040or060 is != 0 for a '040 or higher;
- * used numbers are 4 for 68040 and 6 for 68060.
- */
-
-extern int m68k_is040or060;
-#endif
-
-struct bootinfo {
- unsigned long machtype; /* machine type */
- unsigned long cputype; /* system CPU & FPU */
- struct mem_info memory[NUM_MEMINFO]; /* memory description */
- int num_memory; /* # of memory blocks found */
- unsigned long ramdisk_size; /* ramdisk size in 1024 byte blocks */
- unsigned long ramdisk_addr; /* address of the ram disk in mem */
- char command_line[CL_SIZE]; /* kernel command line parameters */
- union {
- struct bi_Amiga bi_ami; /* Amiga specific information */
- struct bi_Atari bi_ata; /* Atari specific information */
- } bi_un;
-};
-#define bi_amiga bi_un.bi_ami
-#define bi_atari bi_un.bi_ata
-#define bi_mac bi_un.bi_mac
-
-extern struct bootinfo
- boot_info;
-
-#else /* __ASSEMBLY__ */
-
-BI_machtype = 0
-BI_cputype = BI_machtype+4
-BI_memory = BI_cputype+4
-BI_num_memory = BI_memory+(MI_sizeof*NUM_MEMINFO)
-BI_ramdisk_size = BI_num_memory+4
-BI_ramdisk_addr = BI_ramdisk_size+4
-BI_command_line = BI_ramdisk_addr+4
-BI_un = BI_command_line+CL_SIZE
-
-#endif /* __ASSEMBLY__ */
-
-
-/*
- * Stuff for bootinfo interface versioning
- *
- * At the start of kernel code, a 'struct bootversion' is located. bootstrap
- * checks for a matching version of the interface before booting a kernel, to
- * avoid user confusion if kernel and bootstrap don't work together :-)
- *
- * If incompatible changes are made to the bootinfo interface, the major
- * number below should be stepped (and the minor reset to 0) for the
- * appropriate machine. If a change is backward-compatible, the minor should
- * be stepped. "Backwards-compatible" means that booting will work, but
- * certain features may not.
- */
-
-#define BOOTINFOV_MAGIC 0x4249561A /* 'BIV^Z' */
-#define MK_BI_VERSION(major,minor) (((major)<<16)+(minor))
-#define BI_VERSION_MAJOR(v) (((v) >> 16) & 0xffff)
-#define BI_VERSION_MINOR(v) ((v) & 0xffff)
-
-#ifndef __ASSEMBLY__
-
-struct bootversion {
- unsigned short branch;
- unsigned long magic;
- struct {
- unsigned long machtype;
- unsigned long version;
- } machversions[0];
-};
-
-#endif /* __ASSEMBLY__ */
-
-#define AMIGA_BOOTI_VERSION MK_BI_VERSION( 1, 0 )
-#define ATARI_BOOTI_VERSION MK_BI_VERSION( 1, 0 )
-
-#endif
-
-
-#endif /* _M68K_SETUP_H */
diff --git a/include/asm-cris/signal.h b/include/asm-cris/signal.h
index bd6f9484dbfc..1335bf27d8e2 100644
--- a/include/asm-cris/signal.h
+++ b/include/asm-cris/signal.h
@@ -85,13 +85,13 @@ typedef unsigned long sigset_t;
* Unix names RESETHAND and NODEFER respectively.
*/
-#define SA_NOCLDSTOP 0x00000001
-#define SA_NOCLDWAIT 0x00000002
-#define SA_SIGINFO 0x00000004
-#define SA_ONSTACK 0x08000000
-#define SA_RESTART 0x10000000
-#define SA_NODEFER 0x40000000
-#define SA_RESETHAND 0x80000000
+#define SA_NOCLDSTOP 0x00000001u
+#define SA_NOCLDWAIT 0x00000002u
+#define SA_SIGINFO 0x00000004u
+#define SA_ONSTACK 0x08000000u
+#define SA_RESTART 0x10000000u
+#define SA_NODEFER 0x40000000u
+#define SA_RESETHAND 0x80000000u
#define SA_NOMASK SA_NODEFER
#define SA_ONESHOT SA_RESETHAND
diff --git a/include/asm-cris/smp_lock.h b/include/asm-cris/smp_lock.h
deleted file mode 100644
index 085543014cd5..000000000000
--- a/include/asm-cris/smp_lock.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef __CRIS_SMPLOCK_H
-#define __CRIS_SMPLOCK_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_SMP
-
-#error "SMP is not supported for CRIS"
-
-/*
- * Locking the kernel
- */
-
-extern __inline void lock_kernel(void)
-{
- unsigned long flags;
- int proc = smp_processor_id();
-
- save_flags(flags);
- cli();
- /* set_bit works atomic in SMP machines */
- while(set_bit(0, (void *)&kernel_flag))
- {
- /*
- * We just start another level if we have the lock
- */
- if (proc == active_kernel_processor)
- break;
- do
- {
-#ifdef __SMP_PROF__
- smp_spins[smp_processor_id()]++;
-#endif
- /*
- * Doing test_bit here doesn't lock the bus
- */
- if (test_bit(proc, (void *)&smp_invalidate_needed))
- if (clear_bit(proc, (void *)&smp_invalidate_needed))
- local_flush_tlb();
- }
- while(test_bit(0, (void *)&kernel_flag));
- }
- /*
- * We got the lock, so tell the world we are here and increment
- * the level counter
- */
- active_kernel_processor = proc;
- kernel_counter++;
- restore_flags(flags);
-}
-
-extern __inline void unlock_kernel(void)
-{
- unsigned long flags;
- save_flags(flags);
- cli();
- /*
- * If it's the last level we have in the kernel, then
- * free the lock
- */
- if (kernel_counter == 0)
- panic("Kernel counter wrong.\n"); /* FIXME: Why is kernel_counter sometimes 0 here? */
-
- if(! --kernel_counter)
- {
- active_kernel_processor = NO_PROC_ID;
- clear_bit(0, (void *)&kernel_flag);
- }
- restore_flags(flags);
-}
-
-#endif
-#endif
diff --git a/include/asm-cris/sync_serial.h b/include/asm-cris/sync_serial.h
deleted file mode 100644
index 423b46175e5d..000000000000
--- a/include/asm-cris/sync_serial.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * ioctl defines for synchrnous serial port driver
- *
- * Copyright (c) 2001 Axis Communications AB
- *
- * Author: Mikael Starvik
- *
- */
-
-#ifndef SYNC_SERIAL_H
-#define SYNC_SERIAL_H
-
-#include <linux/ioctl.h>
-
-#define SSP_SPEED _IOR('S', 0, unsigned int)
-#define SSP_MODE _IOR('S', 1, unsigned int)
-#define SSP_FRAME_SYNC _IOR('S', 2, unsigned int)
-#define SSP_IPOLARITY _IOR('S', 3, unsigned int)
-#define SSP_OPOLARITY _IOR('S', 4, unsigned int)
-#define SSP_SPI _IOR('S', 5, unsigned int)
-
-/* Values for SSP_SPEED */
-#define SSP150 0
-#define SSP300 1
-#define SSP600 2
-#define SSP1200 3
-#define SSP2400 4
-#define SSP4800 5
-#define SSP9600 6
-#define SSP19200 7
-#define SSP28800 8
-#define SSP57600 9
-#define SSP115200 10
-#define SSP230400 11
-#define SSP460800 12
-#define SSP921600 13
-#define SSP3125000 14
-#define CODEC 15
-
-#define FREQ_4MHz 0
-#define FREQ_2MHz 1
-#define FREQ_1MHz 2
-#define FREQ_512kHz 3
-#define FREQ_256kHz 4
-#define FREQ_128kHz 5
-#define FREQ_64kHz 6
-#define FREQ_32kHz 7
-
-/* Used by application to set CODEC divider, word rate and frame rate */
-#define CODEC_VAL(freq, word, frame) (CODEC | (freq << 8) | (word << 16) | (frame << 28))
-
-/* Used by driver to extract speed */
-#define GET_SPEED(x) (x & 0xff)
-#define GET_FREQ(x) ((x & 0xff00) >> 8)
-#define GET_WORD_RATE(x) (((x & 0x0fff0000) >> 16) - 1)
-#define GET_FRAME_RATE(x) (((x & 0xf0000000) >> 28) - 1)
-
-/* Values for SSP_MODE */
-#define MASTER_OUTPUT 0
-#define SLAVE_OUTPUT 1
-#define MASTER_INPUT 2
-#define SLAVE_INPUT 3
-#define MASTER_BIDIR 4
-#define SLAVE_BIDIR 5
-
-/* Values for SSP_FRAME_SYNC */
-#define NORMAL_SYNC 1
-#define EARLY_SYNC 2
-#define BIT_SYNC 4
-#define WORD_SYNC 8
-#define EXTENDED_SYNC 0x10
-#define SYNC_OFF 0x20
-#define SYNC_ON 0x40
-#define WORD_SIZE_8 0x80
-#define WORD_SIZE_12 0x100
-#define WORD_SIZE_16 0x200
-#define WORD_SIZE_24 0x300
-#define WORD_SIZE_32 0x800
-#define BIT_ORDER_LSB 0x1000
-#define BIT_ORDER_MSB 0x2000
-#define FLOW_CONTROL_ENABLE 0x4000
-#define FLOW_CONTROL_DISABLE 0x8000
-#define CLOCK_GATED 0x10000
-#define CLOCK_NOT_GATED 0x20000
-
-/* Values for SSP_IPOLARITY and SSP_OPOLARITY */
-#define CLOCK_NORMAL 1
-#define CLOCK_INVERT 2
-#define FRAME_NORMAL 4
-#define FRAME_INVERT 8
-#define STATUS_NORMAL 0x10
-#define STATUS_INVERT 0x20
-
-/* Values for SSP_SPI */
-#define SPI_MASTER 0
-#define SPI_SLAVE 1
-#endif
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h
index 63d2dee8172e..f9cf80262574 100644
--- a/include/asm-cris/system.h
+++ b/include/asm-cris/system.h
@@ -1,9 +1,7 @@
#ifndef __ASM_CRIS_SYSTEM_H
#define __ASM_CRIS_SYSTEM_H
-#include <linux/config.h>
-
-#include <asm/segment.h>
+#include <asm/arch/system.h>
/* the switch_to macro calls resume, an asm function in entry.S which does the actual
* task switching.
@@ -14,117 +12,42 @@ extern struct task_struct *resume(struct task_struct *prev, struct task_struct *
#define switch_to(prev,next,last) last = resume(prev,next, \
(int)&((struct task_struct *)0)->thread)
-/* read the CPU version register */
-
-static inline unsigned long rdvr(void) {
- unsigned char vr;
- __asm__ volatile ("move $vr,%0" : "=rm" (vr));
- return vr;
-}
-
-/* read/write the user-mode stackpointer */
-
-static inline unsigned long rdusp(void) {
- unsigned long usp;
- __asm__ __volatile__("move $usp,%0" : "=rm" (usp));
- return usp;
-}
-
-#define wrusp(usp) \
- __asm__ __volatile__("move %0,$usp" : /* no outputs */ : "rm" (usp))
-
-/* read the current stackpointer */
-
-static inline unsigned long rdsp(void) {
- unsigned long sp;
- __asm__ __volatile__("move.d $sp,%0" : "=rm" (sp));
- return sp;
-}
-
-static inline unsigned long _get_base(char * addr)
-{
- return 0;
-}
-
-#define nop() __asm__ __volatile__ ("nop");
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
+#define barrier() __asm__ __volatile__("": : :"memory")
+#define mb() barrier()
+#define rmb() mb()
+#define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-#if 0
-/* use these and an oscilloscope to see the fraction of time we're running with IRQ's disabled */
-/* it assumes the LED's are on port 0x90000000 of course. */
-#define sti() __asm__ __volatile__ ( "ei\n\tpush $r0\n\tmoveq 0,$r0\n\tmove.d $r0,[0x90000000]\n\tpop $r0" );
-#define cli() __asm__ __volatile__ ( "di\n\tpush $r0\n\tmove.d 0x40000,$r0\n\tmove.d $r0,[0x90000000]\n\tpop $r0");
-#define save_flags(x) __asm__ __volatile__ ("move $ccr,%0" : "=rm" (x) : : "memory");
-#define restore_flags(x) __asm__ __volatile__ ("move %0,$ccr\n\tbtstq 5,%0\n\tbpl 1f\n\tnop\n\tpush $r0\n\tmoveq 0,$r0\n\tmove.d $r0,[0x90000000]\n\tpop $r0\n1:\n" : : "r" (x) : "memory");
+#ifdef CONFIG_SMP
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#define smp_read_barrier_depends() read_barrier_depends()
#else
-#define local_irq_disable() __asm__ __volatile__ ( "di");
-#define local_irq_enable() __asm__ __volatile__ ( "ei" );
-#define local_save_flags(x) __asm__ __volatile__ ("move $ccr,%0" : "=rm" (x) : : "memory");
-#define local_irq_restore(x) __asm__ __volatile__ ("move %0,$ccr" : : "rm" (x) : "memory");
-
-/* For spinlocks etc */
-#define local_irq_save(x) __asm__ __volatile__ ("move $ccr,%0\n\tdi" : "=rm" (x) : : "memory");
-#define local_irq_restore(x) restore_flags(x)
-
-#define local_irq_disable() cli()
-#define local_irq_enable() sti()
-
+#define smp_mb() barrier()
+#define smp_rmb() barrier()
+#define smp_wmb() barrier()
+#define smp_read_barrier_depends() do { } while(0)
#endif
-#define cli() local_irq_disable()
-#define sti() local_irq_enable()
-#define save_flags(x) local_save_flags(x)
-#define restore_flags(x) local_irq_restore(x)
-#define save_and_cli(x) do { local_save_flags(x); cli(); } while(0)
+#define iret()
-static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
+
+extern inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
/* since Etrax doesn't have any atomic xchg instructions, we need to disable
irq's (if enabled) and do it with move.d's */
-#if 0
- unsigned int flags;
- save_flags(flags); /* save flags, including irq enable bit */
- cli(); /* shut off irq's */
- switch (size) {
- case 1:
- __asm__ __volatile__ (
- "move.b %0,r0\n\t"
- "move.b %1,%0\n\t"
- "move.b r0,%1\n\t"
- : "=r" (x)
- : "m" (*__xg(ptr)), "r" (x)
- : "memory","r0");
- break;
- case 2:
- __asm__ __volatile__ (
- "move.w %0,r0\n\t"
- "move.w %1,%0\n\t"
- "move.w r0,%1\n\t"
- : "=r" (x)
- : "m" (*__xg(ptr)), "r" (x)
- : "memory","r0");
- break;
- case 4:
- __asm__ __volatile__ (
- "move.d %0,r0\n\t"
- "move.d %1,%0\n\t"
- "move.d r0,%1\n\t"
- : "=r" (x)
- : "m" (*__xg(ptr)), "r" (x)
- : "memory","r0");
- break;
- }
- restore_flags(flags); /* restore irq enable bit */
- return x;
-#else
unsigned long flags,temp;
- save_flags(flags); /* save flags, including irq enable bit */
- cli(); /* shut off irq's */
+ local_save_flags(flags); /* save flags, including irq enable bit */
+ local_irq_disable(); /* shut off irq's */
switch (size) {
case 1:
*((unsigned char *)&temp) = x;
@@ -142,37 +65,8 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
*(unsigned long *)ptr = temp;
break;
}
- restore_flags(flags); /* restore irq enable bit */
+ local_irq_restore(flags); /* restore irq enable bit */
return x;
-#endif
}
-#define mb() __asm__ __volatile__ ("" : : : "memory")
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while(0)
-#endif
-
-#define iret()
-
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-void disable_hlt(void);
-void enable_hlt(void);
-
#endif
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index cea712a634f1..4f35a7d95443 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -88,6 +88,30 @@ struct termios {
#define FF1 0100000
/* c_cflag bit meaning */
+/*
+ * 3 2 1
+ * 10 987 654 321 098 765 432 109 876 543 210
+ * | | ||| CBAUD
+ * obaud
+ *
+ * ||CSIZE
+ *
+ * |CSTOP
+ * |CREAD
+ * |CPARENB
+ *
+ * |CPARODD
+ * |HUPCL
+ * |CLOCAL
+ * |CBAUDEX
+ * 10 987 654 321 098 765 432 109 876 543 210
+ * | || || CIBAUD, IBSHIFT=16
+ * ibaud
+ * |CMSPAR
+ * | CRTSCTS
+ * x x xxx xxx x x xx Free bits
+ */
+
#define CBAUD 0010017
#define B0 0000000 /* hang up */
#define B50 0000001
@@ -123,11 +147,18 @@ struct termios {
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
-/* etrax100 supports these additional three baud rates */
-#define B921600 0010005
-#define B1843200 0010006
-#define B6250000 0010007
-#define CIBAUD 002003600000 /* input baud rate (not used) */
+/* etrax supports these additional three baud rates */
+#define B921600 0010005
+#define B1843200 0010006
+#define B6250000 0010007
+/* etrax 200 supports this as well */
+#define B12500000 0010010
+#define CIBAUD 002003600000 /* input baud rate */
+/* The values for CIBAUD bits are the same as the values for CBAUD and CBAUDEX
+ * shifted left IBSHIFT bits.
+ */
+#define IBSHIFT 16
+#define CMSPAR 010000000000 /* mark or space (stick) parity - PARODD=space*/
#define CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
diff --git a/include/asm-cris/termios.h b/include/asm-cris/termios.h
index cc60e3781b00..5ce1023c5d7b 100644
--- a/include/asm-cris/termios.h
+++ b/include/asm-cris/termios.h
@@ -3,6 +3,7 @@
#include <asm/termbits.h>
#include <asm/ioctls.h>
+#include <asm/rs485.h>
struct winsize {
unsigned short ws_row;
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h
new file mode 100644
index 000000000000..f191637ac9ec
--- /dev/null
+++ b/include/asm-cris/thread_info.h
@@ -0,0 +1,100 @@
+/* thread_info.h: CRIS low-level thread information
+ *
+ * Copyright (C) 2002 David Howells (dhowells@redhat.com)
+ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ *
+ * CRIS port by Axis Communications
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/processor.h>
+#include <asm/arch/thread_info.h>
+#include <asm/segment.h>
+#endif
+
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants must also be changed
+ */
+#ifndef __ASSEMBLY__
+struct thread_info {
+ struct task_struct *task; /* main task structure */
+ struct exec_domain *exec_domain; /* execution domain */
+ unsigned long flags; /* low level flags */
+ __u32 cpu; /* current CPU */
+ __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+
+ mm_segment_t addr_limit; /* thread address space:
+ 0-0xBFFFFFFF for user-thead
+ 0-0xFFFFFFFF for kernel-thread
+ */
+ struct restart_block restart_block;
+ __u8 supervisor_stack[0];
+};
+
+#endif
+
+#define PREEMPT_ACTIVE 0x4000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#ifndef __ASSEMBLY__
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .flags = 0, \
+ .cpu = 0, \
+ .preempt_count = 1, \
+ .addr_limit = KERNEL_DS, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
+}
+
+#define init_thread_info (init_thread_union.thread_info)
+
+/* thread information allocation */
+#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/include/asm-cris/timex.h b/include/asm-cris/timex.h
index 5bf3edbd6698..375c41af47de 100644
--- a/include/asm-cris/timex.h
+++ b/include/asm-cris/timex.h
@@ -3,23 +3,11 @@
*
* CRIS architecture timex specifications
*/
+
#ifndef _ASM_CRIS_TIMEX_H
#define _ASM_CRIS_TIMEX_H
-#define CLOCK_TICK_RATE 19200 /* Underlying frequency of the HZ timer */
-
-/* The timer0 values gives ~52.1us resolution (1/19200) but interrupts at HZ*/
-#define TIMER0_FREQ (CLOCK_TICK_RATE)
-#define TIMER0_CLKSEL c19k2Hz
-#define TIMER0_DIV (TIMER0_FREQ/(HZ))
-/* This is the slow one: */
-/*
-#define GET_JIFFIES_USEC() \
- ( (*R_TIMER0_DATA - TIMER0_DIV) * (1000000/HZ)/TIMER0_DIV )
-*/
-/* This is the fast version: */
-extern unsigned short cris_timer0_value_us[TIMER0_DIV+1]; /* in kernel/time.c */
-#define GET_JIFFIES_USEC() (cris_timer0_value_us[*R_TIMER0_DATA])
+#include <asm/arch/timex.h>
/*
* We don't have a cycle-counter.. but we do not support SMP anyway where this is
@@ -28,7 +16,7 @@ extern unsigned short cris_timer0_value_us[TIMER0_DIV+1]; /* in kernel/time.c */
typedef unsigned int cycles_t;
-static inline cycles_t get_cycles(void)
+extern inline cycles_t get_cycles(void)
{
return 0;
}
diff --git a/include/asm-cris/tlb.h b/include/asm-cris/tlb.h
index 69c0faa93194..6cc26debe40f 100644
--- a/include/asm-cris/tlb.h
+++ b/include/asm-cris/tlb.h
@@ -1 +1,17 @@
+#ifndef _CRIS_TLB_H
+#define _CRIS_TLB_H
+
+#include <asm/arch/tlb.h>
+
+/*
+ * cris doesn't need any special per-pte or
+ * per-vma handling..
+ */
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma) do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
+
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
#include <asm-generic/tlb.h>
+
+#endif
diff --git a/include/asm-cris/tlbflush.h b/include/asm-cris/tlbflush.h
new file mode 100644
index 000000000000..1781fe1a32f6
--- /dev/null
+++ b/include/asm-cris/tlbflush.h
@@ -0,0 +1,43 @@
+#ifndef _CRIS_TLBFLUSH_H
+#define _CRIS_TLBFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
+/*
+ * TLB flushing (implemented in arch/cris/mm/tlb.c):
+ *
+ * - flush_tlb() flushes the current mm struct TLBs
+ * - flush_tlb_all() flushes all processes TLBs
+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ * - flush_tlb_page(vma, vmaddr) flushes one page
+ * - flush_tlb_range(mm, start, end) flushes a range of pages
+ *
+ */
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long addr);
+extern void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end);
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+ /* CRIS does not keep any page table caches in TLB */
+}
+
+
+extern inline void flush_tlb(void)
+{
+ flush_tlb_mm(current->mm);
+}
+
+#define flush_tlb_kernel_range(start, end) flush_tlb_all()
+
+#endif /* _CRIS_TLBFLUSH_H */
diff --git a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h
index 41d66748c16b..7532cd76d0af 100644
--- a/include/asm-cris/uaccess.h
+++ b/include/asm-cris/uaccess.h
@@ -81,8 +81,8 @@
#define USER_DS MAKE_MM_SEG(TASK_SIZE)
#define get_ds() (KERNEL_DS)
-#define get_fs() (current->addr_limit)
-#define set_fs(x) (current->addr_limit = (x))
+#define get_fs() (current_thread_info()->addr_limit)
+#define set_fs(x) (current_thread_info()->addr_limit = (x))
#define segment_eq(a,b) ((a).seg == (b).seg)
@@ -91,12 +91,14 @@
#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
-extern inline int verify_area(int type, const void * addr, unsigned long size)
+extern inline int verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
+#include <asm/arch/uaccess.h>
+
/*
* The exception table consists of pairs of addresses: the first is the
* address of an instruction that is allowed to fault, and the second is
@@ -115,10 +117,6 @@ struct exception_table_entry
unsigned long insn, fixup;
};
-/* Returns 0 if exception not found and fixup otherwise. */
-extern unsigned long search_exception_table(unsigned long);
-
-
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
@@ -149,6 +147,30 @@ extern unsigned long search_exception_table(unsigned long);
extern long __put_user_bad(void);
+#define __put_user_size(x,ptr,size,retval) \
+do { \
+ retval = 0; \
+ switch (size) { \
+ case 1: __put_user_asm(x,ptr,retval,"move.b"); break; \
+ case 2: __put_user_asm(x,ptr,retval,"move.w"); break; \
+ case 4: __put_user_asm(x,ptr,retval,"move.d"); break; \
+ case 8: __put_user_asm_64(x,ptr,retval); break; \
+ default: __put_user_bad(); \
+ } \
+} while (0)
+
+#define __get_user_size(x,ptr,size,retval) \
+do { \
+ retval = 0; \
+ switch (size) { \
+ case 1: __get_user_asm(x,ptr,retval,"move.b"); break; \
+ case 2: __get_user_asm(x,ptr,retval,"move.w"); break; \
+ case 4: __get_user_asm(x,ptr,retval,"move.d"); break; \
+ case 8: __get_user_asm_64(x,ptr,retval); break; \
+ default: (x) = __get_user_bad(); \
+ } \
+} while (0)
+
#define __put_user_nocheck(x,ptr,size) \
({ \
long __pu_err; \
@@ -165,58 +187,9 @@ extern long __put_user_bad(void);
__pu_err; \
})
-#define __put_user_size(x,ptr,size,retval) \
-do { \
- retval = 0; \
- switch (size) { \
- case 1: __put_user_asm(x,ptr,retval,"move.b"); break; \
- case 2: __put_user_asm(x,ptr,retval,"move.w"); break; \
- case 4: __put_user_asm(x,ptr,retval,"move.d"); break; \
- case 8: __put_user_asm_64(x,ptr,retval); break; \
- default: __put_user_bad(); \
- } \
-} while (0)
-
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
-/*
- * We don't tell gcc that we are accessing memory, but this is OK
- * because we do not write to any memory gcc knows about, so there
- * are no aliasing issues.
- *
- * Note that PC at a fault is the address *after* the faulting
- * instruction.
- */
-#define __put_user_asm(x, addr, err, op) \
- __asm__ __volatile__( \
- " "op" %1,[%2]\n" \
- "2:\n" \
- " .section .fixup,\"ax\"\n" \
- "3: move.d %3,%0\n" \
- " jump 2b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .dword 2b,3b\n" \
- " .previous\n" \
- : "=r" (err) \
- : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
-
-#define __put_user_asm_64(x, addr, err) \
- __asm__ __volatile__( \
- " move.d %M1,[%2]\n" \
- "2: move.d %H1,[%2+4]\n" \
- "4:\n" \
- " .section .fixup,\"ax\"\n" \
- "3: move.d %3,%0\n" \
- " jump 4b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .dword 2b,3b\n" \
- " .dword 4b,3b\n" \
- " .previous\n" \
- : "=r" (err) \
- : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
#define __get_user_nocheck(x,ptr,size) \
@@ -239,52 +212,6 @@ struct __large_struct { unsigned long buf[100]; };
extern long __get_user_bad(void);
-#define __get_user_size(x,ptr,size,retval) \
-do { \
- retval = 0; \
- switch (size) { \
- case 1: __get_user_asm(x,ptr,retval,"move.b"); break; \
- case 2: __get_user_asm(x,ptr,retval,"move.w"); break; \
- case 4: __get_user_asm(x,ptr,retval,"move.d"); break; \
- case 8: __get_user_asm_64(x,ptr,retval); break; \
- default: (x) = __get_user_bad(); \
- } \
-} while (0)
-
-/* See comment before __put_user_asm. */
-
-#define __get_user_asm(x, addr, err, op) \
- __asm__ __volatile__( \
- " "op" [%2],%1\n" \
- "2:\n" \
- " .section .fixup,\"ax\"\n" \
- "3: move.d %3,%0\n" \
- " moveq 0,%1\n" \
- " jump 2b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .dword 2b,3b\n" \
- " .previous\n" \
- : "=r" (err), "=r" (x) \
- : "r" (addr), "g" (-EFAULT), "0" (err))
-
-#define __get_user_asm_64(x, addr, err) \
- __asm__ __volatile__( \
- " move.d [%2],%M1\n" \
- "2: move.d [%2+4],%H1\n" \
- "4:\n" \
- " .section .fixup,\"ax\"\n" \
- "3: move.d %3,%0\n" \
- " moveq 0,%1\n" \
- " jump 4b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .dword 2b,3b\n" \
- " .dword 4b,3b\n" \
- " .previous\n" \
- : "=r" (err), "=r" (x) \
- : "r" (addr), "g" (-EFAULT), "0" (err))
-
/* More complex functions. Most are inline, but some call functions that
live in lib/usercopy.c */
@@ -292,108 +219,38 @@ extern unsigned long __copy_user(void *to, const void *from, unsigned long n);
extern unsigned long __copy_user_zeroing(void *to, const void *from, unsigned long n);
extern unsigned long __do_clear_user(void *to, unsigned long n);
-/*
- * Copy a null terminated string from userspace.
- *
- * Must return:
- * -EFAULT for an exception
- * count if we hit the buffer limit
- * bytes copied if we hit a null byte
- * (without the null byte)
- */
-
-static inline long
-__do_strncpy_from_user(char *dst, const char *src, long count)
-{
- long res;
-
- if (count == 0)
- return 0;
-
- /*
- * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
- * So do we.
- *
- * This code is deduced from:
- *
- * char tmp2;
- * long tmp1, tmp3
- * tmp1 = count;
- * while ((*dst++ = (tmp2 = *src++)) != 0
- * && --tmp1)
- * ;
- *
- * res = count - tmp1;
- *
- * with tweaks.
- */
-
- __asm__ __volatile__ (
- " move.d %3,%0\n"
- " move.b [%2+],$r9\n"
- "1: beq 2f\n"
- " move.b $r9,[%1+]\n"
-
- " subq 1,%0\n"
- " bne 1b\n"
- " move.b [%2+],$r9\n"
-
- "2: sub.d %3,%0\n"
- " neg.d %0,%0\n"
- "3:\n"
- " .section .fixup,\"ax\"\n"
- "4: move.d %7,%0\n"
- " jump 3b\n"
-
- /* There's one address for a fault at the first move, and
- two possible PC values for a fault at the second move,
- being a delay-slot filler. However, the branch-target
- for the second move is the same as the first address.
- Just so you don't get confused... */
- " .previous\n"
- " .section __ex_table,\"a\"\n"
- " .dword 1b,4b\n"
- " .dword 2b,4b\n"
- " .previous"
- : "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
- : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
- : "r9");
-
- return res;
-}
-
-static inline unsigned long
-__generic_copy_to_user(void *to, const void *from, unsigned long n)
+extern inline unsigned long
+__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
return __copy_user(to,from,n);
return n;
}
-static inline unsigned long
-__generic_copy_from_user(void *to, const void *from, unsigned long n)
+extern inline unsigned long
+__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
return __copy_user_zeroing(to,from,n);
return n;
}
-static inline unsigned long
-__generic_clear_user(void *to, unsigned long n)
+extern inline unsigned long
+__generic_clear_user(void __user *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
return __do_clear_user(to,n);
return n;
}
-static inline long
-__strncpy_from_user(char *dst, const char *src, long count)
+extern inline long
+__strncpy_from_user(char *dst, const char __user *src, long count)
{
return __do_strncpy_from_user(dst, src, count);
}
-static inline long
-strncpy_from_user(char *dst, const char *src, long count)
+extern inline long
+strncpy_from_user(char *dst, const char __user *src, long count)
{
long res = -EFAULT;
if (access_ok(VERIFY_READ, src, 1))
@@ -401,459 +258,12 @@ strncpy_from_user(char *dst, const char *src, long count)
return res;
}
-/* A few copy asms to build up the more complex ones from.
-
- Note again, a post-increment is performed regardless of whether a bus
- fault occurred in that instruction, and PC for a faulted insn is the
- address *after* the insn. */
-
-#define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm__ __volatile__ ( \
- COPY \
- "1:\n" \
- " .section .fixup,\"ax\"\n" \
- FIXUP \
- " jump 1b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- TENTRY \
- " .previous\n" \
- : "=r" (to), "=r" (from), "=r" (ret) \
- : "0" (to), "1" (from), "2" (ret) \
- : "r9", "memory")
-
-#define __asm_copy_from_user_1(to, from, ret) \
- __asm_copy_user_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "2: move.b $r9,[%0+]\n", \
- "3: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 2b,3b\n")
-
-#define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_user_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- "2: move.w $r9,[%0+]\n" COPY, \
- "3: addq 2,%2\n" \
- " clear.w [%0+]\n" FIXUP, \
- " .dword 2b,3b\n" TENTRY)
-
-#define __asm_copy_from_user_2(to, from, ret) \
- __asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_3(to, from, ret) \
- __asm_copy_from_user_2x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "4: move.b $r9,[%0+]\n", \
- "5: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 4b,5b\n")
-
-#define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_user_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- "2: move.d $r9,[%0+]\n" COPY, \
- "3: addq 4,%2\n" \
- " clear.d [%0+]\n" FIXUP, \
- " .dword 2b,3b\n" TENTRY)
-
-#define __asm_copy_from_user_4(to, from, ret) \
- __asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_5(to, from, ret) \
- __asm_copy_from_user_4x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "4: move.b $r9,[%0+]\n", \
- "5: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 4b,5b\n")
-
-#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_4x_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- "4: move.w $r9,[%0+]\n" COPY, \
- "5: addq 2,%2\n" \
- " clear.w [%0+]\n" FIXUP, \
- " .dword 4b,5b\n" TENTRY)
-
-#define __asm_copy_from_user_6(to, from, ret) \
- __asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_7(to, from, ret) \
- __asm_copy_from_user_6x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "6: move.b $r9,[%0+]\n", \
- "7: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 6b,7b\n")
-
-#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_4x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- "4: move.d $r9,[%0+]\n" COPY, \
- "5: addq 4,%2\n" \
- " clear.d [%0+]\n" FIXUP, \
- " .dword 4b,5b\n" TENTRY)
-
-#define __asm_copy_from_user_8(to, from, ret) \
- __asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_9(to, from, ret) \
- __asm_copy_from_user_8x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "6: move.b $r9,[%0+]\n", \
- "7: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 6b,7b\n")
-
-#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_8x_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- "6: move.w $r9,[%0+]\n" COPY, \
- "7: addq 2,%2\n" \
- " clear.w [%0+]\n" FIXUP, \
- " .dword 6b,7b\n" TENTRY)
-
-#define __asm_copy_from_user_10(to, from, ret) \
- __asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_11(to, from, ret) \
- __asm_copy_from_user_10x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "8: move.b $r9,[%0+]\n", \
- "9: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 8b,9b\n")
-
-#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_8x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- "6: move.d $r9,[%0+]\n" COPY, \
- "7: addq 4,%2\n" \
- " clear.d [%0+]\n" FIXUP, \
- " .dword 6b,7b\n" TENTRY)
-
-#define __asm_copy_from_user_12(to, from, ret) \
- __asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_13(to, from, ret) \
- __asm_copy_from_user_12x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "8: move.b $r9,[%0+]\n", \
- "9: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 8b,9b\n")
-
-#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_12x_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- "8: move.w $r9,[%0+]\n" COPY, \
- "9: addq 2,%2\n" \
- " clear.w [%0+]\n" FIXUP, \
- " .dword 8b,9b\n" TENTRY)
-
-#define __asm_copy_from_user_14(to, from, ret) \
- __asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_15(to, from, ret) \
- __asm_copy_from_user_14x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- "10: move.b $r9,[%0+]\n", \
- "11: addq 1,%2\n" \
- " clear.b [%0+]\n", \
- " .dword 10b,11b\n")
-
-#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_12x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- "8: move.d $r9,[%0+]\n" COPY, \
- "9: addq 4,%2\n" \
- " clear.d [%0+]\n" FIXUP, \
- " .dword 8b,9b\n" TENTRY)
-
-#define __asm_copy_from_user_16(to, from, ret) \
- __asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_16x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- "10: move.d $r9,[%0+]\n" COPY, \
- "11: addq 4,%2\n" \
- " clear.d [%0+]\n" FIXUP, \
- " .dword 10b,11b\n" TENTRY)
-
-#define __asm_copy_from_user_20(to, from, ret) \
- __asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_from_user_20x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- "12: move.d $r9,[%0+]\n" COPY, \
- "13: addq 4,%2\n" \
- " clear.d [%0+]\n" FIXUP, \
- " .dword 12b,13b\n" TENTRY)
-
-#define __asm_copy_from_user_24(to, from, ret) \
- __asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
-
-/* And now, the to-user ones. */
-
-#define __asm_copy_to_user_1(to, from, ret) \
- __asm_copy_user_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n2:\n", \
- "3: addq 1,%2\n", \
- " .dword 2b,3b\n")
-
-#define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_user_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- " move.w $r9,[%0+]\n2:\n" COPY, \
- "3: addq 2,%2\n" FIXUP, \
- " .dword 2b,3b\n" TENTRY)
-
-#define __asm_copy_to_user_2(to, from, ret) \
- __asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_3(to, from, ret) \
- __asm_copy_to_user_2x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n4:\n", \
- "5: addq 1,%2\n", \
- " .dword 4b,5b\n")
-
-#define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_user_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- " move.d $r9,[%0+]\n2:\n" COPY, \
- "3: addq 4,%2\n" FIXUP, \
- " .dword 2b,3b\n" TENTRY)
-
-#define __asm_copy_to_user_4(to, from, ret) \
- __asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_5(to, from, ret) \
- __asm_copy_to_user_4x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n4:\n", \
- "5: addq 1,%2\n", \
- " .dword 4b,5b\n")
-
-#define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_4x_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- " move.w $r9,[%0+]\n4:\n" COPY, \
- "5: addq 2,%2\n" FIXUP, \
- " .dword 4b,5b\n" TENTRY)
-
-#define __asm_copy_to_user_6(to, from, ret) \
- __asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_7(to, from, ret) \
- __asm_copy_to_user_6x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n6:\n", \
- "7: addq 1,%2\n", \
- " .dword 6b,7b\n")
-
-#define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_4x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- " move.d $r9,[%0+]\n4:\n" COPY, \
- "5: addq 4,%2\n" FIXUP, \
- " .dword 4b,5b\n" TENTRY)
-
-#define __asm_copy_to_user_8(to, from, ret) \
- __asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_9(to, from, ret) \
- __asm_copy_to_user_8x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n6:\n", \
- "7: addq 1,%2\n", \
- " .dword 6b,7b\n")
-
-#define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_8x_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- " move.w $r9,[%0+]\n6:\n" COPY, \
- "7: addq 2,%2\n" FIXUP, \
- " .dword 6b,7b\n" TENTRY)
-
-#define __asm_copy_to_user_10(to, from, ret) \
- __asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_11(to, from, ret) \
- __asm_copy_to_user_10x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n8:\n", \
- "9: addq 1,%2\n", \
- " .dword 8b,9b\n")
-
-#define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_8x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- " move.d $r9,[%0+]\n6:\n" COPY, \
- "7: addq 4,%2\n" FIXUP, \
- " .dword 6b,7b\n" TENTRY)
-
-#define __asm_copy_to_user_12(to, from, ret) \
- __asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_13(to, from, ret) \
- __asm_copy_to_user_12x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n8:\n", \
- "9: addq 1,%2\n", \
- " .dword 8b,9b\n")
-
-#define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_12x_cont(to, from, ret, \
- " move.w [%1+],$r9\n" \
- " move.w $r9,[%0+]\n8:\n" COPY, \
- "9: addq 2,%2\n" FIXUP, \
- " .dword 8b,9b\n" TENTRY)
-
-#define __asm_copy_to_user_14(to, from, ret) \
- __asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_15(to, from, ret) \
- __asm_copy_to_user_14x_cont(to, from, ret, \
- " move.b [%1+],$r9\n" \
- " move.b $r9,[%0+]\n10:\n", \
- "11: addq 1,%2\n", \
- " .dword 10b,11b\n")
-
-#define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_12x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- " move.d $r9,[%0+]\n8:\n" COPY, \
- "9: addq 4,%2\n" FIXUP, \
- " .dword 8b,9b\n" TENTRY)
-
-#define __asm_copy_to_user_16(to, from, ret) \
- __asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_16x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- " move.d $r9,[%0+]\n10:\n" COPY, \
- "11: addq 4,%2\n" FIXUP, \
- " .dword 10b,11b\n" TENTRY)
-
-#define __asm_copy_to_user_20(to, from, ret) \
- __asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
-
-#define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
- __asm_copy_to_user_20x_cont(to, from, ret, \
- " move.d [%1+],$r9\n" \
- " move.d $r9,[%0+]\n12:\n" COPY, \
- "13: addq 4,%2\n" FIXUP, \
- " .dword 12b,13b\n" TENTRY)
-
-#define __asm_copy_to_user_24(to, from, ret) \
- __asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
-
-/* Define a few clearing asms with exception handlers. */
-
-/* This frame-asm is like the __asm_copy_user_cont one, but has one less
- input. */
-
-#define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
- __asm__ __volatile__ ( \
- CLEAR \
- "1:\n" \
- " .section .fixup,\"ax\"\n" \
- FIXUP \
- " jump 1b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- TENTRY \
- " .previous" \
- : "=r" (to), "=r" (ret) \
- : "0" (to), "1" (ret) \
- : "r9", "memory")
-
-#define __asm_clear_1(to, ret) \
- __asm_clear(to, ret, \
- " clear.b [%0+]\n2:\n", \
- "3: addq 1,%1\n", \
- " .dword 2b,3b\n")
-
-#define __asm_clear_2(to, ret) \
- __asm_clear(to, ret, \
- " clear.w [%0+]\n2:\n", \
- "3: addq 2,%1\n", \
- " .dword 2b,3b\n")
-
-#define __asm_clear_3(to, ret) \
- __asm_clear(to, ret, \
- " clear.w [%0+]\n" \
- "2: clear.b [%0+]\n3:\n", \
- "4: addq 2,%1\n" \
- "5: addq 1,%1\n", \
- " .dword 2b,4b\n" \
- " .dword 3b,5b\n")
-
-#define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
- __asm_clear(to, ret, \
- " clear.d [%0+]\n2:\n" CLEAR, \
- "3: addq 4,%1\n" FIXUP, \
- " .dword 2b,3b\n" TENTRY)
-
-#define __asm_clear_4(to, ret) \
- __asm_clear_4x_cont(to, ret, "", "", "")
-
-#define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
- __asm_clear_4x_cont(to, ret, \
- " clear.d [%0+]\n4:\n" CLEAR, \
- "5: addq 4,%1\n" FIXUP, \
- " .dword 4b,5b\n" TENTRY)
-
-#define __asm_clear_8(to, ret) \
- __asm_clear_8x_cont(to, ret, "", "", "")
-
-#define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
- __asm_clear_8x_cont(to, ret, \
- " clear.d [%0+]\n6:\n" CLEAR, \
- "7: addq 4,%1\n" FIXUP, \
- " .dword 6b,7b\n" TENTRY)
-
-#define __asm_clear_12(to, ret) \
- __asm_clear_12x_cont(to, ret, "", "", "")
-
-#define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
- __asm_clear_12x_cont(to, ret, \
- " clear.d [%0+]\n8:\n" CLEAR, \
- "9: addq 4,%1\n" FIXUP, \
- " .dword 8b,9b\n" TENTRY)
-
-#define __asm_clear_16(to, ret) \
- __asm_clear_16x_cont(to, ret, "", "", "")
-
-#define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
- __asm_clear_16x_cont(to, ret, \
- " clear.d [%0+]\n10:\n" CLEAR, \
- "11: addq 4,%1\n" FIXUP, \
- " .dword 10b,11b\n" TENTRY)
-
-#define __asm_clear_20(to, ret) \
- __asm_clear_20x_cont(to, ret, "", "", "")
-
-#define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
- __asm_clear_20x_cont(to, ret, \
- " clear.d [%0+]\n12:\n" CLEAR, \
- "13: addq 4,%1\n" FIXUP, \
- " .dword 12b,13b\n" TENTRY)
-
-#define __asm_clear_24(to, ret) \
- __asm_clear_24x_cont(to, ret, "", "", "")
/* Note that if these expand awfully if made into switch constructs, so
don't do that. */
-static inline unsigned long
-__constant_copy_from_user(void *to, const void *from, unsigned long n)
+extern inline unsigned long
+__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
{
unsigned long ret = 0;
if (n == 0)
@@ -902,8 +312,8 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n)
/* Ditto, don't make a switch out of this. */
-static inline unsigned long
-__constant_copy_to_user(void *to, const void *from, unsigned long n)
+extern inline unsigned long
+__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
{
unsigned long ret = 0;
if (n == 0)
@@ -952,8 +362,8 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n)
/* No switch, please. */
-static inline unsigned long
-__constant_clear_user(void *to, unsigned long n)
+extern inline unsigned long
+__constant_clear_user(void __user *to, unsigned long n)
{
unsigned long ret = 0;
if (n == 0)
@@ -1002,19 +412,19 @@ __constant_clear_user(void *to, unsigned long n)
* used in fast paths and have only a small space overhead.
*/
-static inline unsigned long
+extern inline unsigned long
__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
{
return __copy_user_zeroing(to,from,n);
}
-static inline unsigned long
+extern inline unsigned long
__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
{
return __copy_user(to,from,n);
}
-static inline unsigned long
+extern inline unsigned long
__generic_clear_user_nocheck(void *to, unsigned long n)
{
return __do_clear_user(to,n);
@@ -1026,68 +436,6 @@ __generic_clear_user_nocheck(void *to, unsigned long n)
#define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
#define __clear_user(to,n) __generic_clear_user_nocheck((to),(n))
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return length of string in userspace including terminating 0
- * or 0 for error. Return a value greater than N if too long.
- */
-
-static inline long
-strnlen_user(const char *s, long n)
-{
- long res, tmp1;
-
- if (!access_ok(VERIFY_READ, s, 0))
- return 0;
-
- /*
- * This code is deduced from:
- *
- * tmp1 = n;
- * while (tmp1-- > 0 && *s++)
- * ;
- *
- * res = n - tmp1;
- *
- * (with tweaks).
- */
-
- __asm__ __volatile__ (
- " move.d %1,$r9\n"
- "0:\n"
- " ble 1f\n"
- " subq 1,$r9\n"
-
- " test.b [%0+]\n"
- " bne 0b\n"
- " test.d $r9\n"
- "1:\n"
- " move.d %1,%0\n"
- " sub.d $r9,%0\n"
- "2:\n"
- " .section .fixup,\"ax\"\n"
-
- "3: clear.d %0\n"
- " jump 2b\n"
-
- /* There's one address for a fault at the first move, and
- two possible PC values for a fault at the second move,
- being a delay-slot filler. However, the branch-target
- for the second move is the same as the first address.
- Just so you don't get confused... */
- " .previous\n"
- " .section __ex_table,\"a\"\n"
- " .dword 0b,3b\n"
- " .dword 1b,3b\n"
- " .previous\n"
- : "=r" (res), "=r" (tmp1)
- : "0" (s), "1" (n)
- : "r9");
-
- return res;
-}
-
#define strlen_user(str) strnlen_user((str), 0x7ffffffe)
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index b06623932f47..4911fee80489 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -1,11 +1,13 @@
#ifndef _ASM_CRIS_UNISTD_H_
#define _ASM_CRIS_UNISTD_H_
+#include <asm/arch/unistd.h>
+
/*
* This file contains the system call numbers, and stub macros for libc.
*/
-#define __NR_setup 0 /* used only by init, to get system going */
+#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
@@ -230,125 +232,54 @@
/* 223 is unused */
#define __NR_gettid 224
#define __NR_readahead 225
-#define __NR_tkill 226
-
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
-#define _syscall0(type,name) \
-type name(void) \
-{ \
- register long __a __asm__ ("r10"); \
- __asm__ __volatile__ ("movu.w %1,$r9\n\tbreak 13" \
- : "=r" (__a) \
- : "g" (__NR_##name) \
- : "r10", "r9"); \
- if(__a >= 0) \
- return (type) __a; \
- errno = -__a; \
- return (type) -1; \
-}
-
-#define _syscall1(type,name,type1,arg1) \
-type name(type1 arg1) \
-{ \
- register long __a __asm__ ("r10") = (long) arg1; \
- __asm__ __volatile__ ("movu.w %1,$r9\n\tbreak 13" \
- : "=r" (__a) \
- : "g" (__NR_##name), "0" (__a) \
- : "r10", "r9"); \
- if(__a >= 0) \
- return (type) __a; \
- errno = -__a; \
- return (type) -1; \
-}
+#define __NR_setxattr 226
+#define __NR_lsetxattr 227
+#define __NR_fsetxattr 228
+#define __NR_getxattr 229
+#define __NR_lgetxattr 230
+#define __NR_fgetxattr 231
+#define __NR_listxattr 232
+#define __NR_llistxattr 233
+#define __NR_flistxattr 234
+#define __NR_removexattr 235
+#define __NR_lremovexattr 236
+#define __NR_fremovexattr 237
+#define __NR_tkill 238
+#define __NR_sendfile64 239
+#define __NR_futex 240
+#define __NR_sched_setaffinity 241
+#define __NR_sched_getaffinity 242
+#define __NR_set_thread_area 243
+#define __NR_get_thread_area 244
+#define __NR_io_setup 245
+#define __NR_io_destroy 246
+#define __NR_io_getevents 247
+#define __NR_io_submit 248
+#define __NR_io_cancel 249
+#define __NR_fadvise64 250
+#define __NR_exit_group 252
+#define __NR_lookup_dcookie 253
+#define __NR_epoll_create 254
+#define __NR_epoll_ctl 255
+#define __NR_epoll_wait 256
+#define __NR_remap_file_pages 257
+#define __NR_set_tid_address 258
+#define __NR_timer_create 259
+#define __NR_timer_settime (__NR_timer_create+1)
+#define __NR_timer_gettime (__NR_timer_create+2)
+#define __NR_timer_getoverrun (__NR_timer_create+3)
+#define __NR_timer_delete (__NR_timer_create+4)
+#define __NR_clock_settime (__NR_timer_create+5)
+#define __NR_clock_gettime (__NR_timer_create+6)
+#define __NR_clock_getres (__NR_timer_create+7)
+#define __NR_clock_nanosleep (__NR_timer_create+8)
+#define __NR_statfs64 268
+#define __NR_fstatfs64 269
+
+#define NR_syscalls 270
-#define _syscall2(type,name,type1,arg1,type2,arg2) \
-type name(type1 arg1,type2 arg2) \
-{ \
- register long __a __asm__ ("r10") = (long) arg1; \
- register long __b __asm__ ("r11") = (long) arg2; \
- __asm__ __volatile__ ("movu.w %1,$r9\n\tbreak 13" \
- : "=r" (__a) \
- : "g" (__NR_##name), "0" (__a), "r" (__b) \
- : "r10", "r9"); \
- if(__a >= 0) \
- return (type) __a; \
- errno = -__a; \
- return (type) -1; \
-}
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-type name(type1 arg1,type2 arg2,type3 arg3) \
-{ \
- register long __a __asm__ ("r10") = (long) arg1; \
- register long __b __asm__ ("r11") = (long) arg2; \
- register long __c __asm__ ("r12") = (long) arg3; \
- __asm__ __volatile__ ("movu.w %1,$r9\n\tbreak 13" \
- : "=r" (__a) \
- : "g" (__NR_##name), "0" (__a), "r" (__b), "r" (__c) \
- : "r10", "r9"); \
- if(__a >= 0) \
- return (type) __a; \
- errno = -__a; \
- return (type) -1; \
-}
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
- register long __a __asm__ ("r10") = (long) arg1; \
- register long __b __asm__ ("r11") = (long) arg2; \
- register long __c __asm__ ("r12") = (long) arg3; \
- register long __d __asm__ ("r13") = (long) arg4; \
- __asm__ __volatile__ ("movu.w %1,$r9\n\tbreak 13" \
- : "=r" (__a) \
- : "g" (__NR_##name), "0" (__a), "r" (__b), \
- "r" (__c), "r" (__d) \
- : "r10", "r9"); \
- if(__a >= 0) \
- return (type) __a; \
- errno = -__a; \
- return (type) -1; \
-}
-
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
- register long __a __asm__ ("r10") = (long) arg1; \
- register long __b __asm__ ("r11") = (long) arg2; \
- register long __c __asm__ ("r12") = (long) arg3; \
- register long __d __asm__ ("r13") = (long) arg4; \
- __asm__ __volatile__ ("move %6,$mof\n\t" \
- "movu.w %1,$r9\n\tbreak 13" \
- : "=r" (__a) \
- : "g" (__NR_##name), "0" (__a), "r" (__b), \
- "r" (__c), "r" (__d), "g" (arg5) \
- : "r10", "r9"); \
- if(__a >= 0) \
- return (type) __a; \
- errno = -__a; \
- return (type) -1; \
-}
-
-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5,type6,arg6) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
-{ \
- register long __a __asm__ ("r10") = (long) arg1; \
- register long __b __asm__ ("r11") = (long) arg2; \
- register long __c __asm__ ("r12") = (long) arg3; \
- register long __d __asm__ ("r13") = (long) arg4; \
- __asm__ __volatile__ ("move %6,$mof\n\tmove %7,$srp\n\t" \
- "movu.w %1,$r9\n\tbreak 13" \
- : "=r" (__a) \
- : "g" (__NR_##name), "0" (__a), "r" (__b), \
- "r" (__c), "r" (__d), "g" (arg5), "g" (arg6)\
- : "r10", "r9", "srp"); \
- if(__a >= 0) \
- return (type) __a; \
- errno = -__a; \
- return (type) -1; \
-}
#ifdef __KERNEL_SYSCALLS__
@@ -365,21 +296,28 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
* some others too.
*/
#define __NR__exit __NR_exit
-static inline _syscall0(pid_t,setsid)
-static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
-static inline _syscall1(int,dup,int,fd)
-static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
-static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
-static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
-
- /* the following are just while developing the elinux port! */
-
-static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+extern inline _syscall0(pid_t,setsid)
+extern inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+extern inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+extern inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
+extern inline _syscall1(int,dup,int,fd)
+extern inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+extern inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+extern inline _syscall1(int,close,int,fd)
+/*
+ * Since we define it "external", it collides with the built-in
+ * definition, which has the "noreturn" attribute and will cause
+ * complaints. We don't want to use -fno-builtin, so just use a
+ * different name when in the kernel.
+ */
+#ifdef __KERNEL__
+#define _exit kernel_syscall_exit
#endif
+extern inline _syscall1(int,_exit,int,exitcode)
+extern inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+#endif
+
/*
* "Conditional" syscalls
diff --git a/include/asm-cris/user.h b/include/asm-cris/user.h
index 982f4163bc94..2538e2a003df 100644
--- a/include/asm-cris/user.h
+++ b/include/asm-cris/user.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <asm/ptrace.h>
#include <asm/page.h>
+#include <asm/arch/user.h>
/*
* Core file format: The core file is written in such a way that gdb
@@ -27,49 +28,6 @@
* current->start_stack, so we round each of these in order to be able
* to write an integer number of pages.
*/
-
-/* User mode registers, used for core dumps. In order to keep ELF_NGREG
- sensible we let all registers be 32 bits. The csr registers are included
- for future use. */
-struct user_regs_struct {
- unsigned long r0; /* General registers. */
- unsigned long r1;
- unsigned long r2;
- unsigned long r3;
- unsigned long r4;
- unsigned long r5;
- unsigned long r6;
- unsigned long r7;
- unsigned long r8;
- unsigned long r9;
- unsigned long r10;
- unsigned long r11;
- unsigned long r12;
- unsigned long r13;
- unsigned long sp; /* Stack pointer. */
- unsigned long pc; /* Program counter. */
- unsigned long p0; /* Constant zero (only 8 bits). */
- unsigned long vr; /* Version register (only 8 bits). */
- unsigned long p2; /* Reserved. */
- unsigned long p3; /* Reserved. */
- unsigned long p4; /* Constant zero (only 16 bits). */
- unsigned long ccr; /* Condition code register (only 16 bits). */
- unsigned long p6; /* Reserved. */
- unsigned long mof; /* Multiply overflow register. */
- unsigned long p8; /* Constant zero. */
- unsigned long ibr; /* Not accessible. */
- unsigned long irp; /* Not accessible. */
- unsigned long srp; /* Subroutine return pointer. */
- unsigned long bar; /* Not accessible. */
- unsigned long dccr; /* Dword condition code register. */
- unsigned long brp; /* Not accessible. */
- unsigned long usp; /* User-mode stack pointer. Same as sp when
- in user mode. */
- unsigned long csrinstr; /* Internal status registers. */
- unsigned long csraddr;
- unsigned long csrdata;
-};
-
struct user {
struct user_regs_struct regs; /* entire machine state */