#include "ibm.h" #include "io.h" #include "pic.h" int output; int intclear; int keywaiting=0; int pic_intpending; void pic_updatepending() { uint16_t temp_pending = 0; if ((pic2.pend&~pic2.mask)&~pic2.mask2) pic.pend |= (1 << 2); else pic.pend &= ~(1 << 2); pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; if (!((pic.mask | pic.mask2) & (1 << 2))) { temp_pending = ((pic2.pend&~pic2.mask)&~pic2.mask2); temp_pending <<= 8; pic_intpending |= temp_pending; } /* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2); 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)); */ } void pic_reset() { pic.icw=0; pic.mask=0xFF; pic.mask2=0; pic.pend=pic.ins=0; pic.vector=8; pic.read=1; pic2.icw=0; pic2.mask=0xFF; pic.mask2=0; pic2.pend=pic2.ins=0; pic_intpending = 0; } void pic_update_mask(uint8_t *mask, uint8_t ins) { int c; *mask = 0; for (c = 0; c < 8; c++) { if (ins & (1 << c)) { *mask = 0xff << c; // pclog("Mask is: %02X\n", *mask); return; } } } static void pic_autoeoi() { int c; for (c=0;c<8;c++) { if (pic.ins&(1<0xFF) { pic2.pend|=(num>>8); if ((pic2.pend&~pic2.mask)&~pic2.mask2) pic.pend |= (1 << 2); } else { pic.pend|=num; } /* if (num == 0x40) { pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend); } */ pic_updatepending(); /* if (num == 0x40) { pclog("Processing FDC interrupt, pending: %s, previously pending: %s, masked: %s, masked (2): %s, T: %s, I: %s\n", (pic_intpending & num) ? "yes" : "no", (old_pend & num) ? "yes" : "no", (pic.mask & num) ? "yes" : "no", (pic.mask2 & num) ? "yes" : "no", (flags & 0x100) ? "yes" : "no", (flags&I_FLAG) ? "yes" : "no"); } */ } void picintlevel(uint16_t num) { int c = 0; while (!(num & (1 << c))) c++; if (AT && c == 2) { c = 9; num = 1 << 9; } // pclog("INTLEVEL %04X %i\n", num, c); if (!pic_current[c]) { pic_current[c]=1; if (num>0xFF) { pic2.pend|=(num>>8); } else { pic.pend|=num; } } pic_updatepending(); } void picintc(uint16_t num) { int c = 0; if (!num) return; while (!(num & (1 << c))) c++; if (AT && c == 2) { c = 9; num = 1 << 9; } // pclog("INTC %04X %i\n", num, c); pic_current[c]=0; if (num > 0xff) { pic2.pend &= ~(num >> 8); if (!((pic2.pend&~pic2.mask)&~pic2.mask2)) pic.pend &= ~(1 << 2); } else { pic.pend&=~num; } pic_updatepending(); } uint8_t picinterrupt() { uint8_t temp=pic.pend&~pic.mask; int c; for (c = 0; c < 2; c++) { if (temp & (1 << c)) { pic.pend &= ~(1 << c); pic.ins |= (1 << c); pic_update_mask(&pic.mask2, pic.ins); pic_updatepending(); if (pic.icw4 & 0x02) pic_autoeoi(); return c+pic.vector; } } if (temp & (1 << 2)) { uint8_t temp2 = pic2.pend & ~pic2.mask; for (c = 0; c < 8; c++) { if (temp2 & (1 << c)) { pic2.pend &= ~(1 << c); pic2.ins |= (1 << c); pic_update_mask(&pic2.mask2, pic2.ins); pic.pend &= ~(1 << c); pic.ins |= (1 << 2); /*Cascade IRQ*/ pic_update_mask(&pic.mask2, pic.ins); pic_updatepending(); if (pic2.icw4 & 0x02) pic2_autoeoi(); return c+pic2.vector; } } } for (c = 3; c < 8; c++) { if (temp & (1 << c)) { pic.pend &= ~(1 << c); pic.ins |= (1 << c); pic_update_mask(&pic.mask2, pic.ins); pic_updatepending(); if (pic.icw4 & 0x02) pic_autoeoi(); return c+pic.vector; } } return 0xFF; } void dumppic() { pclog("PIC1 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic.mask,pic.pend,pic.ins,pic.vector); pclog("PIC2 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic2.mask,pic2.pend,pic2.ins,pic2.vector); }