Inheritance hierarchy improvements, reduced dependencies to Disk class (#662)

* Fixed buster compile-time issue

* Host services inherit from ModePageDevice

* Call base class

* Visibility update

* Updated includes

* Updated dispatcher

* Added TODOs

* Logging update

* Code cleanup

* Use namespace instead of class for ScsiDefs

* Renaming

* Cleanup

* Use dispatcher template in order to remove duplicate code

* Updated all dispatchers

* Clean up commands

* Removed duplicate code

* Removed duplicate code

* Updated template definition

* Fixed typo

* Fixed warning

* Code cleanup

* Device list must be static

* Cleanup

* Logging update

* Added comments

* Cleanup

* Base class update

* SCSIBR is not a subclass of Disk anymore, but of PrimaryDevice

* Updated includes

* Fixed compile-time issue on the Pi

* Header file cleanup

* Interface cleanup

* Removed wrong override

* include file cleanup

* Removed obsolete usage of streams

* Removed more stream usages

* Stream usage cleanup

* Include cleanup

* Renaming

* Include cleanup

* Interface update
This commit is contained in:
Uwe Seimet 2022-02-13 20:30:02 +01:00 committed by GitHub
parent 25b9b4ada2
commit 45cd5e58d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 405 additions and 472 deletions

View File

@ -15,7 +15,7 @@
//---------------------------------------------------------------------------
#pragma once
#include "../rascsi.h"
#include "../config.h"
#include "os.h"
#include "scsi.h"
#include "fileio.h"

View File

@ -17,7 +17,6 @@
#include "controllers/scsidev_ctrl.h"
#include "gpiobus.h"
#include "devices/scsi_daynaport.h"
#include <sstream>
//===========================================================================
//
@ -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;

View File

@ -8,17 +8,20 @@
//---------------------------------------------------------------------------
#include <cassert>
#include <sstream>
#include "rascsi_version.h"
#include "os.h"
#include "log.h"
#include "exceptions.h"
#include "device.h"
set<Device *> 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;

View File

@ -9,6 +9,7 @@
#pragma once
#include <set>
#include <map>
#include <string>
@ -104,10 +105,14 @@ private:
// Sense Key, ASC and ASCQ
int status_code;
protected:
static set<Device *> 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<string, string>&) { return true; };

View File

@ -20,12 +20,11 @@
#include "exceptions.h"
#include "disk.h"
#include "mode_page_device.h"
#include <sstream>
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<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<ScsiDefs::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;
}
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<uint32_t> 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) {

View File

@ -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 <string>
#include <set>
#include <map>
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<ScsiDefs::scsi_command, command_t*> commands;
void AddCommand(ScsiDefs::scsi_command, const char*, void (Disk::*)(SASIDEV *));
Dispatcher<Disk> 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<Disk *> disks;
private:
void Read(SASIDEV *, uint64_t);
void Write(SASIDEV *, uint64_t);

View File

@ -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 <map>
class SASIDEV;
class SCSIDEV;
using namespace std;
using namespace scsi_defs;
template<class T>
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<scsi_command, command_t*> 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<scsi_command>(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;
}
};

View File

@ -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;
}

View File

@ -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<HostServices> dispatcher;
int AddRealtimeClockPage(int, BYTE *);
};

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<ScsiDefs::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;
// The superclass class handles the less specific commands
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
}
void ModePageDevice::ModeSense6(SASIDEV *controller)

View File

@ -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<ScsiDefs::scsi_command, command_t*> commands;
Dispatcher<ModePageDevice> 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 *);

View File

@ -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<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<ScsiDefs::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;
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);

View File

@ -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 <string>
#include <map>
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<ScsiDefs::scsi_command, command_t*> commands;
void AddCommand(ScsiDefs::scsi_command, const char*, void (PrimaryDevice::*)(SASIDEV *));
Dispatcher<PrimaryDevice> dispatcher;
void Inquiry(SASIDEV *);
void ReportLuns(SASIDEV *);

View File

@ -13,11 +13,11 @@
// [ SASI hard disk ]
//
//---------------------------------------------------------------------------
#include "sasihd.h"
#include "fileio.h"
#include "exceptions.h"
#include <sstream>
#include "../rascsi.h"
#include "../config.h"
//===========================================================================
//

View File

@ -28,23 +28,25 @@
//---------------------------------------------------------------------------
#include "scsi_daynaport.h"
#include <sstream>
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<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<ScsiDefs::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;
}
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<string, string>& 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);

View File

@ -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<ScsiDefs::scsi_command, command_t*> 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<SCSIDaynaPort> dispatcher;
typedef struct __attribute__((packed)) {
BYTE operation_code;
BYTE misc_cdb_information;

View File

@ -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 <sstream>
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<string, string>& params)
@ -96,29 +94,10 @@ bool SCSIBR::Init(const map<string, string>& 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<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<ScsiDefs::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;
}
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();}
//---------------------------------------------------------------------------

View File

@ -18,7 +18,7 @@
#pragma once
#include "os.h"
#include "disk.h"
#include "primary_device.h"
#include <string>
//===========================================================================
@ -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<ScsiDefs::scsi_command, command_t*> 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<SCSIBR> dispatcher;
int GetMacAddr(BYTE *buf); // Get MAC address
void SetMacAddr(BYTE *buf); // Set MAC address
void ReceivePacket(); // Receive a packet

View File

@ -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 <sstream>
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<ScsiDefs::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<ScsiDefs::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;
}
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

View File

@ -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<ScsiDefs::scsi_command, command_t*> 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<SCSICD> dispatcher;
// Open
void OpenCue(const Filepath& path); // Open(CUE)
void OpenIso(const Filepath& path); // Open(ISO)

View File

@ -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);

View File

@ -18,7 +18,6 @@
#include "fileio.h"
#include "exceptions.h"
#include <sstream>
//===========================================================================
//

View File

@ -11,7 +11,8 @@
#include "os.h"
#include "filepath.h"
#include "fileio.h"
#include "rascsi.h"
#include "config.h"
//===========================================================================
//

View File

@ -10,8 +10,8 @@
#include "os.h"
#include "filepath.h"
#include "config.h"
#include "fileio.h"
#include "rascsi.h"
//===========================================================================
//

View File

@ -16,8 +16,9 @@
#include "os.h"
#include "gpiobus.h"
#include "config.h"
#include "log.h"
#include "rascsi.h"
#ifdef __linux__
//---------------------------------------------------------------------------

View File

@ -12,7 +12,7 @@
#if !defined(gpiobus_h)
#define gpiobus_h
#include "rascsi.h"
#include "config.h"
#include "scsi.h"
//---------------------------------------------------------------------------

View File

@ -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 <list>
#include <vector>
#include <map>
#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();

View File

@ -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++;
}

View File

@ -14,7 +14,6 @@
#include "rasutil.h"
#include "rasctl_commands.h"
#include "rascsi_interface.pb.h"
#include <sstream>
#include <iostream>
#include <list>
@ -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) {

View File

@ -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?

View File

@ -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,