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

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

unix.superglobalmegacorp.com

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