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

0011-Add-unittest-for-SCSI-commands-for-working-with-Logi.patch

parent fee555fd
......@@ -1103,8 +1103,20 @@ const char * const castor::tape::SCSI::senseKeys::senseKeysText[] = {
do not agree */
};
/* names for the logical block protection methods */
const char * const castor::tape::SCSI::LBPMethods::LBPMethodsName[] = {
"Reed-Solomon",
"CRC32C"
};
//------------------------------------------------------------------------------
// LBPMethodToString
//------------------------------------------------------------------------------
std::string castor::tape::SCSI::LBPMethodToString(const unsigned char LBPMethod)
{
switch (LBPMethod) {
case LBPMethods::Disabled:
return "Disabled";
case LBPMethods::ReedSolomon:
return "Reed-Solomon";
case LBPMethods::CRC32C:
return "CRC32C";
default:
return "Unknown";
}
}
\ No newline at end of file
......@@ -391,15 +391,27 @@ namespace SCSI {
class LBPMethods {
public:
enum {
Disabled = 0x00, // do not use logical block protection
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
ReedSolomonLegth = 4, // Reed-Solomon CRC length in bytes
CRC32CLength = 4 // CRC32C length in bytes
};
static const char * const LBPMethodsName[];
};
};
/**
* Turn a LBP method code into a string
* @param LBPmethod The integer presentation of Logical Block Protection method
* @return The string presentation for LBP method or Unknown if method
* unknown.
*/
std::string LBPMethodToString(const unsigned char LBPMethod);
/**
* Addition for the mode page Length for the Control Data Protection Mode Page
*/
const unsigned char controlDataProtectionModePageLengthAddition = 4;
} // namespace SCSI
} // namespace tape
} // namespace castor
......@@ -474,7 +474,38 @@ namespace unitTests {
buff[26] |= 0xEF;
ASSERT_EQ(0xEFU, devConfig.modePage.selectDataComprAlgorithm);
}
TEST(castor_tape_SCSI_Structures, modeSenseControlDataProtection_t) {
castor::tape::SCSI::Structures::modeSenseControlDataProtection_t dataProt;
unsigned char *buff = (unsigned char *)&dataProt;
/*
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(44U, sizeof(dataProt));
ASSERT_EQ(4U, sizeof(dataProt.header));
ASSERT_EQ(8U, sizeof(dataProt.blockDescriptor));
ASSERT_EQ(32U, sizeof(dataProt.modePage));
/* We will only check used by us parameters */
ASSERT_EQ(0U, dataProt.header.modeDataLength);
buff[0] |= 0xAC;
ASSERT_EQ(0xACU, dataProt.header.modeDataLength);
for(int i=1;i<=15;i++) buff[i] = 0xFF; // fill the space
ASSERT_EQ(0U, dataProt.modePage.LBPMethod );
buff[16] |= 0xEF;
ASSERT_EQ(0xEFU, dataProt.modePage.LBPMethod );
ASSERT_EQ(0U, dataProt.modePage.LBPInformationLength );
buff[17] |= 0xDF;
ASSERT_EQ(0x1FU, dataProt.modePage.LBPInformationLength );
ASSERT_EQ(0U, dataProt.modePage.LBP_W );
buff[18] |= 0x8F;
ASSERT_EQ(0x1U, dataProt.modePage.LBP_W );
ASSERT_EQ(0U, dataProt.modePage.LBP_R );
buff[18] |= 0x4F;
ASSERT_EQ(0x1U, dataProt.modePage.LBP_R );
}
TEST(castor_tape_SCSI_Structures, tapeAlertLogPage_t_and_parameters) {
castor::tape::SCSI::Structures::tapeAlertLogPage_t<12> tal;
unsigned char * buff = (unsigned char *) & tal;
......
......@@ -116,7 +116,7 @@ drive::deviceInfo drive::DriveGeneric::getDeviceInfo() {
devInfo.productRevisionLevel = SCSI::Structures::toString(inquiryData.prodRevLvl);
devInfo.vendor = SCSI::Structures::toString(inquiryData.T10Vendor);
devInfo.serialNumber = getSerialNumber();
devInfo.isPIsupported = inquiryData.protect;
return devInfo;
}
......@@ -389,22 +389,23 @@ void drive::DriveGeneric::setLogicalBlockProtection(
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);
cdb.PF = 1; // means nothing for IBM, LTO, T10000
cdb.paramListLength = sizeof (controlDataProtection.header) +
sizeof (controlDataProtection.blockDescriptor) +
SCSI::controlDataProtectionModePageLengthAddition +
SCSI::Structures::toU16(controlDataProtection.modePage.pageLength);
if (cdb.paramListLength > sizeof(controlDataProtection)) {
// should never happen
throw castor::exception::Exception(
std::string("cdb.paramListLength greater then size "
"of controlDataProtection in setLogicalBlockProtection"));
}
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;
}
controlDataProtection.modePage.LBP_W = enableLBPforWrite;
controlDataProtection.modePage.LBP_R = enableLBPforRead;
sgh.setCDB(&cdb);
sgh.setDataBuffer(&controlDataProtection);
......@@ -426,7 +427,7 @@ void drive::DriveGeneric::setLogicalBlockProtection(
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableCRC32CLogicalBlockProtectionReadOnly() {
setLogicalBlockProtection(SCSI::LBPMethods::CRC32C,
SCSI::LBPMethods::CRC32CLenght,true,false);
SCSI::LBPMethods::CRC32CLength,true,false);
}
//------------------------------------------------------------------------------
......@@ -434,7 +435,23 @@ void drive::DriveGeneric::enableCRC32CLogicalBlockProtectionReadOnly() {
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableCRC32CLogicalBlockProtectionReadWrite() {
setLogicalBlockProtection(SCSI::LBPMethods::CRC32C,
SCSI::LBPMethods::CRC32CLenght,true,true);
SCSI::LBPMethods::CRC32CLength,true,true);
}
//------------------------------------------------------------------------------
// enableReedSolomonLogicalBlockProtectionReadOnly
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableReedSolomonLogicalBlockProtectionReadOnly() {
setLogicalBlockProtection(SCSI::LBPMethods::ReedSolomon,
SCSI::LBPMethods::ReedSolomonLegth,true,false);
}
//------------------------------------------------------------------------------
// enableReedSolomonLogicalBlockProtectionReadWrite
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableReedSolomonLogicalBlockProtectionReadWrite() {
setLogicalBlockProtection(SCSI::LBPMethods::ReedSolomon,
SCSI::LBPMethods::ReedSolomonLegth,true,true);
}
//------------------------------------------------------------------------------
......@@ -443,7 +460,44 @@ void drive::DriveGeneric::enableCRC32CLogicalBlockProtectionReadWrite() {
void drive::DriveGeneric::disableLogicalBlockProtection() {
setLogicalBlockProtection(0,0,false,false);
}
//------------------------------------------------------------------------------
// getLBPInfo
//------------------------------------------------------------------------------
drive::LBPInfo drive::DriveGeneric::getLBPInfo() {
SCSI::Structures::modeSenseControlDataProtection_t controlDataProtection;
drive::LBPInfo LBPdata;
/* 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 getLBPInfo: ") +
SCSI::statusToString(sgh.status));
LBPdata.method = controlDataProtection.modePage.LBPMethod;
LBPdata.methodLength = controlDataProtection.modePage.LBPInformationLength;
LBPdata.enableLBPforRead = (1 == controlDataProtection.modePage.LBP_R);
LBPdata.enableLBPforWrite = (1 == controlDataProtection.modePage.LBP_W);
return LBPdata;
}
/**
* Function that checks if a tape is blank (contains no records)
* @return true if tape is blank, false otherwise
......
......@@ -352,20 +352,45 @@ namespace drive {
void SCSI_inquiry();
/**
* TOFILL
* Enable Logical Block Protection on the drive for reading only.
* Set method CRC32C to be used.
*/
virtual void enableCRC32CLogicalBlockProtectionReadOnly();
/**
* TOFILL
* Enable Logical Block Protection on the drive for reading and writing.
* Set method CRC32C to be used.
*/
virtual void enableCRC32CLogicalBlockProtectionReadWrite();
/**
* Enable Logical Block Protection on the drive for reading only.
* Set method Reed-Solomon to be used.
*/
virtual void enableReedSolomonLogicalBlockProtectionReadOnly();
/**
* TOFILL
* Enable Logical Block Protection on the drive for reading and writing.
* Set method Reed-Solomon to be used.
*/
virtual void enableReedSolomonLogicalBlockProtectionReadWrite();
/**
* Disable Logical Block Protection on the drive.
*/
virtual void disableLogicalBlockProtection();
/**
* Return Logical Block Protection Information of the drive.
*
* We use MODE SENSE Control Data Protection (0Ah) mode page as
* described in SSC-5.
*
* @return LBPInfo class. This contains the LBP method to be used for
* Logical Block Protection, the method length, the status if LBP enabled
* for reading and the status if LBP enabled for writing.
*/
virtual LBPInfo getLBPInfo();
protected:
SCSI::DeviceInfo m_SCSIInfo;
int m_tapeFD;
......@@ -384,7 +409,15 @@ namespace drive {
void waitTestUnitReady(const uint32_t timeoutSecond);
/**
* TOFILL
* Set the tape Logical Block Protection.
* We use MODE SENSE/SELECT Control Data Protection (0Ah) mode page as
* described in SSC-5.
*
* @param method The LBP method to be set.
* @param methodLength The method length in bytes.
* @param enableLPBforRead Should be LBP set for reading.
* @param enableLBBforWrite Should be LBP set for writing.
*
*/
virtual void setLogicalBlockProtection(const unsigned char method,
unsigned char methodLength, const bool enableLPBforRead,
......
......@@ -75,6 +75,7 @@ namespace drive {
std::string product;
std::string productRevisionLevel;
std::string serialNumber;
bool isPIsupported;
};
/**
......@@ -90,6 +91,17 @@ namespace drive {
uint32_t dirtyBytesCount;
};
/**
* Logical block protection nformation, returned by getLBPInfo()
*/
class LBPInfo {
public:
unsigned char method;
unsigned char methodLength;
bool enableLBPforRead;
bool enableLBPforWrite;
};
/**
*
*/
......@@ -160,6 +172,15 @@ namespace drive {
virtual std::vector<std::string> getTapeAlertsCompact (const std::vector<uint16_t>&) = 0;
virtual void setDensityAndCompression(bool compression = true,
unsigned char densityCode = 0) = 0;
virtual void enableCRC32CLogicalBlockProtectionReadOnly() = 0;
virtual void enableCRC32CLogicalBlockProtectionReadWrite() = 0;
virtual void enableReedSolomonLogicalBlockProtectionReadOnly() = 0;
virtual void enableReedSolomonLogicalBlockProtectionReadWrite() = 0;
virtual void disableLogicalBlockProtection() = 0;
virtual drive::LBPInfo getLBPInfo() = 0;
virtual void setLogicalBlockProtection(const unsigned char method,
unsigned char methodLength, const bool enableLPBforRead,
const bool enableLBBforWrite) = 0;
virtual driveStatus getDriveStatus() = 0;
virtual tapeError getTapeError() = 0;
virtual void setSTBufferWrite(bool bufWrite) = 0;
......
......@@ -235,13 +235,15 @@ TEST(castor_tape_drive_Drive, getDeviceInfo) {
castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
castor::tape::tapeserver::drive::deviceInfo devInfo;
EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(2);
devInfo.isPIsupported = false;
EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(2);
devInfo = drive->getDeviceInfo();
ASSERT_EQ("STK ",devInfo.vendor);
ASSERT_EQ("T10000B ",devInfo.product);
ASSERT_EQ("0104",devInfo.productRevisionLevel );
ASSERT_EQ("XYZZY_A2 ",devInfo.serialNumber );
ASSERT_TRUE(devInfo.isPIsupported);
}
}
}
......@@ -343,6 +345,45 @@ TEST(castor_tape_drive_Drive, getCompressionAndClearCompressionStats) {
}
}
TEST(castor_tape_drive_Drive, getLBPInfo) {
/* Prepare the test harness */
castor::tape::System::mockWrapper sysWrapper;
sysWrapper.fake.setupSLC5();
sysWrapper.delegateToFake();
/* We expect the following calls: */
EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
EXPECT_CALL(sysWrapper, close(_)).Times(21);
EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
/* Test: detect devices, then open the device files */
castor::tape::SCSI::DeviceVector dl(sysWrapper);
for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
i != dl.end(); i++) {
if (castor::tape::SCSI::Types::tape == i->type) {
std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive (
castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
castor::tape::tapeserver::drive::LBPInfo LBPdata;
EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(1);
LBPdata = drive->getLBPInfo();
ASSERT_EQ(castor::tape::SCSI::LBPMethods::CRC32C,LBPdata.method);
ASSERT_EQ(castor::tape::SCSI::LBPMethods::CRC32CLength,LBPdata.methodLength);
ASSERT_TRUE(LBPdata.enableLBPforRead);
ASSERT_TRUE(LBPdata.enableLBPforWrite);
}
}
}
TEST(castor_tape_drive_Drive, getTapeAlerts) {
/**
......
......@@ -63,6 +63,7 @@ castor::tape::tapeserver::drive::deviceInfo castor::tape::tapeserver::drive::Fak
devInfo.productRevisionLevel = "0.1";
devInfo.vendor = "ACME Ind";
devInfo.serialNumber = "123456";
devInfo.isPIsupported = true;
return devInfo;
}
std::string castor::tape::tapeserver::drive::FakeDrive::getSerialNumber() {
......@@ -105,6 +106,29 @@ void castor::tape::tapeserver::drive::FakeDrive::setDensityAndCompression(bool c
castor::tape::tapeserver::drive::driveStatus castor::tape::tapeserver::drive::FakeDrive::getDriveStatus() {
throw castor::exception::Exception("FakeDrive::getDriveStatus Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::enableCRC32CLogicalBlockProtectionReadOnly() {
throw castor::exception::Exception("FakeDrive::enableCRC32CLogicalBlockProtectionReadOnly Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::enableCRC32CLogicalBlockProtectionReadWrite() {
throw castor::exception::Exception("FakeDrive::enableCRC32CLogicalBlockProtectionReadWrite Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::enableReedSolomonLogicalBlockProtectionReadOnly() {
throw castor::exception::Exception("FakeDrive::enableReedSolomonLogicalBlockProtectionReadOnly Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::enableReedSolomonLogicalBlockProtectionReadWrite() {
throw castor::exception::Exception("FakeDrive::enableCReedSolomonLogicalBlockProtectionReadWrite Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::disableLogicalBlockProtection() {
throw castor::exception::Exception("FakeDrive::disableLogicalBlockProtection Not implemented");
}
castor::tape::tapeserver::drive::LBPInfo castor::tape::tapeserver::drive::FakeDrive::getLBPInfo() {
throw castor::exception::Exception("FakeDrive::dgetLBPInfo Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::setLogicalBlockProtection(const unsigned char method,
unsigned char methodLength, const bool enableLPBforRead,
const bool enableLBBforWrite) {
throw castor::exception::Exception("FakeDrive::setLogicalBlockProtection Not implemented");
}
castor::tape::tapeserver::drive::tapeError castor::tape::tapeserver::drive::FakeDrive::getTapeError() {
throw castor::exception::Exception("FakeDrive::getTapeError Not implemented");
}
......
......@@ -68,6 +68,15 @@ namespace drive {
virtual std::vector<std::string> getTapeAlertsCompact(const std::vector<uint16_t>&) ;
virtual void setDensityAndCompression(bool compression = true,
unsigned char densityCode = 0) ;
virtual void enableCRC32CLogicalBlockProtectionReadOnly() ;
virtual void enableCRC32CLogicalBlockProtectionReadWrite() ;
virtual void enableReedSolomonLogicalBlockProtectionReadOnly() ;
virtual void enableReedSolomonLogicalBlockProtectionReadWrite() ;
virtual void disableLogicalBlockProtection() ;
virtual drive::LBPInfo getLBPInfo();
virtual void setLogicalBlockProtection(const unsigned char method,
unsigned char methodLength, const bool enableLPBforRead,
const bool enableLBBforWrite);
virtual driveStatus getDriveStatus() ;
virtual tapeError getTapeError() ;
virtual void setSTBufferWrite(bool bufWrite) ;
......
......@@ -105,6 +105,10 @@ System::stDeviceFile::stDeviceFile()
blockID = 0xFFFFFFFF; // Logical Object ID - position on tape
clearCompressionStats = false;
m_LBPInfoMethod = SCSI::LBPMethods::CRC32C;
m_LBPInfoLength = SCSI::LBPMethods::CRC32CLength;
m_LBPInfo_R = 1;
m_LBPInfo_W = 1;
}
int System::stDeviceFile::ioctl(unsigned long int request, struct mtop * mt_cmd)
......@@ -417,6 +421,20 @@ int System::stDeviceFile::ioctlModSense6(sg_io_hdr_t * sgio_h) {
errno = EINVAL;
return -1;
}
SCSI::Structures::modeSense6CDB_t & cdb =
*(SCSI::Structures::modeSense6CDB_t *) sgio_h->cmdp;
switch (cdb.pageCode) {
case SCSI::modeSensePages::deviceConfiguration:
return modeSenseDeviceConfiguration(sgio_h);
case SCSI::modeSensePages::controlDataProtection:
return modeSenseControlDataProtection(sgio_h);
}
errno = EINVAL;
return -1;
}
int System::stDeviceFile::modeSenseDeviceConfiguration(sg_io_hdr_t * sgio_h) {
SCSI::Structures::modeSense6CDB_t & cdb =
*(SCSI::Structures::modeSense6CDB_t *) sgio_h->cmdp;
if (SCSI::modeSensePages::deviceConfiguration != cdb.pageCode) {
......@@ -436,6 +454,38 @@ int System::stDeviceFile::ioctlModSense6(sg_io_hdr_t * sgio_h) {
return 0;
}
int System::stDeviceFile::modeSenseControlDataProtection(sg_io_hdr_t * sgio_h) {
SCSI::Structures::modeSense6CDB_t & cdb =
*(SCSI::Structures::modeSense6CDB_t *) sgio_h->cmdp;
if (SCSI::modeSensePages::controlDataProtection != cdb.pageCode) {
errno = EINVAL;
return -1;
}
if (cdb.subPageCode != SCSI::modePageControlDataProtection::subpageCode) {
errno = EINVAL;
return -1;
}
SCSI::Structures::modeSenseControlDataProtection_t & controlDataProtection =
*(SCSI::Structures::modeSenseControlDataProtection_t *) sgio_h->dxferp;
if (sizeof (controlDataProtection) > sgio_h->dxfer_len) {
errno = EINVAL;
return -1;
}
/* fill the replay with random data */
srandom(SCSI::Commands::MODE_SENSE_6);
memset(sgio_h->dxferp, random(), sizeof (controlDataProtection));
controlDataProtection.modePage.LBPMethod = m_LBPInfoMethod;
controlDataProtection.modePage.LBPInformationLength = m_LBPInfoLength;
controlDataProtection.modePage.LBP_R = m_LBPInfo_R;
controlDataProtection.modePage.LBP_W = m_LBPInfo_W;
return 0;
}
int System::stDeviceFile::ioctlModSelect6(sg_io_hdr_t * sgio_h) {
if (SG_DXFER_TO_DEV != sgio_h->dxfer_direction) {
errno = EINVAL;
......@@ -494,6 +544,7 @@ int System::stDeviceFile::ioctlInquiry(sg_io_hdr_t * sgio_h) {
memcpy(inqData.prodRevLvl, prodRevLvl, sizeof (inqData.prodRevLvl));
const char *T10Vendor = "STK ";
memcpy(inqData.T10Vendor, T10Vendor, sizeof (inqData.T10Vendor));
inqData.protect = 1;
} else if (1 == cdb.EVPD && SCSI::inquiryVPDPages::unitSerialNumber == cdb.pageCode) {
/* the unit serial number VPD page is returned*/
SCSI::Structures::inquiryUnitSerialNumberData_t & inqSerialData =
......
......@@ -78,6 +78,10 @@ namespace System {
struct mtop m_mtCmd;
uint32_t blockID;
bool clearCompressionStats;
unsigned char m_LBPInfoMethod;
unsigned char m_LBPInfoLength;
unsigned char m_LBPInfo_R;
unsigned char m_LBPInfo_W;
/**
* This function handles READ_POSITION CDB and prepares the replay.
*
......@@ -199,6 +203,33 @@ namespace System {
* -1 with appropriate errno if an error occurred.
*/
int logSenseTapeAlerts(sg_io_hdr_t * sgio_h);
/**
* This function only checks the corectness of the parameters in sg_io_hdr_t
* sturcture and returns random data.
*
* @param sgio_h The pointer to the sg_io_hdr_t structure with
* ioctl call data
* @return Returns 0 in success and
* -1 with appropriate errno if an error occurred.
*/
int modeSenseDeviceConfiguration(sg_io_hdr_t * sgio_h);
/**
* This function checks the corectness of the parameters in sg_io_hdr_t and
* returns filled filds:
* controlDataProtection.modePage.LBPMethod
* controlDataProtection.modePage.LBPInformationLength
* controlDataProtection.modePage.LBP_R
* controlDataProtection.modePage.LBP_W
* All other filds in SCSI replay are random.
*
* @param sgio_h The pointer to the sg_io_hdr_t structure with
* ioctl call data
* @return Returns 0 in success and
* -1 with appropriate errno if an error occurred.
*/
int modeSenseControlDataProtection(sg_io_hdr_t * sgio_h);
};
} // namespace System
} // namespace tape
......
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