Commit 041ba2aa authored by Victor Kotlyar's avatar Victor Kotlyar
Browse files

added support for sense key and sense information for SCSI sense buffer.

parent 4bb07abb
...@@ -952,3 +952,26 @@ const castor::tape::SCSI::senseConstants::error_range_info castor::tape::SCSI::s ...@@ -952,3 +952,26 @@ const castor::tape::SCSI::senseConstants::error_range_info castor::tape::SCSI::s
{0x70, 0x00, 0xff, "Decompression exception short algorithm id of %02x"}, {0x70, 0x00, 0xff, "Decompression exception short algorithm id of %02x"},
{0, 0, 0, NULL} {0, 0, 0, NULL}
}; };
/* description of the sense key values */
const char * const castor::tape::SCSI::senseKeys::senseKeysText[] = {
"No Sense", /* 0: There is no sense information */
"Recovered Error", /* 1: The last command completed successfully
but used error correction */
"Not Ready", /* 2: The addressed target is not ready */
"Medium Error", /* 3: Data error detected on the medium */
"Hardware Error", /* 4: Controller or device failure */
"Illegal Request", /* 5: Error in request */
"Unit Attention", /* 6: Removable medium was changed, or
the target has been reset, or ... */
"Data Protect", /* 7: Access to the data is blocked */
"Blank Check", /* 8: Reached unexpected written or unwritten
region of the medium */
"Vendor Specific(9)",
"Copy Aborted", /* A: COPY or COMPARE was aborted */
"Aborted Command", /* B: The target aborted the command */
"Equal", /* C: A SEARCH DATA command found data equal */
"Volume Overflow", /* D: Medium full with still data to be written */
"Miscompare" /* E: Source data and data on the medium
do not agree */
};
...@@ -330,8 +330,31 @@ namespace SCSI { ...@@ -330,8 +330,31 @@ namespace SCSI {
uint8_t ascq_max; uint8_t ascq_max;
const char * text; const char * text;
}; };
static const struct error_range_info ascRangesStrings[]; static const struct error_range_info ascRangesStrings[];
}; };
class senseKeys {
public:
enum {
noSense = 0x0,
recoveredError = 0x1,
notReady = 0x2,
mediumError = 0x3,
hardwareError = 0x4,
illegalRequest = 0x5,
unitAttention = 0x6,
dataProtect = 0x7,
blankCheck = 0x8,
vendorSpecific = 0x9,
copyAborted = 0xA,
abortedCommand = 0xB,
equal = 0xC,
volumeOverflow = 0xD,
miscompare = 0xE,
lastWithText = 0xE
};
static const char * const senseKeysText[];
};
} // namespace SCSI } // namespace SCSI
} // namespace tape } // namespace tape
} // namespace castor } // namespace castor
...@@ -43,6 +43,13 @@ namespace SCSI { ...@@ -43,6 +43,13 @@ namespace SCSI {
<< "SCSI command failed with status " << "SCSI command failed with status "
<< SCSI::statusToString(status); << SCSI::statusToString(status);
if (SCSI::Status::CHECK_CONDITION == status) { if (SCSI::Status::CHECK_CONDITION == status) {
w << ": Sense Information";
try {
w << ": " << sense->getSenseKeyString();
} catch (Exception &ex) {
w << ": In addition, failed to get Sense Key string: "
<< ex.getMessage();
}
try { try {
w << ": " << sense->getACSString(); w << ": " << sense->getACSString();
} catch (Exception &ex) { } catch (Exception &ex) {
......
...@@ -861,7 +861,7 @@ namespace SCSI { ...@@ -861,7 +861,7 @@ namespace SCSI {
return responseCode == 0x70 || responseCode == 0x72; return responseCode == 0x70 || responseCode == 0x72;
} }
bool isDeffered() { bool isDeferred() {
return responseCode == 0x71 || responseCode == 0x73; return responseCode == 0x71 || responseCode == 0x73;
} }
...@@ -890,6 +890,36 @@ namespace SCSI { ...@@ -890,6 +890,36 @@ namespace SCSI {
throw castor::exception::Exception(err.str()); throw castor::exception::Exception(err.str());
} }
} }
/**
* Returns the Sense Key value.
*/
unsigned char getSenseKey() {
if (isFixedFormat()) {
return fixedFormat.senseKey;
} else if (isDescriptorFormat()) {
return descriptorFormat.senseKey;
} else {
std::stringstream err;
err << "In senseData_t::getSenseKey: no Sense Key with this response "
"code or response code not supported ("
<< std::hex << std::showbase << (int)responseCode << ")";
throw castor::exception::Exception(err.str());
}
}
/**
* Returns the Sense Key value as string.
*/
std::string getSenseKeyString() {
if ( castor::tape::SCSI::senseKeys::lastWithText >= getSenseKey()) {
return castor::tape::SCSI::senseKeys::senseKeysText[getSenseKey()];
} else {
std::stringstream err;
err << "In senseData_t::getSenseKeyString: no Sense Key with this "
"value ("<< std::hex << std::showbase
<< (int)getSenseKey() << ")";
throw castor::exception::Exception(err.str());
}
}
/** /**
* Function turning the ACS/ACSQ contents into a string. * Function turning the ACS/ACSQ contents into a string.
* This function is taken from the Linux kernel sources. * This function is taken from the Linux kernel sources.
...@@ -916,7 +946,7 @@ namespace SCSI { ...@@ -916,7 +946,7 @@ namespace SCSI {
snprintf(buff, sizeof (buff), "Unknown ASC/ASCQ:%02x/%02x", asc, ascq); snprintf(buff, sizeof (buff), "Unknown ASC/ASCQ:%02x/%02x", asc, ascq);
return std::string(buff); return std::string(buff);
} }
/* TODO: add support for sense key, and other bits. See section 4.5.6 /* TODO: add support for other bits. See section 4.5.6
* of SPC-4 for sense key = NO SENSE. */ * of SPC-4 for sense key = NO SENSE. */
}; };
...@@ -966,7 +996,7 @@ namespace SCSI { ...@@ -966,7 +996,7 @@ namespace SCSI {
} }
return hex.str(); return hex.str();
} }
} } // namespace Structures
} // namespace SCSI } // namespace SCSI
} // namespace tape } // namespace tape
} // namespace castor } // namespace castor
......
...@@ -518,45 +518,57 @@ namespace unitTests { ...@@ -518,45 +518,57 @@ namespace unitTests {
ASSERT_EQ(255U - 1U, sizeof(sense.fixedFormat)); ASSERT_EQ(255U - 1U, sizeof(sense.fixedFormat));
buff[0] = 0x70; buff[0] = 0x70;
buff[2] = 0xFE;
buff[12] = 0x12; buff[12] = 0x12;
buff[13] = 0x34; buff[13] = 0x34;
ASSERT_EQ(true, sense.isCurrent()); ASSERT_EQ(true, sense.isCurrent());
ASSERT_EQ(false, sense.isDeffered()); ASSERT_EQ(false, sense.isDeferred());
ASSERT_EQ(true, sense.isFixedFormat()); ASSERT_EQ(true, sense.isFixedFormat());
ASSERT_EQ(false, sense.isDescriptorFormat()); ASSERT_EQ(false, sense.isDescriptorFormat());
ASSERT_EQ(0x12, sense.getASC()); ASSERT_EQ(0x12, sense.getASC());
ASSERT_EQ(0x34, sense.getASCQ()); ASSERT_EQ(0x34, sense.getASCQ());
ASSERT_EQ(0xE, sense.getSenseKey());
ASSERT_EQ("Miscompare", sense.getSenseKeyString());
buff[0] = 0x71; buff[0] = 0x71;
buff[2] = 0xFA;
buff[12] = 0x12; buff[12] = 0x12;
buff[13] = 0x34; buff[13] = 0x34;
ASSERT_EQ(false, sense.isCurrent()); ASSERT_EQ(false, sense.isCurrent());
ASSERT_EQ(true, sense.isDeffered()); ASSERT_EQ(true, sense.isDeferred());
ASSERT_EQ(true, sense.isFixedFormat()); ASSERT_EQ(true, sense.isFixedFormat());
ASSERT_EQ(false, sense.isDescriptorFormat()); ASSERT_EQ(false, sense.isDescriptorFormat());
ASSERT_EQ(0x12, sense.getASC()); ASSERT_EQ(0x12, sense.getASC());
ASSERT_EQ(0x34, sense.getASCQ()); ASSERT_EQ(0x34, sense.getASCQ());
ASSERT_EQ(0xA, sense.getSenseKey());
ASSERT_EQ("Copy Aborted", sense.getSenseKeyString());
buff[0] = 0x72; buff[0] = 0x72;
buff[1] = 0xFB;
buff[2] = 0x56; buff[2] = 0x56;
buff[3] = 0x78; buff[3] = 0x78;
ASSERT_EQ(true, sense.isCurrent()); ASSERT_EQ(true, sense.isCurrent());
ASSERT_EQ(false, sense.isDeffered()); ASSERT_EQ(false, sense.isDeferred());
ASSERT_EQ(false, sense.isFixedFormat()); ASSERT_EQ(false, sense.isFixedFormat());
ASSERT_EQ(true, sense.isDescriptorFormat()); ASSERT_EQ(true, sense.isDescriptorFormat());
ASSERT_EQ(0x56, sense.getASC()); ASSERT_EQ(0x56, sense.getASC());
ASSERT_EQ(0x78, sense.getASCQ()); ASSERT_EQ(0x78, sense.getASCQ());
ASSERT_EQ(0xB, sense.getSenseKey());
ASSERT_EQ("Aborted Command", sense.getSenseKeyString());
buff[0] = 0x73; buff[0] = 0x73;
buff[1] = 0xFC;
buff[2] = 0x0b; buff[2] = 0x0b;
buff[3] = 0x08; buff[3] = 0x08;
ASSERT_EQ(false, sense.isCurrent()); ASSERT_EQ(false, sense.isCurrent());
ASSERT_EQ(true, sense.isDeffered()); ASSERT_EQ(true, sense.isDeferred());
ASSERT_EQ(false, sense.isFixedFormat()); ASSERT_EQ(false, sense.isFixedFormat());
ASSERT_EQ(true, sense.isDescriptorFormat()); ASSERT_EQ(true, sense.isDescriptorFormat());
ASSERT_EQ(0x0b, sense.getASC()); ASSERT_EQ(0x0b, sense.getASC());
ASSERT_EQ(0x08, sense.getASCQ()); ASSERT_EQ(0x08, sense.getASCQ());
ASSERT_EQ(0xC, sense.getSenseKey());
ASSERT_EQ("Warning - power loss expected", sense.getACSString()); ASSERT_EQ("Warning - power loss expected", sense.getACSString());
ASSERT_EQ("Equal", sense.getSenseKeyString());
buff[2] = 0x40; buff[2] = 0x40;
buff[3] = 0xab; buff[3] = 0xab;
...@@ -566,6 +578,9 @@ namespace unitTests { ...@@ -566,6 +578,9 @@ namespace unitTests {
buff[3] = 0x1F; buff[3] = 0x1F;
ASSERT_EQ("Unknown ASC/ASCQ:00/1f", sense.getACSString()); ASSERT_EQ("Unknown ASC/ASCQ:00/1f", sense.getACSString());
buff[1] = 0xF;
ASSERT_THROW(sense.getSenseKeyString(), castor::exception::Exception);
buff[0] = 0x74; buff[0] = 0x74;
ASSERT_THROW(sense.getASC(), castor::exception::Exception); ASSERT_THROW(sense.getASC(), castor::exception::Exception);
...@@ -576,6 +591,20 @@ namespace unitTests { ...@@ -576,6 +591,20 @@ namespace unitTests {
std::string what(ex.getMessageValue()); std::string what(ex.getMessageValue());
ASSERT_NE(std::string::npos, what.find("response code not supported (0x74)")); ASSERT_NE(std::string::npos, what.find("response code not supported (0x74)"));
} }
buff[1] = 0xA;
ASSERT_THROW(sense.getSenseKey(), castor::exception::Exception);
ASSERT_THROW(sense.getSenseKeyString(), castor::exception::Exception);
try { sense.getSenseKey(); ASSERT_TRUE(false); }
catch (castor::exception::Exception & ex) {
std::string what(ex.getMessageValue());
ASSERT_NE(std::string::npos, what.find("response code not supported (0x74)"));
}
try { sense.getSenseKeyString(); ASSERT_TRUE(false); }
catch (castor::exception::Exception & ex) {
std::string what(ex.getMessageValue());
ASSERT_NE(std::string::npos, what.find("response code not supported (0x74)"));
}
} }
TEST(castor_tape_SCSI_Structures, toU16) { TEST(castor_tape_SCSI_Structures, toU16) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment