|
|
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);
1.1.1.5 ! root 49: monitor->SetCallback(&X68kMainbus::MonitorScreen);
1.1.1.3 root 50: monitor->SetSize(75, 33);
1.1 root 51:
1.1.1.5 ! root 52: accstat_monitor->SetCallback(&X68kMainbus::MonitorScreenAccStat);
1.1.1.3 root 53: accstat_monitor->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: //
117: // PWRRESET
118: // 電源オン ----------+--> VIPS
119: // (7505) +--> VideoCtlr
120: // +--> OSCIAN2
121: // |
122: // | +------+
123: // +-->| |
124: // 本体 SWRESET | YUKI |
125: // リセット ------------->| |
126: // スイッチ +------+
127: // | IPLRESET
128: // |
129: // +--> FPU
130: // |
131: // ▽
132: // RESET |
133: // |<-> MPU (68030)
134: // +--> PPI (8255)
135: // +--> SPC (MB89352)
136: // +--> ADPCM (MSM6258)
137: // +--> FDC (uPD72065B)
138: // +--> MFP (MC68901)
139: // |
140: // | +-------+
141: // +-->| PEDEC |
142: // | +-------+
143: // | |
144: // | +-- OPMIC -----> OPM(YM2151)
145: // | +-- SCCRD/WR --> SCC(Z8530)
146: // |
147: // | EXRESET
148: // +---|>-----------> 外部バス
149: // ▽
150: // SYSRESET |
151: // |<-> SAKI ---+
152: // | | BEC0,BEC1
153: // +--> DMAC <--+
154: // +--> CYNTHIA
155: // リセットされない?
156: // o CACHY
157:
158: // MPU の RESET 命令によるリセット
159: void
160: X68kMainbus::ResetByMPU()
161: {
162: std::vector<int> ids {
163: OBJ_ADPCM,
164: OBJ_BANKRAM0,
165: OBJ_BANKRAM1,
166: OBJ_DMAC,
167: OBJ_ETHERNET0,
168: OBJ_ETHERNET1,
169: OBJ_FDC,
170: OBJ_MFP,
171: OBJ_OPM,
172: OBJ_PEDEC,
173: OBJ_PLUTO,
174: OBJ_PPI,
175: OBJ_MPSCC,
1.1.1.5 ! root 176: OBJ_SPC0,
1.1 root 177: OBJ_WINDRV,
178: };
179: for (auto id : ids) {
180: auto dev = gMainApp.FindObject<IODevice>(id);
181: if (dev) {
182: dev->ResetHard(false);
183: }
184: }
185: }
186:
187: inline bool
188: X68kMainbus::IsIntio(uint32 addr) const
189: {
190: return is_intio[(addr >> 24) & 0xff];
191: }
192:
1.1.1.2 root 193: // 内蔵 16MB 分で折り返す
194: #define ACCSTAT_INTIO(pa) \
195: (((pa) >> AccStat::SHIFT) & ((1U << (24 - AccStat::SHIFT)) - 1))
1.1 root 196:
197: busdata
1.1.1.2 root 198: X68kMainbus::Read(busaddr addr)
1.1 root 199: {
1.1.1.2 root 200: uint32 pa = addr.Addr();
1.1.1.5 ! root 201: lastaddr = pa;
1.1.1.2 root 202: if (IsIntio(pa)) {
203: // 内蔵 16MB を 2MB 単位で
204: accstat_read[ACCSTAT_INTIO(pa)] = AccStat::READ;
205: return pX68kIO->Read(addr);
206: } else {
207: // 拡張メモリのアドレスは折り返しは起きない
208: accstat_read[pa >> AccStat::SHIFT] = AccStat::READ;
209: return pExtRAM->Read(addr);
210: }
1.1 root 211: }
212:
213: busdata
1.1.1.2 root 214: X68kMainbus::Write(busaddr addr, uint32 data)
1.1 root 215: {
1.1.1.2 root 216: uint32 pa = addr.Addr();
1.1.1.5 ! root 217: lastaddr = pa;
1.1.1.2 root 218: if (IsIntio(pa)) {
219: // 内蔵 16MB を 2MB 単位で
220: accstat_write[ACCSTAT_INTIO(pa)] = AccStat::WRITE;
221: return pX68kIO->Write(addr, data);
222: } else { \
223: // 拡張メモリのアドレスは折り返しは起きない
224: accstat_write[pa >> AccStat::SHIFT] = AccStat::WRITE;
225: return pExtRAM->Write(addr, data);
226: }
1.1 root 227: }
228:
229: busdata
1.1.1.2 root 230: X68kMainbus::Peek1(uint32 addr)
1.1 root 231: {
232: if (IsIntio(addr)) {
1.1.1.2 root 233: return pX68kIO->Peek1(addr);
1.1 root 234: } else {
1.1.1.2 root 235: return pExtRAM->Peek1(addr);
1.1 root 236: }
237: }
238:
239: bool
1.1.1.2 root 240: X68kMainbus::Poke1(uint32 addr, uint32 data)
1.1 root 241: {
242: if (IsIntio(addr)) {
1.1.1.2 root 243: return pX68kIO->Poke1(addr, data);
1.1 root 244: } else {
1.1.1.2 root 245: return pExtRAM->Poke1(addr, data);
1.1 root 246: }
247: }
248:
249: void
1.1.1.5 ! root 250: X68kMainbus::MonitorScreen(Monitor *, TextScreen& screen)
1.1 root 251: {
252: screen.Clear();
253:
254: // 012345678901234567890
255: // $0000'0000: 1234567
256:
257: for (int i = 0; i < 8; i++) {
258: screen.Print(12 + i * 8, 0, "+$0%x", i);
259: }
260:
261: auto xioname = FormatDevName(pX68kIO.get()).first;
262: auto extname = FormatDevName(pExtRAM.get()).first;
263:
264: int idx = 0;
265: for (int i = 0; i < is_intio.size() / 8; i++) {
266: screen.Print(0, i + 1, "$%02x00'0000:", idx);
267: for (int j = 0; j < 8; j++) {
268: screen.Print(12 + j * 8, i + 1, "%s",
269: (is_intio[idx] ? xioname : extname).c_str());
270: idx++;
271: }
272: }
273: }
274:
275: void
1.1.1.5 ! root 276: X68kMainbus::MonitorScreenAccStat(Monitor *monitor_, TextScreen& screen)
1.1 root 277: {
1.1.1.2 root 278: // メインバス空間は親クラス側の処理そのまま。
1.1.1.5 ! root 279: inherited::MonitorScreenAccStat(monitor_, screen);
1.1 root 280:
1.1.1.2 root 281: // バンクメモリ側の情報取得。
1.1 root 282: for (int n = 0; n < bankram.size(); n++) {
283: if (bankram[n]) {
1.1.1.2 root 284: bankram[n]->FetchAccStat(&accbank[n * AccStat::BANKLEN]);
1.1 root 285: }
286: }
287:
1.1.1.2 root 288: // バンクメモリ側の描画。
289: for (int n = 0; n < bankram.size(); n++) {
290: int y = 35 + n;
291: screen.Print(0, y, "BankMem #%u:", n);
1.1 root 292: if (bankram[n]) {
1.1.1.2 root 293: for (int i = 0; i < AccStat::BANKLEN; i++) {
294: uint op = accbank[n * AccStat::BANKLEN + i] & 3;
1.1 root 295: uint8 ch = ".RWA"[op];
1.1.1.2 root 296: screen.Putc(12 + i, y, ch);
1.1 root 297: }
298: }
299: }
300: }
301:
302: // ブートページを切り替える。
303: void
304: X68kMainbus::SwitchBootPage(bool isrom)
305: {
306: // X68030 ではすべて X68kIO が担当している
307: pX68kIO->SwitchBootPage(isrom);
308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.