Annotation of nono/vm/busio.h, revision 1.1.1.2

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: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.