summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Makefile61
-rw-r--r--arch/arm/boot/Makefile5
-rw-r--r--arch/arm/boot/compressed/Makefile2
-rw-r--r--arch/arm/config.in48
-rw-r--r--arch/arm/defconfig16
-rw-r--r--arch/arm/kernel/Makefile16
-rw-r--r--arch/arm/kernel/armksyms.c28
-rw-r--r--arch/arm/kernel/bios32.c144
-rw-r--r--arch/arm/kernel/calls.S6
-rw-r--r--arch/arm/kernel/dma-a5k.c79
-rw-r--r--arch/arm/kernel/dma-arc.c115
-rw-r--r--arch/arm/kernel/dma-dummy.c45
-rw-r--r--arch/arm/kernel/dma-rpc.c342
-rw-r--r--arch/arm/kernel/dma.c312
-rw-r--r--arch/arm/kernel/dma.h70
-rw-r--r--arch/arm/kernel/ecard.c100
-rw-r--r--arch/arm/kernel/entry-armv.S329
-rw-r--r--arch/arm/kernel/entry-common.S208
-rw-r--r--arch/arm/kernel/head-armo.S2
-rw-r--r--arch/arm/kernel/head-armv.S159
-rw-r--r--arch/arm/kernel/irq.c51
-rw-r--r--arch/arm/kernel/leds-ebsa285.c44
-rw-r--r--arch/arm/kernel/process.c4
-rw-r--r--arch/arm/kernel/ptrace.c14
-rw-r--r--arch/arm/kernel/setup-ebsa110.c71
-rw-r--r--arch/arm/kernel/setup.c22
-rw-r--r--arch/arm/kernel/time.c8
-rw-r--r--arch/arm/kernel/traps.c54
-rw-r--r--arch/arm/lib/Makefile27
-rw-r--r--arch/arm/lib/extractconstants.pl46
-rw-r--r--arch/arm/lib/getconsdata.c61
-rw-r--r--arch/arm/lib/io-acorn.S4
-rw-r--r--arch/arm/lib/io-ebsa285.S109
-rw-r--r--arch/arm/lib/ll_char_wr.S25
-rw-r--r--arch/arm/lib/memcpy.S11
-rw-r--r--arch/arm/lib/uaccess.S35
-rw-r--r--arch/arm/mm/Makefile16
-rw-r--r--arch/arm/mm/fault-armo.c44
-rw-r--r--arch/arm/mm/fault-armv.c121
-rw-r--r--arch/arm/mm/init.c6
-rw-r--r--arch/arm/mm/mm-arc.c1
-rw-r--r--arch/arm/mm/mm-ebsa110.c19
-rw-r--r--arch/arm/mm/mm-ebsa285.c97
-rw-r--r--arch/arm/mm/mm-nexuspci.c23
-rw-r--r--arch/arm/mm/mm-rpc.c65
-rw-r--r--arch/arm/mm/proc-arm6,7.S6
-rw-r--r--arch/arm/mm/proc-sa110.S10
-rw-r--r--arch/arm/vmlinux.lds11
48 files changed, 2340 insertions, 752 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 5c1efb76a..0c39121be 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -12,6 +12,9 @@
#
# Copyright (C) 1995, 1996 by Russell King
+CFLAGS_PROC :=
+ASFLAGS_PROC :=
+
ifeq ($(CONFIG_CPU_ARM2),y)
PROCESSOR = armo
ASFLAGS_PROC += -m2
@@ -65,7 +68,6 @@ endif
# ZRELADDR - Compressed kernel relocating address (point at which uncompressed kernel is loaded).
#
-HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o
COMPRESSED_HEAD = head.o
ifeq ($(PROCESSOR),armo)
@@ -79,11 +81,13 @@ endif
ifeq ($(CONFIG_ARCH_A5K),y)
MACHINE = a5k
+ARCHDIR = arc
COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o
endif
ifeq ($(CONFIG_ARCH_ARC),y)
MACHINE = arc
+ARCHDIR = arc
COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o
endif
@@ -96,6 +100,7 @@ endif
ifeq ($(CONFIG_ARCH_RPC),y)
MACHINE = rpc
+ARCHDIR = rpc
COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o
ZTEXTADDR = 0x10008000
ZRELADDR = 0x10008000
@@ -103,6 +108,14 @@ endif
ifeq ($(CONFIG_ARCH_EBSA110),y)
MACHINE = ebsa110
+ARCHDIR = ebsa110
+ZTEXTADDR = 0x00008000
+ZRELADDR = 0x00008000
+endif
+
+ifeq ($(CONFIG_ARCH_EBSA285),y)
+MACHINE = ebsa285
+ARCHDIR = ebsa285
ZTEXTADDR = 0x00008000
ZRELADDR = 0x00008000
endif
@@ -129,35 +142,55 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS := $(CFLAGS:-fomit-frame-pointer=)
endif
CFLAGS := $(CFLAGS_PROC) $(CFLAGS) -pipe
-ASFLAGS := $(ASFLAGS_PROC) $(ASFLAGS) -D__ASSEMBLY__
+ASFLAGS := $(ASFLAGS_PROC) $(ASFLAGS)
LINKFLAGS = -T $(TOPDIR)/arch/arm/vmlinux.lds -e stext -Ttext $(TEXTADDR)
ZLINKFLAGS = -Ttext $(ZTEXTADDR)
SUBDIRS := $(SUBDIRS:drivers=) arch/arm/lib arch/arm/kernel arch/arm/mm arch/arm/drivers
+HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o
CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
LIBS := arch/arm/lib/lib.a $(LIBS) $(GCCLIB)
-DRIVERS := arch/arm/drivers/block/block.a \
- arch/arm/drivers/char/char.a \
- drivers/misc/misc.a \
- arch/arm/drivers/net/net.a
+BLOCK_DRIVERS := arch/arm/drivers/block/block.a
+CDROM_DRIVERS := drivers/cdrom/cdrom.a
+CHAR_DRIVERS := arch/arm/drivers/char/char.a
+MISC_DRIVERS := drivers/misc/misc.a
+NET_DRIVERS := drivers/net/net.a
+PARIDE_DRIVERS := drivers/block/paride/paride.a
+PCI_DRIVERS := drivers/pci/pci.a
+SCSI_DRIVERS := drivers/scsi/scsi.a
+SOUND_DRIVERS := drivers/sound/sound.a
-ifeq ($(CONFIG_SCSI),y)
-DRIVERS := $(DRIVERS) arch/arm/drivers/scsi/scsi.a
+ifeq ($(CONFIG_ARCH_ACORN),y)
+BLOCK_DRIVERS += drivers/acorn/block/acorn-block.a
+CHAR_DRIVERS += drivers/acorn/char/acorn-char.a
+NET_DRIVERS += drivers/acorn/net/acorn-net.a drivers/net/net.a
+SCSI_DRIVERS += drivers/acorn/scsi/acorn-scsi.a
endif
+DRIVERS := $(BLOCK_DRIVERS) $(CHAR_DRIVERS) $(MISC_DRIVERS) $(NET_DRIVERS)
+
+ifeq ($(CONFIG_SCSI),y)
+DRIVERS := $(DRIVERS) $(SCSI_DRIVERS)
+endif
ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR),)
-DRIVERS := $(DRIVERS) drivers/cdrom/cdrom.a
+DRIVERS := $(DRIVERS) $(CDROM_DRIVERS)
+endif
+ifdef CONFIG_PCI
+DRIVERS := $(DRIVERS) $(PCI_DRIVERS)
endif
-
ifeq ($(CONFIG_SOUND),y)
-DRIVERS := $(DRIVERS) arch/arm/drivers/sound/sound.a
+DRIVERS := $(DRIVERS) $(SOUND_DRIVERS)
+endif
+ifeq ($(CONFIG_PARIDE),y)
+DRIVERS := $(DRIVERS) $(PARIDE_DRIVERS)
endif
symlinks::
$(RM) include/asm-arm/arch include/asm-arm/proc
- (cd include/asm-arm; ln -sf arch-$(MACHINE) arch; ln -sf proc-$(PROCESSOR) proc)
+ (cd include/asm-arm; ln -sf arch-$(ARCHDIR) arch; ln -sf proc-$(PROCESSOR) proc)
+# Once we've finished integrating the sources, the @$(MAKE) will disappear
mrproper::
rm -f include/asm-arm/arch include/asm-arm/proc
@$(MAKE) -C arch/$(ARCH)/drivers mrproper
@@ -183,7 +216,6 @@ install: vmlinux
@$(MAKEBOOT) install
# My testing targets (that short circuit a few dependencies)
-#
zImg:; @$(MAKEBOOT) zImage
Img:; @$(MAKEBOOT) Image
i:; @$(MAKEBOOT) install
@@ -191,8 +223,7 @@ zi:; @$(MAKEBOOT) zinstall
archclean:
@$(MAKEBOOT) clean
- @$(MAKE) -C arch/arm/lib clean
+ $(RM) arch/arm/lib/constants.h
archdep:
@$(MAKEBOOT) dep
-sed -e /^MACHINE..*=/s,= .*,= rpc,;/^PROCESSOR..*=/s,= .*,= armv, linux/arch/arm/Makefile.normal
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index e6050bf13..d210b92c2 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -25,11 +25,8 @@ install: $(CONFIGURE) Image
zinstall: $(CONFIGURE) zImage
sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
-tools/build: tools/build.c
- $(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
-
clean:
- rm -f Image zImage tools/build
+ rm -f Image zImage
@$(MAKE) -C compressed clean
dep:
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 8e49f5dd0..0c6a04c5b 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -26,7 +26,7 @@ piggy.o: $(SYSTEM)
$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
- $(LD) -m elf_arm -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-arm -T $$tmppiggy.lnk; \
+ $(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-arm -T $$tmppiggy.lnk; \
rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk;
clean:; rm -f vmlinux core
diff --git a/arch/arm/config.in b/arch/arm/config.in
index b95c2f16e..3396b1510 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -7,38 +7,25 @@ mainmenu_name "Linux Kernel Configuration"
define_bool CONFIG_ARM y
mainmenu_option next_comment
-comment 'Code maturity level options'
-bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
-endmenu
-
-mainmenu_option next_comment
-comment 'Loadable module support'
-bool 'Enable loadable module support' CONFIG_MODULES
-if [ "$CONFIG_MODULES" = "y" ]; then
- bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
- bool 'Kernel module loader' CONFIG_KMOD
-fi
-endmenu
-
-mainmenu_option next_comment
-comment 'General setup'
+comment 'System type and processor type'
choice 'ARM system type' \
"Archimedes CONFIG_ARCH_ARC \
A5000 CONFIG_ARCH_A5K \
RiscPC CONFIG_ARCH_RPC \
EBSA-110 CONFIG_ARCH_EBSA110 \
+ EBSA-285 CONFIG_ARCH_EBSA285 \
NexusPCI CONFIG_ARCH_NEXUSPCI" RiscPC
if [ "$CONFIG_ARCH_ARC" = "y" -o "$CONFIG_ARCH_A5K" = "y" -o "$CONFIG_ARCH_RPC" = "y" ]; then
define_bool CONFIG_ARCH_ACORN y
else
define_bool CONFIG_ARCH_ACORN n
fi
-if [ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
+if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then
define_bool CONFIG_PCI y
else
define_bool CONFIG_PCI n
fi
-if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" ]; then
+if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then
define_bool CONFIG_CPU_SA110 y
else
if [ "$CONFIG_ARCH_A5K" = "y" ]; then
@@ -51,11 +38,31 @@ else
StrongARM CONFIG_CPU_SA110" StrongARM
fi
fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
+
+mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+ bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+ bool 'Kernel module loader' CONFIG_KMOD
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW
bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
+# This needs kernel/acct.c to be updated
+#bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
@@ -70,6 +77,7 @@ fi
endmenu
source arch/arm/drivers/block/Config.in
+source drivers/acorn/block/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
@@ -81,7 +89,7 @@ comment 'SCSI support'
tristate 'SCSI support?' CONFIG_SCSI
if [ "$CONFIG_SCSI" != "n" ]; then
- source arch/arm/drivers/scsi/Config.in
+ source drivers/scsi/Config.in
fi
endmenu
@@ -91,7 +99,7 @@ if [ "$CONFIG_NET" = "y" ]; then
bool 'Network device support?' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
- source arch/arm/drivers/net/Config.in
+ source drivers/net/Config.in
fi
endmenu
fi
@@ -128,7 +136,7 @@ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
tristate 'Sound support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
- source arch/arm/drivers/sound/Config.in
+ source drivers/sound/Config.in
fi
endmenu
fi
diff --git a/arch/arm/defconfig b/arch/arm/defconfig
index 48358557b..5e587ffbf 100644
--- a/arch/arm/defconfig
+++ b/arch/arm/defconfig
@@ -31,6 +31,7 @@ CONFIG_ARCH_ACORN=y
CONFIG_CPU_SA110=y
CONFIG_FRAME_POINTER=y
# CONFIG_BINUTILS_NEW is not set
+CONFIG_DEBUG_ERRORS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
@@ -76,7 +77,7 @@ CONFIG_BLK_DEV_PART=y
#
# Networking options
#
-CONFIG_PACKET=m
+# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
@@ -112,8 +113,11 @@ CONFIG_IP_NOSR=y
# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
# CONFIG_CPU_IS_SLOW is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_PROFILE is not set
#
# SCSI support
@@ -149,7 +153,6 @@ CONFIG_SCSI_POWERTECSCSI=m
# The following drives are not fully supported
#
CONFIG_SCSI_CUMANA_1=m
-CONFIG_SCSI_ECOSCSI=m
CONFIG_SCSI_OAK1=m
CONFIG_SCSI_PPA=m
CONFIG_SCSI_PPA_HAVE_PEDANTIC=2
@@ -199,6 +202,7 @@ CONFIG_LOCKD=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_ADFS_FS=y
+CONFIG_ADFS_FS=y
# CONFIG_MAC_PARTITION is not set
CONFIG_NLS=y
@@ -252,10 +256,10 @@ CONFIG_RPCMOUSE=y
#
# Sound
#
-# CONFIG_SOUND is not set
-# CONFIG_VIDC is not set
-# CONFIG_AUDIO is not set
-# DSP_BUFFSIZE is not set
+CONFIG_SOUND=m
+CONFIG_VIDC=y
+CONFIG_AUDIO=y
+DSP_BUFFSIZE=65536
#
# Kernel hacking
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 90e71345a..f263b2a7f 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -19,15 +19,24 @@ else
O_OBJS += armksyms.o
endif
+ifdef CONFIG_PCI
+ O_OBJS += bios32.o
+endif
+
ifdef CONFIG_ARCH_ACORN
O_OBJS += setup.o ecard.o iic.o dma.o
ifdef CONFIG_ARCH_ARC
O_OBJS += oldlatches.o
endif
+ O_OBJS += dma-$(MACHINE).o
endif
ifeq ($(MACHINE),ebsa110)
- O_OBJS += setup-ebsa110.o dma.o
+ O_OBJS += setup-ebsa110.o dma.o dma-dummy.o
+endif
+
+ifeq ($(MACHINE),ebsa285)
+ O_OBJS += dma.o dma-dummy.o leds-ebsa285.o setup-ebsa110.o
endif
ifeq ($(MACHINE),nexuspci)
@@ -37,9 +46,12 @@ endif
$(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
$(CC) -D__ASSEMBLY__ -traditional -c $(HEAD_OBJ:.o=.S) -o $@
+$(ENTRY_OBJ): $(ENTRY_OBJ:.o=.S)
+ $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $(ENTRY_OBJ:.o=.S) -o $@
+
include $(TOPDIR)/Rules.make
-$(ENTRY_OBJ:.o=.S): ../lib/constants.h
+$(ENTRY_OBJ): ../lib/constants.h
.PHONY: ../lib/constants.h
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 20c62e2e6..a5b49bf2a 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -63,7 +63,6 @@ extern void fp_send_sig(int);
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(udelay);
-EXPORT_SYMBOL(dma_str);
EXPORT_SYMBOL(xchg_str);
/* expansion card support */
@@ -83,16 +82,33 @@ EXPORT_SYMBOL(outsw);
EXPORT_SYMBOL(inswb);
EXPORT_SYMBOL(insw);
-#ifdef CONFIG_ARCH_RPC
-EXPORT_SYMBOL(drambank);
+/* address translation */
+#ifndef __virt_to_phys__is_a_macro
+EXPORT_SYMBOL(__virt_to_phys);
+#endif
+#ifndef __phys_to_virt__is_a_macro
+EXPORT_SYMBOL(__phys_to_virt);
+#endif
+#ifndef __virt_to_bus__is_a_macro
+EXPORT_SYMBOL(__virt_to_bus);
#endif
+#ifndef __bus_to_virt__is_a_macro
+EXPORT_SYMBOL(__bus_to_virt);
+#endif
+
+EXPORT_SYMBOL(quicklists);
+EXPORT_SYMBOL(__bad_pmd);
+EXPORT_SYMBOL(__bad_pmd_kernel);
/* dma */
+EXPORT_SYMBOL(dma_str);
EXPORT_SYMBOL(enable_dma);
-EXPORT_SYMBOL(set_dma_mode);
+EXPORT_SYMBOL(disable_dma);
EXPORT_SYMBOL(set_dma_addr);
EXPORT_SYMBOL(set_dma_count);
+EXPORT_SYMBOL(set_dma_mode);
EXPORT_SYMBOL(get_dma_residue);
+EXPORT_SYMBOL(set_dma_sg);
/*
* floating point math emulator support.
@@ -177,7 +193,3 @@ EXPORT_SYMBOL(change_bit);
EXPORT_SYMBOL(test_and_change_bit);
EXPORT_SYMBOL(find_first_zero_bit);
EXPORT_SYMBOL(find_next_zero_bit);
-
-#if CONFIG_PCI
-EXPORT_SYMBOL(pci_devices);
-#endif
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
new file mode 100644
index 000000000..4400dda42
--- /dev/null
+++ b/arch/arm/kernel/bios32.c
@@ -0,0 +1,144 @@
+/*
+ * arch/arm/kernel/bios32.c: PCI functions for ARM
+ *
+ * Copyright (C) 1998 Russell King
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+int pcibios_present(void)
+{
+ return 1;
+}
+
+static unsigned long pcibios_base_address(unsigned char dev_fn)
+{
+ int slot = PCI_SLOT(dev_fn);
+
+ if (slot < 4)
+ return 0xf8000000 + (1 << (19 - slot));
+ else
+ return 0;
+}
+
+int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char *val)
+{
+ unsigned long addr = pcibios_base_address(dev_fn);
+ unsigned char v;
+
+ if (addr) {
+ __asm__("ldr%?b %0, [%1, %2]"
+ : "=r" (v)
+ : "r" (addr), "r" (where));
+ *val = v;
+ } else
+ *val = 0xff;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short *val)
+{
+ unsigned long addr = pcibios_base_address(dev_fn);
+ unsigned short v;
+
+ if (addr) {
+ __asm__("ldrh%? %0, [%1, %2]"
+ : "=r" (v)
+ : "r" (addr), "r" (where));
+ *val = v;
+ } else
+ *val = 0xffff;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int *val)
+{
+ unsigned long addr = pcibios_base_address(dev_fn);
+ unsigned int v;
+
+ if (addr) {
+ __asm__("ldr%? %0, [%1, %2]"
+ : "=r" (v)
+ : "r" (addr), "r" (where));
+ *val = v;
+ } else
+ *val = 0xffffffff;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char val)
+{
+ unsigned long addr = pcibios_base_address(dev_fn);
+
+ if (addr)
+ __asm__("str%?b %0, [%1, %2]"
+ : : "r" (val), "r" (addr), "r" (where));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short val)
+{
+ unsigned long addr = pcibios_base_address(dev_fn);
+
+ if (addr)
+ __asm__("strh%? %0, [%1, %2]"
+ : : "r" (val), "r" (addr), "r" (where));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int val)
+{
+ unsigned long addr = pcibios_base_address(dev_fn);
+
+ if (addr)
+ __asm__("str%? %0, [%1, %2]"
+ : : "r" (val), "r" (addr), "r" (where));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int irq[] = { 18, 8, 9, 11 };
+
+__initfunc(void pcibios_fixup(void))
+{
+ struct pci_dev *dev;
+ unsigned char pin;
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ pcibios_read_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_PIN,
+ &pin);
+
+ dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3];
+
+ pcibios_write_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_LINE,
+ dev->irq);
+
+ printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n",
+ dev->bus->number, dev->devfn,
+ dev->vendor, dev->device,
+ pin, dev->irq);
+ }
+}
+
+__initfunc(void pcibios_init(void))
+{
+ int rev;
+
+ rev = *(unsigned char *)0xfe000008;
+ printk("DEC21285 PCI revision %02X\n", rev);
+}
+
+__initfunc(char *pcibios_setup(char *str))
+{
+ return str;
+}
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 0d02eb85a..8a248c728 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -5,7 +5,7 @@
*/
#ifndef NR_SYSCALLS
#define NR_syscalls 256
-#define NR_SYSCALLS 182
+#define NR_SYSCALLS 184
#else
/* 0 */ .long SYMBOL_NAME(sys_setup)
@@ -190,5 +190,7 @@
.long SYMBOL_NAME(sys_rt_sigsuspend_wrapper)
/* 180 */ .long SYMBOL_NAME(sys_pread)
.long SYMBOL_NAME(sys_pwrite)
- .space (NR_syscalls - 182) * 4
+ .long SYMBOL_NAME(sys_xstat)
+ .long SYMBOL_NAME(sys_xmknod)
+ .space (NR_syscalls - 184) * 4
#endif
diff --git a/arch/arm/kernel/dma-a5k.c b/arch/arm/kernel/dma-a5k.c
new file mode 100644
index 000000000..f722809fa
--- /dev/null
+++ b/arch/arm/kernel/dma-a5k.c
@@ -0,0 +1,79 @@
+/*
+ * arch/arm/kernel/dma-a5k.c
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * DMA functions specific to A5000 architecture
+ */
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include "dma.h"
+
+int arch_request_dma(dmach_t channel, dma_t *dma)
+{
+ if (channel == DMA_VIRTUAL_FLOPPY0)
+ return 0;
+ else
+ return -EINVAL;
+}
+
+void arch_free_dma(dmach_t channel, dma_t *dma)
+{
+ if (channel != DMA_VIRTUAL_FLOPPY0)
+ printk ("arch_free_dma: invalid channel %d\n", channel);
+}
+
+int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+ if (channel != DMA_VIRTUAL_FLOPPY0)
+ printk ("arch_dma_count: invalid channel %d\n", dmanr);
+ else {
+ extern int floppy_fiqresidual(void);
+ return floppy_fiqresidual();
+ }
+ return 0;
+}
+
+void arch_enable_dma(dmach_t channel, dma_t *dma)
+{
+ if (channel != DMA_VIRTUAL_FLOPPY0)
+ printk ("arch_enable_dma: invalid channel %d\n", channel);
+ else {
+ void *fiqhandler_start;
+ unsigned int fiqhandler_length;
+ extern void floppy_fiqsetup (unsigned long len, unsigned long addr,
+ unsigned long port);
+
+ if (dma->dma_mode == DMA_MODE_READ) {
+ extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
+ fiqhandler_start = &floppy_fiqin_start;
+ fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
+ } else {
+ extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
+ fiqhandler_start = &floppy_fiqout_start;
+ fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
+ }
+ memcpy ((void *)0x1c, fiqhandler_start, fiqhandler_length);
+ flush_page_to_ram(0);
+ floppy_fiqsetup (dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
+ enable_irq (dma->dma_irq);
+ }
+}
+
+void arch_disable_dma(dmach_t channel, dma_t *dma)
+{
+ if (channel != DMA_VIRTUAL_FLOPPY0)
+ printk ("arch_disable_dma: invalid channel %d\n", channel);
+ else
+ disable_irq (dma->dma_irq);
+}
+
+__initfunc(void arch_dma_init(dma_t *dma))
+{
+ dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
+}
diff --git a/arch/arm/kernel/dma-arc.c b/arch/arm/kernel/dma-arc.c
new file mode 100644
index 000000000..27a139ad4
--- /dev/null
+++ b/arch/arm/kernel/dma-arc.c
@@ -0,0 +1,115 @@
+/*
+ * arch/arm/kernel/dma-arc.c
+ *
+ * Copyright (C) 1998 Dave Gilbert / Russell King
+ *
+ * DMA functions specific to Archimedes architecture
+ */
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include "dma.h"
+
+int arch_request_dma(dmach_t channel, dma_t *dma)
+{
+ if (channel == DMA_VIRTUAL_FLOPPY0 ||
+ channel == DMA_VIRTUAL_FLOPPY1)
+ return 0;
+ else
+ return -EINVAL;
+}
+
+void arch_free_dma(dmach_t channel, dma_t *dma)
+{
+ if (channel != DMA_VIRTUAL_FLOPPY0 &&
+ channel != DMA_VIRTUAL_FLOPPY1)
+ return 0;
+ else
+ return -EINVAL;
+}
+
+void arch_enable_dma(dmach_t channel, dma_t *dma)
+{
+ switch (channel) {
+ case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */
+ switch (dma->dma_mode) {
+ case DMA_MODE_READ: /* read */
+ {
+ extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
+ extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
+ unsigned long flags;
+#ifdef DEBUG
+ printk("enable_dma fdc1772 data read\n");
+#endif
+ save_flags(flags);
+ cliIF();
+
+ memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
+ &fdc1772_dma_read_end - &fdc1772_dma_read);
+ fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
+ enable_irq (64);
+ restore_flags(flags);
+ }
+ break;
+
+ case DMA_MODE_WRITE: /* write */
+ {
+ extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
+ extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
+ unsigned long flags;
+
+#ifdef DEBUG
+ printk("enable_dma fdc1772 data write\n");
+#endif
+ save_flags(flags);
+ cliIF();
+ memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
+ &fdc1772_dma_write_end - &fdc1772_dma_write);
+ fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
+ enable_irq (64);
+
+ restore_flags(flags);
+ }
+ break;
+ default:
+ printk ("enable_dma: dma%d not initialised\n", channel);
+ return;
+ }
+ }
+ break;
+
+ case DMA_VIRTUAL_FLOPPY1: { /* Command end FIQ - actually just sets a flag */
+ /* Need to build a branch at the FIQ address */
+ extern void fdc1772_comendhandler(void);
+ unsigned long flags;
+
+ /*printk("enable_dma fdc1772 command end FIQ\n");*/
+ save_flags(flags);
+ cliIF();
+
+ *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */
+
+ restore_flags(flags);
+ }
+ break;
+ }
+}
+
+void arch_disable_dma(dmach_t channel, dma_t *dma)
+{
+ if (channel != DMA_VIRTUAL_FLOPPY0 &&
+ channel != DMA_VIRTUAL_FLOPPY1)
+ printk("arch_disable_dma: invalid channel %d\n", channel);
+ else
+ disable_irq(dma->dma_irq);
+}
+
+__initfunc(void arch_dma_init(dma_t *dma))
+{
+ dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
+ dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
+}
diff --git a/arch/arm/kernel/dma-dummy.c b/arch/arm/kernel/dma-dummy.c
new file mode 100644
index 000000000..af47512dd
--- /dev/null
+++ b/arch/arm/kernel/dma-dummy.c
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/kernel/dma-dummy.c
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * Dummy DMA functions
+ */
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include "dma.h"
+
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *devname)
+{
+ return -EINVAL;
+}
+
+void arch_free_dma(dmach_t channel, dma_t *dma)
+{
+ printk ("arch_free_dma: invalid channel %d\n", channel);
+}
+
+void arch_enable_dma(dmach_t channel, dma_t *dma)
+{
+ printk ("arch_enable_dma: invalid channel %d\n", channel);
+}
+
+void arch_disable_dma(dmach_t channel, dma_t *dma)
+{
+ printk ("arch_disable_dma: invalid channel %d\n", channel);
+}
+
+int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+ printk ("arch_get_dma_residue: invalid channel %d\n", channel);
+ return 0;
+}
+
+__initfunc(void arch_dma_init(dma_t *dma))
+{
+}
diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c
new file mode 100644
index 000000000..eb5bc87d7
--- /dev/null
+++ b/arch/arm/kernel/dma-rpc.c
@@ -0,0 +1,342 @@
+/*
+ * arch/arm/kernel/dma-rpc.c
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * DMA functions specific to RiscPC architecture
+ */
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/mman.h>
+#include <linux/init.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/uaccess.h>
+
+#include "dma.h"
+
+#if 0
+typedef enum {
+ dma_size_8 = 1,
+ dma_size_16 = 2,
+ dma_size_32 = 4,
+ dma_size_128 = 16
+} dma_size_t;
+
+typedef struct {
+ dma_size_t transfersize;
+} dma_t;
+#endif
+
+#define TRANSFER_SIZE 2
+
+#define CURA (0)
+#define ENDA ((IOMD_IO0ENDA - IOMD_IO0CURA) << 2)
+#define CURB ((IOMD_IO0CURB - IOMD_IO0CURA) << 2)
+#define ENDB ((IOMD_IO0ENDB - IOMD_IO0CURA) << 2)
+#define CR ((IOMD_IO0CR - IOMD_IO0CURA) << 2)
+#define ST ((IOMD_IO0ST - IOMD_IO0CURA) << 2)
+
+#define state_prog_a 0
+#define state_wait_a 1
+#define state_wait_b 2
+
+static void arch_get_next_sg(dmasg_t *sg, dma_t *dma)
+{
+ unsigned long end, offset, flags = 0;
+
+ if (dma->sg) {
+ sg->address = dma->sg->address;
+ offset = sg->address & ~PAGE_MASK;
+
+ end = offset + dma->sg->length;
+
+ if (end > PAGE_SIZE)
+ end = PAGE_SIZE;
+
+ if (offset + (int) TRANSFER_SIZE > end)
+ flags |= DMA_END_L;
+
+ sg->length = end - TRANSFER_SIZE;
+
+ dma->sg->length -= end - offset;
+ dma->sg->address += end - offset;
+
+ if (dma->sg->length == 0) {
+ if (dma->sgcount > 1) {
+ dma->sg++;
+ dma->sgcount--;
+ } else {
+ dma->sg = NULL;
+ flags |= DMA_END_S;
+ }
+ }
+ } else {
+ flags = DMA_END_S | DMA_END_L;
+ sg->address = 0;
+ sg->length = 0;
+ }
+
+ sg->length |= flags;
+}
+
+static inline void arch_setup_dma_a(dmasg_t *sg, dma_t *dma)
+{
+ outl_t(sg->address, dma->dma_base + CURA);
+ outl_t(sg->length, dma->dma_base + ENDA);
+}
+
+static inline void arch_setup_dma_b(dmasg_t *sg, dma_t *dma)
+{
+ outl_t(sg->address, dma->dma_base + CURB);
+ outl_t(sg->length, dma->dma_base + ENDB);
+}
+
+static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ dma_t *dma = (dma_t *)dev_id;
+ unsigned int status = 0, no_buffer = dma->sg == NULL;
+
+ do {
+ switch (dma->state) {
+ case state_prog_a:
+ arch_get_next_sg(&dma->cur_sg, dma);
+ arch_setup_dma_a(&dma->cur_sg, dma);
+ dma->state = state_wait_a;
+
+ case state_wait_a:
+ status = inb_t(dma->dma_base + ST);
+ switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
+ case DMA_ST_OFL|DMA_ST_INT:
+ arch_get_next_sg(&dma->cur_sg, dma);
+ arch_setup_dma_a(&dma->cur_sg, dma);
+ break;
+
+ case DMA_ST_INT:
+ arch_get_next_sg(&dma->cur_sg, dma);
+ arch_setup_dma_b(&dma->cur_sg, dma);
+ dma->state = state_wait_b;
+ break;
+
+ case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
+ arch_setup_dma_b(&dma->cur_sg, dma);
+ dma->state = state_wait_b;
+ break;
+ }
+ break;
+
+ case state_wait_b:
+ status = inb_t(dma->dma_base + ST);
+ switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
+ case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
+ arch_get_next_sg(&dma->cur_sg, dma);
+ arch_setup_dma_b(&dma->cur_sg, dma);
+ break;
+
+ case DMA_ST_INT|DMA_ST_AB:
+ arch_get_next_sg(&dma->cur_sg, dma);
+ arch_setup_dma_a(&dma->cur_sg, dma);
+ dma->state = state_wait_a;
+ break;
+
+ case DMA_ST_OFL|DMA_ST_INT:
+ arch_setup_dma_a(&dma->cur_sg, dma);
+ dma->state = state_wait_a;
+ break;
+ }
+ break;
+ }
+ } while (dma->sg && (status & DMA_ST_INT));
+
+ if (!no_buffer)
+ enable_irq(irq);
+}
+
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
+{
+ unsigned long flags;
+ int ret;
+
+ switch (channel) {
+ case DMA_0:
+ case DMA_1:
+ case DMA_2:
+ case DMA_3:
+ case DMA_S0:
+ case DMA_S1:
+ save_flags_cli(flags);
+ ret = request_irq(dma->dma_irq, arch_dma_handle, SA_INTERRUPT, dev_name, dma);
+ if (!ret)
+ disable_irq(dma->dma_irq);
+ restore_flags(flags);
+ break;
+
+ case DMA_VIRTUAL_FLOPPY:
+ case DMA_VIRTUAL_SOUND:
+ ret = 0;
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+void arch_free_dma(dmach_t channel, dma_t *dma)
+{
+ switch (channel) {
+ case DMA_0:
+ case DMA_1:
+ case DMA_2:
+ case DMA_3:
+ case DMA_S0:
+ case DMA_S1:
+ free_irq(dma->dma_irq, dma);
+ break;
+
+ default:
+ break;
+ }
+}
+
+int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+ int residue = 0;
+
+ switch (channel) {
+ case DMA_0: /* Physical DMA channels */
+ case DMA_1:
+ case DMA_2:
+ case DMA_3:
+ case DMA_S0:
+ case DMA_S1:
+ break;
+
+ case DMA_VIRTUAL_FLOPPY: {
+ extern int floppy_fiqresidual(void);
+ residue = floppy_fiqresidual();
+ }
+ break;
+ }
+ return residue;
+}
+
+void arch_enable_dma(dmach_t channel, dma_t *dma)
+{
+ unsigned long dma_base = dma->dma_base;
+ unsigned int ctrl;
+
+ switch (channel) {
+ case DMA_0: /* Physical DMA channels */
+ case DMA_1:
+ case DMA_2:
+ case DMA_3:
+ case DMA_S0:
+ case DMA_S1:
+ ctrl = TRANSFER_SIZE | DMA_CR_E;
+
+ if (dma->invalid) {
+ dma->invalid = 0;
+
+ outb_t(DMA_CR_C, dma_base + CR);
+ dma->state = state_prog_a;
+ }
+
+ if (dma->dma_mode == DMA_MODE_READ)
+ ctrl |= DMA_CR_D;
+
+ outb_t(ctrl, dma_base + CR);
+ enable_irq(dma->dma_irq);
+ break;
+
+ case DMA_VIRTUAL_FLOPPY: {
+ void *fiqhandler_start;
+ unsigned int fiqhandler_length;
+ extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
+ unsigned long port);
+
+ if (dma->dma_mode == DMA_MODE_READ) {
+ extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
+ fiqhandler_start = &floppy_fiqin_start;
+ fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
+ } else {
+ extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
+ fiqhandler_start = &floppy_fiqout_start;
+ fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
+ }
+ /* Allow access to page 0 via domains */
+ __asm__ __volatile__("mcr p15, 0, %0, c3, c0" :
+ : "r" (DOMAIN_USER_MANAGER |
+ DOMAIN_KERNEL_CLIENT |
+ DOMAIN_IO_CLIENT));
+ memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
+ /* set domain register to normal */
+ set_fs(get_fs());
+ flush_page_to_ram(0);
+ floppy_fiqsetup(dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
+ enable_irq(dma->dma_irq);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void arch_disable_dma(dmach_t channel, dma_t *dma)
+{
+ unsigned long dma_base = dma->dma_base;
+ unsigned int ctrl;
+
+ switch (channel) {
+ case DMA_0: /* Physical DMA channels */
+ case DMA_1:
+ case DMA_2:
+ case DMA_3:
+ case DMA_S0:
+ case DMA_S1:
+ disable_irq(dma->dma_irq);
+ ctrl = inb_t(dma_base + CR);
+ outb_t(ctrl & ~DMA_CR_E, dma_base + CR);
+ break;
+
+ case DMA_VIRTUAL_FLOPPY:
+ disable_irq(dma->dma_irq);
+ break;
+ }
+}
+
+__initfunc(void arch_dma_init(dma_t *dma))
+{
+ outb(0, IOMD_IO0CR);
+ outb(0, IOMD_IO1CR);
+ outb(0, IOMD_IO2CR);
+ outb(0, IOMD_IO3CR);
+
+// outb(0xf0, IOMD_DMATCR);
+
+ dma[0].dma_base = ioaddr(IOMD_IO0CURA);
+ dma[0].dma_irq = IRQ_DMA0;
+ dma[1].dma_base = ioaddr(IOMD_IO1CURA);
+ dma[1].dma_irq = IRQ_DMA1;
+ dma[2].dma_base = ioaddr(IOMD_IO2CURA);
+ dma[2].dma_irq = IRQ_DMA2;
+ dma[3].dma_base = ioaddr(IOMD_IO3CURA);
+ dma[3].dma_irq = IRQ_DMA3;
+ dma[4].dma_base = ioaddr(IOMD_SD0CURA);
+ dma[4].dma_irq = IRQ_DMAS0;
+ dma[5].dma_base = ioaddr(IOMD_SD1CURA);
+ dma[5].dma_irq = IRQ_DMAS1;
+ dma[6].dma_irq = 64;
+
+ /* Setup DMA channels 2,3 to be for podules
+ * and channels 0,1 for internal devices
+ */
+ outb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
+}
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 3c165c41d..6058a2863 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -1,199 +1,189 @@
/*
* linux/arch/arm/kernel/dma.c
*
- * Copyright (C) 1995, 1996 Russell King
+ * Copyright (C) 1995-1998 Russell King
+ *
+ * Front-end to the DMA handling. You must provide the following
+ * architecture-specific routines:
+ *
+ * int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id);
+ * void arch_free_dma(dmach_t channel, dma_t *dma);
+ * void arch_enable_dma(dmach_t channel, dma_t *dma);
+ * void arch_disable_dma(dmach_t channel, dma_t *dma);
+ * int arch_get_dma_residue(dmach_t channel, dma_t *dma);
+ *
+ * Moved DMA resource allocation here...
*/
-
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/mman.h>
+#include <linux/init.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/io.h>
-#define KERNEL_ARCH_DMA
#include <asm/dma.h>
-static unsigned long dma_address[8];
-static unsigned long dma_count[8];
-static char dma_direction[8] = { -1, -1, -1, -1, -1, -1, -1};
+#include "dma.h"
-#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_RPC)
-#define DMA_PCIO
-#endif
-#if defined(CONFIG_ARCH_ARC) && defined(CONFIG_BLK_DEV_FD)
-#define DMA_OLD
-#endif
+static dma_t dma_chan[MAX_DMA_CHANNELS];
-void enable_dma (unsigned int dmanr)
+/* Get dma list
+ * for /proc/dma
+ */
+int get_dma_list(char *buf)
{
- switch (dmanr) {
-#ifdef DMA_PCIO
- case 2: {
- void *fiqhandler_start;
- unsigned int fiqhandler_length;
- extern void floppy_fiqsetup (unsigned long len, unsigned long addr,
- unsigned long port);
- switch (dma_direction[dmanr]) {
- case 1: {
- extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
- fiqhandler_start = &floppy_fiqin_start;
- fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
- break;
- }
- case 0: {
- extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
- fiqhandler_start = &floppy_fiqout_start;
- fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
- break;
- }
- default:
- printk ("enable_dma: dma%d not initialised\n", dmanr);
- return;
- }
- memcpy ((void *)0x1c, fiqhandler_start, fiqhandler_length);
- flush_page_to_ram(0);
- floppy_fiqsetup (dma_count[dmanr], dma_address[dmanr], (int)PCIO_FLOPPYDMABASE);
- enable_irq (64);
- return;
- }
-#endif
-#ifdef DMA_OLD
- case 0: { /* Data DMA */
- switch (dma_direction[dmanr]) {
- case 1: /* read */
- {
- extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
- extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
- unsigned long flags;
-#ifdef DEBUG
- printk("enable_dma fdc1772 data read\n");
-#endif
- save_flags(flags);
- cliIF();
-
- memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
- &fdc1772_dma_read_end - &fdc1772_dma_read);
- fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */
- enable_irq (64);
- restore_flags(flags);
- }
- break;
-
- case 0: /* write */
- {
- extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
- extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
- unsigned long flags;
-
-#ifdef DEBUG
- printk("enable_dma fdc1772 data write\n");
-#endif
- save_flags(flags);
- cliIF();
- memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
- &fdc1772_dma_write_end - &fdc1772_dma_write);
- fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */
- enable_irq (64);
-
- restore_flags(flags);
- }
- break;
- default:
- printk ("enable_dma: dma%d not initialised\n", dmanr);
- return;
- }
- }
- break;
+ int i, len = 0;
- case 1: { /* Command end FIQ - actually just sets a flag */
- /* Need to build a branch at the FIQ address */
- extern void fdc1772_comendhandler(void);
- unsigned long flags;
+ for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ if (dma_chan[i].lock)
+ len += sprintf(buf + len, "%2d: %s\n",
+ i, dma_chan[i].device_id);
+ }
+ return len;
+}
- /*printk("enable_dma fdc1772 command end FIQ\n");*/
- save_flags(flags);
- cliIF();
-
- *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */
+/* Request DMA channel
+ *
+ * On certain platforms, we have to allocate an interrupt as well...
+ */
+int request_dma(dmach_t channel, const char *device_id)
+{
+ if (channel < MAX_DMA_CHANNELS) {
+ int ret;
+
+ if (xchg(&dma_chan[channel].lock, 1) != 0)
+ return -EBUSY;
+
+ ret = arch_request_dma(channel, &dma_chan[channel], device_id);
+ if (!ret) {
+ dma_chan[channel].device_id = device_id;
+ dma_chan[channel].active = 0;
+ dma_chan[channel].invalid = 1;
+ } else
+ xchg(&dma_chan[channel].lock, 0);
+
+ return ret;
+ } else {
+ printk (KERN_ERR "Trying to allocate DMA%d\n", channel);
+ return -EINVAL;
+ }
+}
+
+/* Free DMA channel
+ *
+ * On certain platforms, we have to free interrupt as well...
+ */
+void free_dma(dmach_t channel)
+{
+ if (channel >= MAX_DMA_CHANNELS) {
+ printk (KERN_ERR "Trying to free DMA%d\n", channel);
+ return;
+ }
- restore_flags(flags);
+ if (xchg(&dma_chan[channel].lock, 0) == 0) {
+ if (dma_chan[channel].active) {
+ printk (KERN_ERR "Freeing active DMA%d\n", channel);
+ arch_disable_dma(channel, &dma_chan[channel]);
+ dma_chan[channel].active = 0;
}
- break;
-#endif
- case DMA_0:
- case DMA_1:
- case DMA_2:
- case DMA_3:
- case DMA_S0:
- case DMA_S1:
- arch_enable_dma (dmanr - DMA_0);
- break;
-
- default:
- printk ("enable_dma: dma %d not supported\n", dmanr);
+
+ printk (KERN_ERR "Trying to free free DMA%d\n", channel);
+ return;
}
+ arch_free_dma(channel, &dma_chan[channel]);
+}
+
+/* Set DMA Scatter-Gather list
+ */
+void set_dma_sg (dmach_t channel, dmasg_t *sg, int nr_sg)
+{
+ dma_chan[channel].sg = sg;
+ dma_chan[channel].sgcount = nr_sg;
+ dma_chan[channel].invalid = 1;
}
-void set_dma_mode (unsigned int dmanr, char mode)
+/* Set DMA address
+ *
+ * Copy address to the structure, and set the invalid bit
+ */
+void set_dma_addr (dmach_t channel, unsigned long physaddr)
{
- if (dmanr < 8) {
- if (mode == DMA_MODE_READ)
- dma_direction[dmanr] = 1;
- else if (mode == DMA_MODE_WRITE)
- dma_direction[dmanr] = 0;
- else
- printk ("set_dma_mode: dma%d: invalid mode %02X not supported\n",
- dmanr, mode);
- } else if (dmanr < MAX_DMA_CHANNELS)
- arch_set_dma_mode (dmanr - DMA_0, mode);
- else
- printk ("set_dma_mode: dma %d not supported\n", dmanr);
+ if (dma_chan[channel].active)
+ printk(KERN_ERR "set_dma_addr: altering DMA%d"
+ " address while DMA active\n",
+ channel);
+
+ dma_chan[channel].sg = &dma_chan[channel].buf;
+ dma_chan[channel].sgcount = 1;
+ dma_chan[channel].buf.address = physaddr;
+ dma_chan[channel].invalid = 1;
}
-void set_dma_addr (unsigned int dmanr, unsigned int addr)
+/* Set DMA byte count
+ *
+ * Copy address to the structure, and set the invalid bit
+ */
+void set_dma_count (dmach_t channel, unsigned long count)
{
- if (dmanr < 8)
- dma_address[dmanr] = (unsigned long)addr;
- else if (dmanr < MAX_DMA_CHANNELS)
- arch_set_dma_addr (dmanr - DMA_0, addr);
- else
- printk ("set_dma_addr: dma %d not supported\n", dmanr);
+ if (dma_chan[channel].active)
+ printk(KERN_ERR "set_dma_count: altering DMA%d"
+ " count while DMA active\n",
+ channel);
+
+ dma_chan[channel].sg = &dma_chan[channel].buf;
+ dma_chan[channel].sgcount = 1;
+ dma_chan[channel].buf.length = count;
+ dma_chan[channel].invalid = 1;
}
-void set_dma_count (unsigned int dmanr, unsigned int count)
+/* Set DMA direction mode
+ */
+void set_dma_mode (dmach_t channel, dmamode_t mode)
{
- if (dmanr < 8)
- dma_count[dmanr] = (unsigned long)count;
- else if (dmanr < MAX_DMA_CHANNELS)
- arch_set_dma_count (dmanr - DMA_0, count);
- else
- printk ("set_dma_count: dma %d not supported\n", dmanr);
+ if (dma_chan[channel].active)
+ printk(KERN_ERR "set_dma_mode: altering DMA%d"
+ " mode while DMA active\n",
+ channel);
+
+ dma_chan[channel].dma_mode = mode;
+ dma_chan[channel].invalid = 1;
}
-int get_dma_residue (unsigned int dmanr)
+/* Enable DMA channel
+ */
+void enable_dma (dmach_t channel)
{
- if (dmanr < 8) {
- switch (dmanr) {
-#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_RPC)
- case 2: {
- extern int floppy_fiqresidual (void);
- return floppy_fiqresidual ();
- }
-#endif
-#if defined(CONFIG_ARCH_ARC) && defined(CONFIG_BLK_DEV_FD)
- case 0: {
- extern unsigned int fdc1772_bytestogo;
- return fdc1772_bytestogo;
+ if (dma_chan[channel].lock) {
+ if (dma_chan[channel].active == 0) {
+ dma_chan[channel].active = 1;
+ arch_enable_dma(channel, &dma_chan[channel]);
}
-#endif
- default:
- return -1;
+ } else
+ printk (KERN_ERR "Trying to enable free DMA%d\n", channel);
+}
+
+/* Disable DMA channel
+ */
+void disable_dma (dmach_t channel)
+{
+ if (dma_chan[channel].lock) {
+ if (dma_chan[channel].active == 1) {
+ dma_chan[channel].active = 0;
+ arch_disable_dma(channel, &dma_chan[channel]);
}
- } else if (dmanr < MAX_DMA_CHANNELS)
- return arch_dma_count (dmanr - DMA_0);
- return -1;
+ } else
+ printk (KERN_ERR "Trying to disable free DMA%d\n", channel);
+}
+
+int get_dma_residue(dmach_t channel)
+{
+ return arch_get_dma_residue(channel, &dma_chan[channel]);
+}
+
+__initfunc(void init_dma(void))
+{
+ arch_dma_init(dma_chan);
}
diff --git a/arch/arm/kernel/dma.h b/arch/arm/kernel/dma.h
new file mode 100644
index 000000000..e4c72c6af
--- /dev/null
+++ b/arch/arm/kernel/dma.h
@@ -0,0 +1,70 @@
+/*
+ * arch/arm/kernel/dma.h
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * This header file describes the interface between the generic DMA handler
+ * (dma.c) and the architecture-specific DMA backends (dma-*.c)
+ */
+
+typedef struct {
+ dmasg_t buf; /* single DMA */
+ int sgcount; /* number of DMA SG */
+ dmasg_t *sg; /* DMA Scatter-Gather List */
+
+ unsigned int active:1; /* Transfer active */
+ unsigned int invalid:1; /* Address/Count changed */
+ dmamode_t dma_mode; /* DMA mode */
+
+ unsigned int lock; /* Device is allocated */
+ const char *device_id; /* Device name */
+
+ unsigned int dma_base; /* Controller base address */
+ int dma_irq; /* Controller IRQ */
+ int state; /* Controller state */
+ dmasg_t cur_sg; /* Current controller buffer */
+} dma_t;
+
+/* Prototype: int arch_request_dma(channel, dma, dev_id)
+ * Purpose : Perform architecture specific claiming of a DMA channel
+ * Params : channel - DMA channel number
+ * : dma - DMA structure (above) for channel
+ * : dev_id - device ID string passed with request
+ * Returns : 0 on success, E????? number on error
+ */
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id);
+
+/* Prototype: int arch_free_dma(channel, dma)
+ * Purpose : Perform architecture specific freeing of a DMA channel
+ * Params : channel - DMA channel number
+ * : dma - DMA structure for channel
+ */
+void arch_free_dma(dmach_t channel, dma_t *dma);
+
+/* Prototype: void arch_enable_dma(channel, dma)
+ * Purpose : Enable a claimed DMA channel
+ * Params : channel - DMA channel number
+ * : dma - DMA structure for channel
+ */
+void arch_enable_dma(dmach_t channel, dma_t *dma);
+
+/* Prototype: void arch_disable_dma(channel, dma)
+ * Purpose : Disable a claimed DMA channel
+ * Params : channel - DMA channel number
+ * : dma - DMA structure for channel
+ */
+void arch_disable_dma(dmach_t channel, dma_t *dma);
+
+/* Prototype: int arch_get_dma_residue(channel, dma)
+ * Purpose : Return number of bytes left to DMA
+ * Params : channel - DMA channel number
+ * : dma - DMA structure for channel
+ * Returns : Number of bytes left to DMA
+ */
+int arch_get_dma_residue(dmach_t channel, dma_t *dma);
+
+/* Prototype: void arch_dma_init(dma)
+ * Purpose : Initialise architecture specific DMA
+ * Params : dma - pointer to array of DMA structures
+ */
+void arch_dma_init(dma_t *dma);
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index cc18252b3..f03147e66 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -13,6 +13,7 @@
* now register their own routine to control interrupts (recommended).
* 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled on reset from
* Linux. (Caused cards not to respond under RiscOS without hard reset).
+ * 15-Feb-1998 RMK Added DMA support
*/
#define ECARD_C
@@ -24,13 +25,14 @@
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <linux/init.h>
-#include <asm/irq-no.h>
-#include <asm/ecard.h>
-#include <asm/irq.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/irq.h>
+#include <asm/ecard.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
#ifdef CONFIG_ARCH_ARC
#include <asm/arch/oldlatches.h>
@@ -59,9 +61,11 @@ static const struct expcard_blacklist {
BLACKLIST_LOADER(MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, atomwide_serial_loader),
BLACKLIST_LOADER(MANU_OAK, PROD_OAK_SCSI, oak_scsi_loader),
+/* Supported cards with broken loader */
+ { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI, noloader, "AlSystems PowerTec SCSI (loader blacklisted)" },
+
/* Unsupported cards with no loader */
-BLACKLIST_NOLOADER(MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI),
-BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32)
+ BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32)
};
extern int setup_arm_irq(int, struct irqaction *);
@@ -75,7 +79,6 @@ static ecard_t expcard[MAX_ECARDS];
static signed char irqno_to_expcard[16];
static unsigned int ecard_numcards, ecard_numirqcards;
static unsigned int have_expmask;
-static unsigned long kmem;
static void ecard_def_irq_enable (ecard_t *ec, int irqnr)
{
@@ -178,20 +181,6 @@ void ecard_disablefiq (unsigned int fiqnr)
}
}
-static void *ecard_malloc(int len)
-{
- int r;
-
- len = (len + 3) & ~3;
-
- if (kmem) {
- r = kmem;
- kmem += len;
- return (void *)r;
- } else
- return kmalloc(len, GFP_KERNEL);
-}
-
static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
{
const int num_cards = ecard_numirqcards;
@@ -301,13 +290,13 @@ static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int usel
lowaddress = 0;
}
while (lowaddress <= laddr) {
- byte = inb (ec->podaddr + haddr);
+ byte = inb(ec->podaddr + haddr);
lowaddress += 1;
}
while (len--) {
*a++ = byte;
if (len) {
- byte = inb (ec->podaddr + haddr);
+ byte = inb(ec->podaddr + haddr);
lowaddress += 1;
}
}
@@ -417,7 +406,7 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
}
if (c_id(&excd) == 0x80) { /* loader */
if (!ec->loader) {
- ec->loader = (loader_t)ecard_malloc(c_len(&excd));
+ ec->loader = (loader_t)kmalloc(c_len(&excd), GFP_KERNEL);
ecard_readbytes(ec->loader, ec, (int)c_start(&excd), c_len(&excd), useld);
}
continue;
@@ -441,20 +430,39 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
return 1;
}
-unsigned int ecard_address (ecard_t *ec, card_type_t memc, card_speed_t speed)
+unsigned int ecard_address (ecard_t *ec, card_type_t type, card_speed_t speed)
{
switch (ec->slot_no) {
case 0:
case 1:
case 2:
case 3:
- return (memc ? MEMCECIO_BASE : IOCECIO_BASE + (speed << 17)) + (ec->slot_no << 12);
+ switch (type) {
+ case ECARD_MEMC:
+ return MEMCECIO_BASE + (ec->slot_no << 12);
+
+ case ECARD_IOC:
+ return IOCECIO_BASE + (speed << 17) + (ec->slot_no << 12);
+
+ default:
+ return 0;
+ }
+
#ifdef IOCEC4IO_BASE
case 4:
case 5:
case 6:
case 7:
- return (memc ? 0 : IOCEC4IO_BASE + (speed << 17)) + ((ec->slot_no - 4) << 12);
+ switch (type) {
+ case ECARD_MEMC:
+ return 0;
+
+ case ECARD_IOC:
+ return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
+
+ default:
+ return 0;
+ }
#endif
#ifdef MEMCEC8IO_BASE
case 8:
@@ -470,7 +478,7 @@ unsigned int ecard_address (ecard_t *ec, card_type_t memc, card_speed_t speed)
* If bit 1 of the first byte of the card is set,
* then the card does not exist.
*/
-static int ecard_probe (int card, int freeslot)
+__initfunc(static int ecard_probe (int card, int freeslot))
{
ecard_t *ec = expcard + freeslot;
struct ex_ecld excld;
@@ -480,7 +488,7 @@ static int ecard_probe (int card, int freeslot)
irqno_to_expcard[card] = -1;
ec->slot_no = card;
- if ((ec->podaddr = ecard_address (ec, 0, ECARD_SYNC)) == 0)
+ if ((ec->podaddr = ecard_address (ec, ECARD_IOC, ECARD_SYNC)) == 0)
return 0;
excld.r_ecld = 2;
@@ -490,8 +498,9 @@ static int ecard_probe (int card, int freeslot)
irqno_to_expcard[card] = freeslot;
- ec->irq = -1;
- ec->fiq = -1;
+ ec->irq = NO_IRQ;
+ ec->fiq = NO_IRQ;
+ ec->dma = NO_DMA;
ec->cld.ecld = e_ecld(&excld);
ec->cld.manufacturer = e_manu(&excld);
ec->cld.product = e_prod(&excld);
@@ -514,15 +523,20 @@ static int ecard_probe (int card, int freeslot)
break;
}
- if (card != 8) {
- ec->irq = 32 + card;
+ ec->irq = 32 + card;
#if 0
- ec->fiq = 96 + card;
+ /* We don't support FIQs on expansion cards at the moment */
+ ec->fiq = 96 + card;
#endif
- } else {
+#ifdef CONFIG_ARCH_RPC
+ if (card != 8) {
+ /* On RiscPC, only first two slots have DMA capability
+ */
+ if (card < 2)
+ ec->dma = 2 + card;
+ } else
ec->irq = 11;
- ec->fiq = -1;
- }
+#endif
if ((ec->cld.ecld & 0x78) == 0) {
struct in_chunk_dir incd;
@@ -551,11 +565,10 @@ static struct irqaction irqexpansioncard = { ecard_irq_noexpmask, SA_INTERRUPT,
* Locate all hardware - interrupt management and
* actual cards.
*/
-unsigned long ecard_init(unsigned long start_mem)
+__initfunc(void ecard_init(void))
{
int i, nc = 0;
- kmem = (start_mem | 3) & ~3;
memset (expcard, 0, sizeof (expcard));
#ifdef HAS_EXPMASK
@@ -565,6 +578,7 @@ unsigned long ecard_init(unsigned long start_mem)
have_expmask = -1;
}
#endif
+
printk("Installed expansion cards:");
/*
@@ -578,27 +592,25 @@ unsigned long ecard_init(unsigned long start_mem)
ecard_numirqcards = nc;
- /*
- * Now probe other cards with different interrupt lines
+ /* Now probe other cards with different interrupt lines
*/
#ifdef MEMCEC8IO_BASE
if (ecard_probe (8, nc))
nc += 1;
#endif
+
printk("\n");
ecard_numcards = nc;
if (nc && setup_arm_irq(IRQ_EXPANSIONCARD, &irqexpansioncard)) {
printk ("Could not allocate interrupt for expansion cards\n");
- return kmem;
+ return;
}
#ifdef HAS_EXPMASK
if (nc && have_expmask)
EXPMASK_ENABLE = have_expmask;
#endif
+
oldlatch_init ();
- start_mem = kmem;
- kmem = 0;
- return start_mem;
}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index a2de41f33..f2d752cd4 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -9,7 +9,7 @@
* Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes
* it to save wrong values... Be aware!
*/
-#include <linux/config.h> /* for CONFIG_ARCH_EBSA110 /*
+#include <linux/config.h> /* for CONFIG_ARCH_EBSA110 */
#include <linux/autoconf.h>
#include <linux/linkage.h>
@@ -21,15 +21,6 @@
.text
-@ Offsets into task structure
-@ ---------------------------
-@
-#define STATE 0
-#define COUNTER 4
-#define PRIORITY 8
-#define FLAGS 12
-#define SIGPENDING 16
-
#define PF_TRACESYS 0x20
@ Bad Abort numbers
@@ -82,21 +73,24 @@
strb r12, [r12, #0x38] @ Disable FIQ register
.endm
- .macro get_irqnr_and_base, irqnr, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base
mov r4, #ioc_base_high @ point at IOC
.if ioc_base_low
orr r4, r4, #ioc_base_low
.endif
- ldrb \irqnr, [r4, #0x24] @ get high priority first
+ ldrb \irqstat, [r4, #0x24] @ get high priority first
adr \base, irq_prio_h
- teq \irqnr, #0
+ teq \irqstat, #0
#ifdef IOMD_BASE
- ldreqb \irqnr, [r4, #0x1f4] @ get dma
+ ldreqb \irqstat, [r4, #0x1f4] @ get dma
adreq \base, irq_prio_d
- teqeq \irqnr, #0
+ teqeq \irqstat, #0
#endif
- ldreqb \irqnr, [r4, #0x14] @ get low priority
+ ldreqb \irqstat, [r4, #0x14] @ get low priority
adreq \base, irq_prio_l
+
+ teq \irqstat, #0
+ ldrneb \irqnr, [r5, \irqstat] @ get IRQ number
.endm
/*
@@ -160,10 +154,13 @@ irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base
mov r4, #0xf3000000
- ldrb \irqnr, [r4] @ get interrupts
+ ldrb \irqstat, [r4] @ get interrupts
adr \base, irq_prio_ebsa110
+
+ teq \irqstat, #0
+ ldrneb \irqnr, [r5, \irqstat] @ get IRQ number
.endm
.macro irq_prio_table
@@ -189,6 +186,26 @@ irq_prio_ebsa110:
.byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
.endm
+#elif defined(CONFIG_ARCH_EBSA285)
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base
+ mov r4, #0xfe000000
+ ldr \irqstat, [r4, #0x180] @ get interrupts
+ mov \irqnr, #0
+1001: tst \irqstat, #1
+ addeq \irqnr, \irqnr, #1
+ moveq \irqstat, \irqstat, lsr #1
+ tsteq \irqnr, #32
+ beq 1001b
+ teq \irqnr, #32
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
#else
#error Unknown architecture
#endif
@@ -267,6 +284,16 @@ irq_prio_ebsa110:
.endm
/*=============================================================================
+ * Address exception handler
+ *-----------------------------------------------------------------------------
+ * These aren't too critical.
+ * (they're not supposed to happen, and won't happen in 32-bit mode).
+ */
+
+vector_addrexcptn:
+ b vector_addrexcptn
+
+/*=============================================================================
* Undefined FIQs
*-----------------------------------------------------------------------------
* Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
@@ -400,86 +427,6 @@ vector_data: @
b __dabt_svc @ 3 (SVC_26 / SVC_32)
/*=============================================================================
- * Undefined instruction handler
- *-----------------------------------------------------------------------------
- * Handles floating point instructions
- */
-__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
- stmia sp, {r0 - r12} @ Save r0 - r12
- add r8, sp, #S_PC
- stmdb r8, {sp, lr}^ @ Save user r0 - r12
- ldr r4, .LCund
- ldmia r4, {r5 - r7}
- stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
- mov fp, #0
-
- adr r1, .LC2
- ldmia r1, {r1, r4}
- ldr r1, [r1]
- get_current_task r2
- teq r1, r2
- blne SYMBOL_NAME(math_state_restore)
- adrsvc, al, r9, SYMBOL_NAME(fpreturn)
- adrsvc al, lr, SYMBOL_NAME(fpundefinstr)
- ldr pc, [r4] @ Call FP module USR entry point
-
- .globl SYMBOL_NAME(fpundefinstr)
-SYMBOL_NAME(fpundefinstr): @ Called by FP module on undefined instr
- mov r0, lr
- mov r1, sp
- mrs r4, cpsr @ Enable interrupts
- bic r4, r4, #I_BIT
- msr cpsr, r4
- bl SYMBOL_NAME(do_undefinstr)
- b ret_from_exception @ Normal FP exit
-
-__und_svc: sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - r12} @ save r0 - r12
- mov r6, lr
- ldr r7, .LCund
- ldmia r7, {r7 - r9}
- add r5, sp, #S_FRAME_SIZE
- add r4, sp, #S_SP
- stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
-
- adr r1, .LC2
- ldmia r1, {r1, r4}
- ldr r1, [r1]
- mov r2, sp, lsr #13
- mov r2, r2, lsl #13
- teq r1, r2
- blne SYMBOL_NAME(math_state_restore)
- adrsvc al, r9, SYMBOL_NAME(fpreturnsvc)
- adrsvc al, lr, SYMBOL_NAME(fpundefinstrsvc)
- ldr pc, [r4] @ Call FP module SVC entry point
-
- .globl SYMBOL_NAME(fpundefinstrsvc)
-SYMBOL_NAME(fpundefinstrsvc):
- mov r0, r5 @ unsigned long pc
- mov r1, sp @ struct pt_regs *regs
- bl SYMBOL_NAME(do_undefinstr)
-
- .globl SYMBOL_NAME(fpreturnsvc)
-SYMBOL_NAME(fpreturnsvc):
- ldr lr, [sp, #S_PSR] @ Get SVC cpsr
- msr spsr, lr
- ldmia sp, {r0 - pc}^ @ Restore SVC registers
-
-.LC2: .word SYMBOL_NAME(last_task_used_math)
- .word SYMBOL_NAME(fp_enter)
-
-__und_invalid: sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - lr}
- mov r7, r0
- ldr r4, .LCund
- ldmia r4, {r5, r6} @ Get UND/IRQ/FIQ/ABT pc, cpsr
- add r4, sp, #S_PC
- stmia r4, {r5, r6, r7} @ Save UND/IRQ/FIQ/ABT pc, cpsr, old_r0
- mov r0, sp @ struct pt_regs *regs
- mov r1, #BAD_UNDEFINSTR @ int reason
- and r2, r6, #31 @ int mode
- b SYMBOL_NAME(bad_mode) @ Does not ever return...
-/*=============================================================================
* Prefetch abort handler
*-----------------------------------------------------------------------------
*/
@@ -531,14 +478,62 @@ t: .ascii "*** undef ***\r\n\0"
#endif
/*=============================================================================
- * Address exception handler
+ * Data abort handler code
*-----------------------------------------------------------------------------
- * These aren't too critical.
- * (they're not supposed to happen, and won't happen in 32-bit mode).
*/
+.LCprocfns: .word SYMBOL_NAME(processor)
-vector_addrexcptn:
- b vector_addrexcptn
+__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
+ stmia sp, {r0 - r12} @ save r0 - r12
+ add r3, sp, #S_PC
+ stmdb r3, {sp, lr}^
+ ldr r0, .LCabt
+ ldmia r0, {r0 - r2} @ Get USR pc, cpsr
+ stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0
+ mov fp, #0
+ mrs r2, cpsr @ Enable interrupts if they were
+ bic r2, r2, #I_BIT @ previously
+ msr cpsr, r2
+ ldr r2, .LCprocfns
+ mov lr, pc
+ ldr pc, [r2, #8] @ call processor specific code
+ mov r3, sp
+ bl SYMBOL_NAME(do_DataAbort)
+ b ret_from_sys_call
+
+__dabt_svc: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ save r0 - r12
+ ldr r2, .LCabt
+ add r0, sp, #S_FRAME_SIZE
+ add r5, sp, #S_SP
+ mov r1, lr
+ ldmia r2, {r2 - r4} @ get pc, cpsr
+ stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+ tst r3, #I_BIT
+ mrseq r0, cpsr @ Enable interrupts if they were
+ biceq r0, r0, #I_BIT @ previously
+ msreq cpsr, r0
+ mov r0, r2
+ ldr r2, .LCprocfns
+ mov lr, pc
+ ldr pc, [r2, #8] @ call processor specific code
+ mov r3, sp
+ bl SYMBOL_NAME(do_DataAbort)
+ ldr r0, [sp, #S_PSR]
+ msr spsr, r0
+ ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+
+__dabt_invalid: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact]
+ mov r7, r0
+ ldr r4, .LCabt
+ ldmia r4, {r5, r6} @ Get SVC pc, cpsr
+ add r4, sp, #S_PC
+ stmia r4, {r5, r6, r7} @ Save SVC pc, cpsr, old_r0
+ mov r0, sp
+ mov r1, #BAD_DATA
+ and r2, r6, #31
+ b SYMBOL_NAME(bad_mode)
/*=============================================================================
* Interrupt (IRQ) handler
@@ -551,9 +546,7 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE
ldr r4, .LCirq
ldmia r4, {r5 - r7} @ get saved PC, SPSR
stmia r8, {r5 - r7} @ save pc, psr, old_r0
-1: get_irqnr_and_base r6, r5
- teq r6, #0
- ldrneb r0, [r5, r6] @ get IRQ number
+1: get_irqnr_and_base r0, r6, r5
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@@ -572,9 +565,7 @@ __irq_svc: sub sp, sp, #S_FRAME_SIZE
add r5, sp, #S_FRAME_SIZE
add r4, sp, #S_SP
stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
-1: get_irqnr_and_base r6, r5
- teq r6, #0
- ldrneb r0, [r5, r6] @ get IRQ number
+1: get_irqnr_and_base r0, r6, r5
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@@ -598,63 +589,85 @@ __irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame
b SYMBOL_NAME(bad_mode)
/*=============================================================================
- * Data abort handler code
+ * Undefined instruction handler
*-----------------------------------------------------------------------------
+ * Handles floating point instructions
*/
-.LCprocfns: .word SYMBOL_NAME(processor)
-
-__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
- stmia sp, {r0 - r12} @ save r0 - r12
- add r3, sp, #S_PC
- stmdb r3, {sp, lr}^
- ldr r0, .LCabt
- ldmia r0, {r0 - r2} @ Get USR pc, cpsr
- stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0
+__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
+ stmia sp, {r0 - r12} @ Save r0 - r12
+ add r8, sp, #S_PC
+ stmdb r8, {sp, lr}^ @ Save user r0 - r12
+ ldr r4, .LCund
+ ldmia r4, {r5 - r7}
+ stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
mov fp, #0
- mrs r2, cpsr @ Enable interrupts if they were
- bic r2, r2, #I_BIT @ previously
- msr cpsr, r2
- ldr r2, .LCprocfns
- mov lr, pc
- ldr pc, [r2, #8] @ call processor specific code
- mov r3, sp
- bl SYMBOL_NAME(do_DataAbort)
- b ret_from_sys_call
-__dabt_svc: sub sp, sp, #S_FRAME_SIZE
+ adr r1, .LC2
+ ldmia r1, {r1, r4}
+ ldr r1, [r1]
+ get_current_task r2
+ teq r1, r2
+ blne SYMBOL_NAME(math_state_restore)
+ adrsvc al, r9, SYMBOL_NAME(fpreturn)
+ adrsvc al, lr, SYMBOL_NAME(fpundefinstr)
+ ldr pc, [r4] @ Call FP module USR entry point
+
+ .globl SYMBOL_NAME(fpundefinstr)
+SYMBOL_NAME(fpundefinstr): @ Called by FP module on undefined instr
+ mov r0, lr
+ mov r1, sp
+ mrs r4, cpsr @ Enable interrupts
+ bic r4, r4, #I_BIT
+ msr cpsr, r4
+ bl SYMBOL_NAME(do_undefinstr)
+ b ret_from_exception @ Normal FP exit
+
+__und_svc: sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ save r0 - r12
- ldr r2, .LCabt
- add r0, sp, #S_FRAME_SIZE
- add r5, sp, #S_SP
- mov r1, lr
- ldmia r2, {r2 - r4} @ get pc, cpsr
- stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
- tst r3, #I_BIT
- mrseq r0, cpsr @ Enable interrupts if they were
- biceq r0, r0, #I_BIT @ previously
- msreq cpsr, r0
- mov r0, r2
- ldr r2, .LCprocfns
- mov lr, pc
- ldr pc, [r2, #8] @ call processor specific code
- mov r3, sp
- bl SYMBOL_NAME(do_DataAbort)
- ldr r0, [sp, #S_PSR]
- msr spsr, r0
- ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+ mov r6, lr
+ ldr r7, .LCund
+ ldmia r7, {r7 - r9}
+ add r5, sp, #S_FRAME_SIZE
+ add r4, sp, #S_SP
+ stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
-__dabt_invalid: sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact]
+ adr r1, .LC2
+ ldmia r1, {r1, r4}
+ ldr r1, [r1]
+ mov r2, sp, lsr #13
+ mov r2, r2, lsl #13
+ teq r1, r2
+ blne SYMBOL_NAME(math_state_restore)
+ adrsvc al, r9, SYMBOL_NAME(fpreturnsvc)
+ adrsvc al, lr, SYMBOL_NAME(fpundefinstrsvc)
+ ldr pc, [r4] @ Call FP module SVC entry point
+
+ .globl SYMBOL_NAME(fpundefinstrsvc)
+SYMBOL_NAME(fpundefinstrsvc):
+ mov r0, r5 @ unsigned long pc
+ mov r1, sp @ struct pt_regs *regs
+ bl SYMBOL_NAME(do_undefinstr)
+
+ .globl SYMBOL_NAME(fpreturnsvc)
+SYMBOL_NAME(fpreturnsvc):
+ ldr lr, [sp, #S_PSR] @ Get SVC cpsr
+ msr spsr, lr
+ ldmia sp, {r0 - pc}^ @ Restore SVC registers
+
+.LC2: .word SYMBOL_NAME(last_task_used_math)
+ .word SYMBOL_NAME(fp_enter)
+
+__und_invalid: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - lr}
mov r7, r0
- ldr r4, .LCabt
- ldmia r4, {r5, r6} @ Get SVC pc, cpsr
+ ldr r4, .LCund
+ ldmia r4, {r5, r6} @ Get UND/IRQ/FIQ/ABT pc, cpsr
add r4, sp, #S_PC
- stmia r4, {r5, r6, r7} @ Save SVC pc, cpsr, old_r0
- mov r0, sp
- mov r1, #BAD_DATA
- and r2, r6, #31
- b SYMBOL_NAME(bad_mode)
-
+ stmia r4, {r5, r6, r7} @ Save UND/IRQ/FIQ/ABT pc, cpsr, old_r0
+ mov r0, sp @ struct pt_regs *regs
+ mov r1, #BAD_UNDEFINSTR @ int reason
+ and r2, r6, #31 @ int mode
+ b SYMBOL_NAME(bad_mode) @ Does not ever return...
#include "entry-common.S"
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 5725e1781..98c41266f 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -1,56 +1,54 @@
-/*
- *=============================================================================
- * Low-level interface code
- *-----------------------------------------------------------------------------
- * Trap initialisation
- *-----------------------------------------------------------------------------
- *
- * Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20
- * that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes
- * some excess cycles).
- *
- * What we need to put into 0-0x1c are ldrs to branch to 0xC0000000
- * (the kernel).
- * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for
- * the actuall address to jump to.
- */
-/*
- * these go into 0x00
- */
-.Lbranches: swi SYS_ERROR0
- ldr pc, .Lbranches + 0xe4
- ldr pc, .Lbranches + 0xe8
- ldr pc, .Lbranches + 0xec
- ldr pc, .Lbranches + 0xf0
- ldr pc, .Lbranches + 0xf4
- ldr pc, .Lbranches + 0xf8
- ldr pc, .Lbranches + 0xfc
-/*
- * this is put into 0xe4 and above
- */
-.Ljump_addresses:
- .word vector_undefinstr @ 0xe4
- .word vector_swi @ 0xe8
- .word vector_prefetch @ 0xec
- .word vector_data @ 0xf0
- .word vector_addrexcptn @ 0xf4
- .word vector_IRQ @ 0xf8
- .word _unexp_fiq @ 0xfc
-/*
- * initialise the trap system
+/*============================================================================
+ * All exits to user mode from the kernel go through this code.
*/
-ENTRY(trap_init)
- stmfd sp!, {r4 - r7, lr}
- initialise_traps_extra
- mov r0, #0xe4
- adr r1, .Ljump_addresses
- ldmia r1, {r1 - r6}
- stmia r0, {r1 - r6}
- mov r0, #0
- adr r1, .Lbranches
- ldmia r1, {r1 - r7}
- stmia r0, {r1 - r7}
- LOADREGS(fd, sp!, {r4 - r7, pc})
+
+ .globl ret_from_sys_call
+
+ .globl SYMBOL_NAME(fpreturn)
+SYMBOL_NAME(fpreturn):
+ret_from_exception:
+ adr r0, 1f
+ ldmia r0, {r0, r1}
+ ldr r0, [r0]
+ ldr r1, [r1]
+ tst r0, r1
+ blne SYMBOL_NAME(do_bottom_half)
+ret_from_intr: ldr r0, [sp, #S_PSR]
+ tst r0, #3
+ beq ret_with_reschedule
+ b ret_from_all
+
+ret_signal: mov r1, sp
+ adrsvc al, lr, ret_from_all
+ b SYMBOL_NAME(do_signal)
+
+2: bl SYMBOL_NAME(schedule)
+
+ret_from_sys_call:
+ adr r0, 1f
+ ldmia r0, {r0, r1}
+ ldr r0, [r0]
+ ldr r1, [r1]
+ tst r0, r1
+ adrsvc ne, lr, ret_from_intr
+ bne SYMBOL_NAME(do_bottom_half)
+
+ret_with_reschedule:
+ ldr r0, 1f + 8
+ ldr r0, [r0]
+ teq r0, #0
+ bne 2b
+
+ get_current_task r1
+ ldr r1, [r1, #TSK_SIGPENDING]
+ teq r1, #0
+ bne ret_signal
+
+ret_from_all: restore_user_regs
+
+1: .word SYMBOL_NAME(bh_mask)
+ .word SYMBOL_NAME(bh_active)
+ .word SYMBOL_NAME(need_resched)
/*=============================================================================
* SWI handler
@@ -77,7 +75,7 @@ vector_swi: save_user_regs
bcs 2f
get_current_task r5
- ldr ip, [r5, #FLAGS] @ check for syscall tracing
+ ldr ip, [r5, #TSK_FLAGS] @ check for syscall tracing
tst ip, #PF_TRACESYS
bne 1f
@@ -91,7 +89,7 @@ vector_swi: save_user_regs
1: ldr r7, [sp, #S_IP] @ save old IP
mov r0, #0
- str r7, [sp, #S_IP] @ trace entry [IP = 0]
+ str r0, [sp, #S_IP] @ trace entry [IP = 0]
bl SYMBOL_NAME(syscall_trace)
str r7, [sp, #S_IP]
ldmia sp, {r0 - r3} @ have to reload r0 - r3
@@ -193,57 +191,59 @@ sys_rt_sigreturn_wrapper:
add r0, sp, #4
b SYMBOL_NAME(sys_rt_sigreturn)
-/*============================================================================
- * All exits to user mode from the kernel go through this code.
+/*
+ *=============================================================================
+ * Low-level interface code
+ *-----------------------------------------------------------------------------
+ * Trap initialisation
+ *-----------------------------------------------------------------------------
+ *
+ * Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20
+ * that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes
+ * some excess cycles).
+ *
+ * What we need to put into 0-0x1c are ldrs to branch to 0xC0000000
+ * (the kernel).
+ * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for
+ * the actuall address to jump to.
*/
-
- .globl ret_from_sys_call
-
- .globl SYMBOL_NAME(fpreturn)
-SYMBOL_NAME(fpreturn):
-ret_from_exception:
- adr r0, 1f
- ldmia r0, {r0, r1}
- ldr r0, [r0]
- ldr r1, [r1]
- tst r0, r1
- blne SYMBOL_NAME(do_bottom_half)
-ret_from_intr: ldr r0, [sp, #S_PSR]
- tst r0, #3
- beq ret_with_reschedule
- b ret_from_all
-
-ret_signal: mov r1, sp
- adrsvc al, lr, ret_from_all
- b SYMBOL_NAME(do_signal)
-
-2: bl SYMBOL_NAME(schedule)
-
-ret_from_sys_call:
- adr r0, 1f
- ldmia r0, {r0, r1}
- ldr r0, [r0]
- ldr r1, [r1]
- tst r0, r1
- adrsvc ne, lr, ret_from_intr
- bne SYMBOL_NAME(do_bottom_half)
-
-ret_with_reschedule:
- ldr r0, 1f + 8
- ldr r0, [r0]
- teq r0, #0
- bne 2b
-
- get_current_task r1
- ldr r1, [r1, #SIGPENDING]
- teq r1, #0
- bne ret_signal
-
-ret_from_all: restore_user_regs
-
-1: .word SYMBOL_NAME(bh_mask)
- .word SYMBOL_NAME(bh_active)
- .word SYMBOL_NAME(need_resched)
+/*
+ * these go into 0x00
+ */
+.Lbranches: swi SYS_ERROR0
+ ldr pc, .Lbranches + 0xe4
+ ldr pc, .Lbranches + 0xe8
+ ldr pc, .Lbranches + 0xec
+ ldr pc, .Lbranches + 0xf0
+ ldr pc, .Lbranches + 0xf4
+ ldr pc, .Lbranches + 0xf8
+ ldr pc, .Lbranches + 0xfc
+/*
+ * this is put into 0xe4 and above
+ */
+.Ljump_addresses:
+ .word vector_undefinstr @ 0xe4
+ .word vector_swi @ 0xe8
+ .word vector_prefetch @ 0xec
+ .word vector_data @ 0xf0
+ .word vector_addrexcptn @ 0xf4
+ .word vector_IRQ @ 0xf8
+ .word _unexp_fiq @ 0xfc
+/*
+ * initialise the trap system
+ */
+ENTRY(trap_init)
+ stmfd sp!, {r4 - r7, lr}
+ initialise_traps_extra
+ mov r0, #0xe4
+ adr r1, .Ljump_addresses
+ ldmia r1, {r1 - r6}
+ stmia r0, {r1 - r6}
+ mov r0, #0
+ adr r1, .Lbranches
+ ldmia r1, {r1 - r7}
+ stmia r0, {r1 - r7}
+ LOADREGS(fd, sp!, {r4 - r7, pc})
/*============================================================================
* FP support
diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S
index 7bd69ed5f..80d88e890 100644
--- a/arch/arm/kernel/head-armo.S
+++ b/arch/arm/kernel/head-armo.S
@@ -42,7 +42,7 @@ Lcontinue: str r5, [r6]
b SYMBOL_NAME(start_kernel)
LC1: .word SYMBOL_NAME(_stext)
-LC0: .word SYMBOL_NAME(_edata)
+LC0: .word SYMBOL_NAME(__bss_start)
.word SYMBOL_NAME(arm_id)
.word SYMBOL_NAME(_end)
.word SYMBOL_NAME(init_task_union)+8192
diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S
index 0af401e43..e53b7144f 100644
--- a/arch/arm/kernel/head-armv.S
+++ b/arch/arm/kernel/head-armv.S
@@ -16,19 +16,21 @@
.globl __stext
/*
* Entry point and restart point. Entry *must* be called with r0 == 0,
- * MMU off.
+ * MMU off. Note! These should be unique!!! Please read Documentation/ARM-README
+ * for more information.
*
- * r1 = 0 -> ebsa (Ram @ 0x00000000)
- * r1 = 1 -> RPC (Ram @ 0x10000000)
- * r1 = 2 -> ebsit (???)
+ * r1 = 0 -> ebsa110 (Ram @ 0x00000000)
+ * r1 = 1 -> RPC (Ram @ 0x10000000)
+ * r1 = 2 -> ebsit (???)
* r1 = 3 -> nexuspci
+ * r1 = 4 -> ebsa285 (Ram @ 0x00000000)
*/
ENTRY(stext)
ENTRY(_stext)
__entry:
teq r0, #0 @ check for illegal entry...
bne .Lerror @ loop indefinitely
- cmp r1, #4 @ Unknown machine architecture
+ cmp r1, #5 @ Unknown machine architecture
bge .Lerror
@
@ First thing to do is to get the page tables set up so that we can call the kernel
@@ -57,18 +59,23 @@ __entry:
adr r4, .LCMachTypes
add r4, r4, r1, lsl #4
- ldmia r4, {r4, r5, r6} @ r4 = page dir in physical ram
-
+ ldmia r4, {r4, r5, r6}
+/*
+ * r4 = page dir in physical ram
+ * r5 = physical address of start of RAM
+ * r6 = I/O address
+ */
mov r0, r4
mov r1, #0
add r2, r0, #0x4000
1: str r1, [r0], #4 @ Clear page table
teq r0, r2
bne 1b
-@
-@ Add enough entries to allow the kernel to be called.
-@ It will sort out the real mapping in paging_init
-@
+/*
+ * Add enough entries to allow the kernel to be called.
+ * It will sort out the real mapping in paging_init.
+ * We map in 2MB of memory into 0xC0000000 - 0xC0200000
+ */
add r0, r4, #0x3000
mov r1, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE
orr r1, r1, r8
@@ -121,7 +128,7 @@ __entry:
.Lbranch: .long .Lalready_done_mmap @ Real address of routine
- @ EBSA (pg dir phys, phys ram start, phys i/o)
+ @ EBSA110 (pg dir phys, phys ram start, phys i/o)
.LCMachTypes: .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical)
.long 0 @ Address of RAM
.long 0xe0000000 @ I/O address
@@ -145,6 +152,14 @@ __entry:
.long 0x10000000
.long 0
+ @ EBSA285
+ .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical)
+ .long 0 @ Address of RAM
+ .long 0x24000000 @ I/O base address (0x42000000 -> 0xFE000000)
+ .long 0
+
+
+
.LCProcTypes: @ ARM6 / 610
.long 0x41560600
.long 0xffffff00
@@ -168,7 +183,7 @@ __entry:
.long 0
-.LC0: .long SYMBOL_NAME(_edata)
+.LC0: .long SYMBOL_NAME(__bss_start)
.long SYMBOL_NAME(arm_id)
.long SYMBOL_NAME(_end)
.long SYMBOL_NAME(init_task_union)+8192
@@ -231,19 +246,84 @@ __entry:
b SYMBOL_NAME(start_kernel)
#if 1
+
+#if defined(CONFIG_ARCH_RPC)
+ .macro addruart,rx
+ mov \rx, #0xe0000000
+ orr \rx, \rx, #0x00010000
+ orr \rx, \rx, #0x00000fe0
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx]
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldrb \rd, [\rx, #0x14]
+ and \rd, \rd, #0x60
+ bne 1002b
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldrb \rd, [\rx, #0x18]
+ tst \rd, #0x10
+ beq 1001b
+ .endm
+
+#elif defined(CONFIG_ARCH_EBSA110)
+ .macro addruart,rx
+ mov \rx, #0xf0000000
+ orr \rx, \rx, #0x00000be0
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx]
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldrb \rd, [\rx, #0x14]
+ and \rd, \rd, #0x60
+ bne 1002b
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldrb \rd, [\rx, #0x18]
+ tst \rd, #0x10
+ beq 1001b
+ .endm
+
+#elif defined(CONFIG_ARCH_EBSA285)
+ .macro addruart,rx
+ mov \rx, #0xfe000000
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #0x160] @ UARTDR
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #0x178] @ UARTFLG
+ tst \rd, #1 << 3
+ bne 1001b
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
+#endif
+
/*
* Useful debugging routines
*/
- .globl _printhex8
-_printhex8: mov r1, #8
+ENTRY(printhex8)
+ mov r1, #8
b printhex
- .globl _printhex4
-_printhex4: mov r1, #4
+ENTRY(printhex4)
+ mov r1, #4
b printhex
- .globl _printhex2
-_printhex2: mov r1, #2
+ENTRY(printhex2)
+ mov r1, #2
printhex: ldr r2, =hexbuf
add r3, r2, r1
mov r1, #0
@@ -258,46 +338,23 @@ printhex: ldr r2, =hexbuf
bne 1b
mov r0, r2
- .globl _printascii
-_printascii:
-#ifdef CONFIG_ARCH_RPC
- mov r3, #0xe0000000
- orr r3, r3, #0x00010000
- orr r3, r3, #0x00000fe0
-#else
- mov r3, #0xf0000000
- orr r3, r3, #0x0be0
-#endif
- b 3f
-1: ldrb r2, [r3, #0x18]
- tst r2, #0x10
- beq 1b
- strb r1, [r3]
-2: ldrb r2, [r3, #0x14]
- and r2, r2, #0x60
- teq r2, #0x60
- bne 2b
+ENTRY(printascii)
+ addruart r3
+ b 2f
+1: waituart r2, r3
+ senduart r1, r3
+ busyuart r2, r3
teq r1, #'\n'
moveq r1, #'\r'
beq 1b
-3: teq r0, #0
+2: teq r0, #0
ldrneb r1, [r0], #1
teqne r1, #0
bne 1b
mov pc, lr
- .ltorg
-
- .globl _printch
-_printch:
-#ifdef CONFIG_ARCH_RPC
- mov r3, #0xe0000000
- orr r3, r3, #0x00010000
- orr r3, r3, #0x00000fe0
-#else
- mov r3, #0xf0000000
- orr r3, r3, #0x0be0
-#endif
+ENTRY(printch)
+ addruart r3
mov r1, r0
mov r0, #0
b 1b
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index e0fb7540a..1dde0e0ba 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -33,16 +33,10 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/hardware.h>
-#include <asm/irq-no.h>
#include <asm/arch/irq.h>
+unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS];
-#ifdef __SMP__
-atomic_t __arm_bh_counter;
-#else
-int __arm_bh_counter;
-#endif
-
spinlock_t irq_controller_lock;
#ifndef SMP
@@ -80,13 +74,21 @@ void enable_irq(unsigned int irq_nr)
struct irqaction *irq_action[NR_IRQS];
-/*
- * Bitmask indicating valid interrupt numbers
+#ifdef CONFIG_ARCH_ACORN
+/* Bitmask indicating valid interrupt numbers
+ * (to be moved to include/asm-arm/arch-*)
*/
unsigned long validirqs[NR_IRQS / 32] = {
- 0x003fffff, 0x000001ff, 0x000000ff, 0x00000000
+ 0x003ffe7f, 0x000001ff, 0x000000ff, 0x00000000
};
+#define valid_irq(x) ((x) < NR_IRQS && validirqs[(x) >> 5] & (1 << ((x) & 31)))
+#else
+
+#define valid_irq(x) ((x) < NR_IRQS)
+
+#endif
+
int get_irq_list(char *buf)
{
int i;
@@ -98,7 +100,7 @@ int get_irq_list(char *buf)
if (!action)
continue;
p += sprintf(p, "%3d: %10u %s",
- i, kstat.interrupts[i], action->name);
+ i, kstat_irqs(i), action->name);
for (action = action->next; action; action = action->next) {
p += sprintf(p, ", %s", action->name);
}
@@ -126,7 +128,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
cpu = smp_processor_id();
irq_enter(cpu, irq);
- kstat.interrupts[irq]++;
+ kstat.irqs[cpu][irq]++;
/* Return with this interrupt masked if no action */
status = 0;
@@ -143,13 +145,26 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
__cli();
+
+ switch (irq) {
#if defined(HAS_IOMD) || defined(HAS_IOC)
- if (irq != IRQ_KEYBOARDTX && irq != IRQ_EXPANSIONCARD)
+ case IRQ_KEYBOARDTX:
+ case IRQ_EXPANSIONCARD:
+ break;
+#endif
+#ifdef HAS_IOMD
+ case IRQ_DMA0:
+ case IRQ_DMA1:
+ case IRQ_DMA2:
+ case IRQ_DMA3:
+ break;
#endif
- {
+
+ default:
spin_lock(&irq_controller_lock);
unmask_irq(irq);
spin_unlock(&irq_controller_lock);
+ break;
}
}
@@ -235,7 +250,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
unsigned long retval;
struct irqaction *action;
- if (irq >= NR_IRQS || !(validirqs[irq >> 5] & (1 << (irq & 31))))
+ if (!valid_irq(irq))
return -EINVAL;
if (!handler)
return -EINVAL;
@@ -263,7 +278,7 @@ void free_irq(unsigned int irq, void *dev_id)
struct irqaction * action, **p;
unsigned long flags;
- if (irq >= NR_IRQS || !(validirqs[irq >> 5] & (1 << (irq & 31)))) {
+ if (!valid_irq(irq)) {
printk(KERN_ERR "Trying to free IRQ%d\n",irq);
#ifdef CONFIG_DEBUG_ERRORS
__backtrace();
@@ -294,7 +309,7 @@ unsigned long probe_irq_on (void)
/* first snaffle up any unassigned irqs */
for (i = 15; i > 0; i--) {
- if (!irq_action[i]) {
+ if (!irq_action[i] && valid_irq(i)) {
enable_irq(i);
irqs |= 1 << i;
}
@@ -323,5 +338,7 @@ int probe_irq_off (unsigned long irqs)
__initfunc(void init_IRQ(void))
{
+ extern void init_dma(void);
irq_init_irq();
+ init_dma();
}
diff --git a/arch/arm/kernel/leds-ebsa285.c b/arch/arm/kernel/leds-ebsa285.c
new file mode 100644
index 000000000..f8add1ab7
--- /dev/null
+++ b/arch/arm/kernel/leds-ebsa285.c
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/kernel/leds-285.c
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * EBSA-285 LED control routines. We use the leds as follows:
+ *
+ * - Green - toggles state every 50 timer interrupts
+ * - Amber - On if system is not idle
+ * - Red - currently unused
+ */
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+static char led_state = XBUS_LED_RED | XBUS_LED_GREEN;
+
+void leds_event(led_event_t ledevt)
+{
+ unsigned long flags;
+
+ save_flags_cli(flags);
+
+ switch(ledevt) {
+ case led_idle_start:
+ led_state |= XBUS_LED_AMBER;
+ break;
+
+ case led_idle_end:
+ led_state &= ~XBUS_LED_AMBER;
+ break;
+
+ case led_timer:
+ led_state ^= XBUS_LED_GREEN;
+ break;
+
+ default:
+ break;
+ }
+
+ restore_flags(flags);
+
+ *XBUS_LEDS = led_state;
+}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 7f45e7c3c..9372539ef 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -69,8 +69,10 @@ asmlinkage int sys_idle(void)
current->priority = -100;
for (;;)
{
+#if 0 //def ARCH_IDLE_OK
if (!hlt_counter && !need_resched)
proc_idle ();
+#endif
run_task_queue(&tq_scheduler);
schedule();
}
@@ -142,7 +144,7 @@ void show_regs(struct pt_regs * regs)
" mrc p15, 0, %1, c2, c0\n"
" mrc p15, 0, %2, c3, c0\n"
: "=r" (ctrl), "=r" (transbase), "=r" (dac));
- printk("Control: %04X Table: %08X DAC: %08X",
+ printk("Control: %04X Table: %08X DAC: %08X ",
ctrl, transbase, dac);
}
#endif
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 5fa67df6c..f95e8de7e 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -27,18 +27,6 @@
*/
#define BREAKINST 0xef9f0001
-/* change a pid into a task struct. */
-static inline struct task_struct * get_task(int pid)
-{
- int i;
-
- for (i = 1; i < NR_TASKS; i++) {
- if (task[i] != NULL && (task[i]->pid == pid))
- return task[i];
- }
- return NULL;
-}
-
/*
* this routine will get a word off of the processes privileged stack.
* the offset is how far from the base addr as stored in the TSS.
@@ -581,7 +569,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if (pid == 1) /* you may not mess with init */
goto out;
ret = -ESRCH;
- if (!(child = get_task(pid)))
+ if (!(child = find_task_by_pid(pid)))
goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) {
diff --git a/arch/arm/kernel/setup-ebsa110.c b/arch/arm/kernel/setup-ebsa110.c
index 285284b7d..8cbfe7dc3 100644
--- a/arch/arm/kernel/setup-ebsa110.c
+++ b/arch/arm/kernel/setup-ebsa110.c
@@ -26,62 +26,95 @@
#include <linux/delay.h>
#include <linux/major.h>
#include <linux/utsname.h>
+#include <linux/init.h>
-#include <asm/segment.h>
-#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <asm/setup.h>
+#include <asm/system.h>
#ifndef CONFIG_CMDLINE
#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8"
#endif
+#define COMMAND_LINE_SIZE 256
+
#define MEM_SIZE (16*1024*1024)
-#define COMMAND_LINE_SIZE 256
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+ char saved_command_line[COMMAND_LINE_SIZE];
+struct processor processor;
+struct screen_info screen_info;
unsigned char aux_device_present;
unsigned long arm_id;
+
extern int root_mountflags;
extern int _etext, _edata, _end;
+extern const struct processor sa110_processor_functions;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_image_start; /* starting block # of image */
-static inline void setup_ramdisk (void)
+static inline void setup_ramdisk(int start, int prompt, int load)
{
- rd_image_start = 0;
- rd_prompt = 1;
- rd_doload = 1;
+ rd_image_start = start;
+ rd_prompt = prompt;
+ rd_doload = load;
}
#else
-#define setup_ramdisk()
+#define setup_ramdisk(start,prompt,load)
#endif
+#ifdef PARAMS_BASE
+static struct param_struct *params = (struct param_struct *)PARAMS_BASE;
+
+static inline char *setup_params(unsigned long *mem_end_p)
+{
+ ROOT_DEV = to_kdev_t(params->u1.s.rootdev);
+ ORIG_X = params->u1.s.video_x;
+ ORIG_Y = params->u1.s.video_y;
+ ORIG_VIDEO_COLS = params->u1.s.video_num_cols;
+ ORIG_VIDEO_LINES = params->u1.s.video_num_rows;
+
+ setup_ramdisk(params->u1.s.rd_start,
+ (params->u1.s.flags & FLAG_RDPROMPT) == 0,
+ (params->u1.s.flags & FLAG_RDLOAD) == 0);
+
+ *mem_end_p = 0xc0000000 + MEM_SIZE;
+
+ return params->commandline;
+}
+#else
static char default_command_line[] = CONFIG_CMDLINE;
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
- char saved_command_line[COMMAND_LINE_SIZE];
-struct processor processor;
-extern const struct processor sa110_processor_functions;
+static inline char *setup_params(unsigned long *mem_end_p)
+{
+ ROOT_DEV = 0x00ff;
+
+ setup_ramdisk(0, 1, 1);
+
+ *mem_end_p = 0xc0000000 + MEM_SIZE;
+
+ return default_command_line;
+}
+#endif
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+__initfunc(void setup_arch(char **cmdline_p,
+ unsigned long * memory_start_p, unsigned long * memory_end_p))
{
unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from;
int len = 0;
memory_start = (unsigned long)&_end;
- memory_end = 0xc0000000 + MEM_SIZE;
- from = default_command_line;
processor = sa110_processor_functions;
- processor._proc_init ();
+ processor._proc_init();
- ROOT_DEV = 0x00ff;
- setup_ramdisk();
+ from = setup_params(&memory_end);
init_task.mm->start_code = TASK_SIZE;
init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index ac304fb3e..a3b86fef7 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -26,15 +26,16 @@
#include <linux/major.h>
#include <linux/utsname.h>
#include <linux/blk.h>
+#include <linux/init.h>
-#include <asm/segment.h>
-#include <asm/system.h>
#include <asm/hardware.h>
+#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/arch/mmu.h>
#include <asm/procinfo.h>
-#include <asm/io.h>
+#include <asm/segment.h>
#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/arch/mmu.h>
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
@@ -153,13 +154,17 @@ static void setup_initrd (struct param_struct *params, unsigned long memory_end)
#define setup_initrd(p,m)
#endif
+#ifdef IOEB_BASE
static inline void check_ioeb_present(void)
{
if (((*IOEB_BASE) & 15) == 5)
armidlist[armidindex].features |= F_IOEB;
}
+#else
+#define check_ioeb_present()
+#endif
-static void get_processor_type (void)
+static inline void get_processor_type (void)
{
for (armidindex = 0; ; armidindex ++)
if (!((armidlist[armidindex].id ^ arm_id) &
@@ -179,11 +184,14 @@ static void get_processor_type (void)
#define COMMAND_LINE_SIZE 256
+/* Can this be initdata? --pb
+ * command_line can be, saved_command_line can't though
+ */
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+__initfunc(void setup_arch(char **cmdline_p,
+ unsigned long * memory_start_p, unsigned long * memory_end_p))
{
static unsigned char smptrap;
unsigned long memory_start, memory_end;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index b1c679ec5..1f598e14d 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/smp.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -30,7 +31,6 @@
#include <asm/delay.h>
#include <linux/timex.h>
-#include <asm/irq-no.h>
#include <asm/hardware.h>
extern int setup_arm_irq(int, struct irqaction *);
@@ -143,12 +143,12 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
update_rtc ();
}
-static struct irqaction irqtimer0 = { timer_interrupt, 0, 0, "timer", NULL, NULL};
+static struct irqaction irqtimer = { timer_interrupt, 0, 0, "timer", NULL, NULL};
-void time_init(void)
+__initfunc(void time_init(void))
{
xtime.tv_sec = setup_timer();
xtime.tv_usec = 0;
- setup_arm_irq(IRQ_TIMER0, &irqtimer0);
+ setup_arm_irq(IRQ_TIMER, &irqtimer);
}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 7ff7436c5..222fd6b17 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -59,17 +59,27 @@ static int verify_stack_pointer (unsigned long stackptr, int size)
return 0;
}
-static void dump_stack (unsigned long *start, unsigned long *end, int offset, int max)
+/*
+ * Dump out the contents of some memory nicely...
+ */
+void dump_mem(unsigned long bottom, unsigned long top)
{
- unsigned long *p;
+ unsigned long p = bottom & ~31;
int i;
- for (p = start + offset, i = 0; i < max && p < end; i++, p++) {
- if (i && (i & 7) == 0)
- printk ("\n ");
- printk ("%08lx ", *p);
+ for (p = bottom & ~31; p < top;) {
+ printk("%08lx: ", p);
+
+ for (i = 0; i < 8; i++, p += 4) {
+ if (p < bottom || p >= top)
+ printk(" ");
+ else
+ printk("%08lx ", *(unsigned long *)p);
+ if (i == 3)
+ printk(" ");
+ }
+ printk ("\n");
}
- printk ("\n");
}
/*
@@ -139,28 +149,26 @@ void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret)
break;
}
- console_verbose ();
- printk ("Internal error: %s: %x\n", str, err);
- printk ("CPU: %d", smp_processor_id());
- show_regs (regs);
- printk ("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
+ console_verbose();
+ printk("Internal error: %s: %x\n", str, err);
+ printk("CPU: %d", smp_processor_id());
+ show_regs(regs);
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, 4096+(unsigned long)current);
cstack = (unsigned long)(regs + 1);
sstack = 4096+(unsigned long)current;
- if (*(unsigned long *)sstack != STACK_MAGIC)
- printk ("*** corrupted stack page\n ");
-
- if (verify_stack_pointer (cstack, 4))
- printk ("%08lx invalid kernel stack pointer\n", cstack);
+ printk("Stack: ");
+ if (verify_stack_pointer(cstack, 4))
+ printk("invalid kernel stack pointer %08lx", cstack);
else if(cstack > sstack + 4096)
- printk("(sp overflow)\n");
+ printk("(sp overflow)");
else if(cstack < sstack)
- printk("(sp underflow)\n");
- else
- dump_stack ((unsigned long *)sstack, (unsigned long *)sstack + 1024,
- cstack - sstack, kstack_depth_to_print);
+ printk("(sp underflow)");
+ printk("\n");
+
+ dump_mem(cstack, sstack + 4096);
frameptr = regs->ARM_fp;
if (frameptr) {
@@ -172,7 +180,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret)
}
}
- dump_instr (instruction_pointer(regs));
+ dump_instr(instruction_pointer(regs));
died = 0;
if (ret != -1)
do_exit (ret);
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 10fad6b43..8ec13266d 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -5,17 +5,13 @@
#
L_TARGET := lib.a
-L_OBJS := backtrace.o bitops.o delay.o fp_support.o \
+L_OBJS := backtrace.o bitops.o checksum.o delay.o fp_support.o \
loaders.o memcpy.o memfastset.o system.o string.o uaccess.o
ifeq ($(PROCESSOR),armo)
L_OBJS += uaccess-armo.o
endif
-ifdef CONFIG_INET
- L_OBJS += checksum.o
-endif
-
ifdef CONFIG_ARCH_ACORN
L_OBJS += ll_char_wr.o io-acorn.o
ifdef CONFIG_ARCH_A5K
@@ -26,30 +22,27 @@ ifdef CONFIG_ARCH_ACORN
endif
endif
-ifdef CONFIG_ARCH_EBSA110
+ifeq ($(MACHINE),ebsa110)
L_OBJS += io-ebsa110.o
endif
-include $(TOPDIR)/Rules.make
+ifeq ($(MACHINE),ebsa285)
+ L_OBJS += io-ebsa285.o
+endif
-constants.h: getconstants
- ./getconstants > constants.h
+include $(TOPDIR)/Rules.make
-getconstants: getconstants.c getconstants.h
- $(HOSTCC) -D__KERNEL__ -o getconstants getconstants.c
+constants.h: getconsdata.o extractconstants.pl
+ $(PERL) extractconstants.pl $(OBJDUMP) > $@
-getconstants.h: getconsdata.c
+getconsdata.o: getconsdata.c
$(CC) $(CFLAGS) -c getconsdata.c
- $(PERL) extractinfo.perl $(OBJDUMP) > $@
%.o: %.S
-ifndef $(CONFIG_BINUTILS_NEW)
+ifneq ($(CONFIG_BINUTILS_NEW),y)
$(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..tmp.$<.s
$(CC) $(CFLAGS:-pipe=) -c -o $@ ..tmp.$<.s
$(RM) ..tmp.$<.s
else
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
endif
-
-clean:
- $(RM) getconstants constants.h getconstants.h
diff --git a/arch/arm/lib/extractconstants.pl b/arch/arm/lib/extractconstants.pl
new file mode 100644
index 000000000..ff095a232
--- /dev/null
+++ b/arch/arm/lib/extractconstants.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+
+$OBJDUMP=$ARGV[0];
+
+sub swapdata {
+ local ($num) = @_;
+
+ return substr($num, 6, 2).substr($num, 4, 2).substr ($num, 2, 2).substr ($num, 0, 2);
+}
+
+open (DATA, $OBJDUMP.' --full-contents --section=.data getconsdata.o | grep \'^ 00\' |') ||
+ die ('Cant objdump!');
+while (<DATA>) {
+ ($addr, $data0, $data1, $data2, $data3) = split (' ');
+ $dat[hex($addr)] = hex(&swapdata($data0));
+ $dat[hex($addr)+4] = hex(&swapdata($data1));
+ $dat[hex($addr)+8] = hex(&swapdata($data2));
+ $dat[hex($addr)+12] = hex(&swapdata($data3));
+}
+close (DATA);
+
+open (DATA, $OBJDUMP.' --syms getconsdata.o |') || die ('Cant objdump!');
+while (<DATA>) {
+ /elf32/ && ( $elf = 1 );
+ /a.out/ && ( $aout = 1 );
+ next if ($aout && ! / 07 /);
+ next if ($elf && ! (/^00...... g/ && /.data/));
+ next if (!$aout && !$elf);
+
+ if ($aout) {
+ ($addr, $flags, $sect, $a1, $a2, $a3, $name) = split (' ');
+ $nam[hex($addr)] = substr($name, 1);
+ }
+ if ($elf) {
+ chomp;
+ $addr = substr ($_, 0, 8);
+ $name = substr ($_, 32);
+ $nam[hex($addr)] = $name;
+ }
+}
+close (DATA);
+
+print "/*\n * *** This file is automatically generated from getconsdata.c. Do not edit! ***\n */\n";
+for ($i = 0; $i < hex($addr)+4; $i += 4) {
+ print "#define $nam[$i] $dat[$i]\n";
+}
diff --git a/arch/arm/lib/getconsdata.c b/arch/arm/lib/getconsdata.c
index 901c1ad16..bdf09d5a3 100644
--- a/arch/arm/lib/getconsdata.c
+++ b/arch/arm/lib/getconsdata.c
@@ -1,9 +1,8 @@
/*
* linux/arch/arm/lib/getconsdata.c
*
- * Copyright (C) 1995, 1996 Russell King
+ * Copyright (C) 1995-1998 Russell King
*/
-
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -15,17 +14,55 @@
#define OFF_MM(n) (unsigned long)&(((struct mm_struct *)0)->n)
#ifdef KERNEL_DOMAIN
-unsigned long kernel_domain = KERNEL_DOMAIN;
+unsigned long DOM_KERNELDOMAIN = KERNEL_DOMAIN;
#endif
#ifdef USER_DOMAIN
-unsigned long user_domain = USER_DOMAIN;
-#endif
-unsigned long addr_limit = OFF_TSK(addr_limit);
-unsigned long tss_memmap = OFF_TSK(tss.memmap);
-unsigned long mm = OFF_TSK(mm);
-unsigned long pgd = OFF_MM(pgd);
-unsigned long tss_save = OFF_TSK(tss.save);
-unsigned long tss_fpesave = OFF_TSK(tss.fpstate.soft.save);
+unsigned long DOM_USERDOMAIN = USER_DOMAIN;
+#endif
+
+unsigned long TSK_STATE = OFF_TSK(state);
+unsigned long TSK_FLAGS = OFF_TSK(flags);
+unsigned long TSK_SIGPENDING = OFF_TSK(sigpending);
+unsigned long TSK_ADDR_LIMIT = OFF_TSK(addr_limit);
+
+unsigned long MM = OFF_TSK(mm);
+unsigned long PGD = OFF_MM(pgd);
+
+unsigned long TSS_MEMMAP = OFF_TSK(tss.memmap);
+unsigned long TSS_SAVE = OFF_TSK(tss.save);
+unsigned long TSS_FPESAVE = OFF_TSK(tss.fpstate.soft.save);
#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
-unsigned long tss_memcmap = OFF_TSK(tss.memcmap);
+unsigned long TSS_MEMCMAP = OFF_TSK(tss.memcmap);
+#endif
+
+#ifdef _PAGE_PRESENT
+unsigned long PAGE_PRESENT = _PAGE_PRESENT;
+#endif
+#ifdef _PAGE_RW
+unsigned long PAGE_RW = _PAGE_RW;
#endif
+#ifdef _PAGE_USER
+unsigned long PAGE_USER = _PAGE_USER;
+#endif
+#ifdef _PAGE_ACCESSED
+unsigned long PAGE_ACCESSED = _PAGE_ACCESSED;
+#endif
+#ifdef _PAGE_DIRTY
+unsigned long PAGE_DIRTY = _PAGE_DIRTY;
+#endif
+#ifdef _PAGE_READONLY
+unsigned long PAGE_READONLY = _PAGE_READONLY;
+#endif
+#ifdef _PAGE_NOT_USER
+unsigned long PAGE_NOT_USER = _PAGE_NOT_USER;
+#endif
+#ifdef _PAGE_OLD
+unsigned long PAGE_OLD = _PAGE_OLD;
+#endif
+#ifdef _PAGE_CLEAN
+unsigned long PAGE_CLEAN = _PAGE_CLEAN;
+#endif
+
+unsigned long KSWI_BASE = 0x900000;
+unsigned long KSWI_SYS_BASE = 0x9f0000;
+unsigned long SYS_ERROR0 = 0x9f0000;
diff --git a/arch/arm/lib/io-acorn.S b/arch/arm/lib/io-acorn.S
index 172783b02..51550e014 100644
--- a/arch/arm/lib/io-acorn.S
+++ b/arch/arm/lib/io-acorn.S
@@ -57,7 +57,7 @@ ENTRY(insw)
mov r2, r2, lsl#1
ENTRY(inswb)
mov ip, sp
- stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc}
+ stmfd sp!, {r4 - r10, fp, ip, lr, pc}
sub fp, ip, #4
addr r3, r0
add r0, r3, r0, lsl #2
@@ -70,7 +70,7 @@ ENTRY(inswb)
strgeb r4, [r1], #1
movgt r4, r4, LSR#8
strgtb r4, [r1], #1
- ldmleea fp, {r4 - r10, fp, sp, pc}^
+ LOADREGS(leea, fp, {r4 - r10, fp, sp, pc})
sub r2, r2, #2
Linswok: mov ip, #0xFF
orr ip, ip, ip, lsl #8
diff --git a/arch/arm/lib/io-ebsa285.S b/arch/arm/lib/io-ebsa285.S
new file mode 100644
index 000000000..a5c6386f0
--- /dev/null
+++ b/arch/arm/lib/io-ebsa285.S
@@ -0,0 +1,109 @@
+#define __ASSEMBLER__
+#include <linux/linkage.h>
+
+ENTRY(insl)
+ add r0, r0, #0xff000000
+ add r0, r0, #0x00e00000
+ ands ip, r1, #3
+ bne 2f
+
+1: ldr r3, [r0]
+ str r3, [r1], #4
+ subs r2, r2, #1
+ bne 1b
+ mov pc, lr
+
+2: cmp ip, #2
+ ldr ip, [r0]
+ blt 3f
+ bgt 4f
+
+ strh ip, [r1], #2
+ mov ip, ip, lsr #16
+1: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #16
+ strne ip, [r1], #4
+ movne ip, r3, lsr #16
+ bne 1b
+ strh ip, [r1], #2
+ mov pc, lr
+
+3: strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strh ip, [r1], #2
+ mov ip, ip, lsr #16
+1: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #8
+ strne ip, [r1], #4
+ movne ip, r3, lsr #24
+ bne 1b
+ strb ip, [r1], #1
+ mov pc, lr
+
+4: strb ip, [r1], #1
+ mov ip, ip, lsr #8
+1: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #24
+ strne ip, [r1], #4
+ movne ip, r3, lsr #8
+ bne 1b
+ strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strh ip, [r1], #2
+ mov pc, lr
+
+ENTRY(outsl)
+ add r0, r0, #0xff000000
+ add r0, r0, #0x00e00000
+ ands ip, r1, #3
+ bne 2f
+
+1: ldr r3, [r1], #4
+ str r3, [r0]
+ subs r2, r2, #1
+ bne 1b
+ mov pc, lr
+
+2: bic r1, r1, #3
+ cmp ip, #2
+ ldr ip, [r1], #4
+ mov ip, ip, lsr #16
+ blt 3f
+ bgt 4f
+
+1: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #16
+ str ip, [r0]
+ mov ip, r3, lsr #16
+ subs r2, r2, #1
+ bne 1b
+ mov pc, lr
+
+3: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #8
+ str ip, [r0]
+ mov ip, r3, lsr #24
+ subs r2, r2, #1
+ bne 3b
+ mov pc, lr
+
+4: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #24
+ str ip, [r0]
+ mov ip, r3, lsr #8
+ subs r2, r2, #1
+ bne 4b
+ mov pc, lr
+
+
+ENTRY(outsw)
+ENTRY(outswb)
+ mov pc, lr
+
+ENTRY(insw)
+ENTRY(inswb)
+ mov pc, lr
+
diff --git a/arch/arm/lib/ll_char_wr.S b/arch/arm/lib/ll_char_wr.S
index 7df08d93b..fb1a5c5a4 100644
--- a/arch/arm/lib/ll_char_wr.S
+++ b/arch/arm/lib/ll_char_wr.S
@@ -3,9 +3,10 @@
*
* Copyright (C) 1995, 1996 Russell King.
*
- * Speedups & 1bpp code (C) 1996 Philip Blundel & Russell King.
+ * Speedups & 1bpp code (C) 1996 Philip Blundell & Russell King.
*
* 10-04-96 RMK Various cleanups & reduced register usage.
+ * 08-04-98 RMK Shifts re-ordered
*/
@ Regs: [] = corruptable
@@ -32,22 +33,22 @@ ENTRY(ll_write_char)
@
@ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc)
@
- eor ip, r1, #UNDERLINE << 24
+ eor ip, r1, #UNDERLINE << 9
/*
* calculate colours
*/
- tst r1, #INVERSE << 24
- moveq r2, r1, lsr #8
- moveq r3, r1, lsr #16
- movne r2, r1, lsr #16
- movne r3, r1, lsr #8
+ tst r1, #INVERSE << 9
+ moveq r2, r1, lsr #16
+ moveq r3, r1, lsr #24
+ movne r2, r1, lsr #24
+ movne r3, r1, lsr #16
and r3, r3, #255
and r2, r2, #255
/*
* calculate offset into character table
*/
- and r1, r1, #255
- mov r1, r1, lsl #3
+ mov r1, r1, lsl #23
+ mov r1, r1, lsr #20
/*
* calculate offset required for each row [maybe I should make this an argument to this fn.
* Have to see what the register usage is like in the calling routines.
@@ -67,7 +68,7 @@ ENTRY(ll_write_char)
add r0, r0, r5, lsl #3 @ Move to bottom of character
add r1, r1, #7
ldrb r7, [r6, r1]
- tst ip, #UNDERLINE << 24
+ tst ip, #UNDERLINE << 9
eoreq r7, r7, #255
teq r4, #8
beq Lrow8bpplp
@@ -131,7 +132,7 @@ Lrow8bpplp: mov ip, r7, lsr #4
@
Lrow1bpp: add r6, r6, r1
ldmia r6, {r4, r7}
- tst ip, #INVERSE << 24
+ tst ip, #INVERSE << 9
mvnne r4, r4
mvnne r7, r7
strb r4, [r0], r5
@@ -147,7 +148,7 @@ Lrow1bpp: add r6, r6, r1
mov r7, r7, lsr #8
strb r7, [r0], r5
mov r7, r7, lsr #8
- tst ip, #UNDERLINE << 24
+ tst ip, #UNDERLINE << 9
mvneq r7, r7
strb r7, [r0], r5
LOADREGS(fd, sp!, {r4 - r7, pc})
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
index 209768f9f..f26e6cb1c 100644
--- a/arch/arm/lib/memcpy.S
+++ b/arch/arm/lib/memcpy.S
@@ -8,6 +8,12 @@
#include <asm/assembler.h>
#include <linux/linkage.h>
+#ifndef ENTRY
+#define ENTRY(x...) \
+ .globl _##x; \
+_##x:
+#endif
+
.text
#define ENTER \
mov ip,sp ;\
@@ -84,6 +90,7 @@ ENTRY(memmove)
blt 6b
ands ip, r1, #3
beq 1b
+
8: bic r1, r1, #3
ldr r7, [r1], #4
cmp ip, #2
@@ -105,14 +112,14 @@ ENTRY(memmove)
subs r2, r2, #16
bge 9b
adds r2, r2, #12
- blt 1b
+ blt 100f
10: mov r3, r7, lsr #8
ldr r7, [r1], #4
orr r3, r3, r7, lsl #24
str r3, [r0], #4
subs r2, r2, #4
bge 10b
- sub r1, r1, #3
+100: sub r1, r1, #3
b 6b
11: cmp r2, #12
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
index a1524bee9..78256b319 100644
--- a/arch/arm/lib/uaccess.S
+++ b/arch/arm/lib/uaccess.S
@@ -13,13 +13,21 @@
#include <asm/errno.h>
.text
-
+#ifdef ENTRY
#define USER(x...) \
9999: x; \
.section __ex_table,"a"; \
.align 3; \
.long 9999b,9001f; \
.previous
+#else
+#define USER(x...) \
+ x
+#define ENTRY(x...) \
+ .globl _##x; \
+_##x:
+#define TESTING
+#endif
#define PAGE_SHIFT 12
@@ -278,12 +286,12 @@ USER( strgebt r3, [r0], #1) // May fault
USER( strgtbt r3, [r0], #1) // May fault
b .c2u_finished
+#ifndef TESTING
.section .fixup,"ax"
.align 0
9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
.previous
-
-
+#endif
/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
* Purpose : copy a block from user memory to kernel memory
@@ -538,10 +546,12 @@ USER( ldrget r3, [r1], #0) // May fault
strgtb r3, [r0], #1
b .cfu_finished
+#ifndef TESTING
.section .fixup,"ax"
.align 0
9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
.previous
+#endif
/* Prototype: int __arch_clear_user(void *addr, size_t sz)
* Purpose : clear some user memory
@@ -556,7 +566,7 @@ ENTRY(__arch_clear_user)
blt 2f
ands ip, r0, #3
beq 1f
- cmp ip, #1
+ cmp ip, #2
USER( strbt r2, [r0], #1)
USER( strlebt r2, [r0], #1)
USER( strltbt r2, [r0], #1)
@@ -566,9 +576,9 @@ USER( strltbt r2, [r0], #1)
USER( strplt r2, [r0], #4)
USER( strplt r2, [r0], #4)
bpl 1b
-2: adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
+ adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
USER( strplt r2, [r0], #4)
- tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
+2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
USER( strnebt r2, [r0], #1)
USER( strnebt r2, [r0], #1)
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
@@ -576,6 +586,7 @@ USER( strnebt r2, [r0], #1)
mov r0, #0
LOADREGS(fd,sp!, {r1, pc})
+#ifndef TESTING
.section .fixup,"ax"
.align 0
9001: LOADREGS(fd,sp!, {r0, pc})
@@ -611,21 +622,25 @@ USER( ldrbt r1, [r0], #1)
*/
ENTRY(__arch_strncpy_from_user)
stmfd sp!, {lr}
- mov ip, r2
+ add ip, r1, #1
1: subs r2, r2, #1
bmi 2f
USER( ldrbt r3, [r1], #1)
strb r3, [r0], #1
teq r3, #0
bne 1b
-2: subs r0, ip, r2
- LOADREGS(fd,sp!, {pc})
+ sub r0, r1, ip
+ LOADREGS(fd, sp!, {pc})
+2: sub ip, ip, #1
+ sub r0, r1, ip
+ LOADREGS(fd, sp!, {pc})
.section .fixup,"ax"
.align 0
9001: mov r0, #-EFAULT
- LOADREGS(fd,sp!, {pc})
+ LOADREGS(fd, sp!, {pc})
.previous
.align
+#endif
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 0488da561..be9be35f0 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -7,8 +7,14 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
+ifeq ($(MACHINE),a5k)
+MMARCH=arc
+else
+MMARCH=$(MACHINE)
+endif
+
O_TARGET := mm.o
-O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(MACHINE).o
+O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(MMARCH).o
ifeq ($(PROCESSOR),armo)
O_OBJS += proc-arm2,3.o
@@ -28,9 +34,9 @@ proc-sa110.o: ../lib/constants.h
../lib/constants.h:
@$(MAKE) -C ../lib constants.h
+ifneq ($(CONFIG_BINUTILS_NEW),y)
%.o: %.S
-ifndef $(CONFIG_BINUTILS_NEW)
- $(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..tmp.s
- $(CC) $(CFLAGS:-pipe=) -c -o $@ ..tmp.s
- $(RM) ..tmp.s
+ $(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..$@.tmp.s
+ $(CC) $(CFLAGS:-pipe=) -c -o $@ ..$@.tmp.s
+ $(RM) ..$@.tmp.s
endif
diff --git a/arch/arm/mm/fault-armo.c b/arch/arm/mm/fault-armo.c
index a0fd65df2..6e1024c30 100644
--- a/arch/arm/mm/fault-armo.c
+++ b/arch/arm/mm/fault-armo.c
@@ -27,6 +27,50 @@
#define FAULT_CODE_WRITE 0x02
#define FAULT_CODE_USER 0x01
+struct pgtable_cache_struct quicklists;
+
+void __bad_pte(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+ set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+}
+
+pgd_t *get_pgd_slow(void)
+{
+ pgd_t *pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
+ pgd_t *init;
+
+ if (pgd) {
+ init = pgd_offset(&init_mm, 0);
+ memzero (pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+ memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
+ }
+ return pgd;
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+ pte_t *pte;
+
+ pte = (pte_t *) kmalloc (PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
+ if (pmd_none(*pmd)) {
+ if (pte) {
+ memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ set_pmd(pmd, mk_pmd(pte));
+ return pte + offset;
+ }
+ set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+ return NULL;
+ }
+ kfree (pte);
+ if (pmd_bad(*pmd)) {
+ __bad_pte(pmd);
+ return NULL;
+ }
+ return (pte_t *) pmd_page(*pmd) + offset;
+}
+
extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 2925761fb..051b336bf 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -25,8 +25,96 @@
#define FAULT_CODE_READ 0x02
#define FAULT_CODE_USER 0x01
+struct pgtable_cache_struct quicklists;
+
+void __bad_pmd(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+ set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+}
+
+void __bad_pmd_kernel(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+ set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+}
+
+pgd_t *get_pgd_slow(void)
+{
+ /*
+ * need to get a 16k page for level 1
+ */
+ pgd_t *pgd = (pgd_t *) __get_free_pages(GFP_KERNEL,2);
+ pgd_t *init;
+
+ if (pgd) {
+ init = pgd_offset(&init_mm, 0);
+ memzero ((void *)pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+ memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
+ }
+ return pgd;
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+ pte_t *pte;
+
+ pte = (pte_t *) get_small_page(GFP_KERNEL);
+ if (pmd_none(*pmd)) {
+ if (pte) {
+ memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ set_pmd(pmd, mk_user_pmd(pte));
+ return pte + offset;
+ }
+ set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+ return NULL;
+ }
+ free_small_page ((unsigned long) pte);
+ if (pmd_bad(*pmd)) {
+ __bad_pmd(pmd);
+ return NULL;
+ }
+ return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
+{
+ pte_t *pte;
+
+ pte = (pte_t *) get_small_page(GFP_KERNEL);
+ if (pmd_none(*pmd)) {
+ if (pte) {
+ memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ set_pmd(pmd, mk_kernel_pmd(pte));
+ return pte + offset;
+ }
+ set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+ return NULL;
+ }
+ free_small_page ((unsigned long) pte);
+ if (pmd_bad(*pmd)) {
+ __bad_pmd_kernel(pmd);
+ return NULL;
+ }
+ return (pte_t *) pmd_page(*pmd) + offset;
+}
+
extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
+#ifdef DEBUG
+static int sp_valid (unsigned long *sp)
+{
+ unsigned long addr = (unsigned long) sp;
+
+ if (addr >= 0xb0000000 && addr < 0xd0000000)
+ return 1;
+ if (addr >= 0x03ff0000 && addr < 0x04000000)
+ return 1;
+ return 0;
+}
+#endif
+
static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
struct task_struct *tsk, struct mm_struct *mm)
{
@@ -103,6 +191,16 @@ bad_area:
printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
#ifdef DEBUG
+ {
+ unsigned int i, j;
+ unsigned long *sp = (unsigned long *) (regs->ARM_sp - 128);
+ for (j = 0; j < 20 && sp_valid (sp); j++) {
+ printk ("%p: ", sp);
+ for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
+ printk ("%08lx ", *sp);
+ printk ("\n");
+ }
+ }
show_regs (regs);
c_backtrace (regs->ARM_fp, regs->ARM_cpsr);
#endif
@@ -133,7 +231,6 @@ do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
{
if (user_mode(regs))
error_code |= FAULT_CODE_USER;
-
#define DIE(signr,nam)\
force_sig(signr, current);\
die_if_kernel(nam, regs, fsr, signr);\
@@ -154,18 +251,22 @@ do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
case 11:
DIE(SIGSEGV, "Domain fault")
case 13:/* permission fault on section */
-#ifndef DEBUG
+#ifdef DEBUG
{
- unsigned int i, j, a;
-static int count=2;
-if (count-- == 0) while (1);
- a = regs->ARM_sp;
- for (j = 0; j < 10; j++) {
- printk ("%08x: ", a);
- for (i = 0; i < 8; i += 1, a += 4)
- printk ("%08lx ", *(unsigned long *)a);
+ unsigned int i, j;
+ unsigned long *sp;
+
+ printk ("%s: section permission fault (bad address=0x%08lx, code %d)\n",
+ current->comm, addr, error_code);
+ sp = (unsigned long *) (regs->ARM_sp - 128);
+ for (j = 0; j < 20 && sp_valid (sp); j++) {
+ printk ("%p: ", sp);
+ for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
+ printk ("%08lx ", *sp);
printk ("\n");
}
+ show_regs (regs);
+ c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
}
#endif
DIE(SIGSEGV, "Permission fault")
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b9e777a32..36b118eb2 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/smp.h>
+#include <linux/init.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
@@ -30,7 +31,6 @@
pgd_t swapper_pg_dir[PTRS_PER_PGD];
-const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
extern char _etext, _stext, _edata, __bss_start, _end;
extern char __init_begin, __init_end;
@@ -103,7 +103,7 @@ void show_mem(void)
/*
* paging_init() sets up the page tables...
*/
-unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
+__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
{
extern unsigned long free_area_init(unsigned long, unsigned long);
@@ -130,7 +130,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
* memory is free. This is done after various parts of the system have
* claimed their memory after the kernel image.
*/
-void mem_init(unsigned long start_mem, unsigned long end_mem)
+__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
extern void sound_init(void);
int codepages = 0;
diff --git a/arch/arm/mm/mm-arc.c b/arch/arm/mm/mm-arc.c
index 4a4b4718c..ff447a6be 100644
--- a/arch/arm/mm/mm-arc.c
+++ b/arch/arm/mm/mm-arc.c
@@ -5,3 +5,4 @@
*
* Copyright (C) 1998 Russell King
*/
+#include <asm/arch/mm-init.h>
diff --git a/arch/arm/mm/mm-ebsa110.c b/arch/arm/mm/mm-ebsa110.c
index 907a3f399..a937e098d 100644
--- a/arch/arm/mm/mm-ebsa110.c
+++ b/arch/arm/mm/mm-ebsa110.c
@@ -5,3 +5,22 @@
*
* Copyright (C) 1998 Russell King
*/
+
+#include <asm/io.h>
+
+/* map in IO */
+void setup_io_pagetables(void)
+{
+ unsigned long address = IO_START;
+ int spi = IO_BASE >> PGDIR_SHIFT;
+
+ pgd_val(swapper_pg_dir[spi-1]) = 0xc0000000 | PMD_TYPE_SECT |
+ PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE;
+
+ while (address < IO_START + IO_SIZE && address) {
+ pgd_val(swapper_pg_dir[spi++]) = address | PMD_TYPE_SECT |
+ PMD_DOMAIN(DOMAIN_IO) |
+ PMD_SECT_AP_WRITE;
+ address += PGDIR_SIZE;
+ }
+}
diff --git a/arch/arm/mm/mm-ebsa285.c b/arch/arm/mm/mm-ebsa285.c
new file mode 100644
index 000000000..eb5d7152a
--- /dev/null
+++ b/arch/arm/mm/mm-ebsa285.c
@@ -0,0 +1,97 @@
+/*
+ * arch/arm/mm/mm-ebsa285.c
+ *
+ * Extra MM routines for the EBSA285 architecture
+ *
+ * Copyright (C) 1998 Russell King
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/proc/mm-init.h>
+
+/* Logical Physical
+ * 0xfff00000 0x40000000 X-Bus
+ * 0xffe00000 0x7c000000 PCI I/O space
+ * 0xfe000000 0x42000000 CSR
+ * 0xfd000000 0x78000000 Outbound write flush
+ * 0xfc000000 0x79000000 PCI IACK/special space
+ * 0xf9000000 0x7a000000 PCI Config type 1
+ * 0xf8000000 0x7b000000 PCI Config type 0
+ */
+
+static struct mapping {
+ unsigned long virtual;
+ unsigned long physical;
+ unsigned long length;
+} io_mapping[] = {
+ /*
+ * This is to allow us to fiddle with the EEPROM
+ * This entry will go away in time
+ */
+ { 0xd8000000, 0x41000000, 0x00400000 },
+
+ /*
+ * These ones are so that we can fiddle
+ * with the various cards (eg VGA)
+ * until we're happy with them...
+ */
+ { 0xdc000000, 0x7c000000, 0x00100000 },
+ { 0xe0000000, 0x80000000, 0x10000000 },
+
+ { 0xf8000000, 0x7b000000, 0x01000000 }, /* Type 0 Config */
+
+ { 0xf9000000, 0x7a000000, 0x01000000 }, /* Type 1 Config */
+
+ { 0xfc000000, 0x79000000, 0x01000000 }, /* PCI IACK */
+ { 0xfd000000, 0x78000000, 0x01000000 }, /* Outbound wflsh*/
+ { 0xfe000000, 0x42000000, 0x01000000 }, /* CSR */
+ { 0xffe00000, 0x7c000000, 0x00100000 }, /* PCI I/O */
+ { 0xfff00000, 0x40000000, 0x00100000 }, /* X-Bus */
+};
+
+#define SIZEOFIO (sizeof(io_mapping) / sizeof(io_mapping[0]))
+
+/* map in IO */
+unsigned long setup_io_pagetables(unsigned long start_mem)
+{
+ struct mapping *mp;
+ int i;
+
+ for (i = 0, mp = io_mapping; i < SIZEOFIO; i++, mp++) {
+ while ((mp->virtual & 1048575 || mp->physical & 1048575) && mp->length >= PAGE_SIZE) {
+ alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
+ PTE_AP_WRITE);
+
+ mp->length -= PAGE_SIZE;
+ mp->virtual += PAGE_SIZE;
+ mp->physical += PAGE_SIZE;
+ }
+
+ while (mp->length >= 1048576) {
+if (mp->virtual > 0xf0000000)
+ alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
+ PMD_SECT_AP_WRITE);
+else
+alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_USER, PMD_SECT_AP_WRITE | PMD_SECT_AP_READ);
+
+ mp->length -= 1048576;
+ mp->virtual += 1048576;
+ mp->physical += 1048576;
+ }
+
+ while (mp->length >= PAGE_SIZE) {
+ alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
+ PTE_AP_WRITE);
+
+ mp->length -= PAGE_SIZE;
+ mp->virtual += PAGE_SIZE;
+ mp->physical += PAGE_SIZE;
+ }
+ }
+ return start_mem;
+}
+
diff --git a/arch/arm/mm/mm-nexuspci.c b/arch/arm/mm/mm-nexuspci.c
index bbae80b19..2bb2d0fab 100644
--- a/arch/arm/mm/mm-nexuspci.c
+++ b/arch/arm/mm/mm-nexuspci.c
@@ -1,7 +1,28 @@
/*
* arch/arm/mm/mm-nexuspci.c
+ * from arch/arm/mm/mm-ebsa110.c
*
- * Extra MM routines for the Archimedes architecture
+ * Extra MM routines for the NexusPCI architecture
*
* Copyright (C) 1998 Russell King
*/
+
+#include <asm/io.h>
+
+/* map in IO */
+void setup_io_pagetables(void)
+{
+ unsigned long address = IO_START;
+ int spi = IO_BASE >> PGDIR_SHIFT;
+
+ pgd_val(swapper_pg_dir[spi-1]) = 0xc0000000 | PMD_TYPE_SECT |
+ PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE;
+
+ while (address < IO_START + IO_SIZE && address) {
+ pgd_val(swapper_pg_dir[spi++]) = address | PMD_TYPE_SECT |
+ PMD_DOMAIN(DOMAIN_IO) |
+ PMD_SECT_AP_WRITE;
+ address += PGDIR_SIZE;
+ }
+}
+
diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c
index 5eccb1f81..f789b8f79 100644
--- a/arch/arm/mm/mm-rpc.c
+++ b/arch/arm/mm/mm-rpc.c
@@ -6,7 +6,14 @@
* Copyright (C) 1998 Russell King
*/
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/pgtable.h>
#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/proc/mm-init.h>
+#include <asm/arch/mm-init.h>
#define NR_DRAM_BANKS 4
#define NR_VRAM_BANKS 1
@@ -21,8 +28,8 @@
#define FIRST_DRAM_ADDR 0x10000000
#define PHYS_TO_BANK(x) (((x) >> BANK_SHIFT) & (NR_DRAM_BANKS - 1))
-#define BANK_TO_PHYS(x) ((FIRST_DRAM_ADDR) +
- (((x) - FIRST_DRAM_BANK) << BANK_SHIFT)
+#define BANK_TO_PHYS(x) ((FIRST_DRAM_ADDR) + \
+ (((x) - FIRST_DRAM_BANK) << BANK_SHIFT))
struct ram_bank {
unsigned int virt_addr; /* virtual address of the *end* of this bank + 1 */
@@ -75,6 +82,56 @@ void init_dram_banks(struct param_struct *params)
rambank[bank].virt_addr = PAGE_OFFSET + bytes;
}
- drambank[4].phys_offset = 0xd6000000;
- drambank[4].virt_addr = 0xd8000000;
+ rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000;
+ rambank[FIRST_VRAM_BANK].virt_addr = 0xd8000000;
+
+ current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir);
+}
+
+static struct mapping {
+ unsigned long virtual;
+ unsigned long physical;
+ unsigned long length;
+} io_mapping[] = {
+ { SCREEN2_BASE, SCREEN_START, 2*1048576 }, /* VRAM */
+ { IO_BASE, IO_START, IO_SIZE } /* IO space */
+};
+
+#define SIZEOFIO (sizeof(io_mapping) / sizeof(io_mapping[0]))
+
+/* map in IO */
+unsigned long setup_io_pagetables(unsigned long start_mem)
+{
+ struct mapping *mp;
+ int i;
+
+ for (i = 0, mp = io_mapping; i < SIZEOFIO; i++, mp++) {
+ while ((mp->virtual & 1048575 || mp->physical & 1048575) && mp->length >= PAGE_SIZE) {
+ alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
+ PTE_AP_WRITE);
+
+ mp->length -= PAGE_SIZE;
+ mp->virtual += PAGE_SIZE;
+ mp->physical += PAGE_SIZE;
+ }
+
+ while (mp->length >= 1048576) {
+ alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
+ PMD_SECT_AP_WRITE);
+ mp->length -= 1048576;
+ mp->virtual += 1048576;
+ mp->physical += 1048576;
+ }
+
+ while (mp->length >= PAGE_SIZE) {
+ alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
+ PTE_AP_WRITE);
+
+ mp->length -= PAGE_SIZE;
+ mp->virtual += PAGE_SIZE;
+ mp->physical += PAGE_SIZE;
+ }
+ }
+
+ return start_mem;
}
diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S
index 776d0d57c..a853671fc 100644
--- a/arch/arm/mm/proc-arm6,7.S
+++ b/arch/arm/mm/proc-arm6,7.S
@@ -72,10 +72,10 @@ _arm6_7_switch_to:
stmfd sp!, {ip} @ Save cpsr_SVC
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r0, [r1, #ADDR_LIMIT]
+ ldr r0, [r1, #TSK_ADDR_LIMIT]
teq r0, #0
- moveq r0, #KERNEL_DOMAIN
- movne r0, #USER_DOMAIN
+ moveq r0, #DOM_KERNELDOMAIN
+ movne r0, #DOM_USERDOMAIN
mcr p15, 0, r0, c3, c0 @ Set domain reg
ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
mov r1, #0
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 7d53bf230..633e8c164 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -161,8 +161,6 @@ _sa110_flush_icache_area:
blt 1b
mcr p15, 0, r0, c7, c5, 0 @ flush I cache
mov pc, lr
-
-@LC0: .word _current
/*
* Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next)
*
@@ -183,10 +181,10 @@ _sa110_switch_to:
stmfd sp!, {ip} @ Save cpsr_SVC
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r0, [r1, #ADDR_LIMIT]
+ ldr r0, [r1, #TSK_ADDR_LIMIT]
teq r0, #0
- moveq r0, #KERNEL_DOMAIN
- movne r0, #USER_DOMAIN
+ moveq r0, #DOM_KERNELDOMAIN
+ movne r0, #DOM_USERDOMAIN
mcr p15, 0, r0, c3, c0 @ Set segment
ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
ldr r3, =Lclean_switch
@@ -227,8 +225,6 @@ _sa110_data_abort:
mov r2, r2, lsr #19 @ b1 = L
and r3, r2, #0x69 << 2
and r2, r2, #2
-// teq r3, #0x21 << 2
-// orreq r2, r2, #1 @ b0 = {LD,ST}RT
mrc p15, 0, r1, c5, c0, 0 @ get FSR
and r1, r1, #255
mov pc, lr
diff --git a/arch/arm/vmlinux.lds b/arch/arm/vmlinux.lds
index 787e5c99d..db1f720e7 100644
--- a/arch/arm/vmlinux.lds
+++ b/arch/arm/vmlinux.lds
@@ -1,4 +1,5 @@
-/* ld script to make i386 Linux kernel
+/* ld script to make ARM Linux kernel
+ * taken from the i386 version
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
@@ -34,11 +35,15 @@ SECTIONS
_edata = .; /* End of data section */
- . = ALIGN(4096); /* Init code and data */
+ /* This has to be aligned to a page boundary to do us any good. This
+ alignment is overkill for ARM6 up but needed for ARM3. Since all this
+ data will be thrown away I don't think the extra padding will hurt.
+ -- pb */
+ . = ALIGN(32768); /* Init code and data */
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
- . = ALIGN(4096);
+ . = ALIGN(32768);
__init_end = .;
__bss_start = .; /* BSS */