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

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

unix.superglobalmegacorp.com

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