URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [m68k/] [kernel/] [ints.c] - Rev 1765
Compare with Previous | Blame | View Log
/* * 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 COPYING 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, void *data) { unsigned long flags; isr_node_t *np; save_flags(flags); cli(); for (np = *listp; np; listp = &np->next, np = *listp) { if (np->isr == isr && np->data == data) { *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, void *data) { if (source & IRQ_MACHSPEC) return mach_remove_isr (source, isr, data); if (source < IRQ1 || source > IRQ7) { printk ("remove_isr: Incorrect IRQ source %ld\n", source); return 0; } delete_isr (&isr_list[source - 1], isr, data); 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; }