Diff for /np2/io/pic.c between versions 1.11 and 1.22

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
 }  }
   

Removed from v.1.11  
changed lines
  Added in v.1.22


RetroPC.NET-CVS <cvs@retropc.net>