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

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

unix.superglobalmegacorp.com

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