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

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

unix.superglobalmegacorp.com

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