mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-31 11:32:11 +00:00
Support for providing sense data for REQUEST SENSE (#120)
* Error() supports passing Sense Key and ASC, REQUEST SENSE returns these data
* Synchronized error handlign with sasidev_ctrl
* Added warning for missing sense key
* Logging and comment update
* Updated invalid LUN handling
* Updated REQUEST SENSE
* Revert "Updated REQUEST SENSE"
This reverts commit 61a1ecbca7
.
* Report MEDIUM NOT PRESENT if capacity cannot be determined
* Updated handling of non-existing LUNs. This change results issue #124.
* Log a warning if drive capacity cannot be determined
* Added enums for sense keys and ASCs
* Updated Error() signature to use enums
* Fixed compiler warnings
* Merge with develop branch
This commit is contained in:
parent
0f5baa8839
commit
fef21a6cf5
@ -466,11 +466,12 @@ void FASTCALL SASIDEV::Command()
|
|||||||
|
|
||||||
// Execution Phase
|
// Execution Phase
|
||||||
try {
|
try {
|
||||||
Execute();
|
Execute();
|
||||||
}
|
}
|
||||||
catch (lunexception& e) {
|
catch (lunexception& e) {
|
||||||
LOGINFO("%s unsupported LUN %d", __PRETTY_FUNCTION__, (int)e.getlun());
|
LOGINFO("%s Invalid LUN %d", __PRETTY_FUNCTION__, (int)e.getlun());
|
||||||
Error();
|
|
||||||
|
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Request the command
|
// Request the command
|
||||||
@ -513,6 +514,12 @@ void FASTCALL SASIDEV::Execute()
|
|||||||
ctrl.execstart = SysTimer::GetTimerLow();
|
ctrl.execstart = SysTimer::GetTimerLow();
|
||||||
#endif // RASCSI
|
#endif // RASCSI
|
||||||
|
|
||||||
|
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||||
|
if ((SASIDEV::scsi_command)ctrl.cmd[0] != eCmdRequestSense) {
|
||||||
|
ctrl.sense_key = 0;
|
||||||
|
ctrl.asc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Process by command
|
// Process by command
|
||||||
switch ((SASIDEV::scsi_command)ctrl.cmd[0]) {
|
switch ((SASIDEV::scsi_command)ctrl.cmd[0]) {
|
||||||
// TEST UNIT READY
|
// TEST UNIT READY
|
||||||
@ -830,7 +837,7 @@ void FASTCALL SASIDEV::DataOut()
|
|||||||
// Error
|
// Error
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void FASTCALL SASIDEV::Error()
|
void FASTCALL SASIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc)
|
||||||
{
|
{
|
||||||
// Get bus information
|
// Get bus information
|
||||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||||
@ -851,9 +858,11 @@ void FASTCALL SASIDEV::Error()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("%s Sense Key and ASC for subsequent REQUEST SENSE: $%02X, $%02X", __PRETTY_FUNCTION__, sense_key, asc);
|
||||||
LOGWARN("Error occured (going to status phase)");
|
|
||||||
#endif // DISK_LOG
|
// Set Sense Key and ASC for a subsequent REQUEST SENSE
|
||||||
|
ctrl.sense_key = sense_key;
|
||||||
|
ctrl.asc = asc;
|
||||||
|
|
||||||
// Logical Unit
|
// Logical Unit
|
||||||
DWORD lun = (ctrl.cmd[1] >> 5) & 0x07;
|
DWORD lun = (ctrl.cmd[1] >> 5) & 0x07;
|
||||||
@ -861,6 +870,10 @@ void FASTCALL SASIDEV::Error()
|
|||||||
// Set status and message(CHECK CONDITION)
|
// Set status and message(CHECK CONDITION)
|
||||||
ctrl.status = (lun << 5) | 0x02;
|
ctrl.status = (lun << 5) | 0x02;
|
||||||
|
|
||||||
|
#if defined(DISK_LOG)
|
||||||
|
LOGWARN("Error occured (going to status phase)");
|
||||||
|
#endif // DISK_LOG
|
||||||
|
|
||||||
// status phase
|
// status phase
|
||||||
Status();
|
Status();
|
||||||
}
|
}
|
||||||
@ -920,13 +933,36 @@ void FASTCALL SASIDEV::CmdRequestSense()
|
|||||||
{
|
{
|
||||||
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
|
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
DWORD lun = GetLun();
|
DWORD lun;
|
||||||
|
try {
|
||||||
|
lun = GetLun();
|
||||||
|
}
|
||||||
|
catch(const lunexception& e) {
|
||||||
|
LOGINFO("%s Non-existing LUN %d", __PRETTY_FUNCTION__, (int)e.getlun());
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
ctrl.sense_key = ERROR_CODES::sense_key::ILLEGAL_REQUEST;
|
||||||
|
ctrl.asc = ERROR_CODES::asc::INVALID_LUN;
|
||||||
|
}
|
||||||
|
|
||||||
ctrl.length = ctrl.unit[lun]->RequestSense(ctrl.cmd, ctrl.buffer);
|
ctrl.length = ctrl.unit[lun]->RequestSense(ctrl.cmd, ctrl.buffer);
|
||||||
ASSERT(ctrl.length > 0);
|
ASSERT(ctrl.length > 0);
|
||||||
|
|
||||||
|
LOGTRACE("%s Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl.sense_key, ctrl.asc);
|
||||||
|
|
||||||
LOGTRACE("%s Sense key $%02X, ASC $%02X",__PRETTY_FUNCTION__, (WORD)ctrl.buffer[2], (WORD)ctrl.buffer[12]);
|
// REQUEST SENSE returns the sense data set by the previous (failed) command
|
||||||
|
ctrl.buffer[2] = ctrl.sense_key;
|
||||||
|
ctrl.buffer[12] = ctrl.asc;
|
||||||
|
|
||||||
|
// The sense data are only valid once
|
||||||
|
ctrl.sense_key = 0;
|
||||||
|
ctrl.asc = 0;
|
||||||
|
|
||||||
// Read phase
|
// Read phase
|
||||||
DataIn();
|
DataIn();
|
||||||
@ -1240,8 +1276,7 @@ void FASTCALL SASIDEV::CmdInvalid()
|
|||||||
{
|
{
|
||||||
LOGWARN("%s Command not supported", __PRETTY_FUNCTION__);
|
LOGWARN("%s Command not supported", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Failure (Error)
|
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE);
|
||||||
Error();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -1519,7 +1554,14 @@ void FASTCALL SASIDEV::ReceiveNext()
|
|||||||
// Command phase
|
// Command phase
|
||||||
case BUS::command:
|
case BUS::command:
|
||||||
// Execution Phase
|
// Execution Phase
|
||||||
Execute();
|
try {
|
||||||
|
Execute();
|
||||||
|
}
|
||||||
|
catch (const lunexception& e) {
|
||||||
|
LOGINFO("%s unsupported LUN %d", __PRETTY_FUNCTION__, (int)e.getlun());
|
||||||
|
// LOGICAL UNIT NOT SUPPORTED
|
||||||
|
Error(SENSE_KEY_ILLEGAL_REQUEST, ASC_INVALID_LUN);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif // RASCSI
|
#endif // RASCSI
|
||||||
|
|
||||||
|
@ -135,12 +135,16 @@ public:
|
|||||||
BYTE *buffer; // Transfer data buffer
|
BYTE *buffer; // Transfer data buffer
|
||||||
int bufsize; // Transfer data buffer size
|
int bufsize; // Transfer data buffer size
|
||||||
DWORD blocks; // Number of transfer block
|
DWORD blocks; // Number of transfer block
|
||||||
DWORD next; // Next record
|
DWORD next; // Next record
|
||||||
DWORD offset; // Transfer offset
|
DWORD offset; // Transfer offset
|
||||||
DWORD length; // Transfer remaining length
|
DWORD length; // Transfer remaining length
|
||||||
|
|
||||||
// Logical unit
|
// Logical unit
|
||||||
Disk *unit[UnitMax]; // Logical Unit
|
Disk *unit[UnitMax];
|
||||||
|
|
||||||
|
// Sense Key and Additional Sense Code (ASC) of the previous command
|
||||||
|
int sense_key;
|
||||||
|
int asc;
|
||||||
} ctrl_t;
|
} ctrl_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -194,7 +198,8 @@ protected:
|
|||||||
void FASTCALL MsgIn(); // Message in phase
|
void FASTCALL MsgIn(); // Message in phase
|
||||||
void FASTCALL DataIn(); // Data in phase
|
void FASTCALL DataIn(); // Data in phase
|
||||||
void FASTCALL DataOut(); // Data out phase
|
void FASTCALL DataOut(); // Data out phase
|
||||||
virtual void FASTCALL Error(); // Common error handling
|
virtual void FASTCALL 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
|
||||||
|
|
||||||
// commands
|
// commands
|
||||||
void FASTCALL CmdTestUnitReady(); // TEST UNIT READY command
|
void FASTCALL CmdTestUnitReady(); // TEST UNIT READY command
|
||||||
|
@ -307,6 +307,12 @@ void FASTCALL SCSIDEV::Execute()
|
|||||||
|
|
||||||
LOGDEBUG("++++ CMD ++++ %s Received %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl.cmd[0]);
|
LOGDEBUG("++++ CMD ++++ %s Received %s ($%02X)", __PRETTY_FUNCTION__, command->name, (unsigned int)ctrl.cmd[0]);
|
||||||
|
|
||||||
|
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||||
|
if ((unsigned int)ctrl.cmd[0] != 0x03) {
|
||||||
|
ctrl.sense_key = 0;
|
||||||
|
ctrl.asc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Process by command
|
// Process by command
|
||||||
(this->*command->execute)();
|
(this->*command->execute)();
|
||||||
}
|
}
|
||||||
@ -361,7 +367,7 @@ void FASTCALL SCSIDEV::MsgOut()
|
|||||||
// Common Error Handling
|
// Common Error Handling
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void FASTCALL SCSIDEV::Error()
|
void FASTCALL SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc)
|
||||||
{
|
{
|
||||||
// Get bus information
|
// Get bus information
|
||||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||||
@ -382,12 +388,18 @@ void FASTCALL SCSIDEV::Error()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGTRACE( "%s Error (to status phase)", __PRETTY_FUNCTION__);
|
LOGTRACE("%s Sense Key and ASC for subsequent REQUEST SENSE: $%02X, $%02X", __PRETTY_FUNCTION__, sense_key, asc);
|
||||||
|
|
||||||
|
// Set Sense Key and ASC for a subsequent REQUEST SENSE
|
||||||
|
ctrl.sense_key = sense_key;
|
||||||
|
ctrl.asc = asc;
|
||||||
|
|
||||||
// Set status and message(CHECK CONDITION)
|
// Set status and message(CHECK CONDITION)
|
||||||
ctrl.status = 0x02;
|
ctrl.status = 0x02;
|
||||||
ctrl.message = 0x00;
|
ctrl.message = 0x00;
|
||||||
|
|
||||||
|
LOGTRACE("%s Error (to status phase)", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// status phase
|
// status phase
|
||||||
Status();
|
Status();
|
||||||
}
|
}
|
||||||
@ -411,10 +423,10 @@ void FASTCALL SCSIDEV::CmdInquiry()
|
|||||||
// TODO The code below is most likely wrong. It results in the same INQUIRY data being
|
// TODO The code below is most likely wrong. It results in the same INQUIRY data being
|
||||||
// used for all LUNs, even though each LUN has its individual set of INQUIRY data.
|
// used for all LUNs, even though each LUN has its individual set of INQUIRY data.
|
||||||
Disk *disk = NULL;
|
Disk *disk = NULL;
|
||||||
int lun;
|
int valid_lun;
|
||||||
for (lun = 0; lun < UnitMax; lun++) {
|
for (valid_lun = 0; valid_lun < UnitMax; valid_lun++) {
|
||||||
if (ctrl.unit[lun]) {
|
if (ctrl.unit[valid_lun]) {
|
||||||
disk = ctrl.unit[lun];
|
disk = ctrl.unit[valid_lun];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,7 +437,7 @@ void FASTCALL SCSIDEV::CmdInquiry()
|
|||||||
DWORD minor = (DWORD)(RASCSI & 0xff);
|
DWORD minor = (DWORD)(RASCSI & 0xff);
|
||||||
LOGTRACE("%s Buffer size is %d",__PRETTY_FUNCTION__, ctrl.bufsize);
|
LOGTRACE("%s Buffer size is %d",__PRETTY_FUNCTION__, ctrl.bufsize);
|
||||||
ctrl.length =
|
ctrl.length =
|
||||||
ctrl.unit[lun]->Inquiry(ctrl.cmd, ctrl.buffer, major, minor);
|
ctrl.unit[valid_lun]->Inquiry(ctrl.cmd, ctrl.buffer, major, minor);
|
||||||
} else {
|
} else {
|
||||||
ctrl.length = 0;
|
ctrl.length = 0;
|
||||||
}
|
}
|
||||||
@ -441,6 +453,12 @@ void FASTCALL SCSIDEV::CmdInquiry()
|
|||||||
ctrl.buffer[7] |= (1 << 4);
|
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
|
// Data-in Phase
|
||||||
DataIn();
|
DataIn();
|
||||||
}
|
}
|
||||||
@ -650,7 +668,7 @@ void FASTCALL SCSIDEV::CmdReadCapacity()
|
|||||||
int length = ctrl.unit[lun]->ReadCapacity(ctrl.cmd, ctrl.buffer);
|
int length = ctrl.unit[lun]->ReadCapacity(ctrl.cmd, ctrl.buffer);
|
||||||
ASSERT(length >= 0);
|
ASSERT(length >= 0);
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
Error();
|
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1510,11 +1528,12 @@ void FASTCALL SCSIDEV::Receive()
|
|||||||
|
|
||||||
// Execution Phase
|
// Execution Phase
|
||||||
try {
|
try {
|
||||||
Execute();
|
Execute();
|
||||||
}
|
}
|
||||||
catch (lunexception& e) {
|
catch (const lunexception& e) {
|
||||||
LOGINFO("%s unsupported LUN %d", __PRETTY_FUNCTION__, (int)e.getlun());
|
LOGINFO("%s Invalid LUN %d", __PRETTY_FUNCTION__, (int)e.getlun());
|
||||||
Error();
|
|
||||||
|
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -74,7 +74,8 @@ private:
|
|||||||
void FASTCALL Selection(); // Selection phase
|
void FASTCALL Selection(); // Selection phase
|
||||||
void FASTCALL Execute(); // Execution phase
|
void FASTCALL Execute(); // Execution phase
|
||||||
void FASTCALL MsgOut(); // Message out phase
|
void FASTCALL MsgOut(); // Message out phase
|
||||||
void FASTCALL Error(); // Common erorr handling
|
void FASTCALL Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE,
|
||||||
|
ERROR_CODES::asc asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION); // Common erorr handling
|
||||||
|
|
||||||
// commands
|
// commands
|
||||||
void FASTCALL CmdInquiry(); // INQUIRY command
|
void FASTCALL CmdInquiry(); // INQUIRY command
|
||||||
|
@ -1216,7 +1216,10 @@ int FASTCALL Disk::RequestSense(const DWORD *cdb, BYTE *buf)
|
|||||||
memset(buf, 0, size);
|
memset(buf, 0, size);
|
||||||
|
|
||||||
// Set 18 bytes including extended sense data
|
// Set 18 bytes including extended sense data
|
||||||
|
|
||||||
|
// Current error
|
||||||
buf[0] = 0x70;
|
buf[0] = 0x70;
|
||||||
|
|
||||||
buf[2] = (BYTE)(disk.code >> 16);
|
buf[2] = (BYTE)(disk.code >> 16);
|
||||||
buf[7] = 10;
|
buf[7] = 10;
|
||||||
buf[12] = (BYTE)(disk.code >> 8);
|
buf[12] = (BYTE)(disk.code >> 8);
|
||||||
@ -2152,8 +2155,13 @@ int FASTCALL Disk::ReadCapacity(const DWORD* /*cdb*/, BYTE *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (disk.blocks <= 0) {
|
||||||
|
LOGWARN("%s Capacity not available, medium may not be present", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Create end of logical block address (disk.blocks-1)
|
// Create end of logical block address (disk.blocks-1)
|
||||||
ASSERT(disk.blocks > 0);
|
|
||||||
blocks = disk.blocks - 1;
|
blocks = disk.blocks - 1;
|
||||||
buf[0] = (BYTE)(blocks >> 24);
|
buf[0] = (BYTE)(blocks >> 24);
|
||||||
buf[1] = (BYTE)(blocks >> 16);
|
buf[1] = (BYTE)(blocks >> 16);
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
|
|
||||||
~lunexception() { }
|
~lunexception() { }
|
||||||
|
|
||||||
DWORD getlun() {
|
DWORD getlun() const {
|
||||||
return lun;
|
return lun;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -12,6 +12,28 @@
|
|||||||
#if !defined(scsi_h)
|
#if !defined(scsi_h)
|
||||||
#define scsi_h
|
#define scsi_h
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Sense Keys and Additional Sense Codes
|
||||||
|
// (See https://www.t10.org/lists/1spc-lst.htm)
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
class ERROR_CODES
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum sense_key : int {
|
||||||
|
NO_SENSE = 0x00,
|
||||||
|
ILLEGAL_REQUEST = 0x05
|
||||||
|
};
|
||||||
|
|
||||||
|
enum asc : int {
|
||||||
|
NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
|
||||||
|
INVALID_COMMAND_OPERATION_CODE = 0x20,
|
||||||
|
INVALID_LUN = 0x25,
|
||||||
|
MEDIUM_NOT_PRESENT = 0x3a
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// SASI/SCSI Bus
|
// SASI/SCSI Bus
|
||||||
|
Loading…
Reference in New Issue
Block a user