plan9fox/sys/src/9/cycv/intr.c
2020-01-08 02:35:01 +00:00

122 lines
2.1 KiB
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();
}
}