From 806e0e0f27d03547e1af949046120c555f93613c Mon Sep 17 00:00:00 2001 From: Uwe Seimet Date: Sun, 22 Aug 2021 17:17:38 +0200 Subject: [PATCH] Moved Daynaport code to the Daynaport class --- src/raspberrypi/controllers/scsidev_ctrl.cpp | 141 +------------------ src/raspberrypi/controllers/scsidev_ctrl.h | 4 - src/raspberrypi/devices/disk.cpp | 8 +- src/raspberrypi/devices/disk.h | 10 +- src/raspberrypi/devices/scsi_daynaport.cpp | 114 +++++++++++++++ src/raspberrypi/devices/scsi_daynaport.h | 22 +++ 6 files changed, 146 insertions(+), 153 deletions(-) diff --git a/src/raspberrypi/controllers/scsidev_ctrl.cpp b/src/raspberrypi/controllers/scsidev_ctrl.cpp index 8d05bda9..ad2238d8 100644 --- a/src/raspberrypi/controllers/scsidev_ctrl.cpp +++ b/src/raspberrypi/controllers/scsidev_ctrl.cpp @@ -48,12 +48,6 @@ SCSIDEV::SCSIDEV() : SASIDEV() SetUpControllerCommand(eCmdPlayAudioMSF, "CmdPlayAudioMSF", &SCSIDEV::CmdPlayAudioMSF); SetUpControllerCommand(eCmdPlayAudioTrack, "CmdPlayAudioTrack", &SCSIDEV::CmdPlayAudioTrack); SetUpControllerCommand(eCmdGetEventStatusNotification, "CmdGetEventStatusNotification", &SCSIDEV::CmdGetEventStatusNotification); - - // DaynaPort specific. TODO Move to separate class - SetUpControllerCommand(eCmdRetrieveStats, "CmdRetrieveStats", &SCSIDEV::CmdRetrieveStats); - SetUpControllerCommand(eCmdSetIfaceMode, "CmdSetIfaceMode", &SCSIDEV::CmdSetIfaceMode); - SetUpControllerCommand(eCmdSetMcastAddr, "CmdSetMcastAddr", &SCSIDEV::CmdSetMcastAddr); - SetUpControllerCommand(eCmdEnableInterface, "CmdEnableInterface", &SCSIDEV::CmdEnableInterface); } SCSIDEV::~SCSIDEV() @@ -550,140 +544,6 @@ void SCSIDEV::CmdSendMessage10() DataOut(); } -//--------------------------------------------------------------------------- -// -// Retrieve Statistics (09) -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdRetrieveStats() -{ - // TODO Move Daynaport specific test - // Error if not a DaynaPort SCSI Link - if (!ctrl.device->IsDaynaPort()) { - LOGWARN("Received a CmdRetrieveStats command for a non-daynaport unit %s", ctrl.device->GetType().c_str()); - Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE); - return; - } - - // Process with drive - SCSIDaynaPort *dayna_port = (SCSIDaynaPort*)ctrl.device; - ctrl.length = dayna_port->RetrieveStats(ctrl.cmd, ctrl.buffer); - - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Set next block - ctrl.blocks = 1; - ctrl.next = 1; - - // Data in phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// Set Interface Mode (0c) -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdSetIfaceMode() -{ - LOGTRACE("%s",__PRETTY_FUNCTION__); - - // TODO Move DaynaPort specific test - // Error if not a DaynaPort SCSI Link - if (!ctrl.device->IsDaynaPort()) { - LOGWARN("%s Received a CmdSetIfaceMode command for a non-daynaport unit %s", __PRETTY_FUNCTION__, ctrl.device->GetType().c_str()); - Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE); - return; - } - - SCSIDaynaPort *dayna_port = (SCSIDaynaPort*)ctrl.device; - - // Check whether this command is telling us to "Set Interface Mode" or "Set MAC Address" - - ctrl.length = dayna_port->RetrieveStats(ctrl.cmd, ctrl.buffer); - switch(ctrl.cmd[5]){ - case SCSIDaynaPort::CMD_SCSILINK_SETMODE: - dayna_port->SetMode(ctrl.cmd, ctrl.buffer); - Status(); - break; - break; - case SCSIDaynaPort::CMD_SCSILINK_SETMAC: - ctrl.length = 6; - // Write phase - DataOut(); - break; - default: - LOGWARN("%s Unknown SetInterface command received: %02X", __PRETTY_FUNCTION__, (unsigned int)ctrl.cmd[5]); - } -} - -//--------------------------------------------------------------------------- -// -// Set the multicast address -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdSetMcastAddr() -{ - LOGTRACE("%s Set Multicast Address Command ", __PRETTY_FUNCTION__); - - // TODO Move DaynaPort specific test - if (!ctrl.device->IsDaynaPort()) { - LOGWARN("Received a SetMcastAddress command for a non-daynaport unit"); - Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE); - return; - } - - // Command processing on drive - ctrl.length = (DWORD)ctrl.cmd[4]; - - // ASSERT(ctrl.length >= 0); - if (ctrl.length == 0) { - LOGWARN("%s Not supported SetMcastAddr Command %02X", __PRETTY_FUNCTION__, (WORD)ctrl.cmd[2]); - - // Failure (Error) - Error(); - return; - } - - DataOut(); -} - -//--------------------------------------------------------------------------- -// -// Enable/disable Interface (0e) -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdEnableInterface() -{ - LOGTRACE("%s",__PRETTY_FUNCTION__); - - // TODO Move DaynaPort specific test - // Error if not a DaynaPort SCSI Link - if (!ctrl.device->IsDaynaPort()) { - LOGWARN("%s Received a CmdEnableInterface command for a non-daynaport unit %s", __PRETTY_FUNCTION__, ctrl.device->GetType().c_str()); - Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE); - return; - } - - SCSIDaynaPort *dayna_port = (SCSIDaynaPort*)ctrl.device; - - // Command processing on drive - bool status = dayna_port->EnableInterface(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - - //=========================================================================== // // Data Transfer @@ -708,6 +568,7 @@ void SCSIDEV::Send() s << __PRETTY_FUNCTION__ << " sending handhake with offset " << ctrl.offset << ", length " << ctrl.length; LOGTRACE("%s", s.str().c_str()); + // TODO Get rid of Daynaport specific code // The Daynaport needs to have a delay after the size/flags field // of the read response. In the MacOS driver, it looks like the // driver is doing two "READ" system calls. diff --git a/src/raspberrypi/controllers/scsidev_ctrl.h b/src/raspberrypi/controllers/scsidev_ctrl.h index b11a6051..9cdfd04f 100644 --- a/src/raspberrypi/controllers/scsidev_ctrl.h +++ b/src/raspberrypi/controllers/scsidev_ctrl.h @@ -131,10 +131,6 @@ private: void CmdGetEventStatusNotification(); void CmdModeSelect10(); // MODE SELECT(10) command void CmdModeSense10(); // MODE SENSE(10) command - void CmdRetrieveStats(); // DaynaPort specific command - void CmdSetIfaceMode(); // DaynaPort specific command - void CmdSetMcastAddr(); // DaynaPort specific command - void CmdEnableInterface(); // DaynaPort specific command // データ転送 void Send(); // Send data void Receive(); // Receive data diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index adaa7bed..92517353 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -1330,22 +1330,22 @@ Disk::~Disk() disk.dcache = NULL; } - for (auto const& command : disk_commands) { + for (auto const& command : commands) { free(command.second); } } void Disk::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (Disk::*execute)(SASIDEV *)) { - disk_commands[opcode] = new disk_command_t(name, execute); + commands[opcode] = new command_t(name, execute); } bool Disk::Dispatch(SCSIDEV *controller) { SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); - if (disk_commands.count(static_cast(ctrl->cmd[0]))) { - disk_command_t *command = disk_commands[static_cast(ctrl->cmd[0])]; + if (commands.count(static_cast(ctrl->cmd[0]))) { + command_t *command = commands[static_cast(ctrl->cmd[0])]; LOGDEBUG("++++ CMD ++++ %s received %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); diff --git a/src/raspberrypi/devices/disk.h b/src/raspberrypi/devices/disk.h index 7d9e0370..24db29cf 100644 --- a/src/raspberrypi/devices/disk.h +++ b/src/raspberrypi/devices/disk.h @@ -140,13 +140,13 @@ protected: } disk_t; private: - typedef struct _disk_command_t { + typedef struct _command_t { const char* name; void (Disk::*execute)(SASIDEV *); - _disk_command_t(const char* _name, void (Disk::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; - } disk_command_t; - std::map disk_commands; + _command_t(const char* _name, void (Disk::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { }; + } command_t; + std::map commands; public: // Basic Functions @@ -231,7 +231,7 @@ public: bool Format(const DWORD *cdb); // FORMAT UNIT command bool Reassign(const DWORD *cdb); // REASSIGN UNIT command - bool Dispatch(SCSIDEV *); + virtual bool Dispatch(SCSIDEV *); protected: // Internal processing diff --git a/src/raspberrypi/devices/scsi_daynaport.cpp b/src/raspberrypi/devices/scsi_daynaport.cpp index 44de1a4d..cfcf7b20 100644 --- a/src/raspberrypi/devices/scsi_daynaport.cpp +++ b/src/raspberrypi/devices/scsi_daynaport.cpp @@ -91,6 +91,10 @@ SCSIDaynaPort::SCSIDaynaPort() : Disk("SCDP") #endif // linux LOGTRACE("SCSIDaynaPort Constructor End"); + AddCommand(SCSIDEV::eCmdRetrieveStats, "CmdRetrieveStats", &SCSIDaynaPort::CmdRetrieveStats); + AddCommand(SCSIDEV::eCmdSetIfaceMode, "CmdSetIfaceMode", &SCSIDaynaPort::CmdSetIfaceMode); + AddCommand(SCSIDEV::eCmdSetMcastAddr, "CmdSetMcastAddr", &SCSIDaynaPort::CmdSetMcastAddr); + AddCommand(SCSIDEV::eCmdEnableInterface, "CmdEnableInterface", &SCSIDaynaPort::CmdEnableInterface); } //--------------------------------------------------------------------------- @@ -106,6 +110,10 @@ SCSIDaynaPort::~SCSIDaynaPort() m_tap->Cleanup(); delete m_tap; } + + for (auto const& command : commands) { + free(command.second); + } } void SCSIDaynaPort::Open(const Filepath& path, BOOL attn) @@ -114,6 +122,28 @@ SCSIDaynaPort::~SCSIDaynaPort() m_tap->OpenDump(path); } + void SCSIDaynaPort::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (SCSIDaynaPort::*execute)(SASIDEV *)) + { + commands[opcode] = new command_t(name, execute); + } + + bool SCSIDaynaPort::Dispatch(SCSIDEV *controller) + { + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + if (commands.count(static_cast(ctrl->cmd[0]))) { + command_t *command = commands[static_cast(ctrl->cmd[0])]; + + LOGDEBUG("++++ CMD ++++ %s received %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]); + + (this->*command->execute)(controller); + + return true; + } + + return Disk::Dispatch(controller); + } + //--------------------------------------------------------------------------- // // INQUIRY @@ -493,6 +523,90 @@ bool SCSIDaynaPort::TestUnitReady(const DWORD* /*cdb*/) return true; } +void SCSIDaynaPort::CmdRetrieveStats(SASIDEV *controller) +{ + LOGTRACE("%s",__PRETTY_FUNCTION__); + + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + ctrl->length = RetrieveStats(ctrl->cmd, ctrl->buffer); + + if (ctrl->length <= 0) { + // Failure (Error) + controller->Error(); + return; + } + + // Set next block + ctrl->blocks = 1; + ctrl->next = 1; + + // Data in phase + controller->DataIn(); +} + +void SCSIDaynaPort::CmdSetIfaceMode(SASIDEV *controller) +{ + LOGTRACE("%s",__PRETTY_FUNCTION__); + + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + // Check whether this command is telling us to "Set Interface Mode" or "Set MAC Address" + + ctrl->length = RetrieveStats(ctrl->cmd, ctrl->buffer); + switch(ctrl->cmd[5]){ + case SCSIDaynaPort::CMD_SCSILINK_SETMODE: + SetMode(ctrl->cmd, ctrl->buffer); + controller->Status(); + break; + break; + case SCSIDaynaPort::CMD_SCSILINK_SETMAC: + ctrl->length = 6; + // Write phase + controller->DataOut(); + break; + default: + LOGWARN("%s Unknown SetInterface command received: %02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[5]); + } +} + +void SCSIDaynaPort::CmdSetMcastAddr(SASIDEV *controller) +{ + LOGTRACE("%s Set Multicast Address Command ", __PRETTY_FUNCTION__); + + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + ctrl->length = (DWORD)ctrl->cmd[4]; + + // ASSERT(ctrl.length >= 0); + if (ctrl->length == 0) { + LOGWARN("%s Not supported SetMcastAddr Command %02X", __PRETTY_FUNCTION__, (WORD)ctrl->cmd[2]); + + // Failure (Error) + controller->Error(); + return; + } + + controller->DataOut(); +} + +void SCSIDaynaPort::CmdEnableInterface(SASIDEV *controller) +{ + LOGTRACE("%s",__PRETTY_FUNCTION__); + + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + bool status = EnableInterface(ctrl->cmd); + if (!status) { + // Failure (Error) + controller->Error(); + return; + } + + // status phase + controller->Status(); +} + //--------------------------------------------------------------------------- // // Set Mode - enable broadcast messages diff --git a/src/raspberrypi/devices/scsi_daynaport.h b/src/raspberrypi/devices/scsi_daynaport.h index 11c913e1..f1701a91 100644 --- a/src/raspberrypi/devices/scsi_daynaport.h +++ b/src/raspberrypi/devices/scsi_daynaport.h @@ -32,6 +32,7 @@ #include "os.h" #include "disk.h" #include "ctapdriver.h" +#include //=========================================================================== // @@ -40,6 +41,16 @@ //=========================================================================== 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; + public: // Basic Functions SCSIDaynaPort(); @@ -70,6 +81,14 @@ public: // Set MAC address void SetMode(const DWORD *cdb, BYTE *buffer); // Set the mode: whether broadcast traffic is enabled or not + + void CmdRetrieveStats(SASIDEV *); + void CmdSetIfaceMode(SASIDEV *); + void CmdSetMcastAddr(SASIDEV *); + void CmdEnableInterface(SASIDEV *); + + bool Dispatch(SCSIDEV *); + static const BYTE CMD_SCSILINK_STATS = 0x09; static const BYTE CMD_SCSILINK_ENABLE = 0x0E; static const BYTE CMD_SCSILINK_SET = 0x0C; @@ -179,4 +198,7 @@ private: // MAC Address static const BYTE m_bcast_addr[6]; static const BYTE m_apple_talk_addr[6]; + +private: + void AddCommand(SCSIDEV::scsi_command, const char*, void (SCSIDaynaPort::*)(SASIDEV *)); };