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