|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // LUNA88K のシステムコントローラのような何か ! 8: ! 9: #include "sysctlr.h" ! 10: ! 11: // この辺を全部一つのデバイスで受け付けておくか。BusIO はまた後で考える。 ! 12: // $6500000n.b HW 割り込みレベル (n*4 = CPU#n) ! 13: // $65000000.b CPU#0 ! 14: // $65000004.b CPU#1 ! 15: // $65000008.b CPU#2 ! 16: // $6500000c.b CPU#3 ! 17: // $6900000n ソフトウェア割り込み(?) ! 18: // $6d00000n CPU#n をリセット(?) ! 19: // $6d000010 全 CPU をリセット ! 20: ! 21: // intmask[] について: ! 22: // I/O ポート 0x6500_00xx での設定値は、 ! 23: // bit 31 30 29 28 27 26 25... ! 24: // lvl 6 5 4 3 2 1 (not used) ! 25: // の対応になっている。intmask では 25bit 右シフトして、 ! 26: // ビット番号が割り込みレベルに対応するようにマップした。 ! 27: ! 28: ! 29: // LUNA88K ! 30: // 割り込みコントロールレジスタ ! 31: // $6500_000n ! 32: // n: CPU ID * 4 (0,4,8,c) ! 33: // この16Mページ内はミラーされている模様。 ! 34: // 下位2bitしかデコードしていない? ! 35: // 書き込み時: ! 36: // 3 2 1 ! 37: // 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 ! 38: // +-+-+-+-+-+-+---------------------------------------------------+ ! 39: // |6|5|4|3|2|1| | ! 40: // +-+-+-+-+-+-+---------------------------------------------------+ ! 41: // bit31: 1=割り込み 6 イネーブル ! 42: // bit30: 1=割り込み 5 イネーブル ! 43: // bit29: 1=割り込み 4 イネーブル ! 44: // bit28: 1=割り込み 3 イネーブル ! 45: // bit27: 1=割り込み 2 イネーブル ! 46: // bit26: 1=割り込み 1 イネーブル ! 47: // m68k と異なり、個別の割り込みごとに許可/禁止できる。 ! 48: // 該当ビットに 1 を書き込むと許可。 ! 49: // 空欄部分は無視される模様。 ! 50: // ! 51: // 読み込み時 ! 52: // 3 2 1 ! 53: // 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 ! 54: // +-----+---------+-+-+-+-+-+-+-----------------------------------+ ! 55: // |Level| |6|5|4|3|2|1| | ! 56: // +-----+---------+-+-+-+-+-+-+-----------------------------------+ ! 57: // bit31-29: 発生している最上位レベルの割り込み。範囲は7-0 ! 58: // bit23-18: 書き込んだ割り込みマスク。 ! 59: // 空欄部分は「不定」の模様。 ! 60: // ! 61: // bit31-29 のレベルは、割り込みコントローラに入力 ! 62: // されている割り込み信号線6本を、マスク処理した後、 ! 63: // プライオリティバイナリエンコーダの値がそのまま出力されている模様。 ! 64: // ラッチ機構は無いようだ。 ! 65: // したがってマスクされている割り込み(マスクビットが 0) の ! 66: // 値が出力されることはない。 ! 67: // 同時に入力があった場合は、数字の大きいほうが出力される。 ! 68: // レベル7 はマスクなしでプライオリティエンコーダに入力されているようだ。 ! 69: // ! 70: // 割り込み入力がないときは 0 になる模様。 ! 71: // 本体 ABRT スイッチを押すと、押している間、すべての CPU の ! 72: // level が 111(=7) になる。離すと戻る。 ! 73: // 88100 には NMI が無いので、通常の割り込みと同じように処理している? ! 74: // (なので IND 状態だとABRT できない。いいのかそれで) ! 75: // (OpenBSD6.7 の割り込みハンドラはABRTには対応していないように読める) ! 76: // ! 77: // 想定される回路 ! 78: // ! 79: // [割り込みソース] ! 80: // 1:SOFTINT レジスタ $6900000n ! 81: // | 2:(XP 低レベル?) ! 82: // | | 3:SPC ! 83: // | | | 4:(LANCE|拡張スロット?) ! 84: // | | | | 5:(拡張PC98?|シリアル?) ! 85: // | | | | | 6:(XP 高レベル?|システムクロック?) ! 86: // | | | | | | 7:ABRTスイッチ ! 87: // V V V V V V | ! 88: // +---------------------+ | ! 89: // | 割り込みマスク | | (R:bit23-18, W:bit31-26) ! 90: // +---------------------+ | ! 91: // | | | | | | | ! 92: // V V V V V V V ! 93: // +-------------------------+ ! 94: // |プライオリティエンコーダ |-> (R:bit31-29) ! 95: // +-------------------------+ ! 96: // (入力のWired-OR) ! 97: // | ! 98: // [M88K INT] ! 99: // ! 100: // LUNA-I とはレベル配置が違う。1 レベルのズレに加え、シリアルが ! 101: // 6 -> 5 に変更されているようだ? ! 102: // ! 103: // 割り込みソース調査状況 ! 104: // 1:SOFTINT レジスタ $6900000n ! 105: // ROM のメモリコマンドで確認。OpenBSD machdep.c の記述の通り。 ! 106: // 2:XP 低レベル ! 107: // LUNA-I からの類推及び、OpenBSD mainbus.c に記述あり。OpenBSD のほうは ! 108: // 低レベルかどうかは不明。 ! 109: // 3:SPC ! 110: // ROM1.2, OpenBSD ともに使用。 ! 111: // 4:LANCE ! 112: // ROM はまだ不明。OpenBSD は使用。 ! 113: // 4:拡張スロット ! 114: // LUNA-I からの類推のみ。不明。 ! 115: // 5:拡張PC98 ! 116: // LUNA-I からの類推のみ。LUNA88K にはスロットがないようなので、 ! 117: // LUNA88K2 が必要。 ! 118: // OpenBSD mainbus.c に記述あり。 ! 119: // 5:シリアル(7201) ! 120: // OpenBSD mainbus.c に記述。 ! 121: // 6:XP 高レベル ! 122: // LUNA-I からの類推。存在するかどうかも不明。 ! 123: // ただ、これをなくすと XP ファームウェアまで作り直しなので、 ! 124: // なくさないんじゃないかなあ。OMRON ファームで使ってなければ ! 125: // さっくり廃止されているかもしれない(PSGPAM が使用...レベル1 に ! 126: // 変えればいいだけだが) ! 127: // 6:システムクロック ! 128: // ROM のメモリコマンドではレベル6割り込みが常時上がっているように観測 ! 129: // できるので、おそらくシステムクロック割り込みが上がっている。 ! 130: // OpenBSD maibus.c にも記述。 ! 131: // 7:ABRTスイッチ ! 132: // ROM のメモリコマンドで確認。 ! 133: // ! 134: // ! 135: // SOFTINT レジスタ $6900000n ! 136: // $69000000: CPU0 ! 137: // $69000004: CPU1 ! 138: // $69000008: CPU2 ! 139: // $6900000c: CPU3 ! 140: // 挙動: ! 141: // この32ビットのどこかにライトアクセスすると、INT1 をアサートする。 ! 142: // この32ビットのどこかをリードアクセスすると、INT1 をネゲートする。 ! 143: // データバスは無視される。 ! 144: // 0x00 を書いても、アサートされることに注意。 ! 145: // リードアクセスで読み込まれる値も不定のようだ。 ! 146: // 要はアドレスバスとR/W信号線しか見ていない。 ! 147: ! 148: ! 149: std::unique_ptr<SysCtlrDevice> gSysCtlr; ! 150: ! 151: ! 152: // コンストラクタ ! 153: SysCtlrDevice::SysCtlrDevice() ! 154: { ! 155: logname = "sysctlr"; ! 156: devname = "SysCtlr"; ! 157: ! 158: monitor.Init(60, 5); ! 159: } ! 160: ! 161: // デストラクタ ! 162: SysCtlrDevice::~SysCtlrDevice() ! 163: { ! 164: } ! 165: ! 166: uint64 ! 167: SysCtlrDevice::Read32(uint32 addr) ! 168: { ! 169: int n = (addr & 15) >> 2; ! 170: ! 171: // 読み込みでは割り込みレベルを返すようだ ! 172: // bit 31..29: アクティブな割り込みのレベル ! 173: // 24 level7 割り込みが発生したら 1 ! 174: // 23 level6 .. ! 175: // 22 level5 ! 176: // 21 level4 ! 177: // 20 level3 ! 178: // 19 level2 ! 179: // 18 level1 ! 180: // XXX: もう資料がないとわからない ! 181: if (0x65000000 <= addr && addr < 0x65000010) { ! 182: int maxlev = 0; ! 183: // 7 to 1 ! 184: for (int i = 7; i > 0; i--) { ! 185: if (intlevel[n] & (1 << i)) { ! 186: maxlev = i; ! 187: break; ! 188: } ! 189: } ! 190: ! 191: uint32 data = (maxlev << 29) | (intlevel[n] << 17); ! 192: putlog(2, "割り込み保持読み出し(CPU#%d) -> $%08x", n, data); ! 193: return data; ! 194: } ! 195: ! 196: if (0x69000000 <= addr && addr < 0x69000010) { ! 197: putlog(1, "ソフトウェア割り込み(CPU#%d)クリア(未実装)", n); ! 198: return 0xffffffff; ! 199: } ! 200: ! 201: if (0x6d000000 <= addr && addr < 0x6d000010) { ! 202: putlog(1, "CPU%d リセット 未実装読み込み", n); ! 203: return 0xffffffff; ! 204: } ! 205: if (addr == 0x6d000010) { ! 206: putlog(1, "CPU ALL リセット 未実装読み込み"); ! 207: return 0xffffffff; ! 208: } ! 209: ! 210: putlog(0, "未実装読み込み $%08x", addr); ! 211: return 0xffffffff; ! 212: } ! 213: ! 214: uint64 ! 215: SysCtlrDevice::Write32(uint32 addr, uint32 data) ! 216: { ! 217: int n = (addr & 15) >> 2; ! 218: ! 219: if (0x65000000 <= addr && addr < 0x65000010) { ! 220: intmask[n] = data >> 25; ! 221: ! 222: // XXX: クリアしてみる ! 223: intlevel[n] = 0; ! 224: ! 225: putlog(1, "割り込みマスク(CPU#%d) <- $%08x", n, intmask[n] << 25); ! 226: return 0; ! 227: } ! 228: if (0x69000000 <= addr && addr < 0x69000010) { ! 229: // 詳細不明。0xFFFFFFFF が書き込まれている、ようだ。 ! 230: intlevel[n] &= ~data; ! 231: // bit 表示したい ! 232: putlog(0, "割り込み(CPU#%d)クリア 0x%x 残り=0x%x", n, data, intlevel[n]); ! 233: return 0; ! 234: } ! 235: if (0x6d000000 <= addr && addr < 0x6d000010) { ! 236: putlog(0, "CPU%d リセット 未実装書き込み", n); ! 237: return 0; ! 238: } ! 239: if (addr == 0x6d000010) { ! 240: putlog(0, "CPU ALL リセット 未実装書き込み"); ! 241: return 0; ! 242: } ! 243: ! 244: putlog(0, "未実装書き込み $%08x <- $%08x", addr, data); ! 245: return 0; ! 246: } ! 247: ! 248: uint64 ! 249: SysCtlrDevice::Peek8(uint32 addr) ! 250: { ! 251: uint32 data; ! 252: int n = (addr & 15) >> 2; ! 253: ! 254: if (0x65000000 <= addr && addr < 0x65000010) { ! 255: data = intmask[n] << 25; ! 256: } else { ! 257: data = 0xffffffff; ! 258: } ! 259: switch (addr & 3) { ! 260: case 0: ! 261: return data >> 24; ! 262: case 1: ! 263: return (data >> 16) & 0xff; ! 264: case 2: ! 265: return (data >> 8) & 0xff; ! 266: case 3: ! 267: return data & 0xff; ! 268: default: ! 269: break; ! 270: } ! 271: __unreachable(); ! 272: } ! 273: ! 274: bool ! 275: SysCtlrDevice::MonitorUpdate() ! 276: { ! 277: monitor.Clear(); ! 278: monitor.Puts(6, 0, "IntrEnable SWIntr"); ! 279: for (int i = 0; i < countof(intmask); i++) { ! 280: monitor.Print(0, i + 1, "CPU#%d $%02x", i, intmask[i]); ! 281: } ! 282: ! 283: return true; ! 284: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.