Annotation of nono/vm/mfp.cpp, revision 1.1.1.15

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.12  root        7: //
                      8: // MFP (MC68901)
                      9: //
                     10: 
1.1       root       11: #include "mfp.h"
1.1.1.7   root       12: #include "interrupt.h"
                     13: #include "keyboard.h"
1.1.1.12  root       14: #include "mpu.h"
                     15: #include "scheduler.h"
1.1.1.9   root       16: #include "x68kkbd.h"
1.1       root       17: 
1.1.1.15! root       18: // InsideOut p.135
        !            19: static const busdata wait = busdata::Wait(24 * 40_nsec);
        !            20: 
1.1       root       21: // コンストラクタ
                     22: MFPDevice::MFPDevice()
1.1.1.14  root       23:        : inherited(OBJ_MFP)
1.1       root       24: {
1.1.1.11  root       25:        for (int ch = 0; ch < event.size(); ch++) {
1.1       root       26:                event[ch].dev = this;
1.1.1.12  root       27:                event[ch].func = ToEventCallback(&MFPDevice::TimerCallback);
1.1       root       28:                event[ch].code = ch;
1.1.1.12  root       29:                event[ch].Regist(string_format("MFP Timer-%c", ch + 'A'));
1.1       root       30:        }
1.1.1.4   root       31: 
                     32:        // キーボード周りは x68kkbd.cpp のコメント参照
1.1.1.12  root       33:        key_event.func = ToEventCallback(&MFPDevice::KeyCallback);
1.1.1.4   root       34:        key_event.time = 3750_usec;
1.1.1.12  root       35:        key_event.Regist("MFP USART");
1.1.1.10  root       36: 
1.1.1.12  root       37:        monitor.func = ToMonitorCallback(&MFPDevice::MonitorUpdate);
1.1.1.10  root       38:        monitor.SetSize(77, 26);
                     39:        monitor.Regist(ID_MONITOR_MFP);
1.1       root       40: }
                     41: 
                     42: // デストラクタ
                     43: MFPDevice::~MFPDevice()
                     44: {
1.1.1.14  root       45: }
                     46: 
                     47: // 初期化
                     48: bool
                     49: MFPDevice::Init()
                     50: {
                     51:        if (inherited::Init() == false) {
                     52:                return false;
                     53:        }
                     54: 
                     55:        interrupt = GetInterruptDevice();
                     56:        keyboard = dynamic_cast<X68030Keyboard *>(GetKeyboard());
                     57: 
                     58:        return true;
1.1       root       59: }
                     60: 
1.1.1.12  root       61: // リセット
1.1.1.6   root       62: void
1.1.1.12  root       63: MFPDevice::ResetHard(bool poweron)
1.1.1.6   root       64: {
1.1.1.15! root       65:        // 3.3 RESET OPERATION には
1.1.1.6   root       66:        // All internal registers are cleared expect the TxDR, UDR, and TSR.
1.1.1.15! root       67:        // と書いてあるが、6.2.1 には TxDR はリセット時に $00 と書いてある。
        !            68:        // 内部カウンタは影響を受けずに next_tdr だけリセットされるという
        !            69:        // 意味だろうか。
1.1.1.6   root       70:        mfp.aer = 0;
                     71:        mfp.ddr = 0;
                     72:        mfp.ier.w = 0;
                     73:        mfp.ipr.w = 0;
                     74:        mfp.isr.w = 0;
                     75:        mfp.imr.w = 0;
                     76:        for (int i = 0; i < countof(mfp.tcr); i++) {
                     77:                mfp.tcr[i] = 0;
1.1.1.15! root       78:                mfp.next_tdr[i] = 256;
1.1.1.6   root       79:        }
                     80:        mfp.scr = 0;
                     81:        mfp.ucr = 0;
                     82:        mfp.rsr = 0;
                     83:        // XXX TSR は変化しないがたぶんバッファはクリアされるので BE は立つ
                     84:        // ということかな。
                     85:        mfp.tsr = MFP::TSR_BE;
1.1       root       86: 
1.1.1.6   root       87:        // All timers are stopped.
1.1.1.11  root       88:        for (auto& ev : event) {
1.1.1.14  root       89:                scheduler->StopEvent(ev);
1.1       root       90:        }
1.1.1.14  root       91:        scheduler->StopEvent(key_event);
1.1       root       92: 
1.1.1.6   root       93:        // USART RX and TX are disabled.
                     94:        // SO line is placed in HighZ.
                     95:        // The interrupt channels are disabled, and
                     96:        // any pending interrupts are cleared.
                     97:        // GPIO lines are placed in HighZ.
                     98:        // timer outputs are driven low.
                     99:        // External signals are nagated.
                    100:        // VR is initialized to $00 (not $0f).
1.1.1.7   root      101:        mfp.vr_vec = 0;
                    102:        mfp.vr_s   = 0;
1.1.1.13  root      103: 
                    104:        // CIRQ | FMIRQ | EXPON | ALARM にしておく
                    105:        mfp.gpip = 0x6b;
1.1.1.15! root      106: 
        !           107:        ChangeInterrupt();
1.1.1.3   root      108: }
                    109: 
1.1.1.15! root      110: busdata
1.1.1.8   root      111: MFPDevice::Read(uint32 offset)
1.1       root      112: {
1.1.1.15! root      113:        busdata data;
1.1.1.6   root      114: 
1.1.1.8   root      115:        switch (offset) {
1.1       root      116:         case MFP::GPIP:
                    117:                data = mfp.gpip;
                    118:                break;
                    119:         case MFP::AER:
                    120:                data = mfp.aer;
                    121:                break;
                    122:         case MFP::DDR:
                    123:                data = mfp.ddr;
                    124:                break;
                    125:         case MFP::IERA:
                    126:                data = mfp.ier.a;
                    127:                break;
                    128:         case MFP::IERB:
                    129:                data = mfp.ier.b;
                    130:                break;
                    131:         case MFP::IPRA:
                    132:                data = mfp.ipr.a;
                    133:                break;
                    134:         case MFP::IPRB:
                    135:                data = mfp.ipr.b;
                    136:                break;
                    137:         case MFP::ISRA:
                    138:                data = mfp.isr.a;
                    139:                break;
                    140:         case MFP::ISRB:
                    141:                data = mfp.isr.b;
                    142:                break;
                    143:         case MFP::IMRA:
                    144:                data = mfp.imr.a;
                    145:                break;
                    146:         case MFP::IMRB:
                    147:                data = mfp.imr.b;
                    148:                break;
                    149:         case MFP::VR:
1.1.1.7   root      150:                data = mfp.GetVR();
1.1       root      151:                break;
                    152:         case MFP::TACR:
                    153:                data = mfp.tcr[0];
                    154:                break;
                    155:         case MFP::TBCR:
                    156:                data = mfp.tcr[1];
                    157:                break;
                    158:         case MFP::TCDCR:
                    159:                data = (mfp.tcr[2] << 4) | mfp.tcr[3];
                    160:                break;
                    161:         case MFP::TADR:
                    162:                data = GetTDR(0);
                    163:                break;
                    164:         case MFP::TBDR:
                    165:                data = GetTDR(1);
                    166:                break;
                    167:         case MFP::TCDR:
                    168:                data = GetTDR(2);
                    169:                break;
                    170:         case MFP::TDDR:
                    171:                data = GetTDR(3);
                    172:                break;
                    173:         case MFP::SCR:
                    174:                data = mfp.scr;
                    175:                break;
                    176:         case MFP::UCR:
                    177:                data = mfp.ucr;
                    178:                break;
                    179:         case MFP::RSR:
                    180:                data = mfp.rsr;
                    181:                break;
                    182:         case MFP::TSR:
                    183:                data = mfp.tsr;
                    184:                break;
                    185:         case MFP::UDR:
1.1.1.9   root      186:                // UDR からデータを読み出したら Buffer Full をクリア
1.1       root      187:                data = mfp.udr;
1.1.1.9   root      188:                ClearBF();
1.1       root      189:                break;
1.1.1.4   root      190:         default:
                    191:                data = 0xff;
                    192:                break;
1.1       root      193:        }
1.1.1.15! root      194: 
        !           195:        data |= wait;
1.1       root      196:        return data;
                    197: }
                    198: 
1.1.1.15! root      199: busdata
1.1.1.8   root      200: MFPDevice::Write(uint32 offset, uint32 data)
1.1       root      201: {
1.1.1.8   root      202:        switch (offset) {
1.1       root      203:         case MFP::GPIP:
1.1.1.13  root      204:                putlog(0, "Write GPIP <- $%02x (NOT IMPLEMENTED)", data);
1.1       root      205:                mfp.gpip = data;
                    206:                break;
                    207:         case MFP::AER:
1.1.1.12  root      208:                putlog(2, "AER <- $%02x", data);
1.1       root      209:                mfp.aer = data;
                    210:                break;
                    211:         case MFP::DDR:
                    212:                if (data != 0) {
1.1.1.13  root      213:                        putlog(0, "Write DDR <- $%02x (NOT IMPLEMENTED)", data);
1.1       root      214:                }
                    215:                mfp.ddr = data;
                    216:                break;
                    217:         case MFP::IERA:
                    218:                putlog(2, "IERA <- $%02x", data);
1.1.1.15! root      219:                SetIER(mfp.ier.a, mfp.ipr.a, data);
1.1       root      220:                break;
                    221:         case MFP::IERB:
                    222:                putlog(2, "IERB <- $%02x", data);
1.1.1.15! root      223:                SetIER(mfp.ier.b, mfp.ipr.b, data);
1.1       root      224:                break;
                    225:         case MFP::IPRA:
                    226:                putlog(2, "IPRA <- $%02x", data);
                    227:                mfp.ipr.a = data;
1.1.1.7   root      228:                ChangeInterrupt();
1.1       root      229:                break;
                    230:         case MFP::IPRB:
                    231:                putlog(2, "IPRB <- $%02x", data);
                    232:                mfp.ipr.b = data;
1.1.1.7   root      233:                ChangeInterrupt();
1.1       root      234:                break;
                    235:         case MFP::ISRA:
                    236:                putlog(2, "ISRA <- $%02x", data);
                    237:                mfp.isr.a = data;
                    238:                break;
                    239:         case MFP::ISRB:
                    240:                putlog(2, "ISRB <- $%02x", data);
                    241:                mfp.isr.b = data;
                    242:                break;
                    243:         case MFP::IMRA:
                    244:                putlog(2, "IMRA <- $%02x", data);
                    245:                mfp.imr.a = data;
1.1.1.7   root      246:                ChangeInterrupt();
1.1       root      247:                break;
                    248:         case MFP::IMRB:
                    249:                putlog(2, "IMRB <- $%02x", data);
                    250:                mfp.imr.b = data;
1.1.1.7   root      251:                ChangeInterrupt();
1.1       root      252:                break;
                    253:         case MFP::VR:
1.1.1.7   root      254:                mfp.vr_vec = data & 0xf0;
                    255:                mfp.vr_s   = data & 0x08;
                    256:                putlog(2, "VR <- $%02x", mfp.GetVR());
1.1       root      257:                break;
                    258:         case MFP::TACR:
                    259:                putlog(2, "TACR <- $%02x", data);
                    260:                SetTCR(0, data);
                    261:                break;
                    262:         case MFP::TBCR:
                    263:                putlog(2, "TBCR <- $%02x", data);
                    264:                SetTCR(1, data);
                    265:                break;
                    266:         case MFP::TCDCR:
                    267:                putlog(2, "TCDCR <- $%02x", data);
                    268:                SetTCR(2, data >> 4);
                    269:                SetTCR(3, data & 7);
                    270:                break;
                    271:         case MFP::TADR:
                    272:                putlog(2, "TADR <- $%02x", data);
                    273:                SetTDR(0, data);
                    274:                break;
                    275:         case MFP::TBDR:
                    276:                putlog(2, "TBDR <- $%02x", data);
                    277:                SetTDR(1, data);
                    278:                break;
                    279:         case MFP::TCDR:
                    280:                putlog(2, "TCDR <- $%02x", data);
                    281:                SetTDR(2, data);
                    282:                break;
                    283:         case MFP::TDDR:
                    284:                putlog(2, "TDDR <- $%02x", data);
                    285:                SetTDR(3, data);
                    286:                break;
                    287:         case MFP::SCR:
1.1.1.13  root      288:                putlog(0, "SCR <- $%02x (NOT IMPLEMENTED)", data);
1.1       root      289:                mfp.scr = data;
                    290:                break;
                    291:         case MFP::UCR:
1.1.1.4   root      292:                putlog(2, "UCR <- $%02x", data);
                    293:                SetUCR(data);
1.1       root      294:                break;
                    295:         case MFP::RSR:
1.1.1.4   root      296:                putlog(2, "RSR <- $%02x", data);
                    297:                SetRSR(data);
1.1       root      298:                break;
                    299:         case MFP::TSR:
1.1.1.13  root      300:                if ((data & 0x0e)) {
                    301:                        // SO 端子関係の B, H, L ビットは未実装
                    302:                        putlog(0, "TSR <- $%02x (B,H,L bit NOT IMPLEMENTED)", data);
                    303:                }
1.1       root      304:                mfp.tsr = (mfp.tsr & 0xf0) | (data & 0x0f);
                    305:                break;
                    306:         case MFP::UDR:
1.1.1.4   root      307:                if (data == 0x40 || data == 0x41) {
                    308:                        // MSCTRL だけ頻度が高いのでログレベルを上げておく
                    309:                        putlog(3, "UDR <- $%02x", data);
                    310:                } else {
                    311:                        putlog(2, "UDR <- $%02x", data);
                    312:                }
                    313:                SetUDR(data);
                    314:                break;
                    315:         default:
1.1       root      316:                break;
                    317:        }
1.1.1.15! root      318: 
        !           319:        return wait;
1.1       root      320: }
                    321: 
1.1.1.15! root      322: busdata
1.1.1.8   root      323: MFPDevice::Peek(uint32 offset)
1.1       root      324: {
                    325:        uint8 data;
                    326: 
1.1.1.8   root      327:        switch (offset) {
1.1       root      328:         case MFP::GPIP:
                    329:                data = mfp.gpip;
                    330:                break;
                    331:         case MFP::AER:
                    332:                data = mfp.aer;
                    333:                break;
                    334:         case MFP::DDR:
                    335:                data = mfp.ddr;
                    336:                break;
                    337:         case MFP::IERA:
                    338:                data = mfp.ier.a;
                    339:                break;
                    340:         case MFP::IERB:
                    341:                data = mfp.ier.b;
                    342:                break;
                    343:         case MFP::IPRA:
                    344:                data = mfp.ipr.a;
                    345:                break;
                    346:         case MFP::IPRB:
                    347:                data = mfp.ipr.b;
                    348:                break;
                    349:         case MFP::ISRA:
                    350:                data = mfp.isr.a;
                    351:                break;
                    352:         case MFP::ISRB:
                    353:                data = mfp.isr.b;
                    354:                break;
                    355:         case MFP::IMRA:
                    356:                data = mfp.imr.a;
                    357:                break;
                    358:         case MFP::IMRB:
                    359:                data = mfp.imr.b;
                    360:                break;
                    361:         case MFP::VR:
1.1.1.7   root      362:                data = mfp.GetVR();
1.1       root      363:                break;
                    364:         case MFP::TACR:
                    365:                data = mfp.tcr[0];
                    366:                break;
                    367:         case MFP::TBCR:
                    368:                data = mfp.tcr[1];
                    369:                break;
                    370:         case MFP::TCDCR:
                    371:                data = (mfp.tcr[2] << 4) | mfp.tcr[3];
                    372:                break;
                    373:         case MFP::TADR:
                    374:                data = GetTDR(0);
                    375:                break;
                    376:         case MFP::TBDR:
                    377:                data = GetTDR(1);
                    378:                break;
                    379:         case MFP::TCDR:
                    380:                data = GetTDR(2);
                    381:                break;
                    382:         case MFP::TDDR:
                    383:                data = GetTDR(3);
                    384:                break;
                    385:         case MFP::SCR:
                    386:                data = mfp.scr;
                    387:                break;
                    388:         case MFP::UCR:
                    389:                data = mfp.ucr;
                    390:                break;
                    391:         case MFP::RSR:
                    392:                data = mfp.rsr;
                    393:                break;
                    394:         case MFP::TSR:
                    395:                data = mfp.tsr;
                    396:                break;
                    397:         case MFP::UDR:
                    398:                data = mfp.udr;
                    399:                break;
1.1.1.4   root      400:         default:
                    401:                data = 0xff;
1.1       root      402:        }
                    403:        return data;
                    404: }
                    405: 
1.1.1.5   root      406: void
1.1.1.10  root      407: MFPDevice::MonitorUpdate(Monitor *, TextScreen& screen)
1.1       root      408: {
1.1.1.15! root      409:        MFP mfp_;
        !           410:        std::array<uint8, 4> tdr_;
1.1       root      411:        int x;
                    412:        int y;
                    413: 
1.1.1.15! root      414:        // ローカルにコピー。
        !           415:        memcpy(&mfp_, &mfp, sizeof(mfp));
        !           416:        for (int ch = 0; ch < tdr_.size(); ch++) {
        !           417:                tdr_[ch] = GetTDR(ch);
        !           418:        }
        !           419: 
1.1.1.10  root      420:        screen.Clear();
1.1       root      421: 
                    422:        // 0         1         2         3         4         5         6
1.1.1.7   root      423:        // 01234567890123456789012345678901234567890123456789012345678901234567890
                    424:        // $e88001(GPIP):$00   $e88007(IERA):$00   $e88019(TACR):$00   $e88027
1.1.1.13  root      425:        //                 IER    IMR  IPR  ISR            Mode        TDR Cnt
                    426:        // An:MPSC TxEmpty Enable Mask Pend Serv   Timer-A Delay(50us) 255 255
1.1       root      427: 
1.1.1.7   root      428: #define A(x)   (baseaddr + (x * 2) + 1)
                    429: 
                    430:        // レジスタ生値
                    431:        // 1列目(GPIP 関連と VR)
                    432:        x = 0;
                    433:        y = 0;
1.1.1.15! root      434:        screen.Print(x, y++, "$%06x(GPIP):$%02x", A(MFP::GPIP), mfp_.gpip);
        !           435:        screen.Print(x, y++, "$%06x(AER): $%02x", A(MFP::AER),  mfp_.aer);
        !           436:        screen.Print(x, y++, "$%06x(DDR): $%02x", A(MFP::DDR),  mfp_.ddr);
        !           437:        screen.Print(x, y++, "$%06x(VR):  $%02x", A(MFP::VR),   mfp_.GetVR());
1.1.1.7   root      438:        // 2列目(割り込み関連)
                    439:        x = 20;
                    440:        y = 0;
1.1.1.15! root      441:        screen.Print(x, y++, "$%06x(IERA):$%02x", A(MFP::IERA), mfp_.ier.a);
        !           442:        screen.Print(x, y++, "$%06x(IERB):$%02x", A(MFP::IERB), mfp_.ier.b);
        !           443:        screen.Print(x, y++, "$%06x(IPRA):$%02x", A(MFP::IPRA), mfp_.ipr.a);
        !           444:        screen.Print(x, y++, "$%06x(IPRB):$%02x", A(MFP::IPRB), mfp_.ipr.b);
        !           445:        screen.Print(x, y++, "$%06x(ISRA):$%02x", A(MFP::ISRA), mfp_.isr.a);
        !           446:        screen.Print(x, y++, "$%06x(ISRB):$%02x", A(MFP::ISRB), mfp_.isr.b);
        !           447:        screen.Print(x, y++, "$%06x(IMRA):$%02x", A(MFP::IMRA), mfp_.imr.a);
        !           448:        screen.Print(x, y++, "$%06x(IMRB):$%02x", A(MFP::IMRB), mfp_.imr.b);
1.1.1.7   root      449:        // 3列目(タイマー関連)
                    450:        x = 40;
                    451:        y = 0;
1.1.1.15! root      452:        screen.Print(x, y++, "$%06x(TACR): $%02x", A(MFP::TACR), mfp_.tcr[0]);
        !           453:        screen.Print(x, y++, "$%06x(TBCR): $%02x", A(MFP::TBCR), mfp_.tcr[1]);
1.1.1.10  root      454:        screen.Print(x, y++, "$%06x(TCDCR):$%02x", A(MFP::TCDCR),
1.1.1.15! root      455:                (mfp_.tcr[2] << 4) | mfp_.tcr[3]);
        !           456:        screen.Print(x, y++, "$%06x(TADR): $%02x", A(MFP::TADR), tdr_[0]);
        !           457:        screen.Print(x, y++, "$%06x(TBDR): $%02x", A(MFP::TBDR), tdr_[1]);
        !           458:        screen.Print(x, y++, "$%06x(TCDR): $%02x", A(MFP::TCDR), tdr_[2]);
        !           459:        screen.Print(x, y++, "$%06x(TDDR): $%02x", A(MFP::TDDR), tdr_[3]);
1.1.1.7   root      460:        // 4列目(USART 関連)
                    461:        x = 61;
                    462:        y = 0;
1.1.1.15! root      463:        screen.Print(x, y++, "$%06x(SCR):$%02x", A(MFP::SCR), mfp_.scr);
        !           464:        screen.Print(x, y++, "$%06x(UCR):$%02x", A(MFP::UCR), mfp_.ucr);
        !           465:        screen.Print(x, y++, "$%06x(RSR):$%02x", A(MFP::RSR), mfp_.rsr);
        !           466:        screen.Print(x, y++, "$%06x(TSR):$%02x", A(MFP::TSR), mfp_.tsr);
1.1.1.10  root      467:        screen.Print(x, y, "$%06x(UDR):", A(MFP::UDR));
1.1.1.15! root      468:        if ((int16)mfp_.udr >= 0) {
        !           469:                screen.Print(x + 13, y, "$%02x", mfp_.udr);
1.1.1.7   root      470:        } else {
1.1.1.10  root      471:                screen.Print(x + 13, y, "---");
1.1.1.7   root      472:        }
                    473: 
1.1       root      474:        // 割り込み関連
1.1.1.7   root      475:        y = 9;
1.1.1.10  root      476:        screen.Print(0, y++, "<Interrupt>     %-6s %-4s %-4s %-4s",
1.1.1.7   root      477:                "IER", "IMR", "IPR", "ISR");
1.1       root      478:        for (int i = 15; i >= 0; i--, y++) {
                    479:                uint16 mask = (1 << i);
1.1.1.10  root      480:                screen.Print(0, y, "%c%d:%-12s %-6s %-4s %-4s %-4s",
1.1       root      481:                        i >= 8 ? 'A' : 'B',
                    482:                        (i % 8),
                    483:                        intrname[i],
1.1.1.15! root      484:                        (mfp_.ier.w & mask) ? "Enable" : "",
        !           485:                        (mfp_.imr.w & mask) ? ""       : "Mask",        // %0 でマスクする
        !           486:                        (mfp_.ipr.w & mask) ? "Pend"   : "",
        !           487:                        (mfp_.isr.w & mask) ? "Serv"   : "");
1.1       root      488:        }
                    489: 
                    490:        // タイマー関連
1.1.1.13  root      491:        x = 40;
1.1.1.7   root      492:        y = 9;
1.1.1.15! root      493:        screen.Print(x, y++, "<Timer> Mode        TDR Next");
1.1       root      494:        for (int ch = 0; ch < 4; ch++) {
1.1.1.10  root      495:                screen.Print(x, y, "Timer-%c", ch + 'A');
1.1.1.15! root      496:                if (mfp_.tcr[ch] == 0) {
1.1.1.10  root      497:                        screen.Print(x + 8, y, "Stopped");
1.1.1.15! root      498:                } else if (mfp_.tcr[ch] == 8) {
1.1.1.10  root      499:                        screen.Print(x + 8, y, "Event");
1.1.1.15! root      500:                } else if (mfp_.tcr[ch] > 8) {
        !           501:                        screen.Print(x + 8, y, "Pulse(%s)", prescale_str[mfp_.tcr[ch] - 8]);
1.1       root      502:                } else {
1.1.1.15! root      503:                        screen.Print(x + 8, y, "Delay(%s)", prescale_str[mfp_.tcr[ch]]);
1.1       root      504:                }
                    505: 
1.1.1.15! root      506:                screen.Print(x + 20, y, "%3d", tdr_[ch]);
        !           507:                screen.Print(x + 25, y, "%3d", mfp_.next_tdr[ch] & 0xff);
1.1.1.7   root      508:                y++;
1.1       root      509:        }
                    510: 
                    511:        // GPIP 関連
1.1.1.13  root      512:        x = 40;
1.1.1.7   root      513:        y = 9 + 8;
1.1.1.10  root      514:        screen.Puts(x, y++, "<GPIP>    GPIP AER DDR");
1.1       root      515:        for (int i = 7; i >= 0; i--, y++) {
                    516:                uint mask = (1 << i);
1.1.1.10  root      517:                screen.Print(x, y, "b%d %-6s  %d   %d   %s", i, gpipname[i],
1.1.1.15! root      518:                        (mfp_.gpip & mask) ? 1 : 0,
        !           519:                        (mfp_.aer & mask) ? 1 : 0,
        !           520:                        (mfp_.ddr & mask) ? "OUT" : "IN");
1.1       root      521:        }
                    522: }
                    523: 
                    524: /*static*/ const char *
                    525: MFPDevice::intrname[] = {
                    526:        "RTC Alarm",
                    527:        "EXPON",
                    528:        "POW SW",
                    529:        "FM IRQ",
                    530:        "Timer-D",
                    531:        "Timer-C",
                    532:        "V-Disp",
                    533:        "---",
                    534:        "Timer-B",
                    535:        "MPSC TxErr",
                    536:        "MPSC TxEmpty",
                    537:        "MPSC RxErr",
                    538:        "MPSC RxFull",
                    539:        "Timer-A",
                    540:        "CRTC IRQ",
                    541:        "H-Sync",
                    542: };
                    543: 
                    544: /*static*/ const char *
                    545: MFPDevice::gpipname[] = {
                    546:        "ALARM",
                    547:        "EXPON",
                    548:        "POW SW",
                    549:        "FMIRQ",
                    550:        "V-Disp",
                    551:        "------",
                    552:        "CIRQ",
                    553:        "H-Sync",
                    554: };
                    555: 
                    556: // TxCR の設定値から分周期間というかメインカウンタ1回分の時間を返す
                    557: /*static*/ const int
                    558: MFPDevice::prescale_ns[8] = {
                    559:        0,
                    560:        1000,   // /4
                    561:        2500,   // /10
                    562:        4000,   // /16
                    563:        12500,  // /50
                    564:        16000,  // /64
                    565:        25000,  // /100
                    566:        50000,  // /200
                    567: };
                    568: 
                    569: /*static*/ const char *
                    570: MFPDevice::prescale_str[8] = {
                    571:        "",
                    572:        "1us",
                    573:        "2.5us",
                    574:        "4us",
                    575:        "12.5us",
                    576:        "16us",
                    577:        "25us",
                    578:        "50us",
                    579: };
                    580: 
1.1.1.7   root      581: // タイマーのチャンネルから MFP 割り込みチャンネル番号に変換する
1.1       root      582: /*static*/ const int
1.1.1.4   root      583: MFPDevice::timer_vector[4] = {
                    584:        MFP::INTR_TIMER_A,
                    585:        MFP::INTR_TIMER_B,
                    586:        MFP::INTR_TIMER_C,
                    587:        MFP::INTR_TIMER_D,
                    588: };
1.1       root      589: 
1.1.1.15! root      590: // IER[AB] に data をセットする
        !           591: void
        !           592: MFPDevice::SetIER(uint8& ier, uint8& ipr, uint32 data)
        !           593: {
        !           594:        // clr は、data によって %1 -> %0 に変化するビットだけを立てたもの。
        !           595:        uint8 clr = ier & (ier ^ data);
        !           596: 
        !           597:        // IER を下げたところは IPR も下げる。(紙資料 p4-4)
        !           598:        ipr &= ~clr;
        !           599: 
        !           600:        // どちらにしても新しい IER によって信号線の状態は変える。
        !           601:        ier = data;
        !           602:        ChangeInterrupt();
        !           603: }
        !           604: 
1.1       root      605: // TxCR をセットする
                    606: void
                    607: MFPDevice::SetTCR(int ch, uint32 data)
                    608: {
                    609:        uint32 prev;
                    610: 
                    611:        prev = mfp.tcr[ch];
                    612:        data &= 0x0f;
                    613: 
                    614:        mfp.tcr[ch] = data;
1.1.1.7   root      615:        if (data == 0) {
                    616:                if (prev == 0) {
                    617:                        // 0 -> 0 なら何も起きない
                    618:                        return;
                    619:                } else if (prev < 8) {
                    620:                        // タイマー停止
1.1.1.13  root      621:                        putlog(1, "Timer-%c Stop", ch + 'A');
1.1.1.7   root      622: 
                    623:                        // ここで TDR を確定させる。
                    624:                        // タイマー動作中の TDR の参照はイベント終了時刻から現在値を逆算
                    625:                        // していたが、イベントを停止すると求められなくなるので、イベント
                    626:                        // 停止前に求めておく。
                    627:                        uint64 period = prescale_ns[prev];
1.1.1.14  root      628:                        uint64 now = scheduler->GetVirtTime();
1.1.1.7   root      629:                        mfp.tdr[ch] = ((event[ch].vtime - now) + period - 1) / period;
                    630: 
                    631:                        // でイベント停止
1.1.1.14  root      632:                        scheduler->StopEvent(event[ch]);
1.1.1.7   root      633:                        return;
                    634:                } else if (prev == 8) {
                    635:                        // イベントカウントモードから停止しても何も起きないはず
                    636:                } else {
                    637:                        // パルス幅測定モード (未実装)
                    638:                }
1.1       root      639:                return;
1.1.1.7   root      640: 
                    641:        } else if (data < 8) {
                    642:                // タイマー開始
                    643: 
1.1.1.15! root      644:                // TDR は触らずイベントを開始。
1.1.1.7   root      645:                uint64 period = prescale_ns[mfp.tcr[ch]];
1.1.1.15! root      646:                event[ch].time = period * mfp.tdr[ch];
1.1.1.14  root      647:                scheduler->RestartEvent(event[ch]);
1.1.1.7   root      648: 
1.1.1.13  root      649:                putlog(1, "Timer-%c Start Delay mode(%u x %u.%uusec)",
1.1.1.7   root      650:                        ch + 'A',
1.1.1.15! root      651:                        mfp.tdr[ch],
1.1.1.7   root      652:                        (uint)period / 1000,
                    653:                        (uint)(period / 100) % 10);
                    654:                return;
                    655: 
                    656:        } else if (data == 8) {
1.1       root      657:                // イベントカウントモード
                    658: 
                    659:                // TDR をロードする
1.1.1.15! root      660:                mfp.next_tdr[ch] = mfp.tdr[ch];
1.1.1.13  root      661:                putlog(1, "Timer-%c Event count mode", ch + 'A');
1.1       root      662:                return;
                    663: 
                    664:        } else {
1.1.1.13  root      665:                putlog(0, "T%cCR Pulse-Width Measurement Mode $%02x (NOT IMPLEMENTED)",
1.1.1.7   root      666:                        ch + 'A', data);
                    667:                return;
1.1       root      668:        }
                    669: }
                    670: 
                    671: // TxDR の読み出し
1.1.1.7   root      672: // (副作用はないので Peek 系からも呼び出してよい)
1.1       root      673: uint8
1.1.1.3   root      674: MFPDevice::GetTDR(int ch) const
1.1       root      675: {
1.1.1.7   root      676:        uint8 tcr = mfp.tcr[ch];
1.1       root      677: 
1.1.1.7   root      678:        if (tcr == 0) {
                    679:                // 停止中なら tdr に現在値が保持されている
1.1.1.15! root      680:                return mfp.tdr[ch] & 0xff;
1.1       root      681: 
1.1.1.7   root      682:        } else if (tcr < 8) {
                    683:                // ディレイモード動作中なら現在値は保持していないので、
                    684:                // プリスケーラと終了時刻から算出。
                    685: 
                    686:                uint64 period = prescale_ns[tcr];
1.1.1.14  root      687:                uint64 now = scheduler->GetVirtTime();
1.1.1.15! root      688:                uint8 data = ((event[ch].vtime - now) + period - 1) / period;
        !           689:                return data;
1.1       root      690: 
1.1.1.7   root      691:        } else {
                    692:                // イベントモード、パルス幅測定モードは未対応
1.1.1.15! root      693:                return mfp.tdr[ch] & 0xff;
1.1       root      694: 
1.1.1.7   root      695:        }
1.1       root      696: }
                    697: 
                    698: // TxDR への書き込み
                    699: void
                    700: MFPDevice::SetTDR(int ch, uint32 data)
                    701: {
1.1.1.7   root      702:        uint8& tcr = mfp.tcr[ch];
1.1       root      703: 
1.1.1.15! root      704:        if (data == 0) {
        !           705:                data = 256;
        !           706:        }
        !           707:        mfp.next_tdr[ch] = data;
        !           708: 
1.1.1.7   root      709:        if (tcr == 0) {
1.1.1.15! root      710:                // 停止中の書き込みはメインカウンタも更新。
1.1.1.7   root      711:                mfp.tdr[ch] = data;
                    712: 
                    713:        } else if (tcr < 8) {
1.1.1.15! root      714:                // ディレイモード動作中の書き込みは
        !           715:                // メインカウンタは影響を受けない。
1.1       root      716: 
1.1.1.7   root      717:        } else {
                    718:                // イベントモード、パルス幅測定モードは未対応
1.1.1.13  root      719:                putlog(0, "Write T%cDR $%02x during unsupported mode (NOT IMPLEMENTED)",
1.1.1.15! root      720:                        ch + 'A', mfp.next_tdr[ch]);
1.1       root      721:        }
                    722: }
                    723: 
                    724: // イベントコールバック
                    725: void
1.1.1.6   root      726: MFPDevice::TimerCallback(Event& ev)
1.1       root      727: {
1.1.1.6   root      728:        int& ch = ev.code;
1.1       root      729: 
1.1.1.7   root      730:        // TDR がゼロになったところで呼ばれるので、TDR をリロードする
1.1.1.15! root      731:        mfp.tdr[ch] = mfp.next_tdr[ch];
1.1       root      732: 
1.1.1.7   root      733:        // 割り込みを上げる
                    734:        SetInterrupt(timer_vector[ch]);
                    735: 
                    736:        // 次のイベントをセット
                    737:        // XXX 1回のイベントで複数のタイムアウトパルスを跨ぐ状況は考慮してない
                    738: 
                    739:        // period が1メインパルス期間
                    740:        // time が1タイムアウトパルス期間
                    741:        uint64 period = prescale_ns[mfp.tcr[ch]];
1.1.1.15! root      742:        ev.time = period * mfp.tdr[ch];
1.1.1.14  root      743:        scheduler->RestartEvent(ev);
1.1.1.12  root      744: }
                    745: 
                    746: // HSync 入力
                    747: void
                    748: MFPDevice::SetHSync(bool hsync)
                    749: {
                    750:        SetGPIP(MFP::GPIP_HSYNC, hsync);
1.1       root      751: }
                    752: 
                    753: // VDisp 入力
                    754: void
                    755: MFPDevice::SetVDisp(bool vdisp)
                    756: {
                    757:        // TAI への入力はイベントカウントモードの時のみ
                    758:        if (mfp.tcr[0] == 8) {
                    759:                // AER が示す方向と同じエッジ方向の時
                    760:                bool aer = (mfp.aer & (1 << MFP::GPIP_VDISP));
                    761:                if (aer == vdisp) {
                    762:                        // カウンタを減算
1.1.1.7   root      763:                        mfp.tdr[0]--;
                    764:                        if (mfp.tdr[0] == 0) {
1.1       root      765:                                // 0 になったらリロード
1.1.1.15! root      766:                                mfp.tdr[0] = mfp.next_tdr[0];
1.1       root      767: 
1.1.1.7   root      768:                                SetInterrupt(MFP::INTR_TIMER_A);
1.1       root      769:                        }
                    770:                }
                    771:        }
                    772: 
                    773:        // GPIP への入力
                    774:        SetGPIP(MFP::GPIP_VDISP, vdisp);
                    775: }
                    776: 
1.1.1.13  root      777: // 電源ボタン状態入力 (PowerDevice から呼ばれる)
                    778: void
                    779: MFPDevice::SetPowSW(bool powsw)
                    780: {
                    781:        SetGPIP(MFP::GPIP_POWSW, powsw);
                    782: }
                    783: 
                    784: // ALARM 信号入力 (RTC の ALARM_OUT 出力端子)
                    785: void
                    786: MFPDevice::SetAlarmOut(bool alarm)
                    787: {
                    788:        SetGPIP(MFP::GPIP_ALARM, alarm);
                    789: }
                    790: 
1.1       root      791: // GPIP への入力。
                    792: // num はビット番号(0..7)。
                    793: void
                    794: MFPDevice::SetGPIP(int num, bool val)
                    795: {
                    796:        bool aer = (mfp.aer & (1 << num));
                    797:        bool old = (mfp.gpip & (1 << num));
                    798: 
                    799:        // 立ち上がりか立ち下がりで割り込みを上げる (AER による)
                    800:        // AER OLD VAL   Interrupt
                    801:        //   0   0   0   0
                    802:        //   0   0   1   0
                    803:        //   0   1   0   1
                    804:        //   0   1   1   0
                    805:        //   1   0   0   0
                    806:        //   1   0   1   1
                    807:        //   1   1   0   0
                    808:        //   1   1   1   0
1.1.1.3   root      809:        if ((old != val) && (aer == val)) {
1.1.1.13  root      810:                // ここで割り込みを上げる
                    811:                // XXX GPIP ビット番号と INTR の対応どうなってんの
                    812:                int intr;
                    813:                if (num < 4) {
                    814:                        intr = num;
                    815:                } else if (num < 6) {
                    816:                        intr = num + 2;
                    817:                } else {
                    818:                        intr = num - MFP::GPIP_CIRQ + MFP::INTR_CRTC_IRQ;
                    819:                }
                    820:                SetInterrupt(intr);
1.1       root      821:        }
                    822: 
                    823:        if (val) {
                    824:                mfp.gpip |= (1 << num);
                    825:        } else {
                    826:                mfp.gpip &= ~(1 << num);
                    827:        }
                    828: }
1.1.1.4   root      829: 
                    830: // UCR への書き込み
                    831: void
                    832: MFPDevice::SetUCR(uint32 data)
                    833: {
                    834:        mfp.ucr = data;
                    835: 
                    836:        if ((mfp.ucr & MFP::UCR_CLK) == 0) {
1.1.1.13  root      837:                putlog(0, "UCR CLK=0 (NOT IMPLEMENTED)");
1.1.1.4   root      838:        }
                    839:        if (((mfp.ucr & MFP::UCR_WL) >> 5) != 0) {
1.1.1.13  root      840:                putlog(0, "UCR WL=%d (NOT IMPLEMENTED)", (mfp.ucr >> 5) & 3);
1.1.1.4   root      841:        }
                    842:        if (((mfp.ucr & MFP::UCR_ST) >> 3) != 1) {
1.1.1.13  root      843:                putlog(0, "UCR ST=%d (NOT IMPLEMENTED)", (mfp.ucr >> 3) & 3);
1.1.1.4   root      844:        }
                    845: }
                    846: 
                    847: // RSR への書き込み
                    848: void
                    849: MFPDevice::SetRSR(uint32 data)
                    850: {
                    851:        uint32 old = mfp.rsr;
                    852: 
                    853:        mfp.rsr = data;
                    854: 
                    855:        if ((old & MFP::RSR_RE) == 0 && (mfp.rsr & MFP::RSR_RE)) {
                    856:                // RE 0 -> 1
                    857:        }
                    858:        if ((old & MFP::RSR_RE) && (mfp.rsr & MFP::RSR_RE) == 0) {
                    859:                // RE 1 -> 0
1.1.1.9   root      860:                // 上位4ビットのステータスを %0 に
                    861:                mfp.rsr &= ~(MFP::RSR_OE | MFP::RSR_PE | MFP::RSR_FE);
                    862:                ClearBF();
1.1.1.4   root      863:        }
                    864: }
                    865: 
1.1.1.9   root      866: // RSR::BF (Buffer Full) をセットする
                    867: void
                    868: MFPDevice::SetBF()
                    869: {
                    870:        mfp.rsr |= MFP::RSR_BF;
                    871: }
                    872: 
                    873: // RSR::BF (Buffer Full) をクリアする
                    874: void
                    875: MFPDevice::ClearBF()
                    876: {
                    877:        mfp.rsr &= ~MFP::RSR_BF;
                    878: 
                    879:        // バッファが空いたのでキーボードに次の転送を催促。
                    880:        // 実際のハードウェアでは、キーボードが本体 MFP が Ready になるのを待って
                    881:        // いるが、それに相当。
                    882:        // システムポートの KEYCTRL はキーボード側で処理している。
1.1.1.14  root      883:        keyboard->Ready();
1.1.1.9   root      884: }
                    885: 
1.1.1.4   root      886: // UDR への書き込み
                    887: void
                    888: MFPDevice::SetUDR(uint32 data)
                    889: {
                    890:        if ((mfp.tsr & MFP::TSR_TE)) {
1.1.1.14  root      891:                keyboard->Command(data);
1.1.1.4   root      892:        }
                    893: }
                    894: 
1.1.1.9   root      895: // __
                    896: // RR 線の状態を返す。アサートなら true。
                    897: bool
                    898: MFPDevice::IsRR() const
1.1.1.4   root      899: {
1.1.1.9   root      900:        //        __
                    901:        // 実際の RR 信号線は、BF が立っていて、PE | FE がクリアされている場合に
                    902:        // アサートされる。ただしエミュレータでは Parity Error も Frame Error も
                    903:        // 起きないので、この2ビットは無視する。
                    904:        return ((mfp.rsr & MFP::RSR_BF) != 0);
1.1.1.4   root      905: }
                    906: 
1.1.1.9   root      907: // キーボードからの受信が可能なら true を返す。
1.1.1.4   root      908: bool
1.1.1.9   root      909: MFPDevice::RxIsReady() const
1.1.1.4   root      910: {
1.1.1.9   root      911:        // __
                    912:        // RR は本来 MFP から CPU/DMAC など上位に対しての Ready で、
                    913:        // UDR にデータが用意できたので引き取ってほしいの意。
                    914:        // X680x0 ではこれを CPU/DMAC (上位) 向けではなく、下位のキーボードからの
                    915:        // フロー制御に流用しており、
                    916:        // 上位への(本来の)「UDR にデータが用意できた」(IsRR() = true) は、
                    917:        // キーボードに対しては「UDR にデータがあるので送信禁止」、
                    918:        // 上位への(本来の)「UDR にデータが用意できていない」(IsRR() = false) は、
                    919:        // キーボードに対しては「UDR は空いているので送信してよい」と
                    920:        // ここで意味が論理反転することに注意。
                    921:        //
                    922:        // また、システムポートの KEYCTRL は X680x0Keyboard 側で処理しているので
                    923:        // こちらでは不要。
                    924:        //
                    925:        // UDR が空いていてキーボードからデータが送られてきている間は RR は Ready
                    926:        // だが、そもそもキーボードは送出作業中で、新たな送信はできないはずなので
                    927:        // この場合、つまり key_event の動作中も false (送信不可) にする。
                    928: 
                    929:        return !IsRR() && !key_event.IsRunning();
1.1.1.4   root      930: }
                    931: 
                    932: // キーボードからデータを受信
                    933: void
                    934: MFPDevice::Rx(uint32 data)
                    935: {
1.1.1.9   root      936:        // ここは受信したビットをシフトレジスタへ入れ始めたところに相当する
                    937:        // ので、まだ Buffer Full は立てない。
1.1.1.4   root      938: 
                    939:        key_event.code = data;
1.1.1.14  root      940:        scheduler->RestartEvent(key_event);
1.1.1.4   root      941: }
                    942: 
                    943: // キーボードからのデータが受信し終わった頃に呼ばれるイベント。
                    944: void
1.1.1.6   root      945: MFPDevice::KeyCallback(Event& ev)
1.1.1.4   root      946: {
1.1.1.9   root      947:        // UDR にデータを置いて Buffer Full をセット
1.1.1.6   root      948:        mfp.udr = ev.code;
1.1.1.9   root      949:        SetBF();
                    950: 
                    951:        // Manual 7-5 7.2.1 Receiver Interrupt Channels より
                    952:        // | 割り込みは1文字受信ごとに1回しか発生しませんが、2つの専用割り込み
                    953:        // | チャネルにより、正常な受信状態と異常な受信状態に別々のベクター番号を
                    954:        // | 割り当てることができます。受信したワードにエラーがあり、エラー割り込み
                    955:        // | チャネルが有効な場合は、エラーチャネルのみに割り込みが発生します。
                    956:        // | しかし、エラーチャネルが無効の場合、エラー状態の割り込みは、
                    957:        // | バッファフル状態の割り込みと一緒にバッファフル割り込みチャネルに
                    958:        // | 生成されます。どのエラー条件で割り込みが発生したかを判断するためには、
                    959:        // | 常にRSRを読み出す必要があります。
                    960:        // XXX: まだエラー状態は実装されていない、なおエラーは起きないので
                    961:        // メモだけのままかも知れない。
1.1.1.4   root      962: 
1.1.1.7   root      963:        SetInterrupt(MFP::INTR_RXFULL);
                    964: }
                    965: 
                    966: // 必要なら割り込みを上げる。
                    967: // ch は MFP 内の割り込みチャンネル番号。MFP::INTR_*
                    968: void
                    969: MFPDevice::SetInterrupt(uint ch)
                    970: {
                    971:        assertmsg(ch < 16, "ch=%u", ch);
                    972:        __assume(ch < 16);
                    973: 
                    974:        uint b = (1U << ch);
                    975: 
                    976:        // IER で割り込みが無効なら何もしない
                    977:        if ((mfp.ier.w & b) == 0) {
                    978:                return;
1.1.1.4   root      979:        }
1.1.1.7   root      980: 
                    981:        // IPR にペンディングを立てる
                    982:        mfp.ipr.w |= b;
                    983: 
                    984:        // 割り込み信号線の状態を変える
                    985:        ChangeInterrupt();
                    986: }
                    987: 
                    988: // 割り込み信号線の状態を変える
                    989: void
                    990: MFPDevice::ChangeInterrupt()
                    991: {
                    992:        // ペンディングの割り込みがあればアサートされる、
                    993:        // IPR をクリアするか IMR をクリアすると /IRQ はネゲートされる。
                    994:        bool irq = ((mfp.ipr.w & mfp.imr.w) != 0);
1.1.1.14  root      995:        interrupt->ChangeINT(this, irq);
1.1.1.7   root      996: }
                    997: 
                    998: // 割り込みアクノリッジ
1.1.1.15! root      999: busdata
1.1.1.7   root     1000: MFPDevice::InterruptAcknowledge()
                   1001: {
1.1.1.15! root     1002:        busdata data;
        !          1003: 
        !          1004:        // IPR が誰も立ってなければ、無視するっぽい?
        !          1005:        // 実際には MFP がバスエラーを出しているのではなく、MFP は俺知らない
        !          1006:        // と思って放置してると上位回路 (たぶん SAKI ちゃん) がタイムアウトして
        !          1007:        // MPU にバスエラー応答する。
1.1.1.7   root     1008:        uint32 pending = mfp.ipr.w;
1.1.1.15! root     1009:        if (__predict_false(pending == 0)) {
        !          1010:                data.SetBusErr();
        !          1011:        } else {
        !          1012:                // ch はこの時点で IPR に立ってる一番優先度の高いチャンネルのビット
        !          1013:                int ch = 31 - __builtin_clz(pending);
        !          1014:                uint b = (1U << ch);
1.1.1.7   root     1015: 
1.1.1.15! root     1016:                // MPU にベクタを引き渡したので Pending をクリア
        !          1017:                mfp.ipr.w &= ~b;
        !          1018:                ChangeInterrupt();
1.1.1.7   root     1019: 
1.1.1.15! root     1020:                // ソフトウェア EOI なら In Service を立てる
        !          1021:                if (mfp.vr_s) {
        !          1022:                        mfp.isr.w |= b;
        !          1023:                }
1.1.1.7   root     1024: 
1.1.1.15! root     1025:                data = mfp.vr_vec + ch;
1.1.1.7   root     1026:        }
                   1027: 
1.1.1.15! root     1028:        // /IEI ネゲート時の /IACK と /IEI の関係がいまいち分からないけど、
        !          1029:        // とりあえず /IACK がアサートされてから 3 MFP クロック後に
        !          1030:        // データバスにベクタを供給、次の 1 MFP クロックで DTACK 応答。
        !          1031:        // で次の 1 MFP クロック以内に CPU が /IACK を下げるとして、
        !          1032:        // 計 5 MFP クロック (= 1.25_usec) としておく。
        !          1033:        const busdata intack_wait = busdata::Wait(5 * 250_nsec);
        !          1034:        data |= intack_wait;
        !          1035: 
        !          1036:        return data;
1.1.1.4   root     1037: }

unix.superglobalmegacorp.com

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