|
|
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.