|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // メインバス (X68030) ! 9: // ! 10: ! 11: // IODevice ! 12: // +-- MainbusBaseDevice (InitMainbus() と FC アクセスを持つ) ! 13: // | +-- MainbusDevice (これがメインバス、システムに1つ) ! 14: // | | +-- Mainbus24Device (上位8ビットがテーブルで表せるメインバス) ! 15: // | | | +-- LunaMainbus ! 16: // | | | | +-- Luna1Mainbus ! 17: // | | | | +-- Luna88kMainbus ! 18: // | | | +-- NewsMainbus ! 19: // | | | +-- Virt68kMainbus ! 20: // | | | ! 21: // | | | +-------------+ ! 22: // | | +--| X68kMainbus |(上位8ビットが IODevice で表せないため) ! 23: // | | +-------------+ ! 24: // | | ! 25: // | +-- X68kIODevice (FC を受け取るため) ! 26: // | ! 27: // +-- XPbusDevice ! 28: ! 29: #include "mainbus_x68k.h" ! 30: #include "bankram.h" ! 31: #include "extram.h" ! 32: #include "interrupt.h" ! 33: #include "mainapp.h" ! 34: #include "x68kio.h" ! 35: ! 36: // コンストラクタ ! 37: X68kMainbus::X68kMainbus() ! 38: : inherited(OBJ_MAINBUS) ! 39: { ! 40: // デバイス ! 41: NEWDV(Interrupt, new X68030Interrupt()); ! 42: NEWDV(X68kIO, new X68kIODevice()); ! 43: NEWDV(ExtRAM, new ExtRAMDevice()); ! 44: ! 45: // デバイスの割り当ては Init() で行っている。 ! 46: ! 47: // モニタの表示外観は Mainbus24 と同じ。 ! 48: monitor.func = ToMonitorCallback(&X68kMainbus::MonitorUpdate); ! 49: monitor.SetSize(75, 33); ! 50: monitor.Regist(ID_MONITOR_MAINBUS); ! 51: ! 52: monitor_accstat.func = ! 53: ToMonitorCallback(&X68kMainbus::MonitorUpdateAccStat); ! 54: monitor_accstat.SetSize(80, 2 + 16 + 3); ! 55: monitor_accstat.Regist(ID_MONITOR_ACCSTAT); ! 56: } ! 57: ! 58: // デストラクタ ! 59: X68kMainbus::~X68kMainbus() ! 60: { ! 61: } ! 62: ! 63: // 初期化 ! 64: bool ! 65: X68kMainbus::Init() ! 66: { ! 67: if (inherited::Init() == false) { ! 68: return false; ! 69: } ! 70: ! 71: for (int i = 0; i < bankram.size(); i++) { ! 72: bankram[i] = gMainApp.FindObject<BankRAMDevice>(OBJ_BANKRAM(i)); ! 73: } ! 74: ! 75: return true; ! 76: } ! 77: ! 78: // メインバスの初期化 ! 79: bool ! 80: X68kMainbus::InitMainbus() ! 81: { ! 82: // 拡張メモリはサイズが確定した後のここで配置。 ! 83: extsize = pExtRAM->GetSizeMB(); ! 84: ! 85: // 上位8ビット全域を一旦全部内蔵空間にしてから ! 86: std::fill(is_intio.begin(), is_intio.end(), true); ! 87: ! 88: if (extsize == 16) { ! 89: // TS-6BE16 互換 (16MB) なら $01 の 16MB。 ! 90: extstart = 16; ! 91: is_intio[1] = false; ! 92: } else { ! 93: // 060turbo 互換なら $10 から。 ! 94: extstart = 256; ! 95: for (int i = 0x10, end = i + (extsize / 16); i < end; i++) { ! 96: is_intio[i] = false; ! 97: } ! 98: } ! 99: ! 100: // 親子構造になっている。 ! 101: if (pX68kIO->InitMainbus() == false) { ! 102: return false; ! 103: } ! 104: ! 105: return true; ! 106: } ! 107: ! 108: // リセット ! 109: void ! 110: X68kMainbus::ResetHard(bool poweron) ! 111: { ! 112: inherited::ResetHard(poweron); ! 113: ! 114: std::fill(accstat_read.begin(), accstat_read.end(), 0); ! 115: std::fill(accstat_write.begin(), accstat_write.end(), 0); ! 116: } ! 117: ! 118: // リセットについて。 ! 119: // ! 120: // PWRRESET ! 121: // 電源オン ----------+--> VIPS ! 122: // (7505) +--> VideoCtlr ! 123: // +--> OSCIAN2 ! 124: // | ! 125: // | +------+ ! 126: // +-->| | ! 127: // 本体 SWRESET | YUKI | ! 128: // リセット ------------->| | ! 129: // スイッチ +------+ ! 130: // | IPLRESET ! 131: // | ! 132: // +--> FPU ! 133: // | ! 134: // ▽ ! 135: // RESET | ! 136: // |<-> MPU (68030) ! 137: // +--> PPI (8255) ! 138: // +--> SPC (MB89352) ! 139: // +--> ADPCM (MSM6258) ! 140: // +--> FDC (uPD72065B) ! 141: // +--> MFP (MC68901) ! 142: // | ! 143: // | +-------+ ! 144: // +-->| PEDEC | ! 145: // | +-------+ ! 146: // | | ! 147: // | +-- OPMIC -----> OPM(YM2151) ! 148: // | +-- SCCRD/WR --> SCC(Z8530) ! 149: // | ! 150: // | EXRESET ! 151: // +---|>-----------> 外部バス ! 152: // ▽ ! 153: // SYSRESET | ! 154: // |<-> SAKI ---+ ! 155: // | | BEC0,BEC1 ! 156: // +--> DMAC <--+ ! 157: // +--> CYNTHIA ! 158: // リセットされない? ! 159: // o CACHY ! 160: ! 161: // MPU の RESET 命令によるリセット ! 162: void ! 163: X68kMainbus::ResetByMPU() ! 164: { ! 165: std::vector<int> ids { ! 166: OBJ_ADPCM, ! 167: OBJ_BANKRAM0, ! 168: OBJ_BANKRAM1, ! 169: OBJ_DMAC, ! 170: OBJ_ETHERNET0, ! 171: OBJ_ETHERNET1, ! 172: OBJ_FDC, ! 173: OBJ_MFP, ! 174: OBJ_OPM, ! 175: OBJ_PEDEC, ! 176: OBJ_PLUTO, ! 177: OBJ_PPI, ! 178: OBJ_MPSCC, ! 179: OBJ_SPC, ! 180: OBJ_WINDRV, ! 181: }; ! 182: for (auto id : ids) { ! 183: auto dev = gMainApp.FindObject<IODevice>(id); ! 184: if (dev) { ! 185: dev->ResetHard(false); ! 186: } ! 187: } ! 188: } ! 189: ! 190: inline bool ! 191: X68kMainbus::IsIntio(uint32 addr) const ! 192: { ! 193: return is_intio[(addr >> 24) & 0xff]; ! 194: } ! 195: ! 196: #define READ(NN) do { \ ! 197: uint32 pa = addr.Addr(); \ ! 198: if (IsIntio(pa)) { \ ! 199: /* 内蔵 16MB を 1MB 単位で */ \ ! 200: accstat_read[(pa >> 20) & 0x0f] = ACC_READ; \ ! 201: return pX68kIO->__CONCAT(Read,NN)(addr); \ ! 202: } else { \ ! 203: /* 拡張メモリのアドレスは折り返しは起きない */ \ ! 204: accstat_read[pa >> 20] = ACC_READ; \ ! 205: return pExtRAM->__CONCAT(Read,NN)(pa); \ ! 206: } \ ! 207: } while (0) ! 208: ! 209: #define WRITE(NN) do { \ ! 210: uint32 pa = addr.Addr(); \ ! 211: if (IsIntio(pa)) { \ ! 212: /* 内蔵 16MB を 1MB 単位で */ \ ! 213: accstat_write[(pa >> 20) & 0x0f] = ACC_WRITE; \ ! 214: return pX68kIO->__CONCAT(Write,NN)(addr, data); \ ! 215: } else { \ ! 216: /* 拡張メモリのアドレスは折り返しは起きない */ \ ! 217: accstat_write[pa >> 20] = ACC_WRITE; \ ! 218: return pExtRAM->__CONCAT(Write,NN)(pa, data); \ ! 219: } \ ! 220: } while (0) ! 221: ! 222: busdata ! 223: X68kMainbus::Read8(busaddr addr) ! 224: { ! 225: READ(8); ! 226: } ! 227: ! 228: busdata ! 229: X68kMainbus::Read16(busaddr addr) ! 230: { ! 231: READ(16); ! 232: } ! 233: ! 234: busdata ! 235: X68kMainbus::Read32(busaddr addr) ! 236: { ! 237: READ(32); ! 238: } ! 239: ! 240: busdata ! 241: X68kMainbus::Write8(busaddr addr, uint32 data) ! 242: { ! 243: WRITE(8); ! 244: } ! 245: ! 246: busdata ! 247: X68kMainbus::Write16(busaddr addr, uint32 data) ! 248: { ! 249: WRITE(16); ! 250: } ! 251: ! 252: busdata ! 253: X68kMainbus::Write32(busaddr addr, uint32 data) ! 254: { ! 255: WRITE(32); ! 256: } ! 257: ! 258: busdata ! 259: X68kMainbus::Peek8(uint32 addr) ! 260: { ! 261: if (IsIntio(addr)) { ! 262: return pX68kIO->Peek8(addr); ! 263: } else { ! 264: return pExtRAM->Peek8(addr); ! 265: } ! 266: } ! 267: ! 268: bool ! 269: X68kMainbus::Poke8(uint32 addr, uint32 data) ! 270: { ! 271: if (IsIntio(addr)) { ! 272: return pX68kIO->Poke8(addr, data); ! 273: } else { ! 274: return pExtRAM->Poke8(addr, data); ! 275: } ! 276: } ! 277: ! 278: void ! 279: X68kMainbus::MonitorUpdate(Monitor *, TextScreen& screen) ! 280: { ! 281: screen.Clear(); ! 282: ! 283: // 012345678901234567890 ! 284: // $0000'0000: 1234567 ! 285: ! 286: for (int i = 0; i < 8; i++) { ! 287: screen.Print(12 + i * 8, 0, "+$0%x", i); ! 288: } ! 289: ! 290: auto xioname = FormatDevName(pX68kIO.get()).first; ! 291: auto extname = FormatDevName(pExtRAM.get()).first; ! 292: ! 293: int idx = 0; ! 294: for (int i = 0; i < is_intio.size() / 8; i++) { ! 295: screen.Print(0, i + 1, "$%02x00'0000:", idx); ! 296: for (int j = 0; j < 8; j++) { ! 297: screen.Print(12 + j * 8, i + 1, "%s", ! 298: (is_intio[idx] ? xioname : extname).c_str()); ! 299: idx++; ! 300: } ! 301: } ! 302: } ! 303: ! 304: void ! 305: X68kMainbus::MonitorUpdateAccStat(Monitor *, TextScreen& screen) ! 306: { ! 307: std::array<uint8, 1024> acc; ! 308: std::array<uint8, 16 + 16> accbank; ! 309: ! 310: // R|W をマージしながらコピー。 ! 311: for (int i = 0, iend = acc.size(); i < iend; i += 4) { ! 312: uint32 tmp = 0; ! 313: tmp |= *(uint32 *)&accstat_read[i]; ! 314: tmp |= *(uint32 *)&accstat_write[i]; ! 315: *(uint32 *)&acc[i] = tmp; ! 316: } ! 317: ! 318: // 読んだのでリセット。 ! 319: std::fill(accstat_read.begin(), accstat_read.end(), 0); ! 320: std::fill(accstat_write.begin(), accstat_write.end(), 0); ! 321: ! 322: // バンクメモリ。 ! 323: for (int n = 0; n < bankram.size(); n++) { ! 324: if (bankram[n]) { ! 325: bankram[n]->FetchAccStat(&accbank[n * 16]); ! 326: } ! 327: } ! 328: ! 329: screen.Clear(); ! 330: screen.Print(0, 0, ! 331: "Shows only the first 1GB. 1MB/char. " ! 332: "'R':Read, 'W':Write, 'A':Read+Write"); ! 333: screen.Print(12, 1, "0123456789ABCDEF"); ! 334: for (int i = 1; i < 4; i++) { ! 335: screen.Print(12 + 17 * i, 1, "+$0%x", i); ! 336: } ! 337: for (int y = 0; y < acc.size() / 64; y++) { ! 338: screen.Print(0, y + 2, "$%02x00'0000:", y * 0x04); ! 339: } ! 340: ! 341: // 拡張メモリ部分。 ! 342: for (int i = extstart, end = extstart + extsize; i < end; i++) { ! 343: uint op = acc[i] & 3; ! 344: uint8 ch = ".RWA"[op]; ! 345: int y = 2 + i / 64; ! 346: int x = 12 + (i % 64) + ((i % 64) / 16)/*区切りの空白分*/; ! 347: screen.Putc(x, y, ch); ! 348: } ! 349: ! 350: // 内蔵I/O 部分。 ! 351: { ! 352: std::array<char, 16 + 1> buf; ! 353: char *d = &buf[0]; ! 354: for (int i = 0; i < 16; i++) { ! 355: uint op = acc[i] & 3; ! 356: *d++ = ".RWA"[op]; ! 357: } ! 358: *d = '\0'; ! 359: screen.Puts(12, 2, &buf[0]); ! 360: } ! 361: ! 362: // バンクメモリ。 ! 363: for (int n = 0; n < 2; n++) { ! 364: screen.Print(0, 19 + n, "BankMem #%d:", n); ! 365: if (bankram[n]) { ! 366: for (int i = 0; i < 16; i++) { ! 367: uint op = accbank[n * 16 + i] & 3; ! 368: uint8 ch = ".RWA"[op]; ! 369: screen.Putc(12 + i, 19 + n, ch); ! 370: } ! 371: } ! 372: } ! 373: } ! 374: ! 375: // ブートページを切り替える。 ! 376: void ! 377: X68kMainbus::SwitchBootPage(bool isrom) ! 378: { ! 379: // X68030 ではすべて X68kIO が担当している ! 380: pX68kIO->SwitchBootPage(isrom); ! 381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.