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