bool SqInq()

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;
    }
}