--- np2/io/pic.c 2003/11/30 11:20:55 1.6 +++ np2/io/pic.c 2007/11/03 00:00:20 1.22 @@ -1,223 +1,169 @@ #include "compiler.h" -#include "i286.h" +#include "cpucore.h" #include "pccore.h" #include "iocore.h" +enum { + PIC_OCW2_L = 0x07, + PIC_OCW2_EOI = 0x20, + PIC_OCW2_SL = 0x40, + PIC_OCW2_R = 0x80, + + PIC_OCW3_RIS = 0x01, + PIC_OCW3_RR = 0x02, + PIC_OCW3_P = 0x04, + PIC_OCW3_SMM = 0x20, + PIC_OCW3_ESMM = 0x40 +}; + + static const _PICITEM def_master = { - 0, {0, 0, 0, 0, 0, 0, 0, 0}, - 0, {0, 0, 0, 0, 0, 0, 0, 0}, - {7, 6, 5, 4, 3, 2, 1, 0}, - {0, 0x08, 0x00, 0}, - 0x7d, 0, 0, 0, - 0, 0, 0, 0}; + {0x11, 0x08, 0x80, 0x1d}, + 0x7d, 0, 0, 0, 0, 0}; static const _PICITEM def_slave = { - 0, {0, 0, 0, 0, 0, 0, 0, 0}, - 0, {0, 0, 0, 0, 0, 0, 0, 0}, - {7, 6, 5, 4, 3, 2, 1, 0}, - {0, 0x10, 0x07, 0}, - 0x70, 0, 0, 0, - 0, 0, 0, 0}; - + {0x11, 0x10, 0x07, 0x09}, + 0x71, 0, 0, 0, 0, 0}; -// ------------------------------------------------------------ ext. interrupt -// 外部でISRを待避する割り込み対策 +// ---- -void extirq_push(void) { +#if 0 // スレーブがおかしい… +void pic_irq(void) { PIC p; - - p = &pic; - if (!p->ext_irq) { - p->ext_irq = 1; - - p->pi[0].levelsbak = p->pi[0].levels; - *(UINT32 *)(p->pi[0].levelbak+0) = *(UINT32 *)(p->pi[0].level+0); - *(UINT32 *)(p->pi[0].levelbak+4) = *(UINT32 *)(p->pi[0].level+4); - p->pi[0].isrbak = p->pi[0].isr; - - p->pi[1].levelsbak = p->pi[1].levels; - *(UINT32 *)(p->pi[1].levelbak+0) = *(UINT32 *)(p->pi[1].level+0); - *(UINT32 *)(p->pi[1].levelbak+4) = *(UINT32 *)(p->pi[1].level+4); - p->pi[1].isrbak = p->pi[1].isr; + REG8 mir; + REG8 sir; + REG8 dat; + REG8 num; + REG8 bit; + REG8 slave; + + // 割込み許可? + if (!CPU_isEI) { + return; } -} - - -void extirq_pop(void) { - - PIC p; - p = &pic; - if (p->ext_irq) { - p->ext_irq = 0; - - p->pi[0].levels = p->pi[0].levelsbak; - *(UINT32 *)(p->pi[0].level+0) = *(UINT32 *)(p->pi[0].levelbak+0); - *(UINT32 *)(p->pi[0].level+4) = *(UINT32 *)(p->pi[0].levelbak+4); - p->pi[0].isr = p->pi[0].isrbak; - - p->pi[1].levels = p->pi[1].levelsbak; - *(UINT32 *)(p->pi[1].level+0) = *(UINT32 *)(p->pi[1].levelbak+0); - *(UINT32 *)(p->pi[1].level+4) = *(UINT32 *)(p->pi[1].levelbak+4); - p->pi[1].isr = p->pi[1].isrbak; - } -} - - -// --------------------------- - -static void pic_rolpry(PICITEM pi) { - // あははーっ 酷いね…こりゃ - *(UINT32 *)(&pi->pry[0]) = - (*(UINT32 *)(&pi->pry[0]) + 0x01010101) & 0x07070707; - *(UINT32 *)(&pi->pry[4]) = - (*(UINT32 *)(&pi->pry[4]) + 0x01010101) & 0x07070707; -} - - -static void pic_downbylevel(PICITEM picp, BYTE level) { - - int i; - - for (i=0; i<8; i++) { - if (picp->pry[i] < picp->pry[level]) { - (picp->pry[i])++; + mir = p->pi[0].irr & (~p->pi[0].imr); + sir = p->pi[1].irr & (~p->pi[1].imr); + if ((mir == 0) && (sir == 0)) { + return; + } + + slave = 1 << (p->pi[1].icw[2] & 7); + dat = mir; + if (sir) { + dat |= slave & (~p->pi[0].imr); + } + if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { + dat |= p->pi[0].isr; + } + num = p->pi[0].pry; + bit = 1 << num; + while(!(dat & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (p->pi[0].icw[2] & bit) { // スレーヴ + dat = sir; + if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { + dat |= p->pi[1].isr; + } + num = p->pi[1].pry; + bit = 1 << num; + while(!(dat & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (!(p->pi[1].isr & bit)) { + p->pi[0].isr |= slave; + p->pi[0].irr &= ~slave; + p->pi[1].isr |= bit; + p->pi[1].irr &= ~bit; + TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); + CPU_INTERRUPT((REG8)((p->pi[1].icw[1] & 0xf8) | num), 0); + } + } + else if (!(p->pi[0].isr & bit)) { // マスター + p->pi[0].isr |= bit; + p->pi[0].irr &= ~bit; + if (num == 0) { + nevent_reset(NEVENT_PICMASK); } + TRACEOUT(("hardware-int %.2x [%.4x:%.4x]", (p->pi[0].icw[1] & 0xf8) | num, CPU_CS, CPU_IP)); + CPU_INTERRUPT((REG8)((p->pi[0].icw[1] & 0xf8) | num), 0); } - picp->pry[level] = 0; } +#else +void pic_irq(void) { // ver0.78 - -// eoi処理 -static void pic_forceeoibylevel(PICITEM picp, BYTE level) { - - int i; - - if (picp->isr & (1 << level)) { - picp->isr &= ~(1 << level); - (picp->levels)--; - for (i=0; (ilevels) && (picp->level[i] != level); i++) { } - for (; ilevels; i++) { - picp->level[i] = picp->level[i+1]; - } - } -} - - -void pic_irq(void) { - - int i; - BYTE bit; - char pry; - BYTE irq; - BYTE sirq; - BYTE targetbit; PIC p; - + REG8 mir; + REG8 sir; + REG8 num; + REG8 bit; + REG8 slave; + + // 割込み許可? + if (!CPU_isEI) { + return; + } p = &pic; - // 割込み許可で 要求あり? - if ((isI286EI) && (!p->ext_irq) && - ((p->pi[0].irr & (~p->pi[0].imr)) || - (p->pi[1].irr & (~p->pi[1].imr)))) { - - // マスターの処理 - if (!p->pi[0].levels) { - pry = -1; - } - else { - pry = (char)p->pi[0].pry[p->pi[0].level[p->pi[0].levels - 1]]; - } - irq = 0xff; - targetbit = 0; - for (bit=1, i=0; bit; bit<<=1, i++) { - if ((p->pi[0].irr & bit) && - (!((p->pi[0].imr | p->pi[0].isr) & bit))) { - if ((char)p->pi[0].pry[i] > pry) { - pry = p->pi[0].pry[i]; - irq = (BYTE)i; - targetbit = bit; - } - } - } - // スレーヴの要求はある? - if (!(p->pi[1].irr & (~p->pi[1].imr))) { - sirq = 0xff; - } - else { - sirq = p->pi[1].icw[2] & 7; - bit = 1 << sirq; - if (!((p->pi[0].imr | p->pi[0].isr) & bit)) { - if ((char)p->pi[0].pry[sirq] > pry) { - irq = sirq; - targetbit = bit; - } - } + sir = p->pi[1].irr & (~p->pi[1].imr); + slave = 1 << (p->pi[1].icw[2] & 7); + mir = p->pi[0].irr; + if (sir) { + mir |= slave; + } + mir &= (~p->pi[0].imr); + if (mir == 0) { + return; + } + if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { + mir |= p->pi[0].isr; + } + num = p->pi[0].pry; + bit = 1 << num; + while(!(mir & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (p->pi[0].icw[2] & bit) { // スレーヴ + if (sir == 0) { + return; } - // マスタの割込 - if (irq != sirq) { - if (targetbit) { - if (p->pi[0].ext & targetbit) { // ver0.30 - extirq_push(); - } - p->pi[0].isr |= targetbit; - p->pi[0].irr &= ~targetbit; - p->pi[0].level[p->pi[0].levels++] = irq; - if (irq == 0) { // ver0.28 - nevent_reset(NEVENT_PICMASK); - } - i286_interrupt((BYTE)((p->pi[0].icw[1] & 0xf8) | irq)); -// TRACEOUT(("hardware-int %.2x", (p->pi[0].icw[1] & 0xf8) | irq)); - return; - } - if ((!p->pi[0].levels) || - (p->pi[0].level[p->pi[0].levels - 1] != sirq)) { - return; - } + if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { + sir |= p->pi[1].isr; } - // スレーヴの処理 - if (!p->pi[1].levels) { - pry = -1; - } - else { - pry = (char)p->pi[1].pry[p->pi[1].level[p->pi[1].levels - 1]]; - } - targetbit = 0; - for (bit=1, i=0; bit; bit<<=1, i++) { - if ((p->pi[1].irr & bit) && - (!((p->pi[1].imr | p->pi[1].isr) & bit))) { - if ((char)p->pi[1].pry[i] > pry) { - pry = p->pi[1].pry[i]; - irq = (BYTE)i; - targetbit = bit; - } - } - } - // スレーヴの割込 - if (targetbit) { - if (!(p->pi[0].icw[2] & targetbit)) { - if (p->pi[1].ext & targetbit) { // ver0.30 - extirq_push(); - } - p->pi[1].isr |= targetbit; - p->pi[1].irr &= ~targetbit; - p->pi[1].level[p->pi[1].levels++] = irq; - if ((!p->pi[0].levels) || - (p->pi[0].level[p->pi[0].levels - 1] != sirq)) { - p->pi[0].isr |= (1 << sirq); - p->pi[0].irr &= ~(1 << sirq); - p->pi[0].level[p->pi[0].levels++] = sirq; - } -// TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | irq)); - i286_interrupt((BYTE)((p->pi[1].icw[1] & 0xf8) | irq)); - } + num = p->pi[1].pry; + bit = 1 << num; + while(!(sir & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (!(p->pi[1].isr & bit)) { + p->pi[0].isr |= slave; + p->pi[0].irr &= ~slave; + p->pi[1].isr |= bit; + p->pi[1].irr &= ~bit; +// TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); + CPU_INTERRUPT((REG8)((p->pi[1].icw[1] & 0xf8) | num), 0); + } + } + else if (!(p->pi[0].isr & bit)) { // マスター + p->pi[0].isr |= bit; + p->pi[0].irr &= ~bit; + if (num == 0) { + nevent_reset(NEVENT_PICMASK); } +// TRACEOUT(("hardware-int %.2x [%.4x:%.4x]", (p->pi[0].icw[1] & 0xf8) | num, CPU_CS, CPU_IP)); + CPU_INTERRUPT((REG8)((p->pi[0].icw[1] & 0xf8) | num), 0); } } +#endif // 簡易モード(SYSTEM TIMERだけ) @@ -231,10 +177,10 @@ void picmask(NEVENTITEM item) { } } -void pic_setirq(BYTE irq) { +void pic_setirq(REG8 irq) { PICITEM pi; - BYTE bit; + REG8 bit; pi = pic.pi; bit = 1 << (irq & 7); @@ -242,14 +188,14 @@ void pic_setirq(BYTE irq) { pi[0].irr |= bit; if (pi[0].imr & bit) { if (bit & PIC_SYSTEMTIMER) { - if ((pit.mode[0] & 0x0c) == 0x04) { + if ((pit.ch[0].ctrl & 0x0c) == 0x04) { SINT32 cnt; // ver0.29 - if (pit.value[0] > 8) { - cnt = pc.multiple * pit.value[0]; + if (pit.ch[0].value > 8) { + cnt = pccore.multiple * pit.ch[0].value; cnt >>= 2; } else { - cnt = pc.multiple << (16 - 2); + cnt = pccore.multiple << (16 - 2); } nevent_set(NEVENT_PICMASK, cnt, picmask, NEVENT_ABSOLUTE); } @@ -267,7 +213,7 @@ void pic_setirq(BYTE irq) { } } -void pic_resetirq(BYTE irq) { +void pic_resetirq(REG8 irq) { PICITEM pi; @@ -276,95 +222,85 @@ void pic_resetirq(BYTE irq) { } -void pic_registext(BYTE irq) { - - PICITEM pi; - - pi = pic.pi + ((irq >> 3) & 1); - pi->ext |= (1 << (irq & 7)); -} - - // ---- I/O -static void IOOUTCALL pic_o00(UINT port, BYTE dat) { +static void IOOUTCALL pic_o00(UINT port, REG8 dat) { - PICITEM picp; - BYTE level; + PICITEM picp; + REG8 level; + UINT8 ocw3; // TRACEOUT(("pic %x %x", port, dat)); picp = &pic.pi[(port >> 3) & 1]; picp->writeicw = 0; switch(dat & 0x18) { - case 0x00: // eoi - if (dat & 0x40) { - level = dat & 7; + case 0x00: // ocw2 + if (dat & PIC_OCW2_SL) { + level = dat & PIC_OCW2_L; } else { - if (picp->levels == 0) { + if (!picp->isr) { break; } - level = picp->level[picp->levels - 1]; - } - if (dat & 0x80) { - if (!(dat & 0x40)) { - pic_rolpry(picp); - } - else { - pic_downbylevel(picp, level); + level = picp->pry; + while(!(picp->isr & (1 << level))) { + level = (level + 1) & 7; } } - if (dat & 0x20) { - pic_forceeoibylevel(picp, level); + if (dat & PIC_OCW2_R) { + picp->pry = (level + 1) & 7; + } + if (dat & PIC_OCW2_EOI) { + picp->isr &= ~(1 << level); } nevent_forceexit(); // mainloop exit break; case 0x08: // ocw3 + ocw3 = picp->ocw3; + if (!(dat & PIC_OCW3_RR)) { + dat &= PIC_OCW3_RIS; + dat |= (ocw3 & PIC_OCW3_RIS); + } + if (!(dat & PIC_OCW3_ESMM)) { + dat &= ~PIC_OCW3_SMM; + dat |= (ocw3 & PIC_OCW3_SMM); + } picp->ocw3 = dat; break; default: picp->icw[0] = dat; picp->imr = 0; - picp->irr = 0; // ver0.28 - picp->ocw3 = 0; // ver0.25 + picp->irr = 0; + picp->ocw3 = 0; #if 0 picp->levels = 0; picp->isr = 0; #endif + picp->pry = 0; picp->writeicw = 1; break; } } -#if defined(TRACE) -extern int piccnt; -#endif - -static void IOOUTCALL pic_o02(UINT port, BYTE dat) { +static void IOOUTCALL pic_o02(UINT port, REG8 dat) { PICITEM picp; // TRACEOUT(("pic %x %x", port, dat)); picp = &pic.pi[(port >> 3) & 1]; if (!picp->writeicw) { -#if 1 // マスクのセットだけなら nevent_forceexit()をコールしない - if ((isI286DI) || (pic.ext_irq) || - ((picp->imr & dat) == picp->imr)) { - picp->imr = dat; - return; - } +#if 1 + UINT8 set; + set = picp->imr & (~dat); // リセットされたビットは割り込みある? - if (!(picp->irr & (picp->imr & (~dat)))) { + if ((CPU_isDI) || (!(picp->irr & set))) { picp->imr = dat; return; } #endif picp->imr = dat; -#if defined(TRACE) - piccnt++; -#endif } else { picp->icw[picp->writeicw] = dat; @@ -376,24 +312,20 @@ static void IOOUTCALL pic_o02(UINT port, nevent_forceexit(); } -static BYTE IOINPCALL pic_i00(UINT port) { +static REG8 IOINPCALL pic_i00(UINT port) { PICITEM picp; picp = &pic.pi[(port >> 3) & 1]; - switch(picp->ocw3 & 0x03) { - case 0x02: // read irr - return(picp->irr); - - case 0x03: // read isr - return(picp->isr); - - default: - return(0x00); // can can bunny + if (!(picp->ocw3 & PIC_OCW3_RIS)) { + return(picp->irr); // read irr + } + else { + return(picp->isr); // read isr } } -static BYTE IOINPCALL pic_i02(UINT port) { +static REG8 IOINPCALL pic_i02(UINT port) { PICITEM picp; @@ -404,21 +336,36 @@ static BYTE IOINPCALL pic_i02(UINT port) // ---- I/F +#if !defined(SUPPORT_PC9821) static const IOOUT pico00[2] = { pic_o00, pic_o02}; static const IOINP pici00[2] = { pic_i00, pic_i02}; +#else +static const IOOUT pico00[4] = { + pic_o00, pic_o02, NULL, NULL}; + +static const IOINP pici00[4] = { + pic_i00, pic_i02, NULL, NULL}; +#endif -void pic_reset(void) { +void pic_reset(const NP2CFG *pConfig) { pic.pi[0] = def_master; pic.pi[1] = def_slave; + + (void)pConfig; } void pic_bind(void) { +#if !defined(SUPPORT_PC9821) iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 2); iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 2); +#else + iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 4); + iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 4); +#endif }