#include <scsi_lnxsg.h>


Definition at line 28 of file scsi_lnxsg.h.
Public Member Functions | |
| scsi_LnxSG (const string &a_deviceID) | |
| virtual | ~scsi_LnxSG () |
| virtual bool | IsOpen () |
| virtual void | Close () |
Protected Member Functions | |
| virtual void | OpenByDeviceName () |
| Open SCSI device by its (platform specific!) name. | |
| virtual void | OpenBySCSIID () |
| Open SCSI device by its (current) SCSI ID. | |
| virtual void | OpenBySerialNumber () |
| Open SCSI device by its unique identification. | |
| virtual void | InqSCSIID () |
| Get SCSI ID of the currently opened device. | |
| int | DoIOCtl (const scsi_CDB &a_cdb, UInt32_t a_timeout) |
| Function to actually execute CDB commands. | |
| virtual scsi_Status_e | GetCDBStatus () |
| 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. | |
| virtual bool | IsSenseValid () |
Private Member Functions | |
| void | SGOpen (bool a_readOnly=false, bool a_excl=false) |
| bool | Reset (int what) |
Private Attributes | |
| log_CLASSID_m | |
| int | m_handle |
| sg_io_hdr_t | m_ioHdr |
| scsi_LnxSG::scsi_LnxSG | ( | const string & | a_deviceID | ) |
Definition at line 43 of file scsi_lnxsg.cpp.
References log_FUNC_m.
00044 : scsi_IO(a_DeviceID), 00045 m_handle(-1) { 00046 00047 log_FUNC_m(scsi_LnxSG); 00048 }
| scsi_LnxSG::~scsi_LnxSG | ( | ) | [virtual] |
Definition at line 54 of file scsi_lnxsg.cpp.
References Close(), IsOpen(), log_FUNC_m, log_WRN_m, and scsi_IO::m_deviceName.
00054 { 00055 log_FUNC_m(~scsi_LnxSG); 00056 00057 if (IsOpen()) { 00058 log_WRN_m("Device not yet closed! Closing device " << m_deviceName); 00059 Close(); 00060 } 00061 }

| bool scsi_LnxSG::IsOpen | ( | ) | [virtual] |
Implements scsi_IO.
Definition at line 50 of file scsi_lnxsg.cpp.
References m_handle.
Referenced by ~scsi_LnxSG().
00050 { 00051 return (m_handle >= 0); 00052 }

| void scsi_LnxSG::Close | ( | ) | [virtual] |
Implements scsi_IO.
Definition at line 173 of file scsi_lnxsg.cpp.
References dbg_LOW, ie_SCSI_CLOSE, ivd_Error, log_DBG_m, log_FUNC_m, log_MARKLINE_m, scsi_IO::m_deviceID, and m_handle.
Referenced by ~scsi_LnxSG().
00173 { 00174 log_FUNC_m(Close); 00175 00176 log_DBG_m(dbg_LOW, "Closing device ID: " << m_deviceID); 00177 00178 if (m_handle < 0) { 00179 log_MARKLINE_m; 00180 throw ivd_Error(ie_SCSI_CLOSE); 00181 } 00182 close(m_handle); 00183 m_handle = -1; 00184 }

| void scsi_LnxSG::OpenByDeviceName | ( | ) | [protected, virtual] |
Open SCSI device by its (platform specific!) name.
Implements scsi_IO.
Definition at line 63 of file scsi_lnxsg.cpp.
References dbg_LOW, InqSCSIID(), scsi_IO::InqSerialNumber(), scsi_IO::InqStandard(), log_DBG_m, log_FUNC_m, scsi_IO::m_deviceName, and SGOpen().
00063 { 00064 log_FUNC_m(OpenByDeviceName); 00065 00066 log_DBG_m(dbg_LOW, "Opening device file: " << m_deviceName); 00067 00068 SGOpen(false, true); 00069 00070 InqSCSIID(); 00071 InqStandard(); 00072 InqSerialNumber(); 00073 }

| void scsi_LnxSG::OpenBySCSIID | ( | ) | [protected, virtual] |
Open SCSI device by its (current) SCSI ID.
Implements scsi_IO.
Definition at line 75 of file scsi_lnxsg.cpp.
References dbg_LOW, log_DBG_m, log_FUNC_m, scsi_IO::m_channel, scsi_IO::m_id, scsi_IO::m_lun, and scsi_IO::m_port.
00075 { 00076 log_FUNC_m(OpenBySCSIID); 00077 00078 log_DBG_m(dbg_LOW, 00079 "Opening SCSI ID: " << 00080 m_port << ":" << 00081 m_channel << ":" << 00082 m_id << ":" << 00083 m_lun); 00084 00085 }
| void scsi_LnxSG::OpenBySerialNumber | ( | ) | [protected, virtual] |
Open SCSI device by its unique identification.
Implements scsi_IO.
Definition at line 87 of file scsi_lnxsg.cpp.
References dbg_LOW, log_DBG_m, log_FUNC_m, scsi_IO::m_productID, scsi_IO::m_productSerialNumber, and scsi_IO::m_vendorID.
00087 { 00088 log_FUNC_m(OpenBySerialNumber); 00089 00090 log_DBG_m(dbg_LOW, 00091 "Opening SCSI Serial #: " << 00092 m_vendorID << ":" << 00093 m_productID << ":" << 00094 m_productSerialNumber); 00095 00096 }
| void scsi_LnxSG::InqSCSIID | ( | ) | [protected, virtual] |
Get SCSI ID of the currently opened device.
Implements scsi_IO.
Definition at line 291 of file scsi_lnxsg.cpp.
References dbg_EXTAPI, errno, scsi_IO::GetSCSIID(), log_DBG_m, log_FUNC_m, log_MARKLINE_m, scsi_IO::m_channel, m_handle, scsi_IO::m_id, scsi_IO::m_lun, scsi_IO::m_port, and scsi_IO::m_strSCSIID.
Referenced by OpenByDeviceName().
00291 { 00292 log_FUNC_m(InqSCSIID); 00293 00294 struct sg_scsi_id scsiID; 00295 00296 log_DBG_m(dbg_EXTAPI, "ioctl(.., SG_GET_SCSI_ID, ..)") 00297 int result = ioctl(m_handle, SG_GET_SCSI_ID, (void*)(&scsiID)); 00298 if (result != 0) { 00299 log_MARKLINE_m; 00300 throw ivd_SysError(errno, 00301 "ioctl(.., SG_GET_SCSI_ID, ..) returned error"); 00302 } 00303 00304 m_port = scsiID.host_no; 00305 m_channel = scsiID.channel; 00306 m_id = scsiID.scsi_id; 00307 m_lun = scsiID.lun; 00308 00309 m_strSCSIID = GetSCSIID(); 00310 }


Function to actually execute CDB commands.
Implements scsi_IO.
Definition at line 186 of file scsi_lnxsg.cpp.
References dbg_DETAIL, dbg_EXTAPI, errno, scsi_CDB::GetBufferPointer(), scsi_CDB::GetBufferSize(), scsi_CDB::GetCmdPointer(), scsi_CDB::GetCmdSize(), scsi_IO::GetSense(), scsi_IO::GetSenseSize(), scsi_CDB::GetTransferDirection(), log_DBG_m, log_FUNC_m, m_handle, m_ioHdr, scsi_IO::m_pdDirectMode, MIN_DIRECT_BUFFER_SIZE, op_READ_10, op_READ_6, op_WRITE_10, and op_WRITE_6.
00186 { 00187 log_FUNC_m(DoIOCtl); 00188 00189 memset(&m_ioHdr, 0, sizeof(m_ioHdr)); 00190 m_ioHdr.interface_id = static_cast<int>('S'); 00191 m_ioHdr.dxfer_direction = a_cdb.GetTransferDirection(); 00192 00193 m_ioHdr.cmdp = const_cast<unsigned char*>(a_cdb.GetCmdPointer()); 00194 m_ioHdr.cmd_len = a_cdb.GetCmdSize(); 00195 00196 // Don't use scatter-gather, we use direct IO, so set this to 0. 00197 m_ioHdr.iovec_count = 0; 00198 00199 m_ioHdr.dxfer_len = 00200 static_cast<const unsigned int>(a_cdb.GetBufferSize()); 00201 00202 m_ioHdr.dxferp = 00203 reinterpret_cast<unsigned char *>(a_cdb.GetBufferPointer()); 00204 00205 // Set pointers to sense structure 00206 m_ioHdr.mx_sb_len = GetSenseSize(); 00207 m_ioHdr.sbp = 00208 reinterpret_cast<UInt8_t*>(const_cast<data_Sense_t*>(GetSense())); 00209 00210 UInt8_t cdbCode = a_cdb.GetCmdPointer()[0]; 00211 00212 if (cdbCode == op_READ_6 || cdbCode == op_READ_10 || 00213 cdbCode == op_WRITE_6 || cdbCode == op_WRITE_10) { 00214 // 00215 // Do not transfer buffers from user space to kernel 00216 // space for larger blocks of data when doing read/write operations 00217 // (use direct IO instead). 00218 // 00219 // Direct IO can also be disabled via env variable SG_NO_DIO! 00220 // 00221 if (m_ioHdr.dxfer_len > MIN_DIRECT_BUFFER_SIZE && m_pdDirectMode) { 00222 m_ioHdr.flags |= SG_FLAG_DIRECT_IO; 00223 } 00224 }; 00225 00226 m_ioHdr.timeout = a_timeout; 00227 00228 log_DBG_m(dbg_EXTAPI, "ioctl(.., SG_IO, ..)") 00229 int result = ioctl(m_handle, SG_IO, &m_ioHdr); 00230 if (result == -1) { 00231 log_DBG_m(dbg_DETAIL, "Return errno: " << errno) 00232 return errno; 00233 } 00234 else { 00235 log_DBG_m(dbg_DETAIL , "Return result: " << result) 00236 return result; 00237 } 00238 }

| virtual scsi_Status_e scsi_LnxSG::GetCDBStatus | ( | ) | [inline, protected, virtual] |
Implements scsi_IO.
Definition at line 47 of file scsi_lnxsg.h.
References m_ioHdr, and st_STATUS_MASK.
Referenced by IsSenseValid().
00047 { 00048 return (scsi_Status_e)(m_ioHdr.status & st_STATUS_MASK); 00049 }

| void scsi_LnxSG::CheckDriverStatus | ( | UInt8_t | a_cdbCode | ) | [protected, virtual] |
Checks the status of the driver after the execution of CDB.
Reimplemented from scsi_IO.
Definition at line 240 of file scsi_lnxsg.cpp.
References dbg_NORM, DRIVER_MASK, evt_ERROR, ie_SCSI_DRIVER, ivd_Error, log_DBG_m, log_FUNC_m, log_MARKLINE_m, log_WriteEvent(), m_ioHdr, scsi_IO::m_strSCSIID, scsi_CommandSize(), scsi_GetOpcodeText(), SG_ERR_DRIVER_OK, and SG_ERR_DRIVER_SENSE.
00240 { 00241 if ( m_ioHdr.driver_status == SG_ERR_DRIVER_OK || 00242 (m_ioHdr.driver_status & DRIVER_MASK) == SG_ERR_DRIVER_SENSE) { 00243 return; 00244 } 00245 log_FUNC_m(CheckDriverStatus); 00246 00247 ostringstream sstr; 00248 sstr 00249 << "Driver status code: " 00250 << hex << m_ioHdr.driver_status << dec 00251 << " CDB: " << scsi_GetOpcodeText(a_cdbCode); 00252 00253 // Some Linux drivers report that they don't support large CDBs in 00254 // driver status. 00255 if (scsi_CommandSize(a_cdbCode) >= 16) { 00256 log_DBG_m(dbg_NORM, "Large CDB: " << sstr.str()); 00257 } 00258 else { 00259 log_WriteEvent(evt_ERROR, sstr.str(), "SCSI", 0, m_strSCSIID); 00260 } 00261 00262 log_MARKLINE_m; 00263 throw ivd_Error(ie_SCSI_DRIVER, sstr.str()); 00264 }

| void scsi_LnxSG::CheckHostStatus | ( | UInt8_t | a_cdbCode | ) | [protected, virtual] |
Checks the status of the host (if available) after the execution of CDB.
Reimplemented from scsi_IO.
Definition at line 266 of file scsi_lnxsg.cpp.
References dbg_NORM, evt_ERROR, ie_SCSI_HOST, ivd_Error, log_DBG_m, log_FUNC_m, log_MARKLINE_m, log_WriteEvent(), m_ioHdr, scsi_IO::m_strSCSIID, scsi_CommandSize(), scsi_GetOpcodeText(), and SG_ERR_DID_OK.
00266 { 00267 if (m_ioHdr.host_status == SG_ERR_DID_OK) { 00268 return; 00269 } 00270 log_FUNC_m(CheckHostStatus); 00271 00272 ostringstream sstr; 00273 sstr 00274 << "SCSI host status code: " 00275 << hex << m_ioHdr.host_status << dec 00276 << " CDB: " << scsi_GetOpcodeText(a_cdbCode); 00277 00278 // Some Linux drivers report that they don't support large CDBs in 00279 // host status. 00280 if (scsi_CommandSize(a_cdbCode) >= 16) { 00281 log_DBG_m(dbg_NORM, "Large CDB: " << sstr.str()); 00282 } 00283 else { 00284 log_WriteEvent(evt_ERROR, sstr.str(), "SCSI", 0, m_strSCSIID); 00285 } 00286 00287 log_MARKLINE_m; 00288 throw ivd_Error(ie_SCSI_HOST, sstr.str()); 00289 }

| virtual bool scsi_LnxSG::IsSenseValid | ( | ) | [inline, protected, virtual] |
Implements scsi_IO.
Definition at line 53 of file scsi_lnxsg.h.
References GetCDBStatus(), m_ioHdr, SG_ERR_DRIVER_SENSE, st_BUSY, st_CHECK_CONDITION, and st_COMMAND_TERMINATED.
00053 { 00054 scsi_Status_e status = GetCDBStatus(); 00055 int drvStatus = m_ioHdr.driver_status; 00056 00057 if (status == st_CHECK_CONDITION || 00058 status == st_COMMAND_TERMINATED || 00059 status == st_BUSY || 00060 drvStatus & SG_ERR_DRIVER_SENSE) { 00061 return true; 00062 } 00063 else { 00064 return false; 00065 } 00066 }

| void scsi_LnxSG::SGOpen | ( | bool | a_readOnly = false, |
|
| bool | a_excl = false | |||
| ) | [private] |
Definition at line 98 of file scsi_lnxsg.cpp.
References dbg_DETAIL, dbg_EXTAPI, dbg_LOW, errno, ie_SCSI_OPEN, ivd_Error, ivd_Sleep, log_DBG_m, log_FUNC_m, log_MARKLINE_m, scsi_IO::m_deviceName, and m_handle.
Referenced by OpenByDeviceName().
00098 { 00099 log_FUNC_m(SGOpen); 00100 00101 if (m_handle >= 0) { 00102 //device already opened 00103 log_MARKLINE_m; 00104 throw ivd_Error(ie_SCSI_OPEN); 00105 } 00106 00107 // Retry open 5 times 00108 for (int i = 5; i > 0; i--) { 00109 log_DBG_m(dbg_EXTAPI, "open(" << m_deviceName << ")"); 00110 00111 m_handle = open( 00112 m_deviceName.c_str(), 00113 (a_readOnly ? O_RDONLY : O_RDWR) 00114 | (a_excl ? O_EXCL : 0) 00115 | O_NONBLOCK); 00116 00117 if (m_handle < 0) { 00118 if (errno == EBUSY || errno == EINTR /*|| errno == ENXIO*/) { 00119 if (i == 1) { 00120 log_MARKLINE_m; 00121 throw ivd_SysError(errno, "open(" + m_deviceName + "...)"); 00122 } 00123 log_DBG_m(dbg_DETAIL, 00124 "open() failed. Retrying. Error: " << strerror(errno)); 00125 ivd_Sleep(1); 00126 continue; 00127 } 00128 else { 00129 log_MARKLINE_m; 00130 throw ivd_SysError(errno, "open(" + m_deviceName + "...)"); 00131 } 00132 } 00133 // open() successful. Break the loop. 00134 break; 00135 } 00136 log_DBG_m(dbg_LOW, "SCSI device handle: " << m_handle); 00137 00138 // It seems that the kernel needs some patch to support SCSI reset. 00139 /* 00140 Reset(SG_SCSI_RESET_DEVICE); 00141 Reset(SG_SCSI_RESET_BUS); 00142 Reset(SG_SCSI_RESET_HOST); 00143 */ 00144 00145 log_DBG_m(dbg_DETAIL, 00146 "Will try to read any garbage from previous usage of the device."); 00147 00148 { 00149 // defining local struct 00150 struct sg_rep { 00151 struct sg_header hd; 00152 unsigned char rbuf[100]; 00153 } sg_rep; 00154 00155 int flags; 00156 00157 flags = fcntl(m_handle, F_GETFL); /* Be very proper about this */ 00158 fcntl(m_handle, F_SETFL, flags|O_NONBLOCK); 00159 // TODO: Do additional checks of return value and errno!! 00160 00161 memset(&sg_rep, 0, sizeof(struct sg_header)); 00162 sg_rep.hd.reply_len = sizeof(struct sg_header); 00163 00164 while (read(m_handle, &sg_rep, sizeof(sg_rep)) >= 0 || 00165 errno != EAGAIN) { 00166 // NULL BODY 00167 }; 00168 00169 fcntl(m_handle, F_SETFL, flags); 00170 } 00171 }

| bool scsi_LnxSG::Reset | ( | int | what | ) | [private] |
Definition at line 313 of file scsi_lnxsg.cpp.
00313 { 00314 /* 00315 int k; 00316 int res; 00317 00318 k = what; 00319 res = ioctl(m_handle, SG_SCSI_RESET, &k); 00320 if (res < 0) { 00321 if (EBUSY == errno) 00322 printf("sg_reset: BUSY, may be resetting now\n"); 00323 else if (EIO == errno) 00324 printf("sg_reset: requested type of reset may not be available\n"); 00325 else if (EACCES == errno) 00326 printf("sg_reset: to do a reset needs root permission\n"); 00327 else 00328 printf("sg_reset: SG_SCSI_RESET not supported\n"); 00329 return false; 00330 } 00331 if (SG_SCSI_RESET_NOTHING == k) 00332 printf("sg_reset: did nothing, device is normal mode\n"); 00333 else { 00334 if (SG_SCSI_RESET_DEVICE == k) 00335 printf("sg_reset: started device reset\n"); 00336 else if (SG_SCSI_RESET_BUS == k) 00337 printf("sg_reset: started bus reset\n"); 00338 else if (SG_SCSI_RESET_HOST == k) 00339 printf("sg_reset: started host reset\n"); 00340 00341 printf("waiting for the reset to complete...\n"); 00342 int j = 0; 00343 k = SG_SCSI_RESET_NOTHING; 00344 do { 00345 if (0 != j) 00346 sleep(1); 00347 res = ioctl(m_handle, SG_SCSI_RESET, &k); 00348 ++j; 00349 } while ((res < 0) && (EBUSY == errno)); 00350 printf(" ... reset seemingly completed\n"); 00351 } 00352 */ 00353 return true; 00354 00355 }
scsi_LnxSG::log_CLASSID_m [private] |
int scsi_LnxSG::m_handle [private] |
Definition at line 71 of file scsi_lnxsg.h.
Referenced by Close(), DoIOCtl(), InqSCSIID(), IsOpen(), and SGOpen().
sg_io_hdr_t scsi_LnxSG::m_ioHdr [private] |
Definition at line 73 of file scsi_lnxsg.h.
Referenced by CheckDriverStatus(), CheckHostStatus(), DoIOCtl(), GetCDBStatus(), and IsSenseValid().
1.5.6