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