|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: #include "interrupt.h" ! 8: #include "dmac.h" ! 9: #include "lance.h" ! 10: #include "pedec.h" ! 11: #include "m68030.h" ! 12: #include "mfp.h" ! 13: #include "mpu680x0.h" ! 14: #include "scc.h" ! 15: #include "sio.h" ! 16: #include "spc.h" ! 17: #include "sysclk.h" ! 18: ! 19: // IODevice ! 20: // | ! 21: // v ! 22: // InterruptDevice ! 23: // | ! 24: // +------------------------+-------------------------+ ! 25: // | | | ! 26: // | v | ! 27: // | M680x0Interrupt | ! 28: // | | | ! 29: // | +--------+--------+ | ! 30: // v v v v ! 31: // PEDECDevice X68030Interrupt LunaInterrupt SysCtlrDevice ! 32: // (X68030のLv1 (X68030) (LUNA-I) (LUNA88K) ! 33: // カスケード) ! 34: ! 35: std::unique_ptr<InterruptDevice> gInterrupt; ! 36: ! 37: // ! 38: // 仮想割り込みコントローラ (共通部) ! 39: // ! 40: ! 41: // コンストラクタ ! 42: InterruptDevice::InterruptDevice() ! 43: { ! 44: logname = "interrupt"; ! 45: devname = "Interrupt"; ! 46: } ! 47: ! 48: // デストラクタ ! 49: InterruptDevice::~InterruptDevice() ! 50: { ! 51: } ! 52: ! 53: ! 54: // ! 55: // 仮想割り込みコントローラ (m680x0 共通部) ! 56: // ! 57: ! 58: // CPU コアからの割り込みアクノリッジを受け付けるグローバル関数 ! 59: int ! 60: m68030_interrupt_acknowledge(int lv) ! 61: { ! 62: return gInterrupt->InterruptAcknowledge(lv); ! 63: } ! 64: ! 65: // コンストラクタ ! 66: M680x0Interrupt::M680x0Interrupt() ! 67: { ! 68: } ! 69: ! 70: // デストラクタ ! 71: M680x0Interrupt::~M680x0Interrupt() ! 72: { ! 73: } ! 74: ! 75: // リセット ! 76: void ! 77: M680x0Interrupt::ResetHard() ! 78: { ! 79: ipl = 0; ! 80: intmap = 0x00000001; ! 81: memset(&counter, 0, sizeof(counter)); ! 82: } ! 83: ! 84: // 子デバイスが割り込み信号線をアサートした (m680x0 共通) ! 85: void ! 86: M680x0Interrupt::AssertINT(Device *source) ! 87: { ! 88: uint32 oldmap; ! 89: uint32 srcmap; ! 90: int newipl; ! 91: ! 92: oldmap = intmap; ! 93: srcmap = GetIntmap(source); ! 94: intmap |= srcmap; ! 95: ! 96: if ((oldmap ^ intmap) != 0) { ! 97: // 立ち上がりエッジでカウント ! 98: counter[__builtin_clz(srcmap)]++; ! 99: } ! 100: ! 101: newipl = (uint)(31 - __builtin_clz(intmap)) / 4; ! 102: ! 103: // アサートによって割り込みレベルが上がったら、新しいレベルを通知 ! 104: // (現在通知中より低い割り込みは受け付けただけでここで保留) ! 105: if (newipl > ipl) { ! 106: ipl = newipl; ! 107: gMPU->Interrupt(ipl); ! 108: } ! 109: } ! 110: ! 111: // 小デバイスが割り込み信号線をネゲートした (m680x0 共通) ! 112: void ! 113: M680x0Interrupt::NegateINT(Device *source) ! 114: { ! 115: int newipl; ! 116: ! 117: intmap &= ~GetIntmap(source); ! 118: // intmap の最下位ビットは常に立ててあり intmap は 0 にならない ! 119: newipl = (uint)(31 - __builtin_clz(intmap)) / 4; ! 120: ! 121: // ネゲートによって割り込みレベルが下がったら、新しいレベルを通知 ! 122: // (以前に保留されていた低いレベルがあればここで見えるようになる) ! 123: if (newipl < ipl) { ! 124: ipl = newipl; ! 125: gMPU->Interrupt(ipl); ! 126: } ! 127: } ! 128: ! 129: ! 130: // ! 131: // X68030 仮想割り込みコントローラ ! 132: // ! 133: ! 134: // コンストラクタ ! 135: X68030Interrupt::X68030Interrupt() ! 136: { ! 137: monitor_size = nnSize(24, 6); ! 138: } ! 139: ! 140: // デストラクタ ! 141: X68030Interrupt::~X68030Interrupt() ! 142: { ! 143: } ! 144: ! 145: // デバイスから Intmap 値を引く ! 146: uint32 ! 147: X68030Interrupt::GetIntmap(Device *source) const ! 148: { ! 149: if (__predict_true(source == gMFP.get())) { ! 150: return IntmapMFP; ! 151: } ! 152: if (__predict_true(source == gSCC.get())) { ! 153: return IntmapSCC; ! 154: } ! 155: if (__predict_true(source == gDMAC.get())) { ! 156: return IntmapDMAC; ! 157: } ! 158: if (__predict_true(source == gPEDEC.get())) { ! 159: return IntmapPEDEC; ! 160: } ! 161: if (source == NULL) { ! 162: // XXX デバイスまだいないのでとりあえず ! 163: return IntmapNMI; ! 164: } ! 165: PANIC("Unknown interrupt source?"); ! 166: } ! 167: ! 168: // 割り込みアクノリッジに応答する ! 169: int ! 170: X68030Interrupt::InterruptAcknowledge(int lv) ! 171: { ! 172: switch (lv) { ! 173: case 6: ! 174: return gMFP->InterruptAcknowledge(); ! 175: ! 176: case 5: ! 177: return gSCC->InterruptAcknowledge(); ! 178: ! 179: case 3: ! 180: return gDMAC->InterruptAcknowledge(); ! 181: ! 182: case 1: ! 183: return gPEDEC->InterruptAcknowledge(lv); ! 184: ! 185: default: ! 186: break; ! 187: } ! 188: PANIC("Unknown interrupt acknowledge lv=%d", lv); ! 189: } ! 190: ! 191: void ! 192: X68030Interrupt::MonitorUpdate(TextScreen& monitor) ! 193: { ! 194: int y; ! 195: struct { ! 196: const char *name; ! 197: uint32 map; ! 198: } table[] = { ! 199: { "NMI", IntmapNMI }, ! 200: { "MFP", IntmapMFP }, ! 201: { "SCC", IntmapSCC }, ! 202: { "DMAC", IntmapDMAC }, ! 203: { "PEDEC", IntmapPEDEC }, ! 204: }; ! 205: ! 206: // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい ! 207: uint intr_level = gMPU680x0->GetCPU()->reg.intr_level; ! 208: ! 209: monitor.Clear(); ! 210: ! 211: y = 0; ! 212: monitor.Print(0, y++, "Lv Device Count IM=%d", intr_level); ! 213: for (int i = 0; i < countof(table); i++) { ! 214: uint32 map = table[i].map; ! 215: int clz = __builtin_clz(map); ! 216: int lv = (31 - clz) / 4; ! 217: monitor.Print(0, y, "%d", lv); ! 218: monitor.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name); ! 219: monitor.Print(8, y, "%10u", counter[clz]); ! 220: if (lv <= intr_level) { ! 221: monitor.Puts(20, y, "Mask"); ! 222: } ! 223: y++; ! 224: } ! 225: // XXX PEDEC 分もここに表示したい ! 226: } ! 227: ! 228: // ! 229: // LUNA-I 仮想割り込みコントローラ ! 230: // ! 231: ! 232: // コンストラクタ ! 233: LunaInterrupt::LunaInterrupt() ! 234: { ! 235: monitor_size = nnSize(24, 5); ! 236: } ! 237: ! 238: // デストラクタ ! 239: LunaInterrupt::~LunaInterrupt() ! 240: { ! 241: } ! 242: ! 243: ! 244: // デバイスから Intmap 値を引く ! 245: uint32 ! 246: LunaInterrupt::GetIntmap(Device *source) const ! 247: { ! 248: if (__predict_true(source == gSIO.get())) { ! 249: return IntmapSIO; ! 250: } ! 251: if (__predict_true(source == gSysClk.get())) { ! 252: return IntmapSysClk; ! 253: } ! 254: if (__predict_true(source == gEthernet.get())) { ! 255: return IntmapLance; ! 256: } ! 257: if (__predict_true(source == gSPC.get())) { ! 258: return IntmapSPC; ! 259: } ! 260: PANIC("Unknown interrupt source?"); ! 261: } ! 262: ! 263: // 割り込みアクノリッジに応答する ! 264: int ! 265: LunaInterrupt::InterruptAcknowledge(int lv) ! 266: { ! 267: // LUNA は全てオートベクタ ! 268: return AutoVector; ! 269: } ! 270: ! 271: void ! 272: LunaInterrupt::MonitorUpdate(TextScreen& monitor) ! 273: { ! 274: int y; ! 275: struct { ! 276: const char *name; ! 277: uint32 map; ! 278: } table[] = { ! 279: { "SIO", IntmapSIO }, ! 280: { "Clock", IntmapSysClk }, ! 281: { "Lance", IntmapLance }, ! 282: { "SPC", IntmapSPC }, ! 283: }; ! 284: ! 285: // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい ! 286: uint intr_level = gMPU680x0->GetCPU()->reg.intr_level; ! 287: ! 288: monitor.Clear(); ! 289: ! 290: y = 0; ! 291: monitor.Print(0, y++, "Lv Device Count IM=%d", intr_level); ! 292: for (int i = 0; i < countof(table); i++) { ! 293: uint32 map = table[i].map; ! 294: int clz = __builtin_clz(map); ! 295: int lv = (31 - clz) / 4; ! 296: monitor.Print(0, y, "%d", lv); ! 297: monitor.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name); ! 298: monitor.Print(8, y, "%10u", counter[clz]); ! 299: if (lv <= intr_level) { ! 300: monitor.Puts(20, y, "Mask"); ! 301: } ! 302: y++; ! 303: } ! 304: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.