|
|
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.