Annotation of nono/vm/pio.cpp, revision 1.1.1.9

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "pio.h"
1.1.1.9 ! root        8: #include "bitops.h"
1.1.1.2   root        9: #include "config.h"
1.1       root       10: #include "lcd.h"
1.1.1.3   root       11: #include "mainapp.h"
1.1       root       12: #include "scheduler.h"
                     13: 
                     14: //           IODevice
                     15: //               |
                     16: //               v
                     17: //          i8255Device  (8255 としての共通部分)
                     18: //               |
                     19: //    +----------+----------+
                     20: //    v          v          v
                     21: // PPIDevice  PIO0Device PIO1Device
                     22: // (X68030)   (LUNA)     (LUNA)
                     23: 
1.1.1.6   root       24: std::unique_ptr<PPIDevice> gPPI;
1.1       root       25: std::unique_ptr<PIO0Device> gPIO0;
                     26: std::unique_ptr<PIO1Device> gPIO1;
                     27: 
                     28: //
                     29: // i8255
                     30: //
                     31: 
                     32: // コンストラクタ
1.1.1.8   root       33: i8255Device::i8255Device(const std::string& objname_)
                     34:        : inherited(objname_)
1.1       root       35: {
                     36: }
                     37: 
                     38: // デストラクタ
                     39: i8255Device::~i8255Device()
                     40: {
                     41: }
                     42: 
1.1.1.4   root       43: // リセット
                     44: void
                     45: i8255Device::ResetHard()
                     46: {
                     47:        // clears the control register
                     48:        // and place ports A, B, and C in input mode.
                     49:        // The input latches in ports A, B, and C are not cleared.
                     50: 
                     51:        ctrl = 0b10011011;
                     52: }
                     53: 
1.1       root       54: // コントロールポートへの書き込み。
                     55: void
                     56: i8255Device::WriteCtrl(uint32 data)
                     57: {
                     58:        if ((data & 0x80)) {
                     59:                // 最上位が立っていればモード設定
                     60:                ctrl = data;
                     61:                putlog(1,
                     62:                        "モード設定 groupA=%d groupB=%d portA=%s portB=%s portC=%s/%s",
                     63:                        GetGroupAMode(), GetGroupBMode(),
                     64:                        PortADir() == DIR_IN ? "IN" : "OUT",
                     65:                        PortBDir() == DIR_IN ? "IN" : "OUT",
                     66:                        PortCHDir() == DIR_IN ? "IN" : "OUT",
                     67:                        PortCLDir() == DIR_IN ? "IN" : "OUT");
                     68: 
                     69:                // モード設定すると PC はゼロクリアされる
                     70:                for (int pc = 0; pc < 8; pc++) {
                     71:                        SetPC(pc, 0);
                     72:                }
                     73:        } else {
                     74:                // portC 出力
                     75:                //
                     76:                // 0  x  x  x  P  P  P  V
                     77:                //             |  |  |  +-- 書き込むビットデータ
                     78:                //             +--+--+----- 書き込むビット位置
                     79: 
                     80:                int pc = (data >> 1) & 7;
                     81:                int val = data & 1;
                     82:                SetPC(pc, val);
                     83:        }
                     84: }
                     85: 
                     86: void
                     87: i8255Device::SetPC(int pc, int data)
                     88: {
                     89:        // 継承側で用意すること。ここには来ない
                     90:        PANIC("not impl");
                     91: }
                     92: 
                     93: //
                     94: // X68k PPI
                     95: //
                     96: 
                     97: // コンストラクタ
                     98: PPIDevice::PPIDevice()
1.1.1.8   root       99:        : inherited("PPI")
1.1       root      100: {
                    101:        devaddr = baseaddr;
                    102:        devlen  = 0x2000;
                    103: }
                    104: 
                    105: // デストラクタ
                    106: PPIDevice::~PPIDevice()
                    107: {
                    108: }
                    109: 
                    110: uint64
1.1.1.6   root      111: PPIDevice::Read(uint32 offset)
1.1       root      112: {
1.1.1.4   root      113:        gMPU->AddCycle(19);     // InsideOut p.135
                    114: 
1.1.1.6   root      115:        switch (offset) {
1.1       root      116:         case 0:
                    117:         case 1:
                    118:                return 0xff;
                    119:         case 2:
1.1.1.6   root      120:                putlog(0, "$e9a005 PortC 未実装読み込み");
1.1.1.5   root      121:                return 0xff;
1.1       root      122:         case 3:
1.1.1.6   root      123:                PANIC("PPI $e9a007 未サポート読み込み");
1.1       root      124:                break;
                    125:         default:
                    126:                __unreachable();
                    127:        }
                    128:        PANIC("not impl");
                    129: }
                    130: 
                    131: uint64
1.1.1.6   root      132: PPIDevice::Write(uint32 offset, uint32 data)
1.1       root      133: {
1.1.1.4   root      134:        gMPU->AddCycle(19);     // InsideOut p.135
                    135: 
1.1.1.6   root      136:        switch (offset) {
1.1       root      137:         case 0:
                    138:         case 1:
                    139:                break;
                    140:         case 2:
1.1.1.6   root      141:                putlog(0, "$e9a005 未実装書き込み $%02X (無視)", data);
1.1       root      142:                break;
                    143:         case 3:
                    144:                if (data != 0x92) {
1.1.1.6   root      145:                        PANIC("PPI $e9a007 未実装書き込み $%02X", data);
1.1       root      146:                } else {
1.1.1.6   root      147:                        putlog(0, "$e9a007 未実装書き込み $%02x (無視)", data);
1.1       root      148:                }
                    149:                break;
                    150:         default:
                    151:                __unreachable();
                    152:        }
                    153:        return 0;
                    154: }
                    155: 
                    156: uint64
1.1.1.6   root      157: PPIDevice::Peek(uint32 offset)
1.1       root      158: {
                    159:        // XXX
                    160:        return 0xff;
                    161: }
                    162: 
                    163: //
                    164: // LUNA PIO0
                    165: //
                    166: // 仕様は 0x49000000 から 4バイトだが、
                    167: // 0x48000000 から 0x4c000000 の手前まで 4バイト単位でミラーが見える。
                    168: //
                    169: // LUNA の DIP-SW は #1, #2 にそれぞれ8個、計16個ある。
1.1.1.9 ! root      170: // DIP-SW #1, #2 が設定ファイルの luna-dipsw{1,2} に対応する。
        !           171: // luna-dipsw{1,2} はいずれも "0"/"1" を8つ並べた文字列であり、
1.1       root      172: // 先頭が本体表記でいう 1番、末尾側が本体表記でいう 8番に対応する。
1.1.1.9 ! root      173: // 値は "0" が down、"1" が up を表す。
        !           174: //
        !           175: // PIO0Device 内ではこの設定を読み込んで bool dipsw1[8], dipsw2[8] の配列で
        !           176: // 値を保持している。dipsw1[0] が本体表記1番、dipsw1[7] が本体表記 8番に対応
        !           177: // する。値は false が down("0")、true が up("1") に対応する。
        !           178: //
        !           179: // PIO から読み出せる値のビットの並び順が機種によって異なる。
        !           180: // LUNA-1  では 1番が LSB、8番が MSB の並び順、
        !           181: // LUNA88K では 1番が MSB、8番が LSB の並び順。
        !           182: // 値は、並び順に関わらずどちらも
        !           183: // %0 が false = down = "0"、%1 が true = up = "1" である。
        !           184: //
        !           185: //    #1 #2 #3 #4 #5 #6 #7 #8
        !           186: //  +-------------------------+
        !           187: //  |    [] [] [] [] [] [] [] | 本体外観
        !           188: //  | []                      |
        !           189: //  +-------------------------+
        !           190: //
        !           191: // luna-dipsw1 = "01111111"    ← 設定ファイル
        !           192: //                ||||||||     ↓ このクラスのメンバ変数
        !           193: //                |||||||+- dipsw1[7] = true;
        !           194: //                ||||||+-- dipsw1[6] = true;
        !           195: //                |||||+--- dipsw1[5] = true;
        !           196: //                ||||+---- dipsw1[4] = true;
        !           197: //                |||+----- dipsw1[3] = true;
        !           198: //                ||+------ dipsw1[2] = true;
        !           199: //                |+------- dipsw1[1] = true;
        !           200: //                +-------- dipsw1[0] = false;
        !           201: //
        !           202: //              b7   b6   b5   b4   b3   b2   b1   b0
        !           203: //            +----+----+----+----+----+----+----+----+
        !           204: // LUNA-1     | #8 | #7 | #6 | #5 | #4 | #3 | #2 | #1 |
        !           205: // PortA      |  1 |  1 |  1 |  1 |  1 |  1 |  1 |  0 | %1=UP, %0=DOWN
        !           206: //            +----+----+----+----+----+----+----+----+
        !           207: //
        !           208: //              b7   b6   b5   b4   b3   b2   b1   b0
        !           209: //            +----+----+----+----+----+----+----+----+
        !           210: // LUNA88K    | #1 | #2 | #3 | #4 | #5 | #6 | #7 | #8 |
        !           211: // PortA      |  0 |  1 |  1 |  1 |  1 |  1 |  1 |  1 | %1=UP, %0=DOWN
        !           212: //            +----+----+----+----+----+----+----+----+
1.1       root      213: //
1.1.1.3   root      214: // LUNA-1:
1.1       root      215: // #1-1 up なら UNIX をロードして移行。down なら ROM モニタで起動。
                    216: // #1-2 up ならディスプレイコンソール。down ならシリアルコンソール。
                    217: // #1-3 up - color display, down - force to have monochrome display
                    218: // #1-4 up - no write verification,
                    219: //      down - verification on every harddisk write operation
                    220: // #1-5 up - OS is UniOS-U (SystemV/COFF),
                    221: //      down - OS is UniOS (4.3BSD/a.out OMAGIC)
                    222: // #1-6 down - force monochrome display?
                    223: // #1-7 up - boot from local device, down - boot from network
                    224: // #1-8 up - normal boot, down - start diagnostics と書いてあるが
                    225: //      down にすると画面真っ暗で詳細不明。
                    226: //
                    227: // #2-x すべて up にすると /boot が自動的にカーネルを起動。一つでも down が
                    228: //      あれば /boot がプロンプトで停止。これは ROM ではなく NetBSD のブート
                    229: //      ローダの話。
                    230: //      どこか由来のソースコードらしいがたぶんビット演算を間違えている。
1.1.1.3   root      231: //
                    232: // LUNA88K:
                    233: // #1-1 up なら ROM モニタで停止、down ならマルチユーザブート。
                    234: //      OpenBSD カーネルも up なら UserKernelConfig で止まる模様?。
                    235: // #1-2 up なら外付けシリアルコンソール、down なら内蔵ビットマップ。
1.1.1.9 ! root      236: // #1-3..#1-7 は不明?
        !           237: // #1-8 down なら自己診断後電源オフするようだ。
1.1.1.3   root      238: // #2-x はユーザ(?)
1.1       root      239: 
                    240: // コンストラクタ
                    241: PIO0Device::PIO0Device()
1.1.1.8   root      242:        : inherited("PIO0")
1.1       root      243: {
                    244:        devaddr = 0x49000000;
                    245:        devlen  = 4;
1.1.1.2   root      246: 
1.1.1.3   root      247:        // 機種固有パラメータ
                    248: 
                    249:        // LUNA-1 と LUNA88K で使いやすいように初期値を変えておく。
                    250:        switch (gMainApp.GetVMType()) {
                    251:         case VMTYPE_LUNA1:
                    252:                gConfig->SetDefault("luna-dipsw1", "11110111");
1.1.1.9 ! root      253:                msb_first = false;
1.1.1.3   root      254:                break;
                    255:         case VMTYPE_LUNA88K:
1.1.1.4   root      256:                gConfig->SetDefault("luna-dipsw1", "11111111");
1.1.1.9 ! root      257:                msb_first = true;
1.1.1.3   root      258:                break;
                    259:         default:
                    260:                __unreachable();
                    261:        }
                    262:        // DIP-SW#2 はユーザ定義(?)なので(今の所?)どちらも共通。
                    263:        gConfig->SetDefault("luna-dipsw2", "11111111");
                    264: 
1.1.1.8   root      265:        monitor.func = (MonitorCallback_t)&PIO0Device::MonitorUpdate;
                    266:        monitor.SetSize(22, 11);
                    267:        monitor.Regist(ID_MONITOR_PIO0);
1.1       root      268: }
                    269: 
                    270: // デストラクタ
                    271: PIO0Device::~PIO0Device()
                    272: {
                    273: }
                    274: 
                    275: bool
                    276: PIO0Device::Init()
                    277: {
                    278:        // XXX 本当はラッチのタイミングが違う気もするけど、とりあえずね
                    279: 
1.1.1.2   root      280:        const ConfigItem& item1 = gConfig->Find("luna-dipsw1");
1.1       root      281:        const std::string& str1 = item1.AsString();
                    282:        if (str1.size() != 8) {
                    283:                item1.Err("must be 8 digits");
                    284:                return false;
                    285:        }
                    286: 
1.1.1.2   root      287:        const ConfigItem& item2 = gConfig->Find("luna-dipsw2");
1.1       root      288:        const std::string& str2 = item2.AsString();
                    289:        if (str2.size() != 8) {
                    290:                item2.Err("must be 8 digits");
                    291:                return false;
                    292:        }
                    293:        for (int i = 0; i < 8; i++) {
                    294:                dipsw1[i] = (str1[i] != '0');
                    295:                dipsw2[i] = (str2[i] != '0');
                    296:        }
                    297:        return true;
                    298: }
                    299: 
1.1.1.7   root      300: // XXX PowerOn か ResetHard 未調査
                    301: 
1.1       root      302: uint64
1.1.1.6   root      303: PIO0Device::Read(uint32 offset)
1.1       root      304: {
                    305:        uint32 data;
                    306: 
1.1.1.6   root      307:        switch (offset) {
1.1       root      308:         case 0:
                    309:                // PortA
                    310:                putlog(1, "DIP-SW 1 読み込み");
                    311:                return GetPA();
                    312: 
                    313:         case 1:
                    314:                // PortB
                    315:                putlog(1, "DIP-SW 2 読み込み");
                    316:                return GetPB();
                    317: 
                    318:         case 2:
                    319:                // PortC
                    320:                data = GetPC();
1.1.1.6   root      321:                putlog(1, "PC 読み込み -> $%02x", data);
1.1       root      322:                return data;
                    323: 
                    324:         case 3:
                    325:                data = ReadCtrl();
                    326:                putlog(1, "コントロール読み込み -> $%02x", data);
                    327:                return data;
                    328: 
                    329:         default:
                    330:                __unreachable();
                    331:        }
                    332: }
                    333: 
                    334: uint64
1.1.1.6   root      335: PIO0Device::Write(uint32 offset, uint32 data)
1.1       root      336: {
1.1.1.6   root      337:        switch (offset) {
1.1       root      338:         case 0:        // PIO0 PortA: DIPSW1 (入力のみ)
                    339:         case 1:        // PIO0 PortB: DIPSW2 (入力のみ)
                    340:                return 0;
                    341: 
                    342:         case 2:        // PIO0 PortC: ホスト割り込み制御
                    343:                for (int i = 0; i < 8; i++) {
                    344:                        SetPC(i, data & 1);
                    345:                        data >>= 1;
                    346:                }
                    347:                return 0;
                    348: 
                    349:         case 3:        // コントロール
                    350:                WriteCtrl(data);
                    351:                return 0;
                    352: 
                    353:         default:
                    354:                __unreachable();
                    355:        }
                    356: }
                    357: 
                    358: uint64
1.1.1.6   root      359: PIO0Device::Peek(uint32 offset)
1.1       root      360: {
1.1.1.6   root      361:        switch (offset) {
1.1       root      362:         case 0:
                    363:                return GetPA();
                    364: 
                    365:         case 1:
                    366:                return GetPB();
                    367: 
                    368:         case 2:
                    369:                return GetPC();
                    370: 
                    371:         case 3:
                    372:                return ReadCtrl();
                    373: 
                    374:         default:
                    375:                __unreachable();
                    376:        }
                    377: }
                    378: 
1.1.1.3   root      379: void
1.1.1.8   root      380: PIO0Device::MonitorUpdate(Monitor *, TextScreen& screen)
1.1.1.2   root      381: {
                    382:        int y;
                    383: 
1.1.1.8   root      384:        screen.Clear();
1.1.1.2   root      385: 
                    386:        y = 0;
1.1.1.8   root      387:        screen.Print(0, y++, "PortA(DIPSW1):%c%c%c%c%c%c%c%c",
1.1.1.2   root      388:                (dipsw1[0] ? '1' : '0'),
                    389:                (dipsw1[1] ? '1' : '0'),
                    390:                (dipsw1[2] ? '1' : '0'),
                    391:                (dipsw1[3] ? '1' : '0'),
                    392:                (dipsw1[4] ? '1' : '0'),
                    393:                (dipsw1[5] ? '1' : '0'),
                    394:                (dipsw1[6] ? '1' : '0'),
                    395:                (dipsw1[7] ? '1' : '0'));
1.1.1.8   root      396:        screen.Print(0, y++, "PortB(DIPSW2):%c%c%c%c%c%c%c%c",
1.1.1.2   root      397:                (dipsw2[0] ? '1' : '0'),
                    398:                (dipsw2[1] ? '1' : '0'),
                    399:                (dipsw2[2] ? '1' : '0'),
                    400:                (dipsw2[3] ? '1' : '0'),
                    401:                (dipsw2[4] ? '1' : '0'),
                    402:                (dipsw2[5] ? '1' : '0'),
                    403:                (dipsw2[6] ? '1' : '0'),
                    404:                (dipsw2[7] ? '1' : '0'));
1.1.1.8   root      405:        screen.Puts(0, y++, "PortC");
                    406:        screen.Puts(1, y++, TA::OnOff(xp_reset), "b7: XP Reset");
                    407:        screen.Puts(1, y++, TA::OnOff(parity),   "b6: Parity");
1.1.1.9 ! root      408:        screen.Puts(1, y++, TA::Disable,         "b5: ---");
1.1.1.8   root      409:        screen.Puts(1, y++, TA::OnOff(int5en),   "b4: Int5 Enable");
                    410:        screen.Puts(1, y++, TA::OnOff(int5rq),   "b3: Int5 Request");
                    411:        screen.Puts(1, y++, TA::OnOff(int1en),   "b2: Int1 Enable");
1.1.1.9 ! root      412:        screen.Puts(1, y++, TA::Disable,         "b1: ---");
1.1.1.8   root      413:        screen.Puts(1, y++, TA::OnOff(int1rq),   "b0: Intq Request");
1.1.1.2   root      414: }
                    415: 
1.1       root      416: // PortA (DIP-SW 1) 読み込み
                    417: uint32
                    418: PIO0Device::GetPA() const
                    419: {
                    420:        uint32 data = 0;
                    421:        for (int i = 0; i < 8; i++) {
                    422:                data |= ((int)dipsw1[i]) << i;
                    423:        }
1.1.1.9 ! root      424:        if (msb_first) {
        !           425:                data = bitrev(data);
        !           426:        }
1.1       root      427:        return data & 0xff;
                    428: }
                    429: 
                    430: // PortB (DIP-SW 2) 読み込み
                    431: uint32
                    432: PIO0Device::GetPB() const
                    433: {
                    434:        uint32 data = 0;
                    435:        for (int i = 0; i < 8; i++) {
                    436:                data |= ((int)dipsw2[i]) << i;
                    437:        }
1.1.1.9 ! root      438:        if (msb_first) {
        !           439:                data = bitrev(data);
        !           440:        }
1.1       root      441:        return data & 0xff;
                    442: }
                    443: 
                    444: // PortC 読み込み
                    445: uint32
                    446: PIO0Device::GetPC() const
                    447: {
                    448:        uint32 data;
                    449: 
                    450:        data = 0x00     // XXX 空きビットは何が読めるか?
                    451:                 | (int1rq ? 0x01 : 0)
                    452:                 | (int1en ? 0x04 : 0)
                    453:                 | (int5rq ? 0x08 : 0)
                    454:                 | (int5en ? 0x10 : 0)
                    455:                 | (parity ? 0x40 : 0)
                    456:                 | (xp_reset?0x80 : 0);
                    457:        return data;
                    458: }
                    459: 
                    460: // PortC 書き込み
                    461: void
                    462: PIO0Device::SetPC(int pc, int val)
                    463: {
                    464:        switch (pc) {
                    465:         case 0:
                    466:                if ((val ^ int1rq)) {
                    467:                        int1rq = val;
                    468:                        putlog(0, "INT1割り込み要求 %d (未実装)", int1rq);
                    469:                }
                    470:                return;
                    471:         case 1:
                    472:                // Not Connected.
                    473:                return;
                    474:         case 2:
                    475:                if ((val ^ int1en)) {
                    476:                        int1en = val;
                    477:                        putlog(0, "INT1割り込み許可 %d (未実装)", int1en);
                    478:                }
                    479:                return;
                    480:         case 3:
                    481:                if ((val ^ int5rq)) {
                    482:                        int5rq = val;
                    483:                        putlog(0, "INT5割り込み要求 %d (未実装)", int5rq);
                    484:                }
                    485:                return;
                    486:         case 4:
                    487:                if ((val ^ int5en)) {
                    488:                        int5en = val;
                    489:                        putlog(0, "INT5割り込み許可 %d (未実装)", int5en);
                    490:                }
                    491:                return;
                    492:         case 5:
                    493:                // Not Connected.
                    494:                return;
                    495:         case 6:
                    496:                // パリティ有効/無効
                    497:                // 使わないので無視するが読み返しのために覚えておく
                    498:                parity = val;
                    499:                return;
                    500:         case 7:
                    501:                // XP リセット
                    502:                if ((val ^ xp_reset)) {
                    503:                        xp_reset = val;
                    504:                        putlog(0, "XPリセット %d (未実装)", xp_reset);
                    505:                }
                    506:                return;
                    507:        }
                    508:        PANIC("invalid pc=%d", pc);
                    509: }
                    510: 
                    511: 
                    512: //
                    513: // LUNA PIO1
                    514: //
                    515: // 仕様は 0x4d000000 から 4バイトだが、
                    516: // 0x4c000000 から 0x50000000 の手前まで 4バイト単位でミラーが見える。
                    517: 
                    518: // コンストラクタ
                    519: PIO1Device::PIO1Device()
1.1.1.8   root      520:        : inherited("PIO1")
1.1       root      521: {
                    522:        devaddr = 0x4d000000;
                    523:        devlen  = 4;
                    524: 
                    525:        poffevent.func = (DeviceCallback_t)&PIO1Device::PowerOffCallback;
                    526:        poffevent.SetName("PIO1 Power Off");
                    527: }
                    528: 
                    529: // デストラクタ
                    530: PIO1Device::~PIO1Device()
                    531: {
                    532: }
                    533: 
1.1.1.4   root      534: // リセット
                    535: void
                    536: PIO1Device::ResetHard()
                    537: {
                    538:        inherited::ResetHard();
                    539: 
                    540:        poffevent.Stop();
                    541: }
                    542: 
1.1       root      543: uint64
1.1.1.6   root      544: PIO1Device::Read(uint32 offset)
1.1       root      545: {
                    546:        uint32 data;
                    547: 
1.1.1.6   root      548:        switch (offset) {
1.1       root      549:         case 0:
                    550:                // PIO1 PortA: LCD データ
                    551:                return gLCD->Read();
                    552: 
                    553:         case 1:
                    554:                // PIO1 PortB: 無効
                    555:                return 0xff;
                    556: 
                    557:         case 2:
                    558:                // PortC
                    559:                data = gLCD->Get();
                    560:                data |= xp_intreq ? 0 : 0x02;
                    561:                // 残りのビットは %1 だろうか?
                    562:                data |= 0x0d;
                    563:                putlog(1, "PC 読み込み -> $%02x", data);
                    564:                return data;
                    565: 
                    566:         case 3:
                    567:                data = ReadCtrl();
                    568:                putlog(1, "コントロール読み込み -> $%02x", data);
                    569:                return data;
                    570: 
                    571:         default:
                    572:                __unreachable();
                    573:        }
                    574: }
                    575: 
                    576: uint64
1.1.1.6   root      577: PIO1Device::Write(uint32 offset, uint32 data)
1.1       root      578: {
1.1.1.6   root      579:        switch (offset) {
1.1       root      580:         case 0:        // PIO1 PortA: LCD データ
                    581:                gLCD->Write(data);
                    582:                return 0;
                    583: 
                    584:         case 1:        // PIO1 PortB: ローカル割り込み
                    585:                break;
                    586: 
                    587:         case 2:        // PIO1 PortC: LCD/パワーオフ制御
                    588:                for (int i = 0; i < 8; i++) {
                    589:                        SetPC(i, data & 1);
                    590:                        data >>= 1;
                    591:                }
                    592:                return 0;
                    593: 
                    594:         case 3:        // コントロール
                    595:                WriteCtrl(data);
                    596:                return 0;
                    597: 
                    598:         default:
                    599:                __unreachable();
                    600:        }
1.1.1.6   root      601:        PANIC("$%08X <- $%02X 未サポート書き込み", gMPU->GetPaddr(), data);
1.1       root      602:        return 0;
                    603: }
                    604: 
                    605: uint64
1.1.1.6   root      606: PIO1Device::Peek(uint32 offset)
1.1       root      607: {
                    608:        uint32 data;
                    609: 
1.1.1.6   root      610:        switch (offset) {
1.1       root      611:         case 0:        // PIO1 PortA LCD データ
                    612:                return gLCD->Peek();
                    613: 
                    614:         case 1:        // PIO1 PortB 無効
                    615:                return 0xff;
                    616: 
                    617:         case 2:        // PIO1 PortC
                    618:                data = gLCD->Get();
                    619:                data |= xp_intreq ? 0 : 0x02;
                    620:                // 残りのビットは %1 だろうか?
                    621:                data |= 0x0d;
                    622:                return data;
                    623: 
                    624:         case 3:
                    625:                return ReadCtrl();
                    626: 
                    627:         default:
                    628:                __unreachable();
                    629:        }
                    630: }
                    631: 
                    632: void
                    633: PIO1Device::SetPC(int pc, int val)
                    634: {
                    635:        switch (pc) {
                    636:         case 0:
                    637:         case 1:
                    638:         case 2:
                    639:         case 3:
                    640:                // PortC の下半分は入力ポートとして使われることを想定して
                    641:                // いるので、ここへの書き込みは起きないだろうし、無視する。
                    642:                return;
                    643: 
                    644:         case 4:
                    645:                power = val;
                    646:                if (power) {
                    647:                        // 電源オフ取り消し
                    648:                        putlog(1, "電源 OFF 取消");
                    649:                        poffevent.Stop();
                    650:                } else {
                    651:                        // 1msec 後に電源オフ
                    652:                        putlog(1, "電源 OFF 指示");
                    653:                        poffevent.time = 1_msec;
                    654:                        poffevent.Start();
                    655:                }
                    656:                return;
                    657:         case 5:
                    658:                gLCD->SetRW(val);
                    659:                return;
                    660:         case 6:
                    661:                gLCD->SetRS(val);
                    662:                return;
                    663:         case 7:
                    664:                gLCD->SetE(val);
                    665:                return;
                    666: 
                    667:         default:
                    668:                break;
                    669:        }
                    670:        PANIC("PC%d 未実装", pc);
                    671: }
                    672: 
                    673: // 電源 OFF イベントのコールバック
                    674: void
1.1.1.4   root      675: PIO1Device::PowerOffCallback(Event& ev)
1.1       root      676: {
                    677:        putlog(0, "電源 OFF");
                    678:        gScheduler->RequestPowerOff();
                    679: }

unix.superglobalmegacorp.com

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