--- nono/vm/dmac.cpp 2026/04/29 17:05:29 1.1.1.14 +++ nono/vm/dmac.cpp 2026/04/29 17:05:38 1.1.1.16 @@ -13,8 +13,10 @@ #include "fdc.h" #include "interrupt.h" #include "mainbus.h" +#include "monitor.h" #include "mpu.h" #include "scheduler.h" +#include "syncer.h" // time 時間後に呼び出すコールバックをセットする。 // func の書式が面倒なのを省略して書きたいため。 @@ -52,9 +54,9 @@ DMACDevice::DMACDevice() channel[2].pcl_prev = true; // #3 は未対応 - monitor.func = ToMonitorCallback(&DMACDevice::MonitorUpdate); - monitor.SetSize(80, 34); - monitor.Regist(ID_MONITOR_DMAC); + monitor = gMonitorManager->Regist(ID_MONITOR_DMAC, this); + monitor->func = ToMonitorCallback(&DMACDevice::MonitorUpdate); + monitor->SetSize(80, 34); } // デストラクタ @@ -66,14 +68,11 @@ DMACDevice::~DMACDevice() bool DMACDevice::Init() { - if (inherited::Init() == false) { - return false; - } - adpcm = GetADPCMDevice(); fdc = GetFDCDevice(); interrupt = GetInterruptDevice(); mainbus = GetMainbusDevice(); + syncer = GetSyncer(); event.SetName("DMAC"); scheduler->RegistEvent(event); @@ -120,6 +119,7 @@ DMACDevice::ResetHard(bool poweron) chan->priority = 0; } + syncer->RequestDMACActive(false); ChangeInterrupt(); // イベントを停止 @@ -1044,6 +1044,22 @@ DMACDevice::WriteCCR(DMACChan *chan, uin ChangeInterrupt(); } +// CSR.ACT ビットの状態を変更。 +void +DMACDevice::ChangeACT(DMACChan *chan, bool active) +{ + chan->active = active; + + // チャンネルの ACT を変更した結果、 + // トータルでアクティブかどうかを Syncer に通知する。 + bool dmac_active = + channel[0].active || + channel[1].active || + channel[2].active || + channel[3].active; + syncer->RequestDMACActive(dmac_active); +} + // 転送開始 void DMACDevice::StartTransfer(DMACChan *chan) @@ -1056,7 +1072,7 @@ DMACDevice::StartTransfer(DMACChan *chan } // ACT を立てたら STR を下げる。 - chan->active = true; + ChangeACT(chan, true); chan->str = false; // XXX あとで移動する @@ -1480,7 +1496,7 @@ DMACDevice::TransferCallback(Event& ev) // すべての転送完了か if (__predict_false(chan->mtc == 0)) { chan->csr |= DMAC::CSR_COC; - chan->active = false; + ChangeACT(chan, false); ChangeInterrupt(); } @@ -1638,7 +1654,7 @@ DMACDevice::Error(DMACChan *chan, uint8 // データシート p.43 chan->cer = errcode; chan->csr |= DMAC::CSR_COC | DMAC::CSR_ERR; - chan->active = false; + ChangeACT(chan, false); chan->str = false; chan->cnt = false; ChangeInterrupt(); @@ -1731,7 +1747,8 @@ DMACDevice::AbortTransfer(DMACChan *chan chan->str = false; chan->cnt = false; - chan->active = false; + ChangeACT(chan, false); + chan->cer = DMAC::CER_SOFT_ABORT; // ERR ビットが立つと SAB をクリアする chan->csr |= DMAC::CSR_ERR;