--- nono/vm/fdc.cpp 2026/04/29 17:05:38 1.1.1.15 +++ nono/vm/fdc.cpp 2026/04/29 17:05:51 1.1.1.17 @@ -84,6 +84,7 @@ #include "bitops.h" #include "config.h" #include "dmac.h" +#include "event.h" #include "fdd.h" #include "monitor.h" #include "pedec.h" @@ -92,8 +93,8 @@ // time [nsec] 後に呼び出す phase_event のコールバックをセットする。 // func の書式が面倒なのを省略して書きたいため。 #define CallAfter(func_, time_) do { \ - phase_event.func = ToEventCallback(&FDCDevice::func_); \ - phase_event.time = time_; \ + phase_event->func = ToEventCallback(&FDCDevice::func_); \ + phase_event->time = time_; \ scheduler->RestartEvent(phase_event); \ } while (0) @@ -133,7 +134,13 @@ FDCDevice::Create() // vector は面倒なので一旦 unique_ptr[] に確保して // 生ポインタの vector を作る。うーん。 for (int i = 0; i < ndrive; i++) { - fdd_list[i].reset(new FDDDevice(i)); + try { + fdd_list[i].reset(new FDDDevice(i)); + } catch (...) { } + if ((bool)fdd_list[i] == false) { + warnx("Failed to initialize FDDDevice(%u) at %s", i, __method__); + return false; + } } for (int i = 0; i < ndrive; i++) { if ((bool)fdd_list[i]) { @@ -153,18 +160,18 @@ FDCDevice::Init() dmac = GetDMACDevice(); pedec = GetPEDECDevice(); - phase_event.SetName("FDC Phase"); - scheduler->RegistEvent(phase_event); + auto evman = GetEventManager(); + phase_event = evman->Regist(this, NULL, "FDC Phase"); - poll_event.func = ToEventCallback(&FDCDevice::PollEventCallback); - poll_event.time = 1024_usec; - poll_event.SetName("FDC Polling"); - scheduler->RegistEvent(poll_event); - - motor_event.func = ToEventCallback(&FDCDevice::MotorEventCallback); - motor_event.time = 38.54_sec; - motor_event.SetName("FDC SED9420A TMOUT"); - scheduler->RegistEvent(motor_event); + poll_event = evman->Regist(this, + ToEventCallback(&FDCDevice::PollEventCallback), + "FDC Polling"); + poll_event->time = 1024_usec; + + motor_event = evman->Regist(this, + ToEventCallback(&FDCDevice::MotorEventCallback), + "FDC SED9420A TMOUT"); + motor_event->time = 38.54_sec; return true; } @@ -578,7 +585,7 @@ FDCDevice::MonitorReg(TextScreen& screen if (names[i][0] == '-') { screen.Puts(x + i * 4, y, TA::Disable, "---"); } else { - bool b = reg & (1 << (7 - i)); + bool b = reg & (1U << (7 - i)); screen.Puts(x + i * 4, y, TA::OnOff(b), names[i]); } } @@ -860,13 +867,13 @@ FDCDevice::ResultPhase() } void -FDCDevice::ResultCallback(Event& ev) +FDCDevice::ResultCallback(Event *ev) { ResultPhase(); } void -FDCDevice::CommandCallback(Event& ev) +FDCDevice::CommandCallback(Event *ev) { msr.cb = true; if (cmdbuf.len == cmd->cmdlen) { @@ -899,11 +906,8 @@ FDCDevice::ReadyChanged(int unit, bool i // ことの通知を受けてポーリングループを起動し、どのユニットも変化が // なくなったらポーリングを止めるようにしておく。 // uPD765 マニュアル POLLING FEATURE OF THE uPD765 (p.433) + StartPoll(); - // SPECIFY コマンドで有効になる - if (initialized) { - StartPoll(); - } // 転送の同期を取るために、READY になった時刻を覚えておく if (is_ready) { unitinfo[unit].ready_time = scheduler->GetVirtTime(); @@ -914,7 +918,11 @@ FDCDevice::ReadyChanged(int unit, bool i void FDCDevice::StartPoll() { - if (poll_event.IsRunning() == false) { + // SPECIFY コマンドで有効になる + if (initialized == false) { + return; + } + if (poll_event->IsRunning() == false) { putlog(3, "Start polling"); scheduler->StartEvent(poll_event); } @@ -922,7 +930,7 @@ FDCDevice::StartPoll() // ポーリングイベントコールバック void -FDCDevice::PollEventCallback(Event& ev) +FDCDevice::PollEventCallback(Event *ev) { bool is_poll = false; @@ -1045,9 +1053,7 @@ FDCDevice::SetForceReady(bool force_read { force_ready = force_ready_; putlog(2, "Force Ready %s", force_ready ? "On" : "Off"); - if (initialized) { - StartPoll(); - } + StartPoll(); } // DACK 信号をアサートする (DMAC から呼ばれる) @@ -1140,9 +1146,7 @@ FDCDevice::DriveSelect(uint8 drive) // ドライブセレクト信号線が変わったら READY が変わるかもしれないので // ポーリングを再開する必要がある。 - if (initialized) { - StartPoll(); - } + StartPoll(); // いまのところ LUNA のことは忘れる } @@ -1150,7 +1154,7 @@ FDCDevice::DriveSelect(uint8 drive) // 一定時間後に MOTOR_ON 信号をネゲートするイベント。 // SED9420 の TMOUT 信号に相当。 void -FDCDevice::MotorEventCallback(Event& ev) +FDCDevice::MotorEventCallback(Event *ev) { // 全ドライブに通知 for (const auto f : fdd_vector) { @@ -1301,7 +1305,7 @@ FDCDevice::XferStart(bool is_write) } void -FDCDevice::XferStartCallback(Event& ev) +FDCDevice::XferStartCallback(Event *ev) { // マーク位置まで待つ。 // マークを読んでみてディスパッチ。 @@ -1322,10 +1326,10 @@ FDCDevice::XferStartCallback(Event& ev) } if (dist == 0) { uint8 mark = fdd->ReadByte(); - ev.time = 1 * 16_usec; + ev->time = 1 * 16_usec; if (mark == MARK_IDAM) { // CHRN と CRC の合計時間を加算 - ev.time += (4 + 2) * 16_usec; + ev->time += (4 + 2) * 16_usec; resbuf.data.c = fdd->PeekByte(1); resbuf.data.h = fdd->PeekByte(2); @@ -1341,7 +1345,7 @@ FDCDevice::XferStartCallback(Event& ev) if ((cmdbuf.code & 0xbf) == 0x0a) { putlog(2, "READ ID complete"); st0.ic = ST0_IC_NT; - CallAfter(XferEndCallback, ev.time); + CallAfter(XferEndCallback, ev->time); return; } @@ -1354,7 +1358,7 @@ FDCDevice::XferStartCallback(Event& ev) { putlog(3, "Transfer decided"); xfer_start = true; - sect_remain = 1 << (7 + resbuf.data.n); + sect_remain = 1U << (7 + resbuf.data.n); if (cmdbuf.data.n == 0) { xfer_remain = cmdbuf.data.dtl; if (xfer_remain > 128) { @@ -1373,7 +1377,7 @@ FDCDevice::XferStartCallback(Event& ev) if (xfer_write) { RequestDataByte(); } - CallAfter(XferDataCallback, ev.time); + CallAfter(XferDataCallback, ev->time); return; } else { putlog(3, "DAM detected. Sector data will be skipped"); @@ -1393,24 +1397,24 @@ FDCDevice::XferStartCallback(Event& ev) } else { st1.ma = true; } - CallAfter(XferEndCallback, ev.time); + CallAfter(XferEndCallback, ev->time); return; } } } } else { // 次のマークまで待つ - ev.time = dist * 16_usec; + ev->time = dist * 16_usec; } scheduler->StartEvent(ev); } void -FDCDevice::XferDataCallback(Event& ev) +FDCDevice::XferDataCallback(Event *ev) { assert(fdd); - ev.time = 1 * 16_usec; + ev->time = 1 * 16_usec; // 変態フォーマットをサポートするときはこのへんに追加が必要。 @@ -1504,7 +1508,7 @@ FDCDevice::XferDataCallback(Event& ev) } void -FDCDevice::XferEndCallback(Event& ev) +FDCDevice::XferEndCallback(Event *ev) { st0.hd = hd; st0.us = us;