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