|
|
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.1.1.3 root 38: static std::unique_ptr<AreaSetDevice> areaset;
39: static std::unique_ptr<PlutoDevice> pluto;
40: static std::unique_ptr<PPIDevice> ppi;
41: static std::unique_ptr<PrinterDevice> printer;
42: static std::unique_ptr<SpriteDevice> sprite;
43: static std::unique_ptr<SysportDevice> sysport;
1.1 root 44:
45: // 1つの 8KB ブロックを複数のデバイスで共有する場合
46: class MuxDevice
47: : public IODevice
48: {
1.1.1.3 root 49: using inherited = IODevice;
1.1 root 50: public:
51: MuxDevice();
1.1.1.5 ! root 52: virtual ~MuxDevice() override;
1.1 root 53:
1.1.1.5 ! root 54: uint64 Read8(uint32 addr) override;
! 55: uint64 Read16(uint32 addr) override;
! 56: uint64 Write8(uint32 addr, uint32 data) override;
! 57: uint64 Write16(uint32 addr, uint32 data) override;
! 58: uint64 Peek8(uint32 addr) override;
1.1 root 59:
1.1.1.2 root 60: IODevice *SearchDevice(uint32 addr) const;
1.1 root 61:
62: void AddDevice(IODevice *dev);
63:
64: std::vector<IODevice*> devlist;
65: };
66:
67: MuxDevice::MuxDevice()
68: {
69: logname = "none";
70: }
71:
72: MuxDevice::~MuxDevice()
73: {
74: }
75:
1.1.1.3 root 76: // デバイスを追加する。
77: // ここに追加するデバイスは dev->devlen を指定すること。
1.1 root 78: void
79: MuxDevice::AddDevice(IODevice *dev)
80: {
81: if (dev->devlen == 0) {
1.1.1.3 root 82: printf("MuxDevice::AddDevice: '%s' devlen not set!\n",
83: dev->devname.c_str());
1.1 root 84: exit(1);
85: }
86: devlist.push_back(dev);
87: }
88:
89: IODevice *
1.1.1.2 root 90: MuxDevice::SearchDevice(uint32 addr) const
1.1 root 91: {
92: for (const auto& d : devlist) {
93: if (d->devaddr <= addr && addr < d->devaddr + d->devlen) {
94: return d;
95: }
96: }
97: return nullptr;
98: }
99:
100: uint64
101: MuxDevice::Read8(uint32 addr)
102: {
103: IODevice *d = SearchDevice(addr);
104: if (d == nullptr) {
105: return (uint64)-1;
106: }
107: return d->Read8(addr);
108: }
109:
110: uint64
111: MuxDevice::Read16(uint32 addr)
112: {
113: IODevice *d = SearchDevice(addr);
114: if (d == nullptr) {
115: return (uint64)-1;
116: }
117: return d->Read16(addr);
118: }
119:
120: uint64
121: MuxDevice::Write8(uint32 addr, uint32 data)
122: {
123: IODevice *d = SearchDevice(addr);
124: if (d == nullptr) {
125: return (uint64)-1;
126: }
127: return d->Write8(addr, data);
128: }
129:
130: uint64
131: MuxDevice::Write16(uint32 addr, uint32 data)
132: {
133: IODevice *d = SearchDevice(addr);
134: if (d == nullptr) {
135: return (uint64)-1;
136: }
137: return d->Write16(addr, data);
138: }
139:
140: uint64
141: MuxDevice::Peek8(uint32 addr)
142: {
143: IODevice *d = SearchDevice(addr);
144: if (d == nullptr) {
145: return (uint64)-1;
146: }
147: return d->Peek8(addr);
148: }
149:
150:
151: // コンストラクタ
152: XIOSpaceDevice::XIOSpaceDevice()
153: {
154: logname = "xiospace";
155: devname = "IOSpace";
156:
157: #define ADD_DEVICE(varname, clsname) do { \
1.1.1.2 root 158: varname.reset(new clsname); \
159: AddDevice(varname.get()); \
1.1 root 160: } while (0)
161:
162: // デバイスクラス作成 (順序に注意)
163: ADD_DEVICE(areaset, AreaSetDevice());
1.1.1.4 root 164: ADD_DEVICE(gCGROM, CGROMDevice());
1.1.1.3 root 165: ADD_DEVICE(gCRTC, BusIO_W<CRTCDevice>());
166: ADD_DEVICE(gDMAC, BusIO_B<DMACDevice>());
1.1.1.5 ! root 167: ADD_DEVICE(gFDC, BusIO_EB<FDCDevice>());
1.1 root 168: ADD_DEVICE(gGVRAM, GVRAMDevice());
1.1.1.5 ! root 169: ADD_DEVICE(gPEDEC, BusIO_EB<PEDECDevice>());
1.1.1.4 root 170: ADD_DEVICE(gIPLROM1, IPLROM1Device());
171: ADD_DEVICE(gIPLROM2, IPLROM2Device());
1.1.1.3 root 172: ADD_DEVICE(gMFP, BusIO_EB<MFPDevice>());
1.1 root 173: ADD_DEVICE(pluto, PlutoDevice());
1.1.1.2 root 174: ADD_DEVICE(ppi, BusIO_EB<PPIDevice>());
1.1 root 175: ADD_DEVICE(printer, PrinterDevice());
1.1.1.3 root 176: ADD_DEVICE(gRTC, BusIO_EB<RP5C15Device>());
177: ADD_DEVICE(gSCC, BusIO_EB<SCCDevice>());
1.1.1.4 root 178: ADD_DEVICE(gSRAM, SRAMDevice()); // Required by SPC
1.1.1.2 root 179: ADD_DEVICE(gSPC, BusIO_X68kSPC<SPCDevice>());
1.1 root 180: ADD_DEVICE(sprite, SpriteDevice());
1.1.1.3 root 181: ADD_DEVICE(sysport, BusIO_FB<SysportDevice>());
1.1 root 182: ADD_DEVICE(gTVRAM, TVRAMDevice());
1.1.1.3 root 183: ADD_DEVICE(gVideoCtlr, BusIO_W<VideoCtlrDevice>());
1.1.1.5 ! root 184: ADD_DEVICE(gOPM, BusIO_EB<OPMDevice>());
1.1.1.4 root 185: }
186:
187: // デストラクタ
188: XIOSpaceDevice::~XIOSpaceDevice()
189: {
190: }
191:
192: bool
193: XIOSpaceDevice::Init()
194: {
195: // RAM のみ RamDevice::Init() で ram_size が決定してから行う。
196: for (int i = 0; i < ram_size / 8192; i++) {
197: table[i] = gRAM.get();
198: }
199:
200: // 必要なデバイスは全部埋めたので、この時点で nullptr なエントリを
201: // buserr に差し替える。
202: IODevice *buserr = gVM->GetBusErrDevice();
203: for (auto&& d : table) {
204: if (d == nullptr) {
205: d = buserr;
206: }
207: }
1.1 root 208:
209: // デバッグ表示
210: if (0) {
211: for (int i = 0; i < 512; i++) {
212: printf("[%3d] $%06x ", i, 0xc00000 + i * 8192);
1.1.1.4 root 213: assert(table[i]);
214: if (dynamic_cast<MuxDevice*>(table[i])) {
1.1 root 215: printf("MuxDevice\n");
1.1.1.4 root 216: } else {
1.1.1.3 root 217: printf("%s\n", table[i]->devname.c_str());
1.1 root 218: }
219: }
220: }
221:
1.1.1.4 root 222: return true;
1.1 root 223: }
224:
225: // デバイステーブルに dev を追加する。
1.1.1.3 root 226: // ここに追加するデバイスは dev->devlen を指定すること。
1.1 root 227: void
228: XIOSpaceDevice::AddDevice(IODevice *dev)
229: {
230: if (dev->devaddr == 0) {
1.1.1.3 root 231: printf("XIOSpaceDevice:AddDevice: '%s' devaddr not set!\n",
232: dev->devname.c_str());
1.1 root 233: exit(1);
234: }
235: if (dev->devlen == 0) {
1.1.1.3 root 236: printf("XIOSpaceDevice:AddDevice: '%s' devlen not set!\n",
237: dev->devname.c_str());
1.1 root 238: exit(1);
239: }
240:
241: int idx = dev->devaddr / 8192;
242: for (int i = idx; i < idx + (dev->devlen + 8191) / 8192; i++) {
243: if (table[i] == nullptr) {
244: table[i] = dev;
245: } else {
1.1.1.4 root 246: MuxDevice *mux = dynamic_cast<MuxDevice*>(table[i]);
247: if (mux) {
248: mux->AddDevice(dev);
249: } else {
250: MuxDevice *muxdev = new MuxDevice();
251: muxdev->AddDevice(table[i]);
252: muxdev->AddDevice(dev);
253: table[i] = muxdev;
254: }
1.1 root 255: }
256: }
257: }
258:
259: uint64
260: XIOSpaceDevice::Read8(uint32 addr)
261: {
262: addr &= 0x00ffffff;
263: IODevice *d = SearchDevice(addr);
264: return d->Read8(addr);
265: }
266:
267: uint64
268: XIOSpaceDevice::Read16(uint32 addr)
269: {
270: addr &= 0x00ffffff;
271: IODevice *d = SearchDevice(addr);
272: return d->Read16(addr);
273: }
274:
275: uint64
276: XIOSpaceDevice::Read32(uint32 addr)
277: {
278: addr &= 0x00ffffff;
279: IODevice *d = SearchDevice(addr);
280: return d->Read32(addr);
281: }
282:
283: uint64
284: XIOSpaceDevice::Write8(uint32 addr, uint32 data)
285: {
286: addr &= 0x00ffffff;
287: IODevice *d = SearchDevice(addr);
288: return d->Write8(addr, data);
289: }
290:
291: uint64
292: XIOSpaceDevice::Write16(uint32 addr, uint32 data)
293: {
294: addr &= 0x00ffffff;
295: IODevice *d = SearchDevice(addr);
296: return d->Write16(addr, data);
297: }
298:
299: uint64
300: XIOSpaceDevice::Write32(uint32 addr, uint32 data)
301: {
302: addr &= 0x00ffffff;
303: IODevice *d = SearchDevice(addr);
304: return d->Write32(addr, data);
305: }
306:
307: uint64
308: XIOSpaceDevice::Peek8(uint32 addr)
309: {
310: addr &= 0x00ffffff;
311: IODevice *d = SearchDevice(addr);
312: return d->Peek8(addr);
313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.