diff --git a/src/raspberrypi/devices/device_factory.cpp b/src/raspberrypi/devices/device_factory.cpp index 3a198e0c..9af35d65 100644 --- a/src/raspberrypi/devices/device_factory.cpp +++ b/src/raspberrypi/devices/device_factory.cpp @@ -20,6 +20,27 @@ using namespace std; using namespace rascsi_interface; +DeviceFactory::DeviceFactory() +{ + sector_sizes_sasi.push_back(256); + sector_sizes_sasi.push_back(1024); + + sector_sizes_scsi.push_back(512); + sector_sizes_scsi.push_back(1024); + sector_sizes_scsi.push_back(2048); + sector_sizes_scsi.push_back(4096); +} + +DeviceFactory::~DeviceFactory() +{ +} + +DeviceFactory& DeviceFactory::instance() +{ + static DeviceFactory instance; + return instance; +} + Device *DeviceFactory::CreateDevice(PbDeviceType& type, const string& filename, const string& ext) { // If no type was specified try to derive the device type from the filename and extension @@ -45,16 +66,12 @@ Device *DeviceFactory::CreateDevice(PbDeviceType& type, const string& filename, } } - vector sector_sizes; - sector_sizes.push_back(512); - sector_sizes.push_back(1024); - sector_sizes.push_back(2048); - sector_sizes.push_back(4096); - Device *device = NULL; switch (type) { - case SAHD: - device = new SASIHD(); + case SAHD: { + device = new SASIHD(); + ((Disk *)device)->SetSectorSizes(sector_sizes_sasi); + } break; case SCHD: @@ -64,7 +81,7 @@ Device *DeviceFactory::CreateDevice(PbDeviceType& type, const string& filename, } else { device = new SCSIHD(); device->SetProtectable(true); - ((Disk *)device)->SetSectorSizes(sector_sizes); + ((Disk *)device)->SetSectorSizes(sector_sizes_scsi); } break; @@ -74,7 +91,7 @@ Device *DeviceFactory::CreateDevice(PbDeviceType& type, const string& filename, device->SetProtectable(true); device->SetLockable(true); device->SetProtectable(true); - ((Disk *)device)->SetSectorSizes(sector_sizes); + ((Disk *)device)->SetSectorSizes(sector_sizes_scsi); break; case SCMO: diff --git a/src/raspberrypi/devices/device_factory.h b/src/raspberrypi/devices/device_factory.h index 9d4265ef..a26f8ed1 100644 --- a/src/raspberrypi/devices/device_factory.h +++ b/src/raspberrypi/devices/device_factory.h @@ -5,12 +5,13 @@ // // Copyright (C) 2021 Uwe Seimet // -// A DeviceFactory creates devices based on their type and the extension of their image file +// The DeviceFactory singleton creates devices based on their type and the extension of their image file // //--------------------------------------------------------------------------- #pragma once +#include #include #include "rascsi_interface.pb.h" @@ -20,8 +21,18 @@ class DeviceFactory { public: - DeviceFactory() { }; - ~DeviceFactory() { }; + DeviceFactory(); + ~DeviceFactory(); - static Device *CreateDevice(rascsi_interface::PbDeviceType& type, const std::string& filename, const std::string& ext); + static DeviceFactory& instance(); + + const std::vector& GetSasiSectorSizes() const { return sector_sizes_sasi; }; + const std::vector& GetScsiSectorSizes() const { return sector_sizes_scsi; }; + + Device *CreateDevice(rascsi_interface::PbDeviceType& type, const std::string& filename, const std::string& ext); + +private: + + std::vector sector_sizes_sasi; + std::vector sector_sizes_scsi; }; diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index 0597fd92..951f2bca 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -29,6 +29,137 @@ // //=========================================================================== +//--------------------------------------------------------------------------- +// +// Constructor +// +//--------------------------------------------------------------------------- +Disk::Disk(const std::string id) : Device(id), PrimaryDevice(), BlockDevice() +{ + // Work initialization + configured_sector_size = 0; + disk.size = 0; + disk.blocks = 0; + disk.dcache = NULL; + disk.imgoffset = 0; + + AddCommand(SCSIDEV::eCmdTestUnitReady, "TestUnitReady", &Disk::TestUnitReady); + AddCommand(SCSIDEV::eCmdRezero, "Rezero", &Disk::Rezero); + AddCommand(SCSIDEV::eCmdRequestSense, "RequestSense", &Disk::RequestSense); + AddCommand(SCSIDEV::eCmdFormat, "FormatUnit", &Disk::FormatUnit); + AddCommand(SCSIDEV::eCmdReassign, "ReassignBlocks", &Disk::ReassignBlocks); + AddCommand(SCSIDEV::eCmdRead6, "Read6", &Disk::Read6); + AddCommand(SCSIDEV::eCmdWrite6, "Write6", &Disk::Write6); + AddCommand(SCSIDEV::eCmdSeek6, "Seek6", &Disk::Seek6); + AddCommand(SCSIDEV::eCmdInquiry, "Inquiry", &Disk::Inquiry); + AddCommand(SCSIDEV::eCmdModeSelect, "ModeSelect", &Disk::ModeSelect); + AddCommand(SCSIDEV::eCmdReserve6, "Reserve6", &Disk::Reserve6); + AddCommand(SCSIDEV::eCmdRelease6, "Release6", &Disk::Release6); + AddCommand(SCSIDEV::eCmdModeSense, "ModeSense", &Disk::ModeSense); + AddCommand(SCSIDEV::eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit); + AddCommand(SCSIDEV::eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic); + AddCommand(SCSIDEV::eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval); + AddCommand(SCSIDEV::eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10); + AddCommand(SCSIDEV::eCmdRead10, "Read10", &Disk::Read10); + AddCommand(SCSIDEV::eCmdWrite10, "Write10", &Disk::Write10); + AddCommand(SCSIDEV::eCmdVerify10, "Verify10", &Disk::Write10); + AddCommand(SCSIDEV::eCmdSeek10, "Seek10", &Disk::Seek10); + AddCommand(SCSIDEV::eCmdVerify10, "Verify10", &Disk::Verify10); + AddCommand(SCSIDEV::eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10); + AddCommand(SCSIDEV::eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16); + AddCommand(SCSIDEV::eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10); + AddCommand(SCSIDEV::eCmdModeSelect10, "ModeSelect10", &Disk::ModeSelect10); + AddCommand(SCSIDEV::eCmdReserve10, "Reserve10", &Disk::Reserve10); + AddCommand(SCSIDEV::eCmdRelease10, "Release10", &Disk::Release10); + AddCommand(SCSIDEV::eCmdModeSense10, "ModeSense10", &Disk::ModeSense10); + AddCommand(SCSIDEV::eCmdRead16, "Read16", &Disk::Read16); + AddCommand(SCSIDEV::eCmdWrite16, "Write16", &Disk::Write16); + AddCommand(SCSIDEV::eCmdVerify16, "Verify16", &Disk::Verify16); + AddCommand(SCSIDEV::eCmdReadCapacity16, "ReadCapacity16", &Disk::ReadCapacity16); + AddCommand(SCSIDEV::eCmdReportLuns, "ReportLuns", &Disk::ReportLuns); +} + +//--------------------------------------------------------------------------- +// +// Destructor +// +//--------------------------------------------------------------------------- +Disk::~Disk() +{ + // Save disk cache + if (IsReady()) { + // Only if ready... + if (disk.dcache) { + disk.dcache->Save(); + } + } + + // Clear disk cache + if (disk.dcache) { + delete disk.dcache; + disk.dcache = NULL; + } + + for (auto const& command : commands) { + delete command.second; + } +} + +void Disk::AddCommand(SCSIDEV::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; + } + + // Unknown command + return false; +} + +//--------------------------------------------------------------------------- +// +// Open +// * Call as a post-process after successful opening in a derived class +// +//--------------------------------------------------------------------------- +void Disk::Open(const Filepath& path) +{ + ASSERT((disk.size >= 8) && (disk.size <= 12)); + ASSERT(disk.blocks > 0); + + SetReady(true); + + // Cache initialization + ASSERT(!disk.dcache); + disk.dcache = new DiskCache(path, disk.size, disk.blocks, disk.imgoffset); + + // Can read/write open + Fileio fio; + if (fio.Open(path, Fileio::ReadWrite)) { + // Write permission + fio.Close(); + } else { + // Permanently write-protected + SetReadOnly(true); + SetProtectable(false); + SetProtected(false); + } + + SetLocked(false); + SetRemoved(false); +} void Disk::TestUnitReady(SASIDEV *controller) { @@ -410,144 +541,6 @@ void Disk::ReadDefectData10(SASIDEV *controller) controller->DataIn(); } -//=========================================================================== -// -// Disk -// -//=========================================================================== - -//--------------------------------------------------------------------------- -// -// Constructor -// -//--------------------------------------------------------------------------- -Disk::Disk(const std::string id) : Device(id), PrimaryDevice(), BlockDevice() -{ - // Work initialization - configured_sector_size = 0; - disk.size = 0; - disk.blocks = 0; - disk.dcache = NULL; - disk.imgoffset = 0; - - AddCommand(SCSIDEV::eCmdTestUnitReady, "TestUnitReady", &Disk::TestUnitReady); - AddCommand(SCSIDEV::eCmdRezero, "Rezero", &Disk::Rezero); - AddCommand(SCSIDEV::eCmdRequestSense, "RequestSense", &Disk::RequestSense); - AddCommand(SCSIDEV::eCmdFormat, "FormatUnit", &Disk::FormatUnit); - AddCommand(SCSIDEV::eCmdReassign, "ReassignBlocks", &Disk::ReassignBlocks); - AddCommand(SCSIDEV::eCmdRead6, "Read6", &Disk::Read6); - AddCommand(SCSIDEV::eCmdWrite6, "Write6", &Disk::Write6); - AddCommand(SCSIDEV::eCmdSeek6, "Seek6", &Disk::Seek6); - AddCommand(SCSIDEV::eCmdInquiry, "Inquiry", &Disk::Inquiry); - AddCommand(SCSIDEV::eCmdModeSelect, "ModeSelect", &Disk::ModeSelect); - AddCommand(SCSIDEV::eCmdReserve6, "Reserve6", &Disk::Reserve6); - AddCommand(SCSIDEV::eCmdRelease6, "Release6", &Disk::Release6); - AddCommand(SCSIDEV::eCmdModeSense, "ModeSense", &Disk::ModeSense); - AddCommand(SCSIDEV::eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit); - AddCommand(SCSIDEV::eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic); - AddCommand(SCSIDEV::eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval); - AddCommand(SCSIDEV::eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10); - AddCommand(SCSIDEV::eCmdRead10, "Read10", &Disk::Read10); - AddCommand(SCSIDEV::eCmdWrite10, "Write10", &Disk::Write10); - AddCommand(SCSIDEV::eCmdVerify10, "Verify10", &Disk::Write10); - AddCommand(SCSIDEV::eCmdSeek10, "Seek10", &Disk::Seek10); - AddCommand(SCSIDEV::eCmdVerify10, "Verify10", &Disk::Verify10); - AddCommand(SCSIDEV::eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10); - AddCommand(SCSIDEV::eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16); - AddCommand(SCSIDEV::eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10); - AddCommand(SCSIDEV::eCmdModeSelect10, "ModeSelect10", &Disk::ModeSelect10); - AddCommand(SCSIDEV::eCmdReserve10, "Reserve10", &Disk::Reserve10); - AddCommand(SCSIDEV::eCmdRelease10, "Release10", &Disk::Release10); - AddCommand(SCSIDEV::eCmdModeSense10, "ModeSense10", &Disk::ModeSense10); - AddCommand(SCSIDEV::eCmdRead16, "Read16", &Disk::Read16); - AddCommand(SCSIDEV::eCmdWrite16, "Write16", &Disk::Write16); - AddCommand(SCSIDEV::eCmdVerify16, "Verify16", &Disk::Verify16); - AddCommand(SCSIDEV::eCmdReadCapacity16, "ReadCapacity16", &Disk::ReadCapacity16); - AddCommand(SCSIDEV::eCmdReportLuns, "ReportLuns", &Disk::ReportLuns); -} - -//--------------------------------------------------------------------------- -// -// Destructor -// -//--------------------------------------------------------------------------- -Disk::~Disk() -{ - // Save disk cache - if (IsReady()) { - // Only if ready... - if (disk.dcache) { - disk.dcache->Save(); - } - } - - // Clear disk cache - if (disk.dcache) { - delete disk.dcache; - disk.dcache = NULL; - } - - for (auto const& command : commands) { - delete command.second; - } -} - -void Disk::AddCommand(SCSIDEV::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; - } - - // Unknown command - return false; -} - -//--------------------------------------------------------------------------- -// -// Open -// * Call as a post-process after successful opening in a derived class -// -//--------------------------------------------------------------------------- -void Disk::Open(const Filepath& path) -{ - ASSERT((disk.size >= 8) && (disk.size <= 12)); - ASSERT(disk.blocks > 0); - - SetReady(true); - - // Cache initialization - ASSERT(!disk.dcache); - disk.dcache = new DiskCache(path, disk.size, disk.blocks, disk.imgoffset); - - // Can read/write open - Fileio fio; - if (fio.Open(path, Fileio::ReadWrite)) { - // Write permission - fio.Close(); - } else { - // Permanently write-protected - SetReadOnly(true); - SetProtectable(false); - SetProtected(false); - } - - SetLocked(false); - SetRemoved(false); -} - //--------------------------------------------------------------------------- // // Eject diff --git a/src/raspberrypi/devices/sasihd.cpp b/src/raspberrypi/devices/sasihd.cpp index b79f9ae6..196ca0d4 100644 --- a/src/raspberrypi/devices/sasihd.cpp +++ b/src/raspberrypi/devices/sasihd.cpp @@ -69,24 +69,14 @@ void SASIHD::Open(const Filepath& path) off_t size = fio.GetFileSize(); fio.Close(); - #if defined(USE_MZ1F23_1024_SUPPORT) - // For MZ-2500 / MZ-2800 MZ-1F23 (SASI 20M / sector size 1024) only - // 20M(22437888 BS=1024 C=21912) - if (size == 0x1566000) { - // Sector size and number of blocks - SetSectorSizeInBytes(1024); - SetBlockCount((DWORD)(size >> 10)); - - Disk::Open(path); - FileSupport::SetPath(path); - } - #endif // USE_MZ1F23_1024_SUPPORT + // Sector size (default 256 bytes) and number of blocks + SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 256); + SetBlockCount((DWORD)(size >> GetSectorSize())); #if defined(REMOVE_FIXED_SASIHD_SIZE) - // Must be in 256-byte units - if (size % 256) { + if (size % GetSectorSizeInBytes()) { stringstream error; - error << "File size must be a multiple of 256 bytes but is " << size << " bytes"; + error << "File size must be a multiple of " << GetSectorSizeInBytes() << " bytes but is " << size << " bytes"; throw io_exception(error.str()); } @@ -120,10 +110,6 @@ void SASIHD::Open(const Filepath& path) } #endif // REMOVE_FIXED_SASIHD_SIZE - // Sector size 256 bytes and number of blocks - SetSectorSizeInBytes(256); - SetBlockCount((DWORD)(size >> 8)); - // Call the base class Disk::Open(path); } diff --git a/src/raspberrypi/devices/scsihd.cpp b/src/raspberrypi/devices/scsihd.cpp index 73e0da34..13a75c3a 100644 --- a/src/raspberrypi/devices/scsihd.cpp +++ b/src/raspberrypi/devices/scsihd.cpp @@ -70,7 +70,7 @@ void SCSIHD::Open(const Filepath& path) off_t size = fio.GetFileSize(); fio.Close(); - // sector size (default 512 bytes) and number of blocks + // Sector size (default 512 bytes) and number of blocks SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512); SetBlockCount((DWORD)(size >> GetSectorSize())); diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 6a7fd1b1..942111d1 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -65,6 +65,7 @@ vector available_log_levels; string current_log_level; // Some versions of spdlog do not support get_log_level() string default_image_folder; set files_in_use; +DeviceFactory& device_factory = DeviceFactory::instance(); //--------------------------------------------------------------------------- // @@ -529,16 +530,21 @@ void GetDeviceTypeFeatures(PbServerInfo& serverInfo) PbDeviceProperties *properties = types_properties->add_properties(); types_properties->set_type(SAHD); properties->set_supports_file(true); + vector block_sizes = device_factory.GetSasiSectorSizes(); + for (auto it = block_sizes.begin(); it != block_sizes.end(); ++it) { + properties->add_block_sizes(*it); + } + + block_sizes = device_factory.GetScsiSectorSizes(); types_properties = serverInfo.add_types_properties(); types_properties->set_type(SCHD); properties = types_properties->add_properties(); properties->set_protectable(true); properties->set_supports_file(true); - properties->add_block_sizes(512); - properties->add_block_sizes(1024); - properties->add_block_sizes(2048); - properties->add_block_sizes(4096); + for (auto it = block_sizes.begin(); it != block_sizes.end(); ++it) { + properties->add_block_sizes(*it); + } types_properties = serverInfo.add_types_properties(); types_properties->set_type(SCRM); @@ -547,10 +553,9 @@ void GetDeviceTypeFeatures(PbServerInfo& serverInfo) properties->set_removable(true); properties->set_lockable(true); properties->set_supports_file(true); - properties->add_block_sizes(512); - properties->add_block_sizes(1024); - properties->add_block_sizes(2048); - properties->add_block_sizes(4096); + for (auto it = block_sizes.begin(); it != block_sizes.end(); ++it) { + properties->add_block_sizes(*it); + } types_properties = serverInfo.add_types_properties(); properties = types_properties->add_properties(); @@ -670,8 +675,8 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pbDevice, const PbOperation cm ext = filename.substr(len - 3); } - // Create a new device, based upon type or file extension - device = DeviceFactory::CreateDevice(type, filename, ext); + // Create a new device, based upon provided type or file extension + device = device_factory.CreateDevice(type, filename, ext); if (!device) { return ReturnStatus(fd, false, "Invalid device type " + PbDeviceType_Name(type)); } diff --git a/src/raspberrypi/xm6.h b/src/raspberrypi/xm6.h index 50c5524d..2c21bfc0 100644 --- a/src/raspberrypi/xm6.h +++ b/src/raspberrypi/xm6.h @@ -20,7 +20,6 @@ //--------------------------------------------------------------------------- #define USE_SEL_EVENT_ENABLE // Check SEL signal by event #define REMOVE_FIXED_SASIHD_SIZE // remove the size limitation of SASIHD -#define USE_MZ1F23_1024_SUPPORT // MZ-1F23 (SASI 20M/sector size 1024) // This avoids an indefinite loop with warnings if there is no RaSCSI hardware // and thus helps with running certain tests on X86 hardware. #if defined(__x86_64__) || defined(__X86__)