--- nono/vm/fdc.cpp 2026/04/29 17:05:14 1.1.1.10 +++ nono/vm/fdc.cpp 2026/04/29 17:05:25 1.1.1.12 @@ -84,25 +84,19 @@ #include "pedec.h" #include "scheduler.h" -// グローバル参照用 -FDCDevice *gFDC; - // time [nsec] 後に呼び出す phase_event のコールバックをセットする。 // func の書式が面倒なのを省略して書きたいため。 #define CallAfter(func_, time_) do { \ phase_event.func = ToEventCallback(&FDCDevice::func_); \ phase_event.time = time_; \ - gScheduler->RestartEvent(phase_event); \ + scheduler->RestartEvent(phase_event); \ } while (0) // コンストラクタ FDCDevice::FDCDevice() - : inherited("FDC") + : inherited(OBJ_FDC) { - devaddr = baseaddr; - devlen = 0x2000; - phase_event.Regist("FDC Phase"); poll_event.func = ToEventCallback(&FDCDevice::PollEventCallback); @@ -121,7 +115,6 @@ FDCDevice::FDCDevice() // デストラクタ FDCDevice::~FDCDevice() { - gFDC = NULL; } bool @@ -158,64 +151,97 @@ FDCDevice::Create() return true; } +// 初期化 +bool +FDCDevice::Init() +{ + if (inherited::Init() == false) { + return false; + } + + dmac = GetDMACDevice(); + pedec = GetPEDECDevice(); + + return true; +} + // リセット void FDCDevice::ResetHard(bool poweron) { + if (poweron) { + // READY ポーリングはリセットの影響を受けないはず + initialized = false; + scheduler->StopEvent(motor_event); + } + // uPD765 マニュアルによると、リセット信号によるリセットでは // SRT, HUT, HLT は影響を受けない。 // シリンダ位置 pcn はとりあえずわからないので放置。 - if (poweron) { - // READY ポーリングはリセットの影響を受けないはず - initialized = false; - gScheduler->StopEvent(motor_event); - } + // US0,US1 を low (FDD0) に。 + us = 0; + // 割り込み (と DRQ) をネゲート。 + msr.ndm = false; + st0.ic = ST0_IC_IC; + st0.se = false; + st0.ec = false; + st0.nr = false; + st0.hd = false; + st0.us = 0; + ChangeInterrupt(); - gScheduler->StopEvent(phase_event); - gScheduler->StopEvent(poll_event); + scheduler->StopEvent(phase_event); + scheduler->StopEvent(poll_event); CommandPhase(); } -uint64 +busdata FDCDevice::Read(uint32 offset) { - gMPU->AddCycle(19); // InsideOut p.135 + busdata data; switch (offset) { case 0: - { if (dack) { // DACK が立っているときは A0 によらずデータレジスタをアクセス - return ReadData(); + data = ReadData(); + } else { + data = GetMSR(); + putlog(4, "STAT -> $%02x", data.Data()); } - - uint8 stat = GetMSR(); - putlog(4, "STAT -> $%02x", stat); - return stat; - } + break; case 1: - return ReadData(); + data = ReadData(); + break; case 2: - return ReadDriveStatus(); + data = ReadDriveStatus(); + break; case 3: - return 0xff; + data = 0xff; + break; + + default: + VMPANIC("corrupted offset=%d", offset); } - __unreachable(); + + // InsideOut p.135 + const busdata wait = busdata::Wait(19 * 40_nsec); + data |= wait; + + return data; } -uint64 +busdata FDCDevice::Write(uint32 offset, uint32 data) { - gMPU->AddCycle(19); // InsideOut p.135 - switch (offset) { case 0: if (dack) { // DACK が立っているときは A0 によらずデータレジスタをアクセス WriteDataReg(data); - return 0; + break; } // ここはフェーズに関わらず 0x34, 0x35, 0x36 のコマンドだけを @@ -236,11 +262,11 @@ FDCDevice::Write(uint32 offset, uint32 d data); break; } - return 0; + break; case 1: WriteCmd(data); - return 0; + break; case 2: { @@ -248,7 +274,7 @@ FDCDevice::Write(uint32 offset, uint32 d putlog(1, "Drive Control <- $%02x", data); // FDD 割り込みクリア(要実機確認) - gPEDEC->NegateINT(fdd_vector[0]); + pedec->NegateINT(fdd_vector[0]); uint8 bit = 0x01; for (const auto f : fdd_vector) { @@ -258,7 +284,7 @@ FDCDevice::Write(uint32 offset, uint32 d bit <<= 1; } drivectrl = data; - return 0; + break; } case 3: @@ -275,7 +301,7 @@ FDCDevice::Write(uint32 offset, uint32 d if (motor_on_bit == false) { // MOTOR_ON ビットが立ち上がったら、全ドライブに通知 // motor_event は止める。 - gScheduler->StopEvent(motor_event); + scheduler->StopEvent(motor_event); for (const auto f : fdd_vector) { if (f) { f->SetMotorOn(true); @@ -294,12 +320,12 @@ FDCDevice::Write(uint32 offset, uint32 d if (motor_on_bit) { // MOTOR_ON ビットが立ち下がったら、一定時間後に MOTOR_ON // 信号をネゲートする。 - gScheduler->RestartEvent(motor_event); + scheduler->RestartEvent(motor_event); } } // FDD 割り込みクリア(要実機確認) - gPEDEC->NegateINT(fdd_vector[0]); + pedec->NegateINT(fdd_vector[0]); motor_on_bit = motor_on_bit_new; @@ -310,13 +336,19 @@ FDCDevice::Write(uint32 offset, uint32 d f->SetDriveSelect(accdrive, is2DD); } } - return 0; + break; } + default: + VMPANIC("corrupted offset=%d", offset); } - __unreachable(); + + // InsideOut p.135 + const busdata wait = busdata::Wait(19 * 40_nsec); + + return wait; } -uint64 +busdata FDCDevice::Peek(uint32 offset) { switch (offset) { @@ -343,9 +375,8 @@ FDCDevice::Peek(uint32 offset) return resbuf.Peek(); default: - __unreachable(); + return 0xff; } - break; } case 2: @@ -355,7 +386,7 @@ FDCDevice::Peek(uint32 offset) return 0xff; default: - __unreachable(); + return 0xff; } } @@ -690,7 +721,6 @@ FDCDevice::ReadData() default: VMPANIC("corrupted phase=$%x", (int)phase); } - __unreachable(); } // ドライブステータスレジスタ取得 @@ -838,10 +868,10 @@ FDCDevice::ChangeInterrupt() { if (GetST0() != 0x80 || (msr.ndm && 0/* XXX DRQ*/)) { putlog(4, "AssertINT"); - gPEDEC->AssertINT(this); + pedec->AssertINT(this); } else { putlog(4, "NegateINT"); - gPEDEC->NegateINT(this); + pedec->NegateINT(this); } } @@ -861,7 +891,7 @@ FDCDevice::ReadyChanged(int unit, bool i } // 転送の同期を取るために、READY になった時刻を覚えておく if (is_ready) { - unitinfo[unit].ready_time = gScheduler->GetVirtTime(); + unitinfo[unit].ready_time = scheduler->GetVirtTime(); } } @@ -871,7 +901,7 @@ FDCDevice::StartPoll() { if (poll_event.IsRunning() == false) { putlog(3, "Start polling"); - gScheduler->StartEvent(poll_event); + scheduler->StartEvent(poll_event); } } @@ -903,7 +933,7 @@ FDCDevice::PollEventCallback(Event& ev) } if (is_poll) { - gScheduler->RestartEvent(ev); + scheduler->RestartEvent(ev); } else { putlog(3, "Stop polling"); } @@ -1012,7 +1042,7 @@ FDCDevice::AssertDACK(bool tc_) dack = true; tc = tc_; // DRQ を下げる - gDMAC->NegateREQ(0); + dmac->NegateREQ(0); } // DACK 信号をネゲートする (DMAC から呼ばれる) @@ -1064,7 +1094,7 @@ FDCDevice::RequestDataByte() if (nd) { putlog(0, "CPU Transfer mode (NOT IMPLEMENTED)"); } else { - gDMAC->AssertREQ(0); + dmac->AssertREQ(0); } } @@ -1242,7 +1272,7 @@ FDCDevice::XferStart(bool is_write) // FDD がバイトを読み書きするちょうど真ん中のタイミングで動くように // 同期してみる。 - uint64 now = gScheduler->GetVirtTime(); + uint64 now = scheduler->GetVirtTime(); uint64 t = 16_usec - ((now - unitinfo[us].ready_time) % 16_usec); t += 8_usec; @@ -1351,7 +1381,7 @@ FDCDevice::XferStartCallback(Event& ev) // 次のマークまで待つ ev.time = dist * 16_usec; } - gScheduler->StartEvent(ev); + scheduler->StartEvent(ev); } void @@ -1449,7 +1479,7 @@ FDCDevice::XferDataCallback(Event& ev) if (xfer_write && xfer_remain > 0) { RequestDataByte(); } - gScheduler->StartEvent(ev); + scheduler->StartEvent(ev); } void