From d3a9ae48af4645ca68b5b060431ace80ca73217c Mon Sep 17 00:00:00 2001 From: Uwe Seimet Date: Sun, 22 Aug 2021 17:52:36 +0200 Subject: [PATCH] Moved DaynPort specific code --- src/raspberrypi/controllers/sasidev_ctrl.cpp | 68 +--------- src/raspberrypi/controllers/sasidev_ctrl.h | 3 +- src/raspberrypi/controllers/scsidev_ctrl.cpp | 126 +------------------ src/raspberrypi/controllers/scsidev_ctrl.h | 14 --- src/raspberrypi/devices/disk.cpp | 35 ++---- src/raspberrypi/devices/disk.h | 2 +- src/raspberrypi/devices/scsi_daynaport.cpp | 90 +++++++++++-- src/raspberrypi/devices/scsi_daynaport.h | 7 +- src/raspberrypi/devices/scsicd.cpp | 94 ++++++++++++++ src/raspberrypi/devices/scsicd.h | 19 +++ 10 files changed, 215 insertions(+), 243 deletions(-) diff --git a/src/raspberrypi/controllers/sasidev_ctrl.cpp b/src/raspberrypi/controllers/sasidev_ctrl.cpp index 44cafe93..d70547e7 100644 --- a/src/raspberrypi/controllers/sasidev_ctrl.cpp +++ b/src/raspberrypi/controllers/sasidev_ctrl.cpp @@ -836,14 +836,6 @@ void SASIDEV::CmdRead6() ctrl.blocks = 0x100; } - // TODO Move Daynaport specific test - // TODO This class must not know about SCDP - if(ctrl.device->IsDaynaPort()){ - // The DaynaPort only wants one block. - // ctrl.cmd[4] and ctrl.cmd[5] are used to specify the maximum buffer size for the DaynaPort - ctrl.blocks=1; - } - LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks); // Command processing on drive @@ -851,7 +843,7 @@ void SASIDEV::CmdRead6() LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, (int)ctrl.length); // The DaynaPort will respond a status of 0x02 when a read of size 1 occurs. - if (ctrl.length <= 0 && !ctrl.device->IsDaynaPort()) { + if (ctrl.length <= 0) { // Failure (Error) Error(); return; @@ -864,56 +856,6 @@ void SASIDEV::CmdRead6() DataIn(); } -//--------------------------------------------------------------------------- -// -// This Send Message command is used by the DaynaPort SCSI/Link -// TODO This class must not know about SCDP -// -//--------------------------------------------------------------------------- -void SASIDEV::DaynaPortWrite() -{ - // Error if not a DaynaPort device - if (!ctrl.device->IsDaynaPort()) { - LOGERROR("Received DaynaPortWrite for a non-DaynaPort device"); - Error(); - return; - } - - // Reallocate buffer (because it is not transfer for each block) - if (ctrl.bufsize < DAYNAPORT_BUFFER_SIZE) { - free(ctrl.buffer); - ctrl.bufsize = DAYNAPORT_BUFFER_SIZE; - ctrl.buffer = (BYTE *)malloc(ctrl.bufsize); - } - - DWORD data_format = ctrl.cmd[5]; - - if(data_format == 0x00){ - ctrl.length = (WORD)ctrl.cmd[4] + ((WORD)ctrl.cmd[3] << 8); - } - else if (data_format == 0x80){ - ctrl.length = (WORD)ctrl.cmd[4] + ((WORD)ctrl.cmd[3] << 8) + 8; - } - else - { - LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, (unsigned int)data_format); - } - LOGTRACE("%s length: %04X (%d) format: %02X", __PRETTY_FUNCTION__, (unsigned int)ctrl.length, (int)ctrl.length, (unsigned int)data_format); - - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Set next block - ctrl.blocks = 1; - ctrl.next = 1; - - // Light phase - DataOut(); -} - //--------------------------------------------------------------------------- // // WRITE(6) @@ -921,12 +863,6 @@ void SASIDEV::DaynaPortWrite() //--------------------------------------------------------------------------- void SASIDEV::CmdWrite6() { - // Special receive function for the DaynaPort - if (ctrl.device->IsDaynaPort()){ - DaynaPortWrite(); - return; - } - // Get record number and block number DWORD record = ctrl.cmd[1] & 0x1f; record <<= 8; @@ -1308,7 +1244,7 @@ BOOL SASIDEV::XferOut(BOOL cont) } // Special case Write function for DaynaPort - // TODO This class must not know about SCSIDP + // TODO This class must not know about DaynaPort if (device->IsDaynaPort()) { LOGTRACE("%s Doing special case write for DaynaPort", __PRETTY_FUNCTION__); if (!(SCSIDaynaPort*)device->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) { diff --git a/src/raspberrypi/controllers/sasidev_ctrl.h b/src/raspberrypi/controllers/sasidev_ctrl.h index e23e0917..e0c16c83 100644 --- a/src/raspberrypi/controllers/sasidev_ctrl.h +++ b/src/raspberrypi/controllers/sasidev_ctrl.h @@ -89,6 +89,7 @@ public: const int UNKNOWN_SCSI_ID = -1; const int DEFAULT_BUFFER_SIZE = 0x1000; + // TODO Remove this duplicate const int DAYNAPORT_BUFFER_SIZE = 0x1000000; // For timing adjustments @@ -162,8 +163,6 @@ public: void MsgIn(); // Message in phase void DataOut(); // Data out phase - void DaynaPortWrite(); // DaynaPort specific 'write' operation - virtual void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE, ERROR_CODES::asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION); // Common error handling diff --git a/src/raspberrypi/controllers/scsidev_ctrl.cpp b/src/raspberrypi/controllers/scsidev_ctrl.cpp index ad2238d8..f14e5ba1 100644 --- a/src/raspberrypi/controllers/scsidev_ctrl.cpp +++ b/src/raspberrypi/controllers/scsidev_ctrl.cpp @@ -41,25 +41,10 @@ SCSIDEV::SCSIDEV() : SASIDEV() scsi.atnmsg = FALSE; scsi.msc = 0; memset(scsi.msb, 0x00, sizeof(scsi.msb)); - - // MMC specific. TODO Move to separate class - SetUpControllerCommand(eCmdReadToc, "CmdReadToc", &SCSIDEV::CmdReadToc); - SetUpControllerCommand(eCmdPlayAudio10, "CmdPlayAudio10", &SCSIDEV::CmdPlayAudio10); - SetUpControllerCommand(eCmdPlayAudioMSF, "CmdPlayAudioMSF", &SCSIDEV::CmdPlayAudioMSF); - SetUpControllerCommand(eCmdPlayAudioTrack, "CmdPlayAudioTrack", &SCSIDEV::CmdPlayAudioTrack); - SetUpControllerCommand(eCmdGetEventStatusNotification, "CmdGetEventStatusNotification", &SCSIDEV::CmdGetEventStatusNotification); } SCSIDEV::~SCSIDEV() { - for (auto const& command : controller_commands) { - free(command.second); - } -} - -void SCSIDEV::SetUpControllerCommand(scsi_command opcode, const char* name, void (SCSIDEV::*execute)(void)) -{ - controller_commands[opcode] = new controller_command_t(name, execute); } //--------------------------------------------------------------------------- @@ -257,23 +242,7 @@ void SCSIDEV::Execute() ctrl.execstart = SysTimer::GetTimerLow(); ctrl.device = ctrl.unit[GetLun()]; - - if (ctrl.device->Dispatch(this)) { - return; - } - - // If the command is valid it must be contained in the command map - if (!controller_commands.count(static_cast(ctrl.cmd[0]))) { - CmdInvalid(); - return; - } - - controller_command_t* command = controller_commands[static_cast(ctrl.cmd[0])]; - - LOGDEBUG("++++ CMD ++++ %s ID %d received %s ($%02X)", __PRETTY_FUNCTION__, GetSCSIID(), command->name, (unsigned int)ctrl.cmd[0]); - - // Process by command - (this->*command->execute)(); + ctrl.device->Dispatch(this); } //--------------------------------------------------------------------------- @@ -366,99 +335,6 @@ void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc) Status(); } -//--------------------------------------------------------------------------- -// -// Command -// -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// -// READ TOC -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdReadToc() -{ - // Command processing on drive - ctrl.length = ctrl.device->ReadToc(ctrl.cmd, ctrl.buffer); - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// PLAY AUDIO(10) -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdPlayAudio10() -{ - // Command processing on drive - bool status = ctrl.device->PlayAudio(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// PLAY AUDIO MSF -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdPlayAudioMSF() -{ - // Command processing on drive - bool status = ctrl.device->PlayAudioMSF(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// PLAY AUDIO TRACK -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdPlayAudioTrack() -{ - // Command processing on drive - bool status = ctrl.device->PlayAudioTrack(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// GET EVENT STATUS NOTIFICATION -// -//--------------------------------------------------------------------------- -void SCSIDEV::CmdGetEventStatusNotification() -{ - // This naive (but legal) implementation avoids constant warnings in the logs - Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); -} - //--------------------------------------------------------------------------- // // GET MESSAGE(10) diff --git a/src/raspberrypi/controllers/scsidev_ctrl.h b/src/raspberrypi/controllers/scsidev_ctrl.h index 9cdfd04f..6d7491d3 100644 --- a/src/raspberrypi/controllers/scsidev_ctrl.h +++ b/src/raspberrypi/controllers/scsidev_ctrl.h @@ -85,15 +85,6 @@ public: BYTE msb[256]; } scsi_t; - // SCSI command name and pointer to implementation - typedef struct _controller_command_t { - const char* name; - void (SCSIDEV::*execute)(void); - - _controller_command_t(const char* _name, void (SCSIDEV::*_execute)(void)) : name(_name), execute(_execute) { }; - } controller_command_t; - std::map controller_commands; - public: // Basic Functions SCSIDEV(); @@ -115,7 +106,6 @@ public: void CmdSendMessage10(); // SEND MESSAGE(10) command private: - void SetUpControllerCommand(scsi_command, const char*, void (SCSIDEV::*)(void)); // Phase void BusFree(); // Bus free phase @@ -124,10 +114,6 @@ private: void MsgOut(); // Message out phase // commands - void CmdReadToc(); // READ TOC command - void CmdPlayAudio10(); // PLAY AUDIO(10) command - void CmdPlayAudioMSF(); // PLAY AUDIO MSF command - void CmdPlayAudioTrack(); // PLAY AUDIO TRACK INDEX command void CmdGetEventStatusNotification(); void CmdModeSelect10(); // MODE SELECT(10) command void CmdModeSense10(); // MODE SENSE(10) command diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index 92517353..a5ca6d73 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -469,24 +469,15 @@ void Disk::Read6(SASIDEV *controller) ctrl->blocks = 0x100; } - // TODO Move Daynaport specific test - // TODO This class must not know about SCDP - if(IsDaynaPort()){ - // The DaynaPort only wants one block. - // ctrl.cmd[4] and ctrl.cmd[5] are used to specify the maximum buffer size for the DaynaPort - ctrl->blocks=1; - } - else { - // Check capacity - DWORD capacity = GetBlockCount(); - if (record > capacity || record + ctrl->blocks > capacity) { - ostringstream s; - s << "Media capacity of " << capacity << " blocks exceeded: " - << "Trying to read block " << record << ", block count " << ctrl->blocks; - LOGWARN("%s", s.str().c_str()); - controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE); - return; - } + // Check capacity + DWORD capacity = GetBlockCount(); + if (record > capacity || record + ctrl->blocks > capacity) { + ostringstream s; + s << "Media capacity of " << capacity << " blocks exceeded: " + << "Trying to read block " << record << ", block count " << ctrl->blocks; + LOGWARN("%s", s.str().c_str()); + controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE); + return; } LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl->blocks); @@ -615,12 +606,6 @@ void Disk::Write6(SASIDEV *controller) { SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); - // Special receive function for the DaynaPort - if (IsDaynaPort()){ - controller->DaynaPortWrite(); - return; - } - // Get record number and block number DWORD record = ctrl->cmd[1] & 0x1f; record <<= 8; @@ -1340,7 +1325,7 @@ void Disk::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (Disk commands[opcode] = new command_t(name, execute); } -bool Disk::Dispatch(SCSIDEV *controller) +bool Disk::Dispatch(SASIDEV *controller) { SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); diff --git a/src/raspberrypi/devices/disk.h b/src/raspberrypi/devices/disk.h index 24db29cf..87f79360 100644 --- a/src/raspberrypi/devices/disk.h +++ b/src/raspberrypi/devices/disk.h @@ -231,7 +231,7 @@ public: bool Format(const DWORD *cdb); // FORMAT UNIT command bool Reassign(const DWORD *cdb); // REASSIGN UNIT command - virtual bool Dispatch(SCSIDEV *); + virtual bool Dispatch(SASIDEV *); protected: // Internal processing diff --git a/src/raspberrypi/devices/scsi_daynaport.cpp b/src/raspberrypi/devices/scsi_daynaport.cpp index cfcf7b20..f1caad2b 100644 --- a/src/raspberrypi/devices/scsi_daynaport.cpp +++ b/src/raspberrypi/devices/scsi_daynaport.cpp @@ -89,12 +89,14 @@ SCSIDaynaPort::SCSIDaynaPort() : Disk("SCDP") m_mac_addr[5]=0xE3; #endif // linux - LOGTRACE("SCSIDaynaPort Constructor End"); + AddCommand(SCSIDEV::eCmdRead6, "CmdRead6", &SCSIDaynaPort::CmdRead6); + AddCommand(SCSIDEV::eCmdWrite6, "CmdWrite6", &SCSIDaynaPort::CmdWrite6); AddCommand(SCSIDEV::eCmdRetrieveStats, "CmdRetrieveStats", &SCSIDaynaPort::CmdRetrieveStats); AddCommand(SCSIDEV::eCmdSetIfaceMode, "CmdSetIfaceMode", &SCSIDaynaPort::CmdSetIfaceMode); AddCommand(SCSIDEV::eCmdSetMcastAddr, "CmdSetMcastAddr", &SCSIDaynaPort::CmdSetMcastAddr); AddCommand(SCSIDEV::eCmdEnableInterface, "CmdEnableInterface", &SCSIDaynaPort::CmdEnableInterface); + AddCommand(SCSIDEV::eCmdGetEventStatusNotification, "CmdGetEventStatusNotification", &SCSIDaynaPort::CmdGetEventStatusNotification); } //--------------------------------------------------------------------------- @@ -104,7 +106,6 @@ SCSIDaynaPort::SCSIDaynaPort() : Disk("SCDP") //--------------------------------------------------------------------------- SCSIDaynaPort::~SCSIDaynaPort() { - LOGTRACE("SCSIDaynaPort Destructor"); // TAP driver release if (m_tap) { m_tap->Cleanup(); @@ -116,9 +117,10 @@ SCSIDaynaPort::~SCSIDaynaPort() } } - void SCSIDaynaPort::Open(const Filepath& path, BOOL attn) +void SCSIDaynaPort::Open(const Filepath& path, BOOL attn) { LOGTRACE("SCSIDaynaPort Open"); + m_tap->OpenDump(path); } @@ -127,7 +129,7 @@ SCSIDaynaPort::~SCSIDaynaPort() commands[opcode] = new command_t(name, execute); } - bool SCSIDaynaPort::Dispatch(SCSIDEV *controller) + bool SCSIDaynaPort::Dispatch(SASIDEV *controller) { SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); @@ -510,11 +512,6 @@ bool SCSIDaynaPort::EnableInterface(const DWORD *cdb) return result; } -//--------------------------------------------------------------------------- -// -// TEST UNIT READY -// -//--------------------------------------------------------------------------- bool SCSIDaynaPort::TestUnitReady(const DWORD* /*cdb*/) { LOGTRACE("%s", __PRETTY_FUNCTION__); @@ -523,6 +520,73 @@ bool SCSIDaynaPort::TestUnitReady(const DWORD* /*cdb*/) return true; } +void SCSIDaynaPort::CmdRead6(SASIDEV *controller) +{ + LOGTRACE("%s",__PRETTY_FUNCTION__); + + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + // Get record number and block number + DWORD record = ctrl->cmd[1] & 0x1f; + record <<= 8; + record |= ctrl->cmd[2]; + record <<= 8; + record |= ctrl->cmd[3]; + ctrl->blocks=1; + + LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl->blocks); + + ctrl->length = Read(ctrl->cmd, ctrl->buffer, record); + LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, (int)ctrl->length); + + // Set next block + ctrl->next = record + 1; + + // Read phase + controller->DataIn(); +} + +void SCSIDaynaPort::CmdWrite6(SASIDEV *controller) +{ + LOGTRACE("%s",__PRETTY_FUNCTION__); + + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + // Reallocate buffer (because it is not transfer for each block) + if (ctrl->bufsize < DAYNAPORT_BUFFER_SIZE) { + free(ctrl->buffer); + ctrl->bufsize = DAYNAPORT_BUFFER_SIZE; + ctrl->buffer = (BYTE *)malloc(ctrl->bufsize); + } + + DWORD data_format = ctrl->cmd[5]; + + if(data_format == 0x00){ + ctrl->length = (WORD)ctrl->cmd[4] + ((WORD)ctrl->cmd[3] << 8); + } + else if (data_format == 0x80){ + ctrl->length = (WORD)ctrl->cmd[4] + ((WORD)ctrl->cmd[3] << 8) + 8; + } + else + { + LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, (unsigned int)data_format); + } + LOGTRACE("%s length: %04X (%d) format: %02X", __PRETTY_FUNCTION__, (unsigned int)ctrl->length, (int)ctrl->length, (unsigned int)data_format); + + if (ctrl->length <= 0) { + // Failure (Error) + controller->Error(); + return; + } + + // Set next block + ctrl->blocks = 1; + ctrl->next = 1; + + // Data out phase + controller->DataOut(); +} + void SCSIDaynaPort::CmdRetrieveStats(SASIDEV *controller) { LOGTRACE("%s",__PRETTY_FUNCTION__); @@ -607,6 +671,14 @@ void SCSIDaynaPort::CmdEnableInterface(SASIDEV *controller) controller->Status(); } +void SCSIDaynaPort::CmdGetEventStatusNotification(SASIDEV *controller) +{ + LOGTRACE("%s",__PRETTY_FUNCTION__); + + // This naive (but legal) implementation avoids constant warnings in the logs + controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB); +} + //--------------------------------------------------------------------------- // // Set Mode - enable broadcast messages diff --git a/src/raspberrypi/devices/scsi_daynaport.h b/src/raspberrypi/devices/scsi_daynaport.h index f1701a91..ca4f6a9f 100644 --- a/src/raspberrypi/devices/scsi_daynaport.h +++ b/src/raspberrypi/devices/scsi_daynaport.h @@ -82,12 +82,17 @@ public: void SetMode(const DWORD *cdb, BYTE *buffer); // Set the mode: whether broadcast traffic is enabled or not + void CmdRead6(SASIDEV *); + void CmdWrite6(SASIDEV *); void CmdRetrieveStats(SASIDEV *); void CmdSetIfaceMode(SASIDEV *); void CmdSetMcastAddr(SASIDEV *); void CmdEnableInterface(SASIDEV *); + void CmdGetEventStatusNotification(SASIDEV *); - bool Dispatch(SCSIDEV *); + bool Dispatch(SASIDEV *); + + const int DAYNAPORT_BUFFER_SIZE = 0x1000000; static const BYTE CMD_SCSILINK_STATS = 0x09; static const BYTE CMD_SCSILINK_ENABLE = 0x0E; diff --git a/src/raspberrypi/devices/scsicd.cpp b/src/raspberrypi/devices/scsicd.cpp index d76436b2..9b021dce 100644 --- a/src/raspberrypi/devices/scsicd.cpp +++ b/src/raspberrypi/devices/scsicd.cpp @@ -244,6 +244,11 @@ SCSICD::SCSICD() : Disk("SCCD") tracks = 0; dataindex = -1; audioindex = -1; + + AddCommand(SCSIDEV::eCmdReadToc, "CmdReadToc", &SCSICD::CmdReadToc); + AddCommand(SCSIDEV::eCmdPlayAudio10, "CmdPlayAudio10", &SCSICD::CmdPlayAudio10); + AddCommand(SCSIDEV::eCmdPlayAudioMSF, "CmdPlayAudioMSF", &SCSICD::CmdPlayAudioMSF); + AddCommand(SCSIDEV::eCmdPlayAudioTrack, "CmdPlayAudioTrack", &SCSICD::CmdPlayAudioTrack); } //--------------------------------------------------------------------------- @@ -255,6 +260,32 @@ SCSICD::~SCSICD() { // Clear track ClearTrack(); + + for (auto const& command : commands) { + free(command.second); + } +} + +void SCSICD::AddCommand(SCSIDEV::scsi_command opcode, const char* name, void (SCSICD::*execute)(SASIDEV *)) +{ + commands[opcode] = new command_t(name, execute); +} + +bool SCSICD::Dispatch(SASIDEV *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); } //--------------------------------------------------------------------------- @@ -470,6 +501,69 @@ void SCSICD::OpenPhysical(const Filepath& path) dataindex = 0; } +void SCSICD::CmdReadToc(SASIDEV *controller) +{ + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + ctrl->length = ReadToc(ctrl->cmd, ctrl->buffer); + if (ctrl->length <= 0) { + // Failure (Error) + controller->Error(); + return; + } + + // Data-in Phase + controller->DataIn(); +} + +void SCSICD::CmdPlayAudio10(SASIDEV *controller) +{ + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + // Command processing on drive + bool status = PlayAudio(ctrl->cmd); + if (!status) { + // Failure (Error) + controller->Error(); + return; + } + + // Status phase + controller->Status(); +} + +void SCSICD::CmdPlayAudioMSF(SASIDEV *controller) +{ + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + // Command processing on drive + bool status = PlayAudioMSF(ctrl->cmd); + if (!status) { + // Failure (Error) + controller->Error(); + return; + } + + // Status phase + controller->Status(); +} + +void SCSICD::CmdPlayAudioTrack(SASIDEV *controller) +{ + SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr(); + + // Command processing on drive + bool status = PlayAudioTrack(ctrl->cmd); + if (!status) { + // Failure (Error) + controller->Error(); + return; + } + + // Status phase + controller->Status(); +} + //--------------------------------------------------------------------------- // // INQUIRY diff --git a/src/raspberrypi/devices/scsicd.h b/src/raspberrypi/devices/scsicd.h index ee8c8bd7..4372ff50 100644 --- a/src/raspberrypi/devices/scsicd.h +++ b/src/raspberrypi/devices/scsicd.h @@ -69,6 +69,15 @@ private: //=========================================================================== class SCSICD : public Disk, 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 commands; + public: // Number of tracks enum { @@ -96,11 +105,21 @@ public: void LBAtoMSF(DWORD lba, BYTE *msf) const; // LBA→MSF conversion DWORD MSFtoLBA(const BYTE *msf) const; // MSF→LBA conversion + bool Dispatch(SASIDEV *); + private: // Open void OpenCue(const Filepath& path); // Open(CUE) void OpenIso(const Filepath& path); // Open(ISO) void OpenPhysical(const Filepath& path); // Open(Physical) + + void AddCommand(SCSIDEV::scsi_command, const char*, void (SCSICD::*)(SASIDEV *)); + + void CmdReadToc(SASIDEV *); + void CmdPlayAudio10(SASIDEV *); + void CmdPlayAudioMSF(SASIDEV *); + void CmdPlayAudioTrack(SASIDEV *); + BOOL rawfile; // RAW flag // Track management