Moved Daynaport code to the Daynaport class

This commit is contained in:
Uwe Seimet 2021-08-22 17:17:38 +02:00
parent cdf9a6ad5b
commit 806e0e0f27
6 changed files with 146 additions and 153 deletions

View File

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

View File

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

View File

@ -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<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
disk_command_t *command = disk_commands[static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0])];
if (commands.count(static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0]))) {
command_t *command = commands[static_cast<SCSIDEV::scsi_command>(ctrl->cmd[0])];
LOGDEBUG("++++ CMD ++++ %s received %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl->cmd[0]);

View File

@ -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<SCSIDEV::scsi_command, disk_command_t*> disk_commands;
_command_t(const char* _name, void (Disk::*_execute)(SASIDEV *)) : name(_name), execute(_execute) { };
} command_t;
std::map<SCSIDEV::scsi_command, command_t*> 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

View File

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

View File

@ -32,6 +32,7 @@
#include "os.h"
#include "disk.h"
#include "ctapdriver.h"
#include <map>
//===========================================================================
//
@ -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<SCSIDEV::scsi_command, command_t*> 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 *));
};