ref: a7b1ab8236b7ccd41e96e9e4008cbc3213294724
dir: /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 = 128,
};
static struct irq {
void (*f)(Ureg*, void*);
void *arg;
char *name;
} irqs[NINTR];
enum {
SYSCFG = 0x10/4,
AutoIdle = 1<<0,
SoftReset = 1<<1,
SYSSTATUS = 0x14/4,
ResetDone = 1<<0,
SIRIRQ = 0x40/4,
CONTROL = 0x48/4,
NewIRQAgr = 1<<0,
PROTECTION = 0x4c/4,
Protection = 1<<0,
IDLE = 0x50/4,
Turbo = 1<<1,
MIRCLRBASE = 0x88/4,
MIRSETBASE = 0x8c/4,
MIRREGSTEP = 0x20/4,
};
#define MIRSET(n) (MIRSETBASE+MIRREGSTEP*(n))
#define MIRCLR(n) (MIRCLRBASE+MIRREGSTEP*(n))
void
intrinit(void)
{
int i;
intcps[SYSCFG] |= SoftReset;
while((intcps[SYSSTATUS] & ResetDone) == 0);
for(i = 0; i < 4; i++)
intcps[MIRSET(i)] = ~0;
intcps[PROTECTION] |= Protection;
}
void
intrenable(int irq, void (*f)(Ureg *, void *), void *arg, char *name)
{
struct irq *i;
if(f == nil)
panic("intrenable: f == nil");
if(irq < 0 || irq >= NINTR)
panic("intrenable: invalid irq %d", irq);
if(irqs[irq].f != nil && irqs[irq].f != f)
panic("intrenable: handler already assigned");
i = &irqs[irq];
i->f = f;
i->arg = arg;
i->name = name;
intcps[MIRCLR((irq>>5)&3)] = 1<<(irq&0x1f);
}
void
intr(Ureg *ureg)
{
ulong v;
int irq;
struct irq *i;
v = intcps[SIRIRQ];
irq = v & 0x7f;
if(v >> 7){
print("spurious interrupt\n");
intcps[CONTROL] = NewIRQAgr;
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);
intcps[CONTROL] = NewIRQAgr;
if(up != nil){
if(irq == TIMER2IRQ){
if(up->delaysched){
splhi();
sched();
}
}else
preempted();
}
}