Commit b6ec11f7 authored by Victor Kotlyar's avatar Victor Kotlyar
Browse files

added implementation for getPositionInfo

We use READ POSTION command with data replay in SHORT FORM.

Tested with mhvtl.
parent ecf6d814
......@@ -63,6 +63,7 @@ namespace Tape {
* Returned by getPositionInfo()
*/
class positionInfo {
public:
uint32_t currentPosition;
uint32_t oldestDirtyObject;
uint32_t dirtyObjectsCount;
......@@ -193,7 +194,39 @@ namespace Tape {
* @return positionInfo class. This contains the logical position, plus information
* on the dirty data still in the write buffer.
*/
virtual positionInfo getPositionInfo () throw (Exception) { throw Exception("Not implemented"); }
virtual positionInfo getPositionInfo () throw (Exception) {
SCSI::Structures::readPositionCDB_t cdb;
SCSI::Structures::readPositionDataShortForm_t positionData;
SCSI::Structures::senseData_t<255> senseBuff;
SCSI::Structures::LinuxSGIO_t sgh;
positionInfo posInfo;
sgh.setCDB(&cdb);
sgh.setDataBuffer(&positionData);
sgh.setSenseBuffer(&senseBuff);
sgh.dxfer_direction = SG_DXFER_FROM_DEV;
/* Manage both system error and SCSI errors. */
if (-1 == m_sysWrapper.ioctl(m_tapeFD, SG_IO, &sgh))
throw Tape::Exceptions::Errnum("Failed SG_IO ioctl");
if (SCSI::Status::GOOD != sgh.status)
throw Tape::Exception(std::string("SCSI error in getPositionInfo: ") +
SCSI::statusToString(sgh.status));
if ( 0 == positionData.PERR ) { // Location fields are valid
posInfo.currentPosition = SCSI::Structures::toU32(positionData.firstBlockLocation);
posInfo.oldestDirtyObject = SCSI::Structures::toU32(positionData.lastBlockLocation);
posInfo.dirtyObjectsCount = SCSI::Structures::toU32(positionData.blocksInBuffer);
posInfo.dirtyBytesCount = SCSI::Structures::toU32(positionData.bytesInBuffer);
} else {
posInfo.currentPosition = 0;
posInfo.oldestDirtyObject = 0;
posInfo.dirtyObjectsCount = 0;
posInfo.dirtyBytesCount = 0;
}
return posInfo;
}
/**
* Get tape alert information from the drive. There is a quite long list of possible tape alerts.
......
......@@ -106,6 +106,21 @@ namespace SCSI {
return ntohl (*((uint32_t *) t));
}
/**
* Helper function to deal with endianness.
* for 3 bytes! fields in SCSI replies
* @param t byte array in SCSI order representing a 32 bits number
* @return
*/
inline uint32_t toU32(const unsigned char(& t)[3])
{
unsigned char tmp[4];
tmp[0]=0;tmp[1]=t[0];tmp[2]=t[1]; tmp[3]=t[2];
/* Like network, SCSI is BigEndian */
return ntohl (*((uint32_t *) tmp));
}
/**
* Helper function to deal with endianness.
* for signed values
......@@ -241,6 +256,71 @@ namespace SCSI {
unsigned char control; // Control byte
};
/*
* READ POSITION CDB as described in SSC-3.
*/
class readPositionCDB_t {
public:
readPositionCDB_t() {
zeroStruct(this);
opCode = SCSI::Commands::READ_POSITION;
}
// byte 0
unsigned char opCode; // OPERATION CODE (34h)
// byte 1
// *note* for T10000 we have BT:1, LONG:1, TCLP:1, Reserved:5
unsigned char serviceAction: 5; // Service action to choice FORM
unsigned char : 3; // Reserved
// bytes 2-6
unsigned char reserved[5]; // Reserved
// bytes 7-8
unsigned char allocationLenght[2] ; // used for EXTENDENT FORM
// byte 9
unsigned char control; // Control byte
};
/*
* READ POSITION data format, short form as described in SSC-3.
*/
class readPositionDataShortForm_t {
public:
readPositionDataShortForm_t() { zeroStruct(this); }
// byte 0
unsigned char BPEW :1; // Beyond Programmable Early Warning
unsigned char PERR :1; // Position ERroR
unsigned char LOLU :1; // Logical Object Location Unknown or Block Position Unknown(BPU) for T10000
unsigned char :1; // Reserved
unsigned char BYCU :1; // BYte Count Unknown
unsigned char LOCU :1; // Logical Object Count Unknown or Block Count Unknown(BCU) for T10000
unsigned char EOP :1; // End Of Partition
unsigned char BOP :1; // Beginning of Partition
// byte 1
unsigned char partitionNumber; // Service action to choice FORM
// bytes 2-3
unsigned char reserved[2]; // Reserved
// bytes 4-7
unsigned char firstBlockLocation[4]; // First Logical object location in SSC3,IBM,LTO
// bytes 8-11
unsigned char lastBlockLocation[4]; // Last Logical object location in SSC3,IBM,LTO
// byte 12
unsigned char :8; // Reserved
// bytes 13-15
unsigned char blocksInBuffer[3]; // Number of logical objects in object buffer
// bytes 16-19
unsigned char bytesInBuffer[4]; // Number if bytes in object buffer
};
/*
* LOG SELECT CDB as described in SPC-4.
*/
......
......@@ -258,6 +258,87 @@ namespace UnitTests {
ASSERT_EQ(0xBC, locate10CDB.control);
}
TEST(SCSI_Structures, readPositionCDB_t) {
SCSI::Structures::readPositionCDB_t readPositionCDB;
unsigned char *buff = (unsigned char *)&readPositionCDB;
/*
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(10, sizeof(readPositionCDB));
/* Check proper initialization an location of struct members match
the bit/byte locations defined in SPC-4 */
ASSERT_EQ(SCSI::Commands::READ_POSITION, readPositionCDB.opCode);
buff[0] = 0xAB;
ASSERT_EQ(0xAB, readPositionCDB.opCode);
ASSERT_EQ(0, readPositionCDB.serviceAction);
buff[1] |= (0x15 & 0xFF) << 0;
ASSERT_EQ(0x15, readPositionCDB.serviceAction);
buff[2] |= 0xFF; buff[3] = 0xFF; buff[4] = 0xFF; buff[5] = 0xFF; buff[6] = 0xFF;
ASSERT_EQ(0, SCSI::Structures::toU16(readPositionCDB.allocationLenght));
buff[7] |= 0x0A;buff[8] |= 0xBC;
ASSERT_EQ(0x0ABC, SCSI::Structures::toU16(readPositionCDB.allocationLenght));
ASSERT_EQ(0, readPositionCDB.control);
buff[9] |= 0xBC;
ASSERT_EQ(0xBC, readPositionCDB.control);
}
TEST(SCSI_Structures, readPositionDataShortForm_t) {
SCSI::Structures::readPositionDataShortForm_t readPositionData;
unsigned char *buff = (unsigned char *)&readPositionData;
ASSERT_EQ(20, sizeof(readPositionData));
ASSERT_EQ(0, readPositionData.BPEW);
buff[0] |= (0x1 & 0xFF) << 0;
ASSERT_EQ(0x1, readPositionData.BPEW);
ASSERT_EQ(0, readPositionData.PERR);
buff[0] |= (0x2 & 0xFF) << 0;
ASSERT_EQ(0x1, readPositionData.PERR);
ASSERT_EQ(0, readPositionData.LOLU);
buff[0] |= (0x4 & 0xFF) << 0;
ASSERT_EQ(0x1, readPositionData.LOLU);
ASSERT_EQ(0, readPositionData.BYCU);
buff[0] |= (0x10 & 0xFF) << 0;
ASSERT_EQ(0x1, readPositionData.BYCU);
ASSERT_EQ(0, readPositionData.LOCU);
buff[0] |= (0x20 & 0xFF) << 0;
ASSERT_EQ(0x1, readPositionData.LOCU);
ASSERT_EQ(0, readPositionData.EOP);
buff[0] |= (0x40 & 0xFF) << 0;
ASSERT_EQ(0x1, readPositionData.EOP);
ASSERT_EQ(0, readPositionData.BOP);
buff[0] |= (0x80 & 0xFF) << 0;
ASSERT_EQ(0x1, readPositionData.BOP);
ASSERT_EQ(0, readPositionData.partitionNumber);
buff[1] |= 0xBC;
ASSERT_EQ(0xBC, readPositionData.partitionNumber);
buff[2] |= 0xFF; buff[3] = 0xFF;
ASSERT_EQ(0, SCSI::Structures::toU32(readPositionData.firstBlockLocation));
buff[4] |= 0x0A;buff[5] |= 0xBC;buff[6] |= 0xDE;buff[7] |= 0xF0;
ASSERT_EQ(0x0ABCDEF0, SCSI::Structures::toU32(readPositionData.firstBlockLocation));
ASSERT_EQ(0, SCSI::Structures::toU32(readPositionData.lastBlockLocation));
buff[8] |= 0x9A;buff[9] |= 0xBC;buff[10] |= 0xDE;buff[11] |= 0xF9;
ASSERT_EQ(0x9ABCDEF9, SCSI::Structures::toU32(readPositionData.lastBlockLocation));
buff[12] |= 0xFF;
ASSERT_EQ(0, SCSI::Structures::toU32(readPositionData.blocksInBuffer));
buff[13] |= 0x9A;buff[14] |= 0xBC;buff[15] |= 0xDE;
ASSERT_EQ(0x009ABCDE, SCSI::Structures::toU32(readPositionData.blocksInBuffer));
ASSERT_EQ(0, SCSI::Structures::toU32(readPositionData.bytesInBuffer));
buff[16] |= 0x7A;buff[17] |= 0xBC;buff[18] |= 0xDE;buff[19] |= 0xF7;
ASSERT_EQ(0x7ABCDEF7, SCSI::Structures::toU32(readPositionData.bytesInBuffer));
}
TEST(SCSI_Structures, tapeAlertLogPage_t_and_parameters) {
SCSI::Structures::tapeAlertLogPage_t<12> tal;
unsigned char * buff = (unsigned char *) & tal;
......@@ -354,6 +435,11 @@ namespace UnitTests {
ASSERT_EQ( 0x1020304, SCSI::Structures::toU32(num));
}
TEST(SCSI_Structures, toU32_3byte) {
unsigned char num[3] = { 0xAA, 0xBB, 0xCC };
ASSERT_EQ( 0x00AABBCC, SCSI::Structures::toU32(num));
}
TEST(SCSI_Structures, toS32) {
unsigned char num[4] = { 0xE6, 0x29, 0x66, 0x5B };
ASSERT_EQ( -433494437, SCSI::Structures::toS32(num));
......
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