mirror of
https://github.com/akuker/RASCSI.git
synced 2025-02-02 18:33:35 +00:00
Moved DaynPort specific code
This commit is contained in:
parent
806e0e0f27
commit
d3a9ae48af
@ -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)) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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<scsi_command>(ctrl.cmd[0]))) {
|
||||
CmdInvalid();
|
||||
return;
|
||||
}
|
||||
|
||||
controller_command_t* command = controller_commands[static_cast<scsi_command>(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)
|
||||
|
@ -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<scsi_command, controller_command_t*> 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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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<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);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@ -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
|
||||
|
@ -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<SCSIDEV::scsi_command, command_t*> 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user