Commit fee555fd authored by Julien Leduc's avatar Julien Leduc
Browse files

0012-Add-SCSI-structures-for-MODE-SENSE-SELECT-for-Contro.patch

parent d20995e8
......@@ -1102,3 +1102,9 @@ const char * const castor::tape::SCSI::senseKeys::senseKeysText[] = {
"Miscompare" /* E: Source data and data on the medium
do not agree */
};
/* names for the logical block protection methods */
const char * const castor::tape::SCSI::LBPMethods::LBPMethodsName[] = {
"Reed-Solomon",
"CRC32C"
};
......@@ -245,13 +245,27 @@ namespace SCSI {
};
};
/**
* Constants for used MODE SENSE/SELECT pages
*/
class modeSensePages {
public:
enum {
controlDataProtection = 0x0A,
deviceConfiguration = 0x10
};
};
/**
* The value for subpage code for the Control Data Protection MODE PAGE
*/
class modePageControlDataProtection {
public:
enum {
subpageCode = 0xF0
};
};
class inquiryVPDPages {
public:
enum {
......@@ -370,6 +384,22 @@ namespace SCSI {
};
static const char * const senseKeysText[];
};
/**
* Logical block protection methods
*/
class LBPMethods {
public:
enum {
ReedSolomon = 0x01, // Reed-Solomon CRC as specified in ECMA-319
CRC32C = 0x02 // CRC32C polynomial as specified for iSCSI
};
enum {
ReedSolomonLeght = 4, // Reed-Solomon CRC length in bytes
CRC32CLenght = 4 // CRC32C length in bytes
};
static const char * const LBPMethodsName[];
};
} // namespace SCSI
} // namespace tape
} // namespace castor
......@@ -697,6 +697,60 @@ namespace SCSI {
modePageDeviceConfiguration_t modePage;
};
/**
* MODE SENSE(6) or MODE SENSE(10) mode page 0Ah: Control Data Protection.
* as described in SSC-5.
*/
class modePageControlDataProtection_t {
public:
// byte 0
unsigned char pageCode :6; // Page code (0Ah)
unsigned char SPF :1; // SubPage Format (1b)
unsigned char PS :1; // Parameters Savable
// 0b required for MODE SELECT IBM,LTO
// 1b returned in MODE SENSE IBM, LTO
// 0b Not supported for T10000
// byte 1
unsigned char subpageCode; // SubPage code (F0h)
// bytes 2-3
unsigned char pageLength[2]; // Page length (n - 3) 1Ch for IBM,LTO
// byte 4
unsigned char LBPMethod; // LBP method
// byte 5
unsigned char LBPInformationLength : 6; // LBP information length
unsigned char : 2; // Reserved
// byte 6
unsigned char : 5; // Reserved
unsigned char RBDP : 1; // Recover Buffered Data Protected
unsigned char LBP_R : 1; // Logical blocks protected during read
unsigned char LBP_W : 1; // Logical blocks protected during write
// byte 7
unsigned char : 4; // Reserved
unsigned char T10PIexponent : 4; // T1000 only for T10 PI mode
// bytes 8-31
unsigned char reserved[24]; // Reserved. Added for IBM, LTO and do
// not used by T10000
};
/**
* MODE SENSE(6) structure for mode page 0Ah: Control Data Protection.
* as described in SSC-5.
*/
class modeSenseControlDataProtection_t {
public:
modeSenseControlDataProtection_t() { zeroStruct(this); }
modeParameterHeader6_t header;
modeParameterBlockDecriptor_t blockDescriptor;
modePageControlDataProtection_t modePage;
};
/**
* MODE SELECT(6) CDB as described in SPC-4.
*/
......
......@@ -351,6 +351,98 @@ void drive::DriveGeneric::setDensityAndCompression(bool compression,
}
}
//------------------------------------------------------------------------------
// setLogicalBlockProtection
//------------------------------------------------------------------------------
void drive::DriveGeneric::setLogicalBlockProtection(
const unsigned char method, const unsigned char methodLength,
const bool enableLBPforRead, const bool enableLBPforWrite) {
SCSI::Structures::modeSenseControlDataProtection_t controlDataProtection;
{
/* fetch Control Data Protection */
SCSI::Structures::modeSense6CDB_t cdb;
SCSI::Structures::senseData_t<255> senseBuff;
SCSI::Structures::LinuxSGIO_t sgh;
cdb.pageCode = SCSI::modeSensePages::controlDataProtection;
cdb.subPageCode = SCSI::modePageControlDataProtection::subpageCode;
cdb.allocationLength = sizeof (controlDataProtection);
sgh.setCDB(&cdb);
sgh.setDataBuffer(&controlDataProtection);
sgh.setSenseBuffer(&senseBuff);
sgh.dxfer_direction = SG_DXFER_FROM_DEV;
/* Manage both system error and SCSI errors. */
castor::exception::Errnum::throwOnMinusOne(
m_sysWrapper.ioctl(m_tapeFD, SG_IO, &sgh),
"Failed SG_IO ioctl" );
SCSI::ExceptionLauncher(sgh,
std::string("SCSI error fetching data in setLogicalBlockProtection: ") +
SCSI::statusToString(sgh.status));
}
{
/* Use the previously fetched page, modify fields and submit it */
SCSI::Structures::modeSelect6CDB_t cdb;
SCSI::Structures::senseData_t<255> senseBuff;
SCSI::Structures::LinuxSGIO_t sgh;
cdb.PF = 0; // required for IBM, LTO, not supported for T10000
cdb.paramListLength = sizeof (controlDataProtection);
controlDataProtection.header.modeDataLength = 0; // must be 0 for IBM, LTO
// ignored by T10000
controlDataProtection.modePage.LBPMethod = method;
controlDataProtection.modePage.LBPInformationLength = methodLength;
if (enableLBPforWrite) {
controlDataProtection.modePage.LBP_W = 1;
} else {
controlDataProtection.modePage.LBP_W = 0;
}
if (enableLBPforRead) {
controlDataProtection.modePage.LBP_R = 1;
} else {
controlDataProtection.modePage.LBP_R = 0;
}
sgh.setCDB(&cdb);
sgh.setDataBuffer(&controlDataProtection);
sgh.setSenseBuffer(&senseBuff);
sgh.dxfer_direction = SG_DXFER_TO_DEV;
/* Manage both system error and SCSI errors. */
castor::exception::Errnum::throwOnMinusOne(
m_sysWrapper.ioctl(m_tapeFD, SG_IO, &sgh),
"Failed SG_IO ioctl" );
SCSI::ExceptionLauncher(sgh,
std::string("SCSI error setting data in setDataProtection : ") +
SCSI::statusToString(sgh.status));
}
}
//------------------------------------------------------------------------------
// enableCRC32CLogicalBlockProtectionReadOnly
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableCRC32CLogicalBlockProtectionReadOnly() {
setLogicalBlockProtection(SCSI::LBPMethods::CRC32C,
SCSI::LBPMethods::CRC32CLenght,true,false);
}
//------------------------------------------------------------------------------
// enableCRC32CLogicalBlockProtectionReadWrite
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableCRC32CLogicalBlockProtectionReadWrite() {
setLogicalBlockProtection(SCSI::LBPMethods::CRC32C,
SCSI::LBPMethods::CRC32CLenght,true,true);
}
//------------------------------------------------------------------------------
// disableLogicalBlockProtection
//------------------------------------------------------------------------------
void drive::DriveGeneric::disableLogicalBlockProtection() {
setLogicalBlockProtection(0,0,false,false);
}
/**
* Function that checks if a tape is blank (contains no records)
......
......@@ -351,6 +351,21 @@ namespace drive {
void SCSI_inquiry();
/**
* TOFILL
*/
virtual void enableCRC32CLogicalBlockProtectionReadOnly();
/**
* TOFILL
*/
virtual void enableCRC32CLogicalBlockProtectionReadWrite();
/**
* TOFILL
*/
virtual void disableLogicalBlockProtection();
protected:
SCSI::DeviceInfo m_SCSIInfo;
int m_tapeFD;
......@@ -367,6 +382,13 @@ namespace drive {
* Time based loop around "test unit ready" command
*/
void waitTestUnitReady(const uint32_t timeoutSecond);
/**
* TOFILL
*/
virtual void setLogicalBlockProtection(const unsigned char method,
unsigned char methodLength, const bool enableLPBforRead,
const bool enableLBBforWrite);
};
class DriveT10000 : public DriveGeneric {
......
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