Moved all hard disk commands to disk.cpp for testing

This commit is contained in:
Uwe Seimet 2021-08-22 14:29:51 +02:00
parent 43cd5263f9
commit 68eb6bba4c
8 changed files with 471 additions and 290 deletions

View File

@ -714,7 +714,7 @@ void SASIDEV::CmdTestUnitReady()
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
// Command processing on drive
bool status = ctrl.device->TestUnitReady(ctrl.cmd);
bool status = ((Disk *)ctrl.device)->TestUnitReady(ctrl.cmd);
if (!status) {
// Failure (Error)
Error();
@ -965,7 +965,6 @@ void SASIDEV::DaynaPortWrite()
DataOut();
}
//---------------------------------------------------------------------------
//
// WRITE(6)

View File

@ -183,6 +183,8 @@ 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
@ -207,7 +209,6 @@ protected:
void CmdAssign(); // ASSIGN command
void CmdSpecify(); // SPECIFY command
void CmdInvalid(); // Unsupported command
void DaynaPortWrite(); // DaynaPort specific 'write' operation
// データ転送
virtual void Send(); // Send data

View File

@ -42,34 +42,34 @@ SCSIDEV::SCSIDEV() : SASIDEV()
scsi.msc = 0;
memset(scsi.msb, 0x00, sizeof(scsi.msb));
SetUpControllerCommand(eCmdTestUnitReady, "CmdTestUnitReady", &SCSIDEV::CmdTestUnitReady);
SetUpControllerCommand(eCmdRezero, "CmdRezero", &SCSIDEV::CmdRezero);
SetUpControllerCommand(eCmdRequestSense, "CmdRequestSense", &SCSIDEV::CmdRequestSense);
SetUpControllerCommand(eCmdFormat, "CmdFormat", &SCSIDEV::CmdFormat);
SetUpControllerCommand(eCmdReassign, "CmdReassign", &SCSIDEV::CmdReassign);
SetUpControllerCommand(eCmdRead6, "CmdRead6", &SCSIDEV::CmdRead6);
SetUpControllerCommand(eCmdWrite6, "CmdWrite6", &SCSIDEV::CmdWrite6);
SetUpDeviceCommand(eCmdTestUnitReady, "CmdTestUnitReady", &Disk::TestUnitReady);
SetUpDeviceCommand(eCmdRezero, "CmdRezero", &Disk::Rezero);
SetUpDeviceCommand(eCmdRequestSense, "CmdRequestSense", &Disk::RequestSense);
SetUpDeviceCommand(eCmdFormat, "CmdFormat", &Disk::Format);
SetUpDeviceCommand(eCmdReassign, "CmdReassign", &Disk::ReassignBlocks);
SetUpDeviceCommand(eCmdRead6, "CmdRead6", &Disk::Read6);
SetUpDeviceCommand(eCmdWrite6, "CmdWrite6", &Disk::Write6);
SetUpDeviceCommand(eCmdSeek6, "CmdSeek6", &Disk::Seek6);
SetUpControllerCommand(eCmdInquiry, "CmdInquiry", &SCSIDEV::CmdInquiry);
SetUpControllerCommand(eCmdModeSelect, "CmdModeSelect", &SCSIDEV::CmdModeSelect);
SetUpDeviceCommand(eCmdInquiry, "CmdInquiry", &Disk::Inquiry);
SetUpDeviceCommand(eCmdModeSelect, "CmdModeSelect", &Disk::ModeSelect);
SetUpDeviceCommand(eCmdReserve6, "CmdReserve6", &Disk::Reserve6);
SetUpDeviceCommand(eCmdRelease6, "CmdRelease6", &Disk::Release6);
SetUpControllerCommand(eCmdModeSense, "CmdModeSense", &SCSIDEV::CmdModeSense);
SetUpControllerCommand(eCmdStartStop, "CmdStartStop", &SCSIDEV::CmdStartStop);
SetUpControllerCommand(eCmdSendDiag, "CmdSendDiag", &SCSIDEV::CmdSendDiag);
SetUpControllerCommand(eCmdRemoval, "CmdRemoval", &SCSIDEV::CmdRemoval);
SetUpDeviceCommand(eCmdModeSense, "CmdModeSense", &Disk::ModeSense);
SetUpDeviceCommand(eCmdStartStop, "CmdStartStop", &Disk::StartStop);
SetUpDeviceCommand(eCmdSendDiag, "CmdSendDiag", &Disk::SendDiagnostic);
SetUpDeviceCommand(eCmdRemoval, "CmdRemoval", &Disk::PreventAllowRemoval);
SetUpDeviceCommand(eCmdReadCapacity10, "CmdReadCapacity10", &Disk::ReadCapacity10);
SetUpDeviceCommand(eCmdRead10, "CmdRead10", &Disk::Read10);
SetUpDeviceCommand(eCmdWrite10, "CmdWrite10", &Disk::Write10);
SetUpDeviceCommand(eCmdVerify10, "CmdVerify10", &Disk::Write10);
SetUpDeviceCommand(eCmdSeek10, "CmdSeek10", &Disk::Seek10);
SetUpDeviceCommand(eCmdVerify, "CmdVerify", &Disk::Verify);
SetUpControllerCommand(eCmdSynchronizeCache, "CmdSynchronizeCache", &SCSIDEV::CmdSynchronizeCache);
SetUpControllerCommand(eCmdReadDefectData10, "CmdReadDefectData10", &SCSIDEV::CmdReadDefectData10);
SetUpControllerCommand(eCmdModeSelect10, "CmdModeSelect10", &SCSIDEV::CmdModeSelect10);
SetUpDeviceCommand(eCmdSynchronizeCache, "CmdSynchronizeCache", &Disk::SynchronizeCache);
SetUpDeviceCommand(eCmdReadDefectData10, "CmdReadDefectData10", &Disk::ReadDefectData10);
SetUpDeviceCommand(eCmdModeSelect10, "CmdModeSelect10", &Disk::ModeSelect10);
SetUpDeviceCommand(eCmdReserve10, "CmdReserve10", &Disk::Reserve10);
SetUpDeviceCommand(eCmdRelease10, "CmdRelease10", &Disk::Release10);
SetUpControllerCommand(eCmdModeSense10, "CmdModeSense10", &SCSIDEV::CmdModeSense10);
SetUpDeviceCommand(eCmdModeSense10, "CmdModeSense10", &Disk::ModeSense10);
SetUpDeviceCommand(eCmdRead16, "CmdRead16", &Disk::Read16);
SetUpDeviceCommand(eCmdWrite16, "CmdWrite16", &Disk::Write16);
SetUpDeviceCommand(eCmdVerify16, "CmdVerify16", &Disk::Write16);
@ -432,197 +432,6 @@ void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc)
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdInquiry()
{
LOGTRACE("%s INQUIRY Command", __PRETTY_FUNCTION__);
// Find a valid unit
// TODO The code below is probably wrong. It results in the same INQUIRY data being
// used for all LUNs, even though each LUN has its individual set of INQUIRY data.
PrimaryDevice *device = NULL;
for (int valid_lun = 0; valid_lun < UnitMax; valid_lun++) {
if (ctrl.unit[valid_lun]) {
device = ctrl.unit[valid_lun];
break;
}
}
// Processed on the disk side (it is originally processed by the controller)
if (device) {
ctrl.length = device->Inquiry(ctrl.cmd, ctrl.buffer);
} else {
ctrl.length = 0;
}
if (ctrl.length <= 0) {
// failure (error)
Error();
return;
}
// Add synchronous transfer support information
if (scsi.syncenable) {
ctrl.buffer[7] |= (1 << 4);
}
// Report if the device does not support the requested LUN
DWORD lun = (ctrl.cmd[1] >> 5) & 0x07;
if (!ctrl.unit[lun]) {
ctrl.buffer[0] |= 0x7f;
}
// Data-in Phase
DataIn();
}
//---------------------------------------------------------------------------
//
// MODE SELECT
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdModeSelect()
{
LOGTRACE( "%s MODE SELECT Command", __PRETTY_FUNCTION__);
// Command processing on drive
ctrl.length = ctrl.device->SelectCheck(ctrl.cmd);
if (ctrl.length <= 0) {
// Failure (Error)
Error();
return;
}
// Data out phase
DataOut();
}
//---------------------------------------------------------------------------
//
// MODE SENSE
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdModeSense()
{
LOGTRACE( "%s MODE SENSE Command ", __PRETTY_FUNCTION__);
// Command processing on drive
ctrl.length = ctrl.device->ModeSense(ctrl.cmd, ctrl.buffer);
ASSERT(ctrl.length >= 0);
if (ctrl.length == 0) {
LOGWARN("%s Not supported MODE SENSE page $%02X",__PRETTY_FUNCTION__, (unsigned int)ctrl.cmd[2]);
// Failure (Error)
Error();
return;
}
// Data-in Phase
DataIn();
}
//---------------------------------------------------------------------------
//
// START STOP UNIT
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdStartStop()
{
LOGTRACE( "%s START STOP UNIT Command ", __PRETTY_FUNCTION__);
// Command processing on drive
bool status = ctrl.device->StartStop(ctrl.cmd);
if (!status) {
// Failure (Error)
Error();
return;
}
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// SEND DIAGNOSTIC
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdSendDiag()
{
LOGTRACE( "%s SEND DIAGNOSTIC Command ", __PRETTY_FUNCTION__);
// Command processing on drive
bool status = ctrl.device->SendDiag(ctrl.cmd);
if (!status) {
// Failure (Error)
Error();
return;
}
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// PREVENT/ALLOW MEDIUM REMOVAL
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdRemoval()
{
LOGTRACE( "%s PREVENT/ALLOW MEDIUM REMOVAL Command ", __PRETTY_FUNCTION__);
// Command processing on drive
bool status = ctrl.device->Removal(ctrl.cmd);
if (!status) {
// Failure (Error)
Error();
return;
}
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// SYNCHRONIZE CACHE
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdSynchronizeCache()
{
// Nothing to do
// status phase
Status();
}
//---------------------------------------------------------------------------
//
// READ DEFECT DATA(10)
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdReadDefectData10()
{
LOGTRACE( "%s READ DEFECT DATA(10) Command ", __PRETTY_FUNCTION__);
// Command processing on drive
ctrl.length = ctrl.device->ReadDefectData10(ctrl.cmd, ctrl.buffer);
ASSERT(ctrl.length >= 0);
if (ctrl.length <= 4) {
Error();
return;
}
// Data-in Phase
DataIn();
}
//---------------------------------------------------------------------------
//
// READ TOC
@ -710,51 +519,6 @@ void SCSIDEV::CmdGetEventStatusNotification()
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
}
//---------------------------------------------------------------------------
//
// MODE SELECT10
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdModeSelect10()
{
LOGTRACE( "%s MODE SELECT10 Command ", __PRETTY_FUNCTION__);
// Command processing on drive
ctrl.length = ctrl.device->SelectCheck10(ctrl.cmd);
if (ctrl.length <= 0) {
// Failure (Error)
Error();
return;
}
// Data out phase
DataOut();
}
//---------------------------------------------------------------------------
//
// MODE SENSE(10)
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdModeSense10()
{
LOGTRACE( "%s MODE SENSE(10) Command ", __PRETTY_FUNCTION__);
// Command processing on drive
ctrl.length = ctrl.device->ModeSense10(ctrl.cmd, ctrl.buffer);
ASSERT(ctrl.length >= 0);
if (ctrl.length == 0) {
LOGWARN("%s Not supported MODE SENSE(10) page $%02X", __PRETTY_FUNCTION__, (WORD)ctrl.cmd[2]);
// Failure (Error)
Error();
return;
}
// Data-in Phase
DataIn();
}
//---------------------------------------------------------------------------
//
// GET MESSAGE(10)

View File

@ -66,8 +66,6 @@ public:
// 外部API
BUS::phase_t Process(); // Run
void SyncTransfer(BOOL enable) { scsi.syncenable = enable; } // Synchronouse transfer enable setting
// Other
BOOL IsSASI() const {return FALSE;} // SASI Check
BOOL IsSCSI() const {return TRUE;} // SCSI check
@ -89,14 +87,6 @@ private:
void MsgOut(); // Message out phase
// commands
void CmdInquiry(); // INQUIRY command
void CmdModeSelect(); // MODE SELECT command
void CmdModeSense(); // MODE SENSE command
void CmdStartStop(); // START STOP UNIT command
void CmdSendDiag(); // SEND DIAGNOSTIC command
void CmdRemoval(); // PREVENT/ALLOW MEDIUM REMOVAL command
void CmdSynchronizeCache(); // SYNCHRONIZE CACHE command
void CmdReadDefectData10(); // READ DEFECT DATA(10) command
void CmdReadToc(); // READ TOC command
void CmdPlayAudio10(); // PLAY AUDIO(10) command
void CmdPlayAudioMSF(); // PLAY AUDIO MSF command

View File

@ -23,10 +23,10 @@ public:
virtual ~BlockDevice() {};
// Mandatory commands
virtual bool TestUnitReady(const DWORD *cdb) override = 0;
virtual int Inquiry(const DWORD *cdb, BYTE *buf) override = 0;
virtual void TestUnitReady(SASIDEV *) override = 0;
virtual void Inquiry(SASIDEV *) override = 0;
virtual void ReportLuns(SASIDEV *) override = 0;
virtual bool Format(const DWORD *cdb) = 0;
virtual void Format(SASIDEV *) = 0;
virtual void ReadCapacity10(SASIDEV *) = 0;
virtual void ReadCapacity16(SASIDEV *) = 0;
virtual void Read10(SASIDEV *) = 0;
@ -38,10 +38,10 @@ public:
// TODO uncomment
//virtual void Verify10(SASIDEV *) = 0;
//virtual void Verify16(SASIDEV *) = 0;
virtual int RequestSense(const DWORD *cdb, BYTE *buf) override = 0;
virtual int ModeSense(const DWORD *cdb, BYTE *buf) override = 0;
virtual int ModeSense10(const DWORD *cdb, BYTE *buf) override = 0;
virtual bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override = 0;
virtual void RequestSense(SASIDEV *) override = 0;
//virtual void ModeSense(SASIDEV *) override = 0;
//virtual void ModeSense10(SASIDEV *) override = 0;
//virtual void ModeSelect(SASIDEV *) override = 0;
// TODO Add the other optional commands currently implemented
};

View File

@ -26,6 +26,7 @@
#include "cfilesystem.h"
#include "controllers/sasidev_ctrl.h"
#include "controllers/scsidev_ctrl.h"
#include "exceptions.h"
#include "disk.h"
#include <sstream>
@ -352,6 +353,162 @@ BOOL DiskTrack::Read(BYTE *buf, int sec) const
return TRUE;
}
void Disk::TestUnitReady(SASIDEV *controller)
{
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
bool status = TestUnitReady(ctrl->cmd);
if (!status) {
// Failure (Error)
controller->Error();
return;
}
// status phase
controller->Status();
}
void Disk::Rezero(SASIDEV *controller)
{
LOGTRACE( "%s REZERO Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
bool status = Rezero(ctrl->cmd);
if (!status) {
// Failure (Error)
controller->Error();
return;
}
// status phase
controller->Status();
}
void Disk::RequestSense(SASIDEV *controller)
{
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
DWORD lun;
try {
lun = GetLun();
}
catch(const lun_exception& e) {
// Note: According to the SCSI specs the LUN handling for REQUEST SENSE is special.
// Non-existing LUNs do *not* result in CHECK CONDITION.
// Only the Sense Key and ASC are set in order to signal the non-existing LUN.
// LUN 0 can be assumed to be present (required to call RequestSense() below)
lun = 0;
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
}
ctrl->length = ctrl->unit[lun]->RequestSense(ctrl->cmd, ctrl->buffer);
ASSERT(ctrl->length > 0);
LOGTRACE("%s Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->buffer[2], ctrl->buffer[12]);
// Read phase
controller->DataIn();
}
void Disk::Format(SASIDEV *controller)
{
LOGTRACE( "%s FORMAT UNIT Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
bool status = Format(ctrl->cmd);
if (!status) {
// Failure (Error)
controller->Error();
return;
}
// status phase
controller->Status();
}
void Disk::ReassignBlocks(SASIDEV *controller)
{
LOGTRACE("%s REASSIGN BLOCKS Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
bool status = Reassign(ctrl->cmd);
if (!status) {
// Failure (Error)
controller->Error();
return;
}
// status phase
controller->Status();
}
void Disk::Read6(SASIDEV *controller)
{
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 = ctrl->cmd[4];
if (ctrl->blocks == 0) {
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;
}
}
LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl->blocks);
// Command processing on drive
ctrl->length = Read(ctrl->cmd, ctrl->buffer, record);
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 && !IsDaynaPort()) {
// Failure (Error)
controller->Error();
return;
}
// Set next block
ctrl->next = record + 1;
// Read phase
controller->DataIn();
}
void Disk::Read10(SASIDEV *controller)
{
// TODO Move to subclass
@ -454,6 +611,55 @@ BOOL DiskTrack::Write(const BYTE *buf, int sec)
return TRUE;
}
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;
record |= ctrl->cmd[2];
record <<= 8;
record |= ctrl->cmd[3];
ctrl->blocks = ctrl->cmd[4];
if (ctrl->blocks == 0) {
ctrl->blocks = 0x100;
}
// Check capacity
DWORD capacity = GetBlockCount();
if (record > capacity || record + ctrl->blocks > capacity) {
ostringstream s;
s << "Media capacity of " << capacity << " blocks exceeded: "
<< "Trying to write 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 WRITE(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (WORD)record, (WORD)ctrl->blocks);
// Command processing on drive
ctrl->length = WriteCheck(record);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::WRITE_PROTECTED);
return;
}
// Set next block
ctrl->next = record + 1;
// Write phase
controller->DataOut();
}
void Disk::Write10(SASIDEV *controller)
{
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
@ -549,6 +755,205 @@ void Disk::Verify(SASIDEV *controller)
controller->DataOut();
}
void Disk::Inquiry(SASIDEV *controller)
{
LOGTRACE("%s INQUIRY Command", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Find a valid unit
// TODO The code below is probably wrong. It results in the same INQUIRY data being
// used for all LUNs, even though each LUN has its individual set of INQUIRY data.
PrimaryDevice *device = NULL;
for (int valid_lun = 0; valid_lun < SASIDEV::UnitMax; valid_lun++) {
if (ctrl->unit[valid_lun]) {
device = ctrl->unit[valid_lun];
break;
}
}
// Processed on the disk side (it is originally processed by the controller)
if (device) {
ctrl->length = Inquiry(ctrl->cmd, ctrl->buffer);
} else {
ctrl->length = 0;
}
if (ctrl->length <= 0) {
// failure (error)
controller->Error();
return;
}
// Report if the device does not support the requested LUN
DWORD lun = (ctrl->cmd[1] >> 5) & 0x07;
if (!ctrl->unit[lun]) {
ctrl->buffer[0] |= 0x7f;
}
// Data-in Phase
controller->DataIn();
}
void Disk::ModeSelect(SASIDEV *controller)
{
LOGTRACE( "%s MODE SELECT Command", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
ctrl->length = SelectCheck(ctrl->cmd);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
return;
}
// Data out phase
controller->DataOut();
}
void Disk::ModeSelect10(SASIDEV *controller)
{
LOGTRACE( "%s MODE SELECT10 Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
ctrl->length = SelectCheck10(ctrl->cmd);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
return;
}
// Data out phase
controller->DataOut();
}
void Disk::ModeSense(SASIDEV *controller)
{
LOGTRACE( "%s MODE SENSE Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
ctrl->length = ModeSense(ctrl->cmd, ctrl->buffer);
ASSERT(ctrl->length >= 0);
if (ctrl->length == 0) {
LOGWARN("%s Not supported MODE SENSE page $%02X",__PRETTY_FUNCTION__, (unsigned int)ctrl->cmd[2]);
// Failure (Error)
controller->Error();
return;
}
// Data-in Phase
controller->DataIn();
}
void Disk::ModeSense10(SASIDEV *controller)
{
LOGTRACE( "%s MODE SENSE(10) Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer);
ASSERT(ctrl->length >= 0);
if (ctrl->length == 0) {
LOGWARN("%s Not supported MODE SENSE(10) page $%02X", __PRETTY_FUNCTION__, (WORD)ctrl->cmd[2]);
// Failure (Error)
controller->Error();
return;
}
// Data-in Phase
controller->DataIn();
}
void Disk::StartStop(SASIDEV *controller)
{
LOGTRACE( "%s START STOP Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
bool status = StartStop(ctrl->cmd);
if (!status) {
// Failure (Error)
controller->Error();
return;
}
// status phase
controller->Status();
}
void Disk::SendDiagnostic(SASIDEV *controller)
{
LOGTRACE( "%s SEND DIAGNOSTIC Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
bool status = SendDiag(ctrl->cmd);
if (!status) {
// Failure (Error)
controller->Error();
return;
}
// status phase
controller->Status();
}
void Disk::PreventAllowRemoval(SASIDEV *controller)
{
LOGTRACE( "%s PREVENT/ALLOW MEDIUM REMOVAL Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
bool status = Removal(ctrl->cmd);
if (!status) {
// Failure (Error)
controller->Error();
return;
}
// status phase
controller->Status();
}
void Disk::SynchronizeCache(SASIDEV *controller)
{
// Nothing to do
// status phase
controller->Status();
}
void Disk::ReadDefectData10(SASIDEV *controller)
{
LOGTRACE( "%s READ DEFECT DATA(10) Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Command processing on drive
ctrl->length = ReadDefectData10(ctrl->cmd, ctrl->buffer);
ASSERT(ctrl->length >= 0);
if (ctrl->length <= 4) {
controller->Error();
return;
}
// Data-in Phase
controller->DataIn();
}
//===========================================================================
//
// Disk Cache
@ -1963,6 +2368,7 @@ void Disk::ReadCapacity10(SASIDEV *controller)
LOGTRACE( "%s READ CAPACITY(10) Command ", __PRETTY_FUNCTION__);
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
BYTE *buf = ctrl->buffer;
ASSERT(buf);

View File

@ -149,24 +149,33 @@ public:
bool Eject(bool) override; // Eject
bool Flush(); // Flush the cache
// commands
virtual bool TestUnitReady(const DWORD *cdb) override; // TEST UNIT READY command
virtual int Inquiry(const DWORD *cdb, BYTE *buf) override; // INQUIRY command
virtual int RequestSense(const DWORD *cdb, BYTE *buf) override; // REQUEST SENSE command
// Commands
void TestUnitReady(SASIDEV *) override;
void Inquiry(SASIDEV *) override;
void RequestSense(SASIDEV *) override;
int SelectCheck(const DWORD *cdb); // SELECT check
int SelectCheck10(const DWORD *cdb); // SELECT(10) check
virtual bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;// MODE SELECT command
virtual int ModeSense(const DWORD *cdb, BYTE *buf) override; // MODE SENSE command
virtual int ModeSense10(const DWORD *cdb, BYTE *buf) override; // MODE SENSE(10) command
int ReadDefectData10(const DWORD *cdb, BYTE *buf); // READ DEFECT DATA(10) command
bool Rezero(const DWORD *cdb); // REZERO command
bool Format(const DWORD *cdb) override; // FORMAT UNIT command
bool Reassign(const DWORD *cdb); // REASSIGN UNIT command
void ModeSelect(SASIDEV *);
void ModeSelect10(SASIDEV *);
void ModeSense(SASIDEV *);
void ModeSense10(SASIDEV *);
void Rezero(SASIDEV *);
void Format(SASIDEV *) override;
void Reassign(SASIDEV *);
void ReassignBlocks(SASIDEV *);
void StartStop(SASIDEV *); // START STOP UNIT command
void SendDiagnostic(SASIDEV *);
void PreventAllowRemoval(SASIDEV *); // PREVENT/ALLOW MEDIUM REMOVAL command
void SynchronizeCache(SASIDEV *);
void ReadDefectData10(SASIDEV *);
virtual int Read(const DWORD *cdb, BYTE *buf, DWORD block); // READ command
void Read6(SASIDEV *);
void Read10(SASIDEV *);
void Read16(SASIDEV *);
virtual int Inquiry(const DWORD *cdb, BYTE *buf); // INQUIRY command
virtual int WriteCheck(DWORD block); // WRITE check
virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block); // WRITE command
void Write6(SASIDEV *);
void Write10(SASIDEV *);
void Write16(SASIDEV *);
void Seek(SASIDEV *);
@ -200,6 +209,18 @@ public:
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, bool);
virtual int ModeSense10(const DWORD *cdb, BYTE *buf); // MODE SENSE(10) command
int ReadDefectData10(const DWORD *cdb, BYTE *buf); // READ DEFECT DATA(10) command
// TODO Try to get rid of these methods, which are currently use by SASIDEV
virtual bool TestUnitReady(const DWORD *cdb); // TEST UNIT READY command
bool Rezero(const DWORD *cdb); // REZERO command
virtual int RequestSense(const DWORD *cdb, BYTE *buf); // REQUEST SENSE command
virtual bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length);// MODE SELECT command
virtual int ModeSense(const DWORD *cdb, BYTE *buf); // MODE SENSE command
bool Format(const DWORD *cdb); // FORMAT UNIT command
bool Reassign(const DWORD *cdb); // REASSIGN UNIT command
protected:
// Internal processing
virtual int AddError(bool change, BYTE *buf); // Add error

View File

@ -23,13 +23,13 @@ public:
virtual ~PrimaryDevice() {};
// Mandatory commands
virtual bool TestUnitReady(const DWORD *cdb) = 0;
virtual int Inquiry(const DWORD *cdb, BYTE *buf) = 0;
virtual void TestUnitReady(SASIDEV *) = 0;
virtual void Inquiry(SASIDEV *) = 0;
virtual void ReportLuns(SASIDEV *) = 0;
// Implemented optional commands
virtual int RequestSense(const DWORD *cdb, BYTE *buf) = 0;
virtual int ModeSense(const DWORD *cdb, BYTE *buf) = 0;
virtual int ModeSense10(const DWORD *cdb, BYTE *buf) = 0;
virtual bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) = 0;
virtual void RequestSense(SASIDEV *) = 0;
virtual void ModeSense(SASIDEV *) = 0;
virtual void ModeSense10(SASIDEV *) = 0;
virtual void ModeSelect(SASIDEV *) = 0;
};