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