From 1df7cdb1f3cc70fce9b163db2dad5eae8dc87520 Mon Sep 17 00:00:00 2001 From: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Wed, 2 Mar 2022 03:25:22 +0100 Subject: [PATCH] Use vector for INQUIRY data, LUN list can have gaps, made methods const (#713) * Use vector for INQUIRY data, Inquiry() is const, moved EVPD check * Moved code * Fixed warning * Updated memcpy * Set length * Limit result vector size * Limit result buffer size * Inquiry() result buffer handling update * Logging update * Inquiry cleanup * NEC drive can also use PrimaryDevice::Inquiry() * NEC drive is never removable * Comment update * Bridge can also use PrimaryDevice::Inquiry() * Removed unused method argument * Comment update * Updated comment * Updated REQUEST SENSE buffer handling * Fixed typo * Fixed typo * Re-added comment * Updated additional length handling * Check for INQUIRY command support first * Added assertion * Size handling update * Renaming * Renaming * Removed obsolete casts * Cleanup * Moved error codes to scsi_defs namespace * Fixed ReadDefectData10 * Comment update * Updated buffer handling * Data type update * SendDiagnostic is now const * Removed obsolete forward declaration * removed unused enum * Reduced method visibility * Renaming * GetSendDelay() can be const * Made method const * Made method const * Added TODO * Use iterator * Made method const * Revert "Made method const" This reverts commit 38412b8dddbd1a60f34baa663a12d8285190e3a8. * No need to sort all set/maps * Do not sort all sets * Removed more unnecessary sorting * Cleaned up includes * More include cleanups * Updated REPORT LUNS * LUNs must not be consecutive anymore * Updated detaching of LUN * Improvements for devices without LUN 0 * Assume LUN 0 is always present * Enforce presence of LUN 0 * Updated error handling --- src/raspberrypi/controllers/sasidev_ctrl.cpp | 2 +- src/raspberrypi/controllers/sasidev_ctrl.h | 35 +---- src/raspberrypi/controllers/scsidev_ctrl.cpp | 28 ++-- src/raspberrypi/controllers/scsidev_ctrl.h | 7 +- src/raspberrypi/devices/ctapdriver.cpp | 4 +- src/raspberrypi/devices/ctapdriver.h | 4 +- src/raspberrypi/devices/device.cpp | 4 +- src/raspberrypi/devices/device.h | 20 +-- src/raspberrypi/devices/device_factory.cpp | 19 ++- src/raspberrypi/devices/device_factory.h | 26 ++-- src/raspberrypi/devices/disk.cpp | 81 ++++-------- src/raspberrypi/devices/disk.h | 31 ++--- src/raspberrypi/devices/dispatcher.h | 4 +- src/raspberrypi/devices/file_support.cpp | 9 +- src/raspberrypi/devices/file_support.h | 13 +- src/raspberrypi/devices/host_services.cpp | 6 +- src/raspberrypi/devices/host_services.h | 2 +- src/raspberrypi/devices/primary_device.cpp | 127 +++++++++---------- src/raspberrypi/devices/primary_device.h | 8 +- src/raspberrypi/devices/sasihd.cpp | 23 ++-- src/raspberrypi/devices/sasihd.h | 9 +- src/raspberrypi/devices/scsi_daynaport.cpp | 10 +- src/raspberrypi/devices/scsi_daynaport.h | 7 +- src/raspberrypi/devices/scsi_host_bridge.cpp | 43 ++----- src/raspberrypi/devices/scsi_host_bridge.h | 8 +- src/raspberrypi/devices/scsi_printer.cpp | 13 +- src/raspberrypi/devices/scsi_printer.h | 6 +- src/raspberrypi/devices/scsicd.cpp | 44 +------ src/raspberrypi/devices/scsicd.h | 8 +- src/raspberrypi/devices/scsihd.cpp | 38 +----- src/raspberrypi/devices/scsihd.h | 4 +- src/raspberrypi/devices/scsihd_nec.cpp | 13 +- src/raspberrypi/devices/scsihd_nec.h | 4 +- src/raspberrypi/devices/scsimo.cpp | 41 +----- src/raspberrypi/devices/scsimo.h | 4 +- src/raspberrypi/localizer.cpp | 3 +- src/raspberrypi/localizer.h | 8 +- src/raspberrypi/rascsi.cpp | 50 +++----- src/raspberrypi/rascsi_response.cpp | 7 +- src/raspberrypi/rascsi_response.h | 6 +- src/raspberrypi/scsi.h | 104 ++++++++------- 41 files changed, 345 insertions(+), 538 deletions(-) diff --git a/src/raspberrypi/controllers/sasidev_ctrl.cpp b/src/raspberrypi/controllers/sasidev_ctrl.cpp index b02e6a6f..ef1a8ebb 100644 --- a/src/raspberrypi/controllers/sasidev_ctrl.cpp +++ b/src/raspberrypi/controllers/sasidev_ctrl.cpp @@ -623,7 +623,7 @@ void SASIDEV::DataOut() // Error // //--------------------------------------------------------------------------- -void SASIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status) +void SASIDEV::Error(sense_key sense_key, asc asc, status status) { // Get bus information ctrl.bus->Aquire(); diff --git a/src/raspberrypi/controllers/sasidev_ctrl.h b/src/raspberrypi/controllers/sasidev_ctrl.h index c4253c1e..b59d1828 100644 --- a/src/raspberrypi/controllers/sasidev_ctrl.h +++ b/src/raspberrypi/controllers/sasidev_ctrl.h @@ -20,7 +20,6 @@ #include "scsi.h" #include "fileio.h" -class Device; class PrimaryDevice; //=========================================================================== @@ -31,30 +30,6 @@ class PrimaryDevice; class SASIDEV { protected: - enum scsi_message_code : BYTE { - eMsgCodeAbort = 0x06, - eMsgCodeAbortTag = 0x0D, - eMsgCodeBusDeviceReset = 0x0C, - eMsgCodeClearQueue = 0x0E, - eMsgCodeCommandComplete = 0x00, - eMsgCodeDisconnect = 0x04, - eMsgCodeIdentify = 0x80, - eMsgCodeIgnoreWideResidue = 0x23, // (Two Bytes) - eMsgCodeInitiateRecovery = 0x0F, - eMsgCodeInitiatorDetectedError = 0x05, - eMsgCodeLinkedCommandComplete = 0x0A, - eMsgCodeLinkedCommandCompleteWithFlag = 0x0B, - eMsgCodeMessageParityError = 0x09, - eMsgCodeMessageReject = 0x07, - eMsgCodeNoOperation = 0x08, - eMsgCodeHeadOfQueueTag = 0x21, - eMsgCodeOrderedQueueTag = 0x22, - eMsgCodeSimpleQueueTag = 0x20, - eMsgCodeReleaseRecovery = 0x10, - eMsgCodeRestorePointers = 0x03, - eMsgCodeSaveDataPointer = 0x02, - eMsgCodeTerminateIOProcess = 0x11 - }; private: enum sasi_command : int { @@ -123,7 +98,7 @@ public: DWORD offset; // Transfer offset DWORD length; // Transfer remaining length - // Logical unit + // Logical units PrimaryDevice *unit[UnitMax]; // The current device @@ -144,7 +119,7 @@ public: // Connect void Connect(int id, BUS *sbus); // Controller connection - Device* GetUnit(int no); // Get logical unit + PrimaryDevice* GetUnit(int no); // Get logical unit void SetUnit(int no, PrimaryDevice *dev); // Logical unit setting bool HasUnit(); // Has a valid logical unit @@ -165,9 +140,9 @@ public: // Get LUN based on IDENTIFY message, with LUN from the CDB as fallback int GetEffectiveLun() const; - virtual void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE, - ERROR_CODES::asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION, - ERROR_CODES::status = ERROR_CODES::status::CHECK_CONDITION); // Common error handling + virtual void Error(scsi_defs::sense_key sense_key = scsi_defs::sense_key::NO_SENSE, + scsi_defs::asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION, + scsi_defs::status = scsi_defs::status::CHECK_CONDITION); // Common error handling protected: // Phase processing diff --git a/src/raspberrypi/controllers/scsidev_ctrl.cpp b/src/raspberrypi/controllers/scsidev_ctrl.cpp index c7efe4c9..9e6c40e5 100644 --- a/src/raspberrypi/controllers/scsidev_ctrl.cpp +++ b/src/raspberrypi/controllers/scsidev_ctrl.cpp @@ -19,6 +19,8 @@ #include "devices/scsi_daynaport.h" #include "devices/scsi_printer.h" +using namespace scsi_defs; + //=========================================================================== // // SCSI Device @@ -264,7 +266,7 @@ void SCSIDEV::Execute() ctrl.execstart = SysTimer::GetTimerLow(); // Discard pending sense data from the previous command if the current command is not REQUEST SENSE - if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) { + if ((scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) { ctrl.status = 0; } @@ -272,11 +274,11 @@ void SCSIDEV::Execute() int lun = GetEffectiveLun(); if (!ctrl.unit[lun]) { - if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdInquiry && - (scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) { + if ((scsi_command)ctrl.cmd[0] != eCmdInquiry && + (scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) { LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID()); - Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN); + Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_LUN); return; } // Use LUN 0 for INQUIRY and REQUEST SENSE because LUN0 is assumed to be always available. @@ -291,18 +293,18 @@ void SCSIDEV::Execute() ctrl.device = ctrl.unit[lun]; // Discard pending sense data from the previous command if the current command is not REQUEST SENSE - if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) { + if ((scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) { ctrl.device->SetStatusCode(0); } if (!ctrl.device->Dispatch(this)) { LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetSCSIID(), lun, (BYTE)ctrl.cmd[0]); - Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE); + Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); } // SCSI-2 p.104 4.4.3 Incorrect logical unit handling - if ((scsi_defs::scsi_command)ctrl.cmd[0] == scsi_defs::eCmdInquiry && !ctrl.unit[lun]) { + if ((scsi_command)ctrl.cmd[0] == scsi_command::eCmdInquiry && !ctrl.unit[lun]) { lun = GetEffectiveLun(); LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, ctrl.device->GetId()); @@ -355,7 +357,7 @@ void SCSIDEV::MsgOut() // Common Error Handling // //--------------------------------------------------------------------------- -void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status) +void SCSIDEV::Error(sense_key sense_key, asc asc, status status) { // Get bus information ctrl.bus->Aquire(); @@ -377,8 +379,10 @@ void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERRO } int lun = GetEffectiveLun(); - if (!ctrl.unit[lun] || asc == ERROR_CODES::INVALID_LUN) { + if (!ctrl.unit[lun] || asc == INVALID_LUN) { lun = 0; + + assert(ctrl.unit[lun]); } if (sense_key || asc) { @@ -408,7 +412,9 @@ void SCSIDEV::Send() LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length " + to_string(ctrl.length)).c_str()); - int len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, ctrl.unit[0]->GetSendDelay()); + // TODO The delay has to be taken from ctrl.unit[lun], but as there are no Daynaport drivers for + // LUNs other than 0 this work-around works. + int len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, ctrl.unit[0] ? ctrl.unit[0]->GetSendDelay() : 0); // If you cannot send all, move to status phase if (len != (int)ctrl.length) { @@ -896,7 +902,7 @@ bool SCSIDEV::XferOut(bool cont) scsi.is_byte_transfer = false; PrimaryDevice *device = dynamic_cast(ctrl.unit[GetEffectiveLun()]); - if (device && ctrl.cmd[0] == scsi_defs::eCmdWrite6) { + if (device && ctrl.cmd[0] == scsi_command::eCmdWrite6) { return device->WriteBytes(ctrl.buffer, scsi.bytes_to_transfer); } diff --git a/src/raspberrypi/controllers/scsidev_ctrl.h b/src/raspberrypi/controllers/scsidev_ctrl.h index 68fc3772..2a0660df 100644 --- a/src/raspberrypi/controllers/scsidev_ctrl.h +++ b/src/raspberrypi/controllers/scsidev_ctrl.h @@ -16,7 +16,6 @@ #pragma once #include "controllers/sasidev_ctrl.h" -#include //=========================================================================== // @@ -67,9 +66,9 @@ public: bool IsSCSI() const override { return true; } // Common error handling - void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE, - ERROR_CODES::asc asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION, - ERROR_CODES::status status = ERROR_CODES::status::CHECK_CONDITION) override; + void Error(scsi_defs::sense_key sense_key = scsi_defs::sense_key::NO_SENSE, + scsi_defs::asc asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION, + scsi_defs::status status = scsi_defs::status::CHECK_CONDITION) override; void ScheduleShutDown(rascsi_shutdown_mode shutdown_mode) { this->shutdown_mode = shutdown_mode; } diff --git a/src/raspberrypi/devices/ctapdriver.cpp b/src/raspberrypi/devices/ctapdriver.cpp index 3a328339..e089fb14 100644 --- a/src/raspberrypi/devices/ctapdriver.cpp +++ b/src/raspberrypi/devices/ctapdriver.cpp @@ -96,9 +96,9 @@ static bool is_interface_up(const string& interface) { return status; } -bool CTapDriver::Init(const map& const_params) +bool CTapDriver::Init(const unordered_map& const_params) { - map params = const_params; + unordered_map params = const_params; if (params.count("interfaces")) { LOGWARN("You are using the deprecated 'interfaces' parameter. " "Provide the interface list and the IP address/netmask with the 'interface' and 'inet' parameters"); diff --git a/src/raspberrypi/devices/ctapdriver.h b/src/raspberrypi/devices/ctapdriver.h index 70ff51e3..a582a451 100644 --- a/src/raspberrypi/devices/ctapdriver.h +++ b/src/raspberrypi/devices/ctapdriver.h @@ -15,7 +15,7 @@ #include #include "filepath.h" -#include +#include #include #include @@ -40,7 +40,7 @@ private: CTapDriver(); ~CTapDriver() {} - bool Init(const map&); + bool Init(const unordered_map&); public: diff --git a/src/raspberrypi/devices/device.cpp b/src/raspberrypi/devices/device.cpp index 83658f4a..15b0b69b 100644 --- a/src/raspberrypi/devices/device.cpp +++ b/src/raspberrypi/devices/device.cpp @@ -14,7 +14,7 @@ #include "exceptions.h" #include "device.h" -set Device::devices; +unordered_set Device::devices; Device::Device(const string& type) { @@ -121,7 +121,7 @@ const string Device::GetParam(const string& key) return params.find(key) != params.end() ? params[key] : ""; } -void Device::SetParams(const map& params) +void Device::SetParams(const unordered_map& params) { this->params = GetDefaultParams(); diff --git a/src/raspberrypi/devices/device.h b/src/raspberrypi/devices/device.h index b3b321f8..a47f601a 100644 --- a/src/raspberrypi/devices/device.h +++ b/src/raspberrypi/devices/device.h @@ -9,8 +9,8 @@ #pragma once -#include -#include +#include +#include #include using namespace std; @@ -97,17 +97,17 @@ private: string revision; // The parameters the device was created with - map params; + unordered_map params; // The default parameters - map default_params; + unordered_map default_params; // Sense Key, ASC and ASCQ int status_code; protected: - static set devices; + static unordered_set devices; public: @@ -115,7 +115,7 @@ public: virtual ~Device(); // Override for device specific initializations, to be called after all device properties have been set - virtual bool Init(const map&) { return true; }; + virtual bool Init(const unordered_map&) { return true; }; virtual bool Dispatch(SCSIDEV *) = 0; @@ -169,11 +169,11 @@ public: bool SupportsParams() const { return supports_params; } bool SupportsFile() const { return !supports_params; } void SupportsParams(bool supports_paams) { this->supports_params = supports_paams; } - const map GetParams() const { return params; } + const unordered_map GetParams() const { return params; } const string GetParam(const string&); - void SetParams(const map&); - const map GetDefaultParams() const { return default_params; } - void SetDefaultParams(const map& default_params) { this->default_params = default_params; } + void SetParams(const unordered_map&); + const unordered_map GetDefaultParams() const { return default_params; } + void SetDefaultParams(const unordered_map& default_params) { this->default_params = default_params; } int GetStatusCode() const { return status_code; } void SetStatusCode(int); diff --git a/src/raspberrypi/devices/device_factory.cpp b/src/raspberrypi/devices/device_factory.cpp index 989cf7f1..731f675f 100644 --- a/src/raspberrypi/devices/device_factory.cpp +++ b/src/raspberrypi/devices/device_factory.cpp @@ -18,8 +18,6 @@ #include "exceptions.h" #include "device_factory.h" #include -#include -#include #include "host_services.h" using namespace std; @@ -86,12 +84,13 @@ string DeviceFactory::GetExtension(const string& filename) const return ext; } -PbDeviceType DeviceFactory::GetTypeForFile(const string& filename) +PbDeviceType DeviceFactory::GetTypeForFile(const string& filename) const { string ext = GetExtension(filename); - if (extension_mapping.find(ext) != extension_mapping.end()) { - return extension_mapping[ext]; + const auto& it = extension_mapping.find(ext); + if (it != extension_mapping.end()) { + return it->second; } else if (filename == "bridge") { return SCBR; @@ -216,19 +215,19 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename) return device; } -const set& DeviceFactory::GetSectorSizes(const string& type) +const unordered_set& DeviceFactory::GetSectorSizes(const string& type) { PbDeviceType t = UNDEFINED; PbDeviceType_Parse(type, &t); return sector_sizes[t]; } -const set DeviceFactory::GetCapacities(PbDeviceType type) +const unordered_set DeviceFactory::GetCapacities(PbDeviceType type) const { - set keys; + unordered_set keys; - for (const auto& geometry : geometries[type]) { - keys.insert(geometry.first); + for (auto it = geometries.begin(); it != geometries.end(); ++it) { + keys.insert(it->first); } return keys; diff --git a/src/raspberrypi/devices/device_factory.h b/src/raspberrypi/devices/device_factory.h index d6f73f63..3edff4c2 100644 --- a/src/raspberrypi/devices/device_factory.h +++ b/src/raspberrypi/devices/device_factory.h @@ -11,9 +11,9 @@ #pragma once -#include #include -#include +#include +#include #include #include "rascsi_interface.pb.h" @@ -28,31 +28,31 @@ class DeviceFactory { private: DeviceFactory(); - ~DeviceFactory() {}; + ~DeviceFactory() {} public: static DeviceFactory& instance(); Device *CreateDevice(PbDeviceType, const string&); - PbDeviceType GetTypeForFile(const string&); - const set& GetSectorSizes(PbDeviceType type) { return sector_sizes[type]; } - const set& GetSectorSizes(const string&); - const set GetCapacities(PbDeviceType); - const map& GetDefaultParams(PbDeviceType type) { return default_params[type]; } + PbDeviceType GetTypeForFile(const string&) const; + const unordered_set& GetSectorSizes(PbDeviceType type) { return sector_sizes[type]; } + const unordered_set& GetSectorSizes(const string&); + const unordered_set GetCapacities(PbDeviceType) const; + const unordered_map& GetDefaultParams(PbDeviceType type) { return default_params[type]; } const list GetNetworkInterfaces() const; - const map GetExtensionMapping() const { return extension_mapping; } + const unordered_map GetExtensionMapping() const { return extension_mapping; } private: - map> sector_sizes; + unordered_map> sector_sizes; // Optional mapping of drive capacities to drive geometries - map> geometries; + unordered_map> geometries; - map> default_params; + unordered_map> default_params; - map extension_mapping; + unordered_map extension_mapping; string GetExtension(const string&) const; }; diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index 02af040c..9dd55c55 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -85,7 +85,7 @@ bool Disk::Dispatch(SCSIDEV *controller) disk.is_medium_changed = false; - controller->Error(ERROR_CODES::sense_key::UNIT_ATTENTION, ERROR_CODES::asc::NOT_READY_TO_READY_CHANGE); + controller->Error(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); return true; } @@ -207,11 +207,11 @@ void Disk::ReadWriteLong10(SASIDEV *controller) { // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard if (ctrl->cmd[7] || ctrl->cmd[8]) { - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); return; } - if (CheckBlockAddress(controller, RW10)) { + if (ValidateBlockAddress(controller, RW10)) { controller->Status(); } } @@ -225,11 +225,11 @@ void Disk::ReadWriteLong16(SASIDEV *controller) { // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard if (ctrl->cmd[12] || ctrl->cmd[13]) { - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); return; } - if (CheckBlockAddress(controller, RW16)) { + if (ValidateBlockAddress(controller, RW16)) { controller->Status(); } } @@ -243,11 +243,11 @@ void Disk::Write(SASIDEV *controller, uint64_t record) { ctrl->length = WriteCheck(record); if (ctrl->length == 0) { - controller->Error(ERROR_CODES::sense_key::NOT_READY, ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION); + controller->Error(sense_key::NOT_READY, asc::NO_ADDITIONAL_SENSE_INFORMATION); return; } else if (ctrl->length < 0) { - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::WRITE_PROTECTED); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::WRITE_PROTECTED); return; } @@ -343,7 +343,7 @@ void Disk::StartStopUnit(SASIDEV *controller) void Disk::SendDiagnostic(SASIDEV *controller) { if (!SendDiag(ctrl->cmd)) { - controller->Error(); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); return; } @@ -380,12 +380,15 @@ void Disk::SynchronizeCache16(SASIDEV *controller) void Disk::ReadDefectData10(SASIDEV *controller) { - ctrl->length = ReadDefectData10(ctrl->cmd, ctrl->buffer, ctrl->bufsize); - if (ctrl->length <= 4) { - controller->Error(); - return; + int allocation_length = (ctrl->cmd[7] << 8) | ctrl->cmd[8]; + if (allocation_length > 4) { + allocation_length = 4; } + // The defect list is empty + memset(ctrl->buffer, 0, allocation_length); + ctrl->length = allocation_length; + controller->DataIn(); } @@ -675,34 +678,6 @@ void Disk::AddVendorPage(map>&, int, bool) const // Nothing to add by default } -int Disk::ReadDefectData10(const DWORD *cdb, BYTE *buf, int max_length) -{ - // Get length, clear buffer - int length = (cdb[7] << 8) | cdb[8]; - if (length > max_length) { - length = max_length; - } - memset(buf, 0, length); - - // P/G/FORMAT - buf[1] = (cdb[1] & 0x18) | 5; - buf[3] = 8; - - buf[4] = 0xff; - buf[5] = 0xff; - buf[6] = 0xff; - buf[7] = 0xff; - - buf[8] = 0xff; - buf[9] = 0xff; - buf[10] = 0xff; - buf[11] = 0xff; - - // no list - SetStatusCode(STATUS_NODEFECT); - return 4; -} - //--------------------------------------------------------------------------- // // FORMAT UNIT @@ -868,17 +843,15 @@ bool Disk::StartStop(const DWORD *cdb) return true; } -bool Disk::SendDiag(const DWORD *cdb) +bool Disk::SendDiag(const DWORD *cdb) const { // Do not support PF bit if (cdb[1] & 0x10) { - SetStatusCode(STATUS_INVALIDCDB); return false; } // Do not support parameter list if ((cdb[3] != 0) || (cdb[4] != 0)) { - SetStatusCode(STATUS_INVALIDCDB); return false; } @@ -888,7 +861,7 @@ bool Disk::SendDiag(const DWORD *cdb) void Disk::ReadCapacity10(SASIDEV *controller) { if (!CheckReady() || disk.blocks <= 0) { - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); return; } @@ -917,7 +890,7 @@ void Disk::ReadCapacity10(SASIDEV *controller) void Disk::ReadCapacity16(SASIDEV *controller) { if (!CheckReady() || disk.blocks <= 0) { - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); return; } @@ -965,7 +938,7 @@ void Disk::ReadCapacity16_ReadLong16(SASIDEV *controller) break; default: - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); break; } } @@ -996,7 +969,7 @@ void Disk::Release(SASIDEV *controller) // //--------------------------------------------------------------------------- -bool Disk::CheckBlockAddress(SASIDEV *controller, access_mode mode) +bool Disk::ValidateBlockAddress(SASIDEV *controller, access_mode mode) { uint64_t block = ctrl->cmd[2]; block <<= 8; @@ -1021,7 +994,7 @@ bool Disk::CheckBlockAddress(SASIDEV *controller, access_mode mode) if (block > capacity) { LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block " + to_string(block)).c_str()); - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); return false; } @@ -1078,14 +1051,14 @@ bool Disk::GetStartAndCount(SASIDEV *controller, uint64_t& start, uint32_t& coun } } - LOGDEBUG("%s READ/WRITE/VERIFY command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, count); + LOGTRACE("%s READ/WRITE/VERIFY command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, count); // Check capacity uint64_t capacity = GetBlockCount(); if (start > capacity || start + count > capacity) { LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block " + to_string(start) + ", block count " + to_string(ctrl->blocks)).c_str()); - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); return false; } @@ -1106,7 +1079,7 @@ uint32_t Disk::GetSectorSizeInBytes() const void Disk::SetSectorSizeInBytes(uint32_t size, bool sasi) { - set sector_sizes = DeviceFactory::instance().GetSectorSizes(GetType()); + unordered_set sector_sizes = DeviceFactory::instance().GetSectorSizes(GetType()); if (!sector_sizes.empty() && sector_sizes.find(size) == sector_sizes.end()) { throw io_exception("Invalid block size of " + to_string(size) + " bytes"); } @@ -1153,7 +1126,7 @@ bool Disk::IsSectorSizeConfigurable() const return !sector_sizes.empty(); } -void Disk::SetSectorSizes(const set& sector_sizes) +void Disk::SetSectorSizes(const unordered_set& sector_sizes) { this->sector_sizes = sector_sizes; } @@ -1167,7 +1140,7 @@ bool Disk::SetConfiguredSectorSize(uint32_t configured_sector_size) { DeviceFactory& device_factory = DeviceFactory::instance(); - set sector_sizes = device_factory.GetSectorSizes(GetType()); + unordered_set sector_sizes = device_factory.GetSectorSizes(GetType()); if (sector_sizes.find(configured_sector_size) == sector_sizes.end()) { return false; } @@ -1177,7 +1150,7 @@ bool Disk::SetConfiguredSectorSize(uint32_t configured_sector_size) return true; } -void Disk::SetGeometries(const map& geometries) +void Disk::SetGeometries(const unordered_map& geometries) { this->geometries = geometries; } diff --git a/src/raspberrypi/devices/disk.h b/src/raspberrypi/devices/disk.h index ffe92cee..68fa3059 100644 --- a/src/raspberrypi/devices/disk.h +++ b/src/raspberrypi/devices/disk.h @@ -28,8 +28,8 @@ #include "interfaces/scsi_block_commands.h" #include "mode_page_device.h" #include -#include -#include +#include +#include using namespace std; @@ -39,11 +39,11 @@ private: enum access_mode { RW6, RW10, RW16 }; // The supported configurable block sizes, empty if not configurable - set sector_sizes; + unordered_set sector_sizes; uint32_t configured_sector_size; // The mapping of supported capacities to block sizes and block counts, empty if there is no capacity restriction - map geometries; + unordered_map geometries; typedef struct { uint32_t size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096) @@ -108,33 +108,30 @@ public: void Seek6(SASIDEV *); // Command helpers - virtual int Inquiry(const DWORD *cdb, BYTE *buf) = 0; // INQUIRY command - virtual int WriteCheck(DWORD block); // WRITE check - virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block); // WRITE command - bool StartStop(const DWORD *cdb); // START STOP UNIT command - bool SendDiag(const DWORD *cdb); // SEND DIAGNOSTIC command + virtual int WriteCheck(DWORD block); + virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block); + bool StartStop(const DWORD *cdb); + bool SendDiag(const DWORD *cdb) const; virtual int Read(const DWORD *cdb, BYTE *buf, uint64_t block); - int ReadDefectData10(const DWORD *, BYTE *, int); uint32_t GetSectorSizeInBytes() const; void SetSectorSizeInBytes(uint32_t, bool); uint32_t GetSectorSizeShiftCount() const; void SetSectorSizeShiftCount(uint32_t); bool IsSectorSizeConfigurable() const; - set GetSectorSizes() const; - void SetSectorSizes(const set&); + unordered_set GetSectorSizes() const; + void SetSectorSizes(const unordered_set&); uint32_t GetConfiguredSectorSize() const; bool SetConfiguredSectorSize(uint32_t); - void SetGeometries(const map&); + void SetGeometries(const unordered_map&); bool SetGeometryForCapacity(uint64_t); uint64_t GetBlockCount() const; void SetBlockCount(uint32_t); - bool CheckBlockAddress(SASIDEV *, access_mode); - bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode); void FlushCache(); protected: + int ModeSense6(const DWORD *cdb, BYTE *buf); int ModeSense10(const DWORD *cdb, BYTE *buf, int); virtual void SetDeviceParameters(BYTE *); @@ -149,6 +146,7 @@ protected: disk_t disk; private: + void Read(SASIDEV *, uint64_t); void Write(SASIDEV *, uint64_t); void Verify(SASIDEV *, uint64_t); @@ -156,4 +154,7 @@ private: void ReadWriteLong16(SASIDEV *); void ReadCapacity16_ReadLong16(SASIDEV *); bool Format(const DWORD *cdb); + + bool ValidateBlockAddress(SASIDEV *, access_mode); + bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode); }; diff --git a/src/raspberrypi/devices/dispatcher.h b/src/raspberrypi/devices/dispatcher.h index 6a2a46c4..b702cd94 100644 --- a/src/raspberrypi/devices/dispatcher.h +++ b/src/raspberrypi/devices/dispatcher.h @@ -13,7 +13,7 @@ #include "log.h" #include "scsi.h" -#include +#include class SASIDEV; class SCSIDEV; @@ -40,7 +40,7 @@ public: _command_t(const char* _name, void (T::*_execute)(U *)) : name(_name), execute(_execute) { }; } command_t; - map commands; + unordered_map commands; void AddCommand(scsi_command opcode, const char* name, void (T::*execute)(U *)) { diff --git a/src/raspberrypi/devices/file_support.cpp b/src/raspberrypi/devices/file_support.cpp index 09b9061a..89219627 100644 --- a/src/raspberrypi/devices/file_support.cpp +++ b/src/raspberrypi/devices/file_support.cpp @@ -7,13 +7,11 @@ // //--------------------------------------------------------------------------- -#include -#include #include "file_support.h" using namespace std; -map FileSupport::reserved_files; +unordered_map FileSupport::reserved_files; void FileSupport::ReserveFile(const Filepath& path, int id, int lun) { @@ -27,8 +25,9 @@ void FileSupport::UnreserveFile() bool FileSupport::GetIdsForReservedFile(const Filepath& path, int& id, int& unit) { - if (reserved_files.find(path.GetPath()) != reserved_files.end()) { - const id_set ids = reserved_files[path.GetPath()]; + const auto& it = reserved_files.find(path.GetPath()); + if (it != reserved_files.end()) { + const id_set ids = it->second; id = ids.first; unit = ids.second; return true; diff --git a/src/raspberrypi/devices/file_support.h b/src/raspberrypi/devices/file_support.h index 0d7df448..a111bbb0 100644 --- a/src/raspberrypi/devices/file_support.h +++ b/src/raspberrypi/devices/file_support.h @@ -11,7 +11,7 @@ #pragma once -#include +#include #include #include "filepath.h" @@ -25,20 +25,21 @@ private: Filepath diskpath; // The list of image files in use and the IDs and LUNs using these files - static map reserved_files; + static unordered_map reserved_files; public: - FileSupport() {}; - virtual ~FileSupport() {}; + FileSupport() {} + virtual ~FileSupport() {} void GetPath(Filepath& path) const { path = diskpath; } void SetPath(const Filepath& path) { diskpath = path; } - static const map GetReservedFiles(){ return reserved_files; } - static void SetReservedFiles(const map& files_in_use) { FileSupport::reserved_files = files_in_use; } void ReserveFile(const Filepath&, int, int); void UnreserveFile(); + static const unordered_map GetReservedFiles() { return reserved_files; } + static void SetReservedFiles(const unordered_map& files_in_use) + { FileSupport::reserved_files = files_in_use; } static bool GetIdsForReservedFile(const Filepath&, int&, int&); static void UnreserveAll(); diff --git a/src/raspberrypi/devices/host_services.cpp b/src/raspberrypi/devices/host_services.cpp index 0c25bdf0..844870c6 100644 --- a/src/raspberrypi/devices/host_services.cpp +++ b/src/raspberrypi/devices/host_services.cpp @@ -57,10 +57,10 @@ void HostServices::TestUnitReady(SCSIDEV *controller) controller->Status(); } -int HostServices::Inquiry(const DWORD *cdb, BYTE *buf) +vector HostServices::Inquiry() const { // Processor device, SPC-5, not removable - return PrimaryDevice::Inquiry(3, 7, false, cdb, buf); + return PrimaryDevice::Inquiry(3, 7, false); } void HostServices::StartStopUnit(SCSIDEV *controller) @@ -96,7 +96,7 @@ void HostServices::StartStopUnit(SCSIDEV *controller) } } - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } int HostServices::ModeSense6(const DWORD *cdb, BYTE *buf) diff --git a/src/raspberrypi/devices/host_services.h b/src/raspberrypi/devices/host_services.h index d71ee9b2..46d506c2 100644 --- a/src/raspberrypi/devices/host_services.h +++ b/src/raspberrypi/devices/host_services.h @@ -25,7 +25,7 @@ public: virtual bool Dispatch(SCSIDEV *) override; - int Inquiry(const DWORD *, BYTE *) override; + vector Inquiry() const override; void TestUnitReady(SCSIDEV *); void StartStopUnit(SCSIDEV *); diff --git a/src/raspberrypi/devices/primary_device.cpp b/src/raspberrypi/devices/primary_device.cpp index cad1212f..1a15e332 100644 --- a/src/raspberrypi/devices/primary_device.cpp +++ b/src/raspberrypi/devices/primary_device.cpp @@ -45,12 +45,22 @@ void PrimaryDevice::TestUnitReady(SASIDEV *controller) void PrimaryDevice::Inquiry(SASIDEV *controller) { - ctrl->length = Inquiry(ctrl->cmd, ctrl->buffer); - if (ctrl->length <= 0) { - controller->Error(); + // EVPD and page code check + if ((ctrl->cmd[1] & 0x01) || ctrl->cmd[2]) { + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); return; } + vector buf = Inquiry(); + + size_t allocation_length = ctrl->cmd[4] + (ctrl->cmd[3] << 8); + if (allocation_length > buf.size()) { + allocation_length = buf.size(); + } + + memcpy(ctrl->buffer, buf.data(), allocation_length); + ctrl->length = allocation_length; + int lun = controller->GetEffectiveLun(); // Report if the device does not support the requested LUN @@ -66,27 +76,25 @@ void PrimaryDevice::Inquiry(SASIDEV *controller) void PrimaryDevice::ReportLuns(SASIDEV *controller) { - BYTE *buf = ctrl->buffer; - int allocation_length = (ctrl->cmd[6] << 24) + (ctrl->cmd[7] << 16) + (ctrl->cmd[8] << 8) + ctrl->cmd[9]; + + BYTE *buf = ctrl->buffer; memset(buf, 0, allocation_length); - // Count number of available LUNs for the current device - int luns; - for (luns = 0; luns < controller->GetCtrl()->device->GetSupportedLuns(); luns++) { - if (!controller->GetCtrl()->unit[luns]) { - break; + int size = 0; + for (int lun = 0; lun < controller->GetCtrl()->device->GetSupportedLuns(); lun++) { + if (controller->GetCtrl()->unit[lun]) { + size += 8; + buf[size + 7] = lun; } } - // LUN list length, 8 bytes per LUN - // SCSI standard: The contents of the LUN LIST LENGTH field are not altered based on the allocation length - buf[0] = (luns * 8) >> 24; - buf[1] = (luns * 8) >> 16; - buf[2] = (luns * 8) >> 8; - buf[3] = luns * 8; + buf[2] = size >> 8; + buf[3] = size; - ctrl->length = allocation_length < 8 + luns * 8 ? allocation_length : 8 + luns * 8; + size += 8; + + ctrl->length = allocation_length < size ? allocation_length : size; controller->DataIn(); } @@ -101,12 +109,21 @@ void PrimaryDevice::RequestSense(SASIDEV *controller) // LUN 0 can be assumed to be present (required to call RequestSense() below) lun = 0; - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_LUN); ctrl->status = 0x00; + return; } - ctrl->length = ((PrimaryDevice *)ctrl->unit[lun])->RequestSense(ctrl->cmd, ctrl->buffer); - assert(ctrl->length > 0); + size_t allocation_length = ctrl->cmd[4]; + + vector buf = ((PrimaryDevice *)ctrl->unit[lun])->RequestSense(allocation_length); + + if (allocation_length > buf.size()) { + allocation_length = buf.size(); + } + + memcpy(ctrl->buffer, buf.data(), allocation_length); + ctrl->length = allocation_length; LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]); @@ -144,71 +161,49 @@ bool PrimaryDevice::CheckReady() return true; } -int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DWORD *cdb, BYTE *buf) +vector PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable) const { - // EVPD and page code check - if ((cdb[1] & 0x01) || cdb[2]) { - SetStatusCode(STATUS_INVALIDCDB); - return 0; - } + vector buf = vector(0x1F + 5); - int allocation_length = cdb[4] + (cdb[3] << 8); - if (allocation_length > 4) { - if (allocation_length > 44) { - allocation_length = 44; - } + // Basic data + // buf[0] ... SCSI Device type + // buf[1] ... Bit 7: Removable/not removable + // buf[2] ... SCSI-2 compliant command system + // buf[3] ... SCSI-2 compliant Inquiry response + // buf[4] ... Inquiry additional data + buf[0] = type; + buf[1] = is_removable ? 0x80 : 0x00; + buf[2] = scsi_level; + // Response data format is SCSI-2 for devices supporting SCSI-2 or newer, otherwise it is SCSI-1-CCS + buf[3] = scsi_level >= 2 ? 2 : 1; + buf[4] = 0x1F; - // Basic data - // buf[0] ... SCSI Device type - // buf[1] ... Bit 7: Removable/not removable - // buf[2] ... SCSI-2 compliant command system - // buf[3] ... SCSI-2 compliant Inquiry response - // buf[4] ... Inquiry additional data - memset(buf, 0, allocation_length); - buf[0] = type; - buf[1] = is_removable ? 0x80 : 0x00; - buf[2] = scsi_level; - // Response data format is SCSI-2 for devices supporting SCSI-2 or newer, otherwise it is SCSI-1-CCS - buf[3] = scsi_level >= 2 ? 2 : 0; - buf[4] = 0x1F; + // Padded vendor, product, revision + memcpy(&buf[8], GetPaddedName().c_str(), 28); - // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); - } - - return allocation_length; + return buf; } -int PrimaryDevice::RequestSense(const DWORD *cdb, BYTE *buf) +vector PrimaryDevice::RequestSense(int) { // Return not ready only if there are no errors if (GetStatusCode() == STATUS_NOERROR && !IsReady()) { SetStatusCode(STATUS_NOTREADY); } - // Size determination (according to allocation length) - int size = (int)cdb[4]; - assert(size >= 0 && size < 0x100); - - // For SCSI-1, transfer 4 bytes when the size is 0 - if (size == 0) { - size = 4; - } - - // Clear the buffer - memset(buf, 0, size); - // Set 18 bytes including extended sense data + vector buf(18); + // Current error buf[0] = 0x70; - buf[2] = (BYTE)(GetStatusCode() >> 16); + buf[2] = GetStatusCode() >> 16; buf[7] = 10; - buf[12] = (BYTE)(GetStatusCode() >> 8); - buf[13] = (BYTE)GetStatusCode(); + buf[12] = GetStatusCode() >> 8; + buf[13] = GetStatusCode(); - return size; + return buf; } bool PrimaryDevice::WriteBytes(BYTE *buf, uint32_t length) diff --git a/src/raspberrypi/devices/primary_device.h b/src/raspberrypi/devices/primary_device.h index c8923fee..30fff210 100644 --- a/src/raspberrypi/devices/primary_device.h +++ b/src/raspberrypi/devices/primary_device.h @@ -34,14 +34,14 @@ public: void SetCtrl(SASIDEV::ctrl_t *ctrl) { this->ctrl = ctrl; } bool CheckReady(); - virtual int Inquiry(const DWORD *, BYTE *) = 0; - virtual int RequestSense(const DWORD *, BYTE *); + virtual vector Inquiry() const = 0; + virtual vector RequestSense(int); virtual bool WriteBytes(BYTE *, uint32_t); - virtual int GetSendDelay() { return BUS::SEND_NO_DELAY; } + virtual int GetSendDelay() const { return BUS::SEND_NO_DELAY; } protected: - int Inquiry(int, int, bool, const DWORD *, BYTE *); + vector Inquiry(int, int, bool) const; SASIDEV::ctrl_t *ctrl; diff --git a/src/raspberrypi/devices/sasihd.cpp b/src/raspberrypi/devices/sasihd.cpp index 463eda6b..9d356f2b 100644 --- a/src/raspberrypi/devices/sasihd.cpp +++ b/src/raspberrypi/devices/sasihd.cpp @@ -19,7 +19,7 @@ #include "exceptions.h" #include "../config.h" -SASIHD::SASIHD(const set& sector_sizes) : Disk("SAHD") +SASIHD::SASIHD(const unordered_set& sector_sizes) : Disk("SAHD") { SetSectorSizes(sector_sizes); } @@ -81,27 +81,20 @@ void SASIHD::Open(const Filepath& path) FileSupport::SetPath(path); } -int SASIHD::Inquiry(const DWORD* /*cdb*/, BYTE* /*buf*/) +vector SASIHD::Inquiry() const { - SetStatusCode(STATUS_INVALIDCMD); - return 0; + assert(false); + return vector(0); } -int SASIHD::RequestSense(const DWORD *cdb, BYTE *buf) +vector SASIHD::RequestSense(int allocation_length) { - // Size decision - int size = (int)cdb[4]; - assert(size >= 0 && size < 0x100); - - // Transfer 4 bytes when size 0 (Shugart Associates System Interface specification) - if (size == 0) { - size = 4; - } + // Transfer 4 bytes when size is 0 (Shugart Associates System Interface specification) + vector buf(allocation_length ? allocation_length : 4); // SASI fixed to non-extended format - memset(buf, 0, size); buf[0] = (BYTE)(GetStatusCode() >> 16); buf[1] = (BYTE)(GetLun() << 5); - return size; + return buf; } diff --git a/src/raspberrypi/devices/sasihd.h b/src/raspberrypi/devices/sasihd.h index c802364b..489139da 100644 --- a/src/raspberrypi/devices/sasihd.h +++ b/src/raspberrypi/devices/sasihd.h @@ -27,13 +27,12 @@ class SASIHD : public Disk, public FileSupport { public: - SASIHD(const set&); + SASIHD(const unordered_set&); ~SASIHD() {} void Reset(); - void Open(const Filepath& path) override; + void Open(const Filepath&) override; - // Commands - int RequestSense(const DWORD *cdb, BYTE *buf) override; - int Inquiry(const DWORD *cdb, BYTE *buf) override; + vector RequestSense(int) override; + vector Inquiry() const override; }; diff --git a/src/raspberrypi/devices/scsi_daynaport.cpp b/src/raspberrypi/devices/scsi_daynaport.cpp index 4094fbcc..5b77fc1c 100644 --- a/src/raspberrypi/devices/scsi_daynaport.cpp +++ b/src/raspberrypi/devices/scsi_daynaport.cpp @@ -64,7 +64,7 @@ bool SCSIDaynaPort::Dispatch(SCSIDEV *controller) return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } -bool SCSIDaynaPort::Init(const map& params) +bool SCSIDaynaPort::Init(const unordered_map& params) { SetParams(params); @@ -112,10 +112,10 @@ void SCSIDaynaPort::Open(const Filepath& path) m_tap->OpenDump(path); } -int SCSIDaynaPort::Inquiry(const DWORD *cdb, BYTE *buf) +vector SCSIDaynaPort::Inquiry() const { // Processor device, SCSI-2, not removable - return PrimaryDevice::Inquiry(3, 2, false, cdb, buf); + return PrimaryDevice::Inquiry(3, 2, false); } //--------------------------------------------------------------------------- @@ -444,7 +444,7 @@ void SCSIDaynaPort::Read6(SASIDEV *controller) // generated by the DaynaPort driver so ignore them if (ctrl->cmd[5] != 0xc0 && ctrl->cmd[5] != 0x80) { LOGTRACE("%s Control value %d, (%04X), returning invalid CDB", __PRETTY_FUNCTION__, ctrl->cmd[5], ctrl->cmd[5]); - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); return; } @@ -584,7 +584,7 @@ void SCSIDaynaPort::EnableInterface(SASIDEV *controller) controller->Status(); } -int SCSIDaynaPort::GetSendDelay() +int SCSIDaynaPort::GetSendDelay() const { // The Daynaport needs to have a delay after the size/flags field // of the read response. In the MacOS driver, it looks like the diff --git a/src/raspberrypi/devices/scsi_daynaport.h b/src/raspberrypi/devices/scsi_daynaport.h index cda2cb0c..dbdbd639 100644 --- a/src/raspberrypi/devices/scsi_daynaport.h +++ b/src/raspberrypi/devices/scsi_daynaport.h @@ -31,7 +31,6 @@ #include "os.h" #include "disk.h" #include "ctapdriver.h" -#include #include //=========================================================================== @@ -46,11 +45,11 @@ public: SCSIDaynaPort(); ~SCSIDaynaPort(); - bool Init(const map&) override; + bool Init(const unordered_map&) override; void Open(const Filepath& path) override; // Commands - int Inquiry(const DWORD *cdb, BYTE *buffer) override; + vector Inquiry() const override; int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override; bool Write(const DWORD *cdb, const BYTE *buf, DWORD block) override; int WriteCheck(DWORD block) override; // WRITE check @@ -67,7 +66,7 @@ public: void SetInterfaceMode(SASIDEV *); void SetMcastAddr(SASIDEV *); void EnableInterface(SASIDEV *); - int GetSendDelay() override; + int GetSendDelay() const override; bool Dispatch(SCSIDEV *) override; diff --git a/src/raspberrypi/devices/scsi_host_bridge.cpp b/src/raspberrypi/devices/scsi_host_bridge.cpp index d0dbb8c7..3f055f63 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.cpp +++ b/src/raspberrypi/devices/scsi_host_bridge.cpp @@ -59,7 +59,7 @@ SCSIBR::~SCSIBR() } } -bool SCSIBR::Init(const map& params) +bool SCSIBR::Init(const unordered_map& params) { SetParams(params); @@ -99,32 +99,16 @@ bool SCSIBR::Dispatch(SCSIDEV *controller) return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } -//--------------------------------------------------------------------------- -// -// INQUIRY -// -//--------------------------------------------------------------------------- -int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf) +vector SCSIBR::Inquiry() const { - // EVPD check - if (cdb[1] & 0x01) { - SetStatusCode(STATUS_INVALIDCDB); - return 0; - } + // Communications device, SCSI-2, not removable + vector b = PrimaryDevice::Inquiry(9, 2, false); - // Basic data - // buf[0] ... Communication Device - // buf[2] ... SCSI-2 compliant command system - // buf[3] ... SCSI-2 compliant Inquiry response - // buf[4] ... Inquiry additional data - memset(buf, 0, 8); - buf[0] = 0x09; - buf[2] = 0x02; - buf[3] = 0x02; - buf[4] = 0x1F + 8; // required + 8 byte extension + // The bridge returns 6 more additional bytes than the other devices + vector buf = vector(0x1F + 8 + 5); + memcpy(buf.data(), b.data(), b.size()); - // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); + buf[4] = 0x1F + 8; // Optional function valid flag buf[36] = '0'; @@ -137,16 +121,7 @@ int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf) // CFileSys Enable buf[38] = '1'; - // Size of data that can be returned - int size = (buf[4] + 5); - - // Limit if the other buffer is small - if (size > (int)cdb[4]) { - size = (int)cdb[4]; - } - - // Success - return size; + return buf; } void SCSIBR::TestUnitReady(SASIDEV *controller) diff --git a/src/raspberrypi/devices/scsi_host_bridge.h b/src/raspberrypi/devices/scsi_host_bridge.h index e7e304e7..d212ea4b 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.h +++ b/src/raspberrypi/devices/scsi_host_bridge.h @@ -36,13 +36,13 @@ public: SCSIBR(); ~SCSIBR(); - bool Init(const map&) override; + bool Init(const unordered_map&) override; bool Dispatch(SCSIDEV *) override; // Commands - int Inquiry(const DWORD *cdb, BYTE *buf) override; // INQUIRY command - int GetMessage10(const DWORD *cdb, BYTE *buf); // GET MESSAGE10 command - bool SendMessage10(const DWORD *cdb, BYTE *buf); // SEND MESSAGE10 command + vector Inquiry() const override; + int GetMessage10(const DWORD *cdb, BYTE *buf); + bool SendMessage10(const DWORD *cdb, BYTE *buf); void TestUnitReady(SASIDEV *) override; void GetMessage10(SASIDEV *); void SendMessage10(SASIDEV *); diff --git a/src/raspberrypi/devices/scsi_printer.cpp b/src/raspberrypi/devices/scsi_printer.cpp index e340ac6d..c3eb6e5b 100644 --- a/src/raspberrypi/devices/scsi_printer.cpp +++ b/src/raspberrypi/devices/scsi_printer.cpp @@ -43,7 +43,6 @@ #include "controllers/scsidev_ctrl.h" #include "../rasutil.h" #include "scsi_printer.h" -#include #define NOT_RESERVED -2 @@ -72,7 +71,7 @@ SCSIPrinter::~SCSIPrinter() Cleanup(); } -bool SCSIPrinter::Init(const map& params) +bool SCSIPrinter::Init(const unordered_map& params) { SetParams(params); @@ -104,10 +103,10 @@ void SCSIPrinter::TestUnitReady(SCSIDEV *controller) controller->Status(); } -int SCSIPrinter::Inquiry(const DWORD *cdb, BYTE *buf) +vector SCSIPrinter::Inquiry() const { // Printer device, SCSI-2, not removable - return PrimaryDevice::Inquiry(2, 2, false, cdb, buf); + return PrimaryDevice::Inquiry(2, 2, false); } void SCSIPrinter::ReserveUnit(SCSIDEV *controller) @@ -172,7 +171,7 @@ void SCSIPrinter::Print(SCSIDEV *controller) if (length > (uint32_t)ctrl->bufsize) { LOGERROR("Transfer buffer overflow"); - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); return; } @@ -279,8 +278,8 @@ bool SCSIPrinter::CheckReservation(SCSIDEV *controller) LOGTRACE("Unknown initiator tries to access reserved device ID %d, LUN %d", GetId(), GetLun()); } - controller->Error(ERROR_CODES::sense_key::ABORTED_COMMAND, ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION, - ERROR_CODES::status::RESERVATION_CONFLICT); + controller->Error(sense_key::ABORTED_COMMAND, asc::NO_ADDITIONAL_SENSE_INFORMATION, + status::RESERVATION_CONFLICT); return false; } diff --git a/src/raspberrypi/devices/scsi_printer.h b/src/raspberrypi/devices/scsi_printer.h index 1abc441f..e24dfddd 100644 --- a/src/raspberrypi/devices/scsi_printer.h +++ b/src/raspberrypi/devices/scsi_printer.h @@ -13,7 +13,7 @@ #include "interfaces/scsi_printer_commands.h" #include "primary_device.h" #include -#include +#include using namespace std; @@ -29,9 +29,9 @@ public: virtual bool Dispatch(SCSIDEV *) override; - bool Init(const map&); + bool Init(const unordered_map&); - int Inquiry(const DWORD *, BYTE *) override; + vector Inquiry() const override; void TestUnitReady(SCSIDEV *); void ReserveUnit(SCSIDEV *); void ReleaseUnit(SCSIDEV *); diff --git a/src/raspberrypi/devices/scsicd.cpp b/src/raspberrypi/devices/scsicd.cpp index b5b16b34..694be96f 100644 --- a/src/raspberrypi/devices/scsicd.cpp +++ b/src/raspberrypi/devices/scsicd.cpp @@ -176,7 +176,7 @@ bool CDTrack::IsAudio() const // //=========================================================================== -SCSICD::SCSICD(const set& sector_sizes) : Disk("SCCD"), ScsiMmcCommands(), FileSupport() +SCSICD::SCSICD(const unordered_set& sector_sizes) : Disk("SCCD"), ScsiMmcCommands(), FileSupport() { SetSectorSizes(sector_sizes); @@ -397,32 +397,10 @@ void SCSICD::ReadToc(SASIDEV *controller) controller->DataIn(); } -int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf) +vector SCSICD::Inquiry() const { - // EVPD check - if (cdb[1] & 0x01) { - SetStatusCode(STATUS_INVALIDCDB); - return 0; - } - - // Basic data - // buf[0] ... CD-ROM Device - // buf[1] ... Removable - // buf[2] ... SCSI-2 compliant command system - // buf[3] ... SCSI-2 compliant Inquiry response - // buf[4] ... Inquiry additional data - memset(buf, 0, 8); - buf[0] = 0x05; - buf[1] = 0x80; - buf[2] = 0x02; - buf[3] = 0x02; - buf[4] = 0x1F; - - // Fill with blanks - memset(&buf[8], 0x20, buf[4] - 3); - - // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); + // CD-ROM device, SCSI-2, removable + return PrimaryDevice::Inquiry(5, 2, true); // // The following code worked with the modified Apple CD-ROM drivers. Need to @@ -446,16 +424,6 @@ int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf) // //strcpy(&buf[35],"A1.9a"); // buf[36]=0x20; // memcpy(&buf[37],"1999/01/01",10); - - // Size of data that can be returned - int size = (buf[4] + 5); - - // Limit if the other buffer is small - if (size > (int)cdb[4]) { - size = (int)cdb[4]; - } - - return size; } void SCSICD::AddModePages(map>& pages, int page, bool changeable) const @@ -658,12 +626,12 @@ void SCSICD::GetEventStatusNotification(SASIDEV *controller) { if (!(ctrl->cmd[1] & 0x01)) { // Asynchronous notification is optional and not supported by rascsi - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); return; } LOGTRACE("Received request for event polling, which is currently not supported"); - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); + controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } //--------------------------------------------------------------------------- diff --git a/src/raspberrypi/devices/scsicd.h b/src/raspberrypi/devices/scsicd.h index b22f398d..8d98408e 100644 --- a/src/raspberrypi/devices/scsicd.h +++ b/src/raspberrypi/devices/scsicd.h @@ -76,7 +76,7 @@ public: TrackMax = 96 // Maximum number of tracks }; - SCSICD(const set&); + SCSICD(const unordered_set&); ~SCSICD(); bool Dispatch(SCSIDEV *) override; @@ -84,9 +84,9 @@ public: void Open(const Filepath& path) override; // Commands - int Inquiry(const DWORD *cdb, BYTE *buf) override; // INQUIRY command - int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override; // READ command - int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command + vector Inquiry() const override; + int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override; + int ReadToc(const DWORD *cdb, BYTE *buf); protected: diff --git a/src/raspberrypi/devices/scsihd.cpp b/src/raspberrypi/devices/scsihd.cpp index 6a0cc194..d4204736 100644 --- a/src/raspberrypi/devices/scsihd.cpp +++ b/src/raspberrypi/devices/scsihd.cpp @@ -26,7 +26,7 @@ // //=========================================================================== -SCSIHD::SCSIHD(const set& sector_sizes, bool removable) : Disk(removable ? "SCRM" : "SCHD") +SCSIHD::SCSIHD(const unordered_set& sector_sizes, bool removable) : Disk(removable ? "SCRM" : "SCHD") { SetSectorSizes(sector_sizes); } @@ -98,38 +98,10 @@ void SCSIHD::Open(const Filepath& path) FinalizeSetup(path, size); } -int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf) +vector SCSIHD::Inquiry() const { - // EVPD check - if (cdb[1] & 0x01) { - SetStatusCode(STATUS_INVALIDCDB); - return 0; - } - - // Basic data - // buf[0] ... Direct Access Device - // buf[1] ... Bit 7 set means removable - // buf[2] ... SCSI-2 compliant command system - // buf[3] ... SCSI-2 compliant Inquiry response - // buf[4] ... Inquiry additional data - memset(buf, 0, 8); - buf[1] = IsRemovable() ? 0x80 : 0x00; - buf[2] = 0x02; - buf[3] = 0x02; - buf[4] = 0x1F; - - // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); - - // Size of data that can be returned - int size = (buf[4] + 5); - - // Limit if the other buffer is small - if (size > (int)cdb[4]) { - size = (int)cdb[4]; - } - - return size; + // Direct access device, SCSI-2 + return PrimaryDevice::Inquiry(0, 2, IsRemovable()); } bool SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) @@ -221,7 +193,7 @@ void SCSIHD::AddVendorPage(map>& pages, int page, bool changea // No changeable area if (!changeable) { - memcpy(&buf.data()[0xa], "APPLE COMPUTER, INC.", 20); + memcpy(&buf[0xa], "APPLE COMPUTER, INC.", 20); } pages[48] = buf; diff --git a/src/raspberrypi/devices/scsihd.h b/src/raspberrypi/devices/scsihd.h index 128578f5..d6d3ed43 100644 --- a/src/raspberrypi/devices/scsihd.h +++ b/src/raspberrypi/devices/scsihd.h @@ -22,7 +22,7 @@ class SCSIHD : public Disk, public FileSupport { public: - SCSIHD(const set&, bool); + SCSIHD(const unordered_set&, bool); virtual ~SCSIHD() {} void FinalizeSetup(const Filepath&, off_t); @@ -31,7 +31,7 @@ public: virtual void Open(const Filepath&) override; // Commands - virtual int Inquiry(const DWORD *cdb, BYTE *buf) override; + virtual vector Inquiry() const override; bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override; void AddVendorPage(map>&, int, bool) const override; diff --git a/src/raspberrypi/devices/scsihd_nec.cpp b/src/raspberrypi/devices/scsihd_nec.cpp index 02b93eae..e4653638 100644 --- a/src/raspberrypi/devices/scsihd_nec.cpp +++ b/src/raspberrypi/devices/scsihd_nec.cpp @@ -18,7 +18,7 @@ #include "fileio.h" #include "exceptions.h" -SCSIHD_NEC::SCSIHD_NEC(const set& sector_sizes) : SCSIHD(sector_sizes, false) +SCSIHD_NEC::SCSIHD_NEC(const unordered_set& sector_sizes) : SCSIHD(sector_sizes, false) { // Work initialization cylinders = 0; @@ -135,15 +135,10 @@ void SCSIHD_NEC::Open(const Filepath& path) FinalizeSetup(path, size); } -int SCSIHD_NEC::Inquiry(const DWORD *cdb, BYTE *buf) +vector SCSIHD_NEC::Inquiry() const { - int size = SCSIHD::Inquiry(cdb, buf); - - // This drive is a SCSI-1 SCCS drive - buf[2] = 0x01; - buf[3] = 0x01; - - return size; + // Direct access device, SCSI-1-CCS, not removable + return PrimaryDevice::Inquiry(0, 1, false); } void SCSIHD_NEC::AddErrorPage(map>& pages, bool) const diff --git a/src/raspberrypi/devices/scsihd_nec.h b/src/raspberrypi/devices/scsihd_nec.h index 75923123..b00cec60 100644 --- a/src/raspberrypi/devices/scsihd_nec.h +++ b/src/raspberrypi/devices/scsihd_nec.h @@ -25,13 +25,13 @@ class SCSIHD_NEC : public SCSIHD { public: - SCSIHD_NEC(const set&); + SCSIHD_NEC(const unordered_set&); ~SCSIHD_NEC() {} void Open(const Filepath& path) override; // Commands - int Inquiry(const DWORD *cdb, BYTE *buf) override; + vector Inquiry() const override; void AddErrorPage(map>&, bool) const override; void AddFormatPage(map>&, bool) const override; diff --git a/src/raspberrypi/devices/scsimo.cpp b/src/raspberrypi/devices/scsimo.cpp index 0bed7926..8a3c2237 100644 --- a/src/raspberrypi/devices/scsimo.cpp +++ b/src/raspberrypi/devices/scsimo.cpp @@ -14,12 +14,11 @@ // //--------------------------------------------------------------------------- -#include "scsimo.h" - #include "fileio.h" #include "exceptions.h" +#include "scsimo.h" -SCSIMO::SCSIMO(const set& sector_sizes, const map& geometries) : Disk("SCMO") +SCSIMO::SCSIMO(const unordered_set& sector_sizes, const unordered_map& geometries) : Disk("SCMO") { SetSectorSizes(sector_sizes); SetGeometries(geometries); @@ -41,6 +40,7 @@ void SCSIMO::Open(const Filepath& path) fio.Close(); // For some priorities there are hard-coded, well-defined sector sizes and block counts + // TODO Find a more flexible solution if (!SetGeometryForCapacity(size)) { // Sector size (default 512 bytes) and number of blocks SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512, true); @@ -63,39 +63,10 @@ void SCSIMO::Open(const Filepath& path) } } -int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf) +vector SCSIMO::Inquiry() const { - // EVPD check - if (cdb[1] & 0x01) { - SetStatusCode(STATUS_INVALIDCDB); - return FALSE; - } - - // Basic data - // buf[0] ... Optical Memory Device - // buf[1] ... Removable - // buf[2] ... SCSI-2 compliant command system - // buf[3] ... SCSI-2 compliant Inquiry response - // buf[4] ... Inquiry additional data - memset(buf, 0, 8); - buf[0] = 0x07; - buf[1] = 0x80; - buf[2] = 0x02; - buf[3] = 0x02; - buf[4] = 0x1F; - - // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); - - // Size return data - int size = (buf[4] + 5); - - // Limit the size if the buffer is too small - if (size > (int)cdb[4]) { - size = (int)cdb[4]; - } - - return size; + // Optical memory device, SCSI-2, removable + return PrimaryDevice::Inquiry(7, 2, true); } void SCSIMO::SetDeviceParameters(BYTE *buf) diff --git a/src/raspberrypi/devices/scsimo.h b/src/raspberrypi/devices/scsimo.h index b55d42ea..4562ca74 100644 --- a/src/raspberrypi/devices/scsimo.h +++ b/src/raspberrypi/devices/scsimo.h @@ -22,13 +22,13 @@ class SCSIMO : public Disk, public FileSupport { public: - SCSIMO(const set&, const map&); + SCSIMO(const unordered_set&, const unordered_map&); ~SCSIMO() {} void Open(const Filepath& path) override; // Commands - int Inquiry(const DWORD *cdb, BYTE *buf) override; + vector Inquiry() const override; bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override; protected: diff --git a/src/raspberrypi/localizer.cpp b/src/raspberrypi/localizer.cpp index cb6b4bd8..63c75071 100644 --- a/src/raspberrypi/localizer.cpp +++ b/src/raspberrypi/localizer.cpp @@ -10,7 +10,6 @@ #include "localizer.h" #include #include -#include #include #include @@ -146,7 +145,7 @@ string Localizer::Localize(LocalizationKey key, const string& locale, const stri string locale_lower = locale; transform(locale_lower.begin(), locale_lower.end(), locale_lower.begin(), ::tolower); - map messages = localized_messages[locale_lower]; + unordered_map messages = localized_messages[locale_lower]; if (messages.empty()) { // Try to fall back to country-indepedent locale (e.g. "en" instead of "en_US") if (locale_lower.length() > 2) { diff --git a/src/raspberrypi/localizer.h b/src/raspberrypi/localizer.h index e59faf84..c660e0b0 100644 --- a/src/raspberrypi/localizer.h +++ b/src/raspberrypi/localizer.h @@ -12,8 +12,8 @@ #pragma once #include -#include -#include +#include +#include using namespace std; @@ -53,7 +53,7 @@ public: private: void Add(LocalizationKey, const string&, const string&); - map> localized_messages; + unordered_map> localized_messages; - set supported_languages; + unordered_set supported_languages; }; diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index fa85c5f1..cbc0f1dd 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -68,7 +68,7 @@ pthread_mutex_t ctrl_mutex; // Semaphore for the ctrl array static void *MonThread(void *param); string current_log_level; // Some versions of spdlog do not support get_log_level() string access_token; -set reserved_ids; +unordered_set reserved_ids; DeviceFactory& device_factory = DeviceFactory::instance(); RascsiImage rascsi_image; RascsiResponse rascsi_response(&device_factory, &rascsi_image); @@ -428,22 +428,10 @@ string ValidateLunSetup(const PbCommand& command, const vector& existi } } - // LUNs must be consecutive + // LUN 0 must exist for all devices for (auto const& [id, lun]: luns) { - bool is_consecutive = false; - - uint32_t lun_vector = 0; - for (int i = 0; i < 32; i++) { - lun_vector |= 1 << i; - - if (lun == lun_vector) { - is_consecutive = true; - break; - } - } - - if (!is_consecutive) { - return "LUNs for device ID " + to_string(id) + " are not consecutive"; + if (!(lun & 0x01)) { + return "LUN 0 is missing for device ID " + to_string(id); } } @@ -505,7 +493,7 @@ string SetReservedIds(const string& ids) } } - set reserved; + unordered_set reserved; for (string id_to_reserve : ids_to_reserve) { int id; if (!GetAsInt(id_to_reserve, id) || id > 7) { @@ -694,7 +682,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, return true; } - std::map params = { pb_device.params().begin(), pb_device.params().end() }; + unordered_map params = { pb_device.params().begin(), pb_device.params().end() }; if (!device->SupportsFile()) { params.erase("file"); } @@ -728,20 +716,24 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, bool Detach(const CommandContext& context, Device *device, Device *map[], bool dryRun) { - if (!dryRun) { + if (!device->GetLun()) { for (auto const& d : devices) { - // Detach all LUNs equal to or higher than the LUN specified - if (d && d->GetId() == device->GetId() && d->GetLun() >= device->GetLun()) { - map[d->GetId() * UnitNum + d->GetLun()] = NULL; - - FileSupport *file_support = dynamic_cast(d); - if (file_support) { - file_support->UnreserveFile(); - } - - LOGINFO("Detached %s device with ID %d, unit %d", d->GetType().c_str(), d->GetId(), d->GetLun()); + // LUN 0 can only be detached if there is no other lUN anymore + if (d && d->GetId() == device->GetId() && d->GetLun()) { + return ReturnStatus(context, false, "LUN 0 cannot be detached as long as there is still another LUN"); } } + } + + if (!dryRun) { + map[device->GetId() * UnitNum + device->GetLun()] = NULL; + + FileSupport *file_support = dynamic_cast(device); + if (file_support) { + file_support->UnreserveFile(); + } + + LOGINFO("Detached %s device with ID %d, unit %d", device->GetType().c_str(), device->GetId(), device->GetLun()); // Re-map the controller MapController(map); diff --git a/src/raspberrypi/rascsi_response.cpp b/src/raspberrypi/rascsi_response.cpp index 8cda4412..afa04959 100644 --- a/src/raspberrypi/rascsi_response.cpp +++ b/src/raspberrypi/rascsi_response.cpp @@ -220,7 +220,7 @@ void RascsiResponse::GetAvailableImages(PbResult& result, PbServerInfo& server_i result.set_status(true); } -PbReservedIdsInfo *RascsiResponse::GetReservedIds(PbResult& result, const set& ids) +PbReservedIdsInfo *RascsiResponse::GetReservedIds(PbResult& result, const unordered_set& ids) { PbReservedIdsInfo *reserved_ids_info = new PbReservedIdsInfo(); for (int id : ids) { @@ -289,8 +289,9 @@ PbDeviceTypesInfo *RascsiResponse::GetDeviceTypesInfo(PbResult& result, const Pb return device_types_info; } -PbServerInfo *RascsiResponse::GetServerInfo(PbResult& result, const vector& devices, const set& reserved_ids, - const string& current_log_level, const string& folder_pattern, const string& file_pattern, int scan_depth) +PbServerInfo *RascsiResponse::GetServerInfo(PbResult& result, const vector& devices, + const unordered_set& reserved_ids, const string& current_log_level, const string& folder_pattern, + const string& file_pattern, int scan_depth) { PbServerInfo *server_info = new PbServerInfo(); diff --git a/src/raspberrypi/rascsi_response.h b/src/raspberrypi/rascsi_response.h index 460d9925..d8c70474 100644 --- a/src/raspberrypi/rascsi_response.h +++ b/src/raspberrypi/rascsi_response.h @@ -30,13 +30,13 @@ public: bool GetImageFile(PbImageFile *, const string&); PbImageFilesInfo *GetAvailableImages(PbResult&, const string&, const string&, int); - PbReservedIdsInfo *GetReservedIds(PbResult&, const set&); + PbReservedIdsInfo *GetReservedIds(PbResult&, const unordered_set&); void GetDevices(PbServerInfo&, const vector&); void GetDevicesInfo(PbResult&, const PbCommand&, const vector&, int); PbDeviceTypesInfo *GetDeviceTypesInfo(PbResult&, const PbCommand&); PbVersionInfo *GetVersionInfo(PbResult&); - PbServerInfo *GetServerInfo(PbResult&, const vector&, const set&, const string&, const string&, - const string&, int); + PbServerInfo *GetServerInfo(PbResult&, const vector&, const unordered_set&, const string&, + const string&, const string&, int); PbNetworkInterfacesInfo *GetNetworkInterfacesInfo(PbResult&); PbMappingInfo *GetMappingInfo(PbResult&); PbLogLevelInfo *GetLogLevelInfo(PbResult&, const string&); diff --git a/src/raspberrypi/scsi.h b/src/raspberrypi/scsi.h index 0c9ec109..d51ee671 100644 --- a/src/raspberrypi/scsi.h +++ b/src/raspberrypi/scsi.h @@ -12,57 +12,6 @@ #pragma once #include "os.h" -//=========================================================================== -// -// Status byte codes, Sense Keys and Additional Sense Codes -// (See https://www.t10.org/lists/1spc-lst.htm) -// -//=========================================================================== -class ERROR_CODES -{ -public: - enum status : int { - GOOD = 0x00, - CHECK_CONDITION = 0x02, - CONDITION_MET = 0x04, - BUSY = 0x08, - INTERMEDIATE = 0x10, - INTERMEDIATE_CONDITION_MET = 0x14, - RESERVATION_CONFLICT = 0x18, - COMMAND_TERMINATED = 0x22, - QUEUE_FULL = 0x28 - }; - - enum sense_key : int { - NO_SENSE = 0x00, - RECOVERED_ERROR = 0x01, - NOT_READY = 0x02, - MEDIUM_ERROR = 0x03, - HARDWARE_ERROR = 0x04, - ILLEGAL_REQUEST = 0x05, - UNIT_ATTENTION = 0x06, - DATA_PROTECT = 0x07, - BLANK_CHECK = 0x08, - VENDOR_SPECIFIC = 0x09, - COPY_ABORTED = 0x0a, - ABORTED_COMMAND = 0x0b, - VOLUME_OVERFLOW = 0x0d, - MISCOMPARE = 0x0e, - COMPLETED = 0x0f - }; - - enum asc : int { - NO_ADDITIONAL_SENSE_INFORMATION = 0x00, - INVALID_COMMAND_OPERATION_CODE = 0x20, - LBA_OUT_OF_RANGE = 0x21, - INVALID_FIELD_IN_CDB = 0x24, - INVALID_LUN = 0x25, - WRITE_PROTECTED = 0x27, - NOT_READY_TO_READY_CHANGE = 0x28, - MEDIUM_NOT_PRESENT = 0x3a - }; -}; - //=========================================================================== // // SASI/SCSI Bus @@ -94,8 +43,8 @@ public: reserved // Unused }; - BUS() { }; - virtual ~BUS() { }; + BUS() {} + virtual ~BUS() {} // Basic Functions virtual BOOL Init(mode_e mode) = 0; @@ -108,8 +57,8 @@ public: return phase_table[mci]; } + // Get the string phase name, based upon the raw data static const char* GetPhaseStrRaw(phase_t current_phase); - // Get the string phase name, based upon the raw data // Extract as specific pin field from a raw data capture static inline DWORD GetPinRaw(DWORD raw_data, DWORD pin_num) @@ -168,6 +117,12 @@ private: static const char* phase_str_table[]; }; +//=========================================================================== +// +// For Status byte codes, Sense Keys and Additional Sense Codes +// See https://www.t10.org/lists/1spc-lst.htm +// +//=========================================================================== namespace scsi_defs { enum scsi_command : int { eCmdTestUnitReady = 0x00, @@ -220,4 +175,45 @@ namespace scsi_defs { eCmdWriteLong16 = 0x9F, eCmdReportLuns = 0xA0 }; + + enum status : int { + GOOD = 0x00, + CHECK_CONDITION = 0x02, + CONDITION_MET = 0x04, + BUSY = 0x08, + INTERMEDIATE = 0x10, + INTERMEDIATE_CONDITION_MET = 0x14, + RESERVATION_CONFLICT = 0x18, + COMMAND_TERMINATED = 0x22, + QUEUE_FULL = 0x28 + }; + + enum sense_key : int { + NO_SENSE = 0x00, + RECOVERED_ERROR = 0x01, + NOT_READY = 0x02, + MEDIUM_ERROR = 0x03, + HARDWARE_ERROR = 0x04, + ILLEGAL_REQUEST = 0x05, + UNIT_ATTENTION = 0x06, + DATA_PROTECT = 0x07, + BLANK_CHECK = 0x08, + VENDOR_SPECIFIC = 0x09, + COPY_ABORTED = 0x0a, + ABORTED_COMMAND = 0x0b, + VOLUME_OVERFLOW = 0x0d, + MISCOMPARE = 0x0e, + COMPLETED = 0x0f + }; + + enum asc : int { + NO_ADDITIONAL_SENSE_INFORMATION = 0x00, + INVALID_COMMAND_OPERATION_CODE = 0x20, + LBA_OUT_OF_RANGE = 0x21, + INVALID_FIELD_IN_CDB = 0x24, + INVALID_LUN = 0x25, + WRITE_PROTECTED = 0x27, + NOT_READY_TO_READY_CHANGE = 0x28, + MEDIUM_NOT_PRESENT = 0x3a + }; };