Annotation of nono/vm/sysctlr.cpp, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.