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
- Lines: 237
- Date:
Sun Mar 31 14:03:24 1996
- Orig file:
v1.3.93/linux/arch/m68k/kernel/ints.c
- Orig date:
Thu Jan 1 02:00:00 1970
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