|
|
1.1 root 1: //
2: // nono
1.1.1.2 ! root 3: // Copyright (C) 2020 nono project
! 4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: // MPU (m88xx0)
8:
9: #include "mpu88xx0.h"
10: #include "config.h"
1.1.1.2 ! root 11: #include "sysctlr.h"
! 12:
! 13: std::unique_ptr<MPU88200ATC> gMPU88200ATC[2];
1.1 root 14:
15: // コンストラクタ
16: MPU88xx0Device::MPU88xx0Device(uint32 addr)
17: {
1.1.1.2 ! root 18: monitor.Init(79, 18);
1.1 root 19:
20: // リセットベクタアドレスは Reset() で指定するので保持しておく
21: reset_vector = addr;
22:
23: cpu.reset(new m88kcpu());
1.1.1.2 ! root 24:
! 25: // LUNA88K では CMMU の ID は次のように割り振ってあるようだ。
! 26: // OpenBSD の sys/arch/luna68k/include/board.h より。
! 27: //
! 28: // Inst Data
! 29: // CPU#0 ID=7 ID=6
! 30: // CPU#1 ID=5 ID=4
! 31: // CPU#2 ID=3 ID=2
! 32: // CPU#3 ID=1 ID=0
! 33: //
! 34: // 厳密にはこれは LUNA88K のハードウェアがどういうコンフィグレーションで
! 35: // m88200 を使うかなので、ここではなくて vm_luna あたりのほうがいいかも
! 36: // しれんけど、あまり遠いのも面倒なので、とりあえずこの辺に。
! 37: // あとマルチプロセッサになったらまたその時考える。
! 38: cpu->cmmu[0].SetID(7);
! 39: cpu->cmmu[1].SetID(6);
! 40:
! 41: // モニタ用の別オブジェクト
! 42: gMPU88200ATC[0].reset(new MPU88200ATC(&cpu->cmmu[0]));
! 43: gMPU88200ATC[1].reset(new MPU88200ATC(&cpu->cmmu[1]));
1.1 root 44: }
45:
46: // デストラクタ
47: MPU88xx0Device::~MPU88xx0Device()
48: {
49: }
50:
51: // リセット
52: // (MPU が動くのはこの後 Scheduler::Run() を発行した後)
53: void
54: MPU88xx0Device::ResetHard()
55: {
56: cpu->Reset(reset_vector);
57: }
58:
1.1.1.2 ! root 59: // Interrupt
! 60: void
! 61: MPU88xx0Device::Interrupt(Object *src, int level)
! 62: {
! 63: // XXX: なぜか 1 レベルずれている?
! 64: level++;
! 65: if (gSysCtlr->GetIntMask(0) & (1 << level)) {
! 66: putlog(1, "Interrupt from %s", src->devname.c_str());
! 67: gSysCtlr->TellIntLevel(0, 1 << level);
! 68: cpu->Interrupt();
! 69: }
! 70: }
! 71:
1.1 root 72: // モニター更新
73: bool
74: MPU88xx0Device::MonitorUpdate()
75: {
76: m88100reg reg;
77: int x;
78: int y;
79:
80: monitor.Clear();
81:
82: // ローカルにコピー
83: reg = *cpu;
84:
85: //
86: for (int i = 0; i < countof(reg.r); i++) {
87: monitor.Print((i / 8) * 14, i % 8, "r%-2d:%08x", i, reg.r[i]);
88: }
89:
90: // 制御レジスタ
91: x = 0;
92: y = 9;
1.1.1.2 ! root 93: monitor.Print(x, y++, "pid (cr0):%08x(Arch=$%02x Ver=$%02x MC=%s)",
1.1 root 94: reg.pid,
95: (reg.pid >> 8) & 0xff,
1.1.1.2 ! root 96: (reg.pid >> 1) & 0x7f,
! 97: (reg.pid & 1) ? "Master" : "Checker");
! 98: monitor.Print(x, y, "psr (cr1):%08x(", reg.psr);
! 99: monitor.Puts(x + 19, y, TA::OnOff(reg.psr & m88100reg::PSR_SUPER), "S");
! 100: monitor.Puts(x + 21, y,
! 101: ((reg.psr & m88100reg::PSR_BO_LE) ? "BO=LE" : "BO=BE"));
! 102: monitor.Puts(x + 27, y, TA::OnOff(reg.psr & m88100reg::PSR_SER), "SER");
! 103: monitor.Puts(x + 31, y, TA::OnOff(reg.psr & m88100reg::PSR_C), "Cy");
! 104: monitor.Puts(x + 34, y, TA::OnOff(reg.psr & m88100reg::PSR_SFD1), "SFD1");
! 105: monitor.Puts(x + 39, y, TA::OnOff(reg.psr & m88100reg::PSR_MXM), "MXM");
! 106: monitor.Puts(x + 43, y, TA::OnOff(reg.psr & m88100reg::PSR_IND), "IND");
! 107: monitor.Puts(x + 47, y, TA::OnOff(reg.psr & m88100reg::PSR_SFRZ), "SFRZ");
! 108: monitor.Puts(x + 51, y, ")");
! 109: y++;
! 110: monitor.Print(x, y, "epsr(cr2):%08x(", reg.epsr);
! 111: monitor.Puts(x + 19, y, TA::OnOff(reg.epsr & m88100reg::PSR_SUPER), "S");
! 112: monitor.Puts(x + 21, y,
! 113: ((reg.epsr& m88100reg::PSR_BO_LE) ? "BO=LE" : "BO=BE"));
! 114: monitor.Puts(x + 27, y, TA::OnOff(reg.epsr & m88100reg::PSR_SER), "SER");
! 115: monitor.Puts(x + 31, y, TA::OnOff(reg.epsr & m88100reg::PSR_C), "Cy");
! 116: monitor.Puts(x + 34, y, TA::OnOff(reg.epsr & m88100reg::PSR_SFD1), "SFD1");
! 117: monitor.Puts(x + 39, y, TA::OnOff(reg.epsr & m88100reg::PSR_MXM), "MXM");
! 118: monitor.Puts(x + 43, y, TA::OnOff(reg.epsr & m88100reg::PSR_IND), "IND");
! 119: monitor.Puts(x + 47, y, TA::OnOff(reg.epsr & m88100reg::PSR_SFRZ), "SFRZ");
! 120: monitor.Puts(x + 51, y, ")");
1.1 root 121:
1.1.1.2 ! root 122: // 制御レジスタ(左中; *IP)
1.1 root 123: x = 0;
124: y = 12;
125: monitor.Print(x, y + 0, "xip:%08x opX:%08x(%c%c)",
126: reg.xip, (uint32)reg.opX,
127: cpu->OpIsBusErr(reg.opX) ? 'B' : '-',
128: cpu->OpIsDelay(reg.opX) ? 'D' : '-');
129: monitor.Print(x, y + 1, "nip:%08x opF:%08x(%c%c)",
130: reg.nip, (uint32)reg.opF,
131: cpu->OpIsBusErr(reg.opF) ? 'B' : '-',
132: cpu->OpIsDelay(reg.opF) ? 'D' : '-');
133: monitor.Print(x, y + 2, "fip:%08x", reg.fip);
134:
135: // 制御レジスタ (S*IP)
136: x = 32;
137: for (int i = 0; i < 3; i++) {
138: monitor.Print(x, y + i, "%s(cr%d):%08x:%c%c",
139: m88100reg::sipname[i], 4 + i,
140: (reg.cr[4 + i] & m88100reg::SIP_MASK),
141: (reg.cr[4 + i] & m88100reg::SIP_V) ? 'V' : '-',
142: (reg.cr[4 + i] & m88100reg::SIP_E) ? 'E' : '-');
143: }
144:
1.1.1.2 ! root 145: // 制御レジスタ(右中)
1.1 root 146: x = 55;
147: y = 9;
148: monitor.Print(x, y++, "ssbr(cr3):%08x", reg.ssbr);
149: monitor.Print(x, y++, "vbr (cr7):%08x", reg.vbr);
150: for (int i = 0; i < 4; i++) {
151: int rn = 17 + i;
152: monitor.Print(x, y + i, "sr%d(cr%d):%08x", i, rn, reg.cr[rn]);
153: }
154:
1.1.1.2 ! root 155: // MMU レジスタ(下段)
! 156: x = 0;
! 157: y = 15;
! 158: for (int i = 0; i <= 2; i++) {
! 159: int dt = 8 + i * 3;
! 160: int dd = 9 + i * 3;
! 161: int da = 10 + i * 3;
! 162:
! 163: monitor.Print(0, y, "dmt%d(cr%-2d):%04x",
! 164: i, dt, (reg.cr[dt] & 0xffff));
! 165: monitor.Puts(15, y, "(b,s,d,l,rx, s,en ,w,v)");
! 166: monitor.Puts(16, y, (reg.cr[dt] & m88100reg::DM_BO) ? "B" : "-");
! 167: monitor.Puts(18, y, (reg.cr[dt] & m88100reg::DM_DAS) ? "S" : "U");
! 168: monitor.Puts(20, y, (reg.cr[dt] & m88100reg::DM_DOUB1) ? "D" : "-");
! 169: monitor.Puts(22, y, (reg.cr[dt] & m88100reg::DM_LOCK) ? "L" : "-");
! 170: // カンマが自然に見えるようにここだけカンマも含めて前詰めで出力
! 171: monitor.Print(25, y, "%d,",
! 172: (reg.cr[dt] & m88100reg::DM_DREG_MASK) >> 7);
! 173: monitor.Puts(28, y, (reg.cr[dt] & m88100reg::DM_SIGNED) ? "S" : "-");
! 174: uint32 en = (reg.cr[dt] & m88100reg::DM_EN_MASK) >> 2;
! 175: monitor.Puts(30, y, m88100reg::dmt_en_str[en]);
! 176: monitor.Puts(35, y, (reg.cr[dt] & m88100reg::DM_WRITE) ? "W" : "-");
! 177: monitor.Puts(37, y, (reg.cr[dt] & m88100reg::DM_VALID) ? "V" : "-");
! 178:
! 179: monitor.Print(40, y, "dmd%d(cr%-2d):%08x", i, dd, reg.cr[dd]);
! 180: monitor.Print(60, y, "dma%d(cr%2d):%08x", i, da, reg.cr[da]);
! 181: y++;
! 182: }
! 183:
! 184: return true;
! 185: }
! 186:
! 187: //
! 188: // {B,P}ATC モニタ
! 189: //
! 190:
! 191: // コンストラクタ
! 192: MPU88200ATC::MPU88200ATC(m88200 *cmmu_)
! 193: {
! 194: cmmu = cmmu_;
! 195:
! 196: monitor.Init(65, 38);
! 197: }
! 198:
! 199: bool
! 200: MPU88200ATC::MonitorUpdate()
! 201: {
! 202: int x;
! 203: int y;
! 204:
! 205: monitor.Clear();
! 206:
! 207: monitor.Print(0, 0, "SAPR %05x'000 TE=%d %c%c%c",
! 208: (cmmu->sapr.addr >> 12) & 0xfffff,
! 209: cmmu->sapr.enable ? 1 : 0,
! 210: (cmmu->sapr.stat & m88200::APR_WT) ? 'T' : '-',
! 211: (cmmu->sapr.stat & m88200::APR_G) ? 'G' : '-',
! 212: (cmmu->sapr.stat & m88200::APR_CI) ? 'C' : '-');
! 213:
! 214: monitor.Print(34, 0, "UAPR %05x'000 TE=%d %c%c%c",
! 215: (cmmu->uapr.addr >> 12) & 0xfffff,
! 216: cmmu->uapr.enable ? 1 : 0,
! 217: (cmmu->uapr.stat & m88200::APR_WT) ? 'T' : '-',
! 218: (cmmu->uapr.stat & m88200::APR_G) ? 'G' : '-',
! 219: (cmmu->uapr.stat & m88200::APR_CI) ? 'C' : '-');
! 220:
! 221: monitor.Puts(0, 1, "<BATC>");
! 222: monitor.Puts(0, 2, "No. LBA PBA Stat");
! 223: monitor.Puts(34, 2, "No. LBA PBA Stat");
! 224: x = 0;
! 225: y = 3;
! 226: for (int i = 0; i < 10; i++) {
! 227: m88200BATC& b = cmmu->batc[i];
! 228:
! 229: if (i == cmmu->batc.size() / 2) {
! 230: x = 34;
! 231: y = 3;
! 232: }
! 233: if (i < 8) {
! 234: monitor.Print(x, y, " %d:", i);
! 235: } else {
! 236: monitor.Print(x, y, "(%d)", i);
! 237: }
! 238: if ((b.lba & 1) == 0) {
! 239: monitor.Print(x + 4, y, "%c:%04x'0000 %04x'0000 %c%c%c%c",
! 240: (b.lba & m88200::BATC_S) ? 'S' : 'U',
! 241: b.lba >> 16, b.pba >> 16,
! 242: (b.stat & m88200::DESC_WT) ? 'T' : '-',
! 243: (b.stat & m88200::DESC_G) ? 'G' : '-',
! 244: (b.stat & m88200::DESC_CI) ? 'C' : '-',
! 245: (b.stat & m88200::DESC_WP) ? 'P' : '-');
! 246: }
! 247: y++;
! 248: }
! 249:
! 250: monitor.Puts(0, 8, "<PATC>");
! 251: monitor.Puts(0, 9, "No. LPA PFA Stat");
! 252: monitor.Puts(34, 9, "No. LPA PFA Stat");
! 253:
! 254: x = 0;
! 255: y = 10;
! 256: for (int i = 0; i < cmmu->patc.size(); i++) {
! 257: m88200PATC& p = cmmu->patc[i];
! 258:
! 259: if (i == cmmu->patc.size() / 2) {
! 260: x = 34;
! 261: y = 10;
! 262: }
! 263:
! 264: monitor.Print(x, y, "%2d:", i);
! 265: if ((p.lpa & 1) == 0) {
! 266: monitor.Print(x + 4, y, "%c:%05x'000 %05x'000 %c%c%c%c%c",
! 267: (p.lpa & m88200::PATC_S) ? 'S' : 'U',
! 268: p.lpa >> 12, p.pfa >> 12,
! 269: (p.stat & m88200::DESC_WT) ? 'T' : '-',
! 270: (p.stat & m88200::DESC_G) ? 'G' : '-',
! 271: (p.stat & m88200::DESC_CI) ? 'C' : '-',
! 272: (p.stat & m88200::DESC_WP) ? 'P' : '-',
! 273: p.m ? 'M' : '-');
! 274: }
! 275:
! 276: y++;
! 277: }
! 278:
1.1 root 279: return true;
280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.