PCem

view src/pic.c @ 113:f749363ad763

Added per-device configuration. Reworked configuration parser a bit. Added configuration for S3 ViRGE and 8-bit Sound Blasters. IRQ 2 routed to IRQ 9 on AT machines.
author TomW
date Mon Jun 30 21:31:28 2014 +0100
parents c63d59bbff1e
children 21f926f1fabf
line source
1 #include "ibm.h"
2 #include "io.h"
3 #include "pic.h"
5 int output;
6 int intclear;
7 int keywaiting=0;
8 int pic_intpending;
10 void pic_updatepending()
11 {
12 if ((pic2.pend&~pic2.mask)&~pic2.mask2)
13 pic.pend |= (1 << 2);
14 else
15 pic.pend &= ~(1 << 2);
16 pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2;
17 if (!((pic.mask | pic.mask2) & (1 << 2)))
18 pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2);
19 /* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2);
20 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));*/
21 }
24 void pic_reset()
25 {
26 pic.icw=0;
27 pic.mask=0xFF;
28 pic.mask2=0;
29 pic.pend=pic.ins=0;
30 pic.vector=8;
31 pic.read=1;
32 pic2.icw=0;
33 pic2.mask=0xFF;
34 pic.mask2=0;
35 pic2.pend=pic2.ins=0;
36 pic_intpending = 0;
37 }
39 void pic_update_mask(uint8_t *mask, uint8_t ins)
40 {
41 int c;
42 *mask = 0;
43 for (c = 0; c < 8; c++)
44 {
45 if (ins & (1 << c))
46 {
47 *mask = 0xff << c;
48 return;
49 }
50 }
51 }
53 void pic_write(uint16_t addr, uint8_t val, void *priv)
54 {
55 int c;
56 // pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc);
57 if (addr&1)
58 {
59 switch (pic.icw)
60 {
61 case 0: /*OCW1*/
62 // printf("Write mask %02X %04X:%04X\n",val,CS,pc);
63 pic.mask=val;
64 pic_updatepending();
65 break;
66 case 1: /*ICW2*/
67 pic.vector=val&0xF8;
68 // printf("PIC vector now %02X\n",pic.vector);
69 // output=1;
70 if (pic.icw1&2) pic.icw=3;
71 else pic.icw=2;
72 break;
73 case 2: /*ICW3*/
74 if (pic.icw1&1) pic.icw=3;
75 else pic.icw=0;
76 break;
77 case 3: /*ICW4*/
78 pic.icw=0;
79 break;
80 }
81 }
82 else
83 {
84 if (val&16) /*ICW1*/
85 {
86 pic.mask=0xFF;
87 pic.mask2=0;
88 pic.icw=1;
89 pic.icw1=val;
90 pic_updatepending();
91 }
92 else if (!(val&8)) /*OCW2*/
93 {
94 // printf("Clear ints - %02X %02X\n",pic.ins,val);
95 if ((val&0xE0)==0x60)
96 {
97 // pclog("Specific EOI - %02X %i\n",pic.ins,1<<(val&7));
98 pic.ins&=~(1<<(val&7));
99 pic_update_mask(&pic.mask2, pic.ins);
100 if (val == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
101 pic.pend |= (1 << 2);
102 // pic.pend&=(1<<(val&7));
103 // if ((val&7)==1) pollkeywaiting();
104 pic_updatepending();
105 }
106 else
107 {
108 for (c=0;c<8;c++)
109 {
110 if (pic.ins&(1<<c))
111 {
112 pic.ins&=~(1<<c);
113 pic_update_mask(&pic.mask2, pic.ins);
115 if (c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
116 pic.pend |= (1 << 2);
118 // pic.pend&=~(1<<c);
119 if (c==1 && keywaiting)
120 {
121 intclear&=~1;
122 // pollkeywaiting();
123 }
124 pic_updatepending();
125 // pclog("Generic EOI - Cleared int %i\n",c);
126 return;
127 }
128 }
129 }
130 }
131 else /*OCW3*/
132 {
133 // if (val&4) fatal("PIC1 write OCW3 4 %02X\n",val);
134 if (val&2) pic.read=(val&1);
135 if (val&0x40) { } //fatal("PIC 1 write OCW3 40 %02X\n",val);
136 }
137 }
138 }
140 uint8_t pic_read(uint16_t addr, void *priv)
141 {
142 if (addr&1) { /*pclog("Read PIC mask %02X\n",pic.mask);*/ return pic.mask; }
143 if (pic.read) { /*pclog("Read PIC ins %02X\n",pic.ins);*/ return pic.ins | (pic2.ins ? 4 : 0); }
144 // pclog("Read PIC pend %02X %08X\n",pic.pend,EDX);
145 return pic.pend;
146 }
148 void pic_init()
149 {
150 io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL);
151 }
153 void pic2_write(uint16_t addr, uint8_t val, void *priv)
154 {
155 int c;
156 // pclog("Write PIC2 %04X %02X %04X:%04X %i\n",addr,val,CS,pc,ins);
157 if (addr&1)
158 {
159 switch (pic2.icw)
160 {
161 case 0: /*OCW1*/
162 // printf("PIC2 Write mask %02X %04X:%04X\n",val,CS,pc);
163 pic2.mask=val;
164 pic_updatepending();
165 break;
166 case 1: /*ICW2*/
167 pic2.vector=val&0xF8;
168 // pclog("PIC2 vector %02X\n", val & 0xf8);
169 if (pic2.icw1&2) pic2.icw=3;
170 else pic2.icw=2;
171 break;
172 case 2: /*ICW3*/
173 if (pic2.icw1&1) pic2.icw=3;
174 else pic2.icw=0;
175 break;
176 case 3: /*ICW4*/
177 pic2.icw=0;
178 break;
179 }
180 }
181 else
182 {
183 if (val&16) /*ICW1*/
184 {
185 pic2.mask=0xFF;
186 pic2.mask2=0;
187 pic2.icw=1;
188 pic2.icw1=val;
189 pic_updatepending();
190 }
191 else if (!(val&8)) /*OCW2*/
192 {
193 if ((val&0xE0)==0x60)
194 {
195 pic2.ins&=~(1<<(val&7));
196 pic_update_mask(&pic2.mask2, pic2.ins);
198 pic_updatepending();
199 }
200 else
201 {
202 for (c=0;c<8;c++)
203 {
204 if (pic2.ins&(1<<c))
205 {
206 pic2.ins &= ~(1<<c);
207 pic_update_mask(&pic2.mask2, pic2.ins);
209 pic_updatepending();
210 return;
211 }
212 }
213 }
214 }
215 else /*OCW3*/
216 {
217 if (val&2) pic2.read=(val&1);
218 }
219 }
220 }
222 uint8_t pic2_read(uint16_t addr, void *priv)
223 {
224 if (addr&1) { /*pclog("Read PIC2 mask %02X %04X:%08X\n",pic2.mask,CS,pc);*/ return pic2.mask; }
225 if (pic2.read) { /*pclog("Read PIC2 ins %02X %04X:%08X\n",pic2.ins,CS,pc);*/ return pic2.ins; }
226 /*pclog("Read PIC2 pend %02X %04X:%08X\n",pic2.pend,CS,pc);*/
227 return pic2.pend;
228 }
230 void pic2_init()
231 {
232 io_sethandler(0x00a0, 0x0002, pic2_read, NULL, NULL, pic2_write, NULL, NULL, NULL);
233 }
236 void clearpic()
237 {
238 pic.pend=pic.ins=0;
239 pic_updatepending();
240 // pclog("Clear PIC\n");
241 }
243 int pic_current[16];
245 void picint(uint16_t num)
246 {
247 if (AT && num == (1 << 2))
248 num = 1 << 9;
249 // pclog("picint : %04X\n", num);
250 // if (num == 0x10) pclog("PICINT 10\n");
251 if (num>0xFF)
252 {
253 pic2.pend|=(num>>8);
254 if ((pic2.pend&~pic2.mask)&~pic2.mask2)
255 pic.pend |= (1 << 2);
256 }
257 else
258 {
259 pic.pend|=num;
260 }
261 // pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend);
262 pic_updatepending();
263 }
265 void picintlevel(uint16_t num)
266 {
267 int c = 0;
268 while (!(num & (1 << c))) c++;
269 if (AT && c == 2)
270 {
271 c = 9;
272 num = 1 << 9;
273 }
274 // pclog("INTLEVEL %04X %i\n", num, c);
275 if (!pic_current[c])
276 {
277 pic_current[c]=1;
278 if (num>0xFF)
279 {
280 pic2.pend|=(num>>8);
281 }
282 else
283 {
284 pic.pend|=num;
285 }
286 }
287 pic_updatepending();
288 }
289 void picintc(uint16_t num)
290 {
291 int c = 0;
292 while (!(num & (1 << c))) c++;
293 if (AT && c == 2)
294 {
295 c = 9;
296 num = 1 << 9;
297 }
298 // pclog("INTC %04X %i\n", num, c);
299 pic_current[c]=0;
301 if (num > 0xff)
302 {
303 pic2.pend &= ~(num >> 8);
304 if (!((pic2.pend&~pic2.mask)&~pic2.mask2))
305 pic.pend &= ~(1 << 2);
306 }
307 else
308 {
309 pic.pend&=~num;
310 }
311 pic_updatepending();
312 }
314 uint8_t picinterrupt()
315 {
316 uint8_t temp=pic.pend&~pic.mask;
317 int c;
318 for (c = 0; c < 2; c++)
319 {
320 if (temp & (1 << c))
321 {
322 pic.pend &= ~(1 << c);
323 pic.ins |= (1 << c);
324 pic_update_mask(&pic.mask2, pic.ins);
325 pic_updatepending();
326 return c+pic.vector;
327 }
328 }
329 if (temp & (1 << 2))
330 {
331 uint8_t temp2 = pic2.pend & ~pic2.mask;
332 for (c = 0; c < 8; c++)
333 {
334 if (temp2 & (1 << c))
335 {
336 pic2.pend &= ~(1 << c);
337 pic2.ins |= (1 << c);
338 pic_update_mask(&pic2.mask2, pic2.ins);
340 pic.pend &= ~(1 << c);
341 pic.ins |= (1 << 2); /*Cascade IRQ*/
342 pic_update_mask(&pic.mask2, pic.ins);
344 pic_updatepending();
345 return c+pic2.vector;
346 }
347 }
348 }
349 for (c = 3; c < 8; c++)
350 {
351 if (temp & (1 << c))
352 {
353 pic.pend &= ~(1 << c);
354 pic.ins |= (1 << c);
355 pic_update_mask(&pic.mask2, pic.ins);
356 pic_updatepending();
357 return c+pic.vector;
358 }
359 }
360 return 0xFF;
361 }
363 void dumppic()
364 {
365 pclog("PIC1 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic.mask,pic.pend,pic.ins,pic.vector);
366 pclog("PIC2 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic2.mask,pic2.pend,pic2.ins,pic2.vector);
367 }