|
|
nono 1.7.0
//
// nono
// Copyright (C) 2022 nono project
// Licensed under nono-license.txt
//
//
// NEWS の I/O 空間担当
//
// NWS-1750
// +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F'0000
// e000'0000 |
// e010'0000 |
// e020'0000 |
// e030'0000 |
// e040'0000 |
// e050'0000 |
// e060'0000 |
// e070'0000 |
// e080'0000 |
// e090'0000 |
// e0a0'0000 |
// e0b0'0000 |
// e0c0'0000 | PAR? FDC SIC
// e0d0'0000 |KBC SCC RTC LED
// e0e0'0000 |MEM DMAC
// e0f0'0000 |ETH
//
// MEM: Lance のメモリ
#include "newsio.h"
#include "busio.h"
#include "config.h"
#include "kbc.h"
#include "lance.h"
#include "mainbus.h"
#include "mk48t02.h"
#include "monitor.h"
#include "newsctlr.h"
#include "nop.h"
#include "scc.h"
#include "subram.h"
#include "vm.h"
// コンストラクタ
NewsIODevice::NewsIODevice()
: inherited(OBJ_NEWSIO)
{
NEWDV(KBC, new BusIO_B<KBCDevice>());
NEWDV(RTC, new BusIO_B<MK48T02Device>());
NEWDV(SCC, new BusIO_B<SCCDevice>());
NEWDV(Lance, new BusIO_W<LanceDevice>());
NEWDV(SubRAM, new SubRAMDevice(16));
// まず NopIO で埋める。
// XXX 全域かどうかは分からないが
auto nopio = GetNopIODevice();
for (int i = 0; i < table.size(); i++) {
table[i] = nopio;
}
// 少ないので手動で置いていく。
newsctlr = GetNewsCtlrDevice();
auto kbc = pKBC.get();
auto lance = pLance.get();
auto rtc = pRTC.get();
auto scc = pSCC.get();
auto subram = pSubRAM.get();
// table[] は $e0c0'0000 以降を 0x10000 (64KB) 単位にしたもの。
#define A(addr) (addr - 0xe0c0)
// FDC は現状サポートしていないが (それに機種が違うっぽい?)、
// NetBSD の locore.s がリセットのためにアクセスしに来るので
// NewsCtlr でついでに対処してある。
table[A(0xe0c8)] = newsctlr; // FDC
table[A(0xe0d0)] = kbc;
table[A(0xe0d4)] = scc;
table[A(0xe0d8)] = rtc;
table[A(0xe0dc)] = newsctlr; // LED
table[A(0xe0e0)] = subram;
table[A(0xe0f0)] = lance;
src_screen.Init(75, 64, TextScreen::Ring);
monitor = gMonitorManager->Regist(ID_SUBWIN_NEWSIO, this);
monitor->SetCallback(&NewsIODevice::MonitorScreen);
monitor->SetSize(src_screen.GetCol(), 1 + 32);
monitor->SetMaxHeight(1 + 64);
}
// デストラクタ
NewsIODevice::~NewsIODevice()
{
}
// 初期化
bool
NewsIODevice::Init()
{
const ConfigItem& olditem = gConfig->Find("xxx-news-sci-ignore");
const ConfigItem& newitem = gConfig->Find("xxx-news-sic-ignore");
// 指定されていれば警告だけ出してスルーする。
if (newitem.GetFrom() != ConfigItem::FromInitial) {
newitem.Err("obsoleted");
}
if (olditem.GetFrom() != ConfigItem::FromInitial) {
olditem.Err("obsoleted");
}
// モニタは実行中には変化しないので最初に作っておく。
InitMonitor();
return true;
}
// アドレスから該当するデバイスを返す
inline IODevice *
NewsIODevice::SearchDevice(uint32 addr) const
{
// アドレスを table のインデックスに変換。ここに来た時点で
// $e0'000000 (かそのミラー) の 16MB 内にいることは分かっている。
addr &= 0x00ff'ffff;
uint idx = (addr - 0x00c0'0000) >> 16;
return table[idx];
}
busdata
NewsIODevice::Read(busaddr addr)
{
IODevice *d = SearchDevice(addr.Addr());
return d->Read(addr);
}
busdata
NewsIODevice::Write(busaddr addr, uint32 data)
{
IODevice *d = SearchDevice(addr.Addr());
return d->Write(addr, data);
}
busdata
NewsIODevice::Peek1(uint32 addr)
{
IODevice *d = SearchDevice(addr);
return d->Peek1(addr);
}
bool
NewsIODevice::Poke1(uint32 addr, uint32 data)
{
IODevice *d = SearchDevice(addr);
return d->Poke1(addr, data);
}
// モニタを初期化。
void
NewsIODevice::InitMonitor()
{
TextScreen& screen = src_screen;
int y = 0;
screen.Clear();
// 012345678901234567890
// $0000'0000: 1234567
// table[] は $e0c0 以降なのでここには何もないが
// モニタ上の表をきりのいい範囲にするために埋めておく。
auto nop = MainbusBaseDevice::FormatDevName(GetNopIODevice());
for (uint32 addr = 0xe000; addr < 0xe0c0; ) {
screen.Print(0, y, "$%04x'0000:", addr);
for (int j = 0; j < 8; j++) {
const std::string& name = nop.first;
TA attr = nop.second;
screen.Puts(12 + j * 8, y, attr, name.c_str());
addr++;
}
y++;
}
int idx = 0;
for (int i = 0; i < table.size() / 8; i++) {
uint32 addr = 0xe0c0 + idx;
screen.Print(0, y, "$%04x'0000:", addr);
for (int j = 0; j < 8; j++) {
auto pair = MainbusBaseDevice::FormatDevName(table[idx]);
const std::string& name = pair.first;
TA attr = pair.second;
screen.Print(12 + j * 8, y, attr, "%s", name.c_str());
idx++;
}
y++;
}
// 下半分は NewsCtlr で処理。
newsctlr->MonitorScreenNewsCtlr(screen, y);
}
void
NewsIODevice::MonitorScreen(Monitor *, TextScreen& screen)
{
// pos が表示開始位置(0-)
int pos = (int)screen.userdata;
// ヘッダは常に描く
screen.Clear();
for (int i = 0; i < 8; i++) {
screen.Print(12 + i * 8, 0, "+$%x'", i);
}
// 裏バッファからコピーするだけ。
screen.CopyRowsFrom(1, screen.GetRow() - 1, src_screen, pos);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.