patch-2.0.21-2.1.0 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: 340
- Date:
Wed Sep 25 10:47:39 1996
- Orig file:
lx2.0/v2.0.21/linux/arch/m68k/kernel/ints.c
- Orig date:
Mon May 20 07:54:26 1996
diff -u --recursive --new-file lx2.0/v2.0.21/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
@@ -1,5 +1,5 @@
/*
- * ints.c -- 680x0 Linux general interrupt handling code
+ * linux/arch/m68k/kernel/ints.c -- Linux/m68k 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
@@ -11,6 +11,18 @@
* remove_isr() to request_irq() and free_irq()
* respectively, so they are compliant with the other
* architectures. /Jes
+ * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
+ * Removed irq list support, if any machine needs an irq server
+ * it must implement this itself (as it's already done), instead
+ * only default handler are used with mach_default_handler.
+ * request_irq got some flags different from other architectures:
+ * - IRQ_FLG_REPLACE : Replace an existing handler (the default one
+ * can be replaced without this flag)
+ * - IRQ_FLG_LOCK : handler can't be replaced
+ * There are other machine depending flags, see there
+ * If you want to replace a default handler you should know what
+ * you're doing, since it might handle different other irq sources
+ * which must be served /Roman Zippel
*/
#include <linux/types.h>
@@ -24,14 +36,19 @@
#include <asm/page.h>
#include <asm/machdep.h>
-/* list is accessed 0-6 for IRQs 1-7 */
-static isr_node_t *isr_list[7];
+/* table for system interrupt handlers */
+static irq_handler_t irq_list[SYS_IRQS];
+
+static const char *default_names[SYS_IRQS] = {
+ "spurious int", "int1 handler", "int2 handler", "int3 handler",
+ "int4 handler", "int5 handler", "int6 handler", "int7 handler"
+};
/* The number of spurious interrupts */
-volatile unsigned long num_spurious;
-/*
-unsigned long interrupt_stack[PAGE_SIZE/sizeof(long)];
-*/
+volatile unsigned int num_spurious;
+
+#define NUM_IRQ_NODES 100
+static irq_node_t nodes[NUM_IRQ_NODES];
/*
* void init_IRQ(void)
@@ -46,147 +63,85 @@
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;
+ int i;
- 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;
+ for (i = 0; i < SYS_IRQS; i++) {
+ if (mach_default_handler)
+ irq_list[i].handler = (*mach_default_handler)[i];
+ irq_list[i].flags = IRQ_FLG_STD;
+ irq_list[i].dev_id = NULL;
+ irq_list[i].devname = default_names[i];
}
- }
- 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 (i = 0; i < NUM_IRQ_NODES; i++)
+ nodes[i].handler = NULL;
- for (np = nodes; np < &nodes[NUM_ISR_NODES]; np++)
- if (np->isr == NULL)
- return np;
-
- printk ("new_isr_node: out of nodes");
- return NULL;
+ mach_init_IRQ ();
}
-int add_isr (unsigned long source, isrfunc isr, int pri, void *data,
- char *name)
+irq_node_t *new_irq_node(void)
{
- isr_node_t *p;
-
- if (source & IRQ_MACHSPEC)
- {
- return mach_add_isr (source, isr, pri, data, name);
- }
+ irq_node_t *node;
+ short i;
- if (source < IRQ1 || source > IRQ7)
- panic ("add_isr: Incorrect IRQ source %ld from %s\n", source, name);
+ for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
+ if (!node->handler)
+ return node;
- 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;
+ printk ("new_irq_node: out of nodes\n");
+ return NULL;
}
-int remove_isr (unsigned long source, isrfunc isr, void *data)
+int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
{
- 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;
- }
+ if (irq & IRQ_MACHSPEC)
+ return mach_request_irq(IRQ_IDX(irq), handler, flags, devname, dev_id);
- delete_isr (&isr_list[source - 1], isr, data);
- return 1;
-}
+ if (irq < IRQ1 || irq > IRQ7) {
+ printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
-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;
- }
+ 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;
+ }
+ }
+ irq_list[irq].handler = handler;
+ irq_list[irq].flags = flags;
+ irq_list[irq].dev_id = dev_id;
+ irq_list[irq].devname = devname;
+ return 0;
}
-asmlinkage void process_int(int vec, struct pt_regs *regs)
+void free_irq(unsigned int irq, void *dev_id)
{
- 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);
+ if (irq & IRQ_MACHSPEC) {
+ mach_free_irq(IRQ_IDX(irq), dev_id);
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;
-}
+ if (irq < IRQ1 || irq > IRQ7) {
+ printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
-void free_irq(unsigned int irq, void *dev_id)
-{
+ if (irq_list[irq].dev_id != dev_id)
+ printk("%s: Removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, irq_list[irq].devname);
+
+ irq_list[irq].handler = (*mach_default_handler)[irq];
+ irq_list[irq].flags = IRQ_FLG_STD;
+ irq_list[irq].dev_id = NULL;
+ irq_list[irq].devname = default_names[irq];
}
/*
@@ -194,43 +149,58 @@
*/
unsigned long probe_irq_on (void)
{
- return 0;
+ return 0;
}
int probe_irq_off (unsigned long irqs)
{
- return 0;
+ return 0;
}
-void enable_irq(unsigned int irq_nr)
+void enable_irq(unsigned int irq)
{
- if ((irq_nr & IRQ_MACHSPEC) && mach_enable_irq)
- mach_enable_irq(irq_nr);
+ if ((irq & IRQ_MACHSPEC) && mach_enable_irq)
+ mach_enable_irq(IRQ_IDX(irq));
}
-void disable_irq(unsigned int irq_nr)
+void disable_irq(unsigned int irq)
{
- if ((irq_nr & IRQ_MACHSPEC) && mach_disable_irq)
- mach_disable_irq(irq_nr);
+ if ((irq & IRQ_MACHSPEC) && mach_disable_irq)
+ mach_disable_irq(IRQ_IDX(irq));
+}
+
+asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
+{
+ if (vec < VEC_INT1 || vec > VEC_INT7) {
+ if (mach_process_int)
+ mach_process_int(vec, fp);
+ else
+ panic("Can't process interrupt vector %ld\n", vec);
+ return;
+ }
+
+ vec -= VEC_SPUR;
+ kstat.interrupts[vec]++;
+ irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
}
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, " ");
+ int i, len = 0;
+
+ /* autovector interrupts */
+ if (mach_default_handler) {
+ for (i = 0; i < SYS_IRQS; i++) {
+ len += sprintf(buf+len, "auto %2d: %10u ", i,
+ i ? kstat.interrupts[i] : num_spurious);
+ if (irq_list[i].flags & IRQ_FLG_LOCK)
+ len += sprintf(buf+len, "L ");
+ else
+ len += sprintf(buf+len, " ");
+ len += sprintf(buf+len, "%s\n", irq_list[i].devname);
+ }
}
- }
- len = mach_get_irq_list(buf, len);
- return 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