summaryrefslogtreecommitdiffstats
path: root/arch/h8300/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/h8300/kernel
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/h8300/kernel')
-rw-r--r--arch/h8300/kernel/Makefile11
-rw-r--r--arch/h8300/kernel/asm-offsets.c65
-rw-r--r--arch/h8300/kernel/gpio.c174
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c112
-rw-r--r--arch/h8300/kernel/init_task.c43
-rw-r--r--arch/h8300/kernel/ints.c255
-rw-r--r--arch/h8300/kernel/module.c122
-rw-r--r--arch/h8300/kernel/process.c288
-rw-r--r--arch/h8300/kernel/ptrace.c277
-rw-r--r--arch/h8300/kernel/semaphore.c133
-rw-r--r--arch/h8300/kernel/setup.c248
-rw-r--r--arch/h8300/kernel/signal.c552
-rw-r--r--arch/h8300/kernel/sys_h8300.c282
-rw-r--r--arch/h8300/kernel/syscalls.S340
-rw-r--r--arch/h8300/kernel/time.c134
-rw-r--r--arch/h8300/kernel/traps.c169
-rw-r--r--arch/h8300/kernel/vmlinux.lds.S172
17 files changed, 3377 insertions, 0 deletions
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
new file mode 100644
index 000000000000..71b6131e98b8
--- /dev/null
+++ b/arch/h8300/kernel/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
+
+extra-y := vmlinux.lds
+
+obj-y := process.o traps.o ptrace.o ints.o \
+ sys_h8300.o time.o semaphore.o signal.o \
+ setup.o gpio.o init_task.o syscalls.o
+
+obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
new file mode 100644
index 000000000000..b78b82ad28a3
--- /dev/null
+++ b/arch/h8300/kernel/asm-offsets.c
@@ -0,0 +1,65 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+ /* offsets into the task struct */
+ DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+ DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
+ DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+ DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+
+ /* offsets into the irq_cpustat_t struct */
+ DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
+
+ /* offsets into the thread struct */
+ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+ DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+ DEFINE(THREAD_CCR, offsetof(struct thread_struct, ccr));
+
+ /* offsets into the pt_regs struct */
+ DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long));
+ DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long));
+ DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long));
+ DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long));
+ DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long));
+ DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long));
+ DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long));
+ DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long));
+ DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long));
+ DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long));
+#if defined(__H8300S__)
+ DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long));
+#endif
+ DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long));
+
+ DEFINE(PT_PTRACED, PT_PTRACED);
+ DEFINE(PT_DTRACE, PT_DTRACE);
+
+ return 0;
+}
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c
new file mode 100644
index 000000000000..795682b873e2
--- /dev/null
+++ b/arch/h8300/kernel/gpio.c
@@ -0,0 +1,174 @@
+/*
+ * linux/arch/h8300/kernel/gpio.c
+ *
+ * Yoshinori Sato <ysato@users.sourceforge.jp>
+ *
+ */
+
+/*
+ * Internal I/O Port Management
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+
+#define _(addr) (volatile unsigned char *)(addr)
+#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
+#include <asm/regs306x.h>
+static volatile unsigned char *ddrs[] = {
+ _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
+ NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
+};
+#define MAX_PORT 11
+#endif
+
+ #if defined(CONFIG_H83002) || defined(CONFIG_H8048)
+/* Fix me!! */
+#include <asm/regs306x.h>
+static volatile unsigned char *ddrs[] = {
+ _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
+ NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
+};
+#define MAX_PORT 11
+#endif
+
+#if defined(CONFIG_H8S2678)
+#include <asm/regs267x.h>
+static volatile unsigned char *ddrs[] = {
+ _(P1DDR),_(P2DDR),_(P3DDR),NULL ,_(P5DDR),_(P6DDR),
+ _(P7DDR),_(P8DDR),NULL, _(PADDR),_(PBDDR),_(PCDDR),
+ _(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR),
+ _(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR),
+ _(PGDDR),_(PHDDR)
+};
+#define MAX_PORT 17
+#endif
+#undef _
+
+#if !defined(P1DDR)
+#error Unsuppoted CPU Selection
+#endif
+
+static struct {
+ unsigned char used;
+ unsigned char ddr;
+} gpio_regs[MAX_PORT];
+
+extern char *_platform_gpio_table(int length);
+
+int h8300_reserved_gpio(int port, unsigned int bits)
+{
+ unsigned char *used;
+
+ if (port < 0 || port >= MAX_PORT)
+ return -1;
+ used = &(gpio_regs[port].used);
+ if ((*used & bits) != 0)
+ return 0;
+ *used |= bits;
+ return 1;
+}
+
+int h8300_free_gpio(int port, unsigned int bits)
+{
+ unsigned char *used;
+
+ if (port < 0 || port >= MAX_PORT)
+ return -1;
+ used = &(gpio_regs[port].used);
+ if ((*used & bits) != bits)
+ return 0;
+ *used &= (~bits);
+ return 1;
+}
+
+int h8300_set_gpio_dir(int port_bit,int dir)
+{
+ int port = (port_bit >> 8) & 0xff;
+ int bit = port_bit & 0xff;
+
+ if (ddrs[port] == NULL)
+ return 0;
+ if (gpio_regs[port].used & bit) {
+ if (dir)
+ gpio_regs[port].ddr |= bit;
+ else
+ gpio_regs[port].ddr &= ~bit;
+ *ddrs[port] = gpio_regs[port].ddr;
+ return 1;
+ } else
+ return 0;
+}
+
+int h8300_get_gpio_dir(int port_bit)
+{
+ int port = (port_bit >> 8) & 0xff;
+ int bit = port_bit & 0xff;
+
+ if (ddrs[port] == NULL)
+ return 0;
+ if (gpio_regs[port].used & bit) {
+ return (gpio_regs[port].ddr & bit) != 0;
+ } else
+ return -1;
+}
+
+#if defined(CONFIG_PROC_FS)
+static char *port_status(int portno)
+{
+ static char result[10];
+ const static char io[2]={'I','O'};
+ char *rp;
+ int c;
+ unsigned char used,ddr;
+
+ used = gpio_regs[portno].used;
+ ddr = gpio_regs[portno].ddr;
+ result[8]='\0';
+ rp = result + 7;
+ for (c = 8; c > 0; c--,rp--,used >>= 1, ddr >>= 1)
+ if (used & 0x01)
+ *rp = io[ ddr & 0x01];
+ else
+ *rp = '-';
+ return result;
+}
+
+static int gpio_proc_read(char *buf, char **start, off_t offset,
+ int len, int *unused_i, void *unused_v)
+{
+ int c,outlen;
+ const static char port_name[]="123456789ABCDEFGH";
+ outlen = 0;
+ for (c = 0; c < MAX_PORT; c++) {
+ if (ddrs[c] == NULL)
+ continue ;
+ len = sprintf(buf,"P%c: %s\n",port_name[c],port_status(c));
+ buf += len;
+ outlen += len;
+ }
+ return outlen;
+}
+
+static __init int register_proc(void)
+{
+ struct proc_dir_entry *proc_gpio;
+
+ proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
+ if (proc_gpio)
+ proc_gpio->read_proc = gpio_proc_read;
+ return proc_gpio != NULL;
+}
+
+__initcall(register_proc);
+#endif
+
+void __init h8300_gpio_init(void)
+{
+ memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs));
+}
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
new file mode 100644
index 000000000000..5a630233112f
--- /dev/null
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -0,0 +1,112 @@
+#include <linux/module.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+
+#include <asm/setup.h>
+#include <asm/pgalloc.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/checksum.h>
+#include <asm/current.h>
+#include <asm/gpio.h>
+
+//asmlinkage long long __ashrdi3 (long long, int);
+//asmlinkage long long __lshrdi3 (long long, int);
+extern char h8300_debug_device[];
+
+extern void dump_thread(struct pt_regs *, struct user *);
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+
+EXPORT_SYMBOL(ip_fast_csum);
+
+EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/* The following are special because they're not called
+ explicitly (the C compiler generates them). Fortunately,
+ their interface isn't gonna change any time soon now, so
+ it's OK to leave it out of version control. */
+//EXPORT_SYMBOL(__ashrdi3);
+//EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memmove);
+
+EXPORT_SYMBOL(get_wchan);
+
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler... (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __gcc_bcmp(void);
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __cmpdi2(void);
+extern void __divdi3(void);
+extern void __divsi3(void);
+extern void __lshrdi3(void);
+extern void __moddi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __mulsi3(void);
+extern void __negdi2(void);
+extern void __ucmpdi2(void);
+extern void __udivdi3(void);
+extern void __udivmoddi4(void);
+extern void __udivsi3(void);
+extern void __umoddi3(void);
+extern void __umodsi3(void);
+
+ /* gcc lib functions */
+EXPORT_SYMBOL(__gcc_bcmp);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__cmpdi2);
+EXPORT_SYMBOL(__divdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__moddi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__negdi2);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__umodsi3);
+
+#ifdef MAGIC_ROM_PTR
+EXPORT_SYMBOL(is_in_rom);
+#endif
+
+EXPORT_SYMBOL(h8300_reserved_gpio);
+EXPORT_SYMBOL(h8300_free_gpio);
+EXPORT_SYMBOL(h8300_set_gpio_dir);
diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c
new file mode 100644
index 000000000000..19272c2ac56a
--- /dev/null
+++ b/arch/h8300/kernel/init_task.c
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/h8300/kernel/init_task.c
+ */
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+__asm__(".align 4");
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
new file mode 100644
index 000000000000..edb3c4170013
--- /dev/null
+++ b/arch/h8300/kernel/ints.c
@@ -0,0 +1,255 @@
+/*
+ * linux/arch/h8300/platform/h8300h/ints.c
+ *
+ * Yoshinori Sato <ysato@users.sourceforge.jp>
+ *
+ * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c
+ *
+ * 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
+ * for more details.
+ *
+ * Copyright 1996 Roman Zippel
+ * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/bootmem.h>
+#include <linux/hardirq.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/errno.h>
+
+/*
+ * This structure has only 4 elements for speed reasons
+ */
+typedef struct irq_handler {
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ int flags;
+ int count;
+ void *dev_id;
+ const char *devname;
+} irq_handler_t;
+
+static irq_handler_t *irq_list[NR_IRQS];
+static int use_kmalloc;
+
+extern unsigned long *interrupt_redirect_table;
+extern const int h8300_saved_vectors[];
+extern const unsigned long h8300_trap_table[];
+int h8300_enable_irq_pin(unsigned int irq);
+void h8300_disable_irq_pin(unsigned int irq);
+
+#define CPU_VECTOR ((unsigned long *)0x000000)
+#define ADDR_MASK (0xffffff)
+
+#if defined(CONFIG_RAMKERNEL)
+static unsigned long __init *get_vector_address(void)
+{
+ unsigned long *rom_vector = CPU_VECTOR;
+ unsigned long base,tmp;
+ int vec_no;
+
+ base = rom_vector[EXT_IRQ0] & ADDR_MASK;
+
+ /* check romvector format */
+ for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
+ if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
+ return NULL;
+ }
+
+ /* ramvector base address */
+ base -= EXT_IRQ0*4;
+
+ /* writerble check */
+ tmp = ~(*(volatile unsigned long *)base);
+ (*(volatile unsigned long *)base) = tmp;
+ if ((*(volatile unsigned long *)base) != tmp)
+ return NULL;
+ return (unsigned long *)base;
+}
+#endif
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_RAMKERNEL)
+ int i;
+ unsigned long *ramvec,*ramvec_p;
+ const unsigned long *trap_entry;
+ const int *saved_vector;
+
+ ramvec = get_vector_address();
+ if (ramvec == NULL)
+ panic("interrupt vector serup failed.");
+ else
+ printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
+
+ /* create redirect table */
+ ramvec_p = ramvec;
+ trap_entry = h8300_trap_table;
+ saved_vector = h8300_saved_vectors;
+ for ( i = 0; i < NR_IRQS; i++) {
+ if (i == *saved_vector) {
+ ramvec_p++;
+ saved_vector++;
+ } else {
+ if ( i < NR_TRAPS ) {
+ if (*trap_entry)
+ *ramvec_p = VECTOR(*trap_entry);
+ ramvec_p++;
+ trap_entry++;
+ } else
+ *ramvec_p++ = REDIRECT(interrupt_entry);
+ }
+ }
+ interrupt_redirect_table = ramvec;
+#ifdef DUMP_VECTOR
+ ramvec_p = ramvec;
+ for (i = 0; i < NR_IRQS; i++) {
+ if ((i % 8) == 0)
+ printk(KERN_DEBUG "\n%p: ",ramvec_p);
+ printk(KERN_DEBUG "%p ",*ramvec_p);
+ ramvec_p++;
+ }
+ printk(KERN_DEBUG "\n");
+#endif
+#endif
+}
+
+int request_irq(unsigned int irq,
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ irq_handler_t *irq_handle;
+ if (irq < 0 || irq >= NR_IRQS) {
+ printk(KERN_ERR "Incorrect IRQ %d from %s\n", irq, devname);
+ return -EINVAL;
+ }
+
+ if (irq_list[irq] || (h8300_enable_irq_pin(irq) == -EBUSY))
+ return -EBUSY;
+
+ if (use_kmalloc)
+ irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
+ else {
+ /* use bootmem allocater */
+ irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
+ irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000);
+ }
+
+ if (irq_handle == NULL)
+ return -ENOMEM;
+
+ irq_handle->handler = handler;
+ irq_handle->flags = flags;
+ irq_handle->count = 0;
+ irq_handle->dev_id = dev_id;
+ irq_handle->devname = devname;
+ irq_list[irq] = irq_handle;
+
+ if (irq_handle->flags & SA_SAMPLE_RANDOM)
+ rand_initialize_irq(irq);
+
+ enable_irq(irq);
+ return 0;
+}
+
+EXPORT_SYMBOL(request_irq);
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq >= NR_IRQS)
+ return;
+
+ if (!irq_list[irq] || irq_list[irq]->dev_id != dev_id)
+ printk(KERN_WARNING "Removing probably wrong IRQ %d from %s\n",
+ irq, irq_list[irq]->devname);
+ disable_irq(irq);
+ h8300_disable_irq_pin(irq);
+ if (((unsigned long)irq_list[irq] & 0x80000000) == 0) {
+ kfree(irq_list[irq]);
+ irq_list[irq] = NULL;
+ }
+}
+
+EXPORT_SYMBOL(free_irq);
+
+/*
+ * Do we need these probe functions on the m68k?
+ */
+unsigned long probe_irq_on (void)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(probe_irq_on);
+
+int probe_irq_off (unsigned long irqs)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(probe_irq_off);
+
+void enable_irq(unsigned int irq)
+{
+ if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
+ IER_REGS |= 1 << (irq - EXT_IRQ0);
+}
+
+void disable_irq(unsigned int irq)
+{
+ if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
+ IER_REGS &= ~(1 << (irq - EXT_IRQ0));
+}
+
+asmlinkage void process_int(int irq, struct pt_regs *fp)
+{
+ irq_enter();
+ h8300_clear_isr(irq);
+ if (irq >= NR_TRAPS && irq < NR_IRQS) {
+ if (irq_list[irq]) {
+ irq_list[irq]->handler(irq, irq_list[irq]->dev_id, fp);
+ irq_list[irq]->count++;
+ if (irq_list[irq]->flags & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(irq);
+ }
+ } else {
+ BUG();
+ }
+ irq_exit();
+}
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v;
+
+ if ((i < NR_IRQS) && (irq_list[i]!=NULL)) {
+ seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
+ seq_printf(p, "%s\n", irq_list[i]->devname);
+ }
+
+ return 0;
+}
+
+void init_irq_proc(void)
+{
+}
+
+static int __init enable_kmalloc(void)
+{
+ use_kmalloc = 1;
+ return 0;
+}
+core_initcall(enable_kmalloc);
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
new file mode 100644
index 000000000000..4fd7138a6e03
--- /dev/null
+++ b/arch/h8300/kernel/module.c
@@ -0,0 +1,122 @@
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ printk(KERN_ERR "module %s: RELOCATION unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
+ /* This is where to make the change */
+ uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rela[i].r_offset);
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rela[i].r_info);
+ uint32_t v = sym->st_value + rela[i].r_addend;
+
+ switch (ELF32_R_TYPE(rela[i].r_info)) {
+ case R_H8_DIR24R8:
+ loc = (uint32_t *)((uint32_t)loc - 1);
+ *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
+ break;
+ case R_H8_DIR24A8:
+ if (ELF32_R_SYM(rela[i].r_info))
+ *loc += v;
+ break;
+ case R_H8_DIR32:
+ case R_H8_DIR32A16:
+ *loc += v;
+ break;
+ case R_H8_PCREL16:
+ v -= (unsigned long)loc + 2;
+ if ((Elf32_Sword)v > 0x7fff ||
+ (Elf32_Sword)v < -(Elf32_Sword)0x8000)
+ goto overflow;
+ else
+ *(unsigned short *)loc = v;
+ break;
+ case R_H8_PCREL8:
+ v -= (unsigned long)loc + 1;
+ if ((Elf32_Sword)v > 0x7f ||
+ (Elf32_Sword)v < -(Elf32_Sword)0x80)
+ goto overflow;
+ else
+ *(unsigned char *)loc = v;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rela[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+ overflow:
+ printk(KERN_ERR "module %s: relocation offset overflow: %08x\n",
+ me->name, rela[i].r_offset);
+ return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
new file mode 100644
index 000000000000..134aec1c6d19
--- /dev/null
+++ b/arch/h8300/kernel/process.c
@@ -0,0 +1,288 @@
+/*
+ * linux/arch/h8300/kernel/process.c
+ *
+ * Yoshinori Sato <ysato@users.sourceforge.jp>
+ *
+ * Based on:
+ *
+ * linux/arch/m68knommu/kernel/process.c
+ *
+ * Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
+ * Kenneth Albanowski <kjahds@kjahds.com>,
+ * The Silver Hammer Group, Ltd.
+ *
+ * linux/arch/m68k/kernel/process.c
+ *
+ * Copyright (C) 1995 Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+
+asmlinkage void ret_from_fork(void);
+
+/*
+ * The idle loop on an H8/300..
+ */
+#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
+void default_idle(void)
+{
+ while(1) {
+ if (need_resched()) {
+ local_irq_enable();
+ __asm__("sleep");
+ local_irq_disable();
+ }
+ schedule();
+ }
+}
+#else
+void default_idle(void)
+{
+ while(1) {
+ if (need_resched())
+ schedule();
+ }
+}
+#endif
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+ idle();
+}
+
+void machine_restart(char * __unused)
+{
+ local_irq_disable();
+ __asm__("jmp @@0");
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_halt(void)
+{
+ local_irq_disable();
+ __asm__("sleep");
+ for (;;);
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void machine_power_off(void)
+{
+ local_irq_disable();
+ __asm__("sleep");
+ for (;;);
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+void show_regs(struct pt_regs * regs)
+{
+ printk("\nPC: %08lx Status: %02x",
+ regs->pc, regs->ccr);
+ printk("\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx",
+ regs->orig_er0, regs->er0, regs->er1);
+ printk("\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx",
+ regs->er2, regs->er3, regs->er4, regs->er5);
+ printk("\nER6' %08lx ",regs->er6);
+ if (user_mode(regs))
+ printk("USP: %08lx\n", rdusp());
+ else
+ printk("\n");
+}
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ long retval;
+ long clone_arg;
+ mm_segment_t fs;
+
+ fs = get_fs();
+ set_fs (KERNEL_DS);
+ clone_arg = flags | CLONE_VM;
+ __asm__("mov.l sp,er3\n\t"
+ "sub.l er2,er2\n\t"
+ "mov.l %2,er1\n\t"
+ "mov.l %1,er0\n\t"
+ "trapa #0\n\t"
+ "cmp.l sp,er3\n\t"
+ "beq 1f\n\t"
+ "mov.l %4,er0\n\t"
+ "mov.l %3,er1\n\t"
+ "jsr @er1\n\t"
+ "mov.l %5,er0\n\t"
+ "trapa #0\n"
+ "1:\n\t"
+ "mov.l er0,%0"
+ :"=r"(retval)
+ :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit)
+ :"er0","er1","er2","er3");
+ set_fs (fs);
+ return retval;
+}
+
+void flush_thread(void)
+{
+}
+
+/*
+ * "h8300_fork()".. By the time we get here, the
+ * non-volatile registers have also been saved on the
+ * stack. We do some ugly pointer stuff here.. (see
+ * also copy_thread)
+ */
+
+asmlinkage int h8300_fork(struct pt_regs *regs)
+{
+ return -EINVAL;
+}
+
+asmlinkage int h8300_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+}
+
+asmlinkage int h8300_clone(struct pt_regs *regs)
+{
+ unsigned long clone_flags;
+ unsigned long newsp;
+
+ /* syscall2 puts clone_flags in er1 and usp in er2 */
+ clone_flags = regs->er1;
+ newsp = regs->er2;
+ if (!newsp)
+ newsp = rdusp();
+ return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
+
+}
+
+int copy_thread(int nr, unsigned long clone_flags,
+ unsigned long usp, unsigned long topstk,
+ struct task_struct * p, struct pt_regs * regs)
+{
+ struct pt_regs * childregs;
+
+ childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
+
+ *childregs = *regs;
+ childregs->retpc = (unsigned long) ret_from_fork;
+ childregs->er0 = 0;
+
+ p->thread.usp = usp;
+ p->thread.ksp = (unsigned long)childregs;
+
+ return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+/* changed the size calculations - should hopefully work better. lbt */
+ dump->magic = CMAGIC;
+ dump->start_code = 0;
+ dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
+ dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+ dump->u_dsize = ((unsigned long) (current->mm->brk +
+ (PAGE_SIZE-1))) >> PAGE_SHIFT;
+ dump->u_dsize -= dump->u_tsize;
+ dump->u_ssize = 0;
+
+ dump->u_ar0 = (struct user_regs_struct *)(((int)(&dump->regs)) -((int)(dump)));
+ dump->regs.er0 = regs->er0;
+ dump->regs.er1 = regs->er1;
+ dump->regs.er2 = regs->er2;
+ dump->regs.er3 = regs->er3;
+ dump->regs.er4 = regs->er4;
+ dump->regs.er5 = regs->er5;
+ dump->regs.er6 = regs->er6;
+ dump->regs.orig_er0 = regs->orig_er0;
+ dump->regs.ccr = regs->ccr;
+ dump->regs.pc = regs->pc;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...)
+{
+ int error;
+ char * filename;
+ struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
+
+ lock_kernel();
+ filename = getname(name);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filena