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