scsi_IO Class Reference
[SCSI Library]

#include <scsi_io.h>

Inheritance diagram for scsi_IO:

Inheritance graph
[legend]
Collaboration diagram for scsi_IO:

Collaboration graph
[legend]

List of all members.


Detailed Description

Interface class to access SCSI devices.

Successors of this class implement actual communication.

Definition at line 41 of file scsi_io.h.


Public Member Functions

 scsi_IO (const string &a_deviceID)
 Device identification is passed in constructor:.
virtual ~scsi_IO ()
void Open ()
 Open SCSI device.
void SkipAttAndDeferred ()
void WaitToBecomeReady ()
virtual bool IsOpen ()=0
virtual void Close ()=0
virtual scsi_Status_e GetCDBStatus ()=0
virtual bool IsSenseValid ()=0
virtual void IOCtl (const scsi_CDB &a_cdb, UInt32_t a_timeout=scsi_TIMEOUT_NORMAL_d)
void SetDeviceID (string a_deviceID)
UInt32_t GetPort () const
UInt32_t GetChannel () const
UInt32_t GetID () const
UInt32_t GetLUN () const
string GetSCSIID () const
const string & GetDeviceName () const
scsi_DeviceType_e GetDeviceType () const
const string & GetVendorID () const
const string & GetProductID () const
const string & GetProductRevision () const
const string & GetProductSerialNumber () const
UInt8_t GetStandard () const
bool GetPossibleMediumChange () const
const data_Sense_tGetSense () const
UInt32_t GetSenseSize () const
UInt32_t GetReadDifference () const
 The difference between the requested and read data if SILI bit is set.

Protected Member Functions

void TestUnitReady ()
virtual void OpenByDeviceName ()=0
 Open SCSI device by its (platform specific!) name.
virtual void OpenBySCSIID ()=0
 Open SCSI device by its (current) SCSI ID.
virtual void OpenBySerialNumber ()=0
 Open SCSI device by its unique identification.
virtual void InqSCSIID ()=0
 Get SCSI ID of the currently opened device.
void InqStandard ()
 Do standard inquiry.
void InqSerialNumber ()
 Do inquiries necessary to get the serial number of the device.
virtual int DoIOCtl (const scsi_CDB &a_cdb, UInt32_t a_timeout)=0
 Function to actually execute CDB commands.
virtual void CheckDriverStatus (UInt8_t a_cdbCode)
 Checks the status of the driver after the execution of CDB.
virtual void CheckHostStatus (UInt8_t a_cdbCode)
 Checks the status of the host (if available) after the execution of CDB.
void CheckStatusAndSense (const scsi_CDB &a_cdb)
 Checks the execution status and sense structure.
void Inquiry ()

Protected Attributes

string m_deviceID
 Unique device identification, passed in constructor or SetDeviceID.
string m_deviceName
 Device name.
UInt32_t m_port
 Also known as bus or host.
UInt32_t m_channel
UInt32_t m_id
UInt32_t m_lun
string m_strSCSIID
string m_vendorID
string m_productID
string m_productSerialNumber
const scsi_SenseVndm_vndSenseText
string m_productRevision
scsi_DeviceType_e m_deviceType
vector< data_Inquiry::inq_Page_tm_supportedPages
UInt8_t m_standard
bool m_possibleMediumChange
data_Sense_t m_sense
bool m_pdDirectMode
 Direct passthrough mode can be disabled via env variable.
UInt32_t m_timeoutOverride
 Default timeouts can be overridden with env.
UInt32_t m_testHWErrProbability
UInt32_t m_testMedErrProbability

Private Member Functions

bool IsPageSupported (data_Inquiry::inq_Page_t a_page)

Private Attributes

 log_CLASSID_m

Constructor & Destructor Documentation

scsi_IO::scsi_IO ( const string &  a_deviceID  ) 

Device identification is passed in constructor:.

  • sn:VENDOR_ID:DEVICE_ID:SERIAL_NUMBER .. open by serial number
  • id:PORT:CHANNEL:ID:LUN .. open by SCSI ID
  • else open by device name (e.g. /dev/sgX)

Definition at line 64 of file scsi_io.cpp.

References cmn_GetEnvVariable(), dbg_LOW, log_DBG_m, log_FUNC_A_m, m_pdDirectMode, m_testHWErrProbability, m_testMedErrProbability, m_timeoutOverride, NULL, scsi_ptDirect_c(), scsi_testHWerror_c(), scsi_testMederror_c(), scsi_testProbUnit(), and scsi_timeout_c().

00065     : m_deviceID(a_deviceID),
00066       m_deviceName(""),
00067       m_port(0xFF),
00068       m_channel(0xFF),
00069       m_id(0xFF),
00070       m_lun(0xFF),
00071       m_vendorID(""),
00072       m_productID(""),
00073       m_productSerialNumber(""),
00074       m_vndSenseText(NULL),
00075       m_productRevision(""),
00076       m_deviceType(dt_NO_LUN),
00077       m_standard(0),
00078       m_possibleMediumChange(false),
00079       m_pdDirectMode(true),
00080       m_timeoutOverride(0),
00081       m_testHWErrProbability(0),
00082       m_testMedErrProbability(0) {
00083 
00084     log_FUNC_A_m(scsi_IO, "device: " << a_deviceID);
00085 
00086     string ptDirect = cmn_GetEnvVariable(scsi_ptDirect_c);
00087     if (ptDirect == "no" || ptDirect == "false") {
00088         log_DBG_m(dbg_LOW,
00089             scsi_ptDirect_c << " = " << ptDirect <<
00090             ". SCSI passthrough direct mode disabled.");
00091 
00092         m_pdDirectMode = false;
00093     }
00094 
00095     string timeout = cmn_GetEnvVariable(scsi_timeout_c);
00096     if (timeout.length() > 0) {
00097         log_DBG_m(dbg_LOW, scsi_timeout_c << " = " << timeout << " sec.");
00098 
00099         m_timeoutOverride = atol(timeout.c_str()) * 1000;
00100         log_DBG_m(dbg_LOW, "SCSI timeout overridden value (ms): " << m_timeoutOverride);
00101     }
00102 
00103 #ifdef scsi_SIMULATE_ERRORS_d
00104     // Reading env variables for simulating hardware/medium errors.
00105     string hwErr = cmn_GetEnvVariable(scsi_testHWerror_c);
00106     if (hwErr.length() > 0) {
00107         log_DBG_m(dbg_LOW,
00108             scsi_testHWerror_c << " = " << hwErr <<
00109             " (1/" << scsi_testProbUnit << ").");
00110         m_testHWErrProbability = atol(hwErr.c_str());
00111     }
00112 
00113     string medErr = cmn_GetEnvVariable(scsi_testMederror_c);
00114     if (medErr.length() > 0) {
00115         log_DBG_m(dbg_LOW,
00116             scsi_testMederror_c << " = " << medErr <<
00117             " (1/" << scsi_testProbUnit << ").");
00118         m_testMedErrProbability = atol(medErr.c_str());
00119     }
00120 
00121     // Set seed for better random
00122     if (m_testHWErrProbability > 0 || m_testMedErrProbability > 0) {
00123         time_t now = time(NULL);
00124         srand(now);
00125     }
00126 #endif
00127 
00128 }

Here is the call graph for this function:

scsi_IO::~scsi_IO (  )  [virtual]

Definition at line 130 of file scsi_io.cpp.

References log_FUNC_m.

00130                  {
00131     log_FUNC_m(~scsi_IO);
00132 }


Member Function Documentation

void scsi_IO::Open (  ) 

Open SCSI device.

Calls one of the OpenBy.. functions..

Definition at line 224 of file scsi_io.cpp.

References dbg_LOW, idPrefix_c, ie_INVALID_ARG, ivd_Error, log_DBG_m, log_FUNC_m, m_channel, m_deviceID, m_deviceName, m_deviceType, m_id, m_lun, m_port, m_possibleMediumChange, m_productID, m_productRevision, m_productSerialNumber, m_standard, m_vendorID, OpenByDeviceName(), OpenBySCSIID(), OpenBySerialNumber(), scsi_GetDeviceTypeText(), and snPrefix_c.

Referenced by la_SCSILibrary::EjectMedium(), main(), la_SCSILibrary::Open(), ParseTapeMedium(), and STapeOpen().

00224                    {
00225     log_FUNC_m(Open);
00226 
00227     log_DBG_m(dbg_LOW, "Opening device ID: " << m_deviceID);
00228 
00229     m_possibleMediumChange = false;
00230 
00231     if (m_deviceID.substr(0, 3) == snPrefix_c) {
00232         //
00233         // Device should be open by its serial number.
00234         // Name is:
00235         // sn:VENDOR:PRODUCT:SERIAL_NUMBER
00236         //
00237         string::size_type start = snPrefix_c.length();
00238         string::size_type end = m_deviceID.find(":", start);
00239         if (end == string::npos) {
00240             goto lbl_error;
00241         }
00242         m_vendorID = m_deviceID.substr(start, end-start);
00243 
00244         start = end + 1;
00245         end = m_deviceID.find(":", start);
00246         if (end == string::npos) {
00247             goto lbl_error;
00248         }
00249         m_productID = m_deviceID.substr(start, end-start);
00250 
00251         start = end + 1;
00252         m_productSerialNumber = m_deviceID.substr(start);
00253 
00254         OpenBySerialNumber();
00255     }
00256     else if (m_deviceID.substr(0, 3) == idPrefix_c) {
00257         //
00258         // Device should be open by its SCSI ID.
00259         // Name is:
00260         // id:PORT:CHANNEL:ID:LUN
00261         //
00262         string::size_type start = idPrefix_c.length();
00263         string::size_type end = m_deviceID.find(":", start);
00264         if (end == string::npos) {
00265             goto lbl_error;
00266         }
00267         m_port = atoi(m_deviceID.substr(start, end-start).c_str());
00268 
00269         start = end + 1;
00270         end = m_deviceID.find(":", start);
00271         if (end == string::npos) {
00272             goto lbl_error;
00273         }
00274         m_channel = atoi(m_deviceID.substr(start, end-start).c_str());
00275 
00276         start = end + 1;
00277         end = m_deviceID.find(":", start);
00278         if (end == string::npos) {
00279             goto lbl_error;
00280         }
00281         m_id = atoi(m_deviceID.substr(start, end-start).c_str());
00282 
00283         start = end + 1;
00284         m_lun = atoi(m_deviceID.substr(start).c_str());
00285 
00286         OpenBySCSIID();
00287     }
00288     else {
00289         //
00290         // Device should be open by its name directly.
00291         //
00292         m_deviceName = m_deviceID;
00293 
00294         OpenByDeviceName();
00295     }
00296 
00297     log_DBG_m(dbg_LOW, endl <<
00298         "** Device parameters **" << endl <<
00299         "devName  : " << "\'" << m_deviceName << "\'" << endl << endl <<
00300         "port     : " << m_port << endl <<
00301         "channel  : " << m_channel << endl <<
00302         "id       : " << m_id << endl <<
00303         "lun      : " << m_lun << endl << endl <<
00304         "vendorID : " << "\'" << m_vendorID << "\'" << endl <<
00305         "prodID   : " << "\'" << m_productID << "\'" << endl <<
00306         "prodSN   : " << "\'" << m_productSerialNumber << "\'" << endl <<
00307         "prodRev  : " << "\'" << m_productRevision << "\'" << endl << endl <<
00308         "devType  : " << scsi_GetDeviceTypeText(m_deviceType) << endl <<
00309         "standard : " << (int)m_standard);
00310 
00311     return;
00312 
00313 lbl_error:
00314     throw ivd_Error(
00315         ie_INVALID_ARG,
00316         "Invalid device name format: " + m_deviceID);
00317 }

Here is the call graph for this function:

Here is the caller graph for this function:

void scsi_IO::SkipAttAndDeferred (  ) 

Definition at line 387 of file scsi_io.cpp.

References dbg_NORM, ivd_BaseException::GetError(), GetSense(), ie_SCSI_UNIT_ATT, ivd_USleep, log_DBG_m, log_FUNC_m, log_WRN_m, m_deviceID, m_deviceName, m_vendorID, NULL, data_Sense_t::responseCode, sns_DEFERRED, and TestUnitReady().

Referenced by main(), and WaitToBecomeReady().

00387                                  {
00388     log_FUNC_m(SkipAttAndDeferred);
00389 
00390     UInt32_t c_timeout = 60 * 20; // Timeout to finish TUR: 20 minutes
00391     ivd_Time_t timeStart = time(NULL);
00392 
00393     log_DBG_m(dbg_NORM, "Skipping ATTENTION and old senses...");
00394 
00395     while(1) {
00396         try {
00397             TestUnitReady();
00398             break;
00399         }
00400         catch (ivd_Error &ie) {
00401             ivd_Time_t now = time(NULL);
00402 
00403             if (now - timeStart > c_timeout) {
00404                 log_WRN_m(
00405                     "Timeout doing TEST UNIT READY. " <<
00406                     "Device ID: " << m_deviceID << " " <<
00407                     "Device Name: " << m_deviceName << " " <<
00408                     "Vendor: " << m_vendorID);
00409 
00410                 throw;
00411             }
00412 
00413             if (ie.GetError() == ie_SCSI_UNIT_ATT ||
00414                 GetSense()->responseCode == sns_DEFERRED) {
00415                 log_DBG_m(dbg_NORM,
00416                     "Skipping UNIT ATTENTION and DEFERRED senses.");
00417 
00418                 ivd_USleep(1000 * 10); // 1/100 s
00419             }
00420             else {
00421                 throw;
00422             }
00423         }
00424     }; // while
00425 }

Here is the call graph for this function:

Here is the caller graph for this function:

void scsi_IO::WaitToBecomeReady (  ) 

Definition at line 321 of file scsi_io.cpp.

References data_Sense_t::additionalLen, data_Sense_t::asc, data_Sense_t::ascq, cmn_HexDump(), dbg_NORM, ivd_BaseException::GetError(), ie_SCSI_HWERR, ie_SCSI_NOT_READY, ie_SCSI_RETRY, ivd_Error, ivd_Sleep, log_DBG_m, log_FUNC_m, log_WRN_m, m_deviceID, m_deviceName, m_deviceType, m_productID, m_productRevision, m_productSerialNumber, m_sense, m_vendorID, m_vndSenseText, NULL, scsi_GetASCText(), scsi_GetSenseKeyText(), scsi_GetSenseText(), data_Sense_t::senseKey, SkipAttAndDeferred(), and TestUnitReady().

Referenced by la_SCSILibrary::EjectMedium(), bea_TapeVolume::GetPosition(), la_SCSILibrary::Inventory(), la_SCSILibrary::Load(), la_SCSILibrary::Open(), bea_TapeVolume::Rewind(), bea_TapeVolume::SeekBlock(), bea_TapeVolume::SeekEOD(), STapeOpen(), and la_SCSILibrary::Unload().

00321                                 {
00322     log_FUNC_m(WaitToBecomeReady);
00323 
00324     UInt32_t c_timeout = 60 * 20; // Timeout to become ready: 20 minutes
00325     ivd_Time_t timeStart = time(NULL);
00326 
00327     log_DBG_m(dbg_NORM, "Waiting to become ready...");
00328 
00329     while(1) {
00330         try {
00331             SkipAttAndDeferred();
00332             TestUnitReady();
00333             break;
00334         }
00335         catch (ivd_Error &ie) {
00336             ivd_Time_t now = time(NULL);
00337 
00338             if (now - timeStart > c_timeout) {
00339 
00340                 if (m_sense.asc  == 0x04 &&
00341                     m_sense.ascq == 0x00) {
00342 
00343                     string senseTxt = scsi_GetSenseText(m_sense, m_deviceType, m_vndSenseText);
00344 
00345                     ostringstream shortText;
00346                     shortText
00347                         << scsi_GetSenseKeyText((scsi_SenseKey_e)m_sense.senseKey)
00348                         << " (" << scsi_GetASCText(m_sense, m_vndSenseText) << ")";
00349 
00350                     // Detailed dump
00351                     ostringstream dump;
00352                     dump
00353                         << "Device: " << m_vendorID << " " << m_productID << " "
00354                         << m_productRevision << " s/n: " << m_productSerialNumber << endl
00355                         << senseTxt << endl
00356                         << "Sense dump (" << static_cast<UInt32_t>(m_sense.additionalLen+8) << " bytes) :" << endl
00357                         << cmn_HexDump(
00358                             reinterpret_cast<const void*>(&m_sense), m_sense.additionalLen+8, 8, true) << endl;
00359 
00360                     throw ivd_Error(ie_SCSI_HWERR, shortText.str(), dump.str());
00361                 }
00362 
00363                 log_WRN_m(
00364                     "Timeout waiting device to become ready. " <<
00365                     "Device ID: " << m_deviceID << " " <<
00366                     "Device Name: " << m_deviceName << " " <<
00367                     "Vendor: " << m_vendorID);
00368 
00369                 throw;
00370             }
00371 
00372             if (   ie.GetError() == ie_SCSI_NOT_READY
00373                 || ie.GetError() == ie_SCSI_RETRY) {
00374 
00375                 log_DBG_m(dbg_NORM, "Device not ready yet. Retrying.");
00376 
00377                 ivd_Sleep(2);
00378             }
00379             else {
00380                 throw;
00381             }
00382         }
00383     }; // while
00384 
00385 }

Here is the call graph for this function:

Here is the caller graph for this function:

virtual bool scsi_IO::IsOpen (  )  [pure virtual]

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by la_SCSILibrary::Close(), IOCtl(), and SetDeviceID().

Here is the caller graph for this function:

virtual void scsi_IO::Close (  )  [pure virtual]

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by la_SCSILibrary::Close(), la_SCSILibrary::EjectMedium(), main(), la_SCSILibrary::Open(), ParseTapeMedium(), STapeClose(), and STapeOpen().

Here is the caller graph for this function:

virtual scsi_Status_e scsi_IO::GetCDBStatus (  )  [pure virtual]

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by CheckStatusAndSense(), and scsi_WinSG::IsSenseValid().

Here is the caller graph for this function:

virtual bool scsi_IO::IsSenseValid (  )  [pure virtual]

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by CheckStatusAndSense().

Here is the caller graph for this function:

void scsi_IO::IOCtl ( const scsi_CDB a_cdb,
UInt32_t  a_timeout = scsi_TIMEOUT_NORMAL_d 
) [virtual]

################### DoIOCtl ###################

################### DoIOCtl ###################

Definition at line 433 of file scsi_io.cpp.

References data_Sense_t::additionalLen, CheckDriverStatus(), CheckHostStatus(), CheckStatusAndSense(), cmn_HexDump(), cmn_Num2Str(), dbg_DETAIL, dbg_GetLevel(), dbg_IsActive(), dbg_NORM, DoIOCtl(), evt_WARNING, scsi_CDB::GetBufferPointer(), scsi_CDB::GetBufferSize(), scsi_CDB::GetCmdPointer(), scsi_CDB::GetCmdSize(), ie_INVALID_ARG, ie_SCSI_HWERR, ie_SCSI_MEDERR, IsOpen(), data_Sense_t::isValid, ivd_Error, log_DBG_m, log_FUNC_m, log_MARKLINE_m, log_WriteEvent(), m_deviceID, m_sense, m_strSCSIID, m_testHWErrProbability, m_testMedErrProbability, m_timeoutOverride, op_READ_10, op_READ_6, op_WRITE_10, op_WRITE_6, data_Sense_t::responseCode, scsi_CommandSize(), scsi_GetOpcodeText(), scsi_testProbUnit(), data_Sense_t::senseKey, and size.

Referenced by Ait(), Append(), bea_TapeMedium::AppendVolume(), bea_TapeMedium::ChangeVolume(), CheckIVDHeader(), Ci(), Compression(), Cp(), Dens(), bea_MicMemory::Detect(), bea_TapeMedium::DetectAITWORM(), bea_TapeMedium::DetectLTOWORM(), Ea(), la_SCSILibrary::EjectMedium(), Eod(), Erase(), bea_TapeVolume::Erase(), FMSeek(), Fmt(), bea_TapeMedium::Format(), bea_MicMemory::GetAvailable(), bea_MamMemory::GetAvailable(), GetCapacityInfo(), bea_MicMemory::GetChecksum(), bea_MicMemory::GetManufacturer(), bea_MamMemory::GetManufacturer(), GetPos(), bea_TapeVolume::GetPosition(), bea_MicMemory::GetSecondaryID(), bea_MicMemory::GetSerialNumber(), bea_MamMemory::GetSerialNumber(), bea_MicMemory::GetSize(), InqSerialNumber(), InqStandard(), la_SCSILibrary::Inventory(), Inventory(), la_SCSILibrary::Load(), Load(), main(), Mamcapacity(), Mamdetect(), Mamfree(), Mamisworm(), Mamrmedinfo(), Mamrvolinfo(), Mamserial(), Mamwmedinfo(), Mamwvolinfo(), Micfree(), Micnote(), Micnotelen(), Micnotemap(), Micnotesize(), Micserial(), Micwritenote(), Mv(), ParseMICMediumNote(), ParseMICVolNote(), ParseTapeMedium(), ParseTapeMediumVolume(), ParseTapeMediumVolumeData(), ParseTapeMediumVolumeFRI(), ParseTapeMediumVolumeHeader(), Pi(), Pn(), Pos(), Rate(), Rd(), bea_MicMemory::Read(), bea_MamMemory::Read(), bea_MamMemory::ReadAttributeList(), ReadBlockPos(), bea_TapeMedium::ReadCurrentVolume(), la_SCSILibrary::ReadElementAssignment(), bea_TapeVolume::ReadEstimSizes(), ReadFromMedium(), ReadOneBackupFromMedium(), bea_TapeVolume::ReadRaw(), bea_TapeMedium::RefreshCompressionState(), bea_TapeMedium::RefreshTapeInfo(), Rewind(), bea_TapeVolume::Rewind(), RewindMedium(), Seek(), bea_TapeVolume::SeekBlock(), bea_TapeVolume::SeekEOD(), bea_TapeVolume::SeekFileMark(), SeekLastBackupFM(), Space(), Spacefm(), STapeOpen(), STapeWriteFileMark(), la_SCSILibrary::Status(), Status(), TestUnitReady(), la_SCSILibrary::Unload(), Unload(), Wfm(), bea_MicMemory::Write(), bea_MamMemory::Write(), bea_TapeVolume::WriteFileMarks(), bea_TapeVolume::WriteRaw(), WriteScsi(), and WriteToMedium().

00433                                                              {
00434     log_FUNC_m(IOCtl);
00435 
00436     if (!IsOpen()) {
00437         throw ivd_Error(
00438             ie_INVALID_ARG, "Device is not open. " + m_deviceID);
00439     }
00440 
00441     UInt8_t cdbCode = a_cdb.GetCmdPointer()[0];
00442     log_DBG_m(dbg_NORM,
00443         "CDB: " << scsi_GetOpcodeText(cdbCode) <<
00444         " size: " << a_cdb.GetCmdSize());
00445 
00446     if (a_cdb.GetCmdSize() != scsi_CommandSize(cdbCode)) {
00447         log_MARKLINE_m;
00448         throw ivd_InternalError(
00449             ie_INVALID_ARG,
00450             string("Expected cdb size ") + cmn_Num2Str(scsi_CommandSize(cdbCode)) +
00451             string(" for CDB ") + scsi_GetOpcodeText(cdbCode));
00452      }
00453 
00454     // Init sense structure.
00455     m_sense.responseCode = 0, m_sense.isValid = 0,
00456     m_sense.senseKey = 0, m_sense.additionalLen = 0;
00457 
00458     UInt32_t timeout(a_timeout);
00459     if (m_timeoutOverride > 0) {
00460         timeout = m_timeoutOverride;
00461     }
00462 
00463     log_DBG_m(dbg_DETAIL, "Timeout = " << (timeout/1000/60) << " min.")
00464 
00465     if (dbg_IsActive()) {
00466         // HEX dump of a command.
00467         const UInt8_t *cdb = a_cdb.GetCmdPointer();
00468         UInt32_t size = a_cdb.GetCmdSize();
00469         string dump = cmn_HexDump((const void*)cdb, size, 8, true);
00470         log_DBG_m(dbg_DETAIL,
00471             endl << "**** CDB HEX DUMP: ****" << endl << dump);
00472     }
00473 
00475     int result = DoIOCtl(a_cdb, timeout);
00477     if (result != 0) {
00478         log_MARKLINE_m;
00479         throw ivd_SysError(result, scsi_GetOpcodeText(cdbCode), true);
00480     };
00481 
00482     // Do hex dump of data for non read/write operations.
00483     if (    cdbCode != op_READ_6
00484         &&  cdbCode != op_READ_10
00485         &&  cdbCode != op_WRITE_6
00486         &&  cdbCode != op_WRITE_10
00487         && dbg_IsActive()) {
00488         // HEX dump of data.
00489         UInt8_t *data = a_cdb.GetBufferPointer();
00490         UInt32_t size = a_cdb.GetBufferSize();
00491 
00492         log_DBG_m(dbg_NORM, "DATA length " << a_cdb.GetBufferSize());
00493         if (size > 0 && dbg_GetLevel() >= dbg_DETAIL) {
00494             string dump = cmn_HexDump(
00495                 (const void*)data, (size < 256)? size : 256, 16, true);
00496             log_DBG_m(dbg_DETAIL,
00497                 endl << "**** DATA HEX DUMP: ****" << endl << dump);
00498         }
00499     }
00500 
00501     // Checks and throws
00502     CheckDriverStatus(cdbCode);
00503     // Checks and throws
00504     CheckHostStatus(cdbCode);
00505     // Checks and throws
00506     CheckStatusAndSense(a_cdb);
00507 
00508 #ifdef scsi_SIMULATE_ERRORS_d
00509     if (m_testHWErrProbability > 0) {
00510         if (   cdbCode == op_READ_6 || cdbCode == op_READ_10
00511             || cdbCode == op_WRITE_6 || cdbCode == op_WRITE_10) {
00512 
00513             if ( (rand() % scsi_testProbUnit) < m_testHWErrProbability ) {
00514                 log_WriteEvent(
00515                     evt_WARNING, "Simulated HW error.", "SCSI", 0, m_strSCSIID);
00516                 throw ivd_Error(ie_SCSI_HWERR, "Triggered HW error for testing.", true);
00517             }
00518         }
00519     }
00520 
00521     if (m_testMedErrProbability > 0) {
00522         if (   cdbCode == op_READ_6 || cdbCode == op_READ_10
00523             || cdbCode == op_WRITE_6 || cdbCode == op_WRITE_10) {
00524 
00525             if ( (rand() % scsi_testProbUnit) < m_testMedErrProbability ) {
00526                 log_WriteEvent(
00527                     evt_WARNING, "Simulated medium error.", "SCSI", 0, m_strSCSIID);
00528                 throw ivd_Error(ie_SCSI_MEDERR, "Triggered medium error for testing.", true);
00529             }
00530         }
00531     }
00532 #endif
00533 
00534 }

Here is the call graph for this function:

void scsi_IO::SetDeviceID ( string  a_deviceID  ) 

Definition at line 134 of file scsi_io.cpp.

References ie_INVALID_ARG, IsOpen(), ivd_Error, log_FUNC_A_m, and m_deviceID.

Referenced by la_SCSILibrary::SetDeviceID().

00134                                            {
00135     log_FUNC_A_m(SetDeviceID, "device: " << a_deviceID);
00136 
00137     if (IsOpen()) {
00138         throw ivd_Error(
00139             ie_INVALID_ARG, "Trying to change device's ID while open.");
00140     }
00141     m_deviceID = a_deviceID;
00142 }

Here is the call graph for this function:

Here is the caller graph for this function:

UInt32_t scsi_IO::GetPort (  )  const

Definition at line 156 of file scsi_io.cpp.

References m_port.

Referenced by main(), and STapeOpen().

00156                                 {
00157     return m_port;
00158 }

Here is the caller graph for this function:

UInt32_t scsi_IO::GetChannel (  )  const

Definition at line 152 of file scsi_io.cpp.

References m_channel.

Referenced by main(), and STapeOpen().

00152                                    {
00153     return m_channel;
00154 }

Here is the caller graph for this function:

UInt32_t scsi_IO::GetID (  )  const

Definition at line 145 of file scsi_io.cpp.

References m_id.

Referenced by main(), and STapeOpen().

00145                               {
00146     return m_id;
00147 }

Here is the caller graph for this function:

UInt32_t scsi_IO::GetLUN (  )  const

Definition at line 149 of file scsi_io.cpp.

References m_lun.

Referenced by main(), and STapeOpen().

00149                                {
00150     return m_lun;
00151 }

Here is the caller graph for this function:

string scsi_IO::GetSCSIID (  )  const

Definition at line 160 of file scsi_io.cpp.

References m_channel, m_id, m_lun, and m_port.

Referenced by la_SCSILibrary::GetSCSIID(), and scsi_LnxSG::InqSCSIID().

00160                                 {
00161     ostringstream sstr;
00162     sstr
00163         << "id:"
00164         << m_port << ":"
00165         << m_channel << ":"
00166         << m_id << ":"
00167         << m_lun;
00168 
00169     return sstr.str();
00170 }

Here is the caller graph for this function:

const string & scsi_IO::GetDeviceName (  )  const

Definition at line 172 of file scsi_io.cpp.

References m_deviceName.

Referenced by main().

00172                                            {
00173     return m_deviceName;
00174 }

Here is the caller graph for this function:

scsi_DeviceType_e scsi_IO::GetDeviceType (  )  const

Definition at line 176 of file scsi_io.cpp.

References m_deviceType.

Referenced by la_SCSILibrary::EjectMedium(), main(), la_SCSILibrary::Open(), and STapeOpen().

00176                                                {
00177     return m_deviceType;
00178 }

Here is the caller graph for this function:

const string & scsi_IO::GetVendorID (  )  const

Definition at line 180 of file scsi_io.cpp.

References m_vendorID.

Referenced by Append(), Fmt(), bea_TapeMedium::Format(), la_SCSILibrary::GetVendorID(), main(), la_SCSILibrary::Open(), ParseMICMediumNote(), and ParseMICVolNote().

00180                                          {
00181     return m_vendorID;
00182 }

Here is the caller graph for this function:

const string & scsi_IO::GetProductID (  )  const

Definition at line 184 of file scsi_io.cpp.

References m_productID.

Referenced by Append(), Fmt(), bea_TapeMedium::Format(), la_SCSILibrary::GetProductID(), main(), and la_SCSILibrary::Open().

00184                                           {
00185     return m_productID;
00186 }

Here is the caller graph for this function:

const string & scsi_IO::GetProductRevision (  )  const

Definition at line 188 of file scsi_io.cpp.

References m_productRevision.

Referenced by bea_TapeMedium::Format(), la_SCSILibrary::GetProductRevision(), and main().

00188                                                 {
00189     return m_productRevision;
00190 }

Here is the caller graph for this function:

const string & scsi_IO::GetProductSerialNumber (  )  const

Definition at line 191 of file scsi_io.cpp.

References m_productSerialNumber.

Referenced by bea_TapeMedium::Format(), la_SCSILibrary::GetSerialNumber(), and main().

00191                                                     {
00192     return m_productSerialNumber;
00193 }

Here is the caller graph for this function:

UInt8_t scsi_IO::GetStandard (  )  const

Definition at line 195 of file scsi_io.cpp.

References m_standard.

Referenced by main().

00195                                    {
00196     return m_standard;
00197 }

Here is the caller graph for this function:

bool scsi_IO::GetPossibleMediumChange (  )  const

Definition at line 199 of file scsi_io.cpp.

References m_possibleMediumChange.

00199                                             {
00200     return m_possibleMediumChange;
00201 }

const data_Sense_t * scsi_IO::GetSense (  )  const

Definition at line 204 of file scsi_io.cpp.

References m_sense.

Referenced by scsi_LnxSG::DoIOCtl(), ParseTapeMedium(), and SkipAttAndDeferred().

00204                                             {
00205     return &m_sense;
00206 }

Here is the caller graph for this function:

UInt32_t scsi_IO::GetSenseSize (  )  const

Definition at line 208 of file scsi_io.cpp.

References m_sense.

Referenced by scsi_LnxSG::DoIOCtl().

00208                                      {
00209     return sizeof(m_sense);
00210 }

Here is the caller graph for this function:

UInt32_t scsi_IO::GetReadDifference (  )  const

The difference between the requested and read data if SILI bit is set.

Definition at line 212 of file scsi_io.cpp.

References data_Sense_t::incorrectLength, data_Sense_t::infoBytes, data_Sense_t::isValid, m_sense, and ntoh().

Referenced by Rd(), and ReadOneBackupFromMedium().

00212                                           {
00213     if (m_sense.incorrectLength == 0 || m_sense.isValid == 0) {
00214         return 0;
00215     }
00216     return static_cast<UInt32_t>(ntoh(m_sense.infoBytes));
00217 }

Here is the call graph for this function:

Here is the caller graph for this function:

void scsi_IO::TestUnitReady (  )  [protected]

Definition at line 427 of file scsi_io.cpp.

References IOCtl().

Referenced by SkipAttAndDeferred(), and WaitToBecomeReady().

00427                             {
00428     cdb_TestUnitReady tur;
00429     IOCtl(tur);
00430 }

Here is the call graph for this function:

Here is the caller graph for this function:

virtual void scsi_IO::OpenByDeviceName (  )  [protected, pure virtual]

Open SCSI device by its (platform specific!) name.

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by Open().

Here is the caller graph for this function:

virtual void scsi_IO::OpenBySCSIID (  )  [protected, pure virtual]

Open SCSI device by its (current) SCSI ID.

Warning:
Implementations must take care to close the device if an error occurs.

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by Open().

Here is the caller graph for this function:

virtual void scsi_IO::OpenBySerialNumber (  )  [protected, pure virtual]

Open SCSI device by its unique identification.

Warning:
Implementations must take care to close the device if an error occurs.

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by Open().

Here is the caller graph for this function:

virtual void scsi_IO::InqSCSIID (  )  [protected, pure virtual]

Get SCSI ID of the currently opened device.

Implemented in scsi_LnxSG, and scsi_WinSG.

void scsi_IO::InqStandard (  )  [protected]

Do standard inquiry.

It gets:

  • Device type
  • Vendor ID
  • Product ID
  • Product revision
  • SCSI Standard

Definition at line 791 of file scsi_io.cpp.

References data_StdInquiry_t::ansi, cmn_Num2Str(), dbg_DETAIL, dbg_LOW, dbg_NORM, dt_MEDIUM_CHANGER, dt_TAPE, ivd_BaseException::GetFriendly(), cdb_Inquiry::GetInquiry(), data_Inquiry::GetInquiryData(), data_Inquiry::inq_PAGES, data_Inquiry_t::inqstd, inqstd_PROD_REVISION_LEN_d, inqstd_PRODUCT_ID_LEN_d, inqstd_VENDOR_ID_LEN_d, IOCtl(), log_DBG_m, log_FUNC_m, m_deviceType, m_productID, m_productRevision, m_standard, m_supportedPages, m_vendorID, m_vndSenseText, data_InqPages_t::pageLen, data_InqPages_t::pages, data_StdInquiry_t::productID, data_StdInquiry_t::productRevision, scsi_GetDeviceTypeText(), scsi_GetVndAddSnsTbl(), data_Inquiry_t::supportedPages, data_StdInquiry_t::type, and data_StdInquiry_t::vendorID.

Referenced by scsi_LnxSG::OpenByDeviceName().

00791                           {
00792     log_FUNC_m(InqStandard);
00793 
00794     {
00795         log_DBG_m(dbg_NORM, "Standard INQ:")
00796         // Standard inquiry
00797 
00798         cdb_Inquiry scsistd;
00799         IOCtl(scsistd);
00800         const data_Inquiry_t &inquiry = scsistd.GetInquiry().GetInquiryData();
00801 
00802         this->m_deviceType = scsi_DeviceType_e(inquiry.inqstd.type);
00803         log_DBG_m(dbg_DETAIL, "Device type: "
00804                 << scsi_GetDeviceTypeText(m_deviceType)
00805                 << "(" << m_deviceType << ")");
00806         m_vendorID = string(
00807             (const char*)inquiry.inqstd.vendorID, inqstd_VENDOR_ID_LEN_d);
00808         m_productID = string(
00809             (const char*)inquiry.inqstd.productID, inqstd_PRODUCT_ID_LEN_d);
00810         m_productRevision = string(
00811             (const char*)inquiry.inqstd.productRevision, inqstd_PROD_REVISION_LEN_d);
00812         m_standard = inquiry.inqstd.ansi;
00813     }
00814 
00815     try {
00816         if ( (m_deviceType == dt_MEDIUM_CHANGER) || (m_deviceType == dt_TAPE)) {
00817             // Supported pages
00818             cdb_Inquiry pages(data_Inquiry::inq_PAGES);
00819             IOCtl(pages);
00820 
00821             const data_Inquiry_t &inquiry = pages.GetInquiry().GetInquiryData();
00822             string strpages;
00823 
00824             for (int i = 0; i < inquiry.supportedPages.pageLen; i++) {
00825                 strpages += cmn_Num2Str(inquiry.supportedPages.pages[i], true) + " ";
00826                 m_supportedPages.push_back(
00827                     (data_Inquiry::inq_Page_t)inquiry.supportedPages.pages[i]);
00828             }
00829             log_DBG_m(dbg_LOW, "Supported INQUIRY pages " << strpages);
00830         }
00831         else {
00832             log_DBG_m(dbg_LOW, "Device type ("
00833                     << scsi_GetDeviceTypeText(m_deviceType)
00834                     << ") not supported. => INQUIRY pages empty");
00835         }
00836     }
00837     catch (const ivd_Error& ie) {
00838         log_DBG_m(dbg_NORM,
00839             "Vital product data not supported by this device." <<
00840             ie.GetFriendly());
00841     }
00842 
00843     m_vndSenseText = scsi_GetVndAddSnsTbl(m_vendorID, m_productID);
00844 }

Here is the call graph for this function:

Here is the caller graph for this function:

void scsi_IO::InqSerialNumber (  )  [protected]

Do inquiries necessary to get the serial number of the device.

Do inquiries necessary to get the serial number of the SCSI device.

Warning:
May not be successful; not all devices support serial #.

Definition at line 847 of file scsi_io.cpp.

References dbg_DETAIL, dbg_LOW, dbg_NORM, data_InqDeviceID_t::devID, data_Inquiry_t::devID, cdb_Inquiry::GetInquiry(), data_Inquiry::GetInquiryData(), id, data_InqDevId_t::idType, ie_NYI, ie_SCSI_INVRESULT, data_InqDevId_t::ieee, data_Inquiry::inq_DEVID, data_Inquiry::inq_SERNO, IOCtl(), IsPageSupported(), log_DBG_m, log_ERR_m, log_FUNC_m, log_WRN_m, m_productSerialNumber, data_InqDeviceID_t::pageLen, data_InqSerialNo_t::pageLen, data_InqDevId_t::pcph, data_Inquiry::pg_DEVID, data_Inquiry::pg_SERNO, data_InqSerialNo_t::serNumber, data_Inquiry_t::serNumber, and data_InqDevId_t::vendor.

Referenced by scsi_LnxSG::OpenByDeviceName().

00847                               {
00848     log_FUNC_m(InqSerialNumber);
00849 
00850     try {
00851         if (IsPageSupported(data_Inquiry::pg_SERNO)) {
00852             // Serial number page
00853             cdb_Inquiry ser(data_Inquiry::inq_SERNO);
00854             IOCtl(ser);
00855             const data_Inquiry_t &inquiry = ser.GetInquiry().GetInquiryData();
00856             log_DBG_m(dbg_DETAIL,
00857                 "serNumber.pageLen = " << (int)(inquiry.serNumber.pageLen));
00858 
00859             if (inquiry.serNumber.pageLen > 0) {
00860 
00861                 m_productSerialNumber = string(
00862                     (const char*)inquiry.serNumber.serNumber,
00863                     inquiry.serNumber.pageLen);
00864 
00865                  // strip potentional trailing blanks
00866                 string::size_type last = m_productSerialNumber.find_last_not_of(string(" \0",2));
00867                 if ( (last != string::npos) && ((last+1) < m_productSerialNumber.size())) {
00868                     m_productSerialNumber.erase(last+1);
00869                 }
00870 
00871                 log_DBG_m(dbg_LOW,
00872                     "Device serial number " << m_productSerialNumber);
00873             }
00874             else {
00875                 log_WRN_m(
00876                     "Serial number page supported but it does not contain any info");
00877             }
00878         }
00879         else if (IsPageSupported(data_Inquiry::pg_DEVID)) {
00880             // Device ID
00881             log_WRN_m("pg_DEVID is untested. Will it work??");
00882             cdb_Inquiry id(data_Inquiry::inq_DEVID);
00883             IOCtl(id);
00884             const data_Inquiry_t &inquiry = id.GetInquiry().GetInquiryData();
00885             if (inquiry.devID.pageLen > 0) {
00886                 switch (inquiry.devID.devID.idType) {
00887                     case 1:
00888                         log_DBG_m(dbg_NORM, "Serial number from DEV ID.");
00889                         m_productSerialNumber = string(
00890                             (const char*)inquiry.devID.devID.vendor.serialNo,
00891                             inquiry.devID.pageLen-8-16);
00892                         break;
00893                     case 2:
00894                         log_ERR_m("IEEE INQ page not supported: " <<
00895                             string((const char*)inquiry.devID.devID.ieee, 64) );
00896                         throw ivd_InternalError(ie_SCSI_INVRESULT);
00897                         break;
00898                     case 3:
00899                         log_ERR_m("PCPH INQ page not supported: " <<
00900                             string((const char*)inquiry.devID.devID.pcph, 64) );
00901                         throw ivd_InternalError(ie_SCSI_INVRESULT);
00902                         break;
00903                     default:
00904                         log_ERR_m("Unknown DEV ID Type " << inquiry.devID.devID.idType);
00905                         throw ivd_InternalError(ie_SCSI_INVRESULT);
00906                         break;
00907                 }
00908                 log_DBG_m(dbg_LOW, "Device serial number " << m_productSerialNumber);
00909                 throw ivd_InternalError(ie_NYI, "Device ID Inquiry");
00910             }
00911             else {
00912                 log_WRN_m(
00913                     "Device ID page supported but it does not contain any info.");
00914             }
00915         } // if (IsPage...
00916         else {
00917             log_DBG_m(dbg_LOW, "Device does not support serial number.");
00918         }
00919     }
00920     catch (ivd_Error &ie) {
00921         log_DBG_m(dbg_NORM, "Error doing device version inquiry: " << endl << ie);
00922         throw;
00923     }
00924     catch (ivd_SysError &ie) {
00925         log_DBG_m(dbg_NORM, "Error doing device version inquiry: " << endl << ie);
00926         throw;
00927     }
00928 }

Here is the call graph for this function:

Here is the caller graph for this function:

virtual int scsi_IO::DoIOCtl ( const scsi_CDB a_cdb,
UInt32_t  a_timeout 
) [protected, pure virtual]

Function to actually execute CDB commands.

Returns:
result code of platform specific ioctl command.

Implemented in scsi_LnxSG, and scsi_WinSG.

Referenced by IOCtl().

Here is the caller graph for this function:

virtual void scsi_IO::CheckDriverStatus ( UInt8_t  a_cdbCode  )  [inline, protected, virtual]

Checks the status of the driver after the execution of CDB.

Reimplemented in scsi_LnxSG, and scsi_WinSG.

Definition at line 137 of file scsi_io.h.

Referenced by IOCtl().

00137                                                       {
00138         // No driver checking by default
00139     }

Here is the caller graph for this function:

virtual void scsi_IO::CheckHostStatus ( UInt8_t  a_cdbCode  )  [inline, protected, virtual]

Checks the status of the host (if available) after the execution of CDB.

Reimplemented in scsi_LnxSG, and scsi_WinSG.

Definition at line 144 of file scsi_io.h.

Referenced by IOCtl().

00144                                                     {
00145         // No host checking by default
00146     }

Here is the caller graph for this function:

void scsi_IO::CheckStatusAndSense ( const scsi_CDB a_cdb  )  [protected]

Checks the execution status and sense structure.

Analysing the SCSI sense buffer.

Platform independent check.

Exceptions:
ivd_Error Throws different exceptions for each of the statuses.

Definition at line 540 of file scsi_io.cpp.

References data_Sense_t::additionalLen, data_Sense_t::ait, data_Sense_t::asc, data_Sense_t::ascq, data_AIT_Sense_t::clean, cmn_HexDump(), dbg_DETAIL, dt_TAPE, data_Sense_t::eom, evt_CRITICAL, evt_ERROR, evt_WARNING, data_Sense_t::fileMark, scsi_CDB::GetBufferPointer(), scsi_CDB::GetBufferSize(), GetCDBStatus(), scsi_CDB::GetCmdPointer(), scsi_CDB::GetCmdSize(), ie_SCSI_BLANK, ie_SCSI_DESTFULL, ie_SCSI_EOD, ie_SCSI_EOM, ie_SCSI_FILEMARK, ie_SCSI_HWERR, ie_SCSI_ILENGTH, ie_SCSI_ILREQ, ie_SCSI_MEDERR, ie_SCSI_NO_MEDIUM, ie_SCSI_NOT_READY, ie_SCSI_OVERFLOW, ie_SCSI_PROTECTED, ie_SCSI_RETRY, ie_SCSI_SENSE, ie_SCSI_SRCEMPTY, ie_SCSI_STATUS, ie_SCSI_UNIT_ATT, data_Sense_t::incorrectLength, IsSenseValid(), ivd_Error, log_DBG_m, log_FUNC_m, log_MARKLINE_m, log_WriteEvent(), log_WRN_m, m_deviceType, m_possibleMediumChange, m_productID, m_productRevision, m_productSerialNumber, m_sense, m_strSCSIID, m_vendorID, m_vndSenseText, data_AIT_Sense_t::mew, scsi_GetASCText(), scsi_GetOpcodeText(), scsi_GetSenseKeyText(), scsi_GetSenseText(), scsi_GetStatusText(), data_Sense_t::senseKey, sk_ABORTED_COMMAND, sk_BLANK_CHECK, sk_COPY_ABORTED, sk_DATA_PROTECT, sk_HARDWARE_ERROR, sk_ILLEGAL_REQUEST, sk_MEDIUM_ERROR, sk_MISCOMPARE, sk_NO_SENSE, sk_NOT_READY, sk_OBSOLETE, sk_RECOVERED_ERROR, sk_RESERVED, sk_UNIT_ATTENTION, sk_VENDOR_SPECIFIC, sk_VOLUME_OVERFLOW, st_ACA_ACTIVE, st_BUSY, st_CHECK_CONDITION, st_COMMAND_TERMINATED, st_CONDITION_GOOD, st_GOOD, st_INTERMEDIATE_C_GOOD, st_INTERMEDIATE_GOOD, st_QUEUE_FULL, and st_RESERVATION_CONFLICT.

Referenced by IOCtl().

00540                                                        {
00541 
00542     if (!IsSenseValid()) {
00543         return;
00544     }
00545 
00546     log_FUNC_m(CheckStatusAndSense);
00547 
00548     scsi_Status_e status = GetCDBStatus();
00549 
00550     log_DBG_m(dbg_DETAIL,
00551         "CDB Status: 0x" <<
00552         hex << status << dec << " " <<
00553         scsi_GetStatusText(status)
00554     );
00555 
00556     // HEX dump of a command.
00557     const UInt8_t *cdb = a_cdb.GetCmdPointer();
00558     UInt8_t cdbCode = cdb[0];
00559     UInt32_t cdbSize = a_cdb.GetCmdSize();
00560     // HEX dump of data.
00561     UInt8_t *data = a_cdb.GetBufferPointer();
00562     UInt32_t dataSize = a_cdb.GetBufferSize();
00563 
00564     string senseTxt = scsi_GetSenseText(m_sense, m_deviceType, m_vndSenseText);
00565 
00566     ostringstream shortText;
00567     shortText
00568         << scsi_GetSenseKeyText((scsi_SenseKey_e)m_sense.senseKey)
00569         << " (" << scsi_GetASCText(m_sense, m_vndSenseText) << ")";
00570 
00571     // Detailed dump
00572     ostringstream dump;
00573     dump
00574         << "Device: " << m_vendorID << " " << m_productID << " "
00575         << m_productRevision << " s/n: " << m_productSerialNumber << endl
00576         << senseTxt << endl
00577         << "Sense dump (" << static_cast<UInt32_t>(m_sense.additionalLen+8) << " bytes) :" << endl
00578         << cmn_HexDump(
00579             reinterpret_cast<const void*>(&m_sense), m_sense.additionalLen+8, 8, true) << endl
00580 
00581         << "CDB: " << scsi_GetOpcodeText(cdbCode) << endl
00582         << cmn_HexDump(
00583             reinterpret_cast<const void*>(cdb), cdbSize, 8, true) << endl
00584 
00585         << "DATA length: " << dataSize << endl
00586         << "DATA:" << endl
00587         << cmn_HexDump(
00588             reinterpret_cast<const void*>(data), (dataSize < 256)? dataSize : 256, 16, true);
00589 
00590 
00591     switch (status) {
00592         case st_GOOD:
00593             break;
00594         case st_CHECK_CONDITION:
00595         case st_BUSY:
00596         case st_COMMAND_TERMINATED:
00597             break;
00598         case st_RESERVATION_CONFLICT:
00599             log_MARKLINE_m;
00600             throw ivd_InternalError(
00601                 ie_SCSI_STATUS, "Reservation not used.", dump.str());
00602             break;
00603 
00604         case st_CONDITION_GOOD:
00605         case st_INTERMEDIATE_GOOD:
00606         case st_INTERMEDIATE_C_GOOD:
00607         case st_QUEUE_FULL:
00608         case st_ACA_ACTIVE:
00609         default:
00610             log_MARKLINE_m;
00611             throw ivd_InternalError(
00612                 ie_SCSI_STATUS, scsi_GetStatusText(status), dump.str());
00613             break;
00614     }
00615 
00616     //
00617     // Detect and log cleaning and media warning (works for AIT tape drives)
00618     //
00619     if (m_deviceType == dt_TAPE && m_sense.additionalLen > 19) {
00620         if (m_sense.ait.clean != 0) {
00621             ostringstream sstr;
00622             sstr
00623                 << "Device: " << m_vendorID << " " << m_productID << " "
00624                 << m_productRevision << " s/n: " << m_productSerialNumber
00625                 << " is requesting cleaning.";
00626             log_WriteEvent(
00627                 evt_WARNING, sstr.str(), "SCSI", 0, m_strSCSIID);
00628         }
00629         if (m_sense.ait.mew != 0) {
00630             ostringstream sstr;
00631             sstr
00632                 << "Device: " << m_vendorID << " " << m_productID << " "
00633                 << m_productRevision << " s/n: " << m_productSerialNumber
00634                 << " is reporting media warning.";
00635             log_WriteEvent(
00636                 evt_WARNING, sstr.str(), "SCSI", 0, m_strSCSIID);
00637         }
00638     }
00639 
00640     // Decode sense information
00641     if (status == st_BUSY || status == st_COMMAND_TERMINATED) {
00642         log_MARKLINE_m;
00643         throw ivd_Error(ie_SCSI_RETRY, shortText.str(), dump.str(), true);
00644     }
00645     switch (m_sense.senseKey) {
00646         case sk_ILLEGAL_REQUEST:
00647             log_MARKLINE_m;
00648             if (m_sense.asc == 0x3B && m_sense.ascq == 0x0D) {
00649                 log_WriteEvent(
00650                     evt_WARNING,
00651                     shortText.str(), "SCSI", 0, m_strSCSIID);
00652                 throw ivd_Error(ie_SCSI_DESTFULL, shortText.str(), dump.str());
00653             }
00654             else if (m_sense.asc == 0x3B && m_sense.ascq == 0x0E) {
00655                 log_WriteEvent(
00656                     evt_WARNING,
00657                     shortText.str(), "SCSI", 0, m_strSCSIID);
00658                 throw ivd_Error(ie_SCSI_SRCEMPTY, shortText.str(), dump.str());
00659             }
00660             log_WriteEvent(
00661                 evt_ERROR,
00662                 shortText.str(), "SCSI", 0, m_strSCSIID);
00663             throw ivd_Error(ie_SCSI_ILREQ, shortText.str(), dump.str(), true);
00664             break;
00665         case sk_NOT_READY:
00666             log_MARKLINE_m;
00667             if (m_sense.asc == 0x3A) {
00668                 throw ivd_Error(ie_SCSI_NO_MEDIUM, shortText.str(), dump.str());
00669             }
00670             throw ivd_Error(ie_SCSI_NOT_READY, shortText.str(), dump.str());
00671             break;
00672         case sk_RECOVERED_ERROR:
00673             log_MARKLINE_m;
00674             // See SCSI documentation (or scsi_err.cpp) for details.
00675             if (m_sense.asc == 0x00 && m_sense.ascq == 0x01) {
00676                 throw ivd_Error(ie_SCSI_FILEMARK, shortText.str(), dump.str());
00677             }
00678             if (m_sense.asc == 0x00 && m_sense.ascq == 0x02) {
00679                 throw ivd_Error(ie_SCSI_EOM, shortText.str(), dump.str());
00680             }
00681             // Else log and check file mark, etc after the switch.
00682             log_WRN_m("RECOVERED ERROR: " << dump.str());
00683             break;
00684         case sk_MEDIUM_ERROR:
00685             log_MARKLINE_m;
00686             log_WriteEvent(evt_ERROR, shortText.str(), "SCSI", 0, m_strSCSIID);
00687             throw ivd_Error(ie_SCSI_MEDERR, shortText.str(), dump.str(), true);
00688             break;
00689         case sk_HARDWARE_ERROR:
00690             log_MARKLINE_m;
00691             log_WriteEvent(evt_ERROR, shortText.str(), "SCSI", 0, m_strSCSIID);
00692             throw ivd_Error(ie_SCSI_HWERR, shortText.str(), dump.str(), true);
00693             break;
00694         case sk_UNIT_ATTENTION:
00695             log_MARKLINE_m;
00696             // See SCSI documentation (or scsi_err.cpp) for details.
00697             if (   ((m_sense.asc  == 0x28) && (m_sense.ascq == 0x00))
00698                 || ((m_sense.asc  == 0x29) && (m_sense.ascq == 0x00)) ) {
00699                 // 28: Not ready to transition (medium may have changed)
00700                 // 29: Power on, reset, or bus device reset occurred
00701                 m_possibleMediumChange = true;
00702             }
00703             throw ivd_Error(ie_SCSI_UNIT_ATT, shortText.str(), dump.str());
00704             break;
00705         case sk_DATA_PROTECT:
00706             log_MARKLINE_m;
00707             throw ivd_Error(ie_SCSI_PROTECTED, shortText.str(), dump.str(), true);
00708             break;
00709         case sk_BLANK_CHECK:
00710             log_MARKLINE_m;
00711             // See SCSI documentation (or scsi_err.cpp) for details.
00712             if (m_sense.asc  == 0x00 && m_sense.ascq == 0x05) {
00713                 throw ivd_Error(ie_SCSI_EOD, shortText.str(), dump.str());
00714             }
00715             throw ivd_Error(ie_SCSI_BLANK, shortText.str(), dump.str());
00716             break;
00717         case sk_VOLUME_OVERFLOW:
00718             log_MARKLINE_m;
00719             log_WriteEvent(
00720                 evt_WARNING,
00721                 shortText.str() + " Physical end of medium or media volume",
00722                 "SCSI", 0, m_strSCSIID);
00723             throw ivd_Error(ie_SCSI_OVERFLOW, shortText.str(), dump.str(), true);
00724             break;
00725 
00726         // The following sense codes are treated as critical.
00727         case sk_VENDOR_SPECIFIC:
00728             log_MARKLINE_m;
00729             //
00730             // Throw ivd_Error for:
00731             //   AIT: MIC exists but is not used.
00732             //
00733             if (m_sense.asc  == 0x83 &&
00734                 m_sense.ascq == 0x83) {
00735                 throw ivd_Error(ie_SCSI_SENSE, shortText.str(), dump.str());
00736             }
00737 
00738             log_WriteEvent(
00739                 evt_CRITICAL,
00740                 shortText.str(), "SCSI", 0, m_strSCSIID);
00741 
00742             throw ivd_Error(ie_SCSI_SENSE, shortText.str(), dump.str(), true);
00743             break;
00744         case sk_COPY_ABORTED:
00745         case sk_ABORTED_COMMAND:
00746         case sk_OBSOLETE:
00747         case sk_MISCOMPARE:
00748         case sk_RESERVED:
00749             log_MARKLINE_m;
00750 
00751             log_WriteEvent(
00752                 evt_CRITICAL,
00753                 shortText.str(), "SCSI", 0, m_strSCSIID);
00754 
00755             throw ivd_Error(ie_SCSI_SENSE, shortText.str(), dump.str(), true);
00756             break;
00757         case sk_NO_SENSE:
00758             log_MARKLINE_m;
00759             log_DBG_m(dbg_DETAIL, "No sense.");
00760             break;
00761         default:
00762             log_MARKLINE_m;
00763 
00764             log_WriteEvent(
00765                 evt_CRITICAL,
00766                 shortText.str(), "SCSI", 0, m_strSCSIID);
00767 
00768             throw ivd_InternalError(
00769                 ie_SCSI_SENSE,
00770                 string("Unknown sense key! ") + shortText.str(), dump.str());
00771             break;
00772     }
00773 
00774     // sk_NO_SENSE
00775 
00776     // We prefer to have file mark reported over the early end of medium
00777     if (m_sense.fileMark) {
00778         log_MARKLINE_m;
00779         throw ivd_Error(ie_SCSI_FILEMARK, shortText.str(), dump.str());
00780     }
00781     if (m_sense.eom) {
00782         log_MARKLINE_m;
00783         throw ivd_Error(ie_SCSI_EOM, shortText.str(), dump.str());
00784     }
00785     if (m_sense.incorrectLength) {
00786         log_MARKLINE_m;
00787         throw ivd_Error(ie_SCSI_ILENGTH, shortText.str(), dump.str());
00788     }
00789 }

Here is the call graph for this function:

Here is the caller graph for this function:

void scsi_IO::Inquiry (  )  [protected]

bool scsi_IO::IsPageSupported ( data_Inquiry::inq_Page_t  a_page  )  [inline, private]

Definition at line 205 of file scsi_io.h.

Referenced by InqSerialNumber().

00205                                                         {
00206         for (unsigned int i = 0; i < m_supportedPages.size(); i++) {
00207             if (m_supportedPages[i] == a_page) {
00208                 return true;
00209             }
00210         }
00211         return false;
00212     }

Here is the caller graph for this function:


Member Data Documentation

string scsi_IO::m_deviceID [protected]

Unique device identification, passed in constructor or SetDeviceID.

Definition at line 158 of file scsi_io.h.

Referenced by scsi_LnxSG::Close(), IOCtl(), Open(), SetDeviceID(), SkipAttAndDeferred(), and WaitToBecomeReady().

string scsi_IO::m_deviceName [protected]

Device name.

It can be a file system entry or whatever name that uniquely identifies the SCSI device on a certain platform.

Definition at line 164 of file scsi_io.h.

Referenced by GetDeviceName(), Open(), scsi_LnxSG::OpenByDeviceName(), scsi_LnxSG::SGOpen(), SkipAttAndDeferred(), WaitToBecomeReady(), and scsi_LnxSG::~scsi_LnxSG().

Also known as bus or host.

Definition at line 167 of file scsi_io.h.

Referenced by GetPort(), GetSCSIID(), scsi_LnxSG::InqSCSIID(), Open(), and scsi_LnxSG::OpenBySCSIID().

UInt32_t scsi_IO::m_id [protected]

Definition at line 169 of file scsi_io.h.

Referenced by GetID(), GetSCSIID(), scsi_LnxSG::InqSCSIID(), Open(), and scsi_LnxSG::OpenBySCSIID().

UInt32_t scsi_IO::m_lun [protected]

Definition at line 170 of file scsi_io.h.

Referenced by GetLUN(), GetSCSIID(), scsi_LnxSG::InqSCSIID(), Open(), and scsi_LnxSG::OpenBySCSIID().

string scsi_IO::m_strSCSIID [protected]

string scsi_IO::m_vendorID [protected]

string scsi_IO::m_productID [protected]

string scsi_IO::m_productSerialNumber [protected]

Definition at line 178 of file scsi_io.h.

Referenced by CheckStatusAndSense(), InqStandard(), and WaitToBecomeReady().

string scsi_IO::m_productRevision [protected]

Definition at line 182 of file scsi_io.h.

Referenced by CheckStatusAndSense(), GetDeviceType(), InqStandard(), Open(), and WaitToBecomeReady().

Definition at line 184 of file scsi_io.h.

Referenced by InqStandard().

Definition at line 186 of file scsi_io.h.

Referenced by GetStandard(), InqStandard(), and Open().

Definition at line 187 of file scsi_io.h.

Referenced by CheckStatusAndSense(), GetPossibleMediumChange(), and Open().

bool scsi_IO::m_pdDirectMode [protected]

Direct passthrough mode can be disabled via env variable.

Definition at line 192 of file scsi_io.h.

Referenced by scsi_LnxSG::DoIOCtl(), and scsi_IO().

Default timeouts can be overridden with env.

variable.

Definition at line 195 of file scsi_io.h.

Referenced by IOCtl(), and scsi_IO().

Definition at line 199 of file scsi_io.h.

Referenced by IOCtl(), and scsi_IO().

Definition at line 200 of file scsi_io.h.

Referenced by IOCtl(), and scsi_IO().

Reimplemented in scsi_LnxSG, and scsi_WinSG.

Definition at line 203 of file scsi_io.h.


The documentation for this class was generated from the following files:

Generated on Mon Feb 27 19:50:09 2012 for OPENARCHIVE by  doxygen 1.5.6