summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
commit86464aed71025541805e7b1515541aee89879e33 (patch)
treee01a457a4912a8553bc65524aa3125d51f29f810 /arch/arm
parent88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff)
Merge with Linux 2.2.1.
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Makefile7
-rw-r--r--arch/arm/config.in34
-rw-r--r--arch/arm/kernel/Makefile54
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/dec21285.c100
-rw-r--r--arch/arm/kernel/dma-a5k.c2
-rw-r--r--arch/arm/kernel/dma-ebsa285.c123
-rw-r--r--arch/arm/kernel/dma-isa.c107
-rw-r--r--arch/arm/kernel/dma-isa.h25
-rw-r--r--arch/arm/kernel/dma-vnc.c51
-rw-r--r--arch/arm/kernel/dma.c20
-rw-r--r--arch/arm/kernel/ecard.c360
-rw-r--r--arch/arm/kernel/entry-armo.S52
-rw-r--r--arch/arm/kernel/entry-armv.S87
-rw-r--r--arch/arm/kernel/entry-common.S2
-rw-r--r--arch/arm/kernel/fiq.c9
-rw-r--r--arch/arm/kernel/head-armo.S3
-rw-r--r--arch/arm/kernel/head-armv.S49
-rw-r--r--arch/arm/kernel/hw-ebsa285.c161
-rw-r--r--arch/arm/kernel/init_task.c1
-rw-r--r--arch/arm/kernel/irq.c6
-rw-r--r--arch/arm/kernel/setup.c65
-rw-r--r--arch/arm/kernel/sys_arm.c3
-rw-r--r--arch/arm/kernel/time.c10
-rw-r--r--arch/arm/kernel/traps.c4
-rw-r--r--arch/arm/lib/Makefile4
-rw-r--r--arch/arm/lib/io-ebsa285.S71
-rw-r--r--arch/arm/mm/fault-armo.c2
-rw-r--r--arch/arm/mm/fault-armv.c2
-rw-r--r--arch/arm/mm/init.c9
-rw-r--r--arch/arm/mm/mm-ebsa285.c62
-rw-r--r--arch/arm/mm/mm-rpc.c3
-rw-r--r--arch/arm/mm/mm-vnc.c19
-rw-r--r--arch/arm/mm/proc-sa110.S16
34 files changed, 1014 insertions, 511 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 5ef8ea75e..967ee6766 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -120,6 +120,7 @@ COMPRESSED_HEAD = head-nexuspci.o
endif
ifeq ($(CONFIG_ARCH_VNC),y)
+TEXTADDR = 0xC000C000
MACHINE = vnc
ARCHDIR = vnc
endif
@@ -141,7 +142,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
OBJDUMP = $(CROSS_COMPILE)objdump
CPP = $(CC) -E
ARCHCC := $(word 1,$(CC))
-GCCLIB := `$(ARCHCC) $(CFLAGS_PROC) --print-libgcc-file-name`
+GCCLIB := `$(CC) $(CFLAGS_PROC) --print-libgcc-file-name`
#GCCARCH := -B/usr/bin/arm-linuxelf-
HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=)
ifeq ($(CONFIG_FRAME_POINTER),y)
@@ -160,10 +161,10 @@ LIBS := arch/arm/lib/lib.a $(LIBS) $(GCCLIB)
BLOCK_DRIVERS := drivers/block/block.a
CDROM_DRIVERS := drivers/cdrom/cdrom.a
ifeq ($(CONFIG_FB),y)
-CHAR_DRIVERS := arch/arm/drivers/char1/char.a
+CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a
else
ifeq ($(CONFIG_VGA_CONSOLE),y)
-CHAR_DRIVERS := arch/arm/drivers/char1/char.a
+CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a
else
CHAR_DRIVERS := arch/arm/drivers/char/char.a
endif
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 2b59a964c..467218db7 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -38,15 +38,22 @@ if [ "$CONFIG_ARCH_TBOX" = "y" ]; then
define_bool CONFIG_BUS_I2C y
fi
-# These machines have PCI/may have PCI
+# These machines always have PCI
if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \
"$CONFIG_ARCH_VNC" = "y" ]; then
define_bool CONFIG_PCI y
+fi
+if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then
+ bool "PCI support" CONFIG_PCI
+fi
+
+# These machines have ISA-DMA
+if [ "$CONFIG_CATS" = "y" -o \
+ "$CONFIG_ARCH_VNC" = "y" ]; then
+ define_bool CONFIG_ISA_DMA y
else
- if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then
- bool "PCI support" CONFIG_PCI
- fi
+ define_bool CONFIG_ISA_DMA n
fi
# Figure out whether this system uses 26-bit or 32-bit CPUs. Nobody has
@@ -122,6 +129,11 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
fi
fi
fi
+if [ "$CONFIG_ARCH_EBSA285" = "y" -o \
+ "$CONFIG_ARCH_EBSA110" = "y" -o \
+ "$CONFIG_ARCH_VNC" = "y" ]; then
+ string 'Initial kernel command string' CONFIG_CMDLINE
+fi
endmenu
source drivers/pnp/Config.in
@@ -132,16 +144,20 @@ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
source drivers/acorn/block/Config.in
fi
-source arch/arm/drivers/char/Config.in
+if [ "$CONFIG_VGA_CONSOLE" = "n" -a "$CONFIG_FB" = "n" ]; then
+ source arch/arm/drivers/char/Config.in
+else
+ source drivers/char/Config.in
+fi
+if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+ source drivers/acorn/char/Config.in
+fi
if [ "$CONFIG_VT" = "y" ]; then
mainmenu_option next_comment
comment 'Console drivers'
if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
bool 'VGA text console' CONFIG_VGA_CONSOLE
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'Video mode selection support' CONFIG_VIDEO_SELECT
- fi
fi
bool 'Support Frame buffer devices' CONFIG_FB
source drivers/video/Config.in
@@ -195,8 +211,6 @@ fi
source fs/Config.in
-source fs/nls/Config.in
-
mainmenu_option next_comment
comment 'Kernel hacking'
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 542ca995a..23b2c1267 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -10,44 +10,54 @@ ENTRY_OBJ = entry-$(PROCESSOR).o
O_TARGET := kernel.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
+ signal.o sys_arm.o time.o traps.o
+
+DMA_OBJS_arc = dma-arc.o
+DMA_OBJS_a5k = dma-a5k.o
+DMA_OBJS_rpc = dma-rpc.o
+DMA_OBJS_ebsa110 = dma-dummy.o
+DMA_OBJS_ebsa285 = dma-ebsa285.o
+DMA_OBJS_nexuspci =
+DMA_OBJS_vnc = dma-vnc.o
+
+O_OBJS_arc = ecard.o iic.o fiq.o oldlatches.o
+O_OBJS_a5k = ecard.o iic.o fiq.o
+O_OBJS_rpc = ecard.o iic.o fiq.o
+O_OBJS_ebsa110 = leds-ebsa110.o
+O_OBJS_ebsa285 = leds-ebsa285.o hw-ebsa285.o
+O_OBJS_nexuspci =
+O_OBJS_vnc = leds-ebsa285.o hw-vnc.o
all: lib kernel.o $(HEAD_OBJ) init_task.o
ifeq ($(CONFIG_MODULES),y)
-OX_OBJS = armksyms.o
+ OX_OBJS = armksyms.o
else
-O_OBJS += armksyms.o
+ O_OBJS += armksyms.o
endif
-ifdef CONFIG_ARCH_ACORN
- O_OBJS += ecard.o iic.o
- ifdef CONFIG_ARCH_ARC
- O_OBJS += oldlatches.o
+ifeq ($(MACHINE),nexuspci)
+ ifdef CONFIG_PCI
+ O_OBJS += plx9080.o
endif
- O_OBJS += dma-$(MACHINE).o
- OX_OBJS += dma.o
-endif
-
-ifeq ($(MACHINE),ebsa110)
- O_OBJS += dma-dummy.o leds-ebsa110.o
-endif
-
-ifeq ($(MACHINE),ebsa285)
- OX_OBJS += dma.o
- O_OBJS += dma-ebsa285.o leds-ebsa285.o
+else
ifdef CONFIG_PCI
O_OBJS += dec21285.o
endif
endif
-ifeq ($(MACHINE),nexuspci)
- O_OBJS += dma-dummy.o
- ifdef CONFIG_PCI
- O_OBJS += plx9080.o
+ifneq ($(DMA_OBJS_$(MACHINE)),)
+ OX_OBJS += dma.o
+ O_OBJS += $(DMA_OBJS_$(MACHINE))
+ ifeq ($(CONFIG_ISA_DMA),y)
+ O_OBJS += dma-isa.o
endif
+else
+ O_OBJS += dma-dummy.o
endif
+O_OBJS += $(O_OBJS_$(MACHINE))
+
$(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
$(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 751f9616a..46f71fa92 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -9,7 +9,7 @@
#define NR_syscalls 256
#else
-/* 0 */ .long SYMBOL_NAME(sys_setup)
+/* 0 */ .long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_exit)
.long SYMBOL_NAME(sys_fork_wrapper)
.long SYMBOL_NAME(sys_read)
diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c
index de4861b82..aa66ee04a 100644
--- a/arch/arm/kernel/dec21285.c
+++ b/arch/arm/kernel/dec21285.c
@@ -3,14 +3,23 @@
*
* Copyright (C) 1998 Russell King, Phil Blundell
*/
+#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
#include <linux/init.h>
+#include <asm/irq.h>
#include <asm/system.h>
#define MAX_SLOTS 20
+extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
+extern void pcibios_init_ebsa285(void);
+extern void pcibios_fixup_vnc(struct pci_dev *dev);
+extern void pcibios_init_vnc(void);
+
int
pcibios_present(void)
{
@@ -24,12 +33,11 @@ pcibios_base_address(unsigned char bus, unsigned char dev_fn)
int slot = PCI_SLOT(dev_fn);
if (slot < MAX_SLOTS)
- return 0xf8c00000 + (slot << 11);
+ return 0xf8c00000 + (slot << 11) + (PCI_FUNC(dev_fn) << 8);
else
return 0;
- } else {
+ } else
return 0xf9000000 | (bus << 16) | (dev_fn << 8);
- }
}
int
@@ -119,56 +127,35 @@ pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 };
-static int irqmap_cats[] __initdata = { 18, 8, 9, 11 };
-
-__initfunc(static int ebsa_irqval(struct pci_dev *dev))
+__initfunc(void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set))
{
- unsigned char pin;
-
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_PIN,
- &pin);
-
- return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
+ unsigned short cmd;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd = (cmd & ~clear) | set;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
}
-__initfunc(static int cats_irqval(struct pci_dev *dev))
+__initfunc(void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr))
{
- 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;
- }
+ int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
- printk("PCI: device %02x:%02x has unknown irq line %x\n",
- dev->bus->number, dev->devfn, dev->irq);
- return 0;
+ pci_write_config_dword(dev, reg, addr);
+ pci_read_config_dword(dev, reg, &addr);
+
+ dev->base_address[idx] = addr;
}
__initfunc(void pcibios_fixup(void))
{
struct pci_dev *dev;
- unsigned char cmd;
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;
- }
+ if (machine_is_ebsa285() || machine_is_cats())
+ pcibios_fixup_ebsa285(dev);
+ if (machine_is_netwinder())
+ pcibios_fixup_vnc(dev);
+
pcibios_write_config_byte(dev->bus->number, dev->devfn,
PCI_INTERRUPT_LINE, dev->irq);
@@ -176,34 +163,19 @@ __initfunc(void pcibios_fixup(void))
"PCI: %02x:%02x [%04x/%04x] on irq %d\n",
dev->bus->number, dev->devfn,
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);
}
+ if (machine_is_netwinder())
+ hw_init();
}
__initfunc(void pcibios_init(void))
{
- int rev;
-
- rev = *(unsigned char *)0xfe000008;
- printk("DEC21285 PCI revision %02X\n", rev);
-
- /*
- * 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;
+ if (machine_is_ebsa285() || machine_is_cats())
+ pcibios_init_ebsa285();
+ if (machine_is_netwinder())
+ pcibios_init_vnc();
+
+ printk("DEC21285 PCI revision %02X\n", *(unsigned char *)0xfe000008);
}
__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
diff --git a/arch/arm/kernel/dma-a5k.c b/arch/arm/kernel/dma-a5k.c
index 50ee42435..18bbf0c9c 100644
--- a/arch/arm/kernel/dma-a5k.c
+++ b/arch/arm/kernel/dma-a5k.c
@@ -16,7 +16,7 @@
#include "dma.h"
-static struct fiq_handler fh = { "floppydma", NULL };
+static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL };
int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id)
{
diff --git a/arch/arm/kernel/dma-ebsa285.c b/arch/arm/kernel/dma-ebsa285.c
index 74af95584..f1c42dac2 100644
--- a/arch/arm/kernel/dma-ebsa285.c
+++ b/arch/arm/kernel/dma-ebsa285.c
@@ -4,6 +4,9 @@
* Copyright (C) 1998 Phil Blundell
*
* DMA functions specific to EBSA-285/CATS architectures
+ *
+ * Changelog:
+ * 09/11/1998 RMK Split out ISA DMA functions to dma-isa.c
*/
#include <linux/config.h>
@@ -19,44 +22,19 @@
#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) */
+#include "dma-isa.h"
int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
{
- /* 21285 internal channels */
- if (channel == 0 || channel == 1)
+ switch (channel) {
+ case 0:
+ case 1: /* 21285 internal channels */
return 0;
- /* ISA channels */
-// if (machine_is_cats() && ((channel >= 2 && channel <= 5) ||
-// (channel >= 7 && channel <= 9)))
-// return 0;
+ case 2 ... 9:
+ if (machine_is_cats())
+ return isa_request_dma(channel - 2, dma, dev_name);
+ }
return -EINVAL;
}
@@ -75,14 +53,9 @@ int arch_get_dma_residue(dmach_t channel, dma_t *dma)
case 1:
break;
#ifdef CONFIG_CATS
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
+ case 2 ... 9:
+ if (machine_is_cats())
+ residue = isa_get_dma_residue(channel - 2);
#endif
}
return residue;
@@ -98,56 +71,9 @@ void arch_enable_dma(dmach_t channel, dma_t *dma)
*/
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);
+ case 2 ... 9:
+ if (machine_is_cats())
+ isa_enable_dma(channel - 2, dma);
#endif
}
}
@@ -162,18 +88,9 @@ void arch_disable_dma(dmach_t channel, dma_t *dma)
*/
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);
+ case 2 ... 9:
+ if (machine_is_cats())
+ isa_disable_dma(channel - 2, dma);
#endif
}
}
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
new file mode 100644
index 000000000..bdf7c6147
--- /dev/null
+++ b/arch/arm/kernel/dma-isa.c
@@ -0,0 +1,107 @@
+/*
+ * arch/arm/kernel/dma-isa.c: ISA DMA primitives
+ *
+ * Copyright (C) Russell King
+ *
+ * Taken from various sources, including:
+ * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+ * Written by Hennus Bergman, 1992.
+ * High DMA channel support & info by Hannu Savolainen and John Boyd, Nov. 1992.
+ * arch/arm/kernel/dma-ebsa285.c
+ * Copyright (C) 1998 Phil Blundell
+ */
+#include <linux/sched.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+
+#include "dma.h"
+#include "dma-isa.h"
+
+#define ISA_DMA_MASK 0
+#define ISA_DMA_MODE 1
+#define ISA_DMA_CLRFF 2
+#define ISA_DMA_PGHI 3
+#define ISA_DMA_PGLO 4
+#define ISA_DMA_ADDR 5
+#define ISA_DMA_COUNT 6
+
+static unsigned int isa_dma_port[8][7] = {
+ /* MASK MODE CLRFF PAGE_HI PAGE_LO ADDR COUNT */
+ { 0x0a, 0x0b, 0x0c, 0x487, 0x087, 0x00, 0x01 },
+ { 0x0a, 0x0b, 0x0c, 0x483, 0x083, 0x02, 0x03 },
+ { 0x0a, 0x0b, 0x0c, 0x481, 0x081, 0x04, 0x05 },
+ { 0x0a, 0x0b, 0x0c, 0x482, 0x082, 0x06, 0x07 },
+ { 0xd4, 0xd6, 0xd8, 0x000, 0x000, 0xc0, 0xc2 },
+ { 0xd4, 0xd6, 0xd8, 0x48b, 0x08b, 0xc4, 0xc6 },
+ { 0xd4, 0xd6, 0xd8, 0x489, 0x089, 0xc8, 0xca },
+ { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce }
+};
+
+int isa_request_dma(int channel, dma_t *dma, const char *dev_name)
+{
+ if (channel != 4)
+ return 0;
+
+ return -EINVAL;
+}
+
+void isa_free_dma(int channel, dma_t *dma)
+{
+ /* nothing to do */
+}
+
+int isa_get_dma_residue(int channel, dma_t *dma)
+{
+ unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT];
+ int count;
+
+ count = 1 + inb(io_port) + (inb(io_port) << 8);
+
+ return channel < 4 ? count : (count << 1);
+}
+
+void isa_enable_dma(int channel, dma_t *dma)
+{
+ unsigned long address, length;
+
+ if (dma->invalid) {
+ address = dma->buf.address;
+ length = dma->buf.length - 1;
+
+ outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]);
+ outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]);
+
+ if (channel >= 4) {
+ address >>= 1;
+ length = (length >> 1) & 0xfe; /* why &0xfe? */
+ }
+
+ outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]);
+
+ outb(address, isa_dma_port[channel][ISA_DMA_ADDR]);
+ outb(address >> 8, isa_dma_port[channel][ISA_DMA_ADDR]);
+
+ outb(length, isa_dma_port[channel][ISA_DMA_COUNT]);
+ outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]);
+
+ outb(dma->dma_mode | (channel & 3), isa_dma_port[channel][ISA_DMA_MODE]);
+
+ switch (dma->dma_mode) {
+ case DMA_MODE_READ:
+ dma_cache_inv(__bus_to_virt(dma->buf.address), dma->buf.length);
+ break;
+
+ case DMA_MODE_WRITE:
+ dma_cache_wback(__bus_to_virt(dma->buf.address), dma->buf.length);
+ break;
+ }
+ dma->invalid = 0;
+ }
+ outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]);
+}
+
+void isa_disable_dma(int channel, dma_t *dma)
+{
+ outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
+}
diff --git a/arch/arm/kernel/dma-isa.h b/arch/arm/kernel/dma-isa.h
new file mode 100644
index 000000000..3fcbdb3c7
--- /dev/null
+++ b/arch/arm/kernel/dma-isa.h
@@ -0,0 +1,25 @@
+/*
+ * Request an ISA DMA channel
+ */
+int isa_request_dma(int channel, dma_t *dma, const char *dev_name);
+
+/*
+ * Free an ISA DMA channel
+ */
+void isa_free_dma(int channel, dma_t *dma);
+
+/*
+ * Get ISA DMA channel residue
+ */
+int isa_get_dma_residue(int channel, dma_t *dma);
+
+/*
+ * Enable (and set up) an ISA DMA channel
+ */
+void isa_enable_dma(int channel, dma_t *dma);
+
+/*
+ * Disable an ISA DMA channel
+ */
+void isa_disable_dma(int channel, dma_t *dma);
+
diff --git a/arch/arm/kernel/dma-vnc.c b/arch/arm/kernel/dma-vnc.c
new file mode 100644
index 000000000..132fa627a
--- /dev/null
+++ b/arch/arm/kernel/dma-vnc.c
@@ -0,0 +1,51 @@
+/*
+ * arch/arm/kernel/dma-vnc.c
+ *
+ * Copyright (C) 1998 Russell King
+ */
+#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"
+#include "dma-isa.h"
+
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
+{
+ if (channel < 8)
+ return isa_request_dma(channel, dma, dev_name);
+ return -EINVAL;
+}
+
+void arch_free_dma(dmach_t channel, dma_t *dma)
+{
+ isa_free_dma(channel, dma);
+}
+
+int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+ return isa_get_dma_residue(channel, dma);
+}
+
+void arch_enable_dma(dmach_t channel, dma_t *dma)
+{
+ isa_enable_dma(channel, dma);
+}
+
+void arch_disable_dma(dmach_t channel, dma_t *dma)
+{
+ isa_disable_dma(channel, dma);
+}
+
+__initfunc(void arch_dma_init(dma_t *dma))
+{
+ /* Nothing to do */
+}
+
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 592cc979c..a164073ae 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -26,6 +26,26 @@
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/dma.h>
+#include <asm/spinlock.h>
+
+
+/* A note on resource allocation:
+ *
+ * All drivers needing DMA channels, should allocate and release them
+ * through the public routines `request_dma()' and `free_dma()'.
+ *
+ * In order to avoid problems, all processes should allocate resources in
+ * the same sequence and release them in the reverse order.
+ *
+ * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
+ * When releasing them, first release the DMA, then release the IRQ.
+ * If you don't, you may cause allocation requests to fail unnecessarily.
+ * This doesn't really matter now, but it will once we get real semaphores
+ * in the kernel.
+ */
+
+
+spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED;
#include "dma.h"
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index f7d204787..fe1c75f5c 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -3,7 +3,7 @@
*
* Find all installed expansion cards, and handle interrupts from them.
*
- * Copyright 1995,1996,1997 Russell King
+ * Copyright 1995-1998 Russell King
*
* Created from information from Acorns RiscOS3 PRMs
*
@@ -14,6 +14,7 @@
* 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
+ * 12-Sep-1998 RMK Added EASI support
*/
#define ECARD_C
@@ -79,7 +80,7 @@ static signed char irqno_to_expcard[16];
static unsigned int ecard_numcards, ecard_numirqcards;
static unsigned int have_expmask;
-static void ecard_def_irq_enable (ecard_t *ec, int irqnr)
+static void ecard_def_irq_enable(ecard_t *ec, int irqnr)
{
#ifdef HAS_EXPMASK
if (irqnr < 4 && have_expmask) {
@@ -89,7 +90,7 @@ static void ecard_def_irq_enable (ecard_t *ec, int irqnr)
#endif
}
-static void ecard_def_irq_disable (ecard_t *ec, int irqnr)
+static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
{
#ifdef HAS_EXPMASK
if (irqnr < 4 && have_expmask) {
@@ -99,14 +100,14 @@ static void ecard_def_irq_disable (ecard_t *ec, int irqnr)
#endif
}
-static void ecard_def_fiq_enable (ecard_t *ec, int fiqnr)
+static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
{
- panic ("ecard_def_fiq_enable called - impossible");
+ panic("ecard_def_fiq_enable called - impossible");
}
-static void ecard_def_fiq_disable (ecard_t *ec, int fiqnr)
+static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr)
{
- panic ("ecard_def_fiq_disable called - impossible");
+ panic("ecard_def_fiq_disable called - impossible");
}
static expansioncard_ops_t ecard_default_ops = {
@@ -122,7 +123,7 @@ static expansioncard_ops_t ecard_default_ops = {
*
* They are not meant to be called directly, but via enable/disable_irq.
*/
-void ecard_enableirq (unsigned int irqnr)
+void ecard_enableirq(unsigned int irqnr)
{
irqnr &= 7;
if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
@@ -132,14 +133,14 @@ void ecard_enableirq (unsigned int irqnr)
ec->ops = &ecard_default_ops;
if (ec->claimed && ec->ops->irqenable)
- ec->ops->irqenable (ec, irqnr);
+ ec->ops->irqenable(ec, irqnr);
else
- printk (KERN_ERR "ecard: rejecting request to "
+ printk(KERN_ERR "ecard: rejecting request to "
"enable IRQs for %d\n", irqnr);
}
}
-void ecard_disableirq (unsigned int irqnr)
+void ecard_disableirq(unsigned int irqnr)
{
irqnr &= 7;
if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
@@ -149,11 +150,11 @@ void ecard_disableirq (unsigned int irqnr)
ec->ops = &ecard_default_ops;
if (ec->ops && ec->ops->irqdisable)
- ec->ops->irqdisable (ec, irqnr);
+ ec->ops->irqdisable(ec, irqnr);
}
}
-void ecard_enablefiq (unsigned int fiqnr)
+void ecard_enablefiq(unsigned int fiqnr)
{
fiqnr &= 7;
if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
@@ -163,14 +164,14 @@ void ecard_enablefiq (unsigned int fiqnr)
ec->ops = &ecard_default_ops;
if (ec->claimed && ec->ops->fiqenable)
- ec->ops->fiqenable (ec, fiqnr);
+ ec->ops->fiqenable(ec, fiqnr);
else
- printk (KERN_ERR "ecard: rejecting request to "
+ printk(KERN_ERR "ecard: rejecting request to "
"enable FIQs for %d\n", fiqnr);
}
}
-void ecard_disablefiq (unsigned int fiqnr)
+void ecard_disablefiq(unsigned int fiqnr)
{
fiqnr &= 7;
if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
@@ -180,7 +181,7 @@ void ecard_disablefiq (unsigned int fiqnr)
ec->ops = &ecard_default_ops;
if (ec->ops->fiqdisable)
- ec->ops->fiqdisable (ec, fiqnr);
+ ec->ops->fiqdisable(ec, fiqnr);
}
}
@@ -198,8 +199,27 @@ static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
}
}
cli();
- if (called == 0)
- printk (KERN_WARNING "Wild interrupt from backplane?\n");
+ if (called == 0) {
+ static int last, lockup;
+
+ if (last == jiffies) {
+ lockup += 1;
+ if (lockup > 1000000) {
+ printk(KERN_ERR "\nInterrupt lockup detected - disabling expansion card IRQs\n");
+ disable_irq(intr_no);
+ printk("Expansion card IRQ state:\n");
+ for (i = 0; i < num_cards; i++)
+ printk(" %d: %sclaimed, irqaddr = %p, irqmask = %X, status=%X\n", expcard[i].irq - 32,
+ expcard[i].claimed ? "" : "not", expcard[i].irqaddr, expcard[i].irqmask, *expcard[i].irqaddr);
+ }
+ } else
+ lockup = 0;
+
+ if (!last || time_after(jiffies, last + 5*HZ)) {
+ last = jiffies;
+ printk(KERN_ERR "\nUnrecognised interrupt from backplane\n");
+ }
+ }
}
#ifdef HAS_EXPMASK
@@ -214,7 +234,7 @@ static unsigned char first_set[] =
0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00
};
-static void ecard_irq_expmask (int intr_no, void *dev_id, struct pt_regs *regs)
+static void ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs)
{
const unsigned int statusmask = 15;
unsigned int status;
@@ -239,22 +259,22 @@ again:
*/
oldexpmask = have_expmask;
EXPMASK_ENABLE = (have_expmask &= priority_masks[irqno]);
- sti ();
- do_ecard_IRQ (ec->irq, regs);
- cli ();
+ sti();
+ do_ecard_IRQ(ec->irq, regs);
+ cli();
EXPMASK_ENABLE = have_expmask = oldexpmask;
status = EXPMASK_STATUS & statusmask;
if (status)
goto again;
} else {
- printk (KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno);
+ printk(KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno);
EXPMASK_ENABLE = (have_expmask &= ~(1 << irqno));
}
} else
- printk (KERN_WARNING "Wild interrupt from backplane (masks)\n");
+ printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
}
-static int ecard_checkirqhw (void)
+static int ecard_checkirqhw(void)
{
int found;
@@ -267,7 +287,7 @@ static int ecard_checkirqhw (void)
}
#endif
-static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int useld)
+static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
{
extern int ecard_loader_read(int off, volatile unsigned int pa, loader_t loader);
unsigned char *a = (unsigned char *)addr;
@@ -287,7 +307,7 @@ static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int usel
* If we require a low address or address 0, then reset, and start again...
*/
if (!off || lowaddress > laddr) {
- outb (0, ec->podaddr);
+ outb(0, ec->podaddr);
lowaddress = 0;
}
while (lowaddress <= laddr) {
@@ -314,15 +334,136 @@ static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int usel
}
}
+static int ecard_prints(char *buffer, ecard_t *ec)
+{
+ char *start = buffer;
+
+ buffer += sprintf(buffer, "\n %d: ", ec->slot_no);
+
+ if (ec->cid.id == 0) {
+ struct in_chunk_dir incd;
+
+ buffer += sprintf(buffer, "[%04X:%04X] ",
+ ec->cid.manufacturer, ec->cid.product);
+
+ if (!ec->card_desc && ec->cid.is && ec->cid.cd &&
+ ecard_readchunk(&incd, ec, 0xf5, 0))
+ ec->card_desc = incd.d.string;
+
+ if (!ec->card_desc)
+ ec->card_desc = "*unknown*";
+
+ buffer += sprintf(buffer, "%s", ec->card_desc);
+ } else
+ buffer += sprintf(buffer, "Simple card %d", ec->cid.id);
+
+ return buffer - start;
+}
+
+static inline unsigned short ecard_getu16(unsigned char *v)
+{
+ return v[0] | v[1] << 8;
+}
+
+static inline signed long ecard_gets24(unsigned char *v)
+{
+ return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
+}
+
+/*
+ * Probe for an expansion card.
+ *
+ * If bit 1 of the first byte of the card is set, then the
+ * card does not exist.
+ */
+__initfunc(static int ecard_probe(int card, int freeslot, card_type_t type))
+{
+ ecard_t *ec = expcard + freeslot;
+ struct ex_ecid cid;
+ char buffer[200];
+ int i;
+
+ irqno_to_expcard[card] = -1;
+
+ ec->slot_no = card;
+ ec->irq = NO_IRQ;
+ ec->fiq = NO_IRQ;
+ ec->dma = NO_DMA;
+ ec->card_desc = NULL;
+ ec->ops = &ecard_default_ops;
+
+ if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
+ return 0;
+
+ cid.r_zero = 1;
+ ecard_readbytes(&cid, ec, 0, 16, 0);
+ if (cid.r_zero)
+ return 0;
+
+ irqno_to_expcard[card] = freeslot;
+
+ ec->type = type;
+ ec->cid.id = cid.r_id;
+ ec->cid.cd = cid.r_cd;
+ ec->cid.is = cid.r_is;
+ ec->cid.w = cid.r_w;
+ ec->cid.manufacturer = ecard_getu16(cid.r_manu);
+ ec->cid.product = ecard_getu16(cid.r_prod);
+ ec->cid.country = cid.r_country;
+ ec->cid.irqmask = cid.r_irqmask;
+ ec->cid.irqoff = ecard_gets24(cid.r_irqoff);
+ ec->cid.fiqmask = cid.r_fiqmask;
+ ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
+ ec->fiqaddr =
+ ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr);
+
+ if (ec->cid.cd && ec->cid.is) {
+ ec->irqmask = ec->cid.irqmask;
+ ec->irqaddr += ec->cid.irqoff;
+ ec->fiqmask = ec->cid.fiqmask;
+ ec->fiqaddr += ec->cid.fiqoff;
+ } else {
+ ec->irqmask = 1;
+ ec->fiqmask = 4;
+ }
+
+ for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
+ if (blacklist[i].manufacturer == ec->cid.manufacturer &&
+ blacklist[i].product == ec->cid.product) {
+ ec->loader = blacklist[i].loader;
+ ec->card_desc = blacklist[i].type;
+ break;
+ }
+
+ ecard_prints(buffer, ec);
+ printk("%s", buffer);
+
+ ec->irq = 32 + card;
+#ifdef IO_EC_MEMC8_BASE
+ if (card == 8)
+ ec->irq = 11;
+#endif
+#ifdef CONFIG_ARCH_RPC
+ /* On RiscPC, only first two slots have DMA capability */
+ if (card < 2)
+ ec->dma = 2 + card;
+#endif
+#if 0 /* We don't support FIQs on expansion cards at the moment */
+ ec->fiq = 96 + card;
+#endif
+
+ return 1;
+}
+
/*
* This is called to reset the loaders for each expansion card on reboot.
*
* This is required to make sure that the card is in the correct state
* that RiscOS expects it to be.
*/
-void ecard_reset (int card)
+void ecard_reset(int card)
{
- extern int ecard_loader_reset (volatile unsigned int pa, loader_t loader);
+ extern int ecard_loader_reset(volatile unsigned int pa, loader_t loader);
if (card >= ecard_numcards)
return;
@@ -330,11 +471,11 @@ void ecard_reset (int card)
if (card < 0) {
for (card = 0; card < ecard_numcards; card++)
if (expcard[card].loader)
- ecard_loader_reset (BUS_ADDR(expcard[card].podaddr),
+ ecard_loader_reset(BUS_ADDR(expcard[card].podaddr),
expcard[card].loader);
} else
if (expcard[card].loader)
- ecard_loader_reset (BUS_ADDR(expcard[card].podaddr),
+ ecard_loader_reset(BUS_ADDR(expcard[card].podaddr),
expcard[card].loader);
#ifdef HAS_EXPMASK
@@ -347,18 +488,19 @@ void ecard_reset (int card)
static unsigned int ecard_startcard;
-void ecard_startfind (void)
+void ecard_startfind(void)
{
ecard_startcard = 0;
}
-ecard_t *ecard_find (int cld, const card_ids *cids)
+ecard_t *ecard_find(int cid, const card_ids *cids)
{
int card;
+
if (!cids) {
for (card = ecard_startcard; card < ecard_numcards; card++)
if (!expcard[card].claimed &&
- ((expcard[card].cld.ecld ^ cld) & 0x78) == 0)
+ (expcard[card].cid.id ^ cid) == 0)
break;
} else {
for (card = ecard_startcard; card < ecard_numcards; card++) {
@@ -368,8 +510,8 @@ ecard_t *ecard_find (int cld, const card_ids *cids)
if (expcard[card].claimed)
continue;
- manufacturer = expcard[card].cld.manufacturer;
- product = expcard[card].cld.product;
+ manufacturer = expcard[card].cid.manufacturer;
+ product = expcard[card].cid.product;
for (i = 0; cids[i].manufacturer != 65535; i++)
if (manufacturer == cids[i].manufacturer &&
@@ -380,16 +522,21 @@ ecard_t *ecard_find (int cld, const card_ids *cids)
break;
}
}
+
ecard_startcard = card + 1;
+
return card < ecard_numcards ? &expcard[card] : NULL;
}
-int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
+int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
{
struct ex_chunk_dir excd;
int index = 16;
int useld = 0;
+ if (!ec->cid.is || !ec->cid.cd)
+ return 0;
+
while(1) {
ecard_readbytes(&excd, ec, index, 8, useld);
index += 8;
@@ -427,124 +574,49 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
}
}
cd->start_offset = c_start(&excd);
- memcpy (cd->d.string, excd.d.string, 256);
+ memcpy(cd->d.string, excd.d.string, 256);
return 1;
}
-unsigned int ecard_address (ecard_t *ec, card_type_t type, 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 ... 3:
switch (type) {
case ECARD_MEMC:
- return MEMCECIO_BASE + (ec->slot_no << 12);
+ return IO_EC_MEMC_BASE + (ec->slot_no << 12);
case ECARD_IOC:
- return IOCECIO_BASE + (speed << 17) + (ec->slot_no << 12);
+ return IO_EC_IOC_BASE + (speed << 17) + (ec->slot_no << 12);
- default:
- return 0;
+#ifdef IO_EC_EASI_BASE
+ case ECARD_EASI:
+ return IO_EC_EASI_BASE + (ec->slot_no << 22);
+#endif
}
+ break;
-#ifdef IOCEC4IO_BASE
case 4 ... 7:
- if (type != ECARD_IOC)
- return 0;
-
- return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
+ switch (type) {
+#ifdef IO_EC_IOC4_BASE
+ case ECARD_IOC:
+ return IO_EC_IOC4_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
#endif
-#ifdef MEMCEC8IO_BASE
- case 8:
- return MEMCEC8IO_BASE;
+#ifdef IO_EC_EASI_BASE
+ case ECARD_EASI:
+ return IO_EC_EASI_BASE + (ec->slot_no << 22);
#endif
- }
- return 0;
-}
-
-/*
- * Probe for an expansion card.
- *
- * If bit 1 of the first byte of the card is set,
- * then the card does not exist.
- */
-__initfunc(static int ecard_probe (int card, int freeslot))
-{
- ecard_t *ec = expcard + freeslot;
- struct ex_ecld excld;
- const char *card_desc = NULL;
- int i;
-
- irqno_to_expcard[card] = -1;
-
- ec->slot_no = card;
- if ((ec->podaddr = ecard_address (ec, ECARD_IOC, ECARD_SYNC)) == 0)
- return 0;
-
- excld.r_ecld = 2;
- ecard_readbytes (&excld, ec, 0, 16, 0);
- if (excld.r_ecld & 2)
- return 0;
-
- irqno_to_expcard[card] = freeslot;
-
- 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);
- ec->cld.country = e_country(&excld);
- ec->cld.fiqmask = e_fiqmask(&excld);
- ec->cld.irqmask = e_irqmask(&excld);
- ec->cld.fiqaddr = e_fiqaddr(&excld);
- ec->cld.irqaddr = e_irqaddr(&excld);
- ec->fiqaddr =
- ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr);
- ec->fiqmask = 4;
- ec->irqmask = 1;
- ec->ops = &ecard_default_ops;
-
- for (i = 0; i < sizeof (blacklist) / sizeof (*blacklist); i++)
- if (blacklist[i].manufacturer == ec->cld.manufacturer &&
- blacklist[i].product == ec->cld.product) {
- ec->loader = blacklist[i].loader;
- card_desc = blacklist[i].type;
+ default:
break;
}
+ break;
- ec->irq = 32 + card;
-#if 0
- /* We don't support FIQs on expansion cards at the moment */
- ec->fiq = 96 + card;
-#endif
-#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;
+#ifdef IO_EC_MEMC8_BASE
+ case 8:
+ return IO_EC_MEMC8_BASE;
#endif
-
- if ((ec->cld.ecld & 0x78) == 0) {
- struct in_chunk_dir incd;
- printk ("\n %d: [%04X:%04X] ", card, ec->cld.manufacturer, ec->cld.product);
- if (e_is (&excld)) {
- ec->fiqmask = e_fiqmask (&excld);
- ec->irqmask = e_irqmask (&excld);
- ec->fiqaddr += e_fiqaddr (&excld);
- ec->irqaddr += e_irqaddr (&excld);
- }
- if (!card_desc && e_cd (&excld) && ecard_readchunk (&incd, ec, 0xf5, 0))
- card_desc = incd.d.string;
- if (card_desc)
- printk ("%s", card_desc);
- else
- printk ("*Unknown*");
- } else
- printk("\n %d: Simple card %d\n", card, (ec->cld.ecld >> 3) & 15);
- return 1;
+ }
+ return 0;
}
static struct irqaction irqexpansioncard = {
@@ -565,11 +637,11 @@ __initfunc(void ecard_init(void))
{
int i, nc = 0;
- memset (expcard, 0, sizeof (expcard));
+ memset(expcard, 0, sizeof(expcard));
#ifdef HAS_EXPMASK
if (ecard_checkirqhw()) {
- printk (KERN_DEBUG "Expansion card interrupt management hardware found\n");
+ printk(KERN_DEBUG "Expansion card interrupt management hardware found\n");
irqexpansioncard.handler = ecard_irq_expmask;
irqexpansioncard.flags |= SA_IRQNOMASK;
have_expmask = -1;
@@ -581,8 +653,8 @@ __initfunc(void ecard_init(void))
/*
* First of all, probe all cards on the expansion card interrupt line
*/
- for (i = 0; i < 4; i++)
- if (ecard_probe (i, nc))
+ for (i = 0; i < 8; i++)
+ if (ecard_probe(i, nc, ECARD_IOC) || ecard_probe(i, nc, ECARD_EASI))
nc += 1;
else
have_expmask &= ~(1<<i);
@@ -591,8 +663,8 @@ __initfunc(void ecard_init(void))
/* Now probe other cards with different interrupt lines
*/
-#ifdef MEMCEC8IO_BASE
- if (ecard_probe (8, nc))
+#ifdef IO_EC_MEMC8_BASE
+ if (ecard_probe(8, nc, ECARD_IOC))
nc += 1;
#endif
@@ -600,7 +672,7 @@ __initfunc(void ecard_init(void))
ecard_numcards = nc;
if (nc && setup_arm_irq(IRQ_EXPANSIONCARD, &irqexpansioncard)) {
- printk ("Could not allocate interrupt for expansion cards\n");
+ printk("Could not allocate interrupt for expansion cards\n");
return;
}
@@ -609,5 +681,5 @@ __initfunc(void ecard_init(void))
EXPMASK_ENABLE = have_expmask;
#endif
- oldlatch_init ();
+ oldlatch_init();
}
diff --git a/arch/arm/kernel/entry-armo.S b/arch/arm/kernel/entry-armo.S
index 4c65fc892..3ca29cd2c 100644
--- a/arch/arm/kernel/entry-armo.S
+++ b/arch/arm/kernel/entry-armo.S
@@ -271,26 +271,18 @@ vector_undefinstr:
mov fp, #0
teqp pc, #I_BIT | MODE_SVC
.Lbug_undef:
- adr r1, .LC2
- ldmia r1, {r1, r4}
- ldr r1, [r1]
- get_current_task r2
- teq r1, r2
- stmnefd sp!, {ip, lr}
- blne SYMBOL_NAME(math_state_restore)
- ldmnefd sp!, {ip, lr}
+ ldr r4, .LC2
ldr pc, [r4] @ Call FP module USR entry point
.globl SYMBOL_NAME(fpundefinstr)
SYMBOL_NAME(fpundefinstr): @ Called by FP module on undefined instr
-SYMBOL_NAME(fpundefinstrsvc):
mov r0, lr
mov r1, sp
teqp pc, #MODE_SVC
bl SYMBOL_NAME(do_undefinstr)
b ret_from_exception @ Normal FP exit
-__und_svc: SVC_SAVE_ALL @ Non-user mode
+__und_svc: SVC_SAVE_ALL @ Non-user mode
mask_pc r0, lr
and r2, lr, #3
sub r0, r0, #4
@@ -298,8 +290,44 @@ __und_svc: SVC_SAVE_ALL @ Non-user mode
bl SYMBOL_NAME(do_undefinstr)
SVC_RESTORE_ALL
-.LC2: .word SYMBOL_NAME(last_task_used_math)
- .word SYMBOL_NAME(fp_enter)
+/* We get here if an undefined instruction happens and the floating
+ * point emulator is not present. If the offending instruction was
+ * a WFS, we just perform a normal return as if we had emulated the
+ * operation. This is a hack to allow some basic userland binaries
+ * to run so that the emulator module proper can be loaded. --philb
+ */
+fpe_not_present:
+ adr r10, wfs_mask_data
+ ldmia r10, {r4, r5, r6, r7, r8}
+ ldr r10, [sp, #S_PC] @ Load PC
+ sub r10, r10, #4
+ mask_pc r10, r10
+ ldrt r10, [r10] @ get instruction
+ and r5, r10, r5
+ teq r5, r4 @ Is it WFS?
+ beq ret_from_exception
+ and r5, r10, r8
+ teq r5, r6 @ Is it LDF/STF on sp or fp?
+ teqne r5, r7
+ bne fpundefinstr
+ tst r10, #0x00200000 @ Does it have WB
+ beq ret_from_exception
+ and r4, r10, #255 @ get offset
+ and r6, r10, #0x000f0000
+ tst r10, #0x00800000 @ +/-
+ rsbeq r4, r4, #0
+ ldr r5, [sp, r6, lsr #14] @ Load reg
+ add r5, r5, r4, lsl #2
+ str r5, [sp, r6, lsr #14] @ Save reg
+ b ret_from_exception
+
+wfs_mask_data: .word 0x0e200110 @ WFS
+ .word 0x0fff0fff
+ .word 0x0d0d0100 @ LDF [sp]/STF [sp]
+ .word 0x0d0b0100 @ LDF [fp]/STF [fp]
+ .word 0x0f0f0f00
+
+.LC2: .word SYMBOL_NAME(fp_enter)
/*=============================================================================
* Prefetch abort handler
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7ecf1d59a..bcc938b32 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -231,60 +231,68 @@ irq_prio_ebsa110:
.macro disable_fiq
.endm
+ .equ pci_iack_high, PCI_IACK & 0xff000000
+ .equ pci_iack_low, PCI_IACK & 0x00ff0000
+
.macro get_irqnr_and_base, irqnr, irqstat, base
mov r4, #IO_BASE_ARM_CSR
- ldr \irqstat, [r4, #IRQ_STATUS] @ just show us the unmasked ones
+ ldr \irqstat, [r4, #CSR_IRQ_STATUS] @ just show us the unmasked ones
@ run through hard priorities
@ timer
tst \irqstat, #IRQ_MASK_TIMER0
movne \irqnr, #IRQ_TIMER0
- bne 1f
+ bne 1001f
@ ether10
tst \irqstat, #IRQ_MASK_ETHER10
movne \irqnr, #IRQ_ETHER10
- bne 1f
+ bne 1001f
@ ether100
tst \irqstat, #IRQ_MASK_ETHER100
movne \irqnr, #IRQ_ETHER100
- bne 1f
+ bne 1001f
@ video compressor
- tst \irqstat, #IRQ_VIDCOMP_MASK
+ tst \irqstat, #IRQ_MASK_VIDCOMP
movne \irqnr, #IRQ_VIDCOMP
- bne 1f
+ bne 1001f
@ now try all the PIC sources
@ determine whether we have an irq
tst \irqstat, #IRQ_MASK_EXTERN_IRQ
- beq 3f
- mov r4, #(IO_BASE_PCI_IACK & 0xff000000)
- orr r4, r4, #(IO_BASE_PCI_IACK & 0x00ff0000)
+ beq 1002f
+ mov r4, #pci_iack_high
+ orr r4, r4, #pci_iack_low
ldrb \irqnr, [r4] @ get the IACK byte
- b 1f
+ b 1001f
-3: @ PCI errors
+1002: @ PCI errors
tst \irqstat, #IRQ_MASK_PCI_ERR
movne \irqnr, #IRQ_PCI_ERR
- bne 1f
+ bne 1001f
@ softint
- tst \irqstat, #IRQ_MASK_SOFT_IRQ
- movne \irqnr, #IRQ_SOFT_IRQ
- bne 1f
+ tst \irqstat, #IRQ_MASK_SOFTIRQ
+ movne \irqnr, #IRQ_SOFTIRQ
+ bne 1001f
@ debug uart
tst \irqstat, #IRQ_MASK_UART_DEBUG
- movne \irqnr, #IRQ_UART_DEBUG
- bne 1f
+ movne \irqnr, #IRQ_CONRX
+ bne 1001f
@ watchdog
- tst \irqstat, #IRQ_WATCHDOG_MASK
+ tst \irqstat, #IRQ_MASK_WATCHDOG
movne \irqnr, #IRQ_WATCHDOG
-1: @ If Z is set, then we will not enter an interrupt
+1001: @ If Z is set, then we will not enter an interrupt
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
#else
#error Unknown architecture
#endif
@@ -696,8 +704,8 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
adrsvc al, lr, fpundefinstr @ lr = undefined instr return
1: get_current_task r10
- mov lr, #1
- strb lr, [r10, #TSK_USED_MATH] @ set current->used_math
+ mov r8, #1
+ strb r8, [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
@@ -742,6 +750,43 @@ __und_invalid: sub sp, sp, #S_FRAME_SIZE
and r2, r6, #31 @ int mode
b SYMBOL_NAME(bad_mode) @ Does not ever return...
+/* We get here if an undefined instruction happens and the floating
+ * point emulator is not present. If the offending instruction was
+ * a WFS, we just perform a normal return as if we had emulated the
+ * operation. This is a hack to allow some basic userland binaries
+ * to run so that the emulator module proper can be loaded. --philb
+ */
+fpe_not_present:
+ adr r10, wfs_mask_data
+ ldmia r10, {r4, r5, r6, r7, r8}
+ ldr r10, [sp, #S_PC] @ Load PC
+ sub r10, r10, #4
+ mask_pc r10, r10
+ ldrt r10, [r10] @ get instruction
+ and r5, r10, r5
+ teq r5, r4 @ Is it WFS?
+ moveq pc, r9
+ and r5, r10, r8
+ teq r5, r6 @ Is it LDF/STF on sp or fp?
+ teqne r5, r7
+ movne pc, lr
+ tst r10, #0x00200000 @ Does it have WB
+ moveq pc, r9
+ and r4, r10, #255 @ get offset
+ and r6, r10, #0x000f0000
+ tst r10, #0x00800000 @ +/-
+ rsbeq r4, r4, #0
+ ldr r5, [sp, r6, lsr #14] @ Load reg
+ add r5, r5, r4, lsl #2
+ str r5, [sp, r6, lsr #14] @ Save reg
+ mov pc, r9
+
+wfs_mask_data: .word 0x0e200110 @ WFS
+ .word 0x0fff0fff
+ .word 0x0d0d0100 @ LDF [sp]/STF [sp]
+ .word 0x0d0b0100 @ LDF [fp]/STF [fp]
+ .word 0x0f0f0f00
+
#include "entry-common.S"
.data
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 6e0e9e38c..c77c0ea51 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -288,4 +288,4 @@ ENTRY(trap_init)
.data
ENTRY(fp_enter)
- .word fpundefinstr
+ .word fpe_not_present
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index c32fef3c8..a5da15c7f 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -106,14 +106,7 @@ void set_fiq_handler(void *start, unsigned int length)
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
+#ifdef CONFIG_CPU_32
processor.u.armv3v4._flush_cache_area(FIQ_VECTOR, FIQ_VECTOR + length, 1);
#endif
}
diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S
index 1dc4fde13..d6b2b79e6 100644
--- a/arch/arm/kernel/head-armo.S
+++ b/arch/arm/kernel/head-armo.S
@@ -58,6 +58,3 @@ Loldparams: mov r4, #0x02000000
cmp r4, r3
blt 1b
movs pc, lr
-
- .align 13
-ENTRY(this_must_match_init_task)
diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S
index 88e71adab..cd4be86cb 100644
--- a/arch/arm/kernel/head-armv.S
+++ b/arch/arm/kernel/head-armv.S
@@ -8,9 +8,23 @@
#include <linux/config.h>
#include <linux/linkage.h>
+#ifndef CONFIG_ARCH_VNC
#if (TEXTADDR & 0xffff) != 0x8000
#error TEXTADDR must start at 0xXXXX8000
#endif
+#else
+ .text
+ mov r0, r0
+ mov r0, r0
+ mov r0, r0
+ mov r0, r0
+ mov r0, r0
+ mov r0, r0
+ mov r0, r0
+ mov r0, r0
+ mov r0, #0
+ mov r1, #5
+#endif
#define DEBUG
@@ -97,6 +111,15 @@ __entry: teq r0, #0 @ check for illegal entry...
add r3, r3, #1 << 20
teq r0, r2
bne 1b
+#ifdef CONFIG_ARCH_VNC
+ add r0, r4, #0x3f00
+ add r0, r0, #0x00f8
+ mov r3, #0x7c000000
+ orr r3, r3, r8
+ str r3, [r0], #4
+ add r3, r3, #1 << 20
+ str r3, [r0], #4
+#endif
#endif
#ifdef CONFIG_ARCH_RPC
/* Map in screen at 0x02000000 & SCREEN2_BASE
@@ -339,7 +362,7 @@ __entry: teq r0, #0 @ check for illegal entry...
beq 1001b
.endm
-#elif defined(CONFIG_ARCH_EBSA285) || defined(CONFIG_ARCH_VNC)
+#elif defined(CONFIG_ARCH_EBSA285)
.macro addruart,rx
mov \rx, #0xfe000000
.endm
@@ -374,6 +397,30 @@ __entry: teq r0, #0 @ check for illegal entry...
.macro waituart,rd,rx
.endm
+
+#elif defined(CONFIG_ARCH_VNC)
+ .macro addruart,rx
+ mov \rx, #0xff000000
+ orr \rx, \rx, #0x00e00000
+ orr \rx, \rx, #0x000003f8
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx]
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldrb \rd, [\rx, #0x5]
+ and \rd, \rd, #0x60
+ teq \rd, #0x60
+ bne 1002b
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldrb \rd, [\rx, #0x6]
+ tst \rd, #0x10
+ beq 1001b
+ .endm
#else
#error Unknown architecture
#endif
diff --git a/arch/arm/kernel/hw-ebsa285.c b/arch/arm/kernel/hw-ebsa285.c
new file mode 100644
index 000000000..e3385696b
--- /dev/null
+++ b/arch/arm/kernel/hw-ebsa285.c
@@ -0,0 +1,161 @@
+/*
+ * arch/arm/kernel/hw-ebsa286.c
+ *
+ * EBSA285 hardware specific functions
+ *
+ * Copyright (C) 1998 Russell King, Phil Blundel
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/system.h>
+
+extern int setup_arm_irq(int, struct irqaction *);
+
+extern void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set);
+extern void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr);
+extern void pci_set_irq_line(struct pci_dev *dev, unsigned int irq);
+
+static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 };
+static int irqmap_cats[] __initdata = { 18, 8, 9, 11 };
+
+__initfunc(static int ebsa_irqval(struct pci_dev *dev))
+{
+ unsigned char pin;
+
+ pcibios_read_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_PIN,
+ &pin);
+
+ return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
+}
+
+__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;
+ }
+
+ printk("PCI: device %02x:%02x has unknown irq line %x\n",
+ dev->bus->number, dev->devfn, dev->irq);
+ return 0;
+}
+
+__initfunc(void pcibios_fixup_ebsa285(struct pci_dev *dev))
+{
+ char cmd;
+
+ /* 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;
+ }
+
+ /* Turn on bus mastering - boot loader doesn't
+ * - perhaps it should! - dag
+ */
+ pci_read_config_byte(dev, PCI_COMMAND, &cmd);
+ pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
+}
+
+static void irq_pci_err(int irq, void *dev_id, struct pt_regs *regs)
+{
+ const char *err = "unknown";
+ unsigned long cmd = *(unsigned long *)0xfe000004 & 0xffff;
+ unsigned long ctrl = *(unsigned long *)0xfe00013c & 0xffffde07;
+ static unsigned long next_warn[7];
+ int idx = 6;
+
+ switch(irq) {
+ case IRQ_PCIPARITY:
+ *(unsigned long *)0xfe000004 = cmd | 1 << 31;
+ idx = 0;
+ err = "parity";
+ break;
+
+ case IRQ_PCITARGETABORT:
+ *(unsigned long *)0xfe000004 = cmd | 1 << 28;
+ idx = 1;
+ err = "target abort";
+ break;
+
+ case IRQ_PCIMASTERABORT:
+ *(unsigned long *)0xfe000004 = cmd | 1 << 29;
+ idx = 2;
+ err = "master abort";
+ break;
+
+ case IRQ_PCIDATAPARITY:
+ *(unsigned long *)0xfe000004 = cmd | 1 << 24;
+ idx = 3;
+ err = "data parity";
+ break;
+
+ case IRQ_DISCARDTIMER:
+ *(unsigned long *)0xfe00013c = ctrl | 1 << 8;
+ idx = 4;
+ err = "discard timer";
+ break;
+
+ case IRQ_SERR:
+ *(unsigned long *)0xfe00013c = ctrl | 1 << 3;
+ idx = 5;
+ err = "system";
+ break;
+ }
+ if (time_after_eq(jiffies, next_warn[idx])) {
+ next_warn[idx] = jiffies + 3 * HZ / 100;
+ printk(KERN_ERR "PCI %s error detected\n", err);
+ }
+}
+
+static struct irqaction irq_pci_error = {
+ irq_pci_err, SA_INTERRUPT, 0, "PCI error", NULL, NULL
+};
+
+__initfunc(void pcibios_init_ebsa285(void))
+{
+ setup_arm_irq(IRQ_PCIPARITY, &irq_pci_error);
+ setup_arm_irq(IRQ_PCITARGETABORT, &irq_pci_error);
+ setup_arm_irq(IRQ_PCIMASTERABORT, &irq_pci_error);
+ setup_arm_irq(IRQ_PCIDATAPARITY, &irq_pci_error);
+ setup_arm_irq(IRQ_DISCARDTIMER, &irq_pci_error);
+ setup_arm_irq(IRQ_SERR, &irq_pci_error);
+
+ /*
+ * 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 the central function is enabled.
+ */
+ *(unsigned long *)0xfe000010 = 0;
+ *(unsigned long *)0xfe000018 = 0xe0000000;
+ *(unsigned long *)0xfe0000f8 = 0;
+ *(unsigned long *)0xfe0000fc = 0;
+ *(unsigned long *)0xfe000100 = 0x01fc0000;
+ *(unsigned long *)0xfe000104 = 0;
+ *(unsigned long *)0xfe000108 = 0x80000000;
+ *(unsigned long *)0xfe000004 = 0x17;
+}
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
index 689c43589..99577f1b7 100644
--- a/arch/arm/kernel/init_task.c
+++ b/arch/arm/kernel/init_task.c
@@ -6,7 +6,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-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;
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index b4950ace2..332e8940d 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -119,7 +119,9 @@ int get_irq_list(char *buf)
*p++ = '\n';
}
+#ifdef CONFIG_ACORN
p += get_fiq_list(p);
+#endif
return p - buf;
}
@@ -354,7 +356,7 @@ unsigned long probe_irq_on(void)
/*
* wait for spurious interrupts to mask themselves out again
*/
- for (delay = jiffies + HZ/10; delay > jiffies; )
+ for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
/* min 100ms delay */;
/*
@@ -424,6 +426,8 @@ __initfunc(void init_IRQ(void))
}
irq_init_irq();
+#ifdef CONFIG_ARCH_ACORN
init_FIQ();
+#endif
init_dma();
}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 767faff9e..cddc3fab3 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -57,13 +57,15 @@
#endif
#ifndef CONFIG_CMDLINE
-#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8"
+#define CONFIG_CMDLINE "root=/dev/nfs rw"
#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 = {
+ orig_video_lines: 30,
+ orig_video_cols: 80,
orig_video_mode: 0,
orig_video_ega_bx: 0,
orig_video_isVGA: 1,
@@ -210,6 +212,8 @@ setup_params(unsigned long *mem_end_p))
#ifdef CONFIG_ARCH_ACORN
*mem_end_p = GET_MEMORY_END(params);
+#elif defined(CONFIG_ARCH_EBSA285)
+ *mem_end_p = PAGE_OFFSET + params->u1.s.page_size * params->u1.s.nr_pages;
#else
*mem_end_p = PAGE_OFFSET + MEM_SIZE;
#endif
@@ -305,18 +309,18 @@ static char command_line[COMMAND_LINE_SIZE] = { 0, };
__initfunc(static void
setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end))
{
- char c = ' ', *to = command_line;
+ 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);
+ if (cmd_line[0] == ' ' &&
+ cmd_line[1] == 'm' &&
+ cmd_line[2] == 'e' &&
+ cmd_line[3] == 'm' &&
+ cmd_line[4] == '=') {
+ *mem_end = simple_strtoul(cmd_line+5, &cmd_line, 0);
switch(*cmd_line) {
case 'M':
case 'm':
@@ -336,7 +340,7 @@ setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end))
*to++ = c;
}
- *to = '\0';
+ *to = '\0';
}
__initfunc(void
@@ -381,33 +385,27 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem
conswitchp = &dummy_con;
#endif
#endif
-printascii("setup_arch done\n");
}
+static const struct {
+ char *machine_name;
+ char *bus_name;
+} machine_desc[] = {
+ { "DEC-EBSA110", "DEC" },
+ { "Acorn-RiscPC", "Acorn" },
+ { "Nexus-NexusPCI", "PCI" },
+ { "DEC-EBSA285", "PCI" },
+ { "Corel-Netwinder", "PCI/ISA" },
+ { "Chalice-CATS", "PCI" },
+ { "unknown-TBOX", "PCI" }
+};
+
#if defined(CONFIG_ARCH_ARC)
#define HARDWARE "Acorn-Archimedes"
#define IO_BUS "Acorn"
#elif defined(CONFIG_ARCH_A5K)
#define HARDWARE "Acorn-A5000"
#define IO_BUS "Acorn"
-#elif defined(CONFIG_ARCH_RPC)
-#define HARDWARE "Acorn-RiscPC"
-#define IO_BUS "Acorn"
-#elif defined(CONFIG_ARCH_EBSA110)
-#define HARDWARE "DEC-EBSA110"
-#define IO_BUS "DEC"
-#elif defined(CONFIG_ARCH_EBSA285)
-#define HARDWARE "DEC-EBSA285"
-#define IO_BUS "PCI"
-#elif defined(CONFIG_ARCH_NEXUSPCI)
-#define HARDWARE "Nexus-NexusPCI"
-#define IO_BUS "PCI"
-#elif defined(CONFIG_ARCH_VNC)
-#define HARDWARE "Corel-VNC"
-#define IO_BUS "PCI"
-#else
-#define HARDWARE "unknown"
-#define IO_BUS "unknown"
#endif
#if defined(CONFIG_CPU_ARM2)
@@ -439,8 +437,17 @@ int get_cpuinfo(char * buffer)
(int)processor_id & 15,
(loops_per_sec+2500) / 500000,
((loops_per_sec+2500) / 5000) % 100,
+#ifdef HARDWARE
HARDWARE,
+#else
+ machine_desc[machine_type].machine_name,
+#endif
OPTIMISATION,
- IO_BUS);
+#ifdef IO_BUS
+ IO_BUS
+#else
+ machine_desc[machine_type].bus_name
+#endif
+ );
return len;
}
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 56ada1dc7..5996398f8 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -77,7 +77,8 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg)
goto out;
if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
- if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
+ if (a.fd >= current->files->max_fds ||
+ !(file = current->files->fd[a.fd]))
goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 7445921d9..22c3639da 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -9,7 +9,7 @@
*
* 1994-07-02 Alan Modra
* fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
- * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
+ * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
* "A Kernel Model for Precision Timekeeping" by Dave Mills
*/
#include <linux/errno.h>
@@ -125,9 +125,11 @@ void do_settimeofday(struct timeval *tv)
}
xtime = *tv;
- time_state = TIME_BAD;
- time_maxerror = MAXPHASE;
- time_esterror = MAXPHASE;
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_state = TIME_ERROR; /* p. 24, (a) */
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
sti ();
}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6da813aa2..5d04f325b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -51,7 +51,7 @@ static int verify_stack_pointer (unsigned long stackptr, int size)
if (stackptr < 0x02048000 || stackptr + size > 0x03000000)
return -EFAULT;
#else
- if (stackptr < 0xc0000000 || stackptr + size > (unsigned long)high_memory)
+ if (stackptr < PAGE_OFFSET || stackptr + size > (unsigned long)high_memory)
return -EFAULT;
#endif
return 0;
@@ -175,7 +175,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret)
printk("(sp underflow)");
printk("\n");
- dump_mem(cstack, sstack + 4096);
+ dump_mem(cstack - 16, sstack + 4096);
frameptr = regs->ARM_fp;
if (frameptr) {
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index d47a092cb..684db2a47 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -26,6 +26,10 @@ ifeq ($(MACHINE),ebsa110)
L_OBJS += io-ebsa110.o
endif
+ifeq ($(MACHINE),vnc)
+ L_OBJS += io-ebsa285.o
+endif
+
ifeq ($(MACHINE),ebsa285)
L_OBJS += io-ebsa285.o
endif
diff --git a/arch/arm/lib/io-ebsa285.S b/arch/arm/lib/io-ebsa285.S
index 0ee1e37fc..a86983d43 100644
--- a/arch/arm/lib/io-ebsa285.S
+++ b/arch/arm/lib/io-ebsa285.S
@@ -104,24 +104,75 @@ ENTRY(outswb)
ENTRY(outsw)
add r0, r0, #0xff000000
add r0, r0, #0x00e00000
-1: teq r2, #0
- ldrneh r3, [r1], #2
- strneh r3, [r0]
- subne r2, r2, #1
- bne 1b
+1: subs r2, r2, #1
+ ldrgeh r3, [r1], #2
+ strgeh r3, [r0]
+ bgt 1b
mov pc, lr
ENTRY(inswb)
mov r2, r2, lsr #1
ENTRY(insw)
+ stmfd sp!, {r4, r5, lr}
add r0, r0, #0xff000000
add r0, r0, #0x00e00000
-1: teq r2, #0
+ @ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17
+ subs ip, r2, #8
+ blo too_little
+ @ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
+ ands lr, r1, #3 @ check alignment
+ beq 1f
+
+ ldrh r3, [r0]
+ strh r3, [r1], #2
+ sub ip, ip, #1
+ cmn ip, #8
+ blo too_little
+
+1: ldrh r2, [r0]
+ ldrh r3, [r0]
+ orr r2, r2, r3, lsl #16
+ ldrh r3, [r0]
+ ldrh r4, [r0]
+ orr r3, r3, r4, lsl #16
+ ldrh r4, [r0]
+ ldrh r5, [r0]
+ orr r4, r4, r5, lsl #16
+ ldrh r5, [r0]
+ ldrh lr, [r0]
+ orr r5, r5, lr, lsl #16
+ stmia r1!, {r2, r3, r4, r5}
+ subs ip, ip, #8
+ @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 + 0 + 1
+ bhs 1b
+ @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 8 - 7
+ cmn ip, #4
+ ldrhsh r2, [r0] @ ... ... ... ... - 4 - 3 - 2 - 1 ... ...
+ ldrhsh r3, [r0]
+ orrhs r2, r2, r3, lsl #16
+ ldrhsh r3, [r0]
+ ldrhsh r4, [r0]
+ orrhs r3, r3, r4, lsl #16
+ stmhsia r1!, {r2, r3}
+
+ tst ip, #2
+ ldrneh r2, [r0] @ ... ... - 6 - 5 ... ... - 2 - 1 ... ...
ldrneh r3, [r0]
- strneh r3, [r1], #2
- subne r2, r2, #1
- bne 1b
- mov pc, lr
+ orrne r2, r2, r3, lsl #16
+ strne r2, [r1], #4
+
+ tst ip, #1
+ ldrneh r2, [r0]
+ strneh r2, [r1], #2
+
+ ldmfd sp!, {r4, r5, pc}
+
+too_little: subs r2, r2, #1
+ ldrgeh r3, [r0]
+ strgeh r3, [r1], #2
+ bgt too_little
+
+ ldmfd sp!, {r4, r5, pc}
ENTRY(insb)
diff --git a/arch/arm/mm/fault-armo.c b/arch/arm/mm/fault-armo.c
index 4e244a297..6fe1f30ff 100644
--- a/arch/arm/mm/fault-armo.c
+++ b/arch/arm/mm/fault-armo.c
@@ -174,7 +174,7 @@ bad_area:
}
/* Are we prepared to handle this kernel fault? */
- if ((fixup = search_exception_table(regs->ARM_pc)) != 0) {
+ if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
tsk->comm, regs->ARM_pc, addr, fixup);
regs->ARM_pc = fixup;
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 98134abac..f090c5f2c 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -208,7 +208,7 @@ bad_area:
}
/* Are we prepared to handle this kernel fault? */
- if ((fixup = search_exception_table(regs->ARM_pc)) != 0) {
+ if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
tsk->comm, regs->ARM_pc, addr, fixup);
regs->ARM_pc = fixup;
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 613fefce1..b3b0ecf56 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -192,6 +192,15 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));
+
+#ifdef CONFIG_CPU_26
+ if (max_mapnr <= 128) {
+ extern int sysctl_overcommit_memory;
+ /* On a machine this small we won't get anywhere without
+ overcommit, so turn it on by default. */
+ sysctl_overcommit_memory = 1;
+ }
+#endif
}
void free_initmem (void)
diff --git a/arch/arm/mm/mm-ebsa285.c b/arch/arm/mm/mm-ebsa285.c
index 82bbce899..a5b17c6b9 100644
--- a/arch/arm/mm/mm-ebsa285.c
+++ b/arch/arm/mm/mm-ebsa285.c
@@ -5,7 +5,6 @@
*
* Copyright (C) 1998 Russell King, Dave Gilbert.
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/init.h>
@@ -14,46 +13,7 @@
#include <asm/page.h>
#include <asm/io.h>
#include <asm/proc/mm-init.h>
-
-/*
- * These two functions convert PCI bus addresses to virtual addresses
- * and back again.
- */
-unsigned long __virt_to_bus(unsigned long res)
-{
- if (res < PAGE_OFFSET || res >= 0xD0000000) {
- printk("__virt_to_bus: invalid address 0x%08lx\n", res);
-#ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
-#endif
- } else
- res = (res - PAGE_OFFSET) + 0x10000000;
-
- return res;
-}
-
-unsigned long __bus_to_virt(unsigned long res)
-{
- if (res < 0x10000000 || res >= 0x20000000) {
- printk("__bus_to_virt: invalid address 0x%08lx\n", res);
-#ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
-#endif
- } else
- res = (res - 0x10000000) + PAGE_OFFSET;
-
- return res;
-}
-
-/* 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
- */
+#include <asm/dec21285.h>
/*
* This is to allow us to fiddle with the EEPROM
@@ -65,15 +25,15 @@ unsigned long __bus_to_virt(unsigned long res)
* until we're happy with them...
*/
#define MAPPING \
- { 0xd8000000, 0x41000000, 0x00400000, DOMAIN_USER, 1, 1 }, /* EEPROM */ \
- { 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 }, /* VGA */ \
- { 0xe0000000, 0x80000000, 0x10000000, DOMAIN_USER, 1, 1 }, /* VGA */ \
- { 0xf8000000, 0x7b000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \
- { 0xf9000000, 0x7a000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \
- { 0xfc000000, 0x79000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \
- { 0xfd000000, 0x78000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* Outbound wflsh*/ \
- { 0xfe000000, 0x42000000, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
- { 0xffe00000, 0x7c000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
- { 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* X-Bus */
+ { 0xd8000000, DC21285_FLASH, 0x00400000, DOMAIN_USER, 1, 1 }, /* EEPROM */ \
+ { 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 }, /* VGA */ \
+ { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_USER, 1, 1 }, /* VGA */ \
+ { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \
+ { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \
+ { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \
+ { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \
+ { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
+ { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
+ { 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* X-Bus */
#include "mm-armv.c"
diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c
index 18ebe4a47..1c755faaf 100644
--- a/arch/arm/mm/mm-rpc.c
+++ b/arch/arm/mm/mm-rpc.c
@@ -91,7 +91,8 @@ init_dram_banks(struct param_struct *params))
#define MAPPING \
{ SCREEN2_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1 }, /* VRAM */ \
- { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1 } /* IO space */
+ { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1 }, /* IO space */ \
+ { EASI_BASE, EASI_START, EASI_SIZE, DOMAIN_IO, 0, 1 } /* EASI space */
/*
* Include common routine to set up page tables
*/
diff --git a/arch/arm/mm/mm-vnc.c b/arch/arm/mm/mm-vnc.c
index eed49eb29..94e037485 100644
--- a/arch/arm/mm/mm-vnc.c
+++ b/arch/arm/mm/mm-vnc.c
@@ -13,20 +13,19 @@
#include <asm/page.h>
#include <asm/io.h>
#include <asm/proc/mm-init.h>
+#include <asm/dec21285.h>
/* Table describing the MMU translation mapping
* mainly used to set up the I/O mappings.
*/
#define MAPPING \
- { 0xe0000000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO, 0, 1 }, /* PCI I/O */ \
- { 0xe0100000, DC21285_PCI_TYPE_0_CONFIG, 0x00f00000, DOMAIN_IO, 0, 1 }, /* Type 0 Config */ \
- { 0xe1000000, DC21285_ARMCSR_BASE, 0x00100000, DOMAIN_IO, 0, 1 }, /* ARM CSR */ \
- { 0xe1100000, DC21285_PCI_IACK, 0x00100000, DOMAIN_IO, 0, 1 }, /* PCI IACK */ \
- { 0xe1300000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \
- { 0xe1400000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \
- { 0xe1500000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \
- { 0xe1600000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \
- { 0xe1700000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh */ \
- { 0xe1800000, DC21285_FLASH, 0x00800000, DOMAIN_IO, 0, 1 } /* Flash */
+ { 0xd0000000, DC21285_FLASH, 0x00800000, DOMAIN_IO , 0, 1 }, /* Flash */ \
+ { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_IO , 0, 1 }, /* PCI Mem */ \
+ { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \
+ { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \
+ { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \
+ { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \
+ { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
+ { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
#include "mm-armv.c"
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index d077ab1d2..221797862 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -10,6 +10,11 @@
#include <asm/assembler.h>
#include "../lib/constants.h"
+/* This is the maximum size of an area which will be flushed. If the area
+ * is larger than this, then we flush the whole cache
+ */
+#define MAX_AREA_SIZE 32768
+
.data
Lclean_switch: .long 0
.text
@@ -52,7 +57,7 @@ _sa110_flush_cache_all_r2:
.align 5
_sa110_flush_cache_area:
sub r3, r1, r0
- cmp r3, #32768
+ cmp r3, #MAX_AREA_SIZE
bgt _sa110_flush_cache_all_r2
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c6, 1 @ flush D entry
@@ -79,16 +84,17 @@ _sa110_flush_cache_area:
.align 5
_sa110_cache_wback_area:
sub r3, r1, r0
- cmp r3, #32768
- movgt r2, #0
- bgt _sa110_flush_cache_all
+ cmp r3, #MAX_AREA_SIZE
+ mov r2, #0
+ bgt _sa110_flush_cache_all_r2
+ bic r0, r0, #31
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
add r0, r0, #32
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
add r0, r0, #32
cmp r0, r1
blt 1b
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mcr p15, 0, r2, c7, c10, 4 @ drain WB
mov pc, lr
/*