From ca23d9b7a3fe480a8023395bf6313f8f091a77cc Mon Sep 17 00:00:00 2001 From: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Sat, 8 Oct 2022 19:26:04 +0200 Subject: [PATCH] Merged FileSupport into Disk, improved granularity, more unit tests, code cleanup (#897) * Merged FileSupport into Disk * Improved code granularity * Made classes previously directly writing to cout testable * Added numerous unit tests * Fixed minor issues uncovered by unit tests * Fixed SonarCloud issues * Replaced remaining proprietary data types (WORD/DWORD) except for files in hal/ --- src/raspberrypi/Makefile | 44 +- src/raspberrypi/{scsi.cpp => bus.cpp} | 15 +- src/raspberrypi/bus.h | 2 +- .../controllers/abstract_controller.cpp | 2 +- .../controllers/abstract_controller.h | 1 + .../controllers/controller_manager.cpp | 15 +- .../controllers/controller_manager.h | 2 +- .../controllers/scsi_controller.cpp | 31 +- src/raspberrypi/devices/cd_track.cpp | 3 +- src/raspberrypi/devices/cd_track.h | 4 +- src/raspberrypi/devices/cfilesystem.cpp | 259 +++++----- src/raspberrypi/devices/cfilesystem.h | 258 +++++----- src/raspberrypi/devices/ctapdriver.cpp | 22 +- src/raspberrypi/devices/ctapdriver.h | 8 +- src/raspberrypi/devices/device.cpp | 2 +- src/raspberrypi/devices/device_factory.cpp | 27 +- src/raspberrypi/devices/device_factory.h | 4 +- src/raspberrypi/devices/disk.cpp | 116 +++-- src/raspberrypi/devices/disk.h | 25 +- src/raspberrypi/devices/disk_cache.cpp | 2 + src/raspberrypi/devices/disk_track.cpp | 10 +- src/raspberrypi/devices/disk_track.h | 3 +- src/raspberrypi/devices/file_support.cpp | 55 --- src/raspberrypi/devices/file_support.h | 48 -- src/raspberrypi/devices/host_services.cpp | 18 +- src/raspberrypi/devices/host_services.h | 2 +- src/raspberrypi/devices/mode_page_device.cpp | 12 +- src/raspberrypi/devices/primary_device.cpp | 20 +- src/raspberrypi/devices/primary_device.h | 2 +- src/raspberrypi/devices/scsi_command_util.cpp | 8 +- src/raspberrypi/devices/scsi_daynaport.cpp | 112 ++--- src/raspberrypi/devices/scsi_daynaport.h | 6 +- src/raspberrypi/devices/scsi_host_bridge.cpp | 106 ++-- src/raspberrypi/devices/scsi_host_bridge.h | 8 +- src/raspberrypi/devices/scsi_printer.cpp | 18 +- src/raspberrypi/devices/scsi_printer.h | 4 +- src/raspberrypi/devices/scsicd.cpp | 36 +- src/raspberrypi/devices/scsicd.h | 10 +- src/raspberrypi/devices/scsihd.cpp | 14 +- src/raspberrypi/devices/scsihd.h | 5 +- src/raspberrypi/devices/scsihd_nec.cpp | 2 +- src/raspberrypi/devices/scsimo.cpp | 4 +- src/raspberrypi/devices/scsimo.h | 5 +- src/raspberrypi/fileio.cpp | 7 +- src/raspberrypi/fileio.h | 2 +- src/raspberrypi/filepath.cpp | 8 +- src/raspberrypi/monitor/data_sample.cpp | 2 +- src/raspberrypi/monitor/data_sample.h | 4 +- src/raspberrypi/monitor/sm_html_report.cpp | 51 +- src/raspberrypi/monitor/sm_json_report.cpp | 31 +- src/raspberrypi/monitor/sm_reports.h | 8 +- src/raspberrypi/monitor/sm_vcd_report.cpp | 38 +- src/raspberrypi/os.h | 6 - src/raspberrypi/protobuf_serializer.cpp | 8 +- src/raspberrypi/protobuf_util.cpp | 103 ++++ .../{command_util.h => protobuf_util.h} | 5 +- src/raspberrypi/rascsi.cpp | 73 ++- src/raspberrypi/rascsi/command_context.cpp | 3 +- src/raspberrypi/rascsi/command_context.h | 2 +- src/raspberrypi/rascsi/rascsi_executor.cpp | 82 ++-- src/raspberrypi/rascsi/rascsi_image.cpp | 38 +- src/raspberrypi/rascsi/rascsi_response.cpp | 25 +- src/raspberrypi/rascsi/rascsi_service.cpp | 6 +- src/raspberrypi/rascsi_exceptions.h | 6 +- src/raspberrypi/rascsi_version.cpp | 2 +- src/raspberrypi/rasctl.cpp | 142 ++---- src/raspberrypi/rasctl/rasctl_commands.cpp | 112 +++-- src/raspberrypi/rasctl/rasctl_commands.h | 5 +- src/raspberrypi/rasctl/rasctl_display.cpp | 455 +++++++++++------- src/raspberrypi/rasctl/rasctl_display.h | 36 +- src/raspberrypi/rasctl/rasctl_parser.cpp | 31 ++ src/raspberrypi/rasctl/rasctl_parser.h | 49 ++ src/raspberrypi/rasdump.cpp | 35 +- src/raspberrypi/rasutil.cpp | 31 +- src/raspberrypi/rasutil.h | 7 +- src/raspberrypi/scsi.h | 1 + src/raspberrypi/scsimon.cpp | 37 +- .../test/abstract_controller_test.cpp | 4 +- src/raspberrypi/test/bus_test.cpp | 89 ++++ src/raspberrypi/test/command_context_test.cpp | 40 +- .../test/controller_manager_test.cpp | 13 +- src/raspberrypi/test/disk_test.cpp | 113 +++-- src/raspberrypi/test/file_support_test.cpp | 61 --- src/raspberrypi/test/host_services_test.cpp | 149 ++++++ src/raspberrypi/test/mocks.h | 61 ++- .../test/mode_page_device_test.cpp | 100 ++++ src/raspberrypi/test/mode_pages_test.cpp | 147 ------ src/raspberrypi/test/phase_handler_test.cpp | 56 +++ src/raspberrypi/test/primary_device_test.cpp | 23 +- .../test/protobuf_serializer_test.cpp | 48 +- ...d_util_test.cpp => protobuf_util_test.cpp} | 27 +- .../test/rascsi_exceptions_test.cpp | 16 +- src/raspberrypi/test/rascsi_executor_test.cpp | 4 +- src/raspberrypi/test/rasctl_display_test.cpp | 288 +++++++++++ src/raspberrypi/test/rasctl_parser_test.cpp | 55 +++ src/raspberrypi/test/rasutil_test.cpp | 30 ++ .../test/scsi_command_util_test.cpp | 37 ++ src/raspberrypi/test/scsi_daynaport_test.cpp | 125 +++++ .../test/scsi_host_bridge_test.cpp | 16 + src/raspberrypi/test/scsi_printer_test.cpp | 72 +++ src/raspberrypi/test/scsicd_test.cpp | 33 ++ src/raspberrypi/test/scsihd_nec_test.cpp | 35 ++ src/raspberrypi/test/scsihd_test.cpp | 21 + src/raspberrypi/test/scsimo_test.cpp | 32 ++ src/raspberrypi/test/test_shared.cpp | 61 +++ src/raspberrypi/test/test_shared.h | 25 + 106 files changed, 2951 insertions(+), 1631 deletions(-) rename src/raspberrypi/{scsi.cpp => bus.cpp} (90%) delete mode 100644 src/raspberrypi/devices/file_support.cpp delete mode 100644 src/raspberrypi/devices/file_support.h create mode 100644 src/raspberrypi/protobuf_util.cpp rename src/raspberrypi/{command_util.h => protobuf_util.h} (85%) create mode 100644 src/raspberrypi/rasctl/rasctl_parser.cpp create mode 100644 src/raspberrypi/rasctl/rasctl_parser.h create mode 100644 src/raspberrypi/test/bus_test.cpp delete mode 100644 src/raspberrypi/test/file_support_test.cpp create mode 100644 src/raspberrypi/test/host_services_test.cpp create mode 100644 src/raspberrypi/test/mode_page_device_test.cpp delete mode 100644 src/raspberrypi/test/mode_pages_test.cpp rename src/raspberrypi/test/{command_util_test.cpp => protobuf_util_test.cpp} (66%) create mode 100644 src/raspberrypi/test/rasctl_display_test.cpp create mode 100644 src/raspberrypi/test/rasctl_parser_test.cpp create mode 100644 src/raspberrypi/test/scsi_daynaport_test.cpp create mode 100644 src/raspberrypi/test/scsi_host_bridge_test.cpp create mode 100644 src/raspberrypi/test/scsi_printer_test.cpp create mode 100644 src/raspberrypi/test/scsicd_test.cpp create mode 100644 src/raspberrypi/test/scsihd_nec_test.cpp create mode 100644 src/raspberrypi/test/scsimo_test.cpp create mode 100644 src/raspberrypi/test/test_shared.cpp create mode 100644 src/raspberrypi/test/test_shared.h diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index 74220ac0..5a09b4aa 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -85,14 +85,16 @@ SRC_PROTOC = \ SRC_PROTOBUF = \ rascsi_interface.pb.cpp -SRC_RASCSI_CORE = \ - scsi.cpp \ - filepath.cpp \ - fileio.cpp \ +SRC_SHARED = \ rascsi_version.cpp \ rasutil.cpp \ - command_util.cpp \ + protobuf_util.cpp \ protobuf_serializer.cpp + +SRC_RASCSI_CORE = \ + bus.cpp \ + filepath.cpp \ + fileio.cpp SRC_RASCSI_CORE += $(shell find ./rascsi -name '*.cpp') SRC_RASCSI_CORE += $(shell find ./controllers -name '*.cpp') SRC_RASCSI_CORE += $(shell find ./devices -name '*.cpp') @@ -102,22 +104,18 @@ SRC_RASCSI = rascsi.cpp SRC_SCSIMON = \ scsimon.cpp \ - scsi.cpp \ + bus.cpp \ rascsi_version.cpp SRC_SCSIMON += $(shell find ./monitor -name '*.cpp') SRC_SCSIMON += $(shell find ./hal -name '*.cpp') -SRC_RASCTL = \ - rasctl.cpp\ - rascsi_version.cpp \ - rasutil.cpp \ - command_util.cpp \ - protobuf_serializer.cpp -SRC_RASCTL += $(shell find ./rasctl -name '*.cpp') +SRC_RASCTL_CORE = $(shell find ./rasctl -name '*.cpp') + +SRC_RASCTL = rasctl.cpp SRC_RASDUMP = \ rasdump.cpp \ - scsi.cpp \ + bus.cpp \ filepath.cpp \ fileio.cpp \ rascsi_version.cpp @@ -134,10 +132,12 @@ vpath ./$(BINDIR) OBJ_RASCSI_CORE := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCSI_CORE:%.cpp=%.o))) OBJ_RASCSI := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCSI:%.cpp=%.o))) +OBJ_RASCTL_CORE := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCTL_CORE:%.cpp=%.o))) OBJ_RASCTL := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCTL:%.cpp=%.o))) OBJ_RASDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASDUMP:%.cpp=%.o))) OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o))) OBJ_RASCSI_TEST := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCSI_TEST:%.cpp=%.o))) +OBJ_SHARED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SHARED:%.cpp=%.o))) OBJ_PROTOBUF := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PROTOBUF:%.cpp=%.o))) GEN_PROTOBUF := $(SRC_PROTOBUF) rascsi_interface.pb.h @@ -145,7 +145,7 @@ GEN_PROTOBUF := $(SRC_PROTOBUF) rascsi_interface.pb.h # The following will include all of the auto-generated dependency files (*.d) # if they exist. This will trigger a rebuild of a source file if a header changes -ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_SCSIMON) $(OBJ_RASCSI_TEST)) +ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_SCSIMON) $(OBJ_RASCSI_TEST)) -include $(ALL_DEPS) $(OBJDIR) $(BINDIR): @@ -186,13 +186,13 @@ lcov: test docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt $(DOC_DIR)/scsimon_man_page.txt -$(SRC_RASCSI_CORE): $(SRC_PROTOBUF) +$(SRC_SHARED): $(SRC_PROTOBUF) -$(BINDIR)/$(RASCSI): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_PROTOBUF) | $(BINDIR) - $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_PROTOBUF) -lpthread -lpcap -lprotobuf -lstdc++fs +$(BINDIR)/$(RASCSI): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_SHARED) $(OBJ_PROTOBUF) | $(BINDIR) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_SHARED) $(OBJ_PROTOBUF) -lpthread -lpcap -lprotobuf -lstdc++fs -$(BINDIR)/$(RASCTL): $(SRC_PROTOBUF) $(OBJ_RASCTL) $(OBJ_PROTOBUF) | $(BINDIR) - $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL) $(OBJ_PROTOBUF) -lpthread -lprotobuf +$(BINDIR)/$(RASCTL): $(SRC_PROTOBUF) $(OBJ_RASCTL_CORE) $(OBJ_RASCTL) $(OBJ_SHARED) $(OBJ_PROTOBUF) | $(BINDIR) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL_CORE) $(OBJ_RASCTL) $(OBJ_SHARED) $(OBJ_PROTOBUF) -lpthread -lprotobuf $(BINDIR)/$(RASDUMP): $(OBJ_RASDUMP) | $(BINDIR) $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASDUMP) @@ -200,8 +200,8 @@ $(BINDIR)/$(RASDUMP): $(OBJ_RASDUMP) | $(BINDIR) $(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) | $(BINDIR) $(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread -$(BINDIR)/$(RASCSI_TEST): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCSI_TEST) $(OBJ_PROTOBUF) | $(BINDIR) - $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI_CORE) $(OBJ_RASCSI_TEST) $(OBJ_PROTOBUF) -lpthread -lpcap -lprotobuf -lstdc++fs -lgmock -lgtest +$(BINDIR)/$(RASCSI_TEST): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI_TEST) $(OBJ_RASCTL_TEST) $(OBJ_SHARED) $(OBJ_PROTOBUF) | $(BINDIR) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI_TEST) $(OBJ_SHARED) $(OBJ_PROTOBUF) -lpthread -lpcap -lprotobuf -lstdc++fs -lgmock -lgtest # Phony rules for building individual utilities diff --git a/src/raspberrypi/scsi.cpp b/src/raspberrypi/bus.cpp similarity index 90% rename from src/raspberrypi/scsi.cpp rename to src/raspberrypi/bus.cpp index 32ae9f1c..206e1701 100644 --- a/src/raspberrypi/scsi.cpp +++ b/src/raspberrypi/bus.cpp @@ -1,11 +1,10 @@ //--------------------------------------------------------------------------- // -// X68000 EMULATOR "XM6" +// X68000 EMULATOR "XM6" // -// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) -// Copyright (C) 2014-2020 GIMONS -// -// [ SCSI Common Functionality ] +// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2020 GIMONS +// Copyright (C) 2022 Uwe Seimet // //--------------------------------------------------------------------------- @@ -31,9 +30,9 @@ BUS::phase_t BUS::GetPhase() } // Get target phase from bus signal line - int mci = GetMSG() ? 0x04 : 0x00; - mci |= GetCD() ? 0x02 : 0x00; - mci |= GetIO() ? 0x01 : 0x00; + int mci = GetMSG() ? 0b100 : 0b000; + mci |= GetCD() ? 0b010 : 0b000; + mci |= GetIO() ? 0b001 : 0b000; return GetPhase(mci); } diff --git a/src/raspberrypi/bus.h b/src/raspberrypi/bus.h index 8310c5c4..52de3be4 100644 --- a/src/raspberrypi/bus.h +++ b/src/raspberrypi/bus.h @@ -59,7 +59,7 @@ public: static const char* GetPhaseStrRaw(phase_t current_phase); // Extract as specific pin field from a raw data capture - static inline DWORD GetPinRaw(DWORD raw_data, DWORD pin_num) + static inline uint32_t GetPinRaw(uint32_t raw_data, uint32_t pin_num) { return ((raw_data >> pin_num) & 1); } diff --git a/src/raspberrypi/controllers/abstract_controller.cpp b/src/raspberrypi/controllers/abstract_controller.cpp index bb1065df..a9d08b13 100644 --- a/src/raspberrypi/controllers/abstract_controller.cpp +++ b/src/raspberrypi/controllers/abstract_controller.cpp @@ -88,7 +88,7 @@ void AbstractController::ProcessPhase() default: LOGERROR("Cannot process phase %s", BUS::GetPhaseStrRaw(GetPhase())) - throw scsi_error_exception(); + throw scsi_exception(); break; } } diff --git a/src/raspberrypi/controllers/abstract_controller.h b/src/raspberrypi/controllers/abstract_controller.h index 4692d0d7..0007662d 100644 --- a/src/raspberrypi/controllers/abstract_controller.h +++ b/src/raspberrypi/controllers/abstract_controller.h @@ -11,6 +11,7 @@ #pragma once +#include "scsi.h" #include "bus.h" #include "phase_handler.h" #include diff --git a/src/raspberrypi/controllers/controller_manager.cpp b/src/raspberrypi/controllers/controller_manager.cpp index 712ad6f8..ce93a4da 100644 --- a/src/raspberrypi/controllers/controller_manager.cpp +++ b/src/raspberrypi/controllers/controller_manager.cpp @@ -9,7 +9,6 @@ #include "devices/device_factory.h" #include "devices/primary_device.h" -#include "devices/file_support.h" #include "scsi_controller.h" #include "controller_manager.h" @@ -20,15 +19,21 @@ bool ControllerManager::AttachToScsiController(int id, shared_ptr auto controller = FindController(id); if (controller == nullptr) { controller = make_shared(bus, id); - controllers[id] = controller; + if (controller->AddDevice(device)) { + controllers[id] = controller; + + return true; + } + + return false; } return controller->AddDevice(device); } -void ControllerManager::DeleteController(shared_ptr controller) +bool ControllerManager::DeleteController(shared_ptr controller) { - controllers.erase(controller->GetTargetId()); + return controllers.erase(controller->GetTargetId()) == 1; } shared_ptr ControllerManager::IdentifyController(int data) const @@ -53,7 +58,7 @@ unordered_set> ControllerManager::GetAllDevices() cons unordered_set> devices; for (const auto& [id, controller] : controllers) { - auto d = controller->GetDevices(); + const auto& d = controller->GetDevices(); devices.insert(d.begin(), d.end()); } diff --git a/src/raspberrypi/controllers/controller_manager.h b/src/raspberrypi/controllers/controller_manager.h index 16e5459c..3bcd1e66 100644 --- a/src/raspberrypi/controllers/controller_manager.h +++ b/src/raspberrypi/controllers/controller_manager.h @@ -36,7 +36,7 @@ public: static const int DEVICE_MAX = 8; bool AttachToScsiController(int, shared_ptr); - void DeleteController(shared_ptr); + bool DeleteController(shared_ptr); shared_ptr IdentifyController(int) const; shared_ptr FindController(int) const; unordered_set> GetAllDevices() const; diff --git a/src/raspberrypi/controllers/scsi_controller.cpp b/src/raspberrypi/controllers/scsi_controller.cpp index 63d171db..df4667aa 100644 --- a/src/raspberrypi/controllers/scsi_controller.cpp +++ b/src/raspberrypi/controllers/scsi_controller.cpp @@ -79,7 +79,7 @@ BUS::phase_t ScsiController::Process(int id) try { ProcessPhase(); } - catch(const scsi_error_exception&) { + catch(const scsi_exception&) { // Any exception should have been handled during the phase processing assert(false); @@ -198,8 +198,8 @@ void ScsiController::Command() bus.SetCD(true); bus.SetIO(false); - int actual_count = bus.CommandHandShake(GetBuffer().data()); - int command_byte_count = GPIOBUS::GetCommandByteCount(GetBuffer()[0]); + const int actual_count = bus.CommandHandShake(GetBuffer().data()); + const 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) { @@ -267,10 +267,10 @@ void ScsiController::Execute() if (!device->Dispatch(GetOpcode())) { LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetTargetId(), lun, (int)GetOpcode()) - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); } } - catch(const scsi_error_exception& e) { //NOSONAR This exception is handled properly + catch(const scsi_exception& e) { //NOSONAR This exception is handled properly Error(e.get_sense_key(), e.get_asc(), e.get_status()); // Fall through @@ -459,10 +459,9 @@ void ScsiController::Error(sense_key sense_key, asc asc, status status) } if (sense_key != sense_key::NO_SENSE || asc != asc::NO_ADDITIONAL_SENSE_INFORMATION) { - LOGDEBUG("Error status: Sense Key $%02X, ASC $%02X, ASCQ $%02X", - (int)sense_key << 16, (int)asc << 8, (int)asc & 0xff) + LOGDEBUG("Error status: Sense Key $%02X, ASC $%02X", (int)sense_key, (int)asc) - // Set Sense Key and ASC for a subsequent REQUEST SENSE + // Set Sense Key and ASC for a subsequent REQUEST SENSE GetDeviceForLun(lun)->SetStatusCode(((int)sense_key << 16) | ((int)asc << 8)); } @@ -485,7 +484,7 @@ void ScsiController::Send() // 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(GetBuffer().data() + ctrl.offset, ctrl.length, + if (const 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 @@ -798,7 +797,7 @@ void ScsiController::FlushUnit() try { disk->ModeSelect(ctrl.cmd, GetBuffer(), GetOffset()); } - catch(const scsi_error_exception& e) { + catch(const scsi_exception& e) { LOGWARN("Error occured while processing Mode Select command %02X\n", (int)GetOpcode()) Error(e.get_sense_key(), e.get_asc(), e.get_status()); return; @@ -841,7 +840,7 @@ bool ScsiController::XferIn(vector& buf) try { ctrl.length = (dynamic_pointer_cast(GetDeviceForLun(lun)))->Read(ctrl.cmd, buf, ctrl.next); } - catch(const scsi_error_exception&) { + catch(const scsi_exception&) { // If there is an error, go to the status phase return false; } @@ -881,7 +880,7 @@ bool ScsiController::XferOutBlockOriented(bool cont) try { disk->ModeSelect(ctrl.cmd, GetBuffer(), GetOffset()); } - catch(const scsi_error_exception& e) { + catch(const scsi_exception& e) { Error(e.get_sense_key(), e.get_asc(), e.get_status()); return false; } @@ -919,7 +918,7 @@ bool ScsiController::XferOutBlockOriented(bool cont) try { disk->Write(ctrl.cmd, GetBuffer(), ctrl.next - 1); } - catch(const scsi_error_exception& e) { + catch(const scsi_exception& e) { Error(e.get_sense_key(), e.get_asc(), e.get_status()); // Write failed @@ -936,7 +935,7 @@ bool ScsiController::XferOutBlockOriented(bool cont) try { ctrl.length = disk->WriteCheck(ctrl.next - 1); } - catch(const scsi_error_exception&) { + catch(const scsi_exception&) { // Cannot write return false; } @@ -976,7 +975,7 @@ void ScsiController::ParseMessage() { int i = 0; while (i < scsi.msc) { - BYTE message_type = scsi.msb[i]; + const BYTE message_type = scsi.msb[i]; if (message_type == 0x06) { LOGTRACE("Received ABORT message") @@ -1064,7 +1063,7 @@ int ScsiController::GetEffectiveLun() const void ScsiController::Sleep() { - if (uint32_t time = SysTimer::GetTimerLow() - execstart; time < MIN_EXEC_TIME) { + if (const uint32_t time = SysTimer::GetTimerLow() - execstart; time < MIN_EXEC_TIME) { SysTimer::SleepUsec(MIN_EXEC_TIME - time); } execstart = 0; diff --git a/src/raspberrypi/devices/cd_track.cpp b/src/raspberrypi/devices/cd_track.cpp index a27b75f9..f32b7621 100644 --- a/src/raspberrypi/devices/cd_track.cpp +++ b/src/raspberrypi/devices/cd_track.cpp @@ -7,12 +7,13 @@ // 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. // //--------------------------------------------------------------------------- #include "cd_track.h" +#include void CDTrack::Init(int track, uint32_t first, uint32_t last) { diff --git a/src/raspberrypi/devices/cd_track.h b/src/raspberrypi/devices/cd_track.h index 20660c4f..0e097399 100644 --- a/src/raspberrypi/devices/cd_track.h +++ b/src/raspberrypi/devices/cd_track.h @@ -23,7 +23,7 @@ public: CDTrack() = default; ~CDTrack() = default; - void Init(int track, DWORD first, DWORD last); + void Init(int track, uint32_t first, uint32_t last); // Properties void SetPath(bool cdda, const Filepath& path); // Set the path @@ -32,7 +32,7 @@ public: uint32_t GetLast() const; // Get the last LBA uint32_t GetBlocks() const; // Get the number of blocks int GetTrackNo() const; // Get the track number - bool IsValid(DWORD lba) const; // Is this a valid LBA? + bool IsValid(uint32_t lba) const; // Is this a valid LBA? bool IsAudio() const; // Is this an audio track? private: diff --git a/src/raspberrypi/devices/cfilesystem.cpp b/src/raspberrypi/devices/cfilesystem.cpp index be8673bc..61c7433a 100644 --- a/src/raspberrypi/devices/cfilesystem.cpp +++ b/src/raspberrypi/devices/cfilesystem.cpp @@ -48,7 +48,7 @@ static void convert(char const *src, char const *dest, return; } - if (size_t ret = iconv(cd, &inbuf, &in, &outbuf, &out); ret == (size_t)-1) { + if (const size_t ret = iconv(cd, &inbuf, &in, &outbuf, &out); ret == (size_t)-1) { return; } @@ -166,7 +166,7 @@ void Human68k::namests_t::GetCopyFilename(BYTE* szFilename) const if (i >= 8) { // Transfer the extraneous part for (i = 0; i < 10; i++) { - BYTE c = add[i]; + const BYTE c = add[i]; if (c == '\0') break; *p++ = c; @@ -178,7 +178,7 @@ void Human68k::namests_t::GetCopyFilename(BYTE* szFilename) const if (ext[0] != ' ' || ext[1] != ' ' || ext[2] != ' ') { *p++ = '.'; for (i = 0; i < 3; i++) { - BYTE c = ext[i]; + const BYTE c = ext[i]; if (c == ' ') { // Check that the file extension continues after a space is detected /// TODO: Should change this function to be compatible with 8+3 chars and TwentyOne @@ -226,7 +226,7 @@ CHostDrv::~CHostDrv() // Initialization (device boot and load) // //--------------------------------------------------------------------------- -void CHostDrv::Init(const TCHAR* szBase, DWORD nFlag) +void CHostDrv::Init(const TCHAR* szBase, uint32_t nFlag) { assert(szBase); assert(strlen(szBase) < FILEPATH_MAX); @@ -253,7 +253,7 @@ void CHostDrv::Init(const TCHAR* szBase, DWORD nFlag) TCHAR* pClear = nullptr; TCHAR* p = m_szBase; for (;;) { - TCHAR c = *p; + const TCHAR c = *p; if (c == '\0') break; if (c == '/' || c == '\\') { @@ -301,7 +301,7 @@ BYTE CHostDrv::GetMediaByte() const // Get drive status // //--------------------------------------------------------------------------- -DWORD CHostDrv::GetStatus() const +uint32_t CHostDrv::GetStatus() const { return 0x40 | (m_bEnable ? (m_bWriteProtect ? 0x08 : 0) | 0x02 : 0); } @@ -408,15 +408,15 @@ bool CHostDrv::GetVolumeCache(TCHAR* szLabel) const return m_bVolumeCache; } -DWORD CHostDrv::GetCapacity(Human68k::capacity_t* pCapacity) +uint32_t CHostDrv::GetCapacity(Human68k::capacity_t* pCapacity) { assert(pCapacity); assert(m_bEnable); - DWORD nFree = 0x7FFF8000; - DWORD freearea; - DWORD clusters; - DWORD sectors; + const uint32_t nFree = 0x7FFF8000; + uint32_t freearea; + uint32_t clusters; + uint32_t sectors; freearea = 0xFFFF; clusters = 0xFFFF; @@ -428,9 +428,9 @@ DWORD CHostDrv::GetCapacity(Human68k::capacity_t* pCapacity) assert(sectors <= 64); // Update cache - m_capCache.freearea = (WORD)freearea; - m_capCache.clusters = (WORD)clusters; - m_capCache.sectors = (WORD)sectors; + m_capCache.freearea = (uint16_t)freearea; + m_capCache.clusters = (uint16_t)clusters; + m_capCache.sectors = (uint16_t)sectors; m_capCache.bytes = 512; // Transfer contents @@ -808,7 +808,7 @@ void CHostFilename::ConvertHuman(int nCount) } size_t nMax = 18; // Number of bytes for the base segment (base name and extension) - DWORD nOption = CFileSys::GetFileOption(); + uint32_t nOption = CFileSys::GetFileOption(); if (nOption & WINDRV_OPT_CONVERT_LENGTH) nMax = 8; @@ -817,7 +817,7 @@ void CHostFilename::ConvertHuman(int nCount) BYTE* pNumber = nullptr; if (nCount >= 0) { pNumber = &szNumber[8]; - for (DWORD i = 0; i < 5; i++) { // Max 5+1 digits (always leave the first 2 bytes of the base name) + for (uint32_t i = 0; i < 5; i++) { // Max 5+1 digits (always leave the first 2 bytes of the base name) int n = nCount % 36; nMax--; pNumber--; @@ -1082,7 +1082,7 @@ bool CHostFilename::isReduce() const /// Evaluate Human68k directory entry attribute // //--------------------------------------------------------------------------- -int CHostFilename::CheckAttribute(DWORD nHumanAttribute) const +int CHostFilename::CheckAttribute(uint32_t nHumanAttribute) const { BYTE nAttribute = m_dirHuman.attr; if ((nAttribute & (Human68k::AT_ARCHIVE | Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) == 0) @@ -1099,7 +1099,7 @@ int CHostFilename::CheckAttribute(DWORD nHumanAttribute) const const BYTE* CHostFilename::SeparateExt(const BYTE* szHuman) // static { // Obtain the file name length - size_t nLength = strlen((const char*)szHuman); + const size_t nLength = strlen((const char*)szHuman); const BYTE* pFirst = szHuman; const BYTE* pLast = pFirst + nLength; @@ -1124,7 +1124,7 @@ const BYTE* CHostFilename::SeparateExt(const BYTE* szHuman) // static // //=========================================================================== -DWORD CHostPath::g_nId; ///< Identifier creation counter +uint32_t CHostPath::g_nId; ///< Identifier creation counter CHostPath::~CHostPath() { @@ -1144,7 +1144,7 @@ CHostPath::ring_t* CHostPath::Alloc(size_t nLength) // static { assert(nLength < FILEPATH_MAX); - size_t n = offsetof(ring_t, f) + CHostFilename::Offset() + (nLength + 1) * sizeof(TCHAR); + const size_t n = offsetof(ring_t, f) + CHostFilename::Offset() + (nLength + 1) * sizeof(TCHAR); auto p = (ring_t*)malloc(n); assert(p); @@ -1295,8 +1295,8 @@ bool CHostPath::isSameHuman(const BYTE* szHuman) const assert(szHuman); // Calulate number of chars - size_t nLength = strlen((const char*)m_szHuman); - size_t n = strlen((const char*)szHuman); + const size_t nLength = strlen((const char*)m_szHuman); + const size_t n = strlen((const char*)szHuman); // Check number of chars if (nLength != n) @@ -1331,7 +1331,7 @@ bool CHostPath::isSameChild(const BYTE* szHuman) const /// Make sure to lock from the top. // //--------------------------------------------------------------------------- -const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, DWORD nHumanAttribute) const +const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, uint32_t nHumanAttribute) const { assert(szHuman); @@ -1368,7 +1368,7 @@ const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, DWORD nHumanAt /// Make sure to lock from the top. // //--------------------------------------------------------------------------- -const CHostFilename* CHostPath::FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const +const CHostFilename* CHostPath::FindFilenameWildcard(const BYTE* szHuman, uint32_t nHumanAttribute, find_t* pFind) const { assert(szHuman); assert(pFind); @@ -1386,7 +1386,7 @@ const CHostFilename* CHostPath::FindFilenameWildcard(const BYTE* szHuman, DWORD p = pFind->pos; } else { // Find the start position in the directory entry contents - DWORD n = 0; + uint32_t n = 0; for (;; p = (const ring_t*)p->r.Next()) { if (p == (const ring_t*)&m_cRing) { // Extrapolate from the count when the same entry isn't found (just in case) @@ -1547,7 +1547,7 @@ void CHostPath::Refresh() // - No duplicated names in previous entries // - No entity with the same name exists if (pFilename->isReduce() || !pFilename->isCorrect()) { // Confirm that file name update is required - for (DWORD n = 0; n < XM6_HOST_FILENAME_PATTERN_MAX; n++) { + for (uint32_t n = 0; n < XM6_HOST_FILENAME_PATTERN_MAX; n++) { // Confirm file name validity if (pFilename->isCorrect()) { // Confirm match with previous entry @@ -1583,14 +1583,14 @@ void CHostPath::Refresh() nHumanAttribute |= Human68k::AT_READONLY; pFilename->SetEntryAttribute(nHumanAttribute); - auto nHumanSize = (DWORD)sb.st_size; + auto nHumanSize = (uint32_t)sb.st_size; pFilename->SetEntrySize(nHumanSize); - WORD nHumanDate = 0; - WORD nHumanTime = 0; + uint16_t nHumanDate = 0; + uint16_t nHumanTime = 0; if (tm pt = {}; localtime_r(&sb.st_mtime, &pt) != nullptr) { - nHumanDate = (WORD)(((pt.tm_year - 80) << 9) | ((pt.tm_mon + 1) << 5) | pt.tm_mday); - nHumanTime = (WORD)((pt.tm_hour << 11) | (pt.tm_min << 5) | (pt.tm_sec >> 1)); + nHumanDate = (uint16_t)(((pt.tm_year - 80) << 9) | ((pt.tm_mon + 1) << 5) | pt.tm_mday); + nHumanTime = (uint16_t)((pt.tm_hour << 11) | (pt.tm_min << 5) | (pt.tm_sec >> 1)); } pFilename->SetEntryDate(nHumanDate); pFilename->SetEntryTime(nHumanTime); @@ -1760,7 +1760,7 @@ void CHostEntry::CleanCache() const /// Update the cache for the specified unit // //--------------------------------------------------------------------------- -void CHostEntry::CleanCache(DWORD nUnit) const +void CHostEntry::CleanCache(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1773,7 +1773,7 @@ void CHostEntry::CleanCache(DWORD nUnit) const /// Update the cache for the specified path // //--------------------------------------------------------------------------- -void CHostEntry::CleanCache(DWORD nUnit, const BYTE* szHumanPath) const +void CHostEntry::CleanCache(uint32_t nUnit, const BYTE* szHumanPath) const { assert(szHumanPath); assert(nUnit < DRIVE_MAX); @@ -1787,7 +1787,7 @@ void CHostEntry::CleanCache(DWORD nUnit, const BYTE* szHumanPath) const /// Update all cache for the specified path and below // //--------------------------------------------------------------------------- -void CHostEntry::CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath) const +void CHostEntry::CleanCacheChild(uint32_t nUnit, const BYTE* szHumanPath) const { assert(szHumanPath); assert(nUnit < DRIVE_MAX); @@ -1801,7 +1801,7 @@ void CHostEntry::CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath) const /// Delete cache for the specified path // //--------------------------------------------------------------------------- -void CHostEntry::DeleteCache(DWORD nUnit, const BYTE* szHumanPath) const +void CHostEntry::DeleteCache(uint32_t nUnit, const BYTE* szHumanPath) const { assert(szHumanPath); assert(nUnit < DRIVE_MAX); @@ -1815,7 +1815,7 @@ void CHostEntry::DeleteCache(DWORD nUnit, const BYTE* szHumanPath) const /// Find host side names (path name + file name (can be abbreviated) + attribute) // //--------------------------------------------------------------------------- -bool CHostEntry::Find(DWORD nUnit, CHostFiles* pFiles) const +bool CHostEntry::Find(uint32_t nUnit, CHostFiles* pFiles) const { assert(pFiles); assert(nUnit < DRIVE_MAX); @@ -1829,7 +1829,7 @@ bool CHostEntry::Find(DWORD nUnit, CHostFiles* pFiles) const /// Drive settings // //--------------------------------------------------------------------------- -void CHostEntry::SetDrv(DWORD nUnit, CHostDrv* pDrv) +void CHostEntry::SetDrv(uint32_t nUnit, CHostDrv* pDrv) { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit] == nullptr); @@ -1842,7 +1842,7 @@ void CHostEntry::SetDrv(DWORD nUnit, CHostDrv* pDrv) /// Is it write-protected? // //--------------------------------------------------------------------------- -bool CHostEntry::isWriteProtect(DWORD nUnit) const +bool CHostEntry::isWriteProtect(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1855,7 +1855,7 @@ bool CHostEntry::isWriteProtect(DWORD nUnit) const /// Is it accessible? // //--------------------------------------------------------------------------- -bool CHostEntry::isEnable(DWORD nUnit) const +bool CHostEntry::isEnable(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1868,7 +1868,7 @@ bool CHostEntry::isEnable(DWORD nUnit) const /// Media check // //--------------------------------------------------------------------------- -bool CHostEntry::isMediaOffline(DWORD nUnit) const +bool CHostEntry::isMediaOffline(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1881,7 +1881,7 @@ bool CHostEntry::isMediaOffline(DWORD nUnit) const /// Get media byte // //--------------------------------------------------------------------------- -BYTE CHostEntry::GetMediaByte(DWORD nUnit) const +BYTE CHostEntry::GetMediaByte(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1894,7 +1894,7 @@ BYTE CHostEntry::GetMediaByte(DWORD nUnit) const /// Get drive status // //--------------------------------------------------------------------------- -DWORD CHostEntry::GetStatus(DWORD nUnit) const +uint32_t CHostEntry::GetStatus(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1907,7 +1907,7 @@ DWORD CHostEntry::GetStatus(DWORD nUnit) const /// Media change check // //--------------------------------------------------------------------------- -bool CHostEntry::CheckMedia(DWORD nUnit) const +bool CHostEntry::CheckMedia(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1920,7 +1920,7 @@ bool CHostEntry::CheckMedia(DWORD nUnit) const /// Eject // //--------------------------------------------------------------------------- -void CHostEntry::Eject(DWORD nUnit) const +void CHostEntry::Eject(uint32_t nUnit) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1933,7 +1933,7 @@ void CHostEntry::Eject(DWORD nUnit) const /// Get volume label // //--------------------------------------------------------------------------- -void CHostEntry::GetVolume(DWORD nUnit, TCHAR* szLabel) const +void CHostEntry::GetVolume(uint32_t nUnit, TCHAR* szLabel) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1946,7 +1946,7 @@ void CHostEntry::GetVolume(DWORD nUnit, TCHAR* szLabel) const /// Get volume label from cache // //--------------------------------------------------------------------------- -bool CHostEntry::GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const +bool CHostEntry::GetVolumeCache(uint32_t nUnit, TCHAR* szLabel) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1959,7 +1959,7 @@ bool CHostEntry::GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const /// Get capacity // //--------------------------------------------------------------------------- -DWORD CHostEntry::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) const +uint32_t CHostEntry::GetCapacity(uint32_t nUnit, Human68k::capacity_t* pCapacity) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -1972,7 +1972,7 @@ DWORD CHostEntry::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) cons /// Get cluster size from cache // //--------------------------------------------------------------------------- -bool CHostEntry::GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const +bool CHostEntry::GetCapacityCache(uint32_t nUnit, Human68k::capacity_t* pCapacity) const { assert(nUnit < DRIVE_MAX); assert(m_pDrv[nUnit]); @@ -2056,7 +2056,7 @@ void CHostFiles::SetPath(const Human68k::namests_t* pNamests) /// Find file on the Human68k side and create data on the host side // //--------------------------------------------------------------------------- -bool CHostFiles::Find(DWORD nUnit, const CHostEntry* pEntry) +bool CHostFiles::Find(uint32_t nUnit, const CHostEntry* pEntry) { assert(pEntry); @@ -2159,7 +2159,7 @@ void CHostFilesManager::Init() assert(m_cRing.Prev() == &m_cRing); // Allocate memory - for (DWORD i = 0; i < XM6_HOST_FILES_MAX; i++) { + for (uint32_t i = 0; i < XM6_HOST_FILES_MAX; i++) { auto p = new ring_t(); p->r.Insert(&m_cRing); } @@ -2180,7 +2180,7 @@ void CHostFilesManager::Clean() } } -CHostFiles* CHostFilesManager::Alloc(DWORD nKey) +CHostFiles* CHostFilesManager::Alloc(uint32_t nKey) { assert(nKey); @@ -2195,7 +2195,7 @@ CHostFiles* CHostFilesManager::Alloc(DWORD nKey) return &p->f; } -CHostFiles* CHostFilesManager::Search(DWORD nKey) +CHostFiles* CHostFilesManager::Search(uint32_t nKey) { // assert(nKey); // The search key may become 0 due to DPB damage @@ -2235,7 +2235,7 @@ void CHostFilesManager::Free(CHostFiles* pFiles) /// Set file open mode // //--------------------------------------------------------------------------- -bool CHostFcb::SetMode(DWORD nHumanMode) +bool CHostFcb::SetMode(uint32_t nHumanMode) { switch (nHumanMode & Human68k::OP_MASK) { case Human68k::OP_READ: @@ -2279,7 +2279,7 @@ void CHostFcb::SetHumanPath(const BYTE* szHumanPath) /// Return false if error is thrown. // //--------------------------------------------------------------------------- -bool CHostFcb::Create(DWORD, bool bForce) +bool CHostFcb::Create(uint32_t, bool bForce) { assert((Human68k::AT_DIRECTORY | Human68k::AT_VOLUME) == 0); assert(strlen(m_szFilename) > 0); @@ -2328,7 +2328,7 @@ bool CHostFcb::Open() /// Return -1 if error is thrown. // //--------------------------------------------------------------------------- -DWORD CHostFcb::Read(BYTE* pBuffer, DWORD nSize) +uint32_t CHostFcb::Read(BYTE* pBuffer, uint32_t nSize) { assert(pBuffer); assert(m_pFile); @@ -2337,7 +2337,7 @@ DWORD CHostFcb::Read(BYTE* pBuffer, DWORD nSize) if (ferror(m_pFile)) nResult = (size_t)-1; - return (DWORD)nResult; + return (uint32_t)nResult; } //--------------------------------------------------------------------------- @@ -2348,7 +2348,7 @@ DWORD CHostFcb::Read(BYTE* pBuffer, DWORD nSize) /// Return -1 if error is thrown. // //--------------------------------------------------------------------------- -DWORD CHostFcb::Write(const BYTE* pBuffer, DWORD nSize) +uint32_t CHostFcb::Write(const BYTE* pBuffer, uint32_t nSize) { assert(pBuffer); assert(m_pFile); @@ -2357,7 +2357,7 @@ DWORD CHostFcb::Write(const BYTE* pBuffer, DWORD nSize) if (ferror(m_pFile)) nResult = (size_t)-1; - return (DWORD)nResult; + return (uint32_t)nResult; } //--------------------------------------------------------------------------- @@ -2381,7 +2381,7 @@ bool CHostFcb::Truncate() const /// Return -1 if error is thrown. // //--------------------------------------------------------------------------- -DWORD CHostFcb::Seek(DWORD nOffset, Human68k::seek_t nHumanSeek) +uint32_t CHostFcb::Seek(uint32_t nOffset, Human68k::seek_t nHumanSeek) { assert(m_pFile); @@ -2399,9 +2399,9 @@ DWORD CHostFcb::Seek(DWORD nOffset, Human68k::seek_t nHumanSeek) break; } if (fseek(m_pFile, nOffset, nSeek)) - return (DWORD)-1; + return (uint32_t)-1; - return (DWORD)ftell(m_pFile); + return (uint32_t)ftell(m_pFile); } //--------------------------------------------------------------------------- @@ -2411,7 +2411,7 @@ DWORD CHostFcb::Seek(DWORD nOffset, Human68k::seek_t nHumanSeek) /// Return false if error is thrown. // //--------------------------------------------------------------------------- -bool CHostFcb::TimeStamp(DWORD nHumanTime) const +bool CHostFcb::TimeStamp(uint32_t nHumanTime) const { assert(m_pFile || m_bFlag); @@ -2480,7 +2480,7 @@ void CHostFcbManager::Init() assert(m_cRing.Prev() == &m_cRing); // Memory allocation - for (DWORD i = 0; i < XM6_HOST_FCB_MAX; i++) { + for (uint32_t i = 0; i < XM6_HOST_FCB_MAX; i++) { auto p = new ring_t; assert(p); p->r.Insert(&m_cRing); @@ -2501,7 +2501,7 @@ void CHostFcbManager::Clean() const } } -CHostFcb* CHostFcbManager::Alloc(DWORD nKey) +CHostFcb* CHostFcbManager::Alloc(uint32_t nKey) { assert(nKey); @@ -2523,7 +2523,7 @@ CHostFcb* CHostFcbManager::Alloc(DWORD nKey) return &p->f; } -CHostFcb* CHostFcbManager::Search(DWORD nKey) +CHostFcb* CHostFcbManager::Search(uint32_t nKey) { assert(nKey); @@ -2560,7 +2560,7 @@ void CHostFcbManager::Free(CHostFcb* pFcb) // //=========================================================================== -DWORD CFileSys::g_nOption; // File name conversion flag +uint32_t CFileSys::g_nOption; // File name conversion flag //--------------------------------------------------------------------------- // @@ -2607,7 +2607,7 @@ void CFileSys::Init() m_cEntry.Init(); // Evaluate per-path setting validity - DWORD nDrives = m_nDrives; + uint32_t nDrives = m_nDrives; if (nDrives == 0) { // Use root directory instead of per-path settings strcpy(m_szBase[0], "/"); @@ -2616,8 +2616,8 @@ void CFileSys::Init() } // Register file system - DWORD nUnit = 0; - for (DWORD n = 0; n < nDrives; n++) { + uint32_t nUnit = 0; + for (uint32_t n = 0; n < nDrives; n++) { // Don't register is base path do not exist if (m_szBase[n][0] == '\0') continue; @@ -2642,7 +2642,7 @@ void CFileSys::Init() /// $40 - Device startup // //--------------------------------------------------------------------------- -DWORD CFileSys::InitDevice(const Human68k::argument_t* pArgument) +uint32_t CFileSys::InitDevice(const Human68k::argument_t* pArgument) { InitOption(pArgument); @@ -2657,7 +2657,7 @@ DWORD CFileSys::InitDevice(const Human68k::argument_t* pArgument) /// $41 - Directory check // //--------------------------------------------------------------------------- -int CFileSys::CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests) const +int CFileSys::CheckDir(uint32_t nUnit, const Human68k::namests_t* pNamests) const { assert(pNamests); @@ -2684,7 +2684,7 @@ int CFileSys::CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests) const /// $42 - Create directory // //--------------------------------------------------------------------------- -int CFileSys::MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests) const +int CFileSys::MakeDir(uint32_t nUnit, const Human68k::namests_t* pNamests) const { assert(pNamests); @@ -2726,7 +2726,7 @@ int CFileSys::MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests) const /// $43 - Delete directory // //--------------------------------------------------------------------------- -int CFileSys::RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests) const +int CFileSys::RemoveDir(uint32_t nUnit, const Human68k::namests_t* pNamests) const { assert(pNamests); @@ -2776,7 +2776,7 @@ int CFileSys::RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests) const /// $44 - Change file name // //--------------------------------------------------------------------------- -int CFileSys::Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew) const +int CFileSys::Rename(uint32_t nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew) const { assert(pNamests); @@ -2834,7 +2834,7 @@ int CFileSys::Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Hum /// $45 - Delete file // //--------------------------------------------------------------------------- -int CFileSys::Delete(DWORD nUnit, const Human68k::namests_t* pNamests) const +int CFileSys::Delete(uint32_t nUnit, const Human68k::namests_t* pNamests) const { assert(pNamests); @@ -2874,7 +2874,7 @@ int CFileSys::Delete(DWORD nUnit, const Human68k::namests_t* pNamests) const /// $46 - Get/set file attribute // //--------------------------------------------------------------------------- -int CFileSys::Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute) const +int CFileSys::Attribute(uint32_t nUnit, const Human68k::namests_t* pNamests, uint32_t nHumanAttribute) const { assert(pNamests); @@ -2908,7 +2908,7 @@ int CFileSys::Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD return FS_FATAL_WRITEPROTECT; // Generate attribute - if (DWORD nAttribute = (nHumanAttribute & Human68k::AT_READONLY) | (f.GetAttribute() & ~Human68k::AT_READONLY); + if (uint32_t nAttribute = (nHumanAttribute & Human68k::AT_READONLY) | (f.GetAttribute() & ~Human68k::AT_READONLY); f.GetAttribute() != nAttribute) { struct stat sb; if (stat(S2U(f.GetPath()), &sb)) @@ -2939,7 +2939,7 @@ int CFileSys::Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD /// $47 - File search // //--------------------------------------------------------------------------- -int CFileSys::Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles) +int CFileSys::Files(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles) { assert(pNamests); assert(nKey); @@ -3025,7 +3025,7 @@ int CFileSys::Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests /// $48 - Search next file // //--------------------------------------------------------------------------- -int CFileSys::NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles) +int CFileSys::NFiles(uint32_t nUnit, uint32_t nKey, Human68k::files_t* pFiles) { assert(nKey); assert(pFiles); @@ -3069,7 +3069,7 @@ int CFileSys::NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles) /// $49 - Create new file // //--------------------------------------------------------------------------- -int CFileSys::Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, bool bForce) +int CFileSys::Create(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, uint32_t nHumanAttribute, bool bForce) { assert(pNamests); assert(nKey); @@ -3114,7 +3114,7 @@ int CFileSys::Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamest pHostFcb->SetHumanPath(f.GetHumanPath()); // Set open mode - pFcb->mode = (WORD)((pFcb->mode & ~Human68k::OP_MASK) | Human68k::OP_FULL); + pFcb->mode = (uint16_t)((pFcb->mode & ~Human68k::OP_MASK) | Human68k::OP_FULL); if (!pHostFcb->SetMode(pFcb->mode)) { m_cFcb.Free(pHostFcb); return FS_ILLEGALMOD; @@ -3137,7 +3137,7 @@ int CFileSys::Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamest /// $4A - File open // //--------------------------------------------------------------------------- -int CFileSys::Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb) +int CFileSys::Open(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb) { assert(pNamests); assert(nKey); @@ -3208,7 +3208,7 @@ int CFileSys::Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, /// $4B - File close // //--------------------------------------------------------------------------- -int CFileSys::Close(DWORD nUnit, DWORD nKey, const Human68k::fcb_t* /* pFcb */) +int CFileSys::Close(uint32_t nUnit, uint32_t nKey, const Human68k::fcb_t* /* pFcb */) { assert(nKey); @@ -3246,7 +3246,7 @@ int CFileSys::Close(DWORD nUnit, DWORD nKey, const Human68k::fcb_t* /* pFcb */) /// Clean exit when 0 bytes are read. // //--------------------------------------------------------------------------- -int CFileSys::Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, DWORD nSize) +int CFileSys::Read(uint32_t nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, uint32_t nSize) { assert(nKey); assert(pFcb); @@ -3265,9 +3265,8 @@ int CFileSys::Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, DWORD nSize } // Read - DWORD nResult; - nResult = pHostFcb->Read(pBuffer, nSize); - if (nResult == (DWORD)-1) { + const uint32_t nResult = pHostFcb->Read(pBuffer, nSize); + if (nResult == (uint32_t)-1) { m_cFcb.Free(pHostFcb); return FS_INVALIDFUNC; // TODO: Should return error code 10 (read error) as well here } @@ -3286,7 +3285,7 @@ int CFileSys::Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, DWORD nSize /// Truncate file if 0 bytes are written. // //--------------------------------------------------------------------------- -int CFileSys::Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, DWORD nSize) +int CFileSys::Write(uint32_t nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, uint32_t nSize) { assert(nKey); assert(pFcb); @@ -3298,7 +3297,7 @@ int CFileSys::Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, DWOR if (pHostFcb == nullptr) return FS_NOTOPENED; - DWORD nResult; + uint32_t nResult; if (nSize == 0) { // Truncate if (!pHostFcb->Truncate()) { @@ -3319,7 +3318,7 @@ int CFileSys::Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, DWOR // Write nResult = pHostFcb->Write(pBuffer, nSize); - if (nResult == (DWORD)-1) { + if (nResult == (uint32_t)-1) { m_cFcb.Free(pHostFcb); return FS_CANTWRITE; /// TODO: Should return error code 11 (write error) as well here } @@ -3344,7 +3343,7 @@ int CFileSys::Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, DWOR /// $4E - File seek // //--------------------------------------------------------------------------- -int CFileSys::Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset) +int CFileSys::Seek(uint32_t nKey, Human68k::fcb_t* pFcb, uint32_t nSeek, int nOffset) { assert(pFcb); @@ -3354,14 +3353,14 @@ int CFileSys::Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset) return FS_NOTOPENED; // Parameter check - if (nSeek > (DWORD)Human68k::seek_t::SK_END) { + if (nSeek > (uint32_t)Human68k::seek_t::SK_END) { m_cFcb.Free(pHostFcb); return FS_INVALIDPRM; } // File seek - DWORD nResult = pHostFcb->Seek(nOffset, (Human68k::seek_t)nSeek); - if (nResult == (DWORD)-1) { + uint32_t nResult = pHostFcb->Seek(nOffset, (Human68k::seek_t)nSeek); + if (nResult == (uint32_t)-1) { m_cFcb.Free(pHostFcb); return FS_CANTSEEK; } @@ -3379,14 +3378,14 @@ int CFileSys::Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset) /// Throw error when the top 16 bits are $FFFF. // //--------------------------------------------------------------------------- -DWORD CFileSys::TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime) +uint32_t CFileSys::TimeStamp(uint32_t nUnit, uint32_t nKey, Human68k::fcb_t* pFcb, uint32_t nHumanTime) { assert(nKey); assert(pFcb); // Get only if (nHumanTime == 0) - return ((DWORD)pFcb->date << 16) | pFcb->time; + return ((uint32_t)pFcb->date << 16) | pFcb->time; // Unit check if (nUnit >= CHostEntry::DRIVE_MAX) @@ -3413,8 +3412,8 @@ DWORD CFileSys::TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD m_cFcb.Free(pHostFcb); return FS_INVALIDPRM; } - pFcb->date = (WORD)(nHumanTime >> 16); - pFcb->time = (WORD)nHumanTime; + pFcb->date = (uint16_t)(nHumanTime >> 16); + pFcb->time = (uint16_t)nHumanTime; // Update cache m_cEntry.CleanCache(nUnit, pHostFcb->GetHumanPath()); @@ -3427,7 +3426,7 @@ DWORD CFileSys::TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD /// $50 - Get capacity // //--------------------------------------------------------------------------- -int CFileSys::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) const +int CFileSys::GetCapacity(uint32_t nUnit, Human68k::capacity_t* pCapacity) const { assert(pCapacity); @@ -3451,7 +3450,7 @@ int CFileSys::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) const /// $51 - Inspect/control drive status // //--------------------------------------------------------------------------- -int CFileSys::CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive) const +int CFileSys::CtrlDrive(uint32_t nUnit, Human68k::ctrldrive_t* pCtrlDrive) const { assert(pCtrlDrive); @@ -3494,7 +3493,7 @@ int CFileSys::CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive) const /// Therefore, treat even a unit out of bounds as normal operation. // //--------------------------------------------------------------------------- -int CFileSys::GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb) const +int CFileSys::GetDPB(uint32_t nUnit, Human68k::dpb_t* pDpb) const { assert(pDpb); @@ -3528,8 +3527,8 @@ int CFileSys::GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb) const } // Calculate number of shifts - DWORD nSize = 1; - DWORD nShift = 0; + uint32_t nSize = 1; + uint32_t nShift = 0; for (;;) { if (nSize >= cap.sectors) break; @@ -3544,23 +3543,23 @@ int CFileSys::GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb) const // Cluster 1: FAT // Cluster 2: Root directory // Cluster 3: Data memory (pseudo-sector) - DWORD nFat = cap.sectors; - DWORD nRoot = cap.sectors * 2; - DWORD nData = cap.sectors * 3; + const uint32_t nFat = cap.sectors; + const uint32_t nRoot = cap.sectors * 2; + const uint32_t nData = cap.sectors * 3; // Set DPB pDpb->sector_size = cap.bytes; // Bytes per sector pDpb->cluster_size = (BYTE)(cap.sectors - 1); // Sectors per cluster - 1 pDpb->shift = (BYTE)nShift; // Number of cluster → sector shifts - pDpb->fat_sector = (WORD)nFat; // First FAT sector number + pDpb->fat_sector = (uint16_t)nFat; // First FAT sector number pDpb->fat_max = 1; // Number of FAT memory spaces pDpb->fat_size = (BYTE)cap.sectors; // Number of sectors controlled by FAT (excluding copies) pDpb->file_max = - (WORD)(cap.sectors * cap.bytes / 0x20); // Number of files in the root directory - pDpb->data_sector = (WORD)nData; // First sector number of data memory + (uint16_t)(cap.sectors * cap.bytes / 0x20); // Number of files in the root directory + pDpb->data_sector = (uint16_t)nData; // First sector number of data memory pDpb->cluster_max = cap.clusters; // Total number of clusters + 1 - pDpb->root_sector = (WORD)nRoot; // First sector number of the root directory + pDpb->root_sector = (uint16_t)nRoot; // First sector number of the root directory pDpb->media = media; // Media byte return 0; @@ -3574,7 +3573,7 @@ int CFileSys::GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb) const /// Buffer size is hard coded to $200 byte. // //--------------------------------------------------------------------------- -int CFileSys::DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize) +int CFileSys::DiskRead(uint32_t nUnit, BYTE* pBuffer, uint32_t nSector, uint32_t nSize) { assert(pBuffer); @@ -3611,7 +3610,7 @@ int CFileSys::DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize) // Note that in lzdsys the sector number to read is calculated by the following formula: // (dirent.cluster - 2) * (dpb.cluster_size + 1) + dpb.data_sector /// @warning little endian only - dir->cluster = (WORD)(m_nHostSectorCount + 2); // Pseudo-sector number + dir->cluster = (uint16_t)(m_nHostSectorCount + 2); // Pseudo-sector number m_nHostSectorBuffer[m_nHostSectorCount] = nSector; // Entity that points to the pseudo-sector m_nHostSectorCount++; m_nHostSectorCount %= XM6_HOST_PSEUDO_CLUSTER_MAX; @@ -3620,8 +3619,8 @@ int CFileSys::DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize) } // Calculate the sector number from the cluster number - DWORD n = nSector - (3 * cap.sectors); - DWORD nMod = 1; + uint32_t n = nSector - (3 * cap.sectors); + uint32_t nMod = 1; if (cap.sectors) { // Beware that cap.sectors becomes 0 when media does not exist nMod = n % cap.sectors; @@ -3639,9 +3638,9 @@ int CFileSys::DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize) if (!f.Open()) return FS_INVALIDPRM; memset(pBuffer, 0, 0x200); - DWORD nResult = f.Read(pBuffer, 0x200); + uint32_t nResult = f.Read(pBuffer, 0x200); f.Close(); - if (nResult == (DWORD)-1) + if (nResult == (uint32_t)-1) return FS_INVALIDPRM; return 0; @@ -3656,7 +3655,7 @@ int CFileSys::DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize) /// $54 - Write sector // //--------------------------------------------------------------------------- -int CFileSys::DiskWrite(DWORD nUnit) const +int CFileSys::DiskWrite(uint32_t nUnit) const { // Unit check if (nUnit >= CHostEntry::DRIVE_MAX) @@ -3682,7 +3681,7 @@ int CFileSys::DiskWrite(DWORD nUnit) const /// $55 - IOCTRL // //--------------------------------------------------------------------------- -int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl) +int CFileSys::Ioctrl(uint32_t nUnit, uint32_t nFunction, Human68k::ioctrl_t* pIoctrl) { assert(pIoctrl); @@ -3705,7 +3704,7 @@ int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl) case 2: switch (pIoctrl->param) { - case (DWORD)-1: + case (uint32_t)-1: // Re-identify media m_cEntry.isMediaOffline(nUnit); return 0; @@ -3720,17 +3719,17 @@ int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl) } break; - case (DWORD)-1: + case (uint32_t)-1: // Resident evaluation memcpy(pIoctrl->buffer, "WindrvXM", 8); return 0; - case (DWORD)-2: + case (uint32_t)-2: // Set options SetOption(pIoctrl->param); return 0; - case (DWORD)-3: + case (uint32_t)-3: // Get options pIoctrl->param = GetOption(); return 0; @@ -3747,7 +3746,7 @@ int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl) /// $56 - Flush // //--------------------------------------------------------------------------- -int CFileSys::Flush(DWORD nUnit) const +int CFileSys::Flush(uint32_t nUnit) const { // Unit check if (nUnit >= CHostEntry::DRIVE_MAX) @@ -3764,7 +3763,7 @@ int CFileSys::Flush(DWORD nUnit) const /// $57 - Media change check // //--------------------------------------------------------------------------- -int CFileSys::CheckMedia(DWORD nUnit) const +int CFileSys::CheckMedia(uint32_t nUnit) const { // Unit check if (nUnit >= CHostEntry::DRIVE_MAX) @@ -3786,7 +3785,7 @@ int CFileSys::CheckMedia(DWORD nUnit) const /// $58 - Lock // //--------------------------------------------------------------------------- -int CFileSys::Lock(DWORD nUnit) const +int CFileSys::Lock(uint32_t nUnit) const { // Unit check if (nUnit >= CHostEntry::DRIVE_MAX) @@ -3808,7 +3807,7 @@ int CFileSys::Lock(DWORD nUnit) const /// Set options // //--------------------------------------------------------------------------- -void CFileSys::SetOption(DWORD nOption) +void CFileSys::SetOption(uint32_t nOption) { // Clear cache when option settings change if (m_nOption ^ nOption) @@ -3833,7 +3832,7 @@ void CFileSys::InitOption(const Human68k::argument_t* pArgument) const BYTE* pp = pArgument->buf; pp += strlen((const char*)pp) + 1; - DWORD nOption = m_nOptionDefault; + uint32_t nOption = m_nOptionDefault; for (;;) { assert(pp < pArgument->buf + sizeof(*pArgument)); const BYTE* p = pp; @@ -3841,7 +3840,7 @@ void CFileSys::InitOption(const Human68k::argument_t* pArgument) if (c == '\0') break; - DWORD nMode; + uint32_t nMode; if (c == '+') { nMode = 1; } else if (c == '-') { @@ -3866,7 +3865,7 @@ void CFileSys::InitOption(const Human68k::argument_t* pArgument) if (c == '\0') break; - DWORD nBit = 0; + uint32_t nBit = 0; switch (c) { case 'A': case 'a': nBit = WINDRV_OPT_CONVERT_LENGTH; break; case 'T': case 't': nBit = WINDRV_OPT_COMPARE_LENGTH; nMode ^= 1; break; @@ -3909,7 +3908,7 @@ void CFileSys::InitOption(const Human68k::argument_t* pArgument) /// Get volume label // //--------------------------------------------------------------------------- -bool CFileSys::FilesVolume(DWORD nUnit, Human68k::files_t* pFiles) const +bool CFileSys::FilesVolume(uint32_t nUnit, Human68k::files_t* pFiles) const { assert(pFiles); diff --git a/src/raspberrypi/devices/cfilesystem.h b/src/raspberrypi/devices/cfilesystem.h index d60353be..47bce73f 100644 --- a/src/raspberrypi/devices/cfilesystem.h +++ b/src/raspberrypi/devices/cfilesystem.h @@ -116,41 +116,41 @@ namespace Human68k { struct files_t { BYTE fatr; ///< + 0 search attribute; read-only // BYTE drive; ///< + 1 drive number; read-only - DWORD sector; ///< + 2 directory sector; DOS _FILES first address substitute - // WORD cluster; ///< + 6 directory cluster; details unknown (unused) - WORD offset; ///< + 8 directory entry; write-only + uint32_t sector; ///< + 2 directory sector; DOS _FILES first address substitute + // uint16_t cluster; ///< + 6 directory cluster; details unknown (unused) + uint16_t offset; ///< + 8 directory entry; write-only // BYTE name[8]; ///< +10 working file name; write-only (unused) // BYTE ext[3]; ///< +18 working extension; write-only (unused) BYTE attr; ///< +21 file attribute; write-only - WORD time; ///< +22 last change time of day; write-only - WORD date; ///< +24 last change date; write-only - DWORD size; ///< +26 file size; write-only + uint16_t time; ///< +22 last change time of day; write-only + uint16_t date; ///< +24 last change date; write-only + uint32_t size; ///< +26 file size; write-only BYTE full[23]; ///< +30 full name; write-only }; struct fcb_t { // BYTE pad00[6]; ///< + 0~+ 5 (unused) - DWORD fileptr; ///< + 6~+ 9 file pointer + uint32_t fileptr; ///< + 6~+ 9 file pointer // BYTE pad01[4]; ///< +10~+13 (unused) - WORD mode; ///< +14~+15 open mode + uint16_t mode; ///< +14~+15 open mode // BYTE pad02[16]; ///< +16~+31 (unused) - // DWORD zero; ///< +32~+35 zeros are written when opened (unused) + // uint32_t zero; ///< +32~+35 zeros are written when opened (unused) // BYTE name[8]; ///< +36~+43 file name (PADDING 0x20) (unused) // BYTE ext[3]; ///< +44~+46 extension (PADDING 0x20) (unused) BYTE attr; ///< +47 file attribute // BYTE add[10]; ///< +48~+57 file name addition (PADDING 0x00) (unused) - WORD time; ///< +58~+59 last change time of day - WORD date; ///< +60~+61 last change date - // WORD cluster; ///< +62~+63 cluster number (unused) - DWORD size; ///< +64~+67 file size + uint16_t time; ///< +58~+59 last change time of day + uint16_t date; ///< +60~+61 last change date + // uint16_t cluster; ///< +62~+63 cluster number (unused) + uint32_t size; ///< +64~+67 file size // BYTE pad03[28]; ///< +68~+95 FAT cache (unused) }; struct capacity_t { - WORD freearea; ///< + 0 Number of available clusters - WORD clusters; ///< + 2 Total number of clusters - WORD sectors; ///< + 4 Number of sectors per cluster - WORD bytes; ///< + 6 Number of bytes per sector + uint16_t freearea; ///< + 0 Number of available clusters + uint16_t clusters; ///< + 2 Total number of clusters + uint16_t sectors; ///< + 4 Number of sectors per cluster + uint16_t bytes; ///< + 6 Number of bytes per sector }; struct ctrldrive_t { @@ -159,17 +159,17 @@ namespace Human68k { }; struct dpb_t { - WORD sector_size; ///< + 0 Number of bytes in one sector + uint16_t sector_size; ///< + 0 Number of bytes in one sector BYTE cluster_size; ///< + 2 Number sectors in one cluster -1 BYTE shift; ///< + 3 Number of cluster→sector shifts - WORD fat_sector; ///< + 4 FAT first sector number + uint16_t fat_sector; ///< + 4 FAT first sector number BYTE fat_max; ///< + 6 FAT storage quantity BYTE fat_size; ///< + 7 FAT controlled sector number (excluding duplicates) - WORD file_max; ///< + 8 Number of files in the root directory - WORD data_sector; ///< +10 First sector number of data storage - WORD cluster_max; ///< +12 Total number of clusters +1 - WORD root_sector; ///< +14 First sector number of root directory - // DWORD driverentry; ///< +16 Device driver pointer (unused) + uint16_t file_max; ///< + 8 Number of files in the root directory + uint16_t data_sector; ///< +10 First sector number of data storage + uint16_t cluster_max; ///< +12 Total number of clusters +1 + uint16_t root_sector; ///< +14 First sector number of root directory + // uint32_t driverentry; ///< +16 Device driver pointer (unused) BYTE media; ///< +20 Media identifier // BYTE flag; ///< +21 Flag used by DPB (unused) }; @@ -180,17 +180,17 @@ namespace Human68k { BYTE ext[3]; ///< + 8 Extension (PADDING 0x20) BYTE attr; ///< +11 File attribute BYTE add[10]; ///< +12 File name addition (PADDING 0x00) - WORD time; ///< +22 Last change time of day - WORD date; ///< +24 Last change date - WORD cluster; ///< +26 Cluster number - DWORD size; ///< +28 File size + uint16_t time; ///< +22 Last change time of day + uint16_t date; ///< +24 Last change date + uint16_t cluster; ///< +26 Cluster number + uint32_t size; ///< +28 File size }; /// IOCTRL parameter union union ioctrl_t { BYTE buffer[8]; ///< Access in byte units - DWORD param; ///< Parameter (First 4 bytes) - WORD media; ///< Media byte (First 2 bytes) + uint32_t param; ///< Parameter (First 4 bytes) + uint16_t media; ///< Media byte (First 2 bytes) }; /// Command line parameter struct @@ -313,7 +313,7 @@ Normal is 0. Becomes 1 if attempting to mount in read-only mode. Reserving the other values for future use. Insurance against hard-to-detect devices such as homemade USB storage. */ -static const DWORD FSFLAG_WRITE_PROTECT = 0x00000001; ///< Bit0: Force write protect +static const uint32_t FSFLAG_WRITE_PROTECT = 0x00000001; ///< Bit0: Force write protect //=========================================================================== // @@ -429,17 +429,17 @@ public: void SetEntryName(); ///< Set Human68k directory entry void SetEntryAttribute(BYTE nHumanAttribute) { m_dirHuman.attr = nHumanAttribute; } ///< Set Human68k directory entry - void SetEntrySize(DWORD nHumanSize) + void SetEntrySize(uint32_t nHumanSize) { m_dirHuman.size = nHumanSize; } ///< Set Human68k directory entry - void SetEntryDate(WORD nHumanDate) + void SetEntryDate(uint16_t nHumanDate) { m_dirHuman.date = nHumanDate; } ///< Set Human68k directory entry - void SetEntryTime(WORD nHumanTime) + void SetEntryTime(uint16_t nHumanTime) { m_dirHuman.time = nHumanTime; } ///< Set Human68k directory entry - void SetEntryCluster(WORD nHumanCluster) + void SetEntryCluster(uint16_t nHumanCluster) { m_dirHuman.cluster = nHumanCluster; } ///< Set Human68k directory entry const Human68k::dirent_t* GetEntry() const { return &m_dirHuman; } ///< Get Human68k directory entry - int CheckAttribute(DWORD nHumanAttribute) const; ///< Determine Human68k directory entry attributes + int CheckAttribute(uint32_t nHumanAttribute) const; ///< Determine Human68k directory entry attributes bool isSameEntry(const Human68k::dirent_t* pdirHuman) const { assert(pdirHuman); return memcmp(&m_dirHuman, pdirHuman, sizeof(m_dirHuman)) == 0; } ///< Determine Human68k directory entry match @@ -491,8 +491,8 @@ class CHostPath: public CRing { public: /// Search buffer struct find_t { - DWORD count; ///< Search execution count + 1 (When 0 the below value is invalid) - DWORD id; ///< Entry unique ID for the path of the next search + uint32_t count; ///< Search execution count + 1 (When 0 the below value is invalid) + uint32_t id; ///< Entry unique ID for the path of the next search const ring_t* pos; ///< Position of the next search (When identical to unique ID) Human68k::dirent_t entry; ///< Contents of the next seach entry @@ -511,9 +511,9 @@ public: bool isSameHuman(const BYTE* szHuman) const; ///< Compare the name on the Human68k side bool isSameChild(const BYTE* szHuman) const; ///< Compare the name on the Human68k side const TCHAR* GetHost() const { return m_szHost; } ///< Obtain the name on the host side - const CHostFilename* FindFilename(const BYTE* szHuman, DWORD nHumanAttribute = Human68k::AT_ALL) const; + const CHostFilename* FindFilename(const BYTE* szHuman, uint32_t nHumanAttribute = Human68k::AT_ALL) const; ///< Find file name - const CHostFilename* FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const; + const CHostFilename* FindFilenameWildcard(const BYTE* szHuman, uint32_t nHumanAttribute, find_t* pFind) const; ///< Find file name (with support for wildcards) bool isRefresh() const; ///< Check that the file change has been done void Refresh(); ///< Refresh file @@ -533,11 +533,11 @@ private: CRing m_cRing; ///< For CHostFilename linking time_t m_tBackup = 0; ///< For time stamp restoration bool m_bRefresh = true; ///< Refresh flag - DWORD m_nId = 0; ///< Unique ID (When the value has changed, it means an update has been made) + uint32_t m_nId = 0; ///< Unique ID (When the value has changed, it means an update has been made) BYTE m_szHuman[HUMAN68K_PATH_MAX]; ///< The internal Human68k name for the relevant entry TCHAR m_szHost[FILEPATH_MAX]; ///< The host side name for the relevant entry - static DWORD g_nId; ///< Counter for the unique ID generation + static uint32_t g_nId; ///< Counter for the unique ID generation }; //=========================================================================== @@ -568,15 +568,15 @@ public: void Init(); - void SetKey(DWORD nKey) { m_nKey = nKey; } ///< Set search key - bool isSameKey(DWORD nKey) const { return m_nKey == nKey; } ///< Compare search key + void SetKey(uint32_t nKey) { m_nKey = nKey; } ///< Set search key + bool isSameKey(uint32_t nKey) const { return m_nKey == nKey; } ///< Compare search key void SetPath(const Human68k::namests_t* pNamests); ///< Create path and file name internally bool isRootPath() const { return m_szHumanPath[1] == '\0'; } ///< Check if root directory void SetPathWildcard() { m_nHumanWildcard = 1; } ///< Enable file search using wildcards void SetPathOnly() { m_nHumanWildcard = 0xFF; } ///< Enable only path names bool isPathOnly() const { return m_nHumanWildcard == 0xFF; } ///< Check if set to only path names - void SetAttribute(DWORD nHumanAttribute) { m_nHumanAttribute = nHumanAttribute; } ///< Set search attribute - bool Find(DWORD nUnit, const class CHostEntry* pEntry); ///< Find files on the Human68k side, generating data on the host side + void SetAttribute(uint32_t nHumanAttribute) { m_nHumanAttribute = nHumanAttribute; } ///< Set search attribute + bool Find(uint32_t nUnit, const class CHostEntry* pEntry); ///< Find files on the Human68k side, generating data on the host side const CHostFilename* Find(const CHostPath* pPath); ///< Find file name void SetEntry(const CHostFilename* pFilename); ///< Store search results on the Human68k side void SetResult(const TCHAR* szPath); ///< Set names on the host side @@ -587,18 +587,18 @@ public: const Human68k::dirent_t* GetEntry() const { return &m_dirHuman; }///< Get Human68k directory entry - DWORD GetAttribute() const { return m_dirHuman.attr; } ///< Get Human68k attribute - WORD GetDate() const { return m_dirHuman.date; } ///< Get Human68k date - WORD GetTime() const { return m_dirHuman.time; } ///< Get Human68k time - DWORD GetSize() const { return m_dirHuman.size; } ///< Get Human68k file size + uint32_t GetAttribute() const { return m_dirHuman.attr; } ///< Get Human68k attribute + uint16_t GetDate() const { return m_dirHuman.date; } ///< Get Human68k date + uint16_t GetTime() const { return m_dirHuman.time; } ///< Get Human68k time + uint32_t GetSize() const { return m_dirHuman.size; } ///< Get Human68k file size const BYTE* GetHumanFilename() const { return m_szHumanFilename; }///< Get Human68k file name const BYTE* GetHumanResult() const { return m_szHumanResult; } ///< Get Human68k file name search results const BYTE* GetHumanPath() const { return m_szHumanPath; } ///< Get Human68k path name private: - DWORD m_nKey = 0; ///< FILES buffer address for Human68k; 0 is unused - DWORD m_nHumanWildcard = 0; ///< Human68k wildcard data - DWORD m_nHumanAttribute = 0; ///< Human68k search attribute + uint32_t m_nKey = 0; ///< FILES buffer address for Human68k; 0 is unused + uint32_t m_nHumanWildcard = 0; ///< Human68k wildcard data + uint32_t m_nHumanAttribute = 0; ///< Human68k search attribute CHostPath::find_t m_findNext = {}; ///< Next search location data Human68k::dirent_t m_dirHuman = {}; ///< Search results: Human68k file data BYTE m_szHumanFilename[24] = {}; ///< Human68k file name @@ -620,8 +620,8 @@ public: void Init(); ///< Initialization (when the driver is installed) void Clean(); ///< Release (when starting up or resetting) - CHostFiles* Alloc(DWORD nKey); - CHostFiles* Search(DWORD nKey); + CHostFiles* Alloc(uint32_t nKey); + CHostFiles* Search(uint32_t nKey); void Free(CHostFiles* pFiles); private: /// For memory management @@ -647,26 +647,26 @@ public: void Init(); - void SetKey(DWORD nKey) { m_nKey = nKey; } ///< Set search key - bool isSameKey(DWORD nKey) const { return m_nKey == nKey; } ///< Compare search key + void SetKey(uint32_t nKey) { m_nKey = nKey; } ///< Set search key + bool isSameKey(uint32_t nKey) const { return m_nKey == nKey; } ///< Compare search key void SetUpdate() { m_bUpdate = true; } ///< Update bool isUpdate() const { return m_bUpdate; } ///< Get update state - bool SetMode(DWORD nHumanMode); ///< Set file open mode + bool SetMode(uint32_t nHumanMode); ///< Set file open mode void SetFilename(const TCHAR* szFilename); ///< Set file name void SetHumanPath(const BYTE* szHumanPath); ///< Set Human68k path name const BYTE* GetHumanPath() const { return m_szHumanPath; } ///< Get Human68k path name - bool Create(DWORD nHumanAttribute, bool bForce); ///< Create file + bool Create(uint32_t nHumanAttribute, bool bForce); ///< Create file bool Open(); ///< Open file - DWORD Read(BYTE* pBuffer, DWORD nSize); ///< Read file - DWORD Write(const BYTE* pBuffer, DWORD nSize); ///< Write file + uint32_t Read(BYTE* pBuffer, uint32_t nSize); ///< Read file + uint32_t Write(const BYTE* pBuffer, uint32_t nSize); ///< Write file bool Truncate() const; ///< Truncate file - DWORD Seek(DWORD nOffset, Human68k::seek_t nHumanSeek); ///< Seek file - bool TimeStamp(DWORD nHumanTime) const; ///< Set file time stamp + uint32_t Seek(uint32_t nOffset, Human68k::seek_t nHumanSeek); ///< Seek file + bool TimeStamp(uint32_t nHumanTime) const; ///< Set file time stamp void Close(); ///< Close file private: - DWORD m_nKey = 0; ///< Human68k FCB buffer address (0 if unused) + uint32_t m_nKey = 0; ///< Human68k FCB buffer address (0 if unused) bool m_bUpdate = false; ///< Update flag FILE* m_pFile = nullptr; ///< Host side file object const char* m_pszMode = nullptr; ///< Host side file open mode @@ -688,8 +688,8 @@ public: void Init(); ///< Initialization (when the driver is installed) void Clean() const; ///< Release (when starting up or resetting) - CHostFcb* Alloc(DWORD nKey); - CHostFcb* Search(DWORD nKey); + CHostFcb* Alloc(uint32_t nKey); + CHostFcb* Search(uint32_t nKey); void Free(CHostFcb* p); private: @@ -717,20 +717,20 @@ public: CHostDrv(CHostDrv&) = default; CHostDrv& operator=(const CHostDrv&) = default; - void Init(const TCHAR* szBase, DWORD nFlag); ///< Initialization (device startup and load) + void Init(const TCHAR* szBase, uint32_t nFlag); ///< Initialization (device startup and load) bool isWriteProtect() const { return m_bWriteProtect; } bool isEnable() const { return m_bEnable; } ///< Is it accessible? bool isMediaOffline() const; BYTE GetMediaByte() const; - DWORD GetStatus() const; + uint32_t GetStatus() const; void SetEnable(bool); ///< Set media status bool CheckMedia(); ///< Check if media was changed void Update(); ///< Update media status void Eject(); void GetVolume(TCHAR* szLabel); ///< Get volume label bool GetVolumeCache(TCHAR* szLabel) const; ///< Get volume label from cache - DWORD GetCapacity(Human68k::capacity_t* pCapacity); + uint32_t GetCapacity(Human68k::capacity_t* pCapacity); bool GetCapacityCache(Human68k::capacity_t* pCapacity) const; ///< Get capacity from cache // Cache operations @@ -756,7 +756,7 @@ private: bool m_bWriteProtect = false; ///< TRUE if write-protected bool m_bEnable = false; ///< TRUE if media is usable - DWORD m_nRing = 0; ///< Number of stored path names + uint32_t m_nRing = 0; ///< Number of stored path names CRing m_cRing; ///< For attaching to CHostPath Human68k::capacity_t m_capCache; ///< Sector data cache: if "sectors == 0" then not cached bool m_bVolumeCache = false; ///< TRUE if the volume label has been read @@ -786,31 +786,31 @@ public: // Cache operations void CleanCache() const; ///< Update all cache - void CleanCache(DWORD nUnit) const; ///< Update cache for the specified unit - void CleanCache(DWORD nUnit, const BYTE* szHumanPath) const; ///< Update cache for the specified path - void CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath) const; ///< Update cache below the specified path - void DeleteCache(DWORD nUnit, const BYTE* szHumanPath) const; ///< Delete cache for the specified path - bool Find(DWORD nUnit, CHostFiles* pFiles) const; ///< Find host side name (path + file name (can be abbreviated) + attribute) - void ShellNotify(DWORD nEvent, const TCHAR* szPath); ///< Notify status change in the host side file system + void CleanCache(uint32_t nUnit) const; ///< Update cache for the specified unit + void CleanCache(uint32_t nUnit, const BYTE* szHumanPath) const; ///< Update cache for the specified path + void CleanCacheChild(uint32_t nUnit, const BYTE* szHumanPath) const; ///< Update cache below the specified path + void DeleteCache(uint32_t nUnit, const BYTE* szHumanPath) const; ///< Delete cache for the specified path + bool Find(uint32_t nUnit, CHostFiles* pFiles) const; ///< Find host side name (path + file name (can be abbreviated) + attribute) + void ShellNotify(uint32_t nEvent, const TCHAR* szPath); ///< Notify status change in the host side file system // Drive object operations - void SetDrv(DWORD nUnit, CHostDrv* pDrv); - bool isWriteProtect(DWORD nUnit) const; - bool isEnable(DWORD nUnit) const; ///< Is it accessible? - bool isMediaOffline(DWORD nUnit) const; - BYTE GetMediaByte(DWORD nUnit) const; - DWORD GetStatus(DWORD nUnit) const; ///< Get drive status - bool CheckMedia(DWORD nUnit) const; ///< Media change check - void Eject(DWORD nUnit) const; - void GetVolume(DWORD nUnit, TCHAR* szLabel) const; ///< Get volume label - bool GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const; ///< Get volume label from cache - DWORD GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) const; - bool GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const; ///< Get cluster size from cache + void SetDrv(uint32_t nUnit, CHostDrv* pDrv); + bool isWriteProtect(uint32_t nUnit) const; + bool isEnable(uint32_t nUnit) const; ///< Is it accessible? + bool isMediaOffline(uint32_t nUnit) const; + BYTE GetMediaByte(uint32_t nUnit) const; + uint32_t GetStatus(uint32_t nUnit) const; ///< Get drive status + bool CheckMedia(uint32_t nUnit) const; ///< Media change check + void Eject(uint32_t nUnit) const; + void GetVolume(uint32_t nUnit, TCHAR* szLabel) const; ///< Get volume label + bool GetVolumeCache(uint32_t nUnit, TCHAR* szLabel) const; ///< Get volume label from cache + uint32_t GetCapacity(uint32_t nUnit, Human68k::capacity_t* pCapacity) const; + bool GetCapacityCache(uint32_t nUnit, Human68k::capacity_t* pCapacity) const; ///< Get cluster size from cache private: CHostDrv* m_pDrv[DRIVE_MAX] = {}; ///< Host side drive object - DWORD m_nTimeout = 0; ///< Last time a timeout check was carried out + uint32_t m_nTimeout = 0; ///< Last time a timeout check was carried out }; //=========================================================================== @@ -854,71 +854,71 @@ public: void Init(); ///< Initialization (device startup and load) // Command handlers - DWORD InitDevice(const Human68k::argument_t* pArgument); ///< $40 - Device startup - int CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests) const; ///< $41 - Directory check - int MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests) const; ///< $42 - Create directory - int RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests) const; ///< $43 - Delete directory - int Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew) const; + uint32_t InitDevice(const Human68k::argument_t* pArgument); ///< $40 - Device startup + int CheckDir(uint32_t nUnit, const Human68k::namests_t* pNamests) const; ///< $41 - Directory check + int MakeDir(uint32_t nUnit, const Human68k::namests_t* pNamests) const; ///< $42 - Create directory + int RemoveDir(uint32_t nUnit, const Human68k::namests_t* pNamests) const; ///< $43 - Delete directory + int Rename(uint32_t nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew) const; ///< $44 - Change file name - int Delete(DWORD nUnit, const Human68k::namests_t* pNamests) const; ///< $45 - Delete file - int Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute) const; + int Delete(uint32_t nUnit, const Human68k::namests_t* pNamests) const; ///< $45 - Delete file + int Attribute(uint32_t nUnit, const Human68k::namests_t* pNamests, uint32_t nHumanAttribute) const; ///< $46 - Get / set file attribute - int Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles); + int Files(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles); ///< $47 - Find file - int NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles); ///< $48 - Find next file - int Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, bool bForce); + int NFiles(uint32_t nUnit, uint32_t nKey, Human68k::files_t* pFiles); ///< $48 - Find next file + int Create(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, uint32_t nHumanAttribute, bool bForce); ///< $49 - Create file - int Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb); + int Open(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb); ///< $4A - Open file - int Close(DWORD nUnit, DWORD nKey, const Human68k::fcb_t* pFcb); ///< $4B - Close file - int Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pAddress, DWORD nSize); + int Close(uint32_t nUnit, uint32_t nKey, const Human68k::fcb_t* pFcb); ///< $4B - Close file + int Read(uint32_t nKey, Human68k::fcb_t* pFcb, BYTE* pAddress, uint32_t nSize); ///< $4C - Read file - int Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pAddress, DWORD nSize); + int Write(uint32_t nKey, Human68k::fcb_t* pFcb, const BYTE* pAddress, uint32_t nSize); ///< $4D - Write file - int Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset); ///< $4E - Seek file - DWORD TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime); + int Seek(uint32_t nKey, Human68k::fcb_t* pFcb, uint32_t nSeek, int nOffset); ///< $4E - Seek file + uint32_t TimeStamp(uint32_t nUnit, uint32_t nKey, Human68k::fcb_t* pFcb, uint32_t nHumanTime); ///< $4F - Get / set file timestamp - int GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) const; ///< $50 - Get capacity - int CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive) const; ///< $51 - Inspect / control drive status - int GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb) const; ///< $52 - Get DPB - int DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize); ///< $53 - Read sectors - int DiskWrite(DWORD nUnit) const; ///< $54 - Write sectors - int Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl); ///< $55 - IOCTRL - int Flush(DWORD nUnit) const; ///< $56 - Flush - int CheckMedia(DWORD nUnit) const; ///< $57 - Media change check - int Lock(DWORD nUnit) const; ///< $58 - Lock + int GetCapacity(uint32_t nUnit, Human68k::capacity_t* pCapacity) const; ///< $50 - Get capacity + int CtrlDrive(uint32_t nUnit, Human68k::ctrldrive_t* pCtrlDrive) const; ///< $51 - Inspect / control drive status + int GetDPB(uint32_t nUnit, Human68k::dpb_t* pDpb) const; ///< $52 - Get DPB + int DiskRead(uint32_t nUnit, BYTE* pBuffer, uint32_t nSector, uint32_t nSize); ///< $53 - Read sectors + int DiskWrite(uint32_t nUnit) const; ///< $54 - Write sectors + int Ioctrl(uint32_t nUnit, uint32_t nFunction, Human68k::ioctrl_t* pIoctrl); ///< $55 - IOCTRL + int Flush(uint32_t nUnit) const; ///< $56 - Flush + int CheckMedia(uint32_t nUnit) const; ///< $57 - Media change check + int Lock(uint32_t nUnit) const; ///< $58 - Lock - void SetOption(DWORD nOption); ///< Set option - DWORD GetOption() const { return m_nOption; } ///< Get option - DWORD GetDefault() const { return m_nOptionDefault; } ///< Get default options - static DWORD GetFileOption() { return g_nOption; } ///< Get file name change option + void SetOption(uint32_t nOption); ///< Set option + uint32_t GetOption() const { return m_nOption; } ///< Get option + uint32_t GetDefault() const { return m_nOptionDefault; } ///< Get default options + static uint32_t GetFileOption() { return g_nOption; } ///< Get file name change option static const int DriveMax = CHostEntry::DRIVE_MAX; ///< Max number of drive candidates private: void InitOption(const Human68k::argument_t* pArgument); - bool FilesVolume(DWORD nUnit, Human68k::files_t* pFiles) const; ///< Get volume label + bool FilesVolume(uint32_t nUnit, Human68k::files_t* pFiles) const; ///< Get volume label - DWORD m_nUnits = 0; ///< Number of current drive objects (Changes for every resume) + uint32_t m_nUnits = 0; ///< Number of current drive objects (Changes for every resume) - DWORD m_nOption = 0; ///< Current runtime flag - DWORD m_nOptionDefault = 0; ///< Runtime flag at reset + uint32_t m_nOption = 0; ///< Current runtime flag + uint32_t m_nOptionDefault = 0; ///< Runtime flag at reset - DWORD m_nDrives = 0; ///< Number of candidates for base path status restoration (scan every time if 0) + uint32_t m_nDrives = 0; ///< Number of candidates for base path status restoration (scan every time if 0) - DWORD m_nKernel = 0; ///< Counter for kernel check - DWORD m_nKernelSearch = 0; ///< Initial address for NUL device + uint32_t m_nKernel = 0; ///< Counter for kernel check + uint32_t m_nKernelSearch = 0; ///< Initial address for NUL device - DWORD m_nHostSectorCount = 0; ///< Virtual sector identifier + uint32_t m_nHostSectorCount = 0; ///< Virtual sector identifier CHostFilesManager m_cFiles; ///< File search memory CHostFcbManager m_cFcb; ///< FCB operation memory CHostEntry m_cEntry; ///< Drive object and directory entry - DWORD m_nHostSectorBuffer[XM6_HOST_PSEUDO_CLUSTER_MAX]; + uint32_t m_nHostSectorBuffer[XM6_HOST_PSEUDO_CLUSTER_MAX]; ///< Entity that the virtual sector points to - DWORD m_nFlag[DriveMax] = {}; ///< Candidate runtime flag for base path restoration + uint32_t m_nFlag[DriveMax] = {}; ///< Candidate runtime flag for base path restoration TCHAR m_szBase[DriveMax][FILEPATH_MAX] = {}; ///< Candidate for base path restoration - static DWORD g_nOption; ///< File name change flag + static uint32_t g_nOption; ///< File name change flag }; diff --git a/src/raspberrypi/devices/ctapdriver.cpp b/src/raspberrypi/devices/ctapdriver.cpp index 34a77241..7dae785a 100644 --- a/src/raspberrypi/devices/ctapdriver.cpp +++ b/src/raspberrypi/devices/ctapdriver.cpp @@ -177,7 +177,7 @@ bool CTapDriver::Init(const unordered_map& const_params) LOGTRACE("Return code from ioctl was %d", ret) - int ip_fd = socket(PF_INET, SOCK_DGRAM, 0); + const int ip_fd = socket(PF_INET, SOCK_DGRAM, 0); if (ip_fd < 0) { LOGERROR("Can't open ip socket: %s", strerror(errno)) @@ -185,7 +185,7 @@ bool CTapDriver::Init(const unordered_map& const_params) return false; } - int br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); + const int br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (br_socket_fd < 0) { LOGERROR("Can't open bridge socket: %s", strerror(errno)) @@ -260,7 +260,7 @@ 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))); + const auto mask = (long long)(pow(2, 32) - (1 << (32 - m))); netmask = to_string((mask >> 24) & 0xff) + '.' + to_string((mask >> 16) & 0xff) + '.' + to_string((mask >> 8) & 0xff) + '.' + to_string(mask & 0xff); @@ -391,18 +391,18 @@ void CTapDriver::OpenDump(const Filepath& path) { bool CTapDriver::Enable() const { - int fd = socket(PF_INET, SOCK_DGRAM, 0); + const int fd = socket(PF_INET, SOCK_DGRAM, 0); LOGDEBUG("%s: ip link set ras0 up", __PRETTY_FUNCTION__) - bool result = ip_link(fd, "ras0", true); + const bool result = ip_link(fd, "ras0", true); close(fd); return result; } bool CTapDriver::Disable() const { - int fd = socket(PF_INET, SOCK_DGRAM, 0); + const int fd = socket(PF_INET, SOCK_DGRAM, 0); LOGDEBUG("%s: ip link set ras0 down", __PRETTY_FUNCTION__) - bool result = ip_link(fd, "ras0", false); + const bool result = ip_link(fd, "ras0", false); close(fd); return result; } @@ -452,7 +452,7 @@ uint32_t CTapDriver::Crc32(const BYTE *buf, int length) { for (int i = 0; i < length; i++) { crc ^= buf[i]; for (int j = 0; j < 8; j++) { - uint32_t mask = -((int)crc & 1); + const uint32_t mask = -((int)crc & 1); crc = (crc >> 1) ^ (0xEDB88320 & mask); } } @@ -469,8 +469,8 @@ int CTapDriver::Receive(BYTE *buf) } // Receive - auto dwReceived = (DWORD)read(m_hTAP, buf, ETH_FRAME_LEN); - if (dwReceived == (DWORD)-1) { + auto dwReceived = (uint32_t)read(m_hTAP, buf, ETH_FRAME_LEN); + if (dwReceived == (uint32_t)-1) { LOGWARN("%s Error occured while receiving a packet", __PRETTY_FUNCTION__) return 0; } @@ -480,7 +480,7 @@ int CTapDriver::Receive(BYTE *buf) // We need to add the Frame Check Status (FCS) CRC back onto the end of the packet. // The Linux network subsystem removes it, since most software apps shouldn't ever // need it. - int crc = Crc32(buf, dwReceived); + const int crc = Crc32(buf, dwReceived); buf[dwReceived + 0] = (BYTE)((crc >> 0) & 0xFF); buf[dwReceived + 1] = (BYTE)((crc >> 8) & 0xFF); diff --git a/src/raspberrypi/devices/ctapdriver.h b/src/raspberrypi/devices/ctapdriver.h index 3d9ece6d..6200451c 100644 --- a/src/raspberrypi/devices/ctapdriver.h +++ b/src/raspberrypi/devices/ctapdriver.h @@ -23,20 +23,16 @@ using namespace std; class CTapDriver { - friend class SCSIDaynaPort; - friend class SCSIBR; - static constexpr const char *BRIDGE_NAME = "rascsi_bridge"; +public: + CTapDriver() = default; ~CTapDriver(); CTapDriver(CTapDriver&) = default; CTapDriver& operator=(const CTapDriver&) = default; bool Init(const unordered_map&); - -public: - void OpenDump(const Filepath& path); // Capture packets void GetMacAddr(BYTE *mac) const; int Receive(BYTE *buf); diff --git a/src/raspberrypi/devices/device.cpp b/src/raspberrypi/devices/device.cpp index 720c6aff..83862157 100644 --- a/src/raspberrypi/devices/device.cpp +++ b/src/raspberrypi/devices/device.cpp @@ -76,7 +76,7 @@ string Device::GetPaddedName() const ostringstream os; os << left << setfill(' ') << setw(8) << vendor << setw(16) << product << setw(4) << revision; - string name = os.str(); + const string name = os.str(); assert(name.length() == 28); return name; diff --git a/src/raspberrypi/devices/device_factory.cpp b/src/raspberrypi/devices/device_factory.cpp index eadd4cff..490ca133 100644 --- a/src/raspberrypi/devices/device_factory.cpp +++ b/src/raspberrypi/devices/device_factory.cpp @@ -56,12 +56,17 @@ DeviceFactory::DeviceFactory() extension_mapping["hdr"] = SCRM; extension_mapping["mos"] = SCMO; extension_mapping["iso"] = SCCD; + + device_mapping["bridge"] = SCBR; + device_mapping["daynaport"] = SCDP; + device_mapping["printer"] = SCLP; + device_mapping["services"] = SCHS; } string DeviceFactory::GetExtension(const string& filename) const { string ext; - if (size_t separator = filename.rfind('.'); separator != string::npos) { + if (const size_t separator = filename.rfind('.'); separator != string::npos) { ext = filename.substr(separator + 1); } std::transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c){ return std::tolower(c); }); @@ -74,17 +79,9 @@ PbDeviceType DeviceFactory::GetTypeForFile(const string& filename) const if (const auto& it = extension_mapping.find(GetExtension(filename)); it != extension_mapping.end()) { return it->second; } - else if (filename == "bridge") { - return SCBR; - } - else if (filename == "daynaport") { - return SCDP; - } - else if (filename == "printer") { - return SCLP; - } - else if (filename == "services") { - return SCHS; + + if (const auto& it = device_mapping.find(filename); it != device_mapping.end()) { + return it->second; } return UNDEFINED; @@ -105,7 +102,7 @@ shared_ptr DeviceFactory::CreateDevice(const ControllerManager& c shared_ptr device; switch (type) { case SCHD: { - if (string ext = GetExtension(filename); ext == "hdn" || ext == "hdi" || ext == "nhd") { + if (const string ext = GetExtension(filename); ext == "hdn" || ext == "hdi" || ext == "nhd") { device = make_shared(lun); } else { device = make_shared(lun, sector_sizes[SCHD], false, @@ -220,10 +217,10 @@ list DeviceFactory::GetNetworkInterfaces() const while (tmp) { if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_PACKET && strcmp(tmp->ifa_name, "lo") && strcmp(tmp->ifa_name, "rascsi_bridge")) { - int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + const int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); ifreq ifr = {}; - strcpy(ifr.ifr_name, tmp->ifa_name); + strncpy(ifr.ifr_name, tmp->ifa_name, IFNAMSIZ); //NOSONAR Using strncpy is safe here // Only list interfaces that are up if (!ioctl(fd, SIOCGIFFLAGS, &ifr) && (ifr.ifr_flags & IFF_UP)) { network_interfaces.emplace_back(tmp->ifa_name); diff --git a/src/raspberrypi/devices/device_factory.h b/src/raspberrypi/devices/device_factory.h index 2c3e445f..f5e06ca8 100644 --- a/src/raspberrypi/devices/device_factory.h +++ b/src/raspberrypi/devices/device_factory.h @@ -38,7 +38,7 @@ public: const unordered_set& GetSectorSizes(const string&) const; const unordered_map& GetDefaultParams(PbDeviceType type) const; list GetNetworkInterfaces() const; - unordered_map GetExtensionMapping() const { return extension_mapping; } + const unordered_map& GetExtensionMapping() const { return extension_mapping; } private: @@ -50,6 +50,8 @@ private: unordered_map extension_mapping; + unordered_map device_mapping; + unordered_set empty_set; unordered_map empty_map; }; diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index 13e5f886..ad2f1660 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -14,9 +14,7 @@ // //--------------------------------------------------------------------------- -#include "os.h" #include "fileio.h" -#include "file_support.h" #include "rascsi_exceptions.h" #include "dispatcher.h" #include "scsi_command_util.h" @@ -25,6 +23,8 @@ using namespace scsi_defs; using namespace scsi_command_util; +unordered_map Disk::reserved_files; + Disk::Disk(const string& type, int lun) : ModePageDevice(type, lun) { dispatcher.Add(scsi_command::eCmdRezero, "Rezero", &Disk::Rezero); @@ -73,7 +73,7 @@ bool Disk::Dispatch(scsi_command cmd) is_medium_changed = false; - throw scsi_error_exception(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); + throw scsi_exception(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); } // The superclass handles the less specific commands @@ -141,7 +141,7 @@ void Disk::FormatUnit() // FMTDATA=1 is not supported (but OK if there is no DEFECT LIST) if ((ctrl->cmd[1] & 0x10) != 0 && ctrl->cmd[4] != 0) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } EnterStatusPhase(); @@ -187,7 +187,7 @@ void Disk::ReadWriteLong10() { // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard if (GetInt16(ctrl->cmd, 7) != 0) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } ValidateBlockAddress(RW10); @@ -199,7 +199,7 @@ void Disk::ReadWriteLong16() { // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard if (GetInt16(ctrl->cmd, 12) != 0) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } ValidateBlockAddress(RW16); @@ -271,8 +271,8 @@ void Disk::Verify16() void Disk::StartStopUnit() { - bool start = ctrl->cmd[4] & 0x01; - bool load = ctrl->cmd[4] & 0x02; + const bool start = ctrl->cmd[4] & 0x01; + const bool load = ctrl->cmd[4] & 0x02; if (load) { LOGTRACE(start ? "Loading medium" : "Ejecting medium") @@ -290,12 +290,12 @@ void Disk::StartStopUnit() if (load) { if (IsLocked()) { // Cannot be ejected because it is locked - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::LOAD_OR_EJECT_FAILED); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::LOAD_OR_EJECT_FAILED); } // Eject if (!Eject(false)) { - throw scsi_error_exception(); + throw scsi_exception(); } } } @@ -307,12 +307,12 @@ void Disk::SendDiagnostic() { // Do not support PF bit if (ctrl->cmd[1] & 0x10) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Do not support parameter list if ((ctrl->cmd[3] != 0) || (ctrl->cmd[4] != 0)) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } EnterStatusPhase(); @@ -322,7 +322,7 @@ void Disk::PreventAllowMediumRemoval() { CheckReady(); - bool lock = ctrl->cmd[4] & 0x01; + const bool lock = ctrl->cmd[4] & 0x01; LOGTRACE(lock ? "Locking medium" : "Unlocking medium") @@ -340,7 +340,7 @@ void Disk::SynchronizeCache() void Disk::ReadDefectData10() { - size_t allocation_length = min((size_t)GetInt16(ctrl->cmd, 7), (size_t)4); + const size_t allocation_length = min((size_t)GetInt16(ctrl->cmd, 7), (size_t)4); // The defect list is empty fill_n(controller->GetBuffer().begin(), allocation_length, 0); @@ -361,15 +361,13 @@ void Disk::MediumChanged() bool Disk::Eject(bool force) { - bool status = super::Eject(force); + const bool status = super::Eject(force); if (status) { FlushCache(); cache.reset(); // The image file for this drive is not in use anymore - if (auto file_support = dynamic_cast(this); file_support) { - file_support->UnreserveFile(); - } + UnreserveFile(); } return status; @@ -378,7 +376,7 @@ bool Disk::Eject(bool force) int Disk::ModeSense6(const vector& cdb, vector& buf) const { // Get length, clear buffer - auto length = (int)min(buf.size(), (size_t)cdb[4]); + const auto length = (int)min(buf.size(), (size_t)cdb[4]); fill_n(buf.begin(), length, 0); // DEVICE SPECIFIC PARAMETER @@ -406,7 +404,7 @@ int Disk::ModeSense6(const vector& cdb, vector& buf) const size += super::AddModePages(cdb, buf, size, length - size); if (size > 255) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Do not return more than ALLOCATION LENGTH bytes @@ -423,7 +421,7 @@ int Disk::ModeSense6(const vector& cdb, vector& buf) const int Disk::ModeSense10(const vector& cdb, vector& buf) const { // Get length, clear buffer - auto length = (int)min(buf.size(), (size_t)GetInt16(cdb, 7)); + const auto length = (int)min(buf.size(), (size_t)GetInt16(cdb, 7)); fill_n(buf.begin(), length, 0); // DEVICE SPECIFIC PARAMETER @@ -467,7 +465,7 @@ int Disk::ModeSense10(const vector& cdb, vector& buf) const size += super::AddModePages(cdb, buf, size, length - size); if (size > 65535) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Do not return more than ALLOCATION LENGTH bytes @@ -623,12 +621,12 @@ int Disk::Read(const vector&, vector& buf, uint64_t block) // Error if the total number of blocks is exceeded if (block >= blocks) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // leave it to the cache if (!cache->ReadSector(buf, (uint32_t)block)) { - throw scsi_error_exception(sense_key::MEDIUM_ERROR, asc::READ_FAULT); + throw scsi_exception(sense_key::MEDIUM_ERROR, asc::READ_FAULT); } // Success @@ -641,12 +639,12 @@ int Disk::WriteCheck(uint64_t block) // Error if the total number of blocks is exceeded if (block >= blocks) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Error if write protected if (IsProtected()) { - throw scsi_error_exception(sense_key::DATA_PROTECT, asc::WRITE_PROTECTED); + throw scsi_exception(sense_key::DATA_PROTECT, asc::WRITE_PROTECTED); } // Success @@ -660,22 +658,22 @@ void Disk::Write(const vector&, const vector& buf, uint64_t block) // Error if not ready if (!IsReady()) { - throw scsi_error_exception(sense_key::NOT_READY); + throw scsi_exception(sense_key::NOT_READY); } // Error if the total number of blocks is exceeded if (block >= blocks) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); } // Error if write protected if (IsProtected()) { - throw scsi_error_exception(sense_key::DATA_PROTECT, asc::WRITE_PROTECTED); + throw scsi_exception(sense_key::DATA_PROTECT, asc::WRITE_PROTECTED); } // Leave it to the cache if (!cache->WriteSector(buf, (uint32_t)block)) { - throw scsi_error_exception(sense_key::MEDIUM_ERROR, asc::WRITE_FAULT); + throw scsi_exception(sense_key::MEDIUM_ERROR, asc::WRITE_FAULT); } } @@ -709,7 +707,7 @@ void Disk::ReadCapacity10() CheckReady(); if (blocks == 0) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); } vector& buf = controller->GetBuffer(); @@ -737,7 +735,7 @@ void Disk::ReadCapacity16() CheckReady(); if (blocks == 0) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT); } vector& buf = controller->GetBuffer(); @@ -772,7 +770,7 @@ void Disk::ReadCapacity16_ReadLong16() break; default: - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); break; } } @@ -805,14 +803,12 @@ void Disk::Release() void Disk::ValidateBlockAddress(access_mode mode) const { - uint64_t block = mode == RW16 ? GetInt64(ctrl->cmd, 2) : GetInt32(ctrl->cmd, 2); + const uint64_t block = mode == RW16 ? GetInt64(ctrl->cmd, 2) : GetInt32(ctrl->cmd, 2); - uint64_t capacity = blocks; - - if (block > capacity) { - LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " block(s) exceeded: Trying to access block " + if (block > blocks) { + LOGTRACE("%s", ("Capacity of " + to_string(blocks) + " block(s) exceeded: Trying to access block " + to_string(block)).c_str()) - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); } } @@ -846,7 +842,7 @@ bool Disk::CheckAndGetStartAndCount(uint64_t& start, uint32_t& count, access_mod if (uint64_t capacity = blocks; start > capacity || start + count > capacity) { LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " block(s) exceeded: Trying to access block " + to_string(start) + ", block count " + to_string(count)).c_str()) - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); } // Do not process 0 blocks @@ -909,3 +905,43 @@ bool Disk::SetConfiguredSectorSize(const DeviceFactory& device_factory, uint32_t return true; } + +void Disk::ReserveFile(const Filepath& path, int id, int lun) const +{ + reserved_files[path.GetPath()] = make_pair(id, lun); +} + +void Disk::UnreserveFile() const +{ + reserved_files.erase(diskpath.GetPath()); +} + +bool Disk::GetIdsForReservedFile(const Filepath& path, int& id, int& lun) +{ + if (const auto& it = reserved_files.find(path.GetPath()); it != reserved_files.end()) { + id = it->second.first; + lun = it->second.second; + + return true; + } + + return false; +} + +void Disk::UnreserveAll() +{ + reserved_files.clear(); +} + +bool Disk::FileExists(const Filepath& filepath) +{ + try { + // Disk::Open closes the file in case it exists + Open(filepath); + } + catch(const file_not_found_exception&) { + return false; + } + + return true; +} diff --git a/src/raspberrypi/devices/disk.h b/src/raspberrypi/devices/disk.h index 6edcaa54..3fe55b0f 100644 --- a/src/raspberrypi/devices/disk.h +++ b/src/raspberrypi/devices/disk.h @@ -25,7 +25,11 @@ #include #include -class Disk : public ModePageDevice, public ScsiBlockCommands +using namespace std; + +using id_set = pair; + +class Disk : public ModePageDevice, private ScsiBlockCommands { enum access_mode { RW6, RW10, RW16, SEEK6, SEEK10 }; @@ -45,6 +49,11 @@ class Disk : public ModePageDevice, public ScsiBlockCommands bool is_medium_changed = false; + Filepath diskpath; + + // The list of image files in use and the IDs and LUNs using these files + static unordered_map reserved_files; + public: Disk(const string&, int); @@ -67,6 +76,18 @@ public: uint64_t GetBlockCount() const { return blocks; } void FlushCache() override; + virtual void Open(const Filepath&); + void GetPath(Filepath& path) const { path = diskpath; } + + void ReserveFile(const Filepath&, int, int) const; + void UnreserveFile() const; + static void UnreserveAll(); + bool FileExists(const Filepath&); + + static unordered_map GetReservedFiles() { return reserved_files; } + static void SetReservedFiles(const unordered_map& files_in_use) { reserved_files = files_in_use; } + static bool GetIdsForReservedFile(const Filepath&, int&, int&); + private: using super = ModePageDevice; @@ -110,7 +131,6 @@ private: protected: - virtual void Open(const Filepath&); void SetUpCache(const Filepath&, off_t, bool = false); void ResizeCache(const Filepath&, bool); @@ -127,4 +147,5 @@ protected: void SetSectorSizeShiftCount(uint32_t count) { size_shift_count = count; } uint32_t GetConfiguredSectorSize() const; void SetBlockCount(uint64_t b) { blocks = b; } + void SetPath(const Filepath& path) { diskpath = path; } }; diff --git a/src/raspberrypi/devices/disk_cache.cpp b/src/raspberrypi/devices/disk_cache.cpp index e1458f00..5bee54e8 100644 --- a/src/raspberrypi/devices/disk_cache.cpp +++ b/src/raspberrypi/devices/disk_cache.cpp @@ -16,6 +16,8 @@ #include "disk_track.h" #include "disk_cache.h" +#include +#include DiskCache::DiskCache(const Filepath& path, int size, uint32_t blocks, off_t imgoff) : sec_size(size), sec_blocks(blocks), imgoffset(imgoff) diff --git a/src/raspberrypi/devices/disk_track.cpp b/src/raspberrypi/devices/disk_track.cpp index 065c1281..58337f7e 100644 --- a/src/raspberrypi/devices/disk_track.cpp +++ b/src/raspberrypi/devices/disk_track.cpp @@ -68,7 +68,7 @@ bool DiskTrack::Load(const Filepath& path) offset += dt.imgoffset; // Calculate length (data size of this track) - int length = dt.sectors << dt.size; + const int length = dt.sectors << dt.size; // Allocate buffer memory assert((dt.sectors > 0) && (dt.sectors <= 0x100)); @@ -85,7 +85,7 @@ bool DiskTrack::Load(const Filepath& path) } // Reallocate if the buffer length is different - if (dt.length != (DWORD)length) { + if (dt.length != (uint32_t)length) { free(dt.buffer); if (posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512)) { LOGWARN("%s posix_memalign failed", __PRETTY_FUNCTION__) @@ -167,7 +167,7 @@ bool DiskTrack::Save(const Filepath& path) offset += dt.imgoffset; // Calculate length per sector - int length = 1 << dt.size; + const int length = 1 << dt.size; // Open file Fileio fio; @@ -265,8 +265,8 @@ bool DiskTrack::WriteSector(const vector& buf, int sec) } // Calculate offset and length - int offset = sec << dt.size; - int length = 1 << dt.size; + const int offset = sec << dt.size; + const int length = 1 << dt.size; // Compare assert(dt.buffer); diff --git a/src/raspberrypi/devices/disk_track.h b/src/raspberrypi/devices/disk_track.h index 19e8ce84..20bc1a51 100644 --- a/src/raspberrypi/devices/disk_track.h +++ b/src/raspberrypi/devices/disk_track.h @@ -16,6 +16,7 @@ #pragma once #include "filepath.h" +#include #include using namespace std; @@ -26,7 +27,7 @@ class DiskTrack int track; // Track Number int size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096) int sectors; // Number of sectors(<0x100) - DWORD length; // Data buffer length + uint32_t length; // Data buffer length BYTE *buffer; // Data buffer bool init; // Is it initilized? bool changed; // Changed flag diff --git a/src/raspberrypi/devices/file_support.cpp b/src/raspberrypi/devices/file_support.cpp deleted file mode 100644 index c6b476ac..00000000 --- a/src/raspberrypi/devices/file_support.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator RaSCSI Reloaded -// for Raspberry Pi -// -// Copyright (C) 2021-2022 Uwe Seimet -// -//--------------------------------------------------------------------------- - -#include "rascsi_exceptions.h" -#include "file_support.h" - -using namespace std; - -unordered_map FileSupport::reserved_files; - -void FileSupport::ReserveFile(const Filepath& path, int id, int lun) const -{ - reserved_files[path.GetPath()] = make_pair(id, lun); -} - -void FileSupport::UnreserveFile() const -{ - reserved_files.erase(diskpath.GetPath()); -} - -bool FileSupport::GetIdsForReservedFile(const Filepath& path, int& id, int& lun) -{ - if (const auto& it = reserved_files.find(path.GetPath()); it != reserved_files.end()) { - id = it->second.first; - lun = it->second.second; - - return true; - } - - return false; -} - -void FileSupport::UnreserveAll() -{ - reserved_files.clear(); -} - -bool FileSupport::FileExists(const Filepath& filepath) -{ - try { - // Disk::Open closes the file in case it exists - Open(filepath); - } - catch(const file_not_found_exception&) { - return false; - } - - return true; -} diff --git a/src/raspberrypi/devices/file_support.h b/src/raspberrypi/devices/file_support.h deleted file mode 100644 index 051ef1dc..00000000 --- a/src/raspberrypi/devices/file_support.h +++ /dev/null @@ -1,48 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator RaSCSI Reloaded -// for Raspberry Pi -// -// Copyright (C) 2021-2022 Uwe Seimet -// -// Devices inheriting from FileSupport support image files -// -//--------------------------------------------------------------------------- - -#pragma once - -#include -#include -#include "filepath.h" - -using namespace std; - -using id_set = pair; - -class FileSupport -{ - Filepath diskpath; - - // The list of image files in use and the IDs and LUNs using these files - static unordered_map reserved_files; - -public: - - FileSupport() = default; - virtual ~FileSupport() = default; - - void GetPath(Filepath& path) const { path = diskpath; } - void SetPath(const Filepath& path) { diskpath = path; } - - void ReserveFile(const Filepath&, int, int) const; - void UnreserveFile() const; - static void UnreserveAll(); - bool FileExists(const Filepath&); - - static unordered_map GetReservedFiles() { return reserved_files; } - static void SetReservedFiles(const unordered_map& files_in_use) - { FileSupport::reserved_files = files_in_use; } - static bool GetIdsForReservedFile(const Filepath&, int&, int&); - - virtual void Open(const Filepath&) = 0; -}; diff --git a/src/raspberrypi/devices/host_services.cpp b/src/raspberrypi/devices/host_services.cpp index 2ff99fa2..aed2079e 100644 --- a/src/raspberrypi/devices/host_services.cpp +++ b/src/raspberrypi/devices/host_services.cpp @@ -57,8 +57,8 @@ vector HostServices::InquiryInternal() const void HostServices::StartStopUnit() { - bool start = ctrl->cmd[4] & 0x01; - bool load = ctrl->cmd[4] & 0x02; + const bool start = ctrl->cmd[4] & 0x01; + const bool load = ctrl->cmd[4] & 0x02; if (!start) { // Flush any caches @@ -77,7 +77,7 @@ void HostServices::StartStopUnit() controller->ScheduleShutdown(AbstractController::rascsi_shutdown_mode::RESTART_PI); } else { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } EnterStatusPhase(); @@ -87,10 +87,10 @@ int HostServices::ModeSense6(const vector& cdb, vector& buf) const { // Block descriptors cannot be returned if (!(cdb[1] & 0x08)) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - auto length = (int)min(buf.size(), (size_t)cdb[4]); + const auto length = (int)min(buf.size(), (size_t)cdb[4]); fill_n(buf.begin(), length, 0); // Basic Information @@ -98,7 +98,7 @@ int HostServices::ModeSense6(const vector& cdb, vector& buf) const size += super::AddModePages(cdb, buf, size, length - size); if (size > 255) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Do not return more than ALLOCATION LENGTH bytes @@ -115,10 +115,10 @@ int HostServices::ModeSense10(const vector& cdb, vector& buf) const { // Block descriptors cannot be returned if (!(cdb[1] & 0x08)) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - auto length = (int)min(buf.size(), (size_t)GetInt16(cdb, 7)); + const auto length = (int)min(buf.size(), (size_t)GetInt16(cdb, 7)); fill_n(buf.begin(), length, 0); // Basic Information @@ -126,7 +126,7 @@ int HostServices::ModeSense10(const vector& cdb, vector& buf) const size += super::AddModePages(cdb, buf, size, length - size); if (size > 65535) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Do not return more than ALLOCATION LENGTH bytes diff --git a/src/raspberrypi/devices/host_services.h b/src/raspberrypi/devices/host_services.h index a5c42338..f34a04a9 100644 --- a/src/raspberrypi/devices/host_services.h +++ b/src/raspberrypi/devices/host_services.h @@ -29,7 +29,6 @@ public: vector InquiryInternal() const override; void TestUnitReady() override; - void StartStopUnit(); bool SupportsFile() const override { return false; } @@ -58,6 +57,7 @@ private: const ControllerManager& controller_manager; + void StartStopUnit(); int ModeSense6(const vector&, vector&) const override; int ModeSense10(const vector&, vector&) const override; diff --git a/src/raspberrypi/devices/mode_page_device.cpp b/src/raspberrypi/devices/mode_page_device.cpp index c0c4b860..0bcf0636 100644 --- a/src/raspberrypi/devices/mode_page_device.cpp +++ b/src/raspberrypi/devices/mode_page_device.cpp @@ -40,10 +40,10 @@ int ModePageDevice::AddModePages(const vector& cdb, vector& buf, int return 0; } - bool changeable = (cdb[2] & 0xc0) == 0x40; + const bool changeable = (cdb[2] & 0xc0) == 0x40; // Get page code (0x3f means all pages) - int page = cdb[2] & 0x3f; + const int page = cdb[2] & 0x3f; LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page) @@ -53,7 +53,7 @@ int ModePageDevice::AddModePages(const vector& cdb, vector& buf, int if (pages.empty()) { LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page) - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Holds all mode page data @@ -63,7 +63,7 @@ int ModePageDevice::AddModePages(const vector& cdb, vector& buf, int for (auto const& [index, data] : pages) { // The specification mandates that page 0 must be returned after all others if (index) { - size_t off = result.size(); + const size_t off = result.size(); // Page data result.insert(result.end(), data.begin(), data.end()); @@ -110,7 +110,7 @@ void ModePageDevice::ModeSense10() void ModePageDevice::ModeSelect(const vector&, const vector&, int) const { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); } void ModePageDevice::ModeSelect6() @@ -132,7 +132,7 @@ int ModePageDevice::ModeSelectCheck(int length) const // 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); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } return length; diff --git a/src/raspberrypi/devices/primary_device.cpp b/src/raspberrypi/devices/primary_device.cpp index 60820f05..0ecbf95a 100644 --- a/src/raspberrypi/devices/primary_device.cpp +++ b/src/raspberrypi/devices/primary_device.cpp @@ -59,12 +59,12 @@ void PrimaryDevice::Inquiry() { // EVPD and page code check if ((ctrl->cmd[1] & 0x01) || ctrl->cmd[2]) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } vector buf = InquiryInternal(); - size_t allocation_length = min(buf.size(), (size_t)GetInt16(ctrl->cmd, 3)); + const size_t allocation_length = min(buf.size(), (size_t)GetInt16(ctrl->cmd, 3)); memcpy(controller->GetBuffer().data(), buf.data(), allocation_length); ctrl->length = (uint32_t)allocation_length; @@ -84,10 +84,10 @@ void PrimaryDevice::ReportLuns() { // Only SELECT REPORT mode 0 is supported if (ctrl->cmd[2]) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - uint32_t allocation_length = GetInt32(ctrl->cmd, 6); + const uint32_t allocation_length = GetInt32(ctrl->cmd, 6); vector& buf = controller->GetBuffer(); fill_n(buf.begin(), min(buf.size(), (size_t)allocation_length), 0); @@ -129,7 +129,7 @@ void PrimaryDevice::RequestSense() vector buf = controller->GetDeviceForLun(lun)->HandleRequestSense(); - size_t allocation_length = min(buf.size(), (size_t)ctrl->cmd[4]); + const size_t allocation_length = min(buf.size(), (size_t)ctrl->cmd[4]); memcpy(controller->GetBuffer().data(), buf.data(), allocation_length); ctrl->length = (uint32_t)allocation_length; @@ -143,20 +143,20 @@ void PrimaryDevice::CheckReady() if (IsReset()) { SetReset(false); LOGTRACE("%s Device in reset", __PRETTY_FUNCTION__) - throw scsi_error_exception(sense_key::UNIT_ATTENTION, asc::POWER_ON_OR_RESET); + throw scsi_exception(sense_key::UNIT_ATTENTION, asc::POWER_ON_OR_RESET); } // Not ready if it needs attention if (IsAttn()) { SetAttn(false); LOGTRACE("%s Device in needs attention", __PRETTY_FUNCTION__) - throw scsi_error_exception(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); + throw scsi_exception(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); } // Return status if not ready if (!IsReady()) { LOGTRACE("%s Device not ready", __PRETTY_FUNCTION__) - throw scsi_error_exception(sense_key::NOT_READY, asc::MEDIUM_NOT_PRESENT); + throw scsi_exception(sense_key::NOT_READY, asc::MEDIUM_NOT_PRESENT); } // Initialization with no error @@ -180,7 +180,7 @@ vector PrimaryDevice::HandleInquiry(device_type type, scsi_level level, bo buf[4] = (byte)0x1F; // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); + memcpy(&buf.data()[8], GetPaddedName().c_str(), 28); return buf; } @@ -189,7 +189,7 @@ vector PrimaryDevice::HandleRequestSense() const { // Return not ready only if there are no errors if (!GetStatusCode() && !IsReady()) { - throw scsi_error_exception(sense_key::NOT_READY, asc::MEDIUM_NOT_PRESENT); + throw scsi_exception(sense_key::NOT_READY, asc::MEDIUM_NOT_PRESENT); } // Set 18 bytes including extended sense data diff --git a/src/raspberrypi/devices/primary_device.h b/src/raspberrypi/devices/primary_device.h index a0659f10..574c9046 100644 --- a/src/raspberrypi/devices/primary_device.h +++ b/src/raspberrypi/devices/primary_device.h @@ -17,7 +17,7 @@ #include "dispatcher.h" #include -class PrimaryDevice: public ScsiPrimaryCommands, public Device +class PrimaryDevice: private ScsiPrimaryCommands, public Device { public: diff --git a/src/raspberrypi/devices/scsi_command_util.cpp b/src/raspberrypi/devices/scsi_command_util.cpp index 9467a218..b2f3849f 100644 --- a/src/raspberrypi/devices/scsi_command_util.cpp +++ b/src/raspberrypi/devices/scsi_command_util.cpp @@ -20,7 +20,7 @@ void scsi_command_util::ModeSelect(const vector& cdb, const vector& b // PF 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); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); } bool has_valid_page_code = false; @@ -33,7 +33,7 @@ void scsi_command_util::ModeSelect(const vector& cdb, const vector& b 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); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); } offset += 12; @@ -52,7 +52,7 @@ void scsi_command_util::ModeSelect(const vector& cdb, const vector& b // 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); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); } has_valid_page_code = true; @@ -68,7 +68,7 @@ void scsi_command_util::ModeSelect(const vector& cdb, const vector& b } if (!has_valid_page_code) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); } } diff --git a/src/raspberrypi/devices/scsi_daynaport.cpp b/src/raspberrypi/devices/scsi_daynaport.cpp index 20be31df..b5b8ce9a 100644 --- a/src/raspberrypi/devices/scsi_daynaport.cpp +++ b/src/raspberrypi/devices/scsi_daynaport.cpp @@ -21,9 +21,6 @@ // following link: // - https://github.com/akuker/RASCSI/wiki/Dayna-Port-SCSI-Link // -// This does NOT include the file system functionality that is present -// in the Sharp X68000 host bridge. -// // Note: This requires a DaynaPort SCSI Link driver. //--------------------------------------------------------------------------- @@ -133,12 +130,11 @@ vector SCSIDaynaPort::InquiryInternal() const int SCSIDaynaPort::Read(const vector& cdb, vector& buf, uint64_t) { int rx_packet_size = 0; - auto response = (scsi_resp_read_t*)buf.data(); + const auto response = (scsi_resp_read_t*)buf.data(); - int requested_length = cdb[4]; + const int requested_length = cdb[4]; LOGTRACE("%s Read maximum length %d, (%04X)", __PRETTY_FUNCTION__, requested_length, requested_length) - // At host startup, it will send a READ(6) command with a length of 1. We should // respond by going into the status mode with a code of 0x02 if (requested_length == 1) { @@ -207,8 +203,7 @@ int SCSIDaynaPort::Read(const vector& cdb, vector& buf, uint64_t) // If there are pending packets to be processed, we'll tell the host that the read // length was 0. - if (!m_tap.PendingPackets()) - { + if (!m_tap.PendingPackets()) { response->length = 0; response->flags = read_data_flags_t::e_no_more_data; return DAYNAPORT_READ_HEADER_SZ; @@ -252,8 +247,8 @@ int SCSIDaynaPort::WriteCheck(uint64_t) { CheckReady(); - if (!m_bTapEnable){ - throw scsi_error_exception(sense_key::UNIT_ATTENTION, asc::MEDIUM_NOT_PRESENT); + if (!m_bTapEnable) { + throw scsi_exception(sense_key::UNIT_ATTENTION, asc::MEDIUM_NOT_PRESENT); } return 1; @@ -279,22 +274,20 @@ int SCSIDaynaPort::WriteCheck(uint64_t) //--------------------------------------------------------------------------- bool SCSIDaynaPort::WriteBytes(const vector& cdb, const vector& buf, uint64_t) { - int data_format = cdb[5]; + const int data_format = cdb[5]; int data_length = GetInt16(cdb, 3); - if (data_format == 0x00){ + if (data_format == 0x00) { m_tap.Send(buf.data(), data_length); LOGTRACE("%s Transmitted %u bytes (00 format)", __PRETTY_FUNCTION__, data_length) } - else if (data_format == 0x80){ + 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); + data_length = buf[1] + (((int)buf[0] & 0xff) << 8); m_tap.Send(&(buf.data()[4]), data_length); LOGTRACE("%s Transmitted %u bytes (80 format)", __PRETTY_FUNCTION__, data_length) } - else - { - // LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, (unsigned int)command->format) + else { LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, data_format) } @@ -321,45 +314,7 @@ int SCSIDaynaPort::RetrieveStats(const vector& cdb, vector& buf) cons { memcpy(buf.data(), &m_scsi_link_stats, sizeof(m_scsi_link_stats)); - return (int)min(sizeof(m_scsi_link_stats), (size_t)GetInt16(cdb, 4)); -} - -//--------------------------------------------------------------------------- -// -// Enable or Disable the interface -// -// Command: 0e 00 00 00 00 XX (XX = 80 or 00) -// Function: Enable (80) / disable (00) Ethernet interface -// Type: No data transferred -// Notes: After issuing an Enable, the initiator should avoid sending -// any subsequent commands to the device for approximately 0.5 -// seconds -// -//--------------------------------------------------------------------------- -bool SCSIDaynaPort::EnableInterface(const vector& cdb) -{ - bool result; - if (cdb[5] & 0x80) { - result = m_tap.Enable(); - if (result) { - LOGINFO("The DaynaPort interface has been ENABLED.") - } - else{ - LOGWARN("Unable to enable the DaynaPort Interface") - } - m_tap.Flush(); - } - else { - result = m_tap.Disable(); - if (result) { - LOGINFO("The DaynaPort interface has been DISABLED.") - } - else{ - LOGWARN("Unable to disable the DaynaPort Interface") - } - } - - return result; + return (int)min(sizeof(m_scsi_link_stats), (size_t)GetInt16(cdb, 3)); } void SCSIDaynaPort::TestUnitReady() @@ -371,14 +326,14 @@ void SCSIDaynaPort::TestUnitReady() void SCSIDaynaPort::Read6() { // Get record number and block number - uint32_t record = GetInt24(ctrl->cmd, 1) & 0x1fffff; + const uint32_t record = GetInt24(ctrl->cmd, 1) & 0x1fffff; ctrl->blocks=1; // If any commands have a bogus control value, they were probably not // generated by the DaynaPort driver so ignore them if (ctrl->cmd[5] != 0xc0 && ctrl->cmd[5] != 0x80) { LOGTRACE("%s Control value %d, (%04X), returning invalid CDB", __PRETTY_FUNCTION__, ctrl->cmd[5], ctrl->cmd[5]) - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, record, ctrl->blocks) @@ -397,7 +352,7 @@ void SCSIDaynaPort::Write6() // Ensure a sufficient buffer size (because it is not transfer for each block) controller->AllocateBuffer(DAYNAPORT_BUFFER_SIZE); - int data_format = ctrl->cmd[5]; + const int data_format = ctrl->cmd[5]; if (data_format == 0x00) { ctrl->length = GetInt16(ctrl->cmd, 3); @@ -411,7 +366,7 @@ void SCSIDaynaPort::Write6() LOGTRACE("%s length: $%04X (%d) format: $%02X", __PRETTY_FUNCTION__, ctrl->length, ctrl->length, data_format) if (ctrl->length <= 0) { - throw scsi_error_exception(); + throw scsi_exception(); } // Set next block @@ -478,10 +433,12 @@ void SCSIDaynaPort::SetInterfaceMode() case CMD_SCSILINK_ENABLE: case CMD_SCSILINK_SET: LOGWARN("%s Unsupported SetInterface command received: %02X", __PRETTY_FUNCTION__, ctrl->cmd[5]) + throw scsi_exception(); break; default: LOGWARN("%s Unknown SetInterface command received: %02X", __PRETTY_FUNCTION__, ctrl->cmd[5]) + throw scsi_exception(); break; } } @@ -492,16 +449,45 @@ void SCSIDaynaPort::SetMcastAddr() if (ctrl->length == 0) { LOGWARN("%s Not supported SetMcastAddr Command %02X", __PRETTY_FUNCTION__, ctrl->cmd[2]) - throw scsi_error_exception(); + throw scsi_exception(); } EnterDataOutPhase(); } +//--------------------------------------------------------------------------- +// +// Enable or Disable the interface +// +// Command: 0e 00 00 00 00 XX (XX = 80 or 00) +// Function: Enable (80) / disable (00) Ethernet interface +// Type: No data transferred +// Notes: After issuing an Enable, the initiator should avoid sending +// any subsequent commands to the device for approximately 0.5 +// seconds +// +//--------------------------------------------------------------------------- void SCSIDaynaPort::EnableInterface() { - if (!EnableInterface(ctrl->cmd)) { - throw scsi_error_exception(); + if (ctrl->cmd[5] & 0x80) { + if (!m_tap.Enable()) { + LOGWARN("Unable to enable the DaynaPort Interface") + + throw scsi_exception(); + } + + m_tap.Flush(); + + LOGINFO("The DaynaPort interface has been ENABLED") + } + else { + if (!m_tap.Disable()) { + LOGWARN("Unable to disable the DaynaPort Interface") + + throw scsi_exception(); + } + + LOGINFO("The DaynaPort interface has been DISABLED") } EnterStatusPhase(); diff --git a/src/raspberrypi/devices/scsi_daynaport.h b/src/raspberrypi/devices/scsi_daynaport.h index 9f45d05d..9ca3a9af 100644 --- a/src/raspberrypi/devices/scsi_daynaport.h +++ b/src/raspberrypi/devices/scsi_daynaport.h @@ -41,7 +41,7 @@ // DaynaPort SCSI Link // //=========================================================================== -class SCSIDaynaPort final : public Disk +class SCSIDaynaPort : public Disk { public: @@ -58,7 +58,6 @@ public: int WriteCheck(uint64_t block) override; int RetrieveStats(const vector&, vector&) const; - bool EnableInterface(const vector&); void TestUnitReady() override; void Read6() override; @@ -88,9 +87,10 @@ public: // The READ response has a header which consists of: // 2 bytes - payload size // 4 bytes - status flags - static const DWORD DAYNAPORT_READ_HEADER_SZ = 2 + 4; + static const uint32_t DAYNAPORT_READ_HEADER_SZ = 2 + 4; private: + using super = Disk; Dispatcher dispatcher; diff --git a/src/raspberrypi/devices/scsi_host_bridge.cpp b/src/raspberrypi/devices/scsi_host_bridge.cpp index f107def5..6d5b4e16 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.cpp +++ b/src/raspberrypi/devices/scsi_host_bridge.cpp @@ -107,13 +107,13 @@ void SCSIBR::TestUnitReady() int SCSIBR::GetMessage10(const vector& cdb, vector& buf) { // Type - int type = cdb[2]; + const int type = cdb[2]; // Function number - int func = cdb[3]; + const int func = cdb[3]; // Phase - int phase = cdb[9]; + const int phase = cdb[9]; switch (type) { case 1: // Ethernet @@ -195,16 +195,16 @@ int SCSIBR::GetMessage10(const vector& cdb, vector& buf) bool SCSIBR::WriteBytes(const vector& cdb, vector& buf, uint64_t) { // Type - int type = cdb[2]; + const int type = cdb[2]; // Function number - int func = cdb[3]; + const int func = cdb[3]; // Phase - int phase = cdb[9]; + const int phase = cdb[9]; // Get the number of lights - int len = GetInt24(cdb, 6); + const int len = GetInt24(cdb, 6); switch (type) { case 1: // Ethernet @@ -257,7 +257,7 @@ void SCSIBR::GetMessage10() ctrl->length = GetMessage10(ctrl->cmd, controller->GetBuffer()); if (ctrl->length <= 0) { - throw scsi_error_exception(); + throw scsi_exception(); } // Set next block @@ -278,7 +278,7 @@ void SCSIBR::SendMessage10() { ctrl->length = GetInt24(ctrl->cmd, 6); if (ctrl->length <= 0) { - throw scsi_error_exception(); + throw scsi_exception(); } // Ensure a sufficient buffer size (because it is not a transfer for each block) @@ -368,8 +368,8 @@ void SCSIBR::FS_InitDevice(vector& buf) void SCSIBR::FS_CheckDir(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); - int i = sizeof(uint32_t); + const uint32_t nUnit = ntohl(*dp); + const int i = sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -384,8 +384,8 @@ void SCSIBR::FS_CheckDir(vector& buf) void SCSIBR::FS_MakeDir(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); - int i = sizeof(uint32_t); + const uint32_t nUnit = ntohl(*dp); + const int i = sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -400,8 +400,8 @@ void SCSIBR::FS_MakeDir(vector& buf) void SCSIBR::FS_RemoveDir(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); - int i = sizeof(uint32_t); + const uint32_t nUnit = ntohl(*dp); + const int i = sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -416,7 +416,7 @@ void SCSIBR::FS_RemoveDir(vector& buf) void SCSIBR::FS_Rename(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -435,8 +435,8 @@ void SCSIBR::FS_Rename(vector& buf) void SCSIBR::FS_Delete(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); - int i = sizeof(uint32_t); + const uint32_t nUnit = ntohl(*dp); + const int i = sizeof(uint32_t); const auto *pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -451,7 +451,7 @@ void SCSIBR::FS_Delete(vector& buf) void SCSIBR::FS_Attribute(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -471,11 +471,11 @@ void SCSIBR::FS_Attribute(vector& buf) void SCSIBR::FS_Files(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); i += sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -512,11 +512,11 @@ void SCSIBR::FS_Files(vector& buf) void SCSIBR::FS_NFiles(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); i += sizeof(uint32_t); auto files = (Human68k::files_t*)&(buf.data()[i]); @@ -550,11 +550,11 @@ void SCSIBR::FS_NFiles(vector& buf) void SCSIBR::FS_Create(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); i += sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -564,11 +564,11 @@ void SCSIBR::FS_Create(vector& buf) i += sizeof(Human68k::fcb_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nAttribute = ntohl(*dp); + const uint32_t nAttribute = ntohl(*dp); i += sizeof(uint32_t); auto bp = (int*)&(buf.data()[i]); - uint32_t bForce = ntohl(*bp); + const uint32_t bForce = ntohl(*bp); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -599,11 +599,11 @@ void SCSIBR::FS_Create(vector& buf) void SCSIBR::FS_Open(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); i += sizeof(uint32_t); const auto pNamests = (Human68k::namests_t*)&(buf.data()[i]); @@ -640,11 +640,11 @@ void SCSIBR::FS_Open(vector& buf) void SCSIBR::FS_Close(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); i += sizeof(uint32_t); auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); @@ -678,14 +678,14 @@ void SCSIBR::FS_Close(vector& buf) void SCSIBR::FS_Read(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); int i = sizeof(uint32_t); auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nSize = ntohl(*dp); + const uint32_t nSize = ntohl(*dp); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -718,14 +718,14 @@ void SCSIBR::FS_Read(vector& buf) void SCSIBR::FS_Write(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); int i = sizeof(uint32_t); auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nSize = ntohl(*dp); + const uint32_t nSize = ntohl(*dp); pFcb->fileptr = ntohl(pFcb->fileptr); pFcb->mode = ntohs(pFcb->mode); @@ -756,14 +756,14 @@ void SCSIBR::FS_Write(vector& buf) void SCSIBR::FS_Seek(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); int i = sizeof(uint32_t); auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); i += sizeof(Human68k::fcb_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nMode = ntohl(*dp); + const uint32_t nMode = ntohl(*dp); i += sizeof(uint32_t); auto ip = (const int*)&(buf.data()[i]); @@ -798,11 +798,11 @@ void SCSIBR::FS_Seek(vector& buf) void SCSIBR::FS_TimeStamp(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nKey = ntohl(*dp); + const uint32_t nKey = ntohl(*dp); i += sizeof(uint32_t); auto pFcb = (Human68k::fcb_t*)&(buf.data()[i]); @@ -840,7 +840,7 @@ void SCSIBR::FS_TimeStamp(vector& buf) void SCSIBR::FS_GetCapacity(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); Human68k::capacity_t cap; fsresult = fs.GetCapacity(nUnit, &cap); @@ -862,8 +862,8 @@ void SCSIBR::FS_GetCapacity(vector& buf) void SCSIBR::FS_CtrlDrive(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); - int i = sizeof(uint32_t); + const uint32_t nUnit = ntohl(*dp); + const int i = sizeof(uint32_t); auto pCtrlDrive = (Human68k::ctrldrive_t*)&(buf.data()[i]); @@ -881,7 +881,7 @@ void SCSIBR::FS_CtrlDrive(vector& buf) void SCSIBR::FS_GetDPB(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); Human68k::dpb_t dpb; fsresult = fs.GetDPB(nUnit, &dpb); @@ -905,11 +905,11 @@ void SCSIBR::FS_GetDPB(vector& buf) void SCSIBR::FS_DiskRead(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nSector = ntohl(*dp); + const uint32_t nSector = ntohl(*dp); i += sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); @@ -927,7 +927,7 @@ void SCSIBR::FS_DiskRead(vector& buf) void SCSIBR::FS_DiskWrite(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); fsresult = fs.DiskWrite(nUnit); } @@ -940,18 +940,18 @@ void SCSIBR::FS_DiskWrite(vector& buf) void SCSIBR::FS_Ioctrl(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); int i = sizeof(uint32_t); dp = (uint32_t*)&(buf.data()[i]); - uint32_t nFunction = ntohl(*dp); + const uint32_t nFunction = ntohl(*dp); i += sizeof(uint32_t); auto pIoctrl = (Human68k::ioctrl_t*)&(buf.data()[i]); switch (nFunction) { case 2: - case (DWORD)-2: + case (uint32_t)-2: pIoctrl->param = htonl(pIoctrl->param); break; default: @@ -965,7 +965,7 @@ void SCSIBR::FS_Ioctrl(vector& buf) pIoctrl->media = htons(pIoctrl->media); break; case 1: - case (DWORD)-3: + case (uint32_t)-3: pIoctrl->param = htonl(pIoctrl->param); break; default: @@ -986,7 +986,7 @@ void SCSIBR::FS_Ioctrl(vector& buf) void SCSIBR::FS_Flush(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); fsresult = fs.Flush(nUnit); } @@ -999,7 +999,7 @@ void SCSIBR::FS_Flush(vector& buf) void SCSIBR::FS_CheckMedia(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); fsresult = fs.CheckMedia(nUnit); } @@ -1012,7 +1012,7 @@ void SCSIBR::FS_CheckMedia(vector& buf) void SCSIBR::FS_Lock(vector& buf) { auto dp = (uint32_t*)buf.data(); - uint32_t nUnit = ntohl(*dp); + const uint32_t nUnit = ntohl(*dp); fsresult = fs.Lock(nUnit); } diff --git a/src/raspberrypi/devices/scsi_host_bridge.h b/src/raspberrypi/devices/scsi_host_bridge.h index 53878b60..9505acb1 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.h +++ b/src/raspberrypi/devices/scsi_host_bridge.h @@ -26,7 +26,7 @@ using namespace std; -class SCSIBR final : public Disk +class SCSIBR : public Disk { static constexpr const array bcast_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -99,9 +99,9 @@ private: void FS_Lock(vector&); // $58 - get exclusive control CFileSys fs; // File system accessor - DWORD fsresult = 0; // File system access result code + uint32_t fsresult = 0; // File system access result code array fsout; // File system access result buffer - DWORD fsoutlen = 0; // File system access result buffer size + uint32_t fsoutlen = 0; // File system access result buffer size array fsopt; // File system access buffer - DWORD fsoptlen = 0; // File system access buffer size + uint32_t fsoptlen = 0; // File system access buffer size }; diff --git a/src/raspberrypi/devices/scsi_printer.cpp b/src/raspberrypi/devices/scsi_printer.cpp index a4fe1823..8356a2d4 100644 --- a/src/raspberrypi/devices/scsi_printer.cpp +++ b/src/raspberrypi/devices/scsi_printer.cpp @@ -145,7 +145,7 @@ void SCSIPrinter::Print() { CheckReservation(); - uint32_t length = GetInt24(ctrl->cmd, 2); + const uint32_t length = GetInt24(ctrl->cmd, 2); LOGTRACE("Receiving %d byte(s) to be printed", length) @@ -153,7 +153,7 @@ void SCSIPrinter::Print() LOGERROR("%s", ("Transfer buffer overflow: Buffer size is " + to_string(controller->GetBuffer().size()) + " bytes, " + to_string(length) + " bytes expected").c_str()) - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } ctrl->length = length; @@ -167,11 +167,11 @@ void SCSIPrinter::SynchronizeBuffer() CheckReservation(); if (fd == -1) { - throw scsi_error_exception(); + throw scsi_exception(); } // Make the file readable for the lp user - fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); //NOSONAR Granting permissions to "others" is required here struct stat st; fstat(fd, &st); @@ -180,7 +180,7 @@ void SCSIPrinter::SynchronizeBuffer() fd = -1; string cmd = GetParam("cmd"); - size_t file_position = cmd.find("%f"); + const size_t file_position = cmd.find("%f"); assert(file_position != string::npos); cmd.replace(file_position, 2, filename); cmd = "sudo -u lp " + cmd; @@ -194,7 +194,7 @@ void SCSIPrinter::SynchronizeBuffer() unlink(filename); - throw scsi_error_exception(); + throw scsi_exception(); } unlink(filename); @@ -217,7 +217,7 @@ void SCSIPrinter::StopPrint() bool SCSIPrinter::WriteByteSequence(vector& buf, uint32_t length) { if (fd == -1) { - strcpy(filename, TMP_FILE_PATTERN); + strcpy(filename, TMP_FILE_PATTERN); //NOSONAR Using strcpy is safe here fd = mkstemp(filename); if (fd == -1) { LOGERROR("Can't create printer output file '%s': %s", filename, strerror(errno)) @@ -229,7 +229,7 @@ bool SCSIPrinter::WriteByteSequence(vector& buf, uint32_t length) LOGTRACE("Appending %d byte(s) to printer output file '%s'", length, filename) - auto num_written = (uint32_t)write(fd, buf.data(), length); + const auto num_written = (uint32_t)write(fd, buf.data(), length); return num_written == length; } @@ -248,7 +248,7 @@ void SCSIPrinter::CheckReservation() LOGTRACE("Unknown initiator tries to access reserved device ID %d, LUN %d", GetId(), GetLun()) } - throw scsi_error_exception(sense_key::ABORTED_COMMAND, asc::NO_ADDITIONAL_SENSE_INFORMATION, + throw scsi_exception(sense_key::ABORTED_COMMAND, asc::NO_ADDITIONAL_SENSE_INFORMATION, status::RESERVATION_CONFLICT); } diff --git a/src/raspberrypi/devices/scsi_printer.h b/src/raspberrypi/devices/scsi_printer.h index d07e65e2..e24d09e5 100644 --- a/src/raspberrypi/devices/scsi_printer.h +++ b/src/raspberrypi/devices/scsi_printer.h @@ -15,9 +15,9 @@ #include #include -class SCSIPrinter final : public PrimaryDevice, public ScsiPrinterCommands //NOSONAR Custom destructor cannot be removed +class SCSIPrinter : public PrimaryDevice, ScsiPrinterCommands //NOSONAR Custom destructor cannot be removed { - static constexpr const char *TMP_FILE_PATTERN = "/tmp/rascsi_sclp-XXXXXX"; + static constexpr const char *TMP_FILE_PATTERN = "/tmp/rascsi_sclp-XXXXXX"; //NOSONAR Using /tmp is safe static const int TMP_FILENAME_LENGTH = string_view(TMP_FILE_PATTERN).size(); static const int NOT_RESERVED = -2; diff --git a/src/raspberrypi/devices/scsicd.cpp b/src/raspberrypi/devices/scsicd.cpp index 7d6cc5f7..c922eb9f 100644 --- a/src/raspberrypi/devices/scsicd.cpp +++ b/src/raspberrypi/devices/scsicd.cpp @@ -90,7 +90,7 @@ void SCSICD::Open(const Filepath& path) assert(GetBlockCount() > 0); super::Open(path); - FileSupport::SetPath(path); + SetPath(path); SetUpCache(path, 0, rawfile); @@ -100,7 +100,7 @@ void SCSICD::Open(const Filepath& path) } } -void SCSICD::OpenCue(const Filepath& /*path*/) const +void SCSICD::OpenCue(const Filepath&) const { throw io_exception("Opening CUE CD-ROM files is not supported"); } @@ -114,7 +114,7 @@ void SCSICD::OpenIso(const Filepath& path) } // Get file size - off_t size = fio.GetFileSize(); + const off_t size = fio.GetFileSize(); if (size < 0x800) { fio.Close(); throw io_exception("ISO CD-ROM file size must be at least 2048 bytes"); @@ -160,10 +160,10 @@ void SCSICD::OpenIso(const Filepath& path) } // Set the number of blocks - SetBlockCount((DWORD)(size / 0x930)); + SetBlockCount((uint32_t)(size / 0x930)); } else { // Set the number of blocks - SetBlockCount((DWORD)(size >> GetSectorSizeShiftCount())); + SetBlockCount((uint32_t)(size >> GetSectorSizeShiftCount())); } // Create only one data track @@ -197,7 +197,7 @@ void SCSICD::OpenPhysical(const Filepath& path) size = (size / 512) * 512; // Set the number of blocks - SetBlockCount((DWORD)(size >> GetSectorSizeShiftCount())); + SetBlockCount((uint32_t)(size >> GetSectorSizeShiftCount())); // Create only one data track assert(!tracks.size()); @@ -275,11 +275,11 @@ int SCSICD::Read(const vector& cdb, vector& buf, uint64_t block) CheckReady(); // Search for the track - int index = SearchTrack((int)block); + const int index = SearchTrack((int)block); // If invalid, out of range if (index < 0) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); } assert(tracks[index]); @@ -315,17 +315,17 @@ int SCSICD::ReadTocInternal(const vector& cdb, vector& buf) assert(tracks[0]); // Get allocation length, clear buffer - int length = GetInt16(cdb, 7); + const int length = GetInt16(cdb, 7); fill_n(buf.data(), length, 0); // Get MSF Flag - bool msf = cdb[1] & 0x02; + const bool msf = cdb[1] & 0x02; // Get and check the last track number - int last = tracks[tracks.size() - 1]->GetTrackNo(); + const int last = tracks[tracks.size() - 1]->GetTrackNo(); // Except for AA if (cdb[6] > last && cdb[6] != 0xaa) { - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } // Check start index @@ -358,12 +358,12 @@ int SCSICD::ReadTocInternal(const vector& cdb, vector& buf) } // Otherwise, error - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } } // Number of track descriptors returned this time (number of loops) - int loop = last - tracks[index]->GetTrackNo() + 1; + const int loop = last - tracks[index]->GetTrackNo() + 1; assert(loop >= 1); // Create header @@ -407,11 +407,11 @@ void SCSICD::GetEventStatusNotification() { if (!(ctrl->cmd[1] & 0x01)) { // Asynchronous notification is optional and not supported by rascsi - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } LOGTRACE("Received request for event polling, which is currently not supported") - throw scsi_error_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } //--------------------------------------------------------------------------- @@ -424,7 +424,7 @@ void SCSICD::LBAtoMSF(uint32_t lba, BYTE *msf) const // 75 and 75*60 get the remainder uint32_t m = lba / (75 * 60); uint32_t s = lba % (75 * 60); - uint32_t f = s % 75; + const uint32_t f = s % 75; s /= 75; // The base point is M=0, S=2, F=0 @@ -459,7 +459,7 @@ void SCSICD::ClearTrack() // * Returns -1 if not found // //--------------------------------------------------------------------------- -int SCSICD::SearchTrack(DWORD lba) const +int SCSICD::SearchTrack(uint32_t lba) const { // Track loop for (size_t i = 0; i < tracks.size(); i++) { diff --git a/src/raspberrypi/devices/scsicd.h b/src/raspberrypi/devices/scsicd.h index c3154f1e..aec65323 100644 --- a/src/raspberrypi/devices/scsicd.h +++ b/src/raspberrypi/devices/scsicd.h @@ -10,20 +10,16 @@ // Licensed under the BSD 3-Clause License. // See LICENSE file in the project root folder. // -// [ SCSI CD-ROM ] -// //--------------------------------------------------------------------------- #pragma once -#include "disk.h" #include "filepath.h" #include "cd_track.h" -#include "file_support.h" +#include "disk.h" #include "interfaces/scsi_mmc_commands.h" -#include "interfaces/scsi_primary_commands.h" -class SCSICD : public Disk, public ScsiMmcCommands, public FileSupport +class SCSICD : public Disk, private ScsiMmcCommands { public: @@ -68,7 +64,7 @@ private: // Track management void ClearTrack(); // Clear the track - int SearchTrack(DWORD lba) const; // Track search + int SearchTrack(uint32_t lba) const; // Track search vector> tracks; // Track opbject references int dataindex = -1; // Current data track int audioindex = -1; // Current audio track diff --git a/src/raspberrypi/devices/scsihd.cpp b/src/raspberrypi/devices/scsihd.cpp index 489d6df6..bc71c966 100644 --- a/src/raspberrypi/devices/scsihd.cpp +++ b/src/raspberrypi/devices/scsihd.cpp @@ -40,13 +40,13 @@ void SCSIHD::FinalizeSetup(const Filepath &path, off_t size, off_t image_offset) uint64_t capacity = GetBlockCount() * GetSectorSizeInBytes(); string unit; // 10 GiB and more - if (capacity >= 1099511627776) { - capacity /= 1099511627776; + if (capacity >= 1'099'511'627'776) { + capacity /= 1'099'511'627'776; unit = "GiB"; } // 1 MiB and more - else if (capacity >= 1048576) { - capacity /= 1048576; + else if (capacity >= 1'048'576) { + capacity /= 1'048'576; unit = "MiB"; } else { @@ -62,8 +62,8 @@ void SCSIHD::FinalizeSetup(const Filepath &path, off_t size, off_t image_offset) SetProtectable(true); SetProtected(false); - Disk::Open(path); - FileSupport::SetPath(path); + super::Open(path); + SetPath(path); SetUpCache(path, image_offset); } @@ -84,7 +84,7 @@ void SCSIHD::Open(const Filepath& path) // Sector size (default 512 bytes) and number of blocks SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512); - SetBlockCount((DWORD)(size >> GetSectorSizeShiftCount())); + SetBlockCount((uint32_t)(size >> GetSectorSizeShiftCount())); // Effective size must be a multiple of the sector size size = (size / GetSectorSizeInBytes()) * GetSectorSizeInBytes(); diff --git a/src/raspberrypi/devices/scsihd.h b/src/raspberrypi/devices/scsihd.h index 2536a95a..9cae8d87 100644 --- a/src/raspberrypi/devices/scsihd.h +++ b/src/raspberrypi/devices/scsihd.h @@ -17,10 +17,9 @@ #pragma once #include "disk.h" -#include "file_support.h" #include "filepath.h" -class SCSIHD : public Disk, public FileSupport +class SCSIHD : public Disk { static constexpr const char *DEFAULT_PRODUCT = "SCSI HD"; @@ -42,5 +41,7 @@ public: private: + using super = Disk; + scsi_defs::scsi_level scsi_level; }; diff --git a/src/raspberrypi/devices/scsihd_nec.cpp b/src/raspberrypi/devices/scsihd_nec.cpp index d81205e1..1a2ddb95 100644 --- a/src/raspberrypi/devices/scsihd_nec.cpp +++ b/src/raspberrypi/devices/scsihd_nec.cpp @@ -7,7 +7,7 @@ // 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 NEC "Genuine" Hard Disk] diff --git a/src/raspberrypi/devices/scsimo.cpp b/src/raspberrypi/devices/scsimo.cpp index d22304c5..5626fd1b 100644 --- a/src/raspberrypi/devices/scsimo.cpp +++ b/src/raspberrypi/devices/scsimo.cpp @@ -59,8 +59,8 @@ void SCSIMO::Open(const Filepath& path) SetProtectable(true); SetProtected(false); - Disk::Open(path); - FileSupport::SetPath(path); + super::Open(path); + SetPath(path); SetUpCache(path, 0); diff --git a/src/raspberrypi/devices/scsimo.h b/src/raspberrypi/devices/scsimo.h index a03a40e5..02237665 100644 --- a/src/raspberrypi/devices/scsimo.h +++ b/src/raspberrypi/devices/scsimo.h @@ -15,12 +15,11 @@ #pragma once #include "disk.h" -#include "file_support.h" #include "filepath.h" using Geometry = pair; -class SCSIMO : public Disk, public FileSupport +class SCSIMO : public Disk { public: @@ -40,6 +39,8 @@ protected: private: + using super = Disk; + void AddOptionPage(map>&, bool) const; bool SetGeometryForCapacity(uint64_t); diff --git a/src/raspberrypi/fileio.cpp b/src/raspberrypi/fileio.cpp index 821f3316..2061e6c1 100644 --- a/src/raspberrypi/fileio.cpp +++ b/src/raspberrypi/fileio.cpp @@ -11,6 +11,7 @@ #include "fileio.h" #include #include +#include Fileio::~Fileio() { @@ -30,7 +31,7 @@ bool Fileio::Open(const char *fname, OpenMode mode, bool directIO) } // Default mode - mode_t omode = directIO ? O_DIRECT : 0; + const mode_t omode = directIO ? O_DIRECT : 0; switch (mode) { case OpenMode::ReadOnly: @@ -111,10 +112,10 @@ off_t Fileio::GetFileSize() const assert(handle >= 0); // Get file position in 64bit - off_t cur = lseek(handle, 0, SEEK_CUR); + const off_t cur = lseek(handle, 0, SEEK_CUR); // Get file size in64bitで - off_t end = lseek(handle, 0, SEEK_END); + const off_t end = lseek(handle, 0, SEEK_END); // Return to start position Seek(cur); diff --git a/src/raspberrypi/fileio.h b/src/raspberrypi/fileio.h index cae25dec..7d6c7785 100644 --- a/src/raspberrypi/fileio.h +++ b/src/raspberrypi/fileio.h @@ -11,7 +11,7 @@ #pragma once #include "filepath.h" -#include +#include class Fileio { diff --git a/src/raspberrypi/filepath.cpp b/src/raspberrypi/filepath.cpp index 626c2897..50e14d38 100644 --- a/src/raspberrypi/filepath.cpp +++ b/src/raspberrypi/filepath.cpp @@ -8,11 +8,11 @@ // //--------------------------------------------------------------------------- -#include "os.h" #include "filepath.h" -#include "config.h" -#include "fileio.h" #include +#include +#include +#include Filepath& Filepath::operator=(const Filepath& path) { @@ -55,7 +55,7 @@ void Filepath::Split() char *pDir = strdup(m_szPath); const char *pDirName = dirname(pDir); char *pBase = strdup(m_szPath); - char *pBaseName = basename(pBase); + const char *pBaseName = basename(pBase); const char *pExtName = strrchr(pBaseName, '.'); // Transmit diff --git a/src/raspberrypi/monitor/data_sample.cpp b/src/raspberrypi/monitor/data_sample.cpp index dedf1a40..f6448cb5 100644 --- a/src/raspberrypi/monitor/data_sample.cpp +++ b/src/raspberrypi/monitor/data_sample.cpp @@ -32,7 +32,7 @@ BUS::phase_t GetPhase(const data_capture *sample) } // Get target phase from bus signal line - DWORD mci = GetMsg(sample) ? 0x04 : 0x00; + uint32_t mci = GetMsg(sample) ? 0x04 : 0x00; mci |= GetCd(sample) ? 0x02 : 0x00; mci |= GetIo(sample) ? 0x01 : 0x00; return BUS::GetPhase(mci); diff --git a/src/raspberrypi/monitor/data_sample.h b/src/raspberrypi/monitor/data_sample.h index 72efc2bd..5631ff48 100644 --- a/src/raspberrypi/monitor/data_sample.h +++ b/src/raspberrypi/monitor/data_sample.h @@ -16,7 +16,7 @@ using data_capture_t = struct data_capture { - DWORD data; + uint32_t data; uint64_t timestamp; }; @@ -34,7 +34,7 @@ inline bool GetReq(const data_capture *sample) { return BUS::GetPinRaw(sample->d inline bool GetDp(const data_capture *sample) { return BUS::GetPinRaw(sample->data, PIN_DP); } inline BYTE GetData(const data_capture *sample) { - DWORD data = sample->data; + uint32_t data = sample->data; return (BYTE)((data >> (PIN_DT0 - 0)) & (1 << 0)) | ((data >> (PIN_DT1 - 1)) & (1 << 1)) | ((data >> (PIN_DT2 - 2)) & (1 << 2)) | diff --git a/src/raspberrypi/monitor/sm_html_report.cpp b/src/raspberrypi/monitor/sm_html_report.cpp index 4ad5b667..404e5961 100644 --- a/src/raspberrypi/monitor/sm_html_report.cpp +++ b/src/raspberrypi/monitor/sm_html_report.cpp @@ -8,7 +8,6 @@ // //--------------------------------------------------------------------------- -#include #include #include #include "os.h" @@ -98,12 +97,12 @@ for (i = 0; i < coll.length; i++) { )"; -static void print_html_data(ofstream& html_fp, const data_capture *data_capture_array, DWORD capture_count) +static void print_html_data(ofstream& html_fp, const data_capture *data_capture_array, uint32_t capture_count) { const data_capture *data; bool prev_data_valid = false; bool curr_data_valid; - DWORD selected_id = 0; + uint32_t selected_id = 0; BUS::phase_t prev_phase = BUS::phase_t::busfree; bool close_row = false; int data_space_count = 0; @@ -112,34 +111,26 @@ static void print_html_data(ofstream& html_fp, const data_capture *data_capture_ html_fp << "" << endl; - for (DWORD idx = 0; idx < capture_count; idx++) - { + for (uint32_t idx = 0; idx < capture_count; idx++) { data = &data_capture_array[idx]; curr_data_valid = GetAck(data) && GetReq(data); BUS::phase_t phase = GetPhase(data); - if (phase == BUS::phase_t::selection && !GetBsy(data)) - { + if (phase == BUS::phase_t::selection && !GetBsy(data)) { selected_id = GetData(data); } - if (prev_phase != phase) - { - if (close_row) - { - if (collapsible_div_active) - { + if (prev_phase != phase) { + if (close_row) { + if (collapsible_div_active) { html_fp << ""; } - else if (button_active) - { + else if (button_active) { html_fp << ""; } html_fp << ""; - if (data_space_count < 1) - { + if (data_space_count < 1) { html_fp << ""; } - else - { + else { html_fp << ""; } html_fp << "" << endl; @@ -152,33 +143,27 @@ static void print_html_data(ofstream& html_fp, const data_capture *data_capture_ html_fp << ""; html_fp << "
--wc: " << std::dec << "(0x" << std::hex << data_space_count << ")
" << std::hex << selected_id << ""; } - if (curr_data_valid && !prev_data_valid) - { - if (data_space_count == 0) - { + if (curr_data_valid && !prev_data_valid) { + if (data_space_count == 0) { button_active = true; html_fp << "
" << endl; collapsible_div_active = true; button_active = false; } - if (((data_space_count % 16) == 0) && (data_space_count > 17)) - { + if (((data_space_count % 16) == 0) && (data_space_count > 17)) { html_fp << "
" << endl; } } @@ -187,9 +172,9 @@ static void print_html_data(ofstream& html_fp, const data_capture *data_capture_ } } -void scsimon_generate_html(const char *filename, const data_capture *data_capture_array, DWORD capture_count) +void scsimon_generate_html(const char *filename, const data_capture *data_capture_array, uint32_t capture_count) { - LOGINFO("Creating HTML report file (%s)", filename); + LOGINFO("Creating HTML report file (%s)", filename) ofstream html_ofstream; diff --git a/src/raspberrypi/monitor/sm_json_report.cpp b/src/raspberrypi/monitor/sm_json_report.cpp index 86bf72d0..4525b87a 100644 --- a/src/raspberrypi/monitor/sm_json_report.cpp +++ b/src/raspberrypi/monitor/sm_json_report.cpp @@ -19,45 +19,39 @@ using namespace std; const char timestamp_label[] = "\"timestamp\":\"0x"; const char data_label[] = "\"data\":\"0x"; -DWORD scsimon_read_json(const char *json_filename, data_capture *data_capture_array, DWORD max_sz) +uint32_t scsimon_read_json(const char *json_filename, data_capture *data_capture_array, uint32_t max_sz) { char str_buf[1024]; FILE *fp = fopen(json_filename, "r"); - DWORD sample_count = 0; + uint32_t sample_count = 0; - while (fgets(str_buf, sizeof(str_buf), fp)) - { + while (fgets(str_buf, sizeof(str_buf), fp)) { char timestamp[1024]; char data[1024]; uint64_t timestamp_uint; uint32_t data_uint; char *ptr; - const char *timestamp_str; - const char *data_str; - timestamp_str = strstr(str_buf, timestamp_label); + const char *timestamp_str = strstr(str_buf, timestamp_label); if (!timestamp_str) continue; strncpy(timestamp, ×tamp_str[strlen(timestamp_label)], 16); timestamp[16] = '\0'; timestamp_uint = strtoull(timestamp, &ptr, 16); - data_str = strstr(str_buf, data_label); + const char *data_str = strstr(str_buf, data_label); if (!data_str) continue; strncpy(data, &data_str[strlen(data_label)], 8); data[8] = '\0'; data_uint = strtoul(data, &ptr, 16); - // printf("Time: %016llX Data: %08X\n", timestamp_uint, data_uint); - data_capture_array[sample_count].timestamp = timestamp_uint; data_capture_array[sample_count].data = data_uint; sample_count++; - if (sample_count >= max_sz) - { - LOGWARN("File exceeds maximum buffer size. Some data may be missing."); - LOGWARN("Try re-running the tool with a larger buffer size"); + if (sample_count >= max_sz) { + LOGWARN("File exceeds maximum buffer size. Some data may be missing.") + LOGWARN("Try re-running the tool with a larger buffer size") break; } } @@ -74,17 +68,16 @@ DWORD scsimon_read_json(const char *json_filename, data_capture *data_capture_ar // Generate JSON Output File // //--------------------------------------------------------------------------- -void scsimon_generate_json(const char *filename, const data_capture *data_capture_array, DWORD capture_count) +void scsimon_generate_json(const char *filename, const data_capture *data_capture_array, uint32_t capture_count) { - LOGTRACE("Creating JSON file (%s)", filename); + LOGTRACE("Creating JSON file (%s)", filename) ofstream json_ofstream; json_ofstream.open(filename, ios::out); json_ofstream << "[" << endl; - DWORD i = 0; - while (i < capture_count) - { + uint32_t i = 0; + while (i < capture_count) { json_ofstream << fmt::format("{{\"id\": \"{0:d}\", \"timestamp\":\"{1:#016x}\", \"data\":\"{2:#08x}\"}}", i, data_capture_array[i].timestamp, data_capture_array[i].data); if (i != (capture_count - 1)) diff --git a/src/raspberrypi/monitor/sm_reports.h b/src/raspberrypi/monitor/sm_reports.h index 4309cc0a..fd5dd71a 100644 --- a/src/raspberrypi/monitor/sm_reports.h +++ b/src/raspberrypi/monitor/sm_reports.h @@ -11,8 +11,8 @@ #include "data_sample.h" -DWORD scsimon_read_json(const char *json_filename, data_capture *data_capture_array, DWORD max_sz); +uint32_t scsimon_read_json(const char *json_filename, data_capture *data_capture_array, uint32_t max_sz); -void scsimon_generate_html(const char *filename, const data_capture *data_capture_array, DWORD capture_count); -void scsimon_generate_json(const char *filename, const data_capture *data_capture_array, DWORD capture_count); -void scsimon_generate_value_change_dump(const char *filename, const data_capture *data_capture_array, DWORD capture_count); +void scsimon_generate_html(const char *filename, const data_capture *data_capture_array, uint32_t capture_count); +void scsimon_generate_json(const char *filename, const data_capture *data_capture_array, uint32_t capture_count); +void scsimon_generate_value_change_dump(const char *filename, const data_capture *data_capture_array, uint32_t capture_count); diff --git a/src/raspberrypi/monitor/sm_vcd_report.cpp b/src/raspberrypi/monitor/sm_vcd_report.cpp index 755829c3..21bba1fe 100644 --- a/src/raspberrypi/monitor/sm_vcd_report.cpp +++ b/src/raspberrypi/monitor/sm_vcd_report.cpp @@ -54,14 +54,14 @@ static BYTE prev_value[32] = {0xFF}; extern double ns_per_loop; -static BYTE get_pin_value(DWORD data, int pin) +static BYTE get_pin_value(uint32_t data, int pin) { return (data >> pin) & 1; } -static BYTE get_data_field(DWORD data) +static BYTE get_data_field(uint32_t data) { - DWORD data_out = + const uint32_t data_out = ((data >> (PIN_DT0 - 0)) & (1 << 7)) | ((data >> (PIN_DT1 - 1)) & (1 << 6)) | ((data >> (PIN_DT2 - 2)) & (1 << 5)) | @@ -74,31 +74,28 @@ static BYTE get_data_field(DWORD data) return (BYTE)data_out; } -static void vcd_output_if_changed_phase(ofstream& fp, DWORD data, int pin, char symbol) +static void vcd_output_if_changed_phase(ofstream& fp, uint32_t data, int pin, char symbol) { - BUS::phase_t new_value = GPIOBUS::GetPhaseRaw(data); - if (prev_value[pin] != (int)new_value) - { + const BUS::phase_t new_value = GPIOBUS::GetPhaseRaw(data); + if (prev_value[pin] != (int)new_value) { prev_value[pin] = (int)new_value; fp << "s" << GPIOBUS::GetPhaseStrRaw(new_value) << " " << symbol << endl; } } -static void vcd_output_if_changed_bool(ofstream& fp, DWORD data, int pin, char symbol) +static void vcd_output_if_changed_bool(ofstream& fp, uint32_t data, int pin, char symbol) { - BYTE new_value = get_pin_value(data, pin); - if (prev_value[pin] != new_value) - { + const BYTE new_value = get_pin_value(data, pin); + if (prev_value[pin] != new_value) { prev_value[pin] = new_value; fp << new_value << symbol << endl; } } -static void vcd_output_if_changed_byte(ofstream& fp, DWORD data, int pin, char symbol) +static void vcd_output_if_changed_byte(ofstream& fp, uint32_t data, int pin, char symbol) { - BYTE new_value = get_data_field(data); - if (prev_value[pin] != new_value) - { + const BYTE new_value = get_data_field(data); + if (prev_value[pin] != new_value) { prev_value[pin] = new_value; fp << "b" << fmt::format("{0:b}", get_pin_value(data, PIN_DT7)) @@ -113,9 +110,9 @@ static void vcd_output_if_changed_byte(ofstream& fp, DWORD data, int pin, char s } } -void scsimon_generate_value_change_dump(const char *filename, const data_capture *data_capture_array, DWORD capture_count) +void scsimon_generate_value_change_dump(const char *filename, const data_capture *data_capture_array, uint32_t capture_count) { - LOGTRACE("Creating Value Change Dump file (%s)", filename); + LOGTRACE("Creating Value Change Dump file (%s)", filename) ofstream vcd_ofstream; vcd_ofstream.open(filename, ios::out); @@ -126,7 +123,7 @@ void scsimon_generate_value_change_dump(const char *filename, const data_capture char timestamp[256]; strftime(timestamp, sizeof(timestamp), "%d-%m-%Y %H-%M-%S", timeinfo); - vcd_ofstream + vcd_ofstream << "$date" << endl << timestamp << endl << "$end" << endl @@ -167,9 +164,8 @@ void scsimon_generate_value_change_dump(const char *filename, const data_capture << "b00000000 " << SYMBOL_PIN_DAT << endl << "$end" << endl; - DWORD i = 0; - while (i < capture_count) - { + uint32_t i = 0; + while (i < capture_count) { vcd_ofstream << "#" << (uint64_t)(data_capture_array[i].timestamp * ns_per_loop) << endl; vcd_output_if_changed_bool(vcd_ofstream, data_capture_array[i].data, PIN_BSY, SYMBOL_PIN_BSY); vcd_output_if_changed_bool(vcd_ofstream, data_capture_array[i].data, PIN_SEL, SYMBOL_PIN_SEL); diff --git a/src/raspberrypi/os.h b/src/raspberrypi/os.h index c6fac869..fe3f54c8 100644 --- a/src/raspberrypi/os.h +++ b/src/raspberrypi/os.h @@ -7,17 +7,11 @@ // Copyright (C) 2016-2020 GIMONS // Copyright (C) 2020 akuker // -// [ OS related definitions ] -// //--------------------------------------------------------------------------- #pragma once -#include -#include -#include #include using BYTE = unsigned char; -using WORD = uint16_t; using DWORD = uint32_t; diff --git a/src/raspberrypi/protobuf_serializer.cpp b/src/raspberrypi/protobuf_serializer.cpp index 61f4fa6f..2f4bed4a 100644 --- a/src/raspberrypi/protobuf_serializer.cpp +++ b/src/raspberrypi/protobuf_serializer.cpp @@ -11,7 +11,6 @@ #include "protobuf_serializer.h" #include "rascsi_exceptions.h" #include -#include using namespace std; using namespace rascsi_interface; @@ -45,10 +44,11 @@ void ProtobufSerializer::DeserializeMessage(int fd, google::protobuf::Message& m // Read the header with the size of the protobuf data vector header_buf(4); if (ReadBytes(fd, header_buf) < header_buf.size()) { - return; + throw io_exception("Invalid protobuf message header"); } - size_t size = ((int)header_buf[3] << 24) + ((int)header_buf[2] << 16) + ((int)header_buf[1] << 8) + (int)header_buf[0]; + const size_t size = ((int)header_buf[3] << 24) + ((int)header_buf[2] << 16) + + ((int)header_buf[1] << 8) + (int)header_buf[0]; if (size <= 0) { throw io_exception("Invalid protobuf message header"); } @@ -68,7 +68,7 @@ size_t ProtobufSerializer::ReadBytes(int fd, vector& buf) const { size_t offset = 0; while (offset < buf.size()) { - ssize_t len = read(fd, &buf[offset], buf.size() - offset); + const ssize_t len = read(fd, &buf.data()[offset], buf.size() - offset); if (len <= 0) { return len; } diff --git a/src/raspberrypi/protobuf_util.cpp b/src/raspberrypi/protobuf_util.cpp new file mode 100644 index 00000000..9b8545e2 --- /dev/null +++ b/src/raspberrypi/protobuf_util.cpp @@ -0,0 +1,103 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2021-2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "log.h" +#include "rascsi_interface.pb.h" +#include "protobuf_serializer.h" +#include "protobuf_util.h" +#include + +using namespace std; +using namespace rascsi_interface; + +#define FPRT(fp, ...) fprintf(fp, __VA_ARGS__ ) + +static const char COMPONENT_SEPARATOR = ':'; +static const char KEY_VALUE_SEPARATOR = '='; + +void protobuf_util::ParseParameters(PbDeviceDefinition& device, const string& params) +{ + if (params.empty()) { + return; + } + + // Old style parameters, for backwards compatibility only. + // Only one of these parameters will be used by rascsi, depending on the device type. + 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()) { + const 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 protobuf_util::GetParam(const PbCommand& command, const string& key) +{ + const auto& it = command.params().find(key); + return it != command.params().end() ? it->second : ""; +} + +string protobuf_util::GetParam(const PbDeviceDefinition& device, const string& key) +{ + const auto& it = device.params().find(key); + return it != device.params().end() ? it->second : ""; +} + +void protobuf_util::AddParam(PbCommand& command, const string& key, string_view value) +{ + if (!key.empty() && !value.empty()) { + auto& map = *command.mutable_params(); + map[key] = value; + } +} + +void protobuf_util::AddParam(PbDevice& device, const string& key, string_view value) +{ + if (!key.empty() && !value.empty()) { + auto& map = *device.mutable_params(); + map[key] = value; + } +} + +void protobuf_util::AddParam(PbDeviceDefinition& device, const string& key, string_view value) +{ + if (!key.empty() && !value.empty()) { + auto& map = *device.mutable_params(); + map[key] = value; + } +} + +void protobuf_util::SetPatternParams(PbCommand& command, string_view patterns) +{ + string folder_pattern; + string file_pattern; + if (const size_t separator_pos = patterns.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { + folder_pattern = patterns.substr(0, separator_pos); + file_pattern = patterns.substr(separator_pos + 1); + } + else { + file_pattern = patterns; + } + + AddParam(command, "folder_pattern", folder_pattern); + AddParam(command, "file_pattern", file_pattern); +} diff --git a/src/raspberrypi/command_util.h b/src/raspberrypi/protobuf_util.h similarity index 85% rename from src/raspberrypi/command_util.h rename to src/raspberrypi/protobuf_util.h index 249d7cc0..4dafe484 100644 --- a/src/raspberrypi/command_util.h +++ b/src/raspberrypi/protobuf_util.h @@ -5,7 +5,7 @@ // // Copyright (C) 2021-2022 Uwe Seimet // -// Helper methods for serializing/deserializing protobuf messages +// Helper methods for setting up/evaluating protobuf messages // //--------------------------------------------------------------------------- @@ -18,7 +18,7 @@ using namespace std; using namespace rascsi_interface; -namespace command_util +namespace protobuf_util { void ParseParameters(PbDeviceDefinition&, const string&); string GetParam(const PbCommand&, const string&); @@ -26,4 +26,5 @@ namespace command_util void AddParam(PbCommand&, const string&, string_view); void AddParam(PbDevice&, const string&, string_view); void AddParam(PbDeviceDefinition&, const string&, string_view); + void SetPatternParams(PbCommand&, string_view); } diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 2717915d..116b431e 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -15,13 +15,13 @@ #include "controllers/controller_manager.h" #include "controllers/scsi_controller.h" #include "devices/device_factory.h" -#include "devices/file_support.h" +#include "devices/disk.h" #include "hal/gpiobus.h" #include "hal/systimer.h" +#include "rascsi_version.h" #include "rascsi_exceptions.h" #include "protobuf_serializer.h" -#include "command_util.h" -#include "rascsi_version.h" +#include "protobuf_util.h" #include "rascsi_interface.pb.h" #include "rascsi/rascsi_executor.h" #include "rascsi/rascsi_response.h" @@ -43,7 +43,7 @@ using namespace std; using namespace spdlog; using namespace rascsi_interface; using namespace ras_util; -using namespace command_util; +using namespace protobuf_util; //--------------------------------------------------------------------------- // @@ -61,7 +61,7 @@ static const char COMPONENT_SEPARATOR = ':'; static volatile bool active; // Processing flag RascsiService service; GPIOBUS bus; -string current_log_level; // Some versions of spdlog do not support get_log_level() +string current_log_level = "info"; // Some versions of spdlog do not support get_log_level() string access_token; DeviceFactory device_factory; ControllerManager controller_manager(bus); @@ -72,28 +72,23 @@ const ProtobufSerializer serializer; void Banner(int argc, char* argv[]) { - cout << "SCSI Target Emulator RaSCSI Reloaded version " << rascsi_get_version_string() - << " (" << __DATE__ << ' ' << __TIME__ << ')' << endl; - cout << "Powered by XM6 TypeG Technology / "; - cout << "Copyright (C) 2016-2020 GIMONS" << endl; - cout << "Copyright (C) 2020-2022 Contributors to the RaSCSI Reloaded project" << endl; - cout << "Connect type: " << CONNECT_DESC << endl; + cout << Banner("Reloaded"); + cout << "Connect type: " << CONNECT_DESC << '\n' << flush; if ((argc > 1 && strcmp(argv[1], "-h") == 0) || (argc > 1 && strcmp(argv[1], "--help") == 0)){ - cout << endl; - cout << "Usage: " << argv[0] << " [-idn[:m] FILE] ..." << endl << endl; - cout << " n is SCSI device ID (0-7)." << endl; - cout << " m is the optional logical unit (LUN) (0-31)." << endl; - cout << " FILE is a disk image file, \"daynaport\", \"bridge\", \"printer\" or \"services\"." << endl << endl; - cout << " Image type is detected based on file extension if no explicit type is specified." << endl; - cout << " hd1 : SCSI-1 HD image (Non-removable generic SCSI-1 HD image)" << endl; - cout << " hds : SCSI HD image (Non-removable generic SCSI HD image)" << endl; - cout << " hdr : SCSI HD image (Removable generic HD image)" << endl; - cout << " hdn : SCSI HD image (NEC GENUINE)" << endl; - cout << " hdi : SCSI HD image (Anex86 HD image)" << endl; - cout << " nhd : SCSI HD image (T98Next HD image)" << endl; - cout << " mos : SCSI MO image (MO image)" << endl; - cout << " iso : SCSI CD image (ISO 9660 image)" << endl; + cout << "\nUsage: " << argv[0] << " [-idn[:m] FILE] ...\n\n"; + cout << " n is SCSI device ID (0-7).\n"; + cout << " m is the optional logical unit (LUN) (0-31).\n"; + cout << " FILE is a disk image file, \"daynaport\", \"bridge\", \"printer\" or \"services\".\n\n"; + cout << " Image type is detected based on file extension if no explicit type is specified.\n"; + cout << " hd1 : SCSI-1 HD image (Non-removable generic SCSI-1 HD image)\n"; + cout << " hds : SCSI HD image (Non-removable generic SCSI HD image)\n"; + cout << " hdr : SCSI HD image (Removable generic HD image)\n"; + cout << " hdn : SCSI HD image (NEC GENUINE)\n"; + cout << " hdi : SCSI HD image (Anex86 HD image)\n"; + cout << " nhd : SCSI HD image (T98Next HD image)\n"; + cout << " mos : SCSI MO image (MO image)\n"; + cout << " iso : SCSI CD image (ISO 9660 image)\n" << flush; exit(EXIT_SUCCESS); } @@ -185,7 +180,7 @@ void TerminationHandler(int signum) bool ProcessId(const string& id_spec, int& id, int& unit) { - if (size_t separator_pos = id_spec.find(COMPONENT_SEPARATOR); separator_pos == string::npos) { + if (const size_t separator_pos = id_spec.find(COMPONENT_SEPARATOR); separator_pos == string::npos) { if (!GetAsInt(id_spec, id) || id < 0 || id >= 8) { cerr << optarg << ": Invalid device ID (0-7)" << endl; return false; @@ -249,7 +244,7 @@ bool ParseArgument(int argc, char* argv[], int& port) continue; case 'F': { - if (string result = rascsi_image.SetDefaultFolder(optarg); !result.empty()) { + if (const string result = rascsi_image.SetDefaultFolder(optarg); !result.empty()) { cerr << result << endl; return false; } @@ -365,7 +360,7 @@ bool ParseArgument(int argc, char* argv[], int& port) const list& devices = { server_info.devices_info().devices().begin(), server_info.devices_info().devices().end() }; const string device_list = ListDevices(devices); LogDevices(device_list); - cout << device_list << endl; + cout << device_list << flush; return true; } @@ -388,8 +383,8 @@ static bool ExecuteCommand(const CommandContext& context, PbCommand& command) switch(command.operation()) { case LOG_LEVEL: { - string log_level = GetParam(command, "level"); - if (bool status = executor.SetLogLevel(log_level); !status) { + const string log_level = GetParam(command, "level"); + if (const bool status = executor.SetLogLevel(log_level); !status) { context.ReturnLocalizedError(LocalizationKey::ERROR_LOG_LEVEL, log_level); } else { @@ -401,7 +396,7 @@ static bool ExecuteCommand(const CommandContext& context, PbCommand& command) } case DEFAULT_FOLDER: { - if (string status = rascsi_image.SetDefaultFolder(GetParam(command, "folder")); !status.empty()) { + if (const string status = rascsi_image.SetDefaultFolder(GetParam(command, "folder")); !status.empty()) { context.ReturnStatus(false, status); } else { @@ -457,7 +452,7 @@ static bool ExecuteCommand(const CommandContext& context, PbCommand& command) } else { auto image_file = make_unique(); - bool status = rascsi_response.GetImageFile(*image_file.get(), rascsi_image.GetDefaultFolder(), filename); + const bool status = rascsi_response.GetImageFile(*image_file.get(), rascsi_image.GetDefaultFolder(), filename); if (status) { result.set_status(true); result.set_allocated_image_file_info(image_file.get()); @@ -505,7 +500,7 @@ static bool ExecuteCommand(const CommandContext& context, PbCommand& command) default: { // Wait until we become idle - timespec ts = { .tv_sec = 0, .tv_nsec = 500 * 1000 * 1000}; + const timespec ts = { .tv_sec = 0, .tv_nsec = 500'000'000}; while (active) { nanosleep(&ts, nullptr); } @@ -537,10 +532,10 @@ int main(int argc, char* argv[]) } } - executor.SetLogLevel("info"); + executor.SetLogLevel(current_log_level); // Create a thread-safe stdout logger to process the log messages - auto logger = stdout_color_mt("rascsi stdout logger"); + const auto logger = stdout_color_mt("rascsi stdout logger"); if (!InitBus()) { return EPERM; @@ -599,7 +594,7 @@ int main(int argc, char* argv[]) #else bus.Acquire(); if (!bus.GetSEL()) { - timespec ts = { .tv_sec = 0, .tv_nsec = 0}; + const timespec ts = { .tv_sec = 0, .tv_nsec = 0}; nanosleep(&ts, nullptr); continue; } @@ -608,8 +603,8 @@ int main(int argc, char* argv[]) // Wait until BSY is released as there is a possibility for the // initiator to assert it while setting the ID (for up to 3 seconds) if (bus.GetBSY()) { - uint32_t now = SysTimer::GetTimerLow(); - while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { + const uint32_t now = SysTimer::GetTimerLow(); + while ((SysTimer::GetTimerLow() - now) < 3'000'000) { bus.Acquire(); if (!bus.GetBSY()) { break; @@ -625,7 +620,7 @@ int main(int argc, char* argv[]) int initiator_id = -1; // The initiator and target ID - BYTE id_data = bus.GetDAT(); + const BYTE id_data = bus.GetDAT(); BUS::phase_t phase = BUS::phase_t::busfree; diff --git a/src/raspberrypi/rascsi/command_context.cpp b/src/raspberrypi/rascsi/command_context.cpp index ed5d7430..da64354d 100644 --- a/src/raspberrypi/rascsi/command_context.cpp +++ b/src/raspberrypi/rascsi/command_context.cpp @@ -15,10 +15,11 @@ using namespace std; using namespace rascsi_interface; -void CommandContext::Cleanup() const +void CommandContext::Cleanup() { if (fd != -1) { close(fd); + fd = -1; } } diff --git a/src/raspberrypi/rascsi/command_context.h b/src/raspberrypi/rascsi/command_context.h index 3736968d..5a0879b5 100644 --- a/src/raspberrypi/rascsi/command_context.h +++ b/src/raspberrypi/rascsi/command_context.h @@ -32,7 +32,7 @@ public: CommandContext(const std::string& s = "", int f = -1) : locale(s), fd(f) {} ~CommandContext() = default; - void Cleanup() const; + void Cleanup(); const ProtobufSerializer& GetSerializer() const { return serializer; } int GetFd() const { return fd; } diff --git a/src/raspberrypi/rascsi/rascsi_executor.cpp b/src/raspberrypi/rascsi/rascsi_executor.cpp index ff5e0458..f7622fde 100644 --- a/src/raspberrypi/rascsi/rascsi_executor.cpp +++ b/src/raspberrypi/rascsi/rascsi_executor.cpp @@ -13,13 +13,12 @@ #include "devices/device_factory.h" #include "devices/primary_device.h" #include "devices/disk.h" -#include "devices/file_support.h" #include "rascsi_service.h" #include "rascsi_response.h" #include "rascsi_image.h" #include "rascsi_exceptions.h" #include "localizer.h" -#include "command_util.h" +#include "protobuf_util.h" #include "command_context.h" #include "rasutil.h" #include "spdlog/spdlog.h" @@ -27,7 +26,7 @@ #include using namespace spdlog; -using namespace command_util; +using namespace protobuf_util; using namespace ras_util; bool RascsiExecutor::ProcessCmd(const CommandContext& context, const PbDeviceDefinition& pb_device, @@ -103,7 +102,7 @@ bool RascsiExecutor::ProcessCmd(const CommandContext& context, const PbCommand& case RESERVE_IDS: { const string ids = GetParam(command, "ids"); - if (string error = SetReservedIds(ids); !error.empty()) { + if (const string error = SetReservedIds(ids); !error.empty()) { return context.ReturnStatus(false, error); } @@ -132,19 +131,19 @@ bool RascsiExecutor::ProcessCmd(const CommandContext& context, const PbCommand& } // Remember the list of reserved files, than run the dry run - const auto& reserved_files = FileSupport::GetReservedFiles(); + const auto& reserved_files = Disk::GetReservedFiles(); for (const auto& device : command.devices()) { if (!ProcessCmd(context, device, command, true)) { // Dry run failed, restore the file list - FileSupport::SetReservedFiles(reserved_files); + Disk::SetReservedFiles(reserved_files); return false; } } // Restore the list of reserved files before proceeding - FileSupport::SetReservedFiles(reserved_files); + Disk::SetReservedFiles(reserved_files); - if (string result = ValidateLunSetup(command); !result.empty()) { + if (const string result = ValidateLunSetup(command); !result.empty()) { return context.ReturnStatus(false, result); } @@ -283,7 +282,7 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit return context.ReturnLocalizedError(LocalizationKey::ERROR_RESERVED_ID, to_string(id)); } - string filename = GetParam(pb_device, "file"); + const string filename = GetParam(pb_device, "file"); auto device = CreateDevice(context, type, lun, filename); if (device == nullptr) { @@ -291,8 +290,8 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit } // If no filename was provided the medium is considered removed - auto file_support = dynamic_cast(device.get()); - device->SetRemoved(file_support != nullptr ? filename.empty() : false); + auto disk = dynamic_pointer_cast(device); + device->SetRemoved(disk != nullptr ? filename.empty() : false); if (!SetProductData(context, pb_device, device)) { return false; @@ -303,8 +302,8 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit } string full_path; - if (file_support != nullptr) { - // File check (type is HD, for removable media drives, CD and MO the medium (=file) may be inserted later + if (device->SupportsFile()) { + // Only with removable media drives, CD and MO the medium (=file) may be inserted later if (!device->IsRemovable() && filename.empty()) { return context.ReturnLocalizedError(LocalizationKey::ERROR_MISSING_FILENAME, PbDeviceType_Name(type)); } @@ -341,7 +340,7 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit Filepath filepath; filepath.SetPath(full_path.c_str()); - file_support->ReserveFile(filepath, id, lun); + disk->ReserveFile(filepath, id, lun); string msg = "Attached "; if (device->IsReadOnly()) { @@ -367,7 +366,7 @@ bool RascsiExecutor::Insert(const CommandContext& context, const PbDeviceDefinit return context.ReturnLocalizedError(LocalizationKey::ERROR_DEVICE_NAME_UPDATE); } - string filename = GetParam(pb_device, "file"); + const string filename = GetParam(pb_device, "file"); if (filename.empty()) { return context.ReturnLocalizedError(LocalizationKey::ERROR_MISSING_FILENAME); } @@ -390,7 +389,7 @@ bool RascsiExecutor::Insert(const CommandContext& context, const PbDeviceDefinit Filepath filepath; filepath.SetPath(full_path.c_str()); - dynamic_pointer_cast(device)->ReserveFile(filepath, device->GetId(), device->GetLun()); + dynamic_pointer_cast(device)->ReserveFile(filepath, device->GetId(), device->GetLun()); // Only non read-only devices support protect/unprotect. // This operation must not be executed before Open() because Open() overrides some settings. @@ -407,31 +406,32 @@ bool RascsiExecutor::Insert(const CommandContext& context, const PbDeviceDefinit bool RascsiExecutor::Detach(const CommandContext& context, shared_ptr device, bool dryRun) const { + auto controller = controller_manager.FindController(device->GetId()); + if (controller == nullptr) { + return context.ReturnLocalizedError(LocalizationKey::ERROR_DETACH); + } + // LUN 0 can only be detached if there is no other LUN anymore - if (!device->GetLun() && controller_manager.FindController(device->GetId())->GetLunCount() > 1) { + if (!device->GetLun() && controller->GetLunCount() > 1) { return context.ReturnLocalizedError(LocalizationKey::ERROR_LUN0); } if (!dryRun) { - // Prepare log string before the device data are lost due to deletion - string s = "Detached " + device->GetType() + " device with ID " + to_string(device->GetId()) - + ", unit " + to_string(device->GetLun()); - - if (auto file_support = dynamic_pointer_cast(device); file_support != nullptr) { - file_support->UnreserveFile(); - } - - auto controller = controller_manager.FindController(device->GetId()); - if (controller == nullptr || !controller->DeleteDevice(device)) { + if (!controller->DeleteDevice(device)) { return context.ReturnLocalizedError(LocalizationKey::ERROR_DETACH); } // If no LUN is left also delete the controller - if (!controller->GetLunCount()) { - controller_manager.DeleteController(controller); + if (!controller->GetLunCount() && !controller_manager.DeleteController(controller)) { + return context.ReturnLocalizedError(LocalizationKey::ERROR_DETACH); } - LOGINFO("%s", s.c_str()) + if (auto disk = dynamic_pointer_cast(device); disk != nullptr) { + disk->UnreserveFile(); + } + + LOGINFO("%s", ("Detached " + device->GetType() + " device with ID " + to_string(device->GetId()) + + ", unit " + to_string(device->GetLun())).c_str()) } return true; @@ -440,7 +440,7 @@ bool RascsiExecutor::Detach(const CommandContext& context, shared_ptr reserved; - for (string id_to_reserve : ids_to_reserve) { + for (const string& id_to_reserve : ids_to_reserve) { int res_id; if (!GetAsInt(id_to_reserve, res_id) || res_id > 7) { return "Invalid ID " + id_to_reserve; @@ -549,8 +549,12 @@ string RascsiExecutor::SetReservedIds(string_view ids) bool RascsiExecutor::ValidateImageFile(const CommandContext& context, shared_ptr device, const string& filename, string& full_path) const { - auto file_support = dynamic_pointer_cast(device); - if (file_support == nullptr || filename.empty()) { + if (!device->SupportsFile()) { + return true; + } + + auto disk = dynamic_pointer_cast(device); + if (disk == nullptr || filename.empty()) { return true; } @@ -559,7 +563,7 @@ bool RascsiExecutor::ValidateImageFile(const CommandContext& context, shared_ptr Filepath filepath; filepath.SetPath(filename.c_str()); - if (FileSupport::GetIdsForReservedFile(filepath, id, lun)) { + if (Disk::GetIdsForReservedFile(filepath, id, lun)) { return context.ReturnLocalizedError(LocalizationKey::ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(lun)); } @@ -567,16 +571,16 @@ bool RascsiExecutor::ValidateImageFile(const CommandContext& context, shared_ptr string initial_filename = filepath.GetPath(); try { - if (!file_support->FileExists(filepath)) { + if (!disk->FileExists(filepath)) { // If the file does not exist search for it in the default image folder filepath.SetPath((rascsi_image.GetDefaultFolder() + "/" + filename).c_str()); - if (FileSupport::GetIdsForReservedFile(filepath, id, lun)) { + if (Disk::GetIdsForReservedFile(filepath, id, lun)) { return context.ReturnLocalizedError(LocalizationKey::ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(lun)); } - file_support->Open(filepath); + disk->Open(filepath); } } catch(const io_exception& e) { @@ -645,7 +649,7 @@ string RascsiExecutor::ValidateLunSetup(const PbCommand& command) const } // LUN 0 must exist for all devices - for (auto const& [id, lun]: luns) { + for (const auto& [id, lun]: luns) { if (!(lun & 0x01)) { return "LUN 0 is missing for device ID " + to_string(id); } diff --git a/src/raspberrypi/rascsi/rascsi_image.cpp b/src/raspberrypi/rascsi/rascsi_image.cpp index 20f2c854..6ae5a9b8 100644 --- a/src/raspberrypi/rascsi/rascsi_image.cpp +++ b/src/raspberrypi/rascsi/rascsi_image.cpp @@ -12,8 +12,8 @@ #include "log.h" #include "filepath.h" #include "spdlog/spdlog.h" -#include "devices/file_support.h" -#include "command_util.h" +#include "devices/disk.h" +#include "protobuf_util.h" #include "command_context.h" #include "rascsi_image.h" #include @@ -26,7 +26,7 @@ using namespace std; using namespace spdlog; using namespace rascsi_interface; -using namespace command_util; +using namespace protobuf_util; RascsiImage::RascsiImage() { @@ -41,8 +41,8 @@ bool RascsiImage::CheckDepth(string_view filename) const bool RascsiImage::CreateImageFolder(const CommandContext& context, const string& filename) const { - if (size_t filename_start = filename.rfind('/'); filename_start != string::npos) { - string folder = filename.substr(0, filename_start); + if (const size_t filename_start = filename.rfind('/'); filename_start != string::npos) { + const string folder = filename.substr(0, filename_start); // Checking for existence first prevents an error if the top-level folder is a softlink if (struct stat st; stat(folder.c_str(), &st)) { @@ -105,7 +105,7 @@ bool RascsiImage::IsValidDstFilename(const string& filename) const bool RascsiImage::CreateImage(const CommandContext& context, const PbCommand& command) const { - string filename = GetParam(command, "file"); + const string filename = GetParam(command, "file"); if (filename.empty()) { return context.ReturnStatus(false, "Can't create image file: Missing image filename"); } @@ -114,7 +114,7 @@ bool RascsiImage::CreateImage(const CommandContext& context, const PbCommand& co return context.ReturnStatus(false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); } - string full_filename = GetFullName(filename); + const string full_filename = GetFullName(filename); if (!IsValidDstFilename(full_filename)) { return context.ReturnStatus(false, "Can't create image file: '" + full_filename + "': File already exists"); } @@ -142,12 +142,12 @@ bool RascsiImage::CreateImage(const CommandContext& context, const PbCommand& co return false; } - string permission = GetParam(command, "read_only"); + const string permission = GetParam(command, "read_only"); // Since rascsi is running as root ensure that others can access the file - int permissions = !strcasecmp(permission.c_str(), "true") ? + const int permissions = !strcasecmp(permission.c_str(), "true") ? S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - int image_fd = open(full_filename.c_str(), O_CREAT|O_WRONLY, permissions); + const int image_fd = open(full_filename.c_str(), O_CREAT|O_WRONLY, permissions); if (image_fd == -1) { return context.ReturnStatus(false, "Can't create image file '" + full_filename + "': " + string(strerror(errno))); } @@ -178,7 +178,7 @@ bool RascsiImage::CreateImage(const CommandContext& context, const PbCommand& co bool RascsiImage::DeleteImage(const CommandContext& context, const PbCommand& command) const { - string filename = GetParam(command, "file"); + const string filename = GetParam(command, "file"); if (filename.empty()) { return context.ReturnStatus(false, "Missing image filename"); } @@ -187,13 +187,13 @@ bool RascsiImage::DeleteImage(const CommandContext& context, const PbCommand& co return context.ReturnStatus(false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); } - string full_filename = GetFullName(filename); + const string full_filename = GetFullName(filename); int id; int unit; Filepath filepath; filepath.SetPath(full_filename.c_str()); - if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { + if (Disk::GetIdsForReservedFile(filepath, id, unit)) { return context.ReturnStatus(false, "Can't delete image file '" + full_filename + "', it is currently being used by device ID " + to_string(id) + ", unit " + to_string(unit)); } @@ -273,17 +273,17 @@ bool RascsiImage::CopyImage(const CommandContext& context, const PbCommand& comm return context.ReturnStatus(); } - int fd_src = open(from.c_str(), O_RDONLY, 0); + const int fd_src = open(from.c_str(), O_RDONLY, 0); if (fd_src == -1) { return context.ReturnStatus(false, "Can't open source image file '" + from + "': " + string(strerror(errno))); } - string permission = GetParam(command, "read_only"); + const string permission = GetParam(command, "read_only"); // Since rascsi is running as root ensure that others can access the file - int permissions = !strcasecmp(permission.c_str(), "true") ? + const int permissions = !strcasecmp(permission.c_str(), "true") ? S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - int fd_dst = open(to.c_str(), O_WRONLY | O_CREAT, permissions); + const int fd_dst = open(to.c_str(), O_WRONLY | O_CREAT, permissions); if (fd_dst == -1) { close(fd_src); @@ -334,9 +334,9 @@ bool RascsiImage::SetImagePermissions(const CommandContext& context, const PbCom return context.ReturnStatus(false, "Can't modify image file '" + filename + "': Invalid name or type"); } - bool protect = command.operation() == PROTECT_IMAGE; + const bool protect = command.operation() == PROTECT_IMAGE; - if (int permissions = protect ? S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + if (const int permissions = protect ? S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; chmod(filename.c_str(), permissions) == -1) { return context.ReturnStatus(false, "Can't " + string(protect ? "protect" : "unprotect") + " image file '" + filename + "': " + strerror(errno)); diff --git a/src/raspberrypi/rascsi/rascsi_response.cpp b/src/raspberrypi/rascsi/rascsi_response.cpp index fcf9f08e..9d477888 100644 --- a/src/raspberrypi/rascsi/rascsi_response.cpp +++ b/src/raspberrypi/rascsi/rascsi_response.cpp @@ -8,16 +8,15 @@ //--------------------------------------------------------------------------- #include "controllers/controller_manager.h" -#include "devices/file_support.h" #include "devices/disk.h" #include "devices/device_factory.h" -#include "command_util.h" +#include "protobuf_util.h" #include "rascsi_version.h" #include "rascsi_interface.pb.h" #include "rascsi_response.h" using namespace rascsi_interface; -using namespace command_util; +using namespace protobuf_util; unique_ptr RascsiResponse::GetDeviceProperties(const Device& device) const { @@ -29,7 +28,7 @@ unique_ptr RascsiResponse::GetDeviceProperties(const Device& properties->set_stoppable(device.IsStoppable()); properties->set_removable(device.IsRemovable()); properties->set_lockable(device.IsLockable()); - properties->set_supports_file(dynamic_cast(&device) != nullptr); + properties->set_supports_file(device.SupportsFile()); properties->set_supports_params(device.SupportsParams()); PbDeviceType t = UNDEFINED; @@ -53,7 +52,7 @@ void RascsiResponse::GetDeviceTypeProperties(PbDeviceTypesInfo& device_types_inf { auto type_properties = device_types_info.add_properties(); type_properties->set_type(type); - auto device = device_factory.CreateDevice(controller_manager, type, 0, ""); + const auto device = device_factory.CreateDevice(controller_manager, type, 0, ""); type_properties->set_allocated_properties(GetDeviceProperties(*device).release()); } //NOSONAR The allocated memory is managed by protobuf @@ -101,10 +100,10 @@ void RascsiResponse::GetDevice(const Device& device, PbDevice& pb_device, const pb_device.set_block_count(device.IsRemoved() ? 0: disk->GetBlockCount()); } - const auto file_support = dynamic_cast(&device); - if (file_support) { + const auto disk = dynamic_cast(&device); + if (disk != nullptr) { Filepath filepath; - file_support->GetPath(filepath); + disk->GetPath(filepath); auto image_file = make_unique().release(); GetImageFile(*image_file, default_folder, device.IsRemovable() && !device.IsReady() ? "" : filepath.GetPath()); pb_device.set_allocated_file(image_file); @@ -117,7 +116,7 @@ bool RascsiResponse::GetImageFile(PbImageFile& image_file, const string& default image_file.set_name(filename); image_file.set_type(device_factory.GetTypeForFile(filename)); - string f = filename[0] == '/' ? filename : default_folder + "/" + filename; + const string f = filename[0] == '/' ? filename : default_folder + "/" + filename; image_file.set_read_only(access(f.c_str(), W_OK)); @@ -209,7 +208,7 @@ void RascsiResponse::GetAvailableImages(PbResult& result, PbServerInfo& server_i unique_ptr RascsiResponse::GetReservedIds(PbResult& result, const unordered_set& ids) const { auto reserved_ids_info = make_unique(); - for (int id : ids) { + for (const int id : ids) { reserved_ids_info->add_ids(id); } @@ -533,14 +532,14 @@ string RascsiResponse::GetNextImageFile(const dirent *dir, const string& folder) return ""; } - string filename = folder + "/" + dir->d_name; + const string filename = folder + "/" + dir->d_name; struct stat st; - bool file_exists = !stat(filename.c_str(), &st); + const bool file_exists = !stat(filename.c_str(), &st); if (dir->d_type == DT_REG && file_exists && !st.st_size) { - LOGWARN("File '%s' in image folder '%s' has a size of 0 bytes", dir->d_name, folder.c_str()) + LOGWARN("File '%s' in image folder '%s' is empty", dir->d_name, folder.c_str()) return ""; } diff --git a/src/raspberrypi/rascsi/rascsi_service.cpp b/src/raspberrypi/rascsi/rascsi_service.cpp index a2296be5..c85c8494 100644 --- a/src/raspberrypi/rascsi/rascsi_service.cpp +++ b/src/raspberrypi/rascsi/rascsi_service.cpp @@ -77,7 +77,7 @@ void RascsiService::Execute() const ras_util::FixCpu(2); // Wait for the execution to start - timespec ts = { .tv_sec = 0, .tv_nsec = 1000}; + const timespec ts = { .tv_sec = 0, .tv_nsec = 1000}; while (!running) { nanosleep(&ts, nullptr); } @@ -109,7 +109,7 @@ PbCommand RascsiService::ReadCommand(CommandContext& context) const // Wait for connection sockaddr client = {}; socklen_t socklen = sizeof(client); - int fd = accept(service_socket, &client, &socklen); + const int fd = accept(service_socket, &client, &socklen); if (fd == -1) { throw io_exception("accept() failed"); } @@ -118,7 +118,7 @@ PbCommand RascsiService::ReadCommand(CommandContext& context) const // Read magic string vector magic(6); - if (size_t bytes_read = context.GetSerializer().ReadBytes(fd, magic); + if (const size_t bytes_read = context.GetSerializer().ReadBytes(fd, magic); bytes_read != magic.size() || memcmp(magic.data(), "RASCSI", magic.size())) { throw io_exception("Invalid magic"); } diff --git a/src/raspberrypi/rascsi_exceptions.h b/src/raspberrypi/rascsi_exceptions.h index a28c4bf1..d3ddbd03 100644 --- a/src/raspberrypi/rascsi_exceptions.h +++ b/src/raspberrypi/rascsi_exceptions.h @@ -30,7 +30,7 @@ class file_not_found_exception : public io_exception using io_exception::io_exception; }; -class scsi_error_exception final : public std::exception +class scsi_exception : public std::exception { scsi_defs::sense_key sense_key; scsi_defs::asc asc; @@ -38,11 +38,11 @@ class scsi_error_exception final : public std::exception public: - scsi_error_exception(scsi_defs::sense_key sense_key = scsi_defs::sense_key::ABORTED_COMMAND, + scsi_exception(scsi_defs::sense_key sense_key = scsi_defs::sense_key::ABORTED_COMMAND, scsi_defs::asc asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION, scsi_defs::status status = scsi_defs::status::CHECK_CONDITION) : sense_key(sense_key), asc(asc), status(status) {} - ~scsi_error_exception() override = default; + ~scsi_exception() override = default; scsi_defs::sense_key get_sense_key() const { return sense_key; } scsi_defs::asc get_asc() const { return asc; } diff --git a/src/raspberrypi/rascsi_version.cpp b/src/raspberrypi/rascsi_version.cpp index 4c43aa37..566656b3 100644 --- a/src/raspberrypi/rascsi_version.cpp +++ b/src/raspberrypi/rascsi_version.cpp @@ -23,7 +23,7 @@ string rascsi_get_version_string() { stringstream s; - s << setw(2) << setfill('0') << rascsi_major_version << '.' << setw(2) << setfill('0') << rascsi_minor_version; + s << setw(2) << setfill('0') << rascsi_major_version << '.' << rascsi_minor_version; if (rascsi_patch_version < 0) { s << " --DEVELOPMENT BUILD--"; diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp index ecb79b55..b81ac86d 100644 --- a/src/raspberrypi/rasctl.cpp +++ b/src/raspberrypi/rasctl.cpp @@ -10,11 +10,11 @@ // //--------------------------------------------------------------------------- -#include #include "rascsi_version.h" -#include "command_util.h" +#include "protobuf_util.h" #include "rasutil.h" #include "rascsi_interface.pb.h" +#include "rasctl/rasctl_parser.h" #include "rasctl/rasctl_commands.h" #include #include @@ -27,125 +27,45 @@ static const char COMPONENT_SEPARATOR = ':'; using namespace std; using namespace rascsi_interface; using namespace ras_util; -using namespace command_util; +using namespace protobuf_util; -PbOperation ParseOperation(const string& operation) +void Banner(int argc, char* argv[]) { - switch (tolower(operation[0])) { - case 'a': - return ATTACH; + if (argc < 2) { + cout << Banner("Controller"); - case 'd': - return DETACH; + cout << "\nUsage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] "; + cout << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] "; + cout << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] "; + cout << "[-x CURRENT_NAME:NEW_NAME] [-z LOCALE] "; + cout << "[-e] [-E FILENAME] [-D] [-I] [-l] [-m] [o] [-O] [-P] [-s] [-v] [-V] [-y] [-X]\n"; + cout << " where ID := {0-7}\n"; + cout << " UNIT := {0-31}, default is 0\n"; + cout << " CMD := {attach|detach|insert|eject|protect|unprotect|show}\n"; + cout << " TYPE := {schd|scrm|sccd|scmo|scbr|scdp} or convenience type {hd|rm|mo|cd|bridge|daynaport}\n"; + cout << " BLOCK_SIZE := {512|1024|2048|4096) bytes per hard disk drive block\n"; + cout << " NAME := name of device to attach (VENDOR:PRODUCT:REVISION)\n"; + cout << " FILE|PARAM := image file path or device-specific parameter\n"; + cout << " IMAGE_FOLDER := default location for image files, default is '~/images'\n"; + cout << " HOST := rascsi host to connect to, default is 'localhost'\n"; + cout << " PORT := rascsi port to connect to, default is 6868\n"; + cout << " RESERVED_IDS := comma-separated list of IDs to reserve\n"; + cout << " LOG_LEVEL := log level {trace|debug|info|warn|err|critical|off}, default is 'info'\n"; + cout << " If CMD is 'attach' or 'insert' the FILE parameter is required.\n"; + cout << "Usage: " << argv[0] << " -l\n"; + cout << " Print device list.\n" << flush; - case 'i': - return INSERT; - - case 'e': - return EJECT; - - case 'p': - return PROTECT; - - case 'u': - return UNPROTECT; - - case 's': - return DEVICES_INFO; - - default: - return NO_OPERATION; + exit(EXIT_SUCCESS); } } -PbDeviceType ParseType(const char *type) -{ - string t = type; - transform(t.begin(), t.end(), t.begin(), ::toupper); - - if (PbDeviceType parsed_type; PbDeviceType_Parse(t, &parsed_type)) { - return parsed_type; - } - - // Parse convenience device types (shortcuts) - switch (tolower(type[0])) { - case 'c': - return SCCD; - - case 'b': - return SCBR; - - case 'd': - return SCDP; - - case 'h': - return SCHD; - - case 'm': - return SCMO; - - case 'r': - return SCRM; - - case 'l': - return SCLP; - - case 's': - return SCHS; - - default: - return UNDEFINED; - } -} - -void SetPatternParams(PbCommand& command, string_view patterns) -{ - string folder_pattern; - string file_pattern; - if (size_t separator_pos = patterns.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { - folder_pattern = patterns.substr(0, separator_pos); - file_pattern = patterns.substr(separator_pos + 1); - } - else { - file_pattern = patterns; - } - - AddParam(command, "folder_pattern", folder_pattern); - AddParam(command, "file_pattern", file_pattern); -} - int main(int argc, char* argv[]) { GOOGLE_PROTOBUF_VERIFY_VERSION; - // Display help - if (argc < 2) { - cerr << "SCSI Target Emulator RaSCSI Controller" << endl; - cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl; - cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] "; - cerr << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] "; - cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] "; - cerr << "[-x CURRENT_NAME:NEW_NAME] [-z LOCALE] "; - cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [o] [-O] [-P] [-s] [-v] [-V] [-y] [-X]" << endl; - cerr << " where ID := {0-7}" << endl; - cerr << " UNIT := {0-31}, default is 0" << endl; - cerr << " CMD := {attach|detach|insert|eject|protect|unprotect|show}" << endl; - cerr << " TYPE := {schd|scrm|sccd|scmo|scbr|scdp} or convenience type {hd|rm|mo|cd|bridge|daynaport}" << endl; - cerr << " BLOCK_SIZE := {512|1024|2048|4096) bytes per hard disk drive block" << endl; - cerr << " NAME := name of device to attach (VENDOR:PRODUCT:REVISION)" << endl; - cerr << " FILE|PARAM := image file path or device-specific parameter" << endl; - cerr << " IMAGE_FOLDER := default location for image files, default is '~/images'" << endl; - cerr << " HOST := rascsi host to connect to, default is 'localhost'" << endl; - cerr << " PORT := rascsi port to connect to, default is 6868" << endl; - cerr << " RESERVED_IDS := comma-separated list of IDs to reserve" << endl; - cerr << " LOG_LEVEL := log level {trace|debug|info|warn|err|critical|off}, default is 'info'" << endl; - cerr << " If CMD is 'attach' or 'insert' the FILE parameter is required." << endl; - cerr << "Usage: " << argv[0] << " -l" << endl; - cerr << " Print device list." << endl; - - exit(EXIT_SUCCESS); - } + Banner(argc, argv); + RasctlParser parser; PbCommand command; list devices; PbDeviceDefinition* device = command.add_devices(); @@ -205,7 +125,7 @@ int main(int argc, char* argv[]) break; case 'c': - command.set_operation(ParseOperation(optarg)); + command.set_operation(parser.ParseOperation(optarg)); if (command.operation() == NO_OPERATION) { cerr << "Error: Unknown operation '" << optarg << "'" << endl; exit(EXIT_FAILURE); @@ -276,7 +196,7 @@ int main(int argc, char* argv[]) break; case 't': - device->set_type(ParseType(optarg)); + device->set_type(parser.ParseType(optarg)); if (device->type() == UNDEFINED) { cerr << "Error: Unknown device type '" << optarg << "'" << endl; exit(EXIT_FAILURE); diff --git a/src/raspberrypi/rasctl/rasctl_commands.cpp b/src/raspberrypi/rasctl/rasctl_commands.cpp index e6289d51..46278b09 100644 --- a/src/raspberrypi/rasctl/rasctl_commands.cpp +++ b/src/raspberrypi/rasctl/rasctl_commands.cpp @@ -9,7 +9,7 @@ #include "rascsi_exceptions.h" #include "protobuf_serializer.h" -#include "command_util.h" +#include "protobuf_util.h" #include "rasutil.h" #include "rasctl_commands.h" #include "rascsi_interface.pb.h" @@ -20,7 +20,7 @@ using namespace std; using namespace rascsi_interface; -using namespace command_util; +using namespace protobuf_util; // Separator for the INQUIRY name components static const char COMPONENT_SEPARATOR = ':'; @@ -115,36 +115,25 @@ void RasctlCommands::Execute(const string& log_level, const string& default_fold void RasctlCommands::SendCommand() { - if (!token.empty()) { - AddParam(command, "token", token); - } + AddParam(command, "token", token); + AddParam(command, "locale", locale); - if (!locale.empty()) { - AddParam(command, "locale", locale); - } - - // Send command int fd = -1; try { - const hostent *host = gethostbyname(hostname.c_str()); - if (!host) { + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) { + throw io_exception("Can't create socket: " + string(strerror(errno))); + } + + sockaddr_in server_addr = {}; + if (!ResolveHostName(hostname, &server_addr)) { throw io_exception("Can't resolve hostname '" + hostname + "'"); } - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) { - throw io_exception("Can't create socket"); - } - - sockaddr_in server = {}; - server.sin_family = AF_INET; - server.sin_port = htons((uint16_t)port); - server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - memcpy(&server.sin_addr.s_addr, host->h_addr, host->h_length); - - if (connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) { - throw io_exception("Can't connect to rascsi process on host '" + hostname + "', port " - + to_string(port)); + server_addr.sin_port = htons(uint16_t(port)); + if (connect(fd, (sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + throw io_exception("Can't connect to rascsi on host '" + hostname + "', port " + to_string(port) + + ": " + strerror(errno)); } if (write(fd, "RASCSI", 6) != 6) { @@ -156,11 +145,11 @@ void RasctlCommands::SendCommand() catch(const io_exception& e) { cerr << "Error: " << e.get_msg() << endl; - if (fd >= 0) { + if (fd != -1) { close(fd); } - exit(fd < 0 ? ENOTCONN : EXIT_FAILURE); + exit(fd == -1 ? ENOTCONN : EXIT_FAILURE); } // Receive result @@ -190,7 +179,7 @@ void RasctlCommands::CommandDevicesInfo() { SendCommand(); - rasctl_display.DisplayDevices(result.devices_info()); + cout << rasctl_display.DisplayDevicesInfo(result.devices_info()) << flush; } void RasctlCommands::CommandLogLevel(const string& log_level) @@ -209,7 +198,7 @@ void RasctlCommands::CommandReserveIds(const string& reserved_ids) void RasctlCommands::CommandCreateImage(const string& image_params) { - if (size_t separator_pos = image_params.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { + if (const size_t separator_pos = image_params.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { AddParam(command, "file", string_view(image_params).substr(0, separator_pos)); AddParam(command, "size", string_view(image_params).substr(separator_pos + 1)); } @@ -232,7 +221,7 @@ void RasctlCommands::CommandDeleteImage(const string& filename) void RasctlCommands::CommandRenameImage(const string& image_params) { - if (size_t separator_pos = image_params.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { + if (const size_t separator_pos = image_params.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { AddParam(command, "from", string_view(image_params).substr(0, separator_pos)); AddParam(command, "to", string_view(image_params).substr(separator_pos + 1)); } @@ -246,7 +235,7 @@ void RasctlCommands::CommandRenameImage(const string& image_params) void RasctlCommands::CommandCopyImage(const string& image_params) { - if (size_t separator_pos = image_params.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { + if (const size_t separator_pos = image_params.find(COMPONENT_SEPARATOR); separator_pos != string::npos) { AddParam(command, "from", string_view(image_params).substr(0, separator_pos)); AddParam(command, "to", string_view(image_params).substr(separator_pos + 1)); } @@ -270,22 +259,24 @@ void RasctlCommands::CommandDeviceInfo() SendCommand(); for (const auto& device : result.devices_info().devices()) { - rasctl_display.DisplayDeviceInfo(device); + cout << rasctl_display.DisplayDeviceInfo(device); } + + cout << flush; } void RasctlCommands::CommandDeviceTypesInfo() { SendCommand(); - rasctl_display.DisplayDeviceTypesInfo(result.device_types_info()); + cout << rasctl_display.DisplayDeviceTypesInfo(result.device_types_info()) << flush; } void RasctlCommands::CommandVersionInfo() { SendCommand(); - rasctl_display.DisplayVersionInfo(result.version_info()); + cout << rasctl_display.DisplayVersionInfo(result.version_info()) << flush; } void RasctlCommands::CommandServerInfo() @@ -294,32 +285,34 @@ void RasctlCommands::CommandServerInfo() PbServerInfo server_info = result.server_info(); - rasctl_display.DisplayVersionInfo(server_info.version_info()); - rasctl_display.DisplayLogLevelInfo(server_info.log_level_info()); - rasctl_display.DisplayImageFiles(server_info.image_files_info()); - rasctl_display.DisplayMappingInfo(server_info.mapping_info()); - rasctl_display.DisplayNetworkInterfaces(server_info.network_interfaces_info()); - rasctl_display.DisplayDeviceTypesInfo(server_info.device_types_info()); - rasctl_display.DisplayReservedIdsInfo(server_info.reserved_ids_info()); - rasctl_display.DisplayOperationInfo(server_info.operation_info()); + cout << rasctl_display.DisplayVersionInfo(server_info.version_info()); + cout << rasctl_display.DisplayLogLevelInfo(server_info.log_level_info()); + cout << rasctl_display.DisplayImageFilesInfo(server_info.image_files_info()); + cout << rasctl_display.DisplayMappingInfo(server_info.mapping_info()); + cout << rasctl_display.DisplayNetworkInterfaces(server_info.network_interfaces_info()); + cout << rasctl_display.DisplayDeviceTypesInfo(server_info.device_types_info()); + cout << rasctl_display.DisplayReservedIdsInfo(server_info.reserved_ids_info()); + cout << rasctl_display.DisplayOperationInfo(server_info.operation_info()); if (server_info.devices_info().devices_size()) { list sorted_devices = { server_info.devices_info().devices().begin(), server_info.devices_info().devices().end() }; sorted_devices.sort([](const auto& a, const auto& b) { return a.id() < b.id() || a.unit() < b.unit(); }); - cout << "Attached devices:" << endl; + cout << "Attached devices:\n"; for (const auto& device : sorted_devices) { - rasctl_display.DisplayDeviceInfo(device); + cout << rasctl_display.DisplayDeviceInfo(device); } } + + cout << flush; } void RasctlCommands::CommandDefaultImageFilesInfo() { SendCommand(); - rasctl_display.DisplayImageFiles(result.image_files_info()); + cout << rasctl_display.DisplayImageFilesInfo(result.image_files_info()) << flush; } void RasctlCommands::CommandImageFileInfo(const string& filename) @@ -328,40 +321,55 @@ void RasctlCommands::CommandImageFileInfo(const string& filename) SendCommand(); - rasctl_display.DisplayImageFile(result.image_file_info()); + cout << rasctl_display.DisplayImageFile(result.image_file_info()) << flush; } void RasctlCommands::CommandNetworkInterfacesInfo() { SendCommand(); - rasctl_display.DisplayNetworkInterfaces(result.network_interfaces_info()); + cout << rasctl_display.DisplayNetworkInterfaces(result.network_interfaces_info()) << flush; } void RasctlCommands::CommandLogLevelInfo() { SendCommand(); - rasctl_display.DisplayLogLevelInfo(result.log_level_info()); + cout << rasctl_display.DisplayLogLevelInfo(result.log_level_info()) << flush; } void RasctlCommands::CommandReservedIdsInfo() { SendCommand(); - rasctl_display.DisplayReservedIdsInfo(result.reserved_ids_info()); + cout << rasctl_display.DisplayReservedIdsInfo(result.reserved_ids_info()) << flush; } void RasctlCommands::CommandMappingInfo() { SendCommand(); - rasctl_display.DisplayMappingInfo(result.mapping_info()); + cout << rasctl_display.DisplayMappingInfo(result.mapping_info()) << flush; } void RasctlCommands::CommandOperationInfo() { SendCommand(); - rasctl_display.DisplayOperationInfo(result.operation_info()); + cout << rasctl_display.DisplayOperationInfo(result.operation_info()) << flush; +} + +bool RasctlCommands::ResolveHostName(const string& host, sockaddr_in *addr) +{ + addrinfo hints = {}; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + if (addrinfo *result; !getaddrinfo(host.c_str(), nullptr, &hints, &result)) { + *addr = *(sockaddr_in *)(result->ai_addr); + freeaddrinfo(result); + return true; + } + + return false; } diff --git a/src/raspberrypi/rasctl/rasctl_commands.h b/src/raspberrypi/rasctl/rasctl_commands.h index e70c6f2b..2764b540 100644 --- a/src/raspberrypi/rasctl/rasctl_commands.h +++ b/src/raspberrypi/rasctl/rasctl_commands.h @@ -3,7 +3,7 @@ // SCSI Target Emulator RaSCSI Reloaded // for Raspberry Pi // -// Copyright (C) 2021 Uwe Seimet +// Copyright (C) 2021-2022 Uwe Seimet // //--------------------------------------------------------------------------- @@ -12,6 +12,7 @@ #include "protobuf_serializer.h" #include "rascsi_interface.pb.h" #include "rasctl_display.h" +#include #include using namespace rascsi_interface; @@ -49,6 +50,8 @@ private: void CommandOperationInfo(); void SendCommand(); + static bool ResolveHostName(const string&, sockaddr_in *); + ProtobufSerializer serializer; PbCommand command; string hostname; diff --git a/src/raspberrypi/rasctl/rasctl_display.cpp b/src/raspberrypi/rasctl/rasctl_display.cpp index 638edfb5..8d36bbdf 100644 --- a/src/raspberrypi/rasctl/rasctl_display.cpp +++ b/src/raspberrypi/rasctl/rasctl_display.cpp @@ -10,274 +10,282 @@ #include "rascsi_interface.pb.h" #include "rasutil.h" #include "rasctl_display.h" -#include +#include #include +#include using namespace std; using namespace rascsi_interface; using namespace ras_util; -void RasctlDisplay::DisplayDevices(const PbDevicesInfo& devices_info) const +string RasctlDisplay::DisplayDevicesInfo(const PbDevicesInfo& devices_info) const { + ostringstream s; + const list& devices = { devices_info.devices().begin(), devices_info.devices().end() }; - cout << ListDevices(devices) << endl; + + s << ListDevices(devices); + + return s.str(); } -void RasctlDisplay::DisplayDeviceInfo(const PbDevice& pb_device) const +string RasctlDisplay::DisplayDeviceInfo(const PbDevice& pb_device) const { - cout << " " << pb_device.id() << ":" << pb_device.unit() << " " << PbDeviceType_Name(pb_device.type()) + ostringstream s; + + s << " " << pb_device.id() << ":" << pb_device.unit() << " " << PbDeviceType_Name(pb_device.type()) << " " << pb_device.vendor() << ":" << pb_device.product() << ":" << pb_device.revision(); if (pb_device.block_size()) { - cout << " " << pb_device.block_size() << " bytes per sector"; + s << " " << pb_device.block_size() << " bytes per sector"; + if (pb_device.block_count()) { - cout << " " << pb_device.block_size() * pb_device.block_count() << " bytes capacity"; + s << " " << pb_device.block_size() * pb_device.block_count() << " bytes capacity"; } } if (pb_device.properties().supports_file() && !pb_device.file().name().empty()) { - cout << " " << pb_device.file().name(); + s << " " << pb_device.file().name(); } - cout << " "; + s << " "; + bool hasProperty = false; + if (pb_device.properties().read_only()) { - cout << "read-only"; + s << "read-only"; hasProperty = true; } + if (pb_device.properties().protectable() && pb_device.status().protected_()) { if (hasProperty) { - cout << ", "; + s << ", "; } - cout << "protected"; + s << "protected"; hasProperty = true; } + if (pb_device.properties().stoppable() && pb_device.status().stopped()) { if (hasProperty) { - cout << ", "; + s << ", "; } - cout << "stopped"; + s << "stopped"; hasProperty = true; } + if (pb_device.properties().removable() && pb_device.status().removed()) { if (hasProperty) { - cout << ", "; + s << ", "; } - cout << "removed"; + s << "removed"; hasProperty = true; } + if (pb_device.properties().lockable() && pb_device.status().locked()) { if (hasProperty) { - cout << ", "; + s << ", "; } - cout << "locked"; + s << "locked"; } + if (hasProperty) { - cout << " "; + s << " "; } - // Creates a sorted map - map params = { pb_device.params().begin(), pb_device.params().end() }; - bool isFirst = true; - for (const auto& [key, value] : params) { - if (!isFirst) { - cout << ":"; - } - isFirst = false; - cout << key << "=" << value; - } + DisplayParams(s, pb_device); - cout << endl; + s << '\n'; + + return s.str(); } -void RasctlDisplay::DisplayVersionInfo(const PbVersionInfo& version_info) const +string RasctlDisplay::DisplayVersionInfo(const PbVersionInfo& version_info) const { - cout << "rascsi server version: " << version_info.major_version() << "." << version_info.minor_version(); + ostringstream s; + + s << "rascsi server version: " << setw(2) << setfill('0') << version_info.major_version() << "." + << setw(2) << setfill('0') << version_info.minor_version(); + if (version_info.patch_version() > 0) { - cout << "." << version_info.patch_version(); + s << "." << version_info.patch_version(); } else if (version_info.patch_version() < 0) { - cout << " (development version)"; + s << " (development version)"; } - cout << endl; + + s << '\n'; + + return s.str(); } -void RasctlDisplay::DisplayLogLevelInfo(const PbLogLevelInfo& log_level_info) const +string RasctlDisplay::DisplayLogLevelInfo(const PbLogLevelInfo& log_level_info) const { + ostringstream s; + if (!log_level_info.log_levels_size()) { - cout << " No log level settings available" << endl; + s << " No log level settings available\n"; } else { - cout << "rascsi log levels, sorted by severity:" << endl; + s << "rascsi log levels, sorted by severity:\n"; + for (const auto& log_level : log_level_info.log_levels()) { - cout << " " << log_level << endl; + s << " " << log_level << '\n'; } } - cout << "Current rascsi log level: " << log_level_info.current_log_level() << endl; + s << "Current rascsi log level: " << log_level_info.current_log_level() << '\n'; + + return s.str(); } -void RasctlDisplay::DisplayDeviceTypesInfo(const PbDeviceTypesInfo& device_types_info) const +string RasctlDisplay::DisplayDeviceTypesInfo(const PbDeviceTypesInfo& device_types_info) const { - cout << "Supported device types and their properties:"; + ostringstream s; + + s << "Supported device types and their properties:"; + for (const auto& device_type_info : device_types_info.properties()) { - cout << endl << " " << PbDeviceType_Name(device_type_info.type()) << " "; + s << "\n " << PbDeviceType_Name(device_type_info.type()) << " "; const PbDeviceProperties& properties = device_type_info.properties(); - if (properties.read_only() || properties.protectable() || properties.stoppable() || properties.lockable()) { - cout << "Properties: "; - bool has_property = false; - if (properties.read_only()) { - cout << "read-only"; - has_property = true; - } - if (properties.protectable()) { - cout << (has_property ? ", " : "") << "protectable"; - has_property = true; - } - if (properties.stoppable()) { - cout << (has_property ? ", " : "") << "stoppable"; - has_property = true; - } - if (properties.removable()) { - cout << (has_property ? ", " : "") << "removable"; - has_property = true; - } - if (properties.lockable()) { - cout << (has_property ? ", " : "") << "lockable"; - } - cout << endl << " "; - } + DisplayAttributes(s, properties); if (properties.supports_file()) { - cout << "Image file support" << endl << " "; + s << "Image file support\n "; } + if (properties.supports_params()) { - cout << "Parameter support" << endl << " "; + s << "Parameter support\n "; } - if (properties.supports_params() && properties.default_params_size()) { - // Creates a sorted map - map params = { properties.default_params().begin(), properties.default_params().end() }; + DisplayDefaultParameters(s, properties); - cout << "Default parameters: "; - - bool isFirst = true; - for (const auto& [key, value] : params) { - if (!isFirst) { - cout << endl << " "; - } - cout << key << "=" << value; - - isFirst = false; - } - } - - if (properties.block_sizes_size()) { - // Creates a sorted set - set block_sizes = { properties.block_sizes().begin(), properties.block_sizes().end() }; - - cout << "Configurable block sizes in bytes: "; - - bool isFirst = true; - for (const auto& block_size : block_sizes) { - if (!isFirst) { - cout << ", "; - } - cout << block_size; - - isFirst = false; - } - } + DisplayBlockSizes(s, properties); } + + return s.str(); } -void RasctlDisplay::DisplayReservedIdsInfo(const PbReservedIdsInfo& reserved_ids_info) const +string RasctlDisplay::DisplayReservedIdsInfo(const PbReservedIdsInfo& reserved_ids_info) const { + ostringstream s; + if (reserved_ids_info.ids_size()) { - cout << "Reserved device IDs: "; + s << "Reserved device IDs: "; + for (int i = 0; i < reserved_ids_info.ids_size(); i++) { if(i) { - cout << ", "; + s << ", "; } - cout << reserved_ids_info.ids(i); + + s << reserved_ids_info.ids(i); } - cout < image_files = { image_files_info.image_files().begin(), image_files_info.image_files().end() }; image_files.sort([](const auto& a, const auto& b) { return a.name() < b.name(); }); - cout << "Available image files:" << endl; + s << "Available image files:\n"; for (const auto& image_file : image_files) { - cout << " "; - DisplayImageFile(image_file); + s << " "; + + s << DisplayImageFile(image_file); } } + + return s.str(); } -void RasctlDisplay::DisplayNetworkInterfaces(const PbNetworkInterfacesInfo& network_interfaces_info) const +string RasctlDisplay::DisplayNetworkInterfaces(const PbNetworkInterfacesInfo& network_interfaces_info) const { - // Creates a sorted list - const list interfaces = { network_interfaces_info.name().begin(), network_interfaces_info.name().end() }; + ostringstream s; + + s << "Available (up) network interfaces:\n"; + + const list sorted_interfaces = { network_interfaces_info.name().begin(), network_interfaces_info.name().end() }; - cout << "Available (up) network interfaces:" << endl; bool isFirst = true; - for (const auto& interface : interfaces) { + for (const auto& interface : sorted_interfaces) { if (!isFirst) { - cout << ", "; + s << ", "; } else { - cout << " "; + s << " "; } + isFirst = false; - cout << interface; + s << interface; } - cout << endl; + + s << '\n'; + + return s.str(); } -void RasctlDisplay::DisplayMappingInfo(const PbMappingInfo& mapping_info) const +string RasctlDisplay::DisplayMappingInfo(const PbMappingInfo& mapping_info) const { - // Creates a sorted map - const map mappings = { mapping_info.mapping().begin(), mapping_info.mapping().end() }; + ostringstream s; - cout << "Supported image file extension to device type mappings:" << endl; - for (const auto& [extension, type] : mappings) { - cout << " " << extension << "->" << PbDeviceType_Name(type) << endl; + s << "Supported image file extension to device type mappings:\n"; + + const map> sorted_mappings = { mapping_info.mapping().begin(), mapping_info.mapping().end() }; + + for (const auto& [extension, type] : sorted_mappings) { + s << " " << extension << "->" << PbDeviceType_Name(type) << '\n'; } + + return s.str(); } -void RasctlDisplay::DisplayOperationInfo(const PbOperationInfo& operation_info) const +string RasctlDisplay::DisplayOperationInfo(const PbOperationInfo& operation_info) const { - const map operations = { operation_info.operations().begin(), operation_info.operations().end() }; + ostringstream s; + + const map> operations = { operation_info.operations().begin(), operation_info.operations().end() }; // Copies result into a map sorted by operation name - const PbOperationMetaData *unknown_operation = new PbOperationMetaData(); - map sorted_operations; + auto unknown_operation = make_unique(); + map> sorted_operations; + for (const auto& [ordinal, meta_data] : operations) { if (PbOperation_IsValid(static_cast(ordinal))) { sorted_operations[PbOperation_Name(static_cast(ordinal))] = meta_data; @@ -289,46 +297,149 @@ void RasctlDisplay::DisplayOperationInfo(const PbOperationInfo& operation_info) } } - cout << "Operations supported by rascsi server and their parameters:" << endl; + s << "Operations supported by rascsi server and their parameters:\n"; for (const auto& [name, meta_data] : sorted_operations) { if (!meta_data.server_side_name().empty()) { - cout << " " << name; + s << " " << name; if (!meta_data.description().empty()) { - cout << " (" << meta_data.description() << ")"; + s << " (" << meta_data.description() << ")"; } - cout << endl; + s << '\n'; - list sorted_parameters = { meta_data.parameters().begin(), meta_data.parameters().end() }; - sorted_parameters.sort([](const auto& a, const auto& b) { return a.name() < b.name(); }); - - for (const auto& parameter : sorted_parameters) { - cout << " " << parameter.name() << ": " - << (parameter.is_mandatory() ? "mandatory" : "optional"); - if (!parameter.description().empty()) { - cout << " (" << parameter.description() << ")"; - } - cout << endl; - - if (parameter.permitted_values_size()) { - cout << " Permitted values: "; - bool isFirst = true; - for (const auto& permitted_value : parameter.permitted_values()) { - if (!isFirst) { - cout << ", "; - } - isFirst = false; - cout << permitted_value; - } - cout << endl; - } - - if (!parameter.default_value().empty()) { - cout << " Default value: " << parameter.default_value() << endl; - } - } + DisplayParameters(s, meta_data); } else { - cout << " " << name << " (Unknown server-side operation)" << endl; + s << " " << name << " (Unknown server-side operation)\n"; + } + } + + return s.str(); +} + +void RasctlDisplay::DisplayParams(ostringstream& s, const PbDevice& pb_device) const +{ + const map> sorted_params = { pb_device.params().begin(), pb_device.params().end() }; + + bool isFirst = true; + for (const auto& [key, value] : sorted_params) { + if (!isFirst) { + s << ":"; + } + + isFirst = false; + s << key << "=" << value; + } +} + +void RasctlDisplay::DisplayAttributes(ostringstream& s, const PbDeviceProperties& properties) const +{ + if (properties.read_only() || properties.protectable() || properties.stoppable() || properties.lockable()) { + s << "Properties: "; + + bool has_property = false; + + if (properties.read_only()) { + s << "read-only"; + has_property = true; + } + + if (properties.protectable()) { + s << (has_property ? ", " : "") << "protectable"; + has_property = true; + } + if (properties.stoppable()) { + s << (has_property ? ", " : "") << "stoppable"; + has_property = true; + } + if (properties.removable()) { + s << (has_property ? ", " : "") << "removable"; + has_property = true; + } + if (properties.lockable()) { + s << (has_property ? ", " : "") << "lockable"; + } + + s << "\n "; + } +} + +void RasctlDisplay::DisplayDefaultParameters(ostringstream& s, const PbDeviceProperties& properties) const +{ + if (properties.supports_params() && properties.default_params_size()) { + s << "Default parameters: "; + + const map> sorted_params = { properties.default_params().begin(), properties.default_params().end() }; + + bool isFirst = true; + for (const auto& [key, value] : sorted_params) { + if (!isFirst) { + s << "\n "; + } + s << key << "=" << value; + + isFirst = false; + } + } + +} + +void RasctlDisplay::DisplayBlockSizes(ostringstream& s, const PbDeviceProperties& properties) const +{ + if (properties.block_sizes_size()) { + s << "Configurable block sizes in bytes: "; + + const set sorted_sizes = { properties.block_sizes().begin(), properties.block_sizes().end() }; + + bool isFirst = true; + for (const auto& size : sorted_sizes) { + if (!isFirst) { + s << ", "; + } + s << size; + + isFirst = false; } } } + +void RasctlDisplay::DisplayParameters(ostringstream& s, const PbOperationMetaData& meta_data) const +{ + list sorted_parameters = { meta_data.parameters().begin(), meta_data.parameters().end() }; + sorted_parameters.sort([](const auto& a, const auto& b) { return a.name() < b.name(); }); + + for (const auto& parameter : sorted_parameters) { + s << " " << parameter.name() << ": " + << (parameter.is_mandatory() ? "mandatory" : "optional"); + + if (!parameter.description().empty()) { + s << " (" << parameter.description() << ")"; + } + s << '\n'; + + DisplayPermittedValues(s, parameter); + + if (!parameter.default_value().empty()) { + s << " Default value: " << parameter.default_value() << '\n'; + } + } +} + +void RasctlDisplay::DisplayPermittedValues(ostringstream& s, const PbOperationParameter& parameter) const +{ + if (parameter.permitted_values_size()) { + s << " Permitted values: "; + + bool isFirst = true; + + for (const auto& permitted_value : parameter.permitted_values()) { + if (!isFirst) { + s << ", "; + } + + isFirst = false; + s << permitted_value; + } + + s << '\n'; + } +} diff --git a/src/raspberrypi/rasctl/rasctl_display.h b/src/raspberrypi/rasctl/rasctl_display.h index 2ad32df9..b944f4b1 100644 --- a/src/raspberrypi/rasctl/rasctl_display.h +++ b/src/raspberrypi/rasctl/rasctl_display.h @@ -10,25 +10,37 @@ #pragma once #include "rascsi_interface.pb.h" +#include +#include +using namespace std; using namespace rascsi_interface; class RasctlDisplay { - friend class RasctlCommands; +public: RasctlDisplay() = default; ~RasctlDisplay() = default; - void DisplayDevices(const PbDevicesInfo&) const; - void DisplayDeviceInfo(const PbDevice&) const; - void DisplayVersionInfo(const PbVersionInfo&) const; - void DisplayLogLevelInfo(const PbLogLevelInfo&) const; - void DisplayDeviceTypesInfo(const PbDeviceTypesInfo&) const; - void DisplayReservedIdsInfo(const PbReservedIdsInfo&) const; - void DisplayImageFile(const PbImageFile&) const; - void DisplayImageFiles(const PbImageFilesInfo&) const; - void DisplayNetworkInterfaces(const PbNetworkInterfacesInfo&) const; - void DisplayMappingInfo(const PbMappingInfo&) const; - void DisplayOperationInfo(const PbOperationInfo&) const; + string DisplayDevicesInfo(const PbDevicesInfo&) const; + string DisplayDeviceInfo(const PbDevice&) const; + string DisplayVersionInfo(const PbVersionInfo&) const; + string DisplayLogLevelInfo(const PbLogLevelInfo&) const; + string DisplayDeviceTypesInfo(const PbDeviceTypesInfo&) const; + string DisplayReservedIdsInfo(const PbReservedIdsInfo&) const; + string DisplayImageFile(const PbImageFile&) const; + string DisplayImageFilesInfo(const PbImageFilesInfo&) const; + string DisplayNetworkInterfaces(const PbNetworkInterfacesInfo&) const; + string DisplayMappingInfo(const PbMappingInfo&) const; + string DisplayOperationInfo(const PbOperationInfo&) const; + +private: + + void DisplayParams(ostringstream&, const PbDevice&) const; + void DisplayAttributes(ostringstream&, const PbDeviceProperties&) const; + void DisplayDefaultParameters(ostringstream&, const PbDeviceProperties&) const; + void DisplayBlockSizes(ostringstream&, const PbDeviceProperties&) const; + void DisplayParameters(ostringstream&, const PbOperationMetaData&) const; + void DisplayPermittedValues(ostringstream&, const PbOperationParameter&) const; }; diff --git a/src/raspberrypi/rasctl/rasctl_parser.cpp b/src/raspberrypi/rasctl/rasctl_parser.cpp new file mode 100644 index 00000000..23fbe4f3 --- /dev/null +++ b/src/raspberrypi/rasctl/rasctl_parser.cpp @@ -0,0 +1,31 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "rasctl_parser.h" + + +PbOperation RasctlParser::ParseOperation(const string& operation) const +{ + const auto& it = operations.find(tolower(operation[0])); + return it != operations.end() ? it->second : NO_OPERATION; +} + +PbDeviceType RasctlParser::ParseType(const string& type) const +{ + string t = type; + transform(t.begin(), t.end(), t.begin(), ::toupper); + + if (PbDeviceType parsed_type; PbDeviceType_Parse(t, &parsed_type)) { + return parsed_type; + } + + // Handle convenience device types (shortcuts) + const auto& it = device_types.find(tolower(type[0])); + return it != device_types.end() ? it->second : UNDEFINED; +} diff --git a/src/raspberrypi/rasctl/rasctl_parser.h b/src/raspberrypi/rasctl/rasctl_parser.h new file mode 100644 index 00000000..7f3e5f06 --- /dev/null +++ b/src/raspberrypi/rasctl/rasctl_parser.h @@ -0,0 +1,49 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "rascsi_interface.pb.h" +#include +#include + +using namespace std; +using namespace rascsi_interface; + +class RasctlParser +{ + +public: + + RasctlParser() = default; + ~RasctlParser() = default; + + PbOperation ParseOperation(const string&) const; + PbDeviceType ParseType(const string&) const; + +private: + + unordered_map operations = { + { 'a', ATTACH }, + { 'd', DETACH }, + { 'i', INSERT }, + { 'e', EJECT }, + { 'p', PROTECT }, + { 'u', UNPROTECT } + }; + + unordered_map device_types = { + { 'b', SCBR }, + { 'c', SCCD }, + { 'd', SCDP }, + { 'h', SCHD }, + { 'l', SCLP }, + { 'm', SCMO }, + { 'r', SCRM }, + { 's', SCHS } + }; +}; diff --git a/src/raspberrypi/rasdump.cpp b/src/raspberrypi/rasdump.cpp index 188ef8b3..348decd4 100644 --- a/src/raspberrypi/rasdump.cpp +++ b/src/raspberrypi/rasdump.cpp @@ -217,7 +217,7 @@ bool ParseArgument(int argc, char* argv[]) bool WaitPhase(BUS::phase_t phase) { // Timeout (3000ms) - uint32_t now = SysTimer::GetTimerLow(); + const uint32_t now = SysTimer::GetTimerLow(); while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { bus.Acquire(); if (bus.GetREQ() && bus.GetPhase() == phase) { @@ -246,21 +246,17 @@ void BusFree() //--------------------------------------------------------------------------- bool Selection(int id) { - BYTE data; - int count; - // ID setting and SEL assert - data = 0; - data |= (1 << boardid); + BYTE data = 1 << boardid; data |= (1 << id); bus.SetDAT(data); bus.SetSEL(true); // wait for busy - count = 10000; + int count = 10000; do { // Wait 20 microseconds - timespec ts = { .tv_sec = 0, .tv_nsec = 20 * 1000}; + const timespec ts = { .tv_sec = 0, .tv_nsec = 20 * 1000}; nanosleep(&ts, nullptr); bus.Acquire(); if (bus.GetBSY()) { @@ -282,15 +278,13 @@ bool Selection(int id) //--------------------------------------------------------------------------- bool Command(BYTE *buf, int length) { - int count; - // Waiting for Phase if (!WaitPhase(BUS::phase_t::command)) { return false; } // Send Command - count = bus.SendHandShake(buf, length, BUS::SEND_NO_DELAY); + const int count = bus.SendHandShake(buf, length, BUS::SEND_NO_DELAY); // Success if the transmission result is the same as the number // of requests @@ -665,7 +659,7 @@ exit: // READ10 // //--------------------------------------------------------------------------- -int Read10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) +int Read10(int id, uint32_t bstart, uint32_t blength, uint32_t length, BYTE *buf) { array cmd = {}; @@ -728,7 +722,7 @@ exit: // WRITE10 // //--------------------------------------------------------------------------- -int Write10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) +int Write10(int id, uint32_t bstart, uint32_t blength, uint32_t length, BYTE *buf) { array cmd = {}; @@ -794,13 +788,12 @@ exit: int main(int argc, char* argv[]) { int i; - int count; char str[32]; - DWORD bsiz; - DWORD bnum; - DWORD duni; - DWORD dsiz; - DWORD dnum; + uint32_t bsiz; + uint32_t bnum; + uint32_t duni; + uint32_t dsiz; + uint32_t dnum; Fileio fio; Fileio::OpenMode omode; off_t size; @@ -855,7 +848,7 @@ int main(int argc, char* argv[]) // Assert reset signal bus.SetRST(true); // Wait 1 ms - timespec ts = { .tv_sec = 0, .tv_nsec = 1000 * 1000}; + const timespec ts = { .tv_sec = 0, .tv_nsec = 1000 * 1000}; nanosleep(&ts, nullptr); bus.SetRST(false); @@ -864,7 +857,7 @@ int main(int argc, char* argv[]) printf("BOARD ID : %d\n", boardid); // TEST UNIT READY - count = TestUnitReady(targetid); + int count = TestUnitReady(targetid); if (count < 0) { fprintf(stderr, "TEST UNIT READY ERROR %d\n", count); goto cleanup_exit; diff --git a/src/raspberrypi/rasutil.cpp b/src/raspberrypi/rasutil.cpp index 20605b8c..a6f19799 100644 --- a/src/raspberrypi/rasutil.cpp +++ b/src/raspberrypi/rasutil.cpp @@ -7,10 +7,9 @@ // //--------------------------------------------------------------------------- -#include -#include -#include "rascsi_interface.pb.h" +#include "rascsi_version.h" #include "rasutil.h" +#include using namespace std; using namespace rascsi_interface; @@ -35,16 +34,30 @@ bool ras_util::GetAsInt(const string& value, int& result) return true; } + +string ras_util::Banner(const string& app) +{ + ostringstream s; + + s << "SCSI Target Emulator RaSCSI " << app << " version " << rascsi_get_version_string() + << " (" << __DATE__ << ' ' << __TIME__ << ")\n"; + s << "Powered by XM6 TypeG Technology / "; + s << "Copyright (C) 2016-2020 GIMONS\n"; + s << "Copyright (C) 2020-2022 Contributors to the RaSCSI Reloaded project\n"; + + return s.str(); +} + string ras_util::ListDevices(const list& pb_devices) { if (pb_devices.empty()) { - return "No devices currently attached."; + return "No devices currently attached.\n"; } ostringstream s; - s << "+----+-----+------+-------------------------------------" << endl - << "| ID | LUN | TYPE | IMAGE FILE" << endl - << "+----+-----+------+-------------------------------------" << endl; + s << "+----+-----+------+-------------------------------------\n" + << "| ID | LUN | TYPE | IMAGE FILE\n" + << "+----+-----+------+-------------------------------------\n"; list devices = pb_devices; devices.sort([](const auto& a, const auto& b) { return a.id() < b.id() || a.unit() < b.unit(); }); @@ -76,10 +89,10 @@ string ras_util::ListDevices(const list& pb_devices) s << "| " << device.id() << " | " << device.unit() << " | " << PbDeviceType_Name(device.type()) << " | " << (filename.empty() ? "NO MEDIA" : filename) << (!device.status().removed() && (device.properties().read_only() || device.status().protected_()) ? " (READ-ONLY)" : "") - << endl; + << '\n'; } - s << "+----+-----+------+-------------------------------------"; + s << "+----+-----+------+-------------------------------------\n"; return s.str(); } diff --git a/src/raspberrypi/rasutil.h b/src/raspberrypi/rasutil.h index e71c10dd..2fff46de 100644 --- a/src/raspberrypi/rasutil.h +++ b/src/raspberrypi/rasutil.h @@ -15,10 +15,13 @@ #include #include "rascsi_interface.pb.h" +using namespace std; + namespace ras_util { - bool GetAsInt(const std::string&, int&); - std::string ListDevices(const std::list&); + bool GetAsInt(const string&, int&); + string Banner(const string&); + string ListDevices(const list&); void FixCpu(int); } diff --git a/src/raspberrypi/scsi.h b/src/raspberrypi/scsi.h index b57e4cef..e44e9825 100644 --- a/src/raspberrypi/scsi.h +++ b/src/raspberrypi/scsi.h @@ -33,6 +33,7 @@ namespace scsi_defs { COMMUNICATIONS = 9 }; + // TODO Use a mapping of enum to structure with command byte count and enum name enum class scsi_command : int { eCmdTestUnitReady = 0x00, eCmdRezero = 0x01, diff --git a/src/raspberrypi/scsimon.cpp b/src/raspberrypi/scsimon.cpp index f28d63b4..c5b55c95 100644 --- a/src/raspberrypi/scsimon.cpp +++ b/src/raspberrypi/scsimon.cpp @@ -35,9 +35,9 @@ static const int _MAX_FNAME = 256; static volatile bool running; // Running flag GPIOBUS bus; // GPIO Bus -DWORD buff_size = 1000000; +uint32_t buff_size = 1000000; data_capture *data_buffer; -DWORD data_idx = 0; +uint32_t data_idx = 0; double ns_per_loop; @@ -94,8 +94,7 @@ void parse_arguments(int argc, char *argv[]) } /* Process any remaining command line arguments (not options). */ - if (optind < argc) - { + if (optind < argc) { while (optind < argc) strncpy(file_base_name, argv[optind++], sizeof(file_base_name)-1); } @@ -147,12 +146,10 @@ void print_help_text(int, char *argv[]) //--------------------------------------------------------------------------- void Banner(int, char *[]) { - if (import_data) - { + if (import_data) { LOGINFO("Reading input file: %s", input_file_name) } - else - { + else { LOGINFO("Reading live data from the GPIO pins") LOGINFO(" Connection type : %s", CONNECT_DESC.c_str()) } @@ -172,16 +169,13 @@ void Banner(int, char *[]) bool Init() { // Interrupt handler settings - if (signal(SIGINT, KillHandler) == SIG_ERR) - { + if (signal(SIGINT, KillHandler) == SIG_ERR) { return false; } - if (signal(SIGHUP, KillHandler) == SIG_ERR) - { + if (signal(SIGHUP, KillHandler) == SIG_ERR) { return false; } - if (signal(SIGTERM, KillHandler) == SIG_ERR) - { + if (signal(SIGTERM, KillHandler) == SIG_ERR) { return false; } @@ -249,8 +243,8 @@ void FixCpu(int cpu) #endif #ifdef DEBUG -static DWORD high_bits = 0x0; -static DWORD low_bits = 0xFFFFFFFF; +static uint32_t high_bits = 0x0; +static uint32_t low_bits = 0xFFFFFFFF; #endif //--------------------------------------------------------------------------- @@ -272,12 +266,12 @@ int main(int argc, char *argv[]) parse_arguments(argc, argv); #ifdef DEBUG - DWORD prev_high = high_bits; - DWORD prev_low = low_bits; + uint32_t prev_high = high_bits; + uint32_t prev_low = low_bits; #endif ostringstream s; - DWORD prev_sample = 0xFFFFFFFF; - DWORD this_sample = 0; + uint32_t prev_sample = 0xFFFFFFFF; + uint32_t this_sample = 0; timeval start_time; timeval stop_time; uint64_t loop_count = 0; @@ -312,8 +306,7 @@ int main(int argc, char *argv[]) // Initialize int ret = 0; - if (!Init()) - { + if (!Init()) { ret = EPERM; goto init_exit; } diff --git a/src/raspberrypi/test/abstract_controller_test.cpp b/src/raspberrypi/test/abstract_controller_test.cpp index 85ca262d..9618db63 100644 --- a/src/raspberrypi/test/abstract_controller_test.cpp +++ b/src/raspberrypi/test/abstract_controller_test.cpp @@ -75,10 +75,10 @@ TEST(AbstractControllerTest, ProcessPhase) controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::reselection); - EXPECT_THROW(controller.ProcessPhase(), scsi_error_exception); + EXPECT_THROW(controller.ProcessPhase(), scsi_exception); controller.SetPhase(BUS::phase_t::reserved); - EXPECT_THROW(controller.ProcessPhase(), scsi_error_exception); + EXPECT_THROW(controller.ProcessPhase(), scsi_exception); } TEST(AbstractControllerTest, DeviceLunLifeCycle) diff --git a/src/raspberrypi/test/bus_test.cpp b/src/raspberrypi/test/bus_test.cpp new file mode 100644 index 00000000..02df56e7 --- /dev/null +++ b/src/raspberrypi/test/bus_test.cpp @@ -0,0 +1,89 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" +#include "bus.h" + +TEST(BusTest, GetPhase) +{ + EXPECT_EQ(BUS::phase_t::dataout, BUS::GetPhase(0b000)); + EXPECT_EQ(BUS::phase_t::datain, BUS::GetPhase(0b001)); + EXPECT_EQ(BUS::phase_t::command, BUS::GetPhase(0b010)); + EXPECT_EQ(BUS::phase_t::status, BUS::GetPhase(0b011)); + EXPECT_EQ(BUS::phase_t::reserved, BUS::GetPhase(0b100)); + EXPECT_EQ(BUS::phase_t::reserved, BUS::GetPhase(0b101)); + EXPECT_EQ(BUS::phase_t::msgout, BUS::GetPhase(0b110)); + EXPECT_EQ(BUS::phase_t::msgin, BUS::GetPhase(0b111)); + + NiceMock bus; + + EXPECT_EQ(BUS::phase_t::busfree, bus.GetPhase()); + + ON_CALL(bus, GetSEL()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::selection, bus.GetPhase()); + + ON_CALL(bus, GetSEL()).WillByDefault(Return(false)); + ON_CALL(bus, GetBSY()).WillByDefault(Return(true)); + + ON_CALL(bus, GetMSG()).WillByDefault(Return(false)); + EXPECT_EQ(BUS::phase_t::dataout, bus.GetPhase()); + ON_CALL(bus, GetMSG()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::reserved, bus.GetPhase()); + + ON_CALL(bus, GetMSG()).WillByDefault(Return(false)); + ON_CALL(bus, GetCD()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::command, bus.GetPhase()); + + ON_CALL(bus, GetMSG()).WillByDefault(Return(true)); + ON_CALL(bus, GetCD()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::msgout, bus.GetPhase()); + + ON_CALL(bus, GetMSG()).WillByDefault(Return(false)); + ON_CALL(bus, GetCD()).WillByDefault(Return(false)); + ON_CALL(bus, GetIO()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::datain, bus.GetPhase()); + + ON_CALL(bus, GetMSG()).WillByDefault(Return(true)); + ON_CALL(bus, GetCD()).WillByDefault(Return(false)); + ON_CALL(bus, GetIO()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::reserved, bus.GetPhase()); + + ON_CALL(bus, GetMSG()).WillByDefault(Return(true)); + ON_CALL(bus, GetCD()).WillByDefault(Return(true)); + ON_CALL(bus, GetIO()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::msgin, bus.GetPhase()); + + ON_CALL(bus, GetMSG()).WillByDefault(Return(false)); + ON_CALL(bus, GetCD()).WillByDefault(Return(true)); + ON_CALL(bus, GetIO()).WillByDefault(Return(true)); + EXPECT_EQ(BUS::phase_t::status, bus.GetPhase()); +} + +TEST(BusTest, GetPhaseStrRaw) +{ + EXPECT_STREQ("busfree", BUS::GetPhaseStrRaw(BUS::phase_t::busfree)); + EXPECT_STREQ("arbitration", BUS::GetPhaseStrRaw(BUS::phase_t::arbitration)); + EXPECT_STREQ("selection", BUS::GetPhaseStrRaw(BUS::phase_t::selection)); + EXPECT_STREQ("reselection", BUS::GetPhaseStrRaw(BUS::phase_t::reselection)); + EXPECT_STREQ("command", BUS::GetPhaseStrRaw(BUS::phase_t::command)); + EXPECT_STREQ("datain", BUS::GetPhaseStrRaw(BUS::phase_t::datain)); + EXPECT_STREQ("dataout", BUS::GetPhaseStrRaw(BUS::phase_t::dataout)); + EXPECT_STREQ("status", BUS::GetPhaseStrRaw(BUS::phase_t::status)); + EXPECT_STREQ("msgin", BUS::GetPhaseStrRaw(BUS::phase_t::msgin)); + EXPECT_STREQ("msgout", BUS::GetPhaseStrRaw(BUS::phase_t::msgout)); + EXPECT_STREQ("reserved", BUS::GetPhaseStrRaw(BUS::phase_t::reserved)); +} + +TEST(BusTest, GetPinRaw) +{ + EXPECT_EQ(0, BUS::GetPinRaw(0, 0)); + EXPECT_EQ(0, BUS::GetPinRaw(0, 7)); + EXPECT_EQ(1, BUS::GetPinRaw(-1, 0)); + EXPECT_EQ(1, BUS::GetPinRaw(-1, 7)); +} diff --git a/src/raspberrypi/test/command_context_test.cpp b/src/raspberrypi/test/command_context_test.cpp index 3af97f19..edfa0576 100644 --- a/src/raspberrypi/test/command_context_test.cpp +++ b/src/raspberrypi/test/command_context_test.cpp @@ -7,14 +7,48 @@ // //--------------------------------------------------------------------------- -#include "mocks.h" +#include + #include "rascsi/command_context.h" -using namespace rascsi_interface; +TEST(CommandContext, GetSerializer) +{ + CommandContext context("", -1); + + // There is nothing more that can be tested + context.GetSerializer(); +} + +TEST(CommandContext, IsValid) +{ + CommandContext context("", -1); + + EXPECT_FALSE(context.IsValid()); + + context.SetFd(1); + EXPECT_TRUE(context.IsValid()); +} + +TEST(CommandContext, Cleanup) +{ + CommandContext context("", 0); + + EXPECT_EQ(0, context.GetFd()); + context.Cleanup(); + EXPECT_EQ(-1, context.GetFd()); +} TEST(CommandContext, ReturnLocalizedError) { - MockCommandContext context; + CommandContext context("en_US", -1); EXPECT_FALSE(context.ReturnLocalizedError(LocalizationKey::ERROR_LOG_LEVEL)); } + +TEST(CommandContext, ReturnStatus) +{ + CommandContext context("", -1); + + EXPECT_TRUE(context.ReturnStatus(true, "status")); + EXPECT_FALSE(context.ReturnStatus(false, "status")); +} diff --git a/src/raspberrypi/test/controller_manager_test.cpp b/src/raspberrypi/test/controller_manager_test.cpp index 0297a5db..4a8eebc3 100644 --- a/src/raspberrypi/test/controller_manager_test.cpp +++ b/src/raspberrypi/test/controller_manager_test.cpp @@ -21,8 +21,11 @@ TEST(ControllerManagerTest, LifeCycle) ControllerManager controller_manager(bus); DeviceFactory device_factory; - auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, LUN1, "services"); - controller_manager.AttachToScsiController(ID, device); + auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, -1, "services"); + EXPECT_FALSE(controller_manager.AttachToScsiController(ID, device)); + + device = device_factory.CreateDevice(controller_manager, UNDEFINED, LUN1, "services"); + EXPECT_TRUE(controller_manager.AttachToScsiController(ID, device)); auto controller = controller_manager.FindController(ID); EXPECT_NE(nullptr, controller); EXPECT_EQ(1, controller->GetLunCount()); @@ -33,9 +36,9 @@ TEST(ControllerManagerTest, LifeCycle) EXPECT_EQ(nullptr, controller_manager.GetDeviceByIdAndLun(0, 0)); device = device_factory.CreateDevice(controller_manager, UNDEFINED, LUN2, "services"); - controller_manager.AttachToScsiController(ID, device); + EXPECT_TRUE(controller_manager.AttachToScsiController(ID, device)); controller = controller_manager.FindController(ID); - controller_manager.DeleteController(controller); + EXPECT_TRUE(controller_manager.DeleteController(controller)); EXPECT_EQ(nullptr, controller_manager.FindController(ID)); controller_manager.DeleteAllControllers(); @@ -52,7 +55,7 @@ TEST(ControllerManagerTest, ResetAllControllers) DeviceFactory device_factory; auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "services"); - controller_manager.AttachToScsiController(ID, device); + EXPECT_TRUE(controller_manager.AttachToScsiController(ID, device)); auto controller = controller_manager.FindController(ID); EXPECT_NE(nullptr, controller); diff --git a/src/raspberrypi/test/disk_test.cpp b/src/raspberrypi/test/disk_test.cpp index 89429295..92c04d16 100644 --- a/src/raspberrypi/test/disk_test.cpp +++ b/src/raspberrypi/test/disk_test.cpp @@ -22,10 +22,8 @@ TEST(DiskTest, Dispatch) controller.AddDevice(disk); - controller.InitCmd(6); - disk->MediumChanged(); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdTestUnitReady), scsi_error_exception); + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception); } TEST(DiskTest, Rezero) @@ -35,7 +33,7 @@ TEST(DiskTest, Rezero) controller.AddDevice(disk); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRezero), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRezero), scsi_exception) << "REZERO must fail because drive is not ready"; disk->SetReady(true); @@ -54,7 +52,7 @@ TEST(DiskTest, FormatUnit) vector& cmd = controller.InitCmd(6); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdFormat), scsi_error_exception); + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdFormat), scsi_exception); disk->SetReady(true); @@ -64,7 +62,7 @@ TEST(DiskTest, FormatUnit) cmd[1] = 0x10; cmd[4] = 1; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdFormat), scsi_error_exception); + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdFormat), scsi_exception); } TEST(DiskTest, ReassignBlocks) @@ -74,7 +72,7 @@ TEST(DiskTest, ReassignBlocks) controller.AddDevice(disk); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReassign), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReassign), scsi_exception) << "REASSIGN must fail because drive is not ready"; disk->SetReady(true); @@ -93,15 +91,15 @@ TEST(DiskTest, Seek) vector& cmd = controller.InitCmd(10); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek6), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek6), scsi_exception) << "SEEK(6) must fail for a medium with 0 blocks"; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek10), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek10), scsi_exception) << "SEEK(10) must fail for a medium with 0 blocks"; disk->SetBlockCount(1); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek6), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek6), scsi_exception) << "SEEK(6) must fail because drive is not ready"; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek10), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek10), scsi_exception) << "SEEK(10) must fail because drive is not ready"; disk->SetReady(true); @@ -129,23 +127,23 @@ TEST(DiskTest, ReadCapacity) vector& cmd = controller.InitCmd(16); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception) << "Neithed READ CAPACITY(16) nor READ LONG(16)"; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity10), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity10), scsi_exception) << "READ CAPACITY(10) must fail because drive is not ready"; // READ CAPACITY(16), not READ LONG(16) cmd[1] = 0x10; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception) << "READ CAPACITY(16) must fail because drive is not ready"; cmd[1] = 0x00; disk->SetReady(true); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity10), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity10), scsi_exception) << "READ CAPACITY(10) must fail because the medium has no capacity"; // READ CAPACITY(16), not READ LONG(16) cmd[1] = 0x10; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception) << "READ CAPACITY(16) must fail because the medium has no capacity"; cmd[1] = 0x00; @@ -201,22 +199,22 @@ TEST(DiskTest, ReadWriteLong) EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[2] = 1; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadLong10), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadLong10), scsi_exception) << "READ LONG(10) must fail because the capacity is exceeded"; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong10), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong10), scsi_exception) << "WRITE LONG(10) must fail because the capacity is exceeded"; // READ LONG(16), not READ CAPACITY(16) cmd[1] = 0x11; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception) << "READ LONG(16) must fail because the capacity is exceeded"; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong16), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong16), scsi_exception) << "WRITE LONG(16) must fail because the capacity is exceeded"; cmd[2] = 0; cmd[7] = 1; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadLong10), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadLong10), scsi_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) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong10), scsi_exception) << "WRITE LONG(10) must fail because it currently only supports 0 bytes transfer length"; cmd[7] = 0; @@ -233,25 +231,31 @@ TEST(DiskTest, ReadWriteLong) cmd[13] = 1; // READ LONG(16), not READ CAPACITY(16) cmd[1] = 0x11; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception) << "READ LONG(16) must fail because it currently only supports 0 bytes transfer length"; cmd[1] = 0x00; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong16), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong16), scsi_exception) << "WRITE LONG(16) must fail because it currently only supports 0 bytes transfer length"; } -TEST(DiskTest, ReserveRelease) +TEST(DiskTest, Reserve) { MockAbstractController controller(0); auto disk = make_shared(); controller.AddDevice(disk); - controller.InitCmd(6); - EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReserve6)); EXPECT_EQ(status::GOOD, controller.GetStatus()); +} + +TEST(DiskTest, Release) +{ + MockAbstractController controller(0); + auto disk = make_shared(); + + controller.AddDevice(disk); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdRelease6)); @@ -272,16 +276,16 @@ TEST(DiskTest, SendDiagnostic) EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[1] = 0x10; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSendDiag), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSendDiag), scsi_exception) << "SEND DIAGNOSTIC must fail because PF bit is not supported"; cmd[1] = 0; cmd[3] = 1; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSendDiag), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSendDiag), scsi_exception) << "SEND DIAGNOSTIC must fail because parameter list is not supported"; cmd[3] = 0; cmd[4] = 1; - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSendDiag), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSendDiag), scsi_exception) << "SEND DIAGNOSTIC must fail because parameter list is not supported"; } @@ -294,7 +298,7 @@ TEST(DiskTest, PreventAllowMediumRemoval) vector& cmd = controller.InitCmd(6); - EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRemoval), scsi_error_exception) + EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRemoval), scsi_exception) << "REMOVAL must fail because drive is not ready"; disk->SetReady(true); @@ -318,15 +322,11 @@ TEST(DiskTest, SynchronizeCache) controller.AddDevice(disk); - controller.InitCmd(10); - EXPECT_CALL(*disk, FlushCache()).Times(1); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSynchronizeCache10)); EXPECT_EQ(status::GOOD, controller.GetStatus()); - controller.InitCmd(16); - EXPECT_CALL(*disk, FlushCache()).Times(1); EXPECT_CALL(controller, Status()).Times(1); EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSynchronizeCache16)); @@ -410,3 +410,46 @@ TEST(DiskTest, BlockCount) disk.SetBlockCount(0x1234567887654321); EXPECT_EQ(0x1234567887654321, disk.GetBlockCount()); } + +TEST(DiskTest, GetIdsForReservedFile) +{ + const int ID = 1; + const int LUN = 2; + + Filepath path; + path.SetPath("path"); + MockDisk disk; + + disk.SetPath(path); + Filepath result; + disk.GetPath(result); + EXPECT_STREQ("path", result.GetPath()); + + int id; + int lun; + EXPECT_FALSE(Disk::GetIdsForReservedFile(path, id, lun)); + + disk.ReserveFile(path, ID, LUN); + EXPECT_TRUE(Disk::GetIdsForReservedFile(path, id, lun)); + EXPECT_EQ(ID, id); + EXPECT_EQ(LUN, lun); + + disk.UnreserveFile(); + EXPECT_FALSE(Disk::GetIdsForReservedFile(path, id, lun)); +} + +TEST(DiskTest, UnreserveAll) +{ + const int ID = 2; + const int LUN = 31; + + Filepath path; + path.SetPath("path"); + MockDisk disk; + + disk.ReserveFile(path, ID, LUN); + Disk::UnreserveAll(); + int id; + int lun; + EXPECT_FALSE(Disk::GetIdsForReservedFile(path, id, lun)); +} diff --git a/src/raspberrypi/test/file_support_test.cpp b/src/raspberrypi/test/file_support_test.cpp deleted file mode 100644 index 08ca9396..00000000 --- a/src/raspberrypi/test/file_support_test.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator RaSCSI Reloaded -// for Raspberry Pi -// -// Copyright (C) 2022 Uwe Seimet -// -//--------------------------------------------------------------------------- - -#include "mocks.h" -#include "devices/file_support.h" - -class TestFileSupport : public FileSupport -{ - void Open(const Filepath&) final { - // Do nothing when running unit tests - } -}; - -TEST(FileSupportTest, Reserve) -{ - const int ID = 1; - const int LUN = 2; - - Filepath path; - path.SetPath("path"); - TestFileSupport file_support; - - file_support.SetPath(path); - Filepath result; - file_support.GetPath(result); - EXPECT_STREQ("path", result.GetPath()); - - int id; - int lun; - EXPECT_FALSE(FileSupport::GetIdsForReservedFile(path, id, lun)); - - file_support.ReserveFile(path, ID, LUN); - EXPECT_TRUE(FileSupport::GetIdsForReservedFile(path, id, lun)); - EXPECT_EQ(ID, id); - EXPECT_EQ(LUN, lun); - - file_support.UnreserveFile(); - EXPECT_FALSE(FileSupport::GetIdsForReservedFile(path, id, lun)); -} - -TEST(FileSupportTest, UnreserveAll) -{ - const int ID = 2; - const int LUN = 31; - - Filepath path; - path.SetPath("path"); - TestFileSupport file_support; - - file_support.ReserveFile(path, ID, LUN); - FileSupport::UnreserveAll(); - int id; - int lun; - EXPECT_FALSE(FileSupport::GetIdsForReservedFile(path, id, lun)); -} diff --git a/src/raspberrypi/test/host_services_test.cpp b/src/raspberrypi/test/host_services_test.cpp new file mode 100644 index 00000000..b086d841 --- /dev/null +++ b/src/raspberrypi/test/host_services_test.cpp @@ -0,0 +1,149 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" +#include "rascsi_exceptions.h" +#include "controllers/controller_manager.h" +#include "devices/host_services.h" + +using namespace std; + +TEST(HostServicesTest, TestUnitReady) +{ + NiceMock controller(0); + auto services = CreateDevice(SCHS, controller); + + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdTestUnitReady)) << "TEST UNIT READY must never fail"; + EXPECT_EQ(status::GOOD, controller.GetStatus()); +} + +TEST(HostServicesTest, Inquiry) +{ + TestInquiry(SCHS, device_type::PROCESSOR, scsi_level::SPC_3, scsi_level::SCSI_2, + "RaSCSI Host Services ", 0x1f, false); +} + +TEST(HostServicesTest, StartStopUnit) +{ + NiceMock controller(0); + auto services = CreateDevice(SCHS, controller); + + vector& cmd = controller.InitCmd(6); + + // STOP + EXPECT_CALL(controller, ScheduleShutdown(AbstractController::rascsi_shutdown_mode::STOP_RASCSI)).Times(1); + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdStartStop)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); + + // LOAD + cmd[4] = 0x02; + EXPECT_CALL(controller, ScheduleShutdown(AbstractController::rascsi_shutdown_mode::STOP_PI)).Times(1); + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdStartStop)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); + + // UNLOAD + cmd[4] = 0x03; + EXPECT_CALL(controller, ScheduleShutdown(AbstractController::rascsi_shutdown_mode::RESTART_PI)).Times(1); + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdStartStop)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); + + // START + cmd[4] = 0x01; + EXPECT_THROW(services->Dispatch(scsi_command::eCmdStartStop), scsi_exception); +} + +TEST(HostServicesTest, ModeSense6) +{ + NiceMock controller(0); + auto services = CreateDevice(SCHS, controller); + + vector& cmd = controller.InitCmd(6); + + EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense6), scsi_exception) + << "Unsupported mode page was returned"; + + cmd[2] = 0x20; + EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense6), scsi_exception) + << "Block descriptors are not supported"; + + cmd[1] = 0x08; + // ALLOCATION LENGTH + cmd[4] = 255; + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense6)); + vector& buffer = controller.GetBuffer(); + // Major version 1 + EXPECT_EQ(0x01, buffer[6]); + // Minor version 0 + EXPECT_EQ(0x00, buffer[7]); + // Year + EXPECT_NE(0x00, buffer[9]); + // Day + EXPECT_NE(0x00, buffer[10]); + + // ALLOCATION LENGTH + cmd[4] = 2; + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense6)); + buffer = controller.GetBuffer(); + EXPECT_EQ(0x02, buffer[0]); +} + +TEST(HostServicesTest, ModeSense10) +{ + NiceMock controller(0); + auto services = CreateDevice(SCHS, controller); + + vector& cmd = controller.InitCmd(10); + + EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense10), scsi_exception) + << "Unsupported mode page was returned"; + + cmd[2] = 0x20; + EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense10), scsi_exception) + << "Block descriptors are not supported"; + + cmd[1] = 0x08; + // ALLOCATION LENGTH + cmd[8] = 255; + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense10)); + vector& buffer = controller.GetBuffer(); + // Major version 1 + EXPECT_EQ(0x01, buffer[10]); + // Minor version 0 + EXPECT_EQ(0x00, buffer[11]); + // Year + EXPECT_NE(0x00, buffer[13]); + // Day + EXPECT_NE(0x00, buffer[14]); + + // ALLOCATION LENGTH + cmd[8] = 2; + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense10)); + buffer = controller.GetBuffer(); + EXPECT_EQ(0x02, buffer[1]); +} + +TEST(HostServicesTest, SetUpModePages) +{ + MockBus bus; + ControllerManager controller_manager(bus); + MockHostServices services(0, controller_manager); + map> mode_pages; + + services.SetUpModePages(mode_pages, 0x3f, false); + EXPECT_EQ(1, mode_pages.size()) << "Unexpected number of mode pages"; + EXPECT_EQ(10, mode_pages[32].size()); +} diff --git a/src/raspberrypi/test/mocks.h b/src/raspberrypi/test/mocks.h index 0a31281f..3c7ee865 100644 --- a/src/raspberrypi/test/mocks.h +++ b/src/raspberrypi/test/mocks.h @@ -11,6 +11,7 @@ #include +#include "test_shared.h" #include "controllers/scsi_controller.h" #include "devices/primary_device.h" #include "devices/scsihd.h" @@ -20,7 +21,9 @@ #include "devices/host_services.h" #include "rascsi/command_context.h" -class MockBus final : public BUS //NOSONAR Having many fields/methods cannot be avoided +using namespace testing; + +class MockBus : public BUS //NOSONAR Having many fields/methods cannot be avoided { public: @@ -78,8 +81,12 @@ public: using PhaseHandler::PhaseHandler; }; -class MockAbstractController final : public AbstractController //NOSONAR Having many fields/methods cannot be avoided +class MockAbstractController : public AbstractController //NOSONAR Having many fields/methods cannot be avoided { + friend shared_ptr CreateDevice(rascsi_interface::PbDeviceType, AbstractController&, int); + friend void TestInquiry(rascsi_interface::PbDeviceType, scsi_defs::device_type, scsi_defs::scsi_level, + scsi_defs::scsi_level, const std::string&, int, bool); + FRIEND_TEST(AbstractControllerTest, Reset); FRIEND_TEST(AbstractControllerTest, ProcessPhase); FRIEND_TEST(AbstractControllerTest, DeviceLunLifeCycle); @@ -93,6 +100,10 @@ class MockAbstractController final : public AbstractController //NOSONAR Having FRIEND_TEST(PrimaryDeviceTest, RequestSense); FRIEND_TEST(PrimaryDeviceTest, ReportLuns); FRIEND_TEST(PrimaryDeviceTest, UnknownCommand); + FRIEND_TEST(ModePageDeviceTest, ModeSense6); + FRIEND_TEST(ModePageDeviceTest, ModeSense10); + FRIEND_TEST(ModePageDeviceTest, ModeSelect6); + FRIEND_TEST(ModePageDeviceTest, ModeSelect10); FRIEND_TEST(DiskTest, Dispatch); FRIEND_TEST(DiskTest, Rezero); FRIEND_TEST(DiskTest, FormatUnit); @@ -100,7 +111,8 @@ class MockAbstractController final : public AbstractController //NOSONAR Having FRIEND_TEST(DiskTest, Seek); FRIEND_TEST(DiskTest, ReadCapacity); FRIEND_TEST(DiskTest, ReadWriteLong); - FRIEND_TEST(DiskTest, ReserveRelease); + FRIEND_TEST(DiskTest, Reserve); + FRIEND_TEST(DiskTest, Release); FRIEND_TEST(DiskTest, SendDiagnostic); FRIEND_TEST(DiskTest, PreventAllowMediumRemoval); FRIEND_TEST(DiskTest, SynchronizeCache); @@ -128,10 +140,12 @@ public: } ~MockAbstractController() override = default; + vector& InitCmd(int size) { return AbstractController::InitCmd(size); } //NOSONAR Hides function on purpose + MockBus bus; }; -class MockScsiController final : public ScsiController +class MockScsiController : public ScsiController { FRIEND_TEST(ScsiControllerTest, RequestSense); FRIEND_TEST(PrimaryDeviceTest, RequestSense); @@ -150,7 +164,7 @@ public: MockBus bus; }; -class MockDevice final : public Device +class MockDevice : public Device { FRIEND_TEST(DeviceTest, Params); FRIEND_TEST(DeviceTest, StatusCode); @@ -167,7 +181,7 @@ public: ~MockDevice() override = default; }; -class MockPrimaryDevice final : public PrimaryDevice +class MockPrimaryDevice : public PrimaryDevice { FRIEND_TEST(PrimaryDeviceTest, PhaseChange); FRIEND_TEST(PrimaryDeviceTest, TestUnitReady); @@ -185,17 +199,19 @@ public: ~MockPrimaryDevice() override = default; }; -class MockModePageDevice final : public ModePageDevice +class MockModePageDevice : public ModePageDevice { - FRIEND_TEST(ModePagesTest, ModePageDevice_AddModePages); + FRIEND_TEST(ModePageDeviceTest, AddModePages); - explicit MockModePageDevice(int lun) : ModePageDevice("test", lun) {} - ~MockModePageDevice() override = default; +public: MOCK_METHOD(vector, InquiryInternal, (), (const)); MOCK_METHOD(int, ModeSense6, (const vector&, vector&), (const override)); MOCK_METHOD(int, ModeSense10, (const vector&, vector&), (const override)); + explicit MockModePageDevice() : ModePageDevice("test", 0) {} + ~MockModePageDevice() override = default; + void SetUpModePages(map>& pages, int page, bool) const override { // Return dummy data for other pages than page 0 if (page) { @@ -205,7 +221,7 @@ class MockModePageDevice final : public ModePageDevice } }; -class MockDisk final : public Disk +class MockDisk : public Disk { FRIEND_TEST(DiskTest, Rezero); FRIEND_TEST(DiskTest, FormatUnit); @@ -220,6 +236,7 @@ class MockDisk final : public Disk FRIEND_TEST(DiskTest, ReadDefectData); FRIEND_TEST(DiskTest, SectorSize); FRIEND_TEST(DiskTest, BlockCount); + FRIEND_TEST(DiskTest, GetIdsForReservedFile); public: @@ -230,41 +247,39 @@ public: ~MockDisk() override = default; }; -class MockSCSIHD final : public SCSIHD +class MockSCSIHD : public SCSIHD { FRIEND_TEST(DiskTest, ConfiguredSectorSize); - FRIEND_TEST(ModePagesTest, SCSIHD_SetUpModePages); + FRIEND_TEST(ScsiHdTest, SetUpModePages); FRIEND_TEST(RascsiExecutorTest, SetSectorSize); using SCSIHD::SCSIHD; }; -class MockSCSIHD_NEC final : public SCSIHD_NEC //NOSONAR Ignore inheritance hierarchy depth in unit tests +class MockSCSIHD_NEC : public SCSIHD_NEC //NOSONAR Ignore inheritance hierarchy depth in unit tests { - FRIEND_TEST(ModePagesTest, SCSIHD_NEC_SetUpModePages); - - MOCK_METHOD(void, FlushCache, (), (override)); + FRIEND_TEST(ScsiHdNecTest, SetUpModePages); using SCSIHD_NEC::SCSIHD_NEC; }; -class MockSCSICD final : public SCSICD +class MockSCSICD : public SCSICD { - FRIEND_TEST(ModePagesTest, SCSICD_SetUpModePages); + FRIEND_TEST(ScsiCdTest, SetUpModePages); using SCSICD::SCSICD; }; -class MockSCSIMO final : public SCSIMO +class MockSCSIMO : public SCSIMO { - FRIEND_TEST(ModePagesTest, SCSIMO_SetUpModePages); + FRIEND_TEST(ScsiMoTest, SetUpModePages); using SCSIMO::SCSIMO; }; -class MockHostServices final : public HostServices +class MockHostServices : public HostServices { - FRIEND_TEST(ModePagesTest, HostServices_SetUpModePages); + FRIEND_TEST(HostServicesTest, SetUpModePages); using HostServices::HostServices; }; diff --git a/src/raspberrypi/test/mode_page_device_test.cpp b/src/raspberrypi/test/mode_page_device_test.cpp new file mode 100644 index 00000000..2748a1e4 --- /dev/null +++ b/src/raspberrypi/test/mode_page_device_test.cpp @@ -0,0 +1,100 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" +#include "rascsi_exceptions.h" +#include "devices/mode_page_device.h" + +using namespace std; + +TEST(ModePageDeviceTest, AddModePages) +{ + vector cdb(6); + vector buf(512); + MockModePageDevice device; + + cdb[2] = 0x3f; + + EXPECT_EQ(0, device.AddModePages(cdb, buf, 0, -1)) << "Negative maximum length must be rejected"; + EXPECT_EQ(0, device.AddModePages(cdb, buf, 0, 0)) << "Allocation length 0 must be rejected"; + EXPECT_EQ(1, device.AddModePages(cdb, buf, 0, 1)) << "Allocation length 1 must be rejected"; + + cdb[2] = 0x00; + EXPECT_THROW(device.AddModePages(cdb, buf, 0, 12), scsi_exception) + << "Data were returned for non-existing mode page 0"; +} + +TEST(ModePageDeviceTest, ModeSense6) +{ + MockAbstractController controller(0); + auto device = make_shared>(); + + controller.AddDevice(device); + + controller.InitCmd(6); + + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSense6)); +} + +TEST(ModePageDeviceTest, ModeSense10) +{ + MockAbstractController controller(0); + auto device = make_shared>(); + + controller.AddDevice(device); + + controller.InitCmd(10); + + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSense10)); +} + +TEST(ModePageDeviceTest, ModeSelect) +{ + MockModePageDevice device; + vector cmd; + vector buf; + + EXPECT_THROW(device.ModeSelect(cmd, buf, 0), scsi_exception) << "Unexpected MODE SELECT default implementation"; +} + +TEST(ModePageDeviceTest, ModeSelect6) +{ + MockAbstractController controller(0); + auto device = make_shared(); + + controller.AddDevice(device); + + vector& cmd = controller.InitCmd(6); + + EXPECT_CALL(controller, DataOut()).Times(1); + EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSelect6)); + + cmd[1] = 0x01; + EXPECT_THROW(device->Dispatch(scsi_command::eCmdModeSelect6), scsi_exception) + << "Saving parameters is not supported for most device types"; +} + +TEST(ModePageDeviceTest, ModeSelect10) +{ + MockAbstractController controller(0); + auto device = make_shared(); + + controller.AddDevice(device); + + vector& cmd = controller.InitCmd(10); + + EXPECT_CALL(controller, DataOut()).Times(1); + EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSelect10)); + + cmd[1] = 0x01; + EXPECT_THROW(device->Dispatch(scsi_command::eCmdModeSelect10), scsi_exception) + << "Saving parameters is not supported for most device types"; +} diff --git a/src/raspberrypi/test/mode_pages_test.cpp b/src/raspberrypi/test/mode_pages_test.cpp deleted file mode 100644 index 652516a6..00000000 --- a/src/raspberrypi/test/mode_pages_test.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator RaSCSI Reloaded -// for Raspberry Pi -// -// Copyright (C) 2022 Uwe Seimet -// -//--------------------------------------------------------------------------- - -#include "mocks.h" -#include "spdlog/spdlog.h" -#include "rascsi_exceptions.h" -#include "controllers/controller_manager.h" -#include "devices/scsi_command_util.h" -#include "devices/scsihd.h" -#include "devices/scsihd_nec.h" -#include "devices/scsicd.h" -#include "devices/scsimo.h" -#include "devices/host_services.h" - -using namespace std; - -TEST(ModePagesTest, ModePageDevice_AddModePages) -{ - vector cdb(6); - vector buf(512); - - MockModePageDevice device(0); - cdb[2] = 0x3f; - - EXPECT_EQ(0, device.AddModePages(cdb, buf, 0, -1)) << "Negative maximum length must be rejected"; - EXPECT_EQ(0, device.AddModePages(cdb, buf, 0, 0)) << "Allocation length 0 must be rejected"; - EXPECT_EQ(1, device.AddModePages(cdb, buf, 0, 1)) << "Allocation length 1 must be rejected"; - - cdb[2] = 0x00; - EXPECT_THROW(device.AddModePages(cdb, buf, 0, 12), scsi_error_exception) << "Data for non-existing mode page 0 were returned"; -} - -TEST(ModePagesTest, SCSIHD_SetUpModePages) -{ - map> mode_pages; - const unordered_set sector_sizes; - MockSCSIHD device(0, sector_sizes, false); - device.SetUpModePages(mode_pages, 0x3f, false); - - EXPECT_EQ(5, mode_pages.size()) << "Unexpected number of mode pages"; - EXPECT_EQ(12, mode_pages[1].size()); - EXPECT_EQ(24, mode_pages[3].size()); - EXPECT_EQ(24, mode_pages[4].size()); - EXPECT_EQ(12, mode_pages[8].size()); - EXPECT_EQ(30, mode_pages[48].size()); -} - -TEST(ModePagesTest, SCSIHD_NEC_SetUpModePages) -{ - map> mode_pages; - MockSCSIHD_NEC device(0); - device.SetUpModePages(mode_pages, 0x3f, false); - - EXPECT_EQ(5, mode_pages.size()) << "Unexpected number of mode pages"; - EXPECT_EQ(8, mode_pages[1].size()); - EXPECT_EQ(24, mode_pages[3].size()); - EXPECT_EQ(20, mode_pages[4].size()); - EXPECT_EQ(12, mode_pages[8].size()); - EXPECT_EQ(30, mode_pages[48].size()); -} - -TEST(ModePagesTest, SCSICD_SetUpModePages) -{ - map> mode_pages; - const unordered_set sector_sizes; - MockSCSICD device(0, sector_sizes); - device.SetUpModePages(mode_pages, 0x3f, false); - - EXPECT_EQ(7, mode_pages.size()) << "Unexpected number of mode pages"; - EXPECT_EQ(12, mode_pages[1].size()); - EXPECT_EQ(24, mode_pages[3].size()); - EXPECT_EQ(24, mode_pages[4].size()); - EXPECT_EQ(12, mode_pages[8].size()); - EXPECT_EQ(8, mode_pages[13].size()); - EXPECT_EQ(16, mode_pages[14].size()); - EXPECT_EQ(30, mode_pages[48].size()); -} - -TEST(ModePagesTest, SCSIMO_SetUpModePages) -{ - map> mode_pages; - const unordered_set sector_sizes; - MockSCSIMO device(0, sector_sizes); - device.SetUpModePages(mode_pages, 0x3f, false); - - EXPECT_EQ(6, mode_pages.size()) << "Unexpected number of mode pages"; - EXPECT_EQ(12, mode_pages[1].size()); - EXPECT_EQ(24, mode_pages[3].size()); - EXPECT_EQ(24, mode_pages[4].size()); - EXPECT_EQ(4, mode_pages[6].size()); - EXPECT_EQ(12, mode_pages[8].size()); - EXPECT_EQ(12, mode_pages[32].size()); -} - -TEST(ModePagesTest, HostServices_SetUpModePages) -{ - MockBus bus; - ControllerManager controller_manager(bus); - MockHostServices device(0, controller_manager); - map> mode_pages; - - device.SetUpModePages(mode_pages, 0x3f, false); - EXPECT_EQ(1, mode_pages.size()) << "Unexpected number of mode pages"; - EXPECT_EQ(10, mode_pages[32].size()); -} - -TEST(ModePagesTest, ModeSelect) -{ - const int LENGTH = 12; - - vector cdb(16); - vector buf(255); - - // PF (vendor-specific parameter format) - cdb[1] = 0x00; - EXPECT_THROW(scsi_command_util::ModeSelect(cdb, buf, LENGTH, 0), scsi_error_exception) - << "Vendor-specific parameters are not supported"; - - // PF (standard parameter format) - cdb[1] = 0x10; - // Request 512 bytes per sector - buf[9] = 0x00; - buf[10] = 0x02; - buf[11] = 0x00; - 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, 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, 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, LENGTH + 2, 512); -} diff --git a/src/raspberrypi/test/phase_handler_test.cpp b/src/raspberrypi/test/phase_handler_test.cpp index 93d1613f..699b83cb 100644 --- a/src/raspberrypi/test/phase_handler_test.cpp +++ b/src/raspberrypi/test/phase_handler_test.cpp @@ -16,25 +16,81 @@ TEST(PhaseHandlerTest, Phases) handler.SetPhase(BUS::phase_t::selection); EXPECT_TRUE(handler.IsSelection()); + EXPECT_FALSE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsCommand()); + EXPECT_FALSE(handler.IsStatus()); + EXPECT_FALSE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsMsgIn()); + EXPECT_FALSE(handler.IsMsgOut()); handler.SetPhase(BUS::phase_t::busfree); EXPECT_TRUE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsSelection()); + EXPECT_FALSE(handler.IsCommand()); + EXPECT_FALSE(handler.IsStatus()); + EXPECT_FALSE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsMsgIn()); + EXPECT_FALSE(handler.IsMsgOut()); handler.SetPhase(BUS::phase_t::command); EXPECT_TRUE(handler.IsCommand()); + EXPECT_FALSE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsSelection()); + EXPECT_FALSE(handler.IsStatus()); + EXPECT_FALSE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsMsgIn()); + EXPECT_FALSE(handler.IsMsgOut()); handler.SetPhase(BUS::phase_t::status); EXPECT_TRUE(handler.IsStatus()); + EXPECT_FALSE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsSelection()); + EXPECT_FALSE(handler.IsCommand()); + EXPECT_FALSE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsMsgIn()); + EXPECT_FALSE(handler.IsMsgOut()); handler.SetPhase(BUS::phase_t::datain); EXPECT_TRUE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsSelection()); + EXPECT_FALSE(handler.IsCommand()); + EXPECT_FALSE(handler.IsStatus()); + EXPECT_FALSE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsMsgIn()); + EXPECT_FALSE(handler.IsMsgOut()); handler.SetPhase(BUS::phase_t::dataout); EXPECT_TRUE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsSelection()); + EXPECT_FALSE(handler.IsCommand()); + EXPECT_FALSE(handler.IsStatus()); + EXPECT_FALSE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsMsgIn()); + EXPECT_FALSE(handler.IsMsgOut()); handler.SetPhase(BUS::phase_t::msgin); EXPECT_TRUE(handler.IsMsgIn()); + EXPECT_FALSE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsSelection()); + EXPECT_FALSE(handler.IsCommand()); + EXPECT_FALSE(handler.IsStatus()); + EXPECT_FALSE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsMsgOut()); handler.SetPhase(BUS::phase_t::msgout); EXPECT_TRUE(handler.IsMsgOut()); + EXPECT_FALSE(handler.IsBusFree()); + EXPECT_FALSE(handler.IsSelection()); + EXPECT_FALSE(handler.IsCommand()); + EXPECT_FALSE(handler.IsStatus()); + EXPECT_FALSE(handler.IsDataIn()); + EXPECT_FALSE(handler.IsDataOut()); + EXPECT_FALSE(handler.IsMsgIn()); } diff --git a/src/raspberrypi/test/primary_device_test.cpp b/src/raspberrypi/test/primary_device_test.cpp index 15ef9729..a700ce99 100644 --- a/src/raspberrypi/test/primary_device_test.cpp +++ b/src/raspberrypi/test/primary_device_test.cpp @@ -56,25 +56,25 @@ TEST(PrimaryDeviceTest, TestUnitReady) device->SetAttn(true); device->SetReady(false); EXPECT_CALL(controller, DataIn()).Times(0); - EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_error_exception); + EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception); device->SetReset(false); EXPECT_CALL(controller, DataIn()).Times(0); - EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_error_exception); + EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception); device->SetReset(true); device->SetAttn(false); EXPECT_CALL(controller, DataIn()).Times(0); - EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_error_exception); + EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception); device->SetReset(false); device->SetAttn(true); EXPECT_CALL(controller, DataIn()).Times(0); - EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_error_exception); + EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception); device->SetAttn(false); EXPECT_CALL(controller, DataIn()).Times(0); - EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_error_exception); + EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception); device->SetReady(true); EXPECT_CALL(controller, Status()).Times(1); @@ -84,7 +84,7 @@ TEST(PrimaryDeviceTest, TestUnitReady) TEST(PrimaryDeviceTest, Inquiry) { - MockAbstractController controller(0); + NiceMock controller(0); auto device = make_shared(0); device->SetController(&controller); @@ -126,11 +126,11 @@ TEST(PrimaryDeviceTest, Inquiry) cmd[1] = 0x01; EXPECT_CALL(controller, DataIn()).Times(0); - EXPECT_THROW(device->Dispatch(scsi_command::eCmdInquiry), scsi_error_exception) << "EVPD bit is not supported"; + EXPECT_THROW(device->Dispatch(scsi_command::eCmdInquiry), scsi_exception) << "EVPD bit is not supported"; 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"; + EXPECT_THROW(device->Dispatch(scsi_command::eCmdInquiry), scsi_exception) << "PAGE CODE field is not supported"; cmd[1] = 0x00; cmd[2] = 0x00; @@ -145,7 +145,7 @@ TEST(PrimaryDeviceTest, Inquiry) TEST(PrimaryDeviceTest, RequestSense) { - MockAbstractController controller(0); + NiceMock controller(0); auto device = make_shared(0); controller.AddDevice(device); @@ -155,7 +155,7 @@ TEST(PrimaryDeviceTest, RequestSense) cmd[4] = 255; device->SetReady(false); - EXPECT_THROW(device->Dispatch(scsi_command::eCmdRequestSense), scsi_error_exception); + EXPECT_THROW(device->Dispatch(scsi_command::eCmdRequestSense), scsi_exception); device->SetReady(true); EXPECT_CALL(controller, DataIn()).Times(1); @@ -206,7 +206,7 @@ TEST(PrimaryDeviceTest, ReportLuns) EXPECT_EQ(LUN2, buffer[23]) << "Wrong LUN2 number"; cmd[2] = 0x01; - EXPECT_THROW(device1->Dispatch(scsi_command::eCmdReportLuns), scsi_error_exception) << "Only SELECT REPORT mode 0 is supported"; + EXPECT_THROW(device1->Dispatch(scsi_command::eCmdReportLuns), scsi_exception) << "Only SELECT REPORT mode 0 is supported"; } TEST(PrimaryDeviceTest, UnknownCommand) @@ -216,7 +216,6 @@ TEST(PrimaryDeviceTest, UnknownCommand) controller.AddDevice(device); - controller.InitCmd(1); EXPECT_FALSE(device->Dispatch((scsi_command)0xFF)); } diff --git a/src/raspberrypi/test/protobuf_serializer_test.cpp b/src/raspberrypi/test/protobuf_serializer_test.cpp index a8aa2c53..7af80ac4 100644 --- a/src/raspberrypi/test/protobuf_serializer_test.cpp +++ b/src/raspberrypi/test/protobuf_serializer_test.cpp @@ -16,12 +16,50 @@ using namespace rascsi_interface; TEST(ProtobufSerializerTest, SerializeMessage) { - PbResult message; + PbResult result; ProtobufSerializer serializer; - int fd = open("/dev/null", O_WRONLY); - ASSERT_NE(-1, fd); - serializer.SerializeMessage(fd, message); + int fd = open("/dev/zero", O_RDONLY); + EXPECT_NE(-1, fd); + EXPECT_THROW(serializer.DeserializeMessage(fd, result), io_exception) << "Writing the message header must fail"; + close(fd); + + fd = open("/dev/null", O_WRONLY); + EXPECT_NE(-1, fd); + serializer.SerializeMessage(fd, result); + EXPECT_THROW(serializer.SerializeMessage(-1, result), io_exception) << "Writing a message must fail"; + close(fd); +} + +TEST(ProtobufSerializerTest, DeserializeMessage) +{ + PbResult result; + ProtobufSerializer serializer; + vector buf(1); + + int fd = open("/dev/null", O_RDONLY); + EXPECT_NE(-1, fd); + EXPECT_THROW(serializer.DeserializeMessage(fd, result), io_exception) << "Reading the message header must fail"; + close(fd); + + fd = open("/dev/zero", O_RDONLY); + EXPECT_NE(-1, fd); + EXPECT_THROW(serializer.DeserializeMessage(fd, result), io_exception) << "Reading a message must fail"; + close(fd); +} + +TEST(ProtobufSerializerTest, ReadBytes) +{ + ProtobufSerializer serializer; + vector buf(1); + + int fd = open("/dev/null", O_RDONLY); + EXPECT_NE(-1, fd); + EXPECT_EQ(0, serializer.ReadBytes(fd, buf)); + close(fd); + + fd = open("/dev/zero", O_RDONLY); + EXPECT_NE(-1, fd); + EXPECT_EQ(1, serializer.ReadBytes(fd, buf)); close(fd); - EXPECT_THROW(serializer.SerializeMessage(-1, message), io_exception); } diff --git a/src/raspberrypi/test/command_util_test.cpp b/src/raspberrypi/test/protobuf_util_test.cpp similarity index 66% rename from src/raspberrypi/test/command_util_test.cpp rename to src/raspberrypi/test/protobuf_util_test.cpp index d206f17a..a5bbb8f3 100644 --- a/src/raspberrypi/test/command_util_test.cpp +++ b/src/raspberrypi/test/protobuf_util_test.cpp @@ -9,10 +9,10 @@ #include "mocks.h" #include "rascsi_interface.pb.h" -#include "command_util.h" +#include "protobuf_util.h" using namespace rascsi_interface; -using namespace command_util; +using namespace protobuf_util; void TestSpecialDevice(const string& name) { @@ -59,3 +59,26 @@ TEST(CommandUtil, ParseParameters) TestSpecialDevice("printer"); TestSpecialDevice("services"); } + +TEST(CommandUtil, SetPatternParams) +{ + PbCommand command1; + SetPatternParams(command1, "file"); + EXPECT_EQ("", GetParam(command1, "folder_pattern")); + EXPECT_EQ("file", GetParam(command1, "file_pattern")); + + PbCommand command2; + SetPatternParams(command2, ":file"); + EXPECT_EQ("", GetParam(command2, "folder_pattern")); + EXPECT_EQ("file", GetParam(command2, "file_pattern")); + + PbCommand command3; + SetPatternParams(command3, "folder:"); + EXPECT_EQ("folder", GetParam(command3, "folder_pattern")); + EXPECT_EQ("", GetParam(command3, "file_pattern")); + + PbCommand command4; + SetPatternParams(command4, "folder:file"); + EXPECT_EQ("folder", GetParam(command4, "folder_pattern")); + EXPECT_EQ("file", GetParam(command4, "file_pattern")); +} diff --git a/src/raspberrypi/test/rascsi_exceptions_test.cpp b/src/raspberrypi/test/rascsi_exceptions_test.cpp index d15d2ba2..89935341 100644 --- a/src/raspberrypi/test/rascsi_exceptions_test.cpp +++ b/src/raspberrypi/test/rascsi_exceptions_test.cpp @@ -35,36 +35,36 @@ TEST(RascsiExceptionsTest, FileNotFoundException) TEST(RascsiExceptionsTest, ScsiErrorException) { try { - throw scsi_error_exception(); + throw scsi_exception(); } - catch(const scsi_error_exception& e) { + catch(const scsi_exception& e) { EXPECT_EQ(sense_key::ABORTED_COMMAND, e.get_sense_key()); EXPECT_EQ(asc::NO_ADDITIONAL_SENSE_INFORMATION, e.get_asc()); EXPECT_EQ(status::CHECK_CONDITION, e.get_status()); } try { - throw scsi_error_exception(sense_key::UNIT_ATTENTION); + throw scsi_exception(sense_key::UNIT_ATTENTION); } - catch(const scsi_error_exception& e) { + catch(const scsi_exception& e) { EXPECT_EQ(sense_key::UNIT_ATTENTION, e.get_sense_key()); EXPECT_EQ(asc::NO_ADDITIONAL_SENSE_INFORMATION, e.get_asc()); EXPECT_EQ(status::CHECK_CONDITION, e.get_status()); } try { - throw scsi_error_exception(sense_key::UNIT_ATTENTION, asc::LBA_OUT_OF_RANGE); + throw scsi_exception(sense_key::UNIT_ATTENTION, asc::LBA_OUT_OF_RANGE); } - catch(const scsi_error_exception& e) { + catch(const scsi_exception& e) { EXPECT_EQ(sense_key::UNIT_ATTENTION, e.get_sense_key()); EXPECT_EQ(asc::LBA_OUT_OF_RANGE, e.get_asc()); EXPECT_EQ(status::CHECK_CONDITION, e.get_status()); } try { - throw scsi_error_exception(sense_key::UNIT_ATTENTION, asc::LBA_OUT_OF_RANGE, status::BUSY); + throw scsi_exception(sense_key::UNIT_ATTENTION, asc::LBA_OUT_OF_RANGE, status::BUSY); } - catch(const scsi_error_exception& e) { + catch(const scsi_exception& e) { EXPECT_EQ(sense_key::UNIT_ATTENTION, e.get_sense_key()); EXPECT_EQ(asc::LBA_OUT_OF_RANGE, e.get_asc()); EXPECT_EQ(status::BUSY, e.get_status()); diff --git a/src/raspberrypi/test/rascsi_executor_test.cpp b/src/raspberrypi/test/rascsi_executor_test.cpp index 93d2ad17..70b306d0 100644 --- a/src/raspberrypi/test/rascsi_executor_test.cpp +++ b/src/raspberrypi/test/rascsi_executor_test.cpp @@ -8,7 +8,7 @@ //--------------------------------------------------------------------------- #include "mocks.h" -#include "command_util.h" +#include "protobuf_util.h" #include "controllers/controller_manager.h" #include "devices/device_factory.h" #include "rascsi/command_context.h" @@ -17,7 +17,7 @@ #include "rascsi/rascsi_executor.h" using namespace rascsi_interface; -using namespace command_util; +using namespace protobuf_util; TEST(RascsiExecutorTest, ProcessCmd) { diff --git a/src/raspberrypi/test/rasctl_display_test.cpp b/src/raspberrypi/test/rasctl_display_test.cpp new file mode 100644 index 00000000..ba222443 --- /dev/null +++ b/src/raspberrypi/test/rasctl_display_test.cpp @@ -0,0 +1,288 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +// These tests only test key aspects of the expected output, because the output may change over time. +// +//--------------------------------------------------------------------------- + +#include + +#include "rasctl/rasctl_display.h" + +TEST(RasctlDisplayTest, DisplayDevicesInfo) +{ + RasctlDisplay display; + PbDevicesInfo info; + + EXPECT_FALSE(display.DisplayDevicesInfo(info).empty()); +} + +TEST(RasctlDisplayTest, DisplayDeviceInfo) +{ + RasctlDisplay display; + PbDevice device; + + EXPECT_FALSE(display.DisplayDeviceInfo(device).empty()); + + device.mutable_properties()->set_supports_file(true); + device.mutable_properties()->set_read_only(true); + device.mutable_properties()->set_protectable(true); + device.mutable_status()->set_protected_(true); + device.mutable_properties()->set_stoppable(true); + device.mutable_status()->set_stopped(true); + device.mutable_properties()->set_removable(true); + device.mutable_status()->set_removed(true); + device.mutable_properties()->set_lockable(true); + device.mutable_status()->set_locked(true); + EXPECT_FALSE(display.DisplayDeviceInfo(device).empty()); + + device.set_block_size(1234); + string s = display.DisplayDeviceInfo(device); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("1234")); + + device.set_block_count(4321); + s = display.DisplayDeviceInfo(device); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find(to_string(1234 *4321))); + + device.mutable_properties()->set_supports_file(true); + auto file = make_unique(); + file->set_name("filename"); + device.set_allocated_file(file.release()); + s = display.DisplayDeviceInfo(device); //NOSONAR The allocated memory is managed by protobuf + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("filename")); + + device.mutable_properties()->set_supports_params(true); + (*device.mutable_params())["key1"] = "value1"; + s = display.DisplayDeviceInfo(device); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("key1=value1")); + (*device.mutable_params())["key2"] = "value2"; + s = display.DisplayDeviceInfo(device); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("key1=value1")); + EXPECT_NE(string::npos, s.find("key2=value2")); +} + +TEST(RasctlDisplayTest, DisplayVersionInfo) +{ + RasctlDisplay display; + PbVersionInfo info; + + info.set_major_version(1); + info.set_minor_version(2); + info.set_patch_version(3); + string s = display.DisplayVersionInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_EQ(string::npos, s.find("development version")); + EXPECT_NE(string::npos, s.find("01.02.3")); + + info.set_patch_version(-1); + s = display.DisplayVersionInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("development version")); + EXPECT_NE(string::npos, s.find("01.02")); +} + +TEST(RasctlDisplayTest, DisplayLogLevelInfo) +{ + RasctlDisplay display; + PbLogLevelInfo info; + + string s = display.DisplayLogLevelInfo(info); + EXPECT_FALSE(s.empty()); + + info.add_log_levels("test"); + s = display.DisplayLogLevelInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("test")); +} + +TEST(RasctlDisplayTest, DisplayDeviceTypesInfo) +{ + RasctlDisplay display; + PbDeviceTypesInfo info; + + // Start with 2 instead of 1. 1 was the removed SASI drive type. + int ordinal = 2; + while (PbDeviceType_IsValid(ordinal)) { + PbDeviceType type = UNDEFINED; + PbDeviceType_Parse(PbDeviceType_Name((PbDeviceType)ordinal), &type); + + auto type_properties = info.add_properties(); + type_properties->set_type(type); + + if (type == SCHD) { + type_properties->mutable_properties()->set_supports_file(true); + type_properties->mutable_properties()->add_block_sizes(512); + type_properties->mutable_properties()->add_block_sizes(1024); + } + + if (type == SCMO) { + type_properties->mutable_properties()->set_supports_file(true); + type_properties->mutable_properties()->set_read_only(true); + type_properties->mutable_properties()->set_protectable(true); + type_properties->mutable_properties()->set_stoppable(true); + type_properties->mutable_properties()->set_removable(true); + type_properties->mutable_properties()->set_lockable(true); + } + + if (type == SCLP) { + type_properties->mutable_properties()->set_supports_params(true); + (*type_properties->mutable_properties()->mutable_default_params())["key1"] = "value1"; + (*type_properties->mutable_properties()->mutable_default_params())["key2"] = "value2"; + } + + ordinal++; + } + + const string s = display.DisplayDeviceTypesInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("key1=value1")); + EXPECT_NE(string::npos, s.find("key2=value2")); +} + +TEST(RasctlDisplayTest, DisplayReservedIdsInfo) +{ + RasctlDisplay display; + PbReservedIdsInfo info; + + string s = display.DisplayReservedIdsInfo(info); + EXPECT_FALSE(s.empty()); + + info.mutable_ids()->Add(5); + s = display.DisplayReservedIdsInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("5")); + + info.mutable_ids()->Add(6); + s = display.DisplayReservedIdsInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("5, 6")); +} + +TEST(RasctlDisplayTest, DisplayNetworkInterfacesInfo) +{ + RasctlDisplay display; + PbNetworkInterfacesInfo info; + + string s = display.DisplayNetworkInterfaces(info); + EXPECT_FALSE(s.empty()); + + info.mutable_name()->Add("eth0"); + s = display.DisplayNetworkInterfaces(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("eth0")); + + info.mutable_name()->Add("wlan0"); + s = display.DisplayNetworkInterfaces(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("eth0, wlan0")); +} + +TEST(RasctlDisplayTest, DisplayImageFile) +{ + RasctlDisplay display; + PbImageFile file; + + string s = display.DisplayImageFile(file); + EXPECT_FALSE(s.empty()); + + file.set_name("filename"); + s = display.DisplayImageFile(file); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("filename")); + EXPECT_EQ(string::npos, s.find("read-only")); + EXPECT_EQ(string::npos, s.find("SCHD")); + + file.set_read_only(true); + s = display.DisplayImageFile(file); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("filename")); + EXPECT_NE(string::npos, s.find("read-only")); + EXPECT_EQ(string::npos, s.find("SCHD")); + + file.set_type(SCHD); + s = display.DisplayImageFile(file); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("SCHD")); +} + +TEST(RasctlDisplayTest, DisplayImageFilesInfo) +{ + RasctlDisplay display; + PbImageFilesInfo info; + + string s = display.DisplayImageFilesInfo(info); + EXPECT_FALSE(display.DisplayImageFilesInfo(info).empty()); + EXPECT_EQ(string::npos, s.find("filename")); + + PbImageFile *file = info.add_image_files(); + file->set_name("filename"); + s = display.DisplayImageFilesInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("filename")); +} + +TEST(RasctlDisplayTest, DisplayMappingInfo) +{ + RasctlDisplay display; + PbMappingInfo info; + + string s = display.DisplayMappingInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_EQ(string::npos, s.find("key->SCHD")); + + (*info.mutable_mapping())["key"] = SCHD; + s = display.DisplayMappingInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("key->SCHD")); +} + +TEST(RasctlDisplayTest, DisplayOperationInfo) +{ + RasctlDisplay display; + PbOperationInfo info; + + string s = display.DisplayOperationInfo(info); + EXPECT_FALSE(s.empty()); + + PbOperationMetaData meta_data; + PbOperationParameter *param1 = meta_data.add_parameters(); + param1->set_name("default_key1"); + param1->set_default_value("default_value1"); + PbOperationParameter *param2 = meta_data.add_parameters(); + param2->set_name("default_key2"); + param2->set_default_value("default_value2"); + param2->set_description("description2"); + PbOperationParameter *param3 = meta_data.add_parameters(); + param3->set_name("default_key3"); + param3->set_default_value("default_value3"); + param3->set_description("description3"); + param3->add_permitted_values("permitted_value3_1"); + param3->add_permitted_values("permitted_value3_2"); + (*info.mutable_operations())[0] = meta_data; + s = display.DisplayOperationInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find(PbOperation_Name(NO_OPERATION))); + + meta_data.set_server_side_name("name"); + meta_data.set_description("description"); + (*info.mutable_operations())[0] = meta_data; + s = display.DisplayOperationInfo(info); + EXPECT_FALSE(s.empty()); + EXPECT_NE(string::npos, s.find("default_key1")); + EXPECT_NE(string::npos, s.find("default_value1")); + EXPECT_NE(string::npos, s.find("default_key2")); + EXPECT_NE(string::npos, s.find("default_value2")); + EXPECT_NE(string::npos, s.find("description2")); + EXPECT_NE(string::npos, s.find("description3")); + EXPECT_NE(string::npos, s.find("permitted_value3_1")); + EXPECT_NE(string::npos, s.find("permitted_value3_2")); +} diff --git a/src/raspberrypi/test/rasctl_parser_test.cpp b/src/raspberrypi/test/rasctl_parser_test.cpp new file mode 100644 index 00000000..78d9670d --- /dev/null +++ b/src/raspberrypi/test/rasctl_parser_test.cpp @@ -0,0 +1,55 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include + +#include "rasctl/rasctl_parser.h" + +TEST(RasctlParserTest, ParseOperation) +{ + RasctlParser parser; + + EXPECT_EQ(ATTACH, parser.ParseOperation("A")); + EXPECT_EQ(ATTACH, parser.ParseOperation("a")); + EXPECT_EQ(DETACH, parser.ParseOperation("d")); + EXPECT_EQ(INSERT, parser.ParseOperation("i")); + EXPECT_EQ(EJECT, parser.ParseOperation("e")); + EXPECT_EQ(PROTECT, parser.ParseOperation("p")); + EXPECT_EQ(UNPROTECT, parser.ParseOperation("u")); + EXPECT_EQ(NO_OPERATION, parser.ParseOperation("")); + EXPECT_EQ(NO_OPERATION, parser.ParseOperation("xyz")); +} + +TEST(RasctlParserTest, ParseType) +{ + RasctlParser parser; + + EXPECT_EQ(SCBR, parser.ParseType("SCBR")); + EXPECT_EQ(SCBR, parser.ParseType("scbr")); + EXPECT_EQ(SCCD, parser.ParseType("sccd")); + EXPECT_EQ(SCDP, parser.ParseType("scdp")); + EXPECT_EQ(SCHD, parser.ParseType("schd")); + EXPECT_EQ(SCLP, parser.ParseType("sclp")); + EXPECT_EQ(SCMO, parser.ParseType("scmo")); + EXPECT_EQ(SCRM, parser.ParseType("scrm")); + EXPECT_EQ(SCHS, parser.ParseType("schs")); + + EXPECT_EQ(SCBR, parser.ParseType("B")); + EXPECT_EQ(SCBR, parser.ParseType("b")); + EXPECT_EQ(SCCD, parser.ParseType("c")); + EXPECT_EQ(SCDP, parser.ParseType("d")); + EXPECT_EQ(SCHD, parser.ParseType("h")); + EXPECT_EQ(SCLP, parser.ParseType("l")); + EXPECT_EQ(SCMO, parser.ParseType("m")); + EXPECT_EQ(SCRM, parser.ParseType("r")); + EXPECT_EQ(SCHS, parser.ParseType("s")); + + EXPECT_EQ(UNDEFINED, parser.ParseType("")); + EXPECT_EQ(UNDEFINED, parser.ParseType("xyz")); +} diff --git a/src/raspberrypi/test/rasutil_test.cpp b/src/raspberrypi/test/rasutil_test.cpp index 66190d65..3f7d7286 100644 --- a/src/raspberrypi/test/rasutil_test.cpp +++ b/src/raspberrypi/test/rasutil_test.cpp @@ -25,3 +25,33 @@ TEST(RasUtilTest, GetAsInt) EXPECT_TRUE(GetAsInt("1234", result)); EXPECT_EQ(1234, result); } + +TEST(RasUtilTest, Banner) +{ + EXPECT_FALSE(Banner("Test").empty()); +} + +TEST(RasUtilTest, ListDevices) +{ + list devices; + + EXPECT_FALSE(ListDevices(devices).empty()); + + PbDevice device; + device.set_type(SCHD); + devices.push_back(device); + device.set_type(SCBR); + devices.push_back(device); + device.set_type(SCDP); + devices.push_back(device); + device.set_type(SCHS); + devices.push_back(device); + device.set_type(SCLP); + devices.push_back(device); + const string device_list = ListDevices(devices); + EXPECT_FALSE(device_list.empty()); + EXPECT_NE(string::npos, device_list.find("X68000 HOST BRIDGE")); + EXPECT_NE(string::npos, device_list.find("DaynaPort SCSI/Link")); + EXPECT_NE(string::npos, device_list.find("Host Services")); + EXPECT_NE(string::npos, device_list.find("SCSI Printer")); +} diff --git a/src/raspberrypi/test/scsi_command_util_test.cpp b/src/raspberrypi/test/scsi_command_util_test.cpp index 9f545609..dc9f7203 100644 --- a/src/raspberrypi/test/scsi_command_util_test.cpp +++ b/src/raspberrypi/test/scsi_command_util_test.cpp @@ -8,10 +8,47 @@ //--------------------------------------------------------------------------- #include "mocks.h" +#include "rascsi_exceptions.h" #include "devices/scsi_command_util.h" using namespace scsi_command_util; +TEST(ScsiCommandUtilTest, ModeSelect) +{ + const int LENGTH = 12; + + vector cdb(16); + vector buf(255); + + // PF (vendor-specific parameter format) + cdb[1] = 0x00; + EXPECT_THROW(ModeSelect(cdb, buf, LENGTH, 0), scsi_exception) + << "Vendor-specific parameters are not supported"; + + // PF (standard parameter format) + cdb[1] = 0x10; + // Request 512 bytes per sector + buf[9] = 0x00; + buf[10] = 0x02; + buf[11] = 0x00; + EXPECT_THROW(ModeSelect(cdb, buf, LENGTH, 256), scsi_exception) + << "Requested sector size does not match current sector size"; + + // Page 0 + buf[LENGTH] = 0x00; + EXPECT_THROW(ModeSelect(cdb, buf, LENGTH + 2, 512), scsi_exception) + << "Unsupported page 0 was not rejected"; + + // Page 3 (Format Device Page) + buf[LENGTH] = 0x03; + EXPECT_THROW(ModeSelect(cdb, buf, LENGTH + 2, 512), scsi_exception) + << "Requested sector size does not match current sector size"; + + // Match the requested to the current sector size + buf[LENGTH + 12] = 0x02; + ModeSelect(cdb, buf, LENGTH + 2, 512); +} + TEST(ScsiCommandUtilTest, EnrichFormatPage) { const int SECTOR_SIZE = 512; diff --git a/src/raspberrypi/test/scsi_daynaport_test.cpp b/src/raspberrypi/test/scsi_daynaport_test.cpp new file mode 100644 index 00000000..8155e32a --- /dev/null +++ b/src/raspberrypi/test/scsi_daynaport_test.cpp @@ -0,0 +1,125 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" +#include "rascsi_exceptions.h" +#include "devices/scsi_daynaport.h" + +TEST(ScsiDaynaportTest, Inquiry) +{ + TestInquiry(SCDP, device_type::PROCESSOR, scsi_level::SCSI_2, scsi_level::SCSI_2, + "Dayna SCSI/Link 1.4a", 0x20, false); +} + +TEST(ScsiDaynaportTest, Dispatch) +{ + NiceMock controller(0); + auto daynaport = CreateDevice(SCDP, controller); + + EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSense6)) + << "Non-DaynaPort commands inherited from Disk must not be supported"; + EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSelect6)) + << "Non-DaynaPort commands inherited from Disk must not be supported"; + EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSense10)) + << "Non-DaynaPort commands inherited from Disk must not be supported"; + EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSelect10)) + << "Non-DaynaPort commands inherited from Disk must not be supported"; +} + +TEST(ScsiDaynaportTest, TestUnitReady) +{ + NiceMock controller(0); + auto daynaport = CreateDevice(SCDP, controller); + + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdTestUnitReady)) << "TEST UNIT READY must never fail"; + EXPECT_EQ(status::GOOD, controller.GetStatus()); +} + +TEST(ScsiDaynaportTest, TestRetrieveStats) +{ + NiceMock controller(0); + auto daynaport = CreateDevice(SCDP, controller); + + vector& cmd = controller.InitCmd(6); + + // ALLOCATION LENGTH + cmd[4] = 255; + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdRetrieveStats)); +} + +TEST(ScsiDaynaportTest, SetInterfaceMode) +{ + NiceMock controller(0); + auto daynaport = CreateDevice(SCDP, controller); + + vector& cmd = controller.InitCmd(6); + + // Unknown interface command + EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception); + + // Not implemented, do nothing + cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SETMODE; + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); + + cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SETMAC; + EXPECT_CALL(controller, DataOut()).Times(1); + EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode)); + + // Not implemented + cmd[5] = SCSIDaynaPort::CMD_SCSILINK_STATS; + EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception); + + // Not implemented + cmd[5] = SCSIDaynaPort::CMD_SCSILINK_ENABLE; + EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception); + + // Not implemented + cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SET; + EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception); +} + +TEST(ScsiDaynaportTest, SetMcastAddr) +{ + NiceMock controller(0); + auto daynaport = CreateDevice(SCDP, controller); + + vector& cmd = controller.InitCmd(6); + + EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetMcastAddr), scsi_exception) << "Length of 0 is not supported"; + + cmd[4] = 1; + EXPECT_CALL(controller, DataOut()).Times(1); + EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdSetMcastAddr)); +} + +TEST(ScsiDaynaportTest, EnableInterface) +{ + NiceMock controller(0); + auto daynaport = CreateDevice(SCDP, controller); + + vector& cmd = controller.InitCmd(6); + + // Enable + EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdEnableInterface), scsi_exception); + + // Disable + cmd[5] = 0x80; + EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdEnableInterface), scsi_exception); +} + +TEST(ScsiDaynaportTest, GetSendDelay) +{ + SCSIDaynaPort daynaport(0); + + EXPECT_EQ(6, daynaport.GetSendDelay()); +} diff --git a/src/raspberrypi/test/scsi_host_bridge_test.cpp b/src/raspberrypi/test/scsi_host_bridge_test.cpp new file mode 100644 index 00000000..58304737 --- /dev/null +++ b/src/raspberrypi/test/scsi_host_bridge_test.cpp @@ -0,0 +1,16 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" + +TEST(ScsiHostBridgeTest, Inquiry) +{ + TestInquiry(SCBR, device_type::COMMUNICATIONS, scsi_level::SCSI_2, scsi_level::SCSI_2, + "RaSCSI RASCSI BRIDGE ", 0x27, false); +} diff --git a/src/raspberrypi/test/scsi_printer_test.cpp b/src/raspberrypi/test/scsi_printer_test.cpp new file mode 100644 index 00000000..2a960bd7 --- /dev/null +++ b/src/raspberrypi/test/scsi_printer_test.cpp @@ -0,0 +1,72 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" +#include "rascsi_exceptions.h" +#include "controllers/controller_manager.h" +#include "devices/scsi_printer.h" + +using namespace std; + +TEST(ScsiPrinterTest, TestUnitReady) +{ + NiceMock controller(0); + auto printer = CreateDevice(SCLP, controller); + + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdTestUnitReady)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); +} + +TEST(ScsiPrinterTest, Inquiry) +{ + TestInquiry(SCLP, device_type::PRINTER, scsi_level::SCSI_2, scsi_level::SCSI_2, + "RaSCSI SCSI PRINTER ", 0x1f, false); +} + +TEST(ScsiPrinterTest, ReserveUnit) +{ + NiceMock controller(0); + auto printer = CreateDevice(SCLP, controller); + + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdReserve6)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); +} + +TEST(ScsiPrinterTest, ReleaseUnit) +{ + NiceMock controller(0); + auto printer = CreateDevice(SCLP, controller); + + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdRelease6)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); +} + +TEST(ScsiPrinterTest, SendDiagnostic) +{ + NiceMock controller(0); + auto printer = CreateDevice(SCLP, controller); + + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdSendDiag)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); +} + + +TEST(ScsiPrinterTest, StopPrint) +{ + NiceMock controller(0); + auto printer = CreateDevice(SCLP, controller); + + EXPECT_CALL(controller, Status()).Times(1); + EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdStartStop)); + EXPECT_EQ(status::GOOD, controller.GetStatus()); +} diff --git a/src/raspberrypi/test/scsicd_test.cpp b/src/raspberrypi/test/scsicd_test.cpp new file mode 100644 index 00000000..d1326ec7 --- /dev/null +++ b/src/raspberrypi/test/scsicd_test.cpp @@ -0,0 +1,33 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" + +TEST(ScsiCdTest, Inquiry) +{ + TestInquiry(SCCD, device_type::CD_ROM, scsi_level::SCSI_2, scsi_level::SCSI_2, + "RaSCSI SCSI CD-ROM ", 0x1f, true); +} + +TEST(ScsiCdTest, SetUpModePages) +{ + map> mode_pages; + const unordered_set sector_sizes; + MockSCSICD cd(0, sector_sizes); + + cd.SetUpModePages(mode_pages, 0x3f, false); + EXPECT_EQ(7, mode_pages.size()) << "Unexpected number of mode pages"; + EXPECT_EQ(12, mode_pages[1].size()); + EXPECT_EQ(24, mode_pages[3].size()); + EXPECT_EQ(24, mode_pages[4].size()); + EXPECT_EQ(12, mode_pages[8].size()); + EXPECT_EQ(8, mode_pages[13].size()); + EXPECT_EQ(16, mode_pages[14].size()); + EXPECT_EQ(30, mode_pages[48].size()); +} diff --git a/src/raspberrypi/test/scsihd_nec_test.cpp b/src/raspberrypi/test/scsihd_nec_test.cpp new file mode 100644 index 00000000..412bd326 --- /dev/null +++ b/src/raspberrypi/test/scsihd_nec_test.cpp @@ -0,0 +1,35 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" +#include "controllers/controller_manager.h" +#include "devices/scsihd_nec.h" + +using namespace std; + +TEST(ScsiHdNecTest, Inquiry) +{ + TestInquiry(SCHD, device_type::DIRECT_ACCESS, scsi_level::SCSI_2, scsi_level::SCSI_2, + "RaSCSI ", 0x1f, false); +} + +TEST(ScsiHdNecTest, SetUpModePages) +{ + map> mode_pages; + MockSCSIHD_NEC hd(0); + + hd.SetUpModePages(mode_pages, 0x3f, false); + EXPECT_EQ(5, mode_pages.size()) << "Unexpected number of mode pages"; + EXPECT_EQ(8, mode_pages[1].size()); + EXPECT_EQ(24, mode_pages[3].size()); + EXPECT_EQ(20, mode_pages[4].size()); + EXPECT_EQ(12, mode_pages[8].size()); + EXPECT_EQ(30, mode_pages[48].size()); +} + diff --git a/src/raspberrypi/test/scsihd_test.cpp b/src/raspberrypi/test/scsihd_test.cpp index 9b37ca37..9568c5cf 100644 --- a/src/raspberrypi/test/scsihd_test.cpp +++ b/src/raspberrypi/test/scsihd_test.cpp @@ -18,3 +18,24 @@ TEST(ScsiHdTest, FinalizeSetup) EXPECT_THROW(disk.FinalizeSetup(filepath, 2LL * 1024 * 1024 * 1024 * 1024 + 1, 0), io_exception); } + +TEST(ScsiHdTest, Inquiry) +{ + TestInquiry(SCHD, device_type::DIRECT_ACCESS, scsi_level::SCSI_2, scsi_level::SCSI_2, + "RaSCSI ", 0x1f, false); +} + +TEST(ScsiHdTest, SetUpModePages) +{ + map> mode_pages; + const unordered_set sector_sizes; + MockSCSIHD hd(0, sector_sizes, false); + + hd.SetUpModePages(mode_pages, 0x3f, false); + EXPECT_EQ(5, mode_pages.size()) << "Unexpected number of mode pages"; + EXPECT_EQ(12, mode_pages[1].size()); + EXPECT_EQ(24, mode_pages[3].size()); + EXPECT_EQ(24, mode_pages[4].size()); + EXPECT_EQ(12, mode_pages[8].size()); + EXPECT_EQ(30, mode_pages[48].size()); +} diff --git a/src/raspberrypi/test/scsimo_test.cpp b/src/raspberrypi/test/scsimo_test.cpp new file mode 100644 index 00000000..cd2c4a25 --- /dev/null +++ b/src/raspberrypi/test/scsimo_test.cpp @@ -0,0 +1,32 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" + +TEST(ScsiMoTest, Inquiry) +{ + TestInquiry(SCMO, device_type::OPTICAL_MEMORY, scsi_level::SCSI_2, scsi_level::SCSI_2, + "RaSCSI SCSI MO ", 0x1f, true); +} + +TEST(ScsiMoTest, SetUpModePages) +{ + map> mode_pages; + const unordered_set sector_sizes; + MockSCSIMO device(0, sector_sizes); + + device.SetUpModePages(mode_pages, 0x3f, false); + EXPECT_EQ(6, mode_pages.size()) << "Unexpected number of mode pages"; + EXPECT_EQ(12, mode_pages[1].size()); + EXPECT_EQ(24, mode_pages[3].size()); + EXPECT_EQ(24, mode_pages[4].size()); + EXPECT_EQ(4, mode_pages[6].size()); + EXPECT_EQ(12, mode_pages[8].size()); + EXPECT_EQ(12, mode_pages[32].size()); +} diff --git a/src/raspberrypi/test/test_shared.cpp b/src/raspberrypi/test/test_shared.cpp new file mode 100644 index 00000000..594f9426 --- /dev/null +++ b/src/raspberrypi/test/test_shared.cpp @@ -0,0 +1,61 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "mocks.h" +#include "controllers/controller_manager.h" +#include "rascsi_version.h" +#include "test_shared.h" +#include + +using namespace std; + +shared_ptr CreateDevice(PbDeviceType type, MockAbstractController& controller) +{ + DeviceFactory device_factory; + auto bus = make_shared(); + auto controller_manager = make_shared(*bus); + + auto device = device_factory.CreateDevice(*controller_manager, type, 0, ""); + + controller.AddDevice(device); + + controller.InitCmd(16); + + return device; +} + +void TestInquiry(PbDeviceType type, device_type t, scsi_level l, scsi_level r, const string& ident, + int additional_length, bool removable) +{ + NiceMock controller(0); + auto device = CreateDevice(type, controller); + + vector& cmd = controller.InitCmd(6); + + // ALLOCATION LENGTH + cmd[4] = 255; + EXPECT_CALL(controller, DataIn()).Times(1); + EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry)); + const vector& buffer = controller.GetBuffer(); + EXPECT_EQ((int)t, buffer[0]); + EXPECT_EQ(removable ? 0x80: 0x00, buffer[1]); + EXPECT_EQ((int)l, buffer[2]); + EXPECT_EQ((int)r, buffer[3]); + EXPECT_EQ(additional_length, buffer[4]); + string product_data; + if (ident.size() == 24) { + ostringstream s; + s << ident << setw(2) << setfill('0') << rascsi_major_version << rascsi_minor_version; + product_data = s.str(); + } + else { + product_data = ident; + } + EXPECT_TRUE(!memcmp(product_data.c_str(), &buffer[8], 28)); +} diff --git a/src/raspberrypi/test/test_shared.h b/src/raspberrypi/test/test_shared.h new file mode 100644 index 00000000..6e2f5ed2 --- /dev/null +++ b/src/raspberrypi/test/test_shared.h @@ -0,0 +1,25 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#pragma once + +#include "scsi.h" +#include "rascsi_interface.pb.h" +#include +#include + +using namespace std; + +class PrimaryDevice; +class MockAbstractController; + +shared_ptr CreateDevice(rascsi_interface::PbDeviceType, MockAbstractController&); + +void TestInquiry(rascsi_interface::PbDeviceType, scsi_defs::device_type, scsi_defs::scsi_level, scsi_defs::scsi_level, + const string&, int, bool);