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