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