|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // NEWS の I/O 空間担当
9: //
10:
11: // NWS-1750
12: // +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F'0000
13: // e000'0000 |
14: // e010'0000 |
15: // e020'0000 |
16: // e030'0000 |
17: // e040'0000 |
18: // e050'0000 |
19: // e060'0000 |
20: // e070'0000 |
21: // e080'0000 |
22: // e090'0000 |
23: // e0a0'0000 |
24: // e0b0'0000 |
25: // e0c0'0000 | PAR? FDC SIC
26: // e0d0'0000 |KBC SCC RTC LED
27: // e0e0'0000 |MEM DMAC
28: // e0f0'0000 |ETH
29: //
30: // MEM: Lance のメモリ
31:
32: #include "newsio.h"
33: #include "busio.h"
34: #include "config.h"
35: #include "kbc.h"
36: #include "lance.h"
1.1.1.2 root 37: #include "mainbus.h"
1.1 root 38: #include "mk48t02.h"
1.1.1.4 root 39: #include "monitor.h"
1.1 root 40: #include "newsctlr.h"
41: #include "scc.h"
42: #include "subram.h"
43: #include "vm.h"
44:
45: // コンストラクタ
46: NewsIODevice::NewsIODevice()
47: : inherited(OBJ_NEWSIO)
48: {
1.1.1.3 root 49: NEWDV(KBC, new BusIO_B<KBCDevice>());
1.1 root 50: NEWDV(RTC, new BusIO_B<MK48T02Device>());
51: NEWDV(SCC, new BusIO_B<SCCDevice>());
52: NEWDV(Lance, new BusIO_W<LanceDevice>());
53: NEWDV(SubRAM, new SubRAMDevice(16));
54:
1.1.1.2 root 55: // まず NopIO で埋める。
56: // XXX 全域かどうかは分からないが
57: auto nopio = GetNopIODevice();
1.1 root 58: for (int i = 0; i < table.size(); i++) {
1.1.1.2 root 59: table[i] = nopio;
1.1 root 60: }
61:
62: // 少ないので手動で置いていく。
1.1.1.2 root 63: newsctlr = GetNewsCtlrDevice();
1.1 root 64: auto kbc = pKBC.get();
65: auto lance = pLance.get();
66: auto rtc = pRTC.get();
67: auto scc = pSCC.get();
68: auto subram = pSubRAM.get();
69:
70: // table[] は $e0c0'0000 以降を 0x10000 (64KB) 単位にしたもの。
71: #define A(addr) (addr - 0xe0c0)
72:
73: // FDC は現状サポートしていないが (それに機種が違うっぽい?)、
74: // NetBSD の locore.s がリセットのためにアクセスしに来るので
75: // NewsCtlr でついでに対処してある。
76: table[A(0xe0c8)] = newsctlr; // FDC
77: table[A(0xe0d0)] = kbc;
78: table[A(0xe0d4)] = scc;
79: table[A(0xe0d8)] = rtc;
80: table[A(0xe0dc)] = newsctlr; // LED
81: table[A(0xe0e0)] = subram;
82: table[A(0xe0f0)] = lance;
1.1.1.2 root 83:
84: src_screen.Init(75, 64, TextScreen::Ring);
85:
1.1.1.4 root 86: monitor = gMonitorManager->Regist(ID_SUBWIN_NEWSIO, this);
87: monitor->func = ToMonitorCallback(&NewsIODevice::MonitorUpdate);
88: monitor->SetSize(src_screen.GetCol(), 1 + 32);
89: monitor->SetMaxHeight(1 + 64);
1.1 root 90: }
91:
92: // デストラクタ
93: NewsIODevice::~NewsIODevice()
94: {
95: }
96:
97: // 初期化
98: bool
99: NewsIODevice::Init()
100: {
101: const ConfigItem& olditem = gConfig->Find("xxx-news-sci-ignore");
102: const ConfigItem& newitem = gConfig->Find("xxx-news-sic-ignore");
103:
1.1.1.2 root 104: // 指定されていれば警告だけ出してスルーする。
105: if (newitem.GetFrom() != ConfigItem::FromInitial) {
106: newitem.Err("obsoleted");
1.1 root 107: }
1.1.1.2 root 108: if (olditem.GetFrom() != ConfigItem::FromInitial) {
109: olditem.Err("obsoleted");
1.1 root 110: }
111:
1.1.1.2 root 112: // モニタは実行中には変化しないので最初に作っておく。
113: InitMonitor();
114:
1.1 root 115: return true;
116: }
117:
118: // アドレスから該当するデバイスを返す
119: inline IODevice *
120: NewsIODevice::SearchDevice(uint32 addr) const
121: {
122: // アドレスを table のインデックスに変換。ここに来た時点で
123: // $e0'000000 (かそのミラー) の 16MB 内にいることは分かっている。
124: addr &= 0x00ff'ffff;
125: uint idx = (addr - 0x00c0'0000) >> 16;
126: return table[idx];
127: }
128:
1.1.1.2 root 129: busdata
1.1.1.3 root 130: NewsIODevice::Read(busaddr addr)
1.1 root 131: {
1.1.1.3 root 132: IODevice *d = SearchDevice(addr.Addr());
133: return d->Read(addr);
1.1 root 134: }
135:
1.1.1.2 root 136: busdata
1.1.1.3 root 137: NewsIODevice::Write(busaddr addr, uint32 data)
1.1 root 138: {
1.1.1.3 root 139: IODevice *d = SearchDevice(addr.Addr());
140: return d->Write(addr, data);
1.1 root 141: }
142:
1.1.1.2 root 143: busdata
1.1.1.3 root 144: NewsIODevice::Peek1(uint32 addr)
1.1 root 145: {
146: IODevice *d = SearchDevice(addr);
1.1.1.3 root 147: return d->Peek1(addr);
1.1 root 148: }
149:
1.1.1.2 root 150: bool
1.1.1.3 root 151: NewsIODevice::Poke1(uint32 addr, uint32 data)
1.1.1.2 root 152: {
153: IODevice *d = SearchDevice(addr);
1.1.1.3 root 154: return d->Poke1(addr, data);
1.1.1.2 root 155: }
156:
157: // モニタを初期化。
158: void
159: NewsIODevice::InitMonitor()
160: {
161: TextScreen& screen = src_screen;
162: int y = 0;
163:
164: screen.Clear();
165:
166: // 012345678901234567890
167: // $0000'0000: 1234567
168:
169: // table[] は $e0c0 以降なのでここには何もないが
170: // モニタ上の表をきりのいい範囲にするために埋めておく。
171: auto nop = MainbusBaseDevice::FormatDevName(GetNopIODevice());
172: for (uint32 addr = 0xe000; addr < 0xe0c0; ) {
173: screen.Print(0, y, "$%04x'0000:", addr);
174: for (int j = 0; j < 8; j++) {
175: const std::string& name = nop.first;
176: TA attr = nop.second;
177: screen.Puts(12 + j * 8, y, attr, name.c_str());
178: addr++;
179: }
180: y++;
181: }
182:
183: int idx = 0;
184: for (int i = 0; i < table.size() / 8; i++) {
185: uint32 addr = 0xe0c0 + idx;
186: screen.Print(0, y, "$%04x'0000:", addr);
187: for (int j = 0; j < 8; j++) {
188: auto pair = MainbusBaseDevice::FormatDevName(table[idx]);
189: const std::string& name = pair.first;
190: TA attr = pair.second;
191: screen.Print(12 + j * 8, y, attr, "%s", name.c_str());
192: idx++;
193: }
194: y++;
195: }
196:
197: // 下半分は NewsCtlr で処理。
198: newsctlr->MonitorUpdateNewsCtlr(screen, y);
199: }
200:
201: void
202: NewsIODevice::MonitorUpdate(Monitor *, TextScreen& screen)
1.1 root 203: {
1.1.1.2 root 204: // pos が表示開始位置(0-)
205: int pos = (int)screen.userdata;
206:
207: // ヘッダは常に描く
208: screen.Clear();
209: for (int i = 0; i < 8; i++) {
210: screen.Print(12 + i * 8, 0, "+$%x'", i);
211: }
212:
213: // 裏バッファからコピーするだけ。
214: screen.CopyRowsFrom(1, screen.GetRow() - 1, src_screen, pos);
1.1 root 215: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.