Annotation of nono/vm/nereid.cpp, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2023 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // Nereid Ethernet/メモリ/USB 複合ボード (のうち Ethernet/バンクメモリ)
                      9: //
                     10: 
                     11: // Nereid の DIPSW
                     12: //
                     13: //  SW1,2   : RAM をメインメモリとして使う場合の容量
                     14: //            OFF,OFF = 割り当てない (この時だけバンクメモリが 16MB 使える)
                     15: //  SW3,4,5 : RAM をメインメモリとして使う場合の開始アドレス
                     16: //  SW6     : RAM をバンクメモリとして使う場合のウィンドウ
                     17: //            OFF = $ee0000
                     18: //            ON  = $ef0000
                     19: //  SW7     : アドレス、割り込みベクタ設定
                     20: //            OFF = $ece3xx, $f9, $fb
                     21: //            ON  = $ecebxx, $f8, $fa
                     22: //  SW8     : バンクメモリ有効無効
                     23: //            OFF = 無効
                     24: //            ON  = 有効
                     25: //
                     26: //  バンクメモリの容量は、SW1-2 でメインメモリに割り当てた余りのうち
                     27: //  4MB か 16MB のどちらか。Nereid のメモリをメインメモリに割り当てる機能は
                     28: //  (意味がないので) 実装せず、SW1-2 を設定した結果バンクメモリ容量が 4MB か
                     29: //  16MB にできるところだけ再現する。
                     30: //
                     31: //  Nereid は SW-6,7 により2枚まで同時に運用することが可能。
                     32: //  SW6 と SW7 の組み合わせは本来自由だが、そこまで自由度を上げるメリットは
                     33: //  なさそうなので、ここでは
                     34: //    Nereid#0 が SW6=OFF、SW7=OFF
                     35: //    Nereid#1 が SW6=ON、 SW7=ON
                     36: //  と固定して扱う。
                     37: 
                     38: // 各デバイスのアドレス配置、割り込みベクタ
                     39: //
                     40: //  #0 (SW7=OFF)   #1 (SW7=ON)
                     41: //  -------------- --------------
                     42: //  $ece300-ece33f $eceb00-eceb3f : RTL8019AS (偶数アドレスのみ)
                     43: //  $ece380-ece383 $eceb80-eceb83 : SL811HS/T (奇数アドレスのみ)
                     44: //  $ece3f0        $ecebf0        : バンクページ選択
                     45: //  $ece3f1        $ecebf1        : 制御ポート
                     46: //
                     47: //  $f9            $f8            : RTL8019AS 割り込みベクタ
                     48: //  $fb            $fa            : SL811HS/T 割り込みベクタ
                     49: 
                     50: #include "nereid.h"
                     51: #include "bankram.h"
                     52: #include "config.h"
                     53: #include "rtl8019as.h"
                     54: #include "x68kio.h"
                     55: 
                     56: //
                     57: // Nereid 空間担当デバイス
                     58: //
                     59: 
                     60: // boards[0]、board[1] を所有し、アクセスをディスパッチする。
                     61: 
                     62: // コンストラクタ
                     63: NereidDevice::NereidDevice()
                     64:        : inherited(OBJ_NEREID)
                     65: {
                     66:        monitor.func = ToMonitorCallback(&NereidDevice::MonitorUpdate);
                     67:        monitor.SetSize(41, 9);
                     68:        monitor.Regist(ID_MONITOR_NEREID);
                     69: }
                     70: 
                     71: // デストラクタ
                     72: NereidDevice::~NereidDevice()
                     73: {
                     74: }
                     75: 
                     76: // デバイス作成
                     77: bool
                     78: NereidDevice::Create()
                     79: {
                     80:        // ボードの有無は nereid%d-enable だけで決まる。
                     81:        for (int i = 0; i < 2; i++) {
                     82:                std::string name = string_format("nereid%d-enable", i);
                     83:                bool enable = gConfig->Find(name).AsInt();
                     84: 
                     85:                if (enable) {
                     86:                        boards[i].reset(new NereidBoardDevice(i));
                     87: 
                     88:                        // 配置場所
                     89:                        if (i == 0) {
                     90:                                loc[i] = 0x03;  // $ece300-
                     91:                        } else {
                     92:                                loc[i] = 0x0b;  // $eceb00-
                     93:                        }
                     94:                } else {
                     95:                        // アドレス比較で一致させないため -1 にしておく。
                     96:                        loc[i] = -1;
                     97:                }
                     98:        }
                     99: 
                    100:        return true;
                    101: }
                    102: 
                    103: // Nereid が1枚でもささっていれば true。
                    104: // (X68kIO.Init() から呼ばれる)
                    105: bool
                    106: NereidDevice::IsInstalled() const
                    107: {
                    108:        return (bool)boards[0] || (bool)boards[1];
                    109: }
                    110: 
                    111: inline uint32
                    112: NereidDevice::Decoder(uint32 addr) const
                    113: {
                    114:        // ここで返すのはオフセットではなく、チップセレクトに近い。
                    115:        // $ece3xx or $ecebxx の $3 か $b のところ (厳密にはそれを含む
                    116:        // 5ビット) を返し、あらかじめ用意してある loc[i] と比較する。
                    117:        return (addr >> 8) & 0x1f;
                    118: }
                    119: 
                    120: uint64
                    121: NereidDevice::Read8(uint32 addr)
                    122: {
                    123:        putlog(2, "Read  $%06x.B", addr);
                    124: 
                    125:        uint32 cs = Decoder(addr);
                    126:        for (int i = 0; i < boards.size(); i++) {
                    127:                if (cs == loc[i]) {
                    128:                        return boards[i]->Read8(addr);
                    129:                }
                    130:        }
                    131:        return (uint64)-1;
                    132: }
                    133: 
                    134: uint64
                    135: NereidDevice::Read16(uint32 addr)
                    136: {
                    137:        putlog(2, "Read  $%06x.W", addr);
                    138: 
                    139:        uint32 cs = Decoder(addr);
                    140:        for (int i = 0; i < boards.size(); i++) {
                    141:                if (cs == loc[i]) {
                    142:                        return boards[i]->Read16(addr);
                    143:                }
                    144:        }
                    145:        return (uint64)-1;
                    146: }
                    147: 
                    148: uint64
                    149: NereidDevice::Write8(uint32 addr, uint32 data)
                    150: {
                    151:        putlog(2, "Write $%06x.B", addr);
                    152: 
                    153:        uint32 cs = Decoder(addr);
                    154:        for (int i = 0; i < boards.size(); i++) {
                    155:                if (cs == loc[i]) {
                    156:                        return boards[i]->Write8(addr, data);
                    157:                }
                    158:        }
                    159:        return (uint64)-1;
                    160: }
                    161: 
                    162: uint64
                    163: NereidDevice::Write16(uint32 addr, uint32 data)
                    164: {
                    165:        putlog(2, "Write $%06x.W", addr);
                    166: 
                    167:        uint32 cs = Decoder(addr);
                    168:        for (int i = 0; i < boards.size(); i++) {
                    169:                if (cs == loc[i]) {
                    170:                        return boards[i]->Write16(addr, data);
                    171:                }
                    172:        }
                    173:        return (uint64)-1;
                    174: }
                    175: 
                    176: uint64
                    177: NereidDevice::Peek8(uint32 addr)
                    178: {
                    179:        uint32 cs = Decoder(addr);
                    180: 
                    181:        for (int i = 0; i < boards.size(); i++) {
                    182:                if (cs == loc[i]) {
                    183:                        return boards[i]->Peek8(addr);
                    184:                }
                    185:        }
                    186:        return (uint64)-1;
                    187: }
                    188: 
                    189: void
                    190: NereidDevice::MonitorUpdate(Monitor *, TextScreen& screen)
                    191: {
                    192:        int y;
                    193: 
                    194:        screen.Clear();
                    195: 
                    196:        // 0123456789012345678901234567890123456789
                    197:        //                #0           #1
                    198:        // Board        : NotInstalled NotInstalled
                    199:        //  Ethernet    : Enable
                    200:        //   Address    : $ece300
                    201:        //   Vector     : $f9
                    202:        //  Bank Memory : 16MB
                    203:        //   Page Select: $ece380
                    204:        //   Bank Window: $ee0000
                    205:        //   CurrentPage: $00
                    206: 
                    207:        y = 1;
                    208:        screen.Puts(0, y++, "Board        :");
                    209:        screen.Puts(1, y++,  "Ethernet    :");
                    210:        screen.Puts(2, y++,   "Address    :");
                    211:        screen.Puts(2, y++,   "Vector     :");
                    212:        screen.Puts(1, y++,  "Bank Memory :");
                    213:        screen.Puts(2, y++,   "Page Select:");
                    214:        screen.Puts(2, y++,   "Bank Window:");
                    215:        screen.Puts(2, y++,   "CurrentPage:");
                    216: 
                    217:        for (int i = 0; i < 2; i++) {
                    218:                int x = 15 + i * 14;
                    219:                TA attr;
                    220: 
                    221:                y = 0;
                    222:                screen.Print(x, y++, "#%d", i);
                    223: 
                    224:                // ボードがささっているか
                    225:                bool installed = (bool)boards[i];
                    226:                if (installed) {
                    227:                        screen.Puts(x, y, "Installed");
                    228:                } else {
                    229:                        screen.Puts(x, y, "NotInstalled");
                    230:                }
                    231:                y++;
                    232: 
                    233:                // イーサネット
                    234:                attr = TA::Disable;
                    235:                if (installed) {
                    236:                        if (boards[i]->IsNetEnable()) {
                    237:                                screen.Puts(x, y, "Available");
                    238:                                attr = TA::Normal;
                    239:                        } else {
                    240:                                screen.Puts(x, y, "NotAvailable");
                    241:                        }
                    242:                } else {
                    243:                        screen.Puts(x, y, attr, "-");
                    244:                }
                    245:                y++;
                    246:                screen.Print(x, y++, attr, "$%06x", 0xece300 + i * 0x800);
                    247:                screen.Print(x, y++, attr, "$%02x", 0xf9 - i);
                    248: 
                    249:                // バンクメモリ
                    250:                attr = TA::Disable;
                    251:                int ramsize = 0;
                    252:                if (installed) {
                    253:                        ramsize = boards[i]->GetBankRAMSize();
                    254:                        if (ramsize > 0) {
                    255:                                screen.Print(x, y, "%d MB", ramsize);
                    256:                                attr = TA::Normal;
                    257:                        } else {
                    258:                                screen.Puts(x, y, "Disabled");
                    259:                        }
                    260:                } else {
                    261:                        screen.Puts(x, y, attr, "-");
                    262:                }
                    263:                y++;
                    264:                screen.Print(x, y++, attr, "$%06x", 0xece3f0 + i * 0x800);
                    265:                screen.Print(x, y++, attr, "$%06x", 0xee0000 + i * 0x10000);
                    266:                if (installed) {
                    267:                        if (ramsize > 0) {
                    268:                                attr = TA::Normal;
                    269:                        } else {
                    270:                                attr = TA::Disable;
                    271:                        }
                    272:                        screen.Print(x, y, attr, "$%02x", boards[i]->GetPage());
                    273:                } else {
                    274:                        screen.Puts(x, y, attr, "---");
                    275:                }
                    276:        }
                    277: }
                    278: 
                    279: 
                    280: //
                    281: // Nereid ボード1枚分
                    282: //
                    283: 
                    284: // コンストラクタ
                    285: NereidBoardDevice::NereidBoardDevice(int id_)
                    286:        : inherited(OBJ_NEREID_BOARD(id_))
                    287: {
                    288:        id = id_;
                    289: }
                    290: 
                    291: // デストラクタ
                    292: NereidBoardDevice::~NereidBoardDevice()
                    293: {
                    294: }
                    295: 
                    296: bool
                    297: NereidBoardDevice::Create()
                    298: {
                    299:        std::string netname = string_format("nereid%d-net", id);
                    300:        std::string ramname = string_format("nereid%d-ram-size", id);
                    301: 
                    302:        const ConfigItem inet = gConfig->Find(netname);
                    303:        bool net_enable = inet.AsInt();
                    304: 
                    305:        const ConfigItem iramsize = gConfig->Find(ramname);
                    306:        ramsize_MB = iramsize.AsInt();
                    307:        switch (ramsize_MB) {
                    308:         case 0:
                    309:         case 4:
                    310:         case 16:
                    311:         case -4:
                    312:         case -16:
                    313:                // 負数は、バンクメモリ無効時の制御ポート bit6 を明示したい場合用。
                    314:                break;
                    315:         default:
                    316:                iramsize.Err("Valid value is one of 0, 4, 16 (or -4, -16)");
                    317:                return false;
                    318:        }
                    319: 
                    320:        // ネットワークが無効の場合 (これは正常な実機では起きないが)、
                    321:        // RTL8019ASDevice インスタンスの生成自体を行わず、net は NULL。
                    322:        if (net_enable) {
                    323:                int vector;
                    324:                if (id == 0) {
                    325:                        vector = 0xf9;
                    326:                } else {
                    327:                        vector = 0xf8;
                    328:                }
                    329:                net.reset(new RTL8019ASDevice(id, vector));
                    330:        }
                    331: 
                    332:        // バンクメモリは (DIPSW によって) 有効/無効どちらであっても
                    333:        // BankRAMDevice インスタンスの生成自体は行う。
                    334:        // ページレジスタは存在している(はずの)ため。
                    335:        if (ramsize_MB <= 0) {
                    336:                bank.reset(new BankRAMDevice(OBJ_BANKRAM(id), 0));
                    337:        } else {
                    338:                bank.reset(new BankRAMDevice(OBJ_BANKRAM(id), ramsize_MB));
                    339: 
                    340:                // メモリウィンドウ領域の登録はバンクメモリが有効な場合のみ行う。
                    341:                uint32 addr = 0xee0000 + id * 0x10000;
                    342:                auto *x68kio = GetX68kIODevice();
                    343:                x68kio->AddDevice(bank.get(), addr, 0x01'0000);
                    344:        }
                    345:        return true;
                    346: }
                    347: 
                    348: inline uint32
                    349: NereidBoardDevice::Decoder(uint32 addr) const
                    350: {
                    351:        return addr & 0xff;
                    352: }
                    353: 
                    354: uint64
                    355: NereidBoardDevice::Read8(uint32 addr)
                    356: {
                    357:        uint32 offset = Decoder(addr);
                    358: 
                    359:        if (offset < 0x40) {
                    360:                if ((bool)net) {
                    361:                        return net->Read8(addr);
                    362:                }
                    363:        } else if (offset == 0xf0) {
                    364:                return GetPage();
                    365: 
                    366:        } else if (offset == 0xf1) {
                    367:                return GetCtrl();
                    368:        }
                    369:        return (uint64)-1;
                    370: }
                    371: 
                    372: uint64
                    373: NereidBoardDevice::Read16(uint32 addr)
                    374: {
                    375:        uint32 offset = Decoder(addr);
                    376:        uint64 data;
                    377: 
                    378:        if (offset < 0x40) {
                    379:                if ((bool)net) {
                    380:                        return net->Read16(addr);
                    381:                }
                    382:        } else if (offset == 0xf0) {
                    383:                data  = GetPage() << 8;
                    384:                data |= GetCtrl();
                    385:                return data;
                    386:        }
                    387:        return (uint64)-1;
                    388: }
                    389: 
                    390: uint64
                    391: NereidBoardDevice::Write8(uint32 addr, uint32 data)
                    392: {
                    393:        uint32 offset = Decoder(addr);
                    394: 
                    395:        if (offset < 0x40) {
                    396:                if ((bool)net) {
                    397:                        return net->Write8(addr, data);
                    398:                }
                    399:        } else if (offset == 0xf0) {
                    400:                SetPage(data);
                    401:                return 0;
                    402: 
                    403:        } else if (offset == 0xf1) {
                    404:                SetCtrl(data);
                    405:                return 0;
                    406:        }
                    407:        return (uint64)-1;
                    408: }
                    409: 
                    410: uint64
                    411: NereidBoardDevice::Write16(uint32 addr, uint32 data)
                    412: {
                    413:        uint32 offset = Decoder(addr);
                    414: 
                    415:        if (offset < 0x40) {
                    416:                if ((bool)net) {
                    417:                        return net->Write16(addr, data);
                    418:                }
                    419:        } else if (offset == 0xf0) {
                    420:                SetPage(data >> 8);
                    421:                SetCtrl(data & 0xff);
                    422:                return 0;
                    423:        }
                    424:        return (uint64)-1;
                    425: }
                    426: 
                    427: uint64
                    428: NereidBoardDevice::Peek8(uint32 addr)
                    429: {
                    430:        uint32 offset = Decoder(addr);
                    431: 
                    432:        if (offset < 0x40) {
                    433:                if ((bool)net) {
                    434:                        return net->Peek8(addr);
                    435:                }
                    436:        } else if (offset == 0xf0) {
                    437:                return GetPage();
                    438: 
                    439:        } else if (offset == 0xf1) {
                    440:                return GetCtrl();
                    441:        }
                    442:        return (uint64)-1;
                    443: }
                    444: 
                    445: // バンクページ選択レジスタの値を取得。
                    446: uint32
                    447: NereidBoardDevice::GetPage() const
                    448: {
                    449:        return bank->GetPage();
                    450: }
                    451: 
                    452: // バンクページ選択レジスタに値を設定。
                    453: void
                    454: NereidBoardDevice::SetPage(uint32 data)
                    455: {
                    456:        bank->SetPage(data);
                    457: }
                    458: 
                    459: // 制御ポートの値を取得。
                    460: uint32
                    461: NereidBoardDevice::GetCtrl() const
                    462: {
                    463:        uint32 data;
                    464: 
                    465:        // bit7: バンクメモリ有効 (%0=無効、%1=有効)、DIPSW8 が見える
                    466:        // bit6: バンクメモリサイズ (%0=4M、%1=16M)
                    467:        // bit5: バンクメモリウィンドウ (%0=$EE0000、%1=$EF0000)、DIPSW6 が見える
                    468:        // bit4
                    469:        // bit3
                    470:        // bit2: USB 割り込み
                    471:        // bit1: USB 電源
                    472:        // bit0: USB 有効
                    473: 
                    474:        // bit5、バンクメモリウィンドウは $EE0000 なら %0、$EF0000 なら %1 だが、
                    475:        // 現状はボード #0 が $EE0000、ボード #1 が $EF0000 と固定してある。
                    476:        data = id << 5;
                    477: 
                    478:        // bit7、bit6。
                    479:        //
                    480:        // bit6 は DIPSW1=OFF, DIPSW2=OFF (メインメモリへの割り当てなし、
                    481:        // つまり 16MB 全部をバンクメモリに割ける) 時に %1 になる。
                    482:        // まったく実用性はないけど再現できるようにしておく。
                    483:        //
                    484:        // DIP8 DIP1 DIP2   bit7 bit6   BankRAM   nereid?-ram-size=
                    485:        // ---------------+-----------+----------+------
                    486:        // ON   OFF  OFF  :    1    1 : 16MB     | 16
                    487:        // ON   *    *    :    1    0 : 4MB      | 4
                    488:        // OFF  OFF  OFF  :    0    1 : Disabled | 0
                    489:        // OFF  OFF  OFF  :    0    1 : Disabled | -16
                    490:        // OFF  *    *    :    0    0 : Disabled | -4
                    491:        if (ramsize_MB > 0) {
                    492:                data |= 0x80;
                    493:                if (ramsize_MB != 4) {
                    494:                        data |= 0x40;
                    495:                }
                    496:        } else {
                    497:                if (ramsize_MB != -4) {
                    498:                        data |= 0x40;
                    499:                }
                    500:        }
                    501: 
                    502:        // USB 関連は無効なままなので %0
                    503: 
                    504:        return data;
                    505: }
                    506: 
                    507: void
                    508: NereidBoardDevice::SetCtrl(uint32 data)
                    509: {
                    510:        // USB はないので書き込みは無効
                    511: }

unix.superglobalmegacorp.com

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