1 /* pro_int.c: interrupt controllers
2
3 Copyright (c) 1997-2004, Tarik Isani (xhomer@isani.org)
4
5 This file is part of Xhomer.
6
7 Xhomer is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 Xhomer is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Xhomer; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21
22 /* XXX TBD:
23 -only one routine can access intr_req at a time!
24 -byte writes
25 -clear highest isr command
26 -rotating priority
27 -clear int_req if pending interrupt goes away???
28 */
29
30 #ifdef PRO
31 #include "pdp11_defs.h"
32 #include "sim_defs.h" /* For sim_gtime() */
33
34 extern int int_req; /* from pdp11_cpu */
35
36 int pro_int_irr[4]; /* Interrupt request register */
37 LOCAL int pro_int_isr[4]; /* Interrupt service register */
38 LOCAL int pro_int_imr[4]; /* Interrupt mask register */
39 LOCAL int pro_int_acr[4]; /* Auto clear register */
40 LOCAL int pro_int_mode[4]; /* Mode register (write-only) */
41 LOCAL int pro_int_presel[4]; /* Write preselect */
42 LOCAL int pro_int_presel_vec[4]; /* response memory preselected vector location */
43 LOCAL int pro_int_vec[4][8]; /* Interrupt vectors */
44
45
46 /* Determine highest priority int */
47
pro_int_check(int irr,int imr)48 LOCAL int pro_int_check(int irr, int imr)
49 {
50 int i, intreqs;
51
52 intreqs = irr & ((~imr) & 0377);
53 if (intreqs == 0) /* no int pending */
54 i = PRO_NO_INT;
55 else
56 {
57 /* Determine highest pending interrupt */
58
59 /* XXX only fixed priority mode is currently implemented */
60
61 for(i=0; i<=7; i++)
62 {
63 if ((intreqs & 01) == 1)
64 break;
65
66 intreqs = intreqs >> 1;
67 }
68 }
69
70 return i;
71 }
72
73
74 /* Update status of int line to processor */
75
pro_int_update(void)76 LOCAL void pro_int_update(void)
77 {
78 int intset, cnum, intnum;
79
80 intset = 0;
81
82 for(cnum=0; cnum<=3; cnum++)
83 {
84 intnum = pro_int_check(pro_int_irr[cnum], pro_int_imr[cnum]);
85
86 if ((intnum != PRO_NO_INT) && ((pro_int_mode[cnum] & PRO_INT_MM) != 0)
87 && ((pro_int_mode[cnum] & PRO_INT_IM) == 0))
88 intset = 1;
89 }
90
91 /* Set or clear interrupt, as needed */
92
93 if (intset == 1)
94 int_req = int_req | INT_PIR4;
95 else
96 int_req = int_req & ~INT_PIR4;
97 }
98
99
100 /* Interrupt controller registers */
101 /* Addresses 17773200-17773212 */
102
pro_int_rd(int pa)103 int pro_int_rd (int pa)
104 {
105 int data, i, cnum;
106
107 /* Determine controller number */
108
109 cnum = (pa >> 2) & 03;
110
111 switch (pa & 02)
112 {
113 case 00: /* 17773200, 17773204, 17773210 */
114 switch ((pro_int_mode[cnum] >> 5) & 03)
115 {
116 case 00:
117 data = pro_int_isr[cnum];
118 break;
119
120 case 01:
121 data = pro_int_imr[cnum];
122 break;
123
124 case 02:
125 data = pro_int_irr[cnum];
126 break;
127
128 case 03:
129 data = pro_int_acr[cnum];
130 break;
131
132 default: /* To get rid of annoying gcc warning */
133 data = 0;
134 break;
135 }
136 break;
137
138 case 02: /* 17773202, 17773206, 17773212 */
139 i = pro_int_check(pro_int_irr[cnum], pro_int_imr[cnum]);
140
141 if (i == PRO_NO_INT)
142 data = 0200; /* no int pending, return 0 in lsbs? */
143 else
144 data = i; /* int pending */
145
146 data = data | ((pro_int_mode[cnum] & 0001) << 5)
147 | ((pro_int_mode[cnum] & 0004) << 2)
148 | ((pro_int_mode[cnum] & 0200) >> 4);
149 break;
150
151 default:
152 data = 0;
153 break;
154 }
155
156 return data;
157 }
158
pro_int_wr(int data,int pa,int access)159 void pro_int_wr (int data, int pa, int access)
160 {
161 int cnum;
162
163 /* XXX byte accesses not handled correctly yet */
164
165 /* Determine controller number */
166
167 cnum = (pa >> 2) & 03;
168
169 switch (pa & 02)
170 {
171 case 00: /* 17773200, 17773204, 17773210 */
172 switch (pro_int_presel[cnum])
173 {
174 case PRO_PRESEL_IMR:
175 pro_int_imr[cnum] = data;
176 pro_int_update();
177 break;
178
179 case PRO_PRESEL_ACR:
180 pro_int_acr[cnum] = data;
181 break;
182
183 case PRO_PRESEL_RESP:
184 pro_int_vec[cnum][pro_int_presel_vec[cnum]] = data;
185 break;
186
187 default:
188 break;
189 }
190 break;
191
192 case 02: /* 17773202, 17773206, 17773212 */
193 if ((data & 0377) == 0) /* reset */
194 {
195 pro_int_presel[cnum] = 0;
196 pro_int_irr[cnum] = 0;
197 pro_int_isr[cnum] = 0;
198 pro_int_imr[cnum] = 0377;
199 pro_int_acr[cnum] = 0;
200 pro_int_mode[cnum] = 0;
201 pro_int_update();
202 break;
203 }
204 else
205 switch (data & 0370)
206 {
207 case 0020: /* clear irr and imr */
208 pro_int_irr[cnum] = 0;
209 pro_int_imr[cnum] = 0;
210 pro_int_update();
211 break;
212
213 case 0030: /* clear single irr and imr bit */
214 pro_clrbit(pro_int_irr[cnum], (data & 07));
215 pro_clrbit(pro_int_imr[cnum], (data & 07));
216 pro_int_update();
217 break;
218
219 case 0040: /* clear imr */
220 pro_int_imr[cnum] = 0;
221 pro_int_update();
222 break;
223
224 case 0050: /* clear single imr bit */
225 pro_clrbit(pro_int_imr[cnum], (data & 07));
226 pro_int_update();
227 break;
228
229 case 0060: /* set imr */
230 pro_int_imr[cnum] = 0377;
231 pro_int_update();
232 break;
233
234 case 0070: /* set single imr bit */
235 pro_setbit(pro_int_imr[cnum], (data & 07));
236 pro_int_update();
237 break;
238
239 case 0100: /* clear irr */
240 pro_int_irr[cnum] = 0;
241 pro_int_update();
242 break;
243
244 case 0110: /* clear single irr bit */
245 pro_clrbit(pro_int_irr[cnum], (data & 07));
246 pro_int_update();
247 break;
248
249 case 0120: /* set irr */
250 pro_int_irr[cnum] = 0377;
251 pro_int_update();
252 break;
253
254 case 0130: /* set single irr bit */
255 pro_setbit(pro_int_irr[cnum], (data & 07));
256 pro_int_update();
257 break;
258
259 case 0140: /* clear highest priority isr bit*/
260 case 0150:
261 /* XXX unimplemented */
262 printf("clear highest priority isr bit!!!!!!!\r\n");
263 break;
264
265 case 0160: /* clear isr */
266 pro_int_isr[cnum] = 0;
267 break;
268
269 case 0170: /* clear single isr bit */
270 pro_clrbit(pro_int_isr[cnum], (data & 07));
271 break;
272
273 case 0200: /* load mode bits m0 thru m4 */
274 case 0210:
275 case 0220:
276 case 0230:
277 pro_int_mode[cnum] = (pro_int_mode[cnum] & 0340) | (data & 0037);
278 pro_int_update();
279 /* XXX
280 if ((pro_int_mode[cnum] & PRO_INT_PM) != 0)
281 printf("%10.0f Warning: rotating priority not implemented in interrupt controller!\r\n", sim_gtime());
282 */
283 break;
284
285 case 0240: /* control mode bits m5 thru m7 */
286 case 0250:
287 pro_int_mode[cnum] = (pro_int_mode[cnum] & 0237) | ((data << 3) & 0140);
288
289 if ((data & 03) == 01)
290 pro_setbit(pro_int_mode[cnum], 7);
291 else if ((data & 03) == 02)
292 pro_clrbit(pro_int_mode[cnum], 7);
293 pro_int_update();
294 break;
295
296 case 0260: /* preselect imr for writing */
297 case 0270:
298 pro_int_presel[cnum] = PRO_PRESEL_IMR;
299 break;
300
301 case 0300: /* preselect acr for writing */
302 case 0310:
303 pro_int_presel[cnum] = PRO_PRESEL_ACR;
304 break;
305
306 case 0340: /* preselect response memory for writing */
307 pro_int_presel[cnum] = PRO_PRESEL_RESP;
308 pro_int_presel_vec[cnum] = (data & 07);
309 break;
310
311 default:
312 break;
313 }
314 break;
315
316 default:
317 break;
318 }
319 }
320
pro_int_ack(void)321 int pro_int_ack (void)
322 {
323 /* XXX handle case where no interrupt is set */
324 int cnum, intnum, vec;
325
326 for(cnum=0; cnum<=3; cnum++)
327 {
328 intnum = pro_int_check(pro_int_irr[cnum], pro_int_imr[cnum]);
329
330 if ((intnum != PRO_NO_INT) && ((pro_int_mode[cnum] & PRO_INT_MM) != 0)
331 && ((pro_int_mode[cnum] & PRO_INT_IM) == 0))
332 break;
333 }
334
335 /* Lookup interrupt vector to return */
336
337 if ((pro_int_mode[cnum] & PRO_INT_VS) != 0)
338 vec = pro_int_vec[cnum][0]; /* return common vector if VSS set */
339 else
340 vec = pro_int_vec[cnum][intnum];
341
342 /* Clear IRR bit */
343
344 pro_clrbit(pro_int_irr[cnum], intnum);
345
346 /* Set ISR bit if corresponding ACR bit is cleared */
347
348 if (((pro_int_acr[cnum] >> intnum) & 01) == 0)
349 pro_setbit(pro_int_isr[cnum], intnum);
350
351 /* Check if more interrupts are pending, set J11 int bit again, if so */
352
353 pro_int_update();
354
355 /* XXX */
356
357 #ifdef IOTRACE
358 fprintf(iotfptr, "%10.0lf Acknowledged interrupt with vector %o\r\n", sim_gtime(), vec);
359 fflush(iotfptr);
360 #endif
361
362 return vec;
363 }
364
pro_int_set(int intnum)365 void pro_int_set (int intnum)
366 {
367 int cnum, intbit;
368
369 /* Extract controller number and interrupt bit */
370
371 cnum = (intnum >> 8) & 0377;
372 intbit = intnum & 0377;
373
374 /* Set interrupt request */
375
376 /* XXX Does master mask mask this? */
377
378 pro_int_irr[cnum] |= intbit;
379
380 pro_int_update();
381
382 /* XXX */
383 /*
384 printf("%o %o %o %o %o\r\n",i, cnum, pro_int_irr[cnum], pro_int_imr[cnum], pro_int_mode[cnum]);
385 */
386 }
387
pro_int_reset()388 void pro_int_reset ()
389 {
390 int cnum;
391
392 for(cnum=0; cnum<=3; cnum++)
393 {
394 pro_int_presel[cnum] = 0;
395 pro_int_irr[cnum] = 0;
396 pro_int_isr[cnum] = 0;
397 pro_int_imr[cnum] = 0377;
398 pro_int_acr[cnum] = 0;
399 pro_int_mode[cnum] = 0;
400 pro_int_presel_vec[cnum] = 0;
401
402 pro_int_vec[cnum][0] = 0;
403 pro_int_vec[cnum][1] = 0;
404 pro_int_vec[cnum][2] = 0;
405 pro_int_vec[cnum][3] = 0;
406 pro_int_vec[cnum][4] = 0;
407 pro_int_vec[cnum][5] = 0;
408 pro_int_vec[cnum][6] = 0;
409 pro_int_vec[cnum][7] = 0;
410 }
411
412 /* Probably not necessary */
413
414 pro_int_update();
415 }
416 #endif
417