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

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"
1.1.1.4 ! root       53: #include "monitor.h"
1.1       root       54: #include "rtl8019as.h"
                     55: 
                     56: //
                     57: // Nereid 空間担当デバイス
                     58: //
                     59: 
                     60: // boards[0]、board[1] を所有し、アクセスをディスパッチする。
                     61: 
                     62: // コンストラクタ
                     63: NereidDevice::NereidDevice()
                     64:        : inherited(OBJ_NEREID)
                     65: {
1.1.1.4 ! root       66:        monitor = gMonitorManager->Regist(ID_MONITOR_NEREID, this);
        !            67:        monitor->func = ToMonitorCallback(&NereidDevice::MonitorUpdate);
        !            68:        monitor->SetSize(41, 9);
1.1       root       69: }
                     70: 
                     71: // デストラクタ
                     72: NereidDevice::~NereidDevice()
                     73: {
                     74: }
                     75: 
                     76: // デバイス作成
                     77: bool
                     78: NereidDevice::Create()
                     79: {
1.1.1.3   root       80:        // ボードの有無は nereid%u-enable だけで決まる。
1.1       root       81:        for (int i = 0; i < 2; i++) {
1.1.1.3   root       82:                std::string name = string_format("nereid%u-enable", i);
1.1       root       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: 
1.1.1.2   root      120: busdata
1.1.1.3   root      121: NereidDevice::Read(busaddr addr)
1.1       root      122: {
1.1.1.3   root      123:        uint32 paddr = addr.Addr();
1.1       root      124: 
1.1.1.3   root      125:        putlog(2, "Read  $%06x.%c", paddr, (addr.GetSize() == 1 ? 'B' : 'W'));
1.1       root      126: 
1.1.1.3   root      127:        uint32 cs = Decoder(paddr);
1.1       root      128:        for (int i = 0; i < boards.size(); i++) {
                    129:                if (cs == loc[i]) {
1.1.1.3   root      130:                        return boards[i]->Read(addr);
1.1       root      131:                }
                    132:        }
                    133: 
1.1.1.3   root      134:        return BusData::BusErr;
1.1       root      135: }
                    136: 
1.1.1.2   root      137: busdata
1.1.1.3   root      138: NereidDevice::Write(busaddr addr, uint32 data)
1.1       root      139: {
1.1.1.3   root      140:        uint32 paddr = addr.Addr();
1.1       root      141: 
1.1.1.3   root      142:        putlog(2, "Write $%06x.%c", paddr, (addr.GetSize() == 1 ? 'B' : 'W'));
                    143: 
                    144:        uint32 cs = Decoder(paddr);
1.1       root      145:        for (int i = 0; i < boards.size(); i++) {
                    146:                if (cs == loc[i]) {
1.1.1.3   root      147:                        return boards[i]->Write(addr, data);
1.1       root      148:                }
                    149:        }
1.1.1.3   root      150:        return BusData::BusErr;
1.1       root      151: }
                    152: 
1.1.1.2   root      153: busdata
1.1.1.3   root      154: NereidDevice::Peek1(uint32 addr)
1.1       root      155: {
                    156:        uint32 cs = Decoder(addr);
                    157: 
                    158:        for (int i = 0; i < boards.size(); i++) {
                    159:                if (cs == loc[i]) {
1.1.1.3   root      160:                        return boards[i]->Peek1(addr);
1.1       root      161:                }
                    162:        }
1.1.1.3   root      163:        return BusData::BusErr;
1.1       root      164: }
                    165: 
                    166: void
                    167: NereidDevice::MonitorUpdate(Monitor *, TextScreen& screen)
                    168: {
                    169:        int y;
                    170: 
                    171:        screen.Clear();
                    172: 
                    173:        // 0123456789012345678901234567890123456789
                    174:        //                #0           #1
                    175:        // Board        : NotInstalled NotInstalled
                    176:        //  Ethernet    : Enable
                    177:        //   Address    : $ece300
                    178:        //   Vector     : $f9
                    179:        //  Bank Memory : 16MB
                    180:        //   Page Select: $ece380
                    181:        //   Bank Window: $ee0000
                    182:        //   CurrentPage: $00
                    183: 
                    184:        y = 1;
                    185:        screen.Puts(0, y++, "Board        :");
                    186:        screen.Puts(1, y++,  "Ethernet    :");
                    187:        screen.Puts(2, y++,   "Address    :");
                    188:        screen.Puts(2, y++,   "Vector     :");
                    189:        screen.Puts(1, y++,  "Bank Memory :");
                    190:        screen.Puts(2, y++,   "Page Select:");
                    191:        screen.Puts(2, y++,   "Bank Window:");
                    192:        screen.Puts(2, y++,   "CurrentPage:");
                    193: 
                    194:        for (int i = 0; i < 2; i++) {
                    195:                int x = 15 + i * 14;
                    196:                TA attr;
                    197: 
                    198:                y = 0;
1.1.1.3   root      199:                screen.Print(x, y++, "#%u", i);
1.1       root      200: 
                    201:                // ボードがささっているか
                    202:                bool installed = (bool)boards[i];
                    203:                if (installed) {
                    204:                        screen.Puts(x, y, "Installed");
                    205:                } else {
                    206:                        screen.Puts(x, y, "NotInstalled");
                    207:                }
                    208:                y++;
                    209: 
                    210:                // イーサネット
                    211:                attr = TA::Disable;
                    212:                if (installed) {
                    213:                        if (boards[i]->IsNetEnable()) {
                    214:                                screen.Puts(x, y, "Available");
                    215:                                attr = TA::Normal;
                    216:                        } else {
                    217:                                screen.Puts(x, y, "NotAvailable");
                    218:                        }
                    219:                } else {
                    220:                        screen.Puts(x, y, attr, "-");
                    221:                }
                    222:                y++;
                    223:                screen.Print(x, y++, attr, "$%06x", 0xece300 + i * 0x800);
                    224:                screen.Print(x, y++, attr, "$%02x", 0xf9 - i);
                    225: 
                    226:                // バンクメモリ
                    227:                attr = TA::Disable;
                    228:                int ramsize = 0;
                    229:                if (installed) {
                    230:                        ramsize = boards[i]->GetBankRAMSize();
                    231:                        if (ramsize > 0) {
1.1.1.3   root      232:                                screen.Print(x, y, "%u MB", ramsize);
1.1       root      233:                                attr = TA::Normal;
                    234:                        } else {
                    235:                                screen.Puts(x, y, "Disabled");
                    236:                        }
                    237:                } else {
                    238:                        screen.Puts(x, y, attr, "-");
                    239:                }
                    240:                y++;
                    241:                screen.Print(x, y++, attr, "$%06x", 0xece3f0 + i * 0x800);
                    242:                screen.Print(x, y++, attr, "$%06x", 0xee0000 + i * 0x10000);
                    243:                if (installed) {
                    244:                        if (ramsize > 0) {
                    245:                                attr = TA::Normal;
                    246:                        } else {
                    247:                                attr = TA::Disable;
                    248:                        }
                    249:                        screen.Print(x, y, attr, "$%02x", boards[i]->GetPage());
                    250:                } else {
                    251:                        screen.Puts(x, y, attr, "---");
                    252:                }
                    253:        }
                    254: }
                    255: 
                    256: 
                    257: //
                    258: // Nereid ボード1枚分
                    259: //
                    260: 
                    261: // コンストラクタ
                    262: NereidBoardDevice::NereidBoardDevice(int id_)
                    263:        : inherited(OBJ_NEREID_BOARD(id_))
                    264: {
                    265:        id = id_;
                    266: }
                    267: 
                    268: // デストラクタ
                    269: NereidBoardDevice::~NereidBoardDevice()
                    270: {
                    271: }
                    272: 
                    273: bool
                    274: NereidBoardDevice::Create()
                    275: {
1.1.1.3   root      276:        std::string netname = string_format("nereid%u-net", id);
                    277:        std::string ramname = string_format("nereid%u-ram-size", id);
1.1       root      278: 
                    279:        const ConfigItem inet = gConfig->Find(netname);
                    280:        bool net_enable = inet.AsInt();
                    281: 
                    282:        const ConfigItem iramsize = gConfig->Find(ramname);
                    283:        ramsize_MB = iramsize.AsInt();
                    284:        switch (ramsize_MB) {
                    285:         case 0:
                    286:         case 4:
                    287:         case 16:
                    288:         case -4:
                    289:         case -16:
                    290:                // 負数は、バンクメモリ無効時の制御ポート bit6 を明示したい場合用。
                    291:                break;
                    292:         default:
                    293:                iramsize.Err("Valid value is one of 0, 4, 16 (or -4, -16)");
                    294:                return false;
                    295:        }
                    296: 
                    297:        // ネットワークが無効の場合 (これは正常な実機では起きないが)、
                    298:        // RTL8019ASDevice インスタンスの生成自体を行わず、net は NULL。
                    299:        if (net_enable) {
                    300:                int vector;
                    301:                if (id == 0) {
                    302:                        vector = 0xf9;
                    303:                } else {
                    304:                        vector = 0xf8;
                    305:                }
                    306:                net.reset(new RTL8019ASDevice(id, vector));
                    307:        }
                    308: 
                    309:        // バンクメモリは (DIPSW によって) 有効/無効どちらであっても
                    310:        // BankRAMDevice インスタンスの生成自体は行う。
                    311:        // ページレジスタは存在している(はずの)ため。
                    312:        if (ramsize_MB <= 0) {
                    313:                bank.reset(new BankRAMDevice(OBJ_BANKRAM(id), 0));
                    314:        } else {
                    315:                bank.reset(new BankRAMDevice(OBJ_BANKRAM(id), ramsize_MB));
1.1.1.2   root      316:                // I/O 空間への登録は X68kIO 側から行っている。
1.1       root      317:        }
                    318:        return true;
                    319: }
                    320: 
                    321: inline uint32
                    322: NereidBoardDevice::Decoder(uint32 addr) const
                    323: {
                    324:        return addr & 0xff;
                    325: }
                    326: 
1.1.1.2   root      327: busdata
1.1.1.3   root      328: NereidBoardDevice::Read(busaddr addr)
1.1       root      329: {
1.1.1.3   root      330:        busdata data = BusData::BusErr;
1.1       root      331: 
1.1.1.3   root      332:        uint32 paddr = addr.Addr();
                    333:        uint32 offset = Decoder(paddr);
1.1       root      334: 
                    335:        if (offset < 0x40) {
                    336:                if ((bool)net) {
1.1.1.3   root      337:                        return net->Read(addr);
1.1       root      338:                }
1.1.1.3   root      339:        } else {
                    340:                uint32 reqsize = addr.GetSize();
                    341:                uint32 datasize = std::min(2 - (paddr & 1), reqsize);
                    342:                if (datasize == 1) {
                    343:                        if (offset == 0xf0) {
                    344:                                data = GetPage();
                    345:                        } else if (offset == 0xf1) {
                    346:                                data = GetCtrl();
                    347:                        }
                    348:                        data |= BusData::Size1;
                    349:                } else {
                    350:                        if (offset == 0xf0) {
                    351:                                data  = GetPage() << 8;
                    352:                                data |= GetCtrl();
                    353:                        }
                    354:                        data |= BusData::Size2;
1.1       root      355:                }
                    356:        }
1.1.1.3   root      357:        return data;
1.1       root      358: }
                    359: 
1.1.1.2   root      360: busdata
1.1.1.3   root      361: NereidBoardDevice::Write(busaddr addr, uint32 data)
1.1       root      362: {
1.1.1.3   root      363:        busdata r;
                    364: 
                    365:        uint32 paddr = addr.Addr();
                    366:        uint32 offset = Decoder(paddr);
1.1       root      367: 
                    368:        if (offset < 0x40) {
                    369:                if ((bool)net) {
1.1.1.3   root      370:                        return net->Write(addr, data);
                    371:                }
                    372:        } else {
                    373:                uint32 reqsize = addr.GetSize();
                    374:                uint32 datasize = std::min(2 - (paddr & 1), reqsize);
                    375:                data >>= (reqsize - datasize) * 8;
                    376:                if (datasize == 1) {
                    377:                        if (offset == 0xf0) {
                    378:                                SetPage(data);
                    379:                        } else if (offset == 0xf1) {
                    380:                                SetCtrl(data);
                    381:                        } else {
                    382:                                r.SetBusErr();
                    383:                        }
                    384:                        r |= BusData::Size1;
                    385:                } else {
                    386:                        if (offset == 0xf0) {
                    387:                                SetPage(data >> 8);
                    388:                                SetCtrl(data & 0xff);
                    389:                        } else {
                    390:                                r.SetBusErr();
                    391:                        }
                    392:                        r |= BusData::Size2;
1.1       root      393:                }
                    394:        }
1.1.1.3   root      395:        return r;
1.1       root      396: }
                    397: 
1.1.1.2   root      398: busdata
1.1.1.3   root      399: NereidBoardDevice::Peek1(uint32 addr)
1.1       root      400: {
                    401:        uint32 offset = Decoder(addr);
                    402: 
                    403:        if (offset < 0x40) {
                    404:                if ((bool)net) {
1.1.1.3   root      405:                        return net->Peek1(addr);
1.1       root      406:                }
                    407:        } else if (offset == 0xf0) {
                    408:                return GetPage();
                    409: 
                    410:        } else if (offset == 0xf1) {
                    411:                return GetCtrl();
                    412:        }
1.1.1.3   root      413:        return BusData::BusErr;
1.1       root      414: }
                    415: 
                    416: // バンクページ選択レジスタの値を取得。
                    417: uint32
                    418: NereidBoardDevice::GetPage() const
                    419: {
                    420:        return bank->GetPage();
                    421: }
                    422: 
                    423: // バンクページ選択レジスタに値を設定。
                    424: void
                    425: NereidBoardDevice::SetPage(uint32 data)
                    426: {
                    427:        bank->SetPage(data);
                    428: }
                    429: 
                    430: // 制御ポートの値を取得。
                    431: uint32
                    432: NereidBoardDevice::GetCtrl() const
                    433: {
                    434:        uint32 data;
                    435: 
                    436:        // bit7: バンクメモリ有効 (%0=無効、%1=有効)、DIPSW8 が見える
                    437:        // bit6: バンクメモリサイズ (%0=4M、%1=16M)
                    438:        // bit5: バンクメモリウィンドウ (%0=$EE0000、%1=$EF0000)、DIPSW6 が見える
                    439:        // bit4
                    440:        // bit3
                    441:        // bit2: USB 割り込み
                    442:        // bit1: USB 電源
                    443:        // bit0: USB 有効
                    444: 
                    445:        // bit5、バンクメモリウィンドウは $EE0000 なら %0、$EF0000 なら %1 だが、
                    446:        // 現状はボード #0 が $EE0000、ボード #1 が $EF0000 と固定してある。
                    447:        data = id << 5;
                    448: 
                    449:        // bit7、bit6。
                    450:        //
                    451:        // bit6 は DIPSW1=OFF, DIPSW2=OFF (メインメモリへの割り当てなし、
                    452:        // つまり 16MB 全部をバンクメモリに割ける) 時に %1 になる。
                    453:        // まったく実用性はないけど再現できるようにしておく。
                    454:        //
                    455:        // DIP8 DIP1 DIP2   bit7 bit6   BankRAM   nereid?-ram-size=
                    456:        // ---------------+-----------+----------+------
                    457:        // ON   OFF  OFF  :    1    1 : 16MB     | 16
                    458:        // ON   *    *    :    1    0 : 4MB      | 4
                    459:        // OFF  OFF  OFF  :    0    1 : Disabled | 0
                    460:        // OFF  OFF  OFF  :    0    1 : Disabled | -16
                    461:        // OFF  *    *    :    0    0 : Disabled | -4
                    462:        if (ramsize_MB > 0) {
                    463:                data |= 0x80;
                    464:                if (ramsize_MB != 4) {
                    465:                        data |= 0x40;
                    466:                }
                    467:        } else {
                    468:                if (ramsize_MB != -4) {
                    469:                        data |= 0x40;
                    470:                }
                    471:        }
                    472: 
                    473:        // USB 関連は無効なままなので %0
                    474: 
                    475:        return data;
                    476: }
                    477: 
                    478: void
                    479: NereidBoardDevice::SetCtrl(uint32 data)
                    480: {
                    481:        // USB はないので書き込みは無効
                    482: }

unix.superglobalmegacorp.com

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