diff --git a/cpp/command/command_dispatcher.cpp b/cpp/command/command_dispatcher.cpp index 6f18f120..0746d9e9 100644 --- a/cpp/command/command_dispatcher.cpp +++ b/cpp/command/command_dispatcher.cpp @@ -30,7 +30,7 @@ bool CommandDispatcher::DispatchCommand(const CommandContext &context, PbResult return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION, UNKNOWN_OPERATION, to_string(operation)); } - trace("Executing {0} command", identifier, PbOperation_Name(operation)); + trace("{0}Executing {1} command", identifier, PbOperation_Name(operation)); switch (operation) { case LOG_LEVEL: diff --git a/cpp/controllers/generic_controller.cpp b/cpp/controllers/generic_controller.cpp index 60ef2356..fcb73060 100644 --- a/cpp/controllers/generic_controller.cpp +++ b/cpp/controllers/generic_controller.cpp @@ -337,19 +337,15 @@ void GenericController::Send() DecrementBlocks(); - // Processing after data collection (read/data-in only) - if (IsDataIn() && HasBlocks()) { - // Set next buffer (set offset, length) - if (!XferIn(GetBuffer())) { - Error(sense_key::aborted_command, asc::controller_send_xfer_in); - return; - } + if (IsDataIn() && HasBlocks() && !XferIn(GetBuffer())) { + Error(sense_key::aborted_command, asc::controller_send_xfer_in); + return; } // Continue sending if blocks != 0 if (HasBlocks()) { assert(HasValidLength()); - assert(GetOffset() == 0); + assert(!GetOffset()); return; } @@ -442,7 +438,7 @@ void GenericController::Receive() // Continue to receive if blocks != 0 if (HasBlocks()) { assert(HasValidLength()); - assert(GetOffset() == 0); + assert(!GetOffset()); return; } diff --git a/cpp/devices/disk.cpp b/cpp/devices/disk.cpp index eb297912..a9341dcb 100644 --- a/cpp/devices/disk.cpp +++ b/cpp/devices/disk.cpp @@ -143,14 +143,13 @@ void Disk::Dispatch(scsi_command cmd) } } -void Disk::SetUpCache(off_t image_offset, bool raw) +void Disk::SetUpCache(bool raw) { - cache = make_unique(GetFilename(), size_shift_count, static_cast(GetBlockCount()), - image_offset); + cache = make_unique(GetFilename(), size_shift_count, static_cast(GetBlockCount())); cache->SetRawMode(raw); } -void Disk::Resize_cache(const string &path, bool raw) +void Disk::ResizeCache(const string &path, bool raw) { cache.reset(new DiskCache(path, size_shift_count, static_cast(GetBlockCount()))); cache->SetRawMode(raw); diff --git a/cpp/devices/disk.h b/cpp/devices/disk.h index cfb635f8..ec8c65d1 100644 --- a/cpp/devices/disk.h +++ b/cpp/devices/disk.h @@ -141,8 +141,8 @@ class Disk : public StorageDevice, private ScsiBlockCommands protected: - void SetUpCache(off_t, bool = false); - void Resize_cache(const string&, bool); + void SetUpCache(bool = false); + void ResizeCache(const string&, bool); void SetUpModePages(map>&, int, bool) const override; void AddReadWriteErrorRecoveryPage(map>&, bool) const; diff --git a/cpp/devices/disk_cache.cpp b/cpp/devices/disk_cache.cpp index 9ecd2c89..a247eebd 100644 --- a/cpp/devices/disk_cache.cpp +++ b/cpp/devices/disk_cache.cpp @@ -8,6 +8,7 @@ // XM6i // Copyright (C) 2010-2015 isaki@NetBSD.org // Copyright (C) 2010 Y.Sugahara +// Copyright (C) 2022-2024 Uwe Seimet // //--------------------------------------------------------------------------- @@ -17,11 +18,10 @@ #include "disk_track.h" #include "disk_cache.h" -DiskCache::DiskCache(const string &path, int size, uint32_t blocks, off_t imgoff) -: sec_path(path), sec_size(size), sec_blocks(blocks), imgoffset(imgoff) +DiskCache::DiskCache(const string &path, int size, uint32_t blocks) +: sec_path(path), sec_size(size), sec_blocks(blocks) { assert(blocks > 0); - assert(imgoff >= 0); } bool DiskCache::Save() @@ -157,7 +157,7 @@ bool DiskCache::Load(int index, int track, shared_ptr disktrk) disktrk = make_shared(); } - disktrk->Init(track, sec_size, sectors, cd_raw, imgoffset); + disktrk->Init(track, sec_size, sectors, cd_raw); // Try loading if (!disktrk->Load(sec_path, cache_miss_read_count)) { diff --git a/cpp/devices/disk_cache.h b/cpp/devices/disk_cache.h index aeeb3ca7..8c175eef 100644 --- a/cpp/devices/disk_cache.h +++ b/cpp/devices/disk_cache.h @@ -7,7 +7,7 @@ // // XM6i // Copyright (C) 2010-2015 isaki@NetBSD.org -// Copyright (C) 2022-2023 Uwe Seimet +// Copyright (C) 2022-2024 Uwe Seimet // //--------------------------------------------------------------------------- @@ -43,7 +43,7 @@ class DiskCache uint32_t serial; }; - DiskCache(const string&, int, uint32_t, off_t = 0); + DiskCache(const string&, int, uint32_t); ~DiskCache() = default; void SetRawMode(bool b) @@ -71,6 +71,5 @@ class DiskCache int sec_size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096) int sec_blocks; // Blocks per sector bool cd_raw = false; // CD-ROM RAW mode - off_t imgoffset; // Offset to actual data }; diff --git a/cpp/devices/disk_track.cpp b/cpp/devices/disk_track.cpp index 80f9542d..445d3302 100644 --- a/cpp/devices/disk_track.cpp +++ b/cpp/devices/disk_track.cpp @@ -8,7 +8,7 @@ // XM6i // Copyright (C) 2010-2015 isaki@NetBSD.org // Copyright (C) 2010 Y.Sugahara -// Copyright (C) 2022-2023 Uwe Seimet +// Copyright (C) 2022-2024 Uwe Seimet // //--------------------------------------------------------------------------- @@ -24,11 +24,10 @@ DiskTrack::~DiskTrack() free(dt.buffer); // NOSONAR free() must be used here because of allocation with posix_memalign } -void DiskTrack::Init(int track, int size, int sectors, bool raw, off_t imgoff) +void DiskTrack::Init(int track, int size, int sectors, bool raw) { assert(track >= 0); assert((sectors > 0) && (sectors <= 0x100)); - assert(imgoff >= 0); // Set Parameters dt.track = track; @@ -41,9 +40,6 @@ void DiskTrack::Init(int track, int size, int sectors, bool raw, off_t imgoff) // Not Changed dt.changed = false; - - // Offset to actual data - dt.imgoffset = imgoff; } bool DiskTrack::Load(const string &path, uint64_t &cache_miss_read_count) @@ -66,9 +62,6 @@ bool DiskTrack::Load(const string &path, uint64_t &cache_miss_read_count) offset <<= dt.size; } - // Add offset to real image - offset += dt.imgoffset; - // Calculate length (data size of this track) const int length = dt.sectors << dt.size; @@ -158,9 +151,6 @@ bool DiskTrack::Save(const string &path, uint64_t &cache_miss_write_count) off_t offset = ((off_t)dt.track << 8); offset <<= dt.size; - // Add offset to real image - offset += dt.imgoffset; - // Calculate length per sector const int length = 1 << dt.size; diff --git a/cpp/devices/disk_track.h b/cpp/devices/disk_track.h index 85c81937..e3f3eae0 100644 --- a/cpp/devices/disk_track.h +++ b/cpp/devices/disk_track.h @@ -7,7 +7,7 @@ // // XM6i // Copyright (C) 2010-2015 isaki@NetBSD.org -// Copyright (C) 2022-2023 Uwe Seimet +// Copyright (C) 2022-2024 Uwe Seimet // //--------------------------------------------------------------------------- @@ -33,7 +33,6 @@ class DiskTrack bool changed; // Changed flag vector changemap; // Changed map bool raw; // RAW mode flag - off_t imgoffset; // Offset to actual data } dt = { }; public: @@ -47,9 +46,9 @@ class DiskTrack friend class DiskCache; - void Init(int track, int size, int sectors, bool raw = false, off_t imgoff = 0); - bool Load(const string &path, uint64_t&); - bool Save(const string &path, uint64_t&); + void Init(int, int, int, bool = false); + bool Load(const string&, uint64_t&); + bool Save(const string&, uint64_t&); bool ReadSector(span, int) const; bool WriteSector(span buf, int); diff --git a/cpp/devices/mode_page_device.cpp b/cpp/devices/mode_page_device.cpp index 3a7aea00..ff56149c 100644 --- a/cpp/devices/mode_page_device.cpp +++ b/cpp/devices/mode_page_device.cpp @@ -138,7 +138,7 @@ void ModePageDevice::ModeSense10() const EnterDataInPhase(); } -void ModePageDevice::ModeSelect(scsi_command, cdb_t, span, int) const +void ModePageDevice::ModeSelect(scsi_command, cdb_t, span, int) { // There is no default implementation of MODE SELECT assert(false); diff --git a/cpp/devices/mode_page_device.h b/cpp/devices/mode_page_device.h index 7607f6af..6abb8339 100644 --- a/cpp/devices/mode_page_device.h +++ b/cpp/devices/mode_page_device.h @@ -24,7 +24,7 @@ class ModePageDevice : public PrimaryDevice bool Init(const param_map&) override; - virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) const; + virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int); protected: diff --git a/cpp/devices/mode_page_util.cpp b/cpp/devices/mode_page_util.cpp index 72240916..d7f00b31 100644 --- a/cpp/devices/mode_page_util.cpp +++ b/cpp/devices/mode_page_util.cpp @@ -16,7 +16,7 @@ using namespace spdlog; using namespace scsi_defs; using namespace memory_util; -void mode_page_util::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length, int sector_size) +int mode_page_util::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length, int sector_size) { assert(cmd == scsi_command::cmd_mode_select6 || cmd == scsi_command::cmd_mode_select10); @@ -24,12 +24,12 @@ void mode_page_util::ModeSelect(scsi_command cmd, cdb_t cdb, span if (!(cdb[1] & 0x10)) { // Vendor-specific parameters (SCSI-1) are not supported. // Do not report an error in order to support Apple's HD SC Setup. - return; + return sector_size; } // The page data are optional if (!length) { - return; + return sector_size; } int offset = EvaluateBlockDescriptors(cmd, buf, length, sector_size); @@ -53,10 +53,10 @@ void mode_page_util::ModeSelect(scsi_command cmd, cdb_t cdb, span throw scsi_exception(sense_key::illegal_request, asc::parameter_list_length_error); } - // With this page the sector size for a subsequent FORMAT can be selected, but only very few - // drives support this, e.g FUJITSU M2624S. - // We are fine as long as the current sector size remains unchanged. - HandleSectorSizeChange(buf, offset + 12, sector_size); + // With this page the sector size for a subsequent FORMAT can be selected, but only a few drives + // support this, e.g FUJITSU M2624S. + // We are fine as long as the permanent current sector size remains unchanged. + HandleSectorSizeChange(buf, offset + 12, sector_size, false); break; } @@ -79,9 +79,11 @@ void mode_page_util::ModeSelect(scsi_command cmd, cdb_t cdb, span length -= size; offset += size; } + + return sector_size; } -int mode_page_util::EvaluateBlockDescriptors(scsi_command cmd, span buf, int length, int sector_size) +int mode_page_util::EvaluateBlockDescriptors(scsi_command cmd, span buf, int length, int §or_size) { assert(cmd == scsi_command::cmd_mode_select6 || cmd == scsi_command::cmd_mode_select10); @@ -102,24 +104,32 @@ int mode_page_util::EvaluateBlockDescriptors(scsi_command cmd, span= required_length + 8) { - HandleSectorSizeChange(buf, required_length + 6, sector_size); + sector_size = HandleSectorSizeChange(buf, required_length + 6, sector_size, true); } return block_descriptor_length + required_length; } -void mode_page_util::HandleSectorSizeChange(span buf, int offset, int sector_size) +int mode_page_util::HandleSectorSizeChange(span buf, int offset, int sector_size, bool temporary) { if (const int requested_size = GetInt16(buf, offset); requested_size != sector_size) { // Simple consistency check if (!(requested_size & 0xe1ff)) { - warn( - "Sector size change from {} to {} bytes requested. Configure the requested sector size in the s2p settings.", - sector_size, requested_size); + if (temporary) { + trace("Temporarily changing sector size from {0} to {1} bytes", sector_size, requested_size); + return requested_size; + } + else { + warn( + "Sector size change from {0} to {1} bytes requested. Configure the requested sector size in the s2p settings.", + sector_size, requested_size); + } } throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_parameter_list); } + + return sector_size; } void mode_page_util::EnrichFormatPage(map> &pages, bool changeable, int sector_size) diff --git a/cpp/devices/mode_page_util.h b/cpp/devices/mode_page_util.h index 99ced488..a76139b1 100644 --- a/cpp/devices/mode_page_util.h +++ b/cpp/devices/mode_page_util.h @@ -4,8 +4,6 @@ // // Copyright (C) 2022-2024 Uwe Seimet // -// Shared code for SCSI command implementations -// //--------------------------------------------------------------------------- #pragma once @@ -19,9 +17,9 @@ using namespace std; namespace mode_page_util { -void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int, int); -int EvaluateBlockDescriptors(scsi_defs::scsi_command, span, int, int); -void HandleSectorSizeChange(span, int, int); +int ModeSelect(scsi_defs::scsi_command, cdb_t, span, int, int); +int EvaluateBlockDescriptors(scsi_defs::scsi_command, span, int, int&); +int HandleSectorSizeChange(span, int, int, bool); void EnrichFormatPage(map>&, bool, int); void AddAppleVendorModePage(map>&, bool); } diff --git a/cpp/devices/optical_memory.cpp b/cpp/devices/optical_memory.cpp index 49f098af..d283e57a 100644 --- a/cpp/devices/optical_memory.cpp +++ b/cpp/devices/optical_memory.cpp @@ -48,7 +48,7 @@ void OpticalMemory::Open() Disk::ValidateFile(); - SetUpCache(0); + SetUpCache(); // Attention if ready if (IsReady()) { @@ -86,9 +86,17 @@ void OpticalMemory::AddOptionPage(map> &pages, bool) const // Do not report update blocks } -void OpticalMemory::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) const +void OpticalMemory::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) { - mode_page_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount()); + const auto current_sector_size = static_cast(GetSectorSizeInBytes()); + const auto new_sector_size = mode_page_util::ModeSelect(cmd, cdb, buf, length, current_sector_size); + if (new_sector_size != current_sector_size) { + const uint64_t capacity = current_sector_size * GetBlockCount(); + SetSectorSizeInBytes(new_sector_size); + SetBlockCount(static_cast(capacity >> GetSectorSizeShiftCount())); + + SetUpCache(); + } } // diff --git a/cpp/devices/optical_memory.h b/cpp/devices/optical_memory.h index 7e3d7a31..d6e0e9a9 100644 --- a/cpp/devices/optical_memory.h +++ b/cpp/devices/optical_memory.h @@ -28,7 +28,7 @@ class OpticalMemory : public Disk void Open() override; vector InquiryInternal() const override; - void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) const override; + void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) override; protected: diff --git a/cpp/devices/scsi_cd.cpp b/cpp/devices/scsi_cd.cpp index 022ac92e..a8c8d86b 100644 --- a/cpp/devices/scsi_cd.cpp +++ b/cpp/devices/scsi_cd.cpp @@ -47,7 +47,7 @@ void ScsiCd::Open() // Initialization, track clear SetBlockCount(0); - rawfile = false; + raw_file = false; ClearTrack(); // Default sector size is 2048 bytes @@ -70,7 +70,7 @@ void ScsiCd::Open() Disk::ValidateFile(); - SetUpCache(0, rawfile); + SetUpCache(raw_file); SetReadOnly(true); SetProtectable(false); @@ -99,7 +99,7 @@ void ScsiCd::OpenIso() array sync = { }; // 00,FFx10,00 is presumed to be RAW format fill_n(sync.begin() + 1, 10, 0xff); - rawfile = false; + raw_file = false; if (memcmp(header.data(), sync.data(), sync.size()) == 0) { // Supports MODE1/2048 or MODE1/2352 only @@ -108,10 +108,10 @@ void ScsiCd::OpenIso() throw io_exception("Illegal raw ISO CD-ROM file header"); } - rawfile = true; + raw_file = true; } - if (rawfile) { + if (raw_file) { if (size % 2536) { LogWarn(fmt::format("Raw ISO CD-ROM file size is not a multiple of 2536 bytes but is {} byte(s)", size)); } @@ -147,9 +147,17 @@ vector ScsiCd::InquiryInternal() const return HandleInquiry(device_type::cd_rom, scsi_level, true); } -void ScsiCd::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) const +void ScsiCd::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) { - mode_page_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount()); + const auto current_sector_size = static_cast(GetSectorSizeInBytes()); + const auto new_sector_size = mode_page_util::ModeSelect(cmd, cdb, buf, length, current_sector_size); + if (new_sector_size != current_sector_size) { + const uint64_t capacity = current_sector_size * GetBlockCount(); + SetSectorSizeInBytes(new_sector_size); + SetBlockCount(static_cast(capacity >> GetSectorSizeShiftCount())); + + SetUpCache(); + } } void ScsiCd::SetUpModePages(map> &pages, int page, bool changeable) const @@ -225,7 +233,7 @@ int ScsiCd::Read(span buf, uint64_t block) assert(GetBlockCount() > 0); // Re-assign disk cache (no need to save) - Resize_cache(tracks[index]->GetPath(), rawfile); + ResizeCache(tracks[index]->GetPath(), raw_file); // Reset data index dataindex = index; diff --git a/cpp/devices/scsi_cd.h b/cpp/devices/scsi_cd.h index 512ca3a0..3ffcdc30 100644 --- a/cpp/devices/scsi_cd.h +++ b/cpp/devices/scsi_cd.h @@ -31,7 +31,7 @@ class ScsiCd : public Disk, private ScsiMmcCommands void Open() override; vector InquiryInternal() const override; - void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) const override; + void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) override; int Read(span, uint64_t) override; protected: @@ -57,7 +57,7 @@ class ScsiCd : public Disk, private ScsiMmcCommands scsi_defs::scsi_level scsi_level; - bool rawfile = false; // RAW flag + bool raw_file = false; // RAW flag // Track management void ClearTrack(); // Clear the track diff --git a/cpp/devices/scsi_hd.cpp b/cpp/devices/scsi_hd.cpp index 51a7b870..6662aba9 100644 --- a/cpp/devices/scsi_hd.cpp +++ b/cpp/devices/scsi_hd.cpp @@ -53,7 +53,7 @@ string ScsiHd::GetProductData() const return DEFAULT_PRODUCT + " " + to_string(capacity) + " " + unit; } -void ScsiHd::FinalizeSetup(off_t image_offset) +void ScsiHd::FinalizeSetup() { Disk::ValidateFile(); @@ -62,7 +62,7 @@ void ScsiHd::FinalizeSetup(off_t image_offset) SetProduct(GetProductData(), false); } - SetUpCache(image_offset); + SetUpCache(); } void ScsiHd::Open() @@ -75,7 +75,7 @@ void ScsiHd::Open() SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512); SetBlockCount(static_cast(size >> GetSectorSizeShiftCount())); - FinalizeSetup(0); + FinalizeSetup(); } vector ScsiHd::InquiryInternal() const @@ -83,9 +83,17 @@ vector ScsiHd::InquiryInternal() const return HandleInquiry(device_type::direct_access, scsi_level, IsRemovable()); } -void ScsiHd::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) const +void ScsiHd::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) { - mode_page_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount()); + const auto current_sector_size = static_cast(GetSectorSizeInBytes()); + const auto new_sector_size = mode_page_util::ModeSelect(cmd, cdb, buf, length, current_sector_size); + if (new_sector_size != current_sector_size) { + const uint64_t capacity = current_sector_size * GetBlockCount(); + SetSectorSizeInBytes(new_sector_size); + SetBlockCount(static_cast(capacity >> GetSectorSizeShiftCount())); + + SetUpCache(); + } } void ScsiHd::AddFormatPage(map> &pages, bool changeable) const diff --git a/cpp/devices/scsi_hd.h b/cpp/devices/scsi_hd.h index 617c3dad..e5393e00 100644 --- a/cpp/devices/scsi_hd.h +++ b/cpp/devices/scsi_hd.h @@ -24,12 +24,12 @@ class ScsiHd : public Disk ScsiHd(int, bool, bool, bool, const unordered_set& = { 512, 1024, 2048, 4096 }); ~ScsiHd() override = default; - void FinalizeSetup(off_t); + void FinalizeSetup(); void Open() override; vector InquiryInternal() const override; - void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) const override; + void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) override; void AddFormatPage(map>&, bool) const override; diff --git a/cpp/test/mode_page_util_test.cpp b/cpp/test/mode_page_util_test.cpp index 4a755327..4eebc0d6 100644 --- a/cpp/test/mode_page_util_test.cpp +++ b/cpp/test/mode_page_util_test.cpp @@ -21,13 +21,13 @@ TEST(ModePageUtilTest, ModeSelect6) // PF (vendor-specific parameter format) must not fail but be ignored cdb[1] = 0x00; - ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, LENGTH, 0); + EXPECT_EQ(1024, ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, LENGTH, 1024)); // PF (standard parameter format) cdb[1] = 0x10; // A length of 0 is valid, the page data are optional - ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, 0, 0); + EXPECT_EQ(512, ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, 0, 512)); // Page 0 buf[4] = 0x00; @@ -46,7 +46,7 @@ TEST(ModePageUtilTest, ModeSelect6) Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))) << "Not enough command parameters"; - ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, 16, 512); + EXPECT_EQ(512, ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, 16, 512)); // Page 7 (Verify error recovery page) buf[4] = 0x07; @@ -57,7 +57,7 @@ TEST(ModePageUtilTest, ModeSelect6) Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))) << "Not enough command parameters"; - ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, 10, 512); + EXPECT_EQ(512, ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, 10, 512)); // Page 3 (Format device page) buf[4] = 0x03; @@ -70,14 +70,14 @@ TEST(ModePageUtilTest, ModeSelect6) << "Requested sector size does not match current sector size"; // Match the requested to the current sector size - buf[16] = 0x02; - EXPECT_THAT([&] {ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, LENGTH - 10, 512);}, + buf[16] = 0x08; + EXPECT_THAT([&] {ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, LENGTH - 10, 2048);}, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))) << "Not enough command parameters"; - ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, LENGTH, 512); + EXPECT_EQ(2048, ModeSelect(scsi_command::cmd_mode_select6, cdb, buf, LENGTH, 2048)); } TEST(ModePageUtilTest, ModeSelect10) @@ -89,13 +89,13 @@ TEST(ModePageUtilTest, ModeSelect10) // PF (vendor-specific parameter format) must not fail but be ignored cdb[1] = 0x00; - ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, LENGTH, 0); + EXPECT_EQ(1024, ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, LENGTH, 1024)); // PF (standard parameter format) cdb[1] = 0x10; // A length of 0 is valid, the page data are optional - ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, 0, 0); + EXPECT_EQ(512, ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, 0, 512)); // Page 0 buf[8] = 0x00; @@ -114,7 +114,7 @@ TEST(ModePageUtilTest, ModeSelect10) Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))) << "Not enough command parameters"; - ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, 20, 512); + EXPECT_EQ(512, ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, 20, 512)); // Page 7 (Verify error recovery page) buf[8] = 0x07; @@ -125,7 +125,7 @@ TEST(ModePageUtilTest, ModeSelect10) Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))) << "Not enough command parameters"; - ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, 14, 512); + EXPECT_EQ(512, ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, 14, 512)); // Page 3 (Format device page) buf[8] = 0x03; @@ -138,26 +138,27 @@ TEST(ModePageUtilTest, ModeSelect10) << "Requested sector size does not match current sector size"; // Match the requested to the current sector size - buf[20] = 0x02; - EXPECT_THAT([&] {ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, LENGTH - 10, 512);}, + buf[20] = 0x08; + EXPECT_THAT([&] {ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, LENGTH - 10, 2048);}, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))) << "Not enough command parameters"; - ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, LENGTH, 512); + EXPECT_EQ(2048, ModeSelect(scsi_command::cmd_mode_select10, cdb, buf, LENGTH, 2048)); } TEST(ModePageUtilTest, EvaluateBlockDescriptors) { vector buf(8); + int sector_size = 512; - EXPECT_THAT([&] {EvaluateBlockDescriptors(scsi_command::cmd_mode_select6, buf, 0, 512);}, + EXPECT_THAT([&] {EvaluateBlockDescriptors(scsi_command::cmd_mode_select6, buf, 0, sector_size);}, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))); - EXPECT_THAT([&] {EvaluateBlockDescriptors(scsi_command::cmd_mode_select10, buf, 0, 512);}, + EXPECT_THAT([&] {EvaluateBlockDescriptors(scsi_command::cmd_mode_select10, buf, 0, sector_size);}, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::parameter_list_length_error)))); @@ -167,17 +168,27 @@ TEST(ModePageUtilTest, HandleSectorSizeChange) { vector buf = { 0x02, 0x00 }; - HandleSectorSizeChange(buf, 0, 512); + EXPECT_EQ(512, HandleSectorSizeChange(buf, 0, 512, false)); buf[0] = 0x04; - EXPECT_THAT([&] {HandleSectorSizeChange(buf, 0, 512);}, + + // Temporary change + EXPECT_EQ(1024, HandleSectorSizeChange(buf, 0, 512, true)); + + // Permanent change + EXPECT_THAT([&] {HandleSectorSizeChange(buf, 0, 512, false);}, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::invalid_field_in_parameter_list)))); + // Sector size 513 is always invalid buf[0] = 0x02; buf[1] = 0x01; - EXPECT_THAT([&] {HandleSectorSizeChange(buf, 0, 512);}, + EXPECT_THAT([&] {HandleSectorSizeChange(buf, 0, 512, false);}, + Throws(AllOf( + Property(&scsi_exception::get_sense_key, sense_key::illegal_request), + Property(&scsi_exception::get_asc, asc::invalid_field_in_parameter_list)))); + EXPECT_THAT([&] {HandleSectorSizeChange(buf, 0, 512, true);}, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::invalid_field_in_parameter_list)))); diff --git a/cpp/test/scsi_hd_test.cpp b/cpp/test/scsi_hd_test.cpp index 55a1495a..3ecbf39d 100644 --- a/cpp/test/scsi_hd_test.cpp +++ b/cpp/test/scsi_hd_test.cpp @@ -78,7 +78,7 @@ TEST(ScsiHdTest, FinalizeSetup) MockScsiHd hd(0, false); hd.SetSectorSizeInBytes(1024); - EXPECT_THROW(hd.FinalizeSetup(0), io_exception)<< "Device has 0 blocks"; + EXPECT_THROW(hd.FinalizeSetup(), io_exception)<< "Device has 0 blocks"; } TEST(ScsiHdTest, GetProductData) @@ -91,21 +91,21 @@ TEST(ScsiHdTest, GetProductData) hd_kb.SetFilename(string(filename)); hd_kb.SetSectorSizeInBytes(1024); hd_kb.SetBlockCount(1); - hd_kb.FinalizeSetup(0); + hd_kb.FinalizeSetup(); string s = hd_kb.GetProduct(); EXPECT_NE(string::npos, s.find("1 KiB")); hd_mb.SetFilename(string(filename)); hd_mb.SetSectorSizeInBytes(1024); hd_mb.SetBlockCount(1'048'576 / 1024); - hd_mb.FinalizeSetup(0); + hd_mb.FinalizeSetup(); s = hd_mb.GetProduct(); EXPECT_NE(string::npos, s.find("1 MiB")); hd_gb.SetFilename(string(filename)); hd_gb.SetSectorSizeInBytes(1024); hd_gb.SetBlockCount(10'737'418'240 / 1024); - hd_gb.FinalizeSetup(0); + hd_gb.FinalizeSetup(); s = hd_gb.GetProduct(); EXPECT_NE(string::npos, s.find("10 GiB")); remove(filename);