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

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

unix.superglobalmegacorp.com

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