Annotation of nono/vm/upd7201.cpp, revision 1.1.1.6

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "upd7201.h"
1.1.1.5   root        8: #include "interrupt.h"
1.1       root        9: 
                     10: // コンストラクタ
                     11: uPD7201Device::uPD7201Device()
                     12: {
1.1.1.5   root       13:        monitor_size = nnSize(48, 22);
1.1       root       14:        cr.chan[0].id = 0;
                     15:        cr.chan[0].name = "A";
                     16:        cr.chan[1].id = 1;
                     17:        cr.chan[1].name = "B";
                     18: 
                     19:        cr.chan[0].desc = NULL;
                     20:        cr.chan[1].desc = NULL;
                     21: }
                     22: 
                     23: // デストラクタ
                     24: uPD7201Device::~uPD7201Device()
                     25: {
                     26: }
                     27: 
                     28: // リセット
                     29: void
1.1.1.6 ! root       30: uPD7201Device::ResetHard()
1.1       root       31: {
                     32:        putlog(2, "リセット");
                     33: 
                     34:        // CR2A はチップリセットで bit6 以外を '0' に
                     35:        cr.cr2a &= ~0xbf;
                     36: 
                     37:        // チャンネルリセット
                     38:        ResetChannel(&cr.chan[0]);
                     39:        ResetChannel(&cr.chan[1]);
                     40: }
                     41: 
                     42: // チャンネルリセット
                     43: void
                     44: uPD7201Device::ResetChannel(struct SIO::channel *chan)
                     45: {
1.1.1.5   root       46:        putlog(2, "Channel %s Reset", chan->name);
1.1       root       47: 
1.1.1.5   root       48:        // CR0 b2-0 (PTR)
1.1       root       49:        chan->ptr = 0;
                     50: 
                     51:        // CR1 b0,1,3,4,7
                     52:        chan->cr1 &= ~(SIO::CR1_WAIT_EN | SIO::CR1_RXINT |
                     53:                       SIO::CR1_TXINT_EN | SIO::CR1_ESINT_EN);
1.1.1.5   root       54:        chan->all_or_first = false;
1.1       root       55: 
                     56:        // CR3 b0-7
                     57:        chan->cr3 = 0;
                     58: 
                     59:        // CR5 b1,2,3,4,7
                     60:        chan->cr5 &= ~(SIO::CR5_DTR | SIO::CR5_SENDBREAK | SIO::CR5_TX_EN |
                     61:                       SIO::CR5_CRC16 | SIO::CR5_RTS);
                     62: 
                     63:        // SR0 は b0,1 が '0'、b2,6 が '1'、残りは不定
                     64:        chan->sr0 &= ~(SIO::SR0_INTPEND | SIO::SR0_RXAVAIL);
                     65:        chan->sr0 |= (SIO::SR0_TXUNDER | SIO::SR0_TXEMPTY);
                     66: 
                     67:        // SR1 は b4-7 が '0'
                     68:        chan->sr1 &= ~(SIO::SR1_ENDOFFRAME | SIO::SR1_CRCERROR |
                     69:                       SIO::SR1_RXOVERRUN | SIO::SR1_PARITYERROR);
                     70: 
1.1.1.5   root       71:        // 内部状態をリセット
1.1       root       72:        chan->es_ratched = false;
1.1.1.5   root       73:        chan->reset_txint_pend = true;
1.1       root       74: 
                     75:        // 受信バッファをクリア
                     76:        memset(chan->rxbuf, 0, sizeof(chan->rxbuf));
                     77:        chan->rxlen = 0;
                     78: }
                     79: 
                     80: // 制御ポートの読み込み
                     81: uint8
                     82: uPD7201Device::ReadCtrl(struct SIO::channel *chan)
                     83: {
                     84:        uint8 data;
                     85: 
                     86:        switch (chan->ptr) {
                     87:         case 0:        // SR0
1.1.1.5   root       88:                data = chan->sr0;
1.1       root       89:                putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
                     90:                // アクセス後は SR0 へ戻す
                     91:                chan->ptr = 0;
                     92:                break;
                     93: 
                     94:         case 1:        // SR1
1.1.1.5   root       95:                data = chan->sr1;
1.1       root       96:                putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
                     97:                // アクセス後は SR0 へ戻す
                     98:                chan->ptr = 0;
                     99:                break;
                    100: 
                    101:         case 2:
                    102:                // SR2B はベクタの読み出し
                    103:                if (chan->id == 1) {
                    104:                        data = cr.vector;
                    105:                        putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
                    106:                        // アクセス後は SR0 へ戻す
                    107:                        chan->ptr = 0;
                    108:                        break;
                    109:                }
                    110: 
                    111:                // SR2A はない
                    112:                FALLTHROUGH;
                    113: 
                    114:         default:
                    115:                putlog(0, "未実装レジスタ読み込み SR%d%s",
                    116:                        chan->ptr, chan->name);
                    117:                // SR0 へ戻る?
                    118:                chan->ptr = 0;
                    119:                return 0xff;
                    120:        }
                    121:        return data;
                    122: }
                    123: 
                    124: // 制御ポートの書き込み
                    125: void
                    126: uPD7201Device::WriteCtrl(struct SIO::channel *chan, uint32 data)
                    127: {
1.1.1.5   root      128:        // CR0 はコマンドかまたは次にアクセスするレジスタを指定する。
                    129:        // CR0 以外のレジスタをアクセスすると、次のアクセスは CR0 に戻る。
1.1       root      130: 
1.1.1.5   root      131:        if (chan->ptr == 0) {
                    132:                WriteCR0(chan, data);
                    133:        } else {
                    134:                switch (chan->ptr) {
                    135:                 case 1:
                    136:                        WriteCR1(chan, data);
1.1       root      137:                        break;
1.1.1.5   root      138:                 case 2:
                    139:                        WriteCR2(chan, data);
1.1       root      140:                        break;
1.1.1.5   root      141:                 case 3:
                    142:                        WriteCR3(chan, data);
1.1       root      143:                        break;
1.1.1.5   root      144:                 case 4:
                    145:                        WriteCR4(chan, data);
1.1       root      146:                        break;
1.1.1.5   root      147:                 case 5:
                    148:                        WriteCR5(chan, data);
1.1       root      149:                        break;
1.1.1.5   root      150:                 case 6:
                    151:                        WriteCR6(chan, data);
1.1       root      152:                        break;
1.1.1.5   root      153:                 case 7:
                    154:                        WriteCR7(chan, data);
1.1       root      155:                        break;
                    156:                 default:
1.1.1.5   root      157:                        putlog(0, "未実装レジスタ書き込み CR%d%s <- $%02x",
                    158:                                chan->ptr, chan->name, data);
                    159:                        break;
1.1       root      160:                }
                    161:                // アクセス後は CR0 へ戻す
                    162:                chan->ptr = 0;
                    163:        }
                    164: }
                    165: 
1.1.1.2   root      166: // 制御ポートの Peek
                    167: uint8
                    168: uPD7201Device::PeekCtrl(const struct SIO::channel *chan) const
                    169: {
                    170:        switch (chan->ptr) {
                    171:         case 0:        // SR0
1.1.1.5   root      172:                return chan->sr0;
1.1.1.2   root      173: 
                    174:         case 1:        // SR1
1.1.1.5   root      175:                return chan->sr1;
1.1.1.2   root      176: 
                    177:         case 2:        // SR2
                    178:                // SR2A はない。SR2B はベクタの読み出し
                    179:                if (chan->id == 1) {
                    180:                        return cr.vector;
                    181:                }
                    182:                FALLTHROUGH;
                    183: 
                    184:         default:
                    185:                // 未調査
                    186:                return 0xff;
                    187:        }
                    188: }
                    189: 
1.1.1.5   root      190: // CR0 への書き込み
                    191: void
                    192: uPD7201Device::WriteCR0(struct SIO::channel *chan, uint32 data)
1.1.1.2   root      193: {
1.1.1.5   root      194:        uint cmd;
1.1.1.2   root      195: 
1.1.1.5   root      196:        // XXX b7,b6 は未対応。
                    197:        // b5,b4,b3 がコマンド。
                    198:        // b2,b1,b0 が次にアクセスするレジスタ(chan->ptr)の切り替え。
                    199:        chan->cr0 = data;
                    200:        chan->ptr = (chan->cr0 & SIO::CR0_PTR);
                    201: 
                    202:        cmd = (chan->cr0 & SIO::CR0_CMD) >> 3;
                    203:        if (cmd == 0) {
                    204:                // コマンド0 ならレジスタ切り替え
                    205:                putlog(3, "CR0%s <- $%02x (ptr=%d)", chan->name, data, chan->ptr);
                    206:        } else {
                    207:                // 0 以外ならコマンド発行
                    208:                putlog(2, "CR0%s <- $%02x", chan->name, data);
                    209:        }
                    210:        switch (cmd) {
                    211:         case 0:        // No operation
                    212:                break;
                    213:         case 1:        // Send Abort
                    214:                if (chan->mode == SIO::Mode::HDLC) {
                    215:                        putlog(0, "CR0: Send Abort 未実装");
                    216:                } else {
                    217:                        // XXX Send Abort コマンドは「HDLC モードのみ有効」と書いて
                    218:                        //     あるがそれ以外の時にどうなるか不明。
                    219:                        putlog(0, "CR0: 未定義コマンド %d", cmd);
                    220:                }
                    221:                break;
                    222:         case 2:        // Reset External/Status Interrupt
                    223:                putlog(3, "CR0%s: Reset E/S Interrupt", chan->name);
                    224:                chan->es_ratched = false;
                    225:                break;
                    226:         case 3:        // Channel Reset
                    227:                ResetChannel(chan);
                    228:                break;
                    229:         case 4:        // Enable Interrupt On Next Receive Character
                    230:                putlog(0, "CR0: 未実装コマンド %d", cmd);
                    231:                break;
                    232:         case 5:        // Reset Transmitter Interrupt/DMA Pending
                    233:                putlog(1, "CR0%s: Reset Tx Int/DMA Pending", chan->name);
                    234:                chan->reset_txint_pend = false;
                    235:                ChangeInterrupt();
                    236:                break;
                    237:         case 6:        // Error Reset
                    238:         case 7:        // End of Interrupt
                    239:                putlog(0, "CR0: 未実装コマンド %d", cmd);
                    240:                break;
                    241:         default:
                    242:                __unreachable();
1.1.1.2   root      243:        }
                    244: }
                    245: 
1.1.1.5   root      246: // CR1 への書き込み
                    247: void
                    248: uPD7201Device::WriteCR1(struct SIO::channel *chan, uint32 data)
1.1.1.2   root      249: {
1.1.1.5   root      250:        putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
                    251: 
                    252:        chan->cr1 = data;
                    253: 
                    254:        // RXINT モードで all_or_first の値(初期値)を用意。
                    255:        // DISABLE なら(使わないのでどっちでもいいはずだけど一応) false にしとく。
                    256:        // FIRSTCHAR なら初期状態が true。ALL_* なら常時 true。
                    257:        chan->all_or_first = ((chan->cr1 & SIO::CR1_RXINT) != SIO::RXINT_DISABLE);
1.1.1.2   root      258: }
                    259: 
1.1.1.5   root      260: // CR2 への書き込み
                    261: void
                    262: uPD7201Device::WriteCR2(struct SIO::channel *chan, uint32 data)
                    263: {
                    264:        if (chan->id == 0) {    // CR2A
                    265:                putlog(2, "CR2A <- $%02x 書き込み(b7,b2-0未実装)", data);
                    266:                cr.cr2a = data;
                    267:        } else {                                // CR2B
                    268:                putlog(2, "CR2B <- $%02x (Set vector)", data);
                    269:                cr.vector = data;
                    270:        }
                    271: }
                    272: 
                    273: // CR3 への書き込み
                    274: void
                    275: uPD7201Device::WriteCR3(struct SIO::channel *chan, uint32 data)
                    276: {
                    277:        chan->cr3 = data;
                    278: 
                    279:        putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
                    280:        putlog(1, "Channel %s RX %s, %dbits",
                    281:                chan->name,
                    282:                (chan->cr3 & SIO::CR3_RX_EN) ? "Enable" : "Disable",
                    283:                bits_per_char[(chan->cr3 & SIO::CR3_RXBITS) >> 6]);
                    284: }
                    285: 
                    286: // CR4 への書き込み
                    287: void
                    288: uPD7201Device::WriteCR4(struct SIO::channel *chan, uint32 data)
                    289: {
                    290:        chan->cr4 = data;
                    291:        putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
                    292:        uint8 stopbits = (chan->cr4 & SIO::CR4_STOPBITS);
                    293:        uint8 syncmode = (chan->cr4 & SIO::CR4_SYNCMODE);
                    294: 
                    295:        // モード分け、優先順位は分からない
                    296:        if (stopbits == SIO::SYNC_MODE) {
                    297:                if (syncmode == SIO::SYNC_HDLC) {
                    298:                        chan->mode = SIO::Mode::HDLC;
                    299:                        putlog(2, "Channel %s HDLC Mode", chan->name);
                    300:                } else {
                    301:                        chan->mode = SIO::Mode::SYNC;
                    302:                        const char *sm[] = { "8bit", "16bit", "HDLC?", "Ext" };
                    303:                        putlog(2, "Channel %s Sync (%s) Mode",
                    304:                                chan->name, sm[syncmode >> 4]);
                    305:                }
                    306:        } else {
                    307:                chan->mode = SIO::Mode::ASYNC;
                    308:                const char *cm[] = { "x1", "x16", "x32", "x64" };
                    309:                const char *sm[] = { "?", "1", "1.5", "2" };
                    310:                putlog(2, "Channel %s Async (%s clock, stopbit %s) Mode",
                    311:                        chan->name,
                    312:                        cm[(chan->cr4 & SIO::CR4_CLKRATE) >> 6],
                    313:                        sm[stopbits >> 2]);
                    314:        }
                    315: }
                    316: 
                    317: // CR5 への書き込み
                    318: void
                    319: uPD7201Device::WriteCR5(struct SIO::channel *chan, uint32 data)
                    320: {
                    321:        chan->cr5 = data;
                    322: 
                    323:        putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
                    324:        putlog(1, "Channel %s TX %s, %dbits",
                    325:                chan->name,
                    326:                (chan->cr5 & SIO::CR5_TX_EN) ? "Enable" : "Disable",
                    327:                bits_per_char[(chan->cr5 & SIO::CR5_TXBITS) >> 5]);
                    328: }
                    329: 
                    330: // CR6 への書き込み
                    331: void
                    332: uPD7201Device::WriteCR6(struct SIO::channel *chan, uint32 data)
                    333: {
                    334:        chan->cr6 = data;
                    335: 
                    336:        putlog(0, "CR6%s <- $%02x 書き込み(未実装)", chan->name, data);
                    337: }
                    338: 
                    339: // CR7 への書き込み
                    340: void
                    341: uPD7201Device::WriteCR7(struct SIO::channel *chan, uint32 data)
                    342: {
                    343:        chan->cr7 = data;
                    344: 
                    345:        putlog(0, "CR7%s <- $%02x 書き込み(未実装)", chan->name, data);
                    346: }
1.1.1.2   root      347: 
1.1       root      348: // データポートの読み込み
                    349: uint8
1.1.1.2   root      350: uPD7201Device::ReadData(struct SIO::channel *chan)
1.1       root      351: {
                    352:        uint8 data;
                    353: 
                    354:        if (chan->rxlen > 0) {
                    355:                data = chan->rxbuf[0];
1.1.1.5   root      356:                putlog(3, "Ch%s Data -> $%02x", chan->name, data);
1.1       root      357:                chan->rxlen--;
1.1.1.5   root      358:                if (chan->rxlen == 0) {
                    359:                        // 取り出して空になった
                    360:                        chan->sr0 &= ~SIO::SR0_RXAVAIL;
                    361:                        ChangeInterrupt();
                    362:                } else {
1.1.1.6 ! root      363:                        chan->rxbuf[0] = chan->rxbuf[1];
        !           364:                        chan->rxbuf[1] = chan->rxbuf[2];
1.1       root      365:                }
                    366:        } else {
                    367:                // XXX 何が読めるか
                    368:                data = 0xff;
1.1.1.5   root      369:                putlog(3, "Ch%s Data -> $%02x (Empty)", chan->name, data);
1.1       root      370:        }
                    371: 
                    372:        return data;
                    373: }
                    374: 
                    375: // データポートの書き込み
                    376: void
                    377: uPD7201Device::WriteData(struct SIO::channel *chan, uint32 data)
                    378: {
                    379:        char charbuf[4];
                    380: 
                    381:        if (isprint((int)data)) {
                    382:                snprintf(charbuf, sizeof(charbuf), "'%c'", data);
                    383:        } else {
                    384:                charbuf[0] = '\0';
                    385:        }
1.1.1.5   root      386:        putlog(3, "Ch%s Data <- $%02x %s", chan->name, data, charbuf);
1.1       root      387: 
                    388:        // 1文字送信
                    389: 
                    390:        // 今のところ内部バッファがなく常に送信できるので
                    391:        // 必ず Tx Buffer Empty が発生する。
                    392:        chan->sr0 |= SIO::SR0_TXEMPTY;
                    393: 
1.1.1.5   root      394:        // 割り込み状態を変える
                    395:        ChangeInterrupt();
1.1       root      396: }
                    397: 
1.1.1.2   root      398: // データポートの Peek
                    399: uint8
                    400: uPD7201Device::PeekData(const struct SIO::channel *chan) const
                    401: {
                    402:        if (chan->rxlen > 0) {
                    403:                // 受信バッファにデータがあれば先頭バイトが見える
                    404:                return chan->rxbuf[0];
                    405:        } else {
                    406:                // 空の時は?
                    407:                return 0xff;
                    408:        }
                    409: }
                    410: 
1.1.1.3   root      411: // TX/RX の bits/char のレジスタ値を実際の bits/char の値に変換する。
1.1       root      412: /* static */
                    413: const int
                    414: uPD7201Device::bits_per_char[] = { 5, 7, 6, 8 };
                    415: 
                    416: // 1バイト受信する。
                    417: // 受理されれば true を返す。
                    418: bool
                    419: uPD7201Device::Rx(int ch, uint32 data)
                    420: {
                    421:        struct SIO::channel *chan = &cr.chan[ch];
                    422: 
                    423:        // Rx Enable でなければ受け取らない?
                    424:        if ((chan->cr3 & SIO::CR3_RX_EN) == 0) {
                    425:                return false;
                    426:        }
                    427: 
1.1.1.5   root      428:        // 1バイトでもあれば有効
                    429:        chan->sr0 |= SIO::SR0_RXAVAIL;
                    430: 
1.1       root      431:        // バッファが一杯なら Rx Overrun Error
                    432:        if (chan->rxlen == sizeof(chan->rxbuf)) {
                    433:                putlog(2, "Rx Overrun");
                    434:                chan->sr1 |= SIO::SR1_RXOVERRUN;
1.1.1.5   root      435:                // XXX special Rx condition interrupt occurs
1.1       root      436:                return false;
                    437:        }
                    438: 
                    439:        // 受信
                    440:        chan->rxbuf[chan->rxlen++] = data;
                    441: 
1.1.1.5   root      442:        // 割り込み状態を変更
                    443:        ChangeInterrupt();
                    444: 
                    445:        return true;
                    446: }
                    447: 
                    448: // 割り込み状態を変更
                    449: void
                    450: uPD7201Device::ChangeInterrupt()
                    451: {
                    452:        uint int_asserted = 0;
                    453: 
                    454:        for (int ch = 0; ch < 2; ch++) {
                    455:                struct SIO::channel *chan = &cr.chan[ch];
                    456: 
                    457:                // Rx
                    458:                bool rx_avail = (chan->rxlen > 0) && chan->all_or_first;
                    459:                // Special Rx
                    460:                bool special = false;   // XXX not yet
                    461: 
                    462:                bool rx_enable = (chan->cr3 & SIO::CR3_RX_EN);
                    463:                bool rx_int = (rx_enable && (rx_avail || special));
                    464: 
                    465:                // FirstChar モードなら1文字受信割り込み後にフラグを下ろす
                    466:                // (Rx 割り込み用の変数 rx_int が確定したここで行う)
                    467:                if ((chan->cr1 & SIO::CR1_RXINT) == SIO::RXINT_FIRSTCHAR) {
                    468:                        chan->all_or_first = false;
1.1       root      469:                }
1.1.1.5   root      470: 
                    471:                // XXX E/S not yet
                    472: 
                    473:                // Tx
                    474:                bool tx_empty = (chan->sr0 & SIO::SR0_TXEMPTY);
                    475:                bool tx_enable = (chan->cr1 & SIO::CR1_TXINT_EN);
                    476:                // reset_txint_pend は通常 true、コマンド発行で false に落ちる。
                    477:                // XXX INT DMA Mode はよく分からんのでスルー
                    478:                bool tx_int = (tx_empty && tx_enable && chan->reset_txint_pend);
                    479: 
                    480:                // 4つの要因の合成
                    481:                chan->int_asserted = 0;
                    482:                chan->int_asserted |= tx_int ? SIO::INTR_TX : 0;
                    483:                chan->int_asserted |= rx_int ? SIO::INTR_RX : 0;
                    484: 
                    485:                // 両方のチャンネル分を合成
                    486:                int_asserted |= chan->int_asserted;
1.1       root      487:        }
                    488: 
1.1.1.5   root      489:        gInterrupt->ChangeINT(this, int_asserted);
1.1       root      490: }
                    491: 
                    492: // モニター
1.1.1.4   root      493: void
                    494: uPD7201Device::MonitorUpdate(TextScreen& monitor)
1.1       root      495: {
1.1.1.5   root      496:        int y;
                    497: 
1.1       root      498:        monitor.Clear();
                    499:        for (int i = 0; i < 2; i++) {
                    500:                int x = 0;
1.1.1.5   root      501:                y = i * 10;
1.1.1.4   root      502:                MonitorUpdateCh(monitor, i, x, y);
1.1       root      503:        }
1.1.1.5   root      504: 
                    505:        // CR2A
                    506:        uint cr2a = cr.cr2a;
                    507:        y = 20;
                    508:        monitor.Print(0, y, "CR2A:$%02x", cr2a);
                    509:        if ((cr2a & 0x80)) {
                    510:                monitor.Print(9, y, TA::On, "SYNC");
                    511:        } else {
                    512:                monitor.Print(9, y, "RTSB");
                    513:        }
                    514:        monitor.Print(14, y, "----");
                    515:        monitor.Print(19, y, TA::OnOff((cr2a & 0x20)), "Vect");
                    516:        if ((cr2a & 0x18) == 0x10) {
                    517:                monitor.Print(24, y, "IM=V4-V2");
                    518:        } else {
                    519:                monitor.Print(24, y, "IM=V2-V0");
                    520:        }
                    521:        // bit2 (Priority Select) は bit0 が 0 の時だけ意味があるようだ
                    522:        if ((cr2a & 0x01) == 0) {
                    523:                if ((cr2a & 0x04)) {
                    524:                        monitor.Print(34, y, "RxTx");
                    525:                } else {
                    526:                        monitor.Print(34, y, "A->B");
                    527:                }
                    528:        }
                    529:        // bit1,0 はよく分からん
                    530:        monitor.Print(39, y, "INT/DMA=%d", (cr2a & 0x3));
                    531:        y++;
                    532: 
                    533:        // CR2B
                    534:        monitor.Print(0, y, "CR2B:$%02x", cr.vector);
1.1       root      535: }
                    536: 
                    537: // モニター (1チャンネル)
                    538: void
1.1.1.4   root      539: uPD7201Device::MonitorUpdateCh(TextScreen& monitor,
                    540:        int ch, int xbase, int ybase)
1.1       root      541: {
                    542:        struct SIO::channel *chan = &cr.chan[ch];
                    543:        uint cr0;
                    544:        uint cr1;
                    545:        uint cr3;
                    546:        uint cr4;
                    547:        uint cr5;
                    548:        uint sr0;
                    549:        uint sr1;
                    550:        uint rxlen;
                    551:        int x;
                    552:        int y;
                    553: 
1.1.1.5   root      554:        cr0 = (chan->cr0 & ~SIO::CR0_PTR) | chan->ptr;
1.1       root      555:        cr1 = chan->cr1;
                    556:        cr3 = chan->cr3;
                    557:        cr4 = chan->cr4;
                    558:        cr5 = chan->cr5;
                    559:        sr0 = chan->sr0;
                    560:        sr1 = chan->sr1;
                    561:        rxlen = chan->rxlen;
                    562: 
                    563:        // 0         1         2         3         4         5         6
                    564:        // 012345678901234567890123456789012345678901234567890123456789012345
                    565:        //          0123 0123 0123 0123 0123 0123 0123 0123
1.1.1.5   root      566:        // CR0: $xx CRC=x     CMD=x          PTR=x
                    567:        // CR1: $xx WE   0    WR   RXInt=x   0    TXEn ESEn
                    568:        // RXBuf: 0 --- --- ---           Intr: Rx Sp Tx ES
1.1       root      569: 
                    570:        x = xbase;
                    571:        y = ybase;
                    572:        monitor.Print(x, y++, "Channel %s: %s", chan->name, chan->desc);
1.1.1.5   root      573:        monitor.Print(x, y++, "CR0: $%02x", cr0);
                    574:        monitor.Print(x, y++, "CR1: $%02x", cr1);
                    575:        monitor.Print(x, y++, "CR3: $%02x", cr3);
                    576:        monitor.Print(x, y++, "CR4: $%02x", cr4);
                    577:        monitor.Print(x, y++, "CR5: $%02x", cr5);
                    578:        monitor.Print(x, y++, "SR0: $%02x", sr0);
                    579:        monitor.Print(x, y++, "SR1: $%02x", sr1);
                    580:        monitor.Print(x, y,   "RXbuf: %d", rxlen);
1.1       root      581:        int i;
                    582:        for (i = 0; i < rxlen; i++) {
1.1.1.5   root      583:                monitor.Print(x + 9 + i * 4, y, "$%02x", chan->rxbuf[i]);
1.1       root      584:        }
                    585:        for (; i < sizeof(chan->rxbuf); i++) {
1.1.1.5   root      586:                monitor.Print(x + 9 + i * 4, y, "---");
1.1       root      587:        }
1.1.1.5   root      588:        // 内部割り込み状態
                    589:        monitor.Print(31, y, "Intr:");
                    590:        monitor.Print(37, y, TA::OnOff(chan->int_asserted & SIO::INTR_RX), "Rx");
                    591:        monitor.Print(40, y, TA::OnOff(chan->int_asserted & SIO::INTR_SP), "SP");
                    592:        monitor.Print(43, y, TA::OnOff(chan->int_asserted & SIO::INTR_TX), "Tx");
                    593:        monitor.Print(46, y, TA::OnOff(chan->int_asserted & SIO::INTR_ES), "ES");
1.1       root      594: 
                    595:        y = ybase + 1;
                    596:        x = xbase;
                    597:        // CR0
                    598:        monitor.Print(x + 9, y, "CRC=%d", (cr0 >> 6));
                    599:        static const char * const cmd_str[] = {
                    600:        //   0123456789012345
                    601:                "No operation",
                    602:                "Send Abort",
                    603:                "Reset E/S Int",
                    604:                "Channel Reset",
                    605:                "Enable IntNextCh",
                    606:                "Reset TxIntPend",
                    607:                "Error Reset",
                    608:                "End of Interrupt",
                    609:        };
                    610:        uint cmd = (cr0 >> 3) & 7;
                    611:        monitor.Print(x + 19, y, "CMD=%d(%s)", cmd, cmd_str[cmd]);
                    612:        monitor.Print(x + 43, y, "PTR=%d", (cr0 & 7));
                    613:        y++;
                    614: 
                    615:        // CR1
                    616:        static const char * const cr1_str[] = {
                    617:                "WaEn", "----", "WaRx", "", "", "----", "TxIE", "ESEn"
                    618:        };
1.1.1.4   root      619:        MonitorReg(monitor, x + 9, y, cr1, cr1_str);
1.1.1.5   root      620:        static const char * const rxint_str[] = {
                    621:        //   2345678
                    622:                "=SpOnly",
                    623:                "=AllChr",
                    624:                "=1stChr",
                    625:                "Disable",
                    626:        };
                    627:        monitor.Print(x + 24, y, "RI%s", rxint_str[(cr1 >> 3) & 3]);
1.1       root      628:        y++;
                    629: 
                    630:        // CR3
                    631:        static const char * const cr3_str[] = {
                    632:                "", "", "AuEn", "----", "----", "----", "----", "RXEn"
                    633:        };
1.1.1.4   root      634:        MonitorReg(monitor, x + 9, y, cr3, cr3_str);
1.1       root      635:        monitor.Print(x + 9, y, "RXbits=%d", 5 + ((cr3 >> 6) & 3));
                    636:        y++;
                    637: 
                    638:        // CR4
                    639:        static const char * const cr4_str[] = {
                    640:                "", "", "", "", "", "", "PaEv", "PaEn"
                    641:        };
1.1.1.4   root      642:        MonitorReg(monitor, x + 9, y, cr4, cr4_str);
1.1       root      643: 
                    644:        static const char * const clkrate_str[] = {
                    645:                "1", "16", "32", "64"
                    646:        };
                    647:        monitor.Print(x + 9, y, "Rate=x%s", clkrate_str[(cr4 >> 6) & 3]);
                    648:        static const char * const syncmode_str[] = {
                    649:                "Mono", "Bi", "HDLC", "Ext"
                    650:        };
                    651:        monitor.Print(x + 19, y, "Sync=%s", syncmode_str[(cr4 >> 4) & 3]);
                    652:        static const char * const stopbit_str[] = {
                    653:                "Sync", "1", "1.5", "2"
                    654:        };
                    655:        monitor.Print(x + 29, y, "Stop=%s", stopbit_str[(cr4 >> 2) & 3]);
                    656:        y++;
                    657: 
                    658:        // CR5
                    659:        static const char * const cr5_str[] = {
                    660:                "DTR", "", "", "SBrk", "TXEn", "CRC", "!RTS", "TCEn"
                    661:        };
1.1.1.4   root      662:        MonitorReg(monitor, x + 9, y, cr5, cr5_str);
1.1       root      663:        monitor.Print(x + 14, y, "TXbits=%d", 5 + ((cr5 >> 5) & 3));
                    664:        y++;
                    665: 
                    666:        // SR0
                    667:        static const char * const sr0_str[] = {
                    668:                "BrAb", "TxUn", "CTS", "SYNC", "DCD", "TxEm", "IntP", "RxAv"
                    669:        };
1.1.1.4   root      670:        MonitorReg(monitor, x + 9, y, sr0, sr0_str);
1.1.1.5   root      671:        // SR0 の bit1 (Interrupt Pending) は SR0A のみ。SR0B では 0。
                    672:        if (ch == 1) {
                    673:                monitor.Print(39, y, "----");
                    674:        }
1.1       root      675:        y++;
                    676: 
                    677:        // SR1
                    678:        static const char * const sr1_str[] = {
                    679:                "EOF", "CRCE", "RxOv", "PaEr", "", "", "", "Sent"
                    680:        };
1.1.1.4   root      681:        MonitorReg(monitor, x + 9, y, sr1, sr1_str);
1.1       root      682:        monitor.Print(x + 29, y, "ResidueCode=%d", (sr1 >> 1) & 7);
                    683:        y++;
                    684: }
                    685: 
                    686: // レジスタをビットごとに表示する。MonitorUpdate の下請け。
                    687: void
1.1.1.4   root      688: uPD7201Device::MonitorReg(TextScreen& monitor,
                    689:        int x, int y, uint32 reg, const char * const *names)
1.1       root      690: {
                    691:        for (int i = 0; i < 8; i++) {
                    692:                if (strcmp(names[i], "----") == 0) {
1.1.1.3   root      693:                        monitor.Puts(x + i * 5, y, TA::Disable, names[i]);
1.1       root      694:                } else {
                    695:                        bool b = reg & (1 << (7 - i));
1.1.1.3   root      696:                        monitor.Puts(x + i * 5, y, TA::OnOff(b), names[i]);
1.1       root      697:                }
                    698:        }
                    699: }

unix.superglobalmegacorp.com

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