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

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

unix.superglobalmegacorp.com

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