ref: 5bc9b0c3cac34864d479c099283793ec4ae5565e
dir: /sys/src/9/cycv/intr.c/
#include "u.h" #include <ureg.h> #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" enum { NINTR = 212, NPRIVATE = 32 }; static struct irq { void (*f)(Ureg *, void *); void *arg; char *name; } irqs[NINTR]; enum { ICCICR = 0x100/4, ICCPMR, ICCBPR, ICCIAR, ICCEOIR, ICDDCR = 0x1000/4, ICDISR = 0x1080/4, ICDISER = 0x1100/4, ICDICER = 0x1180/4, ICDICPR = 0x1280/4, ICDABR = 0x1300/4, ICDIPRI = 0x1400/4, ICDIPTR = 0x1800/4, ICDICFR = 0x1C00/4, }; void intrinit(void) { int i; mpcore[ICDDCR] = 3; mpcore[ICCICR] = 7; mpcore[ICCBPR] = 3; mpcore[ICCPMR] = 255; if(m->machno != 0) return; /* disable all irqs and clear any pending interrupts */ for(i = 0; i < NINTR/32; i++){ mpcore[ICDISR + i] = -1; mpcore[ICDICER + i] = -1; mpcore[ICDICPR + i] = -1; mpcore[ICDABR + i] = 0; } } void intrenable(int irq, void (*f)(Ureg *, void *), void *arg, int type, char *name) { ulong *e, s; struct irq *i; if(f == nil) panic("intrenable: f == nil"); if(irq < 0 || irq >= NINTR) panic("intrenable: invalid irq %d", irq); if(type != LEVEL && type != EDGE) panic("intrenable: invalid type %d", type); if(irqs[irq].f != nil && irqs[irq].f != f) panic("intrenable: handler already assigned"); if(irq >= NPRIVATE){ e = &mpcore[ICDIPTR + (irq >> 2)]; s = irq << 3 & 24; *e = *e & ~(3 << s) | 1 << s; e = &mpcore[ICDICFR + (irq >> 4)]; s = irq << 1 & 30 | 1; *e = *e & ~(1 << s) | type << s; } ((uchar*)&mpcore[ICDIPRI])[irq] = 0; i = &irqs[irq]; i->f = f; i->arg = arg; i->name = name; mpcore[ICDISER + (irq >> 5)] = 1 << (irq & 31); mpcore[ICDABR + (irq >> 5)] |= 1 << (irq & 31); } void intr(Ureg *ureg) { ulong v; int irq; struct irq *i; v = mpcore[ICCIAR]; irq = v & 0x3ff; if(irq == 0x3ff) return; m->intr++; m->lastintr = irq; i = &irqs[irq]; if(i->f == nil) print("irq without handler %d\n", irq); else i->f(ureg, i->arg); mpcore[ICCEOIR] = v; if(up != nil){ if(irq == TIMERIRQ){ if(up->delaysched){ splhi(); sched(); } }else preempted(); } }