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