|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: #pragma once ! 8: ! 9: #include "device.h" ! 10: ! 11: // ! 12: // 割り込みを受け付けるデバイス ! 13: // これ自体は IODevice である必要はないが、PEDEC や SysCtlr がこれを ! 14: // 継承するため。 ! 15: // ! 16: class InterruptDevice : public IODevice ! 17: { ! 18: using inherited = IODevice; ! 19: public: ! 20: InterruptDevice(); ! 21: virtual ~InterruptDevice() override; ! 22: ! 23: // 継承クラスの ResetHard() は保持している割り込み情報を全てキャンセルする。 ! 24: // 各子デバイスはその ResetHard() で NegateINT() を明示的に呼び出して ! 25: // 割り込みをキャンセルする必要はなく、もし自身で独自に割り込み信号線の ! 26: // 状態に関する変数を持っていればそれをクリアするだけでよい。 ! 27: ! 28: // AssertINT()、NegateINT()、ChangeINT() の呼び出し側は、 ! 29: // (アサート中に AssertINT() を呼ぶというような) 現在の状態が ! 30: // 変わらないような呼び出しをしても構わない。特に副作用はない。 ! 31: ! 32: // 子デバイスが割り込み信号線をアサートした ! 33: virtual void AssertINT(Device *source) = 0; ! 34: // 子デバイスが割り込み信号線をネゲートした ! 35: virtual void NegateINT(Device *source) = 0; ! 36: ! 37: // 子デバイスが割り込み信号線を val の状態に変えた。 ! 38: // true ならアサート、false ならネゲート。 ! 39: void ChangeINT(Device *source, bool val) { ! 40: if (val) { ! 41: AssertINT(source); ! 42: } else { ! 43: NegateINT(source); ! 44: } ! 45: } ! 46: ! 47: // MPU からの割り込みアクノリッジに応答する ! 48: virtual int InterruptAcknowledge(int lv) = 0; ! 49: }; ! 50: ! 51: // ! 52: // m680x0 仮想割り込みコントローラ (共通部) ! 53: // ! 54: class M680x0Interrupt : public InterruptDevice ! 55: { ! 56: using inherited = InterruptDevice; ! 57: public: ! 58: static const int AutoVector = -1; // オートベクタ ! 59: ! 60: public: ! 61: M680x0Interrupt(); ! 62: virtual ~M680x0Interrupt() override; ! 63: ! 64: void ResetHard() override; ! 65: ! 66: void AssertINT(Device *source) override; ! 67: void NegateINT(Device *source) override; ! 68: ! 69: protected: ! 70: // Intmap は 32bit のビットマップ値で、値は機種ごとに定義する。 ! 71: // 1つの割り込みレベルにつき 4つまでデバイスをマッピングでき、また、 ! 72: // 同一レベル内での複数のデバイスの割り込み信号線の状態を独立して保持 ! 73: // できるようにするため。 ! 74: // ! 75: // 3 2 1 0 ! 76: // 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 ! 77: // +-------+-------+-------+-------+-------+-------+-------+-------+ ! 78: // |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 | ! 79: // +-------+-------+-------+-------+-------+-------+-------+-------+ ! 80: // ! 81: // bit31-4 でレベル 7-1 の割り込みを表す。 ! 82: // アサートされている信号線のうち最もレベルの高いものは以下で求まる。 ! 83: // ipl = (31 - clz(intmap)) / 4 ! 84: // 例えば bit30 と bit20 が立っている場合 (これは割り込みレベル 7 と 5 が ! 85: // 同時に要求されている状態)、最高レベルは (31 - 1) / 4 = 7 となる。 ! 86: // また __builtin_clz(0) は未定義なので使わない最下位ビットを常に立てて ! 87: // おくことで、割り込みなし(上位28bitがすべて0)の場合でもこの式が使える。 ! 88: ! 89: // デバイスから Intmap 値を引く。 ! 90: virtual uint32 GetIntmap(Device *source) const = 0; ! 91: ! 92: // 現在の割り込みレベル ! 93: int ipl {}; ! 94: ! 95: // 割り込みマップ ! 96: uint32 intmap {}; ! 97: ! 98: // 割り込み回数 (アサートのエッジでカウントアップする) ! 99: // [0] が Intmap の bit31 割り込みのカウント。 ! 100: // [27] が Intmap の bit 4 割り込みのカウント。 ! 101: uint32 counter[28] {}; ! 102: }; ! 103: ! 104: // ! 105: // X68k 仮想割り込みコントローラ ! 106: // ! 107: // Level ! 108: // 7 INTERRUPT スイッチ ! 109: // 6 MFP ! 110: // 5 SCC ! 111: // 4 (拡張ボード) ! 112: // 3 DMAC ! 113: // 2 (拡張ボード) ! 114: // 1 PEDEC <--+-- SPC ! 115: // +-- HDD (SASI) ! 116: // +-- FDC ! 117: // +-- FDD ! 118: // +-- PRN ! 119: // ! 120: class X68030Interrupt : public M680x0Interrupt ! 121: { ! 122: using inherited = M680x0Interrupt; ! 123: ! 124: // 割り込みマップ 76543210 ! 125: static const uint32 IntmapNMI = 0x80000000; ! 126: static const uint32 IntmapMFP = 0x08000000; ! 127: static const uint32 IntmapSCC = 0x00800000; ! 128: static const uint32 IntmapDMAC = 0x00008000; ! 129: static const uint32 IntmapPEDEC = 0x00000080; ! 130: ! 131: public: ! 132: X68030Interrupt(); ! 133: virtual ~X68030Interrupt() override; ! 134: ! 135: void MonitorUpdate(TextScreen& monitor) override; ! 136: ! 137: int InterruptAcknowledge(int lv) override; ! 138: ! 139: private: ! 140: uint32 GetIntmap(Device *soruce) const override; ! 141: }; ! 142: ! 143: // ! 144: // LUNA-I 仮想割り込みコントローラ ! 145: // ! 146: // Level ! 147: // 7 ! 148: // 6 SIO ! 149: // 5 SystemClock ! 150: // 4 (XP high) ! 151: // 3 Lance ! 152: // 2 SPC ! 153: // 1 (XP low) ! 154: // ! 155: class LunaInterrupt : public M680x0Interrupt ! 156: { ! 157: using inherited = M680x0Interrupt; ! 158: ! 159: // 割り込みマップ 76543210 ! 160: static const uint32 IntmapSIO = 0x08000000; ! 161: static const uint32 IntmapSysClk = 0x00800000; ! 162: static const uint32 IntmapLance = 0x00008000; ! 163: static const uint32 IntmapSPC = 0x00000800; ! 164: ! 165: public: ! 166: LunaInterrupt(); ! 167: virtual ~LunaInterrupt() override; ! 168: ! 169: void MonitorUpdate(TextScreen& monitor) override; ! 170: ! 171: int InterruptAcknowledge(int lv) override; ! 172: ! 173: private: ! 174: uint32 GetIntmap(Device *source) const override; ! 175: }; ! 176: ! 177: // LUNA88K は sysctlr.cpp 参照。 ! 178: ! 179: extern std::unique_ptr<InterruptDevice> gInterrupt;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.