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