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