#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
struct Intrregs
{
ulong icip; /* pending IRQs */
ulong icmr; /* IRQ mask */
ulong iclr; /* IRQ if bit == 0, FRIQ if 1 */
ulong iccr; /* control register */
ulong icfp; /* pending FIQs */
ulong dummy1[3]
ulong icpr; /* pending interrupts */
};
struct Intrregs *intrregs;
typedef struct Vctl {
Vctl* next; /* handlers on this vector */
char name[NAMELEN]; /* of driver */
int irq;
void (*f)(Ureg*, void*); /* handler to call */
void* a; /* argument to call it with */
} Vctl;
static Lock vctllock;
static Vctl *vctl[32];
/*
* set up for exceptioons
*/
void
trapinit(void)
{
/*
* exceptionvectors points to a prototype in l.s of the
* exception vectors that save the regs and then call
* trap(). The actual vectorrs are double mapped
* to 0xffff0000 and to KZERO. We write them via
* KZERO since a data access to them will cause an
* exception.
*/
memmove((void*)KZERO, exceptionvectors, 2*4*8);
wbflush();
/* map in interrupt registers */
intrregs = mapspecial(INTRREGS, sizeof(*intrregs));
/* make all interrupts irq and disable all interrupts */
intrregs->iclr = 0;
intrregs->icmr = 0;
}
/*
* enable an interrupt and attach a function to i
*/
void
intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
{
int vno;
Vctl *v;
v = xalloc(sizeof(Vctl));
v->irq = irq;
v->f = f;
v->a = a;
strncpy(v->name, name, NAMELEN-1);
v->name[NAMELEN-1] = 0;
lock(&vctllock);
v->next = vctl[irq];
vctl[irq] = v;
unlock(&vctllock);
}
/*
* here on all exceptions with registers saved
*/
void
trap(Ureg *ureg)
{
switch(ureg->type){
case PsrMfiq: /* fast interrupt */
panic("fiq can't happen");
break;
case PsrMabt: /* fault */
case PsrMabt+1: /* fault */
panic("faults not implemented");
break;
case PsrMund: /* undefined instruction */
panic("undefined instruction");
break;
case PsrMirq: /* device interrupt */
break;
case PsrMsvc: /* system call */
break;
}
}
/* Give enough context in the ureg to produce a kernel stack for
* a sleeping process
*/
void
setkernur(Ureg *ureg, Proc *p)
{
USED(ureg, p);
}
/*
* return the userpc the last exception happened at
*/
ulong
userpc(void)
{
return 0;
}
/* This routine must save the values of registers the user is not permitted
* to write from devproc and then restore the saved values before returning.
*/
void
setregisters(Ureg* ureg, char* pureg, char* uva, int n)
{
USED(ureg, pureg, uva, n);
}
/*
* this is the body for all kproc's
*/
static
void
linkproc(void)
{
spllo();
up->kpfun(up->kparg);
}
/*
* setup stack and initial PC for a new kernel proc. This is architecture
* dependent because of the starting stack location
*/
void
kprocchild(Proc *p, void (*func)(void*), void *arg)
{
p->sched.pc = (ulong)linkproc;
p->sched.sp = (ulong)p->kstack+KSTACK;
p->kpfun = func;
p->kparg = arg;
}
/*
* Craft a return frame which will cause the child to pop out of
* the scheduler in user mode with the return register zero. Set
* pc to point to a l.s return function.
*/
void
forkchild(Proc *p, Ureg *ureg)
{
USED(p, ureg);
}
/*
* setup stack, initial PC, and any arch dependent regs for an execing user proc.
*/
long
execregs(ulong entry, ulong ssize, ulong nargs)
{
ulong *sp;
Ureg *ureg;
sp = (ulong*)(USTKTOP - ssize);
*--sp = nargs;
ureg = up->dbgreg;
ureg->r13 = (ulong)sp;
ureg->pc = entry;
return USTKTOP-BY2WD; /* address of user-level clock */
}
/*
* dump the processor stack for this process
*/
void
dumpstack(void)
{
}
ulong
dbgpc(Proc *p)
{
USED(p);
return 0;
}