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

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

unix.superglobalmegacorp.com

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