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

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

unix.superglobalmegacorp.com

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