Annotation of nono/vm/sysctlr.cpp, revision 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.