diff --git a/src/raspberrypi/rascsi.h b/src/raspberrypi/config.h similarity index 100% rename from src/raspberrypi/rascsi.h rename to src/raspberrypi/config.h diff --git a/src/raspberrypi/controllers/sasidev_ctrl.h b/src/raspberrypi/controllers/sasidev_ctrl.h index 9e790270..719bfc73 100644 --- a/src/raspberrypi/controllers/sasidev_ctrl.h +++ b/src/raspberrypi/controllers/sasidev_ctrl.h @@ -15,7 +15,7 @@ //--------------------------------------------------------------------------- #pragma once -#include "../rascsi.h" +#include "../config.h" #include "os.h" #include "scsi.h" #include "fileio.h" diff --git a/src/raspberrypi/controllers/scsidev_ctrl.cpp b/src/raspberrypi/controllers/scsidev_ctrl.cpp index f85d9f3d..8fb8952e 100644 --- a/src/raspberrypi/controllers/scsidev_ctrl.cpp +++ b/src/raspberrypi/controllers/scsidev_ctrl.cpp @@ -17,7 +17,6 @@ #include "controllers/scsidev_ctrl.h" #include "gpiobus.h" #include "devices/scsi_daynaport.h" -#include //=========================================================================== // @@ -239,7 +238,7 @@ void SCSIDEV::Execute() ctrl.execstart = SysTimer::GetTimerLow(); // Discard pending sense data from the previous command if the current command is not REQUEST SENSE - if ((ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdRequestSense) { + if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) { ctrl.status = 0; } @@ -247,8 +246,8 @@ void SCSIDEV::Execute() int lun = GetEffectiveLun(); if (!ctrl.unit[lun]) { - if ((ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdInquiry && - (ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdRequestSense) { + if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdInquiry && + (scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) { LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID()); Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN); @@ -266,7 +265,7 @@ void SCSIDEV::Execute() ctrl.device = ctrl.unit[lun]; // Discard pending sense data from the previous command if the current command is not REQUEST SENSE - if ((ScsiDefs::scsi_command)ctrl.cmd[0] != ScsiDefs::eCmdRequestSense) { + if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) { ctrl.device->SetStatusCode(0); } @@ -277,7 +276,7 @@ void SCSIDEV::Execute() } // SCSI-2 p.104 4.4.3 Incorrect logical unit handling - if ((ScsiDefs::scsi_command)ctrl.cmd[0] == ScsiDefs::eCmdInquiry && !ctrl.unit[lun]) { + if ((scsi_defs::scsi_command)ctrl.cmd[0] == scsi_defs::eCmdInquiry && !ctrl.unit[lun]) { lun = GetEffectiveLun(); LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, ctrl.device->GetId()); @@ -381,9 +380,8 @@ void SCSIDEV::Send() //if Length! = 0, send if (ctrl.length != 0) { - ostringstream s; - s << __PRETTY_FUNCTION__ << " sending handhake with offset " << ctrl.offset << ", length " << ctrl.length; - LOGTRACE("%s", s.str().c_str()); + LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length " + + to_string(ctrl.length)).c_str()); // TODO Get rid of Daynaport specific code in this class // The Daynaport needs to have a delay after the size/flags field @@ -420,9 +418,7 @@ void SCSIDEV::Send() if (ctrl.blocks != 0) { // set next buffer (set offset, length) result = XferIn(ctrl.buffer); - ostringstream s; - s << __PRETTY_FUNCTION__ << " Processing after data collection. Blocks: " << ctrl.blocks; - LOGTRACE("%s", s.str().c_str()); + LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Processing after data collection. Blocks: " + to_string(ctrl.blocks)).c_str()); } } @@ -434,9 +430,7 @@ void SCSIDEV::Send() // Continue sending if block !=0 if (ctrl.blocks != 0){ - ostringstream s; - s << __PRETTY_FUNCTION__ << " Continuing to send. Blocks: " << ctrl.blocks; - LOGTRACE("%s", s.str().c_str()); + LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Continuing to send. Blocks: " + to_string(ctrl.blocks)).c_str()); ASSERT(ctrl.length > 0); ASSERT(ctrl.offset == 0); return; diff --git a/src/raspberrypi/devices/device.cpp b/src/raspberrypi/devices/device.cpp index 31e75fa2..8e194967 100644 --- a/src/raspberrypi/devices/device.cpp +++ b/src/raspberrypi/devices/device.cpp @@ -8,17 +8,20 @@ //--------------------------------------------------------------------------- #include -#include #include "rascsi_version.h" #include "os.h" #include "log.h" #include "exceptions.h" #include "device.h" +set Device::devices; + Device::Device(const string& type) { assert(type.length() == 4); + devices.insert(this); + this->type = type; vendor = DEFAULT_VENDOR; @@ -48,6 +51,11 @@ Device::Device(const string& type) status_code = STATUS_NOERROR; } +Device::~Device() +{ + devices.erase(this); +} + void Device::Reset() { locked = false; diff --git a/src/raspberrypi/devices/device.h b/src/raspberrypi/devices/device.h index 621ac06e..3978eec0 100644 --- a/src/raspberrypi/devices/device.h +++ b/src/raspberrypi/devices/device.h @@ -9,6 +9,7 @@ #pragma once +#include #include #include @@ -104,10 +105,14 @@ private: // Sense Key, ASC and ASCQ int status_code; +protected: + + static set devices; + public: Device(const string&); - virtual ~Device() {}; + virtual ~Device(); // Override for device specific initializations, to be called after all device properties have been set virtual bool Init(const map&) { return true; }; diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index 44888408..0585ce44 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -20,12 +20,11 @@ #include "exceptions.h" #include "disk.h" #include "mode_page_device.h" -#include -Disk::Disk(const std::string id) : ModePageDevice(id), ScsiBlockCommands() +using namespace scsi_defs; + +Disk::Disk(const string& id) : ModePageDevice(id), ScsiBlockCommands() { - disks.insert(this); - // Work initialization configured_sector_size = 0; disk.size = 0; @@ -33,34 +32,34 @@ Disk::Disk(const std::string id) : ModePageDevice(id), ScsiBlockCommands() disk.dcache = NULL; disk.image_offset = 0; - AddCommand(ScsiDefs::eCmdRezero, "Rezero", &Disk::Rezero); - AddCommand(ScsiDefs::eCmdFormat, "FormatUnit", &Disk::FormatUnit); - AddCommand(ScsiDefs::eCmdReassign, "ReassignBlocks", &Disk::ReassignBlocks); - AddCommand(ScsiDefs::eCmdRead6, "Read6", &Disk::Read6); - AddCommand(ScsiDefs::eCmdWrite6, "Write6", &Disk::Write6); - AddCommand(ScsiDefs::eCmdSeek6, "Seek6", &Disk::Seek6); - AddCommand(ScsiDefs::eCmdReserve6, "Reserve6", &Disk::Reserve6); - AddCommand(ScsiDefs::eCmdRelease6, "Release6", &Disk::Release6); - AddCommand(ScsiDefs::eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit); - AddCommand(ScsiDefs::eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic); - AddCommand(ScsiDefs::eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval); - AddCommand(ScsiDefs::eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10); - AddCommand(ScsiDefs::eCmdRead10, "Read10", &Disk::Read10); - AddCommand(ScsiDefs::eCmdWrite10, "Write10", &Disk::Write10); - AddCommand(ScsiDefs::eCmdReadLong10, "ReadLong10", &Disk::ReadLong10); - AddCommand(ScsiDefs::eCmdWriteLong10, "WriteLong10", &Disk::WriteLong10); - AddCommand(ScsiDefs::eCmdWriteLong16, "WriteLong16", &Disk::WriteLong16); - AddCommand(ScsiDefs::eCmdSeek10, "Seek10", &Disk::Seek10); - AddCommand(ScsiDefs::eCmdVerify10, "Verify10", &Disk::Verify10); - AddCommand(ScsiDefs::eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10); - AddCommand(ScsiDefs::eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16); - AddCommand(ScsiDefs::eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10); - AddCommand(ScsiDefs::eCmdReserve10, "Reserve10", &Disk::Reserve10); - AddCommand(ScsiDefs::eCmdRelease10, "Release10", &Disk::Release10); - AddCommand(ScsiDefs::eCmdRead16, "Read16", &Disk::Read16); - AddCommand(ScsiDefs::eCmdWrite16, "Write16", &Disk::Write16); - AddCommand(ScsiDefs::eCmdVerify16, "Verify16", &Disk::Verify16); - AddCommand(ScsiDefs::eCmdReadCapacity16_ReadLong16, "ReadCapacity16/ReadLong16", &Disk::ReadCapacity16_ReadLong16); + dispatcher.AddCommand(eCmdRezero, "Rezero", &Disk::Rezero); + dispatcher.AddCommand(eCmdFormat, "FormatUnit", &Disk::FormatUnit); + dispatcher.AddCommand(eCmdReassign, "ReassignBlocks", &Disk::ReassignBlocks); + dispatcher.AddCommand(eCmdRead6, "Read6", &Disk::Read6); + dispatcher.AddCommand(eCmdWrite6, "Write6", &Disk::Write6); + dispatcher.AddCommand(eCmdSeek6, "Seek6", &Disk::Seek6); + dispatcher.AddCommand(eCmdReserve6, "Reserve6", &Disk::Reserve6); + dispatcher.AddCommand(eCmdRelease6, "Release6", &Disk::Release6); + dispatcher.AddCommand(eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit); + dispatcher.AddCommand(eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic); + dispatcher.AddCommand(eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval); + dispatcher.AddCommand(eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10); + dispatcher.AddCommand(eCmdRead10, "Read10", &Disk::Read10); + dispatcher.AddCommand(eCmdWrite10, "Write10", &Disk::Write10); + dispatcher.AddCommand(eCmdReadLong10, "ReadLong10", &Disk::ReadLong10); + dispatcher.AddCommand(eCmdWriteLong10, "WriteLong10", &Disk::WriteLong10); + dispatcher.AddCommand(eCmdWriteLong16, "WriteLong16", &Disk::WriteLong16); + dispatcher.AddCommand(eCmdSeek10, "Seek10", &Disk::Seek10); + dispatcher.AddCommand(eCmdVerify10, "Verify10", &Disk::Verify10); + dispatcher.AddCommand(eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10); + dispatcher.AddCommand(eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16); + dispatcher.AddCommand(eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10); + dispatcher.AddCommand(eCmdReserve10, "Reserve10", &Disk::Reserve10); + dispatcher.AddCommand(eCmdRelease10, "Release10", &Disk::Release10); + dispatcher.AddCommand(eCmdRead16, "Read16", &Disk::Read16); + dispatcher.AddCommand(eCmdWrite16, "Write16", &Disk::Write16); + dispatcher.AddCommand(eCmdVerify16, "Verify16", &Disk::Verify16); + dispatcher.AddCommand(eCmdReadCapacity16_ReadLong16, "ReadCapacity16/ReadLong16", &Disk::ReadCapacity16_ReadLong16); } Disk::~Disk() @@ -78,37 +77,12 @@ Disk::~Disk() delete disk.dcache; disk.dcache = NULL; } - - for (auto const& command : commands) { - delete command.second; - } - - disks.erase(this); -} - -void Disk::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (Disk::*execute)(SASIDEV *)) -{ - commands[opcode] = new command_t(name, execute); } bool Disk::Dispatch(SCSIDEV *controller) { - ctrl = controller->GetCtrl(); - - if (commands.count(static_cast(ctrl->cmd[0]))) { - command_t *command = commands[static_cast(ctrl->cmd[0])]; - - LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); - - (this->*command->execute)(controller); - - return true; - } - - LOGTRACE("%s Calling base class for dispatching $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[0]); - - // The base class handles the less specific commands - return ModePageDevice::Dispatch(controller); + // The superclass handles the less specific commands + return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } //--------------------------------------------------------------------------- @@ -1276,9 +1250,8 @@ bool Disk::CheckBlockAddress(SASIDEV *controller, access_mode mode) uint64_t capacity = GetBlockCount(); if (block > capacity) { - ostringstream s; - s << "Capacity of " << capacity << " blocks exceeded: " << "Trying to access block " << block; - LOGTRACE("%s", s.str().c_str()); + LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block " + + to_string(block)).c_str()); controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE); return false; } @@ -1339,10 +1312,8 @@ bool Disk::GetStartAndCount(SASIDEV *controller, uint64_t& start, uint32_t& coun // Check capacity uint64_t capacity = GetBlockCount(); if (start > capacity || start + count > capacity) { - ostringstream s; - s << "Capacity of " << capacity << " blocks exceeded: " - << "Trying to read block " << start << ", block count " << ctrl->blocks; - LOGTRACE("%s", s.str().c_str()); + LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block " + + to_string(start) + ", block count " + to_string(ctrl->blocks)).c_str()); controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE); return false; } @@ -1366,9 +1337,7 @@ void Disk::SetSectorSizeInBytes(uint32_t size, bool sasi) { set sector_sizes = DeviceFactory::instance().GetSectorSizes(GetType()); if (!sector_sizes.empty() && sector_sizes.find(size) == sector_sizes.end()) { - stringstream error; - error << "Invalid block size of " << size << " bytes"; - throw io_exception(error.str()); + throw io_exception("Invalid block size of " + to_string(size) + " bytes"); } switch (size) { diff --git a/src/raspberrypi/devices/disk.h b/src/raspberrypi/devices/disk.h index 68b06dcd..59bdb740 100644 --- a/src/raspberrypi/devices/disk.h +++ b/src/raspberrypi/devices/disk.h @@ -26,12 +26,13 @@ #include "file_support.h" #include "filepath.h" #include "interfaces/scsi_block_commands.h" -#include "interfaces/scsi_primary_commands.h" #include "mode_page_device.h" #include #include #include +using namespace std; + class Disk : public ModePageDevice, ScsiBlockCommands { private: @@ -52,18 +53,10 @@ private: off_t image_offset; // Offset to actual data } disk_t; - typedef struct _command_t { - const char* name; - void (Disk::*execute)(SASIDEV *); - - _command_t(const char* _name, void (Disk::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; - } command_t; - std::map commands; - - void AddCommand(ScsiDefs::scsi_command, const char*, void (Disk::*)(SASIDEV *)); + Dispatcher dispatcher; public: - Disk(std::string); + Disk(const string&); virtual ~Disk(); virtual bool Dispatch(SCSIDEV *) override; @@ -76,13 +69,14 @@ public: bool Eject(bool) override; private: + typedef ModePageDevice super; // Commands covered by the SCSI specification (see https://www.t10.org/drafts.htm) - void StartStopUnit(SASIDEV *) override; - void SendDiagnostic(SASIDEV *) override; + void StartStopUnit(SASIDEV *); + void SendDiagnostic(SASIDEV *); void PreventAllowMediumRemoval(SASIDEV *); - void SynchronizeCache10(SASIDEV *) override; - void SynchronizeCache16(SASIDEV *) override; + void SynchronizeCache10(SASIDEV *); + void SynchronizeCache16(SASIDEV *); void ReadDefectData10(SASIDEV *); virtual void Read6(SASIDEV *); void Read10(SASIDEV *) override; @@ -90,12 +84,12 @@ private: virtual void Write6(SASIDEV *); void Write10(SASIDEV *) override; void Write16(SASIDEV *) override; - void ReadLong10(SASIDEV *) override; - void ReadLong16(SASIDEV *) override; - void WriteLong10(SASIDEV *) override; - void WriteLong16(SASIDEV *) override; - void Verify10(SASIDEV *) override; - void Verify16(SASIDEV *) override; + void ReadLong10(SASIDEV *); + void ReadLong16(SASIDEV *); + void WriteLong10(SASIDEV *); + void WriteLong16(SASIDEV *); + void Verify10(SASIDEV *); + void Verify16(SASIDEV *); void Seek(SASIDEV *); void Seek10(SASIDEV *); void ReadCapacity10(SASIDEV *) override; @@ -110,7 +104,7 @@ public: // Commands covered by the SCSI specification (see https://www.t10.org/drafts.htm) void Rezero(SASIDEV *); void FormatUnit(SASIDEV *) override; - void ReassignBlocks(SASIDEV *) override; + void ReassignBlocks(SASIDEV *); void Seek6(SASIDEV *); // Command helpers @@ -154,8 +148,6 @@ protected: // Internal disk data disk_t disk; - set disks; - private: void Read(SASIDEV *, uint64_t); void Write(SASIDEV *, uint64_t); diff --git a/src/raspberrypi/devices/dispatcher.h b/src/raspberrypi/devices/dispatcher.h new file mode 100644 index 00000000..6cd0cc47 --- /dev/null +++ b/src/raspberrypi/devices/dispatcher.h @@ -0,0 +1,67 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Copyright (C) 2022 Uwe Seimet +// +// A template for dispatching SCSI commands +// +//--------------------------------------------------------------------------- + +#pragma once + +#include "log.h" +#include "scsi.h" +#include + +class SASIDEV; +class SCSIDEV; + +using namespace std; +using namespace scsi_defs; + +template +class Dispatcher +{ +public: + + Dispatcher() {} + ~Dispatcher() + { + for (auto const& command : commands) { + delete command.second; + } + } + + typedef struct _command_t { + const char* name; + void (T::*execute)(SASIDEV *); + + _command_t(const char* _name, void (T::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; + } command_t; + map commands; + + void AddCommand(scsi_command opcode, const char* name, void (T::*execute)(SASIDEV *)) + { + commands[opcode] = new command_t(name, execute); + } + + bool Dispatch(T *instance, SCSIDEV *controller) + { + SASIDEV::ctrl_t *ctrl = controller->GetCtrl(); + instance->SetCtrl(ctrl); + + const auto& it = commands.find(static_cast(ctrl->cmd[0])); + if (it != commands.end()) { + LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, it->second->name, (unsigned int)ctrl->cmd[0]); + + (instance->*it->second->execute)(controller); + + return true; + } + + // Unknown command + return false; + } +}; diff --git a/src/raspberrypi/devices/host_services.cpp b/src/raspberrypi/devices/host_services.cpp index f4e3b6b6..b3b11f25 100644 --- a/src/raspberrypi/devices/host_services.cpp +++ b/src/raspberrypi/devices/host_services.cpp @@ -30,24 +30,20 @@ // b) !start && load (EJECT): Shut down the Raspberry Pi // +#include "controllers/scsidev_ctrl.h" #include "host_services.h" +using namespace scsi_defs; + +HostServices::HostServices() : ModePageDevice("SCHS") +{ + dispatcher.AddCommand(eCmdStartStop, "StartStopUnit", &HostServices::StartStopUnit); +} + bool HostServices::Dispatch(SCSIDEV *controller) { - unsigned int cmd = controller->GetCtrl()->cmd[0]; - - // Only certain commands are supported - // TODO Do not inherit from Disk, mode page handling should be moved to ModePageDevice - if (cmd == ScsiDefs::eCmdTestUnitReady || cmd == ScsiDefs::eCmdRequestSense - || cmd == ScsiDefs::eCmdInquiry || cmd == ScsiDefs::eCmdReportLuns - || cmd == ScsiDefs::eCmdModeSense6 || cmd == ScsiDefs::eCmdModeSense10 - || cmd == ScsiDefs::eCmdStartStop) { - LOGTRACE("%s Calling base class for dispatching $%02X", __PRETTY_FUNCTION__, cmd); - - return Disk::Dispatch(controller); - } - - return false; + // The superclass class handles the less specific commands + return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } void HostServices::TestUnitReady(SASIDEV *controller) @@ -58,28 +54,8 @@ void HostServices::TestUnitReady(SASIDEV *controller) int HostServices::Inquiry(const DWORD *cdb, BYTE *buf) { - int allocation_length = cdb[4] + (((DWORD)cdb[3]) << 8); - if (allocation_length > 4) { - if (allocation_length > 44) { - allocation_length = 44; - } - - // Basic data - // buf[0] ... Processor Device - // buf[1] ... Not removable - // buf[2] ... SCSI-2 compliant command system - // buf[3] ... SCSI-2 compliant Inquiry response - // buf[4] ... Inquiry additional data - memset(buf, 0, allocation_length); - buf[0] = 0x03; - buf[2] = 0x01; - buf[4] = 0x1F; - - // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); - } - - return allocation_length; + // Processor device, not removable + return PrimaryDevice::Inquiry(3, false, cdb, buf); } void HostServices::StartStopUnit(SASIDEV *controller) @@ -88,10 +64,10 @@ void HostServices::StartStopUnit(SASIDEV *controller) bool load = ctrl->cmd[4] & 0x02; if (!start) { - // Delete all regular disk devices. This also flushes their caches. - for (auto disk : disks) { - if (disk && disk != this) { - delete disk; + // Delete all other devices. This will also flush any caches. + for (const Device *device : devices) { + if (device != this) { + delete device; } } @@ -109,7 +85,91 @@ void HostServices::StartStopUnit(SASIDEV *controller) controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); } -int HostServices::AddVendorPage(int page, bool, BYTE *buf) +int HostServices::ModeSense6(const DWORD *cdb, BYTE *buf) +{ + // Get length, clear buffer + int length = (int)cdb[4]; + memset(buf, 0, length); + + // Get page code (0x00 is valid from the beginning) + int page = cdb[2] & 0x3f; + bool valid = page == 0x00; + + LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page); + + // Basic information + int size = 4; + + int ret = AddRealtimeClockPage(page, &buf[size]); + if (ret > 0) { + size += ret; + valid = true; + } + + if (!valid) { + LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page); + SetStatusCode(STATUS_INVALIDCDB); + return 0; + } + + // Do not return more than ALLOCATION LENGTH bytes + if (size > length) { + LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length); + size = length; + } + + // Final setting of mode data length + buf[0] = size; + + return size; +} + +int HostServices::ModeSense10(const DWORD *cdb, BYTE *buf) +{ + // Get length, clear buffer + int length = cdb[7]; + length <<= 8; + length |= cdb[8]; + if (length > 0x800) { + length = 0x800; + } + memset(buf, 0, length); + + // Get page code (0x00 is valid from the beginning) + int page = cdb[2] & 0x3f; + bool valid = page == 0x00; + + LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page); + + // Basic Information + int size = 8; + + int ret = AddRealtimeClockPage(page, &buf[size]); + if (ret > 0) { + size += ret; + valid = true; + } + + if (!valid) { + LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page); + SetStatusCode(STATUS_INVALIDCDB); + return 0; + } + + // Do not return more than ALLOCATION LENGTH bytes + if (size > length) { + LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length); + size = length; + } + + // Final setting of mode data length + buf[0] = size >> 8; + buf[1] = size; + + return size; +} + +int HostServices::AddRealtimeClockPage(int page, BYTE *buf) { if (page == 0x20) { // Data structure version 1.0 @@ -131,4 +191,3 @@ int HostServices::AddVendorPage(int page, bool, BYTE *buf) return 0; } - diff --git a/src/raspberrypi/devices/host_services.h b/src/raspberrypi/devices/host_services.h index 5c6e8e4a..7d7aa944 100644 --- a/src/raspberrypi/devices/host_services.h +++ b/src/raspberrypi/devices/host_services.h @@ -5,21 +5,37 @@ // // Copyright (C) 2022 Uwe Seimet // +// RaSCSI Host Services with realtime clock and shutdown support +// //--------------------------------------------------------------------------- #pragma once -#include "disk.h" +#include "mode_page_device.h" -class HostServices: public Disk +using namespace std; + +class HostServices: public ModePageDevice { + public: - HostServices() : Disk("SCHS") {}; - ~HostServices() {}; + + HostServices(); + ~HostServices() {} virtual bool Dispatch(SCSIDEV *) override; int Inquiry(const DWORD *, BYTE *) override; void TestUnitReady(SASIDEV *) override; - void StartStopUnit(SASIDEV *) override; - int AddVendorPage(int, bool, BYTE *) override; + void StartStopUnit(SASIDEV *); + + int ModeSense6(const DWORD *, BYTE *); + int ModeSense10(const DWORD *, BYTE *); + +private: + + typedef ModePageDevice super; + + Dispatcher dispatcher; + + int AddRealtimeClockPage(int, BYTE *); }; diff --git a/src/raspberrypi/devices/interfaces/scsi_block_commands.h b/src/raspberrypi/devices/interfaces/scsi_block_commands.h index 3a8f08de..584f6af8 100644 --- a/src/raspberrypi/devices/interfaces/scsi_block_commands.h +++ b/src/raspberrypi/devices/interfaces/scsi_block_commands.h @@ -30,17 +30,4 @@ public: virtual void Read16(SASIDEV *) = 0; virtual void Write10(SASIDEV *) = 0; virtual void Write16(SASIDEV *) = 0; - - // Implemented optional commands - virtual void ReadLong10(SASIDEV *) = 0; - virtual void WriteLong10(SASIDEV *) = 0; - virtual void Verify10(SASIDEV *) = 0; - virtual void ReadLong16(SASIDEV *) = 0; - virtual void WriteLong16(SASIDEV *) = 0; - virtual void Verify16(SASIDEV *) = 0; - virtual void ReassignBlocks(SASIDEV *) = 0; - virtual void SendDiagnostic(SASIDEV *) = 0; - virtual void StartStopUnit(SASIDEV *) = 0; - virtual void SynchronizeCache10(SASIDEV *) = 0; - virtual void SynchronizeCache16(SASIDEV *) = 0; }; diff --git a/src/raspberrypi/devices/interfaces/scsi_primary_commands.h b/src/raspberrypi/devices/interfaces/scsi_primary_commands.h index 5a3efdb1..585c90e5 100644 --- a/src/raspberrypi/devices/interfaces/scsi_primary_commands.h +++ b/src/raspberrypi/devices/interfaces/scsi_primary_commands.h @@ -25,10 +25,6 @@ public: virtual void Inquiry(SASIDEV *) = 0; virtual void ReportLuns(SASIDEV *) = 0; - // Optional commands + // Implemented for all RaSCSI device types virtual void RequestSense(SASIDEV *) = 0; - virtual void ModeSense6(SASIDEV *) = 0; - virtual void ModeSense10(SASIDEV *) = 0; - virtual void ModeSelect6(SASIDEV *) = 0; - virtual void ModeSelect10(SASIDEV *) = 0; }; diff --git a/src/raspberrypi/devices/mode_page_device.cpp b/src/raspberrypi/devices/mode_page_device.cpp index 3f05caa9..9b9e08bc 100644 --- a/src/raspberrypi/devices/mode_page_device.cpp +++ b/src/raspberrypi/devices/mode_page_device.cpp @@ -14,36 +14,20 @@ #include "mode_page_device.h" using namespace std; +using namespace scsi_defs; -ModePageDevice::ModePageDevice(const string id) : PrimaryDevice(id) +ModePageDevice::ModePageDevice(const string& id) : PrimaryDevice(id) { - AddCommand(ScsiDefs::eCmdModeSense6, "ModeSense6", &ModePageDevice::ModeSense6); - AddCommand(ScsiDefs::eCmdModeSense10, "ModeSense10", &ModePageDevice::ModeSense10); - AddCommand(ScsiDefs::eCmdModeSelect6, "ModeSelect6", &ModePageDevice::ModeSelect6); - AddCommand(ScsiDefs::eCmdModeSelect10, "ModeSelect10", &ModePageDevice::ModeSelect10); -} - -void ModePageDevice::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (ModePageDevice::*execute)(SASIDEV *)) -{ - commands[opcode] = new command_t(name, execute); + dispatcher.AddCommand(eCmdModeSense6, "ModeSense6", &ModePageDevice::ModeSense6); + dispatcher.AddCommand(eCmdModeSense10, "ModeSense10", &ModePageDevice::ModeSense10); + dispatcher.AddCommand(eCmdModeSelect6, "ModeSelect6", &ModePageDevice::ModeSelect6); + dispatcher.AddCommand(eCmdModeSelect10, "ModeSelect10", &ModePageDevice::ModeSelect10); } bool ModePageDevice::Dispatch(SCSIDEV *controller) { - ctrl = controller->GetCtrl(); - - if (commands.count(static_cast(ctrl->cmd[0]))) { - command_t *command = commands[static_cast(ctrl->cmd[0])]; - - LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); - - (this->*command->execute)(controller); - - return true; - } - - // Unknown command - return false; + // The superclass class handles the less specific commands + return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } void ModePageDevice::ModeSense6(SASIDEV *controller) diff --git a/src/raspberrypi/devices/mode_page_device.h b/src/raspberrypi/devices/mode_page_device.h index 2c204e51..b8200aa2 100644 --- a/src/raspberrypi/devices/mode_page_device.h +++ b/src/raspberrypi/devices/mode_page_device.h @@ -18,7 +18,7 @@ class ModePageDevice: public PrimaryDevice { public: - ModePageDevice(const string); + ModePageDevice(const string&); virtual ~ModePageDevice() {} virtual bool Dispatch(SCSIDEV *) override; @@ -31,20 +31,14 @@ public: private: - typedef struct _command_t { - const char* name; - void (ModePageDevice::*execute)(SASIDEV *); + typedef PrimaryDevice super; - _command_t(const char* _name, void (ModePageDevice::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; - } command_t; - std::map commands; + Dispatcher dispatcher; - void AddCommand(ScsiDefs::scsi_command, const char*, void (ModePageDevice::*)(SASIDEV *)); - - void ModeSense6(SASIDEV *) override; - void ModeSense10(SASIDEV *) override; - void ModeSelect6(SASIDEV *) override; - void ModeSelect10(SASIDEV *) override; + void ModeSense6(SASIDEV *); + void ModeSense10(SASIDEV *); + void ModeSelect6(SASIDEV *); + void ModeSelect10(SASIDEV *); int ModeSelectCheck(const DWORD *, int); int ModeSelectCheck6(const DWORD *); diff --git a/src/raspberrypi/devices/primary_device.cpp b/src/raspberrypi/devices/primary_device.cpp index 75728e32..3f097bc8 100644 --- a/src/raspberrypi/devices/primary_device.cpp +++ b/src/raspberrypi/devices/primary_device.cpp @@ -9,44 +9,28 @@ #include "log.h" #include "controllers/scsidev_ctrl.h" +#include "dispatcher.h" #include "primary_device.h" using namespace std; +using namespace scsi_defs; -PrimaryDevice::PrimaryDevice(const string id) : ScsiPrimaryCommands(), Device(id) +PrimaryDevice::PrimaryDevice(const string& id) : ScsiPrimaryCommands(), Device(id) { ctrl = NULL; // Mandatory SCSI primary commands - AddCommand(ScsiDefs::eCmdTestUnitReady, "TestUnitReady", &PrimaryDevice::TestUnitReady); - AddCommand(ScsiDefs::eCmdInquiry, "Inquiry", &PrimaryDevice::Inquiry); - AddCommand(ScsiDefs::eCmdReportLuns, "ReportLuns", &PrimaryDevice::ReportLuns); + dispatcher.AddCommand(eCmdTestUnitReady, "TestUnitReady", &PrimaryDevice::TestUnitReady); + dispatcher.AddCommand(eCmdInquiry, "Inquiry", &PrimaryDevice::Inquiry); + dispatcher.AddCommand(eCmdReportLuns, "ReportLuns", &PrimaryDevice::ReportLuns); // Optional commands used by all RaSCSI devices - AddCommand(ScsiDefs::eCmdRequestSense, "RequestSense", &PrimaryDevice::RequestSense); -} - -void PrimaryDevice::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (PrimaryDevice::*execute)(SASIDEV *)) -{ - commands[opcode] = new command_t(name, execute); + dispatcher.AddCommand(eCmdRequestSense, "RequestSense", &PrimaryDevice::RequestSense); } bool PrimaryDevice::Dispatch(SCSIDEV *controller) { - ctrl = controller->GetCtrl(); - - if (commands.count(static_cast(ctrl->cmd[0]))) { - command_t *command = commands[static_cast(ctrl->cmd[0])]; - - LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); - - (this->*command->execute)(controller); - - return true; - } - - // Unknown command - return false; + return dispatcher.Dispatch(this, controller); } void PrimaryDevice::TestUnitReady(SASIDEV *controller) @@ -90,7 +74,7 @@ void PrimaryDevice::Inquiry(SASIDEV *controller) // Report if the device does not support the requested LUN if (!ctrl->unit[lun]) { - LOGDEBUG("Reporting LUN %d for device ID %d as not supported", lun, ctrl->device->GetId()); + LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, ctrl->device->GetId()); ctrl->buffer[0] |= 0x7f; } @@ -183,6 +167,33 @@ bool PrimaryDevice::CheckReady() return true; } +int PrimaryDevice::Inquiry(int type, bool is_removable, const DWORD *cdb, BYTE *buf) +{ + int allocation_length = cdb[4] + (((DWORD)cdb[3]) << 8); + if (allocation_length > 4) { + if (allocation_length > 44) { + allocation_length = 44; + } + + // Basic data + // buf[0] ... SCSI Device type + // buf[1] ... Bit 7: Removable/not removable + // buf[2] ... SCSI-2 compliant command system + // buf[3] ... SCSI-2 compliant Inquiry response + // buf[4] ... Inquiry additional data + memset(buf, 0, allocation_length); + buf[0] = type; + buf[1] = is_removable ? 0x80 : 0x00; + buf[2] = 0x01; + buf[4] = 0x1F; + + // Padded vendor, product, revision + memcpy(&buf[8], GetPaddedName().c_str(), 28); + } + + return allocation_length; +} + int PrimaryDevice::RequestSense(const DWORD *cdb, BYTE *buf) { ASSERT(cdb); diff --git a/src/raspberrypi/devices/primary_device.h b/src/raspberrypi/devices/primary_device.h index 6949e17b..1068afdc 100644 --- a/src/raspberrypi/devices/primary_device.h +++ b/src/raspberrypi/devices/primary_device.h @@ -11,11 +11,11 @@ #pragma once -#include "controllers/sasidev_ctrl.h" +#include "controllers/scsidev_ctrl.h" #include "interfaces/scsi_primary_commands.h" #include "device.h" +#include "dispatcher.h" #include -#include using namespace std; @@ -23,33 +23,29 @@ class PrimaryDevice: public Device, virtual public ScsiPrimaryCommands { public: - PrimaryDevice(const string); + PrimaryDevice(const string&); virtual ~PrimaryDevice() {} - virtual bool Dispatch(SCSIDEV *) override; + virtual bool Dispatch(SCSIDEV *); void TestUnitReady(SASIDEV *); void RequestSense(SASIDEV *); + void SetCtrl(SASIDEV::ctrl_t *ctrl) { this->ctrl = ctrl; } + bool CheckReady(); virtual int Inquiry(const DWORD *, BYTE *) = 0; virtual int RequestSense(const DWORD *, BYTE *); protected: + int Inquiry(int, bool, const DWORD *, BYTE *); + SASIDEV::ctrl_t *ctrl; private: - typedef struct _command_t { - const char* name; - void (PrimaryDevice::*execute)(SASIDEV *); - - _command_t(const char* _name, void (PrimaryDevice::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; - } command_t; - std::map commands; - - void AddCommand(ScsiDefs::scsi_command, const char*, void (PrimaryDevice::*)(SASIDEV *)); + Dispatcher dispatcher; void Inquiry(SASIDEV *); void ReportLuns(SASIDEV *); diff --git a/src/raspberrypi/devices/sasihd.cpp b/src/raspberrypi/devices/sasihd.cpp index ec901478..be8293d2 100644 --- a/src/raspberrypi/devices/sasihd.cpp +++ b/src/raspberrypi/devices/sasihd.cpp @@ -13,11 +13,11 @@ // [ SASI hard disk ] // //--------------------------------------------------------------------------- + #include "sasihd.h" #include "fileio.h" #include "exceptions.h" -#include -#include "../rascsi.h" +#include "../config.h" //=========================================================================== // diff --git a/src/raspberrypi/devices/scsi_daynaport.cpp b/src/raspberrypi/devices/scsi_daynaport.cpp index 5c55f678..a789fc00 100644 --- a/src/raspberrypi/devices/scsi_daynaport.cpp +++ b/src/raspberrypi/devices/scsi_daynaport.cpp @@ -28,23 +28,25 @@ //--------------------------------------------------------------------------- #include "scsi_daynaport.h" -#include + +using namespace scsi_defs; const BYTE SCSIDaynaPort::m_bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; const BYTE SCSIDaynaPort::m_apple_talk_addr[6] = { 0x09, 0x00, 0x07, 0xff, 0xff, 0xff }; +// TODO Disk should not be the superclass SCSIDaynaPort::SCSIDaynaPort() : Disk("SCDP") { m_tap = NULL; m_bTapEnable = false; - AddCommand(ScsiDefs::eCmdTestUnitReady, "TestUnitReady", &SCSIDaynaPort::TestUnitReady); - AddCommand(ScsiDefs::eCmdRead6, "Read6", &SCSIDaynaPort::Read6); - AddCommand(ScsiDefs::eCmdWrite6, "Write6", &SCSIDaynaPort::Write6); - AddCommand(ScsiDefs::eCmdRetrieveStats, "RetrieveStats", &SCSIDaynaPort::RetrieveStatistics); - AddCommand(ScsiDefs::eCmdSetIfaceMode, "SetIfaceMode", &SCSIDaynaPort::SetInterfaceMode); - AddCommand(ScsiDefs::eCmdSetMcastAddr, "SetMcastAddr", &SCSIDaynaPort::SetMcastAddr); - AddCommand(ScsiDefs::eCmdEnableInterface, "EnableInterface", &SCSIDaynaPort::EnableInterface); + dispatcher.AddCommand(eCmdTestUnitReady, "TestUnitReady", &SCSIDaynaPort::TestUnitReady); + dispatcher.AddCommand(eCmdRead6, "Read6", &SCSIDaynaPort::Read6); + dispatcher.AddCommand(eCmdWrite6, "Write6", &SCSIDaynaPort::Write6); + dispatcher.AddCommand(eCmdRetrieveStats, "RetrieveStats", &SCSIDaynaPort::RetrieveStatistics); + dispatcher.AddCommand(eCmdSetIfaceMode, "SetIfaceMode", &SCSIDaynaPort::SetInterfaceMode); + dispatcher.AddCommand(eCmdSetMcastAddr, "SetMcastAddr", &SCSIDaynaPort::SetMcastAddr); + dispatcher.AddCommand(eCmdEnableInterface, "EnableInterface", &SCSIDaynaPort::EnableInterface); } SCSIDaynaPort::~SCSIDaynaPort() @@ -54,35 +56,12 @@ SCSIDaynaPort::~SCSIDaynaPort() m_tap->Cleanup(); delete m_tap; } - - for (auto const& command : commands) { - delete command.second; - } -} - -void SCSIDaynaPort::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (SCSIDaynaPort::*execute)(SASIDEV *)) -{ - commands[opcode] = new command_t(name, execute); } bool SCSIDaynaPort::Dispatch(SCSIDEV *controller) { - ctrl = controller->GetCtrl(); - - if (commands.count(static_cast(ctrl->cmd[0]))) { - command_t *command = commands[static_cast(ctrl->cmd[0])]; - - LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); - - (this->*command->execute)(controller); - - return true; - } - - LOGTRACE("%s Calling base class for dispatching $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[0]); - - // The base class handles the less specific commands - return Disk::Dispatch(controller); + // The superclass class handles the less specific commands + return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } bool SCSIDaynaPort::Init(const map& params) @@ -133,36 +112,10 @@ void SCSIDaynaPort::Open(const Filepath& path) m_tap->OpenDump(path); } -//--------------------------------------------------------------------------- -// -// INQUIRY -// -//--------------------------------------------------------------------------- int SCSIDaynaPort::Inquiry(const DWORD *cdb, BYTE *buf) { - int allocation_length = cdb[4] + (((DWORD)cdb[3]) << 8); - if (allocation_length > 4) { - if (allocation_length > 44) { - allocation_length = 44; - } - - // Basic data - // buf[0] ... Processor Device - // buf[1] ... Not removable - // buf[2] ... SCSI-2 compliant command system - // buf[3] ... SCSI-2 compliant Inquiry response - // buf[4] ... Inquiry additional data - // http://www.bitsavers.org/pdf/apple/scsi/dayna/daynaPORT/pocket_scsiLINK/pocketscsilink_inq.png - memset(buf, 0, allocation_length); - buf[0] = 0x03; - buf[2] = 0x01; - buf[4] = 0x1F; - - // Padded vendor, product, revision - memcpy(&buf[8], GetPaddedName().c_str(), 28); - } - - return allocation_length; + // Processor device, not removable + return PrimaryDevice::Inquiry(3, false, cdb, buf); } //--------------------------------------------------------------------------- @@ -201,10 +154,6 @@ int SCSIDaynaPort::Read(const DWORD *cdb, BYTE *buf, uint64_t block) int rx_packet_size = 0; scsi_resp_read_t *response = (scsi_resp_read_t*)buf; - ostringstream s; - s << __PRETTY_FUNCTION__ << " reading DaynaPort block " << block; - LOGTRACE("%s", s.str().c_str()); - int requested_length = cdb[4]; LOGTRACE("%s Read maximum length %d, (%04X)", __PRETTY_FUNCTION__, requested_length, requested_length); diff --git a/src/raspberrypi/devices/scsi_daynaport.h b/src/raspberrypi/devices/scsi_daynaport.h index 1a08b4f2..404965d3 100644 --- a/src/raspberrypi/devices/scsi_daynaport.h +++ b/src/raspberrypi/devices/scsi_daynaport.h @@ -42,19 +42,6 @@ class SCSIDaynaPort: public Disk { -private: - typedef struct _command_t { - const char* name; - void (SCSIDaynaPort::*execute)(SASIDEV *); - - _command_t(const char* _name, void (SCSIDaynaPort::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; - } command_t; - std::map commands; - - SASIDEV::ctrl_t *ctrl; - - void AddCommand(ScsiDefs::scsi_command, const char*, void (SCSIDaynaPort::*)(SASIDEV *)); - public: SCSIDaynaPort(); ~SCSIDaynaPort(); @@ -103,6 +90,10 @@ public: static const DWORD DAYNAPORT_READ_HEADER_SZ = 2 + 4; private: + typedef Disk super; + + Dispatcher dispatcher; + typedef struct __attribute__((packed)) { BYTE operation_code; BYTE misc_cdb_information; diff --git a/src/raspberrypi/devices/scsi_host_bridge.cpp b/src/raspberrypi/devices/scsi_host_bridge.cpp index 73d6cd4d..a4a956c8 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.cpp +++ b/src/raspberrypi/devices/scsi_host_bridge.cpp @@ -16,17 +16,19 @@ // work with the Sharp X68000 operating system. //--------------------------------------------------------------------------- +#include "controllers/scsidev_ctrl.h" #include "scsi_host_bridge.h" #include "ctapdriver.h" #include "cfilesystem.h" -#include using namespace std; +using namespace scsi_defs; -SCSIBR::SCSIBR() : Disk("SCBR") +SCSIBR::SCSIBR() : PrimaryDevice("SCBR") { tap = NULL; m_bTapEnable = false; + packet_enable = false; fsoptlen = 0; fsoutlen = 0; @@ -37,9 +39,9 @@ SCSIBR::SCSIBR() : Disk("SCBR") fs = new CFileSys(); fs->Reset(); - AddCommand(ScsiDefs::eCmdTestUnitReady, "TestUnitReady", &SCSIBR::TestUnitReady); - AddCommand(ScsiDefs::eCmdRead6, "GetMessage10", &SCSIBR::GetMessage10); - AddCommand(ScsiDefs::eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10); + dispatcher.AddCommand(eCmdTestUnitReady, "TestUnitReady", &SCSIBR::TestUnitReady); + dispatcher.AddCommand(eCmdRead6, "GetMessage10", &SCSIBR::GetMessage10); + dispatcher.AddCommand(eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10); } SCSIBR::~SCSIBR() @@ -55,10 +57,6 @@ SCSIBR::~SCSIBR() fs->Reset(); delete fs; } - - for (auto const& command : commands) { - delete command.second; - } } bool SCSIBR::Init(const map& params) @@ -96,29 +94,10 @@ bool SCSIBR::Init(const map& params) #endif } -void SCSIBR::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (SCSIBR::*execute)(SASIDEV *)) -{ - commands[opcode] = new command_t(name, execute); -} - bool SCSIBR::Dispatch(SCSIDEV *controller) { - ctrl = controller->GetCtrl(); - - if (commands.count(static_cast(ctrl->cmd[0]))) { - command_t *command = commands[static_cast(ctrl->cmd[0])]; - - LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); - - (this->*command->execute)(controller); - - return true; - } - - LOGTRACE("%s Calling base class for dispatching $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[0]); - - // The base class handles the less specific commands - return Disk::Dispatch(controller); + // The superclass class handles the less specific commands + return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } //--------------------------------------------------------------------------- @@ -128,14 +107,10 @@ bool SCSIBR::Dispatch(SCSIDEV *controller) //--------------------------------------------------------------------------- int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf) { - ASSERT(cdb); - ASSERT(buf); - ASSERT(cdb[0] == 0x12); - // EVPD check if (cdb[1] & 0x01) { SetStatusCode(STATUS_INVALIDCDB); - return FALSE; + return 0; } // Basic data @@ -175,15 +150,9 @@ int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf) return size; } -//--------------------------------------------------------------------------- -// -// TEST UNIT READY -// -//--------------------------------------------------------------------------- void SCSIBR::TestUnitReady(SASIDEV *controller) { - // TEST UNIT READY Success - + // Always successful controller->Status();} //--------------------------------------------------------------------------- diff --git a/src/raspberrypi/devices/scsi_host_bridge.h b/src/raspberrypi/devices/scsi_host_bridge.h index 1ecee189..81b19dfd 100644 --- a/src/raspberrypi/devices/scsi_host_bridge.h +++ b/src/raspberrypi/devices/scsi_host_bridge.h @@ -18,7 +18,7 @@ #pragma once #include "os.h" -#include "disk.h" +#include "primary_device.h" #include //=========================================================================== @@ -29,22 +29,9 @@ class CTapDriver; class CFileSys; -class SCSIBR : public Disk +class SCSIBR : public PrimaryDevice { -private: - typedef struct _command_t { - const char* name; - void (SCSIBR::*execute)(SASIDEV *); - - _command_t(const char* _name, void (SCSIBR::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; - } command_t; - std::map commands; - - SASIDEV::ctrl_t *ctrl; - - void AddCommand(ScsiDefs::scsi_command, const char*, void (SCSIBR::*)(SASIDEV *)); - public: SCSIBR(); ~SCSIBR(); @@ -61,6 +48,10 @@ public: void SendMessage10(SASIDEV *); private: + typedef PrimaryDevice super; + + Dispatcher dispatcher; + int GetMacAddr(BYTE *buf); // Get MAC address void SetMacAddr(BYTE *buf); // Set MAC address void ReceivePacket(); // Receive a packet diff --git a/src/raspberrypi/devices/scsicd.cpp b/src/raspberrypi/devices/scsicd.cpp index 1744b7f6..a250c443 100644 --- a/src/raspberrypi/devices/scsicd.cpp +++ b/src/raspberrypi/devices/scsicd.cpp @@ -10,14 +10,15 @@ // Licensed under the BSD 3-Clause License. // See LICENSE file in the project root folder. // -// [ SCSI CD-ROM for Apple Macintosh ] +// [ SCSI CD-ROM ] // //--------------------------------------------------------------------------- #include "scsicd.h" #include "fileio.h" #include "exceptions.h" -#include + +using namespace scsi_defs; //=========================================================================== // @@ -240,8 +241,8 @@ SCSICD::SCSICD() : Disk("SCCD"), ScsiMmcCommands(), FileSupport() dataindex = -1; audioindex = -1; - AddCommand(ScsiDefs::eCmdReadToc, "ReadToc", &SCSICD::ReadToc); - AddCommand(ScsiDefs::eCmdGetEventStatusNotification, "GetEventStatusNotification", &SCSICD::GetEventStatusNotification); + dispatcher.AddCommand(eCmdReadToc, "ReadToc", &SCSICD::ReadToc); + dispatcher.AddCommand(eCmdGetEventStatusNotification, "GetEventStatusNotification", &SCSICD::GetEventStatusNotification); } //--------------------------------------------------------------------------- @@ -253,35 +254,12 @@ SCSICD::~SCSICD() { // Clear track ClearTrack(); - - for (auto const& command : commands) { - delete command.second; - } -} - -void SCSICD::AddCommand(ScsiDefs::scsi_command opcode, const char* name, void (SCSICD::*execute)(SASIDEV *)) -{ - commands[opcode] = new command_t(name, execute); } bool SCSICD::Dispatch(SCSIDEV *controller) { - ctrl = controller->GetCtrl(); - - if (commands.count(static_cast(ctrl->cmd[0]))) { - command_t *command = commands[static_cast(ctrl->cmd[0])]; - - LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); - - (this->*command->execute)(controller); - - return true; - } - - LOGTRACE("%s Calling base class for dispatching $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[0]); - - // The base class handles the less specific commands - return Disk::Dispatch(controller); + // The superclass class handles the less specific commands + return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller); } //--------------------------------------------------------------------------- @@ -421,9 +399,8 @@ void SCSICD::OpenIso(const Filepath& path) if (rawfile) { // Size must be a multiple of 2536 if (size % 2536) { - stringstream error; - error << "Raw ISO CD-ROM file size must be a multiple of 2536 bytes but is " << size << " bytes"; - throw io_exception(error.str()); + throw io_exception("Raw ISO CD-ROM file size must be a multiple of 2536 bytes but is " + + to_string(size) + " bytes"); } // Set the number of blocks @@ -499,13 +476,10 @@ void SCSICD::ReadToc(SASIDEV *controller) //--------------------------------------------------------------------------- int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf) { - ASSERT(cdb); - ASSERT(buf); - // EVPD check if (cdb[1] & 0x01) { SetStatusCode(STATUS_INVALIDCDB); - return FALSE; + return 0; } // Basic data diff --git a/src/raspberrypi/devices/scsicd.h b/src/raspberrypi/devices/scsicd.h index 2e860467..c52719ab 100644 --- a/src/raspberrypi/devices/scsicd.h +++ b/src/raspberrypi/devices/scsicd.h @@ -71,25 +71,12 @@ private: //=========================================================================== class SCSICD : public Disk, public ScsiMmcCommands, public FileSupport { -private: - typedef struct _command_t { - const char* name; - void (SCSICD::*execute)(SASIDEV *); - - _command_t(const char* _name, void (SCSICD::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; - } command_t; - std::map commands; - - SASIDEV::ctrl_t *ctrl; - - void AddCommand(ScsiDefs::scsi_command, const char*, void (SCSICD::*)(SASIDEV *)); public: enum { TrackMax = 96 // Maximum number of tracks }; -public: SCSICD(); ~SCSICD(); @@ -103,6 +90,10 @@ public: int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command private: + typedef Disk super; + + Dispatcher dispatcher; + // Open void OpenCue(const Filepath& path); // Open(CUE) void OpenIso(const Filepath& path); // Open(ISO) diff --git a/src/raspberrypi/devices/scsihd.cpp b/src/raspberrypi/devices/scsihd.cpp index 7b509094..58981a05 100644 --- a/src/raspberrypi/devices/scsihd.cpp +++ b/src/raspberrypi/devices/scsihd.cpp @@ -119,9 +119,6 @@ void SCSIHD::Open(const Filepath& path) //--------------------------------------------------------------------------- int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf) { - ASSERT(cdb); - ASSERT(buf); - // EVPD check if (cdb[1] & 0x01) { SetStatusCode(STATUS_INVALIDCDB); diff --git a/src/raspberrypi/devices/scsimo.cpp b/src/raspberrypi/devices/scsimo.cpp index 83496ed6..75d1bc2c 100644 --- a/src/raspberrypi/devices/scsimo.cpp +++ b/src/raspberrypi/devices/scsimo.cpp @@ -18,7 +18,6 @@ #include "fileio.h" #include "exceptions.h" -#include //=========================================================================== // diff --git a/src/raspberrypi/fileio.cpp b/src/raspberrypi/fileio.cpp index 066abddd..c6dc70b2 100644 --- a/src/raspberrypi/fileio.cpp +++ b/src/raspberrypi/fileio.cpp @@ -11,7 +11,8 @@ #include "os.h" #include "filepath.h" #include "fileio.h" -#include "rascsi.h" + +#include "config.h" //=========================================================================== // diff --git a/src/raspberrypi/filepath.cpp b/src/raspberrypi/filepath.cpp index 65555218..1088bcd7 100644 --- a/src/raspberrypi/filepath.cpp +++ b/src/raspberrypi/filepath.cpp @@ -10,8 +10,8 @@ #include "os.h" #include "filepath.h" +#include "config.h" #include "fileio.h" -#include "rascsi.h" //=========================================================================== // diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp index f09372af..e1797bb0 100644 --- a/src/raspberrypi/gpiobus.cpp +++ b/src/raspberrypi/gpiobus.cpp @@ -16,8 +16,9 @@ #include "os.h" #include "gpiobus.h" + +#include "config.h" #include "log.h" -#include "rascsi.h" #ifdef __linux__ //--------------------------------------------------------------------------- diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h index 46babdce..78b01b54 100644 --- a/src/raspberrypi/gpiobus.h +++ b/src/raspberrypi/gpiobus.h @@ -12,7 +12,7 @@ #if !defined(gpiobus_h) #define gpiobus_h -#include "rascsi.h" +#include "config.h" #include "scsi.h" //--------------------------------------------------------------------------- diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 1747e39a..1243720d 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -10,7 +10,6 @@ // //--------------------------------------------------------------------------- -#include "rascsi.h" #include "os.h" #include "controllers/sasidev_ctrl.h" #include "devices/device_factory.h" @@ -34,6 +33,7 @@ #include #include #include +#include "config.h" using namespace std; using namespace spdlog; @@ -520,17 +520,17 @@ string SetReservedIds(const string& ids) reserved_ids = reserved; if (!reserved_ids.empty()) { - ostringstream s; + string s; bool isFirst = true; for (auto const& reserved_id : reserved_ids) { if (!isFirst) { - s << ", "; + s += ", "; } isFirst = false; - s << reserved_id; + s += to_string(reserved_id); } - LOGINFO("Reserved ID(s) set to %s", s.str().c_str()); + LOGINFO("Reserved ID(s) set to %s", s.c_str()); } else { LOGINFO("Cleared reserved IDs"); @@ -580,15 +580,14 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, if (unit >= supported_luns) { delete device; - ostringstream error; - error << "Invalid unit " << unit << " for device type " << PbDeviceType_Name(type); + string error = "Invalid unit " + to_string(unit) + " for device type " + PbDeviceType_Name(type); if (supported_luns == 1) { - error << " (0)"; + error += " (0)"; } else { - error << " (0-" << (supported_luns -1) << ")"; + error += " (0-" + to_string(supported_luns -1) + ")"; } - return ReturnStatus(context, false, error.str()); + return ReturnStatus(context, false, error); } // If no filename was provided the medium is considered removed @@ -709,16 +708,15 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, // Re-map the controller if (MapController(map)) { - ostringstream msg; - msg << "Attached "; + string msg = "Attached "; if (device->IsReadOnly()) { - msg << "read-only "; + msg += "read-only "; } else if (device->IsProtectable() && device->IsProtected()) { - msg << "protected "; + msg += "protected "; } - msg << device->GetType() << " device, ID " << id << ", unit " << unit; - LOGINFO("%s", msg.str().c_str()); + msg += device->GetType() + " device, ID " + to_string(id) + ", unit " + to_string(unit); + LOGINFO("%s", msg.c_str()); return true; } @@ -840,8 +838,6 @@ void TerminationHandler(int signum) bool ProcessCmd(const CommandContext& context, const PbDeviceDefinition& pb_device, const PbCommand& command, bool dryRun) { - ostringstream error; - const int id = pb_device.id(); const int unit = pb_device.unit(); const PbDeviceType type = pb_device.type(); diff --git a/src/raspberrypi/rascsi_response.cpp b/src/raspberrypi/rascsi_response.cpp index a9ff6883..6f7b1fbf 100644 --- a/src/raspberrypi/rascsi_response.cpp +++ b/src/raspberrypi/rascsi_response.cpp @@ -70,7 +70,7 @@ void RascsiResponse::GetAllDeviceTypeProperties(PbDeviceTypesInfo& device_types_ int ordinal = 1; while (PbDeviceType_IsValid(ordinal)) { PbDeviceType type = UNDEFINED; - PbDeviceType_Parse(PbDeviceType_Name(ordinal), &type); + PbDeviceType_Parse(PbDeviceType_Name((PbDeviceType)ordinal), &type); GetDeviceTypeProperties(device_types_info, type); ordinal++; } diff --git a/src/raspberrypi/rasctl_commands.cpp b/src/raspberrypi/rasctl_commands.cpp index af4e21e3..f192432d 100644 --- a/src/raspberrypi/rasctl_commands.cpp +++ b/src/raspberrypi/rasctl_commands.cpp @@ -14,7 +14,6 @@ #include "rasutil.h" #include "rasctl_commands.h" #include "rascsi_interface.pb.h" -#include #include #include @@ -66,9 +65,8 @@ void RasctlCommands::SendCommand() memcpy(&server.sin_addr.s_addr, host->h_addr, host->h_length); if (connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) { - ostringstream error; - error << "Can't connect to rascsi process on host '" << hostname << "', port " << port; - throw io_exception(error.str()); + throw io_exception("Can't connect to rascsi process on host '" + hostname + "', port " + + to_string(port)); } if (write(fd, "RASCSI", 6) != 6) { diff --git a/src/raspberrypi/sasidump.cpp b/src/raspberrypi/sasidump.cpp index c0d3ac0f..92d6dc48 100644 --- a/src/raspberrypi/sasidump.cpp +++ b/src/raspberrypi/sasidump.cpp @@ -23,7 +23,6 @@ #include "fileio.h" #include "filepath.h" #include "gpiobus.h" -#include "rascsi.h" #include "rascsi_version.h" #define BUFSIZE 1024 * 64 // Maybe around 64KB? diff --git a/src/raspberrypi/scsi.h b/src/raspberrypi/scsi.h index 98897efd..ad4f62ee 100644 --- a/src/raspberrypi/scsi.h +++ b/src/raspberrypi/scsi.h @@ -154,8 +154,7 @@ private: static const char* phase_str_table[]; }; -class ScsiDefs { -public: +namespace scsi_defs { enum scsi_command : int { eCmdTestUnitReady = 0x00, eCmdRezero = 0x01,