Made device factory a singleton, replace #ifdef by configurable block size

This commit is contained in:
Uwe Seimet 2021-08-25 12:26:30 +02:00
parent c04f820d56
commit d0976f1ceb
7 changed files with 194 additions and 183 deletions

View File

@ -20,6 +20,27 @@
using namespace std; using namespace std;
using namespace rascsi_interface; 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) 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 // 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<int> 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; Device *device = NULL;
switch (type) { switch (type) {
case SAHD: case SAHD: {
device = new SASIHD(); device = new SASIHD();
((Disk *)device)->SetSectorSizes(sector_sizes_sasi);
}
break; break;
case SCHD: case SCHD:
@ -64,7 +81,7 @@ Device *DeviceFactory::CreateDevice(PbDeviceType& type, const string& filename,
} else { } else {
device = new SCSIHD(); device = new SCSIHD();
device->SetProtectable(true); device->SetProtectable(true);
((Disk *)device)->SetSectorSizes(sector_sizes); ((Disk *)device)->SetSectorSizes(sector_sizes_scsi);
} }
break; break;
@ -74,7 +91,7 @@ Device *DeviceFactory::CreateDevice(PbDeviceType& type, const string& filename,
device->SetProtectable(true); device->SetProtectable(true);
device->SetLockable(true); device->SetLockable(true);
device->SetProtectable(true); device->SetProtectable(true);
((Disk *)device)->SetSectorSizes(sector_sizes); ((Disk *)device)->SetSectorSizes(sector_sizes_scsi);
break; break;
case SCMO: case SCMO:

View File

@ -5,12 +5,13 @@
// //
// Copyright (C) 2021 Uwe Seimet // 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 #pragma once
#include <vector>
#include <string> #include <string>
#include "rascsi_interface.pb.h" #include "rascsi_interface.pb.h"
@ -20,8 +21,18 @@ class DeviceFactory
{ {
public: 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<int>& GetSasiSectorSizes() const { return sector_sizes_sasi; };
const std::vector<int>& GetScsiSectorSizes() const { return sector_sizes_scsi; };
Device *CreateDevice(rascsi_interface::PbDeviceType& type, const std::string& filename, const std::string& ext);
private:
std::vector<int> sector_sizes_sasi;
std::vector<int> sector_sizes_scsi;
}; };

View File

@ -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<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<SCSIDEV::scsi_command>(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) void Disk::TestUnitReady(SASIDEV *controller)
{ {
@ -410,144 +541,6 @@ void Disk::ReadDefectData10(SASIDEV *controller)
controller->DataIn(); 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<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<SCSIDEV::scsi_command>(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 // Eject

View File

@ -69,24 +69,14 @@ void SASIHD::Open(const Filepath& path)
off_t size = fio.GetFileSize(); off_t size = fio.GetFileSize();
fio.Close(); fio.Close();
#if defined(USE_MZ1F23_1024_SUPPORT) // Sector size (default 256 bytes) and number of blocks
// For MZ-2500 / MZ-2800 MZ-1F23 (SASI 20M / sector size 1024) only SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 256);
// 20M(22437888 BS=1024 C=21912) SetBlockCount((DWORD)(size >> GetSectorSize()));
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
#if defined(REMOVE_FIXED_SASIHD_SIZE) #if defined(REMOVE_FIXED_SASIHD_SIZE)
// Must be in 256-byte units if (size % GetSectorSizeInBytes()) {
if (size % 256) {
stringstream error; 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()); throw io_exception(error.str());
} }
@ -120,10 +110,6 @@ void SASIHD::Open(const Filepath& path)
} }
#endif // REMOVE_FIXED_SASIHD_SIZE #endif // REMOVE_FIXED_SASIHD_SIZE
// Sector size 256 bytes and number of blocks
SetSectorSizeInBytes(256);
SetBlockCount((DWORD)(size >> 8));
// Call the base class // Call the base class
Disk::Open(path); Disk::Open(path);
} }

View File

@ -70,7 +70,7 @@ void SCSIHD::Open(const Filepath& path)
off_t size = fio.GetFileSize(); off_t size = fio.GetFileSize();
fio.Close(); fio.Close();
// sector size (default 512 bytes) and number of blocks // Sector size (default 512 bytes) and number of blocks
SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512); SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512);
SetBlockCount((DWORD)(size >> GetSectorSize())); SetBlockCount((DWORD)(size >> GetSectorSize()));

View File

@ -65,6 +65,7 @@ vector<string> available_log_levels;
string current_log_level; // Some versions of spdlog do not support get_log_level() string current_log_level; // Some versions of spdlog do not support get_log_level()
string default_image_folder; string default_image_folder;
set<string> files_in_use; set<string> files_in_use;
DeviceFactory& device_factory = DeviceFactory::instance();
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
@ -529,16 +530,21 @@ void GetDeviceTypeFeatures(PbServerInfo& serverInfo)
PbDeviceProperties *properties = types_properties->add_properties(); PbDeviceProperties *properties = types_properties->add_properties();
types_properties->set_type(SAHD); types_properties->set_type(SAHD);
properties->set_supports_file(true); properties->set_supports_file(true);
vector<int> 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 = serverInfo.add_types_properties();
types_properties->set_type(SCHD); types_properties->set_type(SCHD);
properties = types_properties->add_properties(); properties = types_properties->add_properties();
properties->set_protectable(true); properties->set_protectable(true);
properties->set_supports_file(true); properties->set_supports_file(true);
properties->add_block_sizes(512); for (auto it = block_sizes.begin(); it != block_sizes.end(); ++it) {
properties->add_block_sizes(1024); properties->add_block_sizes(*it);
properties->add_block_sizes(2048); }
properties->add_block_sizes(4096);
types_properties = serverInfo.add_types_properties(); types_properties = serverInfo.add_types_properties();
types_properties->set_type(SCRM); types_properties->set_type(SCRM);
@ -547,10 +553,9 @@ void GetDeviceTypeFeatures(PbServerInfo& serverInfo)
properties->set_removable(true); properties->set_removable(true);
properties->set_lockable(true); properties->set_lockable(true);
properties->set_supports_file(true); properties->set_supports_file(true);
properties->add_block_sizes(512); for (auto it = block_sizes.begin(); it != block_sizes.end(); ++it) {
properties->add_block_sizes(1024); properties->add_block_sizes(*it);
properties->add_block_sizes(2048); }
properties->add_block_sizes(4096);
types_properties = serverInfo.add_types_properties(); types_properties = serverInfo.add_types_properties();
properties = types_properties->add_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); ext = filename.substr(len - 3);
} }
// Create a new device, based upon type or file extension // Create a new device, based upon provided type or file extension
device = DeviceFactory::CreateDevice(type, filename, ext); device = device_factory.CreateDevice(type, filename, ext);
if (!device) { if (!device) {
return ReturnStatus(fd, false, "Invalid device type " + PbDeviceType_Name(type)); return ReturnStatus(fd, false, "Invalid device type " + PbDeviceType_Name(type));
} }

View File

@ -20,7 +20,6 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#define USE_SEL_EVENT_ENABLE // Check SEL signal by event #define USE_SEL_EVENT_ENABLE // Check SEL signal by event
#define REMOVE_FIXED_SASIHD_SIZE // remove the size limitation of SASIHD #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 // This avoids an indefinite loop with warnings if there is no RaSCSI hardware
// and thus helps with running certain tests on X86 hardware. // and thus helps with running certain tests on X86 hardware.
#if defined(__x86_64__) || defined(__X86__) #if defined(__x86_64__) || defined(__X86__)