|
|
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: if (inherited::Init() == false) {
102: return false;
103: }
104:
105: const ConfigItem& olditem = gConfig->Find("xxx-news-sci-ignore");
106: const ConfigItem& newitem = gConfig->Find("xxx-news-sic-ignore");
107:
1.1.1.2 root 108: // 指定されていれば警告だけ出してスルーする。
109: if (newitem.GetFrom() != ConfigItem::FromInitial) {
110: newitem.Err("obsoleted");
1.1 root 111: }
1.1.1.2 root 112: if (olditem.GetFrom() != ConfigItem::FromInitial) {
113: olditem.Err("obsoleted");
1.1 root 114: }
115:
1.1.1.2 root 116: // モニタは実行中には変化しないので最初に作っておく。
117: InitMonitor();
118:
1.1 root 119: return true;
120: }
121:
122: // アドレスから該当するデバイスを返す
123: inline IODevice *
124: NewsIODevice::SearchDevice(uint32 addr) const
125: {
126: // アドレスを table のインデックスに変換。ここに来た時点で
127: // $e0'000000 (かそのミラー) の 16MB 内にいることは分かっている。
128: addr &= 0x00ff'ffff;
129: uint idx = (addr - 0x00c0'0000) >> 16;
130: return table[idx];
131: }
132:
1.1.1.2 root 133: busdata
1.1.1.3 root 134: NewsIODevice::Read(busaddr addr)
1.1 root 135: {
1.1.1.3 root 136: IODevice *d = SearchDevice(addr.Addr());
137: return d->Read(addr);
1.1 root 138: }
139:
1.1.1.2 root 140: busdata
1.1.1.3 root 141: NewsIODevice::Write(busaddr addr, uint32 data)
1.1 root 142: {
1.1.1.3 root 143: IODevice *d = SearchDevice(addr.Addr());
144: return d->Write(addr, data);
1.1 root 145: }
146:
1.1.1.2 root 147: busdata
1.1.1.3 root 148: NewsIODevice::Peek1(uint32 addr)
1.1 root 149: {
150: IODevice *d = SearchDevice(addr);
1.1.1.3 root 151: return d->Peek1(addr);
1.1 root 152: }
153:
1.1.1.2 root 154: bool
1.1.1.3 root 155: NewsIODevice::Poke1(uint32 addr, uint32 data)
1.1.1.2 root 156: {
157: IODevice *d = SearchDevice(addr);
1.1.1.3 root 158: return d->Poke1(addr, data);
1.1.1.2 root 159: }
160:
161: // モニタを初期化。
162: void
163: NewsIODevice::InitMonitor()
164: {
165: TextScreen& screen = src_screen;
166: int y = 0;
167:
168: screen.Clear();
169:
170: // 012345678901234567890
171: // $0000'0000: 1234567
172:
173: // table[] は $e0c0 以降なのでここには何もないが
174: // モニタ上の表をきりのいい範囲にするために埋めておく。
175: auto nop = MainbusBaseDevice::FormatDevName(GetNopIODevice());
176: for (uint32 addr = 0xe000; addr < 0xe0c0; ) {
177: screen.Print(0, y, "$%04x'0000:", addr);
178: for (int j = 0; j < 8; j++) {
179: const std::string& name = nop.first;
180: TA attr = nop.second;
181: screen.Puts(12 + j * 8, y, attr, name.c_str());
182: addr++;
183: }
184: y++;
185: }
186:
187: int idx = 0;
188: for (int i = 0; i < table.size() / 8; i++) {
189: uint32 addr = 0xe0c0 + idx;
190: screen.Print(0, y, "$%04x'0000:", addr);
191: for (int j = 0; j < 8; j++) {
192: auto pair = MainbusBaseDevice::FormatDevName(table[idx]);
193: const std::string& name = pair.first;
194: TA attr = pair.second;
195: screen.Print(12 + j * 8, y, attr, "%s", name.c_str());
196: idx++;
197: }
198: y++;
199: }
200:
201: // 下半分は NewsCtlr で処理。
202: newsctlr->MonitorUpdateNewsCtlr(screen, y);
203: }
204:
205: void
206: NewsIODevice::MonitorUpdate(Monitor *, TextScreen& screen)
1.1 root 207: {
1.1.1.2 root 208: // pos が表示開始位置(0-)
209: int pos = (int)screen.userdata;
210:
211: // ヘッダは常に描く
212: screen.Clear();
213: for (int i = 0; i < 8; i++) {
214: screen.Print(12 + i * 8, 0, "+$%x'", i);
215: }
216:
217: // 裏バッファからコピーするだけ。
218: screen.CopyRowsFrom(1, screen.GetRow() - 1, src_screen, pos);
1.1 root 219: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.