--- nono/vm/pio.cpp 2026/04/29 17:04:59 1.1.1.9 +++ nono/vm/pio.cpp 2026/04/29 17:05:10 1.1.1.10 @@ -4,26 +4,41 @@ // Licensed under nono-license.txt // +// +// PIO/PPI (i8255) +// + +// IODevice +// | +// | +-------------+ +// +--| i8255Device | (8255 としての共通部分) +// +-------------+ +// | +// | +-----------+ +// +--| PPIDevice | (X68030) +// | +-----------+ +// | +// | +------------+ +// +--| PIO0Device | (LUNA) +// | +------------+ +// | +// | +------------+ +// +--| PIO1Device | (LUNA) +// +------------+ + #include "pio.h" #include "bitops.h" #include "config.h" #include "lcd.h" #include "mainapp.h" +#include "mpu.h" +#include "power.h" #include "scheduler.h" -// IODevice -// | -// v -// i8255Device (8255 としての共通部分) -// | -// +----------+----------+ -// v v v -// PPIDevice PIO0Device PIO1Device -// (X68030) (LUNA) (LUNA) - -std::unique_ptr gPPI; -std::unique_ptr gPIO0; -std::unique_ptr gPIO1; +// グローバル参照用 +PPIDevice *gPPI; +PIO0Device *gPIO0; +PIO1Device *gPIO1; // // i8255 @@ -42,7 +57,7 @@ i8255Device::~i8255Device() // リセット void -i8255Device::ResetHard() +i8255Device::ResetHard(bool poweron) { // clears the control register // and place ports A, B, and C in input mode. @@ -83,13 +98,6 @@ i8255Device::WriteCtrl(uint32 data) } } -void -i8255Device::SetPC(int pc, int data) -{ - // 継承側で用意すること。ここには来ない - PANIC("not impl"); -} - // // X68k PPI // @@ -105,6 +113,7 @@ PPIDevice::PPIDevice() // デストラクタ PPIDevice::~PPIDevice() { + gPPI = NULL; } uint64 @@ -120,12 +129,10 @@ PPIDevice::Read(uint32 offset) putlog(0, "$e9a005 PortC 未実装読み込み"); return 0xff; case 3: - PANIC("PPI $e9a007 未サポート読み込み"); - break; + VMPANIC("PPI $e9a007 未サポート読み込み"); default: __unreachable(); } - PANIC("not impl"); } uint64 @@ -142,7 +149,7 @@ PPIDevice::Write(uint32 offset, uint32 d break; case 3: if (data != 0x92) { - PANIC("PPI $e9a007 未実装書き込み $%02X", data); + VMPANIC("PPI $e9a007 未実装書き込み $%02X", data); } else { putlog(0, "$e9a007 未実装書き込み $%02x (無視)", data); } @@ -160,6 +167,13 @@ PPIDevice::Peek(uint32 offset) return 0xff; } +// PortC 書き込み +void +PPIDevice::SetPC(int pc, int data) +{ + VMPANIC("not impl"); +} + // // LUNA PIO0 // @@ -262,7 +276,7 @@ PIO0Device::PIO0Device() // DIP-SW#2 はユーザ定義(?)なので(今の所?)どちらも共通。 gConfig->SetDefault("luna-dipsw2", "11111111"); - monitor.func = (MonitorCallback_t)&PIO0Device::MonitorUpdate; + monitor.func = ToMonitorCallback(&PIO0Device::MonitorUpdate); monitor.SetSize(22, 11); monitor.Regist(ID_MONITOR_PIO0); } @@ -270,6 +284,7 @@ PIO0Device::PIO0Device() // デストラクタ PIO0Device::~PIO0Device() { + gPIO0 = NULL; } bool @@ -297,7 +312,7 @@ PIO0Device::Init() return true; } -// XXX PowerOn か ResetHard 未調査 +// XXX ResetHard 未調査 uint64 PIO0Device::Read(uint32 offset) @@ -505,7 +520,7 @@ PIO0Device::SetPC(int pc, int val) } return; } - PANIC("invalid pc=%d", pc); + VMPANIC("invalid pc=%d", pc); } @@ -522,22 +537,24 @@ PIO1Device::PIO1Device() devaddr = 0x4d000000; devlen = 4; - poffevent.func = (DeviceCallback_t)&PIO1Device::PowerOffCallback; - poffevent.SetName("PIO1 Power Off"); + poffevent.func = ToEventCallback(&PIO1Device::PowerOffCallback); + poffevent.time = 1_msec; + poffevent.Regist("PIO1 Power Off"); } // デストラクタ PIO1Device::~PIO1Device() { + gPIO1 = NULL; } // リセット void -PIO1Device::ResetHard() +PIO1Device::ResetHard(bool poweron) { - inherited::ResetHard(); + inherited::ResetHard(poweron); - poffevent.Stop(); + gScheduler->StopEvent(poffevent); } uint64 @@ -598,7 +615,7 @@ PIO1Device::Write(uint32 offset, uint32 default: __unreachable(); } - PANIC("$%08X <- $%02X 未サポート書き込み", gMPU->GetPaddr(), data); + VMPANIC("$%08X <- $%02X 未サポート書き込み", gMPU->GetPaddr(), data); return 0; } @@ -646,12 +663,11 @@ PIO1Device::SetPC(int pc, int val) if (power) { // 電源オフ取り消し putlog(1, "電源 OFF 取消"); - poffevent.Stop(); + gScheduler->StopEvent(poffevent); } else { // 1msec 後に電源オフ putlog(1, "電源 OFF 指示"); - poffevent.time = 1_msec; - poffevent.Start(); + gScheduler->RestartEvent(poffevent); } return; case 5: @@ -667,13 +683,13 @@ PIO1Device::SetPC(int pc, int val) default: break; } - PANIC("PC%d 未実装", pc); + VMPANIC("PC%d 未実装", pc); } -// 電源 OFF イベントのコールバック +// 電源オフイベントのコールバック void PIO1Device::PowerOffCallback(Event& ev) { putlog(0, "電源 OFF"); - gScheduler->RequestPowerOff(); + gPower->MakePowerOffExit(); }