version 1.1.1.2, 2012/10/09 09:36:45
|
version 1.1.1.3, 2013/07/22 01:17:35
|
Line 4
|
Line 4
|
* Home page of code is: http://smartmontools.sourceforge.net |
* Home page of code is: http://smartmontools.sourceforge.net |
* |
* |
* Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net> |
* Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net> |
* Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net> | * Copyright (C) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net> |
* Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> |
* Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> |
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> |
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> |
* |
* |
Line 14
|
Line 14
|
* any later version. |
* any later version. |
* |
* |
* You should have received a copy of the GNU General Public License |
* You should have received a copy of the GNU General Public License |
* (for example COPYING); if not, write to the Free | * (for example COPYING); If not, see <http://www.gnu.org/licenses/>. |
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
* |
* |
* This code was originally developed as a Senior Thesis by Michael Cornwell |
* This code was originally developed as a Senior Thesis by Michael Cornwell |
* at the Concurrent Systems Laboratory (now part of the Storage Systems |
* at the Concurrent Systems Laboratory (now part of the Storage Systems |
Line 57 bool dont_print_serial_number = false;
|
Line 56 bool dont_print_serial_number = false;
|
#define SRET_STATUS_HI_EXCEEDED 0x2C |
#define SRET_STATUS_HI_EXCEEDED 0x2C |
#define SRET_STATUS_MID_EXCEEDED 0xF4 |
#define SRET_STATUS_MID_EXCEEDED 0xF4 |
|
|
// These Drive Identity tables are taken from hdparm 5.2, and are also |
|
// given in the ATA/ATAPI specs for the IDENTIFY DEVICE command. Note |
|
// that SMART was first added into the ATA/ATAPI-3 Standard with |
|
// Revision 3 of the document, July 25, 1995. Look at the "Document |
|
// Status" revision commands at the beginning of |
|
// http://www.t13.org/Documents/UploadedDocuments/project/d2008r7b-ATA-3.pdf |
|
// to see this. |
|
#define NOVAL_0 0x0000 |
|
#define NOVAL_1 0xffff |
|
/* word 81: minor version number */ |
|
#define MINOR_MAX 0x22 |
|
static const char * const minor_str[] = { /* word 81 value: */ |
|
"Device does not report version", /* 0x0000 */ |
|
"ATA-1 X3T9.2 781D prior to revision 4", /* 0x0001 */ |
|
"ATA-1 published, ANSI X3.221-1994", /* 0x0002 */ |
|
"ATA-1 X3T9.2 781D revision 4", /* 0x0003 */ |
|
"ATA-2 published, ANSI X3.279-1996", /* 0x0004 */ |
|
"ATA-2 X3T10 948D prior to revision 2k", /* 0x0005 */ |
|
"ATA-3 X3T10 2008D revision 1", /* 0x0006 */ /* SMART NOT INCLUDED */ |
|
"ATA-2 X3T10 948D revision 2k", /* 0x0007 */ |
|
"ATA-3 X3T10 2008D revision 0", /* 0x0008 */ |
|
"ATA-2 X3T10 948D revision 3", /* 0x0009 */ |
|
"ATA-3 published, ANSI X3.298-199x", /* 0x000a */ |
|
"ATA-3 X3T10 2008D revision 6", /* 0x000b */ /* 1st VERSION WITH SMART */ |
|
"ATA-3 X3T13 2008D revision 7 and 7a", /* 0x000c */ |
|
"ATA/ATAPI-4 X3T13 1153D revision 6", /* 0x000d */ |
|
"ATA/ATAPI-4 T13 1153D revision 13", /* 0x000e */ |
|
"ATA/ATAPI-4 X3T13 1153D revision 7", /* 0x000f */ |
|
"ATA/ATAPI-4 T13 1153D revision 18", /* 0x0010 */ |
|
"ATA/ATAPI-4 T13 1153D revision 15", /* 0x0011 */ |
|
"ATA/ATAPI-4 published, ANSI NCITS 317-1998", /* 0x0012 */ |
|
"ATA/ATAPI-5 T13 1321D revision 3", /* 0x0013 */ |
|
"ATA/ATAPI-4 T13 1153D revision 14", /* 0x0014 */ |
|
"ATA/ATAPI-5 T13 1321D revision 1", /* 0x0015 */ |
|
"ATA/ATAPI-5 published, ANSI NCITS 340-2000", /* 0x0016 */ |
|
"ATA/ATAPI-4 T13 1153D revision 17", /* 0x0017 */ |
|
"ATA/ATAPI-6 T13 1410D revision 0", /* 0x0018 */ |
|
"ATA/ATAPI-6 T13 1410D revision 3a", /* 0x0019 */ |
|
"ATA/ATAPI-7 T13 1532D revision 1", /* 0x001a */ |
|
"ATA/ATAPI-6 T13 1410D revision 2", /* 0x001b */ |
|
"ATA/ATAPI-6 T13 1410D revision 1", /* 0x001c */ |
|
"ATA/ATAPI-7 published, ANSI INCITS 397-2005",/* 0x001d */ |
|
"ATA/ATAPI-7 T13 1532D revision 0", /* 0x001e */ |
|
"reserved", /* 0x001f */ |
|
"reserved", /* 0x0020 */ |
|
"ATA/ATAPI-7 T13 1532D revision 4a", /* 0x0021 */ |
|
"ATA/ATAPI-6 published, ANSI INCITS 361-2002" /* 0x0022 */ |
|
}; |
|
|
|
// NOTE ATA/ATAPI-4 REV 4 was the LAST revision where the device |
|
// attribute structures were NOT completely vendor specific. So any |
|
// disk that is ATA/ATAPI-4 or above can not be trusted to show the |
|
// vendor values in sensible format. |
|
|
|
// Negative values below are because it doesn't support SMART |
|
static const int actual_ver[] = { |
|
/* word 81 value: */ |
|
0, /* 0x0000 WARNING: */ |
|
1, /* 0x0001 WARNING: */ |
|
1, /* 0x0002 WARNING: */ |
|
1, /* 0x0003 WARNING: */ |
|
2, /* 0x0004 WARNING: This array */ |
|
2, /* 0x0005 WARNING: corresponds */ |
|
-3, /*<== */ /* 0x0006 WARNING: *exactly* */ |
|
2, /* 0x0007 WARNING: to the ATA/ */ |
|
-3, /*<== */ /* 0x0008 WARNING: ATAPI version */ |
|
2, /* 0x0009 WARNING: listed in */ |
|
3, /* 0x000a WARNING: the */ |
|
3, /* 0x000b WARNING: minor_str */ |
|
3, /* 0x000c WARNING: array */ |
|
4, /* 0x000d WARNING: above. */ |
|
4, /* 0x000e WARNING: */ |
|
4, /* 0x000f WARNING: If you change */ |
|
4, /* 0x0010 WARNING: that one, */ |
|
4, /* 0x0011 WARNING: change this one */ |
|
4, /* 0x0012 WARNING: too!!! */ |
|
5, /* 0x0013 WARNING: */ |
|
4, /* 0x0014 WARNING: */ |
|
5, /* 0x0015 WARNING: */ |
|
5, /* 0x0016 WARNING: */ |
|
4, /* 0x0017 WARNING: */ |
|
6, /* 0x0018 WARNING: */ |
|
6, /* 0x0019 WARNING: */ |
|
7, /* 0x001a WARNING: */ |
|
6, /* 0x001b WARNING: */ |
|
6, /* 0x001c WARNING: */ |
|
7, /* 0x001d WARNING: */ |
|
7, /* 0x001e WARNING: */ |
|
0, /* 0x001f WARNING: */ |
|
0, /* 0x0020 WARNING: */ |
|
7, /* 0x0021 WARNING: */ |
|
6 /* 0x0022 WARNING: */ |
|
}; |
|
|
|
// Compile time check of above array sizes |
|
typedef char assert_sizeof_minor_str [sizeof(minor_str) /sizeof(minor_str[0]) == MINOR_MAX+1 ? 1 : -1]; |
|
typedef char assert_sizeof_actual_ver[sizeof(actual_ver)/sizeof(actual_ver[0]) == MINOR_MAX+1 ? 1 : -1]; |
|
|
|
// Get ID and increase flag of current pending or offline |
// Get ID and increase flag of current pending or offline |
// uncorrectable attribute. |
// uncorrectable attribute. |
unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs, |
unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs, |
Line 246 const char * map_old_vendor_opts[][2] = {
|
Line 148 const char * map_old_vendor_opts[][2] = {
|
{"198,increasing" , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag |
{"198,increasing" , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag |
{"200,writeerrorcount" , "200,raw48,Write_Error_Count"}, |
{"200,writeerrorcount" , "200,raw48,Write_Error_Count"}, |
{"201,detectedtacount" , "201,raw48,Detected_TA_Count"}, |
{"201,detectedtacount" , "201,raw48,Detected_TA_Count"}, |
{"220,temp" , "220,raw48,Temperature_Celsius"}, | {"220,temp" , "220,tempminmax,Temperature_Celsius"}, |
}; |
}; |
|
|
const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]); |
const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]); |
Line 327 bool parse_attribute_def(const char * opt, ata_vendor_
|
Line 229 bool parse_attribute_def(const char * opt, ata_vendor_
|
defs[i].priority = priority; |
defs[i].priority = priority; |
defs[i].raw_format = format; |
defs[i].raw_format = format; |
defs[i].flags = flags; |
defs[i].flags = flags; |
strcpy(defs[i].byteorder, byteorder); | snprintf(defs[i].byteorder, sizeof(defs[i].byteorder), "%s", byteorder); |
} |
} |
} |
} |
else if (defs[id].priority <= priority) { |
else if (defs[id].priority <= priority) { |
Line 337 bool parse_attribute_def(const char * opt, ata_vendor_
|
Line 239 bool parse_attribute_def(const char * opt, ata_vendor_
|
defs[id].raw_format = format; |
defs[id].raw_format = format; |
defs[id].priority = priority; |
defs[id].priority = priority; |
defs[id].flags = flags; |
defs[id].flags = flags; |
strcpy(defs[id].byteorder, byteorder); | snprintf(defs[id].byteorder, sizeof(defs[id].byteorder), "%s", byteorder); |
} |
} |
|
|
return true; |
return true; |
Line 359 std::string create_vendor_attribute_arg_list()
|
Line 261 std::string create_vendor_attribute_arg_list()
|
return s; |
return s; |
} |
} |
|
|
|
|
|
// Parse firmwarebug def (-F option). |
|
// Return false on error. |
|
bool parse_firmwarebug_def(const char * opt, firmwarebug_defs & firmwarebugs) |
|
{ |
|
if (!strcmp(opt, "none")) |
|
firmwarebugs.set(BUG_NONE); |
|
else if (!strcmp(opt, "nologdir")) |
|
firmwarebugs.set(BUG_NOLOGDIR); |
|
else if (!strcmp(opt, "samsung")) |
|
firmwarebugs.set(BUG_SAMSUNG); |
|
else if (!strcmp(opt, "samsung2")) |
|
firmwarebugs.set(BUG_SAMSUNG2); |
|
else if (!strcmp(opt, "samsung3")) |
|
firmwarebugs.set(BUG_SAMSUNG3); |
|
else if (!strcmp(opt, "xerrorlba")) |
|
firmwarebugs.set(BUG_XERRORLBA); |
|
else |
|
return false; |
|
return true; |
|
} |
|
|
|
// Return a string of valid argument words for parse_firmwarebug_def() |
|
const char * get_valid_firmwarebug_args() |
|
{ |
|
return "none, nologdir, samsung, samsung2, samsung3, xerrorlba"; |
|
} |
|
|
|
|
// swap two bytes. Point to low address |
// swap two bytes. Point to low address |
void swap2(char *location){ |
void swap2(char *location){ |
char tmp=*location; |
char tmp=*location; |
Line 433 static const char * const commandstrings[]={
|
Line 364 static const char * const commandstrings[]={
|
}; |
}; |
|
|
|
|
static const char * preg(const ata_register & r, char * buf) | static const char * preg(const ata_register & r, char (& buf)[8]) |
{ |
{ |
if (!r.is_set()) |
if (!r.is_set()) |
//return "n/a "; |
//return "n/a "; |
return "...."; |
return "...."; |
sprintf(buf, "0x%02x", r.val()); return buf; | snprintf(buf, sizeof(buf), "0x%02x", r.val()); |
| return buf; |
} |
} |
|
|
static void print_regs(const char * prefix, const ata_in_regs & r, const char * suffix = "\n") |
static void print_regs(const char * prefix, const ata_in_regs & r, const char * suffix = "\n") |
{ |
{ |
char bufs[7][4+1+13]; | char bufs[7][8]; |
pout("%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix, |
pout("%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix, |
preg(r.features, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]), |
preg(r.features, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]), |
preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]), |
preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]), |
Line 452 static void print_regs(const char * prefix, const ata_
|
Line 384 static void print_regs(const char * prefix, const ata_
|
|
|
static void print_regs(const char * prefix, const ata_out_regs & r, const char * suffix = "\n") |
static void print_regs(const char * prefix, const ata_out_regs & r, const char * suffix = "\n") |
{ |
{ |
char bufs[7][4+1+13]; | char bufs[7][8]; |
pout("%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix, |
pout("%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix, |
preg(r.error, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]), |
preg(r.error, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]), |
preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]), |
preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]), |
Line 672 int smartcommandhandler(ata_device * device, smart_com
|
Line 604 int smartcommandhandler(ata_device * device, smart_com
|
} |
} |
else { |
else { |
// We haven't gotten output that makes sense; print out some debugging info |
// We haven't gotten output that makes sense; print out some debugging info |
pout("Error SMART Status command failed\n"); | pout("SMART Status command failed\n"); |
pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE); |
pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE); |
pout("Register values returned from SMART Status command are:\n"); |
pout("Register values returned from SMART Status command are:\n"); |
print_regs(" ", out.out_regs); |
print_regs(" ", out.out_regs); |
Line 883 bool ata_set_features(ata_device * device, unsigned ch
|
Line 815 bool ata_set_features(ata_device * device, unsigned ch
|
// capable). The value of the integer helps identify the type of |
// capable). The value of the integer helps identify the type of |
// Packet device, which is useful so that the user can connect the |
// Packet device, which is useful so that the user can connect the |
// formal device number with whatever object is inside their computer. |
// formal device number with whatever object is inside their computer. |
int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id) | int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id, |
| unsigned char * raw_buf /* = 0 */) |
{ |
{ |
unsigned short *rawshort=(unsigned short *)buf; |
unsigned short *rawshort=(unsigned short *)buf; |
unsigned char *rawbyte =(unsigned char *)buf; |
unsigned char *rawbyte =(unsigned char *)buf; |
Line 909 int ata_read_identity(ata_device * device, ata_identif
|
Line 842 int ata_read_identity(ata_device * device, ata_identif
|
swap2((char *)(buf->model+i)); |
swap2((char *)(buf->model+i)); |
} |
} |
|
|
|
// If requested, save raw data before endianness adjustments |
|
if (raw_buf) |
|
memcpy(raw_buf, buf, sizeof(*buf)); |
|
|
#ifndef __NetBSD__ |
#ifndef __NetBSD__ |
// if machine is big-endian, swap byte order as needed |
// if machine is big-endian, swap byte order as needed |
// NetBSD kernel delivers IDENTIFY data in host byte order |
// NetBSD kernel delivers IDENTIFY data in host byte order |
Line 963 int ata_read_identity(ata_device * device, ata_identif
|
Line 900 int ata_read_identity(ata_device * device, ata_identif
|
return 0; |
return 0; |
} |
} |
|
|
// Returns ATA version as an integer, and a pointer to a string |
|
// describing which revision. Note that Revision 0 of ATA-3 does NOT |
|
// support SMART. For this one case we return -3 rather than +3 as |
|
// the version number. See notes above. |
|
int ataVersionInfo(const char ** description, const ata_identify_device * drive, unsigned short * minor) |
|
{ |
|
// get major and minor ATA revision numbers |
|
unsigned short major = drive->major_rev_num; |
|
*minor=drive->minor_rev_num; |
|
|
|
// First check if device has ANY ATA version information in it |
|
if (major==NOVAL_0 || major==NOVAL_1) { |
|
*description=NULL; |
|
return 0; // No info found |
|
} |
|
|
|
// The minor revision number has more information - try there first |
|
if (*minor && (*minor<=MINOR_MAX)){ |
|
int std = actual_ver[*minor]; |
|
if (std) { |
|
*description=minor_str[*minor]; |
|
return std; |
|
} |
|
} |
|
|
|
// Try new ATA-8 ACS minor revision numbers. |
|
// Table 55 of T13/2015-D Revision 4a (ACS-2), December 9, 2010. |
|
// (not in actual_ver/minor_str to avoid large sparse tables) |
|
const char *desc; |
|
switch (*minor) { |
|
case 0x0027: desc = "ATA-8-ACS revision 3c"; break; |
|
case 0x0028: desc = "ATA-8-ACS revision 6"; break; |
|
case 0x0029: desc = "ATA-8-ACS revision 4"; break; |
|
case 0x0031: desc = "ACS-2 revision 2"; break; |
|
case 0x0033: desc = "ATA-8-ACS revision 3e"; break; |
|
case 0x0039: desc = "ATA-8-ACS revision 4c"; break; |
|
case 0x0042: desc = "ATA-8-ACS revision 3f"; break; |
|
case 0x0052: desc = "ATA-8-ACS revision 3b"; break; |
|
case 0x0107: desc = "ATA-8-ACS revision 2d"; break; |
|
case 0x0110: desc = "ACS-2 revision 3"; break; |
|
default: desc = 0; break; |
|
} |
|
if (desc) { |
|
*description = desc; |
|
return 8; |
|
} |
|
|
|
// HDPARM has a very complicated algorithm from here on. Since SMART only |
|
// exists on ATA-3 and later standards, let's punt on this. If you don't |
|
// like it, please fix it. The code's in CVS. |
|
int i; |
|
for (i=15; i>0; i--) |
|
if (major & (0x1<<i)) |
|
break; |
|
|
|
*description=NULL; |
|
if (i==0) |
|
return 1; |
|
else |
|
return i; |
|
} |
|
|
|
// Get World Wide Name (WWN) fields. |
// Get World Wide Name (WWN) fields. |
// Return NAA field or -1 if WWN is unsupported. |
// Return NAA field or -1 if WWN is unsupported. |
// Table 34 of T13/1699-D Revision 6a (ATA8-ACS), September 6, 2008. |
// Table 34 of T13/1699-D Revision 6a (ATA8-ACS), September 6, 2008. |
Line 1047 int ata_get_wwn(const ata_identify_device * id, unsign
|
Line 922 int ata_get_wwn(const ata_identify_device * id, unsign
|
return (word108 >> 12); |
return (word108 >> 12); |
} |
} |
|
|
|
// Get nominal media rotation rate. |
|
// Returns: 0 = not reported, 1 = SSD, >1 = HDD rpm, < 0 = -(Unknown value) |
|
int ata_get_rotation_rate(const ata_identify_device * id) |
|
{ |
|
// Table 37 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008 |
|
// Table A.31 of T13/2161-D (ACS-3) Revision 3b, August 25, 2012 |
|
unsigned short word217 = id->words088_255[217-88]; |
|
if (word217 == 0x0000 || word217 == 0xffff) |
|
return 0; |
|
else if (word217 == 0x0001) |
|
return 1; |
|
else if (word217 > 0x0400) |
|
return word217; |
|
else |
|
return -(int)word217; |
|
} |
|
|
// returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell |
// returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell |
int ataSmartSupport(const ata_identify_device * drive) |
int ataSmartSupport(const ata_identify_device * drive) |
{ |
{ |
Line 1082 int ataIsSmartEnabled(const ata_identify_device * driv
|
Line 974 int ataIsSmartEnabled(const ata_identify_device * driv
|
int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){ |
int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){ |
|
|
if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){ |
if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){ |
pout("Error SMART Values Read failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
|
|
Line 1127 static void fixsamsungselftestlog(ata_smart_selftestlo
|
Line 1018 static void fixsamsungselftestlog(ata_smart_selftestlo
|
|
|
// Reads the Self Test Log (log #6) |
// Reads the Self Test Log (log #6) |
int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data, |
int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data, |
unsigned char fix_firmwarebug) | firmwarebug_defs firmwarebugs) |
{ |
{ |
|
|
// get data from device |
// get data from device |
if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){ |
if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){ |
pout("Error SMART Error Self-Test Log Read failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
|
|
Line 1141 int ataReadSelfTestLog (ata_device * device, ata_smart
|
Line 1031 int ataReadSelfTestLog (ata_device * device, ata_smart
|
checksumwarning("SMART Self-Test Log Structure"); |
checksumwarning("SMART Self-Test Log Structure"); |
|
|
// fix firmware bugs in self-test log |
// fix firmware bugs in self-test log |
if (fix_firmwarebug == FIX_SAMSUNG) | if (firmwarebugs.is_set(BUG_SAMSUNG)) |
fixsamsungselftestlog(data); |
fixsamsungselftestlog(data); |
|
|
// swap endian order if needed |
// swap endian order if needed |
Line 1272 int ataReadSelectiveSelfTestLog(ata_device * device, s
|
Line 1162 int ataReadSelectiveSelfTestLog(ata_device * device, s
|
|
|
// get data from device |
// get data from device |
if (smartcommandhandler(device, READ_LOG, 0x09, (char *)data)){ |
if (smartcommandhandler(device, READ_LOG, 0x09, (char *)data)){ |
pout("Error SMART Read Selective Self-Test Log failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
|
|
Line 1294 int ataReadSelectiveSelfTestLog(ata_device * device, s
|
Line 1183 int ataReadSelectiveSelfTestLog(ata_device * device, s
|
swap2((char *)&(data->pendingtime)); |
swap2((char *)&(data->pendingtime)); |
} |
} |
|
|
if (data->logversion != 1) |
|
pout("Note: selective self-test log revision number (%d) not 1 implies that no selective self-test has ever been run\n", data->logversion); |
|
|
|
return 0; |
return 0; |
} |
} |
|
|
Line 1315 int ataWriteSelectiveSelfTestLog(ata_device * device,
|
Line 1201 int ataWriteSelectiveSelfTestLog(ata_device * device,
|
struct ata_selective_self_test_log sstlog, *data=&sstlog; |
struct ata_selective_self_test_log sstlog, *data=&sstlog; |
unsigned char *ptr=(unsigned char *)data; |
unsigned char *ptr=(unsigned char *)data; |
if (ataReadSelectiveSelfTestLog(device, data)) { |
if (ataReadSelectiveSelfTestLog(device, data)) { |
|
pout("SMART Read Selective Self-test Log failed: %s\n", device->get_errmsg()); |
pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n"); |
pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n"); |
return -1; |
return -1; |
} |
} |
Line 1325 int ataWriteSelectiveSelfTestLog(ata_device * device,
|
Line 1212 int ataWriteSelectiveSelfTestLog(ata_device * device,
|
// Host is NOT allowed to write selective self-test log if a selective |
// Host is NOT allowed to write selective self-test log if a selective |
// self-test is in progress. |
// self-test is in progress. |
if (0<data->currentspan && data->currentspan<6 && ((sv->self_test_exec_status)>>4)==15) { |
if (0<data->currentspan && data->currentspan<6 && ((sv->self_test_exec_status)>>4)==15) { |
pout("Error SMART Selective or other Self-Test in progress.\n"); | pout("SMART Selective or other Self-test in progress\n"); |
return -4; |
return -4; |
} |
} |
|
|
Line 1470 int ataWriteSelectiveSelfTestLog(ata_device * device,
|
Line 1357 int ataWriteSelectiveSelfTestLog(ata_device * device,
|
|
|
// write new selective self-test log |
// write new selective self-test log |
if (smartcommandhandler(device, WRITE_LOG, 0x09, (char *)data)){ |
if (smartcommandhandler(device, WRITE_LOG, 0x09, (char *)data)){ |
pout("Error Write Selective Self-Test Log failed: %s\n", device->get_errmsg()); | pout("Write Selective Self-test Log failed: %s\n", device->get_errmsg()); |
return -3; |
return -3; |
} |
} |
|
|
Line 1512 static void fixsamsungerrorlog2(ata_smart_errorlog * d
|
Line 1399 static void fixsamsungerrorlog2(ata_smart_errorlog * d
|
// Error Log is #2, and the Extended Comprehensive SMART Error log is |
// Error Log is #2, and the Extended Comprehensive SMART Error log is |
// #3 |
// #3 |
int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data, |
int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data, |
unsigned char fix_firmwarebug) | firmwarebug_defs firmwarebugs) |
{ |
{ |
|
|
// get data from device |
// get data from device |
if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){ |
if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){ |
pout("Error SMART Error Log Read failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
|
|
Line 1527 int ataReadErrorLog (ata_device * device, ata_smart_er
|
Line 1413 int ataReadErrorLog (ata_device * device, ata_smart_er
|
|
|
// Some disks have the byte order reversed in some SMART Summary |
// Some disks have the byte order reversed in some SMART Summary |
// Error log entries |
// Error log entries |
if (fix_firmwarebug == FIX_SAMSUNG) | if (firmwarebugs.is_set(BUG_SAMSUNG)) |
fixsamsungerrorlog(data); |
fixsamsungerrorlog(data); |
else if (fix_firmwarebug == FIX_SAMSUNG2) | else if (firmwarebugs.is_set(BUG_SAMSUNG2)) |
fixsamsungerrorlog2(data); |
fixsamsungerrorlog2(data); |
|
|
// swap endian order if needed |
// swap endian order if needed |
Line 1553 int ataReadErrorLog (ata_device * device, ata_smart_er
|
Line 1439 int ataReadErrorLog (ata_device * device, ata_smart_er
|
return 0; |
return 0; |
} |
} |
|
|
|
|
|
// Fix LBA byte ordering of Extended Comprehensive Error Log |
|
// if little endian instead of ATA register ordering is provided |
|
template <class T> |
|
static inline void fix_exterrlog_lba_cmd(T & cmd) |
|
{ |
|
T org = cmd; |
|
cmd.lba_mid_register_hi = org.lba_high_register; |
|
cmd.lba_low_register_hi = org.lba_mid_register_hi; |
|
cmd.lba_high_register = org.lba_mid_register; |
|
cmd.lba_mid_register = org.lba_low_register_hi; |
|
} |
|
|
|
static void fix_exterrlog_lba(ata_smart_exterrlog * log, unsigned nsectors) |
|
{ |
|
for (unsigned i = 0; i < nsectors; i++) { |
|
for (int ei = 0; ei < 4; ei++) { |
|
ata_smart_exterrlog_error_log & entry = log[i].error_logs[ei]; |
|
fix_exterrlog_lba_cmd(entry.error); |
|
for (int ci = 0; ci < 5; ci++) |
|
fix_exterrlog_lba_cmd(entry.commands[ci]); |
|
} |
|
} |
|
} |
|
|
// Read Extended Comprehensive Error Log |
// Read Extended Comprehensive Error Log |
bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log, |
bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log, |
unsigned nsectors) | unsigned nsectors, firmwarebug_defs firmwarebugs) |
{ |
{ |
if (!ataReadLogExt(device, 0x03, 0x00, 0, log, nsectors)) |
if (!ataReadLogExt(device, 0x03, 0x00, 0, log, nsectors)) |
return false; |
return false; |
Line 1573 bool ataReadExtErrorLog(ata_device * device, ata_smart
|
Line 1484 bool ataReadExtErrorLog(ata_device * device, ata_smart
|
} |
} |
} |
} |
|
|
|
if (firmwarebugs.is_set(BUG_XERRORLBA)) |
|
fix_exterrlog_lba(log, nsectors); |
|
|
return true; |
return true; |
} |
} |
|
|
Line 1581 int ataReadSmartThresholds (ata_device * device, struc
|
Line 1495 int ataReadSmartThresholds (ata_device * device, struc
|
|
|
// get data from device |
// get data from device |
if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){ |
if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){ |
pout("Error SMART Thresholds Read failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
|
|
Line 1598 int ataReadSmartThresholds (ata_device * device, struc
|
Line 1511 int ataReadSmartThresholds (ata_device * device, struc
|
|
|
int ataEnableSmart (ata_device * device ){ |
int ataEnableSmart (ata_device * device ){ |
if (smartcommandhandler(device, ENABLE, 0, NULL)){ |
if (smartcommandhandler(device, ENABLE, 0, NULL)){ |
pout("Error SMART Enable failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
Line 1607 int ataEnableSmart (ata_device * device ){
|
Line 1519 int ataEnableSmart (ata_device * device ){
|
int ataDisableSmart (ata_device * device ){ |
int ataDisableSmart (ata_device * device ){ |
|
|
if (smartcommandhandler(device, DISABLE, 0, NULL)){ |
if (smartcommandhandler(device, DISABLE, 0, NULL)){ |
pout("Error SMART Disable failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
Line 1615 int ataDisableSmart (ata_device * device ){
|
Line 1526 int ataDisableSmart (ata_device * device ){
|
|
|
int ataEnableAutoSave(ata_device * device){ |
int ataEnableAutoSave(ata_device * device){ |
if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){ |
if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){ |
pout("Error SMART Enable Auto-save failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
Line 1624 int ataEnableAutoSave(ata_device * device){
|
Line 1534 int ataEnableAutoSave(ata_device * device){
|
int ataDisableAutoSave(ata_device * device){ |
int ataDisableAutoSave(ata_device * device){ |
|
|
if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){ |
if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){ |
pout("Error SMART Disable Auto-save failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
Line 1638 int ataEnableAutoOffline (ata_device * device){
|
Line 1547 int ataEnableAutoOffline (ata_device * device){
|
|
|
/* timer hard coded to 4 hours */ |
/* timer hard coded to 4 hours */ |
if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){ |
if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){ |
pout("Error SMART Enable Automatic Offline failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
Line 1649 int ataEnableAutoOffline (ata_device * device){
|
Line 1557 int ataEnableAutoOffline (ata_device * device){
|
int ataDisableAutoOffline (ata_device * device){ |
int ataDisableAutoOffline (ata_device * device){ |
|
|
if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){ |
if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){ |
pout("Error SMART Disable Automatic Offline failed: %s\n", device->get_errmsg()); |
|
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
Line 1730 int ataSmartTest(ata_device * device, int testtype, bo
|
Line 1637 int ataSmartTest(ata_device * device, int testtype, bo
|
|
|
// Print ouf message that we are sending the command to test |
// Print ouf message that we are sending the command to test |
if (testtype==ABORT_SELF_TEST) |
if (testtype==ABORT_SELF_TEST) |
sprintf(cmdmsg,"Abort SMART off-line mode self-test routine"); | snprintf(cmdmsg, sizeof(cmdmsg), "Abort SMART off-line mode self-test routine"); |
else if (!type) |
else if (!type) |
sprintf(cmdmsg, "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype); | snprintf(cmdmsg, sizeof(cmdmsg), "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype); |
else |
else |
sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive); | snprintf(cmdmsg, sizeof(cmdmsg), "Execute SMART %s routine immediately in %s mode", type, captive); |
pout("Sending command: \"%s\".\n",cmdmsg); |
pout("Sending command: \"%s\".\n",cmdmsg); |
|
|
if (select) { |
if (select) { |
Line 2195 std::string ata_format_attr_raw_value(const ata_smart_
|
Line 2102 std::string ata_format_attr_raw_value(const ata_smart_
|
|
|
// Attribute names shouldn't be longer than 23 chars, otherwise they break the |
// Attribute names shouldn't be longer than 23 chars, otherwise they break the |
// output of smartctl. |
// output of smartctl. |
static const char * get_default_attr_name(unsigned char id) | static const char * get_default_attr_name(unsigned char id, int rpm) |
{ |
{ |
|
bool hdd = (rpm > 1), ssd = (rpm == 1); |
|
|
|
static const char Unknown_HDD_Attribute[] = "Unknown_HDD_Attribute"; |
|
static const char Unknown_SSD_Attribute[] = "Unknown_SSD_Attribute"; |
|
|
switch (id) { |
switch (id) { |
case 1: |
case 1: |
return "Raw_Read_Error_Rate"; |
return "Raw_Read_Error_Rate"; |
Line 2209 static const char * get_default_attr_name(unsigned cha
|
Line 2121 static const char * get_default_attr_name(unsigned cha
|
case 5: |
case 5: |
return "Reallocated_Sector_Ct"; |
return "Reallocated_Sector_Ct"; |
case 6: |
case 6: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Read_Channel_Margin"; |
return "Read_Channel_Margin"; |
case 7: |
case 7: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Seek_Error_Rate"; |
return "Seek_Error_Rate"; |
case 8: |
case 8: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Seek_Time_Performance"; |
return "Seek_Time_Performance"; |
case 9: |
case 9: |
return "Power_On_Hours"; |
return "Power_On_Hours"; |
case 10: |
case 10: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Spin_Retry_Count"; |
return "Spin_Retry_Count"; |
case 11: |
case 11: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Calibration_Retry_Count"; |
return "Calibration_Retry_Count"; |
case 12: |
case 12: |
return "Power_Cycle_Count"; |
return "Power_Cycle_Count"; |
case 13: |
case 13: |
return "Read_Soft_Error_Rate"; |
return "Read_Soft_Error_Rate"; |
case 175: |
case 175: |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Program_Fail_Count_Chip"; |
return "Program_Fail_Count_Chip"; |
case 176: |
case 176: |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Erase_Fail_Count_Chip"; |
return "Erase_Fail_Count_Chip"; |
case 177: |
case 177: |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Wear_Leveling_Count"; |
return "Wear_Leveling_Count"; |
case 178: |
case 178: |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Used_Rsvd_Blk_Cnt_Chip"; |
return "Used_Rsvd_Blk_Cnt_Chip"; |
case 179: |
case 179: |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Used_Rsvd_Blk_Cnt_Tot"; |
return "Used_Rsvd_Blk_Cnt_Tot"; |
case 180: |
case 180: |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Unused_Rsvd_Blk_Cnt_Tot"; |
return "Unused_Rsvd_Blk_Cnt_Tot"; |
case 181: |
case 181: |
return "Program_Fail_Cnt_Total"; |
return "Program_Fail_Cnt_Total"; |
case 182: |
case 182: |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Erase_Fail_Count_Total"; |
return "Erase_Fail_Count_Total"; |
case 183: |
case 183: |
return "Runtime_Bad_Block"; |
return "Runtime_Bad_Block"; |
Line 2249 static const char * get_default_attr_name(unsigned cha
|
Line 2173 static const char * get_default_attr_name(unsigned cha
|
case 188: |
case 188: |
return "Command_Timeout"; |
return "Command_Timeout"; |
case 189: |
case 189: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "High_Fly_Writes"; |
return "High_Fly_Writes"; |
case 190: |
case 190: |
// Western Digital uses this for temperature. |
// Western Digital uses this for temperature. |
Line 2260 static const char * get_default_attr_name(unsigned cha
|
Line 2185 static const char * get_default_attr_name(unsigned cha
|
// 55C sometime in the past. |
// 55C sometime in the past. |
return "Airflow_Temperature_Cel"; |
return "Airflow_Temperature_Cel"; |
case 191: |
case 191: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "G-Sense_Error_Rate"; |
return "G-Sense_Error_Rate"; |
case 192: |
case 192: |
return "Power-Off_Retract_Count"; |
return "Power-Off_Retract_Count"; |
case 193: |
case 193: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Load_Cycle_Count"; |
return "Load_Cycle_Count"; |
case 194: |
case 194: |
return "Temperature_Celsius"; |
return "Temperature_Celsius"; |
Line 2279 static const char * get_default_attr_name(unsigned cha
|
Line 2206 static const char * get_default_attr_name(unsigned cha
|
case 199: |
case 199: |
return "UDMA_CRC_Error_Count"; |
return "UDMA_CRC_Error_Count"; |
case 200: |
case 200: |
|
if (ssd) return Unknown_SSD_Attribute; |
// Western Digital |
// Western Digital |
return "Multi_Zone_Error_Rate"; |
return "Multi_Zone_Error_Rate"; |
case 201: |
case 201: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Soft_Read_Error_Rate"; |
return "Soft_Read_Error_Rate"; |
case 202: |
case 202: |
|
if (ssd) return Unknown_SSD_Attribute; |
// Fujitsu: "TA_Increase_Count" |
// Fujitsu: "TA_Increase_Count" |
return "Data_Address_Mark_Errs"; |
return "Data_Address_Mark_Errs"; |
case 203: |
case 203: |
Line 2298 static const char * get_default_attr_name(unsigned cha
|
Line 2228 static const char * get_default_attr_name(unsigned cha
|
return "Thermal_Asperity_Rate"; |
return "Thermal_Asperity_Rate"; |
case 206: |
case 206: |
// Fujitsu |
// Fujitsu |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Flying_Height"; |
return "Flying_Height"; |
case 207: |
case 207: |
// Maxtor |
// Maxtor |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Spin_High_Current"; |
return "Spin_High_Current"; |
case 208: |
case 208: |
// Maxtor |
// Maxtor |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Spin_Buzz"; |
return "Spin_Buzz"; |
case 209: |
case 209: |
// Maxtor |
// Maxtor |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Offline_Seek_Performnce"; |
return "Offline_Seek_Performnce"; |
case 220: |
case 220: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Disk_Shift"; |
return "Disk_Shift"; |
case 221: |
case 221: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "G-Sense_Error_Rate"; |
return "G-Sense_Error_Rate"; |
case 222: |
case 222: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Loaded_Hours"; |
return "Loaded_Hours"; |
case 223: |
case 223: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Load_Retry_Count"; |
return "Load_Retry_Count"; |
case 224: |
case 224: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Load_Friction"; |
return "Load_Friction"; |
case 225: |
case 225: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Load_Cycle_Count"; |
return "Load_Cycle_Count"; |
case 226: |
case 226: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Load-in_Time"; |
return "Load-in_Time"; |
case 227: |
case 227: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Torq-amp_Count"; |
return "Torq-amp_Count"; |
case 228: |
case 228: |
return "Power-off_Retract_Count"; |
return "Power-off_Retract_Count"; |
case 230: |
case 230: |
// seen in IBM DTPA-353750 |
// seen in IBM DTPA-353750 |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Head_Amplitude"; |
return "Head_Amplitude"; |
case 231: |
case 231: |
return "Temperature_Celsius"; |
return "Temperature_Celsius"; |
Line 2336 static const char * get_default_attr_name(unsigned cha
|
Line 2279 static const char * get_default_attr_name(unsigned cha
|
return "Available_Reservd_Space"; |
return "Available_Reservd_Space"; |
case 233: |
case 233: |
// seen in Intel X25-E SSD |
// seen in Intel X25-E SSD |
|
if (hdd) return Unknown_HDD_Attribute; |
return "Media_Wearout_Indicator"; |
return "Media_Wearout_Indicator"; |
case 240: |
case 240: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Head_Flying_Hours"; |
return "Head_Flying_Hours"; |
case 241: |
case 241: |
return "Total_LBAs_Written"; |
return "Total_LBAs_Written"; |
Line 2346 static const char * get_default_attr_name(unsigned cha
|
Line 2291 static const char * get_default_attr_name(unsigned cha
|
case 250: |
case 250: |
return "Read_Error_Retry_Rate"; |
return "Read_Error_Retry_Rate"; |
case 254: |
case 254: |
|
if (ssd) return Unknown_SSD_Attribute; |
return "Free_Fall_Sensor"; |
return "Free_Fall_Sensor"; |
default: |
default: |
return "Unknown_Attribute"; |
return "Unknown_Attribute"; |
Line 2353 static const char * get_default_attr_name(unsigned cha
|
Line 2299 static const char * get_default_attr_name(unsigned cha
|
} |
} |
|
|
// Get attribute name |
// Get attribute name |
std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs) | std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs, |
| int rpm /* = 0 */) |
{ |
{ |
if (!defs[id].name.empty()) |
if (!defs[id].name.empty()) |
return defs[id].name; |
return defs[id].name; |
else |
else |
return get_default_attr_name(id); | return get_default_attr_name(id, rpm); |
} |
} |
|
|
// Find attribute index for attribute id, -1 if not found. |
// Find attribute index for attribute id, -1 if not found. |
Line 2377 int ata_find_attr_index(unsigned char id, const ata_sm
|
Line 2324 int ata_find_attr_index(unsigned char id, const ata_sm
|
// non-default interpretations. If the Attribute does not exist, return 0 |
// non-default interpretations. If the Attribute does not exist, return 0 |
unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs) |
unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs) |
{ |
{ |
for (int i = 0; i < 3; i++) { | for (int i = 0; i < 4; i++) { |
static const unsigned char ids[3] = {194, 9, 220}; | static const unsigned char ids[4] = {194, 190, 9, 220}; |
unsigned char id = ids[i]; |
unsigned char id = ids[i]; |
const ata_attr_raw_format format = defs[id].raw_format; |
const ata_attr_raw_format format = defs[id].raw_format; |
if (!( (id == 194 && format == RAWFMT_DEFAULT) | if (!( ((id == 194 || id == 190) && format == RAWFMT_DEFAULT) |
|| format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X)) |
|| format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X)) |
continue; |
continue; |
int idx = ata_find_attr_index(id, *data); |
int idx = ata_find_attr_index(id, *data); |
Line 2409 int ataReadSCTStatus(ata_device * device, ata_sct_stat
|
Line 2356 int ataReadSCTStatus(ata_device * device, ata_sct_stat
|
// read SCT status via SMART log 0xe0 |
// read SCT status via SMART log 0xe0 |
memset(sts, 0, sizeof(*sts)); |
memset(sts, 0, sizeof(*sts)); |
if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){ |
if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){ |
pout("Error Read SCT Status failed: %s\n", device->get_errmsg()); | pout("Read SCT Status failed: %s\n", device->get_errmsg()); |
return -1; |
return -1; |
} |
} |
|
|
Line 2427 int ataReadSCTStatus(ata_device * device, ata_sct_stat
|
Line 2374 int ataReadSCTStatus(ata_device * device, ata_sct_stat
|
|
|
// Check format version |
// Check format version |
if (!(sts->format_version == 2 || sts->format_version == 3)) { |
if (!(sts->format_version == 2 || sts->format_version == 3)) { |
pout("Error unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version); | pout("Unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version); |
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
Line 2464 int ataReadSCTTempHist(ata_device * device, ata_sct_te
|
Line 2411 int ataReadSCTTempHist(ata_device * device, ata_sct_te
|
|
|
// write command via SMART log page 0xe0 |
// write command via SMART log page 0xe0 |
if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){ |
if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){ |
pout("Error Write SCT Data Table command failed: %s\n", device->get_errmsg()); | pout("Write SCT Data Table failed: %s\n", device->get_errmsg()); |
return -1; |
return -1; |
} |
} |
|
|
// read SCT data via SMART log page 0xe1 |
// read SCT data via SMART log page 0xe1 |
memset(tmh, 0, sizeof(*tmh)); |
memset(tmh, 0, sizeof(*tmh)); |
if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){ |
if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){ |
pout("Error Read SCT Data Table failed: %s\n", device->get_errmsg()); | pout("Read SCT Data Table failed: %s\n", device->get_errmsg()); |
return -1; |
return -1; |
} |
} |
|
|
Line 2480 int ataReadSCTTempHist(ata_device * device, ata_sct_te
|
Line 2427 int ataReadSCTTempHist(ata_device * device, ata_sct_te
|
return -1; |
return -1; |
|
|
if (!(sts->ext_status_code == 0 && sts->action_code == 5 && sts->function_code == 1)) { |
if (!(sts->ext_status_code == 0 && sts->action_code == 5 && sts->function_code == 1)) { |
pout("Error unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n", | pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n", |
sts->ext_status_code, sts->action_code, sts->function_code); |
sts->ext_status_code, sts->action_code, sts->function_code); |
return -1; |
return -1; |
} |
} |
Line 2490 int ataReadSCTTempHist(ata_device * device, ata_sct_te
|
Line 2437 int ataReadSCTTempHist(ata_device * device, ata_sct_te
|
swapx(&tmh->format_version); |
swapx(&tmh->format_version); |
swapx(&tmh->sampling_period); |
swapx(&tmh->sampling_period); |
swapx(&tmh->interval); |
swapx(&tmh->interval); |
|
swapx(&tmh->cb_index); |
|
swapx(&tmh->cb_size); |
} |
} |
|
|
// Check format version |
|
if (tmh->format_version != 2) { |
|
pout("Error unknown SCT Temperature History Format Version (%u), should be 2.\n", tmh->format_version); |
|
return -1; |
|
} |
|
return 0; |
return 0; |
} |
} |
|
|
Line 2535 int ataSetSCTTempInterval(ata_device * device, unsigne
|
Line 2478 int ataSetSCTTempInterval(ata_device * device, unsigne
|
|
|
// write command via SMART log page 0xe0 |
// write command via SMART log page 0xe0 |
if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){ |
if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){ |
pout("Error Write SCT Feature Control Command failed: %s\n", device->get_errmsg()); | pout("Write SCT Feature Control Command failed: %s\n", device->get_errmsg()); |
return -1; |
return -1; |
} |
} |
|
|
Line 2544 int ataSetSCTTempInterval(ata_device * device, unsigne
|
Line 2487 int ataSetSCTTempInterval(ata_device * device, unsigne
|
return -1; |
return -1; |
|
|
if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == 1)) { |
if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == 1)) { |
pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n", | pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n", |
sts.ext_status_code, sts.action_code, sts.function_code); |
sts.ext_status_code, sts.action_code, sts.function_code); |
return -1; |
return -1; |
} |
} |
Line 2599 static int ataGetSetSCTErrorRecoveryControltime(ata_de
|
Line 2542 static int ataGetSetSCTErrorRecoveryControltime(ata_de
|
|
|
ata_cmd_out out; |
ata_cmd_out out; |
if (!device->ata_pass_through(in, out)) { |
if (!device->ata_pass_through(in, out)) { |
pout("Error Write SCT (%cet) Error Recovery Control Command failed: %s\n", | pout("Write SCT (%cet) Error Recovery Control Command failed: %s\n", |
(!set ? 'G' : 'S'), device->get_errmsg()); |
(!set ? 'G' : 'S'), device->get_errmsg()); |
return -1; |
return -1; |
} |
} |
Line 2609 static int ataGetSetSCTErrorRecoveryControltime(ata_de
|
Line 2552 static int ataGetSetSCTErrorRecoveryControltime(ata_de
|
return -1; |
return -1; |
|
|
if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) { |
if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) { |
pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n", | pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n", |
sts.ext_status_code, sts.action_code, sts.function_code); |
sts.ext_status_code, sts.action_code, sts.function_code); |
return -1; |
return -1; |
} |
} |
Line 2619 static int ataGetSetSCTErrorRecoveryControltime(ata_de
|
Line 2562 static int ataGetSetSCTErrorRecoveryControltime(ata_de
|
if (!(out.out_regs.sector_count.is_set() && out.out_regs.lba_low.is_set())) { |
if (!(out.out_regs.sector_count.is_set() && out.out_regs.lba_low.is_set())) { |
// TODO: Output register support should be checked within each ata_pass_through() |
// TODO: Output register support should be checked within each ata_pass_through() |
// implementation before command is issued. |
// implementation before command is issued. |
pout("Error SMART WRITE LOG does not return COUNT and LBA_LOW register\n"); | pout("SMART WRITE LOG does not return COUNT and LBA_LOW register\n"); |
return -1; |
return -1; |
} |
} |
|
if ( out.out_regs.sector_count == in.in_regs.sector_count |
|
&& out.out_regs.lba_low == in.in_regs.lba_low ) { |
|
// 0xe001 (5734.5s) - this is most likely a broken ATA pass-through implementation |
|
pout("SMART WRITE LOG returns COUNT and LBA_LOW register unchanged\n"); |
|
return -1; |
|
} |
|
|
// Return value to caller |
// Return value to caller |
time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8); |
time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8); |
} |
} |
Line 2713 int ataPrintSmartSelfTestEntry(unsigned testnum, unsig
|
Line 2663 int ataPrintSmartSelfTestEntry(unsigned testnum, unsig
|
char msglba[32]; |
char msglba[32]; |
if (retval < 0 && failing_lba < 0xffffffffffffULL) |
if (retval < 0 && failing_lba < 0xffffffffffffULL) |
snprintf(msglba, sizeof(msglba), "%"PRIu64, failing_lba); |
snprintf(msglba, sizeof(msglba), "%"PRIu64, failing_lba); |
else | else { |
strcpy(msglba, "-"); | msglba[0] = '-'; msglba[1] = 0; |
| } |
|
|
pout("#%2u %-19s %-29s %1d0%% %8u %s\n", testnum, |
pout("#%2u %-19s %-29s %1d0%% %8u %s\n", testnum, |
msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba); |
msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba); |
Line 2727 int ataPrintSmartSelfTestEntry(unsigned testnum, unsig
|
Line 2678 int ataPrintSmartSelfTestEntry(unsigned testnum, unsig
|
// bottom 8 bits: number of entries found where self-test showed an error |
// bottom 8 bits: number of entries found where self-test showed an error |
// remaining bits: if nonzero, power on hours of last self-test where error was found |
// remaining bits: if nonzero, power on hours of last self-test where error was found |
int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries, |
int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries, |
unsigned char fix_firmwarebug) | firmwarebug_defs firmwarebugs) |
{ |
{ |
if (allentries) |
if (allentries) |
pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber); |
pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber); |
if ((data->revnumber!=0x0001) && allentries && fix_firmwarebug != FIX_SAMSUNG) | if (data->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG)) |
pout("Warning: ATA Specification requires self-test log structure revision number = 1\n"); |
pout("Warning: ATA Specification requires self-test log structure revision number = 1\n"); |
if (data->mostrecenttest==0){ |
if (data->mostrecenttest==0){ |
if (allentries) |
if (allentries) |