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> |
* |
* |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
Line 13
|
Line 13
|
* 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 34
|
Line 33
|
#include "int64.h" |
#include "int64.h" |
#include "atacmdnames.h" |
#include "atacmdnames.h" |
#include "atacmds.h" |
#include "atacmds.h" |
|
#include "ataidentify.h" |
#include "dev_interface.h" |
#include "dev_interface.h" |
#include "ataprint.h" |
#include "ataprint.h" |
#include "smartctl.h" |
#include "smartctl.h" |
Line 60 static bool is_permissive()
|
Line 60 static bool is_permissive()
|
|
|
/* For the given Command Register (CR) and Features Register (FR), attempts |
/* For the given Command Register (CR) and Features Register (FR), attempts |
* to construct a string that describes the contents of the Status |
* to construct a string that describes the contents of the Status |
* Register (ST) and Error Register (ER). The caller passes the string | * Register (ST) and Error Register (ER). If the meanings of the flags of |
* buffer and the return value is a pointer to this string. If the | * the error register are not known for the given command then it returns an |
* meanings of the flags of the error register are not known for the given | * empty string. |
* command then it returns NULL. | |
* |
* |
* The meanings of the flags of the error register for all commands are |
* The meanings of the flags of the error register for all commands are |
* described in the ATA spec and could all be supported here in theory. |
* described in the ATA spec and could all be supported here in theory. |
Line 72 static bool is_permissive()
|
Line 71 static bool is_permissive()
|
* should probably be redesigned. |
* should probably be redesigned. |
*/ |
*/ |
|
|
static const char * construct_st_er_desc( | static std::string format_st_er_desc( |
char * s, | |
unsigned char CR, unsigned char FR, |
unsigned char CR, unsigned char FR, |
unsigned char ST, unsigned char ER, |
unsigned char ST, unsigned char ER, |
unsigned short SC, |
unsigned short SC, |
Line 111 static const char * construct_st_er_desc(
|
Line 109 static const char * construct_st_er_desc(
|
for (i = 0; i < 8; i++) |
for (i = 0; i < 8; i++) |
error_flag[i] = NULL; |
error_flag[i] = NULL; |
|
|
|
std::string str; |
|
|
switch (CR) { |
switch (CR) { |
case 0x10: // RECALIBRATE |
case 0x10: // RECALIBRATE |
error_flag[2] = abrt; |
error_flag[2] = abrt; |
Line 281 static const char * construct_st_er_desc(
|
Line 281 static const char * construct_st_er_desc(
|
error_flag[2] = abrt; |
error_flag[2] = abrt; |
break; |
break; |
default: |
default: |
return NULL; | return str; // "" |
break; |
break; |
} |
} |
break; |
break; |
Line 291 static const char * construct_st_er_desc(
|
Line 291 static const char * construct_st_er_desc(
|
error_flag[2] = abrt; |
error_flag[2] = abrt; |
break; |
break; |
default: |
default: |
return NULL; | return str; // "" |
break; |
break; |
} |
} |
break; |
break; |
Line 320 static const char * construct_st_er_desc(
|
Line 320 static const char * construct_st_er_desc(
|
error_flag[2] = abrt; |
error_flag[2] = abrt; |
break; |
break; |
default: |
default: |
return NULL; | return str; // "" |
} |
} |
|
|
s[0] = '\0'; |
|
|
|
/* We ignore any status flags other than Device Fault and Error */ |
/* We ignore any status flags other than Device Fault and Error */ |
|
|
if (uses_device_fault && (ST & (1 << 5))) { |
if (uses_device_fault && (ST & (1 << 5))) { |
strcat(s, "Device Fault"); | str = "Device Fault"; |
if (ST & 1) // Error flag |
if (ST & 1) // Error flag |
strcat(s, "; "); | str += "; "; |
} |
} |
if (ST & 1) { // Error flag |
if (ST & 1) { // Error flag |
int count = 0; |
int count = 0; |
|
|
strcat(s, "Error: "); | str += "Error: "; |
for (i = 7; i >= 0; i--) |
for (i = 7; i >= 0; i--) |
if ((ER & (1 << i)) && (error_flag[i])) { |
if ((ER & (1 << i)) && (error_flag[i])) { |
if (count++ > 0) |
if (count++ > 0) |
strcat(s, ", "); | str += ", "; |
strcat(s, error_flag[i]); | str += error_flag[i]; |
} |
} |
} |
} |
|
|
// If the error was a READ or WRITE error, print the Logical Block |
// If the error was a READ or WRITE error, print the Logical Block |
// Address (LBA) at which the read or write failed. |
// Address (LBA) at which the read or write failed. |
if (print_lba) { |
if (print_lba) { |
char tmp[128]; |
|
// print number of sectors, if known, and append to print string |
// print number of sectors, if known, and append to print string |
if (print_sector) { | if (print_sector) |
snprintf(tmp, 128, " %d sectors", print_sector); | str += strprintf(" %d sectors", print_sector); |
strcat(s, tmp); | |
} | |
|
|
if (lba28_regs) { |
if (lba28_regs) { |
unsigned lba; |
unsigned lba; |
Line 367 static const char * construct_st_er_desc(
|
Line 362 static const char * construct_st_er_desc(
|
lba <<= 8; |
lba <<= 8; |
// bits 0-7: SN |
// bits 0-7: SN |
lba |= lba28_regs->sector_number; |
lba |= lba28_regs->sector_number; |
snprintf(tmp, 128, " at LBA = 0x%08x = %u", lba, lba); | str += strprintf(" at LBA = 0x%08x = %u", lba, lba); |
strcat(s, tmp); | |
} |
} |
else if (lba48_regs) { |
else if (lba48_regs) { |
// This assumes that upper LBA registers are 0 for 28-bit commands |
// This assumes that upper LBA registers are 0 for 28-bit commands |
Line 386 static const char * construct_st_er_desc(
|
Line 380 static const char * construct_st_er_desc(
|
lba48 |= lba48_regs->lba_mid_register; |
lba48 |= lba48_regs->lba_mid_register; |
lba48 <<= 8; |
lba48 <<= 8; |
lba48 |= lba48_regs->lba_low_register; |
lba48 |= lba48_regs->lba_low_register; |
snprintf(tmp, 128, " at LBA = 0x%08"PRIx64" = %"PRIu64, lba48, lba48); | str += strprintf(" at LBA = 0x%08"PRIx64" = %"PRIu64, lba48, lba48); |
strcat(s, tmp); | |
} |
} |
} |
} |
|
|
return s; | return str; |
} |
} |
|
|
static inline const char * construct_st_er_desc(char * s, | static inline std::string format_st_er_desc( |
const ata_smart_errorlog_struct * data) |
const ata_smart_errorlog_struct * data) |
{ |
{ |
return construct_st_er_desc(s, | return format_st_er_desc( |
data->commands[4].commandreg, |
data->commands[4].commandreg, |
data->commands[4].featuresreg, |
data->commands[4].featuresreg, |
data->error_struct.status, |
data->error_struct.status, |
Line 406 static inline const char * construct_st_er_desc(char *
|
Line 399 static inline const char * construct_st_er_desc(char *
|
&data->error_struct, (const ata_smart_exterrlog_error *)0); |
&data->error_struct, (const ata_smart_exterrlog_error *)0); |
} |
} |
|
|
static inline const char * construct_st_er_desc(char * s, | static inline std::string format_st_er_desc( |
const ata_smart_exterrlog_error_log * data) |
const ata_smart_exterrlog_error_log * data) |
{ |
{ |
return construct_st_er_desc(s, | return format_st_er_desc( |
data->commands[4].command_register, |
data->commands[4].command_register, |
data->commands[4].features_register, |
data->commands[4].features_register, |
data->error.status_register, |
data->error.status_register, |
Line 418 static inline const char * construct_st_er_desc(char *
|
Line 411 static inline const char * construct_st_er_desc(char *
|
(const ata_smart_errorlog_error_struct *)0, &data->error); |
(const ata_smart_errorlog_error_struct *)0, &data->error); |
} |
} |
|
|
|
|
|
static int find_msb(unsigned short word) |
|
{ |
|
for (int bit = 15; bit >= 0; bit--) |
|
if (word & (1 << bit)) |
|
return bit; |
|
return -1; |
|
} |
|
|
|
static const char * get_ata_major_version(const ata_identify_device * drive) |
|
{ |
|
switch (find_msb(drive->major_rev_num)) { |
|
case 10: return "ACS-3"; |
|
case 9: return "ACS-2"; |
|
case 8: return "ATA8-ACS"; |
|
case 7: return "ATA/ATAPI-7"; |
|
case 6: return "ATA/ATAPI-6"; |
|
case 5: return "ATA/ATAPI-5"; |
|
case 4: return "ATA/ATAPI-4"; |
|
case 3: return "ATA-3"; |
|
case 2: return "ATA-2"; |
|
case 1: return "ATA-1"; |
|
default: return 0; |
|
} |
|
} |
|
|
|
static const char * get_ata_minor_version(const ata_identify_device * drive) |
|
{ |
|
switch (drive->minor_rev_num) { |
|
case 0x0001: return "ATA-1 X3T9.2/781D prior to revision 4"; |
|
case 0x0002: return "ATA-1 published, ANSI X3.221-1994"; |
|
case 0x0003: return "ATA-1 X3T9.2/781D revision 4"; |
|
case 0x0004: return "ATA-2 published, ANSI X3.279-1996"; |
|
case 0x0005: return "ATA-2 X3T10/948D prior to revision 2k"; |
|
case 0x0006: return "ATA-3 X3T10/2008D revision 1"; |
|
case 0x0007: return "ATA-2 X3T10/948D revision 2k"; |
|
case 0x0008: return "ATA-3 X3T10/2008D revision 0"; |
|
case 0x0009: return "ATA-2 X3T10/948D revision 3"; |
|
case 0x000a: return "ATA-3 published, ANSI X3.298-1997"; |
|
case 0x000b: return "ATA-3 X3T10/2008D revision 6"; // 1st ATA-3 revision with SMART |
|
case 0x000c: return "ATA-3 X3T13/2008D revision 7 and 7a"; |
|
case 0x000d: return "ATA/ATAPI-4 X3T13/1153D revision 6"; |
|
case 0x000e: return "ATA/ATAPI-4 T13/1153D revision 13"; |
|
case 0x000f: return "ATA/ATAPI-4 X3T13/1153D revision 7"; |
|
case 0x0010: return "ATA/ATAPI-4 T13/1153D revision 18"; |
|
case 0x0011: return "ATA/ATAPI-4 T13/1153D revision 15"; |
|
case 0x0012: return "ATA/ATAPI-4 published, ANSI NCITS 317-1998"; |
|
case 0x0013: return "ATA/ATAPI-5 T13/1321D revision 3"; |
|
case 0x0014: return "ATA/ATAPI-4 T13/1153D revision 14"; |
|
case 0x0015: return "ATA/ATAPI-5 T13/1321D revision 1"; |
|
case 0x0016: return "ATA/ATAPI-5 published, ANSI NCITS 340-2000"; |
|
case 0x0017: return "ATA/ATAPI-4 T13/1153D revision 17"; |
|
case 0x0018: return "ATA/ATAPI-6 T13/1410D revision 0"; |
|
case 0x0019: return "ATA/ATAPI-6 T13/1410D revision 3a"; |
|
case 0x001a: return "ATA/ATAPI-7 T13/1532D revision 1"; |
|
case 0x001b: return "ATA/ATAPI-6 T13/1410D revision 2"; |
|
case 0x001c: return "ATA/ATAPI-6 T13/1410D revision 1"; |
|
case 0x001d: return "ATA/ATAPI-7 published, ANSI INCITS 397-2005"; |
|
case 0x001e: return "ATA/ATAPI-7 T13/1532D revision 0"; |
|
case 0x001f: return "ACS-3 T13/2161-D revision 3b"; |
|
|
|
case 0x0021: return "ATA/ATAPI-7 T13/1532D revision 4a"; |
|
case 0x0022: return "ATA/ATAPI-6 published, ANSI INCITS 361-2002"; |
|
|
|
case 0x0027: return "ATA8-ACS T13/1699-D revision 3c"; |
|
case 0x0028: return "ATA8-ACS T13/1699-D revision 6"; |
|
case 0x0029: return "ATA8-ACS T13/1699-D revision 4"; |
|
|
|
case 0x0031: return "ACS-2 T13/2015-D revision 2"; |
|
|
|
case 0x0033: return "ATA8-ACS T13/1699-D revision 3e"; |
|
|
|
case 0x0039: return "ATA8-ACS T13/1699-D revision 4c"; |
|
|
|
case 0x0042: return "ATA8-ACS T13/1699-D revision 3f"; |
|
|
|
case 0x0052: return "ATA8-ACS T13/1699-D revision 3b"; |
|
|
|
case 0x0107: return "ATA8-ACS T13/1699-D revision 2d"; |
|
|
|
case 0x0110: return "ACS-2 T13/2015-D revision 3"; |
|
|
|
default: return 0; |
|
} |
|
} |
|
|
|
static const char * get_sata_version(const ata_identify_device * drive) |
|
{ |
|
unsigned short word222 = drive->words088_255[222-88]; |
|
if ((word222 & 0xf000) != 0x1000) |
|
return 0; |
|
switch (find_msb(word222 & 0x0fff)) { |
|
default: return "SATA >3.1"; |
|
case 6: return "SATA 3.1"; |
|
case 5: return "SATA 3.0"; |
|
case 4: return "SATA 2.6"; |
|
case 3: return "SATA 2.5"; |
|
case 2: return "SATA II Ext"; |
|
case 1: return "SATA 1.0a"; |
|
case 0: return "ATA8-AST"; |
|
case -1: return 0; |
|
} |
|
} |
|
|
|
static const char * get_sata_speed(int level) |
|
{ |
|
if (level <= 0) |
|
return 0; |
|
switch (level) { |
|
default: return ">6.0 Gb/s"; |
|
case 3: return "6.0 Gb/s"; |
|
case 2: return "3.0 Gb/s"; |
|
case 1: return "1.5 Gb/s"; |
|
} |
|
} |
|
|
|
static const char * get_sata_maxspeed(const ata_identify_device * drive) |
|
{ |
|
unsigned short word076 = drive->words047_079[76-47]; |
|
if (word076 & 0x0001) |
|
return 0; |
|
return get_sata_speed(find_msb(word076 & 0x00fe)); |
|
} |
|
|
|
static const char * get_sata_curspeed(const ata_identify_device * drive) |
|
{ |
|
unsigned short word077 = drive->words047_079[77-47]; |
|
if (word077 & 0x0001) |
|
return 0; |
|
return get_sata_speed((word077 >> 1) & 0x7); |
|
} |
|
|
|
|
static void print_drive_info(const ata_identify_device * drive, |
static void print_drive_info(const ata_identify_device * drive, |
const ata_size_info & sizes, | const ata_size_info & sizes, int rpm, |
const drive_settings * dbentry) |
const drive_settings * dbentry) |
{ |
{ |
// format drive information (with byte swapping as needed) |
// format drive information (with byte swapping as needed) |
Line 440 static void print_drive_info(const ata_identify_device
|
Line 566 static void print_drive_info(const ata_identify_device
|
int naa = ata_get_wwn(drive, oui, unique_id); |
int naa = ata_get_wwn(drive, oui, unique_id); |
if (naa >= 0) |
if (naa >= 0) |
pout("LU WWN Device Id: %x %06x %09"PRIx64"\n", naa, oui, unique_id); |
pout("LU WWN Device Id: %x %06x %09"PRIx64"\n", naa, oui, unique_id); |
|
|
|
// Additional Product Identifier (OEM Id) string in words 170-173 |
|
// (e08130r1, added in ACS-2 Revision 1, December 17, 2008) |
|
if (0x2020 <= drive->words088_255[170-88] && drive->words088_255[170-88] <= 0x7e7e) { |
|
char add[8+1]; |
|
ata_format_id_string(add, (const unsigned char *)(drive->words088_255+170-88), sizeof(add)-1); |
|
if (add[0]) |
|
pout("Add. Product Id: %s\n", add); |
|
} |
} |
} |
pout("Firmware Version: %s\n", infofound(firmware)); |
pout("Firmware Version: %s\n", infofound(firmware)); |
|
|
Line 462 static void print_drive_info(const ata_identify_device
|
Line 597 static void print_drive_info(const ata_identify_device
|
} |
} |
} |
} |
|
|
|
// Print nominal media rotation rate if reported |
|
if (rpm) { |
|
if (rpm == 1) |
|
pout("Rotation Rate: Solid State Device\n"); |
|
else if (rpm > 1) |
|
pout("Rotation Rate: %d rpm\n", rpm); |
|
else |
|
pout("Rotation Rate: Unknown (0x%04x)\n", -rpm); |
|
} |
|
|
// See if drive is recognized |
// See if drive is recognized |
pout("Device is: %s\n", !dbentry ? |
pout("Device is: %s\n", !dbentry ? |
"Not in smartctl database [for details use: -P showall]": |
"Not in smartctl database [for details use: -P showall]": |
"In smartctl database [for details use: -P show]"); |
"In smartctl database [for details use: -P show]"); |
|
|
// now get ATA version info | // Print ATA version |
const char *description; unsigned short minorrev; | std::string ataver; |
int version = ataVersionInfo(&description, drive, &minorrev); | if ( (drive->major_rev_num != 0x0000 && drive->major_rev_num != 0xffff) |
| || (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff)) { |
| const char * majorver = get_ata_major_version(drive); |
| const char * minorver = get_ata_minor_version(drive); |
|
|
// SMART Support was first added into the ATA/ATAPI-3 Standard with | if (majorver && minorver && str_starts_with(minorver, majorver)) { |
// Revision 3 of the document, July 25, 1995. Look at the "Document | // Major and minor strings match, print minor string only |
// Status" revision commands at the beginning of | ataver = minorver; |
// http://www.t13.org/Documents/UploadedDocuments/project/d2008r7b-ATA-3.pdf | |
// to see this. So it's not enough to check if we are ATA-3. | |
// Version=-3 indicates ATA-3 BEFORE Revision 3. | |
// Version=0 indicates that no info is found. This may happen if | |
// the OS provides only part of the IDENTIFY data. | |
| |
std::string majorstr, minorstr; | |
if (version) { | |
if (version <= 8) { | |
majorstr = strprintf("%d", abs(version)); | |
if (description) | |
minorstr = description; | |
else if (!minorrev) | |
minorstr = "Exact ATA specification draft version not indicated"; | |
else | |
minorstr = strprintf("Not recognized. Minor revision code: 0x%04x", minorrev); | |
} |
} |
else { |
else { |
// Bit 9 in word 80 of ATA IDENTIFY data does not mean "ATA-9" but "ACS-2" | if (majorver) |
// TODO: handle this in ataVersionInfo() | ataver = majorver; |
majorstr = "8"; | |
if (description) | |
minorstr = description; | |
else if (!minorrev) | |
minorstr = strprintf("ACS-%d (revision not indicated)", version-9+2); | |
else |
else |
minorstr = strprintf("ACS-%d (unknown minor revision code: 0x%04x)", version-9+2, minorrev); | ataver = strprintf("Unknown(0x%04x)", drive->major_rev_num); |
| |
| if (minorver) |
| ataver += strprintf(", %s", minorver); |
| else if (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff) |
| ataver += strprintf(" (unknown minor revision code: 0x%04x)", drive->minor_rev_num); |
| else |
| ataver += " (minor revision not indicated)"; |
} |
} |
} |
} |
|
pout("ATA Version is: %s\n", infofound(ataver.c_str())); |
|
|
pout("ATA Version is: %s\n", infofound(majorstr.c_str())); | // If SATA drive print SATA version and speed |
pout("ATA Standard is: %s\n", infofound(minorstr.c_str())); | const char * sataver = get_sata_version(drive); |
| if (sataver) { |
| const char * maxspeed = get_sata_maxspeed(drive); |
| const char * curspeed = get_sata_curspeed(drive); |
| pout("SATA Version is: %s%s%s%s%s%s\n", sataver, |
| (maxspeed ? ", " : ""), (maxspeed ? maxspeed : ""), |
| (curspeed ? " (current: " : ""), (curspeed ? curspeed : ""), |
| (curspeed ? ")" : "")); |
| } |
|
|
// print current time and date and timezone |
// print current time and date and timezone |
char timedatetz[DATEANDEPOCHLEN]; dateandtimezone(timedatetz); |
char timedatetz[DATEANDEPOCHLEN]; dateandtimezone(timedatetz); |
Line 514 static void print_drive_info(const ata_identify_device
|
Line 657 static void print_drive_info(const ata_identify_device
|
// Print warning message, if there is one |
// Print warning message, if there is one |
if (dbentry && *dbentry->warningmsg) |
if (dbentry && *dbentry->warningmsg) |
pout("\n==> WARNING: %s\n\n", dbentry->warningmsg); |
pout("\n==> WARNING: %s\n\n", dbentry->warningmsg); |
|
|
if (!version || version >= 3) |
|
return; |
|
|
|
pout("SMART is only available in ATA Version 3 Revision 3 or greater.\n"); |
|
pout("We will try to proceed in spite of this.\n"); |
|
} |
} |
|
|
static const char *OfflineDataCollectionStatus(unsigned char status_byte) |
static const char *OfflineDataCollectionStatus(unsigned char status_byte) |
Line 573 static void PrintSmartOfflineStatus(const ata_smart_va
|
Line 710 static void PrintSmartOfflineStatus(const ata_smart_va
|
} |
} |
|
|
static void PrintSmartSelfExecStatus(const ata_smart_values * data, |
static void PrintSmartSelfExecStatus(const ata_smart_values * data, |
unsigned char fix_firmwarebug) | firmwarebug_defs firmwarebugs) |
{ |
{ |
pout("Self-test execution status: "); |
pout("Self-test execution status: "); |
|
|
Line 633 static void PrintSmartSelfExecStatus(const ata_smart_v
|
Line 770 static void PrintSmartSelfExecStatus(const ata_smart_v
|
pout("damage.\n"); |
pout("damage.\n"); |
break; |
break; |
case 15: |
case 15: |
if (fix_firmwarebug == FIX_SAMSUNG3 && data->self_test_exec_status == 0xf0) { | if (firmwarebugs.is_set(BUG_SAMSUNG3) && data->self_test_exec_status == 0xf0) { |
pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", |
pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", |
(int)data->self_test_exec_status); |
(int)data->self_test_exec_status); |
pout("with unknown result or self-test in\n\t\t\t\t\t"); |
pout("with unknown result or self-test in\n\t\t\t\t\t"); |
Line 798 static int find_failed_attr(const ata_smart_values * d
|
Line 935 static int find_failed_attr(const ata_smart_values * d
|
// onlyfailed=2: ones that are failed, or have failed with or without prefailure bit set |
// onlyfailed=2: ones that are failed, or have failed with or without prefailure bit set |
static void PrintSmartAttribWithThres(const ata_smart_values * data, |
static void PrintSmartAttribWithThres(const ata_smart_values * data, |
const ata_smart_thresholds_pvt * thresholds, |
const ata_smart_thresholds_pvt * thresholds, |
const ata_vendor_attr_defs & defs, | const ata_vendor_attr_defs & defs, int rpm, |
int onlyfailed, unsigned char format) |
int onlyfailed, unsigned char format) |
{ |
{ |
bool brief = !!(format & ata_print_options::FMT_BRIEF); |
bool brief = !!(format & ata_print_options::FMT_BRIEF); |
Line 859 static void PrintSmartAttribWithThres(const ata_smart_
|
Line 996 static void PrintSmartAttribWithThres(const ata_smart_
|
// Print line for each valid attribute |
// Print line for each valid attribute |
std::string idstr = (!hexid ? strprintf("%3d", attr.id) |
std::string idstr = (!hexid ? strprintf("%3d", attr.id) |
: strprintf("0x%02x", attr.id)); |
: strprintf("0x%02x", attr.id)); |
std::string attrname = ata_get_smart_attr_name(attr.id, defs); | std::string attrname = ata_get_smart_attr_name(attr.id, defs, rpm); |
std::string rawstr = ata_format_attr_raw_value(attr, defs); |
std::string rawstr = ata_format_attr_raw_value(attr, defs); |
|
|
if (!brief) |
if (!brief) |
Line 922 static void ataPrintSCTCapability(const ata_identify_d
|
Line 1059 static void ataPrintSCTCapability(const ata_identify_d
|
|
|
|
|
static void PrintGeneralSmartValues(const ata_smart_values *data, const ata_identify_device *drive, |
static void PrintGeneralSmartValues(const ata_smart_values *data, const ata_identify_device *drive, |
unsigned char fix_firmwarebug) | firmwarebug_defs firmwarebugs) |
{ |
{ |
pout("General SMART Values:\n"); |
pout("General SMART Values:\n"); |
|
|
PrintSmartOfflineStatus(data); |
PrintSmartOfflineStatus(data); |
|
|
if (isSupportSelfTest(data)){ |
if (isSupportSelfTest(data)){ |
PrintSmartSelfExecStatus(data, fix_firmwarebug); | PrintSmartSelfExecStatus(data, firmwarebugs); |
} |
} |
|
|
PrintSmartTotalTimeCompleteOffline(data); |
PrintSmartTotalTimeCompleteOffline(data); |
Line 971 static unsigned GetNumLogSectors(const ata_smart_log_d
|
Line 1108 static unsigned GetNumLogSectors(const ata_smart_log_d
|
} |
} |
|
|
// Get name of log. |
// Get name of log. |
// Table A.2 of T13/2161-D Revision 2 (ACS-3), February 21, 2012. | // Table A.2 of T13/2161-D (ACS-3) Revision 4, September 4, 2012 |
static const char * GetLogName(unsigned logaddr) |
static const char * GetLogName(unsigned logaddr) |
{ |
{ |
switch (logaddr) { |
switch (logaddr) { |
Line 980 static const char * GetLogName(unsigned logaddr)
|
Line 1117 static const char * GetLogName(unsigned logaddr)
|
case 0x02: return "Comprehensive SMART error log"; |
case 0x02: return "Comprehensive SMART error log"; |
case 0x03: return "Ext. Comprehensive SMART error log"; |
case 0x03: return "Ext. Comprehensive SMART error log"; |
case 0x04: return "Device Statistics log"; |
case 0x04: return "Device Statistics log"; |
case 0x05: return "Reserved for the CFA"; // ACS-2 | case 0x05: return "Reserved for CFA"; // ACS-2 |
case 0x06: return "SMART self-test log"; |
case 0x06: return "SMART self-test log"; |
case 0x07: return "Extended self-test log"; |
case 0x07: return "Extended self-test log"; |
case 0x08: return "Power Conditions log"; // ACS-2 |
case 0x08: return "Power Conditions log"; // ACS-2 |
case 0x09: return "Selective self-test log"; |
case 0x09: return "Selective self-test log"; |
|
case 0x0a: return "Device Statistics Notification"; // ACS-3 |
|
case 0x0b: return "Reserved for CFA"; // ACS-3 |
|
|
case 0x0d: return "LPS Mis-alignment log"; // ACS-2 |
case 0x0d: return "LPS Mis-alignment log"; // ACS-2 |
|
|
case 0x10: return "NCQ Command Error log"; |
case 0x10: return "NCQ Command Error log"; |
case 0x11: return "SATA Phy Event Counters"; |
case 0x11: return "SATA Phy Event Counters"; |
case 0x12: return "SATA NCQ Queue Management log"; // ACS-3 |
case 0x12: return "SATA NCQ Queue Management log"; // ACS-3 |
Line 993 static const char * GetLogName(unsigned logaddr)
|
Line 1134 static const char * GetLogName(unsigned logaddr)
|
case 0x14: |
case 0x14: |
case 0x15: |
case 0x15: |
case 0x16: return "Reserved for Serial ATA"; |
case 0x16: return "Reserved for Serial ATA"; |
|
|
case 0x19: return "LBA Status log"; // ACS-3 |
case 0x19: return "LBA Status log"; // ACS-3 |
case 0x20: return "Streaming performance log"; // Obsolete | |
| case 0x20: return "Streaming performance log [OBS-8]"; |
case 0x21: return "Write stream error log"; |
case 0x21: return "Write stream error log"; |
case 0x22: return "Read stream error log"; |
case 0x22: return "Read stream error log"; |
case 0x23: return "Delayed sector log"; // Obsolete | case 0x23: return "Delayed sector log [OBS-8]"; |
case 0x24: return "Current Device Internal Status Data log"; // ACS-3 |
case 0x24: return "Current Device Internal Status Data log"; // ACS-3 |
case 0x25: return "Saved Device Internal Status Data log"; // ACS-3 |
case 0x25: return "Saved Device Internal Status Data log"; // ACS-3 |
|
|
case 0x30: return "IDENTIFY DEVICE data log"; // ACS-3 |
case 0x30: return "IDENTIFY DEVICE data log"; // ACS-3 |
|
|
case 0xe0: return "SCT Command/Status"; |
case 0xe0: return "SCT Command/Status"; |
case 0xe1: return "SCT Data Transfer"; |
case 0xe1: return "SCT Data Transfer"; |
default: |
default: |
Line 1013 static const char * GetLogName(unsigned logaddr)
|
Line 1158 static const char * GetLogName(unsigned logaddr)
|
/*NOTREACHED*/ |
/*NOTREACHED*/ |
} |
} |
|
|
|
// Get log access permissions |
|
static const char * get_log_rw(unsigned logaddr) |
|
{ |
|
if ( ( logaddr <= 0x08) |
|
|| (0x0d == logaddr) |
|
|| (0x10 <= logaddr && logaddr <= 0x13) |
|
|| (0x19 == logaddr) |
|
|| (0x20 <= logaddr && logaddr <= 0x25) |
|
|| (0x30 == logaddr)) |
|
return "R/O"; |
|
|
|
if ( (0x09 <= logaddr && logaddr <= 0x0a) |
|
|| (0x80 <= logaddr && logaddr <= 0x9f) |
|
|| (0xe0 <= logaddr && logaddr <= 0xe1)) |
|
return "R/W"; |
|
|
|
if (0xa0 <= logaddr && logaddr <= 0xdf) |
|
return "VS"; // Vendor specific |
|
|
|
return "-"; // Unknown/Reserved |
|
} |
|
|
|
// Init a fake log directory, assume that standard logs are supported |
|
const ata_smart_log_directory * fake_logdir(ata_smart_log_directory * logdir, |
|
const ata_print_options & options) |
|
{ |
|
memset(logdir, 0, sizeof(*logdir)); |
|
logdir->logversion = 255; |
|
logdir->entry[0x01-1].numsectors = 1; |
|
logdir->entry[0x03-1].numsectors = (options.smart_ext_error_log + (4-1)) / 4; |
|
logdir->entry[0x04-1].numsectors = 8; |
|
logdir->entry[0x06-1].numsectors = 1; |
|
logdir->entry[0x07-1].numsectors = (options.smart_ext_selftest_log + (19-1)) / 19; |
|
logdir->entry[0x09-1].numsectors = 1; |
|
logdir->entry[0x11-1].numsectors = 1; |
|
return logdir; |
|
} |
|
|
// Print SMART and/or GP Log Directory |
// Print SMART and/or GP Log Directory |
static void PrintLogDirectories(const ata_smart_log_directory * gplogdir, |
static void PrintLogDirectories(const ata_smart_log_directory * gplogdir, |
const ata_smart_log_directory * smartlogdir) |
const ata_smart_log_directory * smartlogdir) |
Line 1024 static void PrintLogDirectories(const ata_smart_log_di
|
Line 1207 static void PrintLogDirectories(const ata_smart_log_di
|
(gplogdir ? " " : ""), smartlogdir->logversion, |
(gplogdir ? " " : ""), smartlogdir->logversion, |
(smartlogdir->logversion==1 ? " [multi-sector log support]" : "")); |
(smartlogdir->logversion==1 ? " [multi-sector log support]" : "")); |
|
|
|
pout("Address Access R/W Size Description\n"); |
|
|
for (unsigned i = 0; i <= 0xff; i++) { |
for (unsigned i = 0; i <= 0xff; i++) { |
// Get number of sectors |
// Get number of sectors |
unsigned smart_numsect = GetNumLogSectors(smartlogdir, i, false); |
unsigned smart_numsect = GetNumLogSectors(smartlogdir, i, false); |
Line 1032 static void PrintLogDirectories(const ata_smart_log_di
|
Line 1217 static void PrintLogDirectories(const ata_smart_log_di
|
if (!(smart_numsect || gp_numsect)) |
if (!(smart_numsect || gp_numsect)) |
continue; // Log does not exist |
continue; // Log does not exist |
|
|
|
const char * acc; unsigned size; |
|
if (smart_numsect == gp_numsect) { |
|
acc = "GPL,SL"; size = gp_numsect; |
|
} |
|
else if (!smart_numsect) { |
|
acc = "GPL"; size = gp_numsect; |
|
} |
|
else if (!gp_numsect) { |
|
acc = " SL"; size = smart_numsect; |
|
} |
|
else { |
|
acc = 0; size = 0; |
|
} |
|
|
|
unsigned i2 = i; |
|
if (acc && ((0x80 <= i && i < 0x9f) || (0xa0 <= i && i < 0xdf))) { |
|
// Find range of Host/Device vendor specific logs with same size |
|
unsigned imax = (i < 0x9f ? 0x9f : 0xdf); |
|
for (unsigned j = i+1; j <= imax; j++) { |
|
unsigned sn = GetNumLogSectors(smartlogdir, j, false); |
|
unsigned gn = GetNumLogSectors(gplogdir , j, true ); |
|
|
|
if (!(sn == smart_numsect && gn == gp_numsect)) |
|
break; |
|
i2 = j; |
|
} |
|
} |
|
|
const char * name = GetLogName(i); |
const char * name = GetLogName(i); |
|
const char * rw = get_log_rw(i); |
|
|
// Print name and length of log. | if (i2 > i) { |
// If both SMART and GP exist, print separate entries if length differ. | pout("0x%02x-0x%02x %-6s %-3s %5u %s\n", i, i2, acc, rw, size, name); |
if (smart_numsect == gp_numsect) | i = i2; |
pout( "GP/S Log at address 0x%02x has %4d sectors [%s]\n", i, smart_numsect, name); | } |
| else if (acc) |
| pout( "0x%02x %-6s %-3s %5u %s\n", i, acc, rw, size, name); |
else { |
else { |
if (gp_numsect) | // GPL and SL support different sizes |
pout("GP %sLog at address 0x%02x has %4d sectors [%s]\n", (smartlogdir?" ":""), | pout( "0x%02x %-6s %-3s %5u %s\n", i, "GPL", rw, gp_numsect, name); |
i, gp_numsect, name); | pout( "0x%02x %-6s %-3s %5u %s\n", i, "SL", rw, smart_numsect, name); |
if (smart_numsect) | |
pout("SMART Log at address 0x%02x has %4d sectors [%s]\n", i, smart_numsect, name); | |
} |
} |
} |
} |
pout("\n"); |
pout("\n"); |
Line 1227 static void print_device_statistics_page(const unsigne
|
Line 1441 static void print_device_statistics_page(const unsigne
|
} |
} |
else { |
else { |
// Value not known (yet) |
// Value not known (yet) |
strcpy(valstr, "-"); | valstr[0] = '-'; valstr[1] = 0; |
} |
} |
|
|
pout("%3d 0x%03x %d%c %15s%c %s\n", |
pout("%3d 0x%03x %d%c %15s%c %s\n", |
Line 1247 static bool print_device_statistics(ata_device * devic
|
Line 1461 static bool print_device_statistics(ata_device * devic
|
{ |
{ |
// Read list of supported pages from page 0 |
// Read list of supported pages from page 0 |
unsigned char page_0[512] = {0, }; |
unsigned char page_0[512] = {0, }; |
if (!ataReadLogExt(device, 0x04, 0, 0, page_0, 1)) | if (!ataReadLogExt(device, 0x04, 0, 0, page_0, 1)) { |
| pout("Read Device Statistics page 0 failed\n\n"); |
return false; |
return false; |
|
} |
|
|
unsigned char nentries = page_0[8]; |
unsigned char nentries = page_0[8]; |
if (!(page_0[2] == 0 && nentries > 0)) { |
if (!(page_0[2] == 0 && nentries > 0)) { |
pout("Device Statistics page 0 is invalid (page=%d, nentries=%d)\n", page_0[2], nentries); | pout("Device Statistics page 0 is invalid (page=%d, nentries=%d)\n\n", page_0[2], nentries); |
return false; |
return false; |
} |
} |
|
|
Line 1303 static bool print_device_statistics(ata_device * devic
|
Line 1519 static bool print_device_statistics(ata_device * devic
|
for (i = 0; i < pages.size(); i++) { |
for (i = 0; i < pages.size(); i++) { |
int page = pages[i]; |
int page = pages[i]; |
unsigned char page_n[512] = {0, }; |
unsigned char page_n[512] = {0, }; |
if (!ataReadLogExt(device, 0x04, 0, page, page_n, 1)) | if (!ataReadLogExt(device, 0x04, 0, page, page_n, 1)) { |
| pout("Read Device Statistics page %d failed\n\n", page); |
return false; |
return false; |
|
} |
print_device_statistics_page(page_n, page, need_trailer); |
print_device_statistics_page(page_n, page, need_trailer); |
} |
} |
|
|
Line 1385 static void PrintSataPhyEventCounters(const unsigned c
|
Line 1603 static void PrintSataPhyEventCounters(const unsigned c
|
pout("\n"); |
pout("\n"); |
} |
} |
|
|
|
// Format milliseconds from error log entry as "DAYS+H:M:S.MSEC" |
|
static std::string format_milliseconds(unsigned msec) |
|
{ |
|
unsigned days = msec / 86400000U; |
|
msec -= days * 86400000U; |
|
unsigned hours = msec / 3600000U; |
|
msec -= hours * 3600000U; |
|
unsigned min = msec / 60000U; |
|
msec -= min * 60000U; |
|
unsigned sec = msec / 1000U; |
|
msec -= sec * 1000U; |
|
|
|
std::string str; |
|
if (days) |
|
str = strprintf("%2ud+", days); |
|
str += strprintf("%02u:%02u:%02u.%03u", hours, min, sec, msec); |
|
return str; |
|
} |
|
|
// Get description for 'state' value from SMART Error Logs |
// Get description for 'state' value from SMART Error Logs |
static const char * get_error_log_state_desc(unsigned state) |
static const char * get_error_log_state_desc(unsigned state) |
{ |
{ |
Line 1403 static const char * get_error_log_state_desc(unsigned
|
Line 1640 static const char * get_error_log_state_desc(unsigned
|
|
|
// returns number of errors |
// returns number of errors |
static int PrintSmartErrorlog(const ata_smart_errorlog *data, |
static int PrintSmartErrorlog(const ata_smart_errorlog *data, |
unsigned char fix_firmwarebug) | firmwarebug_defs firmwarebugs) |
{ |
{ |
pout("SMART Error Log Version: %d\n", (int)data->revnumber); |
pout("SMART Error Log Version: %d\n", (int)data->revnumber); |
|
|
Line 1422 static int PrintSmartErrorlog(const ata_smart_errorlog
|
Line 1659 static int PrintSmartErrorlog(const ata_smart_errorlog
|
} |
} |
|
|
// Some internal consistency checking of the data structures |
// Some internal consistency checking of the data structures |
if ((data->ata_error_count-data->error_log_pointer)%5 && fix_firmwarebug != FIX_SAMSUNG2) { | if ((data->ata_error_count-data->error_log_pointer) % 5 && !firmwarebugs.is_set(BUG_SAMSUNG2)) { |
pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n", |
pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n", |
data->ata_error_count,data->error_log_pointer); |
data->ata_error_count,data->error_log_pointer); |
} |
} |
Line 1481 static int PrintSmartErrorlog(const ata_smart_errorlog
|
Line 1718 static int PrintSmartErrorlog(const ata_smart_errorlog
|
(int)summary->drive_head); |
(int)summary->drive_head); |
// Add a description of the contents of the status and error registers |
// Add a description of the contents of the status and error registers |
// if possible |
// if possible |
char descbuf[256]; | std::string st_er_desc = format_st_er_desc(elog); |
const char * st_er_desc = construct_st_er_desc(descbuf, elog); | if (!st_er_desc.empty()) |
if (st_er_desc) | pout(" %s", st_er_desc.c_str()); |
pout(" %s", st_er_desc); | |
pout("\n\n"); |
pout("\n\n"); |
pout(" Commands leading to the command that caused the error were:\n" |
pout(" Commands leading to the command that caused the error were:\n" |
" CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n" |
" CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n" |
Line 1494 static int PrintSmartErrorlog(const ata_smart_errorlog
|
Line 1730 static int PrintSmartErrorlog(const ata_smart_errorlog
|
|
|
// Spec says: unused data command structures shall be zero filled |
// Spec says: unused data command structures shall be zero filled |
if (nonempty(thiscommand, sizeof(*thiscommand))) { |
if (nonempty(thiscommand, sizeof(*thiscommand))) { |
char timestring[32]; |
|
|
|
// Convert integer milliseconds to a text-format string |
|
MsecToText(thiscommand->timestamp, timestring); |
|
|
|
pout(" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n", |
pout(" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n", |
(int)thiscommand->commandreg, |
(int)thiscommand->commandreg, |
(int)thiscommand->featuresreg, |
(int)thiscommand->featuresreg, |
Line 1508 static int PrintSmartErrorlog(const ata_smart_errorlog
|
Line 1739 static int PrintSmartErrorlog(const ata_smart_errorlog
|
(int)thiscommand->cylinder_high, |
(int)thiscommand->cylinder_high, |
(int)thiscommand->drive_head, |
(int)thiscommand->drive_head, |
(int)thiscommand->devicecontrolreg, |
(int)thiscommand->devicecontrolreg, |
timestring, | format_milliseconds(thiscommand->timestamp).c_str(), |
look_up_ata_command(thiscommand->commandreg, thiscommand->featuresreg)); |
look_up_ata_command(thiscommand->commandreg, thiscommand->featuresreg)); |
} |
} |
} |
} |
Line 1626 static int PrintSmartExtErrorLog(const ata_smart_exter
|
Line 1857 static int PrintSmartExtErrorLog(const ata_smart_exter
|
|
|
// Add a description of the contents of the status and error registers |
// Add a description of the contents of the status and error registers |
// if possible |
// if possible |
char descbuf[256]; | std::string st_er_desc = format_st_er_desc(&entry); |
const char * st_er_desc = construct_st_er_desc(descbuf, &entry); | if (!st_er_desc.empty()) |
if (st_er_desc) | pout(" %s", st_er_desc.c_str()); |
pout(" %s", st_er_desc); | |
pout("\n\n"); |
pout("\n\n"); |
|
|
// Print command history |
// Print command history |
Line 1644 static int PrintSmartExtErrorLog(const ata_smart_exter
|
Line 1874 static int PrintSmartExtErrorLog(const ata_smart_exter
|
continue; |
continue; |
|
|
// Print registers, timestamp and ATA command name |
// Print registers, timestamp and ATA command name |
char timestring[32]; |
|
MsecToText(cmd.timestamp, timestring); |
|
|
|
pout(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n", |
pout(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n", |
cmd.command_register, |
cmd.command_register, |
cmd.features_register_hi, |
cmd.features_register_hi, |
Line 1661 static int PrintSmartExtErrorLog(const ata_smart_exter
|
Line 1888 static int PrintSmartExtErrorLog(const ata_smart_exter
|
cmd.lba_low_register, |
cmd.lba_low_register, |
cmd.device_register, |
cmd.device_register, |
cmd.device_control_register, |
cmd.device_control_register, |
timestring, | format_milliseconds(cmd.timestamp).c_str(), |
look_up_ata_command(cmd.command_register, cmd.features_register)); |
look_up_ata_command(cmd.command_register, cmd.features_register)); |
} |
} |
pout("\n"); |
pout("\n"); |
Line 1869 static void ataPrintSelectiveSelfTestLog(const ata_sel
|
Line 2096 static void ataPrintSelectiveSelfTestLog(const ata_sel
|
} |
} |
|
|
// Format SCT Temperature value |
// Format SCT Temperature value |
static const char * sct_ptemp(signed char x, char * buf) | static const char * sct_ptemp(signed char x, char (& buf)[20]) |
{ |
{ |
if (x == -128 /*0x80 = unknown*/) |
if (x == -128 /*0x80 = unknown*/) |
strcpy(buf, " ?"); | return " ?"; |
else | snprintf(buf, sizeof(buf), "%2d", x); |
sprintf(buf, "%2d", x); | |
return buf; |
return buf; |
} |
} |
|
|
static const char * sct_pbar(int x, char * buf) | static const char * sct_pbar(int x, char (& buf)[64]) |
{ |
{ |
if (x <= 19) |
if (x <= 19) |
x = 0; |
x = 0; |
Line 1957 static int ataPrintSCTStatus(const ata_sct_status_resp
|
Line 2183 static int ataPrintSCTStatus(const ata_sct_status_resp
|
// Print SCT Temperature History Table |
// Print SCT Temperature History Table |
static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh) |
static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh) |
{ |
{ |
char buf1[20], buf2[80]; | char buf1[20], buf2[20], buf3[64]; |
pout("SCT Temperature History Version: %u\n", tmh->format_version); | pout("SCT Temperature History Version: %u%s\n", tmh->format_version, |
| (tmh->format_version != 2 ? " (Unknown, should be 2)" : "")); |
pout("Temperature Sampling Period: %u minute%s\n", |
pout("Temperature Sampling Period: %u minute%s\n", |
tmh->sampling_period, (tmh->sampling_period==1?"":"s")); |
tmh->sampling_period, (tmh->sampling_period==1?"":"s")); |
pout("Temperature Logging Interval: %u minute%s\n", |
pout("Temperature Logging Interval: %u minute%s\n", |
Line 1968 static int ataPrintSCTTempHist(const ata_sct_temperatu
|
Line 2195 static int ataPrintSCTTempHist(const ata_sct_temperatu
|
pout("Min/Max Temperature Limit: %s/%s Celsius\n", |
pout("Min/Max Temperature Limit: %s/%s Celsius\n", |
sct_ptemp(tmh->under_limit, buf1), sct_ptemp(tmh->over_limit, buf2)); |
sct_ptemp(tmh->under_limit, buf1), sct_ptemp(tmh->over_limit, buf2)); |
pout("Temperature History Size (Index): %u (%u)\n", tmh->cb_size, tmh->cb_index); |
pout("Temperature History Size (Index): %u (%u)\n", tmh->cb_size, tmh->cb_index); |
|
|
if (!(0 < tmh->cb_size && tmh->cb_size <= sizeof(tmh->cb) && tmh->cb_index < tmh->cb_size)) { |
if (!(0 < tmh->cb_size && tmh->cb_size <= sizeof(tmh->cb) && tmh->cb_index < tmh->cb_size)) { |
pout("Error invalid Temperature History Size or Index\n"); | if (!tmh->cb_size) |
| pout("Temperature History is empty\n"); |
| else |
| pout("Invalid Temperature History Size or Index\n"); |
return 0; |
return 0; |
} |
} |
|
|
Line 1992 static int ataPrintSCTTempHist(const ata_sct_temperatu
|
Line 2223 static int ataPrintSCTTempHist(const ata_sct_temperatu
|
// TODO: Don't print times < boot time |
// TODO: Don't print times < boot time |
strftime(date, sizeof(date), "%Y-%m-%d %H:%M", localtime(&t)); |
strftime(date, sizeof(date), "%Y-%m-%d %H:%M", localtime(&t)); |
pout(" %3u %s %s %s\n", i, date, |
pout(" %3u %s %s %s\n", i, date, |
sct_ptemp(tmh->cb[i], buf1), sct_pbar(tmh->cb[i], buf2)); | sct_ptemp(tmh->cb[i], buf1), sct_pbar(tmh->cb[i], buf3)); |
} |
} |
else if (n == n1+1) { |
else if (n == n1+1) { |
pout(" ... ..(%3u skipped). .. %s\n", |
pout(" ... ..(%3u skipped). .. %s\n", |
n2-n1-2, sct_pbar(tmh->cb[i], buf2)); | n2-n1-2, sct_pbar(tmh->cb[i], buf3)); |
} |
} |
t += interval * 60; i = (i+1) % tmh->cb_size; n++; |
t += interval * 60; i = (i+1) % tmh->cb_size; n++; |
} |
} |
Line 2206 int ataPrintMain (ata_device * device, const ata_print
|
Line 2437 int ataPrintMain (ata_device * device, const ata_print
|
options.gp_logdir |
options.gp_logdir |
|| options.smart_ext_error_log |
|| options.smart_ext_error_log |
|| options.smart_ext_selftest_log |
|| options.smart_ext_selftest_log |
|| options.sataphy |
|
|| options.devstat_all_pages |
|| options.devstat_all_pages |
|| options.devstat_ssd_page |
|| options.devstat_ssd_page |
|| !options.devstat_pages.empty() |
|| !options.devstat_pages.empty() |
Line 2230 int ataPrintMain (ata_device * device, const ata_print
|
Line 2460 int ataPrintMain (ata_device * device, const ata_print
|
); |
); |
|
|
// Exit if no further options specified |
// Exit if no further options specified |
if (!( options.drive_info || need_smart_support | if (!( options.drive_info || options.show_presets |
|| need_smart_logdir || need_gp_logdir | || need_smart_support || need_smart_logdir |
|| need_sct_support || options.get_set_used)) { | || need_gp_logdir || need_sct_support |
| || options.sataphy |
| || options.identify_word_level >= 0 |
| || options.get_set_used )) { |
if (powername) |
if (powername) |
pout("Device is in %s mode\n", powername); |
pout("Device is in %s mode\n", powername); |
else |
else |
Line 2244 int ataPrintMain (ata_device * device, const ata_print
|
Line 2477 int ataPrintMain (ata_device * device, const ata_print
|
// Start by getting Drive ID information. We need this, to know if SMART is supported. |
// Start by getting Drive ID information. We need this, to know if SMART is supported. |
int returnval = 0; |
int returnval = 0; |
ata_identify_device drive; memset(&drive, 0, sizeof(drive)); |
ata_identify_device drive; memset(&drive, 0, sizeof(drive)); |
|
unsigned char raw_drive[sizeof(drive)]; memset(&raw_drive, 0, sizeof(raw_drive)); |
|
|
device->clear_err(); |
device->clear_err(); |
int retid = ata_read_identity(device, &drive, options.fix_swapped_id); | int retid = ata_read_identity(device, &drive, options.fix_swapped_id, raw_drive); |
if (retid < 0) { |
if (retid < 0) { |
pout("Smartctl: Device Read Identity Failed: %s\n\n", | pout("Read Device Identity failed: %s\n\n", |
(device->get_errno() ? device->get_errmsg() : "Unknown error")); |
(device->get_errno() ? device->get_errmsg() : "Unknown error")); |
failuretest(MANDATORY_CMD, returnval|=FAILID); |
failuretest(MANDATORY_CMD, returnval|=FAILID); |
} |
} |
else if (!nonempty(&drive, sizeof(drive))) { |
else if (!nonempty(&drive, sizeof(drive))) { |
pout("Smartctl: Device Read Identity Failed: empty IDENTIFY data\n\n"); | pout("Read Device Identity failed: empty IDENTIFY data\n\n"); |
failuretest(MANDATORY_CMD, returnval|=FAILID); |
failuretest(MANDATORY_CMD, returnval|=FAILID); |
} |
} |
|
|
Line 2264 int ataPrintMain (ata_device * device, const ata_print
|
Line 2499 int ataPrintMain (ata_device * device, const ata_print
|
|
|
// Use preset vendor attribute options unless user has requested otherwise. |
// Use preset vendor attribute options unless user has requested otherwise. |
ata_vendor_attr_defs attribute_defs = options.attribute_defs; |
ata_vendor_attr_defs attribute_defs = options.attribute_defs; |
unsigned char fix_firmwarebug = options.fix_firmwarebug; | firmwarebug_defs firmwarebugs = options.firmwarebugs; |
const drive_settings * dbentry = 0; |
const drive_settings * dbentry = 0; |
if (!options.ignore_presets) |
if (!options.ignore_presets) |
dbentry = lookup_drive_apply_presets(&drive, attribute_defs, |
dbentry = lookup_drive_apply_presets(&drive, attribute_defs, |
fix_firmwarebug); | firmwarebugs); |
|
|
// Get capacity and sector sizes | // Get capacity, sector sizes and rotation rate |
ata_size_info sizes; |
ata_size_info sizes; |
ata_get_size_info(&drive, sizes); |
ata_get_size_info(&drive, sizes); |
|
int rpm = ata_get_rotation_rate(&drive); |
|
|
|
// Print ATA IDENTIFY info if requested |
|
if (options.identify_word_level >= 0) { |
|
pout("=== ATA IDENTIFY DATA ===\n"); |
|
// Pass raw data without endianness adjustments |
|
ata_print_identify_data(raw_drive, (options.identify_word_level > 0), options.identify_bit_level); |
|
} |
|
|
// Print most drive identity information if requested |
// Print most drive identity information if requested |
if (options.drive_info) { |
if (options.drive_info) { |
pout("=== START OF INFORMATION SECTION ===\n"); |
pout("=== START OF INFORMATION SECTION ===\n"); |
print_drive_info(&drive, sizes, dbentry); | print_drive_info(&drive, sizes, rpm, dbentry); |
} |
} |
|
|
// Check and print SMART support and state |
// Check and print SMART support and state |
Line 2476 int ataPrintMain (ata_device * device, const ata_print
|
Line 2719 int ataPrintMain (ata_device * device, const ata_print
|
// Enable/Disable SMART commands |
// Enable/Disable SMART commands |
if (options.smart_enable) { |
if (options.smart_enable) { |
if (ataEnableSmart(device)) { |
if (ataEnableSmart(device)) { |
pout("Smartctl: SMART Enable Failed.\n\n"); | pout("SMART Enable failed: %s\n\n", device->get_errmsg()); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
} |
} |
else { |
else { |
Line 2488 int ataPrintMain (ata_device * device, const ata_print
|
Line 2731 int ataPrintMain (ata_device * device, const ata_print
|
// Turn off SMART on device |
// Turn off SMART on device |
if (options.smart_disable) { |
if (options.smart_disable) { |
if (ataDisableSmart(device)) { |
if (ataDisableSmart(device)) { |
pout( "Smartctl: SMART Disable Failed.\n\n"); | pout("SMART Disable failed: %s\n\n", device->get_errmsg()); |
failuretest(MANDATORY_CMD,returnval|=FAILSMART); |
failuretest(MANDATORY_CMD,returnval|=FAILSMART); |
} |
} |
} |
} |
|
|
// Exit if SMART is disabled but must be enabled to proceed |
// Exit if SMART is disabled but must be enabled to proceed |
if (options.smart_disable || (smart_enabled <= 0 && need_smart_enabled)) { | if (options.smart_disable || (smart_enabled <= 0 && need_smart_enabled && !is_permissive())) { |
pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n"); |
pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n"); |
|
if (!options.smart_disable) |
|
pout("(override with '-T permissive' option)\n"); |
return returnval; |
return returnval; |
} |
} |
|
|
// Enable/Disable Auto-save attributes |
// Enable/Disable Auto-save attributes |
if (options.smart_auto_save_enable) { |
if (options.smart_auto_save_enable) { |
if (ataEnableAutoSave(device)){ |
if (ataEnableAutoSave(device)){ |
pout( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n"); | pout("SMART Enable Attribute Autosave failed: %s\n\n", device->get_errmsg()); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2511 int ataPrintMain (ata_device * device, const ata_print
|
Line 2756 int ataPrintMain (ata_device * device, const ata_print
|
|
|
if (options.smart_auto_save_disable) { |
if (options.smart_auto_save_disable) { |
if (ataDisableAutoSave(device)){ |
if (ataDisableAutoSave(device)){ |
pout( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n"); | pout("SMART Disable Attribute Autosave failed: %s\n\n", device->get_errmsg()); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2525 int ataPrintMain (ata_device * device, const ata_print
|
Line 2770 int ataPrintMain (ata_device * device, const ata_print
|
|
|
if (need_smart_val) { |
if (need_smart_val) { |
if (ataReadSmartValues(device, &smartval)) { |
if (ataReadSmartValues(device, &smartval)) { |
pout("Smartctl: SMART Read Values failed.\n\n"); | pout("Read SMART Data failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else { |
else { |
Line 2533 int ataPrintMain (ata_device * device, const ata_print
|
Line 2778 int ataPrintMain (ata_device * device, const ata_print
|
|
|
if (options.smart_check_status || options.smart_vendor_attrib) { |
if (options.smart_check_status || options.smart_vendor_attrib) { |
if (ataReadSmartThresholds(device, &smartthres)){ |
if (ataReadSmartThresholds(device, &smartthres)){ |
pout("Smartctl: SMART Read Thresholds failed.\n\n"); | pout("Read SMART Thresholds failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2546 int ataPrintMain (ata_device * device, const ata_print
|
Line 2791 int ataPrintMain (ata_device * device, const ata_print
|
bool needupdate = false; |
bool needupdate = false; |
if (options.smart_auto_offl_enable) { |
if (options.smart_auto_offl_enable) { |
if (!isSupportAutomaticTimer(&smartval)){ |
if (!isSupportAutomaticTimer(&smartval)){ |
pout("Warning: device does not support SMART Automatic Timers.\n\n"); | pout("SMART Automatic Timers not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
needupdate = smart_val_ok; |
needupdate = smart_val_ok; |
if (ataEnableAutoOffline(device)){ |
if (ataEnableAutoOffline(device)){ |
pout( "Smartctl: SMART Enable Automatic Offline Failed.\n\n"); | pout("SMART Enable Automatic Offline failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2560 int ataPrintMain (ata_device * device, const ata_print
|
Line 2805 int ataPrintMain (ata_device * device, const ata_print
|
|
|
if (options.smart_auto_offl_disable) { |
if (options.smart_auto_offl_disable) { |
if (!isSupportAutomaticTimer(&smartval)){ |
if (!isSupportAutomaticTimer(&smartval)){ |
pout("Warning: device does not support SMART Automatic Timers.\n\n"); | pout("SMART Automatic Timers not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
needupdate = smart_val_ok; |
needupdate = smart_val_ok; |
if (ataDisableAutoOffline(device)){ |
if (ataDisableAutoOffline(device)){ |
pout("Smartctl: SMART Disable Automatic Offline Failed.\n\n"); | pout("SMART Disable Automatic Offline failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2573 int ataPrintMain (ata_device * device, const ata_print
|
Line 2818 int ataPrintMain (ata_device * device, const ata_print
|
} |
} |
|
|
if (needupdate && ataReadSmartValues(device, &smartval)){ |
if (needupdate && ataReadSmartValues(device, &smartval)){ |
pout("Smartctl: SMART Read Values failed.\n\n"); | pout("Read SMART Data failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
smart_val_ok = false; |
smart_val_ok = false; |
} |
} |
Line 2606 int ataPrintMain (ata_device * device, const ata_print
|
Line 2851 int ataPrintMain (ata_device * device, const ata_print
|
else { |
else { |
print_on(); |
print_on(); |
pout("Please note the following marginal Attributes:\n"); |
pout("Please note the following marginal Attributes:\n"); |
PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2, options.output_format); | PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format); |
} |
} |
returnval|=FAILAGE; |
returnval|=FAILAGE; |
} |
} |
Line 2627 int ataPrintMain (ata_device * device, const ata_print
|
Line 2872 int ataPrintMain (ata_device * device, const ata_print
|
else { |
else { |
print_on(); |
print_on(); |
pout("Failed Attributes:\n"); |
pout("Failed Attributes:\n"); |
PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1, options.output_format); | PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format); |
} |
} |
} |
} |
else |
else |
Line 2660 int ataPrintMain (ata_device * device, const ata_print
|
Line 2905 int ataPrintMain (ata_device * device, const ata_print
|
else { |
else { |
print_on(); |
print_on(); |
pout("Failed Attributes:\n"); |
pout("Failed Attributes:\n"); |
PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1, options.output_format); | PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format); |
} |
} |
} |
} |
else { |
else { |
Line 2672 int ataPrintMain (ata_device * device, const ata_print
|
Line 2917 int ataPrintMain (ata_device * device, const ata_print
|
else { |
else { |
print_on(); |
print_on(); |
pout("Please note the following marginal Attributes:\n"); |
pout("Please note the following marginal Attributes:\n"); |
PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2, options.output_format); | PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format); |
} |
} |
returnval|=FAILAGE; |
returnval|=FAILAGE; |
} |
} |
Line 2688 int ataPrintMain (ata_device * device, const ata_print
|
Line 2933 int ataPrintMain (ata_device * device, const ata_print
|
|
|
// Print general SMART values |
// Print general SMART values |
if (smart_val_ok && options.smart_general_values) |
if (smart_val_ok && options.smart_general_values) |
PrintGeneralSmartValues(&smartval, &drive, fix_firmwarebug); | PrintGeneralSmartValues(&smartval, &drive, firmwarebugs); |
|
|
// Print vendor-specific attributes |
// Print vendor-specific attributes |
if (smart_val_ok && options.smart_vendor_attrib) { |
if (smart_val_ok && options.smart_vendor_attrib) { |
print_on(); |
print_on(); |
PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, | PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, |
(printing_is_switchable ? 2 : 0), options.output_format); |
(printing_is_switchable ? 2 : 0), options.output_format); |
print_off(); |
print_off(); |
} |
} |
Line 2710 int ataPrintMain (ata_device * device, const ata_print
|
Line 2955 int ataPrintMain (ata_device * device, const ata_print
|
|
|
// Read SMART Log directory |
// Read SMART Log directory |
if (need_smart_logdir) { |
if (need_smart_logdir) { |
if (ataReadLogDirectory(device, &smartlogdir_buf, false)) { | if (firmwarebugs.is_set(BUG_NOLOGDIR)) |
pout("Read SMART Log Directory failed.\n\n"); | smartlogdir = fake_logdir(&smartlogdir_buf, options); |
| else if (ataReadLogDirectory(device, &smartlogdir_buf, false)) { |
| pout("Read SMART Log Directory failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2720 int ataPrintMain (ata_device * device, const ata_print
|
Line 2967 int ataPrintMain (ata_device * device, const ata_print
|
|
|
// Read GP Log directory |
// Read GP Log directory |
if (need_gp_logdir) { |
if (need_gp_logdir) { |
if (ataReadLogDirectory(device, &gplogdir_buf, true)) { | if (firmwarebugs.is_set(BUG_NOLOGDIR)) |
pout("Read GP Log Directory failed.\n\n"); | gplogdir = fake_logdir(&gplogdir_buf, options); |
| else if (ataReadLogDirectory(device, &gplogdir_buf, true)) { |
| pout("Read GP Log Directory failed\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2729 int ataPrintMain (ata_device * device, const ata_print
|
Line 2978 int ataPrintMain (ata_device * device, const ata_print
|
} |
} |
|
|
// Print log directories |
// Print log directories |
if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir)) | if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir)) { |
PrintLogDirectories(gplogdir, smartlogdir); | if (firmwarebugs.is_set(BUG_NOLOGDIR)) |
| pout("Log Directories not read due to '-F nologdir' option\n\n"); |
| else |
| PrintLogDirectories(gplogdir, smartlogdir); |
| } |
|
|
// Print log pages |
// Print log pages |
for (i = 0; i < options.log_requests.size(); i++) { |
for (i = 0; i < options.log_requests.size(); i++) { |
Line 2787 int ataPrintMain (ata_device * device, const ata_print
|
Line 3040 int ataPrintMain (ata_device * device, const ata_print
|
bool ok = false; |
bool ok = false; |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true); |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true); |
if (!nsectors) |
if (!nsectors) |
pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n"); | pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n\n"); |
else if (nsectors >= 256) |
else if (nsectors >= 256) |
pout("SMART Extended Comprehensive Error Log size %u not supported\n", nsectors); | pout("SMART Extended Comprehensive Error Log size %u not supported\n\n", nsectors); |
else { |
else { |
raw_buffer log_03_buf(nsectors * 512); |
raw_buffer log_03_buf(nsectors * 512); |
ata_smart_exterrlog * log_03 = (ata_smart_exterrlog *)log_03_buf.data(); |
ata_smart_exterrlog * log_03 = (ata_smart_exterrlog *)log_03_buf.data(); |
if (!ataReadExtErrorLog(device, log_03, nsectors)) | if (!ataReadExtErrorLog(device, log_03, nsectors, firmwarebugs)) { |
| pout("Read SMART Extended Comprehensive Error Log failed\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
|
} |
else { |
else { |
if (PrintSmartExtErrorLog(log_03, nsectors, options.smart_ext_error_log)) |
if (PrintSmartExtErrorLog(log_03, nsectors, options.smart_ext_error_log)) |
returnval |= FAILERR; |
returnval |= FAILERR; |
Line 2815 int ataPrintMain (ata_device * device, const ata_print
|
Line 3070 int ataPrintMain (ata_device * device, const ata_print
|
if (!( ( smartlogdir && GetNumLogSectors(smartlogdir, 0x01, false)) |
if (!( ( smartlogdir && GetNumLogSectors(smartlogdir, 0x01, false)) |
|| (!smartlogdir && isSmartErrorLogCapable(&smartval, &drive) ) |
|| (!smartlogdir && isSmartErrorLogCapable(&smartval, &drive) ) |
|| is_permissive() )) { |
|| is_permissive() )) { |
pout("SMART Error Log not supported\n"); | pout("SMART Error Log not supported\n\n"); |
} |
} |
else { |
else { |
ata_smart_errorlog smarterror; memset(&smarterror, 0, sizeof(smarterror)); |
ata_smart_errorlog smarterror; memset(&smarterror, 0, sizeof(smarterror)); |
if (ataReadErrorLog(device, &smarterror, fix_firmwarebug)) { | if (ataReadErrorLog(device, &smarterror, firmwarebugs)) { |
pout("Smartctl: SMART Error Log Read Failed\n"); | pout("Read SMART Error Log failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else { |
else { |
// quiet mode is turned on inside PrintSmartErrorLog() |
// quiet mode is turned on inside PrintSmartErrorLog() |
if (PrintSmartErrorlog(&smarterror, fix_firmwarebug)) | if (PrintSmartErrorlog(&smarterror, firmwarebugs)) |
returnval|=FAILERR; |
returnval|=FAILERR; |
print_off(); |
print_off(); |
} |
} |
Line 2838 int ataPrintMain (ata_device * device, const ata_print
|
Line 3093 int ataPrintMain (ata_device * device, const ata_print
|
bool ok = false; |
bool ok = false; |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true); |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true); |
if (!nsectors) |
if (!nsectors) |
pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n"); | pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n\n"); |
else if (nsectors >= 256) |
else if (nsectors >= 256) |
pout("SMART Extended Self-test Log size %u not supported\n", nsectors); | pout("SMART Extended Self-test Log size %u not supported\n\n", nsectors); |
else { |
else { |
raw_buffer log_07_buf(nsectors * 512); |
raw_buffer log_07_buf(nsectors * 512); |
ata_smart_extselftestlog * log_07 = (ata_smart_extselftestlog *)log_07_buf.data(); |
ata_smart_extselftestlog * log_07 = (ata_smart_extselftestlog *)log_07_buf.data(); |
if (!ataReadExtSelfTestLog(device, log_07, nsectors)) | if (!ataReadExtSelfTestLog(device, log_07, nsectors)) { |
| pout("Read SMART Extended Self-test Log failed\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
|
} |
else { |
else { |
if (PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log)) |
if (PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log)) |
returnval |= FAILLOG; |
returnval |= FAILLOG; |
Line 2866 int ataPrintMain (ata_device * device, const ata_print
|
Line 3123 int ataPrintMain (ata_device * device, const ata_print
|
if (!( ( smartlogdir && GetNumLogSectors(smartlogdir, 0x06, false)) |
if (!( ( smartlogdir && GetNumLogSectors(smartlogdir, 0x06, false)) |
|| (!smartlogdir && isSmartTestLogCapable(&smartval, &drive) ) |
|| (!smartlogdir && isSmartTestLogCapable(&smartval, &drive) ) |
|| is_permissive() )) { |
|| is_permissive() )) { |
pout("SMART Self-test Log not supported\n"); | pout("SMART Self-test Log not supported\n\n"); |
} |
} |
else { |
else { |
ata_smart_selftestlog smartselftest; memset(&smartselftest, 0, sizeof(smartselftest)); |
ata_smart_selftestlog smartselftest; memset(&smartselftest, 0, sizeof(smartselftest)); |
if (ataReadSelfTestLog(device, &smartselftest, fix_firmwarebug)) { | if (ataReadSelfTestLog(device, &smartselftest, firmwarebugs)) { |
pout("Smartctl: SMART Self Test Log Read Failed\n"); | pout("Read SMART Self-test Log failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else { |
else { |
print_on(); |
print_on(); |
if (ataPrintSmartSelfTestlog(&smartselftest, !printing_is_switchable, fix_firmwarebug)) | if (ataPrintSmartSelfTestlog(&smartselftest, !printing_is_switchable, firmwarebugs)) |
returnval |= FAILLOG; |
returnval |= FAILLOG; |
print_off(); |
print_off(); |
pout("\n"); |
pout("\n"); |
Line 2889 int ataPrintMain (ata_device * device, const ata_print
|
Line 3146 int ataPrintMain (ata_device * device, const ata_print
|
ata_selective_self_test_log log; |
ata_selective_self_test_log log; |
|
|
if (!isSupportSelectiveSelfTest(&smartval)) |
if (!isSupportSelectiveSelfTest(&smartval)) |
pout("Device does not support Selective Self Tests/Logging\n"); | pout("Selective Self-tests/Logging not supported\n\n"); |
else if(ataReadSelectiveSelfTestLog(device, &log)) { |
else if(ataReadSelectiveSelfTestLog(device, &log)) { |
pout("Smartctl: SMART Selective Self Test Log Read Failed\n"); | pout("Read SMART Selective Self-test Log failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else { |
else { |
Line 2910 int ataPrintMain (ata_device * device, const ata_print
|
Line 3167 int ataPrintMain (ata_device * device, const ata_print
|
bool sct_ok = false; |
bool sct_ok = false; |
if (need_sct_support) { |
if (need_sct_support) { |
if (!isSCTCapable(&drive)) { |
if (!isSCTCapable(&drive)) { |
pout("Warning: device does not support SCT Commands\n"); | pout("SCT Commands not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else |
else |
Line 2932 int ataPrintMain (ata_device * device, const ata_print
|
Line 3189 int ataPrintMain (ata_device * device, const ata_print
|
} |
} |
else { |
else { |
if (!isSCTDataTableCapable(&drive)) { |
if (!isSCTDataTableCapable(&drive)) { |
pout("Warning: device does not support SCT Data Table command\n"); | pout("SCT Data Table command not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
break; |
break; |
} |
} |
// Read SCT status and temperature history |
// Read SCT status and temperature history |
if (ataReadSCTTempHist(device, &tmh, &sts)) { |
if (ataReadSCTTempHist(device, &tmh, &sts)) { |
|
pout("Read SCT Temperature History failed\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
break; |
break; |
} |
} |
Line 2951 int ataPrintMain (ata_device * device, const ata_print
|
Line 3209 int ataPrintMain (ata_device * device, const ata_print
|
if (options.sct_temp_int) { |
if (options.sct_temp_int) { |
// Set new temperature logging interval |
// Set new temperature logging interval |
if (!isSCTFeatureControlCapable(&drive)) { |
if (!isSCTFeatureControlCapable(&drive)) { |
pout("Warning: device does not support SCT Feature Control command\n"); | pout("SCT Feature Control command not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
break; |
break; |
} |
} |
if (ataSetSCTTempInterval(device, options.sct_temp_int, options.sct_temp_int_pers)) { |
if (ataSetSCTTempInterval(device, options.sct_temp_int, options.sct_temp_int_pers)) { |
|
pout("Write Temperature Logging Interval failed\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
break; |
break; |
} |
} |
Line 2970 int ataPrintMain (ata_device * device, const ata_print
|
Line 3229 int ataPrintMain (ata_device * device, const ata_print
|
// SCT Error Recovery Control |
// SCT Error Recovery Control |
if (sct_ok && (options.sct_erc_get || options.sct_erc_set)) { |
if (sct_ok && (options.sct_erc_get || options.sct_erc_set)) { |
if (!isSCTErrorRecoveryControlCapable(&drive)) { |
if (!isSCTErrorRecoveryControlCapable(&drive)) { |
pout("Warning: device does not support SCT Error Recovery Control command\n"); | pout("SCT Error Recovery Control command not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
else { |
else { |
Line 2979 int ataPrintMain (ata_device * device, const ata_print
|
Line 3238 int ataPrintMain (ata_device * device, const ata_print
|
// Set SCT Error Recovery Control |
// Set SCT Error Recovery Control |
if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime ) |
if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime ) |
|| ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime)) { |
|| ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime)) { |
pout("Warning: device does not support SCT (Set) Error Recovery Control command\n"); | pout("SCT (Set) Error Recovery Control command failed\n"); |
if (!( (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70) |
if (!( (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70) |
|| (options.sct_erc_readtime == 0 && options.sct_erc_writetime == 0))) |
|| (options.sct_erc_readtime == 0 && options.sct_erc_writetime == 0))) |
pout("Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n"); |
pout("Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n"); |
Line 2996 int ataPrintMain (ata_device * device, const ata_print
|
Line 3255 int ataPrintMain (ata_device * device, const ata_print
|
unsigned short read_timer, write_timer; |
unsigned short read_timer, write_timer; |
if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer ) |
if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer ) |
|| ataGetSCTErrorRecoveryControltime(device, 2, write_timer)) { |
|| ataGetSCTErrorRecoveryControltime(device, 2, write_timer)) { |
pout("Warning: device does not support SCT (Get) Error Recovery Control command\n"); | pout("SCT (Get) Error Recovery Control command failed\n"); |
if (options.sct_erc_set) { |
if (options.sct_erc_set) { |
pout("The previous SCT (Set) Error Recovery Control command succeeded\n"); |
pout("The previous SCT (Set) Error Recovery Control command succeeded\n"); |
ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, |
ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, |
Line 3015 int ataPrintMain (ata_device * device, const ata_print
|
Line 3274 int ataPrintMain (ata_device * device, const ata_print
|
if (options.devstat_all_pages || options.devstat_ssd_page || !options.devstat_pages.empty()) { |
if (options.devstat_all_pages || options.devstat_ssd_page || !options.devstat_pages.empty()) { |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x04, true); |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x04, true); |
if (!nsectors) |
if (!nsectors) |
pout("Device Statistics (GP Log 0x04) not supported\n"); | pout("Device Statistics (GP Log 0x04) not supported\n\n"); |
else if (!print_device_statistics(device, nsectors, options.devstat_pages, |
else if (!print_device_statistics(device, nsectors, options.devstat_pages, |
options.devstat_all_pages, options.devstat_ssd_page)) |
options.devstat_all_pages, options.devstat_ssd_page)) |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
Line 3024 int ataPrintMain (ata_device * device, const ata_print
|
Line 3283 int ataPrintMain (ata_device * device, const ata_print
|
// Print SATA Phy Event Counters |
// Print SATA Phy Event Counters |
if (options.sataphy) { |
if (options.sataphy) { |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true); |
unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true); |
|
// Packet interface devices do not provide a log directory, check support bit |
|
if (!nsectors && (drive.words047_079[76-47] & 0x0401) == 0x0400) |
|
nsectors = 1; |
if (!nsectors) |
if (!nsectors) |
pout("SATA Phy Event Counters (GP Log 0x11) not supported\n"); | pout("SATA Phy Event Counters (GP Log 0x11) not supported\n\n"); |
else if (nsectors != 1) |
else if (nsectors != 1) |
pout("SATA Phy Event Counters with %u sectors not supported\n", nsectors); | pout("SATA Phy Event Counters with %u sectors not supported\n\n", nsectors); |
else { |
else { |
unsigned char log_11[512] = {0, }; |
unsigned char log_11[512] = {0, }; |
unsigned char features = (options.sataphy_reset ? 0x01 : 0x00); |
unsigned char features = (options.sataphy_reset ? 0x01 : 0x00); |
if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1)) | if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1)) { |
| pout("Read SATA Phy Event Counters failed\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
|
} |
else |
else |
PrintSataPhyEventCounters(log_11, options.sataphy_reset); |
PrintSataPhyEventCounters(log_11, options.sataphy_reset); |
} |
} |
Line 3058 int ataPrintMain (ata_device * device, const ata_print
|
Line 3322 int ataPrintMain (ata_device * device, const ata_print
|
switch (options.smart_selftest_type) { |
switch (options.smart_selftest_type) { |
case OFFLINE_FULL_SCAN: |
case OFFLINE_FULL_SCAN: |
if (!isSupportExecuteOfflineImmediate(&smartval)){ |
if (!isSupportExecuteOfflineImmediate(&smartval)){ |
pout("Warning: device does not support Execute Offline Immediate function.\n\n"); | pout("Execute Offline Immediate function not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
break; |
break; |
Line 3068 int ataPrintMain (ata_device * device, const ata_print
|
Line 3332 int ataPrintMain (ata_device * device, const ata_print
|
case SHORT_CAPTIVE_SELF_TEST: |
case SHORT_CAPTIVE_SELF_TEST: |
case EXTEND_CAPTIVE_SELF_TEST: |
case EXTEND_CAPTIVE_SELF_TEST: |
if (!isSupportSelfTest(&smartval)){ |
if (!isSupportSelfTest(&smartval)){ |
pout("Warning: device does not support Self-Test functions.\n\n"); | pout("Self-test functions not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
break; |
break; |
case CONVEYANCE_SELF_TEST: |
case CONVEYANCE_SELF_TEST: |
case CONVEYANCE_CAPTIVE_SELF_TEST: |
case CONVEYANCE_CAPTIVE_SELF_TEST: |
if (!isSupportConveyanceSelfTest(&smartval)){ |
if (!isSupportConveyanceSelfTest(&smartval)){ |
pout("Warning: device does not support Conveyance Self-Test functions.\n\n"); | pout("Conveyance Self-test functions not supported\n\n"); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
break; |
break; |
case SELECTIVE_SELF_TEST: |
case SELECTIVE_SELF_TEST: |
case SELECTIVE_CAPTIVE_SELF_TEST: |
case SELECTIVE_CAPTIVE_SELF_TEST: |
if (!isSupportSelectiveSelfTest(&smartval)){ |
if (!isSupportSelectiveSelfTest(&smartval)){ |
pout("Warning: device does not support Selective Self-Test functions.\n\n"); | pout("Selective Self-test functions not supported\n\n"); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
failuretest(MANDATORY_CMD, returnval|=FAILSMART); |
} |
} |
break; |
break; |
Line 3105 int ataPrintMain (ata_device * device, const ata_print
|
Line 3369 int ataPrintMain (ata_device * device, const ata_print
|
if (isSupportOfflineAbort(&smartval)) |
if (isSupportOfflineAbort(&smartval)) |
pout("Note: giving further SMART commands will abort Offline testing\n"); |
pout("Note: giving further SMART commands will abort Offline testing\n"); |
else if (ataReadSmartValues(device, &smartval)){ |
else if (ataReadSmartValues(device, &smartval)){ |
pout("Smartctl: SMART Read Values failed.\n"); | pout("Read SMART Data failed: %s\n\n", device->get_errmsg()); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
failuretest(OPTIONAL_CMD, returnval|=FAILSMART); |
} |
} |
} |
} |