|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: // バスとデバイスとのインタフェース。
8: // バスに対し、デバイスがどのように接続されているかを記述する。
9:
1.1.1.3 root 10: #pragma once
11:
1.1 root 12: #if !defined(SELFTEST)
13: #include "device.h"
14: #endif
15:
16: // バイトデバイスをバイト、ワード、ロングワードポートにミラー配置する共通部
17: template <class T, int rshift>
1.1.1.4 root 18: class BusIO_B_Base : public T
1.1 root 19: {
1.1.1.7 ! root 20: protected:
1.1 root 21: inline uint32 Decoder(uint32 addr) {
22: return (addr >> rshift) & (T::NPORT - 1);
23: }
24:
25: public:
1.1.1.2 root 26: uint64 Read8(uint32 addr) override {
1.1 root 27: return T::Read(Decoder(addr));
28: }
29:
1.1.1.2 root 30: uint64 Write8(uint32 addr, uint32 data) override {
1.1 root 31: return T::Write(Decoder(addr), data);
32: }
33:
1.1.1.2 root 34: uint64 Peek8(uint32 addr) override {
1.1 root 35: return T::Peek(Decoder(addr));
36: }
1.1.1.7 ! root 37:
! 38: uint64 Poke8(uint32 addr, uint32 data) override {
! 39: return T::Poke(Decoder(addr), data);
! 40: }
1.1 root 41: };
42:
43: // バイトデバイスをバイトのまま配置する。
44: // NPORT によるミラーを行う以外はこれを使わないのと何も変わらない。
45: template <class T>
1.1.1.4 root 46: class BusIO_B : public BusIO_B_Base<T, 0> { };
1.1 root 47: // バイトデバイスをワードにミラー配置する。
48: template <class T>
1.1.1.4 root 49: class BusIO_BB : public BusIO_B_Base<T, 1> { };
1.1 root 50: // バイトデバイスをロングワードにミラー配置する。
51: template <class T>
1.1.1.4 root 52: class BusIO_BBBB : public BusIO_B_Base<T, 2> { };
1.1 root 53:
54: // ワードデバイスをワードのまま配置する。
55: // NPORT によるミラーを行う以外はこれを使わないのと何も変わらない。
56: template <class T>
1.1.1.4 root 57: class BusIO_W : public T
1.1 root 58: {
59: private:
60: inline uint32 Decoder(uint32 addr) {
61: return (addr >> 1) & (T::NPORT - 1);
62: }
63:
64: public:
1.1.1.2 root 65: uint64 Read8(uint32 addr) override {
1.1 root 66: if ((addr & 1) == 0) {
67: return T::Read(Decoder(addr)) >> 8;
68: } else {
69: return T::Read(Decoder(addr)) & 0xff;
70: }
71: }
1.1.1.2 root 72: uint64 Read16(uint32 addr) override {
1.1 root 73: return T::Read(Decoder(addr));
74: }
75:
1.1.1.2 root 76: uint64 Write8(uint32 addr, uint32 data) override {
77: uint32 offset = Decoder(addr);
78: uint32 old = T::Read(offset);
79: if ((addr & 1) == 0) {
80: return T::Write(offset, ((data << 8) & 0xff00) | (old & 0x00ff));
81: } else {
82: return T::Write(offset, (old & 0xff00) | (data & 0x00ff));
83: }
1.1 root 84: }
1.1.1.2 root 85: uint64 Write16(uint32 addr, uint32 data) override {
1.1 root 86: return T::Write(Decoder(addr), data);
87: }
88:
89:
1.1.1.2 root 90: uint64 Peek8(uint32 addr) override {
1.1 root 91: if ((addr & 1) == 0) {
92: return T::Peek(Decoder(addr)) >> 8;
93: } else {
94: return T::Peek(Decoder(addr)) & 0xff;
95: }
96: }
97: };
98:
99: /* XXX: stub
1.1.1.4 root 100: class BusIO_L : public T
1.1 root 101: */
102:
103: // バイトデバイスを偶数アドレスに配置し、奇数アドレスはバスエラー。
104: template <class T>
1.1.1.4 root 105: class BusIO_BE : public T
1.1 root 106: {
107: private:
108: inline uint32 Decoder(uint32 addr) {
109: return (addr >> 1) & (T::NPORT - 1);
110: }
111:
112: public:
1.1.1.2 root 113: uint64 Read8(uint32 addr) override {
1.1 root 114: if ((addr & 1) == 0) {
115: return T::Read(Decoder(addr));
116: } else {
117: return (int64)-1;
118: }
119: }
1.1.1.2 root 120: uint64 Read16(uint32 addr) override {
1.1 root 121: return (T::Read(Decoder(addr)) << 8) | 0xff;
122: }
123:
1.1.1.2 root 124: uint64 Write8(uint32 addr, uint32 data) override {
1.1 root 125: if ((addr & 1) == 0) {
126: return T::Write(Decoder(addr), data);
127: } else {
128: return (int64)-1;
129: }
130: }
1.1.1.2 root 131: uint64 Write16(uint32 addr, uint32 data) override {
1.1 root 132: return T::Write(Decoder(addr), data >> 8);
133: }
134:
1.1.1.2 root 135: uint64 Peek8(uint32 addr) override {
1.1 root 136: if ((addr & 1) == 0) {
137: return T::Peek(Decoder(addr));
138: } else {
139: return (int64)-1;
140: }
141: }
142: };
143:
144: // バイトデバイスを奇数アドレスに配置し、偶数アドレスはバスエラー。
145: template <class T>
1.1.1.4 root 146: class BusIO_EB : public T
1.1 root 147: {
148: private:
149: inline uint32 Decoder(uint32 addr) {
150: return (addr >> 1) & (T::NPORT - 1);
151: }
152:
153: public:
1.1.1.2 root 154: uint64 Read8(uint32 addr) override {
1.1 root 155: if ((addr & 1) == 0) {
156: return (int64)-1;
157: } else {
158: return T::Read(Decoder(addr));
159: }
160: }
1.1.1.2 root 161: uint64 Read16(uint32 addr) override {
1.1 root 162: return T::Read(Decoder(addr)) | 0xff00;
163: }
164:
1.1.1.2 root 165: uint64 Write8(uint32 addr, uint32 data) override {
1.1 root 166: if ((addr & 1) == 0) {
167: return (int64)-1;
168: } else {
169: return T::Write(Decoder(addr), data);
170: }
171: }
1.1.1.2 root 172: uint64 Write16(uint32 addr, uint32 data) override {
1.1 root 173: return T::Write(Decoder(addr), data & 0xff);
174: }
175:
1.1.1.2 root 176: uint64 Peek8(uint32 addr) override {
1.1 root 177: if ((addr & 1) == 0) {
178: return (int64)-1;
179: } else {
180: return T::Peek(Decoder(addr));
181: }
182: }
183: };
184:
1.1.1.2 root 185: // バイトデバイスを奇数アドレスに配置し、偶数アドレスは非接続。
186: template <class T>
1.1.1.4 root 187: class BusIO_FB : public T
1.1.1.2 root 188: {
189: private:
190: inline uint32 Decoder(uint32 addr) {
191: return (addr >> 1) & (T::NPORT - 1);
192: }
193:
194: public:
195: uint64 Read8(uint32 addr) override {
196: if ((addr & 1) == 0) {
197: return 0xff;
198: } else {
199: return T::Read(Decoder(addr));
200: }
201: }
202: uint64 Read16(uint32 addr) override {
203: return T::Read(Decoder(addr)) | 0xff00;
204: }
205:
206: uint64 Write8(uint32 addr, uint32 data) override {
207: if ((addr & 1) == 0) {
208: return 0;
209: } else {
210: return T::Write(Decoder(addr), data);
211: }
212: }
213: uint64 Write16(uint32 addr, uint32 data) override {
214: return T::Write(Decoder(addr), data & 0xff);
215: }
216:
217: uint64 Peek8(uint32 addr) override {
218: if ((addr & 1) == 0) {
219: return 0xff;
220: } else {
221: return T::Peek(Decoder(addr));
222: }
223: }
224: };
225:
1.1 root 226: // バイトデバイスをロングワードの先頭に配置し、他は非接続。
227: template <class T>
1.1.1.4 root 228: class BusIO_BFFF : public T
1.1 root 229: {
1.1.1.7 ! root 230: protected:
1.1 root 231: inline uint32 Decoder(uint32 addr) {
232: return (addr >> 2) & (T::NPORT - 1);
233: }
234:
235: public:
1.1.1.2 root 236: uint64 Read8(uint32 addr) override {
1.1 root 237: if ((addr & 3) == 0) {
238: return T::Read(Decoder(addr));
239: } else {
240: return 0xff;
241: }
242: }
1.1.1.2 root 243: uint64 Read16(uint32 addr) override {
1.1 root 244: if ((addr & 2) == 0) {
245: return (T::Read(Decoder(addr)) << 8) | 0xff;
246: } else {
247: return 0xffff;
248: }
249: }
1.1.1.2 root 250: uint64 Read32(uint32 addr) override {
1.1 root 251: return (T::Read(Decoder(addr)) << 24) | 0x00ffffff;
252: }
253:
1.1.1.2 root 254: uint64 Write8(uint32 addr, uint32 data) override {
1.1 root 255: if ((addr & 3) == 0) {
256: return T::Write(Decoder(addr), data);
257: } else {
258: return 0;
259: }
260: }
1.1.1.2 root 261: uint64 Write16(uint32 addr, uint32 data) override {
1.1 root 262: if ((addr & 2) == 0) {
263: return T::Write(Decoder(addr), data >> 8);
264: } else {
265: return 0;
266: }
267: }
1.1.1.2 root 268: uint64 Write32(uint32 addr, uint32 data) override {
1.1 root 269: return T::Write(Decoder(addr), data >> 24);
270: }
271:
1.1.1.2 root 272: uint64 Peek8(uint32 addr) override {
1.1 root 273: if ((addr & 3) == 0) {
274: return T::Peek(Decoder(addr));
275: } else {
276: return 0xff;
277: }
278: }
1.1.1.7 ! root 279:
! 280: uint64 Poke8(uint32 addr, uint32 data) override {
! 281: if ((addr & 3) == 0) {
! 282: return T::Poke(Decoder(addr), data);
! 283: } else {
! 284: // 非接続なので、書き換えようとしてもエラーも起きず何も起きない。
! 285: return 0;
! 286: }
! 287: }
1.1 root 288: };
289:
290: // ワードデバイスをロングワードにミラー配置する。
291: template <class T>
1.1.1.4 root 292: class BusIO_WW : public T
1.1 root 293: {
294: private:
295: inline uint32 Decoder(uint32 addr) {
296: return (addr >> 2) & (T::NPORT - 1);
297: }
298: public:
1.1.1.2 root 299: uint64 Read8(uint32 addr) override {
1.1 root 300: if ((addr & 1) == 0) {
301: return T::Read(Decoder(addr)) >> 8;
302: } else {
303: return T::Read(Decoder(addr)) & 0xff;
304: }
305: }
1.1.1.2 root 306: uint64 Read16(uint32 addr) override {
1.1 root 307: return T::Read(Decoder(addr));
308: }
309:
1.1.1.2 root 310: uint64 Write8(uint32 addr, uint32 data) override {
1.1.1.6 root 311: VMPANIC("(NOT IMPLEMENTED)");
1.1 root 312: return (int64)-1; // XXX 未確認
313: }
1.1.1.2 root 314: uint64 Write16(uint32 addr, uint32 data) override {
1.1 root 315: return T::Write(Decoder(addr), data);
316: }
317:
1.1.1.2 root 318: uint64 Peek8(uint32 addr) override {
1.1 root 319: if ((addr & 1) == 0) {
320: return T::Peek(Decoder(addr)) >> 8;
321: } else {
322: return T::Peek(Decoder(addr)) & 0xff;
323: }
324: }
325: };
326:
327: // ワードデバイスをロングワード先頭に配置し、他は非接続。
328: template <class T>
1.1.1.4 root 329: class BusIO_WF : public T
1.1 root 330: {
331: private:
332: inline uint32 Decoder(uint32 addr) {
333: return (addr >> 2) & (T::NPORT - 1);
334: }
335: public:
1.1.1.2 root 336: uint64 Read8(uint32 addr) override {
1.1 root 337: switch (addr & 3) {
338: case 0:
339: return T::Read(Decoder(addr)) >> 8;
340: case 1:
341: return T::Read(Decoder(addr)) & 0xff;
342: case 2:
343: case 3:
344: return 0xff;
345: }
346: __unreachable();
347: }
1.1.1.2 root 348: uint64 Read16(uint32 addr) override {
1.1 root 349: if ((addr & 2) == 0) {
350: return T::Read(Decoder(addr));
351: } else {
352: return 0xffff;
353: }
354: }
355:
1.1.1.2 root 356: uint64 Write8(uint32 addr, uint32 data) override {
1.1.1.6 root 357: VMPANIC("(NOT IMPLEMENTED)");
1.1 root 358: return 0; // XXX 未確認
359: }
1.1.1.2 root 360: uint64 Write16(uint32 addr, uint32 data) override {
1.1 root 361: if ((addr & 2) == 0) {
362: return T::Write(Decoder(addr), data);
363: } else {
364: return 0;
365: }
366: }
1.1.1.2 root 367: uint64 Peek8(uint32 addr) override {
1.1 root 368: switch (addr & 3) {
369: case 0:
370: return T::Peek(Decoder(addr)) >> 8;
371: case 1:
372: return T::Peek(Decoder(addr)) & 0xff;
373: case 2:
374: case 3:
375: return 0xff;
376: }
377: __unreachable();
378: }
379: };
380:
381: // X680x0 の SPC を収容するための専用バスアダプタ。
382: // ここは SASI 跡地 32バイト分と SCSI 用地 32バイト分を合わせた 64 バイト
383: // (0x40 バイト) でのミラーになっているため、BusIO_EB では表現できない。
384: // SASI 跡地は実際には読み出しパターンがあるようだが、本題ではないので
385: // とりあえず全部 0xff を返しておく。
386: template <class T>
387: class BusIO_X68kSPC : public T
388: {
389: private:
390: inline uint64 Decoder(uint32 addr) {
391: // SASI 跡地と SCSI を合わせて 0x40 バイトでミラーしている
392: return (addr >> 1) & (0x20 - 1);
393: }
394:
395: public:
1.1.1.2 root 396: uint64 Read8(uint32 addr) override {
1.1 root 397: if ((addr & 1) == 0) {
398: return (uint64)-1;
399: } else {
400: addr = Decoder(addr);
401: if (addr < 0x10) {
402: // 前半16ポートは SASI 跡地。
403: return 0xff;
404: } else {
405: // 後半16ポートは SCSI。
406: return T::Read(addr - 0x10);
407: }
408: }
409: }
1.1.1.2 root 410: uint64 Read16(uint32 addr) override {
1.1 root 411: addr = Decoder(addr);
412: if (addr < 0x10) {
413: // 前半16ポートは SASI 跡地
414: return 0xffff;
415: } else {
416: return T::Read(addr - 0x10) | 0xff00;
417: }
418: }
419:
1.1.1.2 root 420: uint64 Write8(uint32 addr, uint32 data) override {
1.1 root 421: if ((addr & 1) == 0) {
422: return (uint64)-1;
423: } else {
424: addr = Decoder(addr);
425: if (addr < 0x10) {
426: // 前半16ポートは SASI 跡地。
427: // XXX 書き込みはどうなる?
428: return 0;
429: } else {
430: // 後半16ポートは SCSI。
431: return T::Write(addr - 0x10, data);
432: }
433: }
434: }
1.1.1.2 root 435: uint64 Write16(uint32 addr, uint32 data) override {
1.1 root 436: addr = Decoder(addr);
437: if (addr < 0x10) {
438: // 前半16ポートは SASI 跡地。
439: // XXX 書き込みはどうなる?
440: return 0;
441: } else {
442: // 後半16ポートは SCSI。
443: return T::Write(addr - 0x10, data & 0xff);
444: }
445: }
446:
1.1.1.2 root 447: uint64 Peek8(uint32 addr) override {
1.1 root 448: if ((addr & 1) == 0) {
449: return (uint64)-1;
450: } else {
451: addr = Decoder(addr);
452: if (addr < 0x10) {
453: // 前半16ポートは SASI 跡地。
454: return 0xff;
455: } else {
456: // 後半16ポートは SCSI。
457: return T::Peek(addr - 0x10);
458: }
459: }
460: }
461: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.