|
|
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"
39: #include "newsctlr.h"
40: #include "scc.h"
41: #include "subram.h"
42: #include "vm.h"
43:
44: // コンストラクタ
45: NewsIODevice::NewsIODevice()
46: : inherited(OBJ_NEWSIO)
47: {
48: NEWDV(KBC, new KBCDevice());
49: NEWDV(RTC, new BusIO_B<MK48T02Device>());
50: NEWDV(SCC, new BusIO_B<SCCDevice>());
51: NEWDV(Lance, new BusIO_W<LanceDevice>());
52: NEWDV(SubRAM, new SubRAMDevice(16));
53:
1.1.1.2 ! root 54: // まず NopIO で埋める。
! 55: // XXX 全域かどうかは分からないが
! 56: auto nopio = GetNopIODevice();
1.1 root 57: for (int i = 0; i < table.size(); i++) {
1.1.1.2 ! root 58: table[i] = nopio;
1.1 root 59: }
60:
61: // 少ないので手動で置いていく。
1.1.1.2 ! root 62: newsctlr = GetNewsCtlrDevice();
1.1 root 63: auto kbc = pKBC.get();
64: auto lance = pLance.get();
65: auto rtc = pRTC.get();
66: auto scc = pSCC.get();
67: auto subram = pSubRAM.get();
68:
69: // table[] は $e0c0'0000 以降を 0x10000 (64KB) 単位にしたもの。
70: #define A(addr) (addr - 0xe0c0)
71:
72: // FDC は現状サポートしていないが (それに機種が違うっぽい?)、
73: // NetBSD の locore.s がリセットのためにアクセスしに来るので
74: // NewsCtlr でついでに対処してある。
75: table[A(0xe0c8)] = newsctlr; // FDC
76: table[A(0xe0d0)] = kbc;
77: table[A(0xe0d4)] = scc;
78: table[A(0xe0d8)] = rtc;
79: table[A(0xe0dc)] = newsctlr; // LED
80: table[A(0xe0e0)] = subram;
81: table[A(0xe0f0)] = lance;
1.1.1.2 ! root 82:
! 83: src_screen.Init(75, 64, TextScreen::Ring);
! 84:
! 85: monitor.func = ToMonitorCallback(&NewsIODevice::MonitorUpdate);
! 86: monitor.SetSize(src_screen.GetCol(), 1 + 32);
! 87: monitor.SetMaxHeight(1 + 64);
! 88: monitor.Regist(ID_SUBWIN_NEWSIO);
! 89:
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 root 134: NewsIODevice::Read8(uint32 addr)
135: {
136: IODevice *d = SearchDevice(addr);
137: return d->Read8(addr);
138: }
139:
1.1.1.2 ! root 140: busdata
1.1 root 141: NewsIODevice::Read16(uint32 addr)
142: {
143: IODevice *d = SearchDevice(addr);
144: return d->Read16(addr);
145: }
146:
1.1.1.2 ! root 147: busdata
1.1 root 148: NewsIODevice::Read32(uint32 addr)
149: {
150: IODevice *d = SearchDevice(addr);
151: return d->Read32(addr);
152: }
153:
1.1.1.2 ! root 154: busdata
1.1 root 155: NewsIODevice::Write8(uint32 addr, uint32 data)
156: {
157: IODevice *d = SearchDevice(addr);
158: return d->Write8(addr, data);
159: }
160:
1.1.1.2 ! root 161: busdata
1.1 root 162: NewsIODevice::Write16(uint32 addr, uint32 data)
163: {
164: IODevice *d = SearchDevice(addr);
165: return d->Write16(addr, data);
166: }
167:
1.1.1.2 ! root 168: busdata
1.1 root 169: NewsIODevice::Write32(uint32 addr, uint32 data)
170: {
171: IODevice *d = SearchDevice(addr);
172: return d->Write32(addr, data);
173: }
174:
1.1.1.2 ! root 175: busdata
1.1 root 176: NewsIODevice::Peek8(uint32 addr)
177: {
178: IODevice *d = SearchDevice(addr);
179: return d->Peek8(addr);
180: }
181:
1.1.1.2 ! root 182: bool
! 183: NewsIODevice::Poke8(uint32 addr, uint32 data)
! 184: {
! 185: IODevice *d = SearchDevice(addr);
! 186: return d->Poke8(addr, data);
! 187: }
! 188:
! 189: // モニタを初期化。
! 190: void
! 191: NewsIODevice::InitMonitor()
! 192: {
! 193: TextScreen& screen = src_screen;
! 194: int y = 0;
! 195:
! 196: screen.Clear();
! 197:
! 198: // 012345678901234567890
! 199: // $0000'0000: 1234567
! 200:
! 201: // table[] は $e0c0 以降なのでここには何もないが
! 202: // モニタ上の表をきりのいい範囲にするために埋めておく。
! 203: auto nop = MainbusBaseDevice::FormatDevName(GetNopIODevice());
! 204: for (uint32 addr = 0xe000; addr < 0xe0c0; ) {
! 205: screen.Print(0, y, "$%04x'0000:", addr);
! 206: for (int j = 0; j < 8; j++) {
! 207: const std::string& name = nop.first;
! 208: TA attr = nop.second;
! 209: screen.Puts(12 + j * 8, y, attr, name.c_str());
! 210: addr++;
! 211: }
! 212: y++;
! 213: }
! 214:
! 215: int idx = 0;
! 216: for (int i = 0; i < table.size() / 8; i++) {
! 217: uint32 addr = 0xe0c0 + idx;
! 218: screen.Print(0, y, "$%04x'0000:", addr);
! 219: for (int j = 0; j < 8; j++) {
! 220: auto pair = MainbusBaseDevice::FormatDevName(table[idx]);
! 221: const std::string& name = pair.first;
! 222: TA attr = pair.second;
! 223: screen.Print(12 + j * 8, y, attr, "%s", name.c_str());
! 224: idx++;
! 225: }
! 226: y++;
! 227: }
! 228:
! 229: // 下半分は NewsCtlr で処理。
! 230: newsctlr->MonitorUpdateNewsCtlr(screen, y);
! 231: }
! 232:
! 233: void
! 234: NewsIODevice::MonitorUpdate(Monitor *, TextScreen& screen)
1.1 root 235: {
1.1.1.2 ! root 236: // pos が表示開始位置(0-)
! 237: int pos = (int)screen.userdata;
! 238:
! 239: // ヘッダは常に描く
! 240: screen.Clear();
! 241: for (int i = 0; i < 8; i++) {
! 242: screen.Print(12 + i * 8, 0, "+$%x'", i);
! 243: }
! 244:
! 245: // 裏バッファからコピーするだけ。
! 246: screen.CopyRowsFrom(1, screen.GetRow() - 1, src_screen, pos);
1.1 root 247: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.