patch-1.3.94 linux/arch/m68k/kernel/ints.c

Next file: linux/arch/m68k/kernel/ksyms.c
Previous file: linux/arch/m68k/kernel/head.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.93/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
@@ -0,0 +1,236 @@
+/*
+ * ints.c -- 680x0 Linux general interrupt handling code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * 07/03/96: Timer initialization, and thus mach_sched_init(),
+ *           removed from request_irq() and moved to init_time().
+ *           We should therefore consider renaming our add_isr() and
+ *           remove_isr() to request_irq() and free_irq()
+ *           respectively, so they are compliant with the other
+ *           architectures.                                     /Jes
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/page.h>
+#include <asm/machdep.h>
+
+/* list is accessed 0-6 for IRQs 1-7 */
+static isr_node_t *isr_list[7];
+
+/* The number of spurious interrupts */
+volatile unsigned long num_spurious;
+/*
+unsigned long interrupt_stack[PAGE_SIZE/sizeof(long)];
+*/
+
+/*
+ * void init_IRQ(void)
+ *
+ * Parameters:	None
+ *
+ * Returns:	Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the IRQ handling routines.
+ */
+
+void init_IRQ(void)
+{
+    /* Setup interrupt stack pointer */
+  /*
+    asm ("movec %0,%/isp"
+	 : : "r" (interrupt_stack + sizeof (interrupt_stack) / sizeof (long)));
+	 */
+    mach_init_INTS ();
+}
+
+void insert_isr (isr_node_t **listp, isr_node_t *node)
+{
+    unsigned long spl;
+    isr_node_t *cur;
+
+    save_flags(spl);
+    cli();
+
+    cur = *listp;
+
+    while (cur && cur->pri <= node->pri)
+    {
+	listp = &cur->next;
+	cur = cur->next;
+    }
+
+    node->next = cur;
+    *listp = node;
+
+    restore_flags(spl);
+}
+
+void delete_isr (isr_node_t **listp, isrfunc isr)
+{
+    unsigned long flags;
+    isr_node_t *np;
+
+    save_flags(flags);
+    cli();
+    for (np = *listp; np; listp = &np->next, np = *listp) {
+	if (np->isr == isr) {
+	    *listp = np->next;
+	    /* Mark it as free. */
+	    np->isr = NULL;
+	    restore_flags(flags);
+	    return;
+	}
+    }
+    restore_flags(flags);
+    printk ("delete_isr: isr %p not found on list!\n", isr);
+}
+
+#define NUM_ISR_NODES 100
+static isr_node_t nodes[NUM_ISR_NODES];
+
+isr_node_t *new_isr_node(void)
+{
+    isr_node_t *np;
+
+    for (np = nodes; np < &nodes[NUM_ISR_NODES]; np++)
+	if (np->isr == NULL)
+	    return np;
+
+    printk ("new_isr_node: out of nodes");
+    return NULL;
+}
+
+int add_isr (unsigned long source, isrfunc isr, int pri, void *data,
+	     char *name)
+{
+    isr_node_t *p;
+
+    if (source & IRQ_MACHSPEC)
+    {
+	return mach_add_isr (source, isr, pri, data, name);
+    }
+
+    if (source < IRQ1 || source > IRQ7)
+	panic ("add_isr: Incorrect IRQ source %ld from %s\n", source, name);
+
+    p = new_isr_node();
+    if (p == NULL)
+	return 0;
+    p->isr = isr;
+    p->pri = pri;
+    p->data = data;
+    p->name = name;
+    p->next = NULL;
+
+    insert_isr (&isr_list[source-1], p);
+
+    return 1;
+}
+
+int remove_isr (unsigned long source, isrfunc isr)
+{
+    if (source & IRQ_MACHSPEC)
+	return mach_remove_isr (source, isr);
+
+    if (source < IRQ1 || source > IRQ7) {
+	printk ("remove_isr: Incorrect IRQ source %ld\n", source);
+	return 0;
+    }
+
+    delete_isr (&isr_list[source - 1], isr);
+    return 1;
+}
+
+void call_isr_list(int irq, isr_node_t *p, struct pt_regs *fp)
+{
+    while (p) {
+	p->isr (irq, fp, p->data);
+	p = p->next;
+    }
+}
+
+asmlinkage void process_int(int vec, struct pt_regs *regs)
+{
+	int level;
+
+	if (vec >= VECOFF(VEC_INT1) && vec <= VECOFF(VEC_INT7))
+		level = (vec - VECOFF(VEC_SPUR)) >> 2;
+	else {
+		if (mach_process_int)
+			mach_process_int(vec, regs);
+		else
+			panic("Can't process interrupt vector 0x%03x\n", vec);
+		return;
+	}
+
+	kstat.interrupts[level]++;  	
+	call_isr_list (level, isr_list[level-1], regs);
+}
+
+int request_irq(unsigned int irq,
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long flags, const char * devname, void *dev_id)
+{
+	return -EINVAL;
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+}
+
+/*
+ * Do we need these probe functions on the m68k?
+ */
+unsigned long probe_irq_on (void)
+{
+  return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+  return 0;
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+	if ((irq_nr & IRQ_MACHSPEC) && mach_enable_irq)
+		mach_enable_irq(irq_nr);
+}
+
+void disable_irq(unsigned int irq_nr)
+{
+	if ((irq_nr & IRQ_MACHSPEC) && mach_disable_irq)
+		mach_disable_irq(irq_nr);
+}
+
+int get_irq_list(char *buf)
+{
+    int i, len = 0;
+    isr_node_t *p;
+    
+    /* autovector interrupts */
+    for (i = IRQ1; i <= IRQ7; ++i) {
+	if (!isr_list[i-1])
+	    continue;
+	len += sprintf(buf+len, "auto %2d: %8d ", i, kstat.interrupts[i]);
+	for (p = isr_list[i-1]; p; p = p->next) {
+	    len += sprintf(buf+len, "%s\n", p->name);
+	    if (p->next)
+		len += sprintf(buf+len, "                  ");
+	}
+    }
+
+    len = mach_get_irq_list(buf, len);
+    return len;
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this