14#define __STDC_FORMAT_MACROS 1
41 return (*output ? output :
"[No Information Found]");
68 unsigned char CR,
unsigned char FR,
69 unsigned char ST,
unsigned char ER,
75 const char *error_flag[8];
76 int i, print_lba=0, print_sector=0;
80 const char *abrt =
"ABRT";
81 const char *amnf =
"AMNF";
82 const char *ccto =
"CCTO";
83 const char *eom =
"EOM";
84 const char *icrc =
"ICRC";
85 const char *idnf =
"IDNF";
86 const char *ili =
"ILI";
87 const char *mc =
"MC";
88 const char *mcr =
"MCR";
89 const char *nm =
"NM";
90 const char *obs =
"obs";
91 const char *tk0nf =
"TK0NF";
92 const char *unc =
"UNC";
93 const char *wp =
"WP";
99 int uses_device_fault = 1;
102 for (i = 0; i < 8; i++)
103 error_flag[i] = NULL;
109 error_flag[2] = abrt;
110 error_flag[1] = tk0nf;
119 error_flag[4] = idnf;
121 error_flag[2] = abrt;
123 error_flag[0] = amnf;
128 error_flag[4] = idnf;
129 error_flag[2] = abrt;
130 error_flag[0] = amnf;
136 error_flag[7] = icrc;
139 error_flag[4] = idnf;
141 error_flag[2] = abrt;
143 error_flag[0] = ccto;
150 error_flag[7] = icrc;
153 error_flag[4] = idnf;
155 error_flag[2] = abrt;
157 error_flag[0] = ccto;
167 error_flag[7] = icrc;
170 error_flag[4] = idnf;
172 error_flag[2] = abrt;
174 error_flag[0] = amnf;
176 if (CR==0x25 || CR==0xC8)
187 error_flag[4] = idnf;
189 error_flag[2] = abrt;
195 error_flag[4] = idnf;
196 error_flag[2] = abrt;
201 error_flag[4] = idnf;
202 error_flag[2] = abrt;
203 error_flag[0] = amnf;
211 error_flag[4] = idnf;
213 error_flag[2] = abrt;
215 error_flag[0] = amnf;
224 error_flag[7] =
"Sense key (bit 3)",
225 error_flag[6] =
"Sense key (bit 2)",
226 error_flag[5] =
"Sense key (bit 1)",
227 error_flag[4] =
"Sense key (bit 0)",
228 error_flag[2] = abrt;
236 error_flag[2] = abrt;
240 error_flag[4] = idnf;
241 error_flag[2] = abrt;
245 error_flag[4] = idnf;
246 error_flag[2] = abrt;
255 error_flag[4] = idnf;
256 error_flag[2] = abrt;
260 error_flag[4] = idnf;
261 error_flag[2] = abrt;
270 error_flag[2] = abrt;
273 error_flag[4] = idnf;
274 error_flag[2] = abrt;
284 error_flag[2] = abrt;
299 error_flag[7] = icrc;
302 error_flag[4] = idnf;
304 error_flag[2] = abrt;
306 error_flag[0] = amnf;
313 error_flag[2] = abrt;
321 if (uses_device_fault && (ST & (1 << 5))) {
322 str =
"Device Fault";
330 for (i = 7; i >= 0; i--)
331 if ((ER & (1 << i)) && (error_flag[i])) {
334 str += error_flag[i];
343 str +=
strprintf(
" %d sectors", print_sector);
358 str +=
strprintf(
" at LBA = 0x%08x = %u", lba, lba);
360 else if (lba48_regs) {
376 str +=
strprintf(
" at LBA = 0x%08" PRIx64
" = %" PRIu64, lba48, lba48);
387 data->commands[4].commandreg,
388 data->commands[4].featuresreg,
389 data->error_struct.status,
390 data->error_struct.error_register,
391 data->error_struct.sector_count,
399 data->commands[4].command_register,
400 data->commands[4].features_register,
401 data->error.status_register,
402 data->error.error_register,
403 data->error.count_register_hi << 8 |
data->error.count_register,
414 switch (word168 & 0xF) {
415 case 0x1:
return "5.25 inches";
416 case 0x2:
return "3.5 inches";
417 case 0x3:
return "2.5 inches";
418 case 0x4:
return "1.8 inches";
419 case 0x5:
return "< 1.8 inches";
420 case 0x6:
return "mSATA";
421 case 0x7:
return "M.2";
422 case 0x8:
return "MicroSSD";
423 case 0x9:
return "CFast";
430 for (
int bit = 15; bit >= 0; bit--)
431 if (word & (1 << bit))
443 case 15:
return "ACS >5 (15)";
444 case 14:
return "ACS >5 (14)";
445 case 13:
return "ACS >5 (13)";
446 case 12:
return "ACS-5";
447 case 11:
return "ACS-4";
448 case 10:
return "ACS-3";
449 case 9:
return "ACS-2";
450 case 8:
return "ATA8-ACS";
451 case 7:
return "ATA/ATAPI-7";
452 case 6:
return "ATA/ATAPI-6";
453 case 5:
return "ATA/ATAPI-5";
454 case 4:
return "ATA/ATAPI-4";
455 case 3:
return "ATA-3";
456 case 2:
return "ATA-2";
457 case 1:
return "ATA-1";
472 case 0x0001:
return "ATA-1 X3T9.2/781D prior to revision 4";
473 case 0x0002:
return "ATA-1 published, ANSI X3.221-1994";
474 case 0x0003:
return "ATA-1 X3T9.2/781D revision 4";
475 case 0x0004:
return "ATA-2 published, ANSI X3.279-1996";
476 case 0x0005:
return "ATA-2 X3T10/948D prior to revision 2k";
477 case 0x0006:
return "ATA-3 X3T10/2008D revision 1";
478 case 0x0007:
return "ATA-2 X3T10/948D revision 2k";
479 case 0x0008:
return "ATA-3 X3T10/2008D revision 0";
480 case 0x0009:
return "ATA-2 X3T10/948D revision 3";
481 case 0x000a:
return "ATA-3 published, ANSI X3.298-1997";
482 case 0x000b:
return "ATA-3 X3T10/2008D revision 6";
483 case 0x000c:
return "ATA-3 X3T13/2008D revision 7 and 7a";
484 case 0x000d:
return "ATA/ATAPI-4 X3T13/1153D revision 6";
485 case 0x000e:
return "ATA/ATAPI-4 T13/1153D revision 13";
486 case 0x000f:
return "ATA/ATAPI-4 X3T13/1153D revision 7";
487 case 0x0010:
return "ATA/ATAPI-4 T13/1153D revision 18";
488 case 0x0011:
return "ATA/ATAPI-4 T13/1153D revision 15";
489 case 0x0012:
return "ATA/ATAPI-4 published, ANSI NCITS 317-1998";
490 case 0x0013:
return "ATA/ATAPI-5 T13/1321D revision 3";
491 case 0x0014:
return "ATA/ATAPI-4 T13/1153D revision 14";
492 case 0x0015:
return "ATA/ATAPI-5 T13/1321D revision 1";
493 case 0x0016:
return "ATA/ATAPI-5 published, ANSI NCITS 340-2000";
494 case 0x0017:
return "ATA/ATAPI-4 T13/1153D revision 17";
495 case 0x0018:
return "ATA/ATAPI-6 T13/1410D revision 0";
496 case 0x0019:
return "ATA/ATAPI-6 T13/1410D revision 3a";
497 case 0x001a:
return "ATA/ATAPI-7 T13/1532D revision 1";
498 case 0x001b:
return "ATA/ATAPI-6 T13/1410D revision 2";
499 case 0x001c:
return "ATA/ATAPI-6 T13/1410D revision 1";
500 case 0x001d:
return "ATA/ATAPI-7 published, ANSI INCITS 397-2005";
501 case 0x001e:
return "ATA/ATAPI-7 T13/1532D revision 0";
502 case 0x001f:
return "ACS-3 T13/2161-D revision 3b";
504 case 0x0021:
return "ATA/ATAPI-7 T13/1532D revision 4a";
505 case 0x0022:
return "ATA/ATAPI-6 published, ANSI INCITS 361-2002";
507 case 0x0027:
return "ATA8-ACS T13/1699-D revision 3c";
508 case 0x0028:
return "ATA8-ACS T13/1699-D revision 6";
509 case 0x0029:
return "ATA8-ACS T13/1699-D revision 4";
511 case 0x0031:
return "ACS-2 T13/2015-D revision 2";
513 case 0x0033:
return "ATA8-ACS T13/1699-D revision 3e";
515 case 0x0039:
return "ATA8-ACS T13/1699-D revision 4c";
517 case 0x0042:
return "ATA8-ACS T13/1699-D revision 3f";
519 case 0x0052:
return "ATA8-ACS T13/1699-D revision 3b";
521 case 0x005e:
return "ACS-4 T13/BSR INCITS 529 revision 5";
523 case 0x006d:
return "ACS-3 T13/2161-D revision 5";
525 case 0x0082:
return "ACS-2 published, ANSI INCITS 482-2012";
527 case 0x009c:
return "ACS-4 published, ANSI INCITS 529-2018";
529 case 0x0107:
return "ATA8-ACS T13/1699-D revision 2d";
531 case 0x010a:
return "ACS-3 published, ANSI INCITS 522-2014";
533 case 0x0110:
return "ACS-2 T13/2015-D revision 3";
535 case 0x011b:
return "ACS-3 T13/2161-D revision 4";
545 switch (word222 & 0x0fff) {
546 default: snprintf(buf,
sizeof(buf),
547 "Unknown (0x%03x)", word222 & 0x0fff);
return buf;
549 case 0x003:
return "ATA8-APT";
550 case 0x002:
return "ATA/ATAPI-7";
561 switch (
find_msb(word222 & 0x0fff)) {
562 case 11:
return "SATA >3.5 (11)";
563 case 10:
return "SATA 3.5";
564 case 9:
return "SATA 3.4";
565 case 8:
return "SATA 3.3";
566 case 7:
return "SATA 3.2";
567 case 6:
return "SATA 3.1";
568 case 5:
return "SATA 3.0";
569 case 4:
return "SATA 2.6";
570 case 3:
return "SATA 2.5";
571 case 2:
return "SATA II Ext";
572 case 1:
return "SATA 1.0a";
573 case 0:
return "ATA8-AST";
587 default:
return ">6.0 Gb/s (7)";
588 case 6:
return ">6.0 Gb/s (6)";
589 case 5:
return ">6.0 Gb/s (5)";
590 case 4:
return ">6.0 Gb/s (4)";
591 case 3:
return "6.0 Gb/s";
592 case 2:
return "3.0 Gb/s";
593 case 1:
return "1.5 Gb/s";
602 jref[
"sata_value"] = value;
604 jref[
"string"] = str;
607 case 3: ups = 60;
break;
608 case 2: ups = 30;
break;
609 case 1: ups = 15;
break;
612 jref[
"units_per_second"] = ups;
613 jref[
"bits_per_unit"] = 100000000;
617 unsigned short word076,
618 unsigned short word077)
620 int allspeeds = (!(word076 & 0x0001) ? (word076 & 0x00fe) : 0);
621 int maxspeed = (allspeeds ?
find_msb(allspeeds) : 0);
622 int curspeed = (!(word077 & 0x0001) ? ((word077 >> 1) & 0x7) : 0);
627 jout(
"SATA Version is: %s%s%s%s%s%s\n",
628 (verstr ? verstr :
"Unknown"),
629 (maxstr ?
", " :
""), (maxstr ? maxstr :
""),
630 (curstr ?
" (current: " :
""), (curstr ? curstr :
""),
631 (curstr ?
")" :
""));
633 jglb[
"sata_version"][
"string"] = verstr;
634 jglb[
"sata_version"][
"value"] = word222 & 0x0fff;
644 char model[40+1], serial[20+1], firmware[8+1];
656 jglb[
"model_name"] = model;
660 jglb[
"serial_number"] = serial;
662 unsigned oui = 0; uint64_t unique_id = 0;
665 jout(
"LU WWN Device Id: %x %06x %09" PRIx64
"\n", naa, oui, unique_id);
666 jglb[
"wwn"][
"naa"] = naa;
667 jglb[
"wwn"][
"oui"] = oui;
668 jglb[
"wwn"][
"id"] = unique_id;
678 jout(
"Add. Product Id: %s\n", add);
679 jglb[
"ata_additional_product_id"] = add;
684 jglb[
"firmware_version"] = firmware;
688 char num[64], cap[32];
689 jout(
"User Capacity: %s bytes [%s]\n",
692 jglb[
"user_capacity"][
"blocks"].set_unsafe_uint64(sizes.
sectors);
693 jglb[
"user_capacity"][
"bytes"].set_unsafe_uint64(sizes.
capacity);
699 jout(
"Sector Sizes: %u bytes logical, %u bytes physical",
712 jout(
"Rotation Rate: Solid State Device\n");
714 jout(
"Rotation Rate: %d rpm\n", rpm);
716 pout(
"Rotation Rate: Unknown (0x%04x)\n", -rpm);
718 jglb[
"rotation_rate"] = (rpm == 1 ? 0 : rpm);
726 jout(
"Form Factor: %s\n", form_factor);
728 jout(
"Form Factor: Unknown (0x%04x)\n", word168);
729 jglb[
"form_factor"][
"ata_value"] = word168;
731 jglb[
"form_factor"][
"name"] = form_factor;
735 bool trim_sup = !!(drive->
words088_255[169-88] & 0x0001);
737 bool trim_det = !!(word069 & 0x4000), trim_zeroed = !!(word069 & 0x0020);
738 if (trim_sup || rpm == 1)
739 jout(
"TRIM Command: %s%s%s\n",
740 (!trim_sup ?
"Unavailable" :
"Available"),
741 (!(trim_sup && trim_det) ?
"" :
", deterministic"),
742 (!(trim_sup && trim_zeroed) ?
"" :
", zeroed") );
743 jglb[
"trim"][
"supported"] = trim_sup;
745 jglb[
"trim"][
"deterministic"] = trim_det;
746 jglb[
"trim"][
"zeroed"] = trim_zeroed;
751 unsigned short zoned_caps = word069 & 0x3;
753 jout(
"Zoned Device: %s\n",
754 (zoned_caps == 0x1 ?
"Host Aware Zones" :
755 zoned_caps == 0x2 ?
"Device managed zones" :
"Unknown (0x3)"));
756 if (zoned_caps < 0x3)
757 jglb[
"zoned_device"][
"capabilities"] = (zoned_caps == 0x1 ?
"host_aware" :
"device_managed");
761 jout(
"Device is: %s%s%s\n",
762 (dbentry ?
"In smartctl database" :
"Not in smartctl database"),
763 (*dbversion ?
" " :
""), (*dbversion ? dbversion :
""));
764 jglb[
"in_smartctl_database"] = !!dbentry;
788 ataver +=
" (minor revision not indicated)";
792 if (!ataver.empty()) {
793 jglb[
"ata_version"][
"string"] = ataver;
800 if (word222 != 0x0000 && word222 != 0xffff)
switch (word222 >> 12) {
813 pout(
"Transport Type: PCIe (0x%03x)\n", word222 & 0x0fff);
816 pout(
"Transport Type: Unknown (0x%04x)\n", word222);
829 unsigned char stat=status_byte & 0x7f;
833 return "was never started";
835 return "was completed without error";
837 if (status_byte == 0x03)
838 return "is in progress";
840 return "is in a Reserved state";
842 return "was suspended by an interrupting command from host";
844 return "was aborted by an interrupting command from host";
846 return "was aborted by the device with a fatal error";
849 return "is in a Vendor Specific state";
851 return "is in a Reserved state";
859 json::ref jref =
jglb[
"ata_smart_data"][
"offline_data_collection"][
"status"];
861 jout(
"Offline data collection status: (0x%02x)\t",
862 (
int)
data->offline_data_collection_status);
863 jref[
"value"] =
data->offline_data_collection_status;
867 jout(
"Offline data collection activity\n"
870 switch (
data->offline_data_collection_status & 0x7f) {
871 case 0x02: jref[
"passed"] =
true;
break;
872 case 0x06: jref[
"passed"] =
false;
break;
877 if (
data->offline_data_collection_status & 0x80)
878 pout(
"\t\t\t\t\tAuto Offline Data Collection: Enabled.\n");
880 pout(
"\t\t\t\t\tAuto Offline Data Collection: Disabled.\n");
888 unsigned char status =
data->self_test_exec_status;
889 jout(
"Self-test execution status: ");
891 switch (
data->self_test_exec_status >> 4) {
893 jout(
"(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status);
894 jout(
"without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
897 jout(
"(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", status);
901 jout(
"(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", status);
902 jout(
"by the host with a hard or soft reset.\n");
905 jout(
"(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", status);
906 jout(
"occurred while the device was executing\n\t\t\t\t\t");
907 jout(
"its self-test routine and the device \n\t\t\t\t\t");
908 jout(
"was unable to complete the self-test \n\t\t\t\t\t");
912 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
913 jout(
"a test element that failed and the test\n\t\t\t\t\t");
914 jout(
"element that failed is not known.\n");
917 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
918 jout(
"the electrical element of the test\n\t\t\t\t\t");
922 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
923 jout(
"the servo (and/or seek) element of the \n\t\t\t\t\t");
924 jout(
"test failed.\n");
927 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
928 jout(
"the read element of the test failed.\n");
931 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
932 jout(
"a test element that failed and the\n\t\t\t\t\t");
933 jout(
"device is suspected of having handling\n\t\t\t\t\t");
938 pout(
"(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status);
939 pout(
"with unknown result or self-test in\n\t\t\t\t\t");
940 pout(
"progress with less than 10%% remaining.\n");
943 jout(
"(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", status);
944 jout(
"%1d0%% of test remaining.\n", status & 0x0f);
948 jout(
"(%4d)\tReserved.\n", status);
952 json::ref jref =
jglb[
"ata_smart_data"][
"self_test"][
"status"];
954 jref[
"value"] = status;
957 switch (status >> 4) {
958 case 0x0: msg =
"completed without error";
break;
959 case 0x1: msg =
"was aborted by the host";
break;
960 case 0x2: msg =
"was interrupted by the host with a reset";
break;
961 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
962 case 0x4: msg =
"completed with error (unknown test element)";
break;
963 case 0x5: msg =
"completed with error (electrical test element)";
break;
964 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
965 case 0x7: msg =
"completed with error (read test element)";
break;
966 case 0x8: msg =
"completed with error (handling damage?)";
break;
970 jref[
"string"] = msg;
971 switch (status >> 4) {
972 case 0x1:
case 0x2:
case 0x3:
break;
973 default: jref[
"passed"] = ((status >> 4) == 0x0);
976 else if ((status >> 4) == 0xf) {
977 jref[
"string"] =
strprintf(
"in progress, %u0%% remaining", status & 0xf);
978 jref[
"remaining_percent"] = (status & 0xf) * 10;
984 jout(
"Total time to complete Offline \n");
985 jout(
"data collection: \t\t(%5d) seconds.\n",
986 (
int)
data->total_time_to_complete_off_line);
988 jglb[
"ata_smart_data"][
"offline_data_collection"][
"completion_seconds"] =
989 data->total_time_to_complete_off_line;
996 jout(
"Offline data collection\n");
997 jout(
"capabilities: \t\t\t (0x%02x) ",
998 (
int)
data->offline_data_collection_capability);
999 jref[
"values"][0] =
data->offline_data_collection_capability;
1001 if (
data->offline_data_collection_capability == 0x00){
1002 jout(
"\tOffline data collection not supported.\n");
1006 "SMART execute Offline immediate." :
1007 "No SMART execute Offline immediate.");
1012 "Auto Offline data collection on/off support.":
1013 "No Auto Offline data collection support.");
1016 "Abort Offline collection upon new\n\t\t\t\t\tcommand.":
1017 "Suspend Offline collection upon new\n\t\t\t\t\tcommand.");
1021 "Offline surface scan supported.":
1022 "No Offline surface scan supported.");
1026 "Self-test supported.":
1027 "No Self-test supported.");
1031 "Conveyance Self-test supported.":
1032 "No Conveyance Self-test supported.");
1036 "Selective Self-test supported.":
1037 "No Selective Self-test supported.");
1046 jout(
"SMART capabilities: ");
1047 jout(
"(0x%04x)\t", (
int)
data->smart_capability);
1048 jref[
"values"][1] =
data->smart_capability;
1050 if (
data->smart_capability == 0x00)
1051 jout(
"Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
1053 jout(
"%s\n", (
data->smart_capability & 0x01)?
1054 "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
1055 "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
1056 jref[
"attribute_autosave_enabled"] = !!(
data->smart_capability & 0x01);
1062 if (
data->smart_capability & 0x02)
1063 pout(
"\t\t\t\t\tSupports SMART auto save timer.\n");
1070 jout(
"Error logging capability: (0x%02x)\tError logging %ssupported.\n",
1071 data->errorlog_capability, (capable ?
"" :
"NOT "));
1072 jglb[
"ata_smart_data"][
"capabilities"][
"error_logging_supported"] = capable;
1077 jout(
"Short self-test routine \n");
1079 jout(
"recommended polling time: \t (%4d) minutes.\n",
1080 (
int)
data->short_test_completion_time);
1081 jglb[
"ata_smart_data"][
"self_test"][
"polling_minutes"][
"short"] =
1082 data->short_test_completion_time;
1085 jout(
"recommended polling time: \t Not Supported.\n");
1090 jout(
"Extended self-test routine\n");
1092 jout(
"recommended polling time: \t (%4d) minutes.\n",
1094 jglb[
"ata_smart_data"][
"self_test"][
"polling_minutes"][
"extended"] =
1098 jout(
"recommended polling time: \t Not Supported.\n");
1103 jout(
"Conveyance self-test routine\n");
1105 jout(
"recommended polling time: \t (%4d) minutes.\n",
1106 (
int)
data->conveyance_test_completion_time);
1107 jglb[
"ata_smart_data"][
"self_test"][
"polling_minutes"][
"conveyance"] =
1108 data->conveyance_test_completion_time;
1111 jout(
"recommended polling time: \t Not Supported.\n");
1148 switch (defs[
id].raw_format) {
1151 case RAWFMT_SEC2HOUR: minutes = (rawval / 60) % 60; rawval /= 60*60;
break;
1155 rawval &= 0xffffffffULL;
1158 minutes = (int)(rawval >> 32) / (1000*60);
1161 rawval &= 0xffffffffULL;
1165 if (rawval > 0x00ffffffULL)
1167 jglb[
"power_on_time"][
"hours"] = rawval;
1169 jglb[
"power_on_time"][
"minutes"] = minutes;
1173 if (strcmp(name,
"Power_Cycle_Count"))
1175 switch (defs[
id].raw_format) {
1180 if (rawval > 0x00ffffffULL)
1182 jglb[
"power_cycle_count"] = rawval;
1195 int onlyfailed,
unsigned char format)
1200 bool needheader =
true;
1207 unsigned char threshold = 0;
1222 jout(
"SMART Attributes Data Structure revision number: %d\n",(
int)
data->revnumber);
1223 jglb[
"ata_smart_attributes"][
"revision"] =
data->revnumber;
1224 jout(
"Vendor Specific SMART Attributes with Thresholds:\n");
1227 jout(
"ID#%s ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n",
1228 (!hexid ?
"" :
" "));
1230 jout(
"ID#%s ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE\n",
1231 (!hexid ?
"" :
" "));
1236 std::string valstr, worstr, threstr;
1241 valstr = (!hexval ?
"---" :
"----");
1246 worstr = (!hexval ?
"---" :
"----");
1248 threstr = (!hexval ?
strprintf(
"%.3d", threshold)
1251 threstr = (!hexval ?
"---" :
"----");
1254 std::string idstr = (!hexid ?
strprintf(
"%3d", attr.
id)
1271 jout(
"%s %-24s0x%04x %-4s %-4s %-4s %-10s%-9s%-12s%s\n",
1272 idstr.c_str(), attrname.c_str(), attr.
flags,
1273 valstr.c_str(), worstr.c_str(), threstr.c_str(),
1281 jout(
"%s %-24s%s %-4s %-4s %-4s %-5s%s\n",
1282 idstr.c_str(), attrname.c_str(), flagstr,
1283 valstr.c_str(), worstr.c_str(), threstr.c_str(),
1292 json::ref jref =
jglb[
"ata_smart_attributes"][
"table"][ji++];
1293 jref[
"id"] = attr.
id;
1294 jref[
"name"] = attrname;
1298 jref[
"worst"] = attr.
worst;
1300 jref[
"thresh"] = threshold;
1307 jreff[
"value"] = attr.
flags;
1308 jreff[
"string"] = flagstr;
1319 jref[
"raw"][
"value"] = rawval;
1320 jref[
"raw"][
"string"] = rawstr;
1326 if (!onlyfailed && brief) {
1327 int n = (!hexid ? 28 : 29);
1328 jout(
"%*s||||||_ K auto-keep\n"
1329 "%*s|||||__ C event count\n"
1330 "%*s||||___ R error rate\n"
1331 "%*s|||____ S speed/performance\n"
1332 "%*s||_____ O updated online\n"
1333 "%*s|______ P prefailure warning\n",
1334 n,
"", n,
"", n,
"", n,
"", n,
"", n,
"");
1345 jglb[
"temperature"][
"current"] = t;
1352 if (!(sctcaps & 0x01))
1355 jout(
"SCT capabilities: \t (0x%04x)\tSCT Status supported.\n", sctcaps);
1356 jref[
"value"] = sctcaps;
1358 jout(
"\t\t\t\t\tSCT Error Recovery Control supported.\n");
1359 jref[
"error_recovery_control_supported"] = !!(sctcaps & 0x08);
1361 jout(
"\t\t\t\t\tSCT Feature Control supported.\n");
1362 jref[
"feature_control_supported"] = !!(sctcaps & 0x10);
1364 jout(
"\t\t\t\t\tSCT Data Table supported.\n");
1365 jref[
"data_table_supported"] = !!(sctcaps & 0x20);
1372 jout(
"General SMART Values:\n");
1387 "General Purpose Logging supported.":
1388 "No General Purpose Logging support.");
1389 jglb[
"ata_smart_data"][
"capabilities"][
"gp_logging_supported"] =
1429 case 0x00:
return "Log Directory";
1430 case 0x01:
return "Summary SMART error log";
1431 case 0x02:
return "Comprehensive SMART error log";
1432 case 0x03:
return "Ext. Comprehensive SMART error log";
1433 case 0x04:
return "Device Statistics log";
1434 case 0x05:
return "Reserved for CFA";
1435 case 0x06:
return "SMART self-test log";
1436 case 0x07:
return "Extended self-test log";
1437 case 0x08:
return "Power Conditions log";
1438 case 0x09:
return "Selective self-test log";
1439 case 0x0a:
return "Device Statistics Notification";
1440 case 0x0b:
return "Reserved for CFA";
1441 case 0x0c:
return "Pending Defects log";
1442 case 0x0d:
return "LPS Mis-alignment log";
1443 case 0x0e:
return "Reserved for ZAC-2";
1444 case 0x0f:
return "Sense Data for Successful NCQ Cmds log";
1445 case 0x10:
return "NCQ Command Error log";
1446 case 0x11:
return "SATA Phy Event Counters log";
1448 case 0x12:
return "SATA NCQ Non-Data log";
1449 case 0x13:
return "SATA NCQ Send and Receive log";
1450 case 0x14:
return "Hybrid Information log";
1451 case 0x15:
return "Rebuild Assist log";
1452 case 0x16:
return "Out Of Band Management Control log";
1453 case 0x17:
return "Reserved for Serial ATA";
1454 case 0x18:
return "Command Duration Limits log";
1455 case 0x19:
return "LBA Status log";
1457 case 0x20:
return "Streaming performance log [OBS-8]";
1458 case 0x21:
return "Write stream error log";
1459 case 0x22:
return "Read stream error log";
1460 case 0x23:
return "Delayed sector log [OBS-8]";
1461 case 0x24:
return "Current Device Internal Status Data log";
1462 case 0x25:
return "Saved Device Internal Status Data log";
1464 case 0x2f:
return "Set Sector Configuration";
1465 case 0x30:
return "IDENTIFY DEVICE data log";
1467 case 0x42:
return "Mutate Configurations log";
1469 case 0x47:
return "Concurrent Positioning Ranges log";
1471 case 0x53:
return "Sense Data log";
1473 case 0xe0:
return "SCT Command/Status";
1474 case 0xe1:
return "SCT Data Transfer";
1476 if (0xa0 <= logaddr && logaddr <= 0xdf)
1477 return "Device vendor specific log";
1478 if (0x80 <= logaddr && logaddr <= 0x9f)
1479 return "Host vendor specific log";
1488 if ( ( logaddr <= 0x08)
1489 || (0x0c <= logaddr && logaddr <= 0x0d)
1490 || (0x0f <= logaddr && logaddr <= 0x14)
1491 || (0x19 == logaddr)
1492 || (0x20 <= logaddr && logaddr <= 0x25)
1493 || (0x30 == logaddr)
1494 || (0x42 == logaddr)
1495 || (0x47 == logaddr)
1496 || (0x53 == logaddr))
1499 if ( ( logaddr <= 0x0a)
1500 || (0x15 <= logaddr && logaddr <= 0x16)
1501 || (0x18 == logaddr)
1502 || (0x80 <= logaddr && logaddr <= 0x9f)
1503 || (0xe0 <= logaddr && logaddr <= 0xe1))
1506 if (0xa0 <= logaddr && logaddr <= 0xdf)
1516 memset(logdir, 0,
sizeof(*logdir));
1534 jout(
"General Purpose Log Directory Version %u\n", gplogdir->
logversion);
1535 jref[
"gp_dir_version"] = gplogdir->
logversion;
1538 jout(
"SMART %sLog Directory Version %u%s\n",
1539 (gplogdir ?
" " :
""), smartlogdir->
logversion,
1540 (smartlogdir->
logversion==1 ?
" [multi-sector log support]" :
""));
1541 jref[
"smart_dir_version"] = smartlogdir->
logversion;
1542 jref[
"smart_dir_multi_sector"] = (smartlogdir->
logversion == 1);
1545 jout(
"Address Access R/W Size Description\n");
1547 for (
unsigned i = 0, ji = 0; i <= 0xff; i++) {
1552 if (!(smart_numsect || gp_numsect))
1555 const char * acc;
unsigned size;
1556 if (smart_numsect == gp_numsect) {
1557 acc =
"GPL,SL";
size = gp_numsect;
1559 else if (!smart_numsect) {
1560 acc =
"GPL";
size = gp_numsect;
1562 else if (!gp_numsect) {
1563 acc =
" SL";
size = smart_numsect;
1570 if (acc && ((0x80 <= i && i < 0x9f) || (0xa0 <= i && i < 0xdf))) {
1572 unsigned imax = (i < 0x9f ? 0x9f : 0xdf);
1573 for (
unsigned j = i+1; j <= imax; j++) {
1577 if (!(sn == smart_numsect && gn == gp_numsect))
1587 jout(
"0x%02x-0x%02x %-6s %-3s %5u %s\n", i, i2, acc, rw,
size, name);
1589 jout(
"0x%02x %-6s %-3s %5u %s\n", i, acc, rw,
size, name);
1592 jout(
"0x%02x %-6s %-3s %5u %s\n", i,
"GPL", rw, gp_numsect, name);
1593 jout(
"0x%02x %-6s %-3s %5u %s\n", i,
"SL", rw, smart_numsect, name);
1598 jrefi[
"address"] = i;
1599 jrefi[
"name"] = name;
1600 if (rw[0] ==
'R' && rw[1] && rw[2]) {
1601 jrefi[
"read"] =
true;
1602 jrefi[
"write"] = (rw[2] ==
'W');
1605 jrefi[
"gp_sectors"] = gp_numsect;
1607 jrefi[
"smart_sectors"] = smart_numsect;
1619 unsigned char logaddr,
unsigned page,
1620 unsigned num_pages,
unsigned max_pages)
1622 pout(
"%s Log 0x%02x [%s], Page %u-%u (of %u)\n",
1623 type, logaddr,
GetLogName(logaddr), page, page+num_pages-1, max_pages);
1624 for (
unsigned i = 0; i < num_pages * 512; i += 16) {
1625 const unsigned char * p =
data+i;
1626 pout(
"%07x: %02x %02x %02x %02x %02x %02x %02x %02x "
1627 "%02x %02x %02x %02x %02x %02x %02x %02x ",
1629 p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
1630 p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15]);
1631#define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.')
1632 pout(
"|%c%c%c%c%c%c%c%c"
1633 "%c%c%c%c%c%c%c%c|\n",
1634 P( 0),
P( 1),
P( 2),
P( 3),
P( 4),
P( 5),
P( 6),
P( 7),
1635 P( 8),
P( 9),
P(10),
P(11),
P(12),
P(13),
P(14),
P(15));
1637 if ((i & 0x1ff) == 0x1f0)
1655 { 2,
"List of supported log pages" },
1660 { 2,
"General Statistics" },
1661 { 4,
"Lifetime Power-On Resets" },
1662 { 4,
"Power-on Hours" },
1663 { 6,
"Logical Sectors Written" },
1664 { 6,
"Number of Write Commands" },
1665 { 6,
"Logical Sectors Read" },
1666 { 6,
"Number of Read Commands" },
1667 { 6,
"Date and Time TimeStamp" },
1668 { 4,
"Pending Error Count" },
1669 { 2,
"Workload Utilization" },
1670 { 6,
"Utilization Usage Rate" },
1671 { 7,
"Resource Availability" },
1672 { 1,
"Random Write Resources Used" },
1677 { 2,
"Free-Fall Statistics" },
1678 { 4,
"Number of Free-Fall Events Detected" },
1679 { 4,
"Overlimit Shock Events" },
1684 { 2,
"Rotating Media Statistics" },
1685 { 4,
"Spindle Motor Power-on Hours" },
1686 { 4,
"Head Flying Hours" },
1687 { 4,
"Head Load Events" },
1688 { 4,
"Number of Reallocated Logical Sectors" },
1689 { 4,
"Read Recovery Attempts" },
1690 { 4,
"Number of Mechanical Start Failures" },
1691 { 4,
"Number of Realloc. Candidate Logical Sectors" },
1692 { 4,
"Number of High Priority Unload Events" },
1697 { 2,
"General Errors Statistics" },
1698 { 4,
"Number of Reported Uncorrectable Errors" },
1700 { 4,
"Resets Between Cmd Acceptance and Completion" },
1701 { 4,
"Physical Element Status Changed" },
1706 { 2,
"Temperature Statistics" },
1707 { -1,
"Current Temperature" },
1708 { -1,
"Average Short Term Temperature" },
1709 { -1,
"Average Long Term Temperature" },
1710 { -1,
"Highest Temperature" },
1711 { -1,
"Lowest Temperature" },
1712 { -1,
"Highest Average Short Term Temperature" },
1713 { -1,
"Lowest Average Short Term Temperature" },
1714 { -1,
"Highest Average Long Term Temperature" },
1715 { -1,
"Lowest Average Long Term Temperature" },
1716 { 4,
"Time in Over-Temperature" },
1717 { -1,
"Specified Maximum Operating Temperature" },
1718 { 4,
"Time in Under-Temperature" },
1719 { -1,
"Specified Minimum Operating Temperature" },
1724 { 2,
"Transport Statistics" },
1725 { 4,
"Number of Hardware Resets" },
1726 { 4,
"Number of ASR Events" },
1727 { 4,
"Number of Interface CRC Errors" },
1732 { 2,
"Solid State Device Statistics" },
1733 { 1,
"Percentage Used Endurance Indicator" },
1757 return "Vendor Specific Statistics";
1758 return "Unknown Statistics";
1766 case 0x008:
jglb[
"power_cycle_count"] = val;
break;
1767 case 0x010:
jglb[
"power_on_time"][
"hours"]= val;
break;
1772 case 0x008:
jglb[
"temperature"][
"current"] = val;
break;
1773 case 0x020:
jglb[
"temperature"][
"lifetime_max"] = val;
break;
1774 case 0x028:
jglb[
"temperature"][
"lifetime_min"] = val;
break;
1775 case 0x050:
jglb[
"temperature"][
"lifetime_over_limit_minutes"] = val;
break;
1776 case 0x058:
jglb[
"temperature"][
"op_limit_max"] = val;
break;
1777 case 0x060:
jglb[
"temperature"][
"lifetime_under_limit_minutes"] = val;
break;
1778 case 0x068:
jglb[
"temperature"][
"op_limit_min"] = val;
break;
1790 static const char line[] =
" ===== = = === == ";
1792 pout(
"0x%02x%s%s (empty) ==\n", page, line, name);
1795 if (
data[2] != page) {
1796 pout(
"0x%02x%s%s (invalid page 0x%02x in header) ==\n", page, line, name,
data[2]);
1800 int rev =
data[0] | (
data[1] << 8);
1801 jout(
"0x%02x%s%s (rev %d) ==\n", page, line, name, rev);
1802 jref[
"number"] = page;
1803 jref[
"name"] = name;
1804 jref[
"revision"] = rev;
1808 for (
int i = 1, offset = 8; offset < 512-7; i++, offset+=8) {
1810 if (info && !info[i].
size)
1815 if (!(
flags & 0x80))
1819 if (!info && (
data[offset+5] ||
data[offset+6])) {
1820 pout(
"0x%02x 0x%03x - - [Trailing garbage ignored]\n", page, offset);
1825 const char * valname = (info ? info[i].
name :
1826 (page == 0xff) ?
"Vendor Specific"
1830 int size = (info ? info[i].
size : 7);
1833 bool valid = !!(
flags & 0x40);
1834 bool normalized = !!(
flags & 0x20);
1835 bool supports_dsn = !!(
flags & 0x10);
1836 bool monitored_condition_met = !!(
flags & 0x08);
1837 unsigned char reserved_flags = (
flags & 0x07);
1845 val = (
signed char)
data[offset];
1848 for (
int j = 0; j <
size; j++)
1849 val |= (int64_t)
data[offset+j] << (j*8);
1851 snprintf(valstr,
sizeof(valstr),
"%" PRId64, val);
1855 valstr[0] =
'-'; valstr[1] = 0;
1859 (valid ?
'V' :
'-'),
1860 (normalized ?
'N' :
'-'),
1861 (supports_dsn ?
'D' :
'-'),
1862 (monitored_condition_met ?
'C' :
'-'),
1863 (reserved_flags ?
'+' :
' '),
1867 jout(
"0x%02x 0x%03x %d %15s %s %s\n",
1868 page, offset, abs(
size), valstr, flagstr+1, valname);
1874 jrefi[
"offset"] = offset;
1875 jrefi[
"name"] = valname;
1876 jrefi[
"size"] = abs(
size);
1878 jrefi[
"value"] = val;
1881 jreff[
"value"] =
flags;
1882 jreff[
"string"] = flagstr;
1883 jreff[
"valid"] = valid;
1884 jreff[
"normalized"] = normalized;
1885 jreff[
"supports_dsn"] = supports_dsn;
1886 jreff[
"monitored_condition_met"] = monitored_condition_met;
1888 jreff[
"other"] = reserved_flags;
1896 const std::vector<int> & single_pages,
bool all_pages,
bool ssd_page,
1900 unsigned char page_0[512] = {0, };
1908 jerr(
"Read Device Statistics page 0x00 failed\n\n");
1912 unsigned char nentries = page_0[8];
1913 if (!(page_0[2] == 0 && nentries > 0)) {
1914 jerr(
"Device Statistics page 0x00 is invalid (page=0x%02x, nentries=%d)\n\n", page_0[2], nentries);
1919 std::vector<int> pages;
1923 for (i = 0; i < nentries; i++) {
1924 int page = page_0[8+1+i];
1926 pages.push_back(page);
1931 bool print_page_0 =
false;
1932 for (i = 0; i < single_pages.size() || ssd_page; i++) {
1933 int page = (i < single_pages.size() ? single_pages[i] : 0x07);
1935 print_page_0 =
true;
1936 else if (page >= (
int)nsectors)
1937 pout(
"Device Statistics Log has only 0x%02x pages\n", nsectors);
1939 pages.push_back(page);
1948 pout(
"Device Statistics (%s Log 0x04) supported pages\n",
1949 use_gplog ?
"GP" :
"SMART");
1950 jout(
"Page Description\n");
1951 for (i = 0; i < nentries; i++) {
1952 int page = page_0[8+1+i];
1954 jout(
"0x%02x %s\n", page, name);
1955 jref[
"supported_pages"][i][
"number"] = page;
1956 jref[
"supported_pages"][i][
"name"] = name;
1962 if (!pages.empty()) {
1963 pout(
"Device Statistics (%s Log 0x04)\n",
1964 use_gplog ?
"GP" :
"SMART");
1965 jout(
"Page Offset Size Value Flags Description\n");
1969 for (i = 0; i < pages.size(); i++) {
1970 int page = pages[i];
1971 if (max_page < page && page < 0xff)
1978 jerr(
"Read Device Statistics pages 0x00-0x%02x failed\n\n", max_page);
1983 for (i = 0; i < pages.size(); i++) {
1984 int page = pages[i];
1987 jerr(
"Read Device Statistics page 0x%02x failed\n\n", page);
1991 else if (page > max_page)
1994 int offset = (use_gplog ? 0 : page * 512);
1998 jout(
"%32s|||_ C monitored condition met\n",
"");
1999 jout(
"%32s||__ D supports DSN\n",
"");
2000 jout(
"%32s|___ N normalized value\n\n",
"");
2013 unsigned max_entries)
2016 unsigned char page_buf[512] = {0, };
2018 pout(
"Read Pending Defects log page 0x00 failed\n\n");
2022 jout(
"Pending Defects log (GP Log 0x0c)\n");
2025 jref[
"size"] = nsectors * 32 - 1;
2026 jref[
"count"] = nentries;
2028 jout(
"No Defects Logged\n\n");
2033 jout(
"Index LBA Hours\n");
2034 for (
unsigned i = 0, pi = 1, page = 0; i < nentries && i < max_entries; i++, pi++) {
2037 if (++page >= nsectors) {
2038 pout(
"Pending Defects count %u exceeds log size (#pages=%u)\n\n",
2039 nentries, nsectors);
2043 pout(
"Read Pending Defects log page 0x%02x failed\n\n", page);
2049 const unsigned char *
entry = page_buf + 16 * pi;
2052 if (hours != 0xffffffffU)
2053 snprintf(hourstr,
sizeof(hourstr),
"%u", hours);
2055 hourstr[0] =
'-', hourstr[1] = 0;
2057 jout(
"%5u %18" PRIu64
" %8s\n", i, lba, hourstr);
2061 if (hours != 0xffffffffU)
2062 jrefi[
"power_on_hours"] = hours;
2065 if (nentries > max_entries)
2066 pout(
"... (%u entries not shown)\n", nentries - max_entries);
2079 jout(
"SATA Phy Event Counters (GP Log 0x11)\n");
2081 pout(
"[Reserved: 0x%02x 0x%02x 0x%02x 0x%02x]\n",
2083 jout(
"ID Size Value Description\n");
2085 for (
unsigned i = 4, ji = 0; ; ) {
2087 unsigned id =
data[i] | (
data[i+1] << 8);
2088 unsigned size = ((
id >> 12) & 0x7) << 1;
2097 pout(
"0x%04x %u: Invalid entry\n",
id,
size);
2102 uint64_t val = 0, max_val = 0;
2103 for (
unsigned j = 0; j <
size; j+=2) {
2104 val |= (uint64_t)(
data[i+j] | (
data[i+j+1] << 8)) << (j*8);
2105 max_val |= (uint64_t)0xffffU << (j*8);
2112 case 0x001: name =
"Command failed due to ICRC error";
break;
2113 case 0x002: name =
"R_ERR response for data FIS";
break;
2114 case 0x003: name =
"R_ERR response for device-to-host data FIS";
break;
2115 case 0x004: name =
"R_ERR response for host-to-device data FIS";
break;
2116 case 0x005: name =
"R_ERR response for non-data FIS";
break;
2117 case 0x006: name =
"R_ERR response for device-to-host non-data FIS";
break;
2118 case 0x007: name =
"R_ERR response for host-to-device non-data FIS";
break;
2119 case 0x008: name =
"Device-to-host non-data FIS retries";
break;
2120 case 0x009: name =
"Transition from drive PhyRdy to drive PhyNRdy";
break;
2121 case 0x00A: name =
"Device-to-host register FISes sent due to a COMRESET";
break;
2122 case 0x00B: name =
"CRC errors within host-to-device FIS";
break;
2123 case 0x00D: name =
"Non-CRC errors within host-to-device FIS";
break;
2124 case 0x00F: name =
"R_ERR response for host-to-device data FIS, CRC";
break;
2125 case 0x010: name =
"R_ERR response for host-to-device data FIS, non-CRC";
break;
2126 case 0x012: name =
"R_ERR response for host-to-device non-data FIS, CRC";
break;
2127 case 0x013: name =
"R_ERR response for host-to-device non-data FIS, non-CRC";
break;
2128 default: name = ((
id & 0x8000) ?
"Vendor specific" :
"Unknown");
break;
2132 jout(
"0x%04x %u %12" PRIu64
"%c %s\n",
id,
size, val,
2133 (val == max_val ?
'+' :
' '), name);
2135 json::ref jref =
jglb[
"sata_phy_event_counters"][
"table"][ji++];
2137 jref[
"name"] = name;
2138 jref[
"size"] =
size;
2139 jref[
"value"] = val;
2140 jref[
"overflow"] = (val == max_val);
2143 jout(
"All counters reset\n");
2145 jglb[
"sata_phy_event_counters"][
"reset"] = reset;
2151 unsigned days = msec / 86400000U;
2152 msec -= days * 86400000U;
2153 unsigned hours = msec / 3600000U;
2154 msec -= hours * 3600000U;
2155 unsigned min = msec / 60000U;
2156 msec -= min * 60000U;
2157 unsigned sec = msec / 1000U;
2158 msec -= sec * 1000U;
2163 str +=
strprintf(
"%02u:%02u:%02u.%03u", hours, min, sec, msec);
2172 case 0x0:
return "in an unknown state";
2173 case 0x1:
return "sleeping";
2174 case 0x2:
return "in standby mode";
2175 case 0x3:
return "active or idle";
2176 case 0x4:
return "doing SMART Offline or Self-test";
2178 return (state < 0xb ?
"in a reserved state"
2179 :
"in a vendor specific state");
2188 jout(
"SMART Error Log Version: %d\n", (
int)
data->revnumber);
2189 jref[
"revision"] =
data->revnumber;
2192 if (!
data->error_log_pointer){
2193 jout(
"No Errors Logged\n\n");
2199 if (
data->error_log_pointer>5){
2200 pout(
"Invalid Error Log index = 0x%02x (valid range is from 1 to 5)\n",
2201 data->error_log_pointer);
2202 pout(
"ATA Error Count: %d (possibly also invalid)\n\n",
data->ata_error_count);
2208 pout(
"Warning: ATA error count %d inconsistent with error log pointer %d\n\n",
2209 data->ata_error_count,
data->error_log_pointer);
2213 if (
data->ata_error_count<=5)
2214 jout(
"ATA Error Count: %d\n", (
int)
data->ata_error_count);
2216 jout(
"ATA Error Count: %d (device log contains only the most recent five errors)\n",
2217 (
int)
data->ata_error_count);
2218 jref[
"count"] =
data->ata_error_count;
2219 jref[
"logged_count"] = (
data->ata_error_count <= 5 ?
data->ata_error_count : 5);
2222 jout(
"\tCR = Command Register [HEX]\n"
2223 "\tFR = Features Register [HEX]\n"
2224 "\tSC = Sector Count Register [HEX]\n"
2225 "\tSN = Sector Number Register [HEX]\n"
2226 "\tCL = Cylinder Low Register [HEX]\n"
2227 "\tCH = Cylinder High Register [HEX]\n"
2228 "\tDH = Device/Head Register [HEX]\n"
2229 "\tDC = Device Command Register [HEX]\n"
2230 "\tER = Error register [HEX]\n"
2231 "\tST = Status register [HEX]\n"
2232 "Powered_Up_Time is measured from power on, and printed as\n"
2233 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2234 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2237 for (
int k = 4, ji = 0; k >= 0; k--) {
2240 int i = (
data->error_log_pointer + k) % 5;
2245 if (
nonempty(elog,
sizeof(*elog))){
2252 jout(
"Error %d occurred at disk power-on lifetime: %d hours (%d days + %d hours)\n",
2257 jrefi[
"error_number"] =
data->ata_error_count + k - 4;
2258 jrefi[
"lifetime_hours"] = summary->
timestamp;
2260 jout(
" When the command that caused the error occurred, the device was %s.\n\n", msgstate);
2261 jout(
" After command completion occurred, registers were:\n"
2262 " ER ST SC SN CL CH DH\n"
2263 " -- -- -- -- -- -- --\n"
2264 " %02x %02x %02x %02x %02x %02x %02x",
2274 json::ref jrefir = jrefi[
"completion_registers"];
2276 jrefir[
"status"] = summary->
status;
2287 if (!st_er_desc.empty()) {
2288 jout(
" %s", st_er_desc.c_str());
2289 jrefi[
"error_description"] = st_er_desc;
2292 jout(
" Commands leading to the command that caused the error were:\n"
2293 " CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n"
2294 " -- -- -- -- -- -- -- -- ---------------- --------------------\n");
2295 for (
int j = 4, jj = 0; j >= 0; j--) {
2299 if (
nonempty(thiscommand,
sizeof(*thiscommand))) {
2301 jout(
" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2313 json::ref jrefic = jrefi[
"previous_commands"][jj++];
2314 json::ref jreficr = jrefic[
"registers"];
2315 jreficr[
"command"] = thiscommand->
commandreg;
2323 jrefic[
"powerup_milliseconds"] = thiscommand->
timestamp;
2324 jrefic[
"command_name"] = atacmd;
2334 return data->ata_error_count;
2341 unsigned nsectors,
unsigned max_errors)
2344 jout(
"SMART Extended Comprehensive Error Log Version: %u (%u sectors)\n",
2346 jref[
"revision"] = log->
version;
2347 jref[
"sectors"] = nsectors;
2350 jout(
"No Errors Logged\n\n");
2357 unsigned nentries = nsectors * 4;
2359 if (!(1 <= erridx && erridx <= nentries)){
2364 pout(
"Invalid Error Log index = 0x%04x (reserved = 0x%02x)\n", erridx, log->
reserved1);
2368 pout(
"Invalid Error Log index = 0x%04x, trying reserved byte (0x%02x) instead\n", erridx, log->
reserved1);
2379 if (errcnt <= nentries)
2383 jout(
"Device Error Count: %u (device log contains only the most recent %u errors)\n",
2387 jref[
"logged_count"] = errcnt;
2389 if (max_errors < errcnt)
2390 errcnt = max_errors;
2393 jout(
"\tCR = Command Register\n"
2394 "\tFEATR = Features Register\n"
2395 "\tCOUNT = Count (was: Sector Count) Register\n"
2396 "\tLBA_48 = Upper bytes of LBA High/Mid/Low Registers ] ATA-8\n"
2397 "\tLH = LBA High (was: Cylinder High) Register ] LBA\n"
2398 "\tLM = LBA Mid (was: Cylinder Low) Register ] Register\n"
2399 "\tLL = LBA Low (was: Sector Number) Register ]\n"
2400 "\tDV = Device (was: Device/Head) Register\n"
2401 "\tDC = Device Control Register\n"
2402 "\tER = Error register\n"
2403 "\tST = Status register\n"
2404 "Powered_Up_Time is measured from power on, and printed as\n"
2405 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2406 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2410 unsigned log_buf_page = ~0;
2414 i < errcnt; i++, errnum--, erridx = (erridx > 0 ? erridx - 1 : nentries - 1)) {
2418 unsigned page = erridx / 4;
2422 if (page != log_buf_page) {
2423 memset(&log_buf, 0,
sizeof(log_buf));
2426 log_buf_page = page;
2434 jrefi[
"error_number"] = errnum;
2435 jrefi[
"log_index"] = erridx;
2439 jout(
"Error %u [%u] log entry is empty\n", errnum, erridx);
2446 jout(
"Error %u [%u] occurred at disk power-on lifetime: %u hours (%u days + %u hours)\n",
2449 jrefi[
"lifetime_hours"] = err.
timestamp;
2452 jout(
" When the command that caused the error occurred, the device was %s.\n\n", msgstate);
2453 jrefi[
"device_state"][
"value"] = err.
state;
2454 jrefi[
"device_state"][
"string"] = msgstate;
2457 jout(
" After command completion occurred, registers were:\n"
2458 " ER -- ST COUNT LBA_48 LH LM LL DV DC\n"
2459 " -- -- -- == -- == == == -- -- -- -- --\n"
2460 " %02x -- %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
2475 json::ref jrefir = jrefi[
"completion_registers"];
2492 if (!st_er_desc.empty()) {
2493 jout(
" %s", st_er_desc.c_str());
2494 jrefi[
"error_description"] = st_er_desc;
2499 jout(
" Commands leading to the command that caused the error were:\n"
2500 " CR FEATR COUNT LBA_48 LH LM LL DV DC Powered_Up_Time Command/Feature_Name\n"
2501 " -- == -- == -- == == == -- -- -- -- -- --------------- --------------------\n");
2502 for (
int ci = 4, cji = 0; ci >= 0; ci--) {
2511 jout(
" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2512 cmd.command_register,
2513 cmd.features_register_hi,
2514 cmd.features_register,
2515 cmd.count_register_hi,
2517 cmd.lba_high_register_hi,
2518 cmd.lba_mid_register_hi,
2519 cmd.lba_low_register_hi,
2520 cmd.lba_high_register,
2521 cmd.lba_mid_register,
2522 cmd.lba_low_register,
2523 cmd.device_register,
2524 cmd.device_control_register,
2528 json::ref jrefic = jrefi[
"previous_commands"][cji++];
2529 json::ref jreficr = jrefic[
"registers"];
2530 jreficr[
"command"] =
cmd.command_register;
2531 jreficr[
"features"] = (
cmd.features_register_hi << 8) |
cmd.features_register;
2532 jreficr[
"count"] = (
cmd.count_register_hi << 8) |
cmd.count_register;
2533 jreficr[
"lba"] = ((uint64_t)
cmd.lba_high_register_hi << 40)
2534 | ((uint64_t)
cmd.lba_mid_register_hi << 32)
2535 | ((uint64_t)
cmd.lba_low_register_hi << 24)
2536 | ((unsigned)
cmd.lba_high_register << 16)
2537 | ((unsigned)
cmd.lba_mid_register << 8)
2538 | ((unsigned)
cmd.lba_low_register );
2539 jreficr[
"device"] =
cmd.device_register;
2540 jreficr[
"device_control"] =
cmd.device_control_register;
2541 jrefic[
"powerup_milliseconds"] =
cmd.timestamp;
2542 jrefic[
"command_name"] = atacmd;
2560 unsigned testnum,
unsigned char test_type,
2561 unsigned char test_status,
2562 unsigned short timestamp,
2563 uint64_t failing_lba,
2564 bool print_error_only,
bool & print_header)
2568 switch (test_status >> 4) {
2570 if ((test_type & 0x7f) == 0x02)
2580 if (retval >= 0 && print_error_only)
2583 std::string msgtest;
2584 switch (test_type) {
2585 case 0x00: msgtest =
"Offline";
break;
2586 case 0x01: msgtest =
"Short offline";
break;
2587 case 0x02: msgtest =
"Extended offline";
break;
2588 case 0x03: msgtest =
"Conveyance offline";
break;
2589 case 0x04: msgtest =
"Selective offline";
break;
2590 case 0x7f: msgtest =
"Abort offline test";
break;
2591 case 0x81: msgtest =
"Short captive";
break;
2592 case 0x82: msgtest =
"Extended captive";
break;
2593 case 0x83: msgtest =
"Conveyance captive";
break;
2594 case 0x84: msgtest =
"Selective captive";
break;
2596 if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
2597 msgtest =
strprintf(
"Vendor (0x%02x)", test_type);
2599 msgtest =
strprintf(
"Reserved (0x%02x)", test_type);
2602 std::string msgstat;
2603 switch (test_status >> 4) {
2604 case 0x0: msgstat =
"Completed without error";
break;
2605 case 0x1: msgstat =
"Aborted by host";
break;
2606 case 0x2: msgstat =
"Interrupted (host reset)";
break;
2607 case 0x3: msgstat =
"Fatal or unknown error";
break;
2608 case 0x4: msgstat =
"Completed: unknown failure";
break;
2609 case 0x5: msgstat =
"Completed: electrical failure";
break;
2610 case 0x6: msgstat =
"Completed: servo/seek failure";
break;
2611 case 0x7: msgstat =
"Completed: read failure";
break;
2612 case 0x8: msgstat =
"Completed: handling damage??";
break;
2613 case 0xf: msgstat =
"Self-test routine in progress";
break;
2614 default: msgstat =
strprintf(
"Unknown status (0x%x)", test_status >> 4);
2619 print_header =
false;
2620 jout(
"Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n");
2624 if (retval < 0 && failing_lba < 0xffffffffffffULL)
2625 snprintf(msglba,
sizeof(msglba),
"%" PRIu64, failing_lba);
2627 msglba[0] =
'-'; msglba[1] = 0;
2630 jout(
"#%2u %-19s %-29s %1d0%% %8u %s\n", testnum,
2631 msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
2633 jref[
"type"][
"value"] = test_type;
2634 jref[
"type"][
"string"] = msgtest;
2636 jref[
"status"][
"value"] = test_status;
2637 jref[
"status"][
"string"] = msgstat;
2638 if (test_status & 0x0f)
2639 jref[
"status"][
"remaining_percent"] = (test_status & 0x0f) * 10;
2640 switch (test_status >> 4) {
2641 case 0x1:
case 0x2:
case 0x3:
break;
2642 default: jref[
"status"][
"passed"] = (retval >= 0);
2645 jref[
"lifetime_hours"] = timestamp;
2647 if (retval < 0 && failing_lba < 0xffffffffffffULL)
2648 jref[
"lba"] = failing_lba;
2657 json::ref jref =
jglb[
"ata_smart_self_test_log"][
"standard"];
2660 jout(
"SMART Self-test log structure revision number %d\n", log->
revnumber);
2663 pout(
"Warning: ATA Specification requires self-test log structure revision number = 1\n");
2666 jout(
"No self-tests have been logged. [To run self-tests, use: smartctl -t]\n");
2671 bool noheaderprinted =
true;
2672 int errcnt = 0, igncnt = 0;
2673 int testnum = 1, ext_ok_testnum = -1;
2676 for (
int i = 20, ji = 0; i >= 0; i--) {
2685 uint64_t lba48 = (
entry.lbafirstfailure < 0xffffffff ?
2686 entry.lbafirstfailure : 0xffffffffffffULL);
2690 testnum,
entry.selftestnumber,
entry.selfteststatus,
2691 entry.timestamp, lba48, !allentries, noheaderprinted);
2695 if (ext_ok_testnum < 0)
2701 else if (state > 0 && ext_ok_testnum < 0) {
2703 ext_ok_testnum = testnum;
2709 jout(
"%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2710 igncnt, igncnt+errcnt, ext_ok_testnum);
2711 jref[
"count"] = testnum - 1;
2712 jref[
"error_count_total"] = igncnt + errcnt;
2713 jref[
"error_count_outdated"] = igncnt;
2715 if (!allentries && !noheaderprinted)
2723 unsigned nsectors,
unsigned max_entries)
2725 json::ref jref =
jglb[
"ata_smart_self_test_log"][
"extended"];
2727 jout(
"SMART Extended Self-test Log Version: %u (%u sectors)\n",
2729 jref[
"revision"] = log->
version;
2730 jref[
"sectors"] = nsectors;
2733 jout(
"No self-tests have been logged. [To run self-tests, use: smartctl -t]\n\n");
2739 unsigned nentries = nsectors * 19;
2741 if (logidx > nentries) {
2742 pout(
"Invalid Self-test Log index = 0x%04x (reserved = 0x%02x)\n", logidx, log->
reserved1);
2750 bool print_header =
true;
2751 int errcnt = 0, igncnt = 0;
2752 int ext_ok_testnum = -1;
2753 unsigned testnum = 1;
2756 for (
unsigned i = 0, ji = 0; i < nentries && testnum <= max_entries;
2757 i++, logidx = (logidx > 0 ? logidx - 1 : nentries - 1)) {
2766 const unsigned char *
b =
entry.failing_lba;
2767 uint64_t lba48 =
b[0]
2770 | ((uint64_t)
b[3] << 24)
2771 | ((uint64_t)
b[4] << 32)
2772 | ((uint64_t)
b[5] << 40);
2776 testnum,
entry.self_test_type,
2777 entry.self_test_status,
entry.timestamp, lba48,
2778 false , print_header);
2782 if (ext_ok_testnum < 0)
2788 else if (state > 0 && ext_ok_testnum < 0) {
2790 ext_ok_testnum = testnum;
2796 jout(
"%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2797 igncnt, igncnt+errcnt, ext_ok_testnum);
2798 jref[
"count"] = testnum - 1;
2799 jref[
"error_count_total"] = igncnt + errcnt;
2800 jref[
"error_count_outdated"] = igncnt;
2811 jout(
"SMART Selective self-test log data structure revision number %d\n", log->
logversion);
2814 pout(
"Note: revision number not 1 implies that no selective self-test has ever been run\n");
2818 case 0:msg=
"Completed";
2820 case 1:msg=
"Aborted_by_host";
2822 case 2:msg=
"Interrupted";
2824 case 3:msg=
"Fatal_error";
2826 case 4:msg=
"Completed_unknown_failure";
2828 case 5:msg=
"Completed_electrical_failure";
2830 case 6:msg=
"Completed_servo/seek_failure";
2832 case 7:msg=
"Completed_read_failure";
2834 case 8:msg=
"Completed_handling_damage??";
2836 case 15:msg=
"Self_test_in_progress";
2838 default:msg=
"Unknown_status ";
2844 uint64_t maxl = 0, maxr = 0;
2846 uint64_t currentend = current + 0xffff;
2851 for (
int i = 0; i < 5; i++) {
2853 uint64_t end =log->
span[i].
end;
2865 if ((field1=snprintf(tmp,64,
"%" PRIu64, maxl))<7)
2867 if ((field2=snprintf(tmp,64,
"%" PRIu64, maxr))<7)
2871 jout(
" SPAN %*s %*s CURRENT_TEST_STATUS\n", field1,
"MIN_LBA", field2,
"MAX_LBA");
2873 for (
int i = 0; i < 5; i++) {
2875 uint64_t end=log->
span[i].
end;
2880 jout(
" %d %*" PRIu64
" %*" PRIu64
" %s [%01d0%% left] (%" PRIu64
"-%" PRIu64
")\n",
2881 i + 1, field1, start, field2, end, msg,
2885 jout(
" %d %*" PRIu64
" %*" PRIu64
" Not_testing\n",
2886 i + 1, field1, start, field2, end);
2889 jrefi[
"lba_min"] = start;
2890 jrefi[
"lba_max"] = end;
2892 jrefi[
"status"][
"string"] = (active ? msg :
"Not_testing");
2895 jrefi[
"current_lba_min"] = current;
2896 jrefi[
"current_lba_max"] = currentend;
2904 jout(
"%5d %*" PRIu64
" %*" PRIu64
" Read_scanning %s\n",
2905 log->
currentspan, field1, current, field2, currentend, ost);
2906 json::ref jrefc = jref[
"current_read_scan"];
2907 jrefc[
"lba_min"] = current;
2908 jrefc[
"lba_max"] = currentend;
2910 jrefc[
"status"][
"string"] = ost;
2924 jout(
"Selective self-test flags (0x%x):\n", (
unsigned)log->
flags);
2926 jreff[
"value"] = log->
flags;
2930 jout(
" Currently read-scanning the remainder of the disk.\n");
2932 jout(
" Read-scan of remainder of disk interrupted; will resume %d min after power-up.\n",
2935 jout(
" After scanning selected spans, read-scan remainder of disk.\n");
2940 jout(
" After scanning selected spans, do NOT read-scan remainder of disk.\n");
2943 jout(
"If Selective self-test is pending on power-up, resume after %d minute delay.\n",
2945 jref[
"power_up_scan_resume_minutes"] = log->
pendingtime;
2949static const char *
sct_ptemp(
signed char x,
char (& buf)[20])
2953 snprintf(buf,
sizeof(buf),
"%2d", x);
2961 jglb[
"temperature"][name] = x;
2962 jref[
"temperature"][name] = x;
2976 memset(buf,
'*', x);
2982 buf[0] =
'-'; buf[1] = 0;
2990 case 0:
return "Active";
2991 case 1:
return "Stand-by";
2992 case 2:
return "Sleep";
2993 case 3:
return "DST executing in background";
2994 case 4:
return "SMART Off-line Data Collection executing in background";
2995 case 5:
return "SCT command executing in background";
2996 default:
return "Unknown";
3016 jref[
"device_state"][
"string"] = statestr;
3030 char buf1[20], buf2[20];
3031 jout(
"Current Temperature: %s Celsius\n",
3034 jout(
"Power Cycle Min/Max Temperature: %s/%s Celsius\n",
3040 jout(
"Lifetime Min/Max Temperature: %s/%s Celsius\n",
3050 jout(
"Specified Max Operating Temperature: %3d Celsius\n", sts->
max_op_limit);
3053 jout(
"Under/Over Temperature Limit Count: %2u/%u\n",
3062 (passed == 0 ?
"FAILED" : passed > 0 ?
"PASSED" :
"Reserved"));
3064 jref[
"smart_status"][
"passed"] = !!passed;
3065 jglb[
"smart_status"][
"passed"] = !!passed;
3068 jref[
"smart_status"][
"reserved_value"] = sts->
smart_status;
3072 pout(
"Minimum supported ERC Time Limit: %d (%0.1f seconds)\n",
3076 jout(
"Vendor specific:\n");
3090 char buf1[20], buf2[20], buf3[64];
3094 jout(
"Temperature Sampling Period: %u minute%s\n",
3097 jout(
"Temperature Logging Interval: %u minute%s\n",
3099 jref[
"logging_interval_minutes"] = tmh->
interval;
3101 jout(
"Min/Max recommended Temperature: %s/%s Celsius\n",
3105 jout(
"Min/Max Temperature Limit: %s/%s Celsius\n",
3115 pout(
"Temperature History is empty\n");
3117 pout(
"Invalid Temperature History Size or Index\n");
3122 jout(
"\nIndex Estimated Time Temperature Celsius\n");
3125 time_t t = time(0) - (time_t)(tmh->
cb_size-1) * interval * 60;
3126 t -= t % (interval * 60);
3127 while (n < tmh->cb_size) {
3129 unsigned n1 = n, n2 = n+1, i2 = (i+1) % tmh->
cb_size;
3130 while (n2 < tmh->cb_size && tmh->
cb[i2] == tmh->
cb[i]) {
3131 n2++; i2 = (i2+1) % tmh->
cb_size;
3135 if (n == n1 || n == n2-1 || n2 <= n1+3) {
3139 strftime(date,
sizeof(date),
"%Y-%m-%d %H:%M",
time_to_tm_local(&tmbuf, t));
3140 jout(
" %3u %s %s %s\n", i, date,
3143 else if (n == n1+1) {
3144 jout(
" ... ..(%3u skipped). .. %s\n",
3147 if (tmh->
cb[i] != -128)
3148 jref[
"table"][n] = tmh->
cb[i];
3149 t += interval * 60; i = (i+1) % tmh->
cb_size; n++;
3160 const char* power_on_str = (power_on ?
"Power-on " :
"");
3162 jout(
"SCT Error Recovery Control%s:%s\n", (set ?
" set to" :
""), (mfg_default ?
" default values." :
""));
3165 jref[
"read"][
"enabled"] = !!read_timer;
3167 jout(
" %sRead: Disabled\n", power_on_str);
3169 jout(
" %sRead: %6d (%0.1f seconds)\n", power_on_str, read_timer, read_timer/10.0);
3170 jref[
"read"][
"deciseconds"] = read_timer;
3173 jref[
"write"][
"enabled"] = !!write_timer;
3175 jout(
" %sWrite: Disabled\n", power_on_str);
3177 jout(
" %sWrite: %6d (%0.1f seconds)\n", power_on_str, write_timer, write_timer/10.0);
3178 jref[
"write"][
"deciseconds"] = write_timer;
3189 s =
"vendor specific";
3190 else if (level < 128)
3191 s =
"unknown/retired";
3192 else if (level == 128)
3194 else if (level < 254)
3196 else if (level == 254)
3197 s =
"maximum performance";
3201 if (recommended >= 0)
3202 jout(
"%s%d (%s), recommended: %d\n", msg, level,
s, recommended);
3204 jout(
"%s%d (%s)\n", msg, level,
s);
3207 jref[
"enabled"] =
true;
3208 jref[
"level"] = level;
3210 if (recommended >= 0)
3211 jref[
"recommended_level"] = recommended;
3218 if (!(1 <= level && level <= 254))
3220 else if (level == 1)
3221 s =
"minimum power consumption with standby";
3222 else if (level < 128)
3223 s =
"intermediate level with standby";
3224 else if (level == 128)
3225 s =
"minimum power consumption without standby";
3226 else if (level < 254)
3227 s =
"intermediate level without standby";
3229 s =
"maximum performance";
3231 jout(
"%s%d (%s)\n", msg, level,
s);
3234 jref[
"enabled"] =
true;
3235 jref[
"level"] = level;
3237 if (1 <= level && level <= 254) {
3238 jref[
"max_performance"] = (level == 254);
3239 jref[
"min_power"] = (level == 1 || level == 128);
3240 jref[
"with_standby"] = (level < 128);
3247 if (!(state & 0x0001)) {
3248 pout(
"%sUnavailable\n", msg);
3252 const char * s1, * s2 =
"", * s3 =
"", * s4 =
"";
3253 bool enabled =
false, locked =
false;
3254 if (!(state & 0x0002)) {
3256 if (!(state & 0x0008))
3257 s2 =
"NOT FROZEN [SEC1]";
3259 s2 =
"frozen [SEC2]";
3263 s1 =
"ENABLED, PW level ";
3264 if (!(state & 0x0100))
3269 if (!(state & 0x0004)) {
3270 s3 =
", not locked, ";
3271 if (!(state & 0x0008))
3272 s4 =
"not frozen [SEC5]";
3274 s4 =
"frozen [SEC6]";
3278 s3 =
", **LOCKED** [SEC4]";
3280 s4 =
", PW ATTEMPTS EXCEEDED";
3287 if (0x0000 < master_password_id && master_password_id < 0xfffe)
3288 snprintf(s5,
sizeof(s5),
", Master PW ID: 0x%04x", master_password_id);
3290 jout(
"%s%s%s%s%s%s\n", msg, s1, s2, s3, s4, s5);
3293 jref[
"state"] = state;
3294 jref[
"string"] =
strprintf(
"%s%s%s%s", s1, s2, s3, s4);
3295 jref[
"enabled"] = enabled;
3296 if (!enabled || !locked)
3297 jref[
"frozen"] = !!(state & 0x0008);
3299 jref[
"pw_level_max"] = !!(state & 0x0100);
3300 jref[
"locked"] = locked;
3302 jref[
"pw_attempts_exceeded"] = !!(state & 0x0010);
3304 jref[
"master_password_id"] = master_password_id;
3309 const char * s1 = 0;
3310 int hours = 0, minutes = 0 , seconds = 0;
3315 else if (timer <= 240)
3316 seconds = timer * 5, minutes = seconds / 60, seconds %= 60;
3317 else if (timer <= 251)
3318 minutes = (timer - 240) * 30, hours = minutes / 60, minutes %= 60;
3319 else if (timer == 252)
3321 else if (timer == 253)
3322 s1 =
"between 8 hours and 12 hours";
3323 else if (timer == 255)
3324 minutes = 21, seconds = 15;
3328 const char * s2 =
"", * s3 =
"";
3330 s2 =
" or vendor-specific";
3331 if (timer > 0 && (drive.
words047_079[50-47] & 0xc001) == 0x4001)
3332 s3 =
", a vendor-specific minimum applies";
3335 pout(
"%s%d (%s%s%s)\n", msg, timer, s1, s2, s3);
3337 pout(
"%s%d (%02d:%02d:%02d%s%s)\n", msg, timer, hours, minutes, seconds, s2, s3);
3344 const char * powername = 0;
3345 bool powerchg =
false;
3347 unsigned char powerlimit = 0xff;
3350 switch (powermode) {
3357 jinf(
"CHECK POWER MODE not implemented, ignoring -n option\n");
break;
3359 powername =
"SLEEP"; powerlimit = 2;
3364 powername =
"STANDBY"; powerlimit = 3;
break;
3366 powername =
"STANDBY_Y"; powerlimit = 3;
break;
3368 powername =
"IDLE"; powerlimit = 4;
break;
3370 powername =
"IDLE_A"; powerlimit = 4;
break;
3372 powername =
"IDLE_B"; powerlimit = 4;
break;
3374 powername =
"IDLE_C"; powerlimit = 4;
break;
3377 powername =
"ACTIVE_NV_DOWN";
break;
3379 powername =
"ACTIVE_NV_UP" ;
break;
3381 powername =
"ACTIVE or IDLE";
break;
3385 jinf(
"CHECK POWER MODE returned unknown value 0x%02x, exit(%d)\n", powermode,
3389 jinf(
"CHECK POWER MODE returned unknown value 0x%02x, ignoring -n option\n", powermode);
3394 jinf(
"Device is in %s mode, exit(%d)\n", powername, options.
powerexit);
3397 powerchg = (powermode != 0xff);
3402 bool need_smart_val = (
3417 bool need_smart_enabled = (
3424 bool need_smart_support = (
3431 bool need_smart_logdir = (
3438 bool need_gp_logdir = (
3452 need_gp_logdir =
true;
3454 need_smart_logdir =
true;
3458 bool need_sct_support = (
3472 || need_smart_support || need_smart_logdir
3473 || need_gp_logdir || need_sct_support
3479 pout(
"Device is in %s mode\n", powername);
3481 pout(
"ATA device successfully opened\n\n"
3482 "Use 'smartctl -a' (or '-x') to print SMART (and more) information\n\n");
3489 unsigned char raw_drive[
sizeof(drive)]; memset(&raw_drive, 0,
sizeof(raw_drive));
3494 pout(
"Read Device Identity failed: %s\n\n",
3496 pout(
"If this is a USB connected device, look at the various "
3497 "--device=TYPE variants\n");
3500 else if (!
nonempty(&drive,
sizeof(drive))) {
3501 pout(
"Read Device Identity failed: empty IDENTIFY data\n\n");
3514 std::string dbversion;
3518 firmwarebugs, dbversion);
3519 if (!dbversion.empty())
3520 jglb[
"smartctl"][
"drive_database_version"][
"string"] = dbversion;
3530 pout(
"=== ATA IDENTIFY DATA ===\n");
3537 pout(
"=== START OF INFORMATION SECTION ===\n");
3542 int smart_supported = -1, smart_enabled = -1;
3543 if (need_smart_support || options.
drive_info) {
3547 pout(
"SMART support is: Unavailable - Packet Interface Devices [this device: %s] don't support ATA SMART\n",
3555 if (smart_supported < 0)
3556 pout(
"SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 82-83 don't show if SMART supported.\n");
3557 if (smart_supported && smart_enabled < 0) {
3558 pout(
"SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 85-87 don't show if SMART is enabled.\n");
3559 if (need_smart_support) {
3562 pout(
" Checking to be sure by trying SMART RETURN STATUS command.\n");
3564 smart_supported = smart_enabled = 1;
3567 else if (smart_supported < 0 && (smart_enabled > 0 || dbentry))
3569 smart_supported = 1;
3571 if (smart_supported < 0)
3572 pout(
"SMART support is: Unknown - Try option -s with argument 'on' to enable it.");
3573 else if (!smart_supported)
3574 jout(
"SMART support is: Unavailable - device lacks SMART capability.\n");
3577 jout(
"SMART support is: Available - device has SMART capability.\n");
3578 if (smart_enabled >= 0) {
3581 pout(
" %sabled status cached by OS, trying SMART RETURN STATUS cmd.\n",
3582 (smart_enabled?
"En":
"Dis"));
3586 jout(
"SMART support is: %s\n",
3587 (smart_enabled ?
"Enabled" :
"Disabled"));
3592 if (options.
drive_info || smart_supported <= 0) {
3593 jglb[
"smart_support"][
"available"] = (smart_supported > 0);
3594 if (smart_supported > 0)
3595 jglb[
"smart_support"][
"enabled"] = (smart_enabled > 0);
3602 pout(
"AAM feature is: Unavailable\n");
3603 else if (!(drive.
word086 & 0x0200)) {
3604 jout(
"AAM feature is: Disabled\n");
3605 jglb[
"ata_aam"][
"enabled"] =
false;
3615 pout(
"APM feature is: Unavailable\n");
3616 else if (!(drive.
word086 & 0x0008)) {
3617 jout(
"APM feature is: Disabled\n");
3618 jglb[
"ata_apm"][
"enabled"] =
false;
3628 pout(
"Rd look-ahead is: Unavailable\n");
3631 jout(
"Rd look-ahead is: %sabled\n", (enabled ?
"En" :
"Dis"));
3632 jglb[
"read_lookahead"][
"enabled"] = enabled;
3640 pout(
"Write cache is: Unavailable\n");
3643 jout(
"Write cache is: %sabled\n", (enabled ?
"En" :
"Dis"));
3644 jglb[
"write_cache"][
"enabled"] = enabled;
3653 || ((word119 & 0xc200) != 0x4200)
3654 || ((word120 & 0xc000) != 0x4000))
3655 pout(
"DSN feature is: Unavailable\n");
3657 bool enabled = !!(word120 & 0x200);
3658 jout(
"DSN feature is: %sabled\n", (enabled ?
"En" :
"Dis"));
3659 jglb[
"ata_dsn"][
"enabled"] = enabled;
3665 bool locked = ((word128 & 0x0007) == 0x0007);
3674 pout(
"Wt Cache Reorder: Unavailable\n");
3676 pout(
"Wt Cache Reorder: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3679 false ,
false ,
false );
3681 if (-1 <= wcache_reorder && wcache_reorder <= 2)
3682 pout(
"Wt Cache Reorder: %s\n",
3683 (wcache_reorder == -1 ?
"Unknown (SCT Feature Control command failed)" :
3684 wcache_reorder == 0 ?
"Unknown" :
3685 wcache_reorder == 1 ?
"Enabled" :
"Disabled"));
3687 pout(
"Wt Cache Reorder: Unknown (0x%02x)\n", wcache_reorder);
3691 const char * sct_write_cache_state_desc[4] = {
3693 "Controlled by ATA",
3701 pout(
"SCT Write Cache Control: Unavailable\n");
3703 pout(
"SCT Write Cache Control: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3706 if (-1 <= state && state <= 3)
3707 pout(
"SCT Write Cache Control: %s\n",
3708 (state == -1 ?
"Unknown (SCT Feature Control command failed)" :
3709 sct_write_cache_state_desc[state]));
3711 pout(
"SCT Write Cache Control: Unknown (0x%02x)\n", state);
3720 pout(
"Power mode %s %s\n", (powerchg?
"was:":
"is: "), powername);
3725 if (smart_supported <= 0 && need_smart_support)
3735 pout(
"=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
3753 pout(
"AAM disabled\n");
3773 pout(
"APM disabled\n");
3781 pout(
"Read look-ahead %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3785 pout(
"Read look-ahead %sabled\n", (enable ?
"en" :
"dis"));
3792 pout(
"Write cache %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3796 pout(
"Write cache %sabled\n", (enable ?
"en" :
"dis"));
3801 bool enable = (options.
set_dsn > 0);
3803 pout(
"DSN %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3807 pout(
"DSN %sabled\n", (enable ?
"en" :
"dis"));
3814 pout(
"Write cache reordering %sable failed: SCT Feature Control command not supported\n",
3815 (enable ?
"en" :
"dis"));
3817 pout(
"Write cache reordering %sable failed: SCT not supported if ATA Security is LOCKED\n",
3818 (enable ?
"en" :
"dis"));
3821 pout(
"Write cache reordering %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3825 pout(
"Write cache reordering %sabled (%s)\n", (enable ?
"en" :
"dis"),
3832 pout(
"SCT Feature Control of write cache failed: SCT Feature Control command not supported\n");
3834 pout(
"SCT Feature Control of write cache failed: SCT not supported if ATA Security is LOCKED\n");
3837 pout(
"SCT Feature Control of write cache failed: %s\n", device->
get_errmsg());
3841 pout(
"Write cache SCT Feature Control is set to: %s (%s)\n",
3849 pout(
"ATA SECURITY FREEZE LOCK failed: %s\n", device->
get_errmsg());
3853 pout(
"ATA Security set to frozen mode\n");
3873 pout(
"SMART Enabled.\n");
3888 pout(
"SMART Disabled. Use option -s with argument 'on' to enable it.\n");
3890 pout(
"(override with '-T permissive' option)\n");
3897 pout(
"SMART Enable Attribute Autosave failed: %s\n\n", device->
get_errmsg());
3901 pout(
"SMART Attribute Autosave Enabled.\n");
3906 pout(
"SMART Disable Attribute Autosave failed: %s\n\n", device->
get_errmsg());
3910 pout(
"SMART Attribute Autosave Disabled.\n");
3916 bool smart_val_ok =
false, smart_thres_ok =
false;
3918 if (need_smart_val) {
3924 smart_val_ok =
true;
3928 pout(
"Read SMART Thresholds failed: %s\n\n", device->
get_errmsg());
3932 smart_thres_ok =
true;
3938 bool needupdate =
false;
3941 pout(
"SMART Automatic Timers not supported\n\n");
3944 needupdate = smart_val_ok;
3946 pout(
"SMART Enable Automatic Offline failed: %s\n\n", device->
get_errmsg());
3950 pout(
"SMART Automatic Offline Testing Enabled every four hours.\n");
3955 pout(
"SMART Automatic Timers not supported\n\n");
3958 needupdate = smart_val_ok;
3960 pout(
"SMART Disable Automatic Offline failed: %s\n\n", device->
get_errmsg());
3964 pout(
"SMART Automatic Offline Testing Disabled.\n");
3970 smart_val_ok =
false;
3988 pout(
"=== START OF READ SMART DATA SECTION ===\n");
3997 jout(
"SMART overall-health self-assessment test result: PASSED\n");
3998 jglb[
"smart_status"][
"passed"] =
true;
3999 if (smart_thres_ok &&
find_failed_attr(&smartval, &smartthres, attribute_defs, 0)) {
4001 pout(
"See vendor-specific Attribute list for marginal Attributes.\n\n");
4004 pout(
"Please note the following marginal Attributes:\n");
4016 jout(
"SMART overall-health self-assessment test result: FAILED!\n"
4017 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
4018 jglb[
"smart_status"][
"passed"] =
false;
4020 if (smart_thres_ok &&
find_failed_attr(&smartval, &smartthres, attribute_defs, 1)) {
4023 pout(
"See vendor-specific Attribute list for failed Attributes.\n\n");
4026 pout(
"Failed Attributes:\n");
4031 pout(
"No failed Attributes found.\n\n");
4042 pout(
"SMART Status %s: %s\n",
4049 if (!(smart_val_ok && smart_thres_ok)) {
4051 pout(
"SMART overall-health self-assessment test result: UNKNOWN!\n"
4052 "SMART Status, Attributes and Thresholds cannot be read.\n\n");
4056 jout(
"SMART overall-health self-assessment test result: FAILED!\n"
4057 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
4058 jwrn(
"Warning: This result is based on an Attribute check.\n");
4059 jglb[
"smart_status"][
"passed"] =
false;
4064 pout(
"See vendor-specific Attribute list for failed Attributes.\n\n");
4067 pout(
"Failed Attributes:\n");
4072 jout(
"SMART overall-health self-assessment test result: PASSED\n");
4073 jwrn(
"Warning: This result is based on an Attribute check.\n");
4074 jglb[
"smart_status"][
"passed"] =
true;
4077 pout(
"See vendor-specific Attribute list for marginal Attributes.\n\n");
4080 pout(
"Please note the following marginal Attributes:\n");
4110 if ( gp_log_supported
4113 need_smart_logdir =
true;
4119 if (need_smart_logdir) {
4121 smartlogdir =
fake_logdir(&smartlogdir_buf, options);
4123 pout(
"Read SMART Log Directory failed: %s\n\n", device->
get_errmsg());
4127 smartlogdir = &smartlogdir_buf;
4131 if (need_gp_logdir) {
4136 pout(
"General Purpose Log Directory not supported\n\n");
4139 pout(
"Read GP Log Directory failed\n\n");
4143 gplogdir = &gplogdir_buf;
4149 pout(
"Log Directories not read due to '-F nologdir' option\n\n");
4159 unsigned max_nsectors;
4161 type =
"General Purpose";
4169 if (!max_nsectors) {
4171 pout(
"%s Log 0x%02x does not exist (override with '-T permissive' option)\n", type, req.
logaddr);
4174 max_nsectors = req.
page+1;
4176 if (max_nsectors <= req.
page) {
4177 pout(
"%s Log 0x%02x has only %u sectors, output skipped\n", type, req.
logaddr, max_nsectors);
4182 if (ns > max_nsectors - req.
page) {
4184 pout(
"%s Log 0x%02x has only %u sectors, output truncated\n", type, req.
logaddr, max_nsectors);
4185 ns = max_nsectors - req.
page;
4189 unsigned offs = (req.
gpl ? 0 : req.
page);
4209 pout(
"SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n\n");
4215 pout(
"Read SMART Extended Comprehensive Error Log failed\n\n");
4227 do_smart_error_log =
true;
4228 else if (!do_smart_error_log)
4229 pout(
"Try '-l [xerror,]error' to read traditional SMART Error Log\n");
4234 if (do_smart_error_log) {
4236 || ( !(smartlogdir && gp_log_supported)
4239 pout(
"SMART Error Log not supported\n\n");
4244 pout(
"Read SMART Error Log failed: %s\n\n", device->
get_errmsg());
4262 pout(
"SMART Extended Self-test Log (GP Log 0x07) not supported\n\n");
4263 else if (nsectors >= 256)
4264 pout(
"SMART Extended Self-test Log size %u not supported\n\n", nsectors);
4269 pout(
"Read SMART Extended Self-test Log failed\n\n");
4281 do_smart_selftest_log =
true;
4282 else if (!do_smart_selftest_log)
4283 pout(
"Try '-l [xselftest,]selftest' to read traditional SMART Self Test Log\n");
4288 if (do_smart_selftest_log) {
4290 || ( !(smartlogdir && gp_log_supported)
4293 pout(
"SMART Self-test Log not supported\n\n");
4298 pout(
"Read SMART Self-test Log failed: %s\n\n", device->
get_errmsg());
4316 pout(
"Selective Self-tests/Logging not supported\n\n");
4318 pout(
"Read SMART Selective Self-test Log failed: %s\n\n", device->
get_errmsg());
4338 pout(
"SCT Commands not supported\n\n");
4340 pout(
"SCT Commands not supported if ATA Security is LOCKED\n\n");
4365 pout(
"SCT Data Table command not supported\n\n");
4375 pout(
"Read SCT Temperature History failed\n\n");
4386 pout(
"SCT Feature Control command not supported\n\n");
4391 pout(
"Write Temperature Logging Interval failed\n\n");
4395 pout(
"Temperature Logging Interval set to %u minute%s (%s)\n",
4406 pout(
"SCT Error Recovery Control command not supported\n\n");
4416 pout(
"SCT (Set) Error Recovery Control command failed\n");
4419 pout(
"Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n");
4423 else if (!sct_erc_get)
4430 bool get_power_on = (sct_erc_get == 2);
4431 unsigned short read_timer, write_timer;
4434 pout(
"SCT (Get) Error Recovery Control command failed\n");
4436 pout(
"The previous SCT (Set) Error Recovery Control command succeeded\n");
4451 bool use_gplog =
true;
4452 unsigned nsectors = 0;
4455 else if (smartlogdir){
4460 pout(
"Device Statistics (GP/SMART Log 0x04) not supported\n\n");
4470 pout(
"Pending Defects log (GP Log 0x0c) not supported\n\n");
4479 if (!nsectors && (drive.
words047_079[76-47] & 0x0401) == 0x0400)
4482 pout(
"SATA Phy Event Counters (GP Log 0x11) not supported\n\n");
4483 else if (nsectors != 1)
4484 pout(
"SATA Phy Event Counters with %u sectors not supported\n\n", nsectors);
4486 unsigned char log_11[512] = {0, };
4487 unsigned char features = (options.
sataphy_reset ? 0x01 : 0x00);
4489 pout(
"Read SATA Phy Event Counters failed\n\n");
4498 bool farm_supported =
true;
4505 jout(
"\nFARM log (GP Log 0xA6) not supported\n\n");
4507 farm_supported =
false;
4511 jout(
"Seagate FARM log supported [try: -l farm]\n\n");
4516 jout(
"\nRead FARM log (GP Log 0xA6) failed\n\n");
4517 farm_supported =
false;
4525 jout(
"FARM log (GP Log 0xA6) not supported for non-Seagate drives\n\n");
4527 farm_supported =
false;
4529 jglb[
"seagate_farm_log"][
"supported"] = farm_supported;
4541 pout(
"Device placed in STANDBY mode\n");
4546 pout(
"ATA STANDBY IMMEDIATE command failed: %s\n", device->
get_errmsg());
4550 pout(
"Device placed in STANDBY mode\n");
4558 pout(
"=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
4563 pout(
"Execute Offline Immediate function not supported\n\n");
4573 pout(
"Self-test functions not supported\n\n");
4580 pout(
"Conveyance Self-test functions not supported\n\n");
4587 pout(
"Selective Self-test functions not supported\n\n");
4608 pout(
"Note: giving further SMART commands will abort Offline testing\n");
4618 time_t t=time(NULL);
4621 pout(
"Please wait %d seconds for test to complete.\n", (
int)timewait);
4624 pout(
"Please wait %d minutes for test to complete.\n", (
int)timewait);
4628 pout(
"Test will complete after %s\n", comptime);
4634 pout(
"Use smartctl -X to abort test.\n");
const char * look_up_ata_command(unsigned char c_code, unsigned char f_reg)
bool ata_nodata_command(ata_device *device, unsigned char command, int sector_count)
int ataDisableAutoOffline(ata_device *device)
unsigned char ata_return_temperature_value(const ata_smart_values *data, const ata_vendor_attr_defs &defs)
bool isSmartErrorLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
int ataGetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short &time_limit, bool power_on)
bool ataReadSmartLog(ata_device *device, unsigned char logaddr, void *data, unsigned nsectors)
int ata_get_wwn(const ata_identify_device *id, unsigned &oui, uint64_t &unique_id)
int ataSmartTest(ata_device *device, int testtype, bool force, const ata_selective_selftest_args &selargs, const ata_smart_values *sv, uint64_t num_sectors)
int ataEnableAutoOffline(ata_device *device)
int ataSmartStatus2(ata_device *device)
int ataSmartSupport(const ata_identify_device *drive)
int ataDisableAutoSave(ata_device *device)
int ata_get_rotation_rate(const ata_identify_device *id)
bool ataReadLogExt(ata_device *device, unsigned char logaddr, unsigned char features, unsigned page, void *data, unsigned nsectors)
int ataEnableAutoSave(ata_device *device)
int ataReadSelfTestLog(ata_device *device, ata_smart_selftestlog *data, firmwarebug_defs firmwarebugs)
std::string ata_format_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
int ataReadSCTTempHist(ata_device *device, ata_sct_temperature_history_table *tmh, ata_sct_status_response *sts)
int ataReadErrorLog(ata_device *device, ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
void ata_get_size_info(const ata_identify_device *id, ata_size_info &sizes)
int ata_read_identity(ata_device *device, ata_identify_device *buf, bool fix_swapped_id, unsigned char *raw_buf)
int TestTime(const ata_smart_values *data, int testtype)
int ataEnableSmart(ata_device *device)
bool isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
int ataCheckPowerMode(ata_device *device)
int ataGetSetSCTWriteCacheReordering(ata_device *device, bool enable, bool persistent, bool set)
unsigned char checksum(const void *data)
bool ataReadExtSelfTestLog(ata_device *device, ata_smart_extselftestlog *log, unsigned nsectors)
int ataReadSelectiveSelfTestLog(ata_device *device, struct ata_selective_self_test_log *data)
bool isSmartTestLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
int ataReadSmartValues(ata_device *device, struct ata_smart_values *data)
int ataSetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default)
int ataDoesSmartWork(ata_device *device)
uint64_t ata_get_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
bool dont_print_serial_number
int ataReadSCTStatus(ata_device *device, ata_sct_status_response *sts)
bool ataReadExtErrorLog(ata_device *device, ata_smart_exterrlog *log, unsigned page, unsigned nsectors, firmwarebug_defs firmwarebugs)
int ataDisableSmart(ata_device *device)
int ataSetSCTTempInterval(ata_device *device, unsigned interval, bool persistent)
std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs &defs, int rpm)
int ataGetSetSCTWriteCache(ata_device *device, unsigned short state, bool persistent, bool set)
int ataReadSmartThresholds(ata_device *device, struct ata_smart_thresholds_pvt *data)
int ataIsSmartEnabled(const ata_identify_device *drive)
void ata_format_id_string(char *out, const unsigned char *in, int n)
int ataReadLogDirectory(ata_device *device, ata_smart_log_directory *data, bool gpl)
bool ata_set_features(ata_device *device, unsigned char features, int sector_count)
ata_attr_state ata_get_attr_state(const ata_smart_attribute &attr, int attridx, const ata_smart_threshold_entry *thresholds, const ata_vendor_attr_defs &defs, unsigned char *threshval)
#define ATA_ENABLE_READ_LOOK_AHEAD
#define ATTRIBUTE_FLAGS_OTHER(x)
#define SELECTIVE_FLAG_PENDING
#define ATA_DISABLE_WRITE_CACHE
#define ATTRIBUTE_FLAGS_SELFPRESERVING(x)
bool isSupportSelfTest(const ata_smart_values *data)
#define SELECTIVE_SELF_TEST
bool isSCTErrorRecoveryControlCapable(const ata_identify_device *drive)
#define ATA_STANDBY_IMMEDIATE
bool isSupportOfflineSurfaceScan(const ata_smart_values *data)
#define OFFLINE_FULL_SCAN
#define SELECTIVE_FLAG_DOSCAN
bool isSupportConveyanceSelfTest(const ata_smart_values *data)
#define ATA_ENABLE_DISABLE_DSN
void checksumwarning(const char *string)
#define ATTRIBUTE_FLAGS_EVENTCOUNT(x)
#define ATTRIBUTE_FLAGS_PERFORMANCE(x)
bool isSupportAutomaticTimer(const ata_smart_values *data)
#define ATA_ENABLE_WRITE_CACHE
bool isSupportSelectiveSelfTest(const ata_smart_values *data)
bool isSCTDataTableCapable(const ata_identify_device *drive)
#define ATA_DISABLE_READ_LOOK_AHEAD
#define ATTRIBUTE_FLAGS_PREFAILURE(x)
bool isSupportExecuteOfflineImmediate(const ata_smart_values *data)
bool isSupportOfflineAbort(const ata_smart_values *data)
#define SELECTIVE_FLAG_ACTIVE
#define ATTRIBUTE_FLAGS_ERRORRATE(x)
#define EXTEND_CAPTIVE_SELF_TEST
#define CONVEYANCE_CAPTIVE_SELF_TEST
#define CONVEYANCE_SELF_TEST
#define ATA_SECURITY_FREEZE_LOCK
#define SHORT_CAPTIVE_SELF_TEST
#define NUMBER_ATA_SMART_ATTRIBUTES
#define SELECTIVE_CAPTIVE_SELF_TEST
#define ATTRIBUTE_FLAGS_ONLINE(x)
bool isSCTFeatureControlCapable(const ata_identify_device *drive)
bool isSCTCapable(const ata_identify_device *drive)
void ata_print_identify_data(const void *id, bool all_words, int bit_level)
static void print_standby_timer(const char *msg, int timer, const ata_identify_device &drive)
static const char * sct_ptemp(signed char x, char(&buf)[20])
static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer, bool power_on, bool mfg_default=false)
static void PrintSmartCapability(const ata_smart_values *data)
static const char * infofound(const char *output)
const char * ataprint_cpp_cvsid
static void ataPrintSCTCapability(const ata_identify_device *drive)
const devstat_entry_info devstat_info_0x04[]
static void PrintSmartTotalTimeCompleteOffline(const ata_smart_values *data)
static void print_aam_level(const char *msg, int level, int recommended=-1)
const devstat_entry_info devstat_info_0x01[]
static void set_json_globals_from_device_statistics(int page, int offset, int64_t val)
static void print_sata_version_and_speed(unsigned short word222, unsigned short word076, unsigned short word077)
static void print_ata_security_status(const char *msg, unsigned short state, unsigned short master_password_id)
static void PrintSmartOfflineCollectCap(const ata_smart_values *data)
int ataPrintMain(ata_device *device, const ata_print_options &options)
static void PrintSmartOfflineStatus(const ata_smart_values *data)
static void print_drive_info(const ata_identify_device *drive, const ata_size_info &sizes, int rpm, const drive_settings *dbentry, const char *dbversion)
static void PrintSmartSelfExecStatus(const ata_smart_values *data, firmwarebug_defs firmwarebugs)
const int num_devstat_infos
static const char * get_sata_version(unsigned short word222)
const devstat_entry_info devstat_info_0x03[]
static void PrintSmartConveyanceSelfTestPollingTime(const ata_smart_values *data)
static bool is_permissive()
const devstat_entry_info devstat_info_0x02[]
static int ataPrintSmartSelfTestlog(const ata_smart_selftestlog *log, bool allentries, firmwarebug_defs firmwarebugs)
static int PrintSmartErrorlog(const ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
static const char * get_ata_major_version(const ata_identify_device *drive)
static const char * sct_device_state_msg(unsigned char state)
static const char * sct_pbar(int x, char(&buf)[64])
static std::string format_st_er_desc(unsigned char CR, unsigned char FR, unsigned char ST, unsigned char ER, unsigned short SC, const ata_smart_errorlog_error_struct *lba28_regs, const ata_smart_exterrlog_error *lba48_regs)
static void ataPrintSelectiveSelfTestLog(const ata_selective_self_test_log *log, const ata_smart_values *sv)
static const char * get_pata_version(unsigned short word222, char(&buf)[32])
static bool print_pending_defects_log(ata_device *device, unsigned nsectors, unsigned max_entries)
static void PrintSmartAttribWithThres(const ata_smart_values *data, const ata_smart_thresholds_pvt *thresholds, const ata_vendor_attr_defs &defs, int rpm, int onlyfailed, unsigned char format)
static void PrintSmartExtendedSelfTestPollingTime(const ata_smart_values *data)
static void print_device_statistics_page(const json::ref &jref, const unsigned char *data, int page)
static bool print_device_statistics(ata_device *device, unsigned nsectors, const std::vector< int > &single_pages, bool all_pages, bool ssd_page, bool use_gplog)
static void PrintSataPhyEventCounters(const unsigned char *data, bool reset)
static void PrintSmartErrorLogCapability(const ata_smart_values *data, const ata_identify_device *identity)
static void PrintSmartShortSelfTestPollingTime(const ata_smart_values *data)
static const char * OfflineDataCollectionStatus(unsigned char status_byte)
static int find_msb(unsigned short word)
static std::string format_milliseconds(unsigned msec)
static void set_json_globals_from_smart_attrib(int id, const char *name, const ata_vendor_attr_defs &defs, uint64_t rawval)
static void PrintGeneralSmartValues(const ata_smart_values *data, const ata_identify_device *drive, firmwarebug_defs firmwarebugs)
static void PrintLogPages(const char *type, const unsigned char *data, unsigned char logaddr, unsigned page, unsigned num_pages, unsigned max_pages)
static void sct_jtemp2(const json::ref &jref, const char *name, signed char x)
static unsigned GetNumLogSectors(const ata_smart_log_directory *logdir, unsigned logaddr, bool gpl)
const ata_smart_log_directory * fake_logdir(ata_smart_log_directory *logdir, const ata_print_options &options)
static void print_apm_level(const char *msg, int level)
const devstat_entry_info devstat_info_0x07[]
static const char * get_error_log_state_desc(unsigned state)
static int ataPrintSCTTempHist(const ata_sct_temperature_history_table *tmh)
const devstat_entry_info devstat_info_0x00[]
static const char * get_log_rw(unsigned logaddr)
static const char * GetLogName(unsigned logaddr)
const devstat_entry_info devstat_info_0x05[]
static int PrintSmartExtSelfTestLog(const ata_smart_extselftestlog *log, unsigned nsectors, unsigned max_entries)
static void jset_sata_speed(const char *key, int value, int speed, const char *str)
static const char * get_sata_speed(int speed)
static int find_failed_attr(const ata_smart_values *data, const ata_smart_thresholds_pvt *thresholds, const ata_vendor_attr_defs &defs, int onlyfailed)
static int ataPrintSCTStatus(const ata_sct_status_response *sts)
static const char * get_device_statistics_page_name(int page)
const devstat_entry_info devstat_info_0x06[]
static const char * get_ata_minor_version(const ata_identify_device *drive)
static int ataPrintSmartSelfTestEntry(const json::ref &jref, unsigned testnum, unsigned char test_type, unsigned char test_status, unsigned short timestamp, uint64_t failing_lba, bool print_error_only, bool &print_header)
static int PrintSmartExtErrorLog(ata_device *device, const firmwarebug_defs &firmwarebugs, const ata_smart_exterrlog *log, unsigned nsectors, unsigned max_errors)
static void PrintLogDirectories(const ata_smart_log_directory *gplogdir, const ata_smart_log_directory *smartlogdir)