--- nono/vm/pio.cpp 2026/04/29 17:04:36 1.1.1.2 +++ nono/vm/pio.cpp 2026/04/29 17:04:55 1.1.1.8 @@ -7,7 +7,7 @@ #include "pio.h" #include "config.h" #include "lcd.h" -#include "mystring.h" +#include "mainapp.h" #include "scheduler.h" // IODevice @@ -20,6 +20,7 @@ // PPIDevice PIO0Device PIO1Device // (X68030) (LUNA) (LUNA) +std::unique_ptr gPPI; std::unique_ptr gPIO0; std::unique_ptr gPIO1; @@ -28,7 +29,8 @@ std::unique_ptr gPIO1; // // コンストラクタ -i8255Device::i8255Device() +i8255Device::i8255Device(const std::string& objname_) + : inherited(objname_) { } @@ -37,6 +39,17 @@ i8255Device::~i8255Device() { } +// リセット +void +i8255Device::ResetHard() +{ + // clears the control register + // and place ports A, B, and C in input mode. + // The input latches in ports A, B, and C are not cleared. + + ctrl = 0b10011011; +} + // コントロールポートへの書き込み。 void i8255Device::WriteCtrl(uint32 data) @@ -82,10 +95,8 @@ i8255Device::SetPC(int pc, int data) // コンストラクタ PPIDevice::PPIDevice() - : inherited() + : inherited("PPI") { - logname = "pio"; - devname = "PPI"; devaddr = baseaddr; devlen = 0x2000; } @@ -96,17 +107,19 @@ PPIDevice::~PPIDevice() } uint64 -PPIDevice::Read(uint32 addr) +PPIDevice::Read(uint32 offset) { - switch (addr) { + gMPU->AddCycle(19); // InsideOut p.135 + + switch (offset) { case 0: case 1: return 0xff; case 2: - PANIC("PPI $E9A005 未サポート読み込み"); - break; + putlog(0, "$e9a005 PortC 未実装読み込み"); + return 0xff; case 3: - PANIC("PPI $E9A007 未サポート読み込み"); + PANIC("PPI $e9a007 未サポート読み込み"); break; default: __unreachable(); @@ -115,20 +128,22 @@ PPIDevice::Read(uint32 addr) } uint64 -PPIDevice::Write(uint32 addr, uint32 data) +PPIDevice::Write(uint32 offset, uint32 data) { - switch (addr) { + gMPU->AddCycle(19); // InsideOut p.135 + + switch (offset) { case 0: case 1: break; case 2: - putlog(0, "$E9A005 未実装書き込み $%02X (無視)", data); + putlog(0, "$e9a005 未実装書き込み $%02X (無視)", data); break; case 3: if (data != 0x92) { - PANIC("PPI $E9A007 未実装書き込み $%02X", data); + PANIC("PPI $e9a007 未実装書き込み $%02X", data); } else { - putlog(0, "$E9A007 未実装書き込み $%02x (無視)", data); + putlog(0, "$e9a007 未実装書き込み $%02x (無視)", data); } break; default: @@ -138,7 +153,7 @@ PPIDevice::Write(uint32 addr, uint32 dat } uint64 -PPIDevice::Peek(uint32 addr) +PPIDevice::Peek(uint32 offset) { // XXX return 0xff; @@ -157,6 +172,7 @@ PPIDevice::Peek(uint32 addr) // 変数は dipsw{1,2}[0..7] に対応。 // 設定ファイルと変数の値は %0 が down を表し、%1 が up を表す。 // +// LUNA-1: // #1-1 up なら UNIX をロードして移行。down なら ROM モニタで起動。 // #1-2 up ならディスプレイコンソール。down ならシリアルコンソール。 // #1-3 up - color display, down - force to have monochrome display @@ -173,17 +189,40 @@ PPIDevice::Peek(uint32 addr) // あれば /boot がプロンプトで停止。これは ROM ではなく NetBSD のブート // ローダの話。 // どこか由来のソースコードらしいがたぶんビット演算を間違えている。 +// +// LUNA88K: +// #1-1 up なら ROM モニタで停止、down ならマルチユーザブート。 +// OpenBSD カーネルも up なら UserKernelConfig で止まる模様?。 +// #1-2 up なら外付けシリアルコンソール、down なら内蔵ビットマップ。 +// #1-3..#1-8 は予約。 +// #2-x はユーザ(?) // コンストラクタ PIO0Device::PIO0Device() - : inherited() + : inherited("PIO0") { - logname = "pio0"; - devname = "PIO0"; devaddr = 0x49000000; devlen = 4; - monitor.Init(22, 11); + // 機種固有パラメータ + + // LUNA-1 と LUNA88K で使いやすいように初期値を変えておく。 + switch (gMainApp.GetVMType()) { + case VMTYPE_LUNA1: + gConfig->SetDefault("luna-dipsw1", "11110111"); + break; + case VMTYPE_LUNA88K: + gConfig->SetDefault("luna-dipsw1", "11111111"); + break; + default: + __unreachable(); + } + // DIP-SW#2 はユーザ定義(?)なので(今の所?)どちらも共通。 + gConfig->SetDefault("luna-dipsw2", "11111111"); + + monitor.func = (MonitorCallback_t)&PIO0Device::MonitorUpdate; + monitor.SetSize(22, 11); + monitor.Regist(ID_MONITOR_PIO0); } // デストラクタ @@ -216,12 +255,14 @@ PIO0Device::Init() return true; } +// XXX PowerOn か ResetHard 未調査 + uint64 -PIO0Device::Read(uint32 addr) +PIO0Device::Read(uint32 offset) { uint32 data; - switch (addr) { + switch (offset) { case 0: // PortA putlog(1, "DIP-SW 1 読み込み"); @@ -235,7 +276,7 @@ PIO0Device::Read(uint32 addr) case 2: // PortC data = GetPC(); - putlog(1, "PC 読み込み -> $%02x", data); + putlog(1, "PC 読み込み -> $%02x", data); return data; case 3: @@ -249,9 +290,9 @@ PIO0Device::Read(uint32 addr) } uint64 -PIO0Device::Write(uint32 addr, uint32 data) +PIO0Device::Write(uint32 offset, uint32 data) { - switch (addr) { + switch (offset) { case 0: // PIO0 PortA: DIPSW1 (入力のみ) case 1: // PIO0 PortB: DIPSW2 (入力のみ) return 0; @@ -273,9 +314,9 @@ PIO0Device::Write(uint32 addr, uint32 da } uint64 -PIO0Device::Peek(uint32 addr) +PIO0Device::Peek(uint32 offset) { - switch (addr) { + switch (offset) { case 0: return GetPA(); @@ -293,15 +334,15 @@ PIO0Device::Peek(uint32 addr) } } -bool -PIO0Device::MonitorUpdate() +void +PIO0Device::MonitorUpdate(Monitor *, TextScreen& screen) { int y; - monitor.Clear(); + screen.Clear(); y = 0; - monitor.Print(0, y++, "PortA(DIPSW1):%c%c%c%c%c%c%c%c", + screen.Print(0, y++, "PortA(DIPSW1):%c%c%c%c%c%c%c%c", (dipsw1[0] ? '1' : '0'), (dipsw1[1] ? '1' : '0'), (dipsw1[2] ? '1' : '0'), @@ -310,7 +351,7 @@ PIO0Device::MonitorUpdate() (dipsw1[5] ? '1' : '0'), (dipsw1[6] ? '1' : '0'), (dipsw1[7] ? '1' : '0')); - monitor.Print(0, y++, "PortB(DIPSW2):%c%c%c%c%c%c%c%c", + screen.Print(0, y++, "PortB(DIPSW2):%c%c%c%c%c%c%c%c", (dipsw2[0] ? '1' : '0'), (dipsw2[1] ? '1' : '0'), (dipsw2[2] ? '1' : '0'), @@ -319,17 +360,15 @@ PIO0Device::MonitorUpdate() (dipsw2[5] ? '1' : '0'), (dipsw2[6] ? '1' : '0'), (dipsw2[7] ? '1' : '0')); - monitor.Puts(0, y++, "PortC"); - monitor.Puts(1, y++, TA::OnOff(xp_reset), "b7: XP Reset"); - monitor.Puts(1, y++, TA::OnOff(parity), "b6: Parity"); - monitor.Puts(1, y++, "b5: ---"); - monitor.Puts(1, y++, TA::OnOff(int5en), "b4: Int5 Enable"); - monitor.Puts(1, y++, TA::OnOff(int5rq), "b3: Int5 Request"); - monitor.Puts(1, y++, TA::OnOff(int1en), "b2: Int1 Enable"); - monitor.Puts(1, y++, "b1: ---"); - monitor.Puts(1, y++, TA::OnOff(int1rq), "b0: Intq Request"); - - return true; + screen.Puts(0, y++, "PortC"); + screen.Puts(1, y++, TA::OnOff(xp_reset), "b7: XP Reset"); + screen.Puts(1, y++, TA::OnOff(parity), "b6: Parity"); + screen.Puts(1, y++, "b5: ---"); + screen.Puts(1, y++, TA::OnOff(int5en), "b4: Int5 Enable"); + screen.Puts(1, y++, TA::OnOff(int5rq), "b3: Int5 Request"); + screen.Puts(1, y++, TA::OnOff(int1en), "b2: Int1 Enable"); + screen.Puts(1, y++, "b1: ---"); + screen.Puts(1, y++, TA::OnOff(int1rq), "b0: Intq Request"); } // PortA (DIP-SW 1) 読み込み @@ -430,14 +469,11 @@ PIO0Device::SetPC(int pc, int val) // コンストラクタ PIO1Device::PIO1Device() - : inherited() + : inherited("PIO1") { - logname = "pio1"; - devname = "PIO1"; devaddr = 0x4d000000; devlen = 4; - poffevent.dev = this; poffevent.func = (DeviceCallback_t)&PIO1Device::PowerOffCallback; poffevent.SetName("PIO1 Power Off"); } @@ -447,12 +483,21 @@ PIO1Device::~PIO1Device() { } +// リセット +void +PIO1Device::ResetHard() +{ + inherited::ResetHard(); + + poffevent.Stop(); +} + uint64 -PIO1Device::Read(uint32 addr) +PIO1Device::Read(uint32 offset) { uint32 data; - switch (addr) { + switch (offset) { case 0: // PIO1 PortA: LCD データ return gLCD->Read(); @@ -481,9 +526,9 @@ PIO1Device::Read(uint32 addr) } uint64 -PIO1Device::Write(uint32 addr, uint32 data) +PIO1Device::Write(uint32 offset, uint32 data) { - switch (addr) { + switch (offset) { case 0: // PIO1 PortA: LCD データ gLCD->Write(data); return 0; @@ -505,16 +550,16 @@ PIO1Device::Write(uint32 addr, uint32 da default: __unreachable(); } - PANIC("$%08X <- $%02X 未サポート書き込み", addr, data); + PANIC("$%08X <- $%02X 未サポート書き込み", gMPU->GetPaddr(), data); return 0; } uint64 -PIO1Device::Peek(uint32 addr) +PIO1Device::Peek(uint32 offset) { uint32 data; - switch (addr) { + switch (offset) { case 0: // PIO1 PortA LCD データ return gLCD->Peek(); @@ -579,7 +624,7 @@ PIO1Device::SetPC(int pc, int val) // 電源 OFF イベントのコールバック void -PIO1Device::PowerOffCallback(int arg) +PIO1Device::PowerOffCallback(Event& ev) { putlog(0, "電源 OFF"); gScheduler->RequestPowerOff();