2022-02-10 18:54:48 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2022-12-05 17:58:23 +00:00
|
|
|
// SCSI Target Emulator PiSCSI
|
2022-02-10 18:54:48 +00:00
|
|
|
// for Raspberry Pi
|
|
|
|
//
|
2023-10-15 06:38:15 +00:00
|
|
|
// Copyright (C) 2022-2023 Uwe Seimet
|
2022-02-10 18:54:48 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-12-05 17:58:23 +00:00
|
|
|
#include "shared/piscsi_exceptions.h"
|
2022-10-01 15:56:06 +00:00
|
|
|
#include "scsi_command_util.h"
|
2022-02-10 18:54:48 +00:00
|
|
|
#include "primary_device.h"
|
2022-11-11 20:08:48 +00:00
|
|
|
#include <sstream>
|
|
|
|
#include <iomanip>
|
2022-02-10 18:54:48 +00:00
|
|
|
|
|
|
|
using namespace std;
|
2022-02-13 19:30:02 +00:00
|
|
|
using namespace scsi_defs;
|
2022-10-01 15:56:06 +00:00
|
|
|
using namespace scsi_command_util;
|
2022-02-10 18:54:48 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
bool PrimaryDevice::Init(const param_map& params)
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
|
|
|
// Mandatory SCSI primary commands
|
2022-11-02 14:36:19 +00:00
|
|
|
AddCommand(scsi_command::eCmdTestUnitReady, [this] { TestUnitReady(); });
|
|
|
|
AddCommand(scsi_command::eCmdInquiry, [this] { Inquiry(); });
|
|
|
|
AddCommand(scsi_command::eCmdReportLuns, [this] { ReportLuns(); });
|
2022-02-10 18:54:48 +00:00
|
|
|
|
2022-12-05 17:58:23 +00:00
|
|
|
// Optional commands supported by all PiSCSI devices
|
2022-11-02 14:36:19 +00:00
|
|
|
AddCommand(scsi_command::eCmdRequestSense, [this] { RequestSense(); });
|
|
|
|
AddCommand(scsi_command::eCmdReserve6, [this] { ReserveUnit(); });
|
|
|
|
AddCommand(scsi_command::eCmdRelease6, [this] { ReleaseUnit(); });
|
|
|
|
AddCommand(scsi_command::eCmdSendDiagnostic, [this] { SendDiagnostic(); });
|
|
|
|
|
|
|
|
SetParams(params);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
void PrimaryDevice::AddCommand(scsi_command cmd, const operation& execute)
|
2022-11-02 14:36:19 +00:00
|
|
|
{
|
2023-10-15 06:38:15 +00:00
|
|
|
commands[cmd] = execute;
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 14:36:19 +00:00
|
|
|
void PrimaryDevice::Dispatch(scsi_command cmd)
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
2022-11-11 20:08:48 +00:00
|
|
|
stringstream s;
|
|
|
|
s << "$" << setfill('0') << setw(2) << hex << static_cast<int>(cmd);
|
|
|
|
|
2022-11-02 14:36:19 +00:00
|
|
|
if (const auto& it = commands.find(cmd); it != commands.end()) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogDebug("Device is executing " + command_mapping.find(cmd)->second.second + " (" + s.str() + ")");
|
2022-11-02 14:36:19 +00:00
|
|
|
|
|
|
|
it->second();
|
|
|
|
}
|
|
|
|
else {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Received unsupported command: " + s.str());
|
2022-11-02 14:36:19 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
throw scsi_exception(sense_key::illegal_request, asc::invalid_command_operation_code);
|
2022-11-02 14:36:19 +00:00
|
|
|
}
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2022-10-23 19:51:39 +00:00
|
|
|
void PrimaryDevice::Reset()
|
|
|
|
{
|
|
|
|
DiscardReservation();
|
|
|
|
|
|
|
|
Device::Reset();
|
|
|
|
}
|
|
|
|
|
2022-10-04 15:23:42 +00:00
|
|
|
int PrimaryDevice::GetId() const
|
|
|
|
{
|
2022-11-04 07:22:32 +00:00
|
|
|
return GetController() != nullptr ? GetController()->GetTargetId() : -1;
|
2022-10-04 15:23:42 +00:00
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
void PrimaryDevice::SetController(AbstractController *c)
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
2022-09-10 05:59:41 +00:00
|
|
|
controller = c;
|
2022-11-11 20:08:48 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
device_logger.SetIdAndLun(GetId(), GetLun());
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PrimaryDevice::TestUnitReady()
|
|
|
|
{
|
|
|
|
CheckReady();
|
2022-02-10 18:54:48 +00:00
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
EnterStatusPhase();
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
void PrimaryDevice::Inquiry()
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
2022-03-02 02:25:22 +00:00
|
|
|
// EVPD and page code check
|
2023-10-15 06:38:15 +00:00
|
|
|
if ((GetController()->GetCmdByte(1) & 0x01) || GetController()->GetCmdByte(2)) {
|
|
|
|
throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_cdb);
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
const vector<uint8_t> buf = InquiryInternal();
|
2022-03-02 02:25:22 +00:00
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
const size_t allocation_length = min(buf.size(), static_cast<size_t>(GetInt16(GetController()->GetCmd(), 3)));
|
2022-03-02 02:25:22 +00:00
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
memcpy(GetController()->GetBuffer().data(), buf.data(), allocation_length);
|
|
|
|
GetController()->SetLength(static_cast<uint32_t>(allocation_length));
|
2022-02-18 20:04:07 +00:00
|
|
|
|
2022-02-10 18:54:48 +00:00
|
|
|
// Report if the device does not support the requested LUN
|
2023-10-15 06:38:15 +00:00
|
|
|
if (const int lun = GetController()->GetEffectiveLun(); !GetController()->HasDeviceForLun(lun)) {
|
|
|
|
LogTrace("LUN is not available");
|
2022-02-10 18:54:48 +00:00
|
|
|
|
2022-02-18 20:04:07 +00:00
|
|
|
// Signal that the requested LUN does not exist
|
2022-11-04 07:22:32 +00:00
|
|
|
GetController()->GetBuffer().data()[0] = 0x7f;
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
EnterDataInPhase();
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
void PrimaryDevice::ReportLuns()
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
2022-03-03 18:53:11 +00:00
|
|
|
// Only SELECT REPORT mode 0 is supported
|
2023-10-15 06:38:15 +00:00
|
|
|
if (GetController()->GetCmdByte(2)) {
|
|
|
|
throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_cdb);
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
}
|
2022-02-10 18:54:48 +00:00
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
const uint32_t allocation_length = GetInt32(GetController()->GetCmd(), 6);
|
2022-10-01 15:56:06 +00:00
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
vector<uint8_t>& buf = GetController()->GetBuffer();
|
2022-11-02 06:36:25 +00:00
|
|
|
fill_n(buf.begin(), min(buf.size(), static_cast<size_t>(allocation_length)), 0);
|
2022-10-01 15:56:06 +00:00
|
|
|
|
|
|
|
uint32_t size = 0;
|
2022-11-04 07:22:32 +00:00
|
|
|
for (int lun = 0; lun < GetController()->GetMaxLuns(); lun++) {
|
|
|
|
if (GetController()->HasDeviceForLun(lun)) {
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
size += 8;
|
2022-11-02 06:36:25 +00:00
|
|
|
buf[size + 7] = (uint8_t)lun;
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
}
|
2022-03-03 18:53:11 +00:00
|
|
|
}
|
2022-03-02 02:25:22 +00:00
|
|
|
|
2022-10-01 15:56:06 +00:00
|
|
|
SetInt16(buf, 2, size);
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
|
2022-03-02 02:25:22 +00:00
|
|
|
size += 8;
|
2022-02-10 18:54:48 +00:00
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
GetController()->SetLength(min(allocation_length, size));
|
2022-02-10 18:54:48 +00:00
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
EnterDataInPhase();
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
void PrimaryDevice::RequestSense()
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
2022-11-04 07:22:32 +00:00
|
|
|
int lun = GetController()->GetEffectiveLun();
|
2022-02-10 18:54:48 +00:00
|
|
|
|
|
|
|
// Note: According to the SCSI specs the LUN handling for REQUEST SENSE non-existing LUNs do *not* result
|
|
|
|
// in CHECK CONDITION. Only the Sense Key and ASC are set in order to signal the non-existing LUN.
|
2022-11-04 07:22:32 +00:00
|
|
|
if (!GetController()->HasDeviceForLun(lun)) {
|
2022-02-10 18:54:48 +00:00
|
|
|
// LUN 0 can be assumed to be present (required to call RequestSense() below)
|
2022-11-04 07:22:32 +00:00
|
|
|
assert(GetController()->HasDeviceForLun(0));
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
|
2022-02-10 18:54:48 +00:00
|
|
|
lun = 0;
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
// Do not raise an exception here because the rest of the code must be executed
|
2023-10-15 06:38:15 +00:00
|
|
|
GetController()->Error(sense_key::illegal_request, asc::invalid_lun);
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
GetController()->SetStatus(status::good);
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
vector<byte> buf = GetController()->GetDeviceForLun(lun)->HandleRequestSense();
|
2022-03-02 02:25:22 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
const size_t allocation_length = min(buf.size(), static_cast<size_t>(GetController()->GetCmdByte(4)));
|
2022-03-02 02:25:22 +00:00
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
memcpy(GetController()->GetBuffer().data(), buf.data(), allocation_length);
|
|
|
|
GetController()->SetLength(static_cast<uint32_t>(allocation_length));
|
2022-02-10 18:54:48 +00:00
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
EnterDataInPhase();
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2022-10-23 19:51:39 +00:00
|
|
|
void PrimaryDevice::SendDiagnostic()
|
|
|
|
{
|
|
|
|
// Do not support PF bit
|
2023-10-15 06:38:15 +00:00
|
|
|
if (GetController()->GetCmdByte(1) & 0x10) {
|
|
|
|
throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_cdb);
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do not support parameter list
|
2023-10-15 06:38:15 +00:00
|
|
|
if ((GetController()->GetCmdByte(3) != 0) || (GetController()->GetCmdByte(4) != 0)) {
|
|
|
|
throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_cdb);
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EnterStatusPhase();
|
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
void PrimaryDevice::CheckReady()
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
|
|
|
// Not ready if reset
|
|
|
|
if (IsReset()) {
|
|
|
|
SetReset(false);
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Device in reset");
|
|
|
|
throw scsi_exception(sense_key::unit_attention, asc::power_on_or_reset);
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Not ready if it needs attention
|
|
|
|
if (IsAttn()) {
|
|
|
|
SetAttn(false);
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Device in needs attention");
|
|
|
|
throw scsi_exception(sense_key::unit_attention, asc::not_ready_to_ready_change);
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return status if not ready
|
|
|
|
if (!IsReady()) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Device not ready");
|
|
|
|
throw scsi_exception(sense_key::not_ready, asc::medium_not_present);
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Device is ready");
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 14:36:19 +00:00
|
|
|
vector<uint8_t> PrimaryDevice::HandleInquiry(device_type type, scsi_level level, bool is_removable) const
|
2022-02-13 19:30:02 +00:00
|
|
|
{
|
2022-11-02 14:36:19 +00:00
|
|
|
vector<uint8_t> buf(0x1F + 5);
|
2022-03-02 02:25:22 +00:00
|
|
|
|
|
|
|
// Basic data
|
2022-03-02 17:31:42 +00:00
|
|
|
// buf[0] ... SCSI device type
|
2022-03-02 02:25:22 +00:00
|
|
|
// buf[1] ... Bit 7: Removable/not removable
|
2022-03-02 17:31:42 +00:00
|
|
|
// buf[2] ... SCSI compliance level of command system
|
|
|
|
// buf[3] ... SCSI compliance level of Inquiry response
|
2022-03-02 02:25:22 +00:00
|
|
|
// buf[4] ... Inquiry additional data
|
2022-11-02 14:36:19 +00:00
|
|
|
buf[0] = static_cast<uint8_t>(type);
|
|
|
|
buf[1] = is_removable ? 0x80 : 0x00;
|
|
|
|
buf[2] = static_cast<uint8_t>(level);
|
2023-10-15 06:38:15 +00:00
|
|
|
buf[3] = level >= scsi_level::scsi_2 ?
|
|
|
|
static_cast<uint8_t>(scsi_level::scsi_2) : static_cast<uint8_t>(scsi_level::scsi_1_ccs);
|
2022-11-02 14:36:19 +00:00
|
|
|
buf[4] = 0x1F;
|
2022-03-02 02:25:22 +00:00
|
|
|
|
|
|
|
// Padded vendor, product, revision
|
2022-10-08 17:26:04 +00:00
|
|
|
memcpy(&buf.data()[8], GetPaddedName().c_str(), 28);
|
2022-03-02 02:25:22 +00:00
|
|
|
|
|
|
|
return buf;
|
2022-02-13 19:30:02 +00:00
|
|
|
}
|
|
|
|
|
2022-09-21 06:27:51 +00:00
|
|
|
vector<byte> PrimaryDevice::HandleRequestSense() const
|
2022-02-10 18:54:48 +00:00
|
|
|
{
|
|
|
|
// Return not ready only if there are no errors
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
if (!GetStatusCode() && !IsReady()) {
|
2023-10-15 06:38:15 +00:00
|
|
|
throw scsi_exception(sense_key::not_ready, asc::medium_not_present);
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set 18 bytes including extended sense data
|
|
|
|
|
2022-09-21 06:27:51 +00:00
|
|
|
vector<byte> buf(18);
|
2022-03-02 02:25:22 +00:00
|
|
|
|
2022-02-10 18:54:48 +00:00
|
|
|
// Current error
|
2022-09-21 06:27:51 +00:00
|
|
|
buf[0] = (byte)0x70;
|
2022-02-10 18:54:48 +00:00
|
|
|
|
2022-09-21 06:27:51 +00:00
|
|
|
buf[2] = (byte)(GetStatusCode() >> 16);
|
|
|
|
buf[7] = (byte)10;
|
|
|
|
buf[12] = (byte)(GetStatusCode() >> 8);
|
|
|
|
buf[13] = (byte)GetStatusCode();
|
2022-02-10 18:54:48 +00:00
|
|
|
|
2022-11-11 20:08:48 +00:00
|
|
|
stringstream s;
|
|
|
|
s << setfill('0') << setw(2) << hex
|
|
|
|
<< "Status $" << static_cast<int>(GetController()->GetStatus())
|
|
|
|
<< ", Sense Key $" << static_cast<int>(buf[2])
|
|
|
|
<< ", ASC $" << static_cast<int>(buf[12]);
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace(s.str());
|
2022-03-06 15:17:23 +00:00
|
|
|
|
2022-03-02 02:25:22 +00:00
|
|
|
return buf;
|
2022-02-10 18:54:48 +00:00
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
bool PrimaryDevice::WriteByteSequence(span<const uint8_t>)
|
2022-02-17 02:04:42 +00:00
|
|
|
{
|
2023-10-15 06:38:15 +00:00
|
|
|
LogError("Writing bytes is not supported by this device");
|
2022-02-17 02:04:42 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2022-10-23 19:51:39 +00:00
|
|
|
|
|
|
|
void PrimaryDevice::ReserveUnit()
|
|
|
|
{
|
2022-11-04 07:22:32 +00:00
|
|
|
reserving_initiator = GetController()->GetInitiatorId();
|
2022-10-23 19:51:39 +00:00
|
|
|
|
|
|
|
if (reserving_initiator != -1) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Reserved device for initiator ID " + to_string(reserving_initiator));
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Reserved device for unknown initiator");
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EnterStatusPhase();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrimaryDevice::ReleaseUnit()
|
|
|
|
{
|
|
|
|
if (reserving_initiator != -1) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Released device reserved by initiator ID " + to_string(reserving_initiator));
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Released device reserved by unknown initiator");
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DiscardReservation();
|
|
|
|
|
|
|
|
EnterStatusPhase();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PrimaryDevice::CheckReservation(int initiator_id, scsi_command cmd, bool prevent_removal) const
|
|
|
|
{
|
|
|
|
if (reserving_initiator == NOT_RESERVED || reserving_initiator == initiator_id) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A reservation is valid for all commands except those excluded below
|
|
|
|
if (cmd == scsi_command::eCmdInquiry || cmd == scsi_command::eCmdRequestSense || cmd == scsi_command::eCmdRelease6) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// PREVENT ALLOW MEDIUM REMOVAL is permitted if the prevent bit is 0
|
2022-11-02 14:36:19 +00:00
|
|
|
if (cmd == scsi_command::eCmdPreventAllowMediumRemoval && !prevent_removal) {
|
2022-10-23 19:51:39 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (initiator_id != -1) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Initiator ID " + to_string(initiator_id) + " tries to access reserved device");
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Unknown initiator tries to access reserved device");
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrimaryDevice::DiscardReservation()
|
|
|
|
{
|
|
|
|
reserving_initiator = NOT_RESERVED;
|
|
|
|
}
|