From 69c59b590f4421e02d172037972b9ae4dc910199 Mon Sep 17 00:00:00 2001 From: Uwe Seimet Date: Mon, 9 Dec 2024 12:03:45 +0100 Subject: [PATCH] Add support for WRITE FILEMARKS(16) --- cpp/devices/tape.cpp | 30 +++++++++++++++++++---- cpp/devices/tape.h | 1 + cpp/shared/command_meta_data.cpp | 1 + cpp/shared/scsi.h | 1 + cpp/test/command_meta_data_test.cpp | 3 ++- cpp/test/mocks.h | 4 +++- cpp/test/tape_test.cpp | 37 +++++++++++++++++++++++++---- 7 files changed, 67 insertions(+), 10 deletions(-) diff --git a/cpp/devices/tape.cpp b/cpp/devices/tape.cpp index e2606794..b5750034 100644 --- a/cpp/devices/tape.cpp +++ b/cpp/devices/tape.cpp @@ -63,6 +63,10 @@ bool Tape::SetUp() { WriteFilemarks6(); }); + AddCommand(scsi_command::write_filemarks_16, [this] + { + WriteFilemarks(true); + }); AddCommand(scsi_command::locate_10, [this] { Locate(false); @@ -461,9 +465,14 @@ void Tape::Space6() } void Tape::WriteFilemarks6() +{ + WriteFilemarks(false); +} + +void Tape::WriteFilemarks(bool write_filemarks_16) { if (tar_file) { - LogTrace("Writing filemarks in tar-compatibility mode is not supported, WRITE FILEMARKS(6) command is ignored"); + LogTrace("Writing filemarks in tar-compatibility mode is not supported, WRITE FILEMARKS command is ignored"); StatusPhase(); return; } @@ -475,21 +484,34 @@ void Tape::WriteFilemarks6() CheckWritePreconditions(); - for (int i = 0; i < GetCdbInt24(2); i++) { + int count; + if (write_filemarks_16) { + if (const auto identifier = static_cast(GetCdbInt64(4)); identifier) { + ResetPositions(); + FindObject(identifier); + } + + count = GetCdbInt24(12); + } + else { + count = GetCdbInt24(2); + } + + for (int i = 0; i < count; i++) { WriteMetaData(object_type::filemark); } StatusPhase(); } -void Tape::Locate(bool locate16) +void Tape::Locate(bool locate_16) { // CP is not supported if (GetCdbByte(1) & 0x02) { throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_cdb); } - auto identifier = static_cast(locate16 ? GetCdbInt64(4) : GetCdbInt32(3)); + auto identifier = static_cast(locate_16 ? GetCdbInt64(4) : GetCdbInt32(3)); const bool bt = GetCdbByte(1) & 0x04; if (tar_file) { diff --git a/cpp/devices/tape.h b/cpp/devices/tape.h index 76c93292..ede7dac8 100644 --- a/cpp/devices/tape.h +++ b/cpp/devices/tape.h @@ -78,6 +78,7 @@ class Tape : public StorageDevice, public ScsiStreamCommands void Rewind() override; void Space6() override; void WriteFilemarks6() override; + void WriteFilemarks(bool); void FormatMedium(); void ReadPosition() const; void Locate(bool); diff --git a/cpp/shared/command_meta_data.cpp b/cpp/shared/command_meta_data.cpp index 13363ead..6604d534 100644 --- a/cpp/shared/command_meta_data.cpp +++ b/cpp/shared/command_meta_data.cpp @@ -52,6 +52,7 @@ CommandMetaData::CommandMetaData() AddCommand(scsi_command::read_toc, 10, "READ TOC"); AddCommand(scsi_command::mode_select_10, 10, "MODE SELECT(10)"); AddCommand(scsi_command::mode_sense_10, 10, "MODE SENSE(10)"); + AddCommand(scsi_command::write_filemarks_16, 16, "WRITE FILEMARKS(16)"); AddCommand(scsi_command::read_16, 16, "READ(16)"); AddCommand(scsi_command::write_16, 16, "WRITE(16)"); AddCommand(scsi_command::verify_16, 16, "VERIFY(16)"); diff --git a/cpp/shared/scsi.h b/cpp/shared/scsi.h index 0b65ed3d..91b7a7b8 100644 --- a/cpp/shared/scsi.h +++ b/cpp/shared/scsi.h @@ -100,6 +100,7 @@ enum class scsi_command read_toc = 0x43, mode_select_10 = 0x55, mode_sense_10 = 0x5a, + write_filemarks_16 = 0x80, read_16 = 0x88, write_16 = 0x8a, verify_16 = 0x8f, diff --git a/cpp/test/command_meta_data_test.cpp b/cpp/test/command_meta_data_test.cpp index cdb793c2..607508c3 100644 --- a/cpp/test/command_meta_data_test.cpp +++ b/cpp/test/command_meta_data_test.cpp @@ -59,6 +59,7 @@ TEST(CommandMetaDataTest, GetCommandBytesCount) EXPECT_EQ(10, meta_data.GetCommandBytesCount(scsi_command::read_toc)); EXPECT_EQ(10, meta_data.GetCommandBytesCount(scsi_command::mode_select_10)); EXPECT_EQ(10, meta_data.GetCommandBytesCount(scsi_command::mode_sense_10)); + EXPECT_EQ(16, meta_data.GetCommandBytesCount(scsi_command::write_filemarks_16)); EXPECT_EQ(16, meta_data.GetCommandBytesCount(scsi_command::read_16)); EXPECT_EQ(16, meta_data.GetCommandBytesCount(scsi_command::write_16)); EXPECT_EQ(16, meta_data.GetCommandBytesCount(scsi_command::verify_16)); @@ -77,7 +78,7 @@ TEST(CommandMetaDataTest, GetCommandBytesCount) ++command_count; } } - EXPECT_EQ(48, command_count); + EXPECT_EQ(49, command_count); } TEST(CommandMetaDataTest, LogCdb) diff --git a/cpp/test/mocks.h b/cpp/test/mocks.h index 522f6d7e..01b2caad 100644 --- a/cpp/test/mocks.h +++ b/cpp/test/mocks.h @@ -167,8 +167,10 @@ class MockAbstractController : public AbstractController // NOSONAR Having many FRIEND_TEST(TapeTest, Rewind); FRIEND_TEST(TapeTest, Space6_simh); FRIEND_TEST(TapeTest, Space6_tar); - FRIEND_TEST(TapeTest, WriteFileMarks6_simh); FRIEND_TEST(TapeTest, WriteFileMarks6_tar); + FRIEND_TEST(TapeTest, WriteFileMarks6_simh); + FRIEND_TEST(TapeTest, WriteFileMarks16_tar); + FRIEND_TEST(TapeTest, WriteFileMarks16_simh); FRIEND_TEST(TapeTest, FormatMedium_simh); FRIEND_TEST(TapeTest, FormatMedium_tar); FRIEND_TEST(TapeTest, Locate10_simh); diff --git a/cpp/test/tape_test.cpp b/cpp/test/tape_test.cpp index 82c40fbc..40178bfc 100644 --- a/cpp/test/tape_test.cpp +++ b/cpp/test/tape_test.cpp @@ -687,17 +687,17 @@ TEST(TapeTest, WriteFileMarks6_simh) controller->SetCdbByte(1, 0b010); Dispatch(tape, scsi_command::write_filemarks_6, sense_key::illegal_request, asc::invalid_field_in_cdb); - // Count = 0 + // 0 filemarks controller->SetCdbByte(1, 0b001); EXPECT_NO_THROW(Dispatch(tape, scsi_command::write_filemarks_6)); - // Count = 100 + // 100 filemarks controller->SetCdbByte(1, 0b001); controller->SetCdbByte(4, 100); EXPECT_NO_THROW(Dispatch(tape, scsi_command::write_filemarks_6)); CheckPositions(tape, 400, 0); - // Count = 100 + // 100 filemarks controller->SetCdbByte(1, 0b001); controller->SetCdbByte(4, 100); Dispatch(tape, scsi_command::write_filemarks_6, sense_key::volume_overflow); @@ -713,10 +713,39 @@ TEST(TapeTest, WriteFileMarks6_tar) auto [controller, tape] = CreateTape(); CreateImageFile(*tape, 512, "tar"); - controller->SetCdbByte(1, 0b001); EXPECT_NO_THROW(Dispatch(tape, scsi_command::write_filemarks_6)); } +TEST(TapeTest, WriteFileMarks16_simh) +{ + auto [controller, tape] = CreateTape(); + CreateImageFile(*tape, 1024); + + // 0 filemarks + EXPECT_NO_THROW(Dispatch(tape, scsi_command::write_filemarks_16)); + + // 100 filemarks + controller->SetCdbByte(14, 100); + EXPECT_NO_THROW(Dispatch(tape, scsi_command::write_filemarks_16)); + CheckPositions(tape, 400, 0); + + // 100 filemarks + controller->SetCdbByte(14, 100); + Dispatch(tape, scsi_command::write_filemarks_16, sense_key::volume_overflow); + CheckPositions(tape, 512, 0); + + tape->SetProtected(true); + Dispatch(tape, scsi_command::write_filemarks_16, sense_key::data_protect, asc::write_protected); +} + +TEST(TapeTest, WriteFileMarks16_tar) +{ + auto [controller, tape] = CreateTape(); + CreateImageFile(*tape, 512, "tar"); + + EXPECT_NO_THROW(Dispatch(tape, scsi_command::write_filemarks_16)); +} + TEST(TapeTest, Locate10_simh) { auto [controller, tape] = CreateTape();