diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
commit | dcec8a13bf565e47942a1751a9cec21bec5648fe (patch) | |
tree | 548b69625b18cc2e88c3e68d0923be546c9ebb03 /arch/arm | |
parent | 2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff) |
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash.
o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'arch/arm')
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 */ |