patch-2.1.48 linux/arch/ppc/kernel/irq.c
Next file: linux/arch/ppc/kernel/ksyms.c
Previous file: linux/arch/ppc/kernel/head.S
Back to the patch index
Back to the overall index
- Lines: 930
- Date:
Thu Jul 31 13:09:17 1997
- Orig file:
v2.1.47/linux/arch/ppc/kernel/irq.c
- Orig date:
Mon Apr 14 16:28:06 1997
diff -u --recursive --new-file v2.1.47/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
@@ -1,9 +1,13 @@
/*
- * linux/arch/ppc/kernel/irq.c
+ * arch/ppc/kernel/irq.c
*
- * Copyright (C) 1992 Linus Torvalds
- * Adapted from arch/i386 by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Power Macintosh version
+ * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * Derived from arch/i386/kernel/irq.c
+ * Copyright (C) 1992 Linus Torvalds
+ * Adapted from arch/i386 by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
*
* This file contains the code used by various IRQ handling routines:
* asking for different IRQ's should be done through these routines
@@ -11,7 +15,7 @@
* shouldn't result in any weird surprises, and installing new handlers
* should be easier.
*/
-
+
/*
* IRQ's are in fact implemented a bit like signal handlers for the kernel.
* Naturally it's not a 1:1 relation, but there are similarities.
@@ -25,323 +29,300 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
+#include <linux/config.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/bitops.h>
-inline int get_irq_list(char *);
-void check_irq(void);
-void BeBox_CPU1(void);
-void BeBox_state(void);
-int BeBox_irq(void);
-void show_BeBox_state(void);
-void BeBox_enable_irq(int );
-void BeBox_disable_irq(int );
-void BeBox_init_IRQ(void);
-void _do_bottom_half(void);
-static _NOP(void);
-static _delay(void);
-void hard_disk_LED(int state);
+#define IRQ_FLAG ((unsigned *)0xf3000020)
+#define IRQ_ENABLE ((unsigned *)0xf3000024)
+#define IRQ_ACK ((unsigned *)0xf3000028)
+#define IRQ_LEVEL ((unsigned *)0xf300002c)
+
+#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */
+#undef SHOW_IRQ 1
-#define SHOW_IRQ
-#undef SHOW_IRQ
+unsigned lost_interrupts = 0;
+
+unsigned int local_irq_count[NR_CPUS];
+static struct irqaction irq_action[32];
/*
- * For the BeBox, interrupt numbers are 0..15 for 8259 PIC interrupts
- * and 16..31 for other BeBox motherboard type interrupts.
+ * This contains the irq mask for both irq controllers
*/
-
-unsigned long isBeBox[];
-unsigned char *BeBox_IO_page;
+static unsigned int cached_irq_mask = 0xffff;
+
+#define cached_21 (((char *)(&cached_irq_mask))[0])
+#define cached_A1 (((char *)(&cached_irq_mask))[1])
+
-static unsigned char cache_21 = 0xff;
-static unsigned char cache_A1 = 0xff;
+int __ppc_bh_counter;
-void disable_irq(unsigned int irq_nr)
+void *null_handler(int,void *,struct pt_regs *);
+
+/*
+ * disable and enable intrs in software. This is used
+ * from the non-realtime parts of Linux to disable interrupts.
+ * The realtime part disables/enables intrs in the hardware.
+ * -- Cort
+ */
+unsigned long soft_intr_enable = 1;
+void _soft_cli(void)
{
- unsigned char mask;
- int s = _disable_interrupts();
+ soft_intr_enable = 0;
+}
- if (isBeBox[0] && (irq_nr >= 16))
- {
- BeBox_disable_irq(irq_nr);
- } else
+void _soft_sti(void)
+{
+ soft_intr_enable = 1;
+ if ( lost_interrupts )
{
- mask = 1 << (irq_nr & 7);
- if (irq_nr < 8)
- {
- cache_21 |= mask;
- outb(cache_21,0x21);
- } else
- {
- cache_A1 |= mask;
- outb(cache_A1,0xA1);
- }
+ printk("lost_interrupts from _soft_sti() %x\n",lost_interrupts);
+ fake_interrupt();
}
- _enable_interrupts(s);
}
-void enable_irq(unsigned int irq_nr)
+void *
+null_handler(int a, void *b, struct pt_regs *regs)
+{
+ /*printk("irq.c: null_handler() called. Should not have happened.\n");*/
+}
+
+void
+disable_irq(unsigned int irq_nr)
{
- unsigned char mask;
int s = _disable_interrupts();
+ unsigned char mask;
- if (isBeBox[0] && (irq_nr >= 16))
+#ifdef CONFIG_PMAC
+ out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr));
+#else /* CONFIG_PMAC */
+ mask = 1 << (irq_nr & 7);
+ if (irq_nr < 8)
{
- BeBox_enable_irq(irq_nr);
- _enable_interrupts(s);
- return;
+ cached_21 |= mask;
+ outb(cached_21,0x21);
} else
{
- mask = ~(1 << (irq_nr & 7));
- if (irq_nr < 8) {
- cache_21 &= mask;
- outb(cache_21,0x21);
- } else
- {
- cache_A1 &= mask;
- outb(cache_A1,0xA1);
- }
- }
+ cached_A1 |= mask;
+ outb(cached_A1,0xA1);
+ }
+#endif /* CONFIG_PMAC */
_enable_interrupts(s);
}
-/*
- * Irq handlers.
- */
-struct irq_action {
- void (*handler)(int, void *dev, struct pt_regs *);
- unsigned long flags;
- unsigned long mask;
- const char *name;
- int notified;
- void *dev_id;
-};
-
-static struct irq_action irq_action[32] = {
- { 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 },
- { 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 }
-};
-
-
-inline int get_irq_list(char *buf)
-{
- int i, len = 0;
- struct irq_action * action = irq_action;
-
- for (i = 0; i < 32; i++, action++) {
- if (!action->handler)
- continue;
- len += sprintf(buf+len, "%2d: %8d %c %s\n",
- i, kstat.interrupts[i],
- (action->flags & SA_INTERRUPT) ? '+' : ' ',
- action->name);
- }
- return len;
-}
-
-inline void
-process_IRQ(int irq, int _irq, struct pt_regs *regs)
-{
- struct irq_action *action;
- atomic_inc(&intr_count);
- if (irq < 16)
- {
- /* Mask interrupt */
- if (irq > 7)
- {
- cache_A1 |= (1<<(irq-8));
- outb(cache_A1, 0xA1);
- } else
- {
- cache_21 |= (1<<irq);
- outb(cache_21, 0x21);
- }
- }
- action = irq + irq_action;
- kstat.interrupts[irq]++;
- /* TEMP */
- /* On the Nobis, the keyboard interrupt "edge" gets lost - why? */
- if (irq == 0)
- {
- static int count;
- if (++count == 500)
- {
- if (inb(0x64) & 0x01)
- {
- struct irq_action *action;
- action = irq_action + 1; /* Keyboard */
- printk("Reset KBD, KBSTAT = %x, ELCR = %x/%x, MASK = %x/%x\n",
- inb(0x64), inb(0x4D0), inb(0x4D1), cache_21, cache_A1);
- action->handler(1, action->dev_id, regs);
- }
- count = 0;
- }
- }
- if (action->handler)
- {
- action->handler(irq, action->dev_id, regs);
- } else
- {
- printk("Bogus interrupt %d/%x, pc %x regs %x\n",
- irq, _irq,regs->nip,regs);
-#if 0
- printk("BeBox[] = %x/%x\n", isBeBox[0], isBeBox[1]);
- show_BeBox_state();
- cnpause();
-#endif
- }
- if (_disable_interrupts() && !action->notified)
- {
- action->notified = 1;
- printk("*** WARNING! %s handler [IRQ %d] turned interrupts on!\n",
- action->name, irq);
- }
- if (irq < 16)
- {
- /* Issue EOI to interrupt controller */
- if (irq > 7)
- {
- outb(0xE0|(irq-8), 0xA0);
- outb(0xE2, 0x20);
- } else
- {
- outb(0xE0|irq, 0x20);
- }
- if (!(action->flags & SA_ONESHOT))
- {
- /* Re-enable interrupt */
- if (irq > 7)
- {
- cache_A1 &= ~(1<<(irq-8));
- outb(cache_A1, 0xA1);
- } else
- {
- cache_21 &= ~(1<<irq);
- outb(cache_21, 0x21);
- }
- }
- } else
- {
- BeBox_enable_irq(irq);
- }
- atomic_dec(&intr_count);
-}
-
-asmlinkage inline void handle_IRQ(struct pt_regs *regs)
-{
- int irq, _irq, s;
- struct irq_action *action;
- static int _ints;
-
- if (!isBeBox[0] || ((irq = BeBox_irq()) < 16))
- {
- /* Figure out IRQ#, etc. */
- outb(0x0C, 0x20); /* Poll interrupt controller */
- irq = _irq = inb(0x20);
- irq &= 0x07; /* Caution! */
- if (irq == 2)
- { /* Cascaded interrupt -> IRQ8..IRQ15 */
- outb(0x0C, 0xA0);
- irq = (_irq = inb(0xA0)) & 0x07;
- irq += 8;
- }
- }
- process_IRQ(irq, _irq, regs);
-
- /* Sometimes, the cascaded IRQ controller get's "stuck" */
- if ((irq == 0) && (_ints++ == 100))
- {
- _ints = 0;
- outb(0x0A, 0xA0); _irq = inb(0xA0);
- if (_irq & ~cache_A1)
- { /* Figure out which IRQs are present */
- _irq &= ~cache_A1;
- for (irq = 0; irq < 7; irq++)
- {
- if (_irq & (1<<irq))
+void
+enable_irq(unsigned int irq_nr)
+{
+ int s = _disable_interrupts();
+#ifdef CONFIG_PMAC
+ unsigned bit = 1U << irq_nr;
+
+ out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr));
+ out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) | bit);
+
+ /*
+ * Unfortunately, setting the bit in the enable register
+ * when the device interrupt is already on *doesn't* set
+ * the bit in the flag register or request another interrupt.
+ */
+ if ((ld_le32(IRQ_LEVEL) & bit) && !(ld_le32(IRQ_FLAG) & bit))
+ lost_interrupts |= bit;
+#else /* CONFIG_PMAC */
+ if (irq_nr < 8) {
+ cached_21 &= ~(1 << (irq_nr & 7));
+ outb(cached_21,0x21);
+ } else
{
-#if 0
- printk("Dropped IRQ #%d\n", irq+8);
-#endif
- process_IRQ(irq+8, _irq, regs);
- }
- }
- }
- }
+ cached_A1 &= ~(1 << (irq_nr-8 & 7));
+ outb(cached_A1,0xA1);
+ }
+#endif /* CONFIG_PMAC */
+
+ _enable_interrupts(s);
}
-/*
- * Display current IRQ state
- */
-void
-show_irq_state(void)
+int get_irq_list(char *buf)
{
- unsigned char state_21, state_A1;
- outb(0x0A, 0x20); state_21 = inb(0x20);
- outb(0x0A, 0xA0); state_A1 = inb(0xA0);
- printk("IRQ State = %x/%x, Edge = %x/%x, Processor = %d\n", state_21, state_A1, inb(0x4D0), inb(0x4D1), _Processor);
-}
+ int i, len = 0;
+ struct irqaction * action;
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ action = irq_action + i;
+ if (!action || !action->handler)
+ continue;
+ len += sprintf(buf+len, "%2d: %10u %s",
+ i, kstat.interrupts[i], action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ", %s", action->name);
+ }
+ len += sprintf(buf+len, "\n");
+ }
/*
- * Initialize interrupt controllers to a well-known state.
+ * Linus - should you add NMI counts here ?????
*/
+#ifdef __SMP_PROF__
+ len+=sprintf(buf+len, "IPI: %8lu received\n",
+ ipi_count);
+#endif
+ return len;
+}
-static void
-reset_int_controllers(void)
+asmlinkage void handle_IRQ(struct pt_regs *regs)
{
- /* Initialize interrupt controllers */
- outb(0x11, 0x20); /* Start init sequence */
- outb(0x40, 0x21); /* Vector base */
- outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */
- outb(0x01, 0x21); /* Select 8086 mode */
- outb(0xFF, 0x21); /* Mask all */
- outb(0x11, 0xA0); /* Start init sequence */
- outb(0x48, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */
- outb(0x01, 0xA1); /* Select 8086 mode */
- outb(0xFF, 0xA1); /* Mask all */
-#if 0
- outb(0x00, 0x4D0); /* All edge triggered */
- outb(0xCF, 0x4D1); /* Trigger mode */
+ int irq;
+ unsigned bits;
+ struct irqaction *action;
+ int cpu = smp_processor_id();
+
+ hardirq_enter(cpu);
+
+#ifdef CONFIG_PMAC
+ bits = ld_le32(IRQ_FLAG) | lost_interrupts;
+ lost_interrupts = 0;
+
+ for (irq = NR_IRQS; irq >= 0; --irq)
+ if (bits & (1U << irq))
+ break;
+#else /* CONFIG_PMAC */
+#if 1
+ if ( lost_interrupts )
+ {
+ irq = ffz(~lost_interrupts);
+ lost_interrupts &= ~irq;
+ goto retry;
+ }
+ outb(0x0C, 0x20);
+ irq = inb(0x20) & 7;
+ if (irq == 2)
+ {
+retry_cascade:
+ outb(0x0C, 0xA0);
+ irq = inb(0xA0);
+ /* if no intr left */
+ if ( !(irq & 128 ) )
+ goto out;
+ irq = (irq&7) + 8;
+ }
+retry:
+#else
+ /* get the irr from the intr controller */
+ outb(0x0A, 0x20);
+ bits = inb(0x20);
+ /* handle cascade */
+ if ( bits )
+ {
+ bits &= 4;
+ outb(0x0A, 0xA0);
+ bits = inb(0xA0)<<8;
+ }
+ /* get lost interrupts */
+ bits |= lost_interrupts;
+ /* save intrs that are masked out */
+ lost_interrupts = bits & cached_irq_mask;
+ /* get rid of intrs being masked */
+ bits &= ~cached_irq_mask;
+ /* non-specifc eoi */
+ outb(0x20,0x20);
+ if ( bits & 0xff00 )
+ outb(0x20,0xA0);
+
+ printk("bits %04X lost %04X mask %04x\n",
+ bits, lost_interrupts,cached_irq_mask);
+
+ for (irq = NR_IRQS; irq >= 0; --irq)
+ if (bits & (1U << irq))
+ break;
#endif
- outb(cache_A1, 0xA1);
- outb(cache_21, 0x21);
- enable_irq(2); /* Enable cascade interrupt */
+#endif /* CONFIG_PMAC */
+
+ if (irq < 0) {
+ printk("Bogus interrupt from PC = %lx, irq %d\n",regs->nip,irq);
+ goto out;
+ }
+
+#ifdef CONFIG_PMAC
+ out_le32(IRQ_ACK, 1U << irq);
+#else /* CONFIG_PMAC */
+ /* mask out the irq while handling it */
+ disable_irq(irq);
+ /*
+ * send eoi to interrupt controller right away or lower
+ * priority intrs would be ignored even if with intrs enabled
+ */
+ if (irq > 7)
+ {
+ outb(0xE0|(irq-8), 0xA0);
+ outb(0xE2, 0x20);
+ } else
+ {
+ outb(0xE0|irq, 0x20);
+ }
+#endif /* !CONFIG_PMAC */
+
+ /*
+ * now that we've acked the irq, if intrs are disabled in software
+ * we're in the real-time system and non-rt linux has disabled them
+ * so we just queue it up and return -- Cort
+ */
+ if ( ! soft_intr_enable )
+ {
+ lost_interrupts |= 1UL << irq;
+ /* can't printk - kernel expects intrs off! */
+ /*printk("irq %d while intrs soft disabled\n", irq);*/
+ goto out;
+ }
+
+ action = irq + irq_action;
+ kstat.interrupts[irq]++;
+ if (action->handler) {
+ action->handler(irq, action->dev_id, regs);
+ _disable_interrupts(); /* in case the handler turned them on */
+ } else {
+ disable_irq( irq );
+ }
+#ifdef CONFIG_PREP
+ /* re-enable if the interrupt was good and isn't one-shot */
+ if ( action->handler && !(action->flags & SA_ONESHOT) )
+ enable_irq(irq);
+ /* make sure we don't miss any cascade intrs due to eoi-ing irq 2 */
+ if ( irq > 7 )
+ goto retry_cascade;
+#endif
+
+ hardirq_exit(cpu);
+ /*
+ * This should be conditional: we should really get
+ * a return code from the irq handler to tell us
+ * whether the handler wants us to do software bottom
+ * half handling or not..
+ */
+ if (1)
+ if (bh_active & bh_mask)
+ do_bottom_half();
+ return;
+out:
+ hardirq_exit(cpu);
+
}
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
+ unsigned long irqflags, const char * devname, void *dev_id)
{
- struct irq_action * action;
+ struct irqaction * action;
unsigned long flags;
-
-#ifdef SHOW_IRQ
-if (irq) printk("Request IRQ #%d, Handler: %x\n", irq, handler);
-#endif
- if (irq > 15)
- {
- if (!isBeBox[0] || (irq > 31))
- return -EINVAL;
- }
+
+#ifdef SHOW_IRQ
+ printk("request_irq(): irq %d handler %08x name %s dev_id %04x\n",
+ irq,handler,devname,dev_id);
+#endif /* SHOW_IRQ */
+
+ if (irq > NR_IRQS)
+ return -EINVAL;
action = irq + irq_action;
if (action->handler)
return -EBUSY;
@@ -361,10 +342,14 @@
void free_irq(unsigned int irq, void *dev_id)
{
- struct irq_action * action = irq + irq_action;
+ struct irqaction * action = irq + irq_action;
unsigned long flags;
- if (irq > 31) {
+#ifdef SHOW_IRQ
+ printk("free_irq(): irq %d dev_id %04x\n", irq, dev_id);
+#endif /* SHOW_IRQ */
+
+ if (irq > NR_IRQS) {
printk("Trying to free IRQ%d\n",irq);
return;
}
@@ -383,15 +368,6 @@
restore_flags(flags);
}
-#define SA_PROBE SA_ONESHOT
-
-static void no_action(int irq, void *dev, struct pt_regs * regs)
-{
-#ifdef DEBUG
- printk("Probe got IRQ: %d\n", irq);
-#endif
-}
-
unsigned long probe_irq_on (void)
{
unsigned int i, irqs = 0, irqmask;
@@ -399,7 +375,7 @@
/* first, snaffle up any unassigned irqs */
for (i = 15; i > 0; i--) {
- if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
+ if (!request_irq(i, null_handler, SA_ONESHOT, "probe", NULL)) {
enable_irq(i);
irqs |= (1 << i);
}
@@ -409,7 +385,7 @@
for (delay = jiffies + 2; delay > jiffies; ); /* min 10ms delay */
/* now filter out any obviously spurious interrupts */
- irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+ irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21;
for (i = 15; i > 0; i--) {
if (irqs & (1 << i) & irqmask) {
irqs ^= (1 << i);
@@ -426,13 +402,13 @@
{
unsigned int i, irqmask;
- irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+ irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21;
for (i = 15; i > 0; i--) {
if (irqs & (1 << i)) {
free_irq(i, NULL);
}
}
-#ifdef DEBUG
+#ifdef SHOW_IRQ
printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
#endif
irqs &= irqmask;
@@ -443,209 +419,65 @@
i = -i;
return i;
}
-
-void init_IRQ(void)
-{
- int i;
-
- if ((_get_PVR()>>16) == 1) /* PPC 601 */
- { /* Nobis? */
- reset_int_controllers();
- }
-#define TIMER0_COUNT 0x40
-#define TIMER_CONTROL 0x43
- /* set the clock to 100 Hz */
- outb_p(0x34,TIMER_CONTROL); /* binary, mode 2, LSB/MSB, ch 0 */
- outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
- outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
- if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
- printk("Unable to get IRQ2 for cascade\n");
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
-
- /* Make sure IRQ2 (cascade) interrupt is "level" based */
- outb(inb(0x4D0)|0x04, 0x4D0); /* IRQ2 level based */
-
- /* Set up PCI interrupts */
- route_PCI_interrupts();
-
- if (isBeBox[0])
- {
- BeBox_init_IRQ();
- }
-}
-
-/*
- * Wrapper for "bottom 1/2" of interrupt processing. This routine
- * is called whenever an interrupt needs non-interrupt-time service.
- */
-
-void _do_bottom_half(void)
-{
- _enable_interrupts(1);
- do_bottom_half();
- _disable_interrupts();
-}
-void hard_disk_LED(int state)
-{
- if (_Processor == _PROC_IBM) {
- outb(state, IBM_HDD_LED);
- }
-}
-
-
-/*
- * Support for interrupts on the BeBox
- */
-
-#define CPU0_INT_MASK (volatile unsigned long *)(BeBox_IO_page+0x0F0)
-#define CPU1_INT_MASK (volatile unsigned long *)(BeBox_IO_page+0x1F0)
-#define INT_SOURCE (volatile unsigned long *)(BeBox_IO_page+0x2F0)
-#define CPU_RESET (volatile unsigned long *)(BeBox_IO_page+0x4F0)
-
-#define _CPU0_INT_MASK (volatile unsigned long *)(0xA0000000+0x0F0)
-#define _CPU1_INT_MASK (volatile unsigned long *)(0xA0000000+0x1F0)
-#define _INT_SOURCE (volatile unsigned long *)(0xA0000000+0x2F0)
-#define _CPU_RESET (volatile unsigned long *)(0xA0000000+0x4F0)
-
-#define CPU_HRESET 0x20000000
-#define CPU_SRESET 0x40000000
-
-#define SCSI_IRQ 16
-
-#define INT_SCSI (1<<21)
-#define INT_8259 (1<<5)
-
-/*
- * Map of pseudo IRQs to actual bits
- * Note: We give out IRQ #16..31 for all interrupt sources which are
- * not found in the 8259 PIC.
- */
-
-unsigned long BeBox_IRQ_map[] =
- {
- INT_SCSI, /* 16 - SCSI */
- 0x00000000, /* 17 - Unused */
- 0x00000000, /* 18 - Unused */
- 0x00000000, /* 19 - Unused */
- 0x00000000, /* 20 - Unused */
- 0x00000000, /* 21 - Unused */
- 0x00000000, /* 22 - Unused */
- 0x00000000, /* 23 - Unused */
- 0x00000000, /* 24 - Unused */
- 0x00000000, /* 25 - Unused */
- 0x00000000, /* 26 - Unused */
- 0x00000000, /* 27 - Unused */
- 0x00000000, /* 28 - Unused */
- 0x00000000, /* 29 - Unused */
- 0x00000000, /* 30 - Unused */
- 0x00000000, /* 31 - Unused */
- };
-
-volatile int CPU1_alive;
-volatile int CPU1_trace;
-
-static
-_NOP(void)
-{
-}
-
-static
-_delay(void)
+void init_IRQ(void)
{
- int i;
- for (i = 0; i < 100; i++) _NOP();
-}
+#ifdef CONFIG_PMAC
+ extern void xmon_irq(int, void *, struct pt_regs *);
-void
-BeBox_init_IRQ(void)
-{
- int tmr;
- volatile extern long BeBox_CPU1_vector;
- *CPU0_INT_MASK = 0x0FFFFFFC; /* Clear all bits? */
- *CPU0_INT_MASK = 0x80000003 | INT_8259;
- *CPU1_INT_MASK = 0x0FFFFFFC;
-printk("Start CPU #1 - CPU Status: %x\n", *CPU_RESET);
- BeBox_CPU1_vector = 0x0100; /* Reset */
- tmr = 0;
- while (CPU1_alive == 0)
- {
- if (++tmr == 1000)
- {
-printk("CPU #1 not there? - CPU Status: %x, Trace: %x\n", *CPU_RESET, CPU1_trace);
- break;
- }
- _delay();
- }
-printk("CPU #1 running!\n");
-}
+ *IRQ_ENABLE = 0;
+ request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0);
+#else /* CONFIG_PMAC */
+ /* Initialize interrupt controllers */
+ outb(0x11, 0x20); /* Start init sequence */
+ outb(0x40, 0x21); /* Vector base */
+#if 1
+ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+#else
+ outb(0x0C, 0x21); /* level triggered, Cascade (slave) on IRQ2 */
+#endif
+
+ outb(0x01, 0x21); /* Select 8086 mode */
+ outb(0xFF, 0x21); /* Mask all */
-void
-BeBox_disable_irq(int irq)
-{
- /* Note: this clears the particular bit */
- *CPU0_INT_MASK = BeBox_IRQ_map[irq-16];
-}
+ outb(0x11, 0xA0); /* Start init sequence */
+ outb(0x48, 0xA1); /* Vector base */
+#if 1
+ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+#else
+ outb(0x0A, 0x21); /* level triggered, Cascade (slave) on IRQ2 */
+#endif
+ outb(0x01, 0xA1); /* Select 8086 mode */
+ outb(0xFF, 0xA1); /* Mask all */
-void
-BeBox_enable_irq(int irq)
-{
- int s = _disable_interrupts();
- /* Sets a single bit */
+ /*
+ * Program level mode for irq's that 'can' be level triggered.
+ * This does not effect irq's 0,1,2 and 8 since they must be
+ * edge triggered. This is not the PIC controller. The default
+ * here is for edge trigger mode. -- Cort
+ */
#if 0
-printk("BeBox IRQ Mask = %x", *CPU0_INT_MASK);
+ outb(0xf8, 0x4d0); /* level triggered */
+ outb(0xff, 0x4d1);
#endif
- *CPU0_INT_MASK = 0x80000000 | BeBox_IRQ_map[irq-16];
-#if 0
-printk("/%x\n", *CPU0_INT_MASK);
-#endif
- _enable_interrupts(s);
-}
-
-void
-show_BeBox_state(void)
-{
- unsigned long cpu0_int_mask;
- unsigned long int_state;
- cpu0_int_mask = (*CPU0_INT_MASK & 0x0FFFFFFC) & ~INT_8259;
- int_state = cpu0_int_mask & *INT_SOURCE;
- printk("Ints[%x] = %x, Mask[%x] = %x/%x, State = %x\n", INT_SOURCE, *INT_SOURCE, CPU0_INT_MASK, *CPU0_INT_MASK, cpu0_int_mask, int_state);
-}
-
-int
-BeBox_irq(void)
-{
- int i;
- unsigned long cpu0_int_mask;
- unsigned long int_state;
- cpu0_int_mask = (*CPU0_INT_MASK & 0x0FFFFFFC) & ~INT_8259;
- int_state = cpu0_int_mask & *INT_SOURCE;
- if (int_state)
- { /* Determine the pseudo-interrupt # */
#if 0
- printk("Ints[%x] = %x, Mask[%x] = %x/%x, State = %x\n", INT_SOURCE, *INT_SOURCE, CPU0_INT_MASK, *CPU0_INT_MASK, cpu0_int_mask, int_state);
-#endif
- for (i = 0; i < 16; i++)
- {
- if (BeBox_IRQ_map[i] & int_state)
- {
- return (i+16);
- }
- }
-printk("Ints[%x] = %x, Mask[%x] = %x/%x, State = %x\n", INT_SOURCE, *INT_SOURCE, CPU0_INT_MASK, *CPU0_INT_MASK, cpu0_int_mask, int_state);
-printk("Can't find BeBox IRQ!\n");
- }
- return (0);
-}
-
-void BeBox_state(void)
-{
- printk("Int state = %x, CPU0 mask = %x, CPU1 mask = %x\n", *INT_SOURCE, *CPU0_INT_MASK, *CPU1_INT_MASK);
-}
+ outb(0x00, 0x4D0); /* All edge triggered */
+ outb(0xCF, 0x4D1); /* Trigger mode */
+#endif
+ outb(cached_A1, 0xA1);
+ outb(cached_21, 0x21);
+ if (request_irq(2, null_handler, SA_INTERRUPT, "cascade", NULL))
+ printk("Unable to get IRQ2 for cascade\n");
+ enable_irq(2); /* Enable cascade interrupt */
+
+#define TIMER0_COUNT 0x40
+#define TIMER_CONTROL 0x43
+ /* set timer to periodic mode */
+ outb_p(0x34,TIMER_CONTROL); /* binary, mode 2, LSB/MSB, ch 0 */
+ /* set the clock to ~100 Hz */
+ outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
+ outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
-void BeBox_CPU1(void)
-{
- CPU1_alive++;
- while (1) ;
+ route_pci_interrupts();
+#endif /* CONFIG_PMAC */
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov