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

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

unix.superglobalmegacorp.com

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