Skip to content

Commit

Permalink
Honor sector size change via ModeSelect6 in scsicd (#1406)
Browse files Browse the repository at this point in the history
* Make ModeSelect() non-const

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>

* Implement ModeSelect for scsicd

and honor sector size setting.

DEC's VMS can't handle 2k sector sizes and uses ModeSelect6 to set the
sector size to 512 bytes.

Fixes #1397

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>

* Test sector size setting via ModeSelect in SCSICD

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>

* Re-calculate total blocks when sector size changes

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>

* Reset CD data tracks after sector size change

The track calculation is based on sector size and must be reset after
change of sector size.

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>

* resize cache after change of sector size

The disk cache is based on sector size and must be resized when the
sector size changes.

Disk::ResizeCache needs a `raw` parameter, make this value accessible
from the current cache.

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>

* Make GetRawMode const

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>

---------

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>
  • Loading branch information
kkaempf authored Jan 9, 2024
1 parent ad5eae9 commit b7f65d3
Show file tree
Hide file tree
Showing 13 changed files with 64 additions and 9 deletions.
10 changes: 8 additions & 2 deletions cpp/devices/disk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,11 +696,17 @@ uint32_t Disk::GetSectorSizeInBytes() const
void Disk::SetSectorSizeInBytes(uint32_t size_in_bytes)
{
if (!GetSupportedSectorSizes().contains(size_in_bytes)) {
throw io_exception("Invalid sector size of " + to_string(size_in_bytes) + " byte(s)");
throw io_exception("Invalid sector size of " + to_string(size_in_bytes) + " byte(s)");
}
uint64_t current_blocks = GetBlockCount();
uint32_t current_size_shift_count = size_shift_count;
uint64_t current_size = current_blocks << current_size_shift_count;

size_shift_count = CalculateShiftCount(size_in_bytes);
assert(size_shift_count);
if ((current_blocks > 0) && (current_size_shift_count > 0)) {
SetBlockCount(current_size >> size_shift_count);
}
}

uint32_t Disk::GetConfiguredSectorSize() const
Expand All @@ -714,7 +720,7 @@ bool Disk::SetConfiguredSectorSize(uint32_t configured_size)
return false;
}

configured_sector_size = configured_size;
configured_sector_size = configured_size;

return true;
}
Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/disk.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class Disk : public StorageDevice, private ScsiBlockCommands

void SetUpCache(off_t, bool = false);
void ResizeCache(const string&, bool);

bool GetRawMode() const { return (cache?cache->GetRawMode():false); }
void SetUpModePages(map<int, vector<byte>>&, int, bool) const override;
void AddErrorPage(map<int, vector<byte>>&, bool) const;
virtual void AddFormatPage(map<int, vector<byte>>&, bool) const;
Expand Down
1 change: 1 addition & 0 deletions cpp/devices/disk_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class DiskCache
~DiskCache() = default;

void SetRawMode(bool b) { cd_raw = b; } // CD-ROM raw mode setting
bool GetRawMode() const { return cd_raw; }

bool Save(); // Save and release all
bool ReadSector(span<uint8_t>, uint32_t); // Sector Read
Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/mode_page_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void ModePageDevice::ModeSense10() const
EnterDataInPhase();
}

void ModePageDevice::ModeSelect(scsi_command, cdb_t, span<const uint8_t>, int) const
void ModePageDevice::ModeSelect(scsi_command, cdb_t, span<const uint8_t>, int)
{
// There is no default implementation of MODE SELECT
throw scsi_exception(sense_key::illegal_request, asc::invalid_command_operation_code);
Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/mode_page_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ModePageDevice : public PrimaryDevice

bool Init(const param_map&) override;

virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int) const;
virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int);

protected:

Expand Down
23 changes: 23 additions & 0 deletions cpp/devices/scsicd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,29 @@ vector<uint8_t> SCSICD::InquiryInternal() const
return HandleInquiry(device_type::cd_rom, scsi_level, true);
}

void SCSICD::ModeSelect(scsi_command cmd, cdb_t cdb, span<const uint8_t> buf, int length)
{
int sector_size = 1 << GetSectorSizeShiftCount();
int wanted_sector_size;
// skip Block Descriptor
int offset = 4;
// evaluate Mode Parameter Block Descriptor, sector size
wanted_sector_size = scsi_command_util::GetInt16(buf, offset + 6);
if (wanted_sector_size != sector_size) {
LogDebug("Changing sector size from " + to_string(sector_size) + " to " + to_string(wanted_sector_size));
SetSectorSizeInBytes(wanted_sector_size);
ClearTrack();
CreateDataTrack();
FlushCache();
ResizeCache(GetFilename(), GetRawMode());
}

if (const string result = scsi_command_util::ModeSelect(cmd, cdb, buf, length, sector_size);
!result.empty()) {
LogWarn(result);
}
}

void SCSICD::SetUpModePages(map<int, vector<byte>>& pages, int page, bool changeable) const
{
Disk::SetUpModePages(pages, page, changeable);
Expand Down
1 change: 1 addition & 0 deletions cpp/devices/scsicd.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class SCSICD : public Disk, private ScsiMmcCommands

vector<uint8_t> InquiryInternal() const override;
int Read(span<uint8_t>, uint64_t) override;
void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int) override;

protected:

Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/scsihd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ vector<uint8_t> SCSIHD::InquiryInternal() const
return HandleInquiry(device_type::direct_access, scsi_level, IsRemovable());
}

void SCSIHD::ModeSelect(scsi_command cmd, cdb_t cdb, span<const uint8_t> buf, int length) const
void SCSIHD::ModeSelect(scsi_command cmd, cdb_t cdb, span<const uint8_t> buf, int length)
{
if (const string result = scsi_command_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount());
!result.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/scsihd.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class SCSIHD : public Disk

// Commands
vector<uint8_t> InquiryInternal() const override;
void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int) const override;
void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int) override;

void AddFormatPage(map<int, vector<byte>>&, bool) const override;
void AddVendorPage(map<int, vector<byte>>&, int, bool) const override;
Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/scsimo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ void SCSIMO::AddOptionPage(map<int, vector<byte>>& pages, bool) const
// Do not report update blocks
}

void SCSIMO::ModeSelect(scsi_command cmd, cdb_t cdb, span<const uint8_t> buf, int length) const
void SCSIMO::ModeSelect(scsi_command cmd, cdb_t cdb, span<const uint8_t> buf, int length)
{
if (const string result = scsi_command_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount());
!result.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/scsimo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class SCSIMO : public Disk
void Open() override;

vector<uint8_t> InquiryInternal() const override;
void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int) const override;
void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int) override;

protected:

Expand Down
1 change: 1 addition & 0 deletions cpp/test/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ class MockSCSICD : public SCSICD //NOSONAR Ignore inheritance hierarchy depth in
FRIEND_TEST(ScsiCdTest, GetSectorSizes);
FRIEND_TEST(ScsiCdTest, SetUpModePages);
FRIEND_TEST(ScsiCdTest, ReadToc);
FRIEND_TEST(ScsiCdTest, ModeSelect);

using SCSICD::SCSICD;
};
Expand Down
23 changes: 23 additions & 0 deletions cpp/test/scsicd_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,26 @@ TEST(ScsiCdTest, ReadToc)

// Further testing requires filesystem access
}

TEST(ScsiCdTest, ModeSelect)
{
MockSCSICD cd(0);
vector<int> cmd(6);
vector<uint8_t> buf(255);

cd.SetSectorSizeInBytes(2048);

// PF
cmd[1] = 0x10;
// Length
buf[3] = 0x08;
// 2048 bytes per sector
buf[10] = 0x08;
// Page 3 (Device Format Page)
buf[12] = 0x01;
EXPECT_NO_THROW(cd.ModeSelect(scsi_command::eCmdModeSelect6, cmd, buf, 255)) << "MODE SELECT(6) with sector size 2048 is supported";

// 512 bytes per sector
buf[10] = 0x02;
EXPECT_NO_THROW(cd.ModeSelect(scsi_command::eCmdModeSelect6, cmd, buf, 255)) << "MODE SELECT(6) with sector size 512 is supported";
}

0 comments on commit b7f65d3

Please sign in to comment.