--- nono/wx/wxstatuspanel.cpp 2026/04/29 17:05:31 1.1.1.10 +++ nono/wx/wxstatuspanel.cpp 2026/04/29 17:05:40 1.1.1.12 @@ -28,8 +28,10 @@ #include "newsctlr.h" #include "power.h" #include "scsi.h" +#include "scsidomain.h" #include "syncer.h" #include "virtio_block.h" +#include "virtio_scsi.h" // // インジケータ情報 (ほぼ構造体) @@ -327,7 +329,7 @@ WXStatusPanel::OnTimer(wxTimerEvent& eve } } -// store に value を代入。更新されていれば updated を立てる。 +// store に value を代入。更新されていれば true を返す。 // value は引数に渡す時に一度だけ評価される。 #define MODIFY(store, value_) ({ \ bool mod_; \ @@ -358,40 +360,104 @@ Status::~Status() { } +// Read/Write が別の3値タイプのアクセスインジケータ用 +enum class RWStatus : uint8 { + None = 0, + Read = 1, + Write = 2, +}; + // -// SCSI 情報 +// SCSI 情報 (Bus/VirtIO 共通) // class StatusSCSI : public Status { public: - StatusSCSI(SCSIBus *scsibus_) { + std::array active {}; +}; + +// +// SCSIBus 情報 +// +class StatusSCSIBus : public StatusSCSI +{ + public: + StatusSCSIBus(SCSIBus *scsibus_) { scsibus = scsibus_; } - ~StatusSCSI() override; + ~StatusSCSIBus() override; bool Poll() override { - bool mod = false; - mod |= MODIFY(bsy, scsibus->GetBSY()); + uint8 bsy = scsibus->GetBSY(); // 転送フェーズで DataOut の時だけ書き込みとみなす bool out = (scsibus->GetPhase() == SCSI::Phase::Transfer) && (scsibus->GetXfer() == SCSI::XferPhase::DataOut); - mod |= MODIFY(dataout, out); + + bool mod = false; + for (uint id = 0; id < 8; id++) { + RWStatus newactive; + if (__predict_false((bsy & (1U << id)) != 0)) { + if (out) { + newactive = RWStatus::Write; + } else { + newactive = RWStatus::Read; + } + } else { + newactive = RWStatus::None; + } + mod |= MODIFY(active[id], newactive); + } return mod; } - uint8 bsy {}; // BSY (ID0-7) - bool dataout {}; // DataOut フェーズなら true - private: SCSIBus *scsibus {}; }; // デストラクタ -StatusSCSI::~StatusSCSI() +StatusSCSIBus::~StatusSCSIBus() { } // +// VirtIOSCSI 情報 +// +class StatusVSCSI : public StatusSCSI +{ + public: + StatusVSCSI(VirtIOSCSIDevice *dev_) { + dev = dev_; + } + ~StatusVSCSI() override = default; + + bool Poll() override { + std::array newacc; + dev->GetAccess(&newacc); + bool mod = false; + for (uint id = 0; id < 8; id++) { + bool rmod = MODIFY(access[id * 2 + 0], newacc[id * 2 + 0]); + bool wmod = MODIFY(access[id * 2 + 1], newacc[id * 2 + 1]); + + RWStatus newactive; + if (wmod) { + newactive = RWStatus::Write; + } else if (rmod) { + newactive = RWStatus::Read; + } else { + newactive = RWStatus::None; + } + mod |= MODIFY(active[id], newactive); + } + return mod; + } + + std::array access {}; + + private: + VirtIOSCSIDevice *dev {}; +}; + +// // VirtIOBlock 情報 // class StatusVBlk : public Status @@ -405,18 +471,21 @@ class StatusVBlk : public Status bool Poll() override { bool rmod = MODIFY(access_read, dev->GetAccessRead()); bool wmod = MODIFY(access_write, dev->GetAccessWrite()); - - bool mod = false; - mod |= MODIFY(read_active, rmod); - mod |= MODIFY(write_active, wmod); - return mod; + RWStatus newactive; + if (wmod) { + newactive = RWStatus::Write; + } else if (rmod) { + newactive = RWStatus::Read; + } else { + newactive = RWStatus::None; + } + return MODIFY(active, newactive); } // アクセス状況 uint32 access_read {}; uint32 access_write {}; - bool read_active {}; - bool write_active {}; + RWStatus active {}; private: VirtIOBlockDevice *dev {}; @@ -536,14 +605,13 @@ WXStatusPanel::InitIndicators() // SCSI // 接続済みデバイスリストから取得。 - auto scsi = gMainApp.FindObject(OBJ_SCSI); - if (scsi) { - auto scsibus = scsi->GetOwnedBus(); - stat = new StatusSCSI(scsibus); + auto scsibus = gMainApp.FindObject(OBJ_SCSIBUS); + if (scsibus) { + stat = new StatusSCSIBus(scsibus); stats.emplace_back(stat); - const auto& conn = scsibus->GetConnectedDevices(); - for (auto& dev : conn) { + const auto& conn = scsibus->GetDomain()->GetConnectedDevices(); + for (const auto& dev : conn) { SCSI::DevType devtype = dev->GetDevType(); if (devtype == SCSI::DevType::Initiator) { continue; @@ -584,6 +652,32 @@ WXStatusPanel::InitIndicators() } } + // VirtIOSCSI + auto vscsi = gMainApp.FindObject(OBJ_VIRTIO_SCSI); + if (vscsi) { + stat = new StatusVSCSI(vscsi); + stats.emplace_back(stat); + + const auto& conn = vscsi->GetDomain()->GetConnectedDevices(); + for (const auto& dev : conn) { + int scsiid = dev->GetMyID(); + + // 文字列は OnSCSIMediaChanged() でセットする。 + ind = new Indicator(Indicator::SCSI0 + scsiid, + &WXStatusPanel::DrawSCSI, 3, stat); + ind->contextmenu = &WXStatusPanel::ContextMenuCD; + ind->dev = dev; + ind->panel = new wxPanel(this); + ind->panel->SetName("WXStatusPanel.VSCSI"); + // このパネルがフォーカスを受け取らないようにする。 + // StatusPanel がフォーカスを持っていてもキー入力を MainFrame に渡す + // ようにしているため、StatusPanel のフォーカスを奪ってはいけない。 + ind->panel->SetCanFocus(false); + + indicators.emplace_back(ind); + } + } + // ネットワーク for (int i = 0; i < 2; i++) { auto hostnet = gMainApp.FindObject(OBJ_HOSTNET(i)); @@ -789,7 +883,7 @@ WXStatusPanel::DrawPerf(const Indicator // パフォーマンス表示は // o 高速モード指示中なら倍率表記 (115% なら 1.2x) // o 通常モード指示中ならパーセント表記 - if ((perf_mode & Syncer::SCHED_SYNC) == 0) { + if ((perf_mode & Syncer::SYNCMODE_SYNC) == 0) { // 高速モード指示 if (perf_mode == 0) { // 高速走行中 @@ -830,11 +924,9 @@ WXStatusPanel::DrawSCSI(const Indicator Color fg; Color bg; int scsiid; - uint idmask; scsiid = ind->GetSCSIID(); assertmsg(scsiid >= 0, "id=%d", ind->id); - idmask = 1U << scsiid; if (scsi_loaded[scsiid]) { fg = UD_BLACK; @@ -842,12 +934,10 @@ WXStatusPanel::DrawSCSI(const Indicator fg = UD_GREY; } - if ((stat->bsy & idmask) != 0) { - if (stat->dataout) { - bg = UD_RED; - } else { - bg = UD_YELLOW_GREEN; - } + if (stat->active[scsiid] == RWStatus::Write) { + bg = UD_RED; + } else if (stat->active[scsiid] == RWStatus::Read) { + bg = UD_YELLOW_GREEN; } else { bg = BGPANEL; } @@ -864,9 +954,9 @@ WXStatusPanel::DrawVBlk(const Indicator Color bg; fg = UD_BLACK; - if (stat->write_active) { + if (stat->active == RWStatus::Write) { bg = UD_RED; - } else if (stat->read_active) { + } else if (stat->active == RWStatus::Read) { bg = UD_YELLOW_GREEN; } else { bg = BGPANEL;