--- nono/vm/scsidev.cpp 2026/04/29 17:04:42 1.1.1.5 +++ nono/vm/scsidev.cpp 2026/04/29 17:04:56 1.1.1.10 @@ -9,14 +9,14 @@ #include "scsidev.h" #include "config.h" #include "mainapp.h" -#include "mystring.h" // // SCSI デバイス // // コンストラクタ -SCSIDevice::SCSIDevice() +SCSIDevice::SCSIDevice(const std::string& objname_) + : inherited(objname_) { } @@ -30,7 +30,8 @@ SCSIDevice::~SCSIDevice() // // コンストラクタ -SCSIHostDevice::SCSIHostDevice() +SCSIHostDevice::SCSIHostDevice(const std::string& objname_) + : inherited(objname_) { devtype = SCSI::DevType::Initiator; @@ -114,7 +115,7 @@ SCSIHostDevice::Init() } } if (!typestr.empty()) { - putmsg("%s target #%d %s", GetConfigName(), id, + putmsgn("%s target #%d %s", GetConfigName(), id, typestr.c_str()); } } @@ -152,6 +153,12 @@ SCSIHostDevice::BusFreeCB(int id) SetData(0); } +#if defined(__clang__) +// デストラクタがインラインで書けないのは面倒なのでとりあえず +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + // // SCSI コマンドの共通部分 // @@ -239,7 +246,7 @@ class SCSICmdTestUnitReady : public SCSI using inherited = SCSICmd; public: SCSICmdTestUnitReady(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdTestUnitReady() { } + virtual ~SCSICmdTestUnitReady() override { } }; // @@ -250,7 +257,7 @@ class SCSICmdRezeroUnit : public SCSICmd using inherited = SCSICmd; public: SCSICmdRezeroUnit(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdRezeroUnit() { } + virtual ~SCSICmdRezeroUnit() override { } // とりあえず黙って成功するだけでいいか }; @@ -263,15 +270,15 @@ class SCSICmdRequestSense : public SCSIC using inherited = SCSICmd; public: SCSICmdRequestSense(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdRequestSense() { } + virtual ~SCSICmdRequestSense() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { // 応答のセンスデータは SCSI-2 形式(最小18バイト) を実装。 // 今の所、センスキー、ASC、ASCQ だけで返せる内容にだけ対応している。 // これ以外のフィールドを返す必要が出来たらまた考えること。 buf.clear(); - buf.resize(17); + buf.resize(18); buf[0] = 0xf0; // Valid、エラーコード 0x70 buf[1] = 0; // セグメント番号(?) buf[2] = parent->sensekey; // センスキー (上位4ビットは今の所 0) @@ -310,9 +317,9 @@ class SCSICmdRead6 : public SCSICmd using inherited = SCSICmd; public: SCSICmdRead6(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdRead6() { } + virtual ~SCSICmdRead6() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { SCSIHD *hdparent = dynamic_cast(parent); uint32 lba; uint32 blks; @@ -328,7 +335,7 @@ class SCSICmdRead6 : public SCSICmd if (blks == 0) { blks = 256; } - parent->putlog(1, "READ6 LBA=0x%x blks=0x%x", lba, blks); + parent->putlogf(1, lstr("READ6 LBA=0x%x blks=0x%x", lba, blks)); if (((uint64)lba + (uint64)blks) * parent->GetBlocksize() > hdparent->GetSize()) @@ -360,9 +367,9 @@ class SCSICmdWrite6 : public SCSICmd SCSICmdWrite6(SCSITarget *p) : inherited(p) { hdparent = dynamic_cast(parent); } - virtual ~SCSICmdWrite6() { } + virtual ~SCSICmdWrite6() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { // センスデータをクリア parent->ClearSense(); @@ -391,8 +398,8 @@ class SCSICmdWrite6 : public SCSICmd return SCSI::XferPhase::DataOut; } - virtual SCSI::XferPhase DoneDataOut() { - parent->putlog(1, "WRITE6 LBA=0x%x blks=0x%x", lba, blks); + SCSI::XferPhase DoneDataOut() override { + parent->putlogf(1, lstr("WRITE6 LBA=0x%x blks=0x%x", lba, blks)); if (hdparent->writeprotect == false) { memcpy(hdparent->mem + (lba * parent->GetBlocksize()), buf.data(), buf.size()); @@ -414,9 +421,9 @@ class SCSICmdInquiry : public SCSICmd using inherited = SCSICmd; public: SCSICmdInquiry(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdInquiry() { } + virtual ~SCSICmdInquiry() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { // センスデータをクリア parent->ClearSense(); @@ -440,9 +447,9 @@ class SCSICmdModeSelect6 : public SCSICm using inherited = SCSICmd; public: SCSICmdModeSelect6(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdModeSelect6() { } + virtual ~SCSICmdModeSelect6() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { // センスデータをクリア parent->ClearSense(); @@ -450,7 +457,7 @@ class SCSICmdModeSelect6 : public SCSICm return SCSI::XferPhase::DataOut; } - virtual SCSI::XferPhase DoneDataOut() { + SCSI::XferPhase DoneDataOut() override { // Mode Select(6) のデータは以下の構造で並んでいる。 // ヘッダ // ブロックディスクリプタ#1 @@ -485,16 +492,17 @@ class SCSICmdModeSense6 : public SCSICmd using inherited = SCSICmd; public: SCSICmdModeSense6(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdModeSense6() { } + virtual ~SCSICmdModeSense6() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { uint8 pagecode = (cmdseq[2] & 0x3f); // センスデータをクリア parent->ClearSense(); // 未実装 (XXX センスデータは適当) - parent->putlog(1, "ModeSense(6) PageCode $%02x 未実装", pagecode); + parent->putlogf(1, lstr("ModeSense(6) PageCode $%02x 未実装", + pagecode)); parent->sensekey = SCSI::SenseKey::IllegalRequest; parent->senseasc = SCSI::ASC::InvalidFieldInCDB; status_byte = SCSI::StatusByte::CheckCondition; @@ -511,14 +519,14 @@ class SCSICmdStartStopUnit : public SCSI using inherited = SCSICmd; public: SCSICmdStartStopUnit(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdStartStopUnit() { } + virtual ~SCSICmdStartStopUnit() override { } // スピンアップ/ダウンやメディアのロード/アンロードを指示する。 // ので今の所エミュレーション上は特にすることはない。 // XXX それっぽい時間待つくらいはしてもいいかも知れない - virtual SCSI::XferPhase Command(std::vector& cmdseq) { - parent->putlog(1, "StartStopUnit"); + SCSI::XferPhase Command(std::vector& cmdseq) override { + parent->putlogf(1, lstr("StartStopUnit")); return inherited::Command(cmdseq); } }; @@ -531,9 +539,9 @@ class SCSICmdReadCapacity : public SCSIC using inherited = SCSICmd; public: SCSICmdReadCapacity(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdReadCapacity() { } + virtual ~SCSICmdReadCapacity() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { SCSIHD *hdparent = dynamic_cast(parent); // センスデータをクリア @@ -541,7 +549,7 @@ class SCSICmdReadCapacity : public SCSIC // PMI=1 は未サポート if ((cmdseq[8] & 0x01) != 0) { - parent->putmsg("SCSI ReadCapacity PMI=1 not supported"); + parent->putlogf(0, lstr("SCSI ReadCapacity PMI=1 not supported")); } // 応答データは @@ -571,9 +579,9 @@ class SCSICmdRead10 : public SCSICmd using inherited = SCSICmd; public: SCSICmdRead10(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdRead10() { } + virtual ~SCSICmdRead10() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { SCSIHD *hdparent = dynamic_cast(parent); uint32 lba; uint32 blks; @@ -582,7 +590,7 @@ class SCSICmdRead10 : public SCSICmd parent->ClearSense(); if ((cmdseq[1] & 0x01)) { - parent->putmsg("SCSI Read(10) RelAdr not supported"); + parent->putlogf(0, lstr("SCSI Read(10) RelAdr not supported")); } lba = cmdseq[2] << 24; @@ -591,7 +599,7 @@ class SCSICmdRead10 : public SCSICmd lba |= cmdseq[5]; blks = cmdseq[7] << 8; blks |= cmdseq[8]; - parent->putlog(1, "READ10 LBA=0x%x blks=0x%x", lba, blks); + parent->putlogf(1, lstr("READ10 LBA=0x%x blks=0x%x", lba, blks)); if (((uint64)lba + (uint64)blks) * parent->GetBlocksize() > hdparent->GetSize()) @@ -614,6 +622,60 @@ class SCSICmdRead10 : public SCSICmd }; // +// SCSI コマンド 0x2a Write(10) (ダイレクトアクセスデバイス) +// +class SCSICmdWrite10 : public SCSICmd +{ + using inherited = SCSICmd; + public: + SCSICmdWrite10(SCSITarget *p) : inherited(p) { + hdparent = dynamic_cast(parent); + } + virtual ~SCSICmdWrite10() override { } + + SCSI::XferPhase Command(std::vector& cmdseq) override { + // センスデータをクリア + parent->ClearSense(); + + lba = cmdseq[2] << 24; + lba |= cmdseq[3] << 16; + lba |= cmdseq[4] << 8; + lba |= cmdseq[5]; + blks = cmdseq[7] << 8; + blks |= cmdseq[8]; + + if (((uint64)lba + (uint64)blks) * parent->GetBlocksize() > + hdparent->GetSize()) + { + parent->sensekey = SCSI::SenseKey::IllegalRequest; + parent->senseasc = SCSI::ASC::InvalidFieldInCDB; + status_byte = SCSI::StatusByte::CheckCondition; + return SCSI::XferPhase::Status; + } + + // 平均シークタイム + optime = hdparent->seektime; + + recvbytes = blks * parent->GetBlocksize(); + return SCSI::XferPhase::DataOut; + } + + SCSI::XferPhase DoneDataOut() override { + parent->putlogf(1, lstr("WRITE10 LBA=0x%x blks=0x%x", lba, blks)); + if (hdparent->writeprotect == false) { + memcpy(hdparent->mem + (lba * parent->GetBlocksize()), + buf.data(), buf.size()); + } + return SCSI::XferPhase::Status; + } + + private: + SCSIHD *hdparent; + uint32 lba; + uint32 blks; +}; + +// // SCSI コマンド サポートしていないコマンド // class SCSICmdNotSupportedCommand : public SCSICmd @@ -621,9 +683,9 @@ class SCSICmdNotSupportedCommand : publi using inherited = SCSICmd; public: SCSICmdNotSupportedCommand(SCSITarget *p) : inherited(p) { } - virtual ~SCSICmdNotSupportedCommand() { } + virtual ~SCSICmdNotSupportedCommand() override { } - virtual SCSI::XferPhase Command(std::vector& cmdseq) { + SCSI::XferPhase Command(std::vector& cmdseq) override { // XXX センスキーよく分からんけどとりあえず parent->sensekey = SCSI::SenseKey::IllegalRequest; parent->senseasc = SCSI::ASC::InvalidCommandOperationCode; @@ -632,17 +694,19 @@ class SCSICmdNotSupportedCommand : publi } }; +#if defined(__clang__) +#pragma clang diagnostic pop +#endif // // SCSI ターゲットデバイスの共通部分 // // コンストラクタ -SCSITarget::SCSITarget(SCSIHostDevice *h, int id, std::vector& inq) +SCSITarget::SCSITarget(const std::string& objname_, + SCSIHostDevice *h, int id, std::vector& inq) + : inherited(objname_) { - logname = "scsitarget"; - devname = "SCSITarget"; - inquiry_data = inq; // ホストへのリンク (所有関係のないポインタ) host = h; @@ -654,6 +718,20 @@ SCSITarget::~SCSITarget() { } +// 電源オン +bool +SCSITarget::PowerOn() +{ + ClearSense(); + cmdseq.clear(); + cmdlen = 0; + cmd.reset(); + bytecount = 0; + lastbyte = false; + + return true; +} + // バスリセットされた (SCSIBus から呼ばれる) void SCSITarget::BusResetCB() @@ -776,7 +854,7 @@ SCSITarget::TransferCB() for (const auto& v : cmdseq) { cmdbuf += string_format(" $%02x", v); } - putlog("%s", cmdbuf.c_str()); + putlogn("%s", cmdbuf.c_str()); } // 最終バイトを受信したらコマンドを選択 DispatchCmd(); @@ -955,9 +1033,10 @@ SCSITarget::DispatchCmd() // コンストラクタ SCSIHD::SCSIHD(SCSIHostDevice *h, int id) - : inherited(h, id, inquiry_data) + : inherited(string_format("SCSIHD%d", id), h, id, inquiry_data) { - devname = "SCSIHD"; + AddAlias(string_format("HD%d", id)); + devtype = SCSI::DevType::HD; } @@ -1034,6 +1113,10 @@ SCSIHD::DispatchCmd() cmd.reset(new SCSICmdRead10(this)); break; + case SCSI::Command::Write10: // 0x2a + cmd.reset(new SCSICmdWrite10(this)); + break; + default: // 見付からなければ基本クラス側に任せる inherited::DispatchCmd();