linuxdisksataraidahci

How can I get the value of "power on time(POH)" of a sata disk with ata passthrough?


I want to get smart imformation of a sata disk attached to raid card through ata passthrough. I find that smartmontools use the funciton bool sat_device::ata_pass_through() to get my disk's smart values when I execute the command sudo smartctl -a /dev/sdb -d megaraid,29.

bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)

The struct cdb in the function above is the same as what I saw in this ata passthrough document link .

But I find that I can only use the api which is similar to

bool csmi_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)

in the source code of smartmontools. This function utilizes a 14-byte structure named fis.

And it fills the fis structure in this way

  {
    unsigned char * fis = pthru.bCommandFIS;
    const ata_in_regs & lo = in.in_regs;
    const ata_in_regs & hi = in.in_regs.prev;
    fis[ 0] = 0x27; // Type: host-to-device FIS
    fis[ 1] = 0x80; // Bit7: Update command register
    fis[ 2] = lo.command;
    fis[ 3] = lo.features;
    fis[ 4] = lo.lba_low;
    fis[ 5] = lo.lba_mid;
    fis[ 6] = lo.lba_high;
    fis[ 7] = lo.device;
    fis[ 8] = hi.lba_low;
    fis[ 9] = hi.lba_mid;
    fis[10] = hi.lba_high;
    fis[11] = hi.features;
    fis[12] = lo.sector_count;
    fis[13] = hi.sector_count;
  }

So I want to know how to populate this structure so that it can obtain the SMART information I need. Or where can I learn some document relative.

What I only know is to set

    fis[ 0] = 0x27; // Type: host-to-device FIS
    fis[ 1] = 0x80; // Bit7: Update command register
    fis[ 2] = 0xB0; // ATA_CMD_SMART

Solution

  • In this document , section

    7.53.6 SMART READ DATA - B0h/D0h, PIO data-in

    told me that I should set FIS[2] = 0xB0; FIS[3] = 0xD0; FIS[5] = 0x4F; FIS[6] = 0xC2; to read SMART DATA

    And refer to drivedb.h in the source code of smartmontools, you may find some structure definitions of SMART raw data

    { "DEFAULT",
    "-", "-",
    "Default settings",
    "-v 1,raw48,Raw_Read_Error_Rate "
    "-v 2,raw48,Throughput_Performance "
    "-v 3,raw16(avg16),Spin_Up_Time "
    "-v 4,raw48,Start_Stop_Count "
    "-v 5,raw16(raw16),Reallocated_Sector_Ct "
    "-v 6,raw48,Read_Channel_Margin,HDD "
    "-v 7,raw48,Seek_Error_Rate,HDD "
    "-v 8,raw48,Seek_Time_Performance,HDD "
    "-v 9,raw24(raw8),Power_On_Hours "
    "-v 10,raw48,Spin_Retry_Count,HDD "
    "-v 11,raw48,Calibration_Retry_Count,HDD "
    "-v 12,raw48,Power_Cycle_Count "
    ...
    

    After comparison, I used int poh = rawSMARTData[21] << 16 | rawSMARTData[20] << 8 | rawSMARTData[19]; to get the power-on time