summaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r--arch/m68k/kernel/Makefile4
-rw-r--r--arch/m68k/kernel/dma.c129
-rw-r--r--arch/m68k/kernel/entry.S104
-rw-r--r--arch/m68k/kernel/ints.c382
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c2
-rw-r--r--arch/m68k/kernel/setup.c3
-rw-r--r--arch/m68k/kernel/signal.c2
-rw-r--r--arch/m68k/kernel/traps.c188
8 files changed, 523 insertions, 291 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 458925c471a..dae609797dc 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -9,8 +9,8 @@ else
endif
extra-y += vmlinux.lds
-obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \
- sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
+obj-y := entry.o process.o traps.o ints.o dma.o signal.o ptrace.o \
+ sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
obj-$(CONFIG_PCI) += bios32.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
new file mode 100644
index 00000000000..fc449f8b204
--- /dev/null
+++ b/arch/m68k/kernel/dma.c
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+
+#include <asm/pgalloc.h>
+#include <asm/scatterlist.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *handle, int flag)
+{
+ struct page *page, **map;
+ pgprot_t pgprot;
+ void *addr;
+ int i, order;
+
+ pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+ page = alloc_pages(flag, order);
+ if (!page)
+ return NULL;
+
+ *handle = page_to_phys(page);
+ map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
+ if (!map) {
+ __free_pages(page, order);
+ return NULL;
+ }
+ split_page(page, order);
+
+ order = 1 << order;
+ size >>= PAGE_SHIFT;
+ map[0] = page;
+ for (i = 1; i < size; i++)
+ map[i] = page + i;
+ for (; i < order; i++)
+ __free_page(page + i);
+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+ if (CPU_IS_040_OR_060)
+ pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
+ else
+ pgprot_val(pgprot) |= _PAGE_NOCACHE030;
+ addr = vmap(map, size, flag, pgprot);
+ kfree(map);
+
+ return addr;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size,
+ void *addr, dma_addr_t handle)
+{
+ pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
+ vfree(addr);
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ cache_push(handle, size);
+ break;
+ case DMA_FROM_DEVICE:
+ cache_clear(handle, size);
+ break;
+ default:
+ if (printk_ratelimit())
+ printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
+ break;
+ }
+}
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < nents; sg++, i++)
+ dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_addr_t handle = virt_to_bus(addr);
+
+ dma_sync_single_for_device(dev, handle, size, dir);
+ return handle;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_addr_t handle = page_to_phys(page) + offset;
+
+ dma_sync_single_for_device(dev, handle, size, dir);
+ return handle;
+}
+EXPORT_SYMBOL(dma_map_page);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < nents; sg++, i++) {
+ sg->dma_address = page_to_phys(sg->page) + sg->offset;
+ dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+ }
+ return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 320fde05dc6..449b62b30f4 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -45,9 +45,11 @@
#include <asm/asm-offsets.h>
.globl system_call, buserr, trap, resume
-.globl inthandler, sys_call_table
+.globl sys_call_table
.globl sys_fork, sys_clone, sys_vfork
.globl ret_from_interrupt, bad_interrupt
+.globl auto_irqhandler_fixup
+.globl user_irqvec_fixup, user_irqhandler_fixup
.text
ENTRY(buserr)
@@ -191,65 +193,29 @@ do_delayed_trace:
jbra resume_userspace
-#if 0
-#ifdef CONFIG_AMIGA
-ami_inthandler:
- addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT
- SAVE_ALL_INT
- GET_CURRENT(%d0)
+/* This is the main interrupt handler for autovector interrupts */
- bfextu %sp@(PT_VECTOR){#4,#12},%d0
- movel %d0,%a0
- addql #1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR))
- movel %a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0
-
-| amiga vector int handler get the req mask instead of irq vector
- lea CUSTOMBASE,%a1
- movew %a1@(C_INTREQR),%d0
- andw %a1@(C_INTENAR),%d0
-
-| prepare stack (push frame pointer, dev_id & req mask)
- pea %sp@
- movel %a0@(IRQ_DEVID),%sp@-
- movel %d0,%sp@-
- pea %pc@(ret_from_interrupt:w)
- jbra @(IRQ_HANDLER,%a0)@(0)
-
-ENTRY(nmi_handler)
- rte
-#endif
-#endif
-
-/*
-** This is the main interrupt handler, responsible for calling process_int()
-*/
-inthandler:
+ENTRY(auto_inthandler)
SAVE_ALL_INT
GET_CURRENT(%d0)
- addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
+ addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
| put exception # in d0
- bfextu %sp@(PT_VECTOR){#4,#10},%d0
+ bfextu %sp@(PT_VECTOR){#4,#10},%d0
+ subw #VEC_SPUR,%d0
movel %sp,%sp@-
movel %d0,%sp@- | put vector # on stack
-#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
- btstb #4,0xff000000 | Q40 floppy needs very special treatment ...
- jbeq 1f
- btstb #3,0xff000004
- jbeq 1f
- jbsr floppy_hardint
- jbra 3f
-1:
-#endif
- jbsr process_int | process the IRQ
-3: addql #8,%sp | pop parameters off stack
+auto_irqhandler_fixup = . + 2
+ jsr m68k_handle_int | process the IRQ
+ addql #8,%sp | pop parameters off stack
ret_from_interrupt:
- subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
- jeq 1f
-2:
- RESTORE_ALL
-1:
+ subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+ jeq ret_from_last_interrupt
+2: RESTORE_ALL
+
+ ALIGN
+ret_from_last_interrupt:
moveq #(~ALLOWINT>>8)&0xff,%d0
andb %sp@(PT_SR),%d0
jne 2b
@@ -260,12 +226,42 @@ ret_from_interrupt:
pea ret_from_exception
jra do_softirq
+/* Handler for user defined interrupt vectors */
+
+ENTRY(user_inthandler)
+ SAVE_ALL_INT
+ GET_CURRENT(%d0)
+ addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+ | put exception # in d0
+ bfextu %sp@(PT_VECTOR){#4,#10},%d0
+user_irqvec_fixup = . + 2
+ subw #VEC_USER,%d0
+
+ movel %sp,%sp@-
+ movel %d0,%sp@- | put vector # on stack
+user_irqhandler_fixup = . + 2
+ jsr m68k_handle_int | process the IRQ
+ addql #8,%sp | pop parameters off stack
+
+ subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+ jeq ret_from_last_interrupt
+ RESTORE_ALL
/* Handler for uninitialized and spurious interrupts */
-bad_interrupt:
- addql #1,num_spurious
- rte
+ENTRY(bad_inthandler)
+ SAVE_ALL_INT
+ GET_CURRENT(%d0)
+ addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+
+ movel %sp,%sp@-
+ jsr handle_badint
+ addql #4,%sp
+
+ subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+ jeq ret_from_last_interrupt
+ RESTORE_ALL
+
ENTRY(sys_fork)
SAVE_SWITCH_STACK
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 514d323ad53..5a8344b9354 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -39,47 +39,40 @@
#include <asm/traps.h>
#include <asm/page.h>
#include <asm/machdep.h>
+#include <asm/cacheflush.h>
#ifdef CONFIG_Q40
#include <asm/q40ints.h>
#endif
+extern u32 auto_irqhandler_fixup[];
+extern u32 user_irqhandler_fixup[];
+extern u16 user_irqvec_fixup[];
+
/* table for system interrupt handlers */
-static irq_handler_t irq_list[SYS_IRQS];
-
-static const char *default_names[SYS_IRQS] = {
- [0] = "spurious int",
- [1] = "int1 handler",
- [2] = "int2 handler",
- [3] = "int3 handler",
- [4] = "int4 handler",
- [5] = "int5 handler",
- [6] = "int6 handler",
- [7] = "int7 handler"
+static struct irq_node *irq_list[NR_IRQS];
+static struct irq_controller *irq_controller[NR_IRQS];
+static int irq_depth[NR_IRQS];
+
+static int m68k_first_user_vec;
+
+static struct irq_controller auto_irq_controller = {
+ .name = "auto",
+ .lock = SPIN_LOCK_UNLOCKED,
+ .startup = m68k_irq_startup,
+ .shutdown = m68k_irq_shutdown,
};
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
+static struct irq_controller user_irq_controller = {
+ .name = "user",
+ .lock = SPIN_LOCK_UNLOCKED,
+ .startup = m68k_irq_startup,
+ .shutdown = m68k_irq_shutdown,
+};
#define NUM_IRQ_NODES 100
static irq_node_t nodes[NUM_IRQ_NODES];
-static void dummy_enable_irq(unsigned int irq);
-static void dummy_disable_irq(unsigned int irq);
-static int dummy_request_irq(unsigned int irq,
- irqreturn_t (*handler) (int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id);
-static void dummy_free_irq(unsigned int irq, void *dev_id);
-
-void (*enable_irq) (unsigned int) = dummy_enable_irq;
-void (*disable_irq) (unsigned int) = dummy_disable_irq;
-
-int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *),
- unsigned long, const char *, void *) = dummy_request_irq;
-void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
-
-void init_irq_proc(void);
-
/*
* void init_IRQ(void)
*
@@ -95,18 +88,76 @@ void __init init_IRQ(void)
{
int i;
- for (i = 0; i < SYS_IRQS; i++) {
- if (mach_default_handler)
- irq_list[i].handler = (*mach_default_handler)[i];
- irq_list[i].flags = 0;
- irq_list[i].dev_id = NULL;
- irq_list[i].devname = default_names[i];
+ /* assembly irq entry code relies on this... */
+ if (HARDIRQ_MASK != 0x00ff0000) {
+ extern void hardirq_mask_is_broken(void);
+ hardirq_mask_is_broken();
}
- for (i = 0; i < NUM_IRQ_NODES; i++)
- nodes[i].handler = NULL;
+ for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
+ irq_controller[i] = &auto_irq_controller;
+
+ mach_init_IRQ();
+}
+
+/**
+ * m68k_setup_auto_interrupt
+ * @handler: called from auto vector interrupts
+ *
+ * setup the handler to be called from auto vector interrupts instead of the
+ * standard m68k_handle_int(), it will be called with irq numbers in the range
+ * from IRQ_AUTO_1 - IRQ_AUTO_7.
+ */
+void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
+{
+ if (handler)
+ *auto_irqhandler_fixup = (u32)handler;
+ flush_icache();
+}
+
+/**
+ * m68k_setup_user_interrupt
+ * @vec: first user vector interrupt to handle
+ * @cnt: number of active user vector interrupts
+ * @handler: called from user vector interrupts
+ *
+ * setup user vector interrupts, this includes activating the specified range
+ * of interrupts, only then these interrupts can be requested (note: this is
+ * different from auto vector interrupts). An optional handler can be installed
+ * to be called instead of the default m68k_handle_int(), it will be called
+ * with irq numbers starting from IRQ_USER.
+ */
+void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
+ void (*handler)(unsigned int, struct pt_regs *))
+{
+ int i;
+
+ m68k_first_user_vec = vec;
+ for (i = 0; i < cnt; i++)
+ irq_controller[IRQ_USER + i] = &user_irq_controller;
+ *user_irqvec_fixup = vec - IRQ_USER;
+ if (handler)
+ *user_irqhandler_fixup = (u32)handler;
+ flush_icache();
+}
+
+/**
+ * m68k_setup_irq_controller
+ * @contr: irq controller which controls specified irq
+ * @irq: first irq to be managed by the controller
+ *
+ * Change the controller for the specified range of irq, which will be used to
+ * manage these irq. auto/user irq already have a default controller, which can
+ * be changed as well, but the controller probably should use m68k_irq_startup/
+ * m68k_irq_shutdown.
+ */
+void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
+ unsigned int cnt)
+{
+ int i;
- mach_init_IRQ ();
+ for (i = 0; i < cnt; i++)
+ irq_controller[irq + i] = contr;
}
irq_node_t *new_irq_node(void)
@@ -114,84 +165,183 @@ irq_node_t *new_irq_node(void)
irq_node_t *node;
short i;
- for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
- if (!node->handler)
+ for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
+ if (!node->handler) {
+ memset(node, 0, sizeof(*node));
return node;
+ }
+ }
printk ("new_irq_node: out of nodes\n");
return NULL;
}
-/*
- * We will keep these functions until I have convinced Linus to move
- * the declaration of them from include/linux/sched.h to
- * include/asm/irq.h.
- */
+int setup_irq(unsigned int irq, struct irq_node *node)
+{
+ struct irq_controller *contr;
+ struct irq_node **prev;
+ unsigned long flags;
+
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+ printk("%s: Incorrect IRQ %d from %s\n",
+ __FUNCTION__, irq, node->devname);
+ return -ENXIO;
+ }
+
+ spin_lock_irqsave(&contr->lock, flags);
+
+ prev = irq_list + irq;
+ if (*prev) {
+ /* Can't share interrupts unless both agree to */
+ if (!((*prev)->flags & node->flags & SA_SHIRQ)) {
+ spin_unlock_irqrestore(&contr->lock, flags);
+ return -EBUSY;
+ }
+ while (*prev)
+ prev = &(*prev)->next;
+ }
+
+ if (!irq_list[irq]) {
+ if (contr->startup)
+ contr->startup(irq);
+ else
+ contr->enable(irq);
+ }
+ node->next = NULL;
+ *prev = node;
+
+ spin_unlock_irqrestore(&contr->lock, flags);
+
+ return 0;
+}
+
int request_irq(unsigned int irq,
irqreturn_t (*handler) (int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
- return mach_request_irq(irq, handler, flags, devname, dev_id);
+ struct irq_node *node;
+ int res;
+
+ node = new_irq_node();
+ if (!node)
+ return -ENOMEM;
+
+ node->handler = handler;
+ node->flags = flags;
+ node->dev_id = dev_id;
+ node->devname = devname;
+
+ res = setup_irq(irq, node);
+ if (res)
+ node->handler = NULL;
+
+ return res;
}
EXPORT_SYMBOL(request_irq);
void free_irq(unsigned int irq, void *dev_id)
{
- mach_free_irq(irq, dev_id);
+ struct irq_controller *contr;
+ struct irq_node **p, *node;
+ unsigned long flags;
+
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+ printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ spin_lock_irqsave(&contr->lock, flags);
+
+ p = irq_list + irq;
+ while ((node = *p)) {
+ if (node->dev_id == dev_id)
+ break;
+ p = &node->next;
+ }
+
+ if (node) {
+ *p = node->next;
+ node->handler = NULL;
+ } else
+ printk("%s: Removing probably wrong IRQ %d\n",
+ __FUNCTION__, irq);
+
+ if (!irq_list[irq]) {
+ if (contr->shutdown)
+ contr->shutdown(irq);
+ else
+ contr->disable(irq);
+ }
+
+ spin_unlock_irqrestore(&contr->lock, flags);
}
EXPORT_SYMBOL(free_irq);
-int cpu_request_irq(unsigned int irq,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id)
+void enable_irq(unsigned int irq)
{
- if (irq < IRQ1 || irq > IRQ7) {
- printk("%s: Incorrect IRQ %d from %s\n",
- __FUNCTION__, irq, devname);
- return -ENXIO;
- }
+ struct irq_controller *contr;
+ unsigned long flags;
-#if 0
- if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
- if (irq_list[irq].flags & IRQ_FLG_LOCK) {
- printk("%s: IRQ %d from %s is not replaceable\n",
- __FUNCTION__, irq, irq_list[irq].devname);
- return -EBUSY;
- }
- if (!(flags & IRQ_FLG_REPLACE)) {
- printk("%s: %s can't replace IRQ %d from %s\n",
- __FUNCTION__, devname, irq, irq_list[irq].devname);
- return -EBUSY;
- }
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+ printk("%s: Incorrect IRQ %d\n",
+ __FUNCTION__, irq);
+ return;
}
-#endif
- irq_list[irq].handler = handler;
- irq_list[irq].flags = flags;
- irq_list[irq].dev_id = dev_id;
- irq_list[irq].devname = devname;
- return 0;
+ spin_lock_irqsave(&contr->lock, flags);
+ if (irq_depth[irq]) {
+ if (!--irq_depth[irq]) {
+ if (contr->enable)
+ contr->enable(irq);
+ }
+ } else
+ WARN_ON(1);
+ spin_unlock_irqrestore(&contr->lock, flags);
}
-void cpu_free_irq(unsigned int irq, void *dev_id)
+EXPORT_SYMBOL(enable_irq);
+
+void disable_irq(unsigned int irq)
{
- if (irq < IRQ1 || irq > IRQ7) {
- printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ struct irq_controller *contr;
+ unsigned long flags;
+
+ if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+ printk("%s: Incorrect IRQ %d\n",
+ __FUNCTION__, irq);
return;
}
- if (irq_list[irq].dev_id != dev_id)
- printk("%s: Removing probably wrong IRQ %d from %s\n",
- __FUNCTION__, irq, irq_list[irq].devname);
+ spin_lock_irqsave(&contr->lock, flags);
+ if (!irq_depth[irq]++) {
+ if (contr->disable)
+ contr->disable(irq);
+ }
+ spin_unlock_irqrestore(&contr->lock, flags);
+}
- irq_list[irq].handler = (*mach_default_handler)[irq];
- irq_list[irq].flags = 0;
- irq_list[irq].dev_id = NULL;
- irq_list[irq].devname = default_names[irq];
+EXPORT_SYMBOL(disable_irq);
+
+int m68k_irq_startup(unsigned int irq)
+{
+ if (irq <= IRQ_AUTO_7)
+ vectors[VEC_SPUR + irq] = auto_inthandler;
+ else
+ vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler;
+ return 0;
}
+void m68k_irq_shutdown(unsigned int irq)
+{
+ if (irq <= IRQ_AUTO_7)
+ vectors[VEC_SPUR + irq] = bad_inthandler;
+ else
+ vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
+}
+
+
/*
* Do we need these probe functions on the m68k?
*
@@ -219,58 +369,50 @@ int probe_irq_off (unsigned long irqs)
EXPORT_SYMBOL(probe_irq_off);
-static void dummy_enable_irq(unsigned int irq)
-{
- printk("calling uninitialized enable_irq()\n");
-}
-
-static void dummy_disable_irq(unsigned int irq)
+unsigned int irq_canonicalize(unsigned int irq)
{
- printk("calling uninitialized disable_irq()\n");
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40 && irq == 11)
+ irq = 10;
+#endif
+ return irq;
}
-static int dummy_request_irq(unsigned int irq,
- irqreturn_t (*handler) (int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id)
-{
- printk("calling uninitialized request_irq()\n");
- return 0;
-}
+EXPORT_SYMBOL(irq_canonicalize);
-static void dummy_free_irq(unsigned int irq, void *dev_id)
+asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs)
{
- printk("calling uninitialized disable_irq()\n");
+ struct irq_node *node;
+
+ kstat_cpu(0).irqs[irq]++;
+ node = irq_list[irq];
+ do {
+ node->handler(irq, node->dev_id, regs);
+ node = node->next;
+ } while (node);
}
-asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
+asmlinkage void handle_badint(struct pt_regs *regs)
{
- if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
- vec -= VEC_SPUR;
- kstat_cpu(0).irqs[vec]++;
- irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
- } else {
- if (mach_process_int)
- mach_process_int(vec, fp);
- else
- panic("Can't process interrupt vector %ld\n", vec);
- return;
- }
+ kstat_cpu(0).irqs[0]++;
+ printk("unexpected interrupt from %u\n", regs->vector);
}
int show_interrupts(struct seq_file *p, void *v)
{
+ struct irq_controller *contr;
+ struct irq_node *node;
int i = *(loff_t *) v;
/* autovector interrupts */
- if (i < SYS_IRQS) {
- if (mach_default_handler) {
- seq_printf(p, "auto %2d: %10u ", i,
- i ? kstat_cpu(0).irqs[i] : num_spurious);
- seq_puts(p, " ");
- seq_printf(p, "%s\n", irq_list[i].devname);
- }
- } else if (i == SYS_IRQS)
- mach_get_irq_list(p, v);
+ if (irq_list[i]) {
+ contr = irq_controller[i];
+ node = irq_list[i];
+ seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
+ while ((node = node->next))
+ seq_printf(p, ", %s", node->devname);
+ seq_puts(p, "\n");
+ }
return 0;
}
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 5b7952ea2ba..1f5e1b5aeda 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -57,8 +57,6 @@ EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
#ifdef CONFIG_VME
EXPORT_SYMBOL(vme_brdtype);
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 750d5b3c971..214a95f9f3a 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -68,11 +68,8 @@ char m68k_debug_device[6] = "";
void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void) __initdata = NULL;
-irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
void (*mach_get_model) (char *model);
int (*mach_get_hardware_list) (char *buffer);
-int (*mach_get_irq_list) (struct seq_file *, void *);
-irqreturn_t (*mach_process_int) (int, struct pt_regs *);
/* machine dependent timer functions */
unsigned long (*mach_gettimeoffset) (void);
int (*mach_hwclk) (int, struct rtc_time*);
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 866917bfa02..f9af893cd28 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -763,7 +763,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!on_sig_stack(usp))
+ if (!sas_ss_flags(usp))
usp = current->sas_ss_sp + current->sas_ss_size;
}
return (void __user *)((usp - frame_size) & -8UL);
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index cdf58fbb3e7..e86de7b061c 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -45,7 +45,6 @@
asmlinkage void system_call(void);
asmlinkage void buserr(void);
asmlinkage void trap(void);
-asmlinkage void inthandler(void);
asmlinkage void nmihandler(void);
#ifdef CONFIG_M68KFPU_EMU
asmlinkage void fpu_emu(void);
@@ -53,51 +52,7 @@ asmlinkage void fpu_emu(void);
e_vector vectors[256] = {
[VEC_BUSERR] = buserr,
- [VEC_ADDRERR] = trap,
- [VEC_ILLEGAL] = trap,
- [VEC_ZERODIV] = trap,
- [VEC_CHK] = trap,
- [VEC_TRAP] = trap,
- [VEC_PRIV] = trap,
- [VEC_TRACE] = trap,
- [VEC_LINE10] = trap,
- [VEC_LINE11] = trap,
- [VEC_RESV12] = trap,
- [VEC_COPROC] = trap,
- [VEC_FORMAT] = trap,
- [VEC_UNINT] = trap,
- [VEC_RESV16] = trap,
- [VEC_RESV17] = trap,
- [VEC_RESV18] = trap,
- [VEC_RESV19] = trap,
- [VEC_RESV20] = trap,
- [VEC_RESV21] = trap,
- [VEC_RESV22] = trap,
- [VEC_RESV23] = trap,
- [VEC_SPUR] = inthandler,
- [VEC_INT1] = inthandler,
- [VEC_INT2] = inthandler,
- [VEC_INT3] = inthandler,
- [VEC_INT4] = inthandler,
- [VEC_INT5] = inthandler,
- [VEC_INT6] = inthandler,
- [VEC_INT7] = inthandler,
[VEC_SYS] = system_call,
- [VEC_TRAP1] = trap,
- [VEC_TRAP2] = trap,
- [VEC_TRAP3] = trap,
- [VEC_TRAP4] = trap,
- [VEC_TRAP5] = trap,
- [VEC_TRAP6] = trap,
- [VEC_TRAP7] = trap,
- [VEC_TRAP8] = trap,
- [VEC_TRAP9] = trap,
- [VEC_TRAP10] = trap,
- [VEC_TRAP11] = trap,
- [VEC_TRAP12] = trap,
- [VEC_TRAP13] = trap,
- [VEC_TRAP14] = trap,
- [VEC_TRAP15] = trap,
};
/* nmi handler for the Amiga */
@@ -114,7 +69,7 @@ void __init base_trap_init(void)
if(MACH_IS_SUN3X) {
extern e_vector *sun3x_prom_vbr;
- __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr));
+ __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
}
/* setup the exception vector table */
@@ -132,12 +87,15 @@ void __init trap_init (void)
{
int i;
- for (i = 48; i < 64; i++)
+ for (i = VEC_SPUR; i <= VEC_INT7; i++)
+ vectors[i] = bad_inthandler;
+
+ for (i = 0; i < VEC_USER; i++)
if (!vectors[i])
vectors[i] = trap;
- for (i = 64; i < 256; i++)
- vectors[i] = inthandler;
+ for (i = VEC_USER; i < 256; i++)
+ vectors[i] = bad_inthandler;
#ifdef CONFIG_M68KFPU_EMU
if (FPU_IS_EMU)
@@ -927,71 +885,94 @@ void show_trace(unsigned long *stack)
void show_registers(struct pt_regs *regs)
{
struct frame *fp = (struct frame *)regs;
+ mm_segment_t old_fs = get_fs();
+ u16 c, *cp;
unsigned long addr;
int i;
+ print_modules();
+ printk("PC: [<%08lx>]",regs->pc);
+ print_symbol(" %s", regs->pc);
+ printk("\nSR: %04x SP: %p a2: %08lx\n",
+ regs->sr, regs, regs->a2);
+ printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
+ regs->d0, regs->d1, regs->d2, regs->d3);
+ printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
+ regs->d4, regs->d5, regs->a0, regs->a1);
+
+ printk("Process %s (pid: %d, task=%p)\n",
+ current->comm, current->pid, current);
addr = (unsigned long)&fp->un;
- printk("Frame format=%X ", fp->ptregs.format);
- switch (fp->ptregs.format) {
+ printk("Frame format=%X ", regs->format);
+ switch (regs->format) {
case 0x2:
- printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
- addr += sizeof(fp->un.fmt2);
- break;
+ printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
+ addr += sizeof(fp->un.fmt2);
+ break;
case 0x3:
- printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
- addr += sizeof(fp->un.fmt3);
- break;
+ printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
+ addr += sizeof(fp->un.fmt3);
+ break;
case 0x4:
- printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
- : "eff addr=%08lx pc=%08lx\n"),
- fp->un.fmt4.effaddr, fp->un.fmt4.pc);
- addr += sizeof(fp->un.fmt4);
- break;
+ printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
+ : "eff addr=%08lx pc=%08lx\n"),
+ fp->un.fmt4.effaddr, fp->un.fmt4.pc);
+ addr += sizeof(fp->un.fmt4);
+ break;
case 0x7:
- printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
- fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
- printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
- fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
- printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
- fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
- printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
- fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
- printk("push data: %08lx %08lx %08lx %08lx\n",
- fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
- fp->un.fmt7.pd3);
- addr += sizeof(fp->un.fmt7);
- break;
+ printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
+ fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
+ printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
+ fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
+ printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
+ fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
+ printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
+ fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
+ printk("push data: %08lx %08lx %08lx %08lx\n",
+ fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
+ fp->un.fmt7.pd3);
+ addr += sizeof(fp->un.fmt7);
+ break;
case 0x9:
- printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
- addr += sizeof(fp->un.fmt9);
- break;
+ printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
+ addr += sizeof(fp->un.fmt9);
+ break;
case 0xa:
- printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
- fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
- fp->un.fmta.daddr, fp->un.fmta.dobuf);
- addr += sizeof(fp->un.fmta);
- break;
+ printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+ fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
+ fp->un.fmta.daddr, fp->un.fmta.dobuf);
+ addr += sizeof(fp->un.fmta);
+ break;
case 0xb:
- printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
- fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
- fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
- printk("baddr=%08lx dibuf=%08lx ver=%x\n",
- fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
- addr += sizeof(fp->un.fmtb);
- break;
+ printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+ fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
+ fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
+ printk("baddr=%08lx dibuf=%08lx ver=%x\n",
+ fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
+ addr += sizeof(fp->un.fmtb);
+ break;
default:
- printk("\n");
+ printk("\n");
}
show_stack(NULL, (unsigned long *)addr);
- printk("Code: ");
- for (i = 0; i < 10; i++)
- printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
+ printk("Code:");
+ set_fs(KERNEL_DS);
+ cp = (u16 *)regs->pc;
+ for (i = -8; i < 16; i++) {
+ if (get_user(c, cp + i) && i >= 0) {
+ printk(" Bad PC value.");
+ break;
+ }
+ printk(i ? " %04x" : " <%04x>", c);
+ }
+ set_fs(old_fs);
printk ("\n");
}
void show_stack(struct task_struct *task, unsigned long *stack)
{
+ unsigned long *p;
unsigned long *endstack;
int i;
@@ -1004,12 +985,13 @@ void show_stack(struct task_struct *task, unsigned long *stack)
endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
printk("Stack from %08lx:", (unsigned long)stack);
+ p = stack;
for (i = 0; i < kstack_depth_to_print; i++) {
- if (stack + 1 > endstack)
+ if (p + 1 > endstack)
break;
if (i % 8 == 0)
printk("\n ");
- printk(" %08lx", *stack++);
+ printk(" %08lx", *p++);
}
printk("\n");
show_trace(stack);
@@ -1188,19 +1170,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
console_verbose();
printk("%s: %08x\n",str,nr);
- print_modules();
- printk("PC: [<%08lx>]",fp->pc);
- print_symbol(" %s\n", fp->pc);
- printk("\nSR: %04x SP: %p a2: %08lx\n",
- fp->sr, fp, fp->a2);
- printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
- fp->d0, fp->d1, fp->d2, fp->d3);
- printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
- fp->d4, fp->d5, fp->a0, fp->a1);
-
- printk("Process %s (pid: %d, stackpage=%08lx)\n",
- current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
- show_stack(NULL, (unsigned long *)fp);
+ show_registers(fp);
do_exit(SIGSEGV);
}