|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.3 root 7: #include "xiospace.h"
1.1 root 8: #include "areaset.h"
1.1.1.2 root 9: #include "busio.h"
1.1 root 10: #include "crtc.h"
11: #include "dmac.h"
12: #include "fdc.h"
13: #include "gvram.h"
14: #include "mfp.h"
1.1.1.5 root 15: #include "opm.h"
16: #include "pedec.h"
1.1.1.2 root 17: #include "pio.h"
1.1.1.3 root 18: #include "pluto.h"
1.1 root 19: #include "printer.h"
20: #include "ram.h"
1.1.1.2 root 21: #include "romimg_x68k.h"
1.1 root 22: #include "rp5c15.h"
23: #include "scc.h"
24: #include "spc.h"
25: #include "sprite.h"
26: #include "sram.h"
27: #include "sysport.h"
28: #include "tvram.h"
1.1.1.3 root 29: #include "videoctlr.h"
1.1 root 30: #include "vm.h"
1.1.1.3 root 31: #include <typeinfo>
1.1 root 32:
33: //
34: // X68030 のメイン空間 ($000000-$FFFFFF) 担当。
35: //
36:
37: // 1つの 8KB ブロックを複数のデバイスで共有する場合
38: class MuxDevice
39: : public IODevice
40: {
1.1.1.3 root 41: using inherited = IODevice;
1.1 root 42: public:
43: MuxDevice();
1.1.1.5 root 44: virtual ~MuxDevice() override;
1.1 root 45:
1.1.1.5 root 46: uint64 Read8(uint32 addr) override;
47: uint64 Read16(uint32 addr) override;
48: uint64 Write8(uint32 addr, uint32 data) override;
49: uint64 Write16(uint32 addr, uint32 data) override;
50: uint64 Peek8(uint32 addr) override;
1.1 root 51:
1.1.1.2 root 52: IODevice *SearchDevice(uint32 addr) const;
1.1 root 53:
54: void AddDevice(IODevice *dev);
55:
56: std::vector<IODevice*> devlist;
57: };
58:
59: MuxDevice::MuxDevice()
60: {
61: logname = "none";
62: }
63:
64: MuxDevice::~MuxDevice()
65: {
66: }
67:
1.1.1.3 root 68: // デバイスを追加する。
69: // ここに追加するデバイスは dev->devlen を指定すること。
1.1 root 70: void
71: MuxDevice::AddDevice(IODevice *dev)
72: {
73: if (dev->devlen == 0) {
1.1.1.3 root 74: printf("MuxDevice::AddDevice: '%s' devlen not set!\n",
75: dev->devname.c_str());
1.1 root 76: exit(1);
77: }
78: devlist.push_back(dev);
79: }
80:
81: IODevice *
1.1.1.2 root 82: MuxDevice::SearchDevice(uint32 addr) const
1.1 root 83: {
84: for (const auto& d : devlist) {
85: if (d->devaddr <= addr && addr < d->devaddr + d->devlen) {
86: return d;
87: }
88: }
89: return nullptr;
90: }
91:
92: uint64
93: MuxDevice::Read8(uint32 addr)
94: {
95: IODevice *d = SearchDevice(addr);
96: if (d == nullptr) {
97: return (uint64)-1;
98: }
99: return d->Read8(addr);
100: }
101:
102: uint64
103: MuxDevice::Read16(uint32 addr)
104: {
105: IODevice *d = SearchDevice(addr);
106: if (d == nullptr) {
107: return (uint64)-1;
108: }
109: return d->Read16(addr);
110: }
111:
112: uint64
113: MuxDevice::Write8(uint32 addr, uint32 data)
114: {
115: IODevice *d = SearchDevice(addr);
116: if (d == nullptr) {
117: return (uint64)-1;
118: }
119: return d->Write8(addr, data);
120: }
121:
122: uint64
123: MuxDevice::Write16(uint32 addr, uint32 data)
124: {
125: IODevice *d = SearchDevice(addr);
126: if (d == nullptr) {
127: return (uint64)-1;
128: }
129: return d->Write16(addr, data);
130: }
131:
132: uint64
133: MuxDevice::Peek8(uint32 addr)
134: {
135: IODevice *d = SearchDevice(addr);
136: if (d == nullptr) {
137: return (uint64)-1;
138: }
139: return d->Peek8(addr);
140: }
141:
142:
1.1.1.6 root 143: std::unique_ptr<XIOSpaceDevice> gXIOSpace;
144:
1.1 root 145: // コンストラクタ
146: XIOSpaceDevice::XIOSpaceDevice()
147: {
148: logname = "xiospace";
149: devname = "IOSpace";
150:
151: #define ADD_DEVICE(varname, clsname) do { \
1.1.1.2 root 152: varname.reset(new clsname); \
153: AddDevice(varname.get()); \
1.1 root 154: } while (0)
155:
156: // デバイスクラス作成 (順序に注意)
1.1.1.6 root 157: ADD_DEVICE(gAreaSet, AreaSetDevice());
1.1.1.4 root 158: ADD_DEVICE(gCGROM, CGROMDevice());
1.1.1.3 root 159: ADD_DEVICE(gCRTC, BusIO_W<CRTCDevice>());
160: ADD_DEVICE(gDMAC, BusIO_B<DMACDevice>());
1.1.1.5 root 161: ADD_DEVICE(gFDC, BusIO_EB<FDCDevice>());
1.1 root 162: ADD_DEVICE(gGVRAM, GVRAMDevice());
1.1.1.5 root 163: ADD_DEVICE(gPEDEC, BusIO_EB<PEDECDevice>());
1.1.1.4 root 164: ADD_DEVICE(gIPLROM1, IPLROM1Device());
165: ADD_DEVICE(gIPLROM2, IPLROM2Device());
1.1.1.3 root 166: ADD_DEVICE(gMFP, BusIO_EB<MFPDevice>());
1.1.1.6 root 167: ADD_DEVICE(gPluto, PlutoDevice());
168: ADD_DEVICE(gPPI, BusIO_EB<PPIDevice>());
169: ADD_DEVICE(gPrinter, PrinterDevice());
1.1.1.3 root 170: ADD_DEVICE(gRTC, BusIO_EB<RP5C15Device>());
171: ADD_DEVICE(gSCC, BusIO_EB<SCCDevice>());
1.1.1.4 root 172: ADD_DEVICE(gSRAM, SRAMDevice()); // Required by SPC
1.1.1.2 root 173: ADD_DEVICE(gSPC, BusIO_X68kSPC<SPCDevice>());
1.1.1.6 root 174: ADD_DEVICE(gSprite, SpriteDevice());
175: ADD_DEVICE(gSysport, BusIO_FB<SysportDevice>());
1.1 root 176: ADD_DEVICE(gTVRAM, TVRAMDevice());
1.1.1.3 root 177: ADD_DEVICE(gVideoCtlr, BusIO_W<VideoCtlrDevice>());
1.1.1.5 root 178: ADD_DEVICE(gOPM, BusIO_EB<OPMDevice>());
1.1.1.4 root 179: }
180:
181: // デストラクタ
182: XIOSpaceDevice::~XIOSpaceDevice()
183: {
184: }
185:
186: bool
187: XIOSpaceDevice::Init()
188: {
189: // RAM のみ RamDevice::Init() で ram_size が決定してから行う。
1.1.1.6 root 190: int ram_size = gRAM->GetSize();
1.1.1.4 root 191: for (int i = 0; i < ram_size / 8192; i++) {
192: table[i] = gRAM.get();
193: }
194:
195: // 必要なデバイスは全部埋めたので、この時点で nullptr なエントリを
1.1.1.7 ! root 196: // BusErr に差し替える。
1.1.1.4 root 197: for (auto&& d : table) {
198: if (d == nullptr) {
1.1.1.7 ! root 199: d = gBusErr.get();
1.1.1.4 root 200: }
201: }
1.1 root 202:
203: // デバッグ表示
204: if (0) {
205: for (int i = 0; i < 512; i++) {
206: printf("[%3d] $%06x ", i, 0xc00000 + i * 8192);
1.1.1.4 root 207: assert(table[i]);
208: if (dynamic_cast<MuxDevice*>(table[i])) {
1.1 root 209: printf("MuxDevice\n");
1.1.1.4 root 210: } else {
1.1.1.3 root 211: printf("%s\n", table[i]->devname.c_str());
1.1 root 212: }
213: }
214: }
215:
1.1.1.4 root 216: return true;
1.1 root 217: }
218:
219: // デバイステーブルに dev を追加する。
1.1.1.3 root 220: // ここに追加するデバイスは dev->devlen を指定すること。
1.1 root 221: void
222: XIOSpaceDevice::AddDevice(IODevice *dev)
223: {
224: if (dev->devaddr == 0) {
1.1.1.3 root 225: printf("XIOSpaceDevice:AddDevice: '%s' devaddr not set!\n",
226: dev->devname.c_str());
1.1 root 227: exit(1);
228: }
229: if (dev->devlen == 0) {
1.1.1.3 root 230: printf("XIOSpaceDevice:AddDevice: '%s' devlen not set!\n",
231: dev->devname.c_str());
1.1 root 232: exit(1);
233: }
234:
235: int idx = dev->devaddr / 8192;
236: for (int i = idx; i < idx + (dev->devlen + 8191) / 8192; i++) {
237: if (table[i] == nullptr) {
238: table[i] = dev;
239: } else {
1.1.1.4 root 240: MuxDevice *mux = dynamic_cast<MuxDevice*>(table[i]);
241: if (mux) {
242: mux->AddDevice(dev);
243: } else {
244: MuxDevice *muxdev = new MuxDevice();
245: muxdev->AddDevice(table[i]);
246: muxdev->AddDevice(dev);
247: table[i] = muxdev;
248: }
1.1 root 249: }
250: }
251: }
252:
253: uint64
254: XIOSpaceDevice::Read8(uint32 addr)
255: {
256: addr &= 0x00ffffff;
257: IODevice *d = SearchDevice(addr);
258: return d->Read8(addr);
259: }
260:
261: uint64
262: XIOSpaceDevice::Read16(uint32 addr)
263: {
264: addr &= 0x00ffffff;
265: IODevice *d = SearchDevice(addr);
266: return d->Read16(addr);
267: }
268:
269: uint64
270: XIOSpaceDevice::Read32(uint32 addr)
271: {
272: addr &= 0x00ffffff;
273: IODevice *d = SearchDevice(addr);
274: return d->Read32(addr);
275: }
276:
277: uint64
278: XIOSpaceDevice::Write8(uint32 addr, uint32 data)
279: {
280: addr &= 0x00ffffff;
281: IODevice *d = SearchDevice(addr);
282: return d->Write8(addr, data);
283: }
284:
285: uint64
286: XIOSpaceDevice::Write16(uint32 addr, uint32 data)
287: {
288: addr &= 0x00ffffff;
289: IODevice *d = SearchDevice(addr);
290: return d->Write16(addr, data);
291: }
292:
293: uint64
294: XIOSpaceDevice::Write32(uint32 addr, uint32 data)
295: {
296: addr &= 0x00ffffff;
297: IODevice *d = SearchDevice(addr);
298: return d->Write32(addr, data);
299: }
300:
301: uint64
302: XIOSpaceDevice::Peek8(uint32 addr)
303: {
304: addr &= 0x00ffffff;
305: IODevice *d = SearchDevice(addr);
306: return d->Peek8(addr);
307: }
1.1.1.7 ! root 308:
! 309: // ブートページを切り替える。
! 310: // (VM_X68030::SwitchBootPage() の下請け)
! 311: void
! 312: XIOSpaceDevice::SwitchBootPage(bool isrom)
! 313: {
! 314: IODevice *ram;
! 315: IODevice *rom;
! 316:
! 317: if (isrom) {
! 318: // 0x000000 からの 64KB ( 8エントリ)、
! 319: // 0xfe0000 からの 128KB (16エントリ) のどちらも IPLROM0 が担当する。
! 320: ram = gIPLROM0.get();
! 321: rom = ram;
! 322: } else {
! 323: // 0x000000 からの 64KB ( 8エントリ) に RAM を見せる。
! 324: // 0xfe0000 からの 128KB (16エントリ) に IPLROM1 を見せる。
! 325: ram = gRAM.get();
! 326: rom = gIPLROM1.get();
! 327: }
! 328:
! 329: for (int i = 0; i < 8; i++) {
! 330: table[i] = ram;
! 331: }
! 332: for (int i = 0; i < 16; i++) {
! 333: table[table.size() - 16 + i] = rom;
! 334: }
! 335: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.