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

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
1.1.1.6   root        7: //
                      8: // 割り込みコントローラ
                      9: //
                     10: 
                     11: // IODevice
                     12: //    |
                     13: //    |  +-----------------+
                     14: //    +--| InterruptDevice | (割り込みコントローラの共通部)
                     15: //       +-----------------+
                     16: //          |  +-----------------+
                     17: //          +--| M680x0Interrupt | (m68k 割り込みコントローラの共通部)
                     18: //          |  +-----------------+
                     19: //          |     |
                     20: //          |     |  +-----------------+
                     21: //          |     +--| X68030Interrupt | (X68030 の割り込みコントローラ)
                     22: //          |     |  +-----------------+
                     23: //          |     |
                     24: //          |     |  +---------------+
                     25: //          |     +--| LunaInterrupt |   (LUNA-I の割り込みコントローラ)
1.1.1.9   root       26: //          |     |  +---------------+
                     27: //          |     |
                     28: //          |     |  +---------------+
                     29: //          |     +--| NewsInterrupt |   (NEWS の割り込みコントローラ)
                     30: //          |     |  +---------------+
                     31: //          |     |
                     32: //          |     |  +------------------+
1.1.1.10  root       33: //          |     +--| Virt68kInterrupt | (virt-m68k の割り込みコントローラ)
1.1.1.9   root       34: //          |        +------------------+
1.1.1.6   root       35: //          |
                     36: //          +-- PEDECDevice   (X68030 の Lv1 担当コントローラ)
1.1.1.7   root       37: //          +-- SysCtlrDevice (LUNA-88K の割り込みコントローラ)
1.1.1.10  root       38: //          +-- GFPICDevice   (virt-m68k の各レベル担当コントローラ)
1.1.1.6   root       39: 
1.1       root       40: #include "interrupt.h"
                     41: #include "dmac.h"
1.1.1.9   root       42: #include "goldfish_pic.h"
1.1       root       43: #include "lance.h"
                     44: #include "pedec.h"
1.1.1.11  root       45: #include "m680x0.h"
1.1       root       46: #include "mfp.h"
1.1.1.11  root       47: #include "monitor.h"
1.1       root       48: #include "mpu680x0.h"
1.1.1.7   root       49: #include "newsctlr.h"
1.1.1.6   root       50: #include "nmi.h"
1.1.1.8   root       51: #include "rtl8019as.h"
1.1       root       52: #include "scc.h"
                     53: #include "sio.h"
                     54: #include "spc.h"
                     55: #include "sysclk.h"
                     56: 
                     57: //
1.1.1.9   root       58: // 割り込みコントローラ (共通部)
1.1       root       59: //
                     60: 
1.1.1.7   root       61: // コンストラクタ(オブジェクト名指定なし)
                     62: InterruptDevice::InterruptDevice()
                     63:        : InterruptDevice(OBJ_INTERRUPT)        // 移譲
1.1.1.4   root       64: {
                     65: }
                     66: 
1.1.1.7   root       67: // コンストラクタ(オブジェクト名指定あり)
1.1.1.10  root       68: InterruptDevice::InterruptDevice(uint objid_)
1.1.1.7   root       69:        : inherited(objid_)
1.1       root       70: {
                     71: }
                     72: 
                     73: // デストラクタ
                     74: InterruptDevice::~InterruptDevice()
                     75: {
                     76: }
                     77: 
1.1.1.5   root       78: // リセット
                     79: void
1.1.1.6   root       80: InterruptDevice::ResetHard(bool poweron)
1.1.1.5   root       81: {
                     82:        memset(&counter, 0, sizeof(counter));
                     83: }
                     84: 
1.1.1.9   root       85: // 子デバイスを登録する。
                     86: void
                     87: InterruptDevice::RegistINT(uint32 intmap_, const char *name_, Device *source_)
                     88: {
                     89:        for (const auto& m : intmap_list) {
                     90:                assertmsg(m.intmap != intmap_,
                     91:                        "intmap=%08x already registered", intmap_);
                     92:                if (source_ != NULL) {
                     93:                        assertmsg(m.source != source_,
                     94:                                "source=%p already registered", source_);
                     95:                }
                     96:        }
                     97:        intmap_list.emplace_back(intmap_, name_, source_);
                     98: 
                     99:        // 登録された intmap の和
                    100:        intmap_avail |= intmap_;
                    101: }
                    102: 
                    103: // デバイスから Intmap 値を引く
                    104: uint32
                    105: InterruptDevice::GetIntmap(const Device *source) const
                    106: {
                    107:        for (const auto& m : intmap_list) {
                    108:                if (m.source == source) {
                    109:                        return m.intmap;
                    110:                }
                    111:        }
                    112: 
                    113:        VMPANIC("Unknown interrupt source?");
                    114: }
                    115: 
                    116: // Intmap 値から名前を引く
                    117: const char *
                    118: InterruptDevice::GetIntName(uint32 intmap_) const
                    119: {
                    120:        for (const auto& m : intmap_list) {
                    121:                if (m.intmap == intmap_) {
                    122:                        return m.name;
                    123:                }
                    124:        }
                    125: 
                    126:        return "???";
                    127: }
                    128: 
1.1.1.5   root      129: // 子デバイスが割り込み信号線をアサートした
                    130: void
                    131: InterruptDevice::AssertINT(Device *source)
                    132: {
                    133:        uint32 oldmap;
                    134:        uint32 srcmap;
                    135: 
1.1.1.9   root      136:        oldmap = intmap_status;
1.1.1.5   root      137:        srcmap = GetIntmap(source);
1.1.1.9   root      138:        intmap_status |= srcmap;
1.1.1.5   root      139: 
1.1.1.9   root      140:        if ((oldmap ^ intmap_status) != 0) {
1.1.1.5   root      141:                // 立ち上がりエッジでカウント
                    142:                counter[__builtin_clz(srcmap)]++;
                    143:                ChangeInterrupt();
                    144:        }
                    145: }
                    146: 
                    147: // 子デバイスが割り込み信号線をネゲートした
                    148: void
                    149: InterruptDevice::NegateINT(Device *source)
                    150: {
                    151:        uint32 oldmap;
                    152:        uint32 srcmap;
                    153: 
1.1.1.9   root      154:        oldmap = intmap_status;
1.1.1.5   root      155:        srcmap = GetIntmap(source);
1.1.1.9   root      156:        intmap_status &= ~srcmap;
1.1.1.5   root      157: 
1.1.1.9   root      158:        if ((oldmap ^ intmap_status) != 0) {
1.1.1.5   root      159:                ChangeInterrupt();
                    160:        }
                    161: }
1.1       root      162: 
1.1.1.8   root      163: // 割り込み信号線の状態を取得
                    164: bool
                    165: InterruptDevice::GetINT(const Device *source) const
                    166: {
                    167:        uint32 srcmap;
                    168: 
                    169:        srcmap = GetIntmap(source);
                    170: 
1.1.1.9   root      171:        return (intmap_status & srcmap);
1.1.1.8   root      172: }
                    173: 
                    174: 
1.1       root      175: //
                    176: // 仮想割り込みコントローラ (m680x0 共通部)
                    177: //
                    178: 
                    179: // コンストラクタ
                    180: M680x0Interrupt::M680x0Interrupt()
                    181: {
1.1.1.9   root      182:        intmap_status = IntmapSentinel;
                    183:        // m680x0 仮想割り込みコントローラにはマスクがないので使わない。
                    184:        // 念のためそれっぽい値を入れておく。
                    185:        intmap_enable = 0xfffffff0;
1.1       root      186: }
                    187: 
                    188: // デストラクタ
                    189: M680x0Interrupt::~M680x0Interrupt()
                    190: {
                    191: }
                    192: 
1.1.1.7   root      193: // 初期化
                    194: bool
                    195: M680x0Interrupt::Init()
                    196: {
1.1.1.9   root      197:        mpu680x0 = GetMPU680x0Device(mpu);
                    198: 
1.1.1.7   root      199:        return true;
                    200: }
                    201: 
1.1       root      202: void
1.1.1.5   root      203: M680x0Interrupt::ChangeInterrupt()
1.1       root      204: {
1.1.1.10  root      205:        uint newipl;
1.1       root      206: 
1.1.1.9   root      207:        // intmap_status は最下位ビットを常に立ててあるので 0 にならない
                    208:        newipl = (uint)(31 - __builtin_clz(intmap_status)) / 4;
1.1       root      209: 
1.1.1.5   root      210:        // 割り込みレベルが変わったら、新しいレベルを通知
                    211:        if (newipl != ipl) {
1.1       root      212:                ipl = newipl;
1.1.1.7   root      213:                mpu->Interrupt(ipl);
1.1       root      214:        }
                    215: }
                    216: 
                    217: 
                    218: //
                    219: // X68030 仮想割り込みコントローラ
                    220: //
                    221: 
                    222: // コンストラクタ
                    223: X68030Interrupt::X68030Interrupt()
                    224: {
1.1.1.11  root      225:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
1.1.1.14! root      226:        monitor->SetCallback(&X68030Interrupt::MonitorScreen);
1.1       root      227: }
                    228: 
                    229: // デストラクタ
                    230: X68030Interrupt::~X68030Interrupt()
                    231: {
                    232: }
                    233: 
1.1.1.7   root      234: // 初期化
                    235: bool
                    236: X68030Interrupt::Init()
                    237: {
                    238:        if (inherited::Init() == false) {
                    239:                return false;
                    240:        }
                    241: 
                    242:        dmac = GetDMACDevice();
                    243:        mfp = GetMFPDevice();
                    244:        nmi = GetNMIDevice();
                    245:        pedec = GetPEDECDevice();
                    246:        scc = GetSCCDevice();
1.1.1.9   root      247:        for (int i = 0; i < 2; i++) {
                    248:                net[i] = gMainApp.FindObject<RTL8019ASDevice>(OBJ_ETHERNET(i));
1.1       root      249:        }
1.1.1.9   root      250: 
                    251:        // 検索順
                    252:        RegistINT(IntmapMFP,    "MFP",          mfp);
                    253:        RegistINT(IntmapDMAC,   "DMAC",         dmac);
                    254:        RegistINT(IntmapPEDEC,  "PEDEC",        pedec);
                    255:        RegistINT(IntmapSCC,    "SCC",          scc);
                    256:        if (net[0]) {
                    257:                RegistINT(IntmapNereid0,"Nereid0",      net[0]);
                    258:        }
                    259:        if (net[1]) {
                    260:                RegistINT(IntmapNereid1,"Nereid1",      net[1]);
                    261:        }
                    262:        RegistINT(IntmapNMI,    "NMI",          nmi);
                    263: 
                    264:        // 表示順
                    265:        // XXX const uint32 がそのまま push_back() 出来ないようだ
                    266:        disp_list.clear();
                    267:        disp_list.push_back((uint32)IntmapNMI);
                    268:        disp_list.push_back((uint32)IntmapMFP);
                    269:        disp_list.push_back((uint32)IntmapSCC);
                    270:        if (net[0]) {
                    271:                disp_list.push_back((uint32)IntmapNereid0);
1.1       root      272:        }
1.1.1.9   root      273:        if (net[1]) {
                    274:                disp_list.push_back((uint32)IntmapNereid1);
1.1       root      275:        }
1.1.1.9   root      276:        disp_list.push_back((uint32)IntmapDMAC);
                    277:        disp_list.push_back((uint32)IntmapPEDEC);
                    278: 
                    279:        // 行数が確定したのでサイズ設定
1.1.1.11  root      280:        monitor->SetSize(41, 1 + disp_list.size() + 5/*PEDEC*/);
1.1.1.9   root      281: 
                    282:        return true;
1.1       root      283: }
                    284: 
                    285: // 割り込みアクノリッジに応答する
1.1.1.9   root      286: busdata
1.1       root      287: X68030Interrupt::InterruptAcknowledge(int lv)
                    288: {
                    289:        switch (lv) {
1.1.1.6   root      290:         case 7:
                    291:                return AutoVector;
                    292: 
1.1       root      293:         case 6:
1.1.1.7   root      294:                return mfp->InterruptAcknowledge();
1.1       root      295: 
                    296:         case 5:
1.1.1.7   root      297:                return scc->InterruptAcknowledge();
1.1       root      298: 
1.1.1.8   root      299:         case 4:
1.1.1.9   root      300:                if ((intmap_status & IntmapNereid0)) {
                    301:                        return net[0]->InterruptAcknowledge();
                    302:                }
                    303:                if ((intmap_status & IntmapNereid1)) {
                    304:                        return net[1]->InterruptAcknowledge();
1.1.1.8   root      305:                }
                    306:                break;
                    307: 
1.1       root      308:         case 3:
1.1.1.7   root      309:                return dmac->InterruptAcknowledge();
1.1       root      310: 
                    311:         case 1:
1.1.1.7   root      312:                return pedec->InterruptAcknowledge(lv);
1.1       root      313: 
                    314:         default:
                    315:                break;
                    316:        }
1.1.1.9   root      317: 
1.1.1.10  root      318:        return BusData::BusErr;
1.1       root      319: }
                    320: 
                    321: void
1.1.1.14! root      322: X68030Interrupt::MonitorScreen(Monitor *, TextScreen& screen)
1.1       root      323: {
                    324:        int y;
                    325: 
                    326:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
1.1.1.7   root      327:        uint intr_mask = mpu680x0->reg.intr_mask;
1.1       root      328: 
1.1.1.4   root      329:        screen.Clear();
1.1       root      330: 
1.1.1.7   root      331:        // 0         1         2         3         4
                    332:        // 01234567890123456789012345678901234567890
1.1.1.8   root      333:        // Lv Device  IM=7                     Count
                    334:        // 1  Nereid0     01234567890123456789012345
                    335:        //     SPC    Mask
1.1.1.7   root      336: 
1.1       root      337:        y = 0;
1.1.1.10  root      338:        screen.Print(0, y, "Lv Device  IM=%u", intr_mask);
1.1.1.8   root      339:        screen.Puts(36, y, "Count");
1.1.1.7   root      340:        y++;
1.1.1.9   root      341:        for (uint32 map : disp_list) {
1.1       root      342:                int clz = __builtin_clz(map);
                    343:                int lv = (31 - clz) / 4;
1.1.1.10  root      344:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      345:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.6   root      346:                if (lv <= intr_mask) {
1.1.1.8   root      347:                        screen.Puts(11, y, "Mask");
1.1       root      348:                }
1.1.1.8   root      349:                screen.Print(15, y, "%26s", format_number(counter[clz]).c_str());
1.1       root      350:                y++;
                    351:        }
1.1.1.2   root      352: 
1.1.1.5   root      353:        // PEDEC 分も一緒に表示したい
1.1.1.14! root      354:        pedec->MonitorScreen(screen, intr_mask, y);
1.1       root      355: }
                    356: 
1.1.1.6   root      357: 
1.1       root      358: //
                    359: // LUNA-I 仮想割り込みコントローラ
                    360: //
                    361: 
                    362: // コンストラクタ
                    363: LunaInterrupt::LunaInterrupt()
                    364: {
1.1.1.11  root      365:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
1.1.1.14! root      366:        monitor->SetCallback(&LunaInterrupt::MonitorScreen);
1.1       root      367: }
                    368: 
                    369: // デストラクタ
                    370: LunaInterrupt::~LunaInterrupt()
                    371: {
                    372: }
                    373: 
1.1.1.7   root      374: // 初期化
                    375: bool
                    376: LunaInterrupt::Init()
                    377: {
                    378:        if (inherited::Init() == false) {
                    379:                return false;
                    380:        }
                    381: 
1.1.1.9   root      382:        // 検索順
                    383:        RegistINT(IntmapSysClk, "Clock",        GetSysClkDevice());
                    384:        RegistINT(IntmapSPC,    "SPC",          GetSPCDevice());
                    385:        RegistINT(IntmapSIO,    "SIO",          GetSIODevice());
                    386:        RegistINT(IntmapLance,  "Lance",        GetLanceDevice());
                    387:        RegistINT(IntmapXPHigh, "XP(Hi)",       DEVICE_XPINT_HIGH);
                    388:        RegistINT(IntmapXPLow,  "XP(Lo)",       DEVICE_XPINT_LOW);
                    389:        RegistINT(IntmapNMI,    "NMI",          GetNMIDevice());
                    390: 
                    391:        // 表示順
                    392:        disp_list = {
                    393:                IntmapNMI,
                    394:                IntmapSIO,
                    395:                IntmapSysClk,
                    396:                IntmapXPHigh,
                    397:                IntmapLance,
                    398:                IntmapSPC,
                    399:                IntmapXPLow,
                    400:        };
1.1.1.7   root      401: 
1.1.1.9   root      402:        // 行数が確定したのでサイズ設定
1.1.1.11  root      403:        monitor->SetSize(40, 1 + disp_list.size());
1.1.1.7   root      404: 
1.1.1.9   root      405:        return true;
1.1       root      406: }
                    407: 
                    408: // 割り込みアクノリッジに応答する
1.1.1.9   root      409: busdata
1.1       root      410: LunaInterrupt::InterruptAcknowledge(int lv)
                    411: {
                    412:        // LUNA は全てオートベクタ
                    413:        return AutoVector;
                    414: }
                    415: 
                    416: void
1.1.1.14! root      417: LunaInterrupt::MonitorScreen(Monitor *, TextScreen& screen)
1.1       root      418: {
                    419:        int y;
1.1.1.7   root      420: 
                    421:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
                    422:        uint intr_mask = mpu680x0->reg.intr_mask;
                    423: 
                    424:        screen.Clear();
                    425: 
                    426:        // 0         1         2         3         4
                    427:        // 01234567890123456789012345678901234567890
                    428:        // Lv Device IM=7                     Count
                    429:        // 1  XP(Hi) Mask01234567890123456789012345
                    430: 
                    431:        y = 0;
1.1.1.10  root      432:        screen.Print(0, y, "Lv Device IM=%u", intr_mask);
1.1.1.7   root      433:        screen.Puts(35, y, "Count");
                    434:        y++;
1.1.1.9   root      435:        for (uint32 map : disp_list) {
1.1.1.7   root      436:                int clz = __builtin_clz(map);
                    437:                int lv = (31 - clz) / 4;
1.1.1.10  root      438:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      439:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.7   root      440:                if (lv <= intr_mask) {
                    441:                        screen.Puts(10, y, "Mask");
                    442:                }
                    443:                screen.Print(14, y, "%26s", format_number(counter[clz]).c_str());
                    444:                y++;
                    445:        }
                    446: }
                    447: 
                    448: 
                    449: //
                    450: // NEWS 仮想割り込みコントローラ
                    451: //
                    452: 
                    453: // コンストラクタ
                    454: NewsInterrupt::NewsInterrupt()
                    455: {
1.1.1.11  root      456:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
1.1.1.14! root      457:        monitor->SetCallback(&NewsInterrupt::MonitorScreen);
1.1.1.7   root      458: }
                    459: 
                    460: // デストラクタ
                    461: NewsInterrupt::~NewsInterrupt()
                    462: {
                    463: }
                    464: 
                    465: // 初期化
                    466: bool
                    467: NewsInterrupt::Init()
                    468: {
                    469:        if (inherited::Init() == false) {
                    470:                return false;
                    471:        }
                    472: 
1.1.1.9   root      473:        // 割り込みアクノリッジで使う
1.1.1.7   root      474:        scc = GetSCCDevice();
                    475: 
1.1.1.9   root      476:        // 検索順
                    477:        RegistINT(IntmapTimer,  "Timer",        GetNewsCtlrDevice());
                    478:        RegistINT(IntmapLance,  "Lance",        GetLanceDevice());
                    479:        RegistINT(IntmapSCC,    "SCC",          scc);
                    480: 
                    481:        // 表示順
                    482:        disp_list = {
                    483:                IntmapTimer,
                    484:                IntmapSCC,
                    485:                IntmapLance,
                    486:        };
1.1.1.7   root      487: 
1.1.1.9   root      488:        // 行数が確定したのでサイズ設定
1.1.1.11  root      489:        monitor->SetSize(40, 1 + disp_list.size());
1.1.1.9   root      490: 
                    491:        return true;
1.1.1.7   root      492: }
                    493: 
                    494: // 割り込みアクノリッジに応答する
1.1.1.9   root      495: busdata
1.1.1.7   root      496: NewsInterrupt::InterruptAcknowledge(int lv)
                    497: {
                    498:        // NEWS では 5 の SCC だけベクタで、他はオートベクタ?
                    499:        switch (lv) {
                    500:         case 5:
                    501:                return scc->InterruptAcknowledge();
                    502: 
                    503:         default:
                    504:                return AutoVector;
                    505:        }
                    506: }
                    507: 
                    508: // ステータスバイトを読み出す。NewsCtlr から呼ばれる。
                    509: uint8
                    510: NewsInterrupt::PeekStatus() const
                    511: {
                    512:        uint8 data = 0;
                    513: 
1.1.1.9   root      514:        if ((intmap_status & IntmapSIC)) {
1.1.1.7   root      515:                data |= 0x80;
                    516:        }
1.1.1.9   root      517:        if ((intmap_status & IntmapLance)) {
1.1.1.7   root      518:                data |= 0x04;
                    519:        }
                    520: 
                    521:        return data;
                    522: }
                    523: 
                    524: void
1.1.1.14! root      525: NewsInterrupt::MonitorScreen(Monitor *, TextScreen& screen)
1.1.1.7   root      526: {
                    527:        int y;
1.1       root      528: 
                    529:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
1.1.1.7   root      530:        uint intr_mask = mpu680x0->reg.intr_mask;
1.1       root      531: 
1.1.1.4   root      532:        screen.Clear();
1.1       root      533: 
1.1.1.7   root      534:        // 0         1         2         3         4
                    535:        // 01234567890123456789012345678901234567890
                    536:        // Lv Device IM=7                     Count
                    537:        // 1  XP(Hi) Mask01234567890123456789012345
                    538: 
1.1       root      539:        y = 0;
1.1.1.10  root      540:        screen.Print(0, y, "Lv Device IM=%u", intr_mask);
1.1.1.7   root      541:        screen.Puts(35, y, "Count");
                    542:        y++;
1.1.1.9   root      543:        for (uint32 map : disp_list) {
1.1       root      544:                int clz = __builtin_clz(map);
                    545:                int lv = (31 - clz) / 4;
1.1.1.10  root      546:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      547:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.6   root      548:                if (lv <= intr_mask) {
1.1.1.7   root      549:                        screen.Puts(10, y, "Mask");
1.1       root      550:                }
1.1.1.7   root      551:                screen.Print(14, y, "%26s", format_number(counter[clz]).c_str());
1.1       root      552:                y++;
                    553:        }
                    554: }
1.1.1.9   root      555: 
                    556: 
                    557: //
1.1.1.10  root      558: // virt-m68k 仮想割り込みコントローラ
1.1.1.9   root      559: //
                    560: 
                    561: // コンストラクタ
                    562: Virt68kInterrupt::Virt68kInterrupt()
                    563: {
1.1.1.11  root      564:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
1.1.1.14! root      565:        monitor->SetCallback(&Virt68kInterrupt::MonitorScreen);
1.1.1.9   root      566: }
                    567: 
                    568: // デストラクタ
                    569: Virt68kInterrupt::~Virt68kInterrupt()
                    570: {
                    571: }
                    572: 
                    573: // 初期化
                    574: bool
                    575: Virt68kInterrupt::Init()
                    576: {
                    577:        if (inherited::Init() == false) {
                    578:                return false;
                    579:        }
                    580: 
                    581:        // [0] は無視。
                    582:        gfpic[6] = GetGFPICDevice(6);
                    583:        gfpic[5] = GetGFPICDevice(5);
                    584:        gfpic[4] = GetGFPICDevice(4);
                    585:        gfpic[3] = GetGFPICDevice(3);
                    586:        gfpic[2] = GetGFPICDevice(2);
                    587:        gfpic[1] = GetGFPICDevice(1);
                    588: 
                    589:        // 検索順
                    590:        RegistINT(IntmapGFPIC6, "GFPIC6",       gfpic[6]);
                    591:        RegistINT(IntmapGFPIC5, "GFPIC5",       gfpic[5]);
                    592:        RegistINT(IntmapGFPIC4, "GFPIC4",       gfpic[4]);
                    593:        RegistINT(IntmapGFPIC3, "GFPIC3",       gfpic[3]);
                    594:        RegistINT(IntmapGFPIC2, "GFPIC2",       gfpic[2]);
                    595:        RegistINT(IntmapGFPIC1, "GFPIC1",       gfpic[1]);
                    596: 
                    597:        // 表示順
                    598:        disp_list = {
                    599:                IntmapGFPIC6,
                    600:                IntmapGFPIC5,
                    601:                IntmapGFPIC4,
                    602:                IntmapGFPIC3,
                    603:                IntmapGFPIC2,
                    604:                IntmapGFPIC1,
                    605:        };
                    606: 
                    607:        // ここまでの行数でサイズ設定。
                    608:        // この後各割り込みソースの Init() から GFPIC への RegistIRQ() する
                    609:        // たびに増やされていく。
1.1.1.11  root      610:        monitor->SetSize(77, 2 + disp_list.size() + 1);
1.1.1.9   root      611: 
                    612:        return true;
                    613: }
                    614: 
                    615: void
                    616: Virt68kInterrupt::IncMonitorHeight()
                    617: {
1.1.1.13  root      618:        monitor->AddHeight(1);
1.1.1.9   root      619: }
                    620: 
                    621: // 割り込みアクノリッジに応答する
                    622: busdata
                    623: Virt68kInterrupt::InterruptAcknowledge(int lv)
                    624: {
                    625:        // ?
                    626:        return AutoVector;
                    627: }
                    628: 
                    629: void
1.1.1.14! root      630: Virt68kInterrupt::MonitorScreen(Monitor *, TextScreen& screen)
1.1.1.9   root      631: {
                    632:        int y;
                    633: 
                    634:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
                    635:        uint intr_mask = mpu680x0->reg.intr_mask;
                    636:        // 各 PIC の状況も一緒に表示したい。picmap の添字はレベル(1-6)
                    637:        std::array<uint32, 7> picmap;
                    638:        for (int lv = 1; lv < picmap.size(); lv++) {
                    639:                picmap[lv] = gfpic[lv]->intmap_status;
                    640:        }
                    641: 
                    642:        screen.Clear();
                    643: 
                    644: // 0         1         2         3         4         5         6         7
                    645: // 01234567890123456789012345678901234567890123456789012345678901234567890123456
                    646: // Lv Device IM=7 IRQ         20         10         1                      Count
                    647: // 1  GFPIC1 Mask 21098765 43210987 65432109 87654321 01234567890123456789012345
                    648: //                E:Enable  D:Disable  .:NotConnected
                    649: 
                    650:        y = 0;
1.1.1.10  root      651:        screen.Print(0, y, "Lv Device IM=%u IRQ         20         10         1",
1.1.1.9   root      652:                intr_mask);
                    653:        screen.Puts(72, y, "Count");
                    654:        y++;
                    655:        for (uint32 map : disp_list) {
1.1.1.10  root      656:                uint clz = __builtin_clz(map);
                    657:                uint lv = (uint)(31 - clz) / 4;
                    658:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      659:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
                    660:                if (lv <= intr_mask) {
                    661:                        screen.Puts(10, y, "Mask");
                    662:                }
                    663: 
                    664:                // 各入力ピンの状態も表示しないと何も分からない。
1.1.1.14! root      665:                gfpic[lv]->MonitorScreenSummary(screen, 15, y);
1.1.1.9   root      666: 
                    667:                screen.Print(51, y, "%26s", format_number(counter[clz]).c_str());
                    668:                y++;
                    669:        }
                    670:        screen.Puts(15, y, "E:Enable  D:Disable  .:NotConnected");
                    671:        y++;
                    672:        y++;
                    673: 
                    674:        for (uint32 map : disp_list) {
                    675:                int clz = __builtin_clz(map);
                    676:                int lv = (31 - clz) / 4;
1.1.1.14! root      677:                y = gfpic[lv]->MonitorScreenDetail(screen, y, lv);
1.1.1.9   root      678:        }
                    679: }

unix.superglobalmegacorp.com

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