mirror of
https://github.com/akuker/RASCSI.git
synced 2025-02-05 23:30:05 +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;
|
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);
|
LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
@ -851,7 +843,7 @@ void SASIDEV::CmdRead6()
|
|||||||
LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, (int)ctrl.length);
|
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.
|
// 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)
|
// Failure (Error)
|
||||||
Error();
|
Error();
|
||||||
return;
|
return;
|
||||||
@ -864,56 +856,6 @@ void SASIDEV::CmdRead6()
|
|||||||
DataIn();
|
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)
|
// WRITE(6)
|
||||||
@ -921,12 +863,6 @@ void SASIDEV::DaynaPortWrite()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SASIDEV::CmdWrite6()
|
void SASIDEV::CmdWrite6()
|
||||||
{
|
{
|
||||||
// Special receive function for the DaynaPort
|
|
||||||
if (ctrl.device->IsDaynaPort()){
|
|
||||||
DaynaPortWrite();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get record number and block number
|
// Get record number and block number
|
||||||
DWORD record = ctrl.cmd[1] & 0x1f;
|
DWORD record = ctrl.cmd[1] & 0x1f;
|
||||||
record <<= 8;
|
record <<= 8;
|
||||||
@ -1308,7 +1244,7 @@ BOOL SASIDEV::XferOut(BOOL cont)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special case Write function for DaynaPort
|
// 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()) {
|
if (device->IsDaynaPort()) {
|
||||||
LOGTRACE("%s Doing special case write for DaynaPort", __PRETTY_FUNCTION__);
|
LOGTRACE("%s Doing special case write for DaynaPort", __PRETTY_FUNCTION__);
|
||||||
if (!(SCSIDaynaPort*)device->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) {
|
if (!(SCSIDaynaPort*)device->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) {
|
||||||
|
@ -89,6 +89,7 @@ public:
|
|||||||
|
|
||||||
const int UNKNOWN_SCSI_ID = -1;
|
const int UNKNOWN_SCSI_ID = -1;
|
||||||
const int DEFAULT_BUFFER_SIZE = 0x1000;
|
const int DEFAULT_BUFFER_SIZE = 0x1000;
|
||||||
|
// TODO Remove this duplicate
|
||||||
const int DAYNAPORT_BUFFER_SIZE = 0x1000000;
|
const int DAYNAPORT_BUFFER_SIZE = 0x1000000;
|
||||||
|
|
||||||
// For timing adjustments
|
// For timing adjustments
|
||||||
@ -162,8 +163,6 @@ public:
|
|||||||
void MsgIn(); // Message in phase
|
void MsgIn(); // Message in phase
|
||||||
void DataOut(); // Data out 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,
|
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
|
ERROR_CODES::asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION); // Common error handling
|
||||||
|
|
||||||
|
@ -41,25 +41,10 @@ SCSIDEV::SCSIDEV() : SASIDEV()
|
|||||||
scsi.atnmsg = FALSE;
|
scsi.atnmsg = FALSE;
|
||||||
scsi.msc = 0;
|
scsi.msc = 0;
|
||||||
memset(scsi.msb, 0x00, sizeof(scsi.msb));
|
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()
|
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.execstart = SysTimer::GetTimerLow();
|
||||||
|
|
||||||
ctrl.device = ctrl.unit[GetLun()];
|
ctrl.device = ctrl.unit[GetLun()];
|
||||||
|
ctrl.device->Dispatch(this);
|
||||||
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)();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -366,99 +335,6 @@ void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc)
|
|||||||
Status();
|
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)
|
// GET MESSAGE(10)
|
||||||
|
@ -85,15 +85,6 @@ public:
|
|||||||
BYTE msb[256];
|
BYTE msb[256];
|
||||||
} scsi_t;
|
} 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:
|
public:
|
||||||
// Basic Functions
|
// Basic Functions
|
||||||
SCSIDEV();
|
SCSIDEV();
|
||||||
@ -115,7 +106,6 @@ public:
|
|||||||
void CmdSendMessage10(); // SEND MESSAGE(10) command
|
void CmdSendMessage10(); // SEND MESSAGE(10) command
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetUpControllerCommand(scsi_command, const char*, void (SCSIDEV::*)(void));
|
|
||||||
|
|
||||||
// Phase
|
// Phase
|
||||||
void BusFree(); // Bus free phase
|
void BusFree(); // Bus free phase
|
||||||
@ -124,10 +114,6 @@ private:
|
|||||||
void MsgOut(); // Message out phase
|
void MsgOut(); // Message out phase
|
||||||
|
|
||||||
// commands
|
// 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 CmdGetEventStatusNotification();
|
||||||
void CmdModeSelect10(); // MODE SELECT(10) command
|
void CmdModeSelect10(); // MODE SELECT(10) command
|
||||||
void CmdModeSense10(); // MODE SENSE(10) command
|
void CmdModeSense10(); // MODE SENSE(10) command
|
||||||
|
@ -469,24 +469,15 @@ void Disk::Read6(SASIDEV *controller)
|
|||||||
ctrl->blocks = 0x100;
|
ctrl->blocks = 0x100;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Move Daynaport specific test
|
// Check capacity
|
||||||
// TODO This class must not know about SCDP
|
DWORD capacity = GetBlockCount();
|
||||||
if(IsDaynaPort()){
|
if (record > capacity || record + ctrl->blocks > capacity) {
|
||||||
// The DaynaPort only wants one block.
|
ostringstream s;
|
||||||
// ctrl.cmd[4] and ctrl.cmd[5] are used to specify the maximum buffer size for the DaynaPort
|
s << "Media capacity of " << capacity << " blocks exceeded: "
|
||||||
ctrl->blocks=1;
|
<< "Trying to read block " << record << ", block count " << ctrl->blocks;
|
||||||
}
|
LOGWARN("%s", s.str().c_str());
|
||||||
else {
|
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE);
|
||||||
// Check capacity
|
return;
|
||||||
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);
|
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();
|
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
|
||||||
|
|
||||||
// Special receive function for the DaynaPort
|
|
||||||
if (IsDaynaPort()){
|
|
||||||
controller->DaynaPortWrite();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get record number and block number
|
// Get record number and block number
|
||||||
DWORD record = ctrl->cmd[1] & 0x1f;
|
DWORD record = ctrl->cmd[1] & 0x1f;
|
||||||
record <<= 8;
|
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);
|
commands[opcode] = new command_t(name, execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Disk::Dispatch(SCSIDEV *controller)
|
bool Disk::Dispatch(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
|
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ public:
|
|||||||
bool Format(const DWORD *cdb); // FORMAT UNIT command
|
bool Format(const DWORD *cdb); // FORMAT UNIT command
|
||||||
bool Reassign(const DWORD *cdb); // REASSIGN UNIT command
|
bool Reassign(const DWORD *cdb); // REASSIGN UNIT command
|
||||||
|
|
||||||
virtual bool Dispatch(SCSIDEV *);
|
virtual bool Dispatch(SASIDEV *);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Internal processing
|
// Internal processing
|
||||||
|
@ -89,12 +89,14 @@ SCSIDaynaPort::SCSIDaynaPort() : Disk("SCDP")
|
|||||||
m_mac_addr[5]=0xE3;
|
m_mac_addr[5]=0xE3;
|
||||||
|
|
||||||
#endif // linux
|
#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::eCmdRetrieveStats, "CmdRetrieveStats", &SCSIDaynaPort::CmdRetrieveStats);
|
||||||
AddCommand(SCSIDEV::eCmdSetIfaceMode, "CmdSetIfaceMode", &SCSIDaynaPort::CmdSetIfaceMode);
|
AddCommand(SCSIDEV::eCmdSetIfaceMode, "CmdSetIfaceMode", &SCSIDaynaPort::CmdSetIfaceMode);
|
||||||
AddCommand(SCSIDEV::eCmdSetMcastAddr, "CmdSetMcastAddr", &SCSIDaynaPort::CmdSetMcastAddr);
|
AddCommand(SCSIDEV::eCmdSetMcastAddr, "CmdSetMcastAddr", &SCSIDaynaPort::CmdSetMcastAddr);
|
||||||
AddCommand(SCSIDEV::eCmdEnableInterface, "CmdEnableInterface", &SCSIDaynaPort::CmdEnableInterface);
|
AddCommand(SCSIDEV::eCmdEnableInterface, "CmdEnableInterface", &SCSIDaynaPort::CmdEnableInterface);
|
||||||
|
AddCommand(SCSIDEV::eCmdGetEventStatusNotification, "CmdGetEventStatusNotification", &SCSIDaynaPort::CmdGetEventStatusNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -104,7 +106,6 @@ SCSIDaynaPort::SCSIDaynaPort() : Disk("SCDP")
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
SCSIDaynaPort::~SCSIDaynaPort()
|
SCSIDaynaPort::~SCSIDaynaPort()
|
||||||
{
|
{
|
||||||
LOGTRACE("SCSIDaynaPort Destructor");
|
|
||||||
// TAP driver release
|
// TAP driver release
|
||||||
if (m_tap) {
|
if (m_tap) {
|
||||||
m_tap->Cleanup();
|
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");
|
LOGTRACE("SCSIDaynaPort Open");
|
||||||
|
|
||||||
m_tap->OpenDump(path);
|
m_tap->OpenDump(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ SCSIDaynaPort::~SCSIDaynaPort()
|
|||||||
commands[opcode] = new command_t(name, execute);
|
commands[opcode] = new command_t(name, execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SCSIDaynaPort::Dispatch(SCSIDEV *controller)
|
bool SCSIDaynaPort::Dispatch(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
|
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
|
||||||
|
|
||||||
@ -510,11 +512,6 @@ bool SCSIDaynaPort::EnableInterface(const DWORD *cdb)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// TEST UNIT READY
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
bool SCSIDaynaPort::TestUnitReady(const DWORD* /*cdb*/)
|
bool SCSIDaynaPort::TestUnitReady(const DWORD* /*cdb*/)
|
||||||
{
|
{
|
||||||
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
||||||
@ -523,6 +520,73 @@ bool SCSIDaynaPort::TestUnitReady(const DWORD* /*cdb*/)
|
|||||||
return true;
|
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)
|
void SCSIDaynaPort::CmdRetrieveStats(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
LOGTRACE("%s",__PRETTY_FUNCTION__);
|
LOGTRACE("%s",__PRETTY_FUNCTION__);
|
||||||
@ -607,6 +671,14 @@ void SCSIDaynaPort::CmdEnableInterface(SASIDEV *controller)
|
|||||||
controller->Status();
|
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
|
// Set Mode - enable broadcast messages
|
||||||
|
@ -82,12 +82,17 @@ public:
|
|||||||
void SetMode(const DWORD *cdb, BYTE *buffer);
|
void SetMode(const DWORD *cdb, BYTE *buffer);
|
||||||
// Set the mode: whether broadcast traffic is enabled or not
|
// Set the mode: whether broadcast traffic is enabled or not
|
||||||
|
|
||||||
|
void CmdRead6(SASIDEV *);
|
||||||
|
void CmdWrite6(SASIDEV *);
|
||||||
void CmdRetrieveStats(SASIDEV *);
|
void CmdRetrieveStats(SASIDEV *);
|
||||||
void CmdSetIfaceMode(SASIDEV *);
|
void CmdSetIfaceMode(SASIDEV *);
|
||||||
void CmdSetMcastAddr(SASIDEV *);
|
void CmdSetMcastAddr(SASIDEV *);
|
||||||
void CmdEnableInterface(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_STATS = 0x09;
|
||||||
static const BYTE CMD_SCSILINK_ENABLE = 0x0E;
|
static const BYTE CMD_SCSILINK_ENABLE = 0x0E;
|
||||||
|
@ -244,6 +244,11 @@ SCSICD::SCSICD() : Disk("SCCD")
|
|||||||
tracks = 0;
|
tracks = 0;
|
||||||
dataindex = -1;
|
dataindex = -1;
|
||||||
audioindex = -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
|
// Clear track
|
||||||
ClearTrack();
|
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;
|
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
|
// INQUIRY
|
||||||
|
@ -69,6 +69,15 @@ private:
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
class SCSICD : public Disk, public FileSupport
|
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:
|
public:
|
||||||
// Number of tracks
|
// Number of tracks
|
||||||
enum {
|
enum {
|
||||||
@ -96,11 +105,21 @@ public:
|
|||||||
void LBAtoMSF(DWORD lba, BYTE *msf) const; // LBA→MSF conversion
|
void LBAtoMSF(DWORD lba, BYTE *msf) const; // LBA→MSF conversion
|
||||||
DWORD MSFtoLBA(const BYTE *msf) const; // MSF→LBA conversion
|
DWORD MSFtoLBA(const BYTE *msf) const; // MSF→LBA conversion
|
||||||
|
|
||||||
|
bool Dispatch(SASIDEV *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Open
|
// Open
|
||||||
void OpenCue(const Filepath& path); // Open(CUE)
|
void OpenCue(const Filepath& path); // Open(CUE)
|
||||||
void OpenIso(const Filepath& path); // Open(ISO)
|
void OpenIso(const Filepath& path); // Open(ISO)
|
||||||
void OpenPhysical(const Filepath& path); // Open(Physical)
|
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
|
BOOL rawfile; // RAW flag
|
||||||
|
|
||||||
// Track management
|
// Track management
|
||||||
|
Loading…
x
Reference in New Issue
Block a user