xref: /plan9-contrib/sys/src/boot/vt4/intr.c (revision da917039c7f233c1a27d212bf012c6afa758af39)
1*da917039SDavid du Colombier /* Xilink XPS interrupt controller */
2*da917039SDavid du Colombier 
3*da917039SDavid du Colombier #include "include.h"
4*da917039SDavid du Colombier 
5*da917039SDavid du Colombier enum {
6*da917039SDavid du Colombier 	/* mer bits */
7*da917039SDavid du Colombier 	Merme	= 1<<0,		/* master enable */
8*da917039SDavid du Colombier 	Merhie	= 1<<1,		/* hw intr enable */
9*da917039SDavid du Colombier 
10*da917039SDavid du Colombier 	Maxintrs = 8,		/* from 32; size reduction */
11*da917039SDavid du Colombier };
12*da917039SDavid du Colombier 
13*da917039SDavid du Colombier typedef struct {
14*da917039SDavid du Colombier 	ulong	isr;		/* status */
15*da917039SDavid du Colombier 	ulong	ipr;		/* pending (ro) */
16*da917039SDavid du Colombier 	ulong	ier;		/* enable */
17*da917039SDavid du Colombier 	ulong	iar;		/* acknowledge (wo) */
18*da917039SDavid du Colombier 	ulong	sieb;		/* set ie bits; avoid */
19*da917039SDavid du Colombier 	ulong	cieb;		/* clear ie bits; avoid */
20*da917039SDavid du Colombier 	ulong	ivr;		/* vector; silly */
21*da917039SDavid du Colombier 	ulong	mer;		/* master enable */
22*da917039SDavid du Colombier } Intregs;
23*da917039SDavid du Colombier 
24*da917039SDavid du Colombier typedef struct {
25*da917039SDavid du Colombier 	ulong	bit;
26*da917039SDavid du Colombier 	int	(*func)(ulong);
27*da917039SDavid du Colombier } Intr;
28*da917039SDavid du Colombier 
29*da917039SDavid du Colombier Intregs *irp = (Intregs *)Intctlr;
30*da917039SDavid du Colombier Intr intrs[Maxintrs];
31*da917039SDavid du Colombier Intr *nextintr;
32*da917039SDavid du Colombier 
33*da917039SDavid du Colombier static uvlong extintrs;
34*da917039SDavid du Colombier 
35*da917039SDavid du Colombier /* called from trap to poll for external interrupts */
36*da917039SDavid du Colombier void
intr(Ureg *)37*da917039SDavid du Colombier intr(Ureg *)
38*da917039SDavid du Colombier {
39*da917039SDavid du Colombier 	int handled;
40*da917039SDavid du Colombier 	Intr *ip;
41*da917039SDavid du Colombier 
42*da917039SDavid du Colombier 	extintrs++;
43*da917039SDavid du Colombier 	dcflush(PTR2UINT(&extintrs), sizeof extintrs);	/* seems needed */
44*da917039SDavid du Colombier 	handled = 0;
45*da917039SDavid du Colombier 	for (ip = intrs; ip->bit != 0; ip++)
46*da917039SDavid du Colombier 		handled |= ip->func(ip->bit);
47*da917039SDavid du Colombier 	if (!handled)
48*da917039SDavid du Colombier 		print("interrupt with no handler\n");
49*da917039SDavid du Colombier }
50*da917039SDavid du Colombier 
51*da917039SDavid du Colombier void
intrinit(void)52*da917039SDavid du Colombier intrinit(void)
53*da917039SDavid du Colombier {
54*da917039SDavid du Colombier 	intrack(~0);			/* clear dregs */
55*da917039SDavid du Colombier 	putesr(0);			/* clears machine check */
56*da917039SDavid du Colombier 	coherence();
57*da917039SDavid du Colombier 
58*da917039SDavid du Colombier 	irp->mer = Merme | Merhie;
59*da917039SDavid du Colombier 	irp->ier = 0;			/* clear any pending spurious intrs */
60*da917039SDavid du Colombier 	coherence();
61*da917039SDavid du Colombier 	nextintr = intrs;		/* touches sram, not dram */
62*da917039SDavid du Colombier 	nextintr->bit = 0;
63*da917039SDavid du Colombier 	coherence();
64*da917039SDavid du Colombier 
65*da917039SDavid du Colombier 	intrack(~0);			/* clear dregs */
66*da917039SDavid du Colombier 	putesr(0);			/* clears machine check */
67*da917039SDavid du Colombier 	coherence();
68*da917039SDavid du Colombier }
69*da917039SDavid du Colombier 
70*da917039SDavid du Colombier /* register func as the interrupt-service routine for bit */
71*da917039SDavid du Colombier void
intrenable(ulong bit,int (* func)(ulong))72*da917039SDavid du Colombier intrenable(ulong bit, int (*func)(ulong))
73*da917039SDavid du Colombier {
74*da917039SDavid du Colombier 	Intr *ip;
75*da917039SDavid du Colombier 
76*da917039SDavid du Colombier 	if (func == nil)
77*da917039SDavid du Colombier 		return;
78*da917039SDavid du Colombier 	assert(nextintr < intrs + nelem(intrs));
79*da917039SDavid du Colombier 	assert(bit);
80*da917039SDavid du Colombier 	for (ip = intrs; ip->bit != 0; ip++)
81*da917039SDavid du Colombier 		if (bit == ip->bit) {
82*da917039SDavid du Colombier 			iprint("handler for intr bit %#lux already "
83*da917039SDavid du Colombier 				"registered\n", bit);
84*da917039SDavid du Colombier 			return;
85*da917039SDavid du Colombier 		}
86*da917039SDavid du Colombier 	nextintr->bit = bit;
87*da917039SDavid du Colombier 	nextintr->func = func;
88*da917039SDavid du Colombier 	nextintr++;
89*da917039SDavid du Colombier 	coherence();
90*da917039SDavid du Colombier 	irp->ier |= bit;
91*da917039SDavid du Colombier 	coherence();
92*da917039SDavid du Colombier }
93*da917039SDavid du Colombier 
94*da917039SDavid du Colombier void
intrack(ulong bit)95*da917039SDavid du Colombier intrack(ulong bit)
96*da917039SDavid du Colombier {
97*da917039SDavid du Colombier 	if (bit) {
98*da917039SDavid du Colombier 		irp->iar = bit;
99*da917039SDavid du Colombier 		coherence();
100*da917039SDavid du Colombier 	}
101*da917039SDavid du Colombier }
102