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