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

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

unix.superglobalmegacorp.com

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