#include "ibm.h" #include "io.h" #include "pic.h" int output; int intclear; int keywaiting=0; int pic_intpending; void pic_updatepending() { 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))) pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2); /* 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; return; } } } void pic_write(uint16_t addr, uint8_t val, void *priv) { int c; // pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc); if (addr&1) { switch (pic.icw) { case 0: /*OCW1*/ // printf("Write mask %02X %04X:%04X\n",val,CS,pc); pic.mask=val; pic_updatepending(); break; case 1: /*ICW2*/ pic.vector=val&0xF8; // printf("PIC vector now %02X\n",pic.vector); // output=1; if (pic.icw1&2) pic.icw=3; else pic.icw=2; break; case 2: /*ICW3*/ if (pic.icw1&1) pic.icw=3; else pic.icw=0; break; case 3: /*ICW4*/ pic.icw=0; break; } } else { if (val&16) /*ICW1*/ { pic.mask=0xFF; pic.mask2=0; pic.icw=1; pic.icw1=val; pic_updatepending(); } else if (!(val&8)) /*OCW2*/ { // printf("Clear ints - %02X %02X\n",pic.ins,val); if ((val&0xE0)==0x60) { // pclog("Specific EOI - %02X %i\n",pic.ins,1<<(val&7)); pic.ins&=~(1<<(val&7)); pic_update_mask(&pic.mask2, pic.ins); if (val == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2) pic.pend |= (1 << 2); // pic.pend&=(1<<(val&7)); // if ((val&7)==1) pollkeywaiting(); pic_updatepending(); } else { 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; } // pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend); pic_updatepending(); } 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(); 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(); 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(); 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); }