|
|
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:
1.1.1.2 ! root 158: monitor_size = nnSize(60, 5);
1.1 root 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:
1.1.1.2 ! root 274: void
! 275: SysCtlrDevice::MonitorUpdate(TextScreen& monitor)
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.