diff --git a/src/raspberrypi/command_context.h b/src/raspberrypi/command_context.h index b7a16416..7f613dc1 100644 --- a/src/raspberrypi/command_context.h +++ b/src/raspberrypi/command_context.h @@ -16,12 +16,12 @@ class Localizer; struct CommandContext { - CommandContext(SocketConnector *c, const Localizer *l, int f, const std::string& s) + CommandContext(const SocketConnector& c, const Localizer& l, int f, const std::string& s) : connector(c), localizer(l), fd(f), locale(s) {} ~CommandContext() = default; - SocketConnector *connector; - const Localizer *localizer; + const SocketConnector& connector; + const Localizer& localizer; int fd; std::string locale; }; diff --git a/src/raspberrypi/command_util.cpp b/src/raspberrypi/command_util.cpp index 8bba229e..ca9884be 100644 --- a/src/raspberrypi/command_util.cpp +++ b/src/raspberrypi/command_util.cpp @@ -28,26 +28,27 @@ void command_util::ParseParameters(PbDeviceDefinition& device, const string& par return; } - if (params.find(KEY_VALUE_SEPARATOR) != string::npos) { - stringstream ss(params); - string p; - while (getline(ss, p, COMPONENT_SEPARATOR)) { - if (!p.empty()) { - size_t separator_pos = p.find(KEY_VALUE_SEPARATOR); - if (separator_pos != string::npos) { - AddParam(device, p.substr(0, separator_pos), string_view(p).substr(separator_pos + 1)); - } - } - } - } // Old style parameters, for backwards compatibility only. // Only one of these parameters will be used by rascsi, depending on the device type. - else { + if (params.find(KEY_VALUE_SEPARATOR) == string::npos) { AddParam(device, "file", params); if (params != "bridge" && params != "daynaport" && params != "printer" && params != "services") { AddParam(device, "interfaces", params); } - } + + return; + } + + stringstream ss(params); + string p; + while (getline(ss, p, COMPONENT_SEPARATOR)) { + if (!p.empty()) { + size_t separator_pos = p.find(KEY_VALUE_SEPARATOR); + if (separator_pos != string::npos) { + AddParam(device, p.substr(0, separator_pos), string_view(p).substr(separator_pos + 1)); + } + } + } } string command_util::GetParam(const PbCommand& command, const string& key) @@ -86,24 +87,24 @@ void command_util::AddParam(PbDeviceDefinition& device, const string& key, strin } } -bool command_util::ReturnLocalizedError(const CommandContext& context, const LocalizationKey key, +bool command_util::ReturnLocalizedError(const CommandContext& context, LocalizationKey key, const string& arg1, const string& arg2, const string& arg3) { return ReturnLocalizedError(context, key, NO_ERROR_CODE, arg1, arg2, arg3); } -bool command_util::ReturnLocalizedError(const CommandContext& context, const LocalizationKey key, - const PbErrorCode error_code, const string& arg1, const string& arg2, const string& arg3) +bool command_util::ReturnLocalizedError(const CommandContext& context, LocalizationKey key, + PbErrorCode error_code, const string& arg1, const string& arg2, const string& arg3) { // For the logfile always use English - LOGERROR("%s", context.localizer->Localize(key, "en", arg1, arg2, arg3).c_str()) + LOGERROR("%s", context.localizer.Localize(key, "en", arg1, arg2, arg3).c_str()) - return ReturnStatus(context, false, context.localizer->Localize(key, context.locale, arg1, arg2, arg3), error_code, + return ReturnStatus(context, false, context.localizer.Localize(key, context.locale, arg1, arg2, arg3), error_code, false); } bool command_util::ReturnStatus(const CommandContext& context, bool status, const string& msg, - const PbErrorCode error_code, bool log) + PbErrorCode error_code, bool log) { // Do not log twice if logging has already been done in the localized error handling above if (log && !status && !msg.empty()) { @@ -128,7 +129,7 @@ bool command_util::ReturnStatus(const CommandContext& context, bool status, cons result.set_status(status); result.set_error_code(error_code); result.set_msg(msg); - context.connector->SerializeMessage(context.fd, result); + context.connector.SerializeMessage(context.fd, result); } return status; diff --git a/src/raspberrypi/command_util.h b/src/raspberrypi/command_util.h index b1bb4c60..91327d11 100644 --- a/src/raspberrypi/command_util.h +++ b/src/raspberrypi/command_util.h @@ -27,10 +27,10 @@ namespace command_util void AddParam(PbCommand&, const string&, string_view); void AddParam(PbDevice&, const string&, string_view); void AddParam(PbDeviceDefinition&, const string&, string_view); - bool ReturnLocalizedError(const CommandContext&, const LocalizationKey, const string& = "", const string& = "", + bool ReturnLocalizedError(const CommandContext&, LocalizationKey, const string& = "", const string& = "", const string& = ""); - bool ReturnLocalizedError(const CommandContext&, const LocalizationKey, const PbErrorCode, const string& = "", + bool ReturnLocalizedError(const CommandContext&, LocalizationKey, PbErrorCode, const string& = "", const string& = "", const string& = ""); bool ReturnStatus(const CommandContext&, bool = true, const string& = "", - const PbErrorCode = PbErrorCode::NO_ERROR_CODE, bool = true); + PbErrorCode = PbErrorCode::NO_ERROR_CODE, bool = true); } diff --git a/src/raspberrypi/controllers/abstract_controller.cpp b/src/raspberrypi/controllers/abstract_controller.cpp index 80556cfe..ba0a1d33 100644 --- a/src/raspberrypi/controllers/abstract_controller.cpp +++ b/src/raspberrypi/controllers/abstract_controller.cpp @@ -10,9 +10,74 @@ #include "abstract_controller.h" #include "devices/primary_device.h" +void AbstractController::AllocateBuffer(size_t size) +{ + if (size > ctrl.buffer.size()) { + ctrl.buffer.resize(size); + } +} + PrimaryDevice *AbstractController::GetDeviceForLun(int lun) const { - const auto& it = ctrl.luns.find(lun); - return it == ctrl.luns.end() ? nullptr : it->second; + const auto& it = luns.find(lun); + return it == luns.end() ? nullptr : it->second; +} + +void AbstractController::Reset() +{ + SetPhase(BUS::phase_t::busfree); + + ctrl.status = 0x00; + ctrl.message = 0x00; + ctrl.blocks = 0; + ctrl.next = 0; + ctrl.offset = 0; + ctrl.length = 0; + + // Reset all LUNs + for (const auto& [lun, device] : luns) { + device->Reset(); + } +} + +void AbstractController::ProcessPhase() +{ + switch (GetPhase()) { + case BUS::phase_t::busfree: + BusFree(); + break; + + case BUS::phase_t::selection: + Selection(); + break; + + case BUS::phase_t::dataout: + DataOut(); + break; + + case BUS::phase_t::datain: + DataIn(); + break; + + case BUS::phase_t::command: + Command(); + break; + + case BUS::phase_t::status: + Status(); + break; + + case BUS::phase_t::msgout: + MsgOut(); + break; + + case BUS::phase_t::msgin: + MsgIn(); + break; + + default: + assert(false); + break; + } } bool AbstractController::AddDevice(PrimaryDevice *device) @@ -25,7 +90,7 @@ bool AbstractController::AddDevice(PrimaryDevice *device) return false; } - ctrl.luns[device->GetLun()] = device; + luns[device->GetLun()] = device; device->SetController(this); return true; @@ -33,12 +98,12 @@ bool AbstractController::AddDevice(PrimaryDevice *device) bool AbstractController::DeleteDevice(const PrimaryDevice *device) { - return ctrl.luns.erase(device->GetLun()) == 1; + return luns.erase(device->GetLun()) == 1; } bool AbstractController::HasDeviceForLun(int lun) const { - return ctrl.luns.find(lun) != ctrl.luns.end(); + return luns.find(lun) != luns.end(); } int AbstractController::ExtractInitiatorId(int id_data) const diff --git a/src/raspberrypi/controllers/abstract_controller.h b/src/raspberrypi/controllers/abstract_controller.h index a9ed6ac8..e0bb7df7 100644 --- a/src/raspberrypi/controllers/abstract_controller.h +++ b/src/raspberrypi/controllers/abstract_controller.h @@ -16,14 +16,21 @@ #include #include +using namespace std; //NOSONAR Not relevant for rascsi + class PrimaryDevice; class AbstractController { -public: + friend class PrimaryDevice; + friend class ScsiController; - // Maximum number of logical units - static const int LUN_MAX = 32; + BUS::phase_t phase = BUS::phase_t::busfree; + + // Logical units of this device controller mapped to their LUN numbers + unordered_map luns; + +public: enum class rascsi_shutdown_mode { NONE, @@ -33,32 +40,23 @@ public: }; using ctrl_t = struct _ctrl_t { - // General - BUS::phase_t phase = BUS::phase_t::busfree; // Transition phase - - // commands - std::vector cmd; // Command data, dynamically allocated per received command + vector cmd; // Command data, dynamically allocated per received command uint32_t status; // Status data int message; // Message data // Transfer - BYTE *buffer; // Transfer data buffer - int bufsize; // Transfer data buffer size + vector buffer; // Transfer data buffer uint32_t blocks; // Number of transfer blocks uint64_t next; // Next record uint32_t offset; // Transfer offset uint32_t length; // Transfer remaining length - - // Logical units of this device controller mapped to their LUN numbers - std::unordered_map luns; }; - AbstractController(shared_ptr bus, int target_id) : target_id(target_id), bus(bus) {} + AbstractController(shared_ptr bus, int target_id, int luns) : target_id(target_id), bus(bus), max_luns(luns) {} virtual ~AbstractController() = default; AbstractController(AbstractController&) = delete; AbstractController& operator=(const AbstractController&) = delete; - virtual void SetPhase(BUS::phase_t) = 0; virtual void BusFree() = 0; virtual void Selection() = 0; virtual void Command() = 0; @@ -72,18 +70,18 @@ public: virtual void Error(scsi_defs::sense_key, scsi_defs::asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION, scsi_defs::status = scsi_defs::status::CHECK_CONDITION) = 0; - virtual void Reset() = 0; + virtual void Reset(); virtual int GetInitiatorId() const = 0; virtual void SetByteTransfer(bool) = 0; // Get requested LUN based on IDENTIFY message, with LUN from the CDB as fallback virtual int GetEffectiveLun() const = 0; - virtual int GetMaxLuns() const = 0; - virtual void ScheduleShutdown(rascsi_shutdown_mode) = 0; int GetTargetId() const { return target_id; } + int GetMaxLuns() const { return max_luns; } + bool HasLuns() const { return !luns.empty(); } PrimaryDevice *GetDeviceForLun(int) const; bool AddDevice(PrimaryDevice *); @@ -91,17 +89,46 @@ public: bool HasDeviceForLun(int) const; int ExtractInitiatorId(int id_data) const; - // TODO Do not expose internal data - ctrl_t* GetCtrl() { return &ctrl; } - - int target_id; + void AllocateBuffer(size_t); + vector& GetBuffer() { return ctrl.buffer; } + size_t GetBufferSize() const { return ctrl.buffer.size(); } + uint32_t GetStatus() const { return ctrl.status; } + void SetStatus(uint32_t s) { ctrl.status = s; } + uint32_t GetLength() const { return ctrl.length; } protected: scsi_defs::scsi_command GetOpcode() const { return (scsi_defs::scsi_command)ctrl.cmd[0]; } int GetLun() const { return (ctrl.cmd[1] >> 5) & 0x07; } + void ProcessPhase(); + + vector& InitCmd(int size) { ctrl.cmd.resize(size); return ctrl.cmd; } + + bool HasValidLength() const { return ctrl.length != 0; } + void ResetOffset() { ctrl.offset = 0; } + void UpdateOffsetAndLength() { ctrl.offset += ctrl.length; ctrl.length = 0; } + + BUS::phase_t GetPhase() const { return phase; } + void SetPhase(BUS::phase_t p) { phase = p; } + bool IsSelection() const { return phase == BUS::phase_t::selection; } + bool IsBusFree() const { return phase == BUS::phase_t::busfree; } + bool IsCommand() const { return phase == BUS::phase_t::command; } + bool IsStatus() const { return phase == BUS::phase_t::status; } + bool IsDataIn() const { return phase == BUS::phase_t::datain; } + bool IsDataOut() const { return phase == BUS::phase_t::dataout; } + bool IsMsgIn() const { return phase == BUS::phase_t::msgin; } + bool IsMsgOut() const { return phase == BUS::phase_t::msgout; } + +private: + + int target_id; + shared_ptr bus; + int max_luns; + ctrl_t ctrl = {}; + + ctrl_t* GetCtrl() { return &ctrl; } }; diff --git a/src/raspberrypi/controllers/scsi_controller.cpp b/src/raspberrypi/controllers/scsi_controller.cpp index ed8e9fe2..c1d1167b 100644 --- a/src/raspberrypi/controllers/scsi_controller.cpp +++ b/src/raspberrypi/controllers/scsi_controller.cpp @@ -10,8 +10,6 @@ // Licensed under the BSD 3-Clause License. // See LICENSE file in the project root folder. // -// [ SCSI device controller ] -// //--------------------------------------------------------------------------- #include "log.h" @@ -29,42 +27,26 @@ using namespace scsi_defs; -ScsiController::ScsiController(shared_ptr bus, int target_id) : AbstractController(bus, target_id) +ScsiController::ScsiController(shared_ptr bus, int target_id) : AbstractController(bus, target_id, LUN_MAX) { // The initial buffer size will default to either the default buffer size OR // the size of an Ethernet message, whichever is larger. - ctrl.bufsize = std::max(DEFAULT_BUFFER_SIZE, ETH_FRAME_LEN + 16 + ETH_FCS_LEN); - ctrl.buffer = new BYTE[ctrl.bufsize]; -} - -ScsiController::~ScsiController() -{ - delete[] ctrl.buffer; + AllocateBuffer(std::max(DEFAULT_BUFFER_SIZE, ETH_FRAME_LEN + 16 + ETH_FCS_LEN)); } void ScsiController::Reset() { - SetPhase(BUS::phase_t::busfree); - ctrl.status = 0x00; - ctrl.message = 0x00; + AbstractController::Reset(); + execstart = 0; - ctrl.blocks = 0; - ctrl.next = 0; - ctrl.offset = 0; - ctrl.length = 0; identified_lun = -1; scsi.atnmsg = false; scsi.msc = 0; - memset(scsi.msb.data(), 0x00, scsi.msb.size()); + scsi.msb = {}; is_byte_transfer = false; bytes_to_transfer = 0; - - // Reset all LUNs - for (const auto& [lun, device] : ctrl.luns) { - device->Reset(); - } } BUS::phase_t ScsiController::Process(int id) @@ -82,7 +64,7 @@ BUS::phase_t ScsiController::Process(int id) // Reset the bus bus->Reset(); - return ctrl.phase; + return GetPhase(); } if (id != UNKNOWN_INITIATOR_ID) { @@ -95,44 +77,7 @@ BUS::phase_t ScsiController::Process(int id) initiator_id = id; try { - // Phase processing - switch (ctrl.phase) { - case BUS::phase_t::busfree: - BusFree(); - break; - - case BUS::phase_t::selection: - Selection(); - break; - - case BUS::phase_t::dataout: - DataOut(); - break; - - case BUS::phase_t::datain: - DataIn(); - break; - - case BUS::phase_t::command: - Command(); - break; - - case BUS::phase_t::status: - Status(); - break; - - case BUS::phase_t::msgout: - MsgOut(); - break; - - case BUS::phase_t::msgin: - MsgIn(); - break; - - default: - assert(false); - break; - } + ProcessPhase(); } catch(const scsi_error_exception&) { // Any exception should have been handled during the phase processing @@ -146,12 +91,12 @@ BUS::phase_t ScsiController::Process(int id) BusFree(); } - return ctrl.phase; + return GetPhase(); } void ScsiController::BusFree() { - if (ctrl.phase != BUS::phase_t::busfree) { + if (!IsBusFree()) { LOGTRACE("%s Bus free phase", __PRETTY_FUNCTION__) SetPhase(BUS::phase_t::busfree); @@ -163,7 +108,7 @@ void ScsiController::BusFree() bus->SetBSY(false); // Initialize status and message - ctrl.status = 0x00; + SetStatus(0); ctrl.message = 0x00; // Initialize ATN message reception status @@ -211,14 +156,14 @@ void ScsiController::BusFree() void ScsiController::Selection() { - if (ctrl.phase != BUS::phase_t::selection) { + if (!IsSelection()) { // A different device controller was selected if (int id = 1 << GetTargetId(); ((int)bus->GetDAT() & id) == 0) { return; } // Abort if there is no LUN for this controller - if (ctrl.luns.empty()) { + if (!HasLuns()) { return; } @@ -244,7 +189,7 @@ void ScsiController::Selection() void ScsiController::Command() { - if (ctrl.phase != BUS::phase_t::command) { + if (!IsCommand()) { LOGTRACE("%s Command Phase", __PRETTY_FUNCTION__) SetPhase(BUS::phase_t::command); @@ -253,8 +198,8 @@ void ScsiController::Command() bus->SetCD(true); bus->SetIO(false); - int actual_count = bus->CommandHandShake(ctrl.buffer); - int command_byte_count = GPIOBUS::GetCommandByteCount(ctrl.buffer[0]); + int actual_count = bus->CommandHandShake(GetBuffer().data()); + int command_byte_count = GPIOBUS::GetCommandByteCount(GetBuffer()[0]); // If not able to receive all, move to the status phase if (actual_count != command_byte_count) { @@ -264,12 +209,12 @@ void ScsiController::Command() return; } - ctrl.cmd.resize(command_byte_count); + InitCmd(command_byte_count); // Command data transfer stringstream s; for (int i = 0; i < command_byte_count; i++) { - ctrl.cmd[i] = ctrl.buffer[i]; + ctrl.cmd[i] = GetBuffer()[i]; s << setfill('0') << setw(2) << hex << ctrl.cmd[i]; } LOGTRACE("%s CDB=$%s",__PRETTY_FUNCTION__, s.str().c_str()) @@ -287,13 +232,13 @@ void ScsiController::Execute() SetPhase(BUS::phase_t::execute); // Initialization for data transfer - ctrl.offset = 0; + ResetOffset(); ctrl.blocks = 1; execstart = SysTimer::GetTimerLow(); // Discard pending sense data from the previous command if the current command is not REQUEST SENSE if (GetOpcode() != scsi_command::eCmdRequestSense) { - ctrl.status = 0; + SetStatus(0); } int lun = GetEffectiveLun(); @@ -339,13 +284,13 @@ void ScsiController::Execute() LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, device->GetId()) - ctrl.buffer[0] = 0x7f; + GetBuffer().data()[0] = 0x7f; } } void ScsiController::Status() { - if (ctrl.phase != BUS::phase_t::status) { + if (!IsStatus()) { // Minimum execution time if (execstart > 0) { Sleep(); @@ -353,7 +298,7 @@ void ScsiController::Status() SysTimer::SleepUsec(5); } - LOGTRACE("%s Status Phase $%02X",__PRETTY_FUNCTION__, ctrl.status) + LOGTRACE("%s Status Phase $%02X",__PRETTY_FUNCTION__, GetStatus()) SetPhase(BUS::phase_t::status); @@ -363,10 +308,10 @@ void ScsiController::Status() bus->SetIO(true); // Data transfer is 1 byte x 1 block - ctrl.offset = 0; + ResetOffset(); ctrl.length = 1; ctrl.blocks = 1; - ctrl.buffer[0] = (BYTE)ctrl.status; + GetBuffer()[0] = (BYTE)GetStatus(); return; } @@ -376,7 +321,7 @@ void ScsiController::Status() void ScsiController::MsgIn() { - if (ctrl.phase != BUS::phase_t::msgin) { + if (!IsMsgIn()) { LOGTRACE("%s Message In phase", __PRETTY_FUNCTION__) SetPhase(BUS::phase_t::msgin); @@ -386,9 +331,9 @@ void ScsiController::MsgIn() bus->SetIO(true); // length, blocks are already set - assert(ctrl.length > 0); + assert(HasValidLength()); assert(ctrl.blocks > 0); - ctrl.offset = 0; + ResetOffset(); return; } @@ -400,14 +345,14 @@ void ScsiController::MsgOut() { LOGTRACE("%s ID %d",__PRETTY_FUNCTION__, GetTargetId()) - if (ctrl.phase != BUS::phase_t::msgout) { + if (!IsMsgOut()) { LOGTRACE("Message Out Phase") // process the IDENTIFY message - if (ctrl.phase == BUS::phase_t::selection) { + if (IsSelection()) { scsi.atnmsg = true; scsi.msc = 0; - memset(scsi.msb.data(), 0x00, scsi.msb.size()); + scsi.msb = {}; } SetPhase(BUS::phase_t::msgout); @@ -417,7 +362,7 @@ void ScsiController::MsgOut() bus->SetIO(false); // Data transfer is 1 byte x 1 block - ctrl.offset = 0; + ResetOffset(); ctrl.length = 1; ctrl.blocks = 1; @@ -429,14 +374,14 @@ void ScsiController::MsgOut() void ScsiController::DataIn() { - if (ctrl.phase != BUS::phase_t::datain) { + if (!IsDataIn()) { // Minimum execution time if (execstart > 0) { Sleep(); } // If the length is 0, go to the status phase - if (ctrl.length == 0) { + if (!HasValidLength()) { Status(); return; } @@ -451,7 +396,7 @@ void ScsiController::DataIn() // length, blocks are already set assert(ctrl.blocks > 0); - ctrl.offset = 0; + ResetOffset(); return; } @@ -461,14 +406,14 @@ void ScsiController::DataIn() void ScsiController::DataOut() { - if (ctrl.phase != BUS::phase_t::dataout) { + if (!IsDataOut()) { // Minimum execution time if (execstart > 0) { Sleep(); } // If the length is 0, go to the status phase - if (ctrl.length == 0) { + if (!HasValidLength()) { Status(); return; } @@ -482,7 +427,7 @@ void ScsiController::DataOut() bus->SetCD(false); bus->SetIO(false); - ctrl.offset = 0; + ResetOffset(); return; } @@ -503,7 +448,7 @@ void ScsiController::Error(sense_key sense_key, asc asc, status status) } // Bus free for status phase and message in phase - if (ctrl.phase == BUS::phase_t::status || ctrl.phase == BUS::phase_t::msgin) { + if (IsStatus() || IsMsgIn()) { BusFree(); return; } @@ -520,7 +465,7 @@ void ScsiController::Error(sense_key sense_key, asc asc, status status) GetDeviceForLun(lun)->SetStatusCode(((int)sense_key << 16) | ((int)asc << 8)); } - ctrl.status = (uint32_t)status; + SetStatus((uint32_t)status); ctrl.message = 0x00; LOGTRACE("%s Error (to status phase)", __PRETTY_FUNCTION__) @@ -533,13 +478,13 @@ void ScsiController::Send() assert(!bus->GetREQ()); assert(bus->GetIO()); - if (ctrl.length != 0) { + if (HasValidLength()) { LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length " + to_string(ctrl.length)).c_str()) // TODO The delay has to be taken from ctrl.unit[lun], but as there are currently no Daynaport drivers for // LUNs other than 0 this work-around works. - if (int len = bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, + if (int len = bus->SendHandShake(GetBuffer().data() + ctrl.offset, ctrl.length, HasDeviceForLun(0) ? GetDeviceForLun(0)->GetSendDelay() : 0); len != (int)ctrl.length) { // If you cannot send all, move to status phase @@ -547,9 +492,8 @@ void ScsiController::Send() return; } - // offset and length - ctrl.offset += ctrl.length; - ctrl.length = 0; + UpdateOffsetAndLength(); + return; } @@ -558,9 +502,9 @@ void ScsiController::Send() bool result = true; // Processing after data collection (read/data-in only) - if (ctrl.phase == BUS::phase_t::datain && ctrl.blocks != 0) { + if (IsDataIn() && ctrl.blocks != 0) { // set next buffer (set offset, length) - result = XferIn(ctrl.buffer); + result = XferIn(GetBuffer()); LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Processing after data collection. Blocks: " + to_string(ctrl.blocks)).c_str()) } @@ -573,14 +517,14 @@ void ScsiController::Send() // Continue sending if block !=0 if (ctrl.blocks != 0){ LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Continuing to send. Blocks: " + to_string(ctrl.blocks)).c_str()) - assert(ctrl.length > 0); + assert(HasValidLength()); assert(ctrl.offset == 0); return; } // Move to next phase - LOGTRACE("%s Move to next phase %s (%d)", __PRETTY_FUNCTION__, BUS::GetPhaseStrRaw(ctrl.phase), (int)ctrl.phase) - switch (ctrl.phase) { + LOGTRACE("%s Move to next phase: %s", __PRETTY_FUNCTION__, BUS::GetPhaseStrRaw(GetPhase())) + switch (GetPhase()) { // Message in phase case BUS::phase_t::msgin: // Completed sending response to extended message of IDENTIFY message @@ -607,7 +551,7 @@ void ScsiController::Send() // Message in phase ctrl.length = 1; ctrl.blocks = 1; - ctrl.buffer[0] = (BYTE)ctrl.message; + GetBuffer()[0] = (BYTE)ctrl.message; MsgIn(); break; @@ -631,20 +575,19 @@ void ScsiController::Receive() assert(!bus->GetIO()); // Length != 0 if received - if (ctrl.length != 0) { + if (HasValidLength()) { LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, ctrl.length) // If not able to receive all, move to status phase - if (int len = bus->ReceiveHandShake(&ctrl.buffer[ctrl.offset], ctrl.length); + if (int len = bus->ReceiveHandShake(GetBuffer().data() + ctrl.offset, ctrl.length); len != (int)ctrl.length) { LOGERROR("%s Not able to receive %d bytes of data, only received %d",__PRETTY_FUNCTION__, ctrl.length, len) Error(sense_key::ABORTED_COMMAND); return; } - // Offset and Length - ctrl.offset += ctrl.length; - ctrl.length = 0; + UpdateOffsetAndLength(); + return; } @@ -653,8 +596,8 @@ void ScsiController::Receive() bool result = true; // Processing after receiving data (by phase) - LOGTRACE("%s ctrl.phase: %d (%s)",__PRETTY_FUNCTION__, (int)ctrl.phase, BUS::GetPhaseStrRaw(ctrl.phase)) - switch (ctrl.phase) { + LOGTRACE("%s Phase: %s",__PRETTY_FUNCTION__, BUS::GetPhaseStrRaw(GetPhase())) + switch (GetPhase()) { case BUS::phase_t::dataout: if (ctrl.blocks == 0) { // End with this buffer @@ -666,7 +609,7 @@ void ScsiController::Receive() break; case BUS::phase_t::msgout: - ctrl.message = ctrl.buffer[0]; + ctrl.message = GetBuffer()[0]; if (!XferMsg(ctrl.message)) { // Immediately free the bus if message output fails BusFree(); @@ -689,13 +632,13 @@ void ScsiController::Receive() // Continue to receive if block !=0 if (ctrl.blocks != 0) { - assert(ctrl.length > 0); + assert(HasValidLength()); assert(ctrl.offset == 0); return; } // Move to next phase - switch (ctrl.phase) { + switch (GetPhase()) { case BUS::phase_t::command: ProcessCommand(); break; @@ -718,7 +661,7 @@ void ScsiController::Receive() bool ScsiController::XferMsg(int msg) { - assert(ctrl.phase == BUS::phase_t::msgout); + assert(IsMsgOut()); // Save message out data if (scsi.atnmsg) { @@ -732,17 +675,14 @@ bool ScsiController::XferMsg(int msg) void ScsiController::ReceiveBytes() { - LOGTRACE("%s",__PRETTY_FUNCTION__) - - // REQ is low assert(!bus->GetREQ()); assert(!bus->GetIO()); - if (ctrl.length) { + if (HasValidLength()) { LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, ctrl.length) // If not able to receive all, move to status phase - if (uint32_t len = bus->ReceiveHandShake(&ctrl.buffer[ctrl.offset], ctrl.length); + if (uint32_t len = bus->ReceiveHandShake(GetBuffer().data() + ctrl.offset, ctrl.length); len != ctrl.length) { LOGERROR("%s Not able to receive %d bytes of data, only received %d", __PRETTY_FUNCTION__, ctrl.length, len) @@ -752,8 +692,7 @@ void ScsiController::ReceiveBytes() bytes_to_transfer = ctrl.length; - ctrl.offset += ctrl.length; - ctrl.length = 0; + UpdateOffsetAndLength(); return; } @@ -762,15 +701,14 @@ void ScsiController::ReceiveBytes() bool result = true; // Processing after receiving data (by phase) - LOGTRACE("%s ctrl.phase: %d (%s)",__PRETTY_FUNCTION__, (int)ctrl.phase, BUS::GetPhaseStrRaw(ctrl.phase)) - switch (ctrl.phase) { - + LOGTRACE("%s Phase: %s",__PRETTY_FUNCTION__, BUS::GetPhaseStrRaw(GetPhase())) + switch (GetPhase()) { case BUS::phase_t::dataout: result = XferOut(false); break; case BUS::phase_t::msgout: - ctrl.message = ctrl.buffer[0]; + ctrl.message = GetBuffer()[0]; if (!XferMsg(ctrl.message)) { // Immediately free the bus if message output fails BusFree(); @@ -792,7 +730,7 @@ void ScsiController::ReceiveBytes() } // Move to next phase - switch (ctrl.phase) { + switch (GetPhase()) { case BUS::phase_t::command: ProcessCommand(); break; @@ -813,7 +751,7 @@ void ScsiController::ReceiveBytes() bool ScsiController::XferOut(bool cont) { - assert(ctrl.phase == BUS::phase_t::dataout); + assert(IsDataOut()); if (!is_byte_transfer) { return XferOutBlockOriented(cont); @@ -823,17 +761,17 @@ bool ScsiController::XferOut(bool cont) if (auto device = GetDeviceForLun(GetEffectiveLun()); device != nullptr && GetOpcode() == scsi_command::eCmdWrite6) { - return device->WriteByteSequence(ctrl.buffer, bytes_to_transfer); + return device->WriteByteSequence(GetBuffer(), bytes_to_transfer); } - LOGWARN("Received an unexpected command ($%02X) in %s", (int)GetOpcode(), __PRETTY_FUNCTION__) + LOGWARN("%s Received unexpected command $%02X", __PRETTY_FUNCTION__, (int)GetOpcode()) return false; } void ScsiController::FlushUnit() { - assert(ctrl.phase == BUS::phase_t::dataout); + assert(IsDataOut()); auto disk = dynamic_cast(GetDeviceForLun(GetEffectiveLun())); if (disk == nullptr) { @@ -857,7 +795,7 @@ void ScsiController::FlushUnit() // Without it we would not need this method at all. // ModeSelect is already handled in XferOutBlockOriented(). Why would it have to be handled once more? try { - disk->ModeSelect(ctrl.cmd, ctrl.buffer, ctrl.offset); + disk->ModeSelect(ctrl.cmd, GetBuffer(), ctrl.offset); } catch(const scsi_error_exception& e) { LOGWARN("Error occured while processing Mode Select command %02X\n", (int)GetOpcode()) @@ -882,9 +820,9 @@ void ScsiController::FlushUnit() // *Reset offset and length // //--------------------------------------------------------------------------- -bool ScsiController::XferIn(BYTE *buf) +bool ScsiController::XferIn(vector& buf) { - assert(ctrl.phase == BUS::phase_t::datain); + assert(IsDataIn()); LOGTRACE("%s command=%02X", __PRETTY_FUNCTION__, (int)GetOpcode()) @@ -910,7 +848,7 @@ bool ScsiController::XferIn(BYTE *buf) ctrl.next++; // If things are normal, work setting - ctrl.offset = 0; + ResetOffset(); break; // Other (impossible) @@ -940,7 +878,7 @@ bool ScsiController::XferOutBlockOriented(bool cont) case scsi_command::eCmdModeSelect6: case scsi_command::eCmdModeSelect10: try { - disk->ModeSelect(ctrl.cmd, ctrl.buffer, ctrl.offset); + disk->ModeSelect(ctrl.cmd, GetBuffer(), ctrl.offset); } catch(const scsi_error_exception& e) { Error(e.get_sense_key(), e.get_asc(), e.get_status()); @@ -958,27 +896,27 @@ bool ScsiController::XferOutBlockOriented(bool cont) // Special case Write function for brige // TODO This class must not know about SCSIBR if (auto bridge = dynamic_cast(disk); bridge) { - if (!bridge->WriteBytes(ctrl.cmd, ctrl.buffer, ctrl.length)) { + if (!bridge->WriteBytes(ctrl.cmd, GetBuffer(), ctrl.length)) { // Write failed return false; } - ctrl.offset = 0; + ResetOffset(); break; } // Special case Write function for DaynaPort // TODO This class must not know about DaynaPort if (auto daynaport = dynamic_cast(disk); daynaport) { - daynaport->WriteBytes(ctrl.cmd, ctrl.buffer, 0); + daynaport->WriteBytes(ctrl.cmd, GetBuffer(), 0); - ctrl.offset = 0; + ResetOffset(); ctrl.blocks = 0; break; } try { - disk->Write(ctrl.cmd, ctrl.buffer, ctrl.next - 1); + disk->Write(ctrl.cmd, GetBuffer(), ctrl.next - 1); } catch(const scsi_error_exception& e) { Error(e.get_sense_key(), e.get_asc(), e.get_status()); @@ -1002,7 +940,7 @@ bool ScsiController::XferOutBlockOriented(bool cont) return false; } - ctrl.offset = 0; + ResetOffset(); break; } @@ -1020,93 +958,94 @@ bool ScsiController::XferOutBlockOriented(bool cont) void ScsiController::ProcessCommand() { - uint32_t len = GPIOBUS::GetCommandByteCount(ctrl.buffer[0]); + uint32_t len = GPIOBUS::GetCommandByteCount(GetBuffer()[0]); + stringstream s; for (uint32_t i = 0; i < len; i++) { - ctrl.cmd[i] = ctrl.buffer[i]; - LOGTRACE("%s Command Byte %d: $%02X",__PRETTY_FUNCTION__, i, ctrl.cmd[i]) + ctrl.cmd[i] = GetBuffer()[i]; + s << setfill('0') << setw(2) << hex << ctrl.cmd[i]; } + LOGTRACE("%s CDB=$%s",__PRETTY_FUNCTION__, s.str().c_str()) Execute(); } +void ScsiController::ParseMessage() +{ + int i = 0; + while (i < scsi.msc) { + BYTE message_type = scsi.msb[i]; + + if (message_type == 0x06) { + LOGTRACE("Received ABORT message") + BusFree(); + return; + } + + if (message_type == 0x0C) { + LOGTRACE("Received BUS DEVICE RESET message") + scsi.syncoffset = 0; + BusFree(); + return; + } + + if (message_type >= 0x80) { + identified_lun = (int)message_type & 0x1F; + LOGTRACE("Received IDENTIFY message for LUN %d", identified_lun) + } + + if (message_type == 0x01) { + LOGTRACE("Received EXTENDED MESSAGE") + + // Check only when synchronous transfer is possible + if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) { + ctrl.length = 1; + ctrl.blocks = 1; + GetBuffer()[0] = 0x07; + MsgIn(); + return; + } + + scsi.syncperiod = scsi.msb[i + 3]; + if (scsi.syncperiod > MAX_SYNC_PERIOD) { + scsi.syncperiod = MAX_SYNC_PERIOD; + } + + scsi.syncoffset = scsi.msb[i + 4]; + if (scsi.syncoffset > MAX_SYNC_OFFSET) { + scsi.syncoffset = MAX_SYNC_OFFSET; + } + + // STDR response message generation + ctrl.length = 5; + ctrl.blocks = 1; + GetBuffer()[0] = 0x01; + GetBuffer()[1] = 0x03; + GetBuffer()[2] = 0x01; + GetBuffer()[3] = scsi.syncperiod; + GetBuffer()[4] = scsi.syncoffset; + MsgIn(); + return; + } + + // Next message + i++; + } +} + void ScsiController::ProcessMessage() { // Continue message out phase as long as ATN keeps asserting if (bus->GetATN()) { // Data transfer is 1 byte x 1 block - ctrl.offset = 0; + ResetOffset(); ctrl.length = 1; ctrl.blocks = 1; return; } - // Parsing messages sent by ATN if (scsi.atnmsg) { - int i = 0; - while (i < scsi.msc) { - // Message type - BYTE data = scsi.msb[i]; - - // ABORT - if (data == 0x06) { - LOGTRACE("Message code ABORT $%02X", data) - BusFree(); - return; - } - - // BUS DEVICE RESET - if (data == 0x0C) { - LOGTRACE("Message code BUS DEVICE RESET $%02X", data) - scsi.syncoffset = 0; - BusFree(); - return; - } - - // IDENTIFY - if (data >= 0x80) { - identified_lun = (int)data & 0x1F; - LOGTRACE("Message code IDENTIFY $%02X, LUN %d selected", data, identified_lun) - } - - // Extended Message - if (data == 0x01) { - LOGTRACE("Message code EXTENDED MESSAGE $%02X", data) - - // Check only when synchronous transfer is possible - if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) { - ctrl.length = 1; - ctrl.blocks = 1; - ctrl.buffer[0] = 0x07; - MsgIn(); - return; - } - - scsi.syncperiod = scsi.msb[i + 3]; - if (scsi.syncperiod > MAX_SYNC_PERIOD) { - scsi.syncperiod = MAX_SYNC_PERIOD; - } - - scsi.syncoffset = scsi.msb[i + 4]; - if (scsi.syncoffset > MAX_SYNC_OFFSET) { - scsi.syncoffset = MAX_SYNC_OFFSET; - } - - // STDR response message generation - ctrl.length = 5; - ctrl.blocks = 1; - ctrl.buffer[0] = 0x01; - ctrl.buffer[1] = 0x03; - ctrl.buffer[2] = 0x01; - ctrl.buffer[3] = scsi.syncperiod; - ctrl.buffer[4] = scsi.syncoffset; - MsgIn(); - return; - } - - // next - i++; - } + ParseMessage(); } // Initialize ATN message reception status diff --git a/src/raspberrypi/controllers/scsi_controller.h b/src/raspberrypi/controllers/scsi_controller.h index f2fc5ef2..47cf3d22 100644 --- a/src/raspberrypi/controllers/scsi_controller.h +++ b/src/raspberrypi/controllers/scsi_controller.h @@ -10,8 +10,6 @@ // Licensed under the BSD 3-Clause License. // See LICENSE file in the project root folder. // -// [ SCSI device controller ] -// //--------------------------------------------------------------------------- #pragma once @@ -53,8 +51,11 @@ class ScsiController : public AbstractController public: + // Maximum number of logical units + static const int LUN_MAX = 32; + ScsiController(shared_ptr, int); - ~ScsiController () override; + ~ScsiController() override = default; ScsiController(ScsiController&) = delete; ScsiController& operator=(const ScsiController&) = delete; @@ -64,8 +65,6 @@ public: int GetEffectiveLun() const override; - int GetMaxLuns() const override { return LUN_MAX; } - void Error(scsi_defs::sense_key sense_key, scsi_defs::asc asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION, scsi_defs::status status = scsi_defs::status::CHECK_CONDITION) override; @@ -91,7 +90,6 @@ private: uint32_t bytes_to_transfer = 0; // Phases - void SetPhase(BUS::phase_t p) override { ctrl.phase = p; } void BusFree() override; void Selection() override; void Command() override; @@ -101,7 +99,7 @@ private: // Data transfer void Send(); bool XferMsg(int); - bool XferIn(BYTE* buf); + bool XferIn(vector&); bool XferOut(bool); bool XferOutBlockOriented(bool); void ReceiveBytes(); @@ -111,6 +109,7 @@ private: void Receive(); void ProcessCommand(); + void ParseMessage(); void ProcessMessage(); void ScheduleShutdown(rascsi_shutdown_mode mode) override { shutdown_mode = mode; } diff --git a/src/raspberrypi/devices/cfilesystem.cpp b/src/raspberrypi/devices/cfilesystem.cpp index 50b8471d..d60215d1 100644 --- a/src/raspberrypi/devices/cfilesystem.cpp +++ b/src/raspberrypi/devices/cfilesystem.cpp @@ -796,9 +796,6 @@ BYTE* CHostFilename::CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLas //--------------------------------------------------------------------------- void CHostFilename::ConvertHuman(int nCount) { - char szHost[FILEPATH_MAX]; - - // Don't do conversion for special directory names if (m_szHost[0] == '.' && (m_szHost[1] == '\0' || (m_szHost[1] == '.' && m_szHost[2] == '\0'))) { @@ -844,6 +841,7 @@ void CHostFilename::ConvertHuman(int nCount) BYTE* pExt = nullptr; { + char szHost[FILEPATH_MAX]; strcpy(szHost, m_szHost); auto pRead = (const BYTE*)szHost; BYTE* pWrite = szHuman; @@ -1558,8 +1556,7 @@ void CHostPath::Refresh() // If no match, confirm existence of real file strcpy(szPath, m_szHost); strcat(szPath, (const char*)pFilename->GetHuman()); - struct stat sb; - if (stat(S2U(szPath), &sb)) + if (struct stat sb; stat(S2U(szPath), &sb)) break; // Discover available patterns } } @@ -1575,7 +1572,7 @@ void CHostPath::Refresh() strcpy(szPath, m_szHost); strcat(szPath, U2S(pe->d_name)); - struct stat sb; //NOSONAR Cannot be declared in a separate statement because struct keyword is required + struct stat sb; if (stat(S2U(szPath), &sb)) continue; @@ -1654,8 +1651,7 @@ void CHostPath::Backup() len--; assert(szPath[len] == '/'); szPath[len] = '\0'; - struct stat sb; //NOSONAR Cannot be declared in a separate statement because struct keyword is required - if (stat(S2U(szPath), &sb) == 0) + if (struct stat sb; stat(S2U(szPath), &sb) == 0) m_tBackup = sb.st_mtime; } } @@ -2291,8 +2287,7 @@ bool CHostFcb::Create(DWORD, bool bForce) // Duplication check if (!bForce) { - struct stat sb; //NOSONAR Cannot be declared in a separate statement because struct keyword is required - if (stat(S2U(m_szFilename), &sb) == 0) + if (struct stat sb; stat(S2U(m_szFilename), &sb) == 0) return false; } @@ -2917,7 +2912,7 @@ int CFileSys::Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD // Generate attribute if (DWORD nAttribute = (nHumanAttribute & Human68k::AT_READONLY) | (f.GetAttribute() & ~Human68k::AT_READONLY); f.GetAttribute() != nAttribute) { - struct stat sb; //NOSONAR Cannot be declared in a separate statement because struct keyword is required + struct stat sb; if (stat(S2U(f.GetPath()), &sb)) return FS_FILENOTFND; mode_t m = sb.st_mode & 0777; diff --git a/src/raspberrypi/devices/ctapdriver.cpp b/src/raspberrypi/devices/ctapdriver.cpp index 5447dca4..a36a5b36 100644 --- a/src/raspberrypi/devices/ctapdriver.cpp +++ b/src/raspberrypi/devices/ctapdriver.cpp @@ -62,7 +62,7 @@ CTapDriver::~CTapDriver() LOGERROR("Can't open bridge socket: %s", strerror(errno)) } else { LOGDEBUG("brctl delif %s ras0", BRIDGE_NAME) - if (!br_setif(br_socket_fd, BRIDGE_NAME, "ras0", false)) { + if (!br_setif(br_socket_fd, BRIDGE_NAME, "ras0", false)) { //NOSONAR No exception is raised here LOGWARN("Warning: Removing ras0 from the bridge failed.") LOGWARN("You may need to manually remove the ras0 tap device from the bridge") } @@ -160,8 +160,7 @@ bool CTapDriver::Init(const unordered_map& const_params) LOGTRACE("Opened tap device %d", m_hTAP) // IFF_NO_PI for no extra packet information - ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); + ifreq ifr = {}; ifr.ifr_flags = IFF_TAP | IFF_NO_PI; string dev = "ras0"; strncpy(ifr.ifr_name, dev.c_str(), IFNAMSIZ - 1); @@ -262,10 +261,9 @@ bool CTapDriver::Init(const unordered_map& const_params) // long long is required for compatibility with 32 bit platforms auto mask = (long long)(pow(2, 32) - (1 << (32 - m))); - char buf[16]; - sprintf(buf, "%lld.%lld.%lld.%lld", (mask >> 24) & 0xff, (mask >> 16) & 0xff, (mask >> 8) & 0xff, - mask & 0xff); - netmask = buf; + netmask = to_string((mask >> 24) & 0xff) + '.' + to_string((mask >> 16) & 0xff) + '.' + + to_string((mask >> 8) & 0xff) + '.' + to_string(mask & 0xff); + } LOGTRACE("brctl addbr %s", BRIDGE_NAME) diff --git a/src/raspberrypi/devices/device_factory.cpp b/src/raspberrypi/devices/device_factory.cpp index 58c90251..58268389 100644 --- a/src/raspberrypi/devices/device_factory.cpp +++ b/src/raspberrypi/devices/device_factory.cpp @@ -34,15 +34,6 @@ DeviceFactory::DeviceFactory() sector_sizes[SCMO] = { 512, 1024, 2048, 4096 }; sector_sizes[SCCD] = { 512, 2048}; - // 128 MB, 512 bytes per sector, 248826 sectors - geometries[SCMO][0x797f400] = make_pair(512, 248826); - // 230 MB, 512 bytes per block, 446325 sectors - geometries[SCMO][0xd9eea00] = make_pair(512, 446325); - // 540 MB, 512 bytes per sector, 1041500 sectors - geometries[SCMO][0x1fc8b800] = make_pair(512, 1041500); - // 640 MB, 20248 bytes per sector, 310352 sectors - geometries[SCMO][0x25e28000] = make_pair(2048, 310352); - string network_interfaces; for (const auto& network_interface : GetNetworkInterfaces()) { if (!network_interfaces.empty()) { @@ -180,7 +171,7 @@ PrimaryDevice *DeviceFactory::CreateDevice(PbDeviceType type, const string& file break; case SCMO: - device = make_unique(sector_sizes[SCMO], geometries[SCMO]); + device = make_unique(sector_sizes[SCMO]); device->SetProtectable(true); device->SetStoppable(true); device->SetRemovable(true); @@ -232,17 +223,17 @@ PrimaryDevice *DeviceFactory::CreateDevice(PbDeviceType type, const string& file break; } - assert(device != nullptr); + if (device != nullptr) { + PrimaryDevice *d = device.release(); - PrimaryDevice *d = device.release(); - - if (d != nullptr) { d->SetId(id); devices.emplace(id, d); + + return d; } - return d; + return nullptr; } const unordered_set& DeviceFactory::GetSectorSizes(PbDeviceType type) const diff --git a/src/raspberrypi/devices/device_factory.h b/src/raspberrypi/devices/device_factory.h index 1a2fd368..61fe34b0 100644 --- a/src/raspberrypi/devices/device_factory.h +++ b/src/raspberrypi/devices/device_factory.h @@ -21,8 +21,6 @@ using namespace std; //NOSONAR Not relevant for rascsi using namespace rascsi_interface; //NOSONAR Not relevant for rascsi -using Geometry = pair; - class PrimaryDevice; class DeviceFactory @@ -50,9 +48,6 @@ private: unordered_map> sector_sizes; - // Optional mapping of drive capacities to drive geometries - unordered_map> geometries; - unordered_map> default_params; unordered_map extension_mapping; diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index 39a070b4..aa8200e4 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -60,20 +60,18 @@ Disk::Disk(const string& id) : ModePageDevice(id) Disk::~Disk() { // Save disk cache, only if ready - if (IsReady() && disk.dcache) { - disk.dcache->Save(); + if (IsReady() && cache != nullptr) { + cache->Save(); } - - delete disk.dcache; } bool Disk::Dispatch(scsi_command cmd) { // Media changes must be reported on the next access, i.e. not only for TEST UNIT READY - if (disk.is_medium_changed) { + if (is_medium_changed) { assert(IsRemovable()); - disk.is_medium_changed = false; + is_medium_changed = false; throw scsi_error_exception(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); } @@ -90,14 +88,10 @@ bool Disk::Dispatch(scsi_command cmd) //--------------------------------------------------------------------------- void Disk::Open(const Filepath& path) { - assert(disk.blocks > 0); + assert(blocks > 0); SetReady(true); - // Cache initialization - assert (!disk.dcache); - disk.dcache = new DiskCache(path, disk.size, (uint32_t)disk.blocks, disk.image_offset); - // Can read/write open if (Fileio fio; fio.Open(path, Fileio::OpenMode::ReadWrite)) { // Write permission @@ -114,10 +108,16 @@ void Disk::Open(const Filepath& path) SetLocked(false); } +void Disk::SetUpCache(const Filepath& path, off_t image_offset) +{ + assert(cache == nullptr); + cache = make_unique(path, size_shift_count, (uint32_t)blocks, image_offset); +} + void Disk::FlushCache() { - if (disk.dcache) { - disk.dcache->Save(); + if (cache != nullptr) { + cache->Save(); } } @@ -146,8 +146,8 @@ void Disk::ReassignBlocks() void Disk::Read(access_mode mode) { if (uint64_t start; CheckAndGetStartAndCount(start, ctrl->blocks, mode)) { - ctrl->length = Read(ctrl->cmd, ctrl->buffer, start); - LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, ctrl->length) + ctrl->length = Read(ctrl->cmd, controller->GetBuffer(), start); + LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, controller->GetLength()) // Set next block ctrl->next = start + 1; @@ -177,7 +177,7 @@ void Disk::Read16() void Disk::ReadWriteLong10() { // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard - if (ctrl->cmd[7] || ctrl->cmd[8]) { + if (GetInt16(ctrl->cmd, 7) != 0) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } @@ -189,7 +189,7 @@ void Disk::ReadWriteLong10() void Disk::ReadWriteLong16() { // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard - if (ctrl->cmd[12] || ctrl->cmd[13]) { + if (GetInt16(ctrl->cmd, 12) != 0) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } @@ -238,7 +238,7 @@ void Disk::Verify(access_mode mode) } // Test reading - ctrl->length = Read(ctrl->cmd, ctrl->buffer, start); + ctrl->length = Read(ctrl->cmd, controller->GetBuffer(), start); // Set next block ctrl->next = start + 1; @@ -331,24 +331,22 @@ void Disk::SynchronizeCache() void Disk::ReadDefectData10() { - int allocation_length = GetInt16(ctrl->cmd, 7); - if (allocation_length > 4) { - allocation_length = 4; - } + size_t allocation_length = min((size_t)GetInt16(ctrl->cmd, 7), (size_t)4); // The defect list is empty - memset(ctrl->buffer, 0, allocation_length); - ctrl->length = allocation_length; + fill_n(controller->GetBuffer().begin(), allocation_length, 0); + ctrl->length = (int)allocation_length; EnterDataInPhase(); } void Disk::MediumChanged() { - assert(IsRemovable()); - if (IsRemovable()) { - disk.is_medium_changed = true; + is_medium_changed = true; + } + else { + LOGWARN("%s Medium change requested for non-reomvable medium", __PRETTY_FUNCTION__) } } @@ -357,11 +355,9 @@ bool Disk::Eject(bool force) bool status = super::Eject(force); if (status) { FlushCache(); - delete disk.dcache; - disk.dcache = nullptr; + cache.reset(); // The image file for this drive is not in use anymore - // TODO This cast and the FileSupport class can be removed as soon as only disk-like devices inherit from Disk if (auto file_support = dynamic_cast(this); file_support) { file_support->UnreserveFile(); } @@ -370,14 +366,11 @@ bool Disk::Eject(bool force) return status; } -int Disk::ModeSense6(const vector& cdb, BYTE *buf, int max_length) const +int Disk::ModeSense6(const vector& cdb, vector& buf, int max_length) const { // Get length, clear buffer - auto length = cdb[4]; - if (length > max_length) { - length = max_length; - } - memset(buf, 0, length); + auto length = (int)min((size_t)max_length, (size_t)cdb[4]); + fill_n(buf.begin(), length, 0); // DEVICE SPECIFIC PARAMETER if (IsProtected()) { @@ -385,7 +378,7 @@ int Disk::ModeSense6(const vector& cdb, BYTE *buf, int max_length) const } // Basic information - int size = 4; + int info_size = 4; // Add block descriptor if DBD is 0 if ((cdb[1] & 0x08) == 0) { @@ -395,37 +388,34 @@ int Disk::ModeSense6(const vector& cdb, BYTE *buf, int max_length) const // Only if ready if (IsReady()) { // Short LBA mode parameter block descriptor (number of blocks and block length) - SetInt32(&buf[4], (uint32_t)GetBlockCount()); - SetInt32(&buf[8], GetSectorSizeInBytes()); + SetInt32(buf, 4, (uint32_t)GetBlockCount()); + SetInt32(buf, 8, GetSectorSizeInBytes()); } - size = 12; + info_size = 12; } - size += super::AddModePages(cdb, &buf[size], length - size); - if (size > 255) { + info_size += super::AddModePages(cdb, buf, info_size, length - info_size); + if (info_size > 255) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Do not return more than ALLOCATION LENGTH bytes - if (size > length) { - size = length; + if (info_size > length) { + info_size = length; } // Final setting of mode data length - buf[0] = (BYTE)size; + buf[0] = (BYTE)info_size; - return size; + return info_size; } -int Disk::ModeSense10(const vector& cdb, BYTE *buf, int max_length) const +int Disk::ModeSense10(const vector& cdb, vector& buf, int max_length) const { // Get length, clear buffer - int length = GetInt16(cdb, 7); - if (length > max_length) { - length = max_length; - } - memset(buf, 0, length); + auto length = (int)min((size_t)max_length, (size_t)GetInt16(cdb, 7)); + fill_n(buf.begin(), length, 0); // DEVICE SPECIFIC PARAMETER if (IsProtected()) { @@ -433,7 +423,7 @@ int Disk::ModeSense10(const vector& cdb, BYTE *buf, int max_length) const } // Basic Information - int size = 8; + int info_size = 8; // Add block descriptor if DBD is 0, only if ready if ((cdb[1] & 0x08) == 0 && IsReady()) { @@ -446,10 +436,10 @@ int Disk::ModeSense10(const vector& cdb, BYTE *buf, int max_length) const buf[7] = 0x08; // Short LBA mode parameter block descriptor (number of blocks and block length) - SetInt32(&buf[8], (uint32_t)disk_blocks); - SetInt32(&buf[12], disk_size); + SetInt32(buf, 8, (uint32_t)disk_blocks); + SetInt32(buf, 12, disk_size); - size = 16; + info_size = 16; } else { // Mode parameter header, LONGLBA @@ -459,27 +449,27 @@ int Disk::ModeSense10(const vector& cdb, BYTE *buf, int max_length) const buf[7] = 0x10; // Long LBA mode parameter block descriptor (number of blocks and block length) - SetInt64(&buf[8], disk_blocks); - SetInt32(&buf[20], disk_size); + SetInt64(buf, 8, disk_blocks); + SetInt32(buf, 20, disk_size); - size = 24; + info_size = 24; } } - size += super::AddModePages(cdb, &buf[size], length - size); - if (size > 65535) { + info_size += super::AddModePages(cdb, buf, info_size, length - info_size); + if (info_size > 65535) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Do not return more than ALLOCATION LENGTH bytes - if (size > length) { - size = length; + if (info_size > length) { + info_size = length; } // Final setting of mode data length - SetInt16(buf, size); + SetInt16(buf, 0, info_size); - return size; + return info_size; } void Disk::SetUpModePages(map>& pages, int page, bool changeable) const @@ -536,7 +526,7 @@ void Disk::AddFormatPage(map>& pages, bool changeable) const SetInt16(buf, 0x0a, 25); // Set the number of bytes in the physical sector - SetInt16(buf, 0x0c, 1 << disk.size); + SetInt16(buf, 0x0c, 1 << size_shift_count); // Interleave 1 SetInt16(buf, 0x0e, 1); @@ -570,7 +560,7 @@ void Disk::AddDrivePage(map>& pages, bool changeable) const if (IsReady()) { // Set the number of cylinders (total number of blocks // divided by 25 sectors/track and 8 heads) - uint64_t cylinders = disk.blocks; + uint64_t cylinders = blocks; cylinders >>= 3; cylinders /= 25; SetInt32(buf, 0x01, (uint32_t)cylinders); @@ -616,24 +606,24 @@ void Disk::AddVendorPage(map>&, int, bool) const } // TODO Read more than one block in a single call. Currently blocked by the the track-oriented cache -int Disk::Read(const vector&, BYTE *buf, uint64_t block) +int Disk::Read(const vector&, vector& buf, uint64_t block) { LOGTRACE("%s", __PRETTY_FUNCTION__) CheckReady(); // Error if the total number of blocks is exceeded - if (block >= disk.blocks) { + if (block >= blocks) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // leave it to the cache - if (!disk.dcache->ReadSector(buf, (uint32_t)block)) { + if (!cache->ReadSector(buf, (uint32_t)block)) { throw scsi_error_exception(sense_key::MEDIUM_ERROR, asc::READ_FAULT); } // Success - return 1 << disk.size; + return 1 << size_shift_count; } int Disk::WriteCheck(uint64_t block) @@ -641,7 +631,7 @@ int Disk::WriteCheck(uint64_t block) CheckReady(); // Error if the total number of blocks is exceeded - if (block >= disk.blocks) { + if (block >= blocks) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } @@ -651,11 +641,11 @@ int Disk::WriteCheck(uint64_t block) } // Success - return 1 << disk.size; + return 1 << size_shift_count; } // TODO Write more than one block in a single call. Currently blocked by the track-oriented cache -void Disk::Write(const vector&, const BYTE *buf, uint64_t block) +void Disk::Write(const vector&, const vector& buf, uint64_t block) { LOGTRACE("%s", __PRETTY_FUNCTION__) @@ -665,7 +655,7 @@ void Disk::Write(const vector&, const BYTE *buf, uint64_t block) } // Error if the total number of blocks is exceeded - if (block >= disk.blocks) { + if (block >= blocks) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); } @@ -675,7 +665,7 @@ void Disk::Write(const vector&, const BYTE *buf, uint64_t block) } // Leave it to the cache - if (!disk.dcache->WriteSector(buf, (uint32_t)block)) { + if (!cache->WriteSector(buf, (uint32_t)block)) { throw scsi_error_exception(sense_key::MEDIUM_ERROR, asc::WRITE_FAULT); } } @@ -709,23 +699,23 @@ void Disk::ReadCapacity10() { CheckReady(); - if (disk.blocks == 0) { + if (blocks == 0) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); } - BYTE *buf = ctrl->buffer; + vector& buf = controller->GetBuffer(); - // Create end of logical block address (disk.blocks-1) - uint64_t blocks = disk.blocks - 1; + // Create end of logical block address (blocks-1) + uint64_t capacity = blocks - 1; // If the capacity exceeds 32 bit, -1 must be returned and the client has to use READ CAPACITY(16) - if (blocks > 4294967295) { - blocks = -1; + if (capacity > 4294967295) { + capacity = -1; } - SetInt32(&buf[0], (uint32_t)blocks); + SetInt32(buf, 0, (uint32_t)capacity); - // Create block length (1 << disk.size) - SetInt32(&buf[4], 1 << disk.size); + // Create block length (1 << size) + SetInt32(buf, 4, 1 << size_shift_count); // the size ctrl->length = 8; @@ -737,17 +727,17 @@ void Disk::ReadCapacity16() { CheckReady(); - if (disk.blocks == 0) { + if (blocks == 0) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); } - BYTE *buf = ctrl->buffer; + vector& buf = controller->GetBuffer(); - // Create end of logical block address (disk.blocks-1) - SetInt64(&buf[0], disk.blocks - 1); + // Create end of logical block address (blocks-1) + SetInt64(buf, 0, blocks - 1); - // Create block length (1 << disk.size) - SetInt32(&buf[8], 1 << disk.size); + // Create block length (1 << size) + SetInt32(buf, 8, 1 << size_shift_count); buf[12] = 0; @@ -820,11 +810,7 @@ void Disk::ValidateBlockAddress(access_mode mode) const bool Disk::CheckAndGetStartAndCount(uint64_t& start, uint32_t& count, access_mode mode) const { if (mode == RW6 || mode == SEEK6) { - start = ctrl->cmd[1] & 0x1f; - start <<= 8; - start |= ctrl->cmd[2]; - start <<= 8; - start |= ctrl->cmd[3]; + start = GetInt24(ctrl->cmd, 1); count = ctrl->cmd[4]; if (!count) { @@ -864,7 +850,7 @@ bool Disk::CheckAndGetStartAndCount(uint64_t& start, uint32_t& count, access_mod uint32_t Disk::GetSectorSizeInBytes() const { - return disk.size ? 1 << disk.size : 0; + return size_shift_count ? 1 << size_shift_count : 0; } void Disk::SetSectorSizeInBytes(uint32_t size_in_bytes) @@ -877,19 +863,19 @@ void Disk::SetSectorSizeInBytes(uint32_t size_in_bytes) switch (size_in_bytes) { case 512: - disk.size = 9; + size_shift_count = 9; break; case 1024: - disk.size = 10; + size_shift_count = 10; break; case 2048: - disk.size = 11; + size_shift_count = 11; break; case 4096: - disk.size = 12; + size_shift_count = 12; break; default: @@ -898,49 +884,19 @@ void Disk::SetSectorSizeInBytes(uint32_t size_in_bytes) } } -uint32_t Disk::GetSectorSizeShiftCount() const -{ - return disk.size; -} - -void Disk::SetSectorSizeShiftCount(uint32_t shift_count) -{ - disk.size = shift_count; -} - -bool Disk::IsSectorSizeConfigurable() const -{ - return !sector_sizes.empty(); -} - -void Disk::SetSectorSizes(const unordered_set& sizes) -{ - sector_sizes = sizes; -} - uint32_t Disk::GetConfiguredSectorSize() const { return configured_sector_size; } -bool Disk::SetConfiguredSectorSize(const DeviceFactory& device_factory, uint32_t size) +bool Disk::SetConfiguredSectorSize(const DeviceFactory& device_factory, uint32_t configured_size) { if (unordered_set sizes = device_factory.GetSectorSizes(GetType()); - sizes.find(size) == sizes.end()) { + sizes.find(configured_size) == sizes.end()) { return false; } - configured_sector_size = size; + configured_sector_size = configured_size; return true; } - -uint64_t Disk::GetBlockCount() const -{ - return disk.blocks; -} - -void Disk::SetBlockCount(uint64_t blocks) -{ - disk.blocks = blocks; -} diff --git a/src/raspberrypi/devices/disk.h b/src/raspberrypi/devices/disk.h index e112bdbe..18873c1d 100644 --- a/src/raspberrypi/devices/disk.h +++ b/src/raspberrypi/devices/disk.h @@ -29,19 +29,19 @@ class Disk : public ModePageDevice, public ScsiBlockCommands { enum access_mode { RW6, RW10, RW16, SEEK6, SEEK10 }; - // The supported configurable block sizes, empty if not configurable + Dispatcher dispatcher; + + // The supported configurable sector sizes, empty if not configurable unordered_set sector_sizes; uint32_t configured_sector_size = 0; - using disk_t = struct { - uint32_t size; // Sector Size (9=512, 10=1024, 11=2048, 12=4096) - uint64_t blocks; // Total number of sectors - DiskCache *dcache; // Disk cache - off_t image_offset; // Offset to actual data - bool is_medium_changed; - }; + // Sector size shift count (9=512, 10=1024, 11=2048, 12=4096) + uint32_t size_shift_count = 0; - Dispatcher dispatcher; + // Total number of sectors + uint64_t blocks = 0; + + bool is_medium_changed = false; public: @@ -57,14 +57,14 @@ public: // Command helpers virtual int WriteCheck(uint64_t); - virtual void Write(const vector&, const BYTE *, uint64_t); + virtual void Write(const vector&, const vector&, uint64_t); - virtual int Read(const vector&, BYTE *, uint64_t); + virtual int Read(const vector&, vector& , uint64_t); uint32_t GetSectorSizeInBytes() const; - bool IsSectorSizeConfigurable() const; + bool IsSectorSizeConfigurable() const { return !sector_sizes.empty(); } bool SetConfiguredSectorSize(const DeviceFactory&, uint32_t); - uint64_t GetBlockCount() const; + uint64_t GetBlockCount() const { return blocks; } void FlushCache() override; private: @@ -105,12 +105,13 @@ private: void ValidateBlockAddress(access_mode) const; bool CheckAndGetStartAndCount(uint64_t&, uint32_t&, access_mode) const; - int ModeSense6(const vector&, BYTE *, int) const override; - int ModeSense10(const vector&, BYTE *, int) const override; + int ModeSense6(const vector&, vector&, int) const override; + int ModeSense10(const vector&, vector&, int) const override; protected: virtual void Open(const Filepath&); + void SetUpCache(const Filepath&, off_t = 0); void SetUpModePages(map>&, int, bool) const override; virtual void AddErrorPage(map>&, bool) const; @@ -119,13 +120,12 @@ protected: void AddCachePage(map>&, bool) const; virtual void AddVendorPage(map>&, int, bool) const; unordered_set GetSectorSizes() const; - void SetSectorSizes(const unordered_set&); + void SetSectorSizes(const unordered_set& sizes) { sector_sizes = sizes; } void SetSectorSizeInBytes(uint32_t); - uint32_t GetSectorSizeShiftCount() const; - void SetSectorSizeShiftCount(uint32_t); + uint32_t GetSectorSizeShiftCount() const { return size_shift_count; } + void SetSectorSizeShiftCount(uint32_t count) { size_shift_count = count; } uint32_t GetConfiguredSectorSize() const; - void SetBlockCount(uint64_t); + void SetBlockCount(uint64_t b) { blocks = b; } - // Internal disk data - disk_t disk = {}; + unique_ptr cache; }; diff --git a/src/raspberrypi/devices/disk_cache.cpp b/src/raspberrypi/devices/disk_cache.cpp index e6dcfed0..e1458f00 100644 --- a/src/raspberrypi/devices/disk_cache.cpp +++ b/src/raspberrypi/devices/disk_cache.cpp @@ -14,7 +14,6 @@ // //--------------------------------------------------------------------------- -#include "log.h" #include "disk_track.h" #include "disk_cache.h" @@ -27,18 +26,6 @@ DiskCache::DiskCache(const Filepath& path, int size, uint32_t blocks, off_t imgo sec_path = path; } -DiskCache::~DiskCache() -{ - // Clear the track - Clear(); -} - -void DiskCache::SetRawMode(bool raw) -{ - // Configuration - cd_raw = raw; -} - bool DiskCache::Save() const { // Save track @@ -52,50 +39,21 @@ bool DiskCache::Save() const return true; } -//--------------------------------------------------------------------------- -// -// Get disk cache information -// -//--------------------------------------------------------------------------- -bool DiskCache::GetCache(int index, int& track, uint32_t& aserial) const +shared_ptr DiskCache::GetTrack(uint32_t block) { - assert((index >= 0) && (index < CACHE_MAX)); - - // false if unused - if (!cache[index].disktrk) { - return false; - } - - // Set track and serial - track = cache[index].disktrk->GetTrack(); - aserial = cache[index].serial; - - return true; -} - -void DiskCache::Clear() -{ - // Free the cache - for (cache_t& c : cache) { - if (c.disktrk) { - delete c.disktrk; - c.disktrk = nullptr; - } - } -} - -bool DiskCache::ReadSector(BYTE *buf, uint32_t block) -{ - assert(sec_size != 0); - // Update first UpdateSerialNumber(); // Calculate track (fixed to 256 sectors/track) int track = block >> 8; - // Get the track data - const DiskTrack *disktrk = Assign(track); + // Get track data + return Assign(track); +} + +bool DiskCache::ReadSector(vector& buf, uint32_t block) +{ + shared_ptr disktrk = GetTrack(block); if (disktrk == nullptr) { return false; } @@ -104,18 +62,9 @@ bool DiskCache::ReadSector(BYTE *buf, uint32_t block) return disktrk->ReadSector(buf, block & 0xff); } -bool DiskCache::WriteSector(const BYTE *buf, uint32_t block) +bool DiskCache::WriteSector(const vector& buf, uint32_t block) { - assert(sec_size != 0); - - // Update first - UpdateSerialNumber(); - - // Calculate track (fixed to 256 sectors/track) - int track = block >> 8; - - // Get that track data - DiskTrack *disktrk = Assign(track); + shared_ptr disktrk = GetTrack(block); if (disktrk == nullptr) { return false; } @@ -129,7 +78,7 @@ bool DiskCache::WriteSector(const BYTE *buf, uint32_t block) // Track Assignment // //--------------------------------------------------------------------------- -DiskTrack* DiskCache::Assign(int track) +shared_ptr DiskCache::Assign(int track) { assert(sec_size != 0); assert(track >= 0); @@ -144,10 +93,10 @@ DiskTrack* DiskCache::Assign(int track) } // Next, check for empty - for (int i = 0; i < CACHE_MAX; i++) { - if (!cache[i].disktrk) { + for (size_t i = 0; i < cache.size(); i++) { + if (cache[i].disktrk == nullptr) { // Try loading - if (Load(i, track)) { + if (Load((int)i, track, nullptr)) { // Success loading cache[i].serial = serial; return cache[i].disktrk; @@ -162,10 +111,10 @@ DiskTrack* DiskCache::Assign(int track) // Set index 0 as candidate c uint32_t s = cache[0].serial; - int c = 0; + size_t c = 0; // Compare candidate with serial and update to smaller one - for (int i = 0; i < CACHE_MAX; i++) { + for (size_t i = 0; i < cache.size(); i++) { assert(cache[i].disktrk); // Compare and update the existing serial @@ -181,10 +130,10 @@ DiskTrack* DiskCache::Assign(int track) } // Delete this track - DiskTrack *disktrk = cache[c].disktrk; - cache[c].disktrk = nullptr; + shared_ptr disktrk = cache[c].disktrk; + cache[c].disktrk.reset(); - if (Load(c, track, disktrk)) { + if (Load((int)c, track, disktrk)) { // Successful loading cache[c].serial = serial; return cache[c].disktrk; @@ -199,11 +148,11 @@ DiskTrack* DiskCache::Assign(int track) // Load cache // //--------------------------------------------------------------------------- -bool DiskCache::Load(int index, int track, DiskTrack *disktrk) +bool DiskCache::Load(int index, int track, shared_ptr disktrk) { - assert((index >= 0) && (index < CACHE_MAX)); + assert(index >= 0 && index < (int)cache.size()); assert(track >= 0); - assert(!cache[index].disktrk); + assert(cache[index].disktrk == nullptr); // Get the number of sectors on this track int sectors = sec_blocks - (track << 8); @@ -214,7 +163,7 @@ bool DiskCache::Load(int index, int track, DiskTrack *disktrk) // Create a disk track if (disktrk == nullptr) { - disktrk = new DiskTrack(); + disktrk = make_shared(); } // Initialize disk track @@ -223,7 +172,6 @@ bool DiskCache::Load(int index, int track, DiskTrack *disktrk) // Try loading if (!disktrk->Load(sec_path)) { // Failure - delete disktrk; return false; } diff --git a/src/raspberrypi/devices/disk_cache.h b/src/raspberrypi/devices/disk_cache.h index 88755dee..501dea7f 100644 --- a/src/raspberrypi/devices/disk_cache.h +++ b/src/raspberrypi/devices/disk_cache.h @@ -16,43 +16,46 @@ #pragma once #include "filepath.h" +#include +#include -// Number of tracks to cache -static const int CACHE_MAX = 16; +using namespace std; //NOSONAR Not relevant for rascsi class DiskCache { + // Number of tracks to cache + static const int CACHE_MAX = 16; + public: // Internal data definition using cache_t = struct { - DiskTrack *disktrk; // Disk Track - uint32_t serial; // Serial + shared_ptr disktrk; // Disk Track + uint32_t serial; // Serial }; DiskCache(const Filepath& path, int size, uint32_t blocks, off_t imgoff = 0); - ~DiskCache(); + ~DiskCache() = default; DiskCache(DiskCache&) = delete; DiskCache& operator=(const DiskCache&) = delete; - void SetRawMode(bool); // CD-ROM raw mode setting + void SetRawMode(bool b) { cd_raw = b; } // CD-ROM raw mode setting // Access bool Save() const; // Save and release all - bool ReadSector(BYTE *buf, uint32_t block); // Sector Read - bool WriteSector(const BYTE *buf, uint32_t block); // Sector Write - bool GetCache(int index, int& track, uint32_t& serial) const; // Get cache information + bool ReadSector(vector&, uint32_t); // Sector Read + bool WriteSector(const vector&, uint32_t); // Sector Write private: // Internal Management - void Clear(); // Clear all tracks - DiskTrack* Assign(int track); // Load track - bool Load(int index, int track, DiskTrack *disktrk = nullptr); // Load track - void UpdateSerialNumber(); // Update serial number + shared_ptr Assign(int); + shared_ptr GetTrack(uint32_t); + bool Load(int index, int track, shared_ptr); + void UpdateSerialNumber(); // Internal data - cache_t cache[CACHE_MAX] = {}; // Cache management + array cache = {}; // Cache management uint32_t serial = 0; // Last serial number Filepath sec_path; // Path int sec_size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096) diff --git a/src/raspberrypi/devices/disk_track.cpp b/src/raspberrypi/devices/disk_track.cpp index 466e53bc..be43c489 100644 --- a/src/raspberrypi/devices/disk_track.cpp +++ b/src/raspberrypi/devices/disk_track.cpp @@ -24,9 +24,6 @@ DiskTrack::~DiskTrack() if (dt.buffer) { free(dt.buffer); } - if (dt.changemap) { - free(dt.changemap); - } } void DiskTrack::Init(int track, int size, int sectors, bool raw, off_t imgoff) @@ -56,7 +53,6 @@ bool DiskTrack::Load(const Filepath& path) // Not needed if already loaded if (dt.init) { assert(dt.buffer); - assert(dt.changemap); return true; } @@ -86,7 +82,7 @@ bool DiskTrack::Load(const Filepath& path) dt.length = length; } - if (!dt.buffer) { + if (dt.buffer == nullptr) { return false; } @@ -99,31 +95,16 @@ bool DiskTrack::Load(const Filepath& path) dt.length = length; } - // Reserve change map memory - if (dt.changemap == nullptr) { - dt.changemap = (bool *)malloc(dt.sectors * sizeof(bool)); - dt.maplen = dt.sectors; - } - - if (!dt.changemap) { - return false; - } - - // Reallocate if the buffer length is different - if (dt.maplen != (DWORD)dt.sectors) { - free(dt.changemap); - dt.changemap = (bool *)malloc(dt.sectors * sizeof(bool)); - dt.maplen = dt.sectors; - } - - // Clear changemap - memset(dt.changemap, 0x00, dt.sectors * sizeof(bool)); + // Resize and clear changemap + dt.changemap.resize(dt.sectors); + fill(dt.changemap.begin(), dt.changemap.end(), false); // Read from File Fileio fio; if (!fio.OpenDIO(path, Fileio::OpenMode::ReadOnly)) { return false; } + if (dt.raw) { // Split Reading for (int i = 0; i < dt.sectors; i++) { @@ -175,7 +156,6 @@ bool DiskTrack::Save(const Filepath& path) // Need to write assert(dt.buffer); - assert(dt.changemap); assert((dt.sectors > 0) && (dt.sectors <= 0x100)); // Writing in RAW mode is not allowed @@ -237,18 +217,18 @@ bool DiskTrack::Save(const Filepath& path) } } - // Close fio.Close(); // Drop the change flag and exit - memset(dt.changemap, 0x00, dt.sectors * sizeof(bool)); + fill(dt.changemap.begin(), dt.changemap.end(), false); dt.changed = false; + return true; } -bool DiskTrack::ReadSector(BYTE *buf, int sec) const +bool DiskTrack::ReadSector(vector& buf, int sec) const { - assert((sec >= 0) && (sec < 0x100)); + assert(sec >= 0 && sec < 0x100); LOGTRACE("%s reading sector: %d", __PRETTY_FUNCTION__,sec) @@ -265,13 +245,13 @@ bool DiskTrack::ReadSector(BYTE *buf, int sec) const // Copy assert(dt.buffer); assert((dt.sectors > 0) && (dt.sectors <= 0x100)); - memcpy(buf, &dt.buffer[(off_t)sec << dt.size], (off_t)1 << dt.size); + memcpy(buf.data(), &dt.buffer[(off_t)sec << dt.size], (off_t)1 << dt.size); // Success return true; } -bool DiskTrack::WriteSector(const BYTE *buf, int sec) +bool DiskTrack::WriteSector(const vector& buf, int sec) { assert((sec >= 0) && (sec < 0x100)); assert(!dt.raw); @@ -293,13 +273,13 @@ bool DiskTrack::WriteSector(const BYTE *buf, int sec) // Compare assert(dt.buffer); assert((dt.sectors > 0) && (dt.sectors <= 0x100)); - if (memcmp(buf, &dt.buffer[offset], length) == 0) { + if (memcmp(buf.data(), &dt.buffer[offset], length) == 0) { // Exit normally since it's attempting to write the same thing return true; } // Copy, change - memcpy(&dt.buffer[offset], buf, length); + memcpy(&dt.buffer[offset], buf.data(), length); dt.changemap[sec] = true; dt.changed = true; diff --git a/src/raspberrypi/devices/disk_track.h b/src/raspberrypi/devices/disk_track.h index b43a8697..0f13a98a 100644 --- a/src/raspberrypi/devices/disk_track.h +++ b/src/raspberrypi/devices/disk_track.h @@ -16,6 +16,9 @@ #pragma once #include "filepath.h" +#include + +using namespace std; //NOSONAR Not relevant for rascsi class DiskTrack { @@ -27,8 +30,7 @@ class DiskTrack BYTE *buffer; // Data buffer bool init; // Is it initilized? bool changed; // Changed flag - DWORD maplen; // Changed map length - bool *changemap; // Changed map + std::vector changemap; // Changed map bool raw; // RAW mode flag off_t imgoffset; // Offset to actual data } dt = {}; @@ -49,8 +51,8 @@ private: bool Save(const Filepath& path); // Read / Write - bool ReadSector(BYTE *buf, int sec) const; // Sector Read - bool WriteSector(const BYTE *buf, int sec); // Sector Write + bool ReadSector(vector&, int) const; // Sector Read + bool WriteSector(const vector& buf, int); // Sector Write int GetTrack() const { return dt.track; } // Get track }; diff --git a/src/raspberrypi/devices/host_services.cpp b/src/raspberrypi/devices/host_services.cpp index d4a5dcfe..33ddca93 100644 --- a/src/raspberrypi/devices/host_services.cpp +++ b/src/raspberrypi/devices/host_services.cpp @@ -25,6 +25,7 @@ #include "scsi_command_util.h" #include "dispatcher.h" #include "host_services.h" +#include using namespace scsi_defs; using namespace scsi_command_util; @@ -85,23 +86,20 @@ void HostServices::StartStopUnit() throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } -int HostServices::ModeSense6(const vector& cdb, BYTE *buf, int max_length) const +int HostServices::ModeSense6(const vector& cdb, vector& buf, int max_length) const { // Block descriptors cannot be returned if (!(cdb[1] & 0x08)) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - int length = cdb[4]; - if (length > max_length) { - length = max_length; - } - memset(buf, 0, length); + auto length = (int)min((size_t)max_length, (size_t)cdb[4]); + fill_n(buf.begin(), length, 0); // Basic Information int size = 4; - size += super::AddModePages(cdb, &buf[size], length - size); + size += super::AddModePages(cdb, buf, size, length - size); if (size > 255) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } @@ -116,23 +114,20 @@ int HostServices::ModeSense6(const vector& cdb, BYTE *buf, int max_length) return size; } -int HostServices::ModeSense10(const vector& cdb, BYTE *buf, int max_length) const +int HostServices::ModeSense10(const vector& cdb, vector& buf, int max_length) const { // Block descriptors cannot be returned if (!(cdb[1] & 0x08)) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - int length = (cdb[7] << 8) | cdb[8]; - if (length > max_length) { - length = max_length; - } - memset(buf, 0, length); + auto length = (int)min((size_t)max_length, (size_t)GetInt16(cdb, 7)); + fill_n(buf.begin(), length, 0); // Basic Information int size = 8; - size += super::AddModePages(cdb, &buf[size], length - size); + size += super::AddModePages(cdb, buf, size, length - size); if (size > 65535) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } @@ -142,7 +137,7 @@ int HostServices::ModeSense10(const vector& cdb, BYTE *buf, int max_length) size = length; } - SetInt16(buf, size); + SetInt16(buf, 0, size); return size; } @@ -157,7 +152,7 @@ void HostServices::SetUpModePages(map>& pages, int page, bool void HostServices::AddRealtimeClockPage(map>& pages, bool changeable) const { if (!changeable) { - std::time_t t = std::time(nullptr); + time_t t = time(nullptr); tm localtime; localtime_r(&t, &localtime); diff --git a/src/raspberrypi/devices/host_services.h b/src/raspberrypi/devices/host_services.h index 8c0d445b..217de0fb 100644 --- a/src/raspberrypi/devices/host_services.h +++ b/src/raspberrypi/devices/host_services.h @@ -58,8 +58,8 @@ private: Dispatcher dispatcher; - int ModeSense6(const vector&, BYTE *, int) const override; - int ModeSense10(const vector&, BYTE *, int) const override; + int ModeSense6(const vector&, vector&, int) const override; + int ModeSense10(const vector&, vector&, int) const override; void AddRealtimeClockPage(map>&, bool) const; diff --git a/src/raspberrypi/devices/mode_page_device.cpp b/src/raspberrypi/devices/mode_page_device.cpp index 1863a460..10011752 100644 --- a/src/raspberrypi/devices/mode_page_device.cpp +++ b/src/raspberrypi/devices/mode_page_device.cpp @@ -11,12 +11,14 @@ #include "log.h" #include "rascsi_exceptions.h" +#include "scsi_command_util.h" #include "dispatcher.h" #include "mode_page_device.h" #include using namespace std; using namespace scsi_defs; +using namespace scsi_command_util; ModePageDevice::ModePageDevice(const string& id) : PrimaryDevice(id) { @@ -32,7 +34,7 @@ bool ModePageDevice::Dispatch(scsi_command cmd) return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); } -int ModePageDevice::AddModePages(const vector& cdb, BYTE *buf, int max_length) const +int ModePageDevice::AddModePages(const vector& cdb, vector& buf, int offset, int max_length) const { if (max_length < 0) { return 0; @@ -77,36 +79,34 @@ int ModePageDevice::AddModePages(const vector& cdb, BYTE *buf, int max_leng // Page 0 must be last if (!page0.empty()) { - size_t offset = result.size(); - // Page data result.insert(result.end(), page0.begin(), page0.end()); // Page payload size - result[offset + 1] = (byte)(page0.size() - 2); + result[result.size() + 1] = (byte)(page0.size() - 2); } // Do not return more than the requested number of bytes - size_t size = (size_t)max_length < result.size() ? max_length : result.size(); - memcpy(buf, result.data(), size); + size_t size = min((size_t)max_length, result.size()); + memcpy(&buf.data()[offset], result.data(), size); return (int)size; } void ModePageDevice::ModeSense6() { - ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer, ctrl->bufsize); + ctrl->length = ModeSense6(ctrl->cmd, controller->GetBuffer(), (int)controller->GetBufferSize()); EnterDataInPhase(); } void ModePageDevice::ModeSense10() { - ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer, ctrl->bufsize); + ctrl->length = ModeSense10(ctrl->cmd, controller->GetBuffer(), (int)controller->GetBufferSize()); EnterDataInPhase(); } -void ModePageDevice::ModeSelect(const vector&, const BYTE *, int) const +void ModePageDevice::ModeSelect(const vector&, const vector&, int) const { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); } @@ -127,7 +127,7 @@ void ModePageDevice::ModeSelect10() int ModePageDevice::ModeSelectCheck(int length) const { - // Error if save parameters are set for other types than of SCHD, SCRM or SCMO + // Error if save parameters are set for other types than SCHD, SCRM or SCMO // TODO The assumption above is not correct, and this code should be located elsewhere if (GetType() != "SCHD" && GetType() != "SCRM" && GetType() != "SCMO" && (ctrl->cmd[1] & 0x01)) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); @@ -145,12 +145,7 @@ int ModePageDevice::ModeSelectCheck6() const int ModePageDevice::ModeSelectCheck10() const { // Receive the data specified by the parameter length - int length = ctrl->cmd[7]; - length <<= 8; - length |= ctrl->cmd[8]; - if (length > ctrl->bufsize) { - length = ctrl->bufsize; - } + size_t length = min(controller->GetBufferSize(), (size_t)GetInt16(ctrl->cmd, 7)); - return ModeSelectCheck(length); + return ModeSelectCheck((int)length); } diff --git a/src/raspberrypi/devices/mode_page_device.h b/src/raspberrypi/devices/mode_page_device.h index 8a4c003f..e660087e 100644 --- a/src/raspberrypi/devices/mode_page_device.h +++ b/src/raspberrypi/devices/mode_page_device.h @@ -25,11 +25,11 @@ public: bool Dispatch(scsi_command) override; - virtual void ModeSelect(const vector&, const BYTE *, int) const; + virtual void ModeSelect(const vector&, const vector&, int) const; protected: - int AddModePages(const vector&, BYTE *, int) const; + int AddModePages(const vector&, vector&, int, int) const; virtual void SetUpModePages(map>&, int, bool) const = 0; private: @@ -38,8 +38,8 @@ private: Dispatcher dispatcher; - virtual int ModeSense6(const vector&, BYTE *, int) const = 0; - virtual int ModeSense10(const vector&, BYTE *, int) const = 0; + virtual int ModeSense6(const vector&, vector&, int) const = 0; + virtual int ModeSense10(const vector&, vector&, int) const = 0; void ModeSense6(); void ModeSense10(); diff --git a/src/raspberrypi/devices/primary_device.cpp b/src/raspberrypi/devices/primary_device.cpp index 1f306562..f7f754d3 100644 --- a/src/raspberrypi/devices/primary_device.cpp +++ b/src/raspberrypi/devices/primary_device.cpp @@ -9,11 +9,13 @@ #include "log.h" #include "rascsi_exceptions.h" +#include "scsi_command_util.h" #include "dispatcher.h" #include "primary_device.h" using namespace std; using namespace scsi_defs; +using namespace scsi_command_util; PrimaryDevice::PrimaryDevice(const string& id) : Device(id) { @@ -53,12 +55,9 @@ void PrimaryDevice::Inquiry() vector buf = InquiryInternal(); - size_t allocation_length = ctrl->cmd[4] + (ctrl->cmd[3] << 8); - if (allocation_length > buf.size()) { - allocation_length = buf.size(); - } + size_t allocation_length = min(buf.size(), (size_t)GetInt16(ctrl->cmd, 3)); - memcpy(ctrl->buffer, buf.data(), allocation_length); + memcpy(controller->GetBuffer().data(), buf.data(), allocation_length); ctrl->length = (uint32_t)allocation_length; // Report if the device does not support the requested LUN @@ -66,7 +65,7 @@ void PrimaryDevice::Inquiry() LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, GetId()) // Signal that the requested LUN does not exist - ctrl->buffer[0] |= 0x7f; + controller->GetBuffer()[0] |= 0x7f; } EnterDataInPhase(); @@ -74,18 +73,17 @@ void PrimaryDevice::Inquiry() void PrimaryDevice::ReportLuns() { - 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 < ctrl->bufsize ? allocation_length : ctrl->bufsize); - - int size = 0; - // Only SELECT REPORT mode 0 is supported if (ctrl->cmd[2]) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } + uint32_t allocation_length = GetInt32(ctrl->cmd, 6); + + vector& buf = controller->GetBuffer(); + fill_n(buf.begin(), min(controller->GetBufferSize(), (size_t)allocation_length), 0); + + uint32_t size = 0; for (int lun = 0; lun < controller->GetMaxLuns(); lun++) { if (controller->HasDeviceForLun(lun)) { size += 8; @@ -93,12 +91,11 @@ void PrimaryDevice::ReportLuns() } } - buf[2] = (BYTE)(size >> 8); - buf[3] = (BYTE)size; + SetInt16(buf, 2, size); size += 8; - ctrl->length = allocation_length < size ? allocation_length : size; + ctrl->length = min(allocation_length, size); EnterDataInPhase(); } @@ -118,17 +115,14 @@ void PrimaryDevice::RequestSense() // Do not raise an exception here because the rest of the code must be executed controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_LUN); - ctrl->status = 0x00; + controller->SetStatus(0); } vector buf = controller->GetDeviceForLun(lun)->HandleRequestSense(); - size_t allocation_length = ctrl->cmd[4]; - if (allocation_length > buf.size()) { - allocation_length = buf.size(); - } + size_t allocation_length = min(buf.size(), (size_t)ctrl->cmd[4]); - memcpy(ctrl->buffer, buf.data(), allocation_length); + memcpy(controller->GetBuffer().data(), buf.data(), allocation_length); ctrl->length = (uint32_t)allocation_length; EnterDataInPhase(); @@ -201,12 +195,13 @@ vector PrimaryDevice::HandleRequestSense() const buf[12] = (byte)(GetStatusCode() >> 8); buf[13] = (byte)GetStatusCode(); - LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]) + LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, controller->GetStatus(), + (int)buf[2], (int)buf[12]) return buf; } -bool PrimaryDevice::WriteByteSequence(BYTE *, uint32_t) +bool PrimaryDevice::WriteByteSequence(vector&, uint32_t) { LOGERROR("%s Writing bytes is not supported by this device", __PRETTY_FUNCTION__) diff --git a/src/raspberrypi/devices/primary_device.h b/src/raspberrypi/devices/primary_device.h index 49af8783..2382b018 100644 --- a/src/raspberrypi/devices/primary_device.h +++ b/src/raspberrypi/devices/primary_device.h @@ -30,7 +30,7 @@ public: virtual bool Dispatch(scsi_command); void SetController(AbstractController *); - virtual bool WriteByteSequence(BYTE *, uint32_t); + virtual bool WriteByteSequence(vector&, uint32_t); virtual int GetSendDelay() const { return BUS::SEND_NO_DELAY; } protected: diff --git a/src/raspberrypi/devices/scsi_command_util.cpp b/src/raspberrypi/devices/scsi_command_util.cpp index e67eaf70..9467a218 100644 --- a/src/raspberrypi/devices/scsi_command_util.cpp +++ b/src/raspberrypi/devices/scsi_command_util.cpp @@ -13,63 +13,61 @@ using namespace scsi_defs; -void scsi_command_util::ModeSelect(const vector& cdb, const BYTE *buf, int length, int sector_size) +void scsi_command_util::ModeSelect(const vector& cdb, const vector& buf, int length, int sector_size) { assert(length >= 0); - int offset = 0; - // PF - if (cdb[1] & 0x10) { - bool has_valid_page_code = false; + if (!(cdb[1] & 0x10)) { + // Vendor-specific parameters (SCSI-1) are not supported + throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); + } - // Mode Parameter header - if (length >= 12) { - // Check the block length - if (buf[9] != (BYTE)(sector_size >> 16) || buf[10] != (BYTE)(sector_size >> 8) || - buf[11] != (BYTE)sector_size) { - // See below for details + bool has_valid_page_code = false; + + // Mode Parameter header + int offset = 0; + if (length >= 12) { + // Check the block length + if (buf[9] != (BYTE)(sector_size >> 16) || buf[10] != (BYTE)(sector_size >> 8) || + buf[11] != (BYTE)sector_size) { + // See below for details + LOGWARN("In order to change the sector size use the -b option when launching rascsi") + throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); + } + + offset += 12; + length -= 12; + } + + // Parsing the page + // TODO The length handling is wrong in case of length < size + while (length > 0) { + // Format device page + if (int page = buf[offset]; page == 0x03) { + // With this page the sector size for a subsequent FORMAT can be selected, but only very few + // drives support this, e.g FUJITSU M2624S + // We are fine as long as the current sector size remains unchanged + if (buf[offset + 0xc] != (BYTE)(sector_size >> 8) || buf[offset + 0xd] != (BYTE)sector_size) { + // With rascsi it is not possible to permanently (by formatting) change the sector size, + // because the size is an externally configurable setting only LOGWARN("In order to change the sector size use the -b option when launching rascsi") throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); } - offset += 12; - length -= 12; + has_valid_page_code = true; + } + else { + LOGWARN("Unknown MODE SELECT page code: $%02X", page) } - // Parsing the page - // TODO The length handling is wrong in case of length < size - while (length > 0) { - // Format device page - if (int page = buf[offset]; page == 0x03) { - // With this page the sector size for a subsequent FORMAT can be selected, but only very few - // drives support this, e.g FUJITSU M2624S - // We are fine as long as the current sector size remains unchanged - if (buf[offset + 0xc] != (BYTE)(sector_size >> 8) || buf[offset + 0xd] != (BYTE)sector_size) { - // With rascsi it is not possible to permanently (by formatting) change the sector size, - // because the size is an externally configurable setting only - LOGWARN("In order to change the sector size use the -b option when launching rascsi") - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); - } - - has_valid_page_code = true; - } - else { - LOGWARN("Unknown MODE SELECT page code: $%02X", page) - } - - // Advance to the next page - int size = buf[offset + 1] + 2; - length -= size; - offset += size; - } - - if (!has_valid_page_code) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); - } + // Advance to the next page + int size = buf[offset + 1] + 2; + length -= size; + offset += size; } - else { - // Vendor-specific parameters (SCSI-1) are not supported + + if (!has_valid_page_code) { throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); } } @@ -105,6 +103,11 @@ int scsi_command_util::GetInt16(const vector& buf, int offset) return (buf[offset] << 8) | buf[offset + 1]; } +int scsi_command_util::GetInt24(const vector& buf, int offset) +{ + return (buf[offset] << 16) | (buf[offset + 1] << 8) | buf[offset + 2]; +} + uint32_t scsi_command_util::GetInt32(const vector& buf, int offset) { return ((uint32_t)buf[offset] << 24) | ((uint32_t)buf[offset + 1] << 16) | @@ -119,42 +122,42 @@ uint64_t scsi_command_util::GetInt64(const vector& buf, int offset) ((uint64_t)buf[offset + 6] << 8) | (uint64_t)buf[offset + 7]; } -void scsi_command_util::SetInt16(BYTE *buf, int value) -{ - buf[0] = (BYTE)(value >> 8); - buf[1] = (BYTE)value; -} - -void scsi_command_util::SetInt32(BYTE *buf, uint32_t value) -{ - buf[0] = (BYTE)(value >> 24); - buf[1] = (BYTE)(value >> 16); - buf[2] = (BYTE)(value >> 8); - buf[3] = (BYTE)value; -} - -void scsi_command_util::SetInt64(BYTE *buf, uint64_t value) -{ - buf[0] = (BYTE)(value >> 56); - buf[1] = (BYTE)(value >> 48); - buf[2] = (BYTE)(value >> 40); - buf[3] = (BYTE)(value >> 32); - buf[4] = (BYTE)(value >> 24); - buf[5] = (BYTE)(value >> 16); - buf[6] = (BYTE)(value >> 8); - buf[7] = (BYTE)value; -} - void scsi_command_util::SetInt16(vector& buf, int offset, int value) { buf[offset] = (byte)(value >> 8); buf[offset + 1] = (byte)value; } -void scsi_command_util::SetInt32(vector& buf, int offset, int value) +void scsi_command_util::SetInt32(vector& buf, int offset, uint32_t value) { buf[offset] = (byte)(value >> 24); buf[offset + 1] = (byte)(value >> 16); buf[offset + 2] = (byte)(value >> 8); buf[offset + 3] = (byte)value; } + +void scsi_command_util::SetInt16(vector& buf, int offset, int value) +{ + buf[offset] = (BYTE)(value >> 8); + buf[offset + 1] = (BYTE)value; +} + +void scsi_command_util::SetInt32(vector& buf, int offset, uint32_t value) +{ + buf[offset] = (BYTE)(value >> 24); + buf[offset + 1] = (BYTE)(value >> 16); + buf[offset + 2] = (BYTE)(value >> 8); + buf[offset + 3] = (BYTE)value; +} + +void scsi_command_util::SetInt64(vector& buf, int offset, uint64_t value) +{ + buf[offset] = (BYTE)(value >> 56); + buf[offset + 1] = (BYTE)(value >> 48); + buf[offset + 2] = (BYTE)(value >> 40); + buf[offset + 3] = (BYTE)(value >> 32); + buf[offset + 4] = (BYTE)(value >> 24); + buf[offset + 5] = (BYTE)(value >> 16); + buf[offset + 6] = (BYTE)(value >> 8); + buf[offset + 7] = (BYTE)value; +} diff --git a/src/raspberrypi/devices/scsi_command_util.h b/src/raspberrypi/devices/scsi_command_util.h index 142bfc2c..ea77a9a0 100644 --- a/src/raspberrypi/devices/scsi_command_util.h +++ b/src/raspberrypi/devices/scsi_command_util.h @@ -18,16 +18,17 @@ using namespace std; //NOSONAR Not relevant for rascsi namespace scsi_command_util { - void ModeSelect(const vector&, const BYTE *, int, int); + void ModeSelect(const vector&, const vector&, int, int); void EnrichFormatPage(map>&, bool, int); void AddAppleVendorModePage(map>&, bool); int GetInt16(const vector&, int); + int GetInt24(const vector&, int); uint32_t GetInt32(const vector&, int); uint64_t GetInt64(const vector&, int); - void SetInt16(BYTE *, int); - void SetInt32(BYTE *, uint32_t); - void SetInt64(BYTE *, uint64_t); void SetInt16(vector&, int, int); - void SetInt32(vector&, int, int); + void SetInt32(vector&, int, uint32_t); + void SetInt16(vector&, int, int); + void SetInt32(vector&, int, uint32_t); + void SetInt64(vector&, int, uint64_t); } diff --git a/src/raspberrypi/devices/scsi_daynaport.cpp b/src/raspberrypi/devices/scsi_daynaport.cpp index 4dda67d7..40243cf6 100644 --- a/src/raspberrypi/devices/scsi_daynaport.cpp +++ b/src/raspberrypi/devices/scsi_daynaport.cpp @@ -79,20 +79,6 @@ bool SCSIDaynaPort::Init(const unordered_map& params) SetReady(true); SetReset(false); - // if (m_bTapEnable) { - // tap->GetMacAddr(m_mac_addr); - // m_mac_addr[5]++; - // } - - // !!!!!!!!!!!!!!!!! For now, hard code the MAC address. Its annoying when it keeps changing during development! - // TODO: Remove this hard-coded address - m_mac_addr[0] = (byte)0x00; - m_mac_addr[1] = (byte)0x80; - m_mac_addr[2] = (byte)0x19; - m_mac_addr[3] = (byte)0x10; - m_mac_addr[4] = (byte)0x98; - m_mac_addr[5] = (byte)0xE3; - return true; } @@ -144,10 +130,10 @@ vector SCSIDaynaPort::InquiryInternal() const // - The SCSI/Link apparently has about 6KB buffer space for packets. // //--------------------------------------------------------------------------- -int SCSIDaynaPort::Read(const vector& cdb, BYTE *buf, uint64_t) +int SCSIDaynaPort::Read(const vector& cdb, vector& buf, uint64_t) { int rx_packet_size = 0; - auto response = (scsi_resp_read_t*)buf; + auto response = (scsi_resp_read_t*)buf.data(); int requested_length = cdb[4]; LOGTRACE("%s Read maximum length %d, (%04X)", __PRETTY_FUNCTION__, requested_length, requested_length) @@ -246,8 +232,8 @@ int SCSIDaynaPort::Read(const vector& cdb, BYTE *buf, uint64_t) // breaks because of this, the work-around has to be re-evaluated. size = 64; } - SetInt16(&buf[0], size); - SetInt32(&buf[2], m_tap.PendingPackets() ? 0x10 : 0x00); + SetInt16(buf, 0, size); + SetInt32(buf, 2, m_tap.PendingPackets() ? 0x10 : 0x00); // Return the packet size + 2 for the length + 4 for the flag field // The CRC was already appended by the ctapdriver @@ -291,19 +277,19 @@ int SCSIDaynaPort::WriteCheck(uint64_t) // XX XX ... is the actual packet // //--------------------------------------------------------------------------- -bool SCSIDaynaPort::WriteBytes(const vector& cdb, const BYTE *buf, uint64_t) +bool SCSIDaynaPort::WriteBytes(const vector& cdb, const vector& buf, uint64_t) { int data_format = cdb[5]; - int data_length = cdb[4] + (cdb[3] << 8); + int data_length = GetInt16(cdb, 3); if (data_format == 0x00){ - m_tap.Send(buf, data_length); + m_tap.Send(buf.data(), data_length); LOGTRACE("%s Transmitted %u bytes (00 format)", __PRETTY_FUNCTION__, data_length) } else if (data_format == 0x80){ // The data length is specified in the first 2 bytes of the payload data_length=buf[1] + (buf[0] << 8); - m_tap.Send(&buf[4], data_length); + m_tap.Send(&(buf.data()[4]), data_length); LOGTRACE("%s Transmitted %u bytes (80 format)", __PRETTY_FUNCTION__, data_length) } else @@ -331,33 +317,11 @@ bool SCSIDaynaPort::WriteBytes(const vector& cdb, const BYTE *buf, uint64_t // - long #3: frames lost // //--------------------------------------------------------------------------- -int SCSIDaynaPort::RetrieveStats(const vector& cdb, BYTE *buffer) const +int SCSIDaynaPort::RetrieveStats(const vector& cdb, vector& buf) const { - int allocation_length = cdb[4] + (cdb[3] << 8); + memcpy(buf.data(), &m_scsi_link_stats, sizeof(m_scsi_link_stats)); - // memset(buffer,0,18); - // memcpy(&buffer[0],m_mac_addr,sizeof(m_mac_addr)); - // uint32_t frame_alignment_errors; - // uint32_t crc_errors; - // uint32_t frames_lost; - // // frame alignment errors - // frame_alignment_errors = htonl(0); - // memcpy(&(buffer[6]),&frame_alignment_errors,sizeof(frame_alignment_errors)); - // // CRC errors - // crc_errors = htonl(0); - // memcpy(&(buffer[10]),&crc_errors,sizeof(crc_errors)); - // // frames lost - // frames_lost = htonl(0); - // memcpy(&(buffer[14]),&frames_lost,sizeof(frames_lost)); - - int response_size = sizeof(m_scsi_link_stats); - memcpy(buffer, &m_scsi_link_stats, sizeof(m_scsi_link_stats)); - - if (response_size > allocation_length) { - response_size = allocation_length; - } - - return response_size; + return (int)min(sizeof(m_scsi_link_stats), (size_t)GetInt16(cdb, 4)); } //--------------------------------------------------------------------------- @@ -407,11 +371,7 @@ void SCSIDaynaPort::TestUnitReady() void SCSIDaynaPort::Read6() { // Get record number and block number - uint32_t record = ctrl->cmd[1] & 0x1f; - record <<= 8; - record |= ctrl->cmd[2]; - record <<= 8; - record |= ctrl->cmd[3]; + uint32_t record = GetInt24(ctrl->cmd, 1) & 0x1fffff; ctrl->blocks=1; // If any commands have a bogus control value, they were probably not @@ -423,7 +383,7 @@ void SCSIDaynaPort::Read6() LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, record, ctrl->blocks) - ctrl->length = Read(ctrl->cmd, ctrl->buffer, record); + ctrl->length = Read(ctrl->cmd, controller->GetBuffer(), record); LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, ctrl->length) // Set next block @@ -434,20 +394,16 @@ void SCSIDaynaPort::Read6() void SCSIDaynaPort::Write6() { - // Reallocate buffer (because it is not transfer for each block) - if (ctrl->bufsize < DAYNAPORT_BUFFER_SIZE) { - delete[] ctrl->buffer; - ctrl->buffer = new BYTE[ctrl->bufsize]; - ctrl->bufsize = DAYNAPORT_BUFFER_SIZE; - } + // Ensure a sufficient buffer size (because it is not transfer for each block) + controller->AllocateBuffer(DAYNAPORT_BUFFER_SIZE); int data_format = ctrl->cmd[5]; - if(data_format == 0x00) { - ctrl->length = ctrl->cmd[4] + (ctrl->cmd[3] << 8); + if (data_format == 0x00) { + ctrl->length = GetInt16(ctrl->cmd, 3); } else if (data_format == 0x80) { - ctrl->length = ctrl->cmd[4] + (ctrl->cmd[3] << 8) + 8; + ctrl->length = GetInt16(ctrl->cmd, 3 + 8); } else { LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, data_format) @@ -467,7 +423,7 @@ void SCSIDaynaPort::Write6() void SCSIDaynaPort::RetrieveStatistics() { - ctrl->length = RetrieveStats(ctrl->cmd, ctrl->buffer); + ctrl->length = RetrieveStats(ctrl->cmd, controller->GetBuffer()); // Set next block ctrl->blocks = 1; @@ -506,7 +462,7 @@ void SCSIDaynaPort::SetInterfaceMode() { // Check whether this command is telling us to "Set Interface Mode" or "Set MAC Address" - ctrl->length = RetrieveStats(ctrl->cmd, ctrl->buffer); + ctrl->length = RetrieveStats(ctrl->cmd, controller->GetBuffer()); switch(ctrl->cmd[5]){ case CMD_SCSILINK_SETMODE: // TODO Not implemented, do nothing diff --git a/src/raspberrypi/devices/scsi_daynaport.h b/src/raspberrypi/devices/scsi_daynaport.h index f36f78c6..4aaf8ab6 100644 --- a/src/raspberrypi/devices/scsi_daynaport.h +++ b/src/raspberrypi/devices/scsi_daynaport.h @@ -24,8 +24,9 @@ // This does NOT include the file system functionality that is present // in the Sharp X68000 host bridge. // -// Note: This requires the DaynaPort SCSI Link driver. +// Note: This requires a DaynaPort SCSI Link driver. //--------------------------------------------------------------------------- + #pragma once #include "os.h" @@ -42,8 +43,8 @@ //=========================================================================== class SCSIDaynaPort final : public Disk { - public: + SCSIDaynaPort(); ~SCSIDaynaPort() override = default; SCSIDaynaPort(SCSIDaynaPort&) = delete; @@ -54,15 +55,13 @@ public: // Commands vector InquiryInternal() const override; - int Read(const vector&, BYTE *, uint64_t) override; - bool WriteBytes(const vector&, const BYTE *, uint64_t); + int Read(const vector&, vector&, uint64_t) override; + bool WriteBytes(const vector&, const vector&, uint64_t); int WriteCheck(uint64_t block) override; - int RetrieveStats(const vector&, BYTE *) const; + int RetrieveStats(const vector&, vector&) const; bool EnableInterface(const vector&); - void SetMacAddr(const vector&, BYTE *); // Set MAC address - void TestUnitReady() override; void Read6() override; void Write6() override; @@ -108,19 +107,19 @@ private: uint32_t length; read_data_flags_t flags; byte pad; - byte data[ETH_FRAME_LEN + sizeof(uint32_t)]; // Frame length + 4 byte CRC + array data; // Frame length + 4 byte CRC }; using scsi_resp_link_stats_t = struct __attribute__((packed)) { - byte mac_address[6]; + array mac_address; uint32_t frame_alignment_errors; uint32_t crc_errors; uint32_t frames_lost; }; scsi_resp_link_stats_t m_scsi_link_stats = { - //MAC address of @PotatoFi's DayanPort - .mac_address = { byte{0x00}, byte{0x80}, byte{0x19}, byte{0x10}, byte{0x98}, byte{0xE3} }, + // TODO Remove this hard-coded MAC address, see https://github.com/akuker/RASCSI/issues/598 + .mac_address = { byte{0x00}, byte{0x80}, byte{0x19}, byte{0x10}, byte{0x98}, byte{0xe3} }, .frame_alignment_errors = 0, .crc_errors = 0, .frames_lost = 0, @@ -130,6 +129,4 @@ private: // TAP valid flag bool m_bTapEnable = false; - - array m_mac_addr; }; diff --git a/src/raspberrypi/devices/scsi_host_bridge.cpp b/src/raspberrypi/devices/scsi_host_bridge.cpp index 074928af..c61abe19 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.cpp +++ b/src/raspberrypi/devices/scsi_host_bridge.cpp @@ -37,12 +37,6 @@ SCSIBR::SCSIBR() : Disk("SCBR") dispatcher.Add(scsi_command::eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10); } -SCSIBR::~SCSIBR() -{ - // Release host file system - fs.Reset(); -} - bool SCSIBR::Init(const unordered_map& params) { SetParams(params); @@ -54,17 +48,16 @@ bool SCSIBR::Init(const unordered_map& params) LOGERROR("Unable to open the TAP interface") return false; } +#endif // Generate MAC Address - memset(mac_addr, 0x00, 6); if (m_bTapEnable) { - tap.GetMacAddr(mac_addr); + tap.GetMacAddr(mac_addr.data()); mac_addr[5]++; } // Packet reception flag OFF packet_enable = false; -#endif SetReady(m_bTapEnable); @@ -84,11 +77,10 @@ bool SCSIBR::Dispatch(scsi_command cmd) vector SCSIBR::InquiryInternal() const { - vector b = HandleInquiry(device_type::COMMUNICATIONS, scsi_level::SCSI_2, false); + vector buf = HandleInquiry(device_type::COMMUNICATIONS, scsi_level::SCSI_2, false); - // The bridge returns 6 more additional bytes than the other devices - auto buf = vector(0x1F + 8 + 5); - memcpy(buf.data(), b.data(), b.size()); + // The bridge returns more additional bytes than the other devices + buf.resize(0x1F + 8 + 5); buf[4] = byte{0x1F + 8}; @@ -112,7 +104,7 @@ void SCSIBR::TestUnitReady() EnterStatusPhase(); } -int SCSIBR::GetMessage10(const vector& cdb, BYTE *buf) +int SCSIBR::GetMessage10(const vector& cdb, vector& buf) { // Type int type = cdb[2]; @@ -138,18 +130,18 @@ int SCSIBR::GetMessage10(const vector& cdb, BYTE *buf) if (phase == 0) { // Get packet size ReceivePacket(); - SetInt16(&buf[0], packet_len); + SetInt16(buf, 0, packet_len); return 2; } else { // Get package data - GetPacketBuf(buf); + GetPacketBuf(buf, 0); return packet_len; } case 2: // Received packet acquisition (size + buffer simultaneously) ReceivePacket(); - SetInt16(&buf[0], packet_len); - GetPacketBuf(&buf[2]); + SetInt16(buf, 0, packet_len); + GetPacketBuf(buf, 2); return packet_len + 2; case 3: { @@ -159,14 +151,11 @@ int SCSIBR::GetMessage10(const vector& cdb, BYTE *buf) int total_len = 0; for (int i = 0; i < 10; i++) { ReceivePacket(); - SetInt16(&buf[0], packet_len); - // TODO Callee should not modify buffer pointer - buf += 2; + SetInt16(buf, total_len, packet_len); total_len += 2; if (packet_len == 0) break; - GetPacketBuf(buf); - buf += packet_len; + GetPacketBuf(buf, 0); total_len += packet_len; } return total_len; @@ -203,7 +192,7 @@ int SCSIBR::GetMessage10(const vector& cdb, BYTE *buf) return 0; } -bool SCSIBR::WriteBytes(const vector& cdb, BYTE *buf, uint64_t) +bool SCSIBR::WriteBytes(const vector& cdb, vector& buf, uint64_t) { // Type int type = cdb[2]; @@ -215,11 +204,7 @@ bool SCSIBR::WriteBytes(const vector& cdb, BYTE *buf, uint64_t) int phase = cdb[9]; // Get the number of lights - int len = cdb[6]; - len <<= 8; - len |= cdb[7]; - len <<= 8; - len |= cdb[8]; + int len = GetInt24(cdb, 6); switch (type) { case 1: // Ethernet @@ -229,11 +214,11 @@ bool SCSIBR::WriteBytes(const vector& cdb, BYTE *buf, uint64_t) } switch (func) { - case 0: // MAC address setting + case 0: SetMacAddr(buf); return true; - case 1: // Send packet + case 1: SendPacket(buf, len); return true; @@ -267,14 +252,10 @@ bool SCSIBR::WriteBytes(const vector& cdb, BYTE *buf, uint64_t) void SCSIBR::GetMessage10() { - // Reallocate buffer (because it is not transfer for each block) - if (ctrl->bufsize < 0x1000000) { - delete[] ctrl->buffer; - ctrl->bufsize = 0x1000000; - ctrl->buffer = new BYTE[ctrl->bufsize]; - } + // Ensure a sufficient buffer size (because it is not a transfer for each block) + controller->AllocateBuffer(0x1000000); - ctrl->length = GetMessage10(ctrl->cmd, ctrl->buffer); + ctrl->length = GetMessage10(ctrl->cmd, controller->GetBuffer()); if (ctrl->length <= 0) { throw scsi_error_exception(); } @@ -295,24 +276,14 @@ void SCSIBR::GetMessage10() //--------------------------------------------------------------------------- void SCSIBR::SendMessage10() { - // Reallocate buffer (because it is not transfer for each block) - if (ctrl->bufsize < 0x1000000) { - delete[] ctrl->buffer; - ctrl->bufsize = 0x1000000; - ctrl->buffer = new BYTE[ctrl->bufsize]; - } - - // Set transfer amount - ctrl->length = ctrl->cmd[6]; - ctrl->length <<= 8; - ctrl->length |= ctrl->cmd[7]; - ctrl->length <<= 8; - ctrl->length |= ctrl->cmd[8]; - + ctrl->length = GetInt24(ctrl->cmd, 6); if (ctrl->length <= 0) { throw scsi_error_exception(); } + // Ensure a sufficient buffer size (because it is not a transfer for each block) + controller->AllocateBuffer(0x1000000); + // Set next block ctrl->blocks = 1; ctrl->next = 1; @@ -320,39 +291,36 @@ void SCSIBR::SendMessage10() EnterDataOutPhase(); } -int SCSIBR::GetMacAddr(BYTE *mac) const +int SCSIBR::GetMacAddr(vector& mac) const { - memcpy(mac, mac_addr, 6); - return 6; + memcpy(mac.data(), mac_addr.data(), mac_addr.size()); + return (int)mac_addr.size(); } -void SCSIBR::SetMacAddr(const BYTE *mac) +void SCSIBR::SetMacAddr(const vector& mac) { - memcpy(mac_addr, mac, 6); + memcpy(mac_addr.data(), mac.data(), mac_addr.size()); } void SCSIBR::ReceivePacket() { - static const array bcast_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - // previous packet has not been received if (packet_enable) { return; } // Receive packet - packet_len = tap.Receive(packet_buf); + packet_len = tap.Receive(packet_buf.data()); // Check if received packet - if (memcmp(packet_buf, mac_addr, 6) != 0 && memcmp(packet_buf, bcast_addr.data(), bcast_addr.size()) != 0) { + if (memcmp(packet_buf.data(), mac_addr.data(), mac_addr.size()) != 0 + && memcmp(packet_buf.data(), bcast_addr.data(), bcast_addr.size()) != 0) { packet_len = 0; - return; } // Discard if it exceeds the buffer size if (packet_len > 2048) { packet_len = 0; - return; } // Store in receive buffer @@ -361,7 +329,7 @@ void SCSIBR::ReceivePacket() } } -void SCSIBR::GetPacketBuf(BYTE *buf) +void SCSIBR::GetPacketBuf(vector& buf, int index) { // Size limit int len = packet_len; @@ -370,15 +338,15 @@ void SCSIBR::GetPacketBuf(BYTE *buf) } // Copy - memcpy(buf, packet_buf, len); + memcpy(buf.data() + index, packet_buf.data(), len); // Received packet_enable = false; } -void SCSIBR::SendPacket(const BYTE *buf, int len) +void SCSIBR::SendPacket(const vector& buf, int len) { - tap.Send(buf, len); + tap.Send(buf.data(), len); } //--------------------------------------------------------------------------- @@ -386,10 +354,10 @@ void SCSIBR::SendPacket(const BYTE *buf, int len) // $40 - Device Boot // //--------------------------------------------------------------------------- -void SCSIBR::FS_InitDevice(BYTE *buf) +void SCSIBR::FS_InitDevice(vector& buf) { fs.Reset(); - fsresult = fs.InitDevice((Human68k::argument_t*)buf); + fsresult = fs.InitDevice((Human68k::argument_t*)buf.data()); } //--------------------------------------------------------------------------- @@ -397,13 +365,13 @@ void SCSIBR::FS_InitDevice(BYTE *buf) // $41 - Directory Check // //--------------------------------------------------------------------------- -void SCSIBR::FS_CheckDir(BYTE *buf) +void SCSIBR::FS_CheckDir(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); fsresult = fs.CheckDir(nUnit, pNamests); } @@ -413,13 +381,13 @@ void SCSIBR::FS_CheckDir(BYTE *buf) // $42 - Create Directory // //--------------------------------------------------------------------------- -void SCSIBR::FS_MakeDir(BYTE *buf) +void SCSIBR::FS_MakeDir(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); fsresult = fs.MakeDir(nUnit, pNamests); } @@ -429,13 +397,13 @@ void SCSIBR::FS_MakeDir(BYTE *buf) // $43 - Remove Directory // //--------------------------------------------------------------------------- -void SCSIBR::FS_RemoveDir(BYTE *buf) +void SCSIBR::FS_RemoveDir(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); fsresult = fs.RemoveDir(nUnit, pNamests); } @@ -445,16 +413,16 @@ void SCSIBR::FS_RemoveDir(BYTE *buf) // $44 - Rename // //--------------------------------------------------------------------------- -void SCSIBR::FS_Rename(BYTE *buf) +void SCSIBR::FS_Rename(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); i += sizeof(Human68k::namests_t); - const Human68k::namests_t *pNamestsNew = (Human68k::namests_t*)&buf[i]; + const Human68k::namests_t *pNamestsNew = (Human68k::namests_t*)&(buf.data()[i]); fsresult = fs.Rename(nUnit, pNamests, pNamestsNew); } @@ -464,13 +432,13 @@ void SCSIBR::FS_Rename(BYTE *buf) // $45 - Delete File // //--------------------------------------------------------------------------- -void SCSIBR::FS_Delete(BYTE *buf) +void SCSIBR::FS_Delete(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - const auto *pNamests = (Human68k::namests_t*)&buf[i]; + const auto *pNamests = (Human68k::namests_t*)&(buf.data()[i]); fsresult = fs.Delete(nUnit, pNamests); } @@ -480,17 +448,17 @@ void SCSIBR::FS_Delete(BYTE *buf) // $46 - Get / Set file attributes // //--------------------------------------------------------------------------- -void SCSIBR::FS_Attribute(BYTE *buf) +void SCSIBR::FS_Attribute(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); i += sizeof(Human68k::namests_t); - dp = (DWORD*)&buf[i]; - DWORD nHumanAttribute = ntohl(*dp); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nHumanAttribute = ntohl(*dp); fsresult = fs.Attribute(nUnit, pNamests, nHumanAttribute); } @@ -500,20 +468,20 @@ void SCSIBR::FS_Attribute(BYTE *buf) // $47 - File Search // //--------------------------------------------------------------------------- -void SCSIBR::FS_Files(BYTE *buf) +void SCSIBR::FS_Files(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nKey = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nKey = ntohl(*dp); + i += sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); i += sizeof(Human68k::namests_t); - auto files = (Human68k::files_t*)&buf[i]; + auto files = (Human68k::files_t*)&(buf.data()[i]); files->sector = ntohl(files->sector); files->offset = ntohs(files->offset); @@ -541,17 +509,17 @@ void SCSIBR::FS_Files(BYTE *buf) // $48 - File next search // //--------------------------------------------------------------------------- -void SCSIBR::FS_NFiles(BYTE *buf) +void SCSIBR::FS_NFiles(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nKey = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nKey = ntohl(*dp); + i += sizeof(uint32_t); - auto files = (Human68k::files_t*)&buf[i]; + auto files = (Human68k::files_t*)&(buf.data()[i]); files->sector = ntohl(files->sector); files->offset = ntohs(files->offset); @@ -579,28 +547,28 @@ void SCSIBR::FS_NFiles(BYTE *buf) // $49 - File Creation // //--------------------------------------------------------------------------- -void SCSIBR::FS_Create(BYTE *buf) +void SCSIBR::FS_Create(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nKey = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nKey = ntohl(*dp); + i += sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); i += sizeof(Human68k::namests_t); - auto pFcb = (Human68k::fcb_t*)&buf[i]; + auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); - dp = (DWORD*)&buf[i]; - DWORD nAttribute = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nAttribute = ntohl(*dp); + i += sizeof(uint32_t); - auto bp = (int*)&buf[i]; - DWORD bForce = ntohl(*bp); + auto bp = (int*)&(buf.data()[i]); + uint32_t bForce = ntohl(*bp); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -628,20 +596,20 @@ void SCSIBR::FS_Create(BYTE *buf) // $4A - Open File // //--------------------------------------------------------------------------- -void SCSIBR::FS_Open(BYTE *buf) +void SCSIBR::FS_Open(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nKey = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nKey = ntohl(*dp); + i += sizeof(uint32_t); - const auto pNamests = (Human68k::namests_t*)&buf[i]; + const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); i += sizeof(Human68k::namests_t); - auto pFcb = (Human68k::fcb_t*)&buf[i]; + auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -669,17 +637,17 @@ void SCSIBR::FS_Open(BYTE *buf) // $4B - Close File // //--------------------------------------------------------------------------- -void SCSIBR::FS_Close(BYTE *buf) +void SCSIBR::FS_Close(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nKey = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nKey = ntohl(*dp); + i += sizeof(uint32_t); - auto pFcb = (Human68k::fcb_t*)&buf[i]; + auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -707,17 +675,17 @@ void SCSIBR::FS_Close(BYTE *buf) // $4C - Read File // //--------------------------------------------------------------------------- -void SCSIBR::FS_Read(BYTE *buf) +void SCSIBR::FS_Read(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nKey = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nKey = ntohl(*dp); + int i = sizeof(uint32_t); - auto pFcb = (Human68k::fcb_t*)&buf[i]; + auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); - dp = (DWORD*)&buf[i]; - DWORD nSize = ntohl(*dp); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nSize = ntohl(*dp); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -725,7 +693,7 @@ void SCSIBR::FS_Read(BYTE *buf) pFcb->date = ntohs(pFcb->date); pFcb->size = ntohl(pFcb->size); - fsresult = fs.Read(nKey, pFcb, fsopt, nSize); + fsresult = fs.Read(nKey, pFcb, fsopt.data(), nSize); pFcb->fileptr = htonl(pFcb->fileptr); pFcb->mode = htons(pFcb->mode); @@ -747,17 +715,17 @@ void SCSIBR::FS_Read(BYTE *buf) // $4D - Write file // //--------------------------------------------------------------------------- -void SCSIBR::FS_Write(BYTE *buf) +void SCSIBR::FS_Write(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nKey = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nKey = ntohl(*dp); + int i = sizeof(uint32_t); - auto pFcb = (Human68k::fcb_t*)&buf[i]; + auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); - dp = (DWORD*)&buf[i]; - DWORD nSize = ntohl(*dp); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nSize = ntohl(*dp); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -765,7 +733,7 @@ void SCSIBR::FS_Write(BYTE *buf) pFcb->date = ntohs(pFcb->date); pFcb->size = ntohl(pFcb->size); - fsresult = fs.Write(nKey, pFcb, fsopt, nSize); + fsresult = fs.Write(nKey, pFcb, fsopt.data(), nSize); pFcb->fileptr = htonl(pFcb->fileptr); pFcb->mode = htons(pFcb->mode); @@ -785,20 +753,20 @@ void SCSIBR::FS_Write(BYTE *buf) // $4E - Seek file // //--------------------------------------------------------------------------- -void SCSIBR::FS_Seek(BYTE *buf) +void SCSIBR::FS_Seek(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nKey = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nKey = ntohl(*dp); + int i = sizeof(uint32_t); - auto pFcb = (Human68k::fcb_t*)&buf[i]; + auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); - dp = (DWORD*)&buf[i]; - DWORD nMode = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nMode = ntohl(*dp); + i += sizeof(uint32_t); - auto ip = (const int*)&buf[i]; + auto ip = (const int*)&(buf.data()[i]); int nOffset = ntohl(*ip); pFcb->fileptr = ntohl(pFcb->fileptr); @@ -827,21 +795,21 @@ void SCSIBR::FS_Seek(BYTE *buf) // $4F - File Timestamp Get / Set // //--------------------------------------------------------------------------- -void SCSIBR::FS_TimeStamp(BYTE *buf) +void SCSIBR::FS_TimeStamp(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nKey = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nKey = ntohl(*dp); + i += sizeof(uint32_t); - auto pFcb = (Human68k::fcb_t*)&buf[i]; + auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); - dp = (DWORD*)&buf[i]; - DWORD nHumanTime = ntohl(*dp); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nHumanTime = ntohl(*dp); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -869,10 +837,10 @@ void SCSIBR::FS_TimeStamp(BYTE *buf) // $50 - Get Capacity // //--------------------------------------------------------------------------- -void SCSIBR::FS_GetCapacity(BYTE *buf) +void SCSIBR::FS_GetCapacity(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); Human68k::capacity_t cap; fsresult = fs.GetCapacity(nUnit, &cap); @@ -882,7 +850,7 @@ void SCSIBR::FS_GetCapacity(BYTE *buf) cap.sectors = htons(cap.sectors); cap.bytes = htons(cap.bytes); - memcpy(fsout, &cap, sizeof(Human68k::capacity_t)); + memcpy(fsout.data(), &cap, sizeof(Human68k::capacity_t)); fsoutlen = sizeof(Human68k::capacity_t); } @@ -891,17 +859,17 @@ void SCSIBR::FS_GetCapacity(BYTE *buf) // $51 - Drive status inspection/control // //--------------------------------------------------------------------------- -void SCSIBR::FS_CtrlDrive(BYTE *buf) +void SCSIBR::FS_CtrlDrive(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - auto pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i]; + auto pCtrlDrive = (Human68k::ctrldrive_t*)&(buf.data()[i]); fsresult = fs.CtrlDrive(nUnit, pCtrlDrive); - memcpy(fsout, pCtrlDrive, sizeof(Human68k::ctrldrive_t)); + memcpy(fsout.data(), pCtrlDrive, sizeof(Human68k::ctrldrive_t)); fsoutlen = sizeof(Human68k::ctrldrive_t); } @@ -910,10 +878,10 @@ void SCSIBR::FS_CtrlDrive(BYTE *buf) // $52 - Get DPB // //--------------------------------------------------------------------------- -void SCSIBR::FS_GetDPB(BYTE *buf) +void SCSIBR::FS_GetDPB(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); Human68k::dpb_t dpb; fsresult = fs.GetDPB(nUnit, &dpb); @@ -925,7 +893,7 @@ void SCSIBR::FS_GetDPB(BYTE *buf) dpb.cluster_max = htons(dpb.cluster_max); dpb.root_sector = htons(dpb.root_sector); - memcpy(fsout, &dpb, sizeof(Human68k::dpb_t)); + memcpy(fsout.data(), &dpb, sizeof(Human68k::dpb_t)); fsoutlen = sizeof(Human68k::dpb_t); } @@ -934,20 +902,20 @@ void SCSIBR::FS_GetDPB(BYTE *buf) // $53 - Read Sector // //--------------------------------------------------------------------------- -void SCSIBR::FS_DiskRead(BYTE *buf) +void SCSIBR::FS_DiskRead(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nSector = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nSector = ntohl(*dp); + i += sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nSize = ntohl(*dp); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nSize = ntohl(*dp); - fsresult = fs.DiskRead(nUnit, fsout, nSector, nSize); + fsresult = fs.DiskRead(nUnit, fsout.data(), nSector, nSize); fsoutlen = 0x200; } @@ -956,10 +924,10 @@ void SCSIBR::FS_DiskRead(BYTE *buf) // $54 - Write Sector // //--------------------------------------------------------------------------- -void SCSIBR::FS_DiskWrite(BYTE *buf) +void SCSIBR::FS_DiskWrite(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); fsresult = fs.DiskWrite(nUnit); } @@ -969,17 +937,17 @@ void SCSIBR::FS_DiskWrite(BYTE *buf) // $55 - IOCTRL // //--------------------------------------------------------------------------- -void SCSIBR::FS_Ioctrl(BYTE *buf) +void SCSIBR::FS_Ioctrl(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); - int i = sizeof(DWORD); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); + int i = sizeof(uint32_t); - dp = (DWORD*)&buf[i]; - DWORD nFunction = ntohl(*dp); - i += sizeof(DWORD); + dp = (uint32_t*)&(buf.data()[i]); + uint32_t nFunction = ntohl(*dp); + i += sizeof(uint32_t); - auto pIoctrl = (Human68k::ioctrl_t*)&buf[i]; + auto pIoctrl = (Human68k::ioctrl_t*)&(buf.data()[i]); switch (nFunction) { case 2: @@ -1015,10 +983,10 @@ void SCSIBR::FS_Ioctrl(BYTE *buf) // $56 - Flush // //--------------------------------------------------------------------------- -void SCSIBR::FS_Flush(BYTE *buf) +void SCSIBR::FS_Flush(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); fsresult = fs.Flush(nUnit); } @@ -1028,10 +996,10 @@ void SCSIBR::FS_Flush(BYTE *buf) // $57 - Check Media // //--------------------------------------------------------------------------- -void SCSIBR::FS_CheckMedia(BYTE *buf) +void SCSIBR::FS_CheckMedia(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); fsresult = fs.CheckMedia(nUnit); } @@ -1041,10 +1009,10 @@ void SCSIBR::FS_CheckMedia(BYTE *buf) // $58 - Lock // //--------------------------------------------------------------------------- -void SCSIBR::FS_Lock(BYTE *buf) +void SCSIBR::FS_Lock(vector& buf) { - auto dp = (DWORD*)buf; - DWORD nUnit = ntohl(*dp); + auto dp = (uint32_t*)buf.data(); + uint32_t nUnit = ntohl(*dp); fsresult = fs.Lock(nUnit); } @@ -1054,11 +1022,11 @@ void SCSIBR::FS_Lock(BYTE *buf) // Read Filesystem (result code) // //--------------------------------------------------------------------------- -int SCSIBR::ReadFsResult(BYTE *buf) const +int SCSIBR::ReadFsResult(vector& buf) const { - auto dp = (DWORD*)buf; + auto dp = (uint32_t *)buf.data(); *dp = htonl(fsresult); - return sizeof(DWORD); + return sizeof(uint32_t); } //--------------------------------------------------------------------------- @@ -1066,9 +1034,9 @@ int SCSIBR::ReadFsResult(BYTE *buf) const // Read Filesystem (return data) // //--------------------------------------------------------------------------- -int SCSIBR::ReadFsOut(BYTE *buf) const +int SCSIBR::ReadFsOut(vector& buf) const { - memcpy(buf, fsout, fsoutlen); + copy_n(fsout.begin(), fsoutlen, buf.begin()); return fsoutlen; } @@ -1077,9 +1045,9 @@ int SCSIBR::ReadFsOut(BYTE *buf) const // Read file system (return option data) // //--------------------------------------------------------------------------- -int SCSIBR::ReadFsOpt(BYTE *buf) const +int SCSIBR::ReadFsOpt(vector& buf) const { - memcpy(buf, fsopt, fsoptlen); + copy_n(fsopt.begin(), fsoptlen, buf.begin()); return fsoptlen; } @@ -1088,7 +1056,7 @@ int SCSIBR::ReadFsOpt(BYTE *buf) const // Write Filesystem // //--------------------------------------------------------------------------- -void SCSIBR::WriteFs(int func, BYTE *buf) +void SCSIBR::WriteFs(int func, vector& buf) { fsresult = FS_FATAL_INVALIDCOMMAND; fsoutlen = 0; @@ -1096,32 +1064,83 @@ void SCSIBR::WriteFs(int func, BYTE *buf) func &= 0x1f; switch (func) { - case 0x00: return FS_InitDevice(buf); // $40 - start device - case 0x01: return FS_CheckDir(buf); // $41 - directory check - case 0x02: return FS_MakeDir(buf); // $42 - create directory - case 0x03: return FS_RemoveDir(buf); // $43 - remove directory - case 0x04: return FS_Rename(buf); // $44 - change file name - case 0x05: return FS_Delete(buf); // $45 - delete file - case 0x06: return FS_Attribute(buf); // $46 - Get/set file attribute - case 0x07: return FS_Files(buf); // $47 - file search - case 0x08: return FS_NFiles(buf); // $48 - next file search - case 0x09: return FS_Create(buf); // $49 - create file - case 0x0A: return FS_Open(buf); // $4A - File open - case 0x0B: return FS_Close(buf); // $4B - File close - case 0x0C: return FS_Read(buf); // $4C - read file - case 0x0D: return FS_Write(buf); // $4D - write file - case 0x0E: return FS_Seek(buf); // $4E - File seek - case 0x0F: return FS_TimeStamp(buf); // $4F - Get/set file modification time - case 0x10: return FS_GetCapacity(buf); // $50 - get capacity - case 0x11: return FS_CtrlDrive(buf); // $51 - Drive control/state check - case 0x12: return FS_GetDPB(buf); // $52 - Get DPB - case 0x13: return FS_DiskRead(buf); // $53 - read sector - case 0x14: return FS_DiskWrite(buf); // $54 - write sector - case 0x15: return FS_Ioctrl(buf); // $55 - IOCTRL - case 0x16: return FS_Flush(buf); // $56 - flush - case 0x17: return FS_CheckMedia(buf); // $57 - check media exchange - case 0x18: return FS_Lock(buf); // $58 - exclusive control - default: break; + case 0x00: + FS_InitDevice(buf); // $40 - start device + break; + case 0x01: + FS_CheckDir(buf); // $41 - directory check + break; + case 0x02: + FS_MakeDir(buf); // $42 - create directory + break; + case 0x03: + FS_RemoveDir(buf); // $43 - remove directory + break; + case 0x04: + FS_Rename(buf); // $44 - change file name + break; + case 0x05: + FS_Delete(buf); // $45 - delete file + break; + case 0x06: + FS_Attribute(buf); // $46 - Get/set file attribute + break; + case 0x07: + FS_Files(buf); // $47 - file search + break; + case 0x08: + FS_NFiles(buf); // $48 - next file search + break; + case 0x09: + FS_Create(buf); // $49 - create file + break; + case 0x0A: + FS_Open(buf); // $4A - File open + break; + case 0x0B: + FS_Close(buf); // $4B - File close + break; + case 0x0C: + FS_Read(buf); // $4C - read file + break; + case 0x0D: + FS_Write(buf); // $4D - write file + break; + case 0x0E: + FS_Seek(buf); // $4E - File seek + break; + case 0x0F: + FS_TimeStamp(buf); // $4F - Get/set file modification time + break; + case 0x10: + FS_GetCapacity(buf); // $50 - get capacity + break; + case 0x11: + FS_CtrlDrive(buf); // $51 - Drive control/state check + break; + case 0x12: + FS_GetDPB(buf); // $52 - Get DPB + break; + case 0x13: + FS_DiskRead(buf); // $53 - read sector + break; + case 0x14: + FS_DiskWrite(buf); // $54 - write sector + break; + case 0x15: + FS_Ioctrl(buf); // $55 - IOCTRL + break; + case 0x16: + FS_Flush(buf); // $56 - flush + break; + case 0x17: + FS_CheckMedia(buf); // $57 - check media exchange + break; + case 0x18: + FS_Lock(buf); // $58 - exclusive control + break; + default: + break; } } @@ -1130,7 +1149,7 @@ void SCSIBR::WriteFs(int func, BYTE *buf) // File system write (input option data) // //--------------------------------------------------------------------------- -void SCSIBR::WriteFsOpt(const BYTE *buf, int num) +void SCSIBR::WriteFsOpt(const vector& buf, int num) { - memcpy(fsopt, buf, num); + copy_n(buf.begin(), num, fsopt.begin()); } diff --git a/src/raspberrypi/devices/scsi_host_bridge.h b/src/raspberrypi/devices/scsi_host_bridge.h index 4fb4efea..937fad3b 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.h +++ b/src/raspberrypi/devices/scsi_host_bridge.h @@ -22,13 +22,18 @@ #include "ctapdriver.h" #include "cfilesystem.h" #include +#include + +using namespace std; //NOSONAR Not relevant for rascsi class SCSIBR final : public Disk { + static constexpr const array bcast_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + public: SCSIBR(); - ~SCSIBR() override; + ~SCSIBR() override = default; SCSIBR(SCSIBR&) = delete; SCSIBR& operator=(const SCSIBR&) = delete; @@ -37,8 +42,8 @@ public: // Commands vector InquiryInternal() const override; - int GetMessage10(const vector&, BYTE *); - bool WriteBytes(const vector&, BYTE *, uint64_t); + int GetMessage10(const vector&, vector&); + bool WriteBytes(const vector&, vector&, uint64_t); void TestUnitReady() override; void GetMessage10(); void SendMessage10(); @@ -49,56 +54,56 @@ private: Dispatcher dispatcher; - int GetMacAddr(BYTE *buf) const; // Get MAC address - void SetMacAddr(const BYTE *buf); // Set MAC address + int GetMacAddr(vector&) const; // Get MAC address + void SetMacAddr(const vector&); // Set MAC address void ReceivePacket(); // Receive a packet - void GetPacketBuf(BYTE *buf); // Get a packet - void SendPacket(const BYTE *buf, int len); // Send a packet + void GetPacketBuf(vector&, int); // Get a packet + void SendPacket(const vector&, int); // Send a packet CTapDriver tap; // TAP driver bool m_bTapEnable = false; // TAP valid flag - BYTE mac_addr[6]; // MAC Addres + array mac_addr = {}; // MAC Address int packet_len = 0; // Receive packet size - BYTE packet_buf[0x1000]; // Receive packet buffer + array packet_buf; // Receive packet buffer bool packet_enable = false; // Received packet valid - int ReadFsResult(BYTE *buf) const; // Read filesystem (result code) - int ReadFsOut(BYTE *buf) const; // Read filesystem (return data) - int ReadFsOpt(BYTE *buf) const; // Read file system (optional data) - void WriteFs(int func, BYTE *buf); // File system write (execute) - void WriteFsOpt(const BYTE *buf, int len); // File system write (optional data) + int ReadFsResult(vector&) const; // Read filesystem (result code) + int ReadFsOut(vector&) const; // Read filesystem (return data) + int ReadFsOpt(vector&) const; // Read file system (optional data) + void WriteFs(int, vector&); // File system write (execute) + void WriteFsOpt(const vector&, int); // File system write (optional data) // Command handlers - void FS_InitDevice(BYTE *buf); // $40 - boot - void FS_CheckDir(BYTE *buf); // $41 - directory check - void FS_MakeDir(BYTE *buf); // $42 - create directory - void FS_RemoveDir(BYTE *buf); // $43 - delete directory - void FS_Rename(BYTE *buf); // $44 - change filename - void FS_Delete(BYTE *buf); // $45 - delete file - void FS_Attribute(BYTE *buf); // $46 - get/set file attributes - void FS_Files(BYTE *buf); // $47 - file search - void FS_NFiles(BYTE *buf); // $48 - find next file - void FS_Create(BYTE *buf); // $49 - create file - void FS_Open(BYTE *buf); // $4A - open file - void FS_Close(BYTE *buf); // $4B - close file - void FS_Read(BYTE *buf); // $4C - read file - void FS_Write(BYTE *buf); // $4D - write file - void FS_Seek(BYTE *buf); // $4E - seek file - void FS_TimeStamp(BYTE *buf); // $4F - get/set file time - void FS_GetCapacity(BYTE *buf); // $50 - get capacity - void FS_CtrlDrive(BYTE *buf); // $51 - drive status check/control - void FS_GetDPB(BYTE *buf); // $52 - get DPB - void FS_DiskRead(BYTE *buf); // $53 - read sector - void FS_DiskWrite(BYTE *buf); // $54 - write sector - void FS_Ioctrl(BYTE *buf); // $55 - IOCTRL - void FS_Flush(BYTE *buf); // $56 - flush cache - void FS_CheckMedia(BYTE *buf); // $57 - check media - void FS_Lock(BYTE *buf); // $58 - get exclusive control + void FS_InitDevice(vector&); // $40 - boot + void FS_CheckDir(vector&); // $41 - directory check + void FS_MakeDir(vector&); // $42 - create directory + void FS_RemoveDir(vector&); // $43 - delete directory + void FS_Rename(vector&); // $44 - change filename + void FS_Delete(vector&); // $45 - delete file + void FS_Attribute(vector&); // $46 - get/set file attributes + void FS_Files(vector&); // $47 - file search + void FS_NFiles(vector&); // $48 - find next file + void FS_Create(vector&); // $49 - create file + void FS_Open(vector&); // $4A - open file + void FS_Close(vector&); // $4B - close file + void FS_Read(vector&); // $4C - read file + void FS_Write(vector&); // $4D - write file + void FS_Seek(vector&); // $4E - seek file + void FS_TimeStamp(vector&); // $4F - get/set file time + void FS_GetCapacity(vector&); // $50 - get capacity + void FS_CtrlDrive(vector&); // $51 - drive status check/control + void FS_GetDPB(vector&); // $52 - get DPB + void FS_DiskRead(vector&); // $53 - read sector + void FS_DiskWrite(vector&); // $54 - write sector + void FS_Ioctrl(vector&); // $55 - IOCTRL + void FS_Flush(vector&); // $56 - flush cache + void FS_CheckMedia(vector&); // $57 - check media + void FS_Lock(vector&); // $58 - get exclusive control CFileSys fs; // File system accessor DWORD fsresult = 0; // File system access result code - BYTE fsout[0x800]; // File system access result buffer + array fsout; // File system access result buffer DWORD fsoutlen = 0; // File system access result buffer size - BYTE fsopt[0x1000000]; // File system access buffer + array fsopt; // File system access buffer DWORD fsoptlen = 0; // File system access buffer size }; diff --git a/src/raspberrypi/devices/scsi_printer.cpp b/src/raspberrypi/devices/scsi_printer.cpp index 475d9c55..7a116c2a 100644 --- a/src/raspberrypi/devices/scsi_printer.cpp +++ b/src/raspberrypi/devices/scsi_printer.cpp @@ -41,6 +41,7 @@ #include #include "rascsi_exceptions.h" +#include "scsi_command_util.h" #include "../rasutil.h" #include "dispatcher.h" #include "scsi_printer.h" @@ -48,6 +49,7 @@ using namespace std; using namespace scsi_defs; using namespace ras_util; +using namespace scsi_command_util; SCSIPrinter::SCSIPrinter() : PrimaryDevice("SCLP") { @@ -143,18 +145,13 @@ void SCSIPrinter::Print() { CheckReservation(); - uint32_t length = ctrl->cmd[2]; - length <<= 8; - length |= ctrl->cmd[3]; - length <<= 8; - length |= ctrl->cmd[4]; + uint32_t length = GetInt24(ctrl->cmd, 2); LOGTRACE("Receiving %d byte(s) to be printed", length) - // TODO This device suffers from the statically allocated buffer size, - // see https://github.com/akuker/RASCSI/issues/669 - if (length > (uint32_t)ctrl->bufsize) { - LOGERROR("Transfer buffer overflow") + if (length > controller->GetBufferSize()) { + LOGERROR("%s", string("Transfer buffer overflow: Buffer size is " + to_string(controller->GetBufferSize()) + + " bytes, " + to_string(length) + " bytes expected").c_str()) throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } @@ -217,7 +214,7 @@ void SCSIPrinter::StopPrint() TestUnitReady(); } -bool SCSIPrinter::WriteByteSequence(BYTE *buf, uint32_t length) +bool SCSIPrinter::WriteByteSequence(vector& buf, uint32_t length) { if (fd == -1) { strcpy(filename, TMP_FILE_PATTERN); @@ -232,7 +229,7 @@ bool SCSIPrinter::WriteByteSequence(BYTE *buf, uint32_t length) LOGTRACE("Appending %d byte(s) to printer output file '%s'", length, filename) - auto num_written = (uint32_t)write(fd, buf, length); + auto num_written = (uint32_t)write(fd, buf.data(), length); return num_written == length; } diff --git a/src/raspberrypi/devices/scsi_printer.h b/src/raspberrypi/devices/scsi_printer.h index afeaf72d..1fd0f55b 100644 --- a/src/raspberrypi/devices/scsi_printer.h +++ b/src/raspberrypi/devices/scsi_printer.h @@ -42,7 +42,7 @@ public: void SendDiagnostic() override; void StopPrint(); - bool WriteByteSequence(BYTE *, uint32_t) override; + bool WriteByteSequence(vector&, uint32_t) override; void CheckReservation(); void DiscardReservation(); void Cleanup(); diff --git a/src/raspberrypi/devices/scsicd.cpp b/src/raspberrypi/devices/scsicd.cpp index a1971a08..b076582c 100644 --- a/src/raspberrypi/devices/scsicd.cpp +++ b/src/raspberrypi/devices/scsicd.cpp @@ -32,11 +32,6 @@ SCSICD::SCSICD(const unordered_set& sector_sizes) : Disk("SCCD") dispatcher.Add(scsi_command::eCmdGetEventStatusNotification, "GetEventStatusNotification", &SCSICD::GetEventStatusNotification); } -SCSICD::~SCSICD() -{ - ClearTrack(); -} - bool SCSICD::Dispatch(scsi_command cmd) { // The superclass class handles the less specific commands @@ -97,8 +92,10 @@ void SCSICD::Open(const Filepath& path) super::Open(path); FileSupport::SetPath(path); + SetUpCache(path); + // Set RAW flag - disk.dcache->SetRawMode(rawfile); + cache->SetRawMode(rawfile); // Attention if ready if (IsReady()) { @@ -120,8 +117,8 @@ void SCSICD::OpenIso(const Filepath& path) } // Get file size - off_t size = fio.GetFileSize(); - if (size < 0x800) { + off_t file_size = fio.GetFileSize(); + if (file_size < 0x800) { fio.Close(); throw io_exception("ISO CD-ROM file size must be at least 2048 bytes"); } @@ -135,7 +132,7 @@ void SCSICD::OpenIso(const Filepath& path) // Check if it is RAW format array sync; - memset(sync.data(), 0xff, sync.size()); + sync.fill(0xff); sync[0] = 0x00; sync[11] = 0x00; rawfile = false; @@ -160,16 +157,16 @@ void SCSICD::OpenIso(const Filepath& path) if (rawfile) { // Size must be a multiple of 2536 - if (size % 2536) { + if (file_size % 2536) { throw io_exception("Raw ISO CD-ROM file size must be a multiple of 2536 bytes but is " - + to_string(size) + " bytes"); + + to_string(file_size) + " bytes"); } // Set the number of blocks - SetBlockCount((DWORD)(size / 0x930)); + SetBlockCount((DWORD)(file_size / 0x930)); } else { // Set the number of blocks - SetBlockCount((DWORD)(size >> GetSectorSizeShiftCount())); + SetBlockCount((DWORD)(file_size >> GetSectorSizeShiftCount())); } // Create only one data track @@ -216,7 +213,7 @@ void SCSICD::OpenPhysical(const Filepath& path) void SCSICD::ReadToc() { - ctrl->length = ReadTocInternal(ctrl->cmd, ctrl->buffer); + ctrl->length = ReadTocInternal(ctrl->cmd, controller->GetBuffer()); EnterDataInPhase(); } @@ -276,11 +273,8 @@ void SCSICD::AddVendorPage(map>& pages, int page, bool changea } } - -int SCSICD::Read(const vector& cdb, BYTE *buf, uint64_t block) +int SCSICD::Read(const vector& cdb, vector& buf, uint64_t block) { - assert(buf); - CheckReady(); // Search for the track @@ -295,10 +289,6 @@ int SCSICD::Read(const vector& cdb, BYTE *buf, uint64_t block) // If different from the current data track if (dataindex != index) { - // Delete current disk cache (no need to save) - delete disk.dcache; - disk.dcache = nullptr; - // Reset the number of blocks SetBlockCount(tracks[index]->GetBlocks()); assert(GetBlockCount() > 0); @@ -306,8 +296,9 @@ int SCSICD::Read(const vector& cdb, BYTE *buf, uint64_t block) // Recreate the disk cache Filepath path; tracks[index]->GetPath(path); - disk.dcache = new DiskCache(path, GetSectorSizeShiftCount(), (uint32_t)GetBlockCount()); - disk.dcache->SetRawMode(rawfile); + // Re-assign disk cache (no need to save) + cache.reset(new DiskCache(path, GetSectorSizeShiftCount(), (uint32_t)GetBlockCount())); + cache->SetRawMode(rawfile); // Reset data index dataindex = index; @@ -318,7 +309,7 @@ int SCSICD::Read(const vector& cdb, BYTE *buf, uint64_t block) return super::Read(cdb, buf, block); } -int SCSICD::ReadTocInternal(const vector& cdb, BYTE *buf) +int SCSICD::ReadTocInternal(const vector& cdb, vector& buf) { CheckReady(); @@ -327,9 +318,8 @@ int SCSICD::ReadTocInternal(const vector& cdb, BYTE *buf) assert(tracks[0]); // Get allocation length, clear buffer - int length = cdb[7] << 8; - length |= cdb[8]; - memset(buf, 0, length); + int length = GetInt16(cdb, 7); + fill_n(buf.data(), length, 0); // Get MSF Flag bool msf = cdb[1] & 0x02; @@ -365,7 +355,7 @@ int SCSICD::ReadTocInternal(const vector& cdb, BYTE *buf) if (msf) { LBAtoMSF(lba, &buf[8]); } else { - SetInt16(&buf[10], lba); + SetInt16(buf, 10, lba); } return length; } @@ -380,34 +370,35 @@ int SCSICD::ReadTocInternal(const vector& cdb, BYTE *buf) assert(loop >= 1); // Create header - SetInt16(&buf[0], (loop << 3) + 2); + SetInt16(buf, 0, (loop << 3) + 2); buf[2] = (BYTE)tracks[0]->GetTrackNo(); buf[3] = (BYTE)last; - buf += 4; + + int offset = 4; // Loop.... for (int i = 0; i < loop; i++) { // ADR and Control if (tracks[index]->IsAudio()) { // audio track - buf[1] = 0x10; + buf[offset + 1] = 0x10; } else { // data track - buf[1] = 0x14; + buf[offset + 1] = 0x14; } // track number - buf[2] = (BYTE)tracks[index]->GetTrackNo(); + buf[offset + 2] = (BYTE)tracks[index]->GetTrackNo(); // track address if (msf) { - LBAtoMSF(tracks[index]->GetFirst(), &buf[4]); + LBAtoMSF(tracks[index]->GetFirst(), &buf[offset + 4]); } else { - SetInt16(&buf[6], tracks[index]->GetFirst()); + SetInt16(buf, offset + 6, tracks[index]->GetFirst()); } // Advance buffer pointer and index - buf += 8; + offset += 8; index++; } diff --git a/src/raspberrypi/devices/scsicd.h b/src/raspberrypi/devices/scsicd.h index 8964d162..40d3c8e5 100644 --- a/src/raspberrypi/devices/scsicd.h +++ b/src/raspberrypi/devices/scsicd.h @@ -28,7 +28,7 @@ class SCSICD : public Disk, public ScsiMmcCommands, public FileSupport public: explicit SCSICD(const unordered_set&); - ~SCSICD() override; + ~SCSICD() override = default; SCSICD(SCSICD&) = delete; SCSICD& operator=(const SCSICD&) = delete; @@ -38,7 +38,7 @@ public: // Commands vector InquiryInternal() const override; - int Read(const vector&, BYTE *, uint64_t) override; + int Read(const vector&, vector&, uint64_t) override; protected: @@ -51,7 +51,7 @@ private: Dispatcher dispatcher; - int ReadTocInternal(const vector&, BYTE *); + int ReadTocInternal(const vector&, vector&); void AddCDROMPage(map>&, bool) const; void AddCDDAPage(map>&, bool) const; diff --git a/src/raspberrypi/devices/scsihd.cpp b/src/raspberrypi/devices/scsihd.cpp index e16289ba..7b9b3758 100644 --- a/src/raspberrypi/devices/scsihd.cpp +++ b/src/raspberrypi/devices/scsihd.cpp @@ -30,7 +30,7 @@ SCSIHD::SCSIHD(const unordered_set& sector_sizes, bool removable, scsi SetSectorSizes(sector_sizes); } -void SCSIHD::FinalizeSetup(const Filepath &path, off_t size) +void SCSIHD::FinalizeSetup(const Filepath &path, off_t size, off_t image_offset) { // 2TB is the current maximum if (size > 2LL * 1024 * 1024 * 1024 * 1024) { @@ -60,6 +60,8 @@ void SCSIHD::FinalizeSetup(const Filepath &path, off_t size) Disk::Open(path); FileSupport::SetPath(path); + + SetUpCache(path, image_offset); } void SCSIHD::Open(const Filepath& path) @@ -73,17 +75,17 @@ void SCSIHD::Open(const Filepath& path) } // Get file size - off_t size = fio.GetFileSize(); + off_t file_size = fio.GetFileSize(); fio.Close(); // Sector size (default 512 bytes) and number of blocks SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512); - SetBlockCount((DWORD)(size >> GetSectorSizeShiftCount())); + SetBlockCount((DWORD)(file_size >> GetSectorSizeShiftCount())); // Effective size must be a multiple of the sector size - size = (size / GetSectorSizeInBytes()) * GetSectorSizeInBytes(); + file_size = (file_size / GetSectorSizeInBytes()) * GetSectorSizeInBytes(); - FinalizeSetup(path, size); + FinalizeSetup(path, file_size); } vector SCSIHD::InquiryInternal() const @@ -91,7 +93,7 @@ vector SCSIHD::InquiryInternal() const return HandleInquiry(device_type::DIRECT_ACCESS, scsi_level, IsRemovable()); } -void SCSIHD::ModeSelect(const vector& cdb, const BYTE *buf, int length) const +void SCSIHD::ModeSelect(const vector& cdb, const vector& buf, int length) const { scsi_command_util::ModeSelect(cdb, buf, length, 1 << GetSectorSizeShiftCount()); } diff --git a/src/raspberrypi/devices/scsihd.h b/src/raspberrypi/devices/scsihd.h index da4553f9..7b19c3f7 100644 --- a/src/raspberrypi/devices/scsihd.h +++ b/src/raspberrypi/devices/scsihd.h @@ -31,13 +31,13 @@ public: SCSIHD(SCSIHD&) = delete; SCSIHD& operator=(const SCSIHD&) = delete; - void FinalizeSetup(const Filepath&, off_t); + void FinalizeSetup(const Filepath&, off_t, off_t = 0); void Open(const Filepath&) override; // Commands vector InquiryInternal() const override; - void ModeSelect(const vector&, const BYTE *, int) const override; + void ModeSelect(const vector&, const vector&, int) const override; void AddFormatPage(map>&, bool) const 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 89b15647..3ca9dbdf 100644 --- a/src/raspberrypi/devices/scsihd_nec.cpp +++ b/src/raspberrypi/devices/scsihd_nec.cpp @@ -30,7 +30,7 @@ const unordered_set SCSIHD_NEC::sector_sizes = { 512 }; //--------------------------------------------------------------------------- static inline int getWordLE(const BYTE *b) { - return (b[1] << 8) | b[0]; + return ((int)b[1] << 8) | (int)b[0]; } //--------------------------------------------------------------------------- @@ -38,9 +38,9 @@ static inline int getWordLE(const BYTE *b) // Extract longwords assumed to be little endian // //--------------------------------------------------------------------------- -static inline DWORD getDwordLE(const BYTE *b) +static inline uint32_t getDwordLE(const BYTE *b) { - return ((DWORD)(b[3]) << 24) | ((DWORD)(b[2]) << 16) | ((DWORD)(b[1]) << 8) | b[0]; + return ((uint32_t)(b[3]) << 24) | ((uint32_t)(b[2]) << 16) | ((uint32_t)(b[1]) << 8) | b[0]; } void SCSIHD_NEC::Open(const Filepath& path) @@ -54,18 +54,18 @@ void SCSIHD_NEC::Open(const Filepath& path) } // Get file size - off_t size = fio.GetFileSize(); + off_t file_size = fio.GetFileSize(); // NEC root sector array root_sector; - if (size >= (off_t)root_sector.size() && !fio.Read(root_sector.data(), root_sector.size())) { + if (file_size >= (off_t)root_sector.size() && !fio.Read(root_sector.data(), root_sector.size())) { fio.Close(); throw io_exception("Can't read NEC hard disk file root sector"); } fio.Close(); // Effective size must be a multiple of 512 - size = (size / 512) * 512; + file_size = (file_size / 512) * 512; int image_size = 0; int sector_size = 0; @@ -75,18 +75,18 @@ void SCSIHD_NEC::Open(const Filepath& path) // PC-9801-55 NEC genuine? if (const char *ext = path.GetFileExt(); !strcasecmp(ext, ".hdn")) { // Assuming sector size 512, number of sectors 25, number of heads 8 as default settings - disk.image_offset = 0; - image_size = (int)size; + image_offset = 0; + image_size = (int)file_size; sector_size = 512; sectors = 25; heads = 8; - cylinders = (int)(size >> 9); + cylinders = (int)(file_size >> 9); cylinders >>= 3; cylinders /= 25; } // Anex86 HD image? else if (!strcasecmp(ext, ".hdi")) { - disk.image_offset = getDwordLE(&root_sector[8]); + image_offset = getDwordLE(&root_sector[8]); image_size = getDwordLE(&root_sector[12]); sector_size = getDwordLE(&root_sector[16]); sectors = getDwordLE(&root_sector[20]); @@ -96,7 +96,7 @@ void SCSIHD_NEC::Open(const Filepath& path) // T98Next HD image? else if (!strcasecmp(ext, ".nhd")) { if (!memcmp(root_sector.data(), "T98HDDIMAGE.R0\0", 15)) { - disk.image_offset = getDwordLE(&root_sector[0x110]); + image_offset = getDwordLE(&root_sector[0x110]); cylinders = getDwordLE(&root_sector[0x114]); heads = getWordLE(&root_sector[0x118]); sectors = getWordLE(&root_sector[0x11a]); @@ -113,24 +113,23 @@ void SCSIHD_NEC::Open(const Filepath& path) } // Image size consistency check - if (disk.image_offset + image_size > size || image_size % sector_size != 0) { + if (image_offset + image_size > file_size || image_size % sector_size != 0) { throw io_exception("Image size consistency check failed"); } // Calculate sector size - for (size = 16; size > 0; --size) { - if ((1 << size) == sector_size) + for (file_size = 16; file_size > 0; --file_size) { + if ((1 << file_size) == sector_size) break; } - if (size <= 0 || size > 16) { + if (file_size <= 0 || file_size > 16) { throw io_exception("Invalid NEC disk size"); } - SetSectorSizeShiftCount((uint32_t)size); + SetSectorSizeShiftCount((uint32_t)file_size); - // Number of blocks - SetBlockCount(image_size >> disk.size); + SetBlockCount(image_size >> GetSectorSizeShiftCount()); - FinalizeSetup(path, size); + FinalizeSetup(path, file_size, image_offset); } vector SCSIHD_NEC::InquiryInternal() const @@ -171,7 +170,7 @@ void SCSIHD_NEC::AddFormatPage(map>& pages, bool changeable) c SetInt16(buf, 0x0a, sectors); // Set the number of bytes in the physical sector - SetInt16(buf, 0x0c, 1 << disk.size); + SetInt16(buf, 0x0c, GetSectorSizeInBytes()); } // Set removable attributes (remains of the old days) diff --git a/src/raspberrypi/devices/scsihd_nec.h b/src/raspberrypi/devices/scsihd_nec.h index d132c293..a0b9dc88 100644 --- a/src/raspberrypi/devices/scsihd_nec.h +++ b/src/raspberrypi/devices/scsihd_nec.h @@ -13,9 +13,14 @@ // [ SCSI NEC "Genuine" Hard Disk] // //--------------------------------------------------------------------------- + #pragma once #include "scsihd.h" +#include +#include + +using namespace std; //NOSONAR Not relevant for rascsi //=========================================================================== // @@ -24,16 +29,14 @@ //=========================================================================== class SCSIHD_NEC : public SCSIHD { - static const unordered_set sector_sizes; - public: - explicit SCSIHD_NEC() : SCSIHD(sector_sizes, false) {} + SCSIHD_NEC() : SCSIHD(sector_sizes, false) {} ~SCSIHD_NEC() override = default; SCSIHD_NEC(SCSIHD_NEC&) = delete; SCSIHD_NEC& operator=(const SCSIHD_NEC&) = delete; - void Open(const Filepath& path) override; + void Open(const Filepath&) override; vector InquiryInternal() const override; @@ -43,6 +46,11 @@ public: private: + static const unordered_set sector_sizes; + + // Image file offset (NEC only) + off_t image_offset = 0; + // Geometry data int cylinders = 0; int heads = 0; diff --git a/src/raspberrypi/devices/scsimo.cpp b/src/raspberrypi/devices/scsimo.cpp index 2ce5cbc7..756ba3bc 100644 --- a/src/raspberrypi/devices/scsimo.cpp +++ b/src/raspberrypi/devices/scsimo.cpp @@ -7,11 +7,9 @@ // Copyright (C) 2014-2020 GIMONS // Copyright (C) akuker // -// Licensed under the BSD 3-Clause License. +// Licensed under the BSD 3-Clause License. // See LICENSE file in the project root folder. // -// [ SCSI Magneto-Optical Disk] -// //--------------------------------------------------------------------------- #include "fileio.h" @@ -21,11 +19,18 @@ using namespace scsi_command_util; -SCSIMO::SCSIMO(const unordered_set& sector_sizes, const unordered_map& geometries) - : Disk("SCMO") +SCSIMO::SCSIMO(const unordered_set& sector_sizes) : Disk("SCMO") { SetSectorSizes(sector_sizes); - SetGeometries(geometries); + + // 128 MB, 512 bytes per sector, 248826 sectors + geometries[512 * 248826] = make_pair(512, 248826); + // 230 MB, 512 bytes per block, 446325 sectors + geometries[512 * 446325] = make_pair(512, 446325); + // 540 MB, 512 bytes per sector, 1041500 sectors + geometries[512 * 1041500] = make_pair(512, 1041500); + // 640 MB, 20248 bytes per sector, 310352 sectors + geometries[2048 * 310352] = make_pair(2048, 310352); } void SCSIMO::Open(const Filepath& path) @@ -40,15 +45,14 @@ void SCSIMO::Open(const Filepath& path) } // Get file size - off_t size = fio.GetFileSize(); + off_t file_size = fio.GetFileSize(); 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)) { + // For some capacities there are hard-coded, well-defined sector sizes and block counts + if (!SetGeometryForCapacity(file_size)) { // Sector size (default 512 bytes) and number of blocks SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512); - SetBlockCount(size >> GetSectorSizeShiftCount()); + SetBlockCount(file_size >> GetSectorSizeShiftCount()); } SetReadOnly(false); @@ -58,6 +62,8 @@ void SCSIMO::Open(const Filepath& path) Disk::Open(path); FileSupport::SetPath(path); + SetUpCache(path); + // Attention if ready if (IsReady()) { SetAttn(true); @@ -94,7 +100,7 @@ void SCSIMO::AddOptionPage(map>& pages, bool) const // Do not report update blocks } -void SCSIMO::ModeSelect(const vector& cdb, const BYTE *buf, int length) const +void SCSIMO::ModeSelect(const vector& cdb, const vector& buf, int length) const { scsi_command_util::ModeSelect(cdb, buf, length, 1 << GetSectorSizeShiftCount()); } diff --git a/src/raspberrypi/devices/scsimo.h b/src/raspberrypi/devices/scsimo.h index 172b8c0d..409422f2 100644 --- a/src/raspberrypi/devices/scsimo.h +++ b/src/raspberrypi/devices/scsimo.h @@ -5,12 +5,10 @@ // // Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) // Copyright (C) 2014-2020 GIMONS -// Copyright (C) akuker +// Copyright (C) akuker // -// Licensed under the BSD 3-Clause License. -// See LICENSE file in the project root folder. -// -// [ SCSI Magneto-Optical Disk] +// Licensed under the BSD 3-Clause License. +// See LICENSE file in the project root folder. // //--------------------------------------------------------------------------- @@ -20,11 +18,13 @@ #include "file_support.h" #include "filepath.h" +using Geometry = pair; + class SCSIMO : public Disk, public FileSupport { public: - SCSIMO(const unordered_set&, const unordered_map&); + explicit SCSIMO(const unordered_set&); ~SCSIMO() override = default; SCSIMO(SCSIMO&) = delete; SCSIMO& operator=(const SCSIMO&) = delete; @@ -32,7 +32,7 @@ public: void Open(const Filepath&) override; vector InquiryInternal() const override; - void ModeSelect(const vector&, const BYTE *, int) const override; + void ModeSelect(const vector&, const vector&, int) const override; protected: @@ -44,7 +44,6 @@ private: void AddOptionPage(map>&, bool) const; - void SetGeometries(const unordered_map& g) { geometries = g; } bool SetGeometryForCapacity(uint64_t); // The mapping of supported capacities to block sizes and block counts, empty if there is no capacity restriction diff --git a/src/raspberrypi/fileio.cpp b/src/raspberrypi/fileio.cpp index 64fcd4f1..821f3316 100644 --- a/src/raspberrypi/fileio.cpp +++ b/src/raspberrypi/fileio.cpp @@ -42,10 +42,6 @@ bool Fileio::Open(const char *fname, OpenMode mode, bool directIO) break; case OpenMode::ReadWrite: - // Make sure RW does not succeed when reading from CD-ROM - if (access(fname, 0x06) != 0) { - return false; - } handle = open(fname, O_RDWR | omode); break; @@ -115,7 +111,7 @@ off_t Fileio::GetFileSize() const assert(handle >= 0); // Get file position in 64bit - off_t cur = GetFilePos(); + off_t cur = lseek(handle, 0, SEEK_CUR); // Get file size in64bitで off_t end = lseek(handle, 0, SEEK_END); @@ -126,14 +122,6 @@ off_t Fileio::GetFileSize() const return end; } -off_t Fileio::GetFilePos() const -{ - assert(handle >= 0); - - // Get file position in 64bit - return lseek(handle, 0, SEEK_CUR); -} - void Fileio::Close() { if (handle != -1) { diff --git a/src/raspberrypi/fileio.h b/src/raspberrypi/fileio.h index 7b0e4f18..1946d431 100644 --- a/src/raspberrypi/fileio.h +++ b/src/raspberrypi/fileio.h @@ -35,7 +35,6 @@ public: bool Read(BYTE *buffer, int size) const; bool Write(const BYTE *buffer, int size) const; off_t GetFileSize() const; - off_t GetFilePos() const; void Close(); private: diff --git a/src/raspberrypi/hal/gpiobus.cpp b/src/raspberrypi/hal/gpiobus.cpp index f1b06562..0bfd1cae 100644 --- a/src/raspberrypi/hal/gpiobus.cpp +++ b/src/raspberrypi/hal/gpiobus.cpp @@ -31,44 +31,40 @@ using namespace std; // imported from bcm_host.c // //--------------------------------------------------------------------------- -static DWORD get_dt_ranges(const char *filename, DWORD offset) +static uint32_t get_dt_ranges(const char *filename, DWORD offset) { - DWORD address = ~0; + uint32_t address = ~0; if (FILE *fp = fopen(filename, "rb"); fp) { fseek(fp, offset, SEEK_SET); - if (BYTE buf[4]; fread(buf, 1, sizeof buf, fp) == sizeof buf) { - address = - buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0; + if (array buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) { + address = (int)buf[0] << 24 | (int)buf[1] << 16 | (int)buf[2] << 8 | (int)buf[3] << 0; } fclose(fp); } return address; } -DWORD bcm_host_get_peripheral_address(void) +uint32_t bcm_host_get_peripheral_address() { - DWORD address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); + uint32_t address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); if (address == 0) { address = get_dt_ranges("/proc/device-tree/soc/ranges", 8); } - address = (address == (DWORD)~0) ? 0x20000000 : address; -#if 0 - printf("Peripheral address : 0x%lx\n", address); -#endif + address = (address == (uint32_t)~0) ? 0x20000000 : address; return address; } #endif #ifdef __NetBSD__ // Assume the Raspberry Pi series and estimate the address from CPU -DWORD bcm_host_get_peripheral_address(void) +uint32_t bcm_host_get_peripheral_address() { - char buf[1024]; - size_t len = sizeof(buf); + array buf; + size_t len = buf.size(); DWORD address; - if (sysctlbyname("hw.model", buf, &len, NULL, 0) || - strstr(buf, "ARM1176JZ-S") != buf) { + if (sysctlbyname("hw.model", buf.data(), &len, NULL, 0) || + strstr(buf, "ARM1176JZ-S") != buf.data()) { // Failed to get CPU model || Not BCM2835 // use the address of BCM283[67] address = 0x3f000000; @@ -79,7 +75,7 @@ DWORD bcm_host_get_peripheral_address(void) printf("Peripheral address : 0x%lx\n", address); return address; } -#endif // __NetBSD__ +#endif bool GPIOBUS::Init(mode_e mode) { @@ -91,11 +87,11 @@ bool GPIOBUS::Init(mode_e mode) #else int i; #ifdef USE_SEL_EVENT_ENABLE - struct epoll_event ev; + epoll_event ev = {}; #endif // Get the base address - baseaddr = (DWORD)bcm_host_get_peripheral_address(); + baseaddr = (uint32_t)bcm_host_get_peripheral_address(); // Open /dev/mem int fd = open("/dev/mem", O_RDWR | O_SYNC); @@ -232,7 +228,6 @@ bool GPIOBUS::Init(mode_e mode) // epoll initialization epfd = epoll_create(1); - memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN | EPOLLPRI; ev.data.fd = selevreq.fd; epoll_ctl(epfd, EPOLL_CTL_ADD, selevreq.fd, &ev); @@ -1021,20 +1016,17 @@ int GPIOBUS::SendHandShake(BYTE *buf, int count, int delay_after_bytes) //--------------------------------------------------------------------------- bool GPIOBUS::PollSelectEvent() { - // clear errno errno = 0; - struct epoll_event epev; - struct gpioevent_data gpev; - if (epoll_wait(epfd, &epev, 1, -1) <= 0) { - LOGWARN("%s epoll_wait failed", __PRETTY_FUNCTION__) + if (epoll_event epev; epoll_wait(epfd, &epev, 1, -1) <= 0) { + LOGWARN("%s epoll_wait failed", __PRETTY_FUNCTION__) return false; } - if (read(selevreq.fd, &gpev, sizeof(gpev)) < 0) { - LOGWARN("%s read failed", __PRETTY_FUNCTION__) - return false; - } + if (gpioevent_data gpev; read(selevreq.fd, &gpev, sizeof(gpev)) < 0) { + LOGWARN("%s read failed", __PRETTY_FUNCTION__) + return false; + } return true; } @@ -1054,7 +1046,7 @@ void GPIOBUS::ClearSelectEvent() // Signal table // //--------------------------------------------------------------------------- -const int GPIOBUS::SignalTable[19] = { +const array GPIOBUS::SignalTable = { PIN_DT0, PIN_DT1, PIN_DT2, PIN_DT3, PIN_DT4, PIN_DT5, PIN_DT6, PIN_DT7, PIN_DP, PIN_SEL,PIN_ATN, PIN_RST, PIN_ACK, @@ -1077,9 +1069,9 @@ void GPIOBUS::MakeTable(void) array tblParity; // Create parity table - for (int i = 0; i < 0x100; i++) { - auto bits = (DWORD)i; - DWORD parity = 0; + for (uint32_t i = 0; i < 0x100; i++) { + uint32_t bits = i; + uint32_t parity = 0; for (int j = 0; j < 8; j++) { parity ^= bits & 1; bits >>= 1; @@ -1090,11 +1082,16 @@ void GPIOBUS::MakeTable(void) #if SIGNAL_CONTROL_MODE == 0 // Mask and setting data generation - memset(tblDatMsk, 0xff, sizeof(tblDatMsk)); - memset(tblDatSet, 0x00, sizeof(tblDatSet)); - for (int i = 0; i < 0x100; i++) { + for (auto& tbl : tblDatMsk) { + tbl.fill(-1); + } + for (auto& tbl : tblDatSet) { + tbl.fill(0); + } + + for (uint32_t i = 0; i < 0x100; i++) { // Bit string for inspection - auto bits = (DWORD)i; + uint32_t bits = i; // Get parity if (tblParity[i]) { @@ -1119,14 +1116,11 @@ void GPIOBUS::MakeTable(void) } } #else - // Mask and setting data generation - memset(tblDatMsk, 0x00, sizeof(tblDatMsk)); - memset(tblDatSet, 0x00, sizeof(tblDatSet)); - for (int i = 0; i < 0x100; i++) { - // bit string for inspection - DWORD bits = (DWORD)i; + for (uint32_t i = 0; i < 0x100; i++) { + // Bit string for inspection + uint32_t bits = i; - // get parity + // Get parity if (tblParity[i]) { bits |= (1 << 8); } @@ -1137,8 +1131,8 @@ void GPIOBUS::MakeTable(void) #endif // Create GPIO register information - DWORD gpclr = 0; - DWORD gpset = 0; + uint32_t gpclr = 0; + uint32_t gpset = 0; for (int j = 0; j < 9; j++) { if (bits & 1) { gpset |= (1 << pintbl[j]); @@ -1400,11 +1394,10 @@ void GPIOBUS::DrvConfig(DWORD drive) BUS::phase_t GPIOBUS::GetPhaseRaw(DWORD raw_data) { // Selection Phase - if (GetPinRaw(raw_data, PIN_SEL)) - { - if(GetPinRaw(raw_data, PIN_IO)){ + if (GetPinRaw(raw_data, PIN_SEL)) { + if(GetPinRaw(raw_data, PIN_IO)) { return BUS::phase_t::reselection; - }else{ + } else{ return BUS::phase_t::selection; } } @@ -1415,7 +1408,7 @@ BUS::phase_t GPIOBUS::GetPhaseRaw(DWORD raw_data) } // Get target phase from bus signal line - DWORD mci = GetPinRaw(raw_data, PIN_MSG) ? 0x04 : 0x00; + int mci = GetPinRaw(raw_data, PIN_MSG) ? 0x04 : 0x00; mci |= GetPinRaw(raw_data, PIN_CD) ? 0x02 : 0x00; mci |= GetPinRaw(raw_data, PIN_IO) ? 0x01 : 0x00; return GetPhase(mci); diff --git a/src/raspberrypi/hal/gpiobus.h b/src/raspberrypi/hal/gpiobus.h index 3b74078e..6005944c 100644 --- a/src/raspberrypi/hal/gpiobus.h +++ b/src/raspberrypi/hal/gpiobus.h @@ -13,6 +13,7 @@ #include "config.h" #include "scsi.h" +#include #ifdef __linux #include @@ -40,6 +41,8 @@ #error Invalid connection type or none specified #endif +using namespace std; //NOSONAR Not relevant for rascsi + //--------------------------------------------------------------------------- // // Signal control logic and pin assignment customization @@ -455,7 +458,9 @@ private: mode_e actmode = mode_e::TARGET; // Operation mode +#if !defined(__x86_64__) && !defined(__X86__) uint32_t baseaddr = 0; // Base address +#endif int rpitype = 0; // Type of Raspberry Pi @@ -463,7 +468,9 @@ private: volatile uint32_t *pads = nullptr; // PADS register +#if !defined(__x86_64__) && !defined(__X86__) volatile uint32_t *level = nullptr; // GPIO input level +#endif volatile uint32_t *irpctl = nullptr; // Interrupt control register @@ -477,11 +484,13 @@ private: volatile uint32_t giccpmr; // GICC priority setting +#if !defined(__x86_64__) && !defined(__X86__) volatile uint32_t *gicd = nullptr; // GIC Interrupt distributor register +#endif volatile uint32_t *gicc = nullptr; // GIC CPU interface register - DWORD gpfsel[4]; // GPFSEL0-4 backup values + array gpfsel; // GPFSEL0-4 backup values uint32_t signals = 0; // All bus signals @@ -492,15 +501,15 @@ private: #endif // USE_SEL_EVENT_ENABLE #if SIGNAL_CONTROL_MODE == 0 - DWORD tblDatMsk[3][256]; // Data mask table + array, 3> tblDatMsk; // Data mask table - DWORD tblDatSet[3][256]; // Data setting table + array, 3> tblDatSet; // Data setting table #else - DWORD tblDatMsk[256]; // Data mask table + array tblDatMsk = {}; // Data mask table - DWORD tblDatSet[256]; // Table setting table + array tblDatSet = {}; // Table setting table #endif - static const int SignalTable[19]; // signal table + static const array SignalTable; // signal table }; diff --git a/src/raspberrypi/localizer.cpp b/src/raspberrypi/localizer.cpp index 063764cc..841258a8 100644 --- a/src/raspberrypi/localizer.cpp +++ b/src/raspberrypi/localizer.cpp @@ -17,155 +17,154 @@ using namespace std; Localizer::Localizer() { - // Positional string arguments are %1, %2, %3 - Add(ERROR_AUTHENTICATION, "en", "Authentication failed"); - Add(ERROR_AUTHENTICATION, "de", "Authentifizierung fehlgeschlagen"); - Add(ERROR_AUTHENTICATION, "sv", "Autentiseringen misslyckades"); - Add(ERROR_AUTHENTICATION, "fr", "Authentification éronnée"); - Add(ERROR_AUTHENTICATION, "es", "Fallo de autentificación"); - Add(ERROR_OPERATION, "en", "Unknown operation"); - Add(ERROR_OPERATION, "de", "Unbekannte Operation"); - Add(ERROR_OPERATION, "sv", "Okänd operation"); - Add(ERROR_OPERATION, "fr", "Opération inconnue"); - Add(ERROR_OPERATION, "es", "Operación desconocida"); - Add(ERROR_LOG_LEVEL, "en", "Invalid log level %1"); - Add(ERROR_LOG_LEVEL, "de", "Ungültiger Log-Level %1"); - Add(ERROR_LOG_LEVEL, "sv", "Ogiltig loggnivå %1"); - Add(ERROR_LOG_LEVEL, "fr", "Niveau de journalisation invalide %1"); - Add(ERROR_LOG_LEVEL, "es", "Nivel de registro %1 no válido"); - Add(ERROR_MISSING_DEVICE_ID, "en", "Missing device ID"); - Add(ERROR_MISSING_DEVICE_ID, "de", "Fehlende Geräte-ID"); - Add(ERROR_MISSING_DEVICE_ID, "sv", "Enhetens id saknas"); - Add(ERROR_MISSING_DEVICE_ID, "fr", "ID de périphérique manquante"); - Add(ERROR_MISSING_DEVICE_ID, "es", "Falta el ID del dispositivo"); - Add(ERROR_MISSING_FILENAME, "en", "Missing filename"); - Add(ERROR_MISSING_FILENAME, "de", "Fehlender Dateiname"); - Add(ERROR_MISSING_FILENAME, "sv", "Filnamn saknas"); - Add(ERROR_MISSING_FILENAME, "fr", "Nom de fichier manquant"); - Add(ERROR_MISSING_FILENAME, "es", "Falta el nombre del archivo"); - Add(ERROR_DEVICE_MISSING_FILENAME, "en", "Device type %1 requires a filename"); - Add(ERROR_DEVICE_MISSING_FILENAME, "de", "Gerätetyp %1 erfordert einen Dateinamen"); - Add(ERROR_DEVICE_MISSING_FILENAME, "sv", "Enhetstypen %1 kräver ett filnamn"); - Add(ERROR_DEVICE_MISSING_FILENAME, "es", "El tipo de dispositivo %1 requiere un nombre de archivo"); - Add(ERROR_IMAGE_IN_USE, "en", "Image file '%1' is already being used by ID %2, unit %3"); - Add(ERROR_IMAGE_IN_USE, "de", "Image-Datei '%1' wird bereits von ID %2, Einheit %3 benutzt"); - Add(ERROR_IMAGE_IN_USE, "sv", "Skivbildsfilen '%1' används redan av id %2, enhetsnummer %3"); - Add(ERROR_IMAGE_IN_USE, "fr", "Le fichier d'image '%1' est déjà utilisé par l'ID %2, unité %3"); - Add(ERROR_IMAGE_IN_USE, "es", "El archivo de imagen '%1' ya está siendo utilizado por el ID %2, unidad %3"); - Add(ERROR_IMAGE_FILE_INFO, "en", "Can't create image file info for '%1'"); - Add(ERROR_IMAGE_FILE_INFO, "de", "Image-Datei-Information für '%1' kann nicht erzeugt werden"); - Add(ERROR_IMAGE_FILE_INFO, "sv", "Kunde ej skapa skivbildsfilsinfo för '%1'"); - Add(ERROR_IMAGE_FILE_INFO, "es", "No se puede crear información de archivo de imagen para '%1'"); - Add(ERROR_RESERVED_ID, "en", "Device ID %1 is reserved"); - Add(ERROR_RESERVED_ID, "de", "Geräte-ID %1 ist reserviert"); - Add(ERROR_RESERVED_ID, "sv", "Enhets-id %1 är reserverat"); - Add(ERROR_RESERVED_ID, "fr", "ID de périphérique %1 réservée"); - Add(ERROR_RESERVED_ID, "es", "El ID de dispositivo %1 está reservado"); - Add(ERROR_NON_EXISTING_DEVICE, "en", "Command for non-existing ID %1"); - Add(ERROR_NON_EXISTING_DEVICE, "de", "Kommando für nicht existente ID %1"); - Add(ERROR_NON_EXISTING_DEVICE, "sv", "Kommando för id %1 som ej existerar"); - Add(ERROR_NON_EXISTING_DEVICE, "fr", "Commande pour ID %1 non-existant"); - Add(ERROR_NON_EXISTING_DEVICE, "es", "Comando para ID %1 no existente"); - Add(ERROR_NON_EXISTING_UNIT, "en", "Command for non-existing ID %1, unit %2"); - Add(ERROR_NON_EXISTING_UNIT, "de", "Kommando für nicht existente ID %1, Einheit %2"); - Add(ERROR_NON_EXISTING_UNIT, "sv", "Kommando för id %1, enhetsnummer %2 som ej existerar"); - Add(ERROR_NON_EXISTING_UNIT, "fr", "Command pour ID %1, unité %2 non-existant"); - Add(ERROR_NON_EXISTING_UNIT, "es", "Comando para ID %1 inexistente, unidad %2"); - Add(ERROR_UNKNOWN_DEVICE_TYPE, "en", "Unknown device type %1"); - Add(ERROR_UNKNOWN_DEVICE_TYPE, "de", "Unbekannter Gerätetyp %1"); - Add(ERROR_UNKNOWN_DEVICE_TYPE, "sv", "Obekant enhetstyp: %1"); - Add(ERROR_UNKNOWN_DEVICE_TYPE, "fr", "Type de périphérique inconnu %1"); - Add(ERROR_UNKNOWN_DEVICE_TYPE, "es", "Tipo de dispositivo desconocido %1"); - Add(ERROR_MISSING_DEVICE_TYPE, "en", "Device type required for unknown extension of file '%1'"); - Add(ERROR_MISSING_DEVICE_TYPE, "de", "Gerätetyp erforderlich für unbekannte Extension der Datei '%1'"); - Add(ERROR_MISSING_DEVICE_TYPE, "sv", "Man måste ange enhetstyp för obekant filändelse '%1'"); - Add(ERROR_MISSING_DEVICE_TYPE, "fr", "Type de périphérique requis pour extension inconnue du fichier '%1'"); - Add(ERROR_MISSING_DEVICE_TYPE, "es", "Tipo de dispositivo requerido para la extensión desconocida del archivo '%1'"); - Add(ERROR_DUPLICATE_ID, "en", "Duplicate ID %1, unit %2"); - Add(ERROR_DUPLICATE_ID, "de", "Doppelte ID %1, Einheit %2"); - Add(ERROR_DUPLICATE_ID, "sv", "Duplikat id %1, enhetsnummer %2"); - Add(ERROR_DUPLICATE_ID, "fr", "ID %1, unité %2 dupliquée"); - Add(ERROR_DUPLICATE_ID, "es", "ID duplicado %1, unidad %2"); - Add(ERROR_DETACH, "en", "Couldn't detach device"); - Add(ERROR_DETACH, "de", "Geräte konnte nicht entfernt werden"); - Add(ERROR_DETACH, "sv", "Kunde ej koppla ifrån enheten"); - Add(ERROR_DETACH, "es", "No se ha podido desconectar el dispositivo"); - Add(ERROR_EJECT_REQUIRED, "en", "Existing medium must first be ejected"); - Add(ERROR_EJECT_REQUIRED, "de", "Das vorhandene Medium muss erst ausgeworfen werden"); - Add(ERROR_EJECT_REQUIRED, "sv", "Nuvarande skiva måste utmatas först"); - Add(ERROR_EJECT_REQUIRED, "fr", "Media déjà existant doit d'abord être éjecté"); - Add(ERROR_EJECT_REQUIRED, "es", "El medio existente debe ser expulsado primero"); - Add(ERROR_DEVICE_NAME_UPDATE, "en", "Once set the device name cannot be changed anymore"); - Add(ERROR_DEVICE_NAME_UPDATE, "de", "Ein bereits gesetzter Gerätename kann nicht mehr geändert werden"); - Add(ERROR_DEVICE_NAME_UPDATE, "sv", "Enhetsnamn kan ej ändras efter att ha fastställts en gång"); - Add(ERROR_DEVICE_NAME_UPDATE, "fr", "Une fois défini, le nom de périphérique ne peut plus être changé"); - Add(ERROR_DEVICE_NAME_UPDATE, "es", "Una vez establecido el nombre del dispositivo ya no se puede cambiar"); - Add(ERROR_SHUTDOWN_MODE_MISSING, "en", "Missing shutdown mode"); - Add(ERROR_SHUTDOWN_MODE_MISSING, "de", "Fehlender Shutdown-Modus"); - Add(ERROR_SHUTDOWN_MODE_MISSING, "sv", "Avstängningsläge saknas"); - Add(ERROR_SHUTDOWN_MODE_MISSING, "fr", "Mode d'extinction manquant"); - Add(ERROR_SHUTDOWN_MODE_MISSING, "es", "Falta el modo de apagado"); - Add(ERROR_SHUTDOWN_MODE_INVALID, "en", "Invalid shutdown mode '%1'"); - Add(ERROR_SHUTDOWN_MODE_INVALID, "de", "Ungültiger Shutdown-Modus '%1'"); - Add(ERROR_SHUTDOWN_MODE_INVALID, "sv", "Ogiltigt avstängsningsläge: '%1'"); - Add(ERROR_SHUTDOWN_MODE_INVALID, "fr", "Mode d'extinction invalide '%1'"); - Add(ERROR_SHUTDOWN_MODE_INVALID, "es", "Modo de apagado inválido '%1'"); - Add(ERROR_SHUTDOWN_PERMISSION, "en", "Missing root permission for shutdown or reboot"); - Add(ERROR_SHUTDOWN_PERMISSION, "de", "Fehlende Root-Berechtigung für Shutdown oder Neustart"); - Add(ERROR_SHUTDOWN_PERMISSION, "sv", "Saknar root-rättigheter för att kunna stänga av eller starta om systemet"); - Add(ERROR_SHUTDOWN_PERMISSION, "fr", "Permissions root manquantes pour extinction ou redémarrage"); - Add(ERROR_SHUTDOWN_PERMISSION, "es", "Falta el permiso de root para el apagado o el reinicio"); - Add(ERROR_FILE_OPEN, "en", "Invalid or non-existing file '%1': %2"); - Add(ERROR_FILE_OPEN, "de", "Ungültige oder fehlende Datei '%1': %2"); - Add(ERROR_FILE_OPEN, "sv", "Ogiltig eller saknad fil '%1': %2"); - Add(ERROR_FILE_OPEN, "fr", "Fichier invalide ou non-existant '%1': %2"); - Add(ERROR_FILE_OPEN, "es", "Archivo inválido o inexistente '%1': %2"); - Add(ERROR_BLOCK_SIZE, "en", "Invalid block size %1 bytes"); - Add(ERROR_BLOCK_SIZE, "de", "Ungültige Blockgröße %1 Bytes"); - Add(ERROR_BLOCK_SIZE, "sv", "Ogiltig blockstorlek: %1 byte"); - Add(ERROR_BLOCK_SIZE, "fr", "Taille de bloc invalide %1 octets"); - Add(ERROR_BLOCK_SIZE, "es", "Tamaño de bloque inválido %1 bytes"); - Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "en", "Block size for device type %1 is not configurable"); - Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "de", "Blockgröße für Gerätetyp %1 ist nicht konfigurierbar"); - Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "sv", "Enhetstypen %1 kan inte använda andra blockstorlekar"); - Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "fr", "Taille de block pour le type de périphérique %1 non configurable"); - Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "es", "El tamaño del bloque para el tipo de dispositivo %1 no es configurable"); - Add(ERROR_SCSI_CONTROLLER, "en", "Couldn't create SCSI controller"); - Add(ERROR_SCSI_CONTROLLER, "de", "SCSI-Controller konnte nicht erzeugt werden"); - Add(ERROR_SCSI_CONTROLLER, "sv", "Kunde ej skapa SCSI-gränssnitt"); - Add(ERROR_SCSI_CONTROLLER, "es", "No se ha podido crear el controlador SCSI"); - Add(ERROR_INVALID_ID, "en", "Invalid device ID %1 (0-%2)"); - Add(ERROR_INVALID_ID, "de", "Ungültige Geräte-ID %1 (0-%2)"); - Add(ERROR_INVALID_ID, "sv", "Ogiltigt enhets-id %1 (0-%2)"); - Add(ERROR_INVALID_ID, "es", "ID de dispositivo inválido %1 (0-%2)"); - Add(ERROR_INVALID_LUN, "en", "Invalid LUN %1 (0-%2)"); - Add(ERROR_INVALID_LUN, "de", "Ungültige LUN %1 (0-%2)"); - Add(ERROR_INVALID_LUN, "sv", "Ogiltigt enhetsnummer %1 (0-%2)"); - Add(ERROR_INVALID_LUN, "es", "LUN invalido %1 (0-%2)"); - Add(ERROR_LUN0, "en", "LUN 0 cannot be detached as long as there is still another LUN"); - Add(ERROR_LUN0, "de", "LUN 0 kann nicht entfernt werden, solange noch eine andere LUN existiert"); - Add(ERROR_LUN0, "sv", "Enhetsnummer 0 kan ej bli frånkopplat så länge som andra enhetsnummer är anslutna"); - Add(ERROR_LUN0, "es", "El LUN 0 no se puede desconectar mientras haya otro LUN"); - Add(ERROR_INITIALIZATION, "en", "Initialization of %1 device, ID %2, LUN %3 failed"); - Add(ERROR_INITIALIZATION, "de", "Initialisierung von %1-Gerät, ID %2, LUN %3 fehlgeschlagen"); - Add(ERROR_INITIALIZATION, "sv", "Kunde ej initialisera enheten %1 med id %2 och enhetsnummer %3"); - Add(ERROR_INITIALIZATION, "es", "La inicialización del dispositivo %1, ID %2, LUN %3 falló"); - Add(ERROR_OPERATION_DENIED_STOPPABLE, "en", "%1 operation denied, %2 isn't stoppable"); - Add(ERROR_OPERATION_DENIED_STOPPABLE, "de", "%1-Operation verweigert, %2 ist nicht stopbar"); - Add(ERROR_OPERATION_DENIED_STOPPABLE, "sv", "Operationen %1 nekades för att %2 inte kan stoppas"); - Add(ERROR_OPERATION_DENIED_STOPPABLE, "es", "%1 operación denegada, %2 no se puede parar"); - Add(ERROR_OPERATION_DENIED_REMOVABLE, "en", "%1 operation denied, %2 isn't removable"); - Add(ERROR_OPERATION_DENIED_REMOVABLE, "de", "%1-Operation verweigert, %2 ist nicht wechselbar"); - Add(ERROR_OPERATION_DENIED_REMOVABLE, "sv", "Operationen %1 nekades för att %2 inte är uttagbar(t)"); - Add(ERROR_OPERATION_DENIED_REMOVABLE, "es", "%1 operación denegada, %2 no es removible"); - Add(ERROR_OPERATION_DENIED_PROTECTABLE, "en", "%1 operation denied, %2 isn't protectable"); - Add(ERROR_OPERATION_DENIED_PROTECTABLE, "de", "%1-Operation verweigert, %2 ist nicht schützbar"); - Add(ERROR_OPERATION_DENIED_PROTECTABLE, "sv", "Operationen %1 nekades för att %2 inte är skyddbar(t)"); - Add(ERROR_OPERATION_DENIED_PROTECTABLE, "es", "%1 operación denegada, %2 no es protegible"); - Add(ERROR_OPERATION_DENIED_READY, "en", "%1 operation denied, %2 isn't ready"); - Add(ERROR_OPERATION_DENIED_READY, "de", "%1-Operation verweigert, %2 ist nicht bereit"); - Add(ERROR_OPERATION_DENIED_READY, "sv", "Operationen %1 nekades för att %2 inte är redo"); - Add(ERROR_OPERATION_DENIED_READY, "es", "%1 operación denegada, %2 no está listo"); + Add(LocalizationKey::ERROR_AUTHENTICATION, "en", "Authentication failed"); + Add(LocalizationKey::ERROR_AUTHENTICATION, "de", "Authentifizierung fehlgeschlagen"); + Add(LocalizationKey::ERROR_AUTHENTICATION, "sv", "Autentiseringen misslyckades"); + Add(LocalizationKey::ERROR_AUTHENTICATION, "fr", "Authentification éronnée"); + Add(LocalizationKey::ERROR_AUTHENTICATION, "es", "Fallo de autentificación"); + Add(LocalizationKey::ERROR_OPERATION, "en", "Unknown operation"); + Add(LocalizationKey::ERROR_OPERATION, "de", "Unbekannte Operation"); + Add(LocalizationKey::ERROR_OPERATION, "sv", "Okänd operation"); + Add(LocalizationKey::ERROR_OPERATION, "fr", "Opération inconnue"); + Add(LocalizationKey::ERROR_OPERATION, "es", "Operación desconocida"); + Add(LocalizationKey::ERROR_LOG_LEVEL, "en", "Invalid log level %1"); + Add(LocalizationKey::ERROR_LOG_LEVEL, "de", "Ungültiger Log-Level %1"); + Add(LocalizationKey::ERROR_LOG_LEVEL, "sv", "Ogiltig loggnivå %1"); + Add(LocalizationKey::ERROR_LOG_LEVEL, "fr", "Niveau de journalisation invalide %1"); + Add(LocalizationKey::ERROR_LOG_LEVEL, "es", "Nivel de registro %1 no válido"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_ID, "en", "Missing device ID"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_ID, "de", "Fehlende Geräte-ID"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_ID, "sv", "Enhetens id saknas"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_ID, "fr", "ID de périphérique manquante"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_ID, "es", "Falta el ID del dispositivo"); + Add(LocalizationKey::ERROR_MISSING_FILENAME, "en", "Missing filename"); + Add(LocalizationKey::ERROR_MISSING_FILENAME, "de", "Fehlender Dateiname"); + Add(LocalizationKey::ERROR_MISSING_FILENAME, "sv", "Filnamn saknas"); + Add(LocalizationKey::ERROR_MISSING_FILENAME, "fr", "Nom de fichier manquant"); + Add(LocalizationKey::ERROR_MISSING_FILENAME, "es", "Falta el nombre del archivo"); + Add(LocalizationKey::ERROR_DEVICE_MISSING_FILENAME, "en", "Device type %1 requires a filename"); + Add(LocalizationKey::ERROR_DEVICE_MISSING_FILENAME, "de", "Gerätetyp %1 erfordert einen Dateinamen"); + Add(LocalizationKey::ERROR_DEVICE_MISSING_FILENAME, "sv", "Enhetstypen %1 kräver ett filnamn"); + Add(LocalizationKey::ERROR_DEVICE_MISSING_FILENAME, "es", "El tipo de dispositivo %1 requiere un nombre de archivo"); + Add(LocalizationKey::ERROR_IMAGE_IN_USE, "en", "Image file '%1' is already being used by ID %2, unit %3"); + Add(LocalizationKey::ERROR_IMAGE_IN_USE, "de", "Image-Datei '%1' wird bereits von ID %2, Einheit %3 benutzt"); + Add(LocalizationKey::ERROR_IMAGE_IN_USE, "sv", "Skivbildsfilen '%1' används redan av id %2, enhetsnummer %3"); + Add(LocalizationKey::ERROR_IMAGE_IN_USE, "fr", "Le fichier d'image '%1' est déjà utilisé par l'ID %2, unité %3"); + Add(LocalizationKey::ERROR_IMAGE_IN_USE, "es", "El archivo de imagen '%1' ya está siendo utilizado por el ID %2, unidad %3"); + Add(LocalizationKey::ERROR_IMAGE_FILE_INFO, "en", "Can't create image file info for '%1'"); + Add(LocalizationKey::ERROR_IMAGE_FILE_INFO, "de", "Image-Datei-Information für '%1' kann nicht erzeugt werden"); + Add(LocalizationKey::ERROR_IMAGE_FILE_INFO, "sv", "Kunde ej skapa skivbildsfilsinfo för '%1'"); + Add(LocalizationKey::ERROR_IMAGE_FILE_INFO, "es", "No se puede crear información de archivo de imagen para '%1'"); + Add(LocalizationKey::ERROR_RESERVED_ID, "en", "Device ID %1 is reserved"); + Add(LocalizationKey::ERROR_RESERVED_ID, "de", "Geräte-ID %1 ist reserviert"); + Add(LocalizationKey::ERROR_RESERVED_ID, "sv", "Enhets-id %1 är reserverat"); + Add(LocalizationKey::ERROR_RESERVED_ID, "fr", "ID de périphérique %1 réservée"); + Add(LocalizationKey::ERROR_RESERVED_ID, "es", "El ID de dispositivo %1 está reservado"); + Add(LocalizationKey::ERROR_NON_EXISTING_DEVICE, "en", "Command for non-existing ID %1"); + Add(LocalizationKey::ERROR_NON_EXISTING_DEVICE, "de", "Kommando für nicht existente ID %1"); + Add(LocalizationKey::ERROR_NON_EXISTING_DEVICE, "sv", "Kommando för id %1 som ej existerar"); + Add(LocalizationKey::ERROR_NON_EXISTING_DEVICE, "fr", "Commande pour ID %1 non-existant"); + Add(LocalizationKey::ERROR_NON_EXISTING_DEVICE, "es", "Comando para ID %1 no existente"); + Add(LocalizationKey::ERROR_NON_EXISTING_UNIT, "en", "Command for non-existing ID %1, unit %2"); + Add(LocalizationKey::ERROR_NON_EXISTING_UNIT, "de", "Kommando für nicht existente ID %1, Einheit %2"); + Add(LocalizationKey::ERROR_NON_EXISTING_UNIT, "sv", "Kommando för id %1, enhetsnummer %2 som ej existerar"); + Add(LocalizationKey::ERROR_NON_EXISTING_UNIT, "fr", "Command pour ID %1, unité %2 non-existant"); + Add(LocalizationKey::ERROR_NON_EXISTING_UNIT, "es", "Comando para ID %1 inexistente, unidad %2"); + Add(LocalizationKey::ERROR_UNKNOWN_DEVICE_TYPE, "en", "Unknown device type %1"); + Add(LocalizationKey::ERROR_UNKNOWN_DEVICE_TYPE, "de", "Unbekannter Gerätetyp %1"); + Add(LocalizationKey::ERROR_UNKNOWN_DEVICE_TYPE, "sv", "Obekant enhetstyp: %1"); + Add(LocalizationKey::ERROR_UNKNOWN_DEVICE_TYPE, "fr", "Type de périphérique inconnu %1"); + Add(LocalizationKey::ERROR_UNKNOWN_DEVICE_TYPE, "es", "Tipo de dispositivo desconocido %1"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_TYPE, "en", "Device type required for unknown extension of file '%1'"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_TYPE, "de", "Gerätetyp erforderlich für unbekannte Extension der Datei '%1'"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_TYPE, "sv", "Man måste ange enhetstyp för obekant filändelse '%1'"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_TYPE, "fr", "Type de périphérique requis pour extension inconnue du fichier '%1'"); + Add(LocalizationKey::ERROR_MISSING_DEVICE_TYPE, "es", "Tipo de dispositivo requerido para la extensión desconocida del archivo '%1'"); + Add(LocalizationKey::ERROR_DUPLICATE_ID, "en", "Duplicate ID %1, unit %2"); + Add(LocalizationKey::ERROR_DUPLICATE_ID, "de", "Doppelte ID %1, Einheit %2"); + Add(LocalizationKey::ERROR_DUPLICATE_ID, "sv", "Duplikat id %1, enhetsnummer %2"); + Add(LocalizationKey::ERROR_DUPLICATE_ID, "fr", "ID %1, unité %2 dupliquée"); + Add(LocalizationKey::ERROR_DUPLICATE_ID, "es", "ID duplicado %1, unidad %2"); + Add(LocalizationKey::ERROR_DETACH, "en", "Couldn't detach device"); + Add(LocalizationKey::ERROR_DETACH, "de", "Geräte konnte nicht entfernt werden"); + Add(LocalizationKey::ERROR_DETACH, "sv", "Kunde ej koppla ifrån enheten"); + Add(LocalizationKey::ERROR_DETACH, "es", "No se ha podido desconectar el dispositivo"); + Add(LocalizationKey::ERROR_EJECT_REQUIRED, "en", "Existing medium must first be ejected"); + Add(LocalizationKey::ERROR_EJECT_REQUIRED, "de", "Das vorhandene Medium muss erst ausgeworfen werden"); + Add(LocalizationKey::ERROR_EJECT_REQUIRED, "sv", "Nuvarande skiva måste utmatas först"); + Add(LocalizationKey::ERROR_EJECT_REQUIRED, "fr", "Media déjà existant doit d'abord être éjecté"); + Add(LocalizationKey::ERROR_EJECT_REQUIRED, "es", "El medio existente debe ser expulsado primero"); + Add(LocalizationKey::ERROR_DEVICE_NAME_UPDATE, "en", "Once set the device name cannot be changed anymore"); + Add(LocalizationKey::ERROR_DEVICE_NAME_UPDATE, "de", "Ein bereits gesetzter Gerätename kann nicht mehr geändert werden"); + Add(LocalizationKey::ERROR_DEVICE_NAME_UPDATE, "sv", "Enhetsnamn kan ej ändras efter att ha fastställts en gång"); + Add(LocalizationKey::ERROR_DEVICE_NAME_UPDATE, "fr", "Une fois défini, le nom de périphérique ne peut plus être changé"); + Add(LocalizationKey::ERROR_DEVICE_NAME_UPDATE, "es", "Una vez establecido el nombre del dispositivo ya no se puede cambiar"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_MISSING, "en", "Missing shutdown mode"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_MISSING, "de", "Fehlender Shutdown-Modus"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_MISSING, "sv", "Avstängningsläge saknas"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_MISSING, "fr", "Mode d'extinction manquant"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_MISSING, "es", "Falta el modo de apagado"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_INVALID, "en", "Invalid shutdown mode '%1'"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_INVALID, "de", "Ungültiger Shutdown-Modus '%1'"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_INVALID, "sv", "Ogiltigt avstängsningsläge: '%1'"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_INVALID, "fr", "Mode d'extinction invalide '%1'"); + Add(LocalizationKey::ERROR_SHUTDOWN_MODE_INVALID, "es", "Modo de apagado inválido '%1'"); + Add(LocalizationKey::ERROR_SHUTDOWN_PERMISSION, "en", "Missing root permission for shutdown or reboot"); + Add(LocalizationKey::ERROR_SHUTDOWN_PERMISSION, "de", "Fehlende Root-Berechtigung für Shutdown oder Neustart"); + Add(LocalizationKey::ERROR_SHUTDOWN_PERMISSION, "sv", "Saknar root-rättigheter för att kunna stänga av eller starta om systemet"); + Add(LocalizationKey::ERROR_SHUTDOWN_PERMISSION, "fr", "Permissions root manquantes pour extinction ou redémarrage"); + Add(LocalizationKey::ERROR_SHUTDOWN_PERMISSION, "es", "Falta el permiso de root para el apagado o el reinicio"); + Add(LocalizationKey::ERROR_FILE_OPEN, "en", "Invalid or non-existing file '%1': %2"); + Add(LocalizationKey::ERROR_FILE_OPEN, "de", "Ungültige oder fehlende Datei '%1': %2"); + Add(LocalizationKey::ERROR_FILE_OPEN, "sv", "Ogiltig eller saknad fil '%1': %2"); + Add(LocalizationKey::ERROR_FILE_OPEN, "fr", "Fichier invalide ou non-existant '%1': %2"); + Add(LocalizationKey::ERROR_FILE_OPEN, "es", "Archivo inválido o inexistente '%1': %2"); + Add(LocalizationKey::ERROR_BLOCK_SIZE, "en", "Invalid block size %1 bytes"); + Add(LocalizationKey::ERROR_BLOCK_SIZE, "de", "Ungültige Blockgröße %1 Bytes"); + Add(LocalizationKey::ERROR_BLOCK_SIZE, "sv", "Ogiltig blockstorlek: %1 byte"); + Add(LocalizationKey::ERROR_BLOCK_SIZE, "fr", "Taille de bloc invalide %1 octets"); + Add(LocalizationKey::ERROR_BLOCK_SIZE, "es", "Tamaño de bloque inválido %1 bytes"); + Add(LocalizationKey::ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "en", "Block size for device type %1 is not configurable"); + Add(LocalizationKey::ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "de", "Blockgröße für Gerätetyp %1 ist nicht konfigurierbar"); + Add(LocalizationKey::ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "sv", "Enhetstypen %1 kan inte använda andra blockstorlekar"); + Add(LocalizationKey::ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "fr", "Taille de block pour le type de périphérique %1 non configurable"); + Add(LocalizationKey::ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "es", "El tamaño del bloque para el tipo de dispositivo %1 no es configurable"); + Add(LocalizationKey::ERROR_SCSI_CONTROLLER, "en", "Couldn't create SCSI controller"); + Add(LocalizationKey::ERROR_SCSI_CONTROLLER, "de", "SCSI-Controller konnte nicht erzeugt werden"); + Add(LocalizationKey::ERROR_SCSI_CONTROLLER, "sv", "Kunde ej skapa SCSI-gränssnitt"); + Add(LocalizationKey::ERROR_SCSI_CONTROLLER, "es", "No se ha podido crear el controlador SCSI"); + Add(LocalizationKey::ERROR_INVALID_ID, "en", "Invalid device ID %1 (0-%2)"); + Add(LocalizationKey::ERROR_INVALID_ID, "de", "Ungültige Geräte-ID %1 (0-%2)"); + Add(LocalizationKey::ERROR_INVALID_ID, "sv", "Ogiltigt enhets-id %1 (0-%2)"); + Add(LocalizationKey::ERROR_INVALID_ID, "es", "ID de dispositivo inválido %1 (0-%2)"); + Add(LocalizationKey::ERROR_INVALID_LUN, "en", "Invalid LUN %1 (0-%2)"); + Add(LocalizationKey::ERROR_INVALID_LUN, "de", "Ungültige LUN %1 (0-%2)"); + Add(LocalizationKey::ERROR_INVALID_LUN, "sv", "Ogiltigt enhetsnummer %1 (0-%2)"); + Add(LocalizationKey::ERROR_INVALID_LUN, "es", "LUN invalido %1 (0-%2)"); + Add(LocalizationKey::ERROR_LUN0, "en", "LUN 0 cannot be detached as long as there is still another LUN"); + Add(LocalizationKey::ERROR_LUN0, "de", "LUN 0 kann nicht entfernt werden, solange noch eine andere LUN existiert"); + Add(LocalizationKey::ERROR_LUN0, "sv", "Enhetsnummer 0 kan ej bli frånkopplat så länge som andra enhetsnummer är anslutna"); + Add(LocalizationKey::ERROR_LUN0, "es", "El LUN 0 no se puede desconectar mientras haya otro LUN"); + Add(LocalizationKey::ERROR_INITIALIZATION, "en", "Initialization of %1 device, ID %2, LUN %3 failed"); + Add(LocalizationKey::ERROR_INITIALIZATION, "de", "Initialisierung von %1-Gerät, ID %2, LUN %3 fehlgeschlagen"); + Add(LocalizationKey::ERROR_INITIALIZATION, "sv", "Kunde ej initialisera enheten %1 med id %2 och enhetsnummer %3"); + Add(LocalizationKey::ERROR_INITIALIZATION, "es", "La inicialización del dispositivo %1, ID %2, LUN %3 falló"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_STOPPABLE, "en", "%1 operation denied, %2 isn't stoppable"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_STOPPABLE, "de", "%1-Operation verweigert, %2 ist nicht stopbar"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_STOPPABLE, "sv", "Operationen %1 nekades för att %2 inte kan stoppas"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_STOPPABLE, "es", "%1 operación denegada, %2 no se puede parar"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_REMOVABLE, "en", "%1 operation denied, %2 isn't removable"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_REMOVABLE, "de", "%1-Operation verweigert, %2 ist nicht wechselbar"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_REMOVABLE, "sv", "Operationen %1 nekades för att %2 inte är uttagbar(t)"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_REMOVABLE, "es", "%1 operación denegada, %2 no es removible"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_PROTECTABLE, "en", "%1 operation denied, %2 isn't protectable"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_PROTECTABLE, "de", "%1-Operation verweigert, %2 ist nicht schützbar"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_PROTECTABLE, "sv", "Operationen %1 nekades för att %2 inte är skyddbar(t)"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_PROTECTABLE, "es", "%1 operación denegada, %2 no es protegible"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_READY, "en", "%1 operation denied, %2 isn't ready"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_READY, "de", "%1-Operation verweigert, %2 ist nicht bereit"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_READY, "sv", "Operationen %1 nekades för att %2 inte är redo"); + Add(LocalizationKey::ERROR_OPERATION_DENIED_READY, "es", "%1 operación denegada, %2 no está listo"); } void Localizer::Add(LocalizationKey key, const string& locale, string_view value) @@ -200,7 +199,7 @@ string Localizer::Localize(LocalizationKey key, const string& locale, const stri auto messages = it->second; if (messages.empty()) { - return "Missing localization for enum value " + to_string(key); + return "Missing localization for enum value " + to_string((int)key); } string message = messages[key]; diff --git a/src/raspberrypi/localizer.h b/src/raspberrypi/localizer.h index dcd83423..67a05c87 100644 --- a/src/raspberrypi/localizer.h +++ b/src/raspberrypi/localizer.h @@ -17,7 +17,7 @@ using namespace std; //NOSONAR Not relevant for rascsi -enum LocalizationKey { +enum class LocalizationKey { ERROR_AUTHENTICATION, ERROR_OPERATION, ERROR_LOG_LEVEL, diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 3b1b8fe4..117600b1 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -71,7 +71,7 @@ DeviceFactory device_factory; ControllerManager controller_manager; RascsiImage rascsi_image; RascsiResponse rascsi_response(&device_factory, &rascsi_image); -SocketConnector socket_connector; +const SocketConnector socket_connector; void DetachAll(); static void *MonThread(void *); @@ -139,9 +139,8 @@ bool InitService(int port) } // Create socket for monitor - sockaddr_in server; + sockaddr_in server = {}; monsocket = socket(PF_INET, SOCK_STREAM, 0); - memset(&server, 0, sizeof(server)); server.sin_family = PF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = htonl(INADDR_ANY); @@ -388,11 +387,11 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, const PbDeviceType type = pb_device.type(); if (controller_manager.GetDeviceByIdAndLun(id, unit) != nullptr) { - return ReturnLocalizedError(context, ERROR_DUPLICATE_ID, to_string(id), to_string(unit)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_DUPLICATE_ID, to_string(id), to_string(unit)); } - if (unit >= AbstractController::LUN_MAX) { - return ReturnLocalizedError(context, ERROR_INVALID_LUN, to_string(unit), to_string(AbstractController::LUN_MAX)); + if (unit >= ScsiController::LUN_MAX) { + return ReturnLocalizedError(context, LocalizationKey::ERROR_INVALID_LUN, to_string(unit), to_string(ScsiController::LUN_MAX)); } string filename = GetParam(pb_device, "file"); @@ -400,10 +399,10 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, PrimaryDevice *device = device_factory.CreateDevice(type, filename, id); if (device == nullptr) { if (type == UNDEFINED) { - return ReturnLocalizedError(context, ERROR_MISSING_DEVICE_TYPE, filename); + return ReturnLocalizedError(context, LocalizationKey::ERROR_MISSING_DEVICE_TYPE, filename); } else { - return ReturnLocalizedError(context, ERROR_UNKNOWN_DEVICE_TYPE, PbDeviceType_Name(type)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_UNKNOWN_DEVICE_TYPE, PbDeviceType_Name(type)); } } @@ -434,13 +433,13 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, if (!disk->SetConfiguredSectorSize(device_factory, pb_device.block_size())) { device_factory.DeleteDevice(*device); - return ReturnLocalizedError(context, ERROR_BLOCK_SIZE, to_string(pb_device.block_size())); + return ReturnLocalizedError(context, LocalizationKey::ERROR_BLOCK_SIZE, to_string(pb_device.block_size())); } } else { device_factory.DeleteDevice(*device); - return ReturnLocalizedError(context, ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, PbDeviceType_Name(type)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, PbDeviceType_Name(type)); } } @@ -448,7 +447,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, if (file_support != nullptr && !device->IsRemovable() && filename.empty()) { device_factory.DeleteDevice(*device); - return ReturnLocalizedError(context, ERROR_MISSING_FILENAME, PbDeviceType_Name(type)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_MISSING_FILENAME, PbDeviceType_Name(type)); } Filepath filepath; @@ -461,7 +460,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { device_factory.DeleteDevice(*device); - return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } try { @@ -475,7 +474,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { device_factory.DeleteDevice(*device); - return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } file_support->Open(filepath); @@ -484,7 +483,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, catch(const io_exception& e) { device_factory.DeleteDevice(*device); - return ReturnLocalizedError(context, ERROR_FILE_OPEN, initial_filename, e.get_msg()); + return ReturnLocalizedError(context, LocalizationKey::ERROR_FILE_OPEN, initial_filename, e.get_msg()); } file_support->ReserveFile(filepath, device->GetId(), device->GetLun()); @@ -510,7 +509,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, if (!device->Init(params)) { device_factory.DeleteDevice(*device); - return ReturnLocalizedError(context, ERROR_INITIALIZATION, PbDeviceType_Name(type), to_string(id), to_string(unit)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_INITIALIZATION, PbDeviceType_Name(type), to_string(id), to_string(unit)); } pthread_mutex_lock(&ctrl_mutex); @@ -518,7 +517,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, if (!controller_manager.CreateScsiController(bus, device)) { pthread_mutex_unlock(&ctrl_mutex); - return ReturnLocalizedError(context, ERROR_SCSI_CONTROLLER); + return ReturnLocalizedError(context, LocalizationKey::ERROR_SCSI_CONTROLLER); } pthread_mutex_unlock(&ctrl_mutex); @@ -541,7 +540,7 @@ bool Detach(const CommandContext& context, PrimaryDevice *device, bool dryRun) for (const Device *d : device_factory.GetAllDevices()) { // LUN 0 can only be detached if there is no other LUN anymore if (d->GetId() == device->GetId() && d->GetLun()) { - return ReturnLocalizedError(context, ERROR_LUN0); + return ReturnLocalizedError(context, LocalizationKey::ERROR_LUN0); } } } @@ -561,7 +560,7 @@ bool Detach(const CommandContext& context, PrimaryDevice *device, bool dryRun) if (!controller_manager.FindController(id)->DeleteDevice(device)) { pthread_mutex_unlock(&ctrl_mutex); - return ReturnLocalizedError(context, ERROR_DETACH); + return ReturnLocalizedError(context, LocalizationKey::ERROR_DETACH); } device_factory.DeleteDevice(*device); pthread_mutex_unlock(&ctrl_mutex); @@ -575,16 +574,16 @@ bool Detach(const CommandContext& context, PrimaryDevice *device, bool dryRun) bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device, Device *device, bool dryRun) { if (!device->IsRemoved()) { - return ReturnLocalizedError(context, ERROR_EJECT_REQUIRED); + return ReturnLocalizedError(context, LocalizationKey::ERROR_EJECT_REQUIRED); } if (!pb_device.vendor().empty() || !pb_device.product().empty() || !pb_device.revision().empty()) { - return ReturnLocalizedError(context, ERROR_DEVICE_NAME_UPDATE); + return ReturnLocalizedError(context, LocalizationKey::ERROR_DEVICE_NAME_UPDATE); } string filename = GetParam(pb_device, "file"); if (filename.empty()) { - return ReturnLocalizedError(context, ERROR_MISSING_FILENAME); + return ReturnLocalizedError(context, LocalizationKey::ERROR_MISSING_FILENAME); } if (dryRun) { @@ -599,11 +598,11 @@ bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device, if (pb_device.block_size()) { if (disk != nullptr&& disk->IsSectorSizeConfigurable()) { if (!disk->SetConfiguredSectorSize(device_factory, pb_device.block_size())) { - return ReturnLocalizedError(context, ERROR_BLOCK_SIZE, to_string(pb_device.block_size())); + return ReturnLocalizedError(context, LocalizationKey::ERROR_BLOCK_SIZE, to_string(pb_device.block_size())); } } else { - return ReturnLocalizedError(context, ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, device->GetType()); + return ReturnLocalizedError(context, LocalizationKey::ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, device->GetType()); } } @@ -614,7 +613,7 @@ bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device, string initial_filename = filepath.GetPath(); if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { - return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } auto file_support = dynamic_cast(device); @@ -627,14 +626,14 @@ bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device, filepath.SetPath((rascsi_image.GetDefaultImageFolder() + "/" + filename).c_str()); if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { - return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } file_support->Open(filepath); } } catch(const io_exception& e) { //NOSONAR This exception is handled properly - return ReturnLocalizedError(context, ERROR_FILE_OPEN, initial_filename, e.get_msg()); + return ReturnLocalizedError(context, LocalizationKey::ERROR_FILE_OPEN, initial_filename, e.get_msg()); } file_support->ReserveFile(filepath, device->GetId(), device->GetLun()); @@ -711,19 +710,19 @@ bool ProcessCmd(const CommandContext& context, const PbDeviceDefinition& pb_devi // Check the Controller Number if (id < 0) { - return ReturnLocalizedError(context, ERROR_MISSING_DEVICE_ID); + return ReturnLocalizedError(context, LocalizationKey::ERROR_MISSING_DEVICE_ID); } if (id >= ControllerManager::DEVICE_MAX) { - return ReturnLocalizedError(context, ERROR_INVALID_ID, to_string(id), to_string(ControllerManager::DEVICE_MAX - 1)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_INVALID_ID, to_string(id), to_string(ControllerManager::DEVICE_MAX - 1)); } if (operation == ATTACH && reserved_ids.find(id) != reserved_ids.end()) { - return ReturnLocalizedError(context, ERROR_RESERVED_ID, to_string(id)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_RESERVED_ID, to_string(id)); } // Check the Unit Number - if (unit < 0 || unit >= AbstractController::LUN_MAX) { - return ReturnLocalizedError(context, ERROR_INVALID_LUN, to_string(unit), to_string(AbstractController::LUN_MAX - 1)); + if (unit < 0 || unit >= ScsiController::LUN_MAX) { + return ReturnLocalizedError(context, LocalizationKey::ERROR_INVALID_LUN, to_string(unit), to_string(ScsiController::LUN_MAX - 1)); } if (operation == ATTACH) { @@ -732,13 +731,13 @@ bool ProcessCmd(const CommandContext& context, const PbDeviceDefinition& pb_devi // Does the controller exist? if (!dryRun && controller_manager.FindController(id) == nullptr) { - return ReturnLocalizedError(context, ERROR_NON_EXISTING_DEVICE, to_string(id)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_NON_EXISTING_DEVICE, to_string(id)); } // Does the unit exist? PrimaryDevice *device = controller_manager.GetDeviceByIdAndLun(id, unit); if (device == nullptr) { - return ReturnLocalizedError(context, ERROR_NON_EXISTING_UNIT, to_string(id), to_string(unit)); + return ReturnLocalizedError(context, LocalizationKey::ERROR_NON_EXISTING_UNIT, to_string(id), to_string(unit)); } if (operation == DETACH) { @@ -746,18 +745,18 @@ bool ProcessCmd(const CommandContext& context, const PbDeviceDefinition& pb_devi } if ((operation == START || operation == STOP) && !device->IsStoppable()) { - return ReturnLocalizedError(context, ERROR_OPERATION_DENIED_STOPPABLE, device->GetType()); + return ReturnLocalizedError(context, LocalizationKey::ERROR_OPERATION_DENIED_STOPPABLE, device->GetType()); } if ((operation == INSERT || operation == EJECT) && !device->IsRemovable()) { - return ReturnLocalizedError(context, ERROR_OPERATION_DENIED_REMOVABLE, device->GetType()); + return ReturnLocalizedError(context, LocalizationKey::ERROR_OPERATION_DENIED_REMOVABLE, device->GetType()); } if ((operation == PROTECT || operation == UNPROTECT) && !device->IsProtectable()) { - return ReturnLocalizedError(context, ERROR_OPERATION_DENIED_PROTECTABLE, device->GetType()); + return ReturnLocalizedError(context, LocalizationKey::ERROR_OPERATION_DENIED_PROTECTABLE, device->GetType()); } if ((operation == PROTECT || operation == UNPROTECT) && !device->IsReady()) { - return ReturnLocalizedError(context, ERROR_OPERATION_DENIED_READY, device->GetType()); + return ReturnLocalizedError(context, LocalizationKey::ERROR_OPERATION_DENIED_READY, device->GetType()); } switch (operation) { @@ -824,7 +823,7 @@ bool ProcessCmd(const CommandContext& context, const PbDeviceDefinition& pb_devi break; default: - return ReturnLocalizedError(context, ERROR_OPERATION); + return ReturnLocalizedError(context, LocalizationKey::ERROR_OPERATION); } return true; @@ -915,8 +914,8 @@ bool ProcessId(const string& id_spec, int& id, int& unit) unit = 0; } else if (!GetAsInt(id_spec.substr(0, separator_pos), id) || id < 0 || id > 7 || - !GetAsInt(id_spec.substr(separator_pos + 1), unit) || unit < 0 || unit >= AbstractController::LUN_MAX) { - cerr << optarg << ": Invalid unit (0-" << (AbstractController::LUN_MAX - 1) << ")" << endl; + !GetAsInt(id_spec.substr(separator_pos + 1), unit) || unit < 0 || unit >= ScsiController::LUN_MAX) { + cerr << optarg << ": Invalid unit (0-" << (ScsiController::LUN_MAX - 1) << ")" << endl; return false; } @@ -925,7 +924,7 @@ bool ProcessId(const string& id_spec, int& id, int& unit) void ShutDown(const CommandContext& context, const string& mode) { if (mode.empty()) { - ReturnLocalizedError(context, ERROR_SHUTDOWN_MODE_MISSING); + ReturnLocalizedError(context, LocalizationKey::ERROR_SHUTDOWN_MODE_MISSING); return; } @@ -942,7 +941,7 @@ void ShutDown(const CommandContext& context, const string& mode) { // The root user has UID 0 if (getuid()) { - ReturnLocalizedError(context, ERROR_SHUTDOWN_PERMISSION); + ReturnLocalizedError(context, LocalizationKey::ERROR_SHUTDOWN_PERMISSION); return; } @@ -969,7 +968,7 @@ void ShutDown(const CommandContext& context, const string& mode) { } } else { - ReturnLocalizedError(context, ERROR_SHUTDOWN_MODE_INVALID); + ReturnLocalizedError(context, LocalizationKey::ERROR_SHUTDOWN_MODE_INVALID); } } @@ -1132,7 +1131,7 @@ bool ParseArgument(int argc, char* argv[], int& port) command.set_operation(ATTACH); Localizer localizer; - CommandContext context(&socket_connector, &localizer, -1, locale); + CommandContext context(socket_connector, localizer, -1, locale); if (!ProcessCmd(context, command)) { return false; } @@ -1179,13 +1178,13 @@ static bool ExecuteCommand(PbCommand& command, CommandContext& context) } if (!access_token.empty() && access_token != GetParam(command, "token")) { - return ReturnLocalizedError(context, ERROR_AUTHENTICATION, UNAUTHORIZED); + return ReturnLocalizedError(context, LocalizationKey::ERROR_AUTHENTICATION, UNAUTHORIZED); } if (!PbOperation_IsValid(command.operation())) { LOGERROR("Received unknown command with operation opcode %d", command.operation()) - return ReturnLocalizedError(context, ERROR_OPERATION, UNKNOWN_OPERATION); + return ReturnLocalizedError(context, LocalizationKey::ERROR_OPERATION, UNKNOWN_OPERATION); } LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()) @@ -1196,7 +1195,7 @@ static bool ExecuteCommand(PbCommand& command, CommandContext& context) case LOG_LEVEL: { string log_level = GetParam(command, "level"); if (bool status = SetLogLevel(log_level); !status) { - ReturnLocalizedError(context, ERROR_LOG_LEVEL, log_level); + ReturnLocalizedError(context, LocalizationKey::ERROR_LOG_LEVEL, log_level); } else { ReturnStatus(context); @@ -1256,7 +1255,7 @@ static bool ExecuteCommand(PbCommand& command, CommandContext& context) case IMAGE_FILE_INFO: { if (string filename = GetParam(command, "file"); filename.empty()) { - ReturnLocalizedError(context, ERROR_MISSING_FILENAME); + ReturnLocalizedError(context, LocalizationKey::ERROR_MISSING_FILENAME); } else { auto image_file = make_unique(); @@ -1267,7 +1266,7 @@ static bool ExecuteCommand(PbCommand& command, CommandContext& context) socket_connector.SerializeMessage(context.fd, result); } else { - ReturnLocalizedError(context, ERROR_IMAGE_FILE_INFO); + ReturnLocalizedError(context, LocalizationKey::ERROR_IMAGE_FILE_INFO); } } break; @@ -1340,9 +1339,10 @@ static void *MonThread(void *) //NOSONAR The pointer cannot be const void * beca // Set up the monitor socket to receive commands listen(monsocket, 1); + Localizer localizer; + while (true) { - Localizer localizer; - CommandContext context(&socket_connector, &localizer, -1, ""); + CommandContext context(socket_connector, localizer, -1, ""); try { PbCommand command; diff --git a/src/raspberrypi/rascsi_image.cpp b/src/raspberrypi/rascsi_image.cpp index 3549e386..a6e3a82d 100644 --- a/src/raspberrypi/rascsi_image.cpp +++ b/src/raspberrypi/rascsi_image.cpp @@ -44,8 +44,7 @@ bool RascsiImage::CreateImageFolder(const CommandContext& context, const string& string folder = filename.substr(0, filename_start); // Checking for existence first prevents an error if the top-level folder is a softlink - struct stat st; - if (stat(folder.c_str(), &st)) { + if (struct stat st; stat(folder.c_str(), &st)) { std::error_code error; filesystem::create_directories(folder, error); if (error) { diff --git a/src/raspberrypi/rascsi_response.cpp b/src/raspberrypi/rascsi_response.cpp index 8eb6a5c0..491996c2 100644 --- a/src/raspberrypi/rascsi_response.cpp +++ b/src/raspberrypi/rascsi_response.cpp @@ -24,7 +24,7 @@ PbDeviceProperties *RascsiResponse::GetDeviceProperties(const Device *device) { auto properties = make_unique().release(); - properties->set_luns(AbstractController::LUN_MAX); + properties->set_luns(ScsiController::LUN_MAX); properties->set_read_only(device->IsReadOnly()); properties->set_protectable(device->IsProtectable()); properties->set_stoppable(device->IsStoppable()); @@ -56,7 +56,7 @@ void RascsiResponse::GetDeviceTypeProperties(PbDeviceTypesInfo& device_types_inf type_properties->set_type(type); const PrimaryDevice *device = device_factory->CreateDevice(type, "", -1); type_properties->set_allocated_properties(GetDeviceProperties(device)); - device_factory->DeleteDevice(*device); //NOSONAR The alloced memory is managed by protobuf + device_factory->DeleteDevice(*device); //NOSONAR The allocated memory is managed by protobuf } void RascsiResponse::GetAllDeviceTypeProperties(PbDeviceTypesInfo& device_types_info) @@ -92,7 +92,7 @@ void RascsiResponse::GetDevice(const Device *device, PbDevice *pb_device) status->set_removed(device->IsRemoved()); status->set_locked(device->IsLocked()); - if (device->SupportsParams()) { //NOSONAR The alloced memory is managed by protobuf + if (device->SupportsParams()) { //NOSONAR The allocated memory is managed by protobuf for (const auto& [key, value] : device->GetParams()) { AddParam(*pb_device, key, value); } @@ -111,7 +111,7 @@ void RascsiResponse::GetDevice(const Device *device, PbDevice *pb_device) GetImageFile(image_file, device->IsRemovable() && !device->IsReady() ? "" : filepath.GetPath()); pb_device->set_allocated_file(image_file); } -} //NOSONAR The alloced memory is managed by protobuf +} //NOSONAR The allocated memory is managed by protobuf bool RascsiResponse::GetImageFile(PbImageFile *image_file, const string& filename) const { @@ -123,8 +123,7 @@ bool RascsiResponse::GetImageFile(PbImageFile *image_file, const string& filenam image_file->set_read_only(access(f.c_str(), W_OK)); - struct stat st; //NOSONAR Cannot be declared in a separate statement because struct keyword is required - if (!stat(f.c_str(), &st) && !S_ISDIR(st.st_mode)) { + if (struct stat st; !stat(f.c_str(), &st) && !S_ISDIR(st.st_mode)) { image_file->set_size(st.st_size); return true; } @@ -135,52 +134,57 @@ bool RascsiResponse::GetImageFile(PbImageFile *image_file, const string& filenam void RascsiResponse::GetAvailableImages(PbImageFilesInfo& image_files_info, string_view default_image_folder, const string& folder, const string& folder_pattern, const string& file_pattern, int scan_depth) { + if (scan_depth-- < 0) { + return; + } + string folder_pattern_lower = folder_pattern; transform(folder_pattern_lower.begin(), folder_pattern_lower.end(), folder_pattern_lower.begin(), ::tolower); string file_pattern_lower = file_pattern; transform(file_pattern_lower.begin(), file_pattern_lower.end(), file_pattern_lower.begin(), ::tolower); - if (scan_depth-- >= 0) { - if (DIR *d = opendir(folder.c_str()); d) { - const dirent *dir; - while ((dir = readdir(d))) { - bool is_supported_type = dir->d_type == DT_REG || dir->d_type == DT_DIR || dir->d_type == DT_LNK || dir->d_type == DT_BLK; - if (is_supported_type && dir->d_name[0] != '.') { - string name_lower = dir->d_name; - if (!file_pattern.empty()) { - transform(name_lower.begin(), name_lower.end(), name_lower.begin(), ::tolower); - } + DIR *d = opendir(folder.c_str()); + if (d == nullptr) { + return; + } - string filename = folder + "/" + dir->d_name; - - if (struct stat st; dir->d_type == DT_REG && !stat(filename.c_str(), &st)) { - if (!st.st_size) { - LOGWARN("File '%s' in image folder '%s' has a size of 0 bytes", dir->d_name, folder.c_str()) - continue; - } - } else if (dir->d_type == DT_LNK && stat(filename.c_str(), &st)) { - LOGWARN("Symlink '%s' in image folder '%s' is broken", dir->d_name, folder.c_str()) - continue; - } else if (dir->d_type == DT_DIR) { - if (folder_pattern_lower.empty() || name_lower.find(folder_pattern_lower) != string::npos) { - GetAvailableImages(image_files_info, default_image_folder, filename, folder_pattern, - file_pattern, scan_depth); - } - continue; - } - - if (file_pattern_lower.empty() || name_lower.find(file_pattern_lower) != string::npos) { - if (auto image_file = make_unique(); GetImageFile(image_file.get(), filename)) { - GetImageFile(image_files_info.add_image_files(), filename.substr(default_image_folder.length() + 1)); - } - } - } + const dirent *dir; + while ((dir = readdir(d))) { + bool is_supported_type = dir->d_type == DT_REG || dir->d_type == DT_DIR || dir->d_type == DT_LNK || dir->d_type == DT_BLK; + if (is_supported_type && dir->d_name[0] != '.') { + string name_lower = dir->d_name; + if (!file_pattern.empty()) { + transform(name_lower.begin(), name_lower.end(), name_lower.begin(), ::tolower); } - closedir(d); + string filename = folder + "/" + dir->d_name; + + if (struct stat st; dir->d_type == DT_REG && !stat(filename.c_str(), &st)) { + if (!st.st_size) { + LOGWARN("File '%s' in image folder '%s' has a size of 0 bytes", dir->d_name, folder.c_str()) + continue; + } + } else if (dir->d_type == DT_LNK && stat(filename.c_str(), &st)) { + LOGWARN("Symlink '%s' in image folder '%s' is broken", dir->d_name, folder.c_str()) + continue; + } else if (dir->d_type == DT_DIR) { + if (folder_pattern_lower.empty() || name_lower.find(folder_pattern_lower) != string::npos) { + GetAvailableImages(image_files_info, default_image_folder, filename, folder_pattern, + file_pattern, scan_depth); + } + continue; + } + + if (file_pattern_lower.empty() || name_lower.find(file_pattern_lower) != string::npos) { + if (auto image_file = make_unique(); GetImageFile(image_file.get(), filename)) { + GetImageFile(image_files_info.add_image_files(), filename.substr(default_image_folder.length() + 1)); + } + } } } + + closedir(d); } PbImageFilesInfo *RascsiResponse::GetAvailableImages(PbResult& result, const string& folder_pattern, @@ -207,7 +211,7 @@ void RascsiResponse::GetAvailableImages(PbResult& result, PbServerInfo& server_i image_files_info->set_default_image_folder(rascsi_image->GetDefaultImageFolder()); server_info.set_allocated_image_files_info(image_files_info); - result.set_status(true); //NOSONAR The alloced memory is managed by protobuf + result.set_status(true); //NOSONAR The allocated memory is managed by protobuf } PbReservedIdsInfo *RascsiResponse::GetReservedIds(PbResult& result, const unordered_set& ids) @@ -278,14 +282,14 @@ PbServerInfo *RascsiResponse::GetServerInfo(PbResult& result, const unordered_se auto server_info = make_unique().release(); server_info->set_allocated_version_info(GetVersionInfo(result)); - server_info->set_allocated_log_level_info(GetLogLevelInfo(result, current_log_level)); //NOSONAR The alloced memory is managed by protobuf - GetAllDeviceTypeProperties(*server_info->mutable_device_types_info()); //NOSONAR The alloced memory is managed by protobuf + server_info->set_allocated_log_level_info(GetLogLevelInfo(result, current_log_level)); //NOSONAR The allocated memory is managed by protobuf + GetAllDeviceTypeProperties(*server_info->mutable_device_types_info()); //NOSONAR The allocated memory is managed by protobuf GetAvailableImages(result, *server_info, folder_pattern, file_pattern, scan_depth); server_info->set_allocated_network_interfaces_info(GetNetworkInterfacesInfo(result)); - server_info->set_allocated_mapping_info(GetMappingInfo(result)); //NOSONAR The alloced memory is managed by protobuf - GetDevices(*server_info); //NOSONAR The alloced memory is managed by protobuf + server_info->set_allocated_mapping_info(GetMappingInfo(result)); //NOSONAR The allocated memory is managed by protobuf + GetDevices(*server_info); //NOSONAR The allocated memory is managed by protobuf server_info->set_allocated_reserved_ids_info(GetReservedIds(result, reserved_ids)); - server_info->set_allocated_operation_info(GetOperationInfo(result, scan_depth)); //NOSONAR The alloced memory is managed by protobuf + server_info->set_allocated_operation_info(GetOperationInfo(result, scan_depth)); //NOSONAR The allocated memory is managed by protobuf result.set_status(true); @@ -461,11 +465,11 @@ PbOperationInfo *RascsiResponse::GetOperationInfo(PbResult& result, int depth) PbOperationMetaData *RascsiResponse::CreateOperation(PbOperationInfo& operation_info, const PbOperation& operation, const string& description) const { - auto meta_data = make_unique(); + auto meta_data = make_shared(); meta_data->set_server_side_name(PbOperation_Name(operation)); meta_data->set_description(description); int ordinal = PbOperation_descriptor()->FindValueByName(PbOperation_Name(operation))->index(); - (*operation_info.mutable_operations())[ordinal] = *meta_data.release(); + (*operation_info.mutable_operations())[ordinal] = *meta_data.get(); return &(*operation_info.mutable_operations())[ordinal]; } diff --git a/src/raspberrypi/rasdump.cpp b/src/raspberrypi/rasdump.cpp index 661bedf0..def76923 100644 --- a/src/raspberrypi/rasdump.cpp +++ b/src/raspberrypi/rasdump.cpp @@ -18,6 +18,10 @@ #include "hal/gpiobus.h" #include "hal/systimer.h" #include "rascsi_version.h" +#include +#include + +using namespace std; //--------------------------------------------------------------------------- // @@ -380,7 +384,7 @@ int MessageIn() //--------------------------------------------------------------------------- int TestUnitReady(int id) { - BYTE cmd[256]; + array cmd = {}; // Result code initialization result = 0; @@ -392,9 +396,8 @@ int TestUnitReady(int id) } // COMMAND - memset(cmd, 0x00, 6); cmd[0] = 0x00; - if (!Command(cmd, 6)) { + if (!Command(cmd.data(), 6)) { result = -2; goto exit; } @@ -425,12 +428,11 @@ exit: //--------------------------------------------------------------------------- int RequestSense(int id, BYTE *buf) { - BYTE cmd[256]; - int count; + array cmd = {}; // Result code initialization result = 0; - count = 0; + int count = 0; // SELECTION if (!Selection(id)) { @@ -439,10 +441,9 @@ int RequestSense(int id, BYTE *buf) } // COMMAND - memset(cmd, 0x00, 6); cmd[0] = 0x03; cmd[4] = 0xff; - if (!Command(cmd, 6)) { + if (!Command(cmd.data(), 6)) { result = -2; goto exit; } @@ -486,12 +487,11 @@ exit: //--------------------------------------------------------------------------- int ModeSense(int id, BYTE *buf) { - BYTE cmd[256]; - int count; + array cmd = {}; // Result code initialization result = 0; - count = 0; + int count = 0; // SELECTION if (!Selection(id)) { @@ -500,11 +500,10 @@ int ModeSense(int id, BYTE *buf) } // COMMAND - memset(cmd, 0x00, 6); cmd[0] = 0x1a; cmd[2] = 0x3f; cmd[4] = 0xff; - if (!Command(cmd, 6)) { + if (!Command(cmd.data(), 6)) { result = -2; goto exit; } @@ -548,12 +547,11 @@ exit: //--------------------------------------------------------------------------- int Inquiry(int id, BYTE *buf) { - BYTE cmd[256]; - int count; + array cmd = {}; // Result code initialization result = 0; - count = 0; + int count = 0; // SELECTION if (!Selection(id)) { @@ -562,10 +560,9 @@ int Inquiry(int id, BYTE *buf) } // COMMAND - memset(cmd, 0x00, 6); cmd[0] = 0x12; cmd[4] = 0xff; - if (!Command(cmd, 6)) { + if (!Command(cmd.data(), 6)) { result = -2; goto exit; } @@ -609,12 +606,11 @@ exit: //--------------------------------------------------------------------------- int ReadCapacity(int id, BYTE *buf) { - BYTE cmd[256]; - int count; + array cmd = {}; // Result code initialization result = 0; - count = 0; + int count = 0; // SELECTION if (!Selection(id)) { @@ -623,9 +619,8 @@ int ReadCapacity(int id, BYTE *buf) } // COMMAND - memset(cmd, 0x00, 10); cmd[0] = 0x25; - if (!Command(cmd, 10)) { + if (!Command(cmd.data(), 10)) { result = -2; goto exit; } @@ -669,12 +664,11 @@ exit: //--------------------------------------------------------------------------- int Read10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) { - BYTE cmd[256]; - int count; + array cmd = {}; // Result code initialization result = 0; - count = 0; + int count = 0; // SELECTION if (!Selection(id)) { @@ -683,7 +677,6 @@ int Read10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) } // COMMAND - memset(cmd, 0x00, 10); cmd[0] = 0x28; cmd[2] = (BYTE)(bstart >> 24); cmd[3] = (BYTE)(bstart >> 16); @@ -691,7 +684,7 @@ int Read10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) cmd[5] = (BYTE)bstart; cmd[7] = (BYTE)(blength >> 8); cmd[8] = (BYTE)blength; - if (!Command(cmd, 10)) { + if (!Command(cmd.data(), 10)) { result = -2; goto exit; } @@ -734,12 +727,11 @@ exit: //--------------------------------------------------------------------------- int Write10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) { - BYTE cmd[256]; - int count; + array cmd = {}; // Result code initialization result = 0; - count = 0; + int count = 0; // SELECTION if (!Selection(id)) { @@ -748,7 +740,6 @@ int Write10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) } // COMMAND - memset(cmd, 0x00, 10); cmd[0] = 0x2a; cmd[2] = (BYTE)(bstart >> 24); cmd[3] = (BYTE)(bstart >> 16); @@ -756,7 +747,7 @@ int Write10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) cmd[5] = (BYTE)bstart; cmd[7] = (BYTE)(blength >> 8); cmd[8] = (BYTE)blength; - if (!Command(cmd, 10)) { + if (!Command(cmd.data(), 10)) { result = -2; goto exit; } @@ -833,6 +824,11 @@ int main(int argc, char* argv[]) exit(EINVAL); } +#ifndef USE_SEL_EVENT_ENABLE + cerr << "Error: No RaSCSI hardware support" << endl; + exit(EXIT_FAILURE); +#endif + // Reset the SCSI bus Reset(); @@ -910,15 +906,15 @@ int main(int argc, char* argv[]) (buffer[2] << 8) | buffer[3]; bnum++; printf("Number of blocks : %d Blocks\n", (int)bnum); - printf("Block length : %d B\n", (int)bsiz); - printf("Unit Capacity : %d MiB %d B\n", + printf("Block length : %d Bytes\n", (int)bsiz); + printf("Unit Capacity : %d MBytes %d Bytes\n", (int)(bsiz * bnum / 1024 / 1024), (int)(bsiz * bnum)); // Get the restore file size if (restore) { size = fio.GetFileSize(); - printf("Restore file size : %d B", (int)size); + printf("Restore file size : %d bytes", (int)size); if (size > (off_t)(bsiz * bnum)) { printf("(WARNING : File size is larger than disk size)"); } else if (size < (off_t)(bsiz * bnum)) { diff --git a/src/raspberrypi/socket_connector.cpp b/src/raspberrypi/socket_connector.cpp index 3f42c584..a95d4253 100644 --- a/src/raspberrypi/socket_connector.cpp +++ b/src/raspberrypi/socket_connector.cpp @@ -20,10 +20,9 @@ using namespace rascsi_interface; int SocketConnector::ReadCommand(PbCommand& command, int socket) const { // Wait for connection - sockaddr_in client; + sockaddr client = {}; socklen_t socklen = sizeof(client); - memset(&client, 0, socklen); - int fd = accept(socket, (sockaddr*)&client, &socklen); + int fd = accept(socket, &client, &socklen); if (fd < 0) { throw io_exception("accept() failed"); } diff --git a/src/raspberrypi/test/abstract_controller_test.cpp b/src/raspberrypi/test/abstract_controller_test.cpp index 3010cd2d..1fca4ad8 100644 --- a/src/raspberrypi/test/abstract_controller_test.cpp +++ b/src/raspberrypi/test/abstract_controller_test.cpp @@ -10,23 +10,114 @@ #include "testing.h" #include "controllers/abstract_controller.h" +TEST(AbstractControllerTest, Reset) +{ + MockAbstractController controller(0); + + controller.SetPhase(BUS::phase_t::status); + EXPECT_EQ(BUS::phase_t::status, controller.GetPhase()); + controller.Reset(); + EXPECT_TRUE(controller.IsBusFree()); +} + +TEST(AbstractControllerTest, SetGetStatus) +{ + MockAbstractController controller(0); + + controller.SetStatus(0x1234); + EXPECT_EQ(0x1234, controller.GetStatus()); +} + +TEST(AbstractControllerTest, SetPhase) +{ + MockAbstractController controller(0); + + controller.SetPhase(BUS::phase_t::selection); + EXPECT_TRUE(controller.IsSelection()); + + controller.SetPhase(BUS::phase_t::busfree); + EXPECT_TRUE(controller.IsBusFree()); + + controller.SetPhase(BUS::phase_t::command); + EXPECT_TRUE(controller.IsCommand()); + + controller.SetPhase(BUS::phase_t::status); + EXPECT_TRUE(controller.IsStatus()); + + controller.SetPhase(BUS::phase_t::datain); + EXPECT_TRUE(controller.IsDataIn()); + + controller.SetPhase(BUS::phase_t::dataout); + EXPECT_TRUE(controller.IsDataOut()); + + controller.SetPhase(BUS::phase_t::msgin); + EXPECT_TRUE(controller.IsMsgIn()); + + controller.SetPhase(BUS::phase_t::msgout); + EXPECT_TRUE(controller.IsMsgOut()); +} + +TEST(AbstractControllerTest, ProcessPhase) +{ + MockAbstractController controller(0); + + controller.SetPhase(BUS::phase_t::selection); + EXPECT_CALL(controller, Selection()).Times(1); + controller.ProcessPhase(); + + controller.SetPhase(BUS::phase_t::busfree); + EXPECT_CALL(controller, BusFree()).Times(1); + controller.ProcessPhase(); + + controller.SetPhase(BUS::phase_t::datain); + EXPECT_CALL(controller, DataIn()).Times(1); + controller.ProcessPhase(); + + controller.SetPhase(BUS::phase_t::dataout); + EXPECT_CALL(controller, DataOut()).Times(1); + controller.ProcessPhase(); + + controller.SetPhase(BUS::phase_t::command); + EXPECT_CALL(controller, Command()).Times(1); + controller.ProcessPhase(); + + controller.SetPhase(BUS::phase_t::status); + EXPECT_CALL(controller, Status()).Times(1); + controller.ProcessPhase(); + + controller.SetPhase(BUS::phase_t::msgin); + EXPECT_CALL(controller, MsgIn()).Times(1); + controller.ProcessPhase(); + + controller.SetPhase(BUS::phase_t::msgout); + EXPECT_CALL(controller, MsgOut()).Times(1); + controller.ProcessPhase(); +} + TEST(AbstractControllerTest, DeviceLunLifeCycle) { const int ID = 1; const int LUN = 4; MockAbstractController controller(ID); - MockPrimaryDevice device; + MockPrimaryDevice device1; + MockPrimaryDevice device2; - device.SetLun(LUN); + EXPECT_FALSE(controller.HasLuns()); + + device1.SetLun(LUN); + device2.SetLun(32); EXPECT_EQ(ID, controller.GetTargetId()); - EXPECT_TRUE(controller.AddDevice(&device)); + EXPECT_TRUE(controller.AddDevice(&device1)); + EXPECT_FALSE(controller.AddDevice(&device2)); + EXPECT_TRUE(controller.HasLuns()); EXPECT_TRUE(controller.HasDeviceForLun(LUN)); EXPECT_FALSE(controller.HasDeviceForLun(0)); - EXPECT_EQ(&device, controller.GetDeviceForLun(LUN)); + EXPECT_EQ(&device1, controller.GetDeviceForLun(LUN)); EXPECT_EQ(nullptr, controller.GetDeviceForLun(0)); - EXPECT_TRUE(controller.DeleteDevice(&device)); + EXPECT_TRUE(controller.DeleteDevice(&device1)); + EXPECT_FALSE(controller.HasLuns()); } TEST(AbstractControllerTest, ExtractInitiatorId) @@ -45,9 +136,9 @@ TEST(AbstractControllerTest, GetOpcode) { MockAbstractController controller(0); - controller.ctrl.cmd.resize(1); + vector& cmd = controller.InitCmd(2); - controller.ctrl.cmd[0] = 0x12; + cmd[0] = 0x12; EXPECT_EQ(0x12, (int)controller.GetOpcode()); } @@ -57,8 +148,16 @@ TEST(AbstractControllerTest, GetLun) MockAbstractController controller(0); - controller.ctrl.cmd.resize(2); + vector& cmd = controller.InitCmd(2); - controller.ctrl.cmd[1] = LUN << 5; + cmd[1] = LUN << 5; EXPECT_EQ(LUN, controller.GetLun()); } + +TEST(AbstractControllerTest, Ctrl) +{ + MockAbstractController controller(0); + + EXPECT_FALSE(controller.HasValidLength()); +} + diff --git a/src/raspberrypi/test/device_factory_test.cpp b/src/raspberrypi/test/device_factory_test.cpp index b06aab03..7a775461 100644 --- a/src/raspberrypi/test/device_factory_test.cpp +++ b/src/raspberrypi/test/device_factory_test.cpp @@ -12,6 +12,7 @@ #include "rascsi_version.h" #include "devices/device.h" #include "devices/device_factory.h" +#include TEST(DeviceFactoryTest, GetTypeForFile) { @@ -101,12 +102,64 @@ TEST(DeviceFactoryTest, GetSectorSizes) EXPECT_TRUE(sector_sizes.find(2048) != sector_sizes.end()); } +TEST(DeviceFactoryTest, GetExtensionMapping) +{ + DeviceFactory device_factory; + + unordered_map mapping = device_factory.GetExtensionMapping(); + EXPECT_EQ(9, mapping.size()); + EXPECT_EQ(SCHD, mapping["hd1"]); + EXPECT_EQ(SCHD, mapping["hds"]); + EXPECT_EQ(SCHD, mapping["hda"]); + EXPECT_EQ(SCHD, mapping["hdn"]); + EXPECT_EQ(SCHD, mapping["hdi"]); + EXPECT_EQ(SCHD, mapping["nhd"]); + EXPECT_EQ(SCRM, mapping["hdr"]); + EXPECT_EQ(SCMO, mapping["mos"]); + EXPECT_EQ(SCCD, mapping["iso"]); +} + +TEST(DeviceFactoryTest, GetDefaultParams) +{ + DeviceFactory device_factory; + + unordered_map params = device_factory.GetDefaultParams(SCHD); + EXPECT_TRUE(params.empty()); + + params = device_factory.GetDefaultParams(SCRM); + EXPECT_TRUE(params.empty()); + + params = device_factory.GetDefaultParams(SCMO); + EXPECT_TRUE(params.empty()); + + params = device_factory.GetDefaultParams(SCCD); + EXPECT_TRUE(params.empty()); + + params = device_factory.GetDefaultParams(SCHS); + EXPECT_TRUE(params.empty()); + + params = device_factory.GetDefaultParams(SCBR); + EXPECT_EQ(2, params.size()); + + params = device_factory.GetDefaultParams(SCDP); + EXPECT_EQ(2, params.size()); + + params = device_factory.GetDefaultParams(SCLP); + EXPECT_EQ(2, params.size()); +} + TEST(DeviceFactoryTest, UnknownDeviceType) { DeviceFactory device_factory; - PrimaryDevice *device = device_factory.CreateDevice(UNDEFINED, "test", -1); - EXPECT_EQ(nullptr, device); + PrimaryDevice *device1 = device_factory.CreateDevice(UNDEFINED, "test", -1); + EXPECT_EQ(nullptr, device1); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + PrimaryDevice *device2 = device_factory.CreateDevice(SAHD, "test", -1); +#pragma GCC diagnostic pop + EXPECT_EQ(nullptr, device2); } TEST(DeviceFactoryTest, SCHD_Device_Defaults) diff --git a/src/raspberrypi/test/device_test.cpp b/src/raspberrypi/test/device_test.cpp index d7423a96..18356b9c 100644 --- a/src/raspberrypi/test/device_test.cpp +++ b/src/raspberrypi/test/device_test.cpp @@ -13,7 +13,7 @@ class TestDevice final : public Device { - FRIEND_TEST(DeviceTest, GetSetParams); + FRIEND_TEST(DeviceTest, Params); FRIEND_TEST(DeviceTest, StatusCode); FRIEND_TEST(DeviceTest, Reset); FRIEND_TEST(DeviceTest, Start); @@ -102,7 +102,7 @@ TEST(DeviceTest, ProductData) EXPECT_EQ("V P R ", device.GetPaddedName()); } -TEST(DeviceTest, GetSetParams) +TEST(DeviceTest, Params) { TestDevice device; unordered_map params; diff --git a/src/raspberrypi/test/disk_test.cpp b/src/raspberrypi/test/disk_test.cpp index ea80e935..fe2b1699 100644 --- a/src/raspberrypi/test/disk_test.cpp +++ b/src/raspberrypi/test/disk_test.cpp @@ -24,7 +24,7 @@ TEST(DiskTest, Rezero) EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdRezero)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(DiskTest, FormatUnit) @@ -34,7 +34,7 @@ TEST(DiskTest, FormatUnit) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(6); + vector& cmd = controller.InitCmd(6); EXPECT_THROW(disk.Dispatch(scsi_command::eCmdFormat), scsi_error_exception); @@ -42,10 +42,10 @@ TEST(DiskTest, FormatUnit) EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdFormat)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); - controller.ctrl.cmd[1] = 0x10; - controller.ctrl.cmd[4] = 1; + cmd[1] = 0x10; + cmd[4] = 1; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdFormat), scsi_error_exception); } @@ -63,7 +63,7 @@ TEST(DiskTest, ReassignBlocks) EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReassign)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(DiskTest, Seek) @@ -73,7 +73,7 @@ TEST(DiskTest, Seek) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(10); + vector& cmd = controller.InitCmd(10); EXPECT_THROW(disk.Dispatch(scsi_command::eCmdSeek6), scsi_error_exception) << "SEEK(6) must fail for a medium with 0 blocks"; @@ -89,17 +89,17 @@ TEST(DiskTest, Seek) disk.SetReady(true); // Block count for SEEK(6) - controller.ctrl.cmd[4] = 1; + cmd[4] = 1; EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdSeek6)); - EXPECT_EQ(0, controller.ctrl.status); - controller.ctrl.cmd[4] = 0; + EXPECT_EQ(0, controller.GetStatus()); + cmd[4] = 0; // Block count for SEEK(10) - controller.ctrl.cmd[5] = 1; + cmd[5] = 1; EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdSeek10)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(DiskTest, ReadCapacity) @@ -109,7 +109,7 @@ TEST(DiskTest, ReadCapacity) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(16); + vector& cmd = controller.InitCmd(16); EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) << "Neithed READ CAPACITY(16) nor READ LONG(16)"; @@ -117,53 +117,53 @@ TEST(DiskTest, ReadCapacity) EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadCapacity10), scsi_error_exception) << "READ CAPACITY(10) must fail because drive is not ready"; // READ CAPACITY(16), not READ LONG(16) - controller.ctrl.cmd[1] = 0x10; + cmd[1] = 0x10; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) << "READ CAPACITY(16) must fail because drive is not ready"; - controller.ctrl.cmd[1] = 0x00; + cmd[1] = 0x00; disk.SetReady(true); EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadCapacity10), scsi_error_exception) << "READ CAPACITY(10) must fail because the medium has no capacity"; // READ CAPACITY(16), not READ LONG(16) - controller.ctrl.cmd[1] = 0x10; + cmd[1] = 0x10; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) << "READ CAPACITY(16) must fail because the medium has no capacity"; - controller.ctrl.cmd[1] = 0x00; + cmd[1] = 0x00; disk.SetBlockCount(0x12345678); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReadCapacity10)); - EXPECT_EQ(0x12, controller.ctrl.buffer[0]); - EXPECT_EQ(0x34, controller.ctrl.buffer[1]); - EXPECT_EQ(0x56, controller.ctrl.buffer[2]); - EXPECT_EQ(0x77, controller.ctrl.buffer[3]); + EXPECT_EQ(0x12, controller.GetBuffer()[0]); + EXPECT_EQ(0x34, controller.GetBuffer()[1]); + EXPECT_EQ(0x56, controller.GetBuffer()[2]); + EXPECT_EQ(0x77, controller.GetBuffer()[3]); disk.SetBlockCount(0x1234567887654321); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReadCapacity10)); - EXPECT_EQ(0xff, controller.ctrl.buffer[0]); - EXPECT_EQ(0xff, controller.ctrl.buffer[1]); - EXPECT_EQ(0xff, controller.ctrl.buffer[2]); - EXPECT_EQ(0xff, controller.ctrl.buffer[3]); + EXPECT_EQ(0xff, controller.GetBuffer()[0]); + EXPECT_EQ(0xff, controller.GetBuffer()[1]); + EXPECT_EQ(0xff, controller.GetBuffer()[2]); + EXPECT_EQ(0xff, controller.GetBuffer()[3]); disk.SetSectorSizeInBytes(1024); // READ CAPACITY(16), not READ LONG(16) - controller.ctrl.cmd[1] = 0x10; + cmd[1] = 0x10; EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16)); - EXPECT_EQ(0x12, controller.ctrl.buffer[0]); - EXPECT_EQ(0x34, controller.ctrl.buffer[1]); - EXPECT_EQ(0x56, controller.ctrl.buffer[2]); - EXPECT_EQ(0x78, controller.ctrl.buffer[3]); - EXPECT_EQ(0x87, controller.ctrl.buffer[4]); - EXPECT_EQ(0x65, controller.ctrl.buffer[5]); - EXPECT_EQ(0x43, controller.ctrl.buffer[6]); - EXPECT_EQ(0x20, controller.ctrl.buffer[7]); - EXPECT_EQ(0x00, controller.ctrl.buffer[8]); - EXPECT_EQ(0x00, controller.ctrl.buffer[9]); - EXPECT_EQ(0x04, controller.ctrl.buffer[10]); - EXPECT_EQ(0x00, controller.ctrl.buffer[11]); + EXPECT_EQ(0x12, controller.GetBuffer()[0]); + EXPECT_EQ(0x34, controller.GetBuffer()[1]); + EXPECT_EQ(0x56, controller.GetBuffer()[2]); + EXPECT_EQ(0x78, controller.GetBuffer()[3]); + EXPECT_EQ(0x87, controller.GetBuffer()[4]); + EXPECT_EQ(0x65, controller.GetBuffer()[5]); + EXPECT_EQ(0x43, controller.GetBuffer()[6]); + EXPECT_EQ(0x20, controller.GetBuffer()[7]); + EXPECT_EQ(0x00, controller.GetBuffer()[8]); + EXPECT_EQ(0x00, controller.GetBuffer()[9]); + EXPECT_EQ(0x04, controller.GetBuffer()[10]); + EXPECT_EQ(0x00, controller.GetBuffer()[11]); } TEST(DiskTest, ReadWriteLong) @@ -173,51 +173,51 @@ TEST(DiskTest, ReadWriteLong) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(16); + vector& cmd = controller.InitCmd(16); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReadLong10)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdWriteLong10)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); - controller.ctrl.cmd[2] = 1; + cmd[2] = 1; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadLong10), scsi_error_exception) << "READ LONG(10) must fail because the capacity is exceeded"; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdWriteLong10), scsi_error_exception) << "WRITE LONG(10) must fail because the capacity is exceeded"; // READ LONG(16), not READ CAPACITY(16) - controller.ctrl.cmd[1] = 0x11; + cmd[1] = 0x11; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) << "READ LONG(16) must fail because the capacity is exceeded"; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdWriteLong16), scsi_error_exception) << "WRITE LONG(16) must fail because the capacity is exceeded"; - controller.ctrl.cmd[2] = 0; + cmd[2] = 0; - controller.ctrl.cmd[7] = 1; + cmd[7] = 1; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadLong10), scsi_error_exception) << "READ LONG(10) must fail because it currently only supports 0 bytes transfer length"; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdWriteLong10), scsi_error_exception) << "WRITE LONG(10) must fail because it currently only supports 0 bytes transfer length"; - controller.ctrl.cmd[7] = 0; + cmd[7] = 0; // READ LONG(16), not READ CAPACITY(16) - controller.ctrl.cmd[1] = 0x11; + cmd[1] = 0x11; EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16)); - EXPECT_EQ(0, controller.ctrl.status); - controller.ctrl.cmd[1] = 0x00; + EXPECT_EQ(0, controller.GetStatus()); + cmd[1] = 0x00; EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdWriteLong16)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); - controller.ctrl.cmd[13] = 1; + cmd[13] = 1; // READ LONG(16), not READ CAPACITY(16) - controller.ctrl.cmd[1] = 0x11; + cmd[1] = 0x11; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) << "READ LONG(16) must fail because it currently only supports 0 bytes transfer length"; - controller.ctrl.cmd[1] = 0x00; + cmd[1] = 0x00; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdWriteLong16), scsi_error_exception) << "WRITE LONG(16) must fail because it currently only supports 0 bytes transfer length"; } @@ -229,15 +229,15 @@ TEST(DiskTest, ReserveRelease) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(6); + controller.InitCmd(6); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReserve6)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdRelease6)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(DiskTest, SendDiagnostic) @@ -247,22 +247,22 @@ TEST(DiskTest, SendDiagnostic) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(6); + vector& cmd = controller.InitCmd(6); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdSendDiag)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); - controller.ctrl.cmd[1] = 0x10; + cmd[1] = 0x10; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdSendDiag), scsi_error_exception) << "SEND DIAGNOSTIC must fail because PF bit is not supported"; - controller.ctrl.cmd[1] = 0; + cmd[1] = 0; - controller.ctrl.cmd[3] = 1; + cmd[3] = 1; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdSendDiag), scsi_error_exception) << "SEND DIAGNOSTIC must fail because parameter list is not supported"; - controller.ctrl.cmd[3] = 0; - controller.ctrl.cmd[4] = 1; + cmd[3] = 0; + cmd[4] = 1; EXPECT_THROW(disk.Dispatch(scsi_command::eCmdSendDiag), scsi_error_exception) << "SEND DIAGNOSTIC must fail because parameter list is not supported"; } @@ -274,7 +274,7 @@ TEST(DiskTest, PreventAllowMediumRemoval) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(6); + vector& cmd = controller.InitCmd(6); EXPECT_THROW(disk.Dispatch(scsi_command::eCmdRemoval), scsi_error_exception) << "REMOVAL must fail because drive is not ready"; @@ -283,13 +283,13 @@ TEST(DiskTest, PreventAllowMediumRemoval) EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdRemoval)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); EXPECT_FALSE(disk.IsLocked()); - controller.ctrl.cmd[4] = 1; + cmd[4] = 1; EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdRemoval)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); EXPECT_TRUE(disk.IsLocked()); } @@ -300,19 +300,19 @@ TEST(DiskTest, SynchronizeCache) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(10); + controller.InitCmd(10); EXPECT_CALL(disk, FlushCache()).Times(1); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdSynchronizeCache10)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); - controller.ctrl.cmd.resize(16); + controller.InitCmd(16); EXPECT_CALL(disk, FlushCache()).Times(1); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdSynchronizeCache16)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(DiskTest, ReadDefectData) @@ -322,11 +322,11 @@ TEST(DiskTest, ReadDefectData) controller.AddDevice(&disk); - controller.ctrl.cmd.resize(10); + controller.InitCmd(10); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(disk.Dispatch(scsi_command::eCmdReadDefectData10)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(DiskTest, SectorSize) diff --git a/src/raspberrypi/test/mode_pages_test.cpp b/src/raspberrypi/test/mode_pages_test.cpp index 95ef6693..d853fc2c 100644 --- a/src/raspberrypi/test/mode_pages_test.cpp +++ b/src/raspberrypi/test/mode_pages_test.cpp @@ -27,11 +27,11 @@ TEST(ModePagesTest, ModePageDevice_AddModePages) MockModePageDevice device; cdb[2] = 0x3f; - EXPECT_EQ(0, device.AddModePages(cdb, buf.data(), 0)) << "Allocation length was not limited"; - EXPECT_EQ(1, device.AddModePages(cdb, buf.data(), 1)) << "Allocation length was not limited"; + EXPECT_EQ(0, device.AddModePages(cdb, buf, 0, 0)) << "Allocation length was not limited"; + EXPECT_EQ(1, device.AddModePages(cdb, buf, 0, 1)) << "Allocation length was not limited"; cdb[2] = 0x00; - EXPECT_THROW(device.AddModePages(cdb, buf.data(), 12), scsi_error_exception) << "Data for non-existing mode page 0 were returned"; + EXPECT_THROW(device.AddModePages(cdb, buf, 0, 12), scsi_error_exception) << "Data for non-existing mode page 0 were returned"; } TEST(ModePagesTest, SCSIHD_SetUpModePages) @@ -83,9 +83,8 @@ TEST(ModePagesTest, SCSICD_SetUpModePages) TEST(ModePagesTest, SCSIMO_SetUpModePages) { map> mode_pages; - unordered_map geometries; const unordered_set sector_sizes; - MockSCSIMO device(sector_sizes, geometries); + MockSCSIMO device(sector_sizes); device.SetUpModePages(mode_pages, 0x3f, false); EXPECT_EQ(6, mode_pages.size()) << "Unexpected number of mode pages"; @@ -117,7 +116,7 @@ TEST(ModePagesTest, ModeSelect) // PF (vendor-specific parameter format) cdb[1] = 0x00; - EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf.data(), LENGTH, 0), scsi_error_exception) + EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf, LENGTH, 0), scsi_error_exception) << "Vendor-specific parameters are not supported"; // PF (standard parameter format) @@ -126,20 +125,20 @@ TEST(ModePagesTest, ModeSelect) buf[9] = 0x00; buf[10] = 0x02; buf[11] = 0x00; - EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf.data(), LENGTH, 256), scsi_error_exception) + EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf, LENGTH, 256), scsi_error_exception) << "Requested sector size does not match current sector size"; // Page 0 buf[LENGTH] = 0x00; - EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf.data(), LENGTH + 2, 512), scsi_error_exception) + EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf, LENGTH + 2, 512), scsi_error_exception) << "Unsupported page 0 was not rejected"; // Page 3 (Format Device Page) buf[LENGTH] = 0x03; - EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf.data(), LENGTH + 2, 512), scsi_error_exception) + EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf, LENGTH + 2, 512), scsi_error_exception) << "Requested sector size does not match current sector size"; // Match the requested to the current sector size buf[LENGTH + 12] = 0x02; - scsi_command_util::ModeSelect(cdb, buf.data(), LENGTH + 2, 512); + scsi_command_util::ModeSelect(cdb, buf, LENGTH + 2, 512); } diff --git a/src/raspberrypi/test/primary_device_test.cpp b/src/raspberrypi/test/primary_device_test.cpp index 5543c7ca..2cde1cc0 100644 --- a/src/raspberrypi/test/primary_device_test.cpp +++ b/src/raspberrypi/test/primary_device_test.cpp @@ -63,7 +63,7 @@ TEST(PrimaryDeviceTest, TestUnitReady) device.SetReady(true); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(device.Dispatch(scsi_command::eCmdTestUnitReady)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(PrimaryDeviceTest, Inquiry) @@ -73,9 +73,9 @@ TEST(PrimaryDeviceTest, Inquiry) device.SetController(&controller); - controller.ctrl.cmd.resize(6); + vector& cmd = controller.InitCmd(6); // ALLOCATION LENGTH - controller.ctrl.cmd[4] = 255; + cmd[4] = 255; ON_CALL(device, InquiryInternal()).WillByDefault([&device]() { return device.HandleInquiry(device_type::PROCESSOR, scsi_level::SPC_3, false); @@ -83,18 +83,18 @@ TEST(PrimaryDeviceTest, Inquiry) EXPECT_CALL(device, InquiryInternal()).Times(1); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(device.Dispatch(scsi_command::eCmdInquiry)); - EXPECT_EQ(0x7F, controller.ctrl.buffer[0]) << "Invalid LUN was not reported"; + EXPECT_EQ(0x7F, controller.GetBuffer()[0]) << "Invalid LUN was not reported"; EXPECT_TRUE(controller.AddDevice(&device)); EXPECT_FALSE(controller.AddDevice(&device)) << "Duplicate LUN was not rejected"; EXPECT_CALL(device, InquiryInternal()).Times(1); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(device.Dispatch(scsi_command::eCmdInquiry)); - EXPECT_EQ(device_type::PROCESSOR, (device_type)controller.ctrl.buffer[0]); - EXPECT_EQ(0x00, controller.ctrl.buffer[1]) << "Device was not reported as non-removable"; - EXPECT_EQ(scsi_level::SPC_3, (scsi_level)controller.ctrl.buffer[2]) << "Wrong SCSI level"; - EXPECT_EQ(scsi_level::SCSI_2, (scsi_level)controller.ctrl.buffer[3]) << "Wrong response level"; - EXPECT_EQ(0x1F, controller.ctrl.buffer[4]) << "Wrong additional data size"; + EXPECT_EQ(device_type::PROCESSOR, (device_type)controller.GetBuffer()[0]); + EXPECT_EQ(0x00, controller.GetBuffer()[1]) << "Device was not reported as non-removable"; + EXPECT_EQ(scsi_level::SPC_3, (scsi_level)controller.GetBuffer()[2]) << "Wrong SCSI level"; + EXPECT_EQ(scsi_level::SCSI_2, (scsi_level)controller.GetBuffer()[3]) << "Wrong response level"; + EXPECT_EQ(0x1f, controller.GetBuffer()[4]) << "Wrong additional data size"; ON_CALL(device, InquiryInternal()).WillByDefault([&device]() { return device.HandleInquiry(device_type::DIRECT_ACCESS, scsi_level::SCSI_1_CCS, true); @@ -102,29 +102,29 @@ TEST(PrimaryDeviceTest, Inquiry) EXPECT_CALL(device, InquiryInternal()).Times(1); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(device.Dispatch(scsi_command::eCmdInquiry)); - EXPECT_EQ(device_type::DIRECT_ACCESS, (device_type)controller.ctrl.buffer[0]); - EXPECT_EQ(0x80, controller.ctrl.buffer[1]) << "Device was not reported as removable"; - EXPECT_EQ(scsi_level::SCSI_1_CCS, (scsi_level)controller.ctrl.buffer[2]) << "Wrong SCSI level"; - EXPECT_EQ(scsi_level::SCSI_1_CCS, (scsi_level)controller.ctrl.buffer[3]) << "Wrong response level"; - EXPECT_EQ(0x1F, controller.ctrl.buffer[4]) << "Wrong additional data size"; + EXPECT_EQ(device_type::DIRECT_ACCESS, (device_type)controller.GetBuffer()[0]); + EXPECT_EQ(0x80, controller.GetBuffer()[1]) << "Device was not reported as removable"; + EXPECT_EQ(scsi_level::SCSI_1_CCS, (scsi_level)controller.GetBuffer()[2]) << "Wrong SCSI level"; + EXPECT_EQ(scsi_level::SCSI_1_CCS, (scsi_level)controller.GetBuffer()[3]) << "Wrong response level"; + EXPECT_EQ(0x1F, controller.GetBuffer()[4]) << "Wrong additional data size"; - controller.ctrl.cmd[1] = 0x01; + cmd[1] = 0x01; EXPECT_CALL(controller, DataIn()).Times(0); EXPECT_THROW(device.Dispatch(scsi_command::eCmdInquiry), scsi_error_exception) << "EVPD bit is not supported"; - controller.ctrl.cmd[2] = 0x01; + cmd[2] = 0x01; EXPECT_CALL(controller, DataIn()).Times(0); EXPECT_THROW(device.Dispatch(scsi_command::eCmdInquiry), scsi_error_exception) << "PAGE CODE field is not supported"; - controller.ctrl.cmd[1] = 0x00; - controller.ctrl.cmd[2] = 0x00; + cmd[1] = 0x00; + cmd[2] = 0x00; // ALLOCATION LENGTH - controller.ctrl.cmd[4] = 1; + cmd[4] = 1; EXPECT_CALL(device, InquiryInternal()).Times(1); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(device.Dispatch(scsi_command::eCmdInquiry)); - EXPECT_EQ(0x1F, controller.ctrl.buffer[4]) << "Wrong additional data size"; - EXPECT_EQ(1, controller.ctrl.length) << "Wrong ALLOCATION LENGTH handling"; + EXPECT_EQ(0x1F, controller.GetBuffer()[4]) << "Wrong additional data size"; + EXPECT_EQ(1, controller.GetLength()) << "Wrong ALLOCATION LENGTH handling"; } TEST(PrimaryDeviceTest, RequestSense) @@ -134,9 +134,9 @@ TEST(PrimaryDeviceTest, RequestSense) controller.AddDevice(&device); - controller.ctrl.cmd.resize(6); + vector& cmd = controller.InitCmd(6); // ALLOCATION LENGTH - controller.ctrl.cmd[4] = 255; + cmd[4] = 255; device.SetReady(false); EXPECT_THROW(device.Dispatch(scsi_command::eCmdRequestSense), scsi_error_exception); @@ -144,7 +144,7 @@ TEST(PrimaryDeviceTest, RequestSense) device.SetReady(true); EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(device.Dispatch(scsi_command::eCmdRequestSense)); - EXPECT_EQ(0, controller.ctrl.status); + EXPECT_EQ(0, controller.GetStatus()); } TEST(PrimaryDeviceTest, ReportLuns) @@ -163,13 +163,13 @@ TEST(PrimaryDeviceTest, ReportLuns) controller.AddDevice(&device2); EXPECT_TRUE(controller.HasDeviceForLun(LUN2)); - controller.ctrl.cmd.resize(10); + vector& cmd = controller.InitCmd(10); // ALLOCATION LENGTH - controller.ctrl.cmd[9] = 255; + cmd[9] = 255; EXPECT_CALL(controller, DataIn()).Times(1); EXPECT_TRUE(device1.Dispatch(scsi_command::eCmdReportLuns)); - const BYTE *buffer = controller.ctrl.buffer; + const vector& buffer = controller.GetBuffer(); EXPECT_EQ(0x00, buffer[0]) << "Wrong data length"; EXPECT_EQ(0x00, buffer[1]) << "Wrong data length"; EXPECT_EQ(0x00, buffer[2]) << "Wrong data length"; @@ -191,7 +191,7 @@ TEST(PrimaryDeviceTest, ReportLuns) EXPECT_EQ(0x00, buffer[22]) << "Wrong LUN2 number"; EXPECT_EQ(LUN2, buffer[23]) << "Wrong LUN2 number"; - controller.ctrl.cmd[2] = 0x01; + cmd[2] = 0x01; EXPECT_THROW(device1.Dispatch(scsi_command::eCmdReportLuns), scsi_error_exception) << "Only SELECT REPORT mode 0 is supported"; } @@ -202,7 +202,7 @@ TEST(PrimaryDeviceTest, UnknownCommand) controller.AddDevice(&device); - controller.ctrl.cmd.resize(1); + controller.InitCmd(1); EXPECT_FALSE(device.Dispatch((scsi_command)0xFF)); } diff --git a/src/raspberrypi/test/scsi_command_util_test.cpp b/src/raspberrypi/test/scsi_command_util_test.cpp index 8d0f7cf1..a3507a31 100644 --- a/src/raspberrypi/test/scsi_command_util_test.cpp +++ b/src/raspberrypi/test/scsi_command_util_test.cpp @@ -52,6 +52,12 @@ TEST(ScsiCommandUtilTest, GetInt16) EXPECT_EQ(0x1234, GetInt16(v, 0)); } +TEST(ScsiCommandUtilTest, GetInt24) +{ + vector v = { 0x12, 0x34, 0x56 }; + EXPECT_EQ(0x123456, GetInt24(v, 0)); +} + TEST(ScsiCommandUtilTest, GetInt32) { vector v = { 0x12, 0x34, 0x56, 0x78 }; @@ -66,11 +72,6 @@ TEST(ScsiCommandUtilTest, GetInt64) TEST(ScsiCommandUtilTest, SetInt16) { - vector buf(2); - SetInt16(buf.data(), 0x1234); - EXPECT_EQ(0x12, buf[0]); - EXPECT_EQ(0x34, buf[1]); - vector v(2); SetInt16(v, 0, 0x1234); EXPECT_EQ(byte{0x12}, v[0]); @@ -80,7 +81,7 @@ TEST(ScsiCommandUtilTest, SetInt16) TEST(ScsiCommandUtilTest, SetInt32) { vector buf(4); - SetInt32(buf.data(), 0x12345678); + SetInt32(buf, 0, 0x12345678); EXPECT_EQ(0x12, buf[0]); EXPECT_EQ(0x34, buf[1]); EXPECT_EQ(0x56, buf[2]); @@ -97,7 +98,7 @@ TEST(ScsiCommandUtilTest, SetInt32) TEST(ScsiCommandUtilTest, SetInt64) { vector buf(8); - SetInt64(buf.data(), 0x1234567887654321); + SetInt64(buf, 0, 0x1234567887654321); EXPECT_EQ(0x12, buf[0]); EXPECT_EQ(0x34, buf[1]); EXPECT_EQ(0x56, buf[2]); diff --git a/src/raspberrypi/test/scsi_controller_test.cpp b/src/raspberrypi/test/scsi_controller_test.cpp index 0a6fc8dc..dbdb19ae 100644 --- a/src/raspberrypi/test/scsi_controller_test.cpp +++ b/src/raspberrypi/test/scsi_controller_test.cpp @@ -10,14 +10,6 @@ #include "testing.h" #include "controllers/scsi_controller.h" -TEST(ScsiControllerTest, Reset) -{ - MockScsiController controller(nullptr, 0); - - EXPECT_CALL(controller, SetPhase(BUS::phase_t::busfree)).Times(1); - controller.Reset(); -} - TEST(ScsiControllerTest, GetMaxLuns) { MockScsiController controller(nullptr, 0); diff --git a/src/raspberrypi/test/testing.h b/src/raspberrypi/test/testing.h index 72559b0b..5ac012e1 100644 --- a/src/raspberrypi/test/testing.h +++ b/src/raspberrypi/test/testing.h @@ -20,16 +20,23 @@ #include "devices/scsimo.h" #include "devices/host_services.h" -class MockAbstractController final : public AbstractController +class MockAbstractController final : public AbstractController //NOSONAR Having many fields/methods cannot be avoided { + FRIEND_TEST(AbstractControllerTest, Reset); + FRIEND_TEST(AbstractControllerTest, SetPhase); + FRIEND_TEST(AbstractControllerTest, ProcessPhase); + FRIEND_TEST(AbstractControllerTest, DeviceLunLifeCycle); + FRIEND_TEST(AbstractControllerTest, ExtractInitiatorId); + FRIEND_TEST(AbstractControllerTest, GetOpcode); + FRIEND_TEST(AbstractControllerTest, GetLun); + FRIEND_TEST(AbstractControllerTest, Ctrl); + public: MOCK_METHOD(BUS::phase_t, Process, (int), (override)); MOCK_METHOD(int, GetEffectiveLun, (), (const override)); MOCK_METHOD(void, Error, (scsi_defs::sense_key, scsi_defs::asc, scsi_defs::status), (override)); MOCK_METHOD(int, GetInitiatorId, (), (const override)); - MOCK_METHOD(void, SetUnit, (int), ()); - MOCK_METHOD(void, Connect, (int, BUS *), ()); MOCK_METHOD(void, Status, (), ()); MOCK_METHOD(void, DataIn, (), ()); MOCK_METHOD(void, DataOut, (), ()); @@ -38,60 +45,15 @@ public: MOCK_METHOD(void, Command, (), ()); MOCK_METHOD(void, MsgIn, (), ()); MOCK_METHOD(void, MsgOut, (), ()); - MOCK_METHOD(void, Send, (), ()); - MOCK_METHOD(bool, XferMsg, (int), ()); - MOCK_METHOD(bool, XferIn, (BYTE *), ()); - MOCK_METHOD(bool, XferOut, (bool), ()); - MOCK_METHOD(void, ReceiveBytes, (), ()); - MOCK_METHOD(void, Execute, (), ()); - MOCK_METHOD(void, FlushUnit, (), ()); - MOCK_METHOD(void, Receive, (), ()); - MOCK_METHOD(bool, HasUnit, (), (const override)); MOCK_METHOD(void, SetByteTransfer, (bool), (override)); MOCK_METHOD(void, ScheduleShutdown, (rascsi_shutdown_mode), (override)); - MOCK_METHOD(void, SetPhase, (BUS::phase_t), (override)); - MOCK_METHOD(void, Reset, (), (override)); - FRIEND_TEST(AbstractControllerTest, DeviceLunLifeCycle); - FRIEND_TEST(AbstractControllerTest, ExtractInitiatorId); - FRIEND_TEST(AbstractControllerTest, GetOpcode); - FRIEND_TEST(AbstractControllerTest, GetLun); - - explicit MockAbstractController(int target_id) : AbstractController(nullptr, target_id) {} + explicit MockAbstractController(int target_id) : AbstractController(nullptr, target_id, 32) {} ~MockAbstractController() override = default; - - int GetMaxLuns() const override { return 32; } }; class MockScsiController final : public ScsiController { -public: - - MOCK_METHOD(BUS::phase_t, Process, (int), (override)); - MOCK_METHOD(void, Error, (scsi_defs::sense_key, scsi_defs::asc, scsi_defs::status), (override)); - MOCK_METHOD(int, GetInitiatorId, (), (const override)); - MOCK_METHOD(void, SetUnit, (int), ()); - MOCK_METHOD(void, Connect, (int, BUS *), ()); - MOCK_METHOD(void, Status, (), ()); - MOCK_METHOD(void, DataIn, (), ()); - MOCK_METHOD(void, DataOut, (), ()); - MOCK_METHOD(void, BusFree, (), ()); - MOCK_METHOD(void, Selection, (), ()); - MOCK_METHOD(void, Command, (), ()); - MOCK_METHOD(void, MsgIn, (), ()); - MOCK_METHOD(void, MsgOut, (), ()); - MOCK_METHOD(void, Send, (), ()); - MOCK_METHOD(bool, XferMsg, (int), ()); - MOCK_METHOD(bool, XferIn, (BYTE *), ()); - MOCK_METHOD(bool, XferOut, (bool), ()); - MOCK_METHOD(void, ReceiveBytes, (), ()); - MOCK_METHOD(void, Execute, (), ()); - MOCK_METHOD(void, FlushUnit, (), ()); - MOCK_METHOD(void, Receive, (), ()); - MOCK_METHOD(bool, HasUnit, (), (const override)); - MOCK_METHOD(void, SetPhase, (BUS::phase_t), (override)); - MOCK_METHOD(void, Sleep, (), ()); - FRIEND_TEST(PrimaryDeviceTest, TestUnitReady); FRIEND_TEST(PrimaryDeviceTest, Inquiry); FRIEND_TEST(PrimaryDeviceTest, RequestSense); @@ -109,6 +71,12 @@ public: FRIEND_TEST(DiskTest, SynchronizeCache); FRIEND_TEST(DiskTest, ReadDefectData); +public: + + MOCK_METHOD(void, Status, (), ()); + MOCK_METHOD(void, DataIn, (), ()); + MOCK_METHOD(void, DataOut, (), ()); + using ScsiController::ScsiController; }; @@ -131,14 +99,12 @@ class MockModePageDevice final : public ModePageDevice { FRIEND_TEST(ModePagesTest, ModePageDevice_AddModePages); -public: - MockModePageDevice() : ModePageDevice("test") {} ~MockModePageDevice() override = default; MOCK_METHOD(vector, InquiryInternal, (), (const)); - MOCK_METHOD(int, ModeSense6, (const vector&, BYTE *, int), (const override)); - MOCK_METHOD(int, ModeSense10, (const vector&, BYTE *, int), (const override)); + MOCK_METHOD(int, ModeSense6, (const vector&, vector&, int), (const override)); + MOCK_METHOD(int, ModeSense10, (const vector&, vector&, int), (const override)); void SetUpModePages(map>& pages, int page, bool) const override { // Return dummy data for other pages than page 0 @@ -177,25 +143,21 @@ class MockSCSIHD_NEC final : public SCSIHD_NEC //NOSONAR Ignore inheritance hier MOCK_METHOD(void, FlushCache, (), (override)); - MockSCSIHD_NEC() = default; - ~MockSCSIHD_NEC() override = default; + using SCSIHD_NEC::SCSIHD_NEC; }; class MockSCSICD final : public SCSICD { FRIEND_TEST(ModePagesTest, SCSICD_SetUpModePages); - explicit MockSCSICD(const unordered_set& sector_sizes) : SCSICD(sector_sizes) {} - ~MockSCSICD() override = default; + using SCSICD::SCSICD; }; class MockSCSIMO final : public SCSIMO { FRIEND_TEST(ModePagesTest, SCSIMO_SetUpModePages); - MockSCSIMO(const unordered_set& sector_sizes, const unordered_map& geometries) - : SCSIMO(sector_sizes, geometries) {} - ~MockSCSIMO() override = default; + using SCSIMO::SCSIMO; }; class MockHostServices final : public HostServices