1 #include "ibm.h"
2 #include "io.h"
3 #include "pic.h"
4 #include "pit.h"
5 #include "video.h"
6
7 int output;
8 int intclear;
9 int keywaiting=0;
10 int pic_intpending;
11
pic_updatepending()12 void pic_updatepending()
13 {
14 if ((pic2.pend&~pic2.mask)&~pic2.mask2)
15 pic.pend |= (1 << 2);
16 else
17 pic.pend &= ~(1 << 2);
18 pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2;
19 if (!((pic.mask | pic.mask2) & (1 << 2)))
20 pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2);
21 /* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2);
22 pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2));*/
23 }
24
25
pic_reset()26 void pic_reset()
27 {
28 pic.icw=0;
29 pic.mask=0xFF;
30 pic.mask2=0;
31 pic.pend=pic.ins=0;
32 pic.vector=8;
33 pic.read=1;
34 pic2.icw=0;
35 pic2.mask=0xFF;
36 pic.mask2=0;
37 pic2.pend=pic2.ins=0;
38 pic_intpending = 0;
39 pic.level_sensitive = 0;
40 pic2.level_sensitive = 0;
41 }
42
pic_update_mask(uint8_t * mask,uint8_t ins)43 void pic_update_mask(uint8_t *mask, uint8_t ins)
44 {
45 int c;
46 *mask = 0;
47 for (c = 0; c < 8; c++)
48 {
49 if (ins & (1 << c))
50 {
51 *mask = 0xff << c;
52 return;
53 }
54 }
55 }
56
pic_autoeoi()57 static void pic_autoeoi()
58 {
59 int c;
60
61 for (c=0;c<8;c++)
62 {
63 if (pic.ins&(1<<c))
64 {
65 pic.ins&=~(1<<c);
66 pic_update_mask(&pic.mask2, pic.ins);
67
68 if (c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
69 pic.pend |= (1 << 2);
70
71 pic_updatepending();
72 return;
73 }
74 }
75 }
76
pic_write(uint16_t addr,uint8_t val,void * priv)77 void pic_write(uint16_t addr, uint8_t val, void *priv)
78 {
79 int c;
80 // pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc);
81 if (addr&1)
82 {
83 switch (pic.icw)
84 {
85 case 0: /*OCW1*/
86 // printf("Write mask %02X %04X:%04X\n",val,CS,pc);
87 pic.mask=val;
88 pic_updatepending();
89 break;
90 case 1: /*ICW2*/
91 pic.vector=val&0xF8;
92 // printf("PIC vector now %02X\n",pic.vector);
93 // output=1;
94 if (pic.icw1&2) pic.icw=3;
95 else pic.icw=2;
96 break;
97 case 2: /*ICW3*/
98 if (pic.icw1&1) pic.icw=3;
99 else pic.icw=0;
100 break;
101 case 3: /*ICW4*/
102 pic.icw4 = val;
103 // pclog("ICW4 = %02x\n", val);
104 pic.icw=0;
105 break;
106 }
107 }
108 else
109 {
110 if (val&16) /*ICW1*/
111 {
112 pic.mask = 0;
113 pic.mask2=0;
114 pic.icw=1;
115 pic.icw1=val;
116 pic.ins = 0;
117 pic_updatepending();
118 }
119 else if (!(val&8)) /*OCW2*/
120 {
121 // printf("Clear ints - %02X %02X\n",pic.ins,val);
122 if ((val&0xE0)==0x60)
123 {
124 // pclog("Specific EOI - %02X %i\n",pic.ins,1<<(val&7));
125 pic.ins&=~(1<<(val&7));
126 pic_update_mask(&pic.mask2, pic.ins);
127 if (val == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
128 pic.pend |= (1 << 2);
129 // pic.pend&=(1<<(val&7));
130 // if ((val&7)==1) pollkeywaiting();
131 pic_updatepending();
132 }
133 else
134 {
135 for (c=0;c<8;c++)
136 {
137 if (pic.ins&(1<<c))
138 {
139 pic.ins&=~(1<<c);
140 pic_update_mask(&pic.mask2, pic.ins);
141
142 if (c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
143 pic.pend |= (1 << 2);
144
145 if (c==1 && keywaiting)
146 {
147 intclear&=~1;
148 // pollkeywaiting();
149 }
150 pic_updatepending();
151 // pclog("Generic EOI - Cleared int %i\n",c);
152 return;
153 }
154 }
155 }
156 }
157 else /*OCW3*/
158 {
159 // if (val&4) fatal("PIC1 write OCW3 4 %02X\n",val);
160 if (val&2) pic.read=(val&1);
161 if (val&0x40) { } //fatal("PIC 1 write OCW3 40 %02X\n",val);
162 }
163 }
164 }
165
pic_read(uint16_t addr,void * priv)166 uint8_t pic_read(uint16_t addr, void *priv)
167 {
168 if (addr&1) { /*pclog("Read PIC mask %02X\n",pic.mask);*/ return pic.mask; }
169 if (pic.read) { /*pclog("Read PIC ins %02X\n",pic.ins);*/ return pic.ins | (pic2.ins ? 4 : 0); }
170 // pclog("Read PIC pend %02X %08X\n",pic.pend,EDX);
171 return pic.pend;
172 }
173
pic_init()174 void pic_init()
175 {
176 io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL);
177 }
178
pic2_autoeoi()179 static void pic2_autoeoi()
180 {
181 int c;
182
183 for (c = 0; c < 8; c++)
184 {
185 if (pic2.ins & (1 << c))
186 {
187 pic2.ins &= ~(1 << c);
188 pic_update_mask(&pic2.mask2, pic2.ins);
189
190 pic_updatepending();
191 return;
192 }
193 }
194 }
195
pic2_write(uint16_t addr,uint8_t val,void * priv)196 void pic2_write(uint16_t addr, uint8_t val, void *priv)
197 {
198 int c;
199 // pclog("Write PIC2 %04X %02X %04X:%04X %i\n",addr,val,CS,pc,ins);
200 if (addr&1)
201 {
202 switch (pic2.icw)
203 {
204 case 0: /*OCW1*/
205 // printf("PIC2 Write mask %02X %04X:%04X\n",val,CS,pc);
206 pic2.mask=val;
207 pic_updatepending();
208 break;
209 case 1: /*ICW2*/
210 pic2.vector=val&0xF8;
211 // pclog("PIC2 vector %02X\n", val & 0xf8);
212 if (pic2.icw1&2) pic2.icw=3;
213 else pic2.icw=2;
214 break;
215 case 2: /*ICW3*/
216 if (pic2.icw1&1) pic2.icw=3;
217 else pic2.icw=0;
218 break;
219 case 3: /*ICW4*/
220 pic2.icw4 = val;
221 pic2.icw=0;
222 break;
223 }
224 }
225 else
226 {
227 if (val&16) /*ICW1*/
228 {
229 pic2.mask = 0;
230 pic2.mask2=0;
231 pic2.icw=1;
232 pic2.icw1=val;
233 pic2.ins = 0;
234 pic_updatepending();
235 }
236 else if (!(val&8)) /*OCW2*/
237 {
238 if ((val&0xE0)==0x60)
239 {
240 pic2.ins&=~(1<<(val&7));
241 pic_update_mask(&pic2.mask2, pic2.ins);
242
243 pic_updatepending();
244 }
245 else
246 {
247 for (c=0;c<8;c++)
248 {
249 if (pic2.ins&(1<<c))
250 {
251 pic2.ins &= ~(1<<c);
252 pic_update_mask(&pic2.mask2, pic2.ins);
253
254 pic_updatepending();
255 return;
256 }
257 }
258 }
259 }
260 else /*OCW3*/
261 {
262 if (val&2) pic2.read=(val&1);
263 }
264 }
265 }
266
pic2_read(uint16_t addr,void * priv)267 uint8_t pic2_read(uint16_t addr, void *priv)
268 {
269 if (addr&1) { /*pclog("Read PIC2 mask %02X %04X:%08X\n",pic2.mask,CS,pc);*/ return pic2.mask; }
270 if (pic2.read) { /*pclog("Read PIC2 ins %02X %04X:%08X\n",pic2.ins,CS,pc);*/ return pic2.ins; }
271 /*pclog("Read PIC2 pend %02X %04X:%08X\n",pic2.pend,CS,pc);*/
272 return pic2.pend;
273 }
274
pic2_init()275 void pic2_init()
276 {
277 io_sethandler(0x00a0, 0x0002, pic2_read, NULL, NULL, pic2_write, NULL, NULL, NULL);
278 }
279
pic_elcrx_read(uint16_t addr,void * p)280 static uint8_t pic_elcrx_read(uint16_t addr, void *p)
281 {
282 uint8_t temp = 0xff;
283
284 switch (addr)
285 {
286 case 0x4d0:
287 temp = pic.level_sensitive;
288 break;
289 case 0x4d1:
290 temp = pic2.level_sensitive;
291 break;
292 }
293
294 return temp;
295 }
296
pic_elcrx_write(uint16_t addr,uint8_t val,void * p)297 static void pic_elcrx_write(uint16_t addr, uint8_t val, void *p)
298 {
299 // pclog("pic_elcrx_write: addr=%04x val=%02x\n", addr, val);
300 switch (addr)
301 {
302 case 0x4d0:
303 pic.level_sensitive = val & 0xf8;
304 break;
305 case 0x4d1:
306 pic2.level_sensitive = val & 0xde;
307 break;
308 }
309 }
310
pic_init_elcrx()311 void pic_init_elcrx()
312 {
313 io_sethandler(0x04d0, 0x0002, pic_elcrx_read, NULL, NULL, pic_elcrx_write, NULL, NULL, NULL);
314 }
315
clearpic()316 void clearpic()
317 {
318 pic.pend=pic.ins=0;
319 pic_updatepending();
320 // pclog("Clear PIC\n");
321 }
322
323 int pic_current[16];
324
picint(uint16_t num)325 void picint(uint16_t num)
326 {
327 if (AT && num == (1 << 2))
328 num = 1 << 9;
329 // pclog("picint : %04X\n", num);
330 // if (num == 0x10) pclog("PICINT 10\n");
331 if (num>0xFF)
332 {
333 pic2.pend|=(num>>8);
334 if ((pic2.pend&~pic2.mask)&~pic2.mask2)
335 pic.pend |= (1 << 2);
336 }
337 else
338 {
339 pic.pend|=num;
340 }
341 // pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend);
342 pic_updatepending();
343 }
344
picintlevel(uint16_t num)345 void picintlevel(uint16_t num)
346 {
347 int c = 0;
348 while (!(num & (1 << c))) c++;
349 if (AT && c == 2)
350 {
351 c = 9;
352 num = 1 << 9;
353 }
354 // pclog("INTLEVEL %04X %i\n", num, c);
355 if (!pic_current[c])
356 {
357 pic_current[c]=1;
358 if (num>0xFF)
359 {
360 pic2.pend|=(num>>8);
361 }
362 else
363 {
364 pic.pend|=num;
365 }
366 }
367 pic_updatepending();
368 }
picintc(uint16_t num)369 void picintc(uint16_t num)
370 {
371 int c = 0;
372 if (!num)
373 return;
374 while (!(num & (1 << c))) c++;
375 if (AT && c == 2)
376 {
377 c = 9;
378 num = 1 << 9;
379 }
380 // pclog("INTC %04X %i\n", num, c);
381 pic_current[c]=0;
382
383 if (num > 0xff)
384 {
385 pic2.pend &= ~(num >> 8);
386 if (!((pic2.pend&~pic2.mask)&~pic2.mask2))
387 pic.pend &= ~(1 << 2);
388 }
389 else
390 {
391 pic.pend&=~num;
392 }
393 pic_updatepending();
394 }
395
picinterrupt()396 uint8_t picinterrupt()
397 {
398 uint8_t temp=pic.pend&~pic.mask;
399 int c;
400 for (c = 0; c < 2; c++)
401 {
402 if (temp & (1 << c))
403 {
404 if (!(pic.level_sensitive & (1 << c)))
405 pic.pend &= ~(1 << c);
406 pic.ins |= (1 << c);
407 pic_update_mask(&pic.mask2, pic.ins);
408
409 pic_updatepending();
410 if (!c)
411 pit_set_gate(&pit2, 0, 0);
412
413 if (pic.icw4 & 0x02)
414 pic_autoeoi();
415
416 return c+pic.vector;
417 }
418 }
419 if (temp & (1 << 2))
420 {
421 uint8_t temp2 = pic2.pend & ~pic2.mask;
422 for (c = 0; c < 8; c++)
423 {
424 if (temp2 & (1 << c))
425 {
426 if (!(pic2.level_sensitive & (1 << c)))
427 pic2.pend &= ~(1 << c);
428 pic2.ins |= (1 << c);
429 pic_update_mask(&pic2.mask2, pic2.ins);
430
431 if (!(pic2.level_sensitive & (1 << c)))
432 pic.pend &= ~(1 << c);
433 pic.ins |= (1 << 2); /*Cascade IRQ*/
434 pic_update_mask(&pic.mask2, pic.ins);
435
436 pic_updatepending();
437
438 if (pic2.icw4 & 0x02)
439 pic2_autoeoi();
440
441 return c+pic2.vector;
442 }
443 }
444 }
445 for (c = 3; c < 8; c++)
446 {
447 if (temp & (1 << c))
448 {
449 if (!(pic.level_sensitive & (1 << c)))
450 pic.pend &= ~(1 << c);
451 pic.ins |= (1 << c);
452 pic_update_mask(&pic.mask2, pic.ins);
453 pic_updatepending();
454
455 if (pic.icw4 & 0x02)
456 pic_autoeoi();
457
458 return c+pic.vector;
459 }
460 }
461 return 0xFF;
462 }
463
dumppic()464 void dumppic()
465 {
466 pclog("PIC1 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic.mask,pic.pend,pic.ins,pic.vector);
467 pclog("PIC2 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic2.mask,pic2.pend,pic2.ins,pic2.vector);
468 }
469
470