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

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: {
                    197:        if (inherited::Init() == false) {
                    198:                return false;
                    199:        }
                    200: 
1.1.1.9   root      201:        mpu680x0 = GetMPU680x0Device(mpu);
                    202: 
1.1.1.7   root      203:        return true;
                    204: }
                    205: 
1.1       root      206: // リセット
                    207: void
1.1.1.6   root      208: M680x0Interrupt::ResetHard(bool poweron)
1.1       root      209: {
1.1.1.6   root      210:        inherited::ResetHard(poweron);
1.1       root      211: }
                    212: 
                    213: void
1.1.1.5   root      214: M680x0Interrupt::ChangeInterrupt()
1.1       root      215: {
1.1.1.10  root      216:        uint newipl;
1.1       root      217: 
1.1.1.9   root      218:        // intmap_status は最下位ビットを常に立ててあるので 0 にならない
                    219:        newipl = (uint)(31 - __builtin_clz(intmap_status)) / 4;
1.1       root      220: 
1.1.1.5   root      221:        // 割り込みレベルが変わったら、新しいレベルを通知
                    222:        if (newipl != ipl) {
1.1       root      223:                ipl = newipl;
1.1.1.7   root      224:                mpu->Interrupt(ipl);
1.1       root      225:        }
                    226: }
                    227: 
                    228: 
                    229: //
                    230: // X68030 仮想割り込みコントローラ
                    231: //
                    232: 
                    233: // コンストラクタ
                    234: X68030Interrupt::X68030Interrupt()
                    235: {
1.1.1.11! root      236:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
        !           237:        monitor->func = ToMonitorCallback(&X68030Interrupt::MonitorUpdate);
1.1       root      238: }
                    239: 
                    240: // デストラクタ
                    241: X68030Interrupt::~X68030Interrupt()
                    242: {
                    243: }
                    244: 
1.1.1.7   root      245: // 初期化
                    246: bool
                    247: X68030Interrupt::Init()
                    248: {
                    249:        if (inherited::Init() == false) {
                    250:                return false;
                    251:        }
                    252: 
                    253:        dmac = GetDMACDevice();
                    254:        mfp = GetMFPDevice();
                    255:        nmi = GetNMIDevice();
                    256:        pedec = GetPEDECDevice();
                    257:        scc = GetSCCDevice();
1.1.1.9   root      258:        for (int i = 0; i < 2; i++) {
                    259:                net[i] = gMainApp.FindObject<RTL8019ASDevice>(OBJ_ETHERNET(i));
1.1       root      260:        }
1.1.1.9   root      261: 
                    262:        // 検索順
                    263:        RegistINT(IntmapMFP,    "MFP",          mfp);
                    264:        RegistINT(IntmapDMAC,   "DMAC",         dmac);
                    265:        RegistINT(IntmapPEDEC,  "PEDEC",        pedec);
                    266:        RegistINT(IntmapSCC,    "SCC",          scc);
                    267:        if (net[0]) {
                    268:                RegistINT(IntmapNereid0,"Nereid0",      net[0]);
                    269:        }
                    270:        if (net[1]) {
                    271:                RegistINT(IntmapNereid1,"Nereid1",      net[1]);
                    272:        }
                    273:        RegistINT(IntmapNMI,    "NMI",          nmi);
                    274: 
                    275:        // 表示順
                    276:        // XXX const uint32 がそのまま push_back() 出来ないようだ
                    277:        disp_list.clear();
                    278:        disp_list.push_back((uint32)IntmapNMI);
                    279:        disp_list.push_back((uint32)IntmapMFP);
                    280:        disp_list.push_back((uint32)IntmapSCC);
                    281:        if (net[0]) {
                    282:                disp_list.push_back((uint32)IntmapNereid0);
1.1       root      283:        }
1.1.1.9   root      284:        if (net[1]) {
                    285:                disp_list.push_back((uint32)IntmapNereid1);
1.1       root      286:        }
1.1.1.9   root      287:        disp_list.push_back((uint32)IntmapDMAC);
                    288:        disp_list.push_back((uint32)IntmapPEDEC);
                    289: 
                    290:        // 行数が確定したのでサイズ設定
1.1.1.11! root      291:        monitor->SetSize(41, 1 + disp_list.size() + 5/*PEDEC*/);
1.1.1.9   root      292: 
                    293:        return true;
1.1       root      294: }
                    295: 
                    296: // 割り込みアクノリッジに応答する
1.1.1.9   root      297: busdata
1.1       root      298: X68030Interrupt::InterruptAcknowledge(int lv)
                    299: {
                    300:        switch (lv) {
1.1.1.6   root      301:         case 7:
                    302:                return AutoVector;
                    303: 
1.1       root      304:         case 6:
1.1.1.7   root      305:                return mfp->InterruptAcknowledge();
1.1       root      306: 
                    307:         case 5:
1.1.1.7   root      308:                return scc->InterruptAcknowledge();
1.1       root      309: 
1.1.1.8   root      310:         case 4:
1.1.1.9   root      311:                if ((intmap_status & IntmapNereid0)) {
                    312:                        return net[0]->InterruptAcknowledge();
                    313:                }
                    314:                if ((intmap_status & IntmapNereid1)) {
                    315:                        return net[1]->InterruptAcknowledge();
1.1.1.8   root      316:                }
                    317:                break;
                    318: 
1.1       root      319:         case 3:
1.1.1.7   root      320:                return dmac->InterruptAcknowledge();
1.1       root      321: 
                    322:         case 1:
1.1.1.7   root      323:                return pedec->InterruptAcknowledge(lv);
1.1       root      324: 
                    325:         default:
                    326:                break;
                    327:        }
1.1.1.9   root      328: 
1.1.1.10  root      329:        return BusData::BusErr;
1.1       root      330: }
                    331: 
                    332: void
1.1.1.4   root      333: X68030Interrupt::MonitorUpdate(Monitor *, TextScreen& screen)
1.1       root      334: {
                    335:        int y;
                    336: 
                    337:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
1.1.1.7   root      338:        uint intr_mask = mpu680x0->reg.intr_mask;
1.1       root      339: 
1.1.1.4   root      340:        screen.Clear();
1.1       root      341: 
1.1.1.7   root      342:        // 0         1         2         3         4
                    343:        // 01234567890123456789012345678901234567890
1.1.1.8   root      344:        // Lv Device  IM=7                     Count
                    345:        // 1  Nereid0     01234567890123456789012345
                    346:        //     SPC    Mask
1.1.1.7   root      347: 
1.1       root      348:        y = 0;
1.1.1.10  root      349:        screen.Print(0, y, "Lv Device  IM=%u", intr_mask);
1.1.1.8   root      350:        screen.Puts(36, y, "Count");
1.1.1.7   root      351:        y++;
1.1.1.9   root      352:        for (uint32 map : disp_list) {
1.1       root      353:                int clz = __builtin_clz(map);
                    354:                int lv = (31 - clz) / 4;
1.1.1.10  root      355:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      356:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.6   root      357:                if (lv <= intr_mask) {
1.1.1.8   root      358:                        screen.Puts(11, y, "Mask");
1.1       root      359:                }
1.1.1.8   root      360:                screen.Print(15, y, "%26s", format_number(counter[clz]).c_str());
1.1       root      361:                y++;
                    362:        }
1.1.1.2   root      363: 
1.1.1.5   root      364:        // PEDEC 分も一緒に表示したい
1.1.1.7   root      365:        pedec->MonitorUpdate(screen, intr_mask, y);
1.1       root      366: }
                    367: 
1.1.1.6   root      368: 
1.1       root      369: //
                    370: // LUNA-I 仮想割り込みコントローラ
                    371: //
                    372: 
                    373: // コンストラクタ
                    374: LunaInterrupt::LunaInterrupt()
                    375: {
1.1.1.11! root      376:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
        !           377:        monitor->func = ToMonitorCallback(&LunaInterrupt::MonitorUpdate);
1.1       root      378: }
                    379: 
                    380: // デストラクタ
                    381: LunaInterrupt::~LunaInterrupt()
                    382: {
                    383: }
                    384: 
1.1.1.7   root      385: // 初期化
                    386: bool
                    387: LunaInterrupt::Init()
                    388: {
                    389:        if (inherited::Init() == false) {
                    390:                return false;
                    391:        }
                    392: 
1.1.1.9   root      393:        // 検索順
                    394:        RegistINT(IntmapSysClk, "Clock",        GetSysClkDevice());
                    395:        RegistINT(IntmapSPC,    "SPC",          GetSPCDevice());
                    396:        RegistINT(IntmapSIO,    "SIO",          GetSIODevice());
                    397:        RegistINT(IntmapLance,  "Lance",        GetLanceDevice());
                    398:        RegistINT(IntmapXPHigh, "XP(Hi)",       DEVICE_XPINT_HIGH);
                    399:        RegistINT(IntmapXPLow,  "XP(Lo)",       DEVICE_XPINT_LOW);
                    400:        RegistINT(IntmapNMI,    "NMI",          GetNMIDevice());
                    401: 
                    402:        // 表示順
                    403:        disp_list = {
                    404:                IntmapNMI,
                    405:                IntmapSIO,
                    406:                IntmapSysClk,
                    407:                IntmapXPHigh,
                    408:                IntmapLance,
                    409:                IntmapSPC,
                    410:                IntmapXPLow,
                    411:        };
1.1.1.7   root      412: 
1.1.1.9   root      413:        // 行数が確定したのでサイズ設定
1.1.1.11! root      414:        monitor->SetSize(40, 1 + disp_list.size());
1.1.1.7   root      415: 
1.1.1.9   root      416:        return true;
1.1       root      417: }
                    418: 
                    419: // 割り込みアクノリッジに応答する
1.1.1.9   root      420: busdata
1.1       root      421: LunaInterrupt::InterruptAcknowledge(int lv)
                    422: {
                    423:        // LUNA は全てオートベクタ
                    424:        return AutoVector;
                    425: }
                    426: 
                    427: void
1.1.1.4   root      428: LunaInterrupt::MonitorUpdate(Monitor *, TextScreen& screen)
1.1       root      429: {
                    430:        int y;
1.1.1.7   root      431: 
                    432:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
                    433:        uint intr_mask = mpu680x0->reg.intr_mask;
                    434: 
                    435:        screen.Clear();
                    436: 
                    437:        // 0         1         2         3         4
                    438:        // 01234567890123456789012345678901234567890
                    439:        // Lv Device IM=7                     Count
                    440:        // 1  XP(Hi) Mask01234567890123456789012345
                    441: 
                    442:        y = 0;
1.1.1.10  root      443:        screen.Print(0, y, "Lv Device IM=%u", intr_mask);
1.1.1.7   root      444:        screen.Puts(35, y, "Count");
                    445:        y++;
1.1.1.9   root      446:        for (uint32 map : disp_list) {
1.1.1.7   root      447:                int clz = __builtin_clz(map);
                    448:                int lv = (31 - clz) / 4;
1.1.1.10  root      449:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      450:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.7   root      451:                if (lv <= intr_mask) {
                    452:                        screen.Puts(10, y, "Mask");
                    453:                }
                    454:                screen.Print(14, y, "%26s", format_number(counter[clz]).c_str());
                    455:                y++;
                    456:        }
                    457: }
                    458: 
                    459: 
                    460: //
                    461: // NEWS 仮想割り込みコントローラ
                    462: //
                    463: 
                    464: // コンストラクタ
                    465: NewsInterrupt::NewsInterrupt()
                    466: {
1.1.1.11! root      467:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
        !           468:        monitor->func = ToMonitorCallback(&NewsInterrupt::MonitorUpdate);
1.1.1.7   root      469: }
                    470: 
                    471: // デストラクタ
                    472: NewsInterrupt::~NewsInterrupt()
                    473: {
                    474: }
                    475: 
                    476: // 初期化
                    477: bool
                    478: NewsInterrupt::Init()
                    479: {
                    480:        if (inherited::Init() == false) {
                    481:                return false;
                    482:        }
                    483: 
1.1.1.9   root      484:        // 割り込みアクノリッジで使う
1.1.1.7   root      485:        scc = GetSCCDevice();
                    486: 
1.1.1.9   root      487:        // 検索順
                    488:        RegistINT(IntmapTimer,  "Timer",        GetNewsCtlrDevice());
                    489:        RegistINT(IntmapLance,  "Lance",        GetLanceDevice());
                    490:        RegistINT(IntmapSCC,    "SCC",          scc);
                    491: 
                    492:        // 表示順
                    493:        disp_list = {
                    494:                IntmapTimer,
                    495:                IntmapSCC,
                    496:                IntmapLance,
                    497:        };
1.1.1.7   root      498: 
1.1.1.9   root      499:        // 行数が確定したのでサイズ設定
1.1.1.11! root      500:        monitor->SetSize(40, 1 + disp_list.size());
1.1.1.9   root      501: 
                    502:        return true;
1.1.1.7   root      503: }
                    504: 
                    505: // 割り込みアクノリッジに応答する
1.1.1.9   root      506: busdata
1.1.1.7   root      507: NewsInterrupt::InterruptAcknowledge(int lv)
                    508: {
                    509:        // NEWS では 5 の SCC だけベクタで、他はオートベクタ?
                    510:        switch (lv) {
                    511:         case 5:
                    512:                return scc->InterruptAcknowledge();
                    513: 
                    514:         default:
                    515:                return AutoVector;
                    516:        }
                    517: }
                    518: 
                    519: // ステータスバイトを読み出す。NewsCtlr から呼ばれる。
                    520: uint8
                    521: NewsInterrupt::PeekStatus() const
                    522: {
                    523:        uint8 data = 0;
                    524: 
1.1.1.9   root      525:        if ((intmap_status & IntmapSIC)) {
1.1.1.7   root      526:                data |= 0x80;
                    527:        }
1.1.1.9   root      528:        if ((intmap_status & IntmapLance)) {
1.1.1.7   root      529:                data |= 0x04;
                    530:        }
                    531: 
                    532:        return data;
                    533: }
                    534: 
                    535: void
                    536: NewsInterrupt::MonitorUpdate(Monitor *, TextScreen& screen)
                    537: {
                    538:        int y;
1.1       root      539: 
                    540:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
1.1.1.7   root      541:        uint intr_mask = mpu680x0->reg.intr_mask;
1.1       root      542: 
1.1.1.4   root      543:        screen.Clear();
1.1       root      544: 
1.1.1.7   root      545:        // 0         1         2         3         4
                    546:        // 01234567890123456789012345678901234567890
                    547:        // Lv Device IM=7                     Count
                    548:        // 1  XP(Hi) Mask01234567890123456789012345
                    549: 
1.1       root      550:        y = 0;
1.1.1.10  root      551:        screen.Print(0, y, "Lv Device IM=%u", intr_mask);
1.1.1.7   root      552:        screen.Puts(35, y, "Count");
                    553:        y++;
1.1.1.9   root      554:        for (uint32 map : disp_list) {
1.1       root      555:                int clz = __builtin_clz(map);
                    556:                int lv = (31 - clz) / 4;
1.1.1.10  root      557:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      558:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.6   root      559:                if (lv <= intr_mask) {
1.1.1.7   root      560:                        screen.Puts(10, y, "Mask");
1.1       root      561:                }
1.1.1.7   root      562:                screen.Print(14, y, "%26s", format_number(counter[clz]).c_str());
1.1       root      563:                y++;
                    564:        }
                    565: }
1.1.1.9   root      566: 
                    567: 
                    568: //
1.1.1.10  root      569: // virt-m68k 仮想割り込みコントローラ
1.1.1.9   root      570: //
                    571: 
                    572: // コンストラクタ
                    573: Virt68kInterrupt::Virt68kInterrupt()
                    574: {
1.1.1.11! root      575:        monitor = gMonitorManager->Regist(ID_MONITOR_INTERRUPT, this);
        !           576:        monitor->func = ToMonitorCallback(&Virt68kInterrupt::MonitorUpdate);
1.1.1.9   root      577: }
                    578: 
                    579: // デストラクタ
                    580: Virt68kInterrupt::~Virt68kInterrupt()
                    581: {
                    582: }
                    583: 
                    584: // 初期化
                    585: bool
                    586: Virt68kInterrupt::Init()
                    587: {
                    588:        if (inherited::Init() == false) {
                    589:                return false;
                    590:        }
                    591: 
                    592:        // [0] は無視。
                    593:        gfpic[6] = GetGFPICDevice(6);
                    594:        gfpic[5] = GetGFPICDevice(5);
                    595:        gfpic[4] = GetGFPICDevice(4);
                    596:        gfpic[3] = GetGFPICDevice(3);
                    597:        gfpic[2] = GetGFPICDevice(2);
                    598:        gfpic[1] = GetGFPICDevice(1);
                    599: 
                    600:        // 検索順
                    601:        RegistINT(IntmapGFPIC6, "GFPIC6",       gfpic[6]);
                    602:        RegistINT(IntmapGFPIC5, "GFPIC5",       gfpic[5]);
                    603:        RegistINT(IntmapGFPIC4, "GFPIC4",       gfpic[4]);
                    604:        RegistINT(IntmapGFPIC3, "GFPIC3",       gfpic[3]);
                    605:        RegistINT(IntmapGFPIC2, "GFPIC2",       gfpic[2]);
                    606:        RegistINT(IntmapGFPIC1, "GFPIC1",       gfpic[1]);
                    607: 
                    608:        // 表示順
                    609:        disp_list = {
                    610:                IntmapGFPIC6,
                    611:                IntmapGFPIC5,
                    612:                IntmapGFPIC4,
                    613:                IntmapGFPIC3,
                    614:                IntmapGFPIC2,
                    615:                IntmapGFPIC1,
                    616:        };
                    617: 
                    618:        // ここまでの行数でサイズ設定。
                    619:        // この後各割り込みソースの Init() から GFPIC への RegistIRQ() する
                    620:        // たびに増やされていく。
1.1.1.11! root      621:        monitor->SetSize(77, 2 + disp_list.size() + 1);
1.1.1.9   root      622: 
                    623:        return true;
                    624: }
                    625: 
                    626: void
                    627: Virt68kInterrupt::IncMonitorHeight()
                    628: {
1.1.1.11! root      629:        auto size = monitor->GetSize();
        !           630:        monitor->SetSize(size.width, size.height + 1);
1.1.1.9   root      631: }
                    632: 
                    633: // 割り込みアクノリッジに応答する
                    634: busdata
                    635: Virt68kInterrupt::InterruptAcknowledge(int lv)
                    636: {
                    637:        // ?
                    638:        return AutoVector;
                    639: }
                    640: 
                    641: void
                    642: Virt68kInterrupt::MonitorUpdate(Monitor *, TextScreen& screen)
                    643: {
                    644:        int y;
                    645: 
                    646:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
                    647:        uint intr_mask = mpu680x0->reg.intr_mask;
                    648:        // 各 PIC の状況も一緒に表示したい。picmap の添字はレベル(1-6)
                    649:        std::array<uint32, 7> picmap;
                    650:        for (int lv = 1; lv < picmap.size(); lv++) {
                    651:                picmap[lv] = gfpic[lv]->intmap_status;
                    652:        }
                    653: 
                    654:        screen.Clear();
                    655: 
                    656: // 0         1         2         3         4         5         6         7
                    657: // 01234567890123456789012345678901234567890123456789012345678901234567890123456
                    658: // Lv Device IM=7 IRQ         20         10         1                      Count
                    659: // 1  GFPIC1 Mask 21098765 43210987 65432109 87654321 01234567890123456789012345
                    660: //                E:Enable  D:Disable  .:NotConnected
                    661: 
                    662:        y = 0;
1.1.1.10  root      663:        screen.Print(0, y, "Lv Device IM=%u IRQ         20         10         1",
1.1.1.9   root      664:                intr_mask);
                    665:        screen.Puts(72, y, "Count");
                    666:        y++;
                    667:        for (uint32 map : disp_list) {
1.1.1.10  root      668:                uint clz = __builtin_clz(map);
                    669:                uint lv = (uint)(31 - clz) / 4;
                    670:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      671:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
                    672:                if (lv <= intr_mask) {
                    673:                        screen.Puts(10, y, "Mask");
                    674:                }
                    675: 
                    676:                // 各入力ピンの状態も表示しないと何も分からない。
                    677:                gfpic[lv]->MonitorUpdateSummary(screen, 15, y);
                    678: 
                    679:                screen.Print(51, y, "%26s", format_number(counter[clz]).c_str());
                    680:                y++;
                    681:        }
                    682:        screen.Puts(15, y, "E:Enable  D:Disable  .:NotConnected");
                    683:        y++;
                    684:        y++;
                    685: 
                    686:        for (uint32 map : disp_list) {
                    687:                int clz = __builtin_clz(map);
                    688:                int lv = (31 - clz) / 4;
                    689:                y = gfpic[lv]->MonitorUpdateDetail(screen, y, lv);
                    690:        }
                    691: }

unix.superglobalmegacorp.com

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