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

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

unix.superglobalmegacorp.com

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