15#define __STDC_FORMAT_MACROS 1
34#define GBUF_SIZE 65532
39#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
42#define LOG_RESP_LEN 252
43#define LOG_RESP_LONG_LEN ((62 * 256) + 252)
44#define LOG_RESP_TAPE_ALERT_LEN 0x144
47#define SCSI_SUPP_LOG_PAGES_MAX_COUNT (252 + (62 * 128) + 126)
87#define SCSI_VERSION_SPC_4 0x6
88#define SCSI_VERSION_SPC_5 0x7
89#define SCSI_VERSION_SPC_6 0xd
90#define SCSI_VERSION_HIGHEST SCSI_VERSION_SPC_6
95#define T10_VENDOR_SEAGATE "SEAGATE"
96#define T10_VENDOR_HITACHI_1 "HITACHI"
97#define T10_VENDOR_HITACHI_2 "HL-DT-ST"
98#define T10_VENDOR_HITACHI_3 "HGST"
102static const char *
gsap_s =
"General statistics and performance";
103static const char *
ssm_s =
"Solid state media";
104static const char *
zbds_s =
"Zoned block device statistics";
105static const char *
lp_s =
"log page";
124 if ((
nullptr == bp) || (b_len <= 0))
126 for (--b_len; b_len >= 0; --b_len) {
127 if (0xff != bp[b_len])
134static std::string
rtrim(
const std::string&
s,
const char* t =
" \t\n\r\f\v")
138 r.erase(r.find_last_not_of(t) + 1);
145 bool got_subpages =
false;
146 int k, err, resp_len, num_unreported, num_unreported_spg;
147 int supp_lpg_and_spg_count = 0;
154 memset(supp_lpg_and_spg, 0,
sizeof(supp_lpg_and_spg));
158 pout(
"%s: RSOC says %s not supported\n", __func__,
logSenStr);
172 pout(
"%s for supported pages failed (second attempt) [%s]\n",
182 for (k = 0; k < resp_len; k += 1) {
184 supp_lpg_and_spg[supp_lpg_and_spg_count++] = {
page_code, 0};
202 pout(
"%s for supported pages and subpages failed [%s]\n",
208 pout(
"%s: %s ignored subpage field, bad\n",
210 }
else if (! ((0x40 &
gBuf[0]) &&
213 pout(
"%s supported subpages is bad SPF=%u SUBPG=%u\n",
224 for (k = 0; k < resp_len; k += 2) {
233 num_unreported_spg = 0;
234 for (k = 0; k < supp_lpg_and_spg_count; k += 1) {
243 pout(
"%s: Strange Log page number: 0x0,0x%x\n",
271 ++num_unreported_spg;
284 ++num_unreported_spg;
310 ++num_unreported_spg;
350 ++num_unreported_spg;
359 ++num_unreported_spg;
365 pout(
"%s: number of unreported (standard) %ss: %d (sub-pages: %d)\n",
366 __func__,
lp_s, num_unreported, num_unreported_spg);
376 uint8_t currenttemp = 255;
377 uint8_t triptemp = 255;
384 ¤ttemp, &triptemp)) {
394 jout(
"SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq);
396 jglb[
"smart_status"][
"passed"] =
false;
397 jglb[
"smart_status"][
"scsi"][
"asc"] = asc;
398 jglb[
"smart_status"][
"scsi"][
"ascq"] = ascq;
399 jglb[
"smart_status"][
"scsi"][
"ie_string"] = cp;
402 jout(
"SMART Health Status: OK\n");
403 jglb[
"smart_status"][
"passed"] =
true;
407 if (255 == currenttemp)
408 pout(
"Current Drive Temperature: <not available>\n");
410 jout(
"Current Drive Temperature: %d C\n", currenttemp);
411 jglb[
"temperature"][
"current"] = currenttemp;
414 pout(
"Drive Trip Temperature: <not available>\n");
416 jout(
"Drive Trip Temperature: %d C\n", triptemp);
417 jglb[
"temperature"][
"drive_trip"] = triptemp;
433 unsigned short pagelength;
434 unsigned short parametercode;
439 const char * pad = from_health ?
"" :
" ";
440 static const char *
const tapealert_s =
"scsi_tapealert";
450 if (
gBuf[0] != 0x2e) {
459 for (i = 4, m = 0; i < pagelength; i += 5, ++k, ++m) {
468 jout(
"%sTapeAlert Errors (C=Critical, W=Warning, "
469 "I=Informational):\n", pad);
470 jout(
"%s[0x%02x] %s\n", pad, parametercode, ts);
471 jref[j][
"descriptor_idx"] = m + 1;
472 jref[j][
"parameter_code"] = parametercode;
473 jref[j][
"string"] = ts;
483 jout(
"%sTapeAlert: OK\n", pad);
484 jglb[tapealert_s][
"status"] =
"Good";
493 int err, len, k, extra;
497 static const char * jname =
"scsi_start_stop_cycle_counter";
514 for (k = len; k > 0; k -= extra, ucp += extra) {
524 bool is_all_ffs = (extra > 7) ?
all_ffs(ucp + 4, 4) :
false;
528 jout(
"Manufactured in week %.2s of year %.4s\n", ucp + 8,
530 snprintf(
b,
sizeof(
b),
"%.4s", ucp + 4);
531 jglb[jname][
"year_of_manufacture"] =
b;
532 snprintf(
b,
sizeof(
b),
"%.2s", ucp + 8);
533 jglb[jname][
"week_of_manufacture"] =
b;
540 if ((extra > 7) && (! is_all_ffs)) {
541 q =
"Specified cycle count over device lifetime";
542 jout(
"%s: %u\n", q, u);
547 if ((extra > 7) && (! is_all_ffs)) {
548 q =
"Accumulated start-stop cycles";
549 jout(
"%s: %u\n", q, u);
554 if ((extra > 7) && (! is_all_ffs)) {
555 q =
"Specified load-unload count over device lifetime";
556 jout(
"%s: %u\n", q, u);
561 if ((extra > 7) && (! is_all_ffs)) {
562 q =
"Accumulated load-unload cycles";
563 jout(
"%s: %u\n", q, u);
577 static const char * pDefStr =
"Pending Defects";
578 static const char * jname =
"scsi_pending_defects";
603 const uint8_t * bp =
gBuf + 4;
612 jout(
" Pending defect count:");
613 if ((pl < 8) || (num < 8)) {
615 pout(
"%s truncated descriptor\n", pDefStr);
622 jout(
"0 %s\n", pDefStr);
624 jout(
"1 Pending Defect, LBA and accumulated_power_on_hours "
627 jout(
"%u %s: index, LBA and accumulated_power_on_hours "
628 "follow\n",
count, pDefStr);
631 if ((pl < 16) || (num < 16)) {
633 pout(
"%s truncated descriptor\n", pDefStr);
639 jout(
" %4d: 0x%-16" PRIx64
", %5u\n", pc, lba, poh);
644 jref[
"accum_power_on_hours"] = poh;
658 unsigned int dl_len, div;
659 static const char * hname =
"Read defect list";
666 got_rd12 = (0 == err);
689 }
else if (101 == err)
707 pout(
"%s (12): generation=%d\n", hname, generation);
713 if (0x8 != (
gBuf[1] & 0x18)) {
715 pout(
"%s: asked for grown list but didn't get it\n", hname);
720 dl_format = (
gBuf[1] & 0x7);
739 pout(
"defect list format %d unknown\n", dl_format);
744 jout(
"Elements in grown defect list: 0\n\n");
745 jglb[
"scsi_grown_defect_list"] = 0;
749 pout(
"Grown defect list length=%u bytes [unknown "
750 "number of elements]\n\n", dl_len);
752 jout(
"Elements in grown defect list: %u\n\n", dl_len / div);
753 jglb[
"scsi_grown_defect_list"] = dl_len / div;
761 static const size_t sz_u64 = (int)
sizeof(uint64_t);
762 unsigned int u = ucp[3];
763 const unsigned char * xp = ucp + 4;
775 int num, pl, pc, err, len;
777 static const char * seaCacStr =
"Seagate Cache";
804 case 0:
case 1:
case 2:
case 3:
case 4:
809 pout(
"Vendor (%s) lpage has unexpected parameter, skip\n",
818 pout(
"Vendor (%s) information\n", seaCacStr);
825 case 0:
pout(
" Blocks sent to initiator");
break;
826 case 1:
pout(
" Blocks received from initiator");
break;
827 case 2:
pout(
" Blocks read from cache and sent to initiator");
break;
828 case 3:
pout(
" Number of read and write commands whose size "
829 "<= segment size");
break;
830 case 4:
pout(
" Number of read and write commands whose size "
831 "> segment size");
break;
832 default:
pout(
" Unknown Seagate parameter code [0x%x]", pc);
break;
844 int num, pl, pc, len, err, good, bad;
884 if ((good < 2) || (bad > 4)) {
887 pout(
"\nVendor (Seagate/Hitachi) factory lpage has too many "
888 "unexpected parameters, skip\n");
893 pout(
"Vendor (Seagate/Hitachi) factory information\n");
901 case 0:
jout(
" number of hours powered up");
904 case 8:
pout(
" number of minutes until next internal SMART test");
910 pout(
"Vendor (Seagate/Hitachi) factory lpage: "
911 "unknown parameter code [0x%x]\n", pc);
919 jout(
" = %.2f\n", ull / 60.0 );
920 jglb[
"power_on_time"][
"hours"] = ull / 60;
921 jglb[
"power_on_time"][
"minutes"] = ull % 60;
924 pout(
" = %" PRIu64
"\n", ull);
937 int found[3] = {0, 0, 0};
952 ecp = &errCounterArr[2];
953 for (
int k = 0; k < 7; ++k) {
960 if (found[0] || found[1] || found[2]) {
961 pout(
"Error counter log:\n");
962 pout(
" Errors Corrected by Total "
963 "Correction Gigabytes Total\n");
964 pout(
" ECC rereads/ errors "
965 "algorithm processed uncorrected\n");
966 pout(
" fast | delayed rewrites corrected "
967 "invocations [10^9 bytes] errors\n");
970 for (
int k = 0; k < 3; ++k) {
973 ecp = &errCounterArr[k];
974 static const char *
const pageNames[3] =
975 {
"read: ",
"write: ",
"verify: "};
976 static const char * jpageNames[3] =
977 {
"read",
"write",
"verify"};
978 jout(
"%s%8" PRIu64
" %8" PRIu64
" %8" PRIu64
" %8" PRIu64
979 " %8" PRIu64, pageNames[k], ecp->
counter[0],
982 double processed_gb = ecp->
counter[5] / 1000000000.0;
983 jout(
" %12.3f %8" PRIu64
"\n", processed_gb,
986 jref[jpageNames[k]][
"errors_corrected_by_eccfast"] = ecp->
counter[0];
987 jref[jpageNames[k]][
"errors_corrected_by_eccdelayed"] = ecp->
counter[1];
988 jref[jpageNames[k]][
"errors_corrected_by_rereads_rewrites"] = ecp->
counter[2];
989 jref[jpageNames[k]][
"total_errors_corrected"] = ecp->
counter[3];
990 jref[jpageNames[k]][
"correction_algorithm_invocations"] = ecp->
counter[4];
991 jref[jpageNames[k]][
"gigabytes_processed"] =
strprintf(
"%.3f", processed_gb);
992 jref[jpageNames[k]][
"total_uncorrected_errors"] = ecp->
counter[6];
996 pout(
"Error Counter logging not supported\n");
1002 pout(
"\nNon-medium error count: %8" PRIu64
"\n", nme.
counterPC0);
1004 pout(
"Track following error count [Hitachi]: %8" PRIu64
"\n",
1007 pout(
"Positioning error count [Hitachi]: %8" PRIu64
"\n",
1017 unsigned char * ucp =
gBuf + 4;
1020 pout(
"\nNo error events logged\n");
1022 pout(
"\nLast n error events %s\n",
lp_s);
1023 for (
int k = num, pl; k > 0; k -= pl, ucp += pl) {
1025 pout(
" <<short Last n error events %s>>\n",
lp_s);
1031 if ((ucp[2] & 0x1) && (ucp[2] & 0x2)) {
1032 pout(
" Error event %d:\n", pc);
1033 pout(
" [binary]:\n");
1034 dStrHex((
const uint8_t *)ucp + 4, pl - 4, 1);
1035 }
else if (ucp[2] & 0x1) {
1036 pout(
" Error event %d:\n", pc);
1037 pout(
" %.*s\n", pl - 4, (
const char *)(ucp + 4));
1040 pout(
" Error event %d:\n", pc);
1041 pout(
" [data counter??]:\n");
1042 dStrHex((
const uint8_t *)ucp + 4, pl - 4, 1);
1048 pout(
" >>>> log truncated, fetched %d of %d available "
1068 "Aborted (by user command)",
1069 "Aborted (device reset ?) ",
1070 "Unknown error, incomplete",
1071 "Completed, segment failed",
1072 "Failed in first segment ",
1073 "Failed in second segment ",
1074 "Failed in segment",
1082 "Self test in progress ..."
1092 bool noheader =
true;
1093 int num, k, err, durationSec;
1097 static const char * hname =
"Self-test";
1098 static const char * fixup_stres7 =
" --> ";
1102 (sense_info.
asc == 0x04 && sense_info.
ascq == 0x09 &&
1104 pout(
"%s execution status:\t\t%d%% of test remaining\n", hname,
1105 100 - ((sense_info.
progress * 100) / 65535));
1126 pout(
"%s %s length is 0x%x not 0x190 bytes\n", hname,
logSenStr, num);
1131 for (k = 0, ucp =
gBuf + 4; k < 20; ++k, ucp += 20 ) {
1137 snprintf(st,
sizeof(st),
"scsi_self_test_%d", k);
1140 if ((0 == poh) && (0 == ucp[4]))
1145 jout(
"SMART %s log\n", hname);
1146 jout(
"Num Test Status segment "
1147 "LifeTime LBA_first_err [SK ASC ASQ]\n");
1148 jout(
" Description number "
1154 u = (ucp[4] >> 5) & 0x7;
1156 jglb[st][
"code"][
"value"] = u;
1193 jglb[st][
"result"][
"value"] = tr;
1205 jglb[st][
"failed_segment"][
"value"] = u;
1206 jglb[st][
"failed_segment"][
"aka"] =
"self_test_number";
1211 if (poh==0 && tr==0xf) {
1214 jglb[st][
"self_test_in_progress"] =
true;
1217 jglb[st][
"power_on_time"][
"hours"] = poh;
1218 jglb[st][
"power_on_time"][
"aka"] =
"accumulated_power_on_hours";
1223 bool is_all_ffs =
all_ffs(ucp + 8, 8);
1225 if ((! is_all_ffs) && (tr > 0) && (tr < 0xf)) {
1229 snprintf(buff,
sizeof(buff),
"%" PRIu64, ull);
1232 jglb[st][
"lba_first_failure"][
"value"] = ull;
1233 jglb[st][
"lba_first_failure"][
"aka"] =
"address_of_first_failure";
1239 if (ucp[16] & 0xf) {
1242 jout(
" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]);
1244 jglb[st][
"sense_key"][
"value"] = u;
1245 jglb[st][
"sense_key"][
"string"] =
1247 jglb[st][
"asc"] = ucp[17];
1248 jglb[st][
"ascq"] = ucp[18];
1249 jglb[st][
"vendor_specific"] = ucp[19];
1256 jout(
"No %ss have been logged\n", hname);
1259 if (durationSec > 14400)
1260 jout(
"\nLong (extended) %s duration: %d seconds "
1261 "[%.1f hours]\n", hname, durationSec, durationSec / 3600.0);
1263 jout(
"\nLong (extended) %s duration: %d seconds "
1264 "[%.1f minutes]\n", hname, durationSec, durationSec / 60.0);
1265 jglb[
"scsi_extended_self_test_seconds"] = durationSec;
1274 "pre-scan is active",
1275 "halted due to fatal error",
1276 "halted due to a vendor specific pattern of error",
1277 "halted due to medium formatted without P-List",
1278 "halted - vendor specific cause",
1279 "halted due to temperature out of range",
1280 "waiting until BMS interval timer expires",
1285 "Require Write or Reassign Blocks command",
1286 "Successfully reassigned",
1288 "Reassignment by disk failed",
1289 "Recovered via rewrite in-place",
1290 "Reassigned by app, has valid data",
1291 "Reassigned by app, has no valid data",
1292 "Unsuccessfully reassigned by app",
1304 bool noheader =
true;
1305 bool firstresult =
true;
1306 int num, j, m, err, truncated;
1313 static const char * hname =
"Background scan results";
1314 static const char * jname =
"scsi_background_scan";
1332 if (! only_pow_time) {
1334 pout(
"%s %s length is %d, no scan status\n", hname,
logSenStr,
1348 int pl = ucp[3] + 4;
1353 if (! only_pow_time)
1354 jout(
"%s log\n", hname);
1356 if (! only_pow_time)
1358 if ((pl < 16) || (num < 16)) {
1359 if (! only_pow_time)
1364 if (! only_pow_time) {
1367 jglb[jname][
"status"][
"value"] = j;
1370 jout(
"unknown [0x%x] background scan status value\n", j);
1371 jglb[jname][
"status"][
"value"] = j;
1375 jout(
"%sAccumulated power on time, hours:minutes %d:%02d",
1376 (only_pow_time ?
"" :
" "), (j / 60), (j % 60));
1380 jout(
" [%d minutes]\n", j);
1381 jglb[
"power_on_time"][
"hours"] = j / 60;
1382 jglb[
"power_on_time"][
"minutes"] = j % 60;
1386 jout(
" Number of background scans performed: %u, ", u);
1387 jglb[jname][
"status"][
"number_scans_performed"] = u;
1389 snprintf(
b,
sizeof(
b),
"%.2f%%", (
double)u * 100.0 / 65536.0);
1390 jout(
"scan progress: %s\n",
b);
1391 jglb[jname][
"status"][
"scan_progress"] =
b;
1393 jout(
" Number of background medium scans performed: %d\n", u);
1394 jglb[jname][
"status"][
"number_medium_scans_performed"] = u;
1399 if (! only_pow_time)
1400 jout(
"\n%s log\n", hname);
1406 jout(
"\n # when lba(hex) [sk,asc,ascq] "
1407 "reassign_status\n");
1409 snprintf(res_s,
sizeof(res_s),
"result_%d", pc);
1411 jglb[jname][res_s][
"parameter_code"] = pc;
1412 if ((pl < 24) || (num < 24)) {
1414 jout(
"parameter length >= 24 expected, got %d\n", pl);
1418 jout(
"%4u:%02u ", (u / 60), (u % 60));
1419 jglb[jname][res_s][
"accumulated_power_on"][
"minutes"] = u;
1420 for (m = 0; m < 8; ++m)
1421 jout(
"%02x", ucp[16 + m]);
1423 jglb[jname][res_s][
"lba"] = lba;
1425 jout(
" [%x,%x,%x] ", u, ucp[9], ucp[10]);
1426 jglb[jname][res_s][
"sense_key"][
"value"] = u;
1427 jglb[jname][res_s][
"sense_key"][
"string"] =
1429 jglb[jname][res_s][
"asc"] = ucp[9];
1430 jglb[jname][res_s][
"ascq"] = ucp[10];
1431 u = (ucp[8] >> 4) & 0xf;
1434 jglb[jname][res_s][
"reassign_status"][
"value"] = u;
1435 jglb[jname][res_s][
"reassign_status"][
"string"] =
1438 jout(
"Reassign status: reserved [0x%x]\n", u);
1439 jglb[jname][res_s][
"reassign_status"][
"value"] = u;
1446 if (truncated && (! only_pow_time))
1447 jout(
" >>>> log truncated, fetched %d of %d available "
1450 if (! only_pow_time)
1459 uint16_t loop_pc, pl;
1460 uint32_t a_exp, a_int, casc;
1467 if (loop_pc == ti_pc) {
1471 pout(
"%s Time interval log parameter too short (pl=%d)\n",
1504 int64_t timeUnitInNS)
1506 if ((intervals > 0) && (timeUnitInNS > 0)) {
1507 intervals *= timeUnitInNS;
1508 intervals /= 1000000;
1509 jout(
"%*cin seconds: %" PRIu64
".%03" PRIu64
"\n",
1510 leadin_spaces,
' ', intervals / 1000, intervals % 1000);
1511 if (intervals > 3600000) {
1513 jout(
"%*cin hours: %" PRIu64
".%03" PRIu64
"\n",
1514 leadin_spaces,
' ', intervals / 1000, intervals % 1000);
1524 int num, err, truncated;
1526 int64_t timeUnitInNS;
1531 json::ref jref =
jglb[
"scsi_general_statistics_and_performance_log"];
1532 json::ref jref1 = jref[
"general_access"];
1534 json::ref jref3 = jref[
"time_interval"];
1536 static const char * p1name =
"General access statistics and performance";
1537 static const char * p2name =
"Idle time";
1538 static const char * p3name =
"Time interval";
1539 static const char * p4name =
"Force Unit Access statistics and "
1570 if (timeUnitInNS < 0) {
1573 pout(
"%s unable to decode time unit [%d]\n",
gsap_s,
1583 int pl = ucp[3] + 4;
1587 if (pl < 0x40 + 4) {
1589 pout(
"%s %s log parameter too short (pl=%d)\n",
gsap_s,
1594 jout(
" %s:\n", p1name);
1595 ccp =
"Number of read commands";
1597 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1599 ccp =
"Number of write commands";
1601 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1603 ccp =
"number of logical blocks received";
1605 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1607 ccp =
"number of logical blocks transmitted";
1609 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1611 ccp =
"read command processing intervals";
1613 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1616 ccp =
"write command processing intervals";
1618 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1621 ccp =
"weighted number of read commands plus write commands";
1623 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1625 ccp =
"weighted read command processing plus write command "
1629 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1635 pout(
"%s %s log parameter too short (pl=%d)\n",
gsap_s,
1640 jout(
" %s:\n", p2name);
1641 ccp =
"Idle time intervals";
1643 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1651 pout(
"%s %s log parameter too short (pl=%d)\n",
gsap_s,
1664 if (pl < 0x40 + 4) {
1666 pout(
"%s %s log parameter too short (pl=%d)\n",
gsap_s,
1671 jout(
" %s:\n", p4name);
1672 ccp =
"Number of read FUA commands";
1674 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1676 ccp =
"Number of write FUA commands";
1678 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1680 ccp =
"Number of read FUA_NV commands";
1682 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1684 ccp =
"Number of write FUA_NV commands";
1686 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1688 ccp =
"Number of read FUA intervals";
1690 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1693 ccp =
"Number of write FUA intervals";
1695 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1697 ccp =
"Number of read FUA_NV intervals";
1699 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1702 ccp =
"Number of write FUA_NV intervals";
1704 jout(
" %s: %" PRIu64
"\n", ccp, ull);
1725 int num, err, truncated;
1759 int pl = ucp[3] + 4;
1764 pout(
"%s Percentage used endurance indicator parameter "
1765 "too short (pl=%d)\n",
ssm_s, pl);
1769 q =
"Percentage used endurance indicator";
1770 jout(
"%s: %d%%\n", q, ucp[7]);
1784 int num, err, truncated;
1789 static const char * jname =
"scsi_zoned_block_device_statistics";
1822 int pl = ucp[3] + 4;
1828 q =
"Maximum open zones";
1830 jout(
" %s: %u\n", q, u);
1834 q =
"Maximum explicitly open zones";
1836 jout(
" %s: %u\n", q, u);
1840 q =
"Maximum implicitly open zones";
1842 jout(
" %s: %u\n", q, u);
1846 q =
"Minimum empty zones";
1848 jout(
" %s: %u\n", q, u);
1852 q =
"Maximum nonseq zones";
1854 jout(
" %s: %u\n", q, u);
1858 q =
"Zones emptied";
1860 jout(
" %s: %u\n", q, u);
1864 q =
"Suboptimal write commands";
1866 jout(
" %s: %u\n", q, u);
1870 q =
"Commands exceeding optinmal limit";
1872 jout(
" %s: %u\n", q, u);
1876 q =
"Failed explicit opens";
1878 jout(
" %s: %u\n", q, u);
1882 q =
"Read rule violations";
1884 jout(
" %s: %u\n", q, u);
1888 q =
"Write rule violations";
1890 jout(
" %s: %u\n", q, u);
1894 q =
"Maximum implicitly open sequential or before required zones";
1896 jout(
" %s: %u\n", q, u);
1912 int num, err, truncated;
1918 static const char * hname =
"Device statistics (SSC, tape)";
1919 static const char * jname =
"scsi_device_statistics";
1940 pout(
"%s %s length is %d, too short\n", hname,
logSenStr, num);
1952 int pl = ucp[3] + 4;
1957 q =
"Lifetime volume loads";
1959 jout(
" %s: %" PRIu64
"\n", q, ull);
1963 q =
"Lifetime cleaning operations";
1965 jout(
" %s: %" PRIu64
"\n", q, ull);
1969 q =
"Lifetime power on hours";
1971 jout(
" %s: %" PRIu64
"\n", q, ull);
1975 q =
"Lifetime medium motion hours";
1977 jout(
" %s: %" PRIu64
"\n", q, ull);
1981 q =
"Lifetime meters of tape processed";
1983 jout(
" %s: %" PRIu64
"\n", q, ull);
1987 q =
"Lifetime medium motion hours at last incompatible volume "
1990 jout(
" %s: %" PRIu64
"\n", q, ull);
1994 q =
"Lifetime power on hours at last temperature condition "
1997 jout(
" %s: %" PRIu64
"\n", q, ull);
2001 q =
"Lifetime power on hours at last power consumption condition "
2004 jout(
" %s: %" PRIu64
"\n", q, ull);
2008 q =
"Medium motion hours since last successful cleaning "
2011 jout(
" %s: %" PRIu64
"\n", q, ull);
2015 q =
"Medium motion hours since second to last successful "
2016 "cleaning operation";
2018 jout(
" %s: %" PRIu64
"\n", q, ull);
2022 q =
"Medium motion hours since third to last successful "
2023 "cleaning operation";
2025 jout(
" %s: %" PRIu64
"\n", q, ull);
2029 q =
"Lifetime power on hours at last operator initiated forced "
2030 "reset and/or emergency eject occurrence";
2032 jout(
" %s: %" PRIu64
"\n", q, ull);
2036 q =
"Lifetime power cycles";
2038 jout(
" %s: %" PRIu64
"\n", q, ull);
2042 q =
"Volume loads since last parameter reset";
2044 jout(
" %s: %" PRIu64
"\n", q, ull);
2048 q =
"Hard write errors";
2050 jout(
" %s: %" PRIu64
"\n", q, ull);
2054 q =
"Hard read errors";
2056 jout(
" %s: %" PRIu64
"\n", q, ull);
2060 q =
"Duty cycle sample time";
2062 jout(
" %s: %" PRIu64
"\n", q, ull);
2066 q =
"Read duty cycle";
2068 jout(
" %s: %" PRIu64
"\n", q, ull);
2072 q =
"Write duty cycle";
2074 jout(
" %s: %" PRIu64
"\n", q, ull);
2078 q =
"Activity duty cycle";
2080 jout(
" %s: %" PRIu64
"\n", q, ull);
2084 q =
"Volume not present duty cycle";
2086 jout(
" %s: %" PRIu64
"\n", q, ull);
2090 q =
"Ready duty cycle";
2092 jout(
" %s: %" PRIu64
"\n", q, ull);
2096 q =
"Megabytes transferred from application client in duty cycle"
2099 jout(
" %s: %" PRIu64
"\n", q, ull);
2103 q =
"Megabytes transferred to application client in duty cycle"
2106 jout(
" %s: %" PRIu64
"\n", q, ull);
2111 std::string v((
const char *)(ucp + 4), ucp[3]);
2112 q =
"Drive manufacturer's serial number";
2113 jout(
" %s: %s\n", q, v.c_str());
2119 std::string v((
const char *)(ucp + 4), ucp[3]);
2120 q =
"Drive serial number";
2121 jout(
" %s: %s\n", q, v.c_str());
2127 std::string v((
const char *)(ucp + 4), ucp[3]);
2128 q =
"Manufacturing date year,month,day";
2129 jout(
" %s: %s\n", q, v.c_str());
2135 std::string v((
const char *)(ucp + 4), ucp[3]);
2136 q =
"Manufacturing date year,week";
2137 jout(
" %s: %s\n", q, v.c_str());
2143 std::string v((
const char *)(ucp + 4), ucp[3]);
2144 q =
"Manufacturing date year,week";
2145 jout(
" %s: %s\n", q, v.c_str());
2150 q =
"Medium removal prevented";
2152 jout(
" %s: %" PRIu64
"\n", q, ull);
2156 q =
"Maximum recommended mechanism temperature exceeded";
2158 jout(
" %s: %" PRIu64
"\n", q, ull);
2162 q =
"Medium motion hours for each medium type";
2165 jout(
" %s, number of element: %u\n", q, n);
2166 for (k = 0; k < n; ++k, ucp += 8) {
2168 jout(
" [%d] density code: %u, density code: %u, hours: "
2169 "%u\n", k + 1, ucp[6], ucp[7], u);
2170 jglb[jname][
s][k][
"density_code"] = ucp[6];
2171 jglb[jname][
s][k][
"medium_type"] = ucp[7];
2172 jglb[jname][
s][k][
"medium_motion_hours"] = u;
2187 int num, err, truncated;
2191 static const char * hname =
"Format Status";
2192 static const char * jname =
"scsi_format_status";
2211 jout(
"%s %s length is %d, too short\n", hname,
logSenStr, num);
2223 int pl = ucp[3] + 4;
2225 bool is_count =
true;
2226 const char * jout_str =
"";
2227 const char * jglb_str =
"x";
2232 jout(
"Format data out: <empty>\n");
2235 jout(
"Format data out: <not available>\n");
2237 jout(
"Format data out:\n");
2238 dStrHex((
const uint8_t *)ucp + 4, pl - 4, 0);
2245 jout_str =
"Grown defects during certification";
2246 jglb_str =
"grown_defects_during_cert";
2249 jout_str =
"Total blocks reassigned during format";
2250 jglb_str =
"blocks_reassigned_during_format";
2253 jout_str =
"Total new blocks reassigned";
2254 jglb_str =
"total_new_block_since_format";
2257 jout_str =
"Power on minutes since format";
2258 jglb_str =
"power_on_minutes_since_format";
2262 pout(
" Unknown Format parameter code = 0x%x\n", pc);
2263 dStrHex((
const uint8_t *)ucp, pl, 0);
2269 if (
all_ffs(ucp + 4, ucp[3])) {
2270 pout(
"%s <not available>\n", jout_str);
2273 jout(
"%s = %" PRIu64
"\n", jout_str, ull);
2274 jglb[jname][jglb_str] = ull;
2286 unsigned thresh_val)
2290 static const char * pvd_th =
"Peak value detector threshold";
2291 static const char * pvd_th_j =
"pvd_threshold";
2295 jout(
" No event\n");
2298 q =
"Invalid dword count";
2299 jout(
" %s: %u\n", q, val);
2300 jref[std::string(q) +
"_2"] = val;
2303 q =
"Running disparity error count";
2304 jout(
" %s: %u\n", q, val);
2305 jref[std::string(q) +
"_2"] = val;
2308 q =
"Loss of dword synchronization count";
2309 jout(
" %s: %u\n", q, val);
2310 jref[std::string(q) +
"_2"] = val;
2313 q =
"Phy reset problem count";
2314 jout(
" %s: %u\n", q, val);
2315 jref[std::string(q) +
"_2"] = val;
2318 q =
"Elasticity buffer overflow count";
2319 jout(
" %s: %u\n", q, val);
2323 q =
"Received ERROR count";
2324 jout(
" %s: %u\n", q, val);
2328 q =
"Received address frame error count";
2329 jout(
" %s: %u\n", q, val);
2333 q =
"Transmitted abandon-class OPEN_REJECT count";
2334 jout(
" %s: %u\n", q, val);
2338 q =
"Received abandon-class OPEN_REJECT count";
2339 jout(
" %s: %u\n", q, val);
2343 q =
"Transmitted retry-class OPEN_REJECT count";
2344 jout(
" %s: %u\n", q, val);
2348 q =
"Received retry-class OPEN_REJECT count";
2349 jout(
" %s: %u\n", q, val);
2353 q =
"Received AIP (WAITING ON PARTIAL) count";
2354 jout(
" %s: %u\n", q, val);
2358 q =
"Received AIP (WAITING ON CONNECTION) count";
2359 jout(
" %s: %u\n", q, val);
2363 q =
"Transmitted BREAK count";
2364 jout(
" %s: %u\n", q, val);
2368 q =
"Received BREAK count";
2369 jout(
" %s: %u\n", q, val);
2373 q =
"Break timeout count";
2374 jout(
" %s: %u\n", q, val);
2378 q =
"Connection count";
2379 jout(
" %s: %u\n", q, val);
2383 q =
"Peak transmitted pathway blocked";
2384 jout(
" %s count: %u\n", q, val & 0xff);
2385 jout(
" %s: %u\n", pvd_th, thresh_val & 0xff);
2386 jref[q][
"count"] = val & 0xff;
2387 jref[q][pvd_th_j] = thresh_val & 0xff;
2390 q =
"Peak transmitted arbitration wait time";
2393 jout(
" %s (us): %u\n", q, u);
2394 jref[std::string(q) +
"_us"][
"event"] = u;
2396 jout(
" %s (ms): %u\n", q, 33 + (u - 0x8000));
2397 jref[std::string(q) +
"_ms"][
"event"] = 33 + (u - 0x8000);
2399 u = thresh_val & 0xffff;
2401 jout(
" %s (us): %u\n", pvd_th, u);
2402 jref[std::string(q) +
"_us"][pvd_th_j] = u;
2404 jout(
" %s (ms): %u\n", pvd_th, 33 + (u - 0x8000));
2405 jref[std::string(q) +
"_ms"][pvd_th_j] = 33 + (u - 0x8000);
2409 q =
"Peak arbitration time";
2410 jout(
" %s (us): %u\n", q, val);
2411 jref[std::string(q) +
"_us"][
"event"] = val;
2412 jout(
" %s: %u\n", pvd_th, thresh_val);
2413 jref[std::string(q) +
"_us"][pvd_th_j] = thresh_val;
2416 q =
"Peak connection time";
2417 jout(
" %s (us): %u\n", q, val);
2418 jref[std::string(q) +
"_us"][
"event"] = val;
2419 jout(
" %s: %u\n", pvd_th, thresh_val);
2420 jref[std::string(q) +
"_us"][pvd_th_j] = thresh_val;
2423 q =
"Transmitted SSP frame count";
2424 jout(
" %s: %u\n", q, val);
2428 q =
"Received SSP frame count";
2429 jout(
" %s: %u\n", q, val);
2433 q =
"Transmitted SSP frame error count";
2434 jout(
" %s: %u\n", q, val);
2438 q =
"Received SSP frame error count";
2439 jout(
" %s: %u\n", q, val);
2443 q =
"Transmitted CREDIT_BLOCKED count";
2444 jout(
" %s: %u\n", q, val);
2448 q =
"Received CREDIT_BLOCKED count";
2449 jout(
" %s: %u\n", q, val);
2453 q =
"Transmitted SATA frame count";
2454 jout(
" %s: %u\n", q, val);
2458 q =
"Received SATA frame count";
2459 jout(
" %s: %u\n", q, val);
2463 q =
"SATA flow control buffer overflow count";
2464 jout(
" %s: %u\n", q, val);
2468 q =
"Transmitted SMP frame count";
2469 jout(
" %s: %u\n", q, val);
2473 q =
"Received SMP frame count";
2474 jout(
" %s: %u\n", q, val);
2478 q =
"Received SMP frame error count";
2479 jout(
" %s: %u\n", q, val);
2490 int k, j, m, nphys, t, sz, spld_len;
2492 unsigned char * vcp;
2496 snprintf(pn,
sizeof(pn),
"scsi_sas_port_%d", port_num);
2500 jout(
"relative target port id = %d\n", t);
2501 jglb[pn][
"relative_target_port_id"] = t;
2502 jout(
" generation code = %d\n", ucp[6]);
2503 jglb[pn][
"generation_code"] = ucp[6];
2505 jout(
" number of phys = %d\n", nphys);
2506 jglb[pn][
"number_of_phys"] = nphys;
2508 for (j = 0, k = 0, vcp = ucp + 8; j < (param_len - 8);
2509 vcp += spld_len, j += spld_len, ++k) {
2512 snprintf(yn,
sizeof(yn),
"phy_%d", k);
2514 jout(
" phy identifier = %d\n", vcp[1]);
2515 jref[
"identifier"] = vcp[1];
2521 t = ((0x70 & vcp[4]) >> 4);
2523 case 0: snprintf(
s, sz,
"no device attached");
break;
2524 case 1: snprintf(
s, sz,
"SAS or SATA device");
break;
2525 case 2: snprintf(
s, sz,
"expander device");
break;
2526 case 3: snprintf(
s, sz,
"expander device (fanout)");
break;
2527 default: snprintf(
s, sz,
"reserved [%d]", t);
break;
2529 q =
"attached device type";
2530 jout(
" %s: %s\n", q,
s);
2534 case 0: snprintf(
s, sz,
"unknown");
break;
2535 case 1: snprintf(
s, sz,
"power on");
break;
2536 case 2: snprintf(
s, sz,
"hard reset");
break;
2537 case 3: snprintf(
s, sz,
"SMP phy control function");
break;
2538 case 4: snprintf(
s, sz,
"loss of dword synchronization");
break;
2539 case 5: snprintf(
s, sz,
"mux mix up");
break;
2540 case 6: snprintf(
s, sz,
"I_T nexus loss timeout for STP/SATA");
2542 case 7: snprintf(
s, sz,
"break timeout timer expired");
break;
2543 case 8: snprintf(
s, sz,
"phy test function stopped");
break;
2544 case 9: snprintf(
s, sz,
"expander device reduced functionality");
2546 default: snprintf(
s, sz,
"reserved [0x%x]", t);
break;
2548 q =
"attached reason";
2549 jout(
" %s: %s\n", q,
s);
2551 t = (vcp[5] & 0xf0) >> 4;
2553 case 0: snprintf(
s, sz,
"unknown");
break;
2554 case 1: snprintf(
s, sz,
"power on");
break;
2555 case 2: snprintf(
s, sz,
"hard reset");
break;
2556 case 3: snprintf(
s, sz,
"SMP phy control function");
break;
2557 case 4: snprintf(
s, sz,
"loss of dword synchronization");
break;
2558 case 5: snprintf(
s, sz,
"mux mix up");
break;
2559 case 6: snprintf(
s, sz,
"I_T nexus loss timeout for STP/SATA");
2561 case 7: snprintf(
s, sz,
"break timeout timer expired");
break;
2562 case 8: snprintf(
s, sz,
"phy test function stopped");
break;
2563 case 9: snprintf(
s, sz,
"expander device reduced functionality");
2565 default: snprintf(
s, sz,
"reserved [0x%x]", t);
break;
2568 jout(
" %s: %s\n", q,
s);
2572 case 0: snprintf(
s, sz,
"phy enabled; unknown");
2574 case 1: snprintf(
s, sz,
"phy disabled");
break;
2575 case 2: snprintf(
s, sz,
"phy enabled; speed negotiation failed");
2577 case 3: snprintf(
s, sz,
"phy enabled; SATA spinup hold state");
2579 case 4: snprintf(
s, sz,
"phy enabled; port selector");
2581 case 5: snprintf(
s, sz,
"phy enabled; reset in progress");
2583 case 6: snprintf(
s, sz,
"phy enabled; unsupported phy attached");
2585 case 8: snprintf(
s, sz,
"phy enabled; 1.5 Gbps");
break;
2586 case 9: snprintf(
s, sz,
"phy enabled; 3 Gbps");
break;
2587 case 0xa: snprintf(
s, sz,
"phy enabled; 6 Gbps");
break;
2588 case 0xb: snprintf(
s, sz,
"phy enabled; 12 Gbps");
break;
2589 default: snprintf(
s, sz,
"reserved [%d]", t);
break;
2591 q =
"negotiated logical link rate";
2592 jout(
" %s: %s\n", q,
s);
2594 q =
"attached initiator port";
2595 jout(
" %s: ssp=%d stp=%d smp=%d\n", q,
2596 !! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2));
2597 snprintf(
s, sz,
"%03d", ((vcp[6] & 8) ? 100 : 0) +
2598 ((vcp[6] & 4) ? 10 : 0) + ((vcp[6] & 2) ? 1 : 0));
2599 jref[q][
"ssp_stp_smp"] =
s;
2600 q =
"attached target port";
2601 jout(
" %s: ssp=%d stp=%d smp=%d\n", q,
2602 !! (vcp[7] & 8), !! (vcp[7] & 4), !! (vcp[7] & 2));
2603 snprintf(
s, sz,
"%03d", ((vcp[7] & 8) ? 100 : 0) +
2604 ((vcp[7] & 4) ? 10 : 0) + ((vcp[7] & 2) ? 1 : 0));
2605 jref[q][
"ssp_stp_smp"] =
s;
2610 snprintf(
b,
sizeof(
b),
"0x%" PRIx64, ull);
2612 jout(
" %s = %s\n", q,
b);
2615 snprintf(
b,
sizeof(
b),
"0x%" PRIx64, ull);
2616 q =
"attached SAS address";
2617 jout(
" %s = %s\n", q,
b);
2620 q =
"attached phy identifier";
2621 jout(
" %s = %d\n", q, vcp[24]);
2625 q =
"Invalid DWORD count";
2626 jout(
" %s = %u\n", q, ui);
2629 q =
"Running disparity error count";
2630 jout(
" %s = %u\n", q, ui);
2633 q =
"Loss of DWORD synchronization count";
2634 jout(
" %s = %u\n", q, ui);
2637 q =
"Phy reset problem count";
2638 jout(
" %s = %u\n", q, ui);
2640 if (spld_len > 51) {
2641 bool header_given =
false;
2644 unsigned char * xcp;
2648 for (m = 0; m < (num_ped * 12); m += 12, xcp += 12) {
2655 if (allow_dupl || (peis > 0x4)) {
2656 if (! header_given) {
2657 header_given =
true;
2658 jout(
" Phy event descriptors:\n");
2672 unsigned char * ucp;
2675 for (k = 0, j = 0, ucp = resp + 4; k < num; ++j) {
2676 int param_len = ucp[3] + 4;
2680 jout(
"\nProtocol Specific port %s for SAS SSP\n",
lp_s);
2696 static const char * hname =
"Protocol specific port";
2716 pout(
"Only support %s %s on SAS devices\n\n", hname,
lp_s);
2724 pout(
"%s Log Select (reset) Failed [%s]\n\n", __func__,
2750 "optical card reader",
2752 "object based storage",
2753 "automation/driver interface",
2754 "security manager device",
2755 "host managed zoned block device",
2765 "well known logical unit",
2766 "unknown or no device type",
2771 "Fibre channel (FCP-4)",
2772 "Parallel SCSI (SPI-4)",
2774 "IEEE 1394 (SBP-3)",
2792 bool & have_zbc,
bool all)
2795 bool is_tape =
false;
2796 int err, iec_err, len, req_len, avail_len;
2799 int form_factor = 0;
2805 memset(
gBuf, 0, 96);
2811 pout(
"Retrying with a 64 byte Standard Inquiry\n");
2817 pout(
"Standard Inquiry (64 bytes) failed [%s]\n",
2823 avail_len =
gBuf[4] + 5;
2824 len = (avail_len < req_len) ? avail_len : req_len;
2825 peri_dt =
gBuf[0] & 0x1f;
2826 *peripheral_type = peri_dt;
2835 pout(
"Short INQUIRY response, skip product id\n");
2843 if (all && (0 != strncmp((
char *)&
gBuf[8],
"ATA", 3))) {
2844 char product[16+1], revision[4+1];
2849 pout(
"=== START OF INFORMATION SECTION ===\n");
2852 jout(
"Product: %.16s\n", product);
2853 jglb[
"scsi_product"] = product;
2856 if (
gBuf[32] >=
' ') {
2857 jout(
"Revision: %.4s\n", revision);
2859 jglb[
"scsi_revision"] = revision;
2864 snprintf(sv_arr,
sizeof(sv_arr),
"SPC-%d",
scsi_version - 2);
2865 jout(
"Compliance: %s\n", sv_arr);
2866 jglb[
"scsi_version"] = sv_arr;
2871 (0 == strncmp((
char *)&
gBuf[8],
"ATA", 3))) {
2872 pout(
"\nProbable ATA device behind a SAT layer\n"
2873 "Try an additional '-d ata' or '-d sat' argument.\n");
2879 protect =
gBuf[5] & 0x1;
2885 unsigned char lb_prov_resp[8];
2888 static const char * lb_prov_j =
"scsi_lb_provisioning";
2891 char cap_str[64], si_str[64];
2894 jout(
"User Capacity: %s bytes [%s]\n", cap_str, si_str);
2896 jglb[
"user_capacity"][
"blocks"].set_unsafe_uint64(capacity /
2898 jglb[
"user_capacity"][
"bytes"].set_unsafe_uint64(capacity);
2899 jout(
"Logical block size: %u bytes\n", srr.
lb_size);
2904 jout(
"Physical block size: %u bytes\n", pb_size);
2905 jglb[
"physical_block_size"] = pb_size;
2912 pout(
"Formatted with type 1 protection\n");
2915 pout(
"Formatted with type 2 protection\n");
2918 pout(
"Formatted with type 3 protection\n");
2921 pout(
"Formatted with unknown protection type [%d]\n",
2926 unsigned p_i_per_lb = (1 << srr.
p_i_exp);
2927 const unsigned pi_sz = 8;
2930 if (p_i_per_lb > 1) {
2931 jout(
"%d protection information intervals per "
2932 "logical block\n", p_i_per_lb);
2935 jout(
"%d bytes of protection information per logical "
2936 "block\n", pi_sz * p_i_per_lb);
2937 jglb[
"scsi_protection_interval_bytes_per_lb"] =
2949 lb_prov_resp,
sizeof(lb_prov_resp))) {
2950 int prov_type = lb_prov_resp[6] & 0x7;
2951 int vpd_lbprz = ((lb_prov_resp[5] >> 2) & 0x7);
2955 else if ((0 == vpd_lbprz) && (1 ==
lbprz))
2959 switch (prov_type) {
2962 jout(
"LU is fully provisioned");
2963 jglb[lb_prov_j][
"name"] =
"fully provisioned";
2969 jout(
"LB provisioning type: not reported [LBPME=1, "
2970 "LBPRZ=%d]\n",
lbprz);
2971 jglb[lb_prov_j][
"name"] =
"not reported";
2975 jout(
"LU is resource provisioned, LBPRZ=%d\n",
lbprz);
2976 jglb[lb_prov_j][
"name"] =
"resource provisioned";
2979 jout(
"LU is thin provisioned, LBPRZ=%d\n",
lbprz);
2980 jglb[lb_prov_j][
"name"] =
"thin provisioned";
2983 jout(
"LU provisioning type reserved [%d], LBPRZ=%d\n",
2985 jglb[lb_prov_j][
"name"] =
"reserved";
2988 jglb[lb_prov_j][
"value"] = prov_type;
2989 jglb[lb_prov_j][
"management_enabled"][
"name"] =
"LBPME";
2990 jglb[lb_prov_j][
"management_enabled"][
"value"] =
lbpme;
2991 jglb[lb_prov_j][
"read_zeros"][
"name"] =
"LBPRZ";
2992 jglb[lb_prov_j][
"read_zeros"][
"value"] =
lbprz;
2993 }
else if (1 ==
lbpme) {
2995 jout(
"rcap_16 sets LBPME but no LB provisioning VPD page\n");
2996 jout(
"Logical block provisioning enabled, LBPRZ=%d\n",
lbprz);
3004 jout(
"Rotation Rate: Solid State Device\n");
3005 else if ((rpm <= 0x400) || (0xffff == rpm))
3008 jout(
"Rotation Rate: %d rpm\n", rpm);
3009 jglb[
"rotation_rate"] = (rpm == 1 ? 0 : rpm);
3011 if (form_factor > 0) {
3012 const char * cp =
nullptr;
3014 switch (form_factor) {
3031 jglb[
"form_factor"][
"scsi_value"] = form_factor;
3033 jout(
"Form Factor: %s inches\n", cp);
3039 q =
"Host aware zoned block capable";
3042 }
else if (haw_zbc == 2) {
3044 q =
"Device managed zoned block capable";
3063 pout(
">> Terminate command early due to bad response to IEC "
3079 if (strlen(
s) > 0) {
3080 jout(
"Logical Unit id: %s\n",
s);
3081 jglb[
"logical_unit_id"] =
s;
3086 pout(
"Vital Product Data (VPD) bit ignored in INQUIRY\n");
3088 pout(
"Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
3096 gBuf[4 + len] =
'\0';
3098 jout(
"Serial number: %s\n", serial);
3099 jglb[
"serial_number"] = serial;
3103 pout(
"Vital Product Data (VPD) bit ignored in INQUIRY\n");
3105 pout(
"Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
3111 jglb[
"device_type"][
"scsi_terminology"] =
"Peripheral Device Type [PDT]";
3112 jglb[
"device_type"][
"scsi_value"] = peri_dt;
3118 jout(
"Device type: <%d>\n", peri_dt);
3123 if ((transport >= 0) && (transport <= 0xf)) {
3126 jglb[
"scsi_transport_protocol"][
"value"] = transport;
3136 pout(
"device is NOT READY (e.g. spun down, busy)\n");
3138 pout(
"device is NOT READY (e.g. no tape)\n");
3143 pout(
"NO tape present in drive\n");
3145 pout(
"NO MEDIUM present in device\n");
3149 pout(
"device becoming ready (wait)\n");
3165 jout(
"SMART support is: Unavailable - device lacks SMART "
3167 jglb[
"smart_support"][
"available"] =
false;
3178 jout(
"SMART support is: Available - device has SMART capability.\n"
3179 "SMART support is: %s\n", ok ?
"Enabled" :
"Disabled");
3180 jglb[
"smart_support"][
"available"] =
true;
3181 jglb[
"smart_support"][
"enabled"] = ok;
3184 jout(
"Temperature Warning: %s\n",
3185 ok ?
"Enabled" :
"Disabled or Not Supported");
3186 jglb[
"temperature_warning"][
"enabled"] = ok;
3198 pout(
"unable to fetch IEC (SMART) mode page [%s]\n",
3207 pout(
"unable to enable Exception control and warning [%s]\n",
3214 pout(
"unable to fetch IEC (SMART) mode page [%s]\n",
3220 pout(
"Informational Exceptions (SMART) %s\n",
3222 pout(
"Temperature warning %s\n",
3235 pout(
"unable to fetch IEC (SMART) mode page [%s]\n",
3244 pout(
"unable to disable Exception control and warning [%s]\n",
3251 pout(
"unable to fetch IEC (SMART) mode page [%s]\n",
3257 pout(
"Informational Exceptions (SMART) %s\n",
3259 pout(
"Temperature warning %s\n",
3274 pout(
"Current Drive Temperature: <not available>\n");
3276 jout(
"Current Drive Temperature: %d C\n", temp);
3277 jglb[
"temperature"][
"current"] = temp;
3280 pout(
"Drive Trip Temperature: <not available>\n");
3282 jout(
"Drive Trip Temperature: %d C\n", trip);
3283 jglb[
"temperature"][
"drive_trip"] = trip;
3294 unsigned char * ucp;
3296 static const char * hname =
"Environmental Reports";
3297 static const char * jname =
"scsi_environmental_reports";
3298 static const char * rh_n =
"relative humidity";
3299 static const char * temp_n =
"temperature";
3300 static const char * sop_n =
"since power on";
3301 static const char * unkn_n =
"unknown";
3317 if (! (
gBuf[0] & 0x40)) {
3320 pout(
"Another flaky device that doesn't set the SPF bit\n");
3330 int pl = ucp[3] + 4;
3334 if ((pc < 0x100) && (pl == 12)) {
3335 snprintf(pc_s,
sizeof(pc_s),
"temperature_%d", ++temp_num);
3337 int temp = (int)(int8_t)ucp[5];
3339 jglb[jname][pc_s][
"parameter_code"] = pc;
3342 if (ucp[5] == 0x80) {
3343 jout(
"%s %s = %s\n", q, temp_n, unkn_n);
3344 jglb[jname][pc_s][
s] = unkn_n;
3346 jout(
"%s %s = %d\n", q, temp_n, temp);
3347 jglb[jname][pc_s][
s] = temp;
3349 temp = (int)(int8_t)ucp[6];
3350 q =
"Lifetime maximum";
3352 if (ucp[6] == 0x80) {
3353 jout(
"%s %s = %s\n", q, temp_n, unkn_n);
3354 jglb[jname][pc_s][
s] = unkn_n;
3356 jout(
"%s %s = %d\n", q, temp_n, temp);
3357 jglb[jname][pc_s][
s] = temp;
3359 temp = (int)(int8_t)ucp[7];
3360 q =
"Lifetime minimum";
3362 if (ucp[7] == 0x80) {
3363 jout(
"%s %s = %s\n", q, temp_n, unkn_n);
3364 jglb[jname][pc_s][
s] = unkn_n;
3366 jout(
"%s %s = %d\n", q, temp_n, temp);
3367 jglb[jname][pc_s][
s] = temp;
3369 temp = (int)(int8_t)ucp[8];
3370 q =
"Maximum since power on";
3372 if (ucp[8] == 0x80) {
3373 jout(
"Maximum %s %s = %s\n", temp_n, sop_n, unkn_n);
3374 jglb[jname][pc_s][
s] = unkn_n;
3376 jout(
"Maximum %s %s = %d\n", temp_n, sop_n, temp);
3377 jglb[jname][pc_s][
s] = temp;
3379 temp = (int)(int8_t)ucp[9];
3380 q =
"Minimum since power on";
3382 if (ucp[9] == 0x80) {
3383 jout(
"Minimum %s %s = %s\n", temp_n, sop_n, unkn_n);
3384 jglb[jname][pc_s][
s] = unkn_n;
3386 jout(
"Minimum %s %s = %d\n", temp_n, sop_n, temp);
3387 jglb[jname][pc_s][
s] = temp;
3389 if ((ucp[4] & 0x3) == 1) {
3390 temp = (int)(int8_t)ucp[10];
3391 q =
"Maximum other";
3393 if (ucp[10] == 0x80) {
3394 jout(
"%s %s = %s\n", q, temp_n, unkn_n);
3395 jglb[jname][pc_s][
s] = unkn_n;
3397 jout(
"%s %s = %d\n", q, temp_n, temp);
3398 jglb[jname][pc_s][
s] = temp;
3400 temp = (int)(int8_t)ucp[11];
3401 q =
"Minimum other";
3403 if (ucp[11] == 0x80) {
3404 jout(
"%s %s = %s\n", q, temp_n, unkn_n);
3405 jglb[jname][pc_s][
s] = unkn_n;
3407 jout(
"%s %s = %d\n", q, temp_n, temp);
3408 jglb[jname][pc_s][
s] = temp;
3411 }
else if ((pc < 0x200) && (pl == 12)) {
3412 snprintf(pc_s,
sizeof(pc_s),
"relative_humidity_%d", ++humid_num);
3413 jglb[jname][pc_s][
"parameter_code"] = pc;
3414 jout(
"Relative humidity = %u\n", ucp[5]);
3415 jglb[jname][pc_s][
"current"] = ucp[5];
3416 q =
"Lifetime maximum";
3418 jout(
"%s %s = %d\n", q, rh_n, ucp[6]);
3419 jglb[jname][pc_s][
s] = ucp[6];
3420 q =
"Lifetime minimum";
3422 jout(
"%s %s = %d\n", q, rh_n, ucp[7]);
3423 jglb[jname][pc_s][
s] = ucp[7];
3424 jout(
"Maximum %s %s = %d\n", rh_n, sop_n, ucp[8]);
3425 jglb[jname][pc_s][
"maximum_since_power_on"] = ucp[8];
3426 jout(
"Minimum %s %s = %d\n", rh_n, sop_n, ucp[9]);
3427 jglb[jname][pc_s][
"minimum_since_power_on"] = ucp[9];
3428 if ((ucp[4] & 0x3) == 1) {
3429 q =
"Maximum other";
3431 jout(
"%s %s = %d\n", q, rh_n, ucp[10]);
3432 jglb[jname][pc_s][
s] = ucp[10];
3433 q =
"Minimum other";
3435 jout(
"%s %s = %d\n", q, rh_n, ucp[11]);
3436 jglb[jname][pc_s][
s] = ucp[11];
3441 if ((pc < 0x200) && (pl != 12))
3442 pout(
"%s sub-lpage unexpected parameter length [%d], skip\n",
3445 pout(
"%s sub-lpage has unexpected parameter [0x%x], skip\n",
3461 bool envRepDone =
false;
3462 uint8_t peripheral_type = 0;
3464 int res, durationSec;
3472 const char * powername =
nullptr;
3473 bool powerchg =
false;
3477 if (sense_info.
asc == 0x5E) {
3478 unsigned char powerlimit = 0xff;
3479 int powermode = sense_info.
ascq ;
3498 switch (powermode) {
3501 pout(
"CHECK POWER MODE not implemented, ignoring -n option\n");
break;
3503 powername =
"SLEEP"; powerlimit = 2;
3507 powername =
"LOW POWER"; powerlimit = 2;
break;
3509 powername =
"IDLE BY TIMER"; powerlimit = 4;
break;
3511 powername =
"STANDBY BY TIMER"; powerlimit = 2;
break;
3513 powername =
"IDLE BY COMMAND"; powerlimit = 4;
break;
3515 powername =
"STANDBY BY COMMAND"; powerlimit = 2;
break;
3517 powername =
"IDLE BY TIMER"; powerlimit = 4;
break;
3519 powername =
"IDLE_ BY COMMAND"; powerlimit = 4;
break;
3521 powername =
"IDLE_C BY TIMER"; powerlimit = 4;
break;
3523 powername =
"IDLE_C BY COMMAND"; powerlimit = 4;
break;
3525 powername =
"STANDBY_Y BY TIMER"; powerlimit = 2;
break;
3527 powername =
"STANDBY_Y BY COMMAND"; powerlimit = 2;
break;
3530 pout(
"CHECK POWER MODE returned unknown value 0x%02x, "
3531 "ignoring -n option\n", powermode);
3536 jinf(
"Device is in %s mode, exit(%d)\n", powername, options.
powerexit);
3539 powerchg = (powermode != 0xff);
3542 powername =
"ACTIVE";
3565 pout(
"%s: query_cmd_support() failed\n", __func__);
3569 short int wce = -1, rcd = -1;
3575 pout(
"Read Cache is: %s\n",
3576 res ?
"Unavailable" :
3577 rcd ?
"Disabled" :
"Enabled");
3579 pout(
"Writeback Cache is: %s\n",
3580 res ?
"Unavailable" :
3581 !wce ?
"Disabled" :
"Enabled");
3588 pout(
"Power mode %s %s\n", (powerchg?
"was:":
"is: "), powername);
3595 pout(
"=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
3611 pout(
"Enable autosave (clear GLTSD bit) failed\n");
3614 pout(
"Autosave enabled (GLTSD bit cleared).\n");
3619 if (options.
set_wce && is_disk) {
3620 short int enable = wce = (options.
set_wce > 0);
3624 pout(
"Write cache %sable failed: %s\n", (enable ?
"en" :
"dis"),
3628 pout(
"Write cache %sabled\n", (enable ?
"en" :
"dis"));
3633 if (options.
set_rcd && is_disk) {
3634 short int enable = (options.
set_rcd > 0);
3639 pout(
"Read cache %sable failed: %s\n", (enable ?
"en" :
"dis"),
3643 pout(
"Read cache %sabled\n", (enable ?
"en" :
"dis"));
3649 pout(
"Disable autosave (set GLTSD bit) failed\n");
3652 pout(
"Autosave disabled (GLTSD bit set).\n");
3664 pout(
"=== START OF READ SMART DATA SECTION ===\n");
3675 jout(
"TapeAlert Supported\n");
3676 jglb[
"tapealert"][
"supported"] =
true;
3683 jout(
"TapeAlert Not Supported\n");
3684 jglb[
"tapealert"][
"supported"] =
false;
3747 bool farm_supported =
true;
3752 jout(
"Seagate FARM log supported [try: -l farm]\n\n");
3757 pout(
"\nRead FARM log (SCSI Log page 0x3d, sub-page 0x3) failed\n\n");
3758 farm_supported =
false;
3765 jout(
"\nFARM log (SCSI Log page 0x3d, sub-page 0x3) not supported\n\n");
3767 farm_supported =
false;
3769 jglb[
"seagate_farm_log"][
"supported"] = farm_supported;
3782 pout(
"\n[GLTSD (Global Logging Target Save Disable) set. "
3783 "Enable Save with '-S on']\n");
3793 pout(
"Device does not support Self Test logging\n");
3806 pout(
"Device does not support Background scan results logging\n");
3818 pout(
"Device does not support %s logging\n",
zbds_s);
3830 pout(
"Device does not support %s logging\n",
gsap_s);
3844 pout(
"Device does not support (tape) device characteristics "
3857 pout(
"Device does not support TapeAlert logging\n");
3863 pout(
"TapeAlerts only printed if active, so none printed is good\n");
3870 pout(
"Default Self Test Successful\n");
3876 pout(
"Short Foreground Self Test Successful\n");
3882 (sense_info.
asc == 0x04 && sense_info.
ascq == 0x09)) {
3884 pout(
"Can't start self-test without aborting current test");
3886 pout(
" (%d%% remaining)",
3887 100 - sense_info.
progress * 100 / 65535);
3888 pout(
",\nadd '-t force' option to override, or run "
3889 "'smartctl -X' to abort test.\n");
3898 pout(
"Short Background Self Test has begun\n");
3899 pout(
"Use smartctl -X to abort test\n");
3905 pout(
"Extended Background Self Test has begun\n");
3908 time_t t = time(
nullptr);
3911 pout(
"Please wait %d minutes for test to complete.\n",
3915 pout(
"Estimated completion time: %s\n", comptime);
3917 pout(
"Use smartctl -X to abort test\n");
3923 pout(
"Extended Foreground Self Test Successful\n");
3928 pout(
"Self Test returned without error\n");
3947 pout(
"SCSI SSU(ACTIVE) command failed: %s\n",
3951 pout(
"Device placed in ACTIVE mode\n");
3953 pout(
"SCSI SSU(STANDBY) with timeout not supported yet\n");
3960 pout(
"Device placed in STANDBY mode\n");
3963 if (!any_output && powername)
3964 pout(
"Device is in %s mode\n", powername);
3967 pout(
"SCSI device successfully opened\n\nUse 'smartctl -a' (or '-x') "
3968 "to print SMART (and more) information\n\n");
bool dont_print_serial_number
Reference to a JSON element.
static std::string str2key(const char *str)
Replace space and non-alphanumerics with '_', upper to lower case.
bool is_spc4_or_higher() const
bool checked_cmd_support() const
enum scsi_cmd_support cmd_support_level(uint8_t opcode, bool sa_valid, uint16_t sa, bool for_lsense_spc=false) const
const char * get_req_type() const
Get type requested by user, empty if none.
const char * get_errmsg() const
Get last error message.
virtual bool is_syscall_unsup() const
Return true if last error indicates an unsupported system call.
bool is_supported(int vpd_page_num) const
bool scsiReadFarmLog(scsi_device *device, scsiFarmLog &farmLog)
bool scsiIsSeagate(char *scsi_vendor)
void scsiPrintFarmLog(const scsiFarmLog &farmLog)
unsigned char failuretest_permissive
int scsiSetPowerCondition(scsi_device *device, int power_cond, int pcond_modifier)
int scsiReadDefect12(scsi_device *device, int req_plist, int req_glist, int dl_format, int addrDescIndex, uint8_t *pBuf, int bufLen)
int scsiFetchExtendedSelfTestTime(scsi_device *device, int *durationSec, int modese_len)
void scsiDecodeErrCounterPage(unsigned char *resp, struct scsiErrorCounter *ecp, int allocLen)
int scsiSetExceptionControlAndWarning(scsi_device *device, int enabled, const struct scsi_iec_mode_page *iecp)
int scsiSmartExtendCapSelfTest(scsi_device *device)
int scsiFetchIECmpage(scsi_device *device, struct scsi_iec_mode_page *iecp, int modese_len)
int scsiGetTemp(scsi_device *device, uint8_t *currenttemp, uint8_t *triptemp)
int scsiSmartShortCapSelfTest(scsi_device *device)
int scsiSmartSelfTestAbort(scsi_device *device)
char * scsi_get_sense_key_str(int sense_key, int buff_len, char *buff)
const char * scsiTapeAlertsTapeDevice(unsigned short code)
int scsiFetchTransportProtocol(scsi_device *device, int modese_len)
int scsi_decode_lu_dev_id(const unsigned char *b, int blen, char *s, int slen, int *transport)
int scsiTestUnitReady(scsi_device *device)
int scsiInquiryVpd(scsi_device *device, int vpd_page, uint8_t *pBuf, int bufLen)
int scsiSmartExtendSelfTest(scsi_device *device)
void scsiDecodeNonMediumErrPage(unsigned char *resp, struct scsiNonMediumError *nmep, int allocLen)
int scsiRequestSense(scsi_device *device, struct scsi_sense_disect *sense_info)
int scsiCheckIE(scsi_device *device, int hasIELogPage, int hasTempLogPage, uint8_t *asc, uint8_t *ascq, uint8_t *currenttemp, uint8_t *triptemp)
uint64_t scsiGetSize(scsi_device *device, bool avoid_rcap16, struct scsi_readcap_resp *srrp)
char * scsiGetIEString(uint8_t asc, uint8_t ascq, char *b, int blen)
int scsiGetSetCache(scsi_device *device, int modese_len, short int *wcep, short int *rcdp)
supported_vpd_pages * supported_vpd_pages_p
int scsiGetRPM(scsi_device *device, int modese_len, int *form_factorp, int *haw_zbcp)
void scsi_format_id_string(char *out, const uint8_t *in, int n)
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
int scsiSmartDefaultSelfTest(scsi_device *device)
void dStrHex(const uint8_t *up, int len, int no_ascii)
const char * scsiErrString(int scsiErr)
const char * scsiTapeAlertsChangerDevice(unsigned short code)
int scsiFetchControlGLTSD(scsi_device *device, int modese_len, int current)
int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
int scsiSetControlGLTSD(scsi_device *device, int enabled, int modese_len)
int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
int scsiSmartShortSelfTest(scsi_device *device)
int scsiLogSense(scsi_device *device, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen, int known_resp_len)
unsigned char scsi_debugmode
int scsiLogSelect(scsi_device *device, int pcr, int sp, int pc, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen)
int scsiReadDefect10(scsi_device *device, int req_plist, int req_glist, int dl_format, uint8_t *pBuf, int bufLen)
#define ENVIRO_LIMITS_L_SPAGE
#define SIMPLE_ERR_BECOMING_READY
#define SIMPLE_ERR_NOT_READY
#define LAST_N_ERROR_EVENTS_LPAGE
#define SCSI_VPD_DEVICE_IDENTIFICATION
#define PEND_DEFECTS_L_SPAGE
#define LPS_MISALIGN_L_SPAGE
#define SEAGATE_FARM_LPAGE
#define SCSI_VPD_LOGICAL_BLOCK_PROVISIONING
#define SCSI_VPD_ZONED_BLOCK_DEV_CHAR
#define TAPE_ALERTS_LPAGE
#define SIMPLE_ERR_NO_MEDIUM
#define SELFTEST_RESULTS_LPAGE
#define SCSI_POW_COND_ACTIVE
#define SCSI_POW_COND_STANDBY
#define VERIFY_ERROR_COUNTER_LPAGE
#define SCSI_PT_MEDIUM_CHANGER
#define NON_MEDIUM_ERROR_LPAGE
#define SCSI_VPD_UNIT_SERIAL_NUMBER
#define UTILIZATION_L_SPAGE
#define SCSI_PT_SEQUENTIAL_ACCESS
#define ENVIRO_REP_L_SPAGE
#define NO_SUBPAGE_L_SPAGE
#define SCSI_PT_HOST_MANAGED
#define ZB_DEV_STATS_L_SPAGE
#define FORMAT_STATUS_LPAGE
#define SUPP_SPAGE_L_SPAGE
#define LOG_RESP_SELF_TEST_LEN
#define BACKGROUND_RESULTS_LPAGE
#define PROTOCOL_SPECIFIC_LPAGE
#define TEMPERATURE_LPAGE
#define WRITE_ERROR_COUNTER_LPAGE
#define SIMPLE_ERR_BAD_RESP
#define SCSI_PT_DIRECT_ACCESS
#define READ_ERROR_COUNTER_LPAGE
#define SEAGATE_FACTORY_LPAGE
#define BACKGROUND_OP_L_SPAGE
#define SEAGATE_FARM_CURRENT_L_SPAGE
#define GEN_STATS_PERF_LPAGE
#define DEVICE_STATS_LPAGE
#define STARTSTOP_CYCLE_COUNTER_LPAGE
#define SEAGATE_CACHE_LPAGE
static bool gFormatStatusLPage
static bool gSeagateFactoryLPage
static bool gEnviroLimitsLPage
static void scsiPrintTemp(scsi_device *device)
static int scsiPrintActiveTapeAlerts(scsi_device *device, int peripheral_type, bool from_health)
static void scsiPrintSeagateCacheLPage(scsi_device *device)
static void scsiGetSupportedLogPages(scsi_device *device)
static void show_sas_phy_event_info(const json::ref &jref, int peis, unsigned int val, unsigned thresh_val)
static std::string rtrim(const std::string &s, const char *t=" \t\n\r\f\v")
static int scsiGetDriveInfo(scsi_device *device, uint8_t *peripheral_type, bool &have_zbc, bool all)
static bool gBackgroundResultsLPage
#define T10_VENDOR_HITACHI_2
static bool gPendDefectsLPage
static int scsiPrintBackgroundResults(scsi_device *device, bool only_pow_time)
const char * scsiprint_c_cvsid
static const char * bms_status[]
static const char * zbds_s
#define SCSI_VERSION_HIGHEST
#define T10_VENDOR_HITACHI_3
static int scsiPrintSelfTest(scsi_device *device)
static bool gLPSMisalignLPage
#define LOG_RESP_TAPE_ALERT_LEN
static char scsi_vendor[8+1]
#define T10_VENDOR_SEAGATE
static const char * self_test_result[]
#define LOG_RESP_LONG_LEN
static bool gSSMediaLPage
static const char * reassign_status[]
static int scsiPrintFormatStatus(scsi_device *device)
static bool gTapeDeviceStatsLPage
static bool gGenStatsAndPerfLPage
static int show_protocol_specific_port_page(unsigned char *resp, int len)
static bool gStartStopLPage
static void scsiPrintErrorCounterLog(scsi_device *device)
static const char * logSenRspStr
static void scsiPrintPendingDefectsLPage(scsi_device *device)
static bool gUtilizationLPage
static bool gSeagateCacheLPage
static bool gTapeAlertsLPage
static int scsiPrintGStatsPerf(scsi_device *device)
static bool gSelfTestLPage
static void scsiPrintGrownDefectListLen(scsi_device *device, bool prefer12)
static bool gSeagateFarmLPage
static uint64_t variableLengthIntegerParam(const unsigned char *ucp)
static int scsiGetSmartData(scsi_device *device, bool attribs)
static const char * peripheral_dt_arr[32]
static bool gZBDeviceStatsLPage
static void show_sas_port_param(int port_num, unsigned char *ucp, int param_len)
static int scsiSmartEnable(scsi_device *device)
static bool gReadECounterLPage
static const char * transport_proto_arr[]
static void scsiPrintSeagateFactoryLPage(scsi_device *device)
static bool gEnviroReportingLPage
#define SCSI_VERSION_SPC_4
static const char *const severities
static void scsiPrintEnviroReporting(scsi_device *device)
#define T10_VENDOR_HITACHI_1
static int scsiPrintTapeDeviceStats(scsi_device *device)
static bool gProtocolSpecificLPage
#define SCSI_SUPP_LOG_PAGES_MAX_COUNT
static const char * logSenStr
static const char * ssm_s
static bool gBackgroundOpLPage
static const char * gsap_s
static int scsiPrintSSMedia(scsi_device *device)
static int scsiPrintSasPhy(scsi_device *device, int reset)
static bool gVerifyECounterLPage
static int64_t scsiGetTimeUnitInNano(const uint8_t *ucp, int num, uint16_t ti_pc)
static const char * self_test_code[]
static bool gNonMediumELPage
static int scsiSmartDisable(scsi_device *device)
static bool all_ffs(const uint8_t *bp, int b_len)
static void scsiGetStartStopData(scsi_device *device)
static bool gLastNErrorEvLPage
static bool gWriteECounterLPage
int scsiPrintMain(scsi_device *device, const scsi_print_options &options)
static bool seagate_or_hitachi(void)
static void scsiPrintTimeUnitInNano(int leadin_spaces, uint64_t intervals, int64_t timeUnitInNS)
static int scsiPrintZBDeviceStats(scsi_device *device)
#define SCSIPRINT_H_CVSID
static uint64_t sg_get_unaligned_be64(const void *p)
static uint64_t sg_get_unaligned_be(int num_bytes, const void *p)
static uint16_t sg_get_unaligned_be16(const void *p)
static uint32_t sg_get_unaligned_be32(const void *p)
void jout_startup_datetime(const char *prefix)
void failuretest(failure_type type, int returnvalue)
void void jinf(const char *fmt,...) __attribute_format_printf(1
void jout(const char *fmt,...) __attribute_format_printf(1
void pout(const char *fmt,...)
bool smart_background_log
bool smart_selftest_abort
bool smart_auto_save_disable
bool smart_selftest_force
bool smart_default_selftest
bool smart_short_cap_selftest
bool smart_short_selftest
bool smart_extend_cap_selftest
bool smart_extend_selftest
bool smart_auto_save_enable
bool scsi_pending_defects
bool general_stats_and_perf
void dateandtimezoneepoch(char(&buffer)[DATEANDEPOCHLEN], time_t tval)
const char * format_capacity(char *str, int strsize, uint64_t val, const char *decimal_point)
const char * format_with_thousands_sep(char *str, int strsize, uint64_t val, const char *thousands_sep)
std::string strprintf(const char *fmt,...)