in source/code/scxsystemlib/disk/tools/ioctl_scan.cpp [219:355]
bool SqInq(const char *dev, int fd, int page, int evpd, void * dxferp, unsigned short dxfer_len, bool SCSIPowerMode,
string &availability)
{
availability = "Unknown";
/* SCSI INQUIRY command has 6 bytes, OPERATION CODE(12h) */
unsigned char inqCmdBlk[6] = {0x12, 0, 0, 0, 0, 0 };
if(SCSIPowerMode)
inqCmdBlk[0] = 0x03;
unsigned char sense_b[32]; /* 32 bytes is enough for test result */
sg_io_hdr_t io_hdr;
if (evpd)
inqCmdBlk[1] |= 1; /* enable evpd, at bit 0 byte 1 */
inqCmdBlk[2] = (unsigned char) page; /* page code in byte 2 */
inqCmdBlk[3] = (unsigned char)((dxfer_len >> 8) & 0xff); /* allocation length, MSB */
inqCmdBlk[4] = (unsigned char)(dxfer_len & 0xff); /* allocation, LSB */
memset(&io_hdr, 0, sizeof(io_hdr));
memset(sense_b, 0, sizeof(sense_b));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(inqCmdBlk);
io_hdr.mx_sb_len = sizeof(sense_b);
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = dxfer_len;
io_hdr.dxferp = dxferp;
io_hdr.cmdp = inqCmdBlk;
io_hdr.sbp = sense_b;
io_hdr.timeout = 30000; /* 30 seconds */
int ret = ioctl(fd, SG_IO, &io_hdr);
if (page == 0 && evpd == 0 && SCSIPowerMode == false)
{
WriteOneRecord(dev, "ioctl(SG_IO, 0, 0)", ret, (ret == 0)?0:errno, 0);
}
else if (page == 0x80 && evpd == 1 && SCSIPowerMode == false)
{
WriteOneRecord(dev, "ioctl(SG_IO, 0x80, 1)", ret, (ret == 0)?0:errno, 0);
}
else if(SCSIPowerMode)
{
WriteOneRecord(dev, "ioctl(SG_IO, 0, 0, powermode)", ret, (ret == 0)?0:errno, 0);
}
if (ret < 0)
{
cout<<"SG_IO "<<ret<<" "<<errno<<endl;
cout<<"EINVAL = "<<EINVAL<<endl;
return false;
}
cout<<"SG_IO "<<ret<<" "<<errno<<endl;
if(!SCSIPowerMode)
{
if(io_hdr.status == 0 &&io_hdr.host_status == 0 && io_hdr.driver_status == 0)
{
return true;
}
else
{
/* refer spc-4 chapter 4.5.1 */
unsigned char sense_key;
if(sense_b[0] & 0x2) /* for response code 72h and 73h, sense key in byte 1*/
{
sense_key = (unsigned char)(sense_b[1] & 0xf);
}
else /* for response code 72h and 73h, sense key in byte 2 */
{
sense_key = (unsigned char)(sense_b[2] & 0xf);
}
/* 1h RECOVERED ERROR: Indicates that the command completed
successfully, with some recovery action performed by the
device server. */
if(sense_key == 0x01)
{
return true;
}
return false;
}
}
else
{
if(!(io_hdr.masked_status == GOOD &&io_hdr.host_status == 0 && io_hdr.driver_status == 0))
{
return false;
}
unsigned char sense_key = (unsigned char)(((unsigned char*)dxferp)[2] & 0x0f);
if(sense_key == 0)
{
availability = "RunningOrFullPower";
return true;
}
unsigned char ASC = ((unsigned char*)dxferp)[12];
unsigned char ASCQ = ((unsigned char*)dxferp)[13];
switch (ASC)
{
case 0x04: // NOT READY
if ( ASCQ == 0x09 ) // SELF-TEST IN PROGRESS
{
availability = "InTest";
return true;
}
else if ( ASCQ == 0x12 ) // OFFLINE
{
availability = "OffLine";
return true;
}
break;
case 0x0B: // WARNING
availability = "Warning";
return true;
case 0x5E:
if ( ASCQ == 0x00 ) // LOW POWER CONDITION ON
{
availability = "PowerSave-LowPowerMode";
return true;
}
else if ( ASCQ == 0x41 ||
ASCQ == 0x42 ) // POWER STATE CHANGE TO ACTIVE OR IDLE
{
availability = "RunningOrFullPower";
return true;
}
else if ( ASCQ == 0x43 ) // POWER STATE CHANGE TO STANDBY
{
availability = "PowerSave-Standby";
return true;
}
break;
default:
availability = "Unknown";
break;
}
return false;
}
}