|
|
| version 1.11, 2004/01/22 01:10:04 | version 1.22, 2007/11/03 00:00:20 |
|---|---|
| Line 4 | Line 4 |
| #include "iocore.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 = { | static const _PICITEM def_master = { |
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | {0x11, 0x08, 0x80, 0x1d}, |
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | 0x7d, 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}; | |
| static const _PICITEM def_slave = { | static const _PICITEM def_slave = { |
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | {0x11, 0x10, 0x07, 0x09}, |
| 0, {0, 0, 0, 0, 0, 0, 0, 0}, | 0x71, 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}; | |
| // ------------------------------------------------------------ ext. interrupt | |
| // 外部でISRを待避する割り込み対策 | // ---- |
| void extirq_push(void) { | #if 0 // スレーブがおかしい… |
| void pic_irq(void) { | |
| PIC p; | PIC p; |
| REG8 mir; | |
| REG8 sir; | |
| REG8 dat; | |
| REG8 num; | |
| REG8 bit; | |
| REG8 slave; | |
| p = &pic; | // 割込み許可? |
| if (!p->ext_irq) { | if (!CPU_isEI) { |
| p->ext_irq = 1; | return; |
| 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; | |
| } | } |
| } | |
| void extirq_pop(void) { | |
| PIC p; | |
| p = &pic; | 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; | |
| // TRACEOUT(("iret: extirq_pop")); | |
| } | |
| } | |
| // --------------------------- | |
| static void pic_rolpry(PICITEM pi) { | |
| // あははーっ 酷いね…こりゃ | mir = p->pi[0].irr & (~p->pi[0].imr); |
| *(UINT32 *)(&pi->pry[0]) = | sir = p->pi[1].irr & (~p->pi[1].imr); |
| (*(UINT32 *)(&pi->pry[0]) + 0x01010101) & 0x07070707; | if ((mir == 0) && (sir == 0)) { |
| *(UINT32 *)(&pi->pry[4]) = | return; |
| (*(UINT32 *)(&pi->pry[4]) + 0x01010101) & 0x07070707; | } |
| } | |
| slave = 1 << (p->pi[1].icw[2] & 7); | |
| dat = mir; | |
| static void pic_downbylevel(PICITEM picp, UINT level) { | if (sir) { |
| dat |= slave & (~p->pi[0].imr); | |
| int i; | } |
| if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { | |
| for (i=0; i<8; i++) { | dat |= p->pi[0].isr; |
| if (picp->pry[i] < picp->pry[level]) { | } |
| (picp->pry[i])++; | num = p->pi[0].pry; |
| } | bit = 1 << num; |
| } | while(!(dat & bit)) { |
| picp->pry[level] = 0; | num = (num + 1) & 7; |
| } | bit = 1 << num; |
| } | |
| if (p->pi[0].icw[2] & bit) { // スレーヴ | |
| // eoi処理 | dat = sir; |
| static void pic_forceeoibylevel(PICITEM picp, UINT level) { | if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { |
| dat |= p->pi[1].isr; | |
| int i; | } |
| num = p->pi[1].pry; | |
| if (picp->isr & (1 << level)) { | bit = 1 << num; |
| picp->isr &= ~(1 << level); | while(!(dat & bit)) { |
| picp->levels--; | num = (num + 1) & 7; |
| for (i=0; (i<picp->levels) && (picp->level[i] != level); i++) { } | bit = 1 << num; |
| for (; i<picp->levels; i++) { | } |
| picp->level[i] = picp->level[i+1]; | 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); | |
| } | } |
| } | } |
| #else | |
| void pic_irq(void) { // ver0.78 | |
| void pic_irq(void) { | |
| int i; | |
| BYTE bit; | |
| SINT8 pry; | |
| BYTE irq; | |
| BYTE sirq; | |
| BYTE targetbit; | |
| PIC p; | PIC p; |
| REG8 mir; | |
| REG8 sir; | |
| REG8 num; | |
| REG8 bit; | |
| REG8 slave; | |
| // 割込み許可? | |
| if (!CPU_isEI) { | |
| return; | |
| } | |
| p = &pic; | p = &pic; |
| // 割込み許可で 要求あり? | sir = p->pi[1].irr & (~p->pi[1].imr); |
| if ((CPU_isEI) && (!p->ext_irq) && | slave = 1 << (p->pi[1].icw[2] & 7); |
| ((p->pi[0].irr & (~p->pi[0].imr)) || | mir = p->pi[0].irr; |
| (p->pi[1].irr & (~p->pi[1].imr)))) { | if (sir) { |
| mir |= slave; | |
| // マスターの処理 | } |
| if (!p->pi[0].levels) { | mir &= (~p->pi[0].imr); |
| pry = -1; | if (mir == 0) { |
| } | return; |
| else { | } |
| pry = (SINT8)p->pi[0].pry[p->pi[0].level[p->pi[0].levels - 1]]; | if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { |
| } | mir |= p->pi[0].isr; |
| irq = 0xff; | } |
| targetbit = 0; | num = p->pi[0].pry; |
| for (bit=1, i=0; i<8; bit<<=1, i++) { | bit = 1 << num; |
| if ((p->pi[0].irr & bit) && | while(!(mir & bit)) { |
| (!((p->pi[0].imr | p->pi[0].isr) & bit))) { | num = (num + 1) & 7; |
| if ((SINT8)p->pi[0].pry[i] > pry) { | bit = 1 << num; |
| pry = p->pi[0].pry[i]; | } |
| irq = (BYTE)i; | if (p->pi[0].icw[2] & bit) { // スレーヴ |
| targetbit = bit; | if (sir == 0) { |
| } | return; |
| } | |
| } | |
| // スレーヴの要求はある? | |
| 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 ((SINT8)p->pi[0].pry[sirq] > pry) { | |
| irq = sirq; | |
| targetbit = bit; | |
| } | |
| } | |
| } | } |
| // マスタの割込 | if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { |
| if (irq != sirq) { | sir |= p->pi[1].isr; |
| 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); | |
| } | |
| // TRACEOUT(("hardware-int %.2x", (p->pi[0].icw[1] & 0xf8) | irq)); | |
| CPU_INTERRUPT((REG8)((p->pi[0].icw[1] & 0xf8) | irq)); | |
| return; | |
| } | |
| if ((!p->pi[0].levels) || | |
| (p->pi[0].level[p->pi[0].levels - 1] != sirq)) { | |
| return; | |
| } | |
| } | } |
| // スレーヴの処理 | num = p->pi[1].pry; |
| if (!p->pi[1].levels) { | bit = 1 << num; |
| pry = -1; | while(!(sir & bit)) { |
| } | num = (num + 1) & 7; |
| else { | bit = 1 << num; |
| pry = (SINT8)p->pi[1].pry[p->pi[1].level[p->pi[1].levels - 1]]; | } |
| } | if (!(p->pi[1].isr & bit)) { |
| targetbit = 0; | p->pi[0].isr |= slave; |
| for (bit=1, i=0; i<8; bit<<=1, i++) { | p->pi[0].irr &= ~slave; |
| if ((p->pi[1].irr & bit) && | p->pi[1].isr |= bit; |
| (!((p->pi[1].imr | p->pi[1].isr) & bit))) { | p->pi[1].irr &= ~bit; |
| if ((SINT8)p->pi[1].pry[i] > pry) { | // TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); |
| pry = p->pi[1].pry[i]; | CPU_INTERRUPT((REG8)((p->pi[1].icw[1] & 0xf8) | num), 0); |
| irq = (BYTE)i; | } |
| targetbit = bit; | } |
| } | else if (!(p->pi[0].isr & bit)) { // マスター |
| } | p->pi[0].isr |= bit; |
| } | p->pi[0].irr &= ~bit; |
| // スレーヴの割込 | if (num == 0) { |
| if (targetbit) { | nevent_reset(NEVENT_PICMASK); |
| 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)); | |
| CPU_INTERRUPT((REG8)((p->pi[1].icw[1] & 0xf8) | irq)); | |
| } | |
| } | } |
| // 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だけ) | // 簡易モード(SYSTEM TIMERだけ) |
| Line 243 void pic_setirq(REG8 irq) { | Line 188 void pic_setirq(REG8 irq) { |
| pi[0].irr |= bit; | pi[0].irr |= bit; |
| if (pi[0].imr & bit) { | if (pi[0].imr & bit) { |
| if (bit & PIC_SYSTEMTIMER) { | if (bit & PIC_SYSTEMTIMER) { |
| if ((pit.mode[0] & 0x0c) == 0x04) { | if ((pit.ch[0].ctrl & 0x0c) == 0x04) { |
| SINT32 cnt; // ver0.29 | SINT32 cnt; // ver0.29 |
| if (pit.value[0] > 8) { | if (pit.ch[0].value > 8) { |
| cnt = pccore.multiple * pit.value[0]; | cnt = pccore.multiple * pit.ch[0].value; |
| cnt >>= 2; | cnt >>= 2; |
| } | } |
| else { | else { |
| Line 276 void pic_resetirq(REG8 irq) { | Line 221 void pic_resetirq(REG8 irq) { |
| pi->irr &= ~(1 << (irq & 7)); | pi->irr &= ~(1 << (irq & 7)); |
| } | } |
| void pic_registext(REG8 irq) { | |
| PICITEM pi; | |
| pi = pic.pi + ((irq >> 3) & 1); | |
| pi->ext |= (1 << (irq & 7)); | |
| } | |
| // ---- I/O | // ---- I/O |
| static void IOOUTCALL pic_o00(UINT port, REG8 dat) { | static void IOOUTCALL pic_o00(UINT port, REG8 dat) { |
| PICITEM picp; | PICITEM picp; |
| UINT level; | REG8 level; |
| UINT8 ocw3; | |
| // TRACEOUT(("pic %x %x", port, dat)); | // TRACEOUT(("pic %x %x", port, dat)); |
| picp = &pic.pi[(port >> 3) & 1]; | picp = &pic.pi[(port >> 3) & 1]; |
| picp->writeicw = 0; | picp->writeicw = 0; |
| switch(dat & 0x18) { | switch(dat & 0x18) { |
| case 0x00: // eoi | case 0x00: // ocw2 |
| if (dat & 0x40) { | if (dat & PIC_OCW2_SL) { |
| level = dat & 7; | level = dat & PIC_OCW2_L; |
| } | } |
| else { | else { |
| if (picp->levels == 0) { | if (!picp->isr) { |
| break; | break; |
| } | } |
| level = picp->level[picp->levels - 1]; | level = picp->pry; |
| } | while(!(picp->isr & (1 << level))) { |
| if (dat & 0x80) { | level = (level + 1) & 7; |
| if (!(dat & 0x40)) { | |
| pic_rolpry(picp); | |
| } | |
| else { | |
| pic_downbylevel(picp, level); | |
| } | } |
| } | } |
| if (dat & 0x20) { | if (dat & PIC_OCW2_R) { |
| pic_forceeoibylevel(picp, level); | picp->pry = (level + 1) & 7; |
| } | |
| if (dat & PIC_OCW2_EOI) { | |
| picp->isr &= ~(1 << level); | |
| } | } |
| nevent_forceexit(); // mainloop exit | nevent_forceexit(); // mainloop exit |
| break; | break; |
| case 0x08: // ocw3 | 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; | picp->ocw3 = dat; |
| break; | break; |
| default: | default: |
| picp->icw[0] = dat; | picp->icw[0] = dat; |
| picp->imr = 0; | picp->imr = 0; |
| picp->irr = 0; // ver0.28 | picp->irr = 0; |
| picp->ocw3 = 0; // ver0.25 | picp->ocw3 = 0; |
| #if 0 | #if 0 |
| picp->levels = 0; | picp->levels = 0; |
| picp->isr = 0; | picp->isr = 0; |
| #endif | #endif |
| picp->pry = 0; | |
| picp->writeicw = 1; | picp->writeicw = 1; |
| break; | break; |
| } | } |
| } | } |
| #if defined(TRACE) | |
| extern int piccnt; | |
| #endif | |
| static void IOOUTCALL pic_o02(UINT port, REG8 dat) { | static void IOOUTCALL pic_o02(UINT port, REG8 dat) { |
| PICITEM picp; | PICITEM picp; |
| Line 349 static void IOOUTCALL pic_o02(UINT port, | Line 291 static void IOOUTCALL pic_o02(UINT port, |
| // TRACEOUT(("pic %x %x", port, dat)); | // TRACEOUT(("pic %x %x", port, dat)); |
| picp = &pic.pi[(port >> 3) & 1]; | picp = &pic.pi[(port >> 3) & 1]; |
| if (!picp->writeicw) { | if (!picp->writeicw) { |
| #if 1 // マスクのセットだけなら nevent_forceexit()をコールしない | #if 1 |
| if ((CPU_isDI) || (pic.ext_irq) || | UINT8 set; |
| ((picp->imr & dat) == picp->imr)) { | set = picp->imr & (~dat); |
| picp->imr = dat; | |
| return; | |
| } | |
| // リセットされたビットは割り込みある? | // リセットされたビットは割り込みある? |
| if (!(picp->irr & (picp->imr & (~dat)))) { | if ((CPU_isDI) || (!(picp->irr & set))) { |
| picp->imr = dat; | picp->imr = dat; |
| return; | return; |
| } | } |
| #endif | #endif |
| picp->imr = dat; | picp->imr = dat; |
| #if defined(TRACE) | |
| piccnt++; | |
| #endif | |
| } | } |
| else { | else { |
| picp->icw[picp->writeicw] = dat; | picp->icw[picp->writeicw] = dat; |
| Line 381 static REG8 IOINPCALL pic_i00(UINT port) | Line 317 static REG8 IOINPCALL pic_i00(UINT port) |
| PICITEM picp; | PICITEM picp; |
| picp = &pic.pi[(port >> 3) & 1]; | picp = &pic.pi[(port >> 3) & 1]; |
| switch(picp->ocw3 & 0x03) { | if (!(picp->ocw3 & PIC_OCW3_RIS)) { |
| case 0x02: // read irr | return(picp->irr); // read irr |
| return(picp->irr); | } |
| else { | |
| case 0x03: // read isr | return(picp->isr); // read isr |
| return(picp->isr); | |
| default: | |
| return(0x00); // can can bunny | |
| } | } |
| } | } |
| Line 404 static REG8 IOINPCALL pic_i02(UINT port) | Line 336 static REG8 IOINPCALL pic_i02(UINT port) |
| // ---- I/F | // ---- I/F |
| #if !defined(SUPPORT_PC9821) | |
| static const IOOUT pico00[2] = { | static const IOOUT pico00[2] = { |
| pic_o00, pic_o02}; | pic_o00, pic_o02}; |
| static const IOINP pici00[2] = { | static const IOINP pici00[2] = { |
| pic_i00, pic_i02}; | 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[0] = def_master; |
| pic.pi[1] = def_slave; | pic.pi[1] = def_slave; |
| pic.ext_irq = 0; | |
| (void)pConfig; | |
| } | } |
| void pic_bind(void) { | void pic_bind(void) { |
| #if !defined(SUPPORT_PC9821) | |
| iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 2); | iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 2); |
| iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 2); | iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 2); |
| #else | |
| iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 4); | |
| iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 4); | |
| #endif | |
| } | } |