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