Commit 1c09ecbf authored by Eric Cano's avatar Eric Cano
Browse files

Moved bitfield structure for inquiry response to a specific header file in SCSI directory.

Added a few conversion utility functions for handling the strings from devices, and the 
big endianness of SCSI. Added a test to validate both.
Added a dump for all fields of the tape drive's inquery response.
parent 5ca0bbe8
......@@ -24,6 +24,7 @@
#pragma once
#include "../SCSI/Device.hh"
#include "../SCSI/Structures.hh"
#include "../System/Wrapper.hh"
#include "../Exception/Exception.hh"
......@@ -63,7 +64,11 @@ namespace Tape {
if (-1 != m_genericFD)
m_sysWrapper.close(m_genericFD);
}
void SCSI_inquiry() { SCSI_inquiry(m_genericFD); SCSI_inquiry(m_tapeFD); }
void SCSI_inquiry() {
std::cout << "Doing a SCSI inquiry via generic device:" << std::endl;
SCSI_inquiry(m_genericFD);
std::cout << "Re-doing a SCSI inquiry via st device:" << std::endl;
SCSI_inquiry(m_tapeFD); }
private:
SCSI::DeviceInfo m_SCSIInfo;
int m_tapeFD;
......@@ -119,72 +124,40 @@ namespace Tape {
pos += 8;
}
std::cout << hex.str();
/*
* Inquiry data as described in SPC-4.
*/
typedef struct {
unsigned char perifDevType : 5;
unsigned char perifQualifyer: 3;
unsigned char : 7;
unsigned char RMB : 1;
unsigned char version : 8;
unsigned char respDataFmt : 4;
unsigned char HiSup : 1;
unsigned char normACA : 1;
unsigned char : 2;
unsigned char addLength : 8;
unsigned char protect : 1;
unsigned char : 2;
unsigned char threePC : 1;
unsigned char TPGS : 2;
unsigned char ACC : 1;
unsigned char SCCS : 1;
unsigned char addr16 : 1;
unsigned char : 3;
unsigned char multiP : 1;
unsigned char VS1 : 1;
unsigned char encServ : 1;
unsigned char : 1;
unsigned char VS2 : 1;
unsigned char cmdQue : 1;
unsigned char : 2;
unsigned char sync : 1;
unsigned char wbus16 : 1;
unsigned char : 2;
char T10Vendor[8];
char prodId[16];
char prodRevLvl[4];
char vendorSpecific1[20];
unsigned char IUS : 1;
unsigned char QAS : 1;
unsigned char clocking : 2;
unsigned char : 4;
unsigned char reserved1;
unsigned char vendorDescriptior[8][2];
unsigned char reserved2[22];
unsigned char vendorSpecific2[1];
} inquiryData_t;
inquiryData_t & inq = *((inquiryData_t *) dataBuff);
SCSI::Structures::inquiryData_t & inq = *((SCSI::Structures::inquiryData_t *) dataBuff);
std::stringstream inqDump;
inqDump << std::hex << "inq.perifDevType=" << (int) inq.perifDevType << std::endl;
inqDump << "inq.perifQualifyer=" << (int) inq.perifQualifyer << std::endl;
inqDump << "inq.T10Vendor=";
inqDump.write(inq.T10Vendor, std::find(inq.T10Vendor, inq.T10Vendor + 8, '\0') - inq.T10Vendor);
inqDump << std::endl;
inqDump << std::hex << std::showbase << std::nouppercase
<< "inq.perifDevType=" << (int) inq.perifDevType << std::endl
<< "inq.perifQualifyer=" << (int) inq.perifQualifyer << std::endl
<< "inq.RMB=" << (int) inq.RMB << std::endl
<< "inq.version=" << (int) inq.version << std::endl
<< "inq.respDataFmt=" << (int) inq.respDataFmt << std::endl
<< "inq.HiSup=" << (int) inq.HiSup << std::endl
<< "inq.normACA=" << (int) inq.normACA << std::endl
<< "inq.addLength=" << (int) inq.addLength << std::endl
<< "inq.protect=" << (int) inq.protect << std::endl
<< "inq.threePC=" << (int) inq.threePC << std::endl
<< "inq.TPGS=" << (int) inq.TPGS << std::endl
<< "inq.ACC=" << (int) inq.ACC << std::endl
<< "inq.SCCS=" << (int) inq.SCCS << std::endl
<< "inq.addr16=" << (int) inq.addr16 << std::endl
<< "inq.multiP=" << (int) inq.multiP << std::endl
<< "inq.VS1=" << (int) inq.VS1 << std::endl
<< "inq.encServ=" << (int) inq.encServ << std::endl
<< "inq.VS2=" << (int) inq.VS2 << std::endl
<< "inq.cmdQue=" << (int) inq.cmdQue << std::endl
<< "inq.sync=" << (int) inq.sync << std::endl
<< "inq.wbus16=" << (int) inq.wbus16 << std::endl
<< "inq.T10Vendor=" << SCSI::Structures::toString(inq.T10Vendor) << std::endl
<< "inq.prodId=" << SCSI::Structures::toString(inq.prodId) << std::endl
<< "inq.prodRevLv=" << SCSI::Structures::toString(inq.prodRevLvl) << std::endl
<< "inq.vendorSpecific1="<< SCSI::Structures::toString(inq.vendorSpecific1)<< std::endl
<< "inq.IUS=" << (int) inq.IUS << std::endl
<< "inq.QAS=" << (int) inq.QAS << std::endl
<< "inq.clocking=" << (int) inq.clocking << std::endl;
for (int i=0; i < 8; i++)
inqDump << "inq.versionDescriptor[" << i << "]=" << SCSI::Structures::toU16(inq.versionDescriptor[i]) << std::endl;
std::cout << inqDump.str();
}
};
......
add_library(SCSI Device.cc)
add_library(SCSI Device.cc Structures.cc)
#add_executable(SCSIDumpTest DumpTest.cc)
#target_link_libraries(SCSIDumpTest SCSI)
// ----------------------------------------------------------------------
// File: Drive/Structures.cc
// Author: Eric Cano - CERN
// ----------------------------------------------------------------------
/************************************************************************
* Tape Server *
* Copyright (C) 2013 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
************************************************************************/
// ----------------------------------------------------------------------
// File: Drive/Structures.hh
// Author: Eric Cano - CERN
// ----------------------------------------------------------------------
/************************************************************************
* Tape Server *
* Copyright (C) 2013 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
************************************************************************/
#pragma once
#include <sstream>
#include <arpa/inet.h>
namespace SCSI {
namespace Structures {
/*
* Inquiry data as described in SPC-4.
*/
typedef struct {
unsigned char perifDevType : 5;
unsigned char perifQualifyer : 3;
unsigned char : 7;
unsigned char RMB : 1;
unsigned char version : 8;
unsigned char respDataFmt : 4;
unsigned char HiSup : 1;
unsigned char normACA : 1;
unsigned char : 2;
unsigned char addLength : 8;
unsigned char protect : 1;
unsigned char : 2;
unsigned char threePC : 1;
unsigned char TPGS : 2;
unsigned char ACC : 1;
unsigned char SCCS : 1;
unsigned char addr16 : 1;
unsigned char : 3;
unsigned char multiP : 1;
unsigned char VS1 : 1;
unsigned char encServ : 1;
unsigned char : 1;
unsigned char VS2 : 1;
unsigned char cmdQue : 1;
unsigned char : 2;
unsigned char sync : 1;
unsigned char wbus16 : 1;
unsigned char : 2;
char T10Vendor[8];
char prodId[16];
char prodRevLvl[4];
char vendorSpecific1[20];
unsigned char IUS : 1;
unsigned char QAS : 1;
unsigned char clocking : 2;
unsigned char : 4;
unsigned char reserved1;
char versionDescriptor[8][2];
unsigned char reserved2[22];
unsigned char vendorSpecific2[1];
} inquiryData_t;
template <size_t n>
std::string toString(const char(& t)[n]) {
std::stringstream r;
r.write(t, std::find(t, t + n, '\0') - t);
return r.str();
}
inline uint32_t toU32(const char(& t)[4])
{
/* Like network, SCSI is BigEndian */
return ntohl (*((uint32_t *) t));
}
inline uint16_t toU16(const char(& t)[2])
{
/* Like network, SCSI is BigEndian */
return ntohs (*((uint16_t *) t));
}
};
};
// ----------------------------------------------------------------------
// File: SCSI/DeviceTest.cc
// Author: Eric Cano - CERN
// ----------------------------------------------------------------------
/************************************************************************
* Tape Server *
* Copyright (C) 2013 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
************************************************************************/
#include <gtest/gtest.h>
#include <gmock/gmock-cardinalities.h>
#include "Device.hh"
#include "Structures.hh"
#include "../System/Wrapper.hh"
using ::testing::AtLeast;
using ::testing::Return;
using ::testing::_;
namespace UnitTests {
TEST(SCSIStructures, inquiryData_t_and_multi_byte_numbers) {
/* Validate the bit field behavior of the struct inquiryData_t,
which represents the standard INQUIRY data format as defined in
SPC-4. This test also validates the handling of multi-bytes numbers,
as SCSI structures are big endian (and main development target is
little endian. */
unsigned char inqBuff [100];
memset(inqBuff, 0, sizeof(inqBuff));
SCSI::Structures::inquiryData_t & inq = *((SCSI::Structures::inquiryData_t *) inqBuff);
/* Peripheral device type */
ASSERT_EQ(0, inq.perifDevType);
inqBuff[0] |= (0x1A & 0x1F) << 0;
ASSERT_EQ(0x1A, inq.perifDevType);
/* Peripheral qualifier */
ASSERT_EQ(0, inq.perifQualifyer);
inqBuff[0] |= (0x5 & 0x7) << 5;
ASSERT_EQ(0x5, inq.perifQualifyer);
/* ... */
/* sampling of bits */
ASSERT_EQ(0, inq.VS1);
inqBuff[6] |= (0x1 & 0x1) << 5;
ASSERT_EQ(1, inq.VS1);
ASSERT_EQ(0, inq.sync);
inqBuff[7] |= (0x1 & 0x1) << 4;
ASSERT_EQ(1, inq.sync);
/* Test of strings */
ASSERT_EQ("", SCSI::Structures::toString(inq.T10Vendor));
inqBuff[8] = 'V';
inqBuff[9] = 'i';
inqBuff[10] = 'r';
inqBuff[11] = 't';
inqBuff[12] = 'u';
inqBuff[13] = 'a';
inqBuff[14] = 'l';
inqBuff[15] = '\0';
ASSERT_EQ("Virtual", SCSI::Structures::toString(inq.T10Vendor));
/* Test of endian conversion */
ASSERT_EQ(0, SCSI::Structures::toU16(inq.versionDescriptor[7]));
inqBuff[72] = 0xCA;
inqBuff[73] = 0xFE;
ASSERT_EQ(0xCAFE, SCSI::Structures::toU16(inq.versionDescriptor[7]));
/* Test last element */
ASSERT_EQ(0, *inq.vendorSpecific2);
inqBuff[96] = 0x12;
ASSERT_EQ(0x12, *inq.vendorSpecific2);
}
};
add_executable(unitTest unitTest.cc ../SCSI/DeviceTest.cc ../Utils/RegexTest.cc ../Drive/DriveTest.cc)
add_executable(unitTest unitTest.cc
../SCSI/DeviceTest.cc
../SCSI/StructuresTest.cc
../Utils/RegexTest.cc
../Drive/DriveTest.cc
)
target_link_libraries(unitTest Exception SCSI System Utils ${GTEST_LIBRARY} gmock pthread)
install(TARGETS unitTest
......
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