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

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

unix.superglobalmegacorp.com

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