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

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

unix.superglobalmegacorp.com

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