|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1.1.4 root 7: //
8: // 割り込みコントローラ
9: //
10:
1.1 root 11: #pragma once
12:
13: #include "device.h"
1.1.1.6 root 14: #include <array>
1.1.1.7 root 15: #include <vector>
1.1 root 16:
1.1.1.5 root 17: // XP からの割り込み用。
18: // これだけ1デバイスで2本あるので、仕方なく識別子を用意。
1.1.1.8 root 19: #define DEVICE_XPINT_HIGH (reinterpret_cast<Device *>((intptr_t)1))
20: #define DEVICE_XPINT_LOW (reinterpret_cast<Device *>((intptr_t)2))
1.1.1.5 root 21:
22: class DMACDevice;
1.1.1.7 root 23: class GFPICDevice;
1.1.1.5 root 24: class MFPDevice;
1.1.1.7 root 25: class MPU680x0Device;
1.1.1.5 root 26: class NMIDevice;
27: class PEDECDevice;
1.1.1.6 root 28: class RTL8019ASDevice;
1.1.1.5 root 29: class SCCDevice;
30: class SPCDevice;
31:
1.1.1.4 root 32: // 割り込みを受け付けるデバイス。
1.1 root 33: // これ自体は IODevice である必要はないが、PEDEC や SysCtlr がこれを
34: // 継承するため。
35: class InterruptDevice : public IODevice
36: {
37: using inherited = IODevice;
1.1.1.7 root 38:
39: // intmap と名前の紐付け
40: struct mapname {
41: uint32 intmap {};
42: const char *name {};
43: Device *source {};
44:
45: mapname(uint32 intmap_, const char *name_, Device *source_) {
46: intmap = intmap_;
47: name = name_;
48: source = source_;
49: }
50: };
51:
1.1 root 52: public:
53: InterruptDevice();
1.1.1.8 root 54: InterruptDevice(uint objid_);
1.1.1.7 root 55: ~InterruptDevice() override;
1.1 root 56:
1.1.1.7 root 57: // リセットで割り込みを下げるのは各割り込み送出デバイスの責任。
1.1.1.4 root 58: void ResetHard(bool poweron) override;
1.1 root 59:
60: // AssertINT()、NegateINT()、ChangeINT() の呼び出し側は、
61: // (アサート中に AssertINT() を呼ぶというような) 現在の状態が
62: // 変わらないような呼び出しをしても構わない。特に副作用はない。
63:
64: // 子デバイスが割り込み信号線をアサートした
1.1.1.3 root 65: void AssertINT(Device *source);
1.1 root 66: // 子デバイスが割り込み信号線をネゲートした
1.1.1.3 root 67: void NegateINT(Device *source);
1.1 root 68:
69: // 子デバイスが割り込み信号線を val の状態に変えた。
70: // true ならアサート、false ならネゲート。
71: void ChangeINT(Device *source, bool val) {
72: if (val) {
73: AssertINT(source);
74: } else {
75: NegateINT(source);
76: }
77: }
78:
79: // MPU からの割り込みアクノリッジに応答する
1.1.1.7 root 80: virtual busdata InterruptAcknowledge(int lv) = 0;
1.1.1.3 root 81:
1.1.1.6 root 82: // 割り込み信号線の状態を取得する
83: bool GetINT(const Device *source) const;
84:
1.1.1.3 root 85: protected:
86: // 割り込みを上位デバイス(MPUなど)に伝達する。
87: // 子デバイスが割り込み信号線の状態を変えたときに呼び出される。
88: virtual void ChangeInterrupt() = 0;
89:
90: // Intmap について
91: //
92: // Intmap は 32bit のビットマップ値で、最大 31 個(といいつつ今の所 28 個)
93: // の割り込み発生の有無を個別に管理できる。
94: // 発生している割り込みのうち最も優先度が高い 1つを高速に検索するため、
95: // MSB 側を最も優先度が高い割り込みとして、Count-Leading-Zero で検索
96: // することにする。
97: // __builtin_clz(0) は動作未定義になるので、最下位ビットを常に立てて
98: // おくことで、割り込みなし(上位31bitがすべて0)の場合でもこの式が使える
99: // ようにしておく。
100: //
101: // 具体的にどの割り込みをどのビットに割り当てるかは継承先の実装によるが、
102: // m680x0 の場合、以下のように 1レベル 4つずつ割り当てることにする。
103: //
104: // 3 2 1 0
105: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
106: // +-------+-------+-------+-------+-------+-------+-------+-------+
107: // |7 7 7 7|6 6 6 6|5 5 5 5|4 4 4 4|3 3 3 3|2 2 2 2|1 1 1 1| %0001 |
108: // +-------+-------+-------+-------+-------+-------+-------+-------+
109: //
110: // これにより同一レベルのデバイス 4 つまでの割り込み信号線の状態を独立
111: // して保持しつつ、アサートされている信号線のうち最もレベルの高いものは
112: // 以下だけで求めることが出来る。
113: //
1.1.1.7 root 114: // ipl = (31 - __builtin_clz(intmap_status)) / 4;
1.1.1.3 root 115: //
1.1.1.5 root 116: // LUNA-88K の外部割り込みコントローラであるシステムコントローラも
1.1.1.3 root 117: // 概ねこれに近いので、sysctlr もこの構造を使う。
118: //
119: // PEDEC は 7レベル分けする必要ないので、適当に割り当ててある。
1.1.1.7 root 120: //
121: // Goldfish PIC は 7レベル分け不要なのと 32ビット必要そうなので、
122: // 番兵を使わず 32ビット全域を使う。
123: // また元の仕様が LSB 側から数えるスタイルなのでここでもそれに従う。
1.1.1.3 root 124:
125: static const uint32 IntmapSentinel = 0x00000001;
126:
1.1.1.7 root 127: // 割り込みソースを登録する。
128: void RegistINT(uint32 intmap_, const char *name_, Device *source_);
129:
1.1.1.3 root 130: // デバイスから Intmap 値を引く。
1.1.1.7 root 131: uint32 GetIntmap(const Device *source) const;
132:
133: // Intmap 値から名前を引く。
134: const char *GetIntName(uint32 intmap_) const;
135:
136: // 割り込みソース一覧 (概ね使用頻度の高い順)
137: std::vector<mapname> intmap_list {};
138:
139: // モニタでの表示順 (概ね優先度の高い順)
140: std::vector<uint32> disp_list {};
141:
142: // 割り込みソースが存在するところは %1
143: uint32 intmap_avail {};
144:
145: // 割り込み状態 (各 %1 ならアサート)
146: uint32 intmap_status {};
1.1.1.3 root 147:
1.1.1.7 root 148: // (必要なら) 割り込みマスク (各 %1 なら有効)
149: // 割り込みマスク機能を持ってない人は使わなくてもよい。
150: uint32 intmap_enable {};
1.1.1.3 root 151:
152: // 割り込み回数 (アサートのエッジでカウントアップする)
153: // [0] が Intmap の bit31 割り込みのカウント。
154: // [27] が Intmap の bit 4 割り込みのカウント。
1.1.1.7 root 155: uint64 counter[32] {};
1.1.1.9 ! root 156:
! 157: Monitor *monitor {};
1.1 root 158: };
159:
160: // m680x0 仮想割り込みコントローラ (共通部)
161: class M680x0Interrupt : public InterruptDevice
162: {
163: using inherited = InterruptDevice;
1.1.1.7 root 164:
1.1 root 165: public:
1.1.1.7 root 166: // 割り込みアクノリッジの特殊値。
167: static const uint32 AutoVector = -1; // オートベクタ要求
1.1 root 168:
169: public:
170: M680x0Interrupt();
1.1.1.7 root 171: ~M680x0Interrupt() override;
1.1 root 172:
1.1.1.5 root 173: bool Init() override;
1.1.1.4 root 174: void ResetHard(bool poweron) override;
1.1 root 175:
176: protected:
1.1.1.3 root 177: void ChangeInterrupt() override;
1.1 root 178:
179: // 現在の割り込みレベル
180: int ipl {};
1.1.1.7 root 181:
182: MPU680x0Device *mpu680x0 {};
1.1 root 183: };
184:
185: // X68k 仮想割り込みコントローラ
186: //
187: // Level
188: // 7 INTERRUPT スイッチ
189: // 6 MFP
190: // 5 SCC
191: // 4 (拡張ボード)
192: // 3 DMAC
193: // 2 (拡張ボード)
194: // 1 PEDEC <--+-- SPC
195: // +-- HDD (SASI)
196: // +-- FDC
197: // +-- FDD
198: // +-- PRN
199: //
200: class X68030Interrupt : public M680x0Interrupt
201: {
202: using inherited = M680x0Interrupt;
203:
204: // 割り込みマップ 76543210
205: static const uint32 IntmapNMI = 0x80000000;
206: static const uint32 IntmapMFP = 0x08000000;
207: static const uint32 IntmapSCC = 0x00800000;
1.1.1.6 root 208: static const uint32 IntmapNereid0 = 0x00080000;
209: static const uint32 IntmapNereid1 = 0x00040000;
1.1 root 210: static const uint32 IntmapDMAC = 0x00008000;
211: static const uint32 IntmapPEDEC = 0x00000080;
212:
213: public:
214: X68030Interrupt();
1.1.1.7 root 215: ~X68030Interrupt() override;
1.1 root 216:
1.1.1.5 root 217: bool Init() override;
1.1.1.7 root 218: busdata InterruptAcknowledge(int lv) override;
1.1 root 219:
220: private:
1.1.1.2 root 221: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
222:
1.1.1.5 root 223: DMACDevice *dmac {};
224: MFPDevice *mfp {};
225: NMIDevice *nmi {};
226: PEDECDevice *pedec {};
1.1.1.6 root 227: std::array<RTL8019ASDevice *, 2> net {};
1.1.1.5 root 228: SCCDevice *scc {};
1.1 root 229: };
230:
231: // LUNA-I 仮想割り込みコントローラ
232: //
233: // Level
234: // 7
235: // 6 SIO
236: // 5 SystemClock
237: // 4 (XP high)
238: // 3 Lance
239: // 2 SPC
240: // 1 (XP low)
241: //
242: class LunaInterrupt : public M680x0Interrupt
243: {
244: using inherited = M680x0Interrupt;
245:
246: // 割り込みマップ 76543210
1.1.1.4 root 247: static const uint32 IntmapNMI = 0x80000000;
1.1 root 248: static const uint32 IntmapSIO = 0x08000000;
249: static const uint32 IntmapSysClk = 0x00800000;
1.1.1.5 root 250: static const uint32 IntmapXPHigh = 0x00400000;
1.1 root 251: static const uint32 IntmapLance = 0x00008000;
252: static const uint32 IntmapSPC = 0x00000800;
1.1.1.5 root 253: static const uint32 IntmapXPLow = 0x00000080;
1.1 root 254:
255: public:
256: LunaInterrupt();
1.1.1.7 root 257: ~LunaInterrupt() override;
1.1 root 258:
1.1.1.5 root 259: bool Init() override;
1.1.1.7 root 260: busdata InterruptAcknowledge(int lv) override;
1.1.1.5 root 261:
262: private:
263: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
264: };
265:
266: // NEWS 仮想割り込みコントローラ
267: //
268: // Level
269: // 7
270: // 6 Timer
271: // 5 SCC(vectored)
272: // 4 SIC, Lance
273: // 3
274: // 2
275: // 1
276: //
277: class NewsInterrupt : public M680x0Interrupt
278: {
279: using inherited = M680x0Interrupt;
280:
281: // 割り込みマップ 76543210
282: static const uint32 IntmapNMI = 0x80000000;
283: static const uint32 IntmapTimer = 0x08000000;
284: static const uint32 IntmapSCC = 0x00800000;
285: static const uint32 IntmapSIC = 0x00080000;
286: static const uint32 IntmapLance = 0x00040000;
287:
288: public:
289: NewsInterrupt();
1.1.1.7 root 290: ~NewsInterrupt() override;
1.1.1.5 root 291:
292: bool Init() override;
1.1.1.7 root 293: busdata InterruptAcknowledge(int lv) override;
1.1 root 294:
1.1.1.5 root 295: // 割り込みステータスを返す (NewsCtlr から呼ばれる)
296: uint8 PeekStatus() const;
297:
1.1 root 298: private:
1.1.1.2 root 299: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
300:
1.1.1.5 root 301: SCCDevice *scc {};
1.1 root 302: };
303:
1.1.1.8 root 304: // virt-m68k 仮想割り込みコントローラ
1.1.1.7 root 305: //
306: // Level
307: // 7
308: // 6 GFPIC6
309: // 5 GFPIC5
310: // 4 GFPIC4
311: // 3 GFPIC3
312: // 2 GFPIC2
313: // 1 GFPIC1
314: //
315: class Virt68kInterrupt : public M680x0Interrupt
316: {
317: using inherited = M680x0Interrupt;
318:
319: // 割り込みマップ 76543210
320: static const uint32 IntmapGFPIC6 = 0x08000000;
321: static const uint32 IntmapGFPIC5 = 0x00800000;
322: static const uint32 IntmapGFPIC4 = 0x00080000;
323: static const uint32 IntmapGFPIC3 = 0x00008000;
324: static const uint32 IntmapGFPIC2 = 0x00000800;
325: static const uint32 IntmapGFPIC1 = 0x00000080;
326:
327: public:
328: Virt68kInterrupt();
329: ~Virt68kInterrupt() override;
330:
331: bool Init() override;
332: busdata InterruptAcknowledge(int lv) override;
333:
334: // モニタを1行増やす。割り込みソース登録ごとに GFPIC から呼ばれる。
335: void IncMonitorHeight();
336:
337: private:
338: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
339:
340: std::array<GFPICDevice *, 7> gfpic {};
341: };
342:
1.1.1.5 root 343: // LUNA-88K は sysctlr.cpp 参照。
1.1 root 344:
1.1.1.5 root 345: static inline InterruptDevice *GetInterruptDevice() {
346: return Object::GetObject<InterruptDevice>(OBJ_INTERRUPT);
347: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.