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