1*74a4d8c2SCharles.Forsyth #include "boot.h"
2*74a4d8c2SCharles.Forsyth
3*74a4d8c2SCharles.Forsyth enum
4*74a4d8c2SCharles.Forsyth {
5*74a4d8c2SCharles.Forsyth Maxhandler= 32+16, /* max number of interrupt handlers */
6*74a4d8c2SCharles.Forsyth };
7*74a4d8c2SCharles.Forsyth
8*74a4d8c2SCharles.Forsyth typedef struct Handler Handler;
9*74a4d8c2SCharles.Forsyth struct Handler
10*74a4d8c2SCharles.Forsyth {
11*74a4d8c2SCharles.Forsyth void (*r)(Ureg*, void*);
12*74a4d8c2SCharles.Forsyth void *arg;
13*74a4d8c2SCharles.Forsyth Handler *next;
14*74a4d8c2SCharles.Forsyth int edge;
15*74a4d8c2SCharles.Forsyth };
16*74a4d8c2SCharles.Forsyth
17*74a4d8c2SCharles.Forsyth struct
18*74a4d8c2SCharles.Forsyth {
19*74a4d8c2SCharles.Forsyth Handler *ivec[128];
20*74a4d8c2SCharles.Forsyth Handler h[Maxhandler];
21*74a4d8c2SCharles.Forsyth int free;
22*74a4d8c2SCharles.Forsyth } halloc;
23*74a4d8c2SCharles.Forsyth
24*74a4d8c2SCharles.Forsyth char *excname[] = {
25*74a4d8c2SCharles.Forsyth "reserved 0",
26*74a4d8c2SCharles.Forsyth "system reset",
27*74a4d8c2SCharles.Forsyth "machine check",
28*74a4d8c2SCharles.Forsyth "data access",
29*74a4d8c2SCharles.Forsyth "instruction access",
30*74a4d8c2SCharles.Forsyth "external interrupt",
31*74a4d8c2SCharles.Forsyth "alignment",
32*74a4d8c2SCharles.Forsyth "program exception",
33*74a4d8c2SCharles.Forsyth "floating-point unavailable",
34*74a4d8c2SCharles.Forsyth "decrementer",
35*74a4d8c2SCharles.Forsyth "reserved A",
36*74a4d8c2SCharles.Forsyth "reserved B",
37*74a4d8c2SCharles.Forsyth "system call",
38*74a4d8c2SCharles.Forsyth "trace trap",
39*74a4d8c2SCharles.Forsyth "floating point assist",
40*74a4d8c2SCharles.Forsyth "reserved F",
41*74a4d8c2SCharles.Forsyth "software emulation",
42*74a4d8c2SCharles.Forsyth "ITLB miss",
43*74a4d8c2SCharles.Forsyth "DTLB miss",
44*74a4d8c2SCharles.Forsyth "ITLB error",
45*74a4d8c2SCharles.Forsyth "DTLB error",
46*74a4d8c2SCharles.Forsyth };
47*74a4d8c2SCharles.Forsyth
48*74a4d8c2SCharles.Forsyth char *regname[]={
49*74a4d8c2SCharles.Forsyth "CAUSE", "SRR1",
50*74a4d8c2SCharles.Forsyth "PC", "GOK",
51*74a4d8c2SCharles.Forsyth "LR", "CR",
52*74a4d8c2SCharles.Forsyth "XER", "CTR",
53*74a4d8c2SCharles.Forsyth "R0", "R1",
54*74a4d8c2SCharles.Forsyth "R2", "R3",
55*74a4d8c2SCharles.Forsyth "R4", "R5",
56*74a4d8c2SCharles.Forsyth "R6", "R7",
57*74a4d8c2SCharles.Forsyth "R8", "R9",
58*74a4d8c2SCharles.Forsyth "R10", "R11",
59*74a4d8c2SCharles.Forsyth "R12", "R13",
60*74a4d8c2SCharles.Forsyth "R14", "R15",
61*74a4d8c2SCharles.Forsyth "R16", "R17",
62*74a4d8c2SCharles.Forsyth "R18", "R19",
63*74a4d8c2SCharles.Forsyth "R20", "R21",
64*74a4d8c2SCharles.Forsyth "R22", "R23",
65*74a4d8c2SCharles.Forsyth "R24", "R25",
66*74a4d8c2SCharles.Forsyth "R26", "R27",
67*74a4d8c2SCharles.Forsyth "R28", "R29",
68*74a4d8c2SCharles.Forsyth "R30", "R31",
69*74a4d8c2SCharles.Forsyth };
70*74a4d8c2SCharles.Forsyth
71*74a4d8c2SCharles.Forsyth static void intr(Ureg*);
72*74a4d8c2SCharles.Forsyth
73*74a4d8c2SCharles.Forsyth void
sethvec(int v,void (* r)(void))74*74a4d8c2SCharles.Forsyth sethvec(int v, void (*r)(void))
75*74a4d8c2SCharles.Forsyth {
76*74a4d8c2SCharles.Forsyth ulong *vp, pa, o;
77*74a4d8c2SCharles.Forsyth
78*74a4d8c2SCharles.Forsyth if((ulong)r & 3)
79*74a4d8c2SCharles.Forsyth panic("sethvec");
80*74a4d8c2SCharles.Forsyth vp = (ulong*)KADDR(v);
81*74a4d8c2SCharles.Forsyth vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
82*74a4d8c2SCharles.Forsyth vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
83*74a4d8c2SCharles.Forsyth vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
84*74a4d8c2SCharles.Forsyth pa = PADDR(r);
85*74a4d8c2SCharles.Forsyth o = pa >> 25;
86*74a4d8c2SCharles.Forsyth if(o != 0 && o != 0x7F){
87*74a4d8c2SCharles.Forsyth /* a branch too far: running from ROM */
88*74a4d8c2SCharles.Forsyth vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
89*74a4d8c2SCharles.Forsyth vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
90*74a4d8c2SCharles.Forsyth vp[5] = 0x7c0803a6; /* MOVW R0, LR */
91*74a4d8c2SCharles.Forsyth vp[6] = 0x4e800021; /* BL (LR) */
92*74a4d8c2SCharles.Forsyth }else
93*74a4d8c2SCharles.Forsyth vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
94*74a4d8c2SCharles.Forsyth }
95*74a4d8c2SCharles.Forsyth
96*74a4d8c2SCharles.Forsyth #define LEV(n) (((n)<<1)|1)
97*74a4d8c2SCharles.Forsyth #define IRQ(n) (((n)<<1)|0)
98*74a4d8c2SCharles.Forsyth
99*74a4d8c2SCharles.Forsyth void
setvec(int v,void (* r)(Ureg *,void *),void * arg)100*74a4d8c2SCharles.Forsyth setvec(int v, void (*r)(Ureg*, void*), void *arg)
101*74a4d8c2SCharles.Forsyth {
102*74a4d8c2SCharles.Forsyth Handler *h;
103*74a4d8c2SCharles.Forsyth IMM *io;
104*74a4d8c2SCharles.Forsyth
105*74a4d8c2SCharles.Forsyth if(halloc.free >= Maxhandler)
106*74a4d8c2SCharles.Forsyth panic("out of interrupt handlers");
107*74a4d8c2SCharles.Forsyth v -= VectorPIC;
108*74a4d8c2SCharles.Forsyth h = &halloc.h[halloc.free++];
109*74a4d8c2SCharles.Forsyth h->next = halloc.ivec[v];
110*74a4d8c2SCharles.Forsyth h->r = r;
111*74a4d8c2SCharles.Forsyth h->arg = arg;
112*74a4d8c2SCharles.Forsyth halloc.ivec[v] = h;
113*74a4d8c2SCharles.Forsyth
114*74a4d8c2SCharles.Forsyth /*
115*74a4d8c2SCharles.Forsyth * enable corresponding interrupt in SIU/CPM
116*74a4d8c2SCharles.Forsyth */
117*74a4d8c2SCharles.Forsyth
118*74a4d8c2SCharles.Forsyth io = m->iomem;
119*74a4d8c2SCharles.Forsyth if(v >= VectorCPIC){
120*74a4d8c2SCharles.Forsyth v -= VectorCPIC;
121*74a4d8c2SCharles.Forsyth io->cimr |= 1<<(v&0x1F);
122*74a4d8c2SCharles.Forsyth }
123*74a4d8c2SCharles.Forsyth else if(v >= VectorIRQ)
124*74a4d8c2SCharles.Forsyth io->simask |= 1<<(31-IRQ(v&7));
125*74a4d8c2SCharles.Forsyth else
126*74a4d8c2SCharles.Forsyth io->simask |= 1<<(31-LEV(v));
127*74a4d8c2SCharles.Forsyth }
128*74a4d8c2SCharles.Forsyth
129*74a4d8c2SCharles.Forsyth void
trapinit(void)130*74a4d8c2SCharles.Forsyth trapinit(void)
131*74a4d8c2SCharles.Forsyth {
132*74a4d8c2SCharles.Forsyth int i;
133*74a4d8c2SCharles.Forsyth IMM *io;
134*74a4d8c2SCharles.Forsyth
135*74a4d8c2SCharles.Forsyth io = m->iomem;
136*74a4d8c2SCharles.Forsyth io->sypcr &= ~(3<<2); /* disable watchdog (821/823) */
137*74a4d8c2SCharles.Forsyth io->simask = 0; /* mask all */
138*74a4d8c2SCharles.Forsyth io->siel = ~0; /* edge sensitive, wake on all */
139*74a4d8c2SCharles.Forsyth io->cicr = 0; /* disable CPM interrupts */
140*74a4d8c2SCharles.Forsyth io->cipr = ~0; /* clear all interrupts */
141*74a4d8c2SCharles.Forsyth io->cimr = 0; /* mask all events */
142*74a4d8c2SCharles.Forsyth io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
143*74a4d8c2SCharles.Forsyth io->cicr |= 1 << 7; /* enable */
144*74a4d8c2SCharles.Forsyth io->tbscrk = KEEP_ALIVE_KEY;
145*74a4d8c2SCharles.Forsyth io->tbscr = 1; /* TBE */
146*74a4d8c2SCharles.Forsyth io->simask |= 1<<(31-LEV(CPIClevel)); /* CPM's level */
147*74a4d8c2SCharles.Forsyth io->tbk = KEEP_ALIVE_KEY;
148*74a4d8c2SCharles.Forsyth eieio();
149*74a4d8c2SCharles.Forsyth putdec(~0);
150*74a4d8c2SCharles.Forsyth
151*74a4d8c2SCharles.Forsyth /*
152*74a4d8c2SCharles.Forsyth * set all exceptions to trap
153*74a4d8c2SCharles.Forsyth */
154*74a4d8c2SCharles.Forsyth for(i = 0x0; i < 0x3000; i += 0x100)
155*74a4d8c2SCharles.Forsyth sethvec(i, exception);
156*74a4d8c2SCharles.Forsyth }
157*74a4d8c2SCharles.Forsyth
158*74a4d8c2SCharles.Forsyth void
dumpregs(Ureg * ur)159*74a4d8c2SCharles.Forsyth dumpregs(Ureg *ur)
160*74a4d8c2SCharles.Forsyth {
161*74a4d8c2SCharles.Forsyth int i;
162*74a4d8c2SCharles.Forsyth ulong *l;
163*74a4d8c2SCharles.Forsyth l = &ur->cause;
164*74a4d8c2SCharles.Forsyth for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
165*74a4d8c2SCharles.Forsyth print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
166*74a4d8c2SCharles.Forsyth }
167*74a4d8c2SCharles.Forsyth
168*74a4d8c2SCharles.Forsyth void
trap(Ureg * ur)169*74a4d8c2SCharles.Forsyth trap(Ureg *ur)
170*74a4d8c2SCharles.Forsyth {
171*74a4d8c2SCharles.Forsyth int c;
172*74a4d8c2SCharles.Forsyth
173*74a4d8c2SCharles.Forsyth c = ur->cause >> 8;
174*74a4d8c2SCharles.Forsyth switch(c){
175*74a4d8c2SCharles.Forsyth default:
176*74a4d8c2SCharles.Forsyth {extern int predawn; predawn = 1;}
177*74a4d8c2SCharles.Forsyth if(c < 0 || c >= nelem(excname))
178*74a4d8c2SCharles.Forsyth print("exception/interrupt #%x\n", c);
179*74a4d8c2SCharles.Forsyth else
180*74a4d8c2SCharles.Forsyth print("exception %s\n", excname[c]);
181*74a4d8c2SCharles.Forsyth dumpregs(ur);
182*74a4d8c2SCharles.Forsyth /* spllo(); */
183*74a4d8c2SCharles.Forsyth print("^P to reset\n");
184*74a4d8c2SCharles.Forsyth for(;;)
185*74a4d8c2SCharles.Forsyth ;
186*74a4d8c2SCharles.Forsyth
187*74a4d8c2SCharles.Forsyth case 0x09: /* decrementer */
188*74a4d8c2SCharles.Forsyth clockintr(ur, 0);
189*74a4d8c2SCharles.Forsyth return;
190*74a4d8c2SCharles.Forsyth
191*74a4d8c2SCharles.Forsyth case 0x05: /* external interrupt */
192*74a4d8c2SCharles.Forsyth intr(ur);
193*74a4d8c2SCharles.Forsyth break;
194*74a4d8c2SCharles.Forsyth }
195*74a4d8c2SCharles.Forsyth }
196*74a4d8c2SCharles.Forsyth
197*74a4d8c2SCharles.Forsyth static void
intr(Ureg * ur)198*74a4d8c2SCharles.Forsyth intr(Ureg *ur)
199*74a4d8c2SCharles.Forsyth {
200*74a4d8c2SCharles.Forsyth int b, v;
201*74a4d8c2SCharles.Forsyth Handler *h;
202*74a4d8c2SCharles.Forsyth IMM *io;
203*74a4d8c2SCharles.Forsyth
204*74a4d8c2SCharles.Forsyth io = m->iomem;
205*74a4d8c2SCharles.Forsyth b = io->sivec>>2;
206*74a4d8c2SCharles.Forsyth v = b>>1;
207*74a4d8c2SCharles.Forsyth if(b & 1) {
208*74a4d8c2SCharles.Forsyth if(v == CPIClevel){
209*74a4d8c2SCharles.Forsyth io->civr = 1;
210*74a4d8c2SCharles.Forsyth eieio();
211*74a4d8c2SCharles.Forsyth v = VectorCPIC+(io->civr>>11);
212*74a4d8c2SCharles.Forsyth }
213*74a4d8c2SCharles.Forsyth }else
214*74a4d8c2SCharles.Forsyth v += VectorIRQ;
215*74a4d8c2SCharles.Forsyth h = halloc.ivec[v];
216*74a4d8c2SCharles.Forsyth if(h == nil){
217*74a4d8c2SCharles.Forsyth for(;;)
218*74a4d8c2SCharles.Forsyth ;
219*74a4d8c2SCharles.Forsyth //print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
220*74a4d8c2SCharles.Forsyth return;
221*74a4d8c2SCharles.Forsyth }
222*74a4d8c2SCharles.Forsyth if(h->edge)
223*74a4d8c2SCharles.Forsyth io->sipend |= 1<<(31-b);
224*74a4d8c2SCharles.Forsyth /*
225*74a4d8c2SCharles.Forsyth * call the interrupt handlers
226*74a4d8c2SCharles.Forsyth */
227*74a4d8c2SCharles.Forsyth do {
228*74a4d8c2SCharles.Forsyth (*h->r)(ur, h->arg);
229*74a4d8c2SCharles.Forsyth h = h->next;
230*74a4d8c2SCharles.Forsyth } while(h != nil);
231*74a4d8c2SCharles.Forsyth if(v >= VectorCPIC)
232*74a4d8c2SCharles.Forsyth io->cisr |= 1<<(v-VectorCPIC);
233*74a4d8c2SCharles.Forsyth }
234