summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/apm.c2
-rw-r--r--arch/i386/lib/memcpy.c19
-rw-r--r--arch/mips/sgi/kernel/setup.c4
-rw-r--r--arch/mips64/sgi-ip22/ip22-setup.c4
-rw-r--r--arch/sh/boot/compressed/Makefile2
-rw-r--r--arch/sh/boot/compressed/head.S9
-rw-r--r--arch/sh/config.in23
-rw-r--r--arch/sh/defconfig5
-rw-r--r--arch/sh/kernel/Makefile35
-rw-r--r--arch/sh/kernel/cf-enabler.c24
-rw-r--r--arch/sh/kernel/entry.S15
-rw-r--r--arch/sh/kernel/io.c202
-rw-r--r--arch/sh/kernel/io_generic.c119
-rw-r--r--arch/sh/kernel/io_hd64461.c59
-rw-r--r--arch/sh/kernel/io_se.c62
-rw-r--r--arch/sh/kernel/io_unknown.c47
-rw-r--r--arch/sh/kernel/irq.c29
-rw-r--r--arch/sh/kernel/irq_imask.c5
-rw-r--r--arch/sh/kernel/irq_ipr.c75
-rw-r--r--arch/sh/kernel/led_se.c67
-rw-r--r--arch/sh/kernel/mach_hp600.c63
-rw-r--r--arch/sh/kernel/mach_se.c80
-rw-r--r--arch/sh/kernel/mach_unknown.c68
-rw-r--r--arch/sh/kernel/pci-sh.c19
-rw-r--r--arch/sh/kernel/semaphore.c2
-rw-r--r--arch/sh/kernel/setup.c134
-rw-r--r--arch/sh/kernel/setup_cqreek.c224
-rw-r--r--arch/sh/kernel/setup_hd64461.c19
-rw-r--r--arch/sh/kernel/setup_se.c51
-rw-r--r--arch/sh/kernel/sh_bios.c2
-rw-r--r--arch/sh/kernel/signal.c7
-rw-r--r--arch/sh/kernel/time.c16
-rw-r--r--arch/sh/lib/Makefile2
-rw-r--r--arch/sh/lib/checksum.S54
-rw-r--r--arch/sh/lib/strcasecmp.c26
-rw-r--r--arch/sh/mm/Makefile2
-rw-r--r--arch/sh/mm/cache.c116
-rw-r--r--arch/sh/mm/fault.c14
-rw-r--r--arch/sh/vmlinux.lds.S3
-rw-r--r--arch/sparc/config.in29
-rw-r--r--arch/sparc/defconfig11
-rw-r--r--arch/sparc/mm/generic.c2
-rw-r--r--arch/sparc/mm/init.c2
-rw-r--r--arch/sparc/mm/io-unit.c2
-rw-r--r--arch/sparc/mm/iommu.c2
-rw-r--r--arch/sparc/mm/srmmu.c2
-rw-r--r--arch/sparc/mm/sun4c.c2
-rw-r--r--arch/sparc64/kernel/Makefile4
-rw-r--r--arch/sparc64/kernel/rtrap.S2
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c57
-rw-r--r--arch/sparc64/mm/fault.c2
-rw-r--r--arch/sparc64/mm/generic.c2
-rw-r--r--arch/sparc64/mm/init.c2
53 files changed, 1529 insertions, 301 deletions
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 039ba695c..9a4084292 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -410,7 +410,7 @@ static const lookup_t error_table[] = {
#ifndef CONFIG_APM_ALLOW_INTS
# define APM_DO_CLI __cli()
#else
-# define APM_DO_CLI
+# define APM_DO_CLI __sti()
#endif
#ifdef APM_ZERO_SEGS
# define APM_DECL_SEGS \
diff --git a/arch/i386/lib/memcpy.c b/arch/i386/lib/memcpy.c
new file mode 100644
index 000000000..4cb37b6e5
--- /dev/null
+++ b/arch/i386/lib/memcpy.c
@@ -0,0 +1,19 @@
+#include <linux/config.h>
+#include <linux/string.h>
+
+#undef memcpy
+#undef memset
+
+void * memcpy(void * to, const void * from, size_t n)
+{
+#ifdef CONFIG_X86_USE_3DNOW
+ return __memcpy3d(to, from, n);
+#else
+ return __memcpy(to, from, n);
+#endif
+}
+
+void * memset(void * s, int c, size_t count)
+{
+ return __memset(s, c, count);
+}
diff --git a/arch/mips/sgi/kernel/setup.c b/arch/mips/sgi/kernel/setup.c
index 051364fe3..29891e47a 100644
--- a/arch/mips/sgi/kernel/setup.c
+++ b/arch/mips/sgi/kernel/setup.c
@@ -129,9 +129,9 @@ static void __init sgi_irq_setup(void)
int __init page_is_ram(unsigned long pagenr)
{
- if (pagenr < MAP_NR(PAGE_OFFSET + 0x2000UL))
+ if ((pagenr<<PAGE_SHIFT) < 0x2000UL)
return 1;
- if (pagenr > MAP_NR(PAGE_OFFSET + 0x08002000))
+ if ((pagenr<<PAGE_SHIFT) > 0x08002000)
return 1;
return 0;
}
diff --git a/arch/mips64/sgi-ip22/ip22-setup.c b/arch/mips64/sgi-ip22/ip22-setup.c
index 937d291d1..a0f429429 100644
--- a/arch/mips64/sgi-ip22/ip22-setup.c
+++ b/arch/mips64/sgi-ip22/ip22-setup.c
@@ -114,9 +114,9 @@ struct kbd_ops sgi_kbd_ops = {
int __init page_is_ram(unsigned long pagenr)
{
- if (pagenr < MAP_NR(PAGE_OFFSET + 0x2000UL))
+ if ((pagenr<<PAGE_SHIFT) < 0x2000UL)
return 1;
- if (pagenr > MAP_NR(PAGE_OFFSET + 0x08002000))
+ if ((pagenr<<PAGE_SHIFT) > 0x08002000)
return 1;
return 0;
}
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index d62db2722..bd419991b 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -18,7 +18,7 @@ ZLDFLAGS = -e startup -T $(TOPDIR)/arch/sh/vmlinux.lds
#
# ZIMAGE_OFFSET is the load offset of the compression loader
#
-ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000+0x400])
+ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000])
ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
diff --git a/arch/sh/boot/compressed/head.S b/arch/sh/boot/compressed/head.S
index d270d1b47..86a3acf82 100644
--- a/arch/sh/boot/compressed/head.S
+++ b/arch/sh/boot/compressed/head.S
@@ -10,6 +10,9 @@
.global startup
startup:
+ /* Load initial status register */
+ mov.l init_sr, r1
+ ldc r1, sr
/* First clear BSS */
mov.l end_addr, r1
@@ -20,10 +23,6 @@ l1:
cmp/eq r1,r2
bf l1
- /* Load initial status register */
- mov.l init_sr, r1
- ldc r1, sr
-
/* Set the initial pointer. */
mov.l init_stack_addr, r0
mov.l @r0, r15
@@ -44,7 +43,7 @@ bss_start_addr:
end_addr:
.long _end
init_sr:
- .long 0x50000000 /* Privileged mode, Bank=0, Block=1, I3-I0=0 */
+ .long 0x40000000 /* Privileged mode, Bank=0, Block=0, I3-I0=0 */
init_stack_addr:
.long stack_start
decompress_kernel_addr:
diff --git a/arch/sh/config.in b/arch/sh/config.in
index 2d0790bde..fa36d92f7 100644
--- a/arch/sh/config.in
+++ b/arch/sh/config.in
@@ -28,12 +28,19 @@ choice 'SuperH system type' \
"Generic CONFIG_SH_GENERIC \
SolutionEngine CONFIG_SH_SOLUTION_ENGINE \
Overdrive CONFIG_SH_OVERDRIVE \
- HP600 CONFIG_SH_HP600" Generic
+ HP600 CONFIG_SH_HP600 \
+ CqREEK CONFIG_SH_CQREEK \
+ BareCPU CONFIG_SH_UNKNOWN" Generic
choice 'Processor type' \
- "SH7708 CONFIG_CPU_SUBTYPE_SH7708 \
+ "SH7707 CONFIG_CPU_SUBTYPE_SH7707 \
+ SH7708 CONFIG_CPU_SUBTYPE_SH7708 \
SH7709 CONFIG_CPU_SUBTYPE_SH7709 \
SH7750 CONFIG_CPU_SUBTYPE_SH7750" SH7708
+if [ "$CONFIG_CPU_SUBTYPE_SH7707" = "y" ]; then
+ define_bool CONFIG_CPU_SH3 y
+ define_bool CONFIG_CPU_SH4 n
+fi
if [ "$CONFIG_CPU_SUBTYPE_SH7708" = "y" ]; then
define_bool CONFIG_CPU_SH3 y
define_bool CONFIG_CPU_SH4 n
@@ -52,7 +59,6 @@ if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o "$CONFIG_SH_HP600" = "y" -o \
define_hex CONFIG_MEMORY_START 0c000000
else
hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
- hex 'I/O port offset address' CONFIG_IOPORT_START ba000000
fi
endmenu
@@ -178,6 +184,12 @@ bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
fi
+
+if [ "$CONFIG_SH_GENERIC" = "y" -o \
+ "$CONFIG_SH_OVERDRIVE" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
+ bool 'Heartbeat LED' CONFIG_HEARTBEAT
+fi
+
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
if [ "$CONFIG_PRINTER" != "n" ]; then
@@ -221,7 +233,8 @@ comment 'Kernel hacking'
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
bool 'Use LinuxSH standard BIOS' CONFIG_SH_STANDARD_BIOS
if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then
- bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
- bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
+ hex ' GDB Stub VBR' CONFIG_GDB_STUB_VBR a0000000
+ bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+ bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
fi
endmenu
diff --git a/arch/sh/defconfig b/arch/sh/defconfig
index e1d9d1725..5ffc0e0ab 100644
--- a/arch/sh/defconfig
+++ b/arch/sh/defconfig
@@ -21,6 +21,8 @@ CONFIG_SH_GENERIC=y
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_OVERDRIVE is not set
# CONFIG_SH_HP600 is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
CONFIG_CPU_SUBTYPE_SH7708=y
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
@@ -28,7 +30,6 @@ CONFIG_CPU_SH3=y
# CONFIG_CPU_SH4 is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_MEMORY_START=0c000000
-CONFIG_IOPORT_START=ba000000
#
# General setup
@@ -139,6 +140,7 @@ CONFIG_SERIAL_CONSOLE=y
# Unix 98 PTY support
#
# CONFIG_UNIX98_PTYS is not set
+# CONFIG_HEARTBEAT is not set
#
# File systems
@@ -200,4 +202,5 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_SH_STANDARD_BIOS=y
CONFIG_DEBUG_KERNEL_WITH_GDB_STUB=y
+CONFIG_GDB_STUB_VBR=a0000000
CONFIG_SH_EARLY_PRINTK=y
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 7b3852295..c9de70daf 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -11,8 +11,8 @@
O_TARGET := kernel.o
O_OBJS := process.o signal.o entry.o traps.o irq.o irq_ipr.o \
- ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \
- irq_imask.o
+ ptrace.o setup.o time.o sys_sh.o semaphore.o \
+ irq_imask.o io.o
OX_OBJS := sh_ksyms.o
MX_OBJS :=
@@ -21,26 +21,45 @@ O_OBJS += cf-enabler.o
endif
ifdef CONFIG_SH_GENERIC
+
+O_OBJS += mach_se.o setup_se.o setup_cqreek.o io_se.o led_se.o \
+ mach_hp600.o io_hd64461.o \
+ mach_unknown.o io_unknown.o \
+ io_generic.o
+
+else
+
+ifdef CONFIG_SH_HP600
+O_OBJS += mach_hp600.o io_hd64461.o io_generic.o
+endif
+
+ifdef CONFIG_SH_OVERDRIVE
O_OBJS += io_generic.o
endif
ifdef CONFIG_SH_SOLUTION_ENGINE
-O_OBJS += setup_se.o io_se.o
+O_OBJS += mach_se.o setup_se.o io_se.o io_generic.o led_se.o
endif
-ifdef CONFIG_SH_OVERDRIVE
-O_OBJS += setup_od.o io_generic.o
+ifdef CONFIG_SH_CQREEK
+O_OBJS += setup_cqreek.o
+endif
+
+ifdef CONFIG_SH_UNKNOWN
+O_OBJS += mach_unknown.o io_unknown.o io_generic.o
endif
-ifdef CONFIG_SH_HP600
-O_OBJS += io_hd64461.o
endif
ifdef CONFIG_CPU_SH4
O_OBJS += fpu.o
endif
-ifdef CONFIG_HD64461
+ifdef CONFIG_PCI
+O_OBJS += pci-sh.o
+endif
+
+ifneq ($(CONFIG_SH_GENERIC)$(CONFIG_HD64461),)
O_OBJS += setup_hd64461.o
endif
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
index 3727c7264..c446a1151 100644
--- a/arch/sh/kernel/cf-enabler.c
+++ b/arch/sh/kernel/cf-enabler.c
@@ -14,15 +14,18 @@
#include <asm/io.h>
#include <asm/irq.h>
-#ifdef CONFIG_SH_SOLUTION_ENGINE
#include <asm/hitachi_se.h>
+
+
/*
+ * SolutionEngine
+ *
* 0xB8400000 : Common Memory
* 0xB8500000 : Attribute
* 0xB8600000 : I/O
*/
-int __init cf_init(void)
+static int __init cf_init_se(void)
{
if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0)
return 0; /* Not detected */
@@ -68,11 +71,15 @@ int __init cf_init(void)
ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
return 0;
}
-#else /* then generic system type */
+
#define CF_CIS_BASE 0xb8000000
/*
* You can connect Compact Flash directly to the bus of SuperH.
* This is the enabler for that.
+ *
+ * SIM: How generic is this really? It looks pretty board, or at
+ * least SH sub-type, specific to me.
+ * I know it doesn't work on the Overdrive!
*/
/*
@@ -81,7 +88,7 @@ int __init cf_init(void)
* 0xBA000000 : I/O
*/
-int __init cf_init(void)
+static int __init cf_init_default(void)
{
/* Enable the card, and set the level interrupt */
ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
@@ -89,6 +96,13 @@ int __init cf_init(void)
disable_irq(14);
return 0;
}
-#endif
+
+int __init cf_init(void)
+{
+ if (MACH_SE) {
+ return cf_init_se();
+ }
+ return cf_init_default();
+}
__initcall (cf_init);
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
index 450d49824..4e57175e7 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/entry.S
@@ -62,7 +62,7 @@ ENOSYS = 38
#if defined(__sh3__)
TRA = 0xffffffd0
EXPEVT = 0xffffffd4
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
INTEVT = 0xa4000000 ! INTEVTE2(0xa4000000)
#else
INTEVT = 0xffffffd8
@@ -182,7 +182,7 @@ tlb_protection_violation_store:
1: .long SYMBOL_NAME(do_page_fault)
2: .long MMU_TEA
-#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
.align 2
/* Unwind the stack and jmp to the debug entry */
debug_kernel:
@@ -219,12 +219,12 @@ debug_kernel:
ldc $k1, $ssr
.align 2
1: .long 0x300000f0
-2: .long 0xa0000100
+2: .long CONFIG_GDB_STUB_VBR + 0x100
#endif
.align 2
debug_trap:
-#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
mov #SR, $r0
mov.l @($r0,$r15), $r0 ! get status register
shll $r0
@@ -829,7 +829,7 @@ ENTRY(interrupt_table)
.long SYMBOL_NAME(do_IRQ) ! rovi
.long SYMBOL_NAME(do_IRQ)
.long SYMBOL_NAME(do_IRQ)
-#if defined(CONFIG_CPU_SUBTYPE_SH7709)
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
.long SYMBOL_NAME(do_IRQ) ! 32 IRQ irq0
.long SYMBOL_NAME(do_IRQ) ! 33 irq1
.long SYMBOL_NAME(do_IRQ) ! 34 irq2
@@ -859,6 +859,11 @@ ENTRY(interrupt_table)
.long SYMBOL_NAME(do_IRQ) ! 58 bri2
.long SYMBOL_NAME(do_IRQ) ! 59 txi2
.long SYMBOL_NAME(do_IRQ) ! 60 ADC adi
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+ .long SYMBOL_NAME(do_IRQ) ! 61 LCDC lcdi
+ .long SYMBOL_NAME(do_IRQ) ! 62 PCC pcc0i
+ .long SYMBOL_NAME(do_IRQ) ! 63 pcc1i
+#endif
#elif defined(__SH4__)
.long SYMBOL_NAME(do_IRQ) ! Hitachi UDI
.long SYMBOL_NAME(do_IRQ) ! GPIO
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
new file mode 100644
index 000000000..27f250f9f
--- /dev/null
+++ b/arch/sh/kernel/io.c
@@ -0,0 +1,202 @@
+/*
+ * linux/arch/sh/kernel/io_generic.c
+ *
+ * Copyright (C) 2000 Stuart Menefy
+ *
+ * Provide real functions which expand to whatever the header file defined.
+ * Also definitions of machine independant IO functions.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+
+unsigned int _inb(unsigned long port)
+{
+ return __inb(port);
+}
+
+unsigned int _inw(unsigned long port)
+{
+ return __inw(port);
+}
+
+unsigned int _inl(unsigned long port)
+{
+ return __inl(port);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+ __outb(b, port);
+}
+
+void _outw(unsigned short b, unsigned long port)
+{
+ __outw(b, port);
+}
+
+void _outl(unsigned int b, unsigned long port)
+{
+ __outl(b, port);
+}
+
+unsigned int _inb_p(unsigned long port)
+{
+ return __inb_p(port);
+}
+
+unsigned int _inw_p(unsigned long port)
+{
+ return __inw_p(port);
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+ __outb_p(b, port);
+}
+
+void _outw_p(unsigned short b, unsigned long port)
+{
+ __outw_p(b, port);
+}
+
+void _insb(unsigned long port, void *buffer, unsigned long count)
+{
+ return __insb(port, buffer, count);
+}
+
+void _insw(unsigned long port, void *buffer, unsigned long count)
+{
+ __insw(port, buffer, count);
+}
+
+void _insl(unsigned long port, void *buffer, unsigned long count)
+{
+ __insl(port, buffer, count);
+}
+
+void _outsb(unsigned long port, const void *buffer, unsigned long count)
+{
+ __outsb(port, buffer, count);
+}
+
+void _outsw(unsigned long port, const void *buffer, unsigned long count)
+{
+ __outsw(port, buffer, count);
+}
+
+void _outsl(unsigned long port, const void *buffer, unsigned long count)
+{
+ __outsl(port, buffer, count);
+
+}
+
+unsigned long ___raw_readb(unsigned long addr)
+{
+ return __readb(addr);
+}
+
+unsigned long ___raw_readw(unsigned long addr)
+{
+ return __readw(addr);
+}
+
+unsigned long ___raw_readl(unsigned long addr)
+{
+ return __readl(addr);
+}
+
+unsigned long _readb(unsigned long addr)
+{
+ unsigned long r = __readb(addr);
+ mb();
+ return r;
+}
+
+unsigned long _readw(unsigned long addr)
+{
+ unsigned long r = __readw(addr);
+ mb();
+ return r;
+}
+
+unsigned long _readl(unsigned long addr)
+{
+ unsigned long r = __readl(addr);
+ mb();
+ return r;
+}
+
+void ___raw_writeb(unsigned char b, unsigned long addr)
+{
+ __writeb(b, addr);
+}
+
+void ___raw_writew(unsigned short b, unsigned long addr)
+{
+ __writew(b, addr);
+}
+
+void ___raw_writel(unsigned int b, unsigned long addr)
+{
+ __writel(b, addr);
+}
+
+void _writeb(unsigned char b, unsigned long addr)
+{
+ __writeb(b, addr);
+ mb();
+}
+
+void _writew(unsigned short b, unsigned long addr)
+{
+ __writew(b, addr);
+ mb();
+}
+
+void _writel(unsigned int b, unsigned long addr)
+{
+ __writel(b, addr);
+ mb();
+}
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void memcpy_fromio(void * to, unsigned long from, unsigned long count)
+{
+ while (count) {
+ count--;
+ *(char *) to = readb(from);
+ ((char *) to)++;
+ from++;
+ }
+}
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void memcpy_toio(unsigned long to, const void * from, unsigned long count)
+{
+ while (count) {
+ count--;
+ writeb(*(char *) from, to);
+ ((char *) from)++;
+ to++;
+ }
+}
+
+/*
+ * "memset" on IO memory space.
+ * This needs to be optimized.
+ */
+void memset_io(unsigned long dst, int c, unsigned long count)
+{
+ while (count) {
+ count--;
+ writeb(c, dst);
+ dst++;
+ }
+}
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c
index 1faa01ce3..9e5793450 100644
--- a/arch/sh/kernel/io_generic.c
+++ b/arch/sh/kernel/io_generic.c
@@ -4,7 +4,8 @@
*
* Copyright (C) 2000 Niibe Yutaka
*
- * Generic I/O routine.
+ * Generic I/O routine. These can be used where a machine specific version
+ * is not required.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -14,6 +15,7 @@
#include <linux/config.h>
#include <asm/io.h>
+#include <asm/machvec.h>
#if defined(__sh3__)
/* I'm not sure SH7709 has this kind of bug */
@@ -21,19 +23,31 @@
#define DUMMY_READ_AREA6 0xba000000
#endif
-#define PORT2ADDR(x) (CONFIG_IOPORT_START+(x))
+#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
+
+unsigned long generic_io_base;
static inline void delay(void)
{
ctrl_inw(0xa0000000);
}
-unsigned long inb(unsigned int port)
+unsigned long generic_inb(unsigned int port)
{
return *(volatile unsigned char*)PORT2ADDR(port);
}
-unsigned long inb_p(unsigned int port)
+unsigned long generic_inw(unsigned int port)
+{
+ return *(volatile unsigned short*)PORT2ADDR(port);
+}
+
+unsigned long generic_inl(unsigned int port)
+{
+ return *(volatile unsigned long*)PORT2ADDR(port);
+}
+
+unsigned long generic_inb_p(unsigned int port)
{
unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
@@ -41,23 +55,29 @@ unsigned long inb_p(unsigned int port)
return v;
}
-unsigned long inw(unsigned int port)
+unsigned long generic_inw_p(unsigned int port)
{
- return *(volatile unsigned short*)PORT2ADDR(port);
+ unsigned long v = *(volatile unsigned short*)PORT2ADDR(port);
+
+ delay();
+ return v;
}
-unsigned long inl(unsigned int port)
+unsigned long generic_inl_p(unsigned int port)
{
- return *(volatile unsigned long*)PORT2ADDR(port);
+ unsigned long v = *(volatile unsigned long*)PORT2ADDR(port);
+
+ delay();
+ return v;
}
-void insb(unsigned int port, void *buffer, unsigned long count)
+void generic_insb(unsigned int port, void *buffer, unsigned long count)
{
unsigned char *buf=buffer;
while(count--) *buf++=inb(port);
}
-void insw(unsigned int port, void *buffer, unsigned long count)
+void generic_insw(unsigned int port, void *buffer, unsigned long count)
{
unsigned short *buf=buffer;
while(count--) *buf++=inw(port);
@@ -66,7 +86,7 @@ void insw(unsigned int port, void *buffer, unsigned long count)
#endif
}
-void insl(unsigned int port, void *buffer, unsigned long count)
+void generic_insl(unsigned int port, void *buffer, unsigned long count)
{
unsigned long *buf=buffer;
while(count--) *buf++=inl(port);
@@ -75,34 +95,46 @@ void insl(unsigned int port, void *buffer, unsigned long count)
#endif
}
-void outb(unsigned long b, unsigned int port)
+void generic_outb(unsigned long b, unsigned int port)
{
*(volatile unsigned char*)PORT2ADDR(port) = b;
}
-void outb_p(unsigned long b, unsigned int port)
+void generic_outw(unsigned long b, unsigned int port)
+{
+ *(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
+void generic_outl(unsigned long b, unsigned int port)
+{
+ *(volatile unsigned long*)PORT2ADDR(port) = b;
+}
+
+void generic_outb_p(unsigned long b, unsigned int port)
{
*(volatile unsigned char*)PORT2ADDR(port) = b;
delay();
}
-void outw(unsigned long b, unsigned int port)
+void generic_outw_p(unsigned long b, unsigned int port)
{
*(volatile unsigned short*)PORT2ADDR(port) = b;
+ delay();
}
-void outl(unsigned long b, unsigned int port)
+void generic_outl_p(unsigned long b, unsigned int port)
{
- *(volatile unsigned long*)PORT2ADDR(port) = b;
+ *(volatile unsigned long*)PORT2ADDR(port) = b;
+ delay();
}
-void outsb(unsigned int port, const void *buffer, unsigned long count)
+void generic_outsb(unsigned int port, const void *buffer, unsigned long count)
{
const unsigned char *buf=buffer;
while(count--) outb(*buf++, port);
}
-void outsw(unsigned int port, const void *buffer, unsigned long count)
+void generic_outsw(unsigned int port, const void *buffer, unsigned long count)
{
const unsigned short *buf=buffer;
while(count--) outw(*buf++, port);
@@ -111,7 +143,7 @@ void outsw(unsigned int port, const void *buffer, unsigned long count)
#endif
}
-void outsl(unsigned int port, const void *buffer, unsigned long count)
+void generic_outsl(unsigned int port, const void *buffer, unsigned long count)
{
const unsigned long *buf=buffer;
while(count--) outl(*buf++, port);
@@ -119,3 +151,52 @@ void outsl(unsigned int port, const void *buffer, unsigned long count)
ctrl_inb (DUMMY_READ_AREA6);
#endif
}
+
+unsigned long generic_readb(unsigned long addr)
+{
+ return *(volatile unsigned char*)addr;
+}
+
+unsigned long generic_readw(unsigned long addr)
+{
+ return *(volatile unsigned short*)addr;
+}
+
+unsigned long generic_readl(unsigned long addr)
+{
+ return *(volatile unsigned long*)addr;
+}
+
+void generic_writeb(unsigned char b, unsigned long addr)
+{
+ *(volatile unsigned char*)addr = b;
+}
+
+void generic_writew(unsigned short b, unsigned long addr)
+{
+ *(volatile unsigned short*)addr = b;
+}
+
+void generic_writel(unsigned int b, unsigned long addr)
+{
+ *(volatile unsigned long*)addr = b;
+}
+
+void * generic_ioremap(unsigned long offset, unsigned long size)
+{
+ return (void *) P2SEGADDR(offset);
+}
+
+void * generic_ioremap_nocache (unsigned long offset, unsigned long size)
+{
+ return (void *) P2SEGADDR(offset);
+}
+
+void generic_iounmap(void *addr)
+{
+}
+
+unsigned long generic_isa_port2addr(unsigned long offset)
+{
+ return offset + generic_io_base;
+}
diff --git a/arch/sh/kernel/io_hd64461.c b/arch/sh/kernel/io_hd64461.c
index 7c655942b..3fbe6f2d0 100644
--- a/arch/sh/kernel/io_hd64461.c
+++ b/arch/sh/kernel/io_hd64461.c
@@ -10,15 +10,36 @@
static __inline__ unsigned long PORT2ADDR(unsigned long port)
{
+ /* 16550A: HD64461 internal */
+ if (0x3f8<=port && port<=0x3ff)
+ return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1);
+ if (0x2f8<=port && port<=0x2ff)
+ return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1);
+
+#ifdef CONFIG_HD64461_ENABLER
+ /* NE2000: HD64461 PCMCIA channel 0 (I/O) */
+ if (0x300<=port && port<=0x31f)
+ return 0xba000000 + port;
+
+ /* ide0: HD64461 PCMCIA channel 1 (memory) */
+ /* On HP690, CF in slot 1 is configured as a memory card
+ device. See CF+ and CompactFlash Specification for the
+ detail of CF's memory mapped addressing. */
+ if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port;
+ if (port == 0x3f6) return 0xb50001fe;
+#endif
+
+ /* ??? */
+ if (port < 0x10000) return 0xa0000000 + port;
+
/* HD64461 internal devices (0xb0000000) */
- if (port < 0x10000) return CONFIG_HD64461_IOBASE + port;
+ if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000;
/* PCMCIA channel 0, I/O (0xba000000) */
- if (port < 0x20000) return 0xba000000 + port - 0x10000;
+ if (port < 0x30000) return 0xba000000 + port - 0x20000;
- /* PCMCIA channel 1, memory (0xb5000000)
- SH7709 cannot support I/O card attached to Area 5 */
- if (port < 0x30000) return 0xb5000000 + port - 0x20000;
+ /* PCMCIA channel 1, memory (0xb5000000) */
+ if (port < 0x40000) return 0xb5000000 + port - 0x30000;
/* Whole physical address space (0xa0000000) */
return 0xa0000000 + (port & 0x1fffffff);
@@ -29,80 +50,80 @@ static inline void delay(void)
ctrl_inw(0xa0000000);
}
-unsigned long inb(unsigned int port)
+unsigned long hd64461_inb(unsigned int port)
{
return *(volatile unsigned char*)PORT2ADDR(port);
}
-unsigned long inb_p(unsigned int port)
+unsigned long hd64461_inb_p(unsigned int port)
{
unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
delay();
return v;
}
-unsigned long inw(unsigned int port)
+unsigned long hd64461_inw(unsigned int port)
{
return *(volatile unsigned short*)PORT2ADDR(port);
}
-unsigned long inl(unsigned int port)
+unsigned long hd64461_inl(unsigned int port)
{
return *(volatile unsigned long*)PORT2ADDR(port);
}
-void insb(unsigned int port, void *buffer, unsigned long count)
+void hd64461_insb(unsigned int port, void *buffer, unsigned long count)
{
unsigned char *buf=buffer;
while(count--) *buf++=inb(port);
}
-void insw(unsigned int port, void *buffer, unsigned long count)
+void hd64461_insw(unsigned int port, void *buffer, unsigned long count)
{
unsigned short *buf=buffer;
while(count--) *buf++=inw(port);
}
-void insl(unsigned int port, void *buffer, unsigned long count)
+void hd64461_insl(unsigned int port, void *buffer, unsigned long count)
{
unsigned long *buf=buffer;
while(count--) *buf++=inl(port);
}
-void outb(unsigned long b, unsigned int port)
+void hd64461_outb(unsigned long b, unsigned int port)
{
*(volatile unsigned char*)PORT2ADDR(port) = b;
}
-void outb_p(unsigned long b, unsigned int port)
+void hd64461_outb_p(unsigned long b, unsigned int port)
{
*(volatile unsigned char*)PORT2ADDR(port) = b;
delay();
}
-void outw(unsigned long b, unsigned int port)
+void hd64461_outw(unsigned long b, unsigned int port)
{
*(volatile unsigned short*)PORT2ADDR(port) = b;
}
-void outl(unsigned long b, unsigned int port)
+void hd64461_outl(unsigned long b, unsigned int port)
{
*(volatile unsigned long*)PORT2ADDR(port) = b;
}
-void outsb(unsigned int port, const void *buffer, unsigned long count)
+void hd64461_outsb(unsigned int port, const void *buffer, unsigned long count)
{
const unsigned char *buf=buffer;
while(count--) outb(*buf++, port);
}
-void outsw(unsigned int port, const void *buffer, unsigned long count)
+void hd64461_outsw(unsigned int port, const void *buffer, unsigned long count)
{
const unsigned short *buf=buffer;
while(count--) outw(*buf++, port);
}
-void outsl(unsigned int port, const void *buffer, unsigned long count)
+void hd64461_outsl(unsigned int port, const void *buffer, unsigned long count)
{
const unsigned long *buf=buffer;
while(count--) outl(*buf++, port);
diff --git a/arch/sh/kernel/io_se.c b/arch/sh/kernel/io_se.c
index a16c4738d..4d9eeca3b 100644
--- a/arch/sh/kernel/io_se.c
+++ b/arch/sh/kernel/io_se.c
@@ -56,7 +56,7 @@ shifted_port(unsigned int port)
printk("bad PC-like io %s for port 0x%x at 0x%08x\n", \
#name, (port), (__u32) __builtin_return_address(0))
-unsigned long inb(unsigned int port)
+unsigned long se_inb(unsigned int port)
{
if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
@@ -66,7 +66,7 @@ unsigned long inb(unsigned int port)
return (*port2adr(port))&0xff;
}
-unsigned long inb_p(unsigned int port)
+unsigned long se_inb_p(unsigned int port)
{
unsigned long v;
@@ -80,7 +80,7 @@ unsigned long inb_p(unsigned int port)
return v;
}
-unsigned long inw(unsigned int port)
+unsigned long se_inw(unsigned int port)
{
if (port >= 0x2000 ||
(sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
@@ -90,13 +90,13 @@ unsigned long inw(unsigned int port)
return 0;
}
-unsigned long inl(unsigned int port)
+unsigned long se_inl(unsigned int port)
{
maybebadio(inl, port);
return 0;
}
-void outb(unsigned long value, unsigned int port)
+void se_outb(unsigned long value, unsigned int port)
{
if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
*(__u8 *)(sh_pcic_io_wbase + port) = value;
@@ -106,7 +106,7 @@ void outb(unsigned long value, unsigned int port)
*(port2adr(port)) = value;
}
-void outb_p(unsigned long value, unsigned int port)
+void se_outb_p(unsigned long value, unsigned int port)
{
if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
*(__u8 *)(sh_pcic_io_wbase + port) = value;
@@ -117,7 +117,7 @@ void outb_p(unsigned long value, unsigned int port)
delay();
}
-void outw(unsigned long value, unsigned int port)
+void se_outw(unsigned long value, unsigned int port)
{
if (port >= 0x2000 ||
(sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
@@ -126,12 +126,12 @@ void outw(unsigned long value, unsigned int port)
maybebadio(outw, port);
}
-void outl(unsigned long value, unsigned int port)
+void se_outl(unsigned long value, unsigned int port)
{
maybebadio(outl, port);
}
-void insb(unsigned int port, void *addr, unsigned long count)
+void se_insb(unsigned int port, void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
@@ -148,19 +148,19 @@ void insb(unsigned int port, void *addr, unsigned long count)
}
}
-void insw(unsigned int port, void *addr, unsigned long count)
+void se_insw(unsigned int port, void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
while (count--)
*((__u16 *) addr)++ = *p;
}
-void insl(unsigned int port, void *addr, unsigned long count)
+void se_insl(unsigned int port, void *addr, unsigned long count)
{
maybebadio(insl, port);
}
-void outsb(unsigned int port, const void *addr, unsigned long count)
+void se_outsb(unsigned int port, const void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
@@ -177,24 +177,54 @@ void outsb(unsigned int port, const void *addr, unsigned long count)
}
}
-void outsw(unsigned int port, const void *addr, unsigned long count)
+void se_outsw(unsigned int port, const void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
while (count--)
*p = *((__u16 *) addr)++;
}
-void outsl(unsigned int port, const void *addr, unsigned long count)
+void se_outsl(unsigned int port, const void *addr, unsigned long count)
{
maybebadio(outsw, port);
}
+
+unsigned long se_readb(unsigned long addr)
+{
+ return *(volatile unsigned char*)addr;
+}
+
+unsigned long se_readw(unsigned long addr)
+{
+ return *(volatile unsigned short*)addr;
+}
+
+unsigned long se_readl(unsigned long addr)
+{
+ return *(volatile unsigned long*)addr;
+}
+
+void se_writeb(unsigned char b, unsigned long addr)
+{
+ *(volatile unsigned char*)addr = b;
+}
+
+void se_writew(unsigned short b, unsigned long addr)
+{
+ *(volatile unsigned short*)addr = b;
+}
+
+void se_writel(unsigned int b, unsigned long addr)
+{
+ *(volatile unsigned long*)addr = b;
+}
/* Map ISA bus address to the real address. Only for PCMCIA. */
/* ISA page descriptor. */
static __u32 sh_isa_memmap[256];
-int
+static int
sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
{
int idx;
@@ -212,7 +242,7 @@ sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
}
unsigned long
-sh_isa_slot(unsigned long offset)
+se_isa_port2addr(unsigned long offset)
{
int idx;
diff --git a/arch/sh/kernel/io_unknown.c b/arch/sh/kernel/io_unknown.c
new file mode 100644
index 000000000..a0407cade
--- /dev/null
+++ b/arch/sh/kernel/io_unknown.c
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/sh/kernel/io_unknown.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * I/O routine for unknown hardware.
+ */
+
+static unsigned int unknown_handler(void)
+{
+ return 0;
+}
+
+#define UNKNOWN_ALIAS(fn) \
+ void unknown_##fn(void) __attribute__ ((alias ("unknown_handler")));
+
+UNKNOWN_ALIAS(inb)
+UNKNOWN_ALIAS(inw)
+UNKNOWN_ALIAS(inl)
+UNKNOWN_ALIAS(outb)
+UNKNOWN_ALIAS(outw)
+UNKNOWN_ALIAS(outl)
+UNKNOWN_ALIAS(inb_p)
+UNKNOWN_ALIAS(inw_p)
+UNKNOWN_ALIAS(inl_p)
+UNKNOWN_ALIAS(outb_p)
+UNKNOWN_ALIAS(outw_p)
+UNKNOWN_ALIAS(outl_p)
+UNKNOWN_ALIAS(insb)
+UNKNOWN_ALIAS(insw)
+UNKNOWN_ALIAS(insl)
+UNKNOWN_ALIAS(outsb)
+UNKNOWN_ALIAS(outsw)
+UNKNOWN_ALIAS(outsl)
+UNKNOWN_ALIAS(readb)
+UNKNOWN_ALIAS(readw)
+UNKNOWN_ALIAS(readl)
+UNKNOWN_ALIAS(writeb)
+UNKNOWN_ALIAS(writew)
+UNKNOWN_ALIAS(writel)
+UNKNOWN_ALIAS(isa_port2addr)
+UNKNOWN_ALIAS(ioremap)
+UNKNOWN_ALIAS(ioremap_nocache)
+UNKNOWN_ALIAS(iounmap)
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index a353b0995..6451c4c9e 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -37,10 +37,6 @@
#include <asm/irq.h>
#include <linux/irq.h>
-#ifdef CONFIG_HD64461
-#include <asm/hd64461.h>
-#endif
-
/*
* Micro-access to controllers is serialized over the whole
* system. We never hold this lock when we call the actual
@@ -94,6 +90,7 @@ struct hw_interrupt_type no_irq_type = {
* Generic, controller-independent functions:
*/
+#if defined(CONFIG_PROC_FS)
int get_irq_list(char *buf)
{
int i, j;
@@ -105,7 +102,7 @@ int get_irq_list(char *buf)
p += sprintf(p, "CPU%d ",j);
*p++ = '\n';
- for (i = 0 ; i < NR_IRQS ; i++) {
+ for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
action = irq_desc[i].action;
if (!action)
continue;
@@ -120,6 +117,7 @@ int get_irq_list(char *buf)
}
return p - buf;
}
+#endif
/*
* This should really return information about whether
@@ -243,18 +241,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
"shlr %0\n\t"
"add #-16, %0\n\t"
:"=z" (irq));
-#if defined(CONFIG_HD64461)
- if (irq == CONFIG_HD64461_IRQ) {
- unsigned short bit;
- unsigned short nirr = inw(HD64461_NIRR);
- unsigned short nimr = inw(HD64461_NIMR);
- nirr &= ~nimr;
- for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++)
- if (nirr & bit) break;
- if (irq == 16) irq = CONFIG_HD64461_IRQ;
- else irq += HD64461_IRQBASE;
- }
-#endif
+ irq = irq_demux(irq);
kstat.irqs[cpu][irq]++;
desc = irq_desc + irq;
@@ -330,7 +317,7 @@ int request_irq(unsigned int irq,
int retval;
struct irqaction * action;
- if (irq >= NR_IRQS)
+ if (irq >= ACTUAL_NR_IRQS)
return -EINVAL;
if (!handler)
return -EINVAL;
@@ -358,7 +345,7 @@ void free_irq(unsigned int irq, void *dev_id)
struct irqaction **p;
unsigned long flags;
- if (irq >= NR_IRQS)
+ if (irq >= ACTUAL_NR_IRQS)
return;
spin_lock_irqsave(&irq_controller_lock,flags);
@@ -408,7 +395,7 @@ unsigned long probe_irq_on(void)
for (i = NR_IRQS-1; i > 0; i--) {
if (!irq_desc[i].action) {
irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
- if(irq_desc[i].handler->startup(i))
+ if (irq_desc[i].handler->startup(i))
irq_desc[i].status |= IRQ_PENDING;
}
}
@@ -430,7 +417,7 @@ unsigned long probe_irq_on(void)
if (!(status & IRQ_AUTODETECT))
continue;
-
+
/* It triggered already - consider it spurious. */
if (!(status & IRQ_WAITING)) {
irq_desc[i].status = status & ~IRQ_AUTODETECT;
diff --git a/arch/sh/kernel/irq_imask.c b/arch/sh/kernel/irq_imask.c
index 7237ba3b5..8ac95823b 100644
--- a/arch/sh/kernel/irq_imask.c
+++ b/arch/sh/kernel/irq_imask.c
@@ -8,6 +8,9 @@
*
*/
+/* NOTE: Will not work on level 15 */
+
+
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/kernel_stat.h>
@@ -71,7 +74,7 @@ void static inline set_interrupt_registers(int ip)
: "r" (~0xf0), "r" (ip << 4));
}
-void disable_imask_irq(unsigned int irq)
+static void disable_imask_irq(unsigned int irq)
{
clear_bit(irq, &imask_mask);
if (interrupt_priority < IMASK_PRIORITY - irq)
diff --git a/arch/sh/kernel/irq_ipr.c b/arch/sh/kernel/irq_ipr.c
index 8b6b0f5ee..f229e8a12 100644
--- a/arch/sh/kernel/irq_ipr.c
+++ b/arch/sh/kernel/irq_ipr.c
@@ -21,6 +21,7 @@
#include <asm/system.h>
#include <asm/io.h>
+#include <asm/machvec.h>
struct ipr_data {
unsigned int addr; /* Address of Interrupt Priority Register */
@@ -29,15 +30,8 @@ struct ipr_data {
};
static struct ipr_data ipr_data[NR_IRQS];
-void set_ipr_data(unsigned int irq, unsigned int addr, int pos, int priority)
-{
- ipr_data[irq].addr = addr;
- ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
- ipr_data[irq].priority = priority;
-}
-
static void enable_ipr_irq(unsigned int irq);
-void disable_ipr_irq(unsigned int irq);
+static void disable_ipr_irq(unsigned int irq);
/* shutdown is same as "disable" */
#define shutdown_ipr_irq disable_ipr_irq
@@ -61,7 +55,7 @@ static struct hw_interrupt_type ipr_irq_type = {
end_ipr_irq
};
-void disable_ipr_irq(unsigned int irq)
+static void disable_ipr_irq(unsigned int irq)
{
unsigned long val, flags;
unsigned int addr = ipr_data[irq].addr;
@@ -90,18 +84,11 @@ static void enable_ipr_irq(unsigned int irq)
restore_flags(flags);
}
-void make_ipr_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_desc[irq].handler = &ipr_irq_type;
- disable_ipr_irq(irq);
-}
-
static void mask_and_ack_ipr(unsigned int irq)
{
disable_ipr_irq(irq);
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
/* This is needed when we use edge triggered setting */
/* XXX: Is it really needed? */
if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
@@ -118,18 +105,39 @@ static void end_ipr_irq(unsigned int irq)
enable_ipr_irq(irq);
}
+void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
+{
+ disable_irq_nosync(irq);
+ ipr_data[irq].addr = addr;
+ ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
+ ipr_data[irq].priority = priority;
+
+ irq_desc[irq].handler = &ipr_irq_type;
+ disable_ipr_irq(irq);
+}
+
void __init init_IRQ(void)
{
- int i;
+ make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+ make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
- for (i = TIMER_IRQ; i < NR_IRQS; i++) {
- irq_desc[i].handler = &ipr_irq_type;
- }
+ make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+ make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+ make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+
+#ifdef SCIF_ERI_IRQ
+ make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+ make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+ make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+#endif
- set_ipr_data(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
- set_ipr_data(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
+#ifdef IRDA_ERI_IRQ
+ make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+ make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+ make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+#endif
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
/*
* Initialize the Interrupt Controller (INTC)
* registers to their power on values
@@ -161,11 +169,16 @@ void __init init_IRQ(void)
* You should set corresponding bits of PFC to "00"
* to enable these interrupts.
*/
- set_ipr_data(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY);
- set_ipr_data(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY);
- set_ipr_data(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY);
- set_ipr_data(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY);
- set_ipr_data(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY);
- set_ipr_data(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY);
-#endif /* CONFIG_CPU_SUBTYPE_SH7709 */
+ make_ipr_irq(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY);
+ make_ipr_irq(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY);
+ make_ipr_irq(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY);
+ make_ipr_irq(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY);
+ make_ipr_irq(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY);
+ make_ipr_irq(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY);
+#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */
+
+ /* Perform the machine specific initialisation */
+ if (sh_mv.mv_init_irq != NULL) {
+ sh_mv.mv_init_irq();
+ }
}
diff --git a/arch/sh/kernel/led_se.c b/arch/sh/kernel/led_se.c
new file mode 100644
index 000000000..0476f1bd8
--- /dev/null
+++ b/arch/sh/kernel/led_se.c
@@ -0,0 +1,67 @@
+/*
+ * linux/arch/sh/kernel/led_se.c
+ *
+ * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+
+static void mach_led(int position, int value)
+{
+ volatile unsigned short* p = (volatile unsigned short*)0xb0c00000;
+
+ if (value) {
+ *p |= (1<<8);
+ } else {
+ *p &= ~(1<<8);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_se(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short* p = (volatile unsigned short*)0xb0c00000;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ( (300<<FSHIFT)/
+ ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up=0;
+ } else {
+ bit ++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up=1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1<<(bit+8);
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/kernel/mach_hp600.c b/arch/sh/kernel/mach_hp600.c
new file mode 100644
index 000000000..6f68d1af7
--- /dev/null
+++ b/arch/sh/kernel/mach_hp600.c
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/sh/kernel/mach_hp600.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Machine vector for the HP600
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_hd64461.h>
+#include <asm/io_generic.h>
+#include <asm/irq.h>
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_hp600 __initmv = {
+ mv_name: "HP600",
+
+ mv_nr_irqs: 80, /* HD64461_IRQBASE+16, see hd64461.h */
+
+ mv_inb: hd64461_inb,
+ mv_inw: hd64461_inw,
+ mv_inl: hd64461_inl,
+ mv_outb: hd64461_outb,
+ mv_outw: hd64461_outw,
+ mv_outl: hd64461_outl,
+
+ mv_inb_p: hd64461_inb_p,
+ mv_inw_p: hd64461_inw,
+ mv_inl_p: hd64461_inl,
+ mv_outb_p: hd64461_outb_p,
+ mv_outw_p: hd64461_outw,
+ mv_outl_p: hd64461_outl,
+
+ mv_insb: hd64461_insb,
+ mv_insw: hd64461_insw,
+ mv_insl: hd64461_insl,
+ mv_outsb: hd64461_outsb,
+ mv_outsw: hd64461_outsw,
+ mv_outsl: hd64461_outsl,
+
+ mv_readb: generic_readb,
+ mv_readw: generic_readw,
+ mv_readl: generic_readl,
+ mv_writeb: generic_writeb,
+ mv_writew: generic_writew,
+ mv_writel: generic_writel,
+
+ mv_irq_demux: hd64461_irq_demux,
+
+ mv_hw_hp600: 1,
+ mv_hw_hd64461: 1,
+};
+ALIAS_MV(hp600)
diff --git a/arch/sh/kernel/mach_se.c b/arch/sh/kernel/mach_se.c
new file mode 100644
index 000000000..ce142a399
--- /dev/null
+++ b/arch/sh/kernel/mach_se.c
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/sh/kernel/mach_se.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Machine vector for the Hitachi SolutionEngine
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_se.h>
+
+void heartbeat_se(void);
+void setup_se(void);
+void init_se_IRQ(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_se __initmv = {
+ mv_name: "SolutionEngine",
+
+#if defined(__SH4__)
+ mv_nr_irqs: 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ mv_nr_irqs: 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ mv_nr_irqs: 61,
+#endif
+
+ mv_inb: se_inb,
+ mv_inw: se_inw,
+ mv_inl: se_inl,
+ mv_outb: se_outb,
+ mv_outw: se_outw,
+ mv_outl: se_outl,
+
+ mv_inb_p: se_inb_p,
+ mv_inw_p: se_inw,
+ mv_inl_p: se_inl,
+ mv_outb_p: se_outb_p,
+ mv_outw_p: se_outw,
+ mv_outl_p: se_outl,
+
+ mv_insb: se_insb,
+ mv_insw: se_insw,
+ mv_insl: se_insl,
+ mv_outsb: se_outsb,
+ mv_outsw: se_outsw,
+ mv_outsl: se_outsl,
+
+ mv_readb: se_readb,
+ mv_readw: se_readw,
+ mv_readl: se_readl,
+ mv_writeb: se_writeb,
+ mv_writew: se_writew,
+ mv_writel: se_writel,
+
+ mv_ioremap: generic_ioremap,
+ mv_ioremap_nocache: generic_ioremap_nocache,
+ mv_iounmap: generic_iounmap,
+
+ mv_isa_port2addr: se_isa_port2addr,
+
+ mv_init_arch: setup_se,
+ mv_init_irq: init_se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ mv_heartbeat: heartbeat_se,
+#endif
+
+ mv_hw_se: 1,
+};
+ALIAS_MV(se)
diff --git a/arch/sh/kernel/mach_unknown.c b/arch/sh/kernel/mach_unknown.c
new file mode 100644
index 000000000..895a65c1d
--- /dev/null
+++ b/arch/sh/kernel/mach_unknown.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/sh/kernel/mach_unknown.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Machine specific code for an unknown machine (internal peripherials only)
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_unknown.h>
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_unknown __initmv = {
+ mv_name: "Unknown",
+
+#if defined(__SH4__)
+ mv_nr_irqs: 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ mv_nr_irqs: 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ mv_nr_irqs: 61,
+#endif
+
+ mv_inb: unknown_inb,
+ mv_inw: unknown_inw,
+ mv_inl: unknown_inl,
+ mv_outb: unknown_outb,
+ mv_outw: unknown_outw,
+ mv_outl: unknown_outl,
+
+ mv_inb_p: unknown_inb_p,
+ mv_inw_p: unknown_inw_p,
+ mv_inl_p: unknown_inl_p,
+ mv_outb_p: unknown_outb_p,
+ mv_outw_p: unknown_outw_p,
+ mv_outl_p: unknown_outl_p,
+
+ mv_insb: unknown_insb,
+ mv_insw: unknown_insw,
+ mv_insl: unknown_insl,
+ mv_outsb: unknown_outsb,
+ mv_outsw: unknown_outsw,
+ mv_outsl: unknown_outsl,
+
+ mv_readb: unknown_readb,
+ mv_readw: unknown_readw,
+ mv_readl: unknown_readl,
+ mv_writeb: unknown_writeb,
+ mv_writew: unknown_writew,
+ mv_writel: unknown_writel,
+
+ mv_ioremap: unknown_ioremap,
+ mv_ioremap_nocache: unknown_ioremap_nocache,
+ mv_iounmap: unknown_iounmap,
+
+ mv_isa_port2addr: unknown_isa_port2addr,
+};
+ALIAS_MV(unknown)
diff --git a/arch/sh/kernel/pci-sh.c b/arch/sh/kernel/pci-sh.c
index 3613596f7..a4a6c6918 100644
--- a/arch/sh/kernel/pci-sh.c
+++ b/arch/sh/kernel/pci-sh.c
@@ -4,9 +4,22 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/errno.h>
+#include <asm/machvec.h>
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
- unsigned long start, unsigned long size)
+void __init pcibios_init(void)
{
- return start;
+ if (sh_mv.mv_init_pci != NULL) {
+ sh_mv.mv_init_pci();
+ }
}
+
+/* Haven't done anything here as yet */
+char * __init pcibios_setup(char *str)
+{
+ return str;
+}
+
+/* We don't have anything here to fixup */
+struct pci_fixup pcibios_fixups[] = {
+ {0, 0, 0, NULL}
+};
diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c
index c958745b5..f733501c1 100644
--- a/arch/sh/kernel/semaphore.c
+++ b/arch/sh/kernel/semaphore.c
@@ -12,6 +12,8 @@
#include <asm/semaphore.h>
#include <asm/semaphore-helper.h>
+spinlock_t semaphore_wake_lock;
+
/*
* Semaphores are implemented using a two-way counter:
* The "count" variable is decremented for each process
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index be56f8570..aaea2e6df 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -30,13 +30,16 @@
#endif
#include <linux/bootmem.h>
#include <linux/console.h>
+#include <linux/ctype.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
+#include <asm/io_generic.h>
#include <asm/smp.h>
+#include <asm/machvec.h>
#ifdef CONFIG_SH_EARLY_PRINTK
#include <asm/sh_bios.h>
#endif
@@ -53,10 +56,18 @@ extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_image_start; /* starting block # of image */
#endif
+#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+struct sh_machine_vector sh_mv;
+#endif
+
extern void fpu_init(void);
extern int root_mountflags;
extern int _text, _etext, _edata, _end;
+#define MV_NAME_SIZE 32
+
+static struct sh_machine_vector* __init get_mv_byname(const char* name);
+
/*
* This is set up by the setup-routine at boot-time
*/
@@ -180,8 +191,10 @@ void sh_console_unregister(void)
#endif
-
-static inline void parse_mem_cmdline (char ** cmdline_p)
+static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
+ struct sh_machine_vector** mvp,
+ unsigned long *mv_io_base,
+ int *mv_mmio_enable)
{
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
@@ -208,6 +221,35 @@ static inline void parse_mem_cmdline (char ** cmdline_p)
memory_end = memory_start + mem_size;
}
}
+ if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
+ char* mv_end;
+ char* mv_comma;
+ int mv_len;
+ if (to != command_line)
+ to--;
+ from += 6;
+ mv_end = strchr(from, ' ');
+ if (mv_end == NULL)
+ mv_end = from + strlen(from);
+
+ mv_comma = strchr(from, ',');
+ if ((mv_comma != NULL) && (mv_comma < mv_end)) {
+ int ints[3];
+ get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
+ *mv_io_base = ints[1];
+ *mv_mmio_enable = ints[2];
+ mv_len = mv_comma - from;
+ } else {
+ mv_len = mv_end - from;
+ }
+ if (mv_len > (MV_NAME_SIZE-1))
+ mv_len = MV_NAME_SIZE-1;
+ memcpy(mv_name, from, mv_len);
+ mv_name[mv_len] = '\0';
+ from = mv_end;
+
+ *mvp = get_mv_byname(mv_name);
+ }
c = *(from++);
if (!c)
break;
@@ -221,6 +263,10 @@ static inline void parse_mem_cmdline (char ** cmdline_p)
void __init setup_arch(char **cmdline_p)
{
+ struct sh_machine_vector *mv = NULL;
+ char mv_name[MV_NAME_SIZE] = "";
+ unsigned long mv_io_base = 0;
+ int mv_mmio_enable = 0;
unsigned long bootmap_size;
unsigned long start_pfn, max_pfn, max_low_pfn;
@@ -248,7 +294,58 @@ void __init setup_arch(char **cmdline_p)
data_resource.start = virt_to_bus(&_etext);
data_resource.end = virt_to_bus(&_edata)-1;
- parse_mem_cmdline(cmdline_p);
+ parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
+
+#ifdef CONFIG_SH_GENERIC
+ if (mv == NULL) {
+ extern struct sh_machine_vector mv_unknown;
+ mv = &mv_unknown;
+ if (*mv_name != '\0') {
+ printk("Warning: Unsupported machine %s, using unknown\n",
+ mv_name);
+ }
+ }
+ sh_mv = *mv;
+#endif
+#ifdef CONFIG_SH_UNKNOWN
+ sh_mv = mv_unknown;
+#endif
+
+#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
+ if (mv_io_base != 0) {
+ sh_mv.mv_inb = generic_inb;
+ sh_mv.mv_inw = generic_inw;
+ sh_mv.mv_inl = generic_inl;
+ sh_mv.mv_outb = generic_outb;
+ sh_mv.mv_outw = generic_outw;
+ sh_mv.mv_outl = generic_outl;
+
+ sh_mv.mv_inb_p = generic_inb_p;
+ sh_mv.mv_inw_p = generic_inw_p;
+ sh_mv.mv_inl_p = generic_inl_p;
+ sh_mv.mv_outb_p = generic_outb_p;
+ sh_mv.mv_outw_p = generic_outw_p;
+ sh_mv.mv_outl_p = generic_outl_p;
+
+ sh_mv.mv_insb = generic_insb;
+ sh_mv.mv_insw = generic_insw;
+ sh_mv.mv_insl = generic_insl;
+ sh_mv.mv_outsb = generic_outsb;
+ sh_mv.mv_outsw = generic_outsw;
+ sh_mv.mv_outsl = generic_outsl;
+
+ sh_mv.mv_isa_port2addr = generic_isa_port2addr;
+ generic_io_base = mv_io_base;
+ }
+ if (mv_mmio_enable != 0) {
+ sh_mv.mv_readb = generic_readb;
+ sh_mv.mv_readw = generic_readw;
+ sh_mv.mv_readl = generic_readl;
+ sh_mv.mv_writeb = generic_writeb;
+ sh_mv.mv_writew = generic_writew;
+ sh_mv.mv_writel = generic_writel;
+ }
+#endif
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
@@ -358,6 +455,11 @@ void __init setup_arch(char **cmdline_p)
#endif
#endif
+ /* Perform the machine specific initialisation */
+ if (sh_mv.mv_init_arch != NULL) {
+ sh_mv.mv_init_arch();
+ }
+
#if defined(__SH4__)
/* We already grab/initialized FPU in head.S. Make it consisitent. */
init_task.used_math = 1;
@@ -366,10 +468,32 @@ void __init setup_arch(char **cmdline_p)
paging_init();
}
+struct sh_machine_vector* __init get_mv_byname(const char* name)
+{
+ extern int strcasecmp(const char *, const char *);
+ extern long __machvec_start, __machvec_end;
+ struct sh_machine_vector *all_vecs =
+ (struct sh_machine_vector *)&__machvec_start;
+
+ int i, n = ((unsigned long)&__machvec_end
+ - (unsigned long)&__machvec_start)/
+ sizeof(struct sh_machine_vector);
+
+ for (i = 0; i < n; ++i) {
+ struct sh_machine_vector *mv = &all_vecs[i];
+ if (mv == NULL)
+ continue;
+ if (strcasecmp(name, mv->mv_name) == 0) {
+ return mv;
+ }
+ }
+ return NULL;
+}
+
/*
* Get CPU information for use by the procfs.
*/
-
+#ifdef CONFIG_PROC_FS
int get_cpuinfo(char *buffer)
{
char *p = buffer;
@@ -384,6 +508,7 @@ int get_cpuinfo(char *buffer)
p += sprintf(p, "bogomips\t: %lu.%02lu\n\n",
(loops_per_sec+2500)/500000,
((loops_per_sec+2500)/5000) % 100);
+ p += sprintf(p, "Machine: %s\n", sh_mv.mv_name);
#define PRINT_CLOCK(name, value) \
p += sprintf(p, name " clock: %d.%02dMHz\n", \
@@ -395,3 +520,4 @@ int get_cpuinfo(char *buffer)
return p - buffer;
}
+#endif
diff --git a/arch/sh/kernel/setup_cqreek.c b/arch/sh/kernel/setup_cqreek.c
new file mode 100644
index 000000000..3e0422154
--- /dev/null
+++ b/arch/sh/kernel/setup_cqreek.c
@@ -0,0 +1,224 @@
+/* $Id: setup_cqreek.c,v 1.1 2000/08/05 06:25:23 gniibe Exp $
+ *
+ * arch/sh/kernel/setup_cqreek.c
+ *
+ * Copyright (C) 2000 Niibe Yutaka
+ *
+ * CqREEK IDE/ISA Bridge Support.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/io_generic.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+
+#define BRIDGE_FEATURE 0x0002
+
+#define BRIDGE_IDE_CTRL 0x0018
+#define BRIDGE_IDE_INTR_LVL 0x001A
+#define BRIDGE_IDE_INTR_MASK 0x001C
+#define BRIDGE_IDE_INTR_STAT 0x001E
+
+#define BRIDGE_ISA_CTRL 0x0028
+#define BRIDGE_ISA_INTR_LVL 0x002A
+#define BRIDGE_ISA_INTR_MASK 0x002C
+#define BRIDGE_ISA_INTR_STAT 0x002E
+
+#define IDE_OFFSET 0xA4000000UL
+#define ISA_OFFSET 0xA4A00000UL
+
+static unsigned long cqreek_port2addr(unsigned long port)
+{
+ if (0x0000<=port && port<=0x0040)
+ return IDE_OFFSET + port;
+ if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6)
+ return IDE_OFFSET + port;
+
+ return ISA_OFFSET + port;
+}
+
+static void disable_cqreek_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short mask;
+
+ save_and_cli(flags);
+ /* Disable IRQ */
+ mask = inw(BRIDGE_ISA_INTR_MASK) & ~(1 << irq);
+ outw_p(mask, BRIDGE_ISA_INTR_MASK);
+ restore_flags(flags);
+}
+
+static void enable_cqreek_irq(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned short mask;
+
+ save_and_cli(flags);
+ /* Enable IRQ */
+ mask = inw(BRIDGE_ISA_INTR_MASK) | (1 << irq);
+ outw_p(mask, BRIDGE_ISA_INTR_MASK);
+ restore_flags(flags);
+}
+
+#define CLEAR_AT_ACCEPT
+
+static void mask_and_ack_cqreek(unsigned int irq)
+{
+ inw(BRIDGE_ISA_INTR_STAT);
+ disable_cqreek_irq(irq);
+#ifdef CLEAR_AT_ACCEPT
+ /* Clear IRQ (it might be edge IRQ) */
+ outw_p((1<<irq), BRIDGE_ISA_INTR_STAT);
+#endif
+}
+
+static void end_cqreek_irq(unsigned int irq)
+{
+#ifndef CLEAR_AT_ACCEPT
+ /* Clear IRQ (it might be edge IRQ) */
+ outw_p((1<<irq), BRIDGE_ISA_INTR_STAT);
+#endif
+ enable_cqreek_irq(irq);
+}
+
+static unsigned int startup_cqreek_irq(unsigned int irq)
+{
+ enable_cqreek_irq(irq);
+ return 0;
+}
+
+static void shutdown_cqreek_irq(unsigned int irq)
+{
+ disable_cqreek_irq(irq);
+}
+
+static struct hw_interrupt_type cqreek_irq_type = {
+ "CQREEK-IRQ",
+ startup_cqreek_irq,
+ shutdown_cqreek_irq,
+ enable_cqreek_irq,
+ disable_cqreek_irq,
+ mask_and_ack_cqreek,
+ end_cqreek_irq
+};
+
+static int has_ide, has_isa;
+
+/* XXX: This is just for test for my NE2000 ISA board
+ What we really need is virtualized IRQ and demultiplexer like HP600 port */
+void __init init_cqreek_IRQ(void)
+{
+ if (has_ide)
+ make_ipr_irq(14, IDE_OFFSET+BRIDGE_IDE_INTR_LVL, 0, 0x0f-14);
+
+ if (has_isa) {
+ /* XXX: Err... we may need demultiplexer for ISA irq... */
+ irq_desc[10].handler = &cqreek_irq_type;
+ irq_desc[10].status = IRQ_DISABLED;
+ irq_desc[10].action = 0;
+ irq_desc[10].depth = 1;
+
+ disable_cqreek_irq(10);
+ }
+}
+
+/*
+ * Initialize the board
+ */
+void __init setup_cqreek(void)
+{
+ int i;
+/* udelay is not available at setup time yet... */
+#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
+
+ if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */
+ outw_p(0, BRIDGE_IDE_INTR_LVL);
+ outw_p(0, BRIDGE_IDE_INTR_MASK);
+
+ outw_p(0, BRIDGE_IDE_CTRL);
+ DELAY();
+
+ outw_p(0x8000, BRIDGE_IDE_CTRL);
+ DELAY();
+
+ outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */
+ outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */
+ outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */
+ has_ide=1;
+ }
+
+ if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */
+ outw_p(0, BRIDGE_ISA_INTR_LVL);
+ outw_p(0, BRIDGE_ISA_INTR_MASK);
+
+ outw_p(0, BRIDGE_ISA_CTRL);
+ DELAY();
+ outw_p(0x8000, BRIDGE_ISA_CTRL);
+ DELAY();
+
+ outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */
+ outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */
+ outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */
+ has_isa=1;
+ }
+
+ printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", has_ide, has_isa);
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_cqreek __initmv = {
+ mv_name: "CqREEK",
+
+#if defined(__SH4__)
+ mv_nr_irqs: 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ mv_nr_irqs: 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ mv_nr_irqs: 61,
+#endif
+
+ mv_inb: generic_inb,
+ mv_inw: generic_inw,
+ mv_inl: generic_inl,
+ mv_outb: generic_outb,
+ mv_outw: generic_outw,
+ mv_outl: generic_outl,
+
+ mv_inb_p: generic_inb_p,
+ mv_inw_p: generic_inw_p,
+ mv_inl_p: generic_inl_p,
+ mv_outb_p: generic_outb_p,
+ mv_outw_p: generic_outw_p,
+ mv_outl_p: generic_outl_p,
+
+ mv_insb: generic_insb,
+ mv_insw: generic_insw,
+ mv_insl: generic_insl,
+ mv_outsb: generic_outsb,
+ mv_outsw: generic_outsw,
+ mv_outsl: generic_outsl,
+
+ mv_readb: generic_readb,
+ mv_readw: generic_readw,
+ mv_readl: generic_readl,
+ mv_writeb: generic_writeb,
+ mv_writew: generic_writew,
+ mv_writel: generic_writel,
+
+ mv_init_arch: setup_cqreek,
+ mv_init_irq: init_cqreek_IRQ,
+
+ mv_port2addr: cqreek_port2addr,
+ mv_isa_port2addr: cqreek_port2addr,
+};
+ALIAS_MV(cqreek)
diff --git a/arch/sh/kernel/setup_hd64461.c b/arch/sh/kernel/setup_hd64461.c
index 0ee07e887..6132e420d 100644
--- a/arch/sh/kernel/setup_hd64461.c
+++ b/arch/sh/kernel/setup_hd64461.c
@@ -92,6 +92,20 @@ static void hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs)
inw(HD64461_NIRR), inw(HD64461_NIMR));
}
+int hd64461_irq_demux(int irq)
+{
+ if (irq == CONFIG_HD64461_IRQ) {
+ unsigned short bit;
+ unsigned short nirr = inw(HD64461_NIRR);
+ unsigned short nimr = inw(HD64461_NIMR);
+ nirr &= ~nimr;
+ for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++)
+ if (nirr & bit) break;
+ if (irq == 16) irq = CONFIG_HD64461_IRQ;
+ else irq += HD64461_IRQBASE;
+ }
+ return irq;
+}
static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, 0, "HD64461", NULL, NULL};
@@ -100,10 +114,13 @@ int __init setup_hd64461(void)
{
int i;
+ if (!MACH_HD64461)
+ return 0;
+
printk(KERN_INFO "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ,
HD64461_IRQBASE, HD64461_IRQBASE+15);
-#if 1
+#ifdef CONFIG_CPU_SUBTYPE_SH7709
/* IRQ line for HD64461 should be set level trigger mode("10"). */
/* And this should be done earlier than the kernel starts. */
ctrl_outw(0x0200, INTC_ICR1); /* when connected to IRQ4. */
diff --git a/arch/sh/kernel/setup_se.c b/arch/sh/kernel/setup_se.c
index cd9436fff..8b2f59972 100644
--- a/arch/sh/kernel/setup_se.c
+++ b/arch/sh/kernel/setup_se.c
@@ -73,10 +73,8 @@ static void __init init_smsc(void)
/*
* Initialize IRQ setting
*/
-static void __init init_se_IRQ(void)
+void __init init_se_IRQ(void)
{
- int i;
-
/*
* Super I/O (Just mimic PC):
* 1: keyboard
@@ -88,43 +86,34 @@ static void __init init_se_IRQ(void)
* 12: mouse
* 14: ide0
*/
- set_ipr_data(14, BCR_ILCRA, 2, 0x0f-14);
- set_ipr_data(12, BCR_ILCRA, 1, 0x0f-12);
- set_ipr_data( 8, BCR_ILCRB, 1, 0x0f- 8);
- set_ipr_data( 6, BCR_ILCRC, 3, 0x0f- 6);
- set_ipr_data( 5, BCR_ILCRC, 2, 0x0f- 5);
- set_ipr_data( 4, BCR_ILCRC, 1, 0x0f- 4);
- set_ipr_data( 3, BCR_ILCRC, 0, 0x0f- 3);
- set_ipr_data( 1, BCR_ILCRD, 3, 0x0f- 1);
-
- set_ipr_data(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
-
- set_ipr_data( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
- set_ipr_data(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
- set_ipr_data( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
- set_ipr_data( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
+ make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
+ make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12);
+ make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8);
+ make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6);
+ make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5);
+ make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4);
+ make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3);
+ make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1);
+
+ make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
+
+ make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
+ make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
+ make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
+ make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
/* NOTE: #2 and #13 are not used on PC */
- set_ipr_data(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
- set_ipr_data( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
-
- for (i = 0; i < 15; i++) {
- make_ipr_irq(i);
- }
+ make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
+ make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
}
+
/*
* Initialize the board
*/
-int __init setup_se(void)
+void __init setup_se(void)
{
- init_se_IRQ();
init_smsc();
/* XXX: RTC setting comes here */
-
- printk(KERN_INFO "Hitach SolutionEngine Setup...done\n");
- return 0;
}
-
-module_init(setup_se);
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c
index a24b4a842..12f716249 100644
--- a/arch/sh/kernel/sh_bios.c
+++ b/arch/sh/kernel/sh_bios.c
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: sh_bios.c,v 1.2 2000/07/26 04:37:32 gniibe Exp $
*
* linux/arch/sh/kernel/sh_bios.c
* C interface for trapping into the standard LinuxSH BIOS.
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 221af3022..9bdddc9d9 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -198,13 +198,16 @@ static inline int save_sigcontext_fpu(struct sigcontext *sc)
{
struct task_struct *tsk = current;
unsigned long flags;
+ int val;
if (!tsk->used_math) {
- __copy_to_user(&sc->sc_ownedfp, 0, sizeof(int));
+ val = 0;
+ __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
return 0;
}
- __copy_to_user(&sc->sc_ownedfp, 1, sizeof(int));
+ val = 1;
+ __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
/* This will cause a "finit" to be triggered by the next
attempted FPU operation by the 'current' process.
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 2c73255f4..f1e8d28bf 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -26,6 +26,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/delay.h>
+#include <asm/machvec.h>
#include <linux/timex.h>
#include <linux/irq.h>
@@ -226,6 +227,11 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
sh_do_profile(regs->pc);
#endif
+#ifdef CONFIG_HEARTBEAT
+ if (sh_mv.mv_heartbeat != NULL)
+ sh_mv.mv_heartbeat();
+#endif
+
/*
* If we have an externally synchronized Linux clock, then update
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
@@ -441,11 +447,11 @@ void __init time_init(void)
tmp = (frqcr & 0x2000) >> 11;
tmp |= frqcr & 0x0003;
pfc = pfc_table[tmp];
-#ifdef CONFIG_SH_HP600
- master_clock = cpu_clock/6;
-#else
- master_clock = cpu_clock;
-#endif
+ if (MACH_HP600) {
+ master_clock = cpu_clock/6;
+ } else {
+ master_clock = cpu_clock;
+ }
bus_clock = master_clock/pfc;
}
#elif defined(__SH4__)
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
index 7af24f1c3..a0d344cb9 100644
--- a/arch/sh/lib/Makefile
+++ b/arch/sh/lib/Makefile
@@ -7,6 +7,6 @@
L_TARGET = lib.a
L_OBJS = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \
- checksum.o
+ checksum.o strcasecmp.o
include $(TOPDIR)/Rules.make
diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S
index b34a65383..3317b3ccc 100644
--- a/arch/sh/lib/checksum.S
+++ b/arch/sh/lib/checksum.S
@@ -185,15 +185,65 @@ ENTRY(csum_partial_copy_generic)
mov.l r5,@-r15
mov.l r6,@-r15
+ mov #3, r0 ! Check src and dest are equally aligned
+ mov r4, r1
+ and r0, r1
+ and r5, r0
+ cmp/eq r1, r0
+ bf 3f ! Different alignments, use slow version
+ tst #1,r0 ! Check dest word aligned
+ bf 3f ! If not, do it the slow way
+
mov #2,r0
- tst r0,r5 ! Check alignment.
+ tst r0,r5 ! Check dest alignment.
bt 2f ! Jump if alignment is ok.
add #-2,r6 ! Alignment uses up two bytes.
cmp/pz r6 ! Jump if we had at least two bytes.
bt/s 1f
clrt
bra 4f
- add #2,r6 ! $r6 was < 2. Deal with it.
+ add #2,r6 ! $r6 was < 2. Deal with it.
+
+3: ! Handle different src and dest alinments.
+ ! This is not common, so simple byte by byte copy will do.
+ mov r6, r2
+ shlr r6
+ tst r6, r6
+ bt 4f
+ clrt
+SRC(5: mov.b @r4+,r0 )
+DST( mov.b r0,@r5 )
+ add #1, r5
+SRC( mov.b @r4+,r1 )
+DST( mov.b r1,@r5 )
+ add #1,r5
+
+ extu.b r0,r0
+ extu.b r1,r1
+#ifdef __LITTLE_ENDIAN__
+ shll8 r1
+#else
+ shll8 r0
+#endif
+ or r1,r0
+
+ addc r0,r7
+ movt r0
+ dt r6
+ bf/s 5b
+ cmp/eq #1,r0
+ mov #0,r0
+ addc r0, r7
+
+ mov r2, r0
+ tst #1, r0
+ bt 7f
+ bra 5f
+ clrt
+
+ ! src and dest equally aligned, but to a two byte boundary.
+ ! Handle first two bytes as a special case
+ .align 5
SRC(1: mov.w @r4+,r0 )
DST( mov.w r0,@r5 )
add #2,r5
diff --git a/arch/sh/lib/strcasecmp.c b/arch/sh/lib/strcasecmp.c
new file mode 100644
index 000000000..4e57a216f
--- /dev/null
+++ b/arch/sh/lib/strcasecmp.c
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/alpha/lib/strcasecmp.c
+ */
+
+#include <linux/string.h>
+
+
+/* We handle nothing here except the C locale. Since this is used in
+ only one place, on strings known to contain only 7 bit ASCII, this
+ is ok. */
+
+int strcasecmp(const char *a, const char *b)
+{
+ int ca, cb;
+
+ do {
+ ca = *a++ & 0xff;
+ cb = *b++ & 0xff;
+ if (ca >= 'A' && ca <= 'Z')
+ ca += 'a' - 'A';
+ if (cb >= 'A' && cb <= 'Z')
+ cb += 'a' - 'A';
+ } while (ca == cb && ca != '\0');
+
+ return ca - cb;
+}
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 981c25380..1f1815600 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -8,6 +8,6 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
-O_OBJS := init.o fault.o ioremap.o extable.o cache.o
+O_OBJS := init.o fault.o extable.o cache.o # ioremap.o
include $(TOPDIR)/Rules.make
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index 56f444bf4..af494b9a3 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -207,6 +207,9 @@ static void icache_purge_range(unsigned long start, unsigned long end)
* compared the tag of cache and if it's not matched, nothing
* will be occurred. (We can avoid flushing other caches.)
*
+ * NOTE: We can use A-bit feature here, because we have valid
+ * entriy in TLB (at least in UTLB), as dcache_wback_range is
+ * called before this function is called.
*/
for (v = start; v < end; v+=L1_CACHE_BYTES) {
addr = CACHE_IC_ADDRESS_ARRAY | (v&CACHE_IC_ENTRY_MASK)
@@ -225,8 +228,12 @@ static void icache_purge_range(unsigned long start, unsigned long end)
*/
void flush_icache_range(unsigned long start, unsigned long end)
{
+ unsigned long flags;
+
+ save_and_cli(flags);
dcache_wback_range(start, end);
icache_purge_range(start, end);
+ restore_flags(flags);
}
/*
@@ -238,11 +245,6 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
{
unsigned long phys, addr, data, i;
- /*
- * Alas, we don't know where the virtual address is,
- * So, we can't use icache_purge_range().
- */
-
/* Physical address of this page */
phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START;
@@ -259,6 +261,30 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
back_to_P1();
}
+/*
+ * Write back & invalidate the D-cache of the page.
+ * (To avoid "alias" issues)
+ */
+void flush_dcache_page(struct page *pg)
+{
+ unsigned long phys, addr, data, i;
+
+ /* Physical address of this page */
+ phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START;
+
+ jump_to_P2();
+ /* Loop all the D-cache */
+ for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
+ addr = CACHE_OC_ADDRESS_ARRAY| (i<<CACHE_OC_ENTRY_SHIFT);
+ data = ctrl_inl(addr);
+ if ((data & CACHE_VALID) && (data&PAGE_MASK) == phys) {
+ data &= ~(CACHE_VALID|CACHE_UPDATED);
+ ctrl_outl(data, addr);
+ }
+ }
+ back_to_P1();
+}
+
void flush_cache_all(void)
{
unsigned long addr, data, i;
@@ -298,56 +324,64 @@ void flush_cache_mm(struct mm_struct *mm)
flush_cache_all();
}
+/*
+ * Write back and invalidate D-caches.
+ *
+ * START, END: Virtual Address (U0 address)
+ *
+ * NOTE: We need to flush the _physical_ page entry.
+ * Flushing the cache lines for U0 only isn't enough.
+ * We need to flush for P1 too, which may contain aliases.
+ */
void flush_cache_range(struct mm_struct *mm, unsigned long start,
unsigned long end)
{
/*
- * Calling
- * dcache_flush_range(start, end);
- * is not good for the purpose of this function. That is,
- * flushing cache lines indexed by the virtual address is not
- * sufficient.
- *
- * Instead, we need to flush the relevant cache lines which
- * hold the data of the corresponding physical memory, as we
- * have "alias" issues.
- *
- * This is needed because, kernel accesses the memory through
- * P1-area (and/or U0-area) and user-space accesses through U0-area.
- * And P1-area and U0-area may use different cache lines for
- * same physical memory.
+ * We could call flush_cache_page for the pages of these range,
+ * but it's not efficient (scan the caches all the time...).
*
- * If we would call dcache_flush_range(), the line of P1-area
- * could remain in the cache, unflushed.
+ * We can't use A-bit magic, as there's the case we don't have
+ * valid entry on TLB.
*/
- unsigned long addr, data, v;
-
- start &= ~(L1_CACHE_BYTES-1);
- jump_to_P2();
-
- for (v = start; v < end; v+=L1_CACHE_BYTES) {
- addr = CACHE_OC_ADDRESS_ARRAY |
- (v&CACHE_OC_ENTRY_PHYS_MASK) | 0x8 /* A-bit */;
- data = (v&0xfffffc00); /* Update=0, Valid=0 */
-
- /* Try all the cases for aliases */
- ctrl_outl(data, addr);
- ctrl_outl(data, addr | 0x1000);
- ctrl_outl(data, addr | 0x2000);
- ctrl_outl(data, addr | 0x3000);
- }
- back_to_P1();
+ flush_cache_all();
}
+/*
+ * Write back and invalidate D-caches for the page.
+ *
+ * ADDR: Virtual Address (U0 address)
+ *
+ * NOTE: We need to flush the _physical_ page entry.
+ * Flushing the cache lines for U0 only isn't enough.
+ * We need to flush for P1 too, which may contain aliases.
+ */
void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
{
- /* XXX: Umm... this flush out all the cache lines. Any improvement? */
- flush_cache_range(vma->vm_mm, addr, addr+PAGE_SIZE);
+ pgd_t *dir;
+ pmd_t *pmd;
+ pte_t *pte;
+ pte_t entry;
+ unsigned long phys;
+ struct page *pg;
+
+ dir = pgd_offset(vma->vm_mm, addr);
+ pmd = pmd_offset(dir, addr);
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd))
+ return;
+ pte = pte_offset(pmd, addr);
+ entry = *pte;
+ if (pte_none(entry) || !pte_present(entry))
+ return;
+ phys = pte_val(entry)&PAGE_MASK;
+ pg = virt_to_page(__va(phys));
+ flush_dcache_page(pg);
}
/*
* After accessing the memory from kernel space (P1-area), we need to
- * write back the cache line, to avoid "alias" issues.
+ * write back the cache line to maintain DMA coherency.
*
* We search the D-cache to see if we have the entries corresponding to
* the page, and if found, write back them.
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 9dd6ae451..f2e342f0b 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -115,7 +115,8 @@ static void handle_vmalloc_fault(struct mm_struct *mm, unsigned long address)
* ITLB is not affected by "ldtlb" instruction.
* So, we need to flush the entry by ourselves.
*/
- __flush_tlb_page(mm, address&PAGE_MASK);
+ if (mm)
+ __flush_tlb_page(mm, address&PAGE_MASK);
#endif
update_mmu_cache(NULL, address, entry);
}
@@ -281,15 +282,14 @@ void update_mmu_cache(struct vm_area_struct * vma,
save_and_cli(flags);
#if defined(__SH4__)
- if ((vma->vm_flags & VM_SHARED)) {
+ if (vma && (vma->vm_flags & VM_SHARED)) {
+ struct page *pg;
+
pteval = pte_val(pte);
pteval &= PAGE_MASK; /* Physicall page address */
-
__flush_tlb_phys(vma->vm_mm, pteval);
-
- /* It would be good we had routine which takes
- physical memory as argument */
- flush_cache_page(vma, address&PAGE_MASK);
+ pg = virt_to_page(__va(pteval));
+ flush_dcache_page(pg);
}
#endif
diff --git a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
index 1a7c2e820..ad1fc1c1b 100644
--- a/arch/sh/vmlinux.lds.S
+++ b/arch/sh/vmlinux.lds.S
@@ -61,6 +61,9 @@ SECTIONS
__initcall_start = .;
.initcall.init : { *(.initcall.init) }
__initcall_end = .;
+ __machvec_start = .;
+ .machvec.init : { *(.machvec.init) }
+ __machvec_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index 570f86325..e603d2a64 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.99 2000/08/01 04:53:58 anton Exp $
+# $Id: config.in,v 1.100 2000/08/07 18:06:54 anton Exp $
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
@@ -86,13 +86,23 @@ comment 'Block devices'
bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD
-bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
-if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
- tristate ' Linear (append) mode' CONFIG_MD_LINEAR
- tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED
-# tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
-# tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
-fi
+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
+
+#tristate 'Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM N
+#if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then
+# bool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y
+#fi
+
+tristate 'Multiple devices driver support' CONFIG_BLK_DEV_MD
+dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD
+dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD
+dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD
+dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD
+#if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_RAID0" = "y" -o "$CONFIG_MD_RAID1" = "y" -o "$CONFIG_MD_RAID5" = "y" ]; then
+# bool ' Boot support' CONFIG_MD_BOOT
+# bool ' Auto Detect support' CONFIG_AUTODETECT_RAID
+#fi
tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
@@ -100,9 +110,6 @@ if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
fi
dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
-tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-tristate 'Network block device support' CONFIG_BLK_DEV_NBD
-
endmenu
if [ "$CONFIG_NET" = "y" ]; then
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index c58948e71..8bac6f8e3 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -2,6 +2,7 @@
# Automatically generated make config: don't edit
#
CONFIG_UID16=y
+CONFIG_HIGHMEM=y
#
# Code maturity level options
@@ -108,14 +109,16 @@ CONFIG_SUN_AURORA=m
# Block devices
#
CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_MD=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
-CONFIG_MD_STRIPED=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
#
# Networking options
diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c
index ad74d0ed2..dedb18f01 100644
--- a/arch/sparc/mm/generic.c
+++ b/arch/sparc/mm/generic.c
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.9 1999/12/27 06:30:03 anton Exp $
+/* $Id: generic.c,v 1.10 2000/08/09 00:00:15 davem Exp $
* generic.c: Generic Sparc mm routines that are not dependent upon
* MMU type but are Sparc specific.
*
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 3d42e0c63..b0d45d82a 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.89 2000/08/01 04:53:58 anton Exp $
+/* $Id: init.c,v 1.90 2000/08/09 00:00:15 davem Exp $
* linux/arch/sparc/mm/init.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index f395f06f5..1679384d6 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.21 2000/02/06 22:55:45 zaitcev Exp $
+/* $Id: io-unit.c,v 1.22 2000/08/09 00:00:15 davem Exp $
* io-unit.c: IO-UNIT specific routines for memory management.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index e48128479..058fdd0d1 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.19 2000/02/06 22:55:45 zaitcev Exp $
+/* $Id: iommu.c,v 1.20 2000/08/09 00:00:15 davem Exp $
* iommu.c: IOMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 7e76841de..96fbf1b88 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.219 2000/08/01 04:53:58 anton Exp $
+/* $Id: srmmu.c,v 1.220 2000/08/09 00:00:15 davem Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 717269b68..0ce0ca1e8 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.196 2000/07/07 07:33:11 anton Exp $
+/* $Id: sun4c.c,v 1.197 2000/08/09 00:00:15 davem Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index dab4e3bcf..c93f2efc8 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.60 2000/07/16 18:21:24 ecd Exp $
+# $Id: Makefile,v 1.61 2000/08/09 08:25:19 jj Exp $
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -64,7 +64,7 @@ binfmt_elf32.o: $(TOPDIR)/fs/binfmt_elf.c
ifneq ($(NEW_GCC),y)
CMODEL_CFLAG := -mmedlow
else
- CMODEL_CFLAG := -mcmodel=medlow
+ CMODEL_CFLAG := -m64 -mcmodel=medlow
endif
check_asm: dummy
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 3295938e6..729ecd911 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.51 2000/07/28 09:43:39 davem Exp $
+/* $Id: rtrap.S,v 1.53 2000/08/06 05:20:35 davem Exp $
* rtrap.S: Preparing for return from trap on Sparc V9.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 7d8a71d6a..e77d8a385 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.158 2000/07/29 00:55:49 davem Exp $
+/* $Id: sys_sparc32.c,v 1.159 2000/08/08 02:47:50 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1037,7 +1037,8 @@ asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
-typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
static long do_readv_writev32(int type, struct file *file,
const struct iovec32 *vector, u32 count)
@@ -1047,14 +1048,15 @@ static long do_readv_writev32(int type, struct file *file,
struct iovec *iov=iovstack, *ivp;
struct inode *inode;
long retval, i;
- IO_fn_t fn;
+ io_fn_t fn;
+ iov_fn_t fnv;
/* First get the "struct iovec" from user memory and
* verify all the pointers
*/
if (!count)
return 0;
- if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+ if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
return -EFAULT;
if (count > UIO_MAXIOV)
return -EINVAL;
@@ -1086,33 +1088,19 @@ static long do_readv_writev32(int type, struct file *file,
retval = locks_verify_area((type == VERIFY_WRITE
? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
inode, file, file->f_pos, tot_len);
- if (retval) {
- if (iov != iovstack)
- kfree(iov);
- return retval;
- }
+ if (retval)
+ goto out;
- /* Then do the actual IO. Note that sockets need to be handled
- * specially as they have atomicity guarantees and can handle
- * iovec's natively
- */
- if (inode->i_sock) {
- int err;
- err = sock_readv_writev(type, inode, file, iov, count, tot_len);
- if (iov != iovstack)
- kfree(iov);
- return err;
+ /* VERIFY_WRITE actually means a read, as we write to user space */
+ fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
+ if (fnv) {
+ retval = fnv(file, iov, count, &file->f_pos);
+ goto out;
}
- if (!file->f_op) {
- if (iov != iovstack)
- kfree(iov);
- return -EINVAL;
- }
- /* VERIFY_WRITE actually means a read, as we write to user space */
- fn = file->f_op->read;
- if (type == VERIFY_READ)
- fn = (IO_fn_t) file->f_op->write;
+ fn = (type == VERIFY_WRITE ? file->f_op->read :
+ (io_fn_t) file->f_op->write);
+
ivp = iov;
while (count > 0) {
void * base;
@@ -1124,17 +1112,18 @@ static long do_readv_writev32(int type, struct file *file,
count--;
nr = fn(file, base, len, &file->f_pos);
if (nr < 0) {
- if (retval)
- break;
- retval = nr;
+ if (!retval)
+ retval = nr;
break;
}
retval += nr;
if (nr != len)
break;
}
+out:
if (iov != iovstack)
kfree(iov);
+
return retval;
}
@@ -1147,7 +1136,8 @@ asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
if(!file)
goto bad_file;
- if (file->f_op && file->f_op->read && (file->f_mode & FMODE_READ))
+ if (file->f_op && (file->f_mode & FMODE_READ) &&
+ (file->f_op->readv || file->f_op->read))
ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
fput(file);
@@ -1163,7 +1153,8 @@ asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
file = fget(fd);
if(!file)
goto bad_file;
- if (file->f_op && file->f_op->write && (file->f_mode & FMODE_WRITE))
+ if (file->f_op && (file->f_mode & FMODE_WRITE) &&
+ (file->f_op->writev || file->f_op->write))
ret = do_readv_writev32(VERIFY_READ, file, vector, count);
fput(file);
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index cd4b3365c..8c9b7c9fd 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.48 2000/05/03 06:37:03 davem Exp $
+/* $Id: fault.c,v 1.49 2000/08/09 00:00:15 davem Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index c469c6062..68b77cfab 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.13 1999/12/20 05:02:33 davem Exp $
+/* $Id: generic.c,v 1.14 2000/08/09 00:00:15 davem Exp $
* generic.c: Generic Sparc mm routines that are not dependent upon
* MMU type but are Sparc specific.
*
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 63994c51d..7eef97836 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.153 2000/07/27 01:05:15 davem Exp $
+/* $Id: init.c,v 1.154 2000/08/09 00:00:15 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)