|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.