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

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

unix.superglobalmegacorp.com

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