Annotation of nono/vm/scc.cpp, revision 1.1.1.18

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: 
1.1.1.10  root        7: //
                      8: // SCC (Z8530)
                      9: //
                     10: 
1.1       root       11: #include "scc.h"
1.1.1.8   root       12: #include "bitops.h"
1.1.1.17  root       13: #include "event.h"
1.1.1.10  root       14: #include "hostcom.h"
1.1.1.8   root       15: #include "keyboard.h"
1.1       root       16: 
1.1.1.13  root       17: // InsideOut p.135
                     18: static const busdata read_wait  = busdata::Wait(41 * 40_nsec);
                     19: static const busdata write_wait = busdata::Wait(49 * 40_nsec);
                     20: 
1.1.1.10  root       21: // コンストラクタ
1.1       root       22: SCCDevice::SCCDevice()
1.1.1.12  root       23:        : inherited()
1.1       root       24: {
1.1.1.12  root       25:        SetName("SCC");
                     26:        ClearAlias();
                     27:        AddAlias("SCC");
                     28:        AddAlias("MPSCC");
1.1.1.10  root       29: 
1.1.1.12  root       30:        // チャンネル名とポートアドレスは機種ごとに異なる。
                     31:        //
1.1.1.10  root       32:        // デバイス自身は自分が配置されるアドレスを知らなくてよい構造になって
                     33:        // いるが、直接アクセスしたりする場合などに毎回アドレスを確認するのが
                     34:        // 面倒なので(全機種で向きと間隔が異なる)、モニタで表示されてほしい。
1.1.1.12  root       35:        if (gMainApp.IsX68030()) {
                     36:                mpscc.chan[0].desc = "Serial Port";
                     37:                mpscc.chan[1].desc = "Mouse";
                     38:                mpscc.chan[1].ctrladdr = 0xe98001;
                     39:                mpscc.chan[1].dataaddr = 0xe98003;
                     40:                mpscc.chan[0].ctrladdr = 0xe98005;
                     41:                mpscc.chan[0].dataaddr = 0xe98007;
                     42: 
                     43:                // 5MHz
1.1.1.18! root       44:                pclk_tsec = 200_nsec;
1.1.1.12  root       45:        } else {
                     46:                // NWS-1750
                     47:                mpscc.chan[0].desc = "Serial Port #0";
                     48:                mpscc.chan[1].desc = "Serial Port #1 (NotConnected)";
                     49:                mpscc.chan[1].ctrladdr = 0xe0d40000;
                     50:                mpscc.chan[1].dataaddr = 0xe0d40001;
                     51:                mpscc.chan[0].ctrladdr = 0xe0d40002;
                     52:                mpscc.chan[0].dataaddr = 0xe0d40003;
                     53: 
                     54:                // たぶん 4MHz
                     55:                // http://www.ceres.dti.ne.jp/~tsutsui/netbsd/port-news68k.html#19990727
1.1.1.18! root       56:                pclk_tsec = 250_nsec;
1.1.1.12  root       57:        }
1.1.1.7   root       58: 
1.1.1.15  root       59:        monitor = gMonitorManager->Regist(ID_MONITOR_SCC, this);
1.1.1.18! root       60:        monitor->SetCallback(&SCCDevice::MonitorScreen);
1.1.1.15  root       61:        monitor->SetSize(70, 35);
1.1       root       62: }
                     63: 
1.1.1.10  root       64: // デストラクタ
1.1       root       65: SCCDevice::~SCCDevice()
                     66: {
1.1.1.12  root       67: }
                     68: 
                     69: // 初期化
                     70: bool
                     71: SCCDevice::Init()
                     72: {
                     73:        if (inherited::Init() == false) {
                     74:                return false;
                     75:        }
                     76: 
1.1.1.16  root       77:        hostcom->SetPortName("SCC Ch.A");
                     78: 
1.1.1.12  root       79:        if (gMainApp.IsX68030()) {
                     80:                keyboard = GetKeyboard();
                     81:        }
                     82: 
1.1.1.17  root       83:        // X680x0 では SCC と呼ぶほうが通りがいい。
                     84:        // イベントの登録は親クラスで行ってある。
                     85:        for (int ch = 0; ch < txevent.size(); ch++) {
                     86:                auto& chan = mpscc.chan[ch];
                     87:                txevent[ch]->SetName(string_format("SCC Ch%c TX", chan.name));
                     88:                rxevent[ch]->SetName(string_format("SCC Ch%c RX", chan.name));
                     89:        }
                     90: 
1.1.1.12  root       91:        return true;
1.1.1.10  root       92: }
                     93: 
                     94: // リセット
                     95: void
                     96: SCCDevice::ResetHard(bool poweron)
                     97: {
                     98:        // Z8530 は RD と WR を同時に Low にするとリセットがかかる。
                     99:        // 回路図からは PEDEC から繋がってるという以上のことは分からないけど
                    100:        // 普通に考えればハードリセットでリセットされるよな。
                    101: 
                    102:        // WR9 b2,3,4 = %0、b6,7 = %1
                    103:        mpscc.disable_lower_chain = false;
                    104:        mpscc.master_int_enable = false;
                    105:        mpscc.status_high_low = false;
                    106:        // XXX Reset
                    107: 
                    108:        for (auto& chan : mpscc.chan) {
1.1.1.11  root      109:                // XC 設定は ResetChannel() の前に必要。
                    110:                SetXC(chan);
1.1.1.10  root      111:                ResetChannel(chan);
                    112: 
                    113:                // WR10 b5,6 = %0
                    114:                chan.wr10 &= ~0x40;
                    115: 
                    116:                // WR11
                    117:                chan.wr11 = 0x08;
                    118: 
                    119:                // WR14 b0-1 = %0
                    120:                //
                    121:                // b4 (Local Loopback) は p.2-15 ではチャンネルリセット時は %0、
                    122:                // ハードリセット時は %1 に初期化されると書いてあるが、おそらく
                    123:                // そんなことはないだろうし、p.5-20 の WR14 の説明には
                    124:                // "This bit is reset by a channel or hardware reset." とあるので
                    125:                // たぶんこっちのほうが正しい。
                    126:                chan.wr14 &= ~0x03;
                    127:        }
1.1       root      128: }
                    129: 
1.1.1.10  root      130: // チャンネルリセット
                    131: void
                    132: SCCDevice::ResetChannel(MPSCCChan& chan)
                    133: {
1.1.1.11  root      134:        uint8 val;
                    135: 
1.1.1.10  root      136:        // WR0 b0-7 = %0
                    137:        chan.crc_cmd = 0;
                    138:        chan.cmd = 0;
                    139:        chan.ptr = 0;
                    140: 
                    141:        // WR1 b0,1,3,4,6,7 = %0
                    142:        chan.esint_enable = false;
                    143:        chan.txint_enable = false;
                    144:        chan.rxint_mode   = MPSCCChan::RXINT_DISABLE;
                    145:        chan.wait_func    = false;
                    146:        chan.wait_enable  = false;
                    147: 
                    148:        // WR3 b0 = %0
                    149:        chan.rx_enable = false;
                    150: 
                    151:        // WR4 b2 = %1
                    152:        // b2,3 が StopBits 設定だが b2 だけ %1 にするらしい…。
                    153:        // 少なくとも非同期モードにしときたいということだろうか。
1.1.1.11  root      154:        val = GetCR4(chan);
                    155:        SetCR4(chan, val | 0x04);
1.1.1.10  root      156: 
                    157:        // WR5 b1,2,3,4,7 = %0
1.1.1.11  root      158:        val = GetCR5(chan);
                    159:        SetCR5(chan, val & 0x61);
1.1.1.10  root      160: 
                    161:        // WR9 b5 = %0 (未実装ビット)
                    162: 
                    163:        // WR10 b0-4,7 = %0
                    164:        chan.wr10 &= 0x60;
                    165: 
                    166:        // WR14 b2-4 = %0、b5 = %1
                    167:        chan.wr14 &= 0xe3;
                    168:        chan.wr14 |= 0x20;
                    169: 
                    170:        // WR15
                    171:        chan.wr15 = 0xf8;
                    172: 
                    173:        // RR0 b0,1=%0、b2,6=%1
1.1.1.13  root      174:        chan.rxlen = 0;
                    175:        chan.txlen = 0;
1.1.1.10  root      176:        chan.tx_underrun = true;
                    177: 
                    178:        // RR1 b1,2=%1、b3-7=%0
                    179:        chan.sr1 &= ~(MPSCC::SR1_ENDOFFRAME |
                    180:                      MPSCC::SR1_FRAMEERROR |
                    181:                      MPSCC::SR1_RXOVERRUN  |
                    182:                      MPSCC::SR1_PARITYERROR);
                    183:        chan.sr1 &= 0x08;
                    184:        chan.sr1 |= 0x60;
                    185: 
                    186:        // RR3
                    187:        chan.intpend = 0;
                    188: 
                    189:        // RR10 b0-5,7 = %0
                    190:        chan.rr10 &= 0x40;
                    191: 
                    192:        ResetChannelCommon(chan);
                    193: }
1.1       root      194: 
1.1.1.13  root      195: busdata
1.1.1.14  root      196: SCCDevice::ReadPort(uint32 offset)
1.1       root      197: {
1.1.1.13  root      198:        busdata data;
1.1.1.4   root      199: 
1.1.1.6   root      200:        switch (offset) {
1.1.1.3   root      201:         case 0:        // $E98001
1.1.1.10  root      202:                data = ReadCtrl(mpscc.chan[1]);
                    203:                break;
1.1.1.3   root      204:         case 1:        // $E98003
1.1.1.10  root      205:                data = ReadData(mpscc.chan[1]);
                    206:                break;
1.1.1.3   root      207:         case 2:        // $E98005
1.1.1.10  root      208:                data = ReadCtrl(mpscc.chan[0]);
                    209:                break;
1.1.1.3   root      210:         case 3:        // $E98007
1.1.1.10  root      211:                data = ReadData(mpscc.chan[0]);
                    212:                break;
                    213:         default:
1.1.1.14  root      214:                VMPANIC("corrupted offset=%u", offset);
1.1       root      215:        }
1.1.1.13  root      216: 
                    217:        data |= read_wait;
1.1.1.14  root      218:        data |= BusData::Size1;
1.1.1.10  root      219:        return data;
1.1       root      220: }
                    221: 
1.1.1.13  root      222: busdata
1.1.1.14  root      223: SCCDevice::WritePort(uint32 offset, uint32 data)
1.1       root      224: {
1.1.1.6   root      225:        switch (offset) {
1.1.1.3   root      226:         case 0:        // $E98001
1.1.1.10  root      227:                WriteCtrl(mpscc.chan[1], data);
                    228:                break;
1.1.1.3   root      229:         case 1:        // $E98003
1.1.1.10  root      230:                WriteData(mpscc.chan[1], data);
                    231:                break;
1.1.1.3   root      232:         case 2:        // $E98005
1.1.1.10  root      233:                WriteCtrl(mpscc.chan[0], data);
                    234:                break;
1.1.1.3   root      235:         case 3:        // $E98007
1.1.1.10  root      236:                WriteData(mpscc.chan[0], data);
                    237:                break;
                    238:         default:
1.1.1.14  root      239:                VMPANIC("corrupted offset=%u", offset);
1.1       root      240:        }
1.1.1.13  root      241: 
1.1.1.14  root      242:        busdata r = write_wait;
                    243:        r |= BusData::Size1;
                    244:        return r;
1.1       root      245: }
                    246: 
1.1.1.13  root      247: busdata
1.1.1.14  root      248: SCCDevice::PeekPort(uint32 offset)
1.1       root      249: {
1.1.1.10  root      250:        uint64 data;
                    251: 
1.1.1.6   root      252:        switch (offset) {
1.1.1.3   root      253:         case 0:        // $E98001
1.1.1.10  root      254:                data = PeekCtrl(mpscc.chan[1]);
                    255:                break;
1.1.1.3   root      256:         case 1:        // $E98003
1.1.1.10  root      257:                data = PeekData(mpscc.chan[1]);
                    258:                break;
1.1.1.3   root      259:         case 2:        // $E98005
1.1.1.10  root      260:                data = PeekCtrl(mpscc.chan[0]);
                    261:                break;
1.1.1.3   root      262:         case 3:        // $E98007
1.1.1.10  root      263:                data = PeekData(mpscc.chan[0]);
                    264:                break;
                    265:         default:
1.1.1.12  root      266:                data = 0xff;
                    267:                break;
1.1.1.2   root      268:        }
1.1.1.10  root      269:        return data;
1.1       root      270: }
                    271: 
1.1.1.10  root      272: // 書き込みレジスタ名を返す。
1.1.1.9   root      273: const char *
1.1.1.14  root      274: SCCDevice::CRName(const MPSCCChan& chan, uint ptr_) const
1.1.1.9   root      275: {
                    276:        assert(ptr_ < 16);
1.1.1.14  root      277:        uint idx = ptr_ * 2 + chan.id;
1.1.1.9   root      278:        assert(idx < countof(wrnames));
                    279:        return wrnames[idx];
                    280: }
                    281: 
1.1.1.10  root      282: // 読み込みレジスタ名を返す。
1.1.1.9   root      283: const char *
1.1.1.14  root      284: SCCDevice::SRName(const MPSCCChan& chan, uint ptr_) const
1.1.1.9   root      285: {
                    286:        assert(ptr_ < 16);
1.1.1.14  root      287:        uint idx = ptr_ * 2 + chan.id;
1.1.1.9   root      288:        assert(idx < countof(rrnames));
                    289:        return rrnames[idx];
                    290: }
                    291: 
1.1       root      292: // Z8530 制御ポート読み込み
                    293: uint8
1.1.1.10  root      294: SCCDevice::ReadCtrl(MPSCCChan& chan)
1.1       root      295: {
1.1.1.10  root      296:        uint8 data;
1.1       root      297: 
1.1.1.10  root      298:        // PTR とレジスタの対応 (Z8530 p.2-13)
                    299:        //
                    300:        // PTR Reg              PTR Reg         PTR Reg                 PTR Reg
                    301:        // 0 = RR0              4 = (RR0)        8 = RR8                12 = RR12
                    302:        // 1 = RR1              5 = (RR1)        9 = (RR13)             13 = RR13
                    303:        // 2 = RR2              6 = (RR2)       10 = RR10               14 = RR14
                    304:        // 3 = RR3              7 = (RR3)       11 = (RR15)             15 = RR15
1.1       root      305: 
1.1.1.10  root      306:        switch (chan.ptr) {
                    307:         case 0:        // RR0
                    308:         case 4:
                    309:                data = GetRR0(chan);
1.1       root      310:                break;
                    311: 
1.1.1.10  root      312:         case 1:        // RR1
1.1       root      313:         case 5:
1.1.1.10  root      314:                data = chan.sr1;
                    315:                break;
                    316: 
                    317:         case 2:
1.1       root      318:         case 6:
1.1.1.10  root      319:                if (chan.id == 0) {     // RR2A
                    320:                        data = mpscc.vector;
                    321:                } else {                        // RR2B
                    322:                        // 割り込み要因で変化したベクタ
                    323:                        data = GetSR2B();
                    324:                }
                    325:                break;
                    326: 
                    327:         case 3:
1.1       root      328:         case 7:
1.1.1.10  root      329:                if (chan.id == 0) {     // RR3A
                    330:                        data = GetRR3A();
                    331:                } else {                        // RR3B
                    332:                        data = 0;
                    333:                }
1.1       root      334:                break;
                    335: 
1.1.1.10  root      336:         case 8:
                    337:         case 10:
                    338:         case 12:
                    339:         case 13:
                    340:         case 9:
                    341:         case 14:
                    342:         case 15:
                    343:         case 11:
1.1.1.14  root      344:                putlog(0, "ReadCtrl %u (NOT IMPLEMENTED)", chan.ptr);
1.1.1.10  root      345:                data = 0xff;
1.1       root      346:                break;
                    347: 
1.1.1.10  root      348:         default:
1.1.1.14  root      349:                VMPANIC("corrupted chan.ptr=%u", chan.ptr);
1.1.1.10  root      350:        }
1.1.1.11  root      351:        chan.ptr = 0;
1.1.1.10  root      352:        return data;
                    353: }
                    354: 
                    355: // Z8530 制御ポート書き込み
                    356: void
                    357: SCCDevice::WriteCtrl(MPSCCChan& chan, uint32 data)
                    358: {
                    359:        // WR0 はコマンドかまたは次にアクセスするレジスタを指定する。
                    360:        // WR0 以外のレジスタをアクセスすると、次のアクセスは WR0 に戻る。
                    361: 
                    362:        if (chan.ptr == 0) {
                    363:                WriteWR0(chan, data);
                    364:        } else {
                    365:                switch (chan.ptr) {
                    366:                 case 1:
                    367:                        WriteWR1(chan, data);
1.1       root      368:                        break;
1.1.1.10  root      369:                 case 2:
                    370:                        WriteWR2(data);
1.1       root      371:                        break;
1.1.1.10  root      372:                 case 3:
                    373:                        WriteCR3(chan, data);
1.1       root      374:                        break;
1.1.1.10  root      375:                 case 4:
                    376:                        WriteCR4(chan, data);
                    377:                        break;
                    378:                 case 5:
                    379:                        WriteWR5(chan, data);
                    380:                        break;
                    381:                 case 6:
                    382:                        WriteCR6(chan, data);
                    383:                        break;
                    384:                 case 7:
                    385:                        WriteCR7(chan, data);
                    386:                        break;
                    387: 
                    388:                 case 8:
                    389:                        WriteData(chan, data);
                    390:                        break;
                    391:                 case 9:
                    392:                        WriteWR9(data);
                    393:                        break;
                    394:                 case 10:
                    395:                        WriteWR10(chan, data);
                    396:                        break;
                    397:                 case 11:
                    398:                        WriteWR11(chan, data);
                    399:                        break;
                    400:                 case 12:
                    401:                        WriteWR12(chan, data);
                    402:                        break;
                    403:                 case 13:
                    404:                        WriteWR13(chan, data);
                    405:                        break;
                    406:                 case 14:
                    407:                        WriteWR14(chan, data);
                    408:                        break;
                    409:                 case 15:
                    410:                        WriteWR15(chan, data);
1.1       root      411:                        break;
                    412:                 default:
1.1.1.14  root      413:                        VMPANIC("corrupted chan.ptr=%u", chan.ptr);
1.1       root      414:                }
                    415:                // アクセス後は WR0 へ戻す
1.1.1.10  root      416:                chan.ptr = 0;
                    417:        }
                    418: }
1.1       root      419: 
1.1.1.10  root      420: // 制御ポートの Peek
                    421: uint8
                    422: SCCDevice::PeekCtrl(const MPSCCChan& chan) const
                    423: {
                    424:        uint8 data;
                    425: 
                    426:        switch (chan.ptr) {
                    427:         case 0:        // RR0
                    428:         case 4:
                    429:                data = GetRR0(chan);
1.1.1.5   root      430:                break;
                    431: 
1.1.1.10  root      432:         case 1:        // RR1
                    433:         case 5:
                    434:                data = chan.sr1;
1.1       root      435:                break;
                    436: 
1.1.1.10  root      437:         case 2:
                    438:         case 6:
                    439:                if (chan.id == 0) {     // RR2A
                    440:                        data = mpscc.vector;
                    441:                } else {
                    442:                        data = GetSR2B();
                    443:                }
1.1       root      444:                break;
                    445: 
1.1.1.10  root      446:         case 3:
                    447:         case 7:
                    448:                if (chan.id == 0) {     // RR3A
                    449:                        data = GetRR3A();
                    450:                } else {                        // RR3B
                    451:                        data = 0;
                    452:                }
1.1       root      453:                break;
                    454: 
1.1.1.10  root      455:         case 8:
                    456:                data = PeekData(chan);
1.1       root      457:                break;
                    458: 
1.1.1.10  root      459:         case 10:
                    460:         case 12:
                    461:         case 13:
                    462:         case 9:
                    463:         case 14:
                    464:         case 15:
                    465:         case 11:
                    466:                data = 0xff;
1.1       root      467:                break;
                    468: 
                    469:         default:
1.1.1.14  root      470:                VMPANIC("corrupted chan.ptr=%u", chan.ptr);
1.1.1.10  root      471:        }
                    472:        return data;
                    473: }
                    474: 
                    475: // WR1 レジスタの内容を取得
                    476: uint8
                    477: SCCDevice::GetWR1(const MPSCCChan& chan) const
                    478: {
                    479:        uint8 data = 0;
                    480: 
                    481:        if (chan.wait_enable)
                    482:                data |= MPSCC::WR1_WAIT_EN;
                    483:        if (chan.wait_func)
                    484:                data |= MPSCC::WR1_WAIT_FUNC;
                    485:        if (chan.wait_on_rx)
                    486:                data |= MPSCC::WR1_WAIT_RX;
                    487:        switch (chan.rxint_mode) {
                    488:         case MPSCCChan::RXINT_DISABLE:
                    489:                break;
                    490:         case MPSCCChan::RXINT_1STCHAR:
                    491:                data |= MPSCC::WR1_RXINT_1STCHAR;
1.1.1.9   root      492:                break;
1.1.1.10  root      493:         case MPSCCChan::RXINT_ALLCHAR:
                    494:                data |= MPSCC::WR1_RXINT_ALLCHAR;
                    495:                break;
                    496:         case MPSCCChan::RXINT_SPONLY:
                    497:                data |= MPSCC::WR1_RXINT_SPONLY;
                    498:                break;
                    499:         default:
1.1.1.14  root      500:                VMPANIC("corrupted rxint_mode=%u", (uint)chan.rxint_mode);
1.1.1.9   root      501:        }
1.1.1.10  root      502:        if (chan.sp_parity)
                    503:                data |= MPSCC::WR1_SP_INC_PE;
                    504:        if (chan.txint_enable)
                    505:                data |= MPSCC::WR1_TXINT_EN;
                    506:        if (chan.esint_enable)
                    507:                data |= MPSCC::WR1_ESINT_EN;
                    508: 
                    509:        return data;
1.1.1.9   root      510: }
                    511: 
1.1.1.10  root      512: // WR9 レジスタの内容を取得
                    513: uint8
                    514: SCCDevice::GetWR9() const
1.1.1.9   root      515: {
1.1.1.10  root      516:        uint8 data = 0;
                    517: 
                    518:        data |= mpscc.wr9_cmd << 6;
                    519:        if (mpscc.status_high_low)     data |= MPSCC::WR9_SHSL;
                    520:        if (mpscc.master_int_enable)   data |= MPSCC::WR9_MIE;
                    521:        if (mpscc.disable_lower_chain) data |= MPSCC::WR9_DLC;
                    522:        if (!mpscc.vectored_mode)      data |= MPSCC::WR9_NV;
                    523:        if (mpscc.sav_vis)             data |= MPSCC::WR9_VIS;
                    524: 
                    525:        return data;
1.1.1.9   root      526: }
                    527: 
1.1.1.10  root      528: // RR0 レジスタの内容を取得
                    529: uint8
                    530: SCCDevice::GetRR0(const MPSCCChan& chan) const
1.1.1.9   root      531: {
1.1.1.10  root      532:        uint8 data = 0;
                    533: 
                    534:        if (chan.break_detected)data |= MPSCC::RR0_BREAK;
                    535:        if (chan.tx_underrun)   data |= MPSCC::RR0_TXUNDER;
                    536:        if (chan.nCTS)                  data |= MPSCC::RR0_nCTS;
                    537:        if (chan.nSYNC)                 data |= MPSCC::RR0_nSYNC;
                    538:        if (chan.nDCD)                  data |= MPSCC::RR0_nDCD;
                    539:        if (chan.txlen == 0)    data |= MPSCC::RR0_TXEMPTY;
                    540:        if (false)                              data |= MPSCC::RR0_ZEROCNT;     // XXX TODO
                    541:        if (chan.rxlen != 0)    data |= MPSCC::RR0_RXAVAIL;
                    542: 
                    543:        return data;
                    544: }
                    545: 
                    546: // RR3A の内容を取得
                    547: uint8
                    548: SCCDevice::GetRR3A() const
                    549: {
                    550:        uint8 data = 0;
                    551: 
                    552:        if ((mpscc.chan[0].intpend & INTPEND_RX))
                    553:                data |= MPSCC::RR3_RXA;
                    554:        if ((mpscc.chan[0].intpend & INTPEND_TX))
                    555:                data |= MPSCC::RR3_TXA;
                    556:        if ((mpscc.chan[0].intpend & INTPEND_ES))
                    557:                data |= MPSCC::RR3_ESA;
                    558: 
                    559:        if ((mpscc.chan[1].intpend & INTPEND_RX))
                    560:                data |= MPSCC::RR3_RXB;
                    561:        if ((mpscc.chan[1].intpend & INTPEND_TX))
                    562:                data |= MPSCC::RR3_TXB;
                    563:        if ((mpscc.chan[1].intpend & INTPEND_ES))
                    564:                data |= MPSCC::RR3_ESB;
                    565: 
                    566:        return data;
                    567: }
1.1.1.9   root      568: 
1.1.1.10  root      569: // WR0 への書き込み
                    570: void
                    571: SCCDevice::WriteWR0(MPSCCChan& chan, uint32 data)
                    572: {
1.1.1.9   root      573:        // XXX b7,b6 (CRC Reset Command) は未対応。
                    574:        // XXX コマンドが %001、%000 以外の時に PTR(レジスタセレクト) が同時に
                    575:        //     指定されたらどうなるか。
1.1.1.10  root      576:        chan.crc_cmd = (data & MPSCC::CR0_CRC) >> 6;;
                    577:        chan.cmd     = (data & MPSCC::CR0_CMD) >> 3;
1.1.1.9   root      578: 
1.1.1.10  root      579:        if (chan.crc_cmd != 0) {
                    580:                // CRC は非同期モードでは不要のはず
1.1.1.14  root      581:                putlog(3, "%s CRC Reset %u (NOT IMPLEMENTED)",
1.1.1.11  root      582:                        WRName(chan, 0), chan.crc_cmd);
1.1.1.9   root      583:        }
                    584: 
1.1.1.10  root      585:        if (chan.cmd == 0 || chan.cmd == 1) {
1.1.1.9   root      586:                // コマンド 0、1 がレジスタ切り替え
1.1.1.10  root      587:                chan.ptr = data & MPSCC::WR0_PTR;
1.1.1.14  root      588:                putlog(3, "%s <- $%02x (ptr=%u)", WRName(chan, 0), data, chan.ptr);
1.1.1.10  root      589:        } else {
                    590:                // それ以外ならコマンド発行
                    591:                putlog(2, "%s <- $%02x", CRName(chan, 0), data);
                    592: 
                    593:                switch (chan.cmd) {
                    594:                 case 2:        // Reset Ext/Status Interrupts
                    595:                        ResetESIntr(chan);
                    596:                        break;
                    597:                 case 3:        // Send Abort
                    598:                        SendAbort(chan);
                    599:                        break;
                    600:                 case 4:        // Enable Int on Next Rx Character
                    601:                        EnableIntrOnNextRx(chan);
                    602:                        break;
                    603:                 case 5:        // Reset Tx Int Pending
                    604:                        ResetTxIntrPending(chan);
                    605:                        break;
                    606:                 case 6:        // Error Reset
                    607:                        ErrorReset(chan);
                    608:                        break;
                    609:                 case 7:        // Reset Highest IUS
                    610:                        ResetHighestIUS(chan);
                    611:                        break;
                    612:                 default:
1.1.1.14  root      613:                        VMPANIC("corrupted chan.cmd=%u", chan.cmd);
1.1.1.10  root      614:                }
                    615:        }
                    616: }
                    617: 
                    618: // WR1[AB] への書き込み
                    619: void
                    620: SCCDevice::WriteWR1(MPSCCChan& chan, uint32 data)
                    621: {
                    622:        putlog(2, "%s <- $%02x", WRName(chan), data);
                    623: 
                    624:        chan.wait_enable  = (data & MPSCC::WR1_WAIT_EN);
                    625:        chan.wait_func    = (data & MPSCC::WR1_WAIT_FUNC);
                    626:        chan.wait_on_rx   = (data & MPSCC::WR1_WAIT_RX);
                    627:        // SCC の RXINT は内部フォーマットと同じ値にしてあるのでそのまま代入可。
                    628:        chan.rxint_mode   = (data >> 3) & 3;
                    629:        chan.all_or_first = (chan.rxint_mode != 0);
                    630:        chan.sp_parity    = (data & MPSCC::WR1_SP_INC_PE);
                    631:        chan.txint_enable = (data & MPSCC::WR1_TXINT_EN);
                    632:        chan.esint_enable = (data & MPSCC::WR1_ESINT_EN);
                    633: }
                    634: 
                    635: // WR2 への書き込み
                    636: void
                    637: SCCDevice::WriteWR2(uint32 data)
                    638: {
                    639:        // Z8530 の WR2 は A/B 共通でベクタ設定
                    640:        putlog(2, "WR2 <- $%02x (Set Vector)", data);
                    641:        mpscc.vector = data;
                    642: }
                    643: 
                    644: void
                    645: SCCDevice::WriteWR5(MPSCCChan& chan, uint32 data)
                    646: {
1.1.1.11  root      647:        // ~RTS 端子の立ち下がりでマウスに送信要求。
                    648:        // ~RTS 端子の立ち下がりは nRTS ビットでは立ち上がりになる。
                    649:        bool old_nRTS = chan.nRTS;
                    650:        bool new_nRTS = (data & MPSCC::WR5_nRTS);
                    651:        bool rts = (old_nRTS == false && new_nRTS);
1.1.1.10  root      652: 
                    653:        inherited::WriteCR5(chan, data);
                    654: 
                    655:        if (chan.id == 1 && rts) {
1.1.1.12  root      656:                if (keyboard) {
                    657:                        keyboard->MouseSendStart();
                    658:                }
1.1.1.10  root      659:        }
                    660: }
                    661: 
                    662: void
                    663: SCCDevice::WriteWR9(uint32 data)
                    664: {
                    665:        putlog(2, "WR9  <- $%02x", data);
                    666: 
                    667:        mpscc.wr9_cmd = (data >> 6);
                    668:        switch (mpscc.wr9_cmd) {
                    669:         case 0:        // No Reset
1.1.1.9   root      670:                break;
1.1.1.10  root      671:         case 1:        // Channel Reset B
                    672:                putlog(1, "Channel B Reset");
                    673:                ResetChannel(mpscc.chan[1]);
1.1.1.9   root      674:                break;
1.1.1.10  root      675:         case 2:        // Channel Reset A
                    676:                putlog(1, "Channel A Reset");
                    677:                ResetChannel(mpscc.chan[0]);
1.1       root      678:                break;
1.1.1.10  root      679:         case 3:        // Force Hardware Reset
                    680:                ResetHard(false);
1.1.1.9   root      681:                break;
                    682:         default:
1.1.1.14  root      683:                VMPANIC("corrupted mpscc.wr9_cmd=%u", mpscc.wr9_cmd);
1.1       root      684:        }
1.1.1.10  root      685: 
                    686:        // これらはハードウェアリセットと同時に指定されたら、
                    687:        // リセット後に処理のはず?
                    688:        mpscc.status_high_low           = (data & MPSCC::WR9_SHSL);
                    689:        mpscc.master_int_enable         = (data & MPSCC::WR9_MIE);
                    690:        mpscc.disable_lower_chain       = (data & MPSCC::WR9_DLC);
                    691:        mpscc.vectored_mode                     = !(data & MPSCC::WR9_NV);
                    692:        mpscc.sav_vis                           = (data & MPSCC::WR9_VIS);
                    693: 
                    694:        // SHSL と VIS によって vis モードを再設定
                    695:        if (mpscc.sav_vis) {
                    696:                if (mpscc.status_high_low) {
                    697:                        mpscc.vis = MPSCC::VIS_456;
                    698:                } else {
                    699:                        mpscc.vis = MPSCC::VIS_321;
                    700:                }
                    701:        } else {
                    702:                mpscc.vis = MPSCC::VIS_FIXED;
                    703:        }
1.1       root      704: }
                    705: 
1.1.1.8   root      706: void
1.1.1.10  root      707: SCCDevice::WriteWR10(MPSCCChan& chan, uint32 data)
1.1.1.8   root      708: {
1.1.1.11  root      709:        putlog(2, "%s <- $%02x (NOT IMPLEMENTED)", WRName(chan), data);
1.1.1.10  root      710:        chan.wr10 = data;
                    711: }
1.1.1.8   root      712: 
1.1.1.10  root      713: void
                    714: SCCDevice::WriteWR11(MPSCCChan& chan, uint32 data)
                    715: {
1.1.1.11  root      716:        putlog(2, "%s <- $%02x (NOT IMPLEMENTED)", WRName(chan), data);
1.1.1.10  root      717:        chan.wr11 = data;
                    718: }
1.1.1.8   root      719: 
1.1.1.10  root      720: void
                    721: SCCDevice::WriteWR12(MPSCCChan& chan, uint32 data)
                    722: {
                    723:        chan.tc = (chan.tc & 0xff00) | data;
                    724:        putlog(2, "%s TC(L)=%04x", WRName(chan), chan.tc);
                    725:        SetXC(chan);
                    726: }
                    727: 
                    728: void
                    729: SCCDevice::WriteWR13(MPSCCChan& chan, uint32 data)
                    730: {
                    731:        chan.tc = (chan.tc & 0x00ff) | (data << 8);
                    732:        putlog(2, "%s TC(H)=%04x", WRName(chan), chan.tc);
                    733:        SetXC(chan);
                    734: }
                    735: 
                    736: void
                    737: SCCDevice::WriteWR14(MPSCCChan& chan, uint32 data)
                    738: {
1.1.1.11  root      739:        putlog(2, "%s <- $%02x (NOT IMPLEMENTED)", WRName(chan), data);
1.1.1.10  root      740:        chan.wr14 = data;
                    741: }
                    742: 
                    743: void
                    744: SCCDevice::WriteWR15(MPSCCChan& chan, uint32 data)
                    745: {
1.1.1.11  root      746:        putlog(2, "%s <- $%02x (NOT IMPLEMENTED)", WRName(chan), data);
1.1.1.10  root      747:        chan.wr15 = data;
                    748: }
                    749: 
                    750: // モニター
                    751: void
1.1.1.18! root      752: SCCDevice::MonitorScreen(Monitor *, TextScreen& screen)
1.1.1.10  root      753: {
                    754:        uint wr9;
                    755:        uint rr3a;
                    756:        int y;
                    757: 
                    758:        wr9 = GetWR9();
                    759:        rr3a = GetRR3A();
                    760: 
                    761:        screen.Clear();
                    762:        for (int i = 0; i < 2; i++) {
                    763:                int x = 0;
                    764:                y = i * 16;
1.1.1.18! root      765:                MonitorScreenCh(screen, i, x, y);
1.1.1.10  root      766:        }
                    767: 
                    768:        y = 32;
                    769:        // WR9
                    770:        screen.Print(0, y, "WR9 :$%02x", wr9);
                    771:        static const char * const wr9_str[] = {
                    772:                "", "", "-", "SHSL", "MIE", "DLC", "NV", "VIS"
                    773:        };
                    774:        MonitorReg(screen, 9, y, wr9, wr9_str);
                    775:        static const char * const resetcmd_str[] = {
                    776:        //   012345678
                    777:                "(NoReset)",
                    778:                "(RstChB)",
                    779:                "(RstChA)",
                    780:                "(HardRst)",
                    781:        };
                    782:        screen.Puts(9, y, resetcmd_str[wr9 >> 6]);
                    783:        y++;
                    784: 
                    785:        // RR2B / RR2B
                    786:        screen.Print(0, y, "RR2A:$%02x / RR2B:$%02x", mpscc.vector, GetSR2B());
                    787:        y++;
                    788: 
                    789:        // RR3A
                    790:        static const char * const rr3a_str[] = {
                    791:                "-", "-", "RxA", "TxA", "ESA", "RxB", "TxB", "ESB"
                    792:        };
                    793:        screen.Print(0, y, "RR3A:$%02x", rr3a);
                    794:        MonitorReg(screen, 9, y, rr3a, rr3a_str);
                    795:        y++;
                    796: }
                    797: 
                    798: // モニター (1チャンネル)
                    799: void
1.1.1.18! root      800: SCCDevice::MonitorScreenCh(TextScreen& screen, int ch, int xbase, int ybase)
1.1.1.10  root      801: {
                    802:        const MPSCCChan& chan = mpscc.chan[ch];
                    803:        uint crc;
                    804:        uint cmd;
                    805:        uint ptr;
                    806:        uint wr0;
                    807:        uint wr1;
                    808:        uint wr3;
                    809:        uint wr4;
                    810:        uint wr5;
1.1.1.11  root      811:        uint wr6;
                    812:        uint wr7;
1.1.1.10  root      813:        uint wr10;
                    814:        uint wr11;
                    815:        uint wr14;
                    816:        uint wr15;
                    817:        uint rr0;
                    818:        uint rr1;
                    819:        uint rr10;
                    820:        uint rxlen;
                    821:        uint tc;
                    822:        int x;
                    823:        int y;
                    824: 
                    825:        wr0 = GetCR0(chan);
                    826:        crc = chan.crc_cmd;
                    827:        cmd = chan.cmd;
                    828:        ptr = chan.ptr;
                    829:        wr1 = GetWR1(chan);
                    830:        wr3 = GetCR3(chan);
1.1.1.11  root      831:        wr4 = GetCR4(chan);
1.1.1.10  root      832:        wr5 = GetCR5(chan);
1.1.1.11  root      833:        wr6 = chan.cr6;
                    834:        wr7 = chan.cr7;
1.1.1.10  root      835:        wr10 = chan.wr10;
                    836:        wr11 = chan.wr11;
                    837:        tc   = chan.tc;
                    838:        wr14 = chan.wr14;
                    839:        wr15 = chan.wr15;
                    840:        rr0 = GetRR0(chan);
                    841:        rr1 = chan.sr1;
                    842:        rr10 = chan.rr10;
                    843:        rxlen = chan.rxlen;
                    844: 
                    845:        // 0         1         2         3         4         5         6
                    846:        // 0123456789012345678901234567890123456789012345678901234567890123456789
                    847:        //          0123 0123 0123 0123 0123 0123 0123 0123
                    848:        // Channel A: Serial Console                          DataAddr    $000000
                    849:        // WR0: $xx CRC=x     CMD=x          PTR=x            CtrlAddr    $000000
                    850:        // WR1: $xx WE   0    WR   RXInt=x   0    TXEn ESEn
1.1.1.11  root      851:        // WR13/WR12: $001f (196000bps)       WR7/WR6:$1234
1.1.1.10  root      852: 
                    853:        x = xbase;
                    854:        y = ybase;
                    855:        screen.Print(x, y++, "Channel %c: %s", chan.name, chan.desc);
                    856:        screen.Print(x, y++, "WR0: $%02x", wr0);
                    857:        screen.Print(x, y++, "WR1: $%02x", wr1);
                    858:        screen.Print(x, y++, "WR3: $%02x", wr3);
                    859:        screen.Print(x, y++, "WR4: $%02x", wr4);
                    860:        screen.Print(x, y++, "WR5: $%02x", wr5);
                    861:        screen.Print(x, y++, "WR10:$%02x", wr10);
                    862:        screen.Print(x, y++, "WR11:$%02x", wr11);
                    863:        screen.Print(x, y++, "WR14:$%02x", wr14);
                    864:        screen.Print(x, y++, "WR15:$%02x", wr15);
1.1.1.11  root      865:        screen.Print(x, y,   "WR13/WR12:$%04x (%.1fbps)", tc, chan.baudrate);
                    866:        screen.Print(x + 35, y++, "WR7/WR6:$%02x%02x", wr7, wr6);
1.1.1.10  root      867:        screen.Print(x, y++, "RR0: $%02x", rr0);
                    868:        screen.Print(x, y++, "RR1: $%02x", rr1);
                    869:        screen.Print(x, y++, "RR10:$%02x", rr10);
1.1.1.14  root      870:        screen.Print(x, y,   "RXbuf: %u", rxlen);
1.1.1.10  root      871:        int i;
                    872:        for (i = 0; i < rxlen; i++) {
                    873:                screen.Print(x + 9 + i * 4, y, "$%02x", chan.rxbuf[i]);
1.1.1.8   root      874:        }
1.1.1.10  root      875:        for (; i < sizeof(chan.rxbuf); i++) {
                    876:                screen.Print(x + 9 + i * 4, y, "---");
                    877:        }
                    878: 
                    879:        y = ybase + 1;
                    880:        x = xbase;
                    881:        // WR0
1.1.1.14  root      882:        screen.Print(x + 9, y, "CRC=%u", crc);
1.1.1.10  root      883:        static const char * const cmd_str[] = {
                    884:        //   012345678901234
                    885:                "Null command",
                    886:                "Point High",
                    887:                "Reset E/S Int",
                    888:                "Send Abort",
                    889:                "EnableIntNextCh",
                    890:                "Reset TxIntPend",
                    891:                "Error Reset",
                    892:                "ResetHighestIUS",
                    893:        };
1.1.1.14  root      894:        screen.Print(x + 19, y, "CMD=%u(%s)", cmd, cmd_str[cmd]);
                    895:        screen.Print(x + 43 - (ptr > 9 ? 1 : 0), y, "PTR=%u", ptr);
1.1.1.10  root      896:        y++;
                    897: 
                    898:        // WR1
                    899:        static const char * const wr1_str[] = {
                    900:                "Wait", "Func", "OnRx", "", "", "SpPE", "TxIE", "ESIE"
                    901:        };
                    902:        MonitorReg(screen, x + 9, y, wr1, wr1_str);
                    903:        static const char * const rxint_str[] = {
                    904:        //   012345678
                    905:                "RxInt=Dis",
                    906:                "RI=1stChr",
                    907:                "RI=AllChr",
                    908:                "RI=SPOnly",
                    909:        };
                    910:        screen.Puts(x + 24, y, rxint_str[(wr1 >> 3) & 3]);
                    911:        y++;
                    912: 
                    913:        // WR3,WR4,WR5
1.1.1.18! root      914:        y = MonitorScreenCR345(screen, x, y, wr3, wr4, wr5);
1.1.1.10  root      915: 
                    916:        // WR10
                    917:        screen.Puts(x +  9, y, TA::Disable, (wr10 & 0x80) ? "CRC1" : "CRC0");
                    918:        static const char * const de_str[] = {
                    919:        //       012345678
                    920:                "Enc=NRZ",
                    921:                "Enc=NRZI",
                    922:                "Enc=FM(1)",
                    923:                "Enc=FM(0)",
                    924:        };
                    925:        screen.Puts(x + 14, y, de_str[(wr10 >> 5) & 3]);
                    926:        screen.Puts(x + 24, y, TA::Disable, (wr10 & 0x10) ? "1" : "0");
                    927:        screen.Puts(x + 29, y, TA::Disable, (wr10 & 0x08) ? "1" : "0");
                    928:        screen.Puts(x + 34, y, TA::Disable, (wr10 & 0x04) ? "1" : "0");
                    929:        screen.Puts(x + 39, y, TA::Disable, (wr10 & 0x02) ? "1" : "0");
                    930:        screen.Puts(x + 44, y, TA::Disable, (wr10 & 0x01) ? "1" : "0");
                    931:        y++;
                    932: 
                    933:        // WR11
                    934:        screen.Puts(x + 9, y, TA::OnOff(wr11 & 0x80), "XTAL");
                    935:        static const char * const clksrc_str[] = {
                    936:        //       45678
                    937:                "!RTxC",
                    938:                "!TRxC",
                    939:                "BRG",
                    940:                "DPLL",
                    941:        };
                    942:        screen.Print(x + 14, y, "RxC=%s", clksrc_str[(wr11 >> 5) & 3]);
                    943:        screen.Print(x + 24, y, "TxC=%s", clksrc_str[(wr11 >> 3) & 3]);
                    944:        screen.Puts(x + 34, y, TA::OnOff(wr11 & 0x04), "TOUT");
                    945:        static const char * const clkout_str[] = {
                    946:        //       012345678
                    947:                "TRxC=DPLL",
                    948:                "TRxC=BRG",
                    949:                "TRxC=Clk",
                    950:                "TRxC=Xtal",
                    951:        };
                    952:        screen.Puts(x + 39, y, clkout_str[(wr11 & 3)]);
                    953:        y++;
                    954: 
                    955:        // WR14
                    956:        static const char * const wr14_str[] = {
                    957:                "", "", "", "LLB", "Echo", "DTRL", "BRGS", "BRGE",
                    958:        };
                    959:        MonitorReg(screen, x + 9, y, wr14, wr14_str);
                    960:        static const char * const dpllcmd_str[] = {
                    961:        //       01234567890123
                    962:                "(DPLL nullcmd)",
                    963:                "(EntSearchMod)",
                    964:                "(ResetMissClk)",
                    965:                "(Disable DPLL)",
                    966:                "(Set SRC=BRG)",
                    967:                "(Set SRC=RTxC)",
                    968:                "(Set FM Mode)",
                    969:                "(Set NRZIMode)",
                    970:        };
                    971:        screen.Puts(x + 9, y, dpllcmd_str[(wr14 >> 5)]);
                    972:        y++;
                    973: 
                    974:        // WR15
                    975:        static const char * const wr15_str[] = {
                    976:                "BrIE", "TUIE", "CTIE", "SHIE", "DCIE", "-", "ZCIE", "-"
                    977:        };
                    978:        MonitorReg(screen, x + 9, y, wr15, wr15_str);
                    979:        y++;
                    980: 
                    981:        // WR12/WR13
                    982:        y++;
                    983: 
                    984:        // RR0
                    985:        static const char * const rr0_str[] = {
                    986:                "BrAb", "TxUn", "!CTS", "!SYN", "!DCD", "TxEm", "ZCnt", "RxAv"
                    987:        };
                    988:        MonitorReg(screen, x + 9, y, rr0, rr0_str);
                    989:        y++;
                    990: 
                    991:        // RR1
1.1.1.18! root      992:        MonitorScreenSR1(screen, x, y, rr1);
1.1.1.10  root      993:        y++;
                    994: 
                    995:        // RR10
                    996:        static const char * const rr10_str[] = {
                    997:                "1CM", "2CM", "-", "", "-", "-", "", "-"
                    998:        };
                    999:        MonitorReg(screen, x + 9, y, rr10, rr10_str);
                   1000:        screen.Puts(x + 24, y, TA::Disable, (rr10 & 0x10) ? "1" : "0");
                   1001:        screen.Puts(x + 39, y, TA::Disable, (rr10 & 0x02) ? "1" : "0");
                   1002:        y++;
                   1003: 
                   1004:        // 右列
1.1.1.11  root     1005:        y = ybase + 1;
1.1.1.10  root     1006:        x = xbase + 51;
1.1.1.12  root     1007:        if (chan.dataaddr > 0x01000000) {
                   1008:                screen.Print(x, y++, "DataAddr: $%08x", chan.dataaddr);
                   1009:                screen.Print(x, y++, "CtrlAddr: $%08x", chan.ctrladdr);
                   1010:        } else {
                   1011:                screen.Print(x, y++, "DataAddr:   $%06x", chan.dataaddr);
                   1012:                screen.Print(x, y++, "CtrlAddr:   $%06x", chan.ctrladdr);
                   1013:        }
1.1.1.10  root     1014:        y++;
1.1.1.12  root     1015:        screen.Print(x, y++, "Param:%13s", GetParamStr(chan).c_str());
1.1.1.14  root     1016:        screen.Print(x, y++, "Rx Bits/Frame:   %2u", chan.rxframebits);
                   1017:        screen.Print(x, y++, "Tx Bits/Frame:   %2u", chan.txframebits);
1.1.1.8   root     1018: }
                   1019: 
1.1.1.10  root     1020: // 内部の送信データクロックの設定
1.1       root     1021: void
1.1.1.10  root     1022: SCCDevice::SetXC(MPSCCChan& chan)
1.1       root     1023: {
1.1.1.18! root     1024:        chan.xc12_tsec = (2 * (chan.tc + 2)) * pclk_tsec * 12;
1.1.1.11  root     1025:        ChangeBaudrate(chan);
1.1.1.5   root     1026: }
                   1027: 
                   1028: // 割り込みアクノリッジ
1.1.1.13  root     1029: busdata
1.1.1.5   root     1030: SCCDevice::InterruptAcknowledge()
                   1031: {
1.1.1.10  root     1032:        return GetSR2B();
                   1033: }
                   1034: 
                   1035: // ペンディングのうち最も優先度の高い割り込み要因を返す
                   1036: uint
                   1037: SCCDevice::GetHighestInt() const
                   1038: {
                   1039:        // 上から RxA, TxA, ESA, RxB, TxB, ESB の順 (Z8530 p.2-16)。
                   1040: 
                   1041:        if ((mpscc.chan[0].intpend & INTPEND_SP)) return MPSCC::VS_SPA;
                   1042:        if ((mpscc.chan[0].intpend & INTPEND_RX)) return MPSCC::VS_RxA;
                   1043:        if ((mpscc.chan[0].intpend & INTPEND_TX)) return MPSCC::VS_TxA;
                   1044:        if ((mpscc.chan[0].intpend & INTPEND_ES)) return MPSCC::VS_ESA;
                   1045:        if ((mpscc.chan[1].intpend & INTPEND_SP)) return MPSCC::VS_SPB;
                   1046:        if ((mpscc.chan[1].intpend & INTPEND_RX)) return MPSCC::VS_RxB;
                   1047:        if ((mpscc.chan[1].intpend & INTPEND_TX)) return MPSCC::VS_TxB;
                   1048:        if ((mpscc.chan[1].intpend & INTPEND_ES)) return MPSCC::VS_ESB;
                   1049: 
                   1050:        return MPSCC::VS_none;
1.1       root     1051: }
1.1.1.9   root     1052: 
                   1053: void
                   1054: SCCDevice::Tx(int ch, uint32 data)
                   1055: {
1.1.1.10  root     1056:        switch (ch) {
                   1057:         case 0:
                   1058:                hostcom->Tx(data);
                   1059:                break;
                   1060:         case 1:
                   1061:                // ChB はマウスだが TxD は接続されていない
                   1062:                break;
                   1063:         default:
1.1.1.14  root     1064:                VMPANIC("corrupted ch=%u", ch);
1.1.1.10  root     1065:        }
1.1.1.9   root     1066: }
                   1067: 
                   1068: // ログ表示用のレジスタ名
                   1069: /*static*/ const char * const
                   1070: SCCDevice::wrnames[32] = {
                   1071:        "WR0A",         "WR0B",
                   1072:        "WR1A",         "WR1B",
1.1.1.10  root     1073:        "WR2",          "WR2",
1.1.1.9   root     1074:        "WR3A",         "WR3B",
                   1075:        "WR4A",         "WR4B",
                   1076:        "WR5A",         "WR5B",
                   1077:        "WR6A",         "WR6B",
                   1078:        "WR7A",         "WR7B",
                   1079:        "WR8A",         "WR8B",
1.1.1.10  root     1080:        "WR9",          "WR9",
1.1.1.9   root     1081:        "WR10A",        "WR10B",
                   1082:        "WR11A",        "WR11B",
                   1083:        "WR12A",        "WR12B",
                   1084:        "WR13A",        "WR13B",
                   1085:        "WR14A",        "WR14B",
                   1086:        "WR15A",        "WR15B",
                   1087: };
                   1088: /*static*/ const char * const
                   1089: SCCDevice::rrnames[32] = {
                   1090:        "RR0A",         "RR0B",
                   1091:        "RR1A",         "RR1B",
                   1092:        "RR2A",         "RR2B",
                   1093:        "RR3A",         "RR3B",
1.1.1.10  root     1094:        "(RR0A)",       "(RR0B)",
                   1095:        "(RR1A)",       "(RR1B)",
                   1096:        "(RR2A)",       "(RR2B)",
                   1097:        "(RR3A)",       "(RR3B)",
1.1.1.9   root     1098:        "RR8A",         "RR8B",
1.1.1.10  root     1099:        "(RR13A)",      "(RR13B)",
1.1.1.9   root     1100:        "RR10A",        "RR10B",
1.1.1.10  root     1101:        "(RR15A)",      "(RR15B)",
1.1.1.9   root     1102:        "RR12A",        "RR12B",
                   1103:        "RR13A",        "RR13B",
1.1.1.10  root     1104:        "RR14A",        "RR14B",
1.1.1.9   root     1105:        "RR15A",        "RR15B",
                   1106: };

unix.superglobalmegacorp.com

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