diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /arch/alpha/kernel/irq.c | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'arch/alpha/kernel/irq.c')
-rw-r--r-- | arch/alpha/kernel/irq.c | 725 |
1 files changed, 528 insertions, 197 deletions
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index a59077539..a769a37be 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -17,6 +17,8 @@ #include <linux/signal.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <linux/malloc.h> +#include <linux/random.h> #include <asm/system.h> #include <asm/io.h> @@ -24,178 +26,249 @@ #include <asm/bitops.h> #include <asm/dma.h> -static unsigned char cache_21 = 0xff; -static unsigned char cache_A1 = 0xff; +extern void timer_interrupt(struct pt_regs * regs); + +#if NR_IRQS > 64 +# error Unable to handle more than 64 irq levels. +#endif + +/* Reserved interrupts. These must NEVER be requested by any driver! + */ +#define IS_RESERVED_IRQ(irq) ((irq)==2) /* IRQ 2 used by hw cascade */ + +/* + * Shadow-copy of masked interrupts. + * The bits are used as follows: + * 0.. 7 first (E)ISA PIC (irq level 0..7) + * 8..15 second (E)ISA PIC (irq level 8..15) + * Systems with PCI interrupt lines managed by GRU (e.g., Alcor, XLT): + * 16..47 PCI interrupts 0..31 (int at GRU_INT_MASK) + * Mikasa: + * 16..31 PCI interrupts 0..15 (short at I/O port 536) + * Other systems (not Mikasa) with 16 PCI interrupt lines: + * 16..23 PCI interrupts 0.. 7 (char at I/O port 26) + * 24..31 PCI interrupts 8..15 (char at I/O port 27) + * Systems with 17 PCI interrupt lines (e.g., Cabriolet and eb164): + * 16..32 PCI interrupts 0..31 (int at I/O port 804) + */ +static unsigned long irq_mask = ~0UL; + + +/* + * Update the hardware with the irq mask passed in MASK. The function + * exploits the fact that it is known that only bit IRQ has changed. + */ +static void update_hw(unsigned long irq, unsigned long mask) +{ + switch (irq) { +#if NR_IRQS == 48 + default: + /* note inverted sense of mask bits: */ + *(unsigned int *)GRU_INT_MASK = ~(mask >> 16); mb(); + break; + +#elif NR_IRQS == 33 + default: + outl(mask >> 16, 0x804); + break; + +#elif defined(CONFIG_ALPHA_MIKASA) + default: + outw(~(mask >> 16), 0x536); /* note invert */ + break; + +#elif NR_IRQS == 32 + case 16 ... 23: + outb(mask >> 16, 0x26); + break; + + default: + outb(mask >> 24, 0x27); + break; +#endif + /* handle ISA irqs last---fast devices belong on PCI... */ + + case 0 ... 7: /* ISA PIC1 */ + outb(mask, 0x21); + break; + + case 8 ...15: /* ISA PIC2 */ + outb(mask >> 8, 0xA1); + break; + } +} + +static inline void mask_irq(unsigned long irq) +{ + irq_mask |= (1UL << irq); + update_hw(irq, irq_mask); +} + +static inline void unmask_irq(unsigned long irq) +{ + irq_mask &= ~(1UL << irq); + update_hw(irq, irq_mask); +} void disable_irq(unsigned int irq_nr) { unsigned long flags; - unsigned char mask; - mask = 1 << (irq_nr & 7); save_flags(flags); - if (irq_nr < 8) { - cli(); - cache_21 |= mask; - outb(cache_21,0x21); - restore_flags(flags); - return; - } cli(); - cache_A1 |= mask; - outb(cache_A1,0xA1); + mask_irq(irq_nr); restore_flags(flags); } void enable_irq(unsigned int irq_nr) { unsigned long flags; - unsigned char mask; - mask = ~(1 << (irq_nr & 7)); save_flags(flags); - if (irq_nr < 8) { - cli(); - cache_21 &= mask; - outb(cache_21,0x21); - restore_flags(flags); - return; - } cli(); - cache_A1 &= mask; - outb(cache_A1,0xA1); + unmask_irq(irq_nr); restore_flags(flags); } /* * Initial irq handlers. */ -struct irqaction { - void (*handler)(int, struct pt_regs *); - unsigned long flags; - unsigned long mask; - const char *name; -}; - -static struct irqaction irq_action[16] = { - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }, - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }, - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }, - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }, - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }, - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }, - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }, - { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL } -}; +static struct irqaction *irq_action[NR_IRQS]; int get_irq_list(char *buf) { int i, len = 0; - struct irqaction * action = irq_action; + struct irqaction * action; - for (i = 0 ; i < 16 ; i++, action++) { - if (!action->handler) + for (i = 0 ; i < NR_IRQS ; i++) { + action = irq_action[i]; + if (!action) continue; - len += sprintf(buf+len, "%2d: %8d %c %s\n", + len += sprintf(buf+len, "%2d: %8d %c %s", i, kstat.interrupts[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, "\n"); } return len; } static inline void ack_irq(int irq) { - /* ACK the interrupt making it the lowest priority */ - /* First the slave .. */ - if (irq > 7) { - outb(0xE0 | (irq - 8), 0xa0); - irq = 2; - } - /* .. then the master */ - outb(0xE0 | irq, 0x20); -} - -static inline void mask_irq(int irq) -{ - if (irq < 8) { - cache_21 |= 1 << irq; - outb(cache_21, 0x21); - } else { - cache_A1 |= 1 << (irq - 8); - outb(cache_A1, 0xA1); - } -} - -static inline void unmask_irq(unsigned long irq) -{ - if (irq < 8) { - cache_21 &= ~(1 << irq); - outb(cache_21, 0x21); - } else { - cache_A1 &= ~(1 << (irq - 8)); - outb(cache_A1, 0xA1); + if (irq < 16) { + /* ACK the interrupt making it the lowest priority */ + /* First the slave .. */ + if (irq > 7) { + outb(0xE0 | (irq - 8), 0xa0); + irq = 2; + } + /* .. then the master */ + outb(0xE0 | irq, 0x20); +#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) + /* on ALCOR/XLT, need to dismiss interrupt via GRU */ + *(int *)GRU_INT_CLEAR = 0x80000000; mb(); + *(int *)GRU_INT_CLEAR = 0x00000000; mb(); +#endif /* ALCOR || XLT */ } } -int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), - unsigned long irqflags, const char * devname) +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) { - struct irqaction * action; + int shared = 0; + struct irqaction * action, **p; unsigned long flags; - if (irq > 15) + if (irq >= NR_IRQS) + return -EINVAL; + if (IS_RESERVED_IRQ(irq)) return -EINVAL; - action = irq + irq_action; - if (action->handler) - return -EBUSY; if (!handler) return -EINVAL; - save_flags(flags); - cli(); + p = irq_action + irq; + action = *p; + if (action) { + /* Can't share interrupts unless both agree to */ + if (!(action->flags & irqflags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((action->flags ^ irqflags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &action->next; + action = *p; + } while (action); + shared = 1; + } + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), + GFP_KERNEL); + if (!action) + return -ENOMEM; + + if (irqflags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + action->handler = handler; action->flags = irqflags; action->mask = 0; action->name = devname; - if (irq < 8) { - if (irq) { - cache_21 &= ~(1<<irq); - outb(cache_21,0x21); - } - } else { - cache_21 &= ~(1<<2); - cache_A1 &= ~(1<<(irq-8)); - outb(cache_21,0x21); - outb(cache_A1,0xA1); - } + action->next = NULL; + action->dev_id = dev_id; + + save_flags(flags); + cli(); + *p = action; + + if (!shared) + unmask_irq(irq); + restore_flags(flags); return 0; } - -void free_irq(unsigned int irq) + +void free_irq(unsigned int irq, void *dev_id) { - struct irqaction * action = irq + irq_action; + struct irqaction * action, **p; unsigned long flags; - if (irq > 15) { - printk("Trying to free IRQ%d\n", irq); + if (irq >= NR_IRQS) { + printk("Trying to free IRQ%d\n",irq); return; } - if (!action->handler) { - printk("Trying to free free IRQ%d\n", irq); + if (IS_RESERVED_IRQ(irq)) { + printk("Trying to free reserved IRQ %d\n", irq); return; } - save_flags(flags); - cli(); - mask_irq(irq); - action->handler = NULL; - action->flags = 0; - action->mask = 0; - action->name = NULL; - restore_flags(flags); + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_flags(flags); + cli(); + *p = action->next; + if (!irq[irq_action]) + mask_irq(irq); + restore_flags(flags); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); } -static void handle_nmi(struct pt_regs * regs) +static inline void handle_nmi(struct pt_regs * regs) { printk("Whee.. NMI received. Probable hardware error\n"); printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461)); @@ -203,65 +276,285 @@ static void handle_nmi(struct pt_regs * regs) static void unexpected_irq(int irq, struct pt_regs * regs) { + struct irqaction *action; int i; printk("IO device interrupt, irq = %d\n", irq); printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps); printk("Expecting: "); for (i = 0; i < 16; i++) - if (irq_action[i].handler) - printk("[%s:%d] ", irq_action[i].name, i); + if ((action = irq_action[i])) + while (action->handler) { + printk("[%s:%d] ", action->name, i); + action = action->next; + } printk("\n"); +#if defined(CONFIG_ALPHA_JENSEN) printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n", inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa)); outb(0x0c, 0x3fc); outb(0x0c, 0x2fc); outb(0,0x61); outb(0,0x461); +#endif } static inline void handle_irq(int irq, struct pt_regs * regs) { - struct irqaction * action = irq + irq_action; + struct irqaction * action = irq_action[irq]; kstat.interrupts[irq]++; - if (!action->handler) { + if (!action) { unexpected_irq(irq, regs); return; } - action->handler(irq, regs); + do { + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); } -static void local_device_interrupt(unsigned long vector, struct pt_regs * regs) +static inline void device_interrupt(int irq, int ack, struct pt_regs * regs) { - switch (vector) { - /* com1: map to irq 4 */ - case 0x900: - handle_irq(4, regs); - return; + struct irqaction * action; - /* com2: map to irq 3 */ - case 0x920: - handle_irq(3, regs); - return; + if ((unsigned) irq > NR_IRQS) { + printk("device_interrupt: unexpected interrupt %d\n", irq); + return; + } - /* keyboard: map to irq 1 */ - case 0x980: - handle_irq(1, regs); - return; + kstat.interrupts[irq]++; + action = irq_action[irq]; + /* + * For normal interrupts, we mask it out, and then ACK it. + * This way another (more timing-critical) interrupt can + * come through while we're doing this one. + * + * Note! A irq without a handler gets masked and acked, but + * never unmasked. The autoirq stuff depends on this (it looks + * at the masks before and after doing the probing). + */ + mask_irq(ack); + ack_irq(ack); + if (!action) + return; + if (action->flags & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + do { + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + unmask_irq(ack); +} + +#ifdef CONFIG_PCI - /* mouse: map to irq 9 */ - case 0x990: - handle_irq(9, regs); +/* + * Handle ISA interrupt via the PICs. + */ +static inline void isa_device_interrupt(unsigned long vector, + struct pt_regs * regs) +{ +#if defined(CONFIG_ALPHA_APECS) +# define IACK_SC APECS_IACK_SC +#elif defined(CONFIG_ALPHA_LCA) +# define IACK_SC LCA_IACK_SC +#elif defined(CONFIG_ALPHA_CIA) +# define IACK_SC CIA_IACK_SC +#else + /* + * This is bogus but necessary to get it to compile + * on all platforms. If you try to use this on any + * other than the intended platforms, you'll notice + * real fast... + */ +# define IACK_SC 1L +#endif + int j; + +#if 1 + /* + * Generate a PCI interrupt acknowledge cycle. The PIC will + * respond with the interrupt vector of the highest priority + * interrupt that is pending. The PALcode sets up the + * interrupts vectors such that irq level L generates vector + * L. + */ + j = *(volatile int *) IACK_SC; + j &= 0xff; + if (j == 7) { + if (!(inb(0x20) & 0x80)) { + /* it's only a passive release... */ return; - default: - printk("Unknown local interrupt %lx\n", vector); + } + } + device_interrupt(j, j, regs); +#else + unsigned long pic; + + /* + * It seems to me that the probability of two or more *device* + * interrupts occurring at almost exactly the same time is + * pretty low. So why pay the price of checking for + * additional interrupts here if the common case can be + * handled so much easier? + */ + /* + * The first read of gives you *all* interrupting lines. + * Therefore, read the mask register and and out those lines + * not enabled. Note that some documentation has 21 and a1 + * write only. This is not true. + */ + pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */ + pic &= ~irq_mask; /* apply mask */ + pic &= 0xFFFB; /* mask out cascade & hibits */ + + while (pic) { + j = ffz(~pic); + pic &= pic - 1; + device_interrupt(j, j, regs); + } +#endif +} + +#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) +/* we have to conditionally compile this because of GRU_xxx symbols */ +static inline void alcor_and_xlt_device_interrupt(unsigned long vector, + struct pt_regs * regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_flags(flags); + cli(); + + /* read the interrupt summary register of the GRU */ + pld = (*(unsigned int *)GRU_INT_REQ) & GRU_INT_REQ_BITS; + +#if 0 + printk("[0x%08lx/0x%04x]", pld, inb(0x20) | (inb(0xA0) << 8)); +#endif + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 31) { + isa_device_interrupt(vector, regs); + } else { + device_interrupt(16 + i, 16 + i, regs); + } + } + restore_flags(flags); +} +#endif /* ALCOR || XLT */ + +static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector, + struct pt_regs * regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_flags(flags); + cli(); + + /* read the interrupt summary registers */ + pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16); + +#if 0 + printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8)); +#endif + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 4) { + isa_device_interrupt(vector, regs); + } else { + device_interrupt(16 + i, 16 + i, regs); + } + } + restore_flags(flags); +} + +static inline void mikasa_device_interrupt(unsigned long vector, + struct pt_regs * regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_flags(flags); + cli(); + + /* read the interrupt summary registers */ + pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) | + (((unsigned long) inb(0xa0)) << 8) | + ((unsigned long) inb(0x20)); + +#if 0 + printk("[0x%08lx]", pld); +#endif + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i < 16) { + isa_device_interrupt(vector, regs); + } else { + device_interrupt(i, i, regs); + } + } + restore_flags(flags); +} + +static inline void eb66_and_eb64p_device_interrupt(unsigned long vector, + struct pt_regs * regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_flags(flags); + cli(); + + /* read the interrupt summary registers */ + pld = inb(0x26) | (inb(0x27) << 8); + /* + * Now, for every possible bit set, work through + * them and call the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + + if (i == 5) { + isa_device_interrupt(vector, regs); + } else { + device_interrupt(16 + i, 16 + i, regs); + } } + restore_flags(flags); } +#endif /* CONFIG_PCI */ + /* - * The vector is 0x8X0 for EISA interrupt X, and 0x9X0 for the local - * motherboard interrupts.. This is for the Jensen. + * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and + * 0x9X0 for the local motherboard interrupts.. * * 0x660 - NMI * @@ -275,80 +568,73 @@ static void local_device_interrupt(unsigned long vector, struct pt_regs * regs) * 0x980 - keyboard * 0x990 - mouse * - * The PCI version is more sane: it doesn't have the local interrupts at - * all, and has only normal PCI interrupts from devices. Happily it's easy - * enough to do a sane mapping from the Jensen.. Note that this means - * that we may have to do a hardware "ack" to a different interrupt than - * we report to the rest of the world.. + * PCI-based systems are more sane: they don't have the local + * interrupts at all, and have only normal PCI interrupts from + * devices. Happily it's easy enough to do a sane mapping from the + * Jensen.. Note that this means that we may have to do a hardware + * "ack" to a different interrupt than we report to the rest of the + * world. */ -static void device_interrupt(unsigned long vector, struct pt_regs * regs) +static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs) { int irq, ack; - struct irqaction * action; + unsigned long flags; + + save_flags(flags); + cli(); - if (vector == 0x660) { - handle_nmi(regs); - return; - } ack = irq = (vector - 0x800) >> 4; -#ifndef CONFIG_PCI - if (vector >= 0x900) { - local_device_interrupt(vector, regs); - return; + +#ifdef CONFIG_ALPHA_JENSEN + switch (vector) { + case 0x660: handle_nmi(regs); return; + /* local device interrupts: */ + case 0x900: handle_irq(4, regs); return; /* com1 -> irq 4 */ + case 0x920: handle_irq(3, regs); return; /* com2 -> irq 3 */ + case 0x980: handle_irq(1, regs); return; /* kbd -> irq 1 */ + case 0x990: handle_irq(9, regs); return; /* mouse -> irq 9 */ + default: + if (vector > 0x900) { + printk("Unknown local interrupt %lx\n", vector); + } } - /* irq1 is supposed to be the keyboard, silly Jensen */ + /* irq1 is supposed to be the keyboard, silly Jensen (is this really needed??) */ if (irq == 1) irq = 7; -#endif - kstat.interrupts[irq]++; - action = irq_action + irq; - /* quick interrupts get executed with no extra overhead */ - if (action->flags & SA_INTERRUPT) { - action->handler(irq, regs); - ack_irq(ack); - return; - } - /* - * For normal interrupts, we mask it out, and then ACK it. - * This way another (more timing-critical) interrupt can - * come through while we're doing this one. - * - * Note! A irq without a handler gets masked and acked, but - * never unmasked. The autoirq stuff depends on this (it looks - * at the masks before and after doing the probing). - */ - mask_irq(ack); - ack_irq(ack); - if (!action->handler) - return; - action->handler(irq, regs); - unmask_irq(ack); +#endif /* CONFIG_ALPHA_JENSEN */ + + device_interrupt(irq, ack, regs); + + restore_flags(flags) ; } /* * Start listening for interrupts.. */ -unsigned int probe_irq_on(void) +unsigned long probe_irq_on(void) { - unsigned int i, irqs = 0, irqmask; + struct irqaction * action; + unsigned long irqs = 0; unsigned long delay; + unsigned int i; - for (i = 15; i > 0; i--) { - if (!irq_action[i].handler) { + for (i = NR_IRQS - 1; i > 0; i--) { + action = irq_action[i]; + if (!action) { enable_irq(i); irqs |= (1 << i); } } - - /* wait for spurious interrupts to mask themselves out again */ + /* + * Wait about 100ms for spurious interrupts to mask themselves + * out again... + */ for (delay = jiffies + HZ/10; delay > jiffies; ) - /* about 100 ms delay */; - + barrier(); + /* now filter out any obviously spurious interrupts */ - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int) cache_21; - irqs &= ~irqmask; - return irqs; + return irqs & ~irq_mask; } /* @@ -356,23 +642,39 @@ unsigned int probe_irq_on(void) * we have several candidates (but we return the lowest-numbered * one). */ -int probe_irq_off(unsigned int irqs) +int probe_irq_off(unsigned long irqs) { - unsigned int i, irqmask; + int i; - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; - irqs &= irqmask; + irqs &= irq_mask & ~1; /* always mask out irq 0---it's the unused timer */ +#ifdef CONFIG_ALPHA_P2K + irqs &= ~(1 << 8); /* mask out irq 8 since that's the unused RTC input to PIC */ +#endif if (!irqs) return 0; i = ffz(~irqs); - if (irqs != (1 << i)) + if (irqs != (1UL << i)) i = -i; return i; } -static void machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) +static void machine_check(unsigned long vector, unsigned long la, struct pt_regs * regs) { +#if defined(CONFIG_ALPHA_LCA) + extern void lca_machine_check (unsigned long vector, unsigned long la, + struct pt_regs *regs); + lca_machine_check(vector, la, regs); +#elif defined(CONFIG_ALPHA_APECS) + extern void apecs_machine_check(unsigned long vector, unsigned long la, + struct pt_regs * regs); + apecs_machine_check(vector, la, regs); +#elif defined(CONFIG_ALPHA_CIA) + extern void cia_machine_check(unsigned long vector, unsigned long la, + struct pt_regs * regs); + cia_machine_check(vector, la, regs); +#else printk("Machine check\n"); +#endif } asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr, @@ -384,14 +686,26 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned lon printk("Interprocessor interrupt? You must be kidding\n"); break; case 1: - /* timer interrupt.. */ - handle_irq(0, ®s); + timer_interrupt(®s); return; case 2: machine_check(vector, la_ptr, ®s); - break; + return; case 3: - device_interrupt(vector, ®s); +#if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \ + defined(CONFIG_ALPHA_P2K) || defined(CONFIG_ALPHA_SRM) + srm_device_interrupt(vector, ®s); +#elif NR_IRQS == 48 + alcor_and_xlt_device_interrupt(vector, ®s); +#elif NR_IRQS == 33 + cabriolet_and_eb66p_device_interrupt(vector, ®s); +#elif defined(CONFIG_ALPHA_MIKASA) + mikasa_device_interrupt(vector, ®s); +#elif NR_IRQS == 32 + eb66_and_eb64p_device_interrupt(vector, ®s); +#elif NR_IRQS == 16 + isa_device_interrupt(vector, ®s); +#endif return; case 4: printk("Performance counter interrupt\n"); @@ -411,4 +725,21 @@ void init_IRQ(void) dma_outb(0, DMA2_RESET_REG); dma_outb(0, DMA1_CLR_MASK_REG); dma_outb(0, DMA2_CLR_MASK_REG); +#if NR_IRQS == 48 + *(unsigned int *)GRU_INT_MASK = ~(irq_mask >> 16); mb();/* invert */ + *(unsigned int *)GRU_INT_EDGE = 0UL; mb();/* all are level */ + *(unsigned int *)GRU_INT_HILO = 0x80000000UL; mb();/* ISA only HI */ + *(unsigned int *)GRU_INT_CLEAR = 0UL; mb();/* all clear */ + enable_irq(16 + 31); /* enable (E)ISA PIC cascade */ +#elif NR_IRQS == 33 + outl(irq_mask >> 16, 0x804); + enable_irq(16 + 4); /* enable SIO cascade */ +#elif defined(CONFIG_ALPHA_MIKASA) + outw(~(irq_mask >> 16), 0x536); /* note invert */ +#elif NR_IRQS == 32 + outb(irq_mask >> 16, 0x26); + outb(irq_mask >> 24, 0x27); + enable_irq(16 + 5); /* enable SIO cascade */ +#endif + enable_irq(2); /* enable cascade */ } |