|
|
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: monitor.func = ToMonitorCallback(&X68kMainbus::MonitorUpdate);
48: monitor.SetSize(75, 33);
49: monitor.Regist(ID_MONITOR_MAINBUS);
50:
51: monitor_accstat.func =
52: ToMonitorCallback(&X68kMainbus::MonitorUpdateAccStat);
1.1.1.2 ! root 53: monitor_accstat.SetSize(80, 2 + 32 + 3);
1.1 root 54: }
55:
56: // デストラクタ
57: X68kMainbus::~X68kMainbus()
58: {
59: }
60:
61: // 初期化
62: bool
63: X68kMainbus::Init()
64: {
65: if (inherited::Init() == false) {
66: return false;
67: }
68:
69: for (int i = 0; i < bankram.size(); i++) {
70: bankram[i] = gMainApp.FindObject<BankRAMDevice>(OBJ_BANKRAM(i));
71: }
72:
73: return true;
74: }
75:
76: // メインバスの初期化
77: bool
78: X68kMainbus::InitMainbus()
79: {
1.1.1.2 ! root 80: int extstart;
! 81: int extsize;
! 82:
1.1 root 83: // 拡張メモリはサイズが確定した後のここで配置。
84: extsize = pExtRAM->GetSizeMB();
85:
86: // 上位8ビット全域を一旦全部内蔵空間にしてから
87: std::fill(is_intio.begin(), is_intio.end(), true);
88:
89: if (extsize == 16) {
90: // TS-6BE16 互換 (16MB) なら $01 の 16MB。
91: extstart = 16;
92: is_intio[1] = false;
93: } else {
94: // 060turbo 互換なら $10 から。
95: extstart = 256;
96: for (int i = 0x10, end = i + (extsize / 16); i < end; i++) {
97: is_intio[i] = false;
98: }
99: }
100:
101: // 親子構造になっている。
102: if (pX68kIO->InitMainbus() == false) {
103: return false;
104: }
105:
1.1.1.2 ! root 106: // アクセス統計のデバイスがある領域。
! 107: accstat_avail[0] = 0x80;
! 108: for (int i = extstart / 16; i < (extstart + extsize) / 16; i++) {
! 109: accstat_avail[i / 8] |= 0x80U >> (i % 8);
! 110: }
! 111:
1.1 root 112: return true;
113: }
114:
115: // リセット
116: void
117: X68kMainbus::ResetHard(bool poweron)
118: {
119: inherited::ResetHard(poweron);
120:
121: std::fill(accstat_read.begin(), accstat_read.end(), 0);
122: std::fill(accstat_write.begin(), accstat_write.end(), 0);
123: }
124:
125: // リセットについて。
126: //
127: // PWRRESET
128: // 電源オン ----------+--> VIPS
129: // (7505) +--> VideoCtlr
130: // +--> OSCIAN2
131: // |
132: // | +------+
133: // +-->| |
134: // 本体 SWRESET | YUKI |
135: // リセット ------------->| |
136: // スイッチ +------+
137: // | IPLRESET
138: // |
139: // +--> FPU
140: // |
141: // ▽
142: // RESET |
143: // |<-> MPU (68030)
144: // +--> PPI (8255)
145: // +--> SPC (MB89352)
146: // +--> ADPCM (MSM6258)
147: // +--> FDC (uPD72065B)
148: // +--> MFP (MC68901)
149: // |
150: // | +-------+
151: // +-->| PEDEC |
152: // | +-------+
153: // | |
154: // | +-- OPMIC -----> OPM(YM2151)
155: // | +-- SCCRD/WR --> SCC(Z8530)
156: // |
157: // | EXRESET
158: // +---|>-----------> 外部バス
159: // ▽
160: // SYSRESET |
161: // |<-> SAKI ---+
162: // | | BEC0,BEC1
163: // +--> DMAC <--+
164: // +--> CYNTHIA
165: // リセットされない?
166: // o CACHY
167:
168: // MPU の RESET 命令によるリセット
169: void
170: X68kMainbus::ResetByMPU()
171: {
172: std::vector<int> ids {
173: OBJ_ADPCM,
174: OBJ_BANKRAM0,
175: OBJ_BANKRAM1,
176: OBJ_DMAC,
177: OBJ_ETHERNET0,
178: OBJ_ETHERNET1,
179: OBJ_FDC,
180: OBJ_MFP,
181: OBJ_OPM,
182: OBJ_PEDEC,
183: OBJ_PLUTO,
184: OBJ_PPI,
185: OBJ_MPSCC,
186: OBJ_SPC,
187: OBJ_WINDRV,
188: };
189: for (auto id : ids) {
190: auto dev = gMainApp.FindObject<IODevice>(id);
191: if (dev) {
192: dev->ResetHard(false);
193: }
194: }
195: }
196:
197: inline bool
198: X68kMainbus::IsIntio(uint32 addr) const
199: {
200: return is_intio[(addr >> 24) & 0xff];
201: }
202:
1.1.1.2 ! root 203: // 内蔵 16MB 分で折り返す
! 204: #define ACCSTAT_INTIO(pa) \
! 205: (((pa) >> AccStat::SHIFT) & ((1U << (24 - AccStat::SHIFT)) - 1))
1.1 root 206:
207: busdata
1.1.1.2 ! root 208: X68kMainbus::Read(busaddr addr)
1.1 root 209: {
1.1.1.2 ! root 210: uint32 pa = addr.Addr();
! 211: if (IsIntio(pa)) {
! 212: // 内蔵 16MB を 2MB 単位で
! 213: accstat_read[ACCSTAT_INTIO(pa)] = AccStat::READ;
! 214: return pX68kIO->Read(addr);
! 215: } else {
! 216: // 拡張メモリのアドレスは折り返しは起きない
! 217: accstat_read[pa >> AccStat::SHIFT] = AccStat::READ;
! 218: return pExtRAM->Read(addr);
! 219: }
1.1 root 220: }
221:
222: busdata
1.1.1.2 ! root 223: X68kMainbus::Write(busaddr addr, uint32 data)
1.1 root 224: {
1.1.1.2 ! root 225: uint32 pa = addr.Addr();
! 226: if (IsIntio(pa)) {
! 227: // 内蔵 16MB を 2MB 単位で
! 228: accstat_write[ACCSTAT_INTIO(pa)] = AccStat::WRITE;
! 229: return pX68kIO->Write(addr, data);
! 230: } else { \
! 231: // 拡張メモリのアドレスは折り返しは起きない
! 232: accstat_write[pa >> AccStat::SHIFT] = AccStat::WRITE;
! 233: return pExtRAM->Write(addr, data);
! 234: }
1.1 root 235: }
236:
237: busdata
1.1.1.2 ! root 238: X68kMainbus::Peek1(uint32 addr)
1.1 root 239: {
240: if (IsIntio(addr)) {
1.1.1.2 ! root 241: return pX68kIO->Peek1(addr);
1.1 root 242: } else {
1.1.1.2 ! root 243: return pExtRAM->Peek1(addr);
1.1 root 244: }
245: }
246:
247: bool
1.1.1.2 ! root 248: X68kMainbus::Poke1(uint32 addr, uint32 data)
1.1 root 249: {
250: if (IsIntio(addr)) {
1.1.1.2 ! root 251: return pX68kIO->Poke1(addr, data);
1.1 root 252: } else {
1.1.1.2 ! root 253: return pExtRAM->Poke1(addr, data);
1.1 root 254: }
255: }
256:
257: void
258: X68kMainbus::MonitorUpdate(Monitor *, TextScreen& screen)
259: {
260: screen.Clear();
261:
262: // 012345678901234567890
263: // $0000'0000: 1234567
264:
265: for (int i = 0; i < 8; i++) {
266: screen.Print(12 + i * 8, 0, "+$0%x", i);
267: }
268:
269: auto xioname = FormatDevName(pX68kIO.get()).first;
270: auto extname = FormatDevName(pExtRAM.get()).first;
271:
272: int idx = 0;
273: for (int i = 0; i < is_intio.size() / 8; i++) {
274: screen.Print(0, i + 1, "$%02x00'0000:", idx);
275: for (int j = 0; j < 8; j++) {
276: screen.Print(12 + j * 8, i + 1, "%s",
277: (is_intio[idx] ? xioname : extname).c_str());
278: idx++;
279: }
280: }
281: }
282:
283: void
1.1.1.2 ! root 284: X68kMainbus::MonitorUpdateAccStat(Monitor *monitor_, TextScreen& screen)
1.1 root 285: {
1.1.1.2 ! root 286: // メインバス空間は親クラス側の処理そのまま。
! 287: inherited::MonitorUpdateAccStat(monitor_, screen);
1.1 root 288:
1.1.1.2 ! root 289: // バンクメモリ側の情報取得。
1.1 root 290: for (int n = 0; n < bankram.size(); n++) {
291: if (bankram[n]) {
1.1.1.2 ! root 292: bankram[n]->FetchAccStat(&accbank[n * AccStat::BANKLEN]);
1.1 root 293: }
294: }
295:
1.1.1.2 ! root 296: // バンクメモリ側の描画。
! 297: for (int n = 0; n < bankram.size(); n++) {
! 298: int y = 35 + n;
! 299: screen.Print(0, y, "BankMem #%u:", n);
1.1 root 300: if (bankram[n]) {
1.1.1.2 ! root 301: for (int i = 0; i < AccStat::BANKLEN; i++) {
! 302: uint op = accbank[n * AccStat::BANKLEN + i] & 3;
1.1 root 303: uint8 ch = ".RWA"[op];
1.1.1.2 ! root 304: screen.Putc(12 + i, y, ch);
1.1 root 305: }
306: }
307: }
308: }
309:
310: // ブートページを切り替える。
311: void
312: X68kMainbus::SwitchBootPage(bool isrom)
313: {
314: // X68030 ではすべて X68kIO が担当している
315: pX68kIO->SwitchBootPage(isrom);
316: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.