summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
commit03ba4131783cc9e872f8bb26a03f15bc11f27564 (patch)
tree88db8dba75ae06ba3bad08e42c5e52efc162535c /arch/arm/kernel
parent257730f99381dd26e10b832fce4c94cae7ac1176 (diff)
- Merge with Linux 2.1.121.
- Bugfixes.
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile14
-rw-r--r--arch/arm/kernel/armksyms.c66
-rw-r--r--arch/arm/kernel/dec21285.c161
-rw-r--r--arch/arm/kernel/dma-ebsa285.c184
-rw-r--r--arch/arm/kernel/dma-rpc.c32
-rw-r--r--arch/arm/kernel/ecard.c43
-rw-r--r--arch/arm/kernel/entry-armv.S68
-rw-r--r--arch/arm/kernel/entry-common.S46
-rw-r--r--arch/arm/kernel/fiq.c179
-rw-r--r--arch/arm/kernel/head-armo.S2
-rw-r--r--arch/arm/kernel/head-armv.S172
-rw-r--r--arch/arm/kernel/init_task.c4
-rw-r--r--arch/arm/kernel/ioport.c79
-rw-r--r--arch/arm/kernel/irq.c293
-rw-r--r--arch/arm/kernel/leds-ebsa110.c30
-rw-r--r--arch/arm/kernel/leds-ebsa285.c2
-rw-r--r--arch/arm/kernel/process.c29
-rw-r--r--arch/arm/kernel/ptrace.c23
-rw-r--r--arch/arm/kernel/setup-ebsa110.c191
-rw-r--r--arch/arm/kernel/setup.c322
-rw-r--r--arch/arm/kernel/signal.c171
-rw-r--r--arch/arm/kernel/sys_arm.c8
-rw-r--r--arch/arm/kernel/time.c2
-rw-r--r--arch/arm/kernel/traps.c24
24 files changed, 1212 insertions, 933 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7795dd0bc..542ca995a 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -9,7 +9,8 @@ HEAD_OBJ = head-$(PROCESSOR).o
ENTRY_OBJ = entry-$(PROCESSOR).o
O_TARGET := kernel.o
-O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o signal.o sys_arm.o time.o traps.o
+O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o setup.o \
+ signal.o sys_arm.o time.o traps.o fiq.o
all: lib kernel.o $(HEAD_OBJ) init_task.o
@@ -20,7 +21,7 @@ O_OBJS += armksyms.o
endif
ifdef CONFIG_ARCH_ACORN
- O_OBJS += setup.o ecard.o iic.o
+ O_OBJS += ecard.o iic.o
ifdef CONFIG_ARCH_ARC
O_OBJS += oldlatches.o
endif
@@ -29,25 +30,26 @@ ifdef CONFIG_ARCH_ACORN
endif
ifeq ($(MACHINE),ebsa110)
- O_OBJS += setup-ebsa110.o dma-dummy.o
+ O_OBJS += dma-dummy.o leds-ebsa110.o
endif
ifeq ($(MACHINE),ebsa285)
- O_OBJS += dma-dummy.o leds-ebsa285.o setup-ebsa110.o
+ OX_OBJS += dma.o
+ O_OBJS += dma-ebsa285.o leds-ebsa285.o
ifdef CONFIG_PCI
O_OBJS += dec21285.o
endif
endif
ifeq ($(MACHINE),nexuspci)
- O_OBJS += setup-ebsa110.o dma-dummy.o
+ O_OBJS += dma-dummy.o
ifdef CONFIG_PCI
O_OBJS += plx9080.o
endif
endif
$(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
- $(CC) -D__ASSEMBLY__ -traditional -c $(HEAD_OBJ:.o=.S) -o $@
+ $(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@
$(ENTRY_OBJ): $(ENTRY_OBJ:.o=.S)
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $(ENTRY_OBJ:.o=.S) -o $@
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 5c2f1b502..149349b4a 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -12,10 +12,13 @@
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/pgtable.h>
+#include <asm/system.h>
#include <asm/uaccess.h>
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, struct user_fp_struct *);
+extern void inswb(unsigned int port, void *to, int len);
+extern void outswb(unsigned int port, const void *to, int len);
/*
* libgcc functions - functions that are used internally by the
@@ -40,33 +43,27 @@ extern void __udivsi3(void);
extern void __umoddi3(void);
extern void __umodsi3(void);
-extern void inswb(unsigned int port, void *to, int len);
-extern void outswb(unsigned int port, const void *to, int len);
-
-/*
- * floating point math emulator support.
- * These will not change. If they do, then a new version
- * of the emulator will have to be compiled...
- * fp_current is never actually dereferenced - it is just
- * used as a pointer to pass back for send_sig().
- */
-extern void (*fp_save)(unsigned char *);
-extern void (*fp_restore)(unsigned char *);
-extern void fp_setup(void);
-extern void fpreturn(void);
-extern void fpundefinstr(void);
extern void fp_enter(void);
-extern void fp_printk(void);
-extern struct task_struct *fp_current;
-extern void fp_send_sig(int);
+#define EXPORT_SYMBOL_ALIAS(sym,orig) \
+ const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \
+ __MODULE_STRING(##sym##); \
+ const struct module_symbol __ksymtab_##sym __attribute__((section("__ksymtab"))) = \
+ { (unsigned long)&##orig, __kstrtab_##sym };
+ /*
+ * floating point math emulator support.
+ * These symbols will never change their calling convention...
+ */
+EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter);
+EXPORT_SYMBOL_ALIAS(fp_printk,printk);
+EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
-/* platform dependent support */
+ /* platform dependent support */
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(udelay);
EXPORT_SYMBOL(xchg_str);
-/* expansion card support */
+ /* expansion card support */
#ifdef CONFIG_ARCH_ACORN
EXPORT_SYMBOL(ecard_startfind);
EXPORT_SYMBOL(ecard_find);
@@ -77,16 +74,17 @@ EXPORT_SYMBOL(ecard_address);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
-/* processor dependencies */
+ /* processor dependencies */
EXPORT_SYMBOL(processor);
+EXPORT_SYMBOL(machine_type);
-/* io */
+ /* io */
EXPORT_SYMBOL(outswb);
EXPORT_SYMBOL(outsw);
EXPORT_SYMBOL(inswb);
EXPORT_SYMBOL(insw);
-/* address translation */
+ /* address translation */
#ifndef __virt_to_phys__is_a_macro
EXPORT_SYMBOL(__virt_to_phys);
#endif
@@ -104,27 +102,7 @@ EXPORT_SYMBOL(quicklists);
EXPORT_SYMBOL(__bad_pmd);
EXPORT_SYMBOL(__bad_pmd_kernel);
-#define EXPORT_VERS0(sym,orig) \
- const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \
- __MODULE_STRING(##sym##_R00000000); \
- const struct module_symbol __ksymtab_##sym __attribute__((section("__ksymtab"))) = \
- { (unsigned long)&##orig, __kstrtab_##sym };
-/*
- * floating point math emulator support.
- * These symbols will never change their calling convention...
- */
-EXPORT_VERS0(fpreturn,fpreturn);
-EXPORT_VERS0(fpundefinstr,fpundefinstr);
-EXPORT_VERS0(fp_enter,fp_enter);
-EXPORT_VERS0(fp_save,fp_save);
-EXPORT_VERS0(fp_restore,fp_restore);
-EXPORT_VERS0(fp_setup,fp_setup);
-EXPORT_VERS0(fp_printk,printk);
-EXPORT_VERS0(fp_send_sig,send_sig);
-
- /*
- * string / mem functions
- */
+ /* string / mem functions */
EXPORT_SYMBOL_NOVERS(strcpy);
EXPORT_SYMBOL_NOVERS(strncpy);
EXPORT_SYMBOL_NOVERS(strcat);
diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c
index 11ea39e7a..de4861b82 100644
--- a/arch/arm/kernel/dec21285.c
+++ b/arch/arm/kernel/dec21285.c
@@ -1,31 +1,42 @@
/*
* arch/arm/kernel/dec21285.c: PCI functions for DEC 21285
*
- * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998 Russell King, Phil Blundell
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
-int pcibios_present(void)
+#include <asm/system.h>
+
+#define MAX_SLOTS 20
+
+int
+pcibios_present(void)
{
return 1;
}
-static unsigned long pcibios_base_address(unsigned char dev_fn)
+static unsigned long
+pcibios_base_address(unsigned char bus, unsigned char dev_fn)
{
- int slot = PCI_SLOT(dev_fn);
-
- if (slot < 4)
- return 0xf8000000 + (1 << (19 - slot));
- else
- return 0;
+ if (bus == 0) {
+ int slot = PCI_SLOT(dev_fn);
+
+ if (slot < MAX_SLOTS)
+ return 0xf8c00000 + (slot << 11);
+ else
+ return 0;
+ } else {
+ return 0xf9000000 | (bus << 16) | (dev_fn << 8);
+ }
}
-int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned char *val)
+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 long addr = pcibios_base_address(bus, dev_fn);
unsigned char v;
if (addr)
@@ -38,10 +49,11 @@ int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned short *val)
+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 long addr = pcibios_base_address(bus, dev_fn);
unsigned short v;
if (addr)
@@ -54,10 +66,11 @@ int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned int *val)
+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 long addr = pcibios_base_address(bus, dev_fn);
unsigned int v;
if (addr)
@@ -70,10 +83,11 @@ int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned char val)
+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);
+ unsigned long addr = pcibios_base_address(bus, dev_fn);
if (addr)
__asm__("str%?b %0, [%1, %2]"
@@ -81,10 +95,11 @@ int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned short val)
+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);
+ unsigned long addr = pcibios_base_address(bus, dev_fn);
if (addr)
__asm__("str%?h %0, [%1, %2]"
@@ -92,10 +107,11 @@ int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned int val)
+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);
+ unsigned long addr = pcibios_base_address(bus, dev_fn);
if (addr)
__asm__("str%? %0, [%1, %2]"
@@ -103,35 +119,72 @@ int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-static int irq[] = { 18, 8, 9, 11 };
+static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 };
+static int irqmap_cats[] __initdata = { 18, 8, 9, 11 };
-__initfunc(void pcibios_fixup(void))
+__initfunc(static int ebsa_irqval(struct pci_dev *dev))
{
- struct pci_dev *dev;
unsigned char pin;
- unsigned int cmd;
+
+ pcibios_read_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_PIN,
+ &pin);
+
+ return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
+}
- for (dev = pci_devices; dev; dev = dev->next) {
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_PIN,
- &pin);
+__initfunc(static int cats_irqval(struct pci_dev *dev))
+{
+ if (dev->irq >= 128)
+ return 32 + (dev->irq & 0x1f);
+
+ switch (dev->irq) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ return irqmap_cats[dev->irq - 1];
+ case 0:
+ return 0;
+ }
- dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3];
+ printk("PCI: device %02x:%02x has unknown irq line %x\n",
+ dev->bus->number, dev->devfn, dev->irq);
+ return 0;
+}
- pcibios_write_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_LINE,
- dev->irq);
+__initfunc(void pcibios_fixup(void))
+{
+ struct pci_dev *dev;
+ unsigned char cmd;
- printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n",
+ for (dev = pci_devices; dev; dev = dev->next) {
+ /* sort out the irq mapping for this device */
+ switch (machine_type) {
+ case MACH_TYPE_EBSA285:
+ dev->irq = ebsa_irqval(dev);
+ break;
+ case MACH_TYPE_CATS:
+ dev->irq = cats_irqval(dev);
+ break;
+ }
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE, dev->irq);
+
+ printk(KERN_DEBUG
+ "PCI: %02x:%02x [%04x/%04x] on irq %d\n",
dev->bus->number, dev->devfn,
- dev->vendor, dev->device,
- pin, dev->irq);
-
- /* Turn on bus mastering - boot loader doesn't - perhaps it should! */
- pcibios_read_config_byte(dev->bus->number, dev->devfn, PCI_COMMAND, &cmd);
- pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
+ dev->vendor, dev->device, dev->irq);
+
+ /* Turn on bus mastering - boot loader doesn't
+ * - perhaps it should! - dag
+ */
+ pcibios_read_config_byte(dev->bus->number, dev->devfn,
+ PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER;
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_COMMAND, cmd);
}
}
@@ -141,10 +194,16 @@ __initfunc(void pcibios_init(void))
rev = *(unsigned char *)0xfe000008;
printk("DEC21285 PCI revision %02X\n", rev);
-}
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
-{
+ /*
+ * Map our SDRAM at a known address in PCI space, just in case
+ * the firmware had other ideas. Using a nonzero base is slightly
+ * bizarre but apparently necessary to avoid problems with some
+ * video cards.
+ *
+ * We should really only do this if we are the configuration master.
+ */
+ *((unsigned long *)0xfe000018) = 0x10000000;
}
__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
diff --git a/arch/arm/kernel/dma-ebsa285.c b/arch/arm/kernel/dma-ebsa285.c
new file mode 100644
index 000000000..74af95584
--- /dev/null
+++ b/arch/arm/kernel/dma-ebsa285.c
@@ -0,0 +1,184 @@
+/*
+ * arch/arm/kernel/dma-ebsa285.c
+ *
+ * Copyright (C) 1998 Phil Blundell
+ *
+ * DMA functions specific to EBSA-285/CATS architectures
+ */
+
+#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/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include "dma.h"
+
+/* 8237 DMA controllers */
+#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
+#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
+
+/* 8237 DMA controller registers */
+#define DMA1_CMD_REG 0x08 /* command register (w) */
+#define DMA1_STAT_REG 0x08 /* status register (r) */
+#define DMA1_REQ_REG 0x09 /* request register (w) */
+#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+#define DMA1_MODE_REG 0x0B /* mode register (w) */
+#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+
+#define DMA2_CMD_REG 0xD0 /* command register (w) */
+#define DMA2_STAT_REG 0xD0 /* status register (r) */
+#define DMA2_REQ_REG 0xD2 /* request register (w) */
+#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
+{
+ /* 21285 internal channels */
+ if (channel == 0 || channel == 1)
+ return 0;
+
+ /* ISA channels */
+// if (machine_is_cats() && ((channel >= 2 && channel <= 5) ||
+// (channel >= 7 && channel <= 9)))
+// return 0;
+
+ return -EINVAL;
+}
+
+void arch_free_dma(dmach_t channel, dma_t *dma)
+{
+ /* nothing to do */
+}
+
+int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+ int residue = 0;
+
+ switch (channel) {
+ case 0:
+ case 1:
+ break;
+#ifdef CONFIG_CATS
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+#endif
+ }
+ return residue;
+}
+
+void arch_enable_dma(dmach_t channel, dma_t *dma)
+{
+ switch (channel) {
+ case 0:
+ case 1:
+ /*
+ * Not yet implemented
+ */
+ break;
+#ifdef CONFIG_CATS
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 8:
+ case 9:
+ if (dma->invalid) {
+ static unsigned char dma_page[] = { 0x87, 0x83, 0x81, 0x82,
+ 0x00, 0x8b, 0x89, 0x8a };
+ unsigned long int address = dma->buf.address,
+ length = dma->buf.length - 1;
+ outb(address >> 24, dma_page[channel - DMA_ISA_BASE] | 0x400);
+ outb(address >> 16, dma_page[channel - DMA_ISA_BASE]);
+ if (channel >= DMA_ISA_BASE + 5) {
+ outb(0, DMA2_CLEAR_FF_REG);
+ outb(address >> 1,
+ IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2));
+ outb(address >> 9,
+ IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2));
+ outb((length >> 1) & 0xfe,
+ IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2));
+ outb(length >> 9,
+ IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2));
+ outb(dma->dma_mode | (channel - DMA_ISA_BASE - 4), DMA2_MODE_REG);
+ } else {
+ outb(0, DMA1_CLEAR_FF_REG);
+ outb(address >> 0, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1));
+ outb(address >> 8, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1));
+ outb(length >> 0,
+ IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1));
+ outb(length >> 8,
+ IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1));
+ outb(dma->dma_mode | (channel - DMA_ISA_BASE), DMA1_MODE_REG);
+ }
+ switch (dma->dma_mode) {
+ case DMA_MODE_READ:
+ dma_cache_inv(__bus_to_virt(address), length + 1);
+ break;
+ case DMA_MODE_WRITE:
+ dma_cache_wback(__bus_to_virt(address), length + 1);
+ break;
+ }
+ dma->invalid = 0;
+ }
+
+ if (channel >= DMA_ISA_BASE + 5)
+ outb(channel - DMA_ISA_BASE - 4, DMA2_MASK_REG);
+ else
+ outb(channel - DMA_ISA_BASE, DMA1_MASK_REG);
+#endif
+ }
+}
+
+void arch_disable_dma(dmach_t channel, dma_t *dma)
+{
+ switch (channel) {
+ case 0:
+ case 1:
+ /*
+ * Not yet implemented
+ */
+ break;
+#ifdef CONFIG_CATS
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ if (channel >= DMA_ISA_BASE + 5)
+ outb(channel - DMA_ISA_BASE, DMA2_MASK_REG);
+ else
+ outb((channel - DMA_ISA_BASE) | 4, DMA1_MASK_REG);
+#endif
+ }
+}
+
+__initfunc(void arch_dma_init(dma_t *dma))
+{
+ /* Nothing to do */
+}
diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c
index 301b32071..00cd95e79 100644
--- a/arch/arm/kernel/dma-rpc.c
+++ b/arch/arm/kernel/dma-rpc.c
@@ -20,7 +20,7 @@
#include "dma.h"
-static struct fiq_handler fh = { "floppydma", NULL };
+static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL };
#if 0
typedef enum {
@@ -155,8 +155,8 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
}
} while (dma->sg && (status & DMA_ST_INT));
- if (!no_buffer)
- enable_irq(irq);
+ if (no_buffer)
+ disable_irq(irq);
}
int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
@@ -172,7 +172,8 @@ int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
case DMA_S0:
case DMA_S1:
save_flags_cli(flags);
- ret = request_irq(dma->dma_irq, arch_dma_handle, SA_INTERRUPT, dev_name, dma);
+ ret = request_irq(dma->dma_irq, arch_dma_handle,
+ SA_INTERRUPT, dev_name, dma);
if (!ret)
disable_irq(dma->dma_irq);
restore_flags(flags);
@@ -261,8 +262,7 @@ void arch_enable_dma(dmach_t channel, dma_t *dma)
case DMA_VIRTUAL_FLOPPY: {
void *fiqhandler_start;
unsigned int fiqhandler_length;
- extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
- unsigned long port);
+ struct pt_regs regs;
if (dma->dma_mode == DMA_MODE_READ) {
extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
@@ -273,21 +273,20 @@ void arch_enable_dma(dmach_t channel, dma_t *dma)
fiqhandler_start = &floppy_fiqout_start;
fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
}
+
+ regs.ARM_r9 = dma->buf.length;
+ regs.ARM_r10 = __bus_to_virt(dma->buf.address);
+ regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
+
if (claim_fiq(&fh)) {
printk("floppydma: couldn't claim FIQ.\n");
return;
}
- /* 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);
+
+ set_fiq_handler(fiqhandler_start, fiqhandler_length);
+ set_fiq_regs(&regs);
enable_irq(dma->dma_irq);
+
}
break;
@@ -315,6 +314,7 @@ void arch_disable_dma(dmach_t channel, dma_t *dma)
case DMA_VIRTUAL_FLOPPY:
disable_irq(dma->dma_irq);
+ release_fiq(&fh);
break;
}
}
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index f03147e66..f7d204787 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -29,7 +29,6 @@
#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>
@@ -46,7 +45,7 @@
#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
extern unsigned long atomwide_serial_loader[], oak_scsi_loader[], noloader[];
-static const char blacklisted_str[] = "*loader blacklisted - not 32-bit compliant*";
+static const char blacklisted_str[] = "*loader s/w is not 32-bit compliant*";
static const struct expcard_blacklist {
unsigned short manufacturer;
@@ -62,7 +61,7 @@ static const struct expcard_blacklist {
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)" },
+ { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI, noloader, "AlSystems PowerTec SCSI" },
/* Unsupported cards with no loader */
BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32)
@@ -125,6 +124,7 @@ static expansioncard_ops_t ecard_default_ops = {
*/
void ecard_enableirq (unsigned int irqnr)
{
+ irqnr &= 7;
if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
ecard_t *ec = expcard + irqno_to_expcard[irqnr];
@@ -141,6 +141,7 @@ void ecard_enableirq (unsigned int irqnr)
void ecard_disableirq (unsigned int irqnr)
{
+ irqnr &= 7;
if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
ecard_t *ec = expcard + irqno_to_expcard[irqnr];
@@ -154,6 +155,7 @@ void ecard_disableirq (unsigned int irqnr)
void ecard_enablefiq (unsigned int fiqnr)
{
+ fiqnr &= 7;
if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
ecard_t *ec = expcard + irqno_to_expcard[fiqnr];
@@ -170,6 +172,7 @@ void ecard_enablefiq (unsigned int fiqnr)
void ecard_disablefiq (unsigned int fiqnr)
{
+ fiqnr &= 7;
if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
ecard_t *ec = expcard + irqno_to_expcard[fiqnr];
@@ -186,7 +189,6 @@ static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
const int num_cards = ecard_numirqcards;
int i, called = 0;
- mask_irq (IRQ_EXPANSIONCARD);
for (i = 0; i < num_cards; i++) {
if (expcard[i].claimed && expcard[i].irq &&
(!expcard[i].irqmask ||
@@ -195,8 +197,7 @@ static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
called ++;
}
}
- cli ();
- unmask_irq (IRQ_EXPANSIONCARD);
+ cli();
if (called == 0)
printk (KERN_WARNING "Wild interrupt from backplane?\n");
}
@@ -433,10 +434,7 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
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:
+ case 0 ... 3:
switch (type) {
case ECARD_MEMC:
return MEMCECIO_BASE + (ec->slot_no << 12);
@@ -449,20 +447,11 @@ unsigned int ecard_address (ecard_t *ec, card_type_t type, card_speed_t speed)
}
#ifdef IOCEC4IO_BASE
- case 4:
- case 5:
- case 6:
- case 7:
- switch (type) {
- case ECARD_MEMC:
+ case 4 ... 7:
+ if (type != ECARD_IOC)
return 0;
- case ECARD_IOC:
- return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
-
- default:
- return 0;
- }
+ return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
#endif
#ifdef MEMCEC8IO_BASE
case 8:
@@ -558,7 +547,14 @@ __initfunc(static int ecard_probe (int card, int freeslot))
return 1;
}
-static struct irqaction irqexpansioncard = { ecard_irq_noexpmask, SA_INTERRUPT, 0, "expansion cards", NULL, NULL };
+static struct irqaction irqexpansioncard = {
+ ecard_irq_noexpmask,
+ SA_INTERRUPT,
+ 0,
+ "expansion cards",
+ NULL,
+ NULL
+};
/*
* Initialise the expansion card system.
@@ -575,6 +571,7 @@ __initfunc(void ecard_init(void))
if (ecard_checkirqhw()) {
printk (KERN_DEBUG "Expansion card interrupt management hardware found\n");
irqexpansioncard.handler = ecard_irq_expmask;
+ irqexpansioncard.flags |= SA_IRQNOMASK;
have_expmask = -1;
}
#endif
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index a7553d350..7ecf1d59a 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -320,11 +320,19 @@ irq_prio_ebsa110:
.macro mask_pc, rd, rm
.endm
+ /* If we're optimising for StrongARM the resulting code won't
+ run on an ARM7 and we can save a couple of instructions.
+ --pb */
+#ifdef __ARM_ARCH_4__
+ .macro arm700_bug_check, instr, temp
+ .endm
+#else
.macro arm700_bug_check, instr, temp
and \temp, \instr, #0x0f000000 @ check for SWI
teq \temp, #0x0f000000
bne .Larm700bug
.endm
+#endif
.macro enable_irqs, temp
mrs \temp, cpsr
@@ -340,6 +348,7 @@ irq_prio_ebsa110:
.endm
+#ifndef __ARM_ARCH_4__
.Larm700bug: str lr, [r8]
ldr r0, [sp, #S_PSR] @ Get calling cpsr
msr spsr, r0
@@ -348,7 +357,7 @@ irq_prio_ebsa110:
add sp, sp, #S_PC
ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0
movs pc, lr
-
+#endif
.macro get_current_task, rd
mov \rd, sp, lsr #13
@@ -672,6 +681,8 @@ __irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame
*-----------------------------------------------------------------------------
* Handles floating point instructions
*/
+.LC2: .word SYMBOL_NAME(fp_enter)
+
__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
@@ -681,25 +692,15 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
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
+ adrsvc al, r9, ret_from_exception @ r9 = normal FP return
+ adrsvc al, lr, fpundefinstr @ lr = undefined instr return
- .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
+1: get_current_task r10
+ mov lr, #1
+ strb lr, [r10, #TSK_USED_MATH] @ set current->used_math
+ add r10, r10, #TSS_FPESAVE @ r10 = workspace
+ ldr r4, .LC2
+ ldr pc, [r4] @ Call FP module USR entry point
__und_svc: sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ save r0 - r12
@@ -710,31 +711,24 @@ __und_svc: sub sp, 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):
+ adrsvc al, r9, 3f @ r9 = normal FP return
+ bl 1b @ lr = undefined instr return
+
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
+3: 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)
+fpundefinstr: mov r0, lr
+ mov r1, sp
+ mrs r4, cpsr @ Enable interrupts
+ bic r4, r4, #I_BIT
+ msr cpsr, r4
+ adrsvc al, lr, ret_from_exception
+ b SYMBOL_NAME(do_undefinstr)
__und_invalid: sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - lr}
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 422326338..6e0e9e38c 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -6,8 +6,6 @@
.globl ret_from_sys_call
- .globl SYMBOL_NAME(fpreturn)
-SYMBOL_NAME(fpreturn):
ret_from_exception:
adr r0, 1f
ldmia r0, {r0, r1}
@@ -36,12 +34,10 @@ ret_from_sys_call:
bne SYMBOL_NAME(do_bottom_half)
ret_with_reschedule:
- ldr r0, 1f + 8
- ldr r0, [r0]
+ get_current_task r1
+ ldr r0, [r1, #TSK_NEED_RESCHED]
teq r0, #0
bne 2b
-
- get_current_task r1
ldr r1, [r1, #TSK_SIGPENDING]
teq r1, #0
bne ret_signal
@@ -50,7 +46,6 @@ ret_from_all: restore_user_regs
1: .word SYMBOL_NAME(bh_mask)
.word SYMBOL_NAME(bh_active)
- .word SYMBOL_NAME(need_resched)
/*=============================================================================
* SWI handler
@@ -211,8 +206,11 @@ sys_sigaltstack_wrapper:
* 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.
+ * the actual address to jump to.
*/
+
+ .section ".text.init",#alloc,#execinstr
+
#if defined(CONFIG_CPU_32)
/*
* these go into 0x00
@@ -281,39 +279,13 @@ ENTRY(trap_init)
ldmfd sp!, {r4 - r7, pc}^
#endif
+ .previous
+
/*============================================================================
* FP support
*/
-1: .word SYMBOL_NAME(fp_save)
- .word SYMBOL_NAME(fp_restore)
-
-.Lfpnull: mov pc, lr
-
-
-/*
- * Function to call when switching tasks to save FP state
- */
-ENTRY(fpe_save)
- ldr r1, 1b
- ldr pc, [r1]
-
-/*
- * Function to call when switching tasks to restore FP state
- */
-ENTRY(fpe_restore)
- ldr r1, 1b + 4
- ldr pc, [r1]
-
-
.data
ENTRY(fp_enter)
- .word SYMBOL_NAME(fpundefinstr)
- .word SYMBOL_NAME(fpundefinstrsvc)
-
-ENTRY(fp_save)
- .word .Lfpnull
-ENTRY(fp_restore)
- .word .Lfpnull
-
+ .word fpundefinstr
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
new file mode 100644
index 000000000..c32fef3c8
--- /dev/null
+++ b/arch/arm/kernel/fiq.c
@@ -0,0 +1,179 @@
+/*
+ * linux/arch/arm/kernel/fiq.c
+ *
+ * Copyright (C) 1998 Russell King
+ * FIQ support written by Philip Blundell <philb@gnu.org>, 1998.
+ *
+ * FIQ support re-written by Russell King to be more generic
+ *
+ * We now properly support a method by which the FIQ handlers can
+ * be stacked onto the vector. We still do not support sharing
+ * the FIQ vector itself.
+ *
+ * Operation is as follows:
+ * 1. Owner A claims FIQ:
+ * - default_fiq relinquishes control.
+ * 2. Owner A:
+ * - inserts code.
+ * - sets any registers,
+ * - enables FIQ.
+ * 3. Owner B claims FIQ:
+ * - if owner A has a relinquish function.
+ * - disable FIQs.
+ * - saves any registers.
+ * - returns zero.
+ * 4. Owner B:
+ * - inserts code.
+ * - sets any registers,
+ * - enables FIQ.
+ * 5. Owner B releases FIQ:
+ * - Owner A is asked to reacquire FIQ:
+ * - inserts code.
+ * - restores saved registers.
+ * - enables FIQ.
+ * 6. Goto 3
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/init.h>
+
+#include <asm/fiq.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define FIQ_VECTOR 0x1c
+
+static unsigned long no_fiq_insn;
+
+#ifdef CONFIG_CPU_32
+static inline void unprotect_page_0(void)
+{
+ __asm__ __volatile__("mcr p15, 0, %0, c3, c0" :
+ : "r" (DOMAIN_USER_MANAGER |
+ DOMAIN_KERNEL_CLIENT |
+ DOMAIN_IO_CLIENT));
+}
+
+static inline void protect_page_0(void)
+{
+ set_fs(get_fs());
+}
+#else
+
+#define unprotect_page_0()
+#define protect_page_0()
+
+#endif
+
+/* Default reacquire function
+ * - we always relinquish FIQ control
+ * - we always reacquire FIQ control
+ */
+int fiq_def_op(void *ref, int relinquish)
+{
+ if (!relinquish) {
+ unprotect_page_0();
+ *(unsigned long *)FIQ_VECTOR = no_fiq_insn;
+ protect_page_0();
+ __flush_entry_to_ram(FIQ_VECTOR);
+ }
+
+ return 0;
+}
+
+static struct fiq_handler default_owner =
+ { NULL, "default", fiq_def_op, NULL };
+static struct fiq_handler *current_fiq = &default_owner;
+
+int get_fiq_list(char *buf)
+{
+ char *p = buf;
+
+ if (current_fiq != &default_owner)
+ p += sprintf(p, "FIQ: %s\n",
+ current_fiq->name);
+
+ return p - buf;
+}
+
+void set_fiq_handler(void *start, unsigned int length)
+{
+ unprotect_page_0();
+
+ memcpy((void *)FIQ_VECTOR, start, length);
+
+ protect_page_0();
+#if 0
+ /* This doesn'w work correctly. Ok, it's a misuse
+ * of the DMA flushing code, but it ought to work.
+ * More investigation required. Maybe it really
+ * needs the cache flushed.
+ */
+ dma_cache_wback(FIQ_VECTOR, length);
+#else
+ processor.u.armv3v4._flush_cache_area(FIQ_VECTOR, FIQ_VECTOR + length, 1);
+#endif
+}
+
+void set_fiq_regs(struct pt_regs *regs)
+{
+ /* not yet -
+ * this is temporary to get the floppy working
+ * again on RiscPC. It *will* become more
+ * generic.
+ */
+#ifdef CONFIG_ARCH_ACORN
+ extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
+ unsigned long port);
+ floppy_fiqsetup(regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
+#endif
+}
+
+void get_fiq_regs(struct pt_regs *regs)
+{
+ /* not yet */
+}
+
+int claim_fiq(struct fiq_handler *f)
+{
+ int ret = 0;
+
+ if (current_fiq) {
+ ret = -EBUSY;
+
+ if (current_fiq->fiq_op != NULL)
+ ret = current_fiq->fiq_op(current_fiq->dev_id, 1);
+ }
+
+ if (!ret) {
+ f->next = current_fiq;
+ current_fiq = f;
+ }
+
+ return ret;
+}
+
+void release_fiq(struct fiq_handler *f)
+{
+ if (current_fiq != f) {
+ printk(KERN_ERR "%s FIQ trying to release %s FIQ\n",
+ f->name, current_fiq->name);
+#ifdef CONFIG_DEBUG_ERRORS
+ __backtrace();
+#endif
+ return;
+ }
+
+ do
+ current_fiq = current_fiq->next;
+ while (current_fiq->fiq_op(current_fiq->dev_id, 0));
+}
+
+__initfunc(void init_FIQ(void))
+{
+ no_fiq_insn = *(unsigned long *)FIQ_VECTOR;
+ set_fs(get_fs());
+}
diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S
index 80d88e890..1dc4fde13 100644
--- a/arch/arm/kernel/head-armo.S
+++ b/arch/arm/kernel/head-armo.S
@@ -43,7 +43,7 @@ Lcontinue: str r5, [r6]
LC1: .word SYMBOL_NAME(_stext)
LC0: .word SYMBOL_NAME(__bss_start)
- .word SYMBOL_NAME(arm_id)
+ .word SYMBOL_NAME(processor_id)
.word SYMBOL_NAME(_end)
.word SYMBOL_NAME(init_task_union)+8192
Larm2_id: .long 0x41560200
diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S
index 2219d37c3..88e71adab 100644
--- a/arch/arm/kernel/head-armv.S
+++ b/arch/arm/kernel/head-armv.S
@@ -1,58 +1,54 @@
/*
* linux/arch/arm/kernel/head32.S
*
- * Copyright (C) 1994, 1995, 1996, 1997 Russell King
+ * Copyright (C) 1994-1998 Russell King
*
* Kernel 32 bit startup code for ARM6 / ARM7 / StrongARM
*/
#include <linux/config.h>
#include <linux/linkage.h>
-#define DEBUG
+#if (TEXTADDR & 0xffff) != 0x8000
+#error TEXTADDR must start at 0xXXXX8000
+#endif
- .text
- .align
+#define DEBUG
.globl SYMBOL_NAME(swapper_pg_dir)
- .equ SYMBOL_NAME(swapper_pg_dir), 0xc0004000
+ .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
- .globl __stext
+ .text
/*
* Entry point and restart point. Entry *must* be called with r0 == 0,
* MMU off. Note! These should be unique!!! Please read Documentation/ARM-README
* for more information.
*
- * r1 = 0 -> ebsa110
- * r1 = 1 -> RPC
+ * r1 = 0 -> DEC EBSA-110
+ * r1 = 1 -> Acorn RiscPC
* r1 = 2 -> ebsit
* r1 = 3 -> nexuspci
- * r1 = 4 -> ebsa285
- * r1 = 5 -> vnc
+ * r1 = 4 -> DEC EBSA-285
+ * r1 = 5 -> Corel Netwinder
* r1 = 6 -> CATS
+ * r1 = 7 -> tbox
*/
+
ENTRY(stext)
ENTRY(_stext)
-__entry:
- teq r0, #0 @ check for illegal entry...
+__entry: teq r0, #0 @ check for illegal entry...
bne .Lerror @ loop indefinitely
- cmp r1, #7 @ Unknown machine architecture
+ cmp r1, #8 @ Unknown machine architecture
bge .Lerror
-@
-@ First thing to do is to get the page tables set up so that we can call the kernel
-@ in the correct place. This is relocatable code...
-@
+/* First thing to do is to get the page tables set up so that we can call the kernel
+ * in the correct place. This is relocatable code...
+ * - Read processor ID register (CP#15, CR0).
+ */
mrc p15, 0, r9, c0, c0 @ get Processor ID
-@
-@ Read processor ID register (CP#15, CR0).
-@ NOTE: ARM2 & ARM250 cause an undefined instruction exception...
-@ Values are:
-@ XX01XXXX = ARMv4 architecture (StrongARM)
-@ XX00XXXX = ARMv3 architecture
-@ 4156061X = ARM 610
-@ 4156030X = ARM 3
-@ 4156025X = ARM 250
-@ 4156020X = ARM 2
-@
+/* Values are:
+ * XX01XXXX = ARMv4 architecture (StrongARM)
+ * XX00XXXX = ARMv3 architecture
+ * 4156061X = ARM 610
+ */
adr r10, .LCProcTypes
1: ldmia r10!, {r5, r6, r8} @ Get Set, Mask, MMU Flags
teq r5, #0 @ End of list?
@@ -71,44 +67,51 @@ __entry:
* r6 = I/O address
*/
mov r0, r4
- mov r1, #0
+ mov r3, #0
add r2, r0, #0x4000
-1: str r1, [r0], #4 @ Clear page table
+1: str r3, [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.
- * We map in 2MB of memory into 0xC0000000 - 0xC0200000
+ * We map in 2MB of memory into (TEXTADDR-0x8000) + 2MB
+ */
+ add r0, r4, #(TEXTADDR - 0x8000) >> 18
+ mov r3, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE
+ orr r3, r3, r8
+ add r3, r3, r5
+ str r3, [r0], #4
+ add r3, r3, #1 << 20
+ str r3, [r0], #4
+ add r3, r3, #1 << 20
+#ifdef DEBUG
+/* Map in IO space
+ * This allows debug messages to be output via a serial
+ * before/while paging_init.
*/
- add r0, r4, #0x3000
- mov r1, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE
- orr r1, r1, r8
- add r1, r1, r5
- str r1, [r0], #4
- add r1, r1, #1 << 20
- str r1, [r0], #4
- add r1, r1, #1 << 20
-@
-@ Map in IO space
-@
add r0, r4, #0x3800
- orr r1, r6, r8
+ orr r3, r6, r8
add r2, r0, #0x0800
-1: str r1, [r0], #4
- add r1, r1, #1 << 20
+1: str r3, [r0], #4
+ add r3, r3, #1 << 20
teq r0, r2
bne 1b
-@
-@ Map in screen at 0x02000000 & SCREEN2_BASE
-@
+#endif
+#ifdef CONFIG_ARCH_RPC
+/* Map in screen at 0x02000000 & SCREEN2_BASE
+ * Similar reasons here - for debug, and when things go
+ * wrong to a certain extent. This is of limited use to
+ * non-Acorn RiscPC architectures though.
+ */
teq r5, #0
addne r0, r4, #0x80 @ 02000000
- movne r1, #0x02000000
- orrne r1, r1, r8
- strne r1, [r0]
+ movne r3, #0x02000000
+ orrne r3, r3, r8
+ strne r3, [r0]
addne r0, r4, #0x3600 @ d8000000
- strne r1, [r0]
+ strne r3, [r0]
+#endif
@
@ The following should work on both v3 and v4 implementations
@
@@ -122,25 +125,29 @@ __entry:
mov pc, lr
.Lerror:
+#ifdef CONFIG_ARCH_RPC
+/* Turn the screen red on a error - RiscPC only.
+ */
1: mov r0, #0x02000000
- mov r1, #0x11
- orr r1, r1, r1, lsl #8
- orr r1, r1, r1, lsl #16
- str r1, [r0], #4
- str r1, [r0], #4
- str r1, [r0], #4
- str r1, [r0], #4
+ mov r3, #0x11
+ orr r3, r3, r3, lsl #8
+ orr r3, r3, r3, lsl #16
+ str r3, [r0], #4
+ str r3, [r0], #4
+ str r3, [r0], #4
+ str r3, [r0], #4
+#endif
b 1b
.Lbranch: .long .Lalready_done_mmap @ Real address of routine
- @ EBSA110 (pg dir phys, phys ram start, phys i/o)
+ @ DEC 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
.long 0
- @ RPC
+ @ Acorn RiscPC
.long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x10000000
.long 0x10000000
.long 0x03000000
@@ -158,7 +165,7 @@ __entry:
.long 0x10000000
.long 0
- @ EBSA285
+ @ DEC 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)
@@ -176,6 +183,12 @@ __entry:
.long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000)
.long 0
+ @ tbox
+ .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x80000000
+ .long 0x80000000 @ Address of RAM
+ .long 0x00400000 @ Uart
+ .long 0
+
.LCProcTypes: @ ARM6 / 610
.long 0x41560600
.long 0xffffff00
@@ -205,11 +218,6 @@ __entry:
b .Lsa_fastclock
.long 0
-
-.LC0: .long SYMBOL_NAME(__bss_start)
- .long SYMBOL_NAME(arm_id)
- .long SYMBOL_NAME(_end)
- .long SYMBOL_NAME(init_task_union)+8192
.align
.Larmv3_flush_early:
@@ -249,25 +257,36 @@ __entry:
orr r0, r0, #0x1100 @ v4 supports separate I cache
mov pc, lr
+ .section ".text.init",#alloc,#execinstr
+
.Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching
mov pc, lr
+.LC0: .long SYMBOL_NAME(__entry)
+ .long SYMBOL_NAME(machine_type)
+ .long SYMBOL_NAME(__bss_start)
+ .long SYMBOL_NAME(processor_id)
+ .long SYMBOL_NAME(_end)
+ .long SYMBOL_NAME(init_task_union)+8192
+ .align
+
.Lalready_done_mmap:
- adr r5, __entry @ Add base back in
- add r10, r10, r5
- adr r5, .LC0
- ldmia r5, {r5, r6, r8, sp} @ Setup stack
- mov r4, #0
+ adr r4, .LC0
+ ldmia r4, {r3, r4, r5, r6, r8, sp} @ Setup stack
+ add r10, r10, r3 @ Add base back in
+ mov fp, #0
1: cmp r5, r8 @ Clear BSS
- strcc r4, [r5],#4
+ strcc fp, [r5],#4
bcc 1b
+ str r1, [r4] @ Save machine type
str r9, [r6] @ Save processor ID
mov lr, pc
add pc, r10, #4 @ Call post-processor init
mov fp, #0
b SYMBOL_NAME(start_kernel)
+ .text
#ifdef DEBUG
/*
* Some debugging routines (useful if you've got MM problems and
@@ -385,6 +404,9 @@ printhex: ldr r2, =hexbuf
teq r3, r2
bne 1b
mov r0, r2
+ b printascii
+
+ .ltorg
ENTRY(printascii)
addruart r3
@@ -413,7 +435,3 @@ ENTRY(printch)
hexbuf: .space 16
#endif
-
- .text
- .align 13
-ENTRY(this_must_match_init_task)
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
index 90ae6952f..689c43589 100644
--- a/arch/arm/kernel/init_task.c
+++ b/arch/arm/kernel/init_task.c
@@ -6,7 +6,7 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct files * init_fd_array[NR_OPEN] = { NULL, };
+static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
@@ -21,4 +21,4 @@ struct mm_struct init_mm = INIT_MM;
*
* The things we do for performance..
*/
-union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK };
+union task_union init_task_union __attribute__((__section__(".init.task"))) = { INIT_TASK };
diff --git a/arch/arm/kernel/ioport.c b/arch/arm/kernel/ioport.c
index fe88df173..d375dcbdd 100644
--- a/arch/arm/kernel/ioport.c
+++ b/arch/arm/kernel/ioport.c
@@ -1,10 +1,7 @@
/*
* linux/arch/arm/kernel/ioport.c
*
- * This contains the io-permission bitmap code - written by obz, with changes
- * by Linus.
- *
- * Modifications for ARM processor Copyright (C) 1995, 1996 Russell King
+ * Io-port support is not used for ARM
*/
#include <linux/sched.h>
@@ -14,85 +11,19 @@
#include <linux/ioport.h>
/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
-asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
+/*asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
{
- int mask;
- unsigned long *bitmap_base = bitmap + (base >> 5);
- unsigned short low_index = base & 0x1f;
- int length = low_index + extent;
-
- if (low_index != 0) {
- mask = (~0 << low_index);
- if (length < 32)
- mask &= ~(~0 << length);
- if (new_value)
- *bitmap_base++ |= mask;
- else
- *bitmap_base++ &= ~mask;
- length -= 32;
- }
+}*/
- mask = (new_value ? ~0 : 0);
- while (length >= 32) {
- *bitmap_base++ = mask;
- length -= 32;
- }
-
- if (length > 0) {
- mask = ~(~0 << length);
- if (new_value)
- *bitmap_base++ |= mask;
- else
- *bitmap_base++ &= ~mask;
- }
-}
-
-/*
- * this changes the io permissions bitmap in the current task.
- */
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
{
- if (from + num <= from)
- return -EINVAL;
-#ifndef __arm__
- if (from + num > IO_BITMAP_SIZE*32)
- return -EINVAL;
-#endif
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
-
-#ifdef IODEBUG
- printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
-#endif
-#ifndef __arm__
- set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on);
-#endif
- return 0;
+ return -ENOSYS;
}
-unsigned int *stack;
-
-/*
- * sys_iopl has to be used when you want to access the IO ports
- * beyond the 0x3ff range: to get the full 65536 ports bitmapped
- * you'd need 8kB of bitmaps/process, which is a bit excessive.
- *
- * Here we just change the eflags value on the stack: we allow
- * only the super-user to do it. This depends on the stack-layout
- * on system-call entry - see also fork() and the signal handling
- * code.
- */
asmlinkage int sys_iopl(long ebx,long ecx,long edx,
long esi, long edi, long ebp, long eax, long ds,
long es, long fs, long gs, long orig_eax,
long eip,long cs,long eflags,long esp,long ss)
{
- unsigned int level = ebx;
-
- if (level > 3)
- return -EINVAL;
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
- return 0;
+ return -ENOSYS;
}
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 89116048e..b4950ace2 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -3,7 +3,6 @@
*
* Copyright (C) 1992 Linus Torvalds
* Modifications for ARM processor Copyright (C) 1995-1998 Russell King.
- * FIQ support written by Philip Blundell <philb@gnu.org>, 1998.
*
* This file contains the code used by various IRQ handling routines:
* asking for different IRQ's should be done through these routines
@@ -31,20 +30,10 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
-#include <asm/fiq.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/arch/irq.h>
-
-unsigned int local_bh_count[NR_CPUS];
-unsigned int local_irq_count[NR_CPUS];
-spinlock_t irq_controller_lock;
-static struct fiq_handler *current_fiq;
-static unsigned long no_fiq_insn;
-
-#define FIQ_VECTOR ((unsigned long *)0x1c)
#ifndef SMP
#define irq_enter(cpu, irq) (++local_irq_count[cpu])
@@ -53,48 +42,65 @@ static unsigned long no_fiq_insn;
#error SMP not supported
#endif
-#ifdef CONFIG_ARCH_ACORN
-/* Bitmask indicating valid interrupt numbers
- * (to be moved to include/asm-arm/arch-*)
- */
-unsigned long validirqs[NR_IRQS / 32] = {
- 0x003ffe7f, 0x000001ff, 0x000000ff, 0x00000000
+#ifndef cliIF
+#define cliIF()
+#endif
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+spinlock_t irq_controller_lock;
+
+extern int get_fiq_list(char *);
+extern void init_FIQ(void);
+
+struct irqdesc {
+ unsigned int nomask : 1; /* IRQ does not mask in IRQ */
+ unsigned int enabled : 1; /* IRQ is currently enabled */
+ unsigned int triggered: 1; /* IRQ has occurred */
+ unsigned int probing : 1; /* IRQ in use for a probe */
+ unsigned int probe_ok : 1; /* IRQ can be used for probe */
+ unsigned int valid : 1; /* IRQ claimable */
+ unsigned int unused :26;
+ void (*mask_ack)(unsigned int irq); /* Mask and acknowledge IRQ */
+ void (*mask)(unsigned int irq); /* Mask IRQ */
+ void (*unmask)(unsigned int irq); /* Unmask IRQ */
+ struct irqaction *action;
+ unsigned int unused2[3];
};
-#define valid_irq(x) ((x) < NR_IRQS && validirqs[(x) >> 5] & (1 << ((x) & 31)))
-#else
+static struct irqdesc irq_desc[NR_IRQS];
-#define valid_irq(x) ((x) < NR_IRQS)
-#endif
+/*
+ * Dummy mask/unmask handler
+ */
+static void dummy_mask_unmask_irq(unsigned int irq)
+{
+}
-void disable_irq(unsigned int irq_nr)
+void disable_irq(unsigned int irq)
{
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags);
-#ifdef cliIF
- save_flags(flags);
cliIF();
-#endif
- mask_irq(irq_nr);
+ irq_desc[irq].enabled = 0;
+ irq_desc[irq].mask(irq);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
-void enable_irq(unsigned int irq_nr)
+void enable_irq(unsigned int irq)
{
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags);
-#ifdef cliIF
- save_flags (flags);
cliIF();
-#endif
- unmask_irq(irq_nr);
+ irq_desc[irq].enabled = 1;
+ irq_desc[irq].probing = 0;
+ irq_desc[irq].triggered = 0;
+ irq_desc[irq].unmask(irq);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
-struct irqaction *irq_action[NR_IRQS];
-
int get_irq_list(char *buf)
{
int i;
@@ -102,7 +108,7 @@ int get_irq_list(char *buf)
char *p = buf;
for (i = 0 ; i < NR_IRQS ; i++) {
- action = irq_action[i];
+ action = irq_desc[i].action;
if (!action)
continue;
p += sprintf(p, "%3d: %10u %s",
@@ -112,8 +118,8 @@ int get_irq_list(char *buf)
}
*p++ = '\n';
}
- p += sprintf(p, "FIQ: %s\n",
- current_fiq?current_fiq->name:"unused");
+
+ p += get_fiq_list(p);
return p - buf;
}
@@ -122,26 +128,30 @@ int get_irq_list(char *buf)
*/
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
+ struct irqdesc * desc = irq_desc + irq;
struct irqaction * action;
int status, cpu;
-#if defined(HAS_IOMD) || defined(HAS_IOC)
- if (irq != IRQ_EXPANSIONCARD)
-#endif
- {
- spin_lock(&irq_controller_lock);
- mask_and_ack_irq(irq);
- spin_unlock(&irq_controller_lock);
- }
+ spin_lock(&irq_controller_lock);
+ desc->mask_ack(irq);
+ spin_unlock(&irq_controller_lock);
cpu = smp_processor_id();
irq_enter(cpu, irq);
kstat.irqs[cpu][irq]++;
+ desc->triggered = 1;
/* Return with this interrupt masked if no action */
status = 0;
- action = *(irq + irq_action);
+ action = desc->action;
+
if (action) {
+ if (desc->nomask) {
+ spin_lock(&irq_controller_lock);
+ desc->unmask(irq);
+ spin_unlock(&irq_controller_lock);
+ }
+
if (!(action->flags & SA_INTERRUPT))
__sti();
@@ -150,33 +160,20 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
+
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
__cli();
- switch (irq) {
-#if defined(HAS_IOMD) || defined(HAS_IOC)
- 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:
+ if (!desc->nomask && desc->enabled) {
spin_lock(&irq_controller_lock);
- unmask_irq(irq);
+ desc->unmask(irq);
spin_unlock(&irq_controller_lock);
- break;
}
}
irq_exit(cpu, irq);
+
/*
* This should be conditional: we should really get
* a return code from the irq handler to tell us
@@ -197,9 +194,18 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
#if defined(CONFIG_ARCH_ACORN)
void do_ecard_IRQ(int irq, struct pt_regs *regs)
{
+ struct irqdesc * desc;
struct irqaction * action;
+ int cpu;
+
+ desc = irq_desc + irq;
+
+ cpu = smp_processor_id();
+ kstat.irqs[cpu][irq]++;
+ desc->triggered = 1;
+
+ action = desc->action;
- action = *(irq + irq_action);
if (action) {
do {
action->handler(irq, action->dev_id, regs);
@@ -207,7 +213,7 @@ void do_ecard_IRQ(int irq, struct pt_regs *regs)
} while (action);
} else {
spin_lock(&irq_controller_lock);
- mask_irq (irq);
+ desc->mask(irq);
spin_unlock(&irq_controller_lock);
}
}
@@ -219,11 +225,18 @@ int setup_arm_irq(int irq, struct irqaction * new)
struct irqaction *old, **p;
unsigned long flags;
- p = irq_action + irq;
+ if (new->flags & SA_SAMPLE_RANDOM)
+ rand_initialize_irq(irq);
+
+ spin_lock_irqsave(&irq_controller_lock, flags);
+
+ p = &irq_desc[irq].action;
if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
- if (!(old->flags & new->flags & SA_SHIRQ))
+ if (!(old->flags & new->flags & SA_SHIRQ)) {
+ spin_unlock_irqrestore(&irq_controller_lock, flags);
return -EBUSY;
+ }
/* add new interrupt at end of irq queue */
do {
@@ -233,18 +246,16 @@ int setup_arm_irq(int irq, struct irqaction * new)
shared = 1;
}
- if (new->flags & SA_SAMPLE_RANDOM)
- rand_initialize_irq(irq);
-
- save_flags_cli(flags);
*p = new;
if (!shared) {
- spin_lock(&irq_controller_lock);
- unmask_irq(irq);
- spin_unlock(&irq_controller_lock);
+ irq_desc[irq].nomask = (new->flags & SA_IRQNOMASK) ? 1 : 0;
+ irq_desc[irq].enabled = 1;
+ irq_desc[irq].probing = 0;
+ irq_desc[irq].unmask(irq);
}
- restore_flags(flags);
+
+ spin_unlock_irqrestore(&irq_controller_lock, flags);
return 0;
}
@@ -257,8 +268,8 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
{
unsigned long retval;
struct irqaction *action;
-
- if (!valid_irq(irq))
+
+ if (!irq_desc[irq].valid)
return -EINVAL;
if (!handler)
return -EINVAL;
@@ -286,14 +297,14 @@ void free_irq(unsigned int irq, void *dev_id)
struct irqaction * action, **p;
unsigned long flags;
- if (!valid_irq(irq)) {
+ if (!irq_desc[irq].valid) {
printk(KERN_ERR "Trying to free IRQ%d\n",irq);
#ifdef CONFIG_DEBUG_ERRORS
__backtrace();
#endif
return;
}
- for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+ for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
if (action->dev_id != dev_id)
continue;
@@ -310,75 +321,109 @@ void free_irq(unsigned int irq, void *dev_id)
#endif
}
-unsigned long probe_irq_on (void)
+/* Start the interrupt probing. Unlike other architectures,
+ * we don't return a mask of interrupts from probe_irq_on,
+ * but return the number of interrupts enabled for the probe.
+ * The interrupts which have been enabled for probing is
+ * instead recorded in the irq_desc structure.
+ */
+unsigned long probe_irq_on(void)
{
unsigned int i, irqs = 0;
unsigned long delay;
- /* first snaffle up any unassigned irqs */
- for (i = 15; i > 0; i--) {
- if (!irq_action[i] && valid_irq(i)) {
- enable_irq(i);
- irqs |= 1 << i;
- }
+ /*
+ * first snaffle up any unassigned but
+ * probe-able interrupts
+ */
+ spin_lock_irq(&irq_controller_lock);
+ for (i = 0; i < NR_IRQS; i++) {
+ if (!irq_desc[i].valid ||
+ !irq_desc[i].probe_ok ||
+ irq_desc[i].action)
+ continue;
+
+ irq_desc[i].probing = 1;
+ irq_desc[i].enabled = 1;
+ irq_desc[i].triggered = 0;
+ irq_desc[i].unmask(i);
+ irqs += 1;
}
+ spin_unlock_irq(&irq_controller_lock);
- /* wait for spurious interrupts to mask themselves out again */
+ /*
+ * wait for spurious interrupts to mask themselves out again
+ */
for (delay = jiffies + HZ/10; delay > jiffies; )
/* min 100ms delay */;
+ /*
+ * now filter out any obviously spurious interrupts
+ */
+ spin_lock_irq(&irq_controller_lock);
+ for (i = 0; i < NR_IRQS; i++) {
+ if (irq_desc[i].probing && irq_desc[i].triggered) {
+ irq_desc[i].probing = 0;
+ irqs -= 1;
+ }
+ }
+ spin_unlock_irq(&irq_controller_lock);
+
/* now filter out any obviously spurious interrupts */
- return irqs & get_enabled_irqs();
+ return irqs;
}
-int probe_irq_off (unsigned long irqs)
+/*
+ * Possible return values:
+ * >= 0 - interrupt number
+ * -1 - no interrupt/many interrupts
+ */
+int probe_irq_off(unsigned long irqs)
{
unsigned int i;
+ int irq_found = -1;
- irqs &= ~get_enabled_irqs();
- if (!irqs)
- return 0;
- i = ffz (~irqs);
- if (irqs != (irqs & (1 << i)))
- i = -i;
- return i;
-}
-
-int claim_fiq(struct fiq_handler *f)
-{
- if (current_fiq) {
- if (current_fiq->callback == NULL || (*current_fiq->callback)())
- return -EBUSY;
- }
- current_fiq = f;
- return 0;
-}
-
-void release_fiq(struct fiq_handler *f)
-{
- if (current_fiq != f) {
- printk(KERN_ERR "%s tried to release FIQ when not owner!\n",
- f->name);
-#ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
-#endif
- return;
+ /*
+ * look at the interrupts, and find exactly one
+ * that we were probing has been triggered
+ */
+ spin_lock_irq(&irq_controller_lock);
+ for (i = 0; i < NR_IRQS; i++) {
+ if (irq_desc[i].probing &&
+ irq_desc[i].triggered) {
+ if (irq_found != -1) {
+ irq_found = NO_IRQ;
+ goto out;
+ }
+ irq_found = i;
+ }
}
- current_fiq = NULL;
- *FIQ_VECTOR = no_fiq_insn;
- __flush_entry_to_ram(FIQ_VECTOR);
+ if (irq_found == -1)
+ irq_found = NO_IRQ;
+out:
+ spin_unlock_irq(&irq_controller_lock);
+ return irq_found;
}
+/*
+ * Get architecture specific interrupt handlers
+ * and interrupt initialisation.
+ */
+#include <asm/arch/irq.h>
+
__initfunc(void init_IRQ(void))
{
extern void init_dma(void);
+ int irq;
- irq_init_irq();
-
- current_fiq = NULL;
- no_fiq_insn = *FIQ_VECTOR;
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ irq_desc[irq].mask_ack = dummy_mask_unmask_irq;
+ irq_desc[irq].mask = dummy_mask_unmask_irq;
+ irq_desc[irq].unmask = dummy_mask_unmask_irq;
+ }
+ irq_init_irq();
+ init_FIQ();
init_dma();
}
-
diff --git a/arch/arm/kernel/leds-ebsa110.c b/arch/arm/kernel/leds-ebsa110.c
new file mode 100644
index 000000000..cc2f7a91d
--- /dev/null
+++ b/arch/arm/kernel/leds-ebsa110.c
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/kernel/leds-ebsa110.c
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * EBSA-110 LED control routines. We use the led as follows:
+ *
+ * - Red - toggles state every 50 timer interrupts
+ */
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+void leds_event(led_event_t ledevt)
+{
+ unsigned long flags;
+
+ save_flags_cli(flags);
+
+ switch(ledevt) {
+ case led_timer:
+ *(volatile unsigned char *)0xf2400000 ^= 128;
+ break;
+
+ default:
+ break;
+ }
+
+ restore_flags(flags);
+}
diff --git a/arch/arm/kernel/leds-ebsa285.c b/arch/arm/kernel/leds-ebsa285.c
index f8add1ab7..a8cf2e775 100644
--- a/arch/arm/kernel/leds-ebsa285.c
+++ b/arch/arm/kernel/leds-ebsa285.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/kernel/leds-285.c
+ * arch/arm/kernel/leds-ebsa285.c
*
* Copyright (C) 1998 Russell King
*
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index b606384c8..6ea02d891 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -38,9 +38,6 @@
#include <asm/system.h>
#include <asm/io.h>
-struct task_struct *last_task_used_math;
-
-extern void fpe_save(struct fp_soft_struct *);
extern char *processor_modes[];
asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
@@ -108,7 +105,6 @@ void machine_power_off(void)
{
}
-
void show_regs(struct pt_regs * regs)
{
unsigned long flags;
@@ -158,18 +154,14 @@ void show_regs(struct pt_regs * regs)
*/
void exit_thread(void)
{
- if (last_task_used_math == current)
- last_task_used_math = NULL;
}
void flush_thread(void)
{
int i;
- for (i = 0; i < 8; i++)
- current->debugreg[i] = 0;
- if (last_task_used_math == current)
- last_task_used_math = NULL;
+ for (i = 0; i < NR_DEBUGS; i++)
+ current->tss.debug[i] = 0;
current->used_math = 0;
current->flags &= ~PF_USEDFPU;
}
@@ -189,13 +181,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
childregs->ARM_r0 = 0;
save = ((struct context_save_struct *)(childregs)) - 1;
- copy_thread_css (save);
+ copy_thread_css(save);
p->tss.save = save;
- /*
- * Save current math state in p->tss.fpe_save if not already there.
- */
- if (last_task_used_math == current)
- fpe_save (&p->tss.fpstate.soft);
return 0;
}
@@ -207,12 +194,8 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
{
int fpvalid = 0;
- if (current->used_math) {
- if (last_task_used_math == current)
- fpe_save (&current->tss.fpstate.soft);
-
+ if (current->used_math)
memcpy (fp, &current->tss.fpstate.soft, sizeof (fp));
- }
return fpvalid;
}
@@ -232,8 +215,8 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_dsize = (current->mm->brk - current->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
dump->u_ssize = 0;
- for (i = 0; i < 8; i++)
- dump->u_debugreg[i] = current->debugreg[i];
+ for (i = 0; i < NR_DEBUGS; i++)
+ dump->u_debugreg[i] = current->tss.debug[i];
if (dump->start_stack < 0x04000000)
dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9ca7bc964..3df4ce886 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -3,7 +3,6 @@
/* edited by Linus Torvalds */
/* edited for ARM by Russell King */
-#include <linux/head.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -376,7 +375,7 @@ int ptrace_set_bpt (struct task_struct *child)
if (res < 0)
return res;
- child->debugreg[nsaved++] = alt = pc + 4;
+ child->tss.debug[nsaved++] = alt = pc + 4;
printk ("ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc);
switch (insn & 0x0e100000) {
case 0x00000000:
@@ -515,20 +514,20 @@ printk ("b/bl ");
}
printk ("=%08lX\n", alt);
if (alt != pc + 4)
- child->debugreg[nsaved++] = alt;
+ child->tss.debug[nsaved++] = alt;
for (i = 0; i < nsaved; i++) {
- res = read_long (child, child->debugreg[i], &insn);
+ res = read_long (child, child->tss.debug[i], &insn);
if (res >= 0) {
- child->debugreg[i + 2] = insn;
- res = write_long (child, child->debugreg[i], BREAKINST);
+ child->tss.debug[i + 2] = insn;
+ res = write_long (child, child->tss.debug[i], BREAKINST);
}
if (res < 0) {
- child->debugreg[4] = 0;
+ child->tss.debug[4] = 0;
return res;
}
}
- child->debugreg[4] = nsaved;
+ child->tss.debug[4] = nsaved;
return 0;
}
@@ -537,16 +536,16 @@ printk ("=%08lX\n", alt);
*/
int ptrace_cancel_bpt (struct task_struct *child)
{
- int i, nsaved = child->debugreg[4];
+ int i, nsaved = child->tss.debug[4];
- child->debugreg[4] = 0;
+ child->tss.debug[4] = 0;
if (nsaved > 2) {
printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
nsaved = 2;
}
for (i = 0; i < nsaved; i++)
- write_long (child, child->debugreg[i], child->debugreg[i + 2]);
+ write_long (child, child->tss.debug[i], child->tss.debug[i + 2]);
return nsaved != 0;
}
@@ -680,7 +679,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->debugreg[4] = -1;
+ child->tss.debug[4] = -1;
child->flags &= ~PF_TRACESYS;
wake_up_process(child);
child->exit_code = data;
diff --git a/arch/arm/kernel/setup-ebsa110.c b/arch/arm/kernel/setup-ebsa110.c
deleted file mode 100644
index 2da4d6327..000000000
--- a/arch/arm/kernel/setup-ebsa110.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * linux/arch/arm/kernel/setup-sa.c
- *
- * Copyright (C) 1995, 1996 Russell King
- */
-
-/*
- * This file obtains various parameters about the system that the kernel
- * is running on.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/malloc.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/utsname.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <asm/hardware.h>
-#include <asm/pgtable.h>
-#include <asm/procinfo.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)
-
-struct screen_info screen_info;
-struct processor processor;
-unsigned char aux_device_present;
-
-extern const struct processor sa110_processor_functions;
-
-struct armversions armidlist[] = {
- { 0x4401a100, 0xfffffff0, F_MMU|F_32BIT , "DEC", "sa110" , &sa110_processor_functions , "sa1x"},
- { 0x00000000, 0x00000000, 0 , "***", "*unknown*" , NULL , NULL }
-};
-
-unsigned long arm_id;
-int armidindex;
-
-extern int root_mountflags;
-extern int _etext, _edata, _end;
-
-static char command_line[COMMAND_LINE_SIZE] __initdata = { 0, };
- char saved_command_line[COMMAND_LINE_SIZE];
-
-#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(int start, int prompt, int load)
-{
- rd_image_start = start;
- rd_prompt = prompt;
- rd_doload = load;
-}
-#else
-#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 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
-
-__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;
-
- armidindex = 0;
-
- processor = sa110_processor_functions;
- processor._proc_init();
-
- from = setup_params(&memory_end);
-
- init_task.mm->start_code = TASK_SIZE;
- init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
- init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata;
- init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
-
- /* Save unparsed command line copy for /proc/cmdline */
- memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
- saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
- for (;;) {
- if (c == ' ' &&
- from[0] == 'm' &&
- from[1] == 'e' &&
- from[2] == 'm' &&
- from[3] == '=') {
- memory_end = simple_strtoul(from+4, &from, 0);
- if ( *from == 'K' || *from == 'k' ) {
- memory_end = memory_end << 10;
- from++;
- } else if ( *from == 'M' || *from == 'm' ) {
- memory_end = memory_end << 20;
- from++;
- }
- memory_end = memory_end + PAGE_OFFSET;
- }
- c = *from++;
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *to++ = c;
- }
-
- *to = '\0';
- *cmdline_p = command_line;
- *memory_start_p = memory_start;
- *memory_end_p = memory_end;
- strcpy (system_utsname.machine, "sa110");
-
-#ifdef CONFIG_FB
- conswitchp = &fb_con;
-#endif
-}
-
-int get_cpuinfo(char * buffer)
-{
- int len;
-
- len = sprintf (buffer, "CPU:\n"
- "Type\t\t: %s\n"
- "Revision\t: %d\n"
- "Manufacturer\t: %s\n"
- "32bit modes\t: %s\n"
- "BogoMips\t: %lu.%02lu\n",
- "sa110",
- (int)arm_id & 15,
- "DEC",
- "yes",
- (loops_per_sec+2500) / 500000,
- ((loops_per_sec+2500) / 5000) % 100);
- return len;
-}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b69ce22cb..767faff9e 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/kernel/setup.c
*
- * Copyright (C) 1995, 1996, 1997 Russell King
+ * Copyright (C) 1995-1998 Russell King
*/
/*
@@ -37,11 +37,37 @@
#include <asm/segment.h>
#include <asm/setup.h>
#include <asm/system.h>
-#include <asm/arch/mmu.h>
+
+/* Work out which CPUs to support */
+#ifdef CONFIG_ARCH_ACORN
+#define SUPPORT_CPU_ARM6
+#define SUPPORT_CPU_ARM7
+#define SUPPORT_CPU_SA110
+#else
+#define SUPPORT_CPU_SA110
+#endif
+#ifdef CONFIG_CPU_ARM6
+#define SUPPORT_CPU_ARM6
+#endif
+#ifdef CONFIG_CPU_ARM7
+#define SUPPORT_CPU_ARM7
+#endif
+#ifdef CONFIG_CPU_SA110
+#define SUPPORT_CPU_SA110
+#endif
+
+#ifndef CONFIG_CMDLINE
+#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8"
+#endif
+#define MEM_SIZE (16*1024*1024)
+#define COMMAND_LINE_SIZE 256
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8
+ orig_video_mode: 0,
+ orig_video_ega_bx: 0,
+ orig_video_isVGA: 1,
+ orig_video_points: 8
};
struct processor processor;
unsigned char aux_device_present;
@@ -66,35 +92,36 @@ const struct armversions armidlist[] = {
{ 0x41560300, 0xfffffff0, "ARM/VLSI", "arm3" , "armv2" , "v2", HWCAP_SWP,
&arm3_processor_functions },
#elif defined(CONFIG_CPU_32)
+#ifdef SUPPORT_CPU_ARM6
{ 0x41560600, 0xfffffff0, "ARM/VLSI", "arm6" , "armv3" , "v3", HWCAP_SWP,
&arm6_processor_functions },
{ 0x41560610, 0xfffffff0, "ARM/VLSI", "arm610" , "armv3" , "v3", HWCAP_SWP,
&arm6_processor_functions },
+#endif
+#ifdef SUPPORT_CPU_ARM7
{ 0x41007000, 0xffffff00, "ARM/VLSI", "arm7" , "armv3" , "v3", HWCAP_SWP,
&arm7_processor_functions },
/* ARM710 IDs are non-standard */
{ 0x41007100, 0xfff8ff00, "ARM/VLSI", "arm710" , "armv3" , "v3", HWCAP_SWP,
&arm7_processor_functions },
+#endif
+#ifdef SUPPORT_CPU_SA110
{ 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v3", HWCAP_SWP|HWCAP_HALF,
&sa110_processor_functions },
#endif
+#endif
{ 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL }
};
-static const struct param_struct *params = (struct param_struct *)PARAMS_BASE;
-
-unsigned long arm_id;
-unsigned int vram_half_sam;
+/*
+ * From head-armv.S
+ */
+unsigned int processor_id;
+unsigned int machine_type;
int armidindex;
-int memc_ctrl_reg;
-int number_ide_drives;
-int number_mfm_drives;
-extern int bytes_per_char_h;
-extern int bytes_per_char_v;
extern int root_mountflags;
extern int _etext, _edata, _end;
-extern unsigned long real_end_mem;
/*-------------------------------------------------------------------------
* Early initialisation routines for various configurable items in the
@@ -107,12 +134,15 @@ extern unsigned long real_end_mem;
*/
#ifdef CONFIG_ARCH_RPC
-extern void
-init_dram_banks(const struct param_struct *params);
+#include <asm/arch/mmu.h>
+
+unsigned int vram_half_sam;
static void
-setup_rpc(const struct param_struct *params)
+setup_rpc(struct param_struct *params)
{
+ extern void init_dram_banks(const struct param_struct *params);
+
init_dram_banks(params);
switch (params->u1.s.pages_in_vram) {
@@ -123,41 +153,103 @@ setup_rpc(const struct param_struct *params)
default:
vram_half_sam = 2048;
}
-
- /*
- * Set ROM speed to maximum
- */
- outb (0x1d, IOMD_ROMCR0);
}
#else
#define setup_rpc(x)
#endif
-/*
- * ram disk
- */
-#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 */
+#ifdef PARAMS_BASE
-static void
-setup_ramdisk(const struct param_struct *params)
+#ifdef CONFIG_ARCH_ACORN
+int memc_ctrl_reg;
+int number_ide_drives;
+int number_mfm_drives;
+#endif
+
+static struct param_struct *params = (struct param_struct *)PARAMS_BASE;
+
+__initfunc(static char *
+setup_params(unsigned long *mem_end_p))
{
- rd_image_start = params->u1.s.rd_start;
- rd_prompt = (params->u1.s.flags & FLAG_RDPROMPT) == 0;
- rd_doload = (params->u1.s.flags & FLAG_RDLOAD) == 0;
+ 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;
+
+#ifdef CONFIG_ARCH_ACORN
+#ifndef CONFIG_FB
+ {
+ extern int bytes_per_char_h;
+ extern int bytes_per_char_v;
+
+ bytes_per_char_h = params->u1.s.bytes_per_char_h;
+ bytes_per_char_v = params->u1.s.bytes_per_char_v;
+ }
+#endif
+ memc_ctrl_reg = params->u1.s.memc_control_reg;
+ number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3;
+ number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3;
+
+ setup_rpc(params);
+
+ if (!(params->u1.s.flags & FLAG_READONLY))
+ root_mountflags &= ~MS_RDONLY;
+#endif
+#ifdef CONFIG_BLK_DEV_RAM
+ {
+ extern int rd_doload;
+ extern int rd_prompt;
+ extern int rd_image_start;
+
+ rd_image_start = params->u1.s.rd_start;
+ rd_prompt = (params->u1.s.flags & FLAG_RDPROMPT) == 0;
+ rd_doload = (params->u1.s.flags & FLAG_RDLOAD) == 0;
+ }
+#endif
+
+#ifdef CONFIG_ARCH_ACORN
+ *mem_end_p = GET_MEMORY_END(params);
+#else
+ *mem_end_p = PAGE_OFFSET + MEM_SIZE;
+#endif
+
+ return params->commandline;
}
+
#else
-#define setup_ramdisk(p)
+
+static char default_command_line[] __initdata = CONFIG_CMDLINE;
+
+__initfunc(static char *
+setup_params(unsigned long *mem_end_p))
+{
+ ROOT_DEV = 0x00ff;
+
+#ifdef CONFIG_BLK_DEV_RAM
+ {
+ extern int rd_doload;
+ extern int rd_prompt;
+ extern int rd_image_start;
+
+ rd_image_start = 0;
+ rd_prompt = 1;
+ rd_doload = 1;
+ }
+#endif
+
+ *mem_end_p = PAGE_OFFSET + MEM_SIZE;
+
+ return default_command_line;
+}
#endif
/*
* initial ram disk
*/
#ifdef CONFIG_BLK_DEV_INITRD
-static void
-setup_initrd(const struct param_struct *params, unsigned long memory_end)
+__initfunc(static void
+setup_initrd(const struct param_struct *params))
{
if (params->u1.s.initrd_start) {
initrd_start = params->u1.s.initrd_start;
@@ -166,130 +258,130 @@ setup_initrd(const struct param_struct *params, unsigned long memory_end)
initrd_start = 0;
initrd_end = 0;
}
+}
- if (initrd_end > memory_end) {
+__initfunc(static void
+check_initrd(unsigned long mem_start, unsigned long mem_end))
+{
+ if (initrd_end > mem_end) {
printk ("initrd extends beyond end of memory "
"(0x%08lx > 0x%08lx) - disabling initrd\n",
- initrd_end, memory_end);
+ initrd_end, mem_end);
initrd_start = 0;
}
}
+
#else
-#define setup_initrd(p,m)
+#define setup_initrd(p)
+#define check_initrd(ms,me)
#endif
-static inline void
-get_processor_type(void)
+__initfunc(void
+setup_processor(void))
{
- for (armidindex = 0; ; armidindex ++)
- if (!((armidlist[armidindex].id ^ arm_id) &
- armidlist[armidindex].mask))
- break;
+ armidindex = 0;
+
+ while ((armidlist[armidindex].id ^ processor_id) &
+ armidlist[armidindex].mask)
+ armidindex += 1;
if (armidlist[armidindex].id == 0) {
+#ifdef CONFIG_ARCH_ACORN
int i;
for (i = 0; i < 3200; i++)
((unsigned long *)SCREEN2_BASE)[i] = 0x77113322;
-
+#endif
while (1);
}
+
processor = *armidlist[armidindex].proc;
+ processor._proc_init();
}
-#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] __initdata = { 0, };
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
-__initfunc(void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p))
+__initfunc(static void
+setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end))
+{
+ char c = ' ', *to = command_line;
+ int len = 0;
+
+ *mem_start = (unsigned long)&_end;
+
+ for (;;) {
+ if (c == ' ' &&
+ cmd_line[0] == 'm' &&
+ cmd_line[1] == 'e' &&
+ cmd_line[2] == 'm' &&
+ cmd_line[3] == '=') {
+ *mem_end = simple_strtoul(cmd_line+4, &cmd_line, 0);
+ switch(*cmd_line) {
+ case 'M':
+ case 'm':
+ *mem_end <<= 10;
+ case 'K':
+ case 'k':
+ *mem_end <<= 10;
+ cmd_line++;
+ }
+ *mem_end = *mem_end + PAGE_OFFSET;
+ }
+ c = *cmd_line++;
+ if (!c)
+ break;
+ if (COMMAND_LINE_SIZE <= ++len)
+ break;
+ *to++ = c;
+ }
+
+ *to = '\0';
+}
+
+__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;
- char endian = 'l', c = ' ', *to = command_line;
+ unsigned long memory_end;
+ char endian = 'l';
char *from;
- int len = 0;
if (smptrap == 1)
return;
smptrap = 1;
- get_processor_type ();
- processor._proc_init ();
+ setup_processor();
-#ifndef CONFIG_FB
- bytes_per_char_h = params->u1.s.bytes_per_char_h;
- bytes_per_char_v = params->u1.s.bytes_per_char_v;
-#endif
- from = (char *)params->commandline;
- 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;
- memc_ctrl_reg = params->u1.s.memc_control_reg;
- number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3;
- number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3;
+ from = setup_params(&memory_end);
+ setup_initrd(params);
- setup_rpc(params);
- setup_ramdisk(params);
-
- if (!(params->u1.s.flags & FLAG_READONLY))
- root_mountflags &= ~MS_RDONLY;
+ /* Save unparsed command line copy for /proc/cmdline */
+ memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
+ saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
- memory_start = MAPTOPHYS((unsigned long)&_end);
- memory_end = GET_MEMORY_END(params);
+ setup_mem(from, memory_start_p, &memory_end);
+ check_initrd(*memory_start_p, memory_end);
init_task.mm->start_code = TASK_SIZE;
init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata;
init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
- /* Save unparsed command line copy for /proc/cmdline */
- memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
- saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
- for (;;) {
- if (c == ' ' &&
- from[0] == 'm' &&
- from[1] == 'e' &&
- from[2] == 'm' &&
- from[3] == '=') {
- memory_end = simple_strtoul(from+4, &from, 0);
- if (*from == 'K' || *from == 'k') {
- memory_end = memory_end << 10;
- from++;
- } else if (*from == 'M' || *from == 'm') {
- memory_end = memory_end << 20;
- from++;
- }
- memory_end = memory_end + PAGE_OFFSET;
- }
- c = *from++;
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *to++ = c;
- }
-
- *to = '\0';
*cmdline_p = command_line;
- *memory_start_p = memory_start;
*memory_end_p = memory_end;
- setup_initrd(params, memory_end);
-
sprintf(system_utsname.machine, "%s%c", armidlist[armidindex].arch_vsn, endian);
sprintf(elf_platform, "%s%c", armidlist[armidindex].elf_vsn, endian);
-#ifdef CONFIG_FB
- conswitchp = &fb_con;
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
#endif
+printascii("setup_arch done\n");
}
#if defined(CONFIG_ARCH_ARC)
@@ -341,10 +433,10 @@ int get_cpuinfo(char * buffer)
"BogoMips\t: %lu.%02lu\n"
"Hardware\t: %s\n"
"Optimisation\t: %s\n"
- "IO Bus\t: %s\n",
+ "IO Bus\t\t: %s\n",
armidlist[armidindex].manu,
armidlist[armidindex].name,
- (int)arm_id & 15,
+ (int)processor_id & 15,
(loops_per_sec+2500) / 500000,
((loops_per_sec+2500) / 5000) % 100,
HARDWARE,
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 59e802a6c..fc5717e87 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -21,6 +21,17 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+void checksignals(void)
+{
+ sigset_t *blocked = &current->blocked;
+ unsigned long mask = blocked->sig[0] | sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT);
+ mask &= blocked->sig[1];
+ if (~mask) {
+ printk("Bad signal mask\n");
+ __backtrace();
+ }
+}
+
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn))
@@ -137,31 +148,35 @@ struct rt_sigframe
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
{
- __get_user(regs->ARM_r0, &sc->arm_r0);
- __get_user(regs->ARM_r1, &sc->arm_r1);
- __get_user(regs->ARM_r2, &sc->arm_r2);
- __get_user(regs->ARM_r3, &sc->arm_r3);
- __get_user(regs->ARM_r4, &sc->arm_r4);
- __get_user(regs->ARM_r5, &sc->arm_r5);
- __get_user(regs->ARM_r6, &sc->arm_r6);
- __get_user(regs->ARM_r7, &sc->arm_r7);
- __get_user(regs->ARM_r8, &sc->arm_r8);
- __get_user(regs->ARM_r9, &sc->arm_r9);
- __get_user(regs->ARM_r10, &sc->arm_r10);
- __get_user(regs->ARM_fp, &sc->arm_fp);
- __get_user(regs->ARM_ip, &sc->arm_ip);
- __get_user(regs->ARM_sp, &sc->arm_sp);
- __get_user(regs->ARM_lr, &sc->arm_lr);
- __get_user(regs->ARM_pc, &sc->arm_pc); /* security! */
+ int err = 0;
+
+ err |= __get_user(regs->ARM_r0, &sc->arm_r0);
+ err |= __get_user(regs->ARM_r1, &sc->arm_r1);
+ err |= __get_user(regs->ARM_r2, &sc->arm_r2);
+ err |= __get_user(regs->ARM_r3, &sc->arm_r3);
+ err |= __get_user(regs->ARM_r4, &sc->arm_r4);
+ err |= __get_user(regs->ARM_r5, &sc->arm_r5);
+ err |= __get_user(regs->ARM_r6, &sc->arm_r6);
+ err |= __get_user(regs->ARM_r7, &sc->arm_r7);
+ err |= __get_user(regs->ARM_r8, &sc->arm_r8);
+ err |= __get_user(regs->ARM_r9, &sc->arm_r9);
+ err |= __get_user(regs->ARM_r10, &sc->arm_r10);
+ err |= __get_user(regs->ARM_fp, &sc->arm_fp);
+ err |= __get_user(regs->ARM_ip, &sc->arm_ip);
+ err |= __get_user(regs->ARM_sp, &sc->arm_sp);
+ err |= __get_user(regs->ARM_lr, &sc->arm_lr);
+ err |= __get_user(regs->ARM_pc, &sc->arm_pc);
#ifdef CONFIG_CPU_32
- __get_user(regs->ARM_cpsr, &sc->arm_cpsr); /* security! */
+ err |= __get_user(regs->ARM_cpsr, &sc->arm_cpsr);
#endif
+ if (!valid_user_regs(regs))
+ return 1;
/* send SIGTRAP if we're single-stepping */
if (ptrace_cancel_bpt (current))
send_sig (SIGTRAP, current, 1);
- return regs->ARM_r0;
+ return err;
}
asmlinkage int sys_sigreturn(struct pt_regs *regs)
@@ -185,11 +200,14 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
- return restore_sigcontext(regs, &frame->sc);
+ if (restore_sigcontext(regs, &frame->sc))
+ goto badframe;
+
+ return regs->ARM_r0;
badframe:
- lock_kernel();
- do_exit(SIGSEGV);
+ force_sig(SIGSEGV, current);
+ return 0;
}
asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
@@ -210,40 +228,47 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
- return restore_sigcontext(regs, &frame->uc.uc_mcontext);
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
+ return regs->ARM_r0;
badframe:
- lock_kernel();
- do_exit(SIGSEGV);
+ force_sig(SIGSEGV, current);
+ return 0;
}
-static void
+static int
setup_sigcontext(struct sigcontext *sc, /*struct _fpstate *fpstate,*/
struct pt_regs *regs, unsigned long mask)
{
- __put_user (regs->ARM_r0, &sc->arm_r0);
- __put_user (regs->ARM_r1, &sc->arm_r1);
- __put_user (regs->ARM_r2, &sc->arm_r2);
- __put_user (regs->ARM_r3, &sc->arm_r3);
- __put_user (regs->ARM_r4, &sc->arm_r4);
- __put_user (regs->ARM_r5, &sc->arm_r5);
- __put_user (regs->ARM_r6, &sc->arm_r6);
- __put_user (regs->ARM_r7, &sc->arm_r7);
- __put_user (regs->ARM_r8, &sc->arm_r8);
- __put_user (regs->ARM_r9, &sc->arm_r9);
- __put_user (regs->ARM_r10, &sc->arm_r10);
- __put_user (regs->ARM_fp, &sc->arm_fp);
- __put_user (regs->ARM_ip, &sc->arm_ip);
- __put_user (regs->ARM_sp, &sc->arm_sp);
- __put_user (regs->ARM_lr, &sc->arm_lr);
- __put_user (regs->ARM_pc, &sc->arm_pc); /* security! */
+ int err = 0;
+
+ err |= __put_user (regs->ARM_r0, &sc->arm_r0);
+ err |= __put_user (regs->ARM_r1, &sc->arm_r1);
+ err |= __put_user (regs->ARM_r2, &sc->arm_r2);
+ err |= __put_user (regs->ARM_r3, &sc->arm_r3);
+ err |= __put_user (regs->ARM_r4, &sc->arm_r4);
+ err |= __put_user (regs->ARM_r5, &sc->arm_r5);
+ err |= __put_user (regs->ARM_r6, &sc->arm_r6);
+ err |= __put_user (regs->ARM_r7, &sc->arm_r7);
+ err |= __put_user (regs->ARM_r8, &sc->arm_r8);
+ err |= __put_user (regs->ARM_r9, &sc->arm_r9);
+ err |= __put_user (regs->ARM_r10, &sc->arm_r10);
+ err |= __put_user (regs->ARM_fp, &sc->arm_fp);
+ err |= __put_user (regs->ARM_ip, &sc->arm_ip);
+ err |= __put_user (regs->ARM_sp, &sc->arm_sp);
+ err |= __put_user (regs->ARM_lr, &sc->arm_lr);
+ err |= __put_user (regs->ARM_pc, &sc->arm_pc);
#ifdef CONFIG_CPU_32
- __put_user (regs->ARM_cpsr, &sc->arm_cpsr); /* security! */
+ err |= __put_user (regs->ARM_cpsr, &sc->arm_cpsr);
#endif
- __put_user (current->tss.trap_no, &sc->trap_no);
- __put_user (current->tss.error_code, &sc->error_code);
- __put_user (mask, &sc->oldmask);
+ err |= __put_user (current->tss.trap_no, &sc->trap_no);
+ err |= __put_user (current->tss.error_code, &sc->error_code);
+ err |= __put_user (mask, &sc->oldmask);
+
+ return err;
}
static void setup_frame(int sig, struct k_sigaction *ka,
@@ -251,41 +276,47 @@ static void setup_frame(int sig, struct k_sigaction *ka,
{
struct sigframe *frame;
unsigned long retcode;
+ int err = 0;
frame = (struct sigframe *)regs->ARM_sp - 1;
if (!access_ok(VERIFT_WRITE, frame, sizeof (*frame)))
goto segv_and_exit;
- setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
+ err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
if (_NSIG_WORDS > 1) {
- __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
}
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- retcode = (unsigned long)ka->sa.sa_restorer; /* security! */
+ retcode = (unsigned long)ka->sa.sa_restorer;
} else {
retcode = (unsigned long)&frame->retcode;
- __put_user(SWI_SYS_SIGRETURN, &frame->retcode);
+ err |= __put_user(SWI_SYS_SIGRETURN, &frame->retcode);
__flush_entry_to_ram (&frame->retcode);
}
+ if (err)
+ goto segv_and_exit;
+
if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32)
regs->ARM_r0 = current->exec_domain->signal_invmap[sig];
else
regs->ARM_r0 = sig;
regs->ARM_sp = (unsigned long)frame;
regs->ARM_lr = retcode;
- regs->ARM_pc = (unsigned long)ka->sa.sa_handler; /* security! */
- return;
+ regs->ARM_pc = (unsigned long)ka->sa.sa_handler;
+ if (valid_user_regs(regs))
+ return;
segv_and_exit:
- lock_kernel();
- do_exit (SIGSEGV);
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
}
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -293,44 +324,50 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
{
struct rt_sigframe *frame;
unsigned long retcode;
+ int err = 0;
frame = (struct rt_sigframe *)regs->ARM_sp - 1;
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto segv_and_exit;
- __put_user(&frame->info, &frame->pinfo);
- __put_user(&frame->uc, &frame->puc);
- __copy_to_user(&frame->info, info, sizeof(*info));
+ err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->uc, &frame->puc);
+ err |= __copy_to_user(&frame->info, info, sizeof(*info));
/* Clear all the bits of the ucontext we don't use. */
- __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+ err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
- setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/
- regs, set->sig[0]);
- __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/
+ regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- retcode = (unsigned long)ka->sa.sa_restorer; /* security! */
+ retcode = (unsigned long)ka->sa.sa_restorer;
} else {
retcode = (unsigned long)&frame->retcode;
- __put_user(SWI_SYS_RT_SIGRETURN, &frame->retcode);
+ err |= __put_user(SWI_SYS_RT_SIGRETURN, &frame->retcode);
__flush_entry_to_ram (&frame->retcode);
}
+ if (err)
+ goto segv_and_exit;
+
if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32)
regs->ARM_r0 = current->exec_domain->signal_invmap[sig];
else
regs->ARM_r0 = sig;
regs->ARM_sp = (unsigned long)frame;
regs->ARM_lr = retcode;
- regs->ARM_pc = (unsigned long)ka->sa.sa_handler; /* security! */
- return;
+ regs->ARM_pc = (unsigned long)ka->sa.sa_handler;
+ if (valid_user_regs(regs))
+ return;
segv_and_exit:
- lock_kernel();
- do_exit (SIGSEGV);
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
}
/*
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index ba0d4eda2..56ada1dc7 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -363,14 +363,6 @@ asmlinkage int sys_olduname(struct oldold_utsname * name)
asmlinkage int sys_pause(void)
{
- static int warned = 0;
-
- if (warned == 0) {
- warned ++;
- printk (KERN_NOTICE "%s (%d): obsolete pause call\n",
- current->comm, current->pid);
- }
-
current->state = TASK_INTERRUPTIBLE;
schedule();
return -ERESTARTNOHAND;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 32aa6a083..7445921d9 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -62,7 +62,7 @@ extern volatile unsigned long lost_ticks;
* machines were long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
-static inline unsigned long mktime(unsigned int year, unsigned int mon,
+unsigned long mktime(unsigned int year, unsigned int mon,
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec)
{
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 2170dfd58..6da813aa2 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -24,9 +24,6 @@
#include <asm/atomic.h>
#include <asm/pgtable.h>
-extern struct task_struct *last_task_used_math;
-extern void fpe_save(struct fp_soft_struct *);
-extern void fpe_restore(struct fp_soft_struct *);
extern void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret);
extern void c_backtrace (unsigned long fp, int pmode);
extern int ptrace_cancel_bpt (struct task_struct *);
@@ -252,26 +249,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
*/
asmlinkage void math_state_restore (void)
{
- if (last_task_used_math == current)
- return;
- if (last_task_used_math)
- /*
- * Save current fp state into last_task_used_math->tss.fpe_save
- */
- fpe_save (&last_task_used_math->tss.fpstate.soft);
- last_task_used_math = current;
- if (current->used_math) {
- /*
- * Restore current fp state from current->tss.fpe_save
- */
- fpe_restore (&current->tss.fpstate.soft);
- } else {
- /*
- * initialise fp state
- */
- fpe_restore (&init_task.tss.fpstate.soft);
- current->used_math = 1;
- }
+ current->used_math = 1;
}
asmlinkage void arm_syscall (int no, struct pt_regs *regs)