4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2002-11 Bruce Allen
7 * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
8 * Copyright (C) 2003-15 Douglas Gilbert <dgilbert@interlog.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
15 * You should have received a copy of the GNU General Public License
16 * (for example COPYING); if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * This code was originally developed as a Senior Thesis by Michael Cornwell
20 * at the Concurrent Systems Laboratory (now part of the Storage Systems
21 * Research Center), Jack Baskin School of Engineering, University of
22 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
35 #include "atacmds.h" // smart_command_set
36 #include "dev_interface.h"
37 #include "scsiprint.h"
41 #define GBUF_SIZE 65535
44 const char * scsiprint_c_cvsid
= "$Id: scsiprint.cpp 4292 2016-04-12 23:06:59Z dpgilbert $"
46 const char * scsiprint_c_cvsid
= "$Id: scsiprint.cpp 4040 2015-03-10 22:30:44Z dpgilbert $"
47 >>>>>>> 3d8ad6fa4529eb02ae1391a1e937bf57aad3fb74
51 UINT8 gBuf
[GBUF_SIZE
];
52 #define LOG_RESP_LEN 252
53 #define LOG_RESP_LONG_LEN ((62 * 256) + 252)
54 #define LOG_RESP_TAPE_ALERT_LEN 0x144
56 /* Log pages supported */
57 static int gSmartLPage
= 0; /* Informational Exceptions log page */
58 static int gTempLPage
= 0;
59 static int gSelfTestLPage
= 0;
60 static int gStartStopLPage
= 0;
61 static int gReadECounterLPage
= 0;
62 static int gWriteECounterLPage
= 0;
63 static int gVerifyECounterLPage
= 0;
64 static int gNonMediumELPage
= 0;
65 static int gLastNErrorLPage
= 0;
66 static int gBackgroundResultsLPage
= 0;
67 static int gProtocolSpecificLPage
= 0;
68 static int gTapeAlertsLPage
= 0;
69 static int gSSMediaLPage
= 0;
71 /* Vendor specific log pages */
72 static int gSeagateCacheLPage
= 0;
73 static int gSeagateFactoryLPage
= 0;
75 /* Mode pages supported */
76 static int gIecMPage
= 1; /* N.B. assume it until we know otherwise */
78 /* Remember last successful mode sense/select command */
79 static int modese_len
= 0;
83 scsiGetSupportedLogPages(scsi_device
* device
)
87 if ((err
= scsiLogSense(device
, SUPPORTED_LPAGES
, 0, gBuf
,
89 if (scsi_debugmode
> 0)
90 pout("Log Sense for supported pages failed [%s]\n",
92 /* try one more time with defined length, workaround for the bug #678
93 found with ST8000NM0075/E001 */
94 err
= scsiLogSense(device
, SUPPORTED_LPAGES
, 0, gBuf
,
95 LOG_RESP_LEN
, 68); /* 64 max pages + 4b header */
96 if (scsi_debugmode
> 0)
97 pout("Log Sense for supported pages failed (second attempt) [%s]\n",
103 for (i
= 4; i
< gBuf
[3] + LOGPAGEHDRSIZE
; i
++) {
106 case READ_ERROR_COUNTER_LPAGE
:
107 gReadECounterLPage
= 1;
109 case WRITE_ERROR_COUNTER_LPAGE
:
110 gWriteECounterLPage
= 1;
112 case VERIFY_ERROR_COUNTER_LPAGE
:
113 gVerifyECounterLPage
= 1;
115 case LAST_N_ERROR_LPAGE
:
116 gLastNErrorLPage
= 1;
118 case NON_MEDIUM_ERROR_LPAGE
:
119 gNonMediumELPage
= 1;
121 case TEMPERATURE_LPAGE
:
124 case STARTSTOP_CYCLE_COUNTER_LPAGE
:
127 case SELFTEST_RESULTS_LPAGE
:
133 case BACKGROUND_RESULTS_LPAGE
:
134 gBackgroundResultsLPage
= 1;
136 case PROTOCOL_SPECIFIC_LPAGE
:
137 gProtocolSpecificLPage
= 1;
139 case TAPE_ALERTS_LPAGE
:
140 gTapeAlertsLPage
= 1;
145 case SEAGATE_CACHE_LPAGE
:
146 gSeagateCacheLPage
= 1;
148 case SEAGATE_FACTORY_LPAGE
:
149 gSeagateFactoryLPage
= 1;
157 /* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad
158 (or at least something to report). */
160 scsiGetSmartData(scsi_device
* device
, bool attribs
)
164 UINT8 currenttemp
= 255;
165 UINT8 triptemp
= 255;
169 if (scsiCheckIE(device
, gSmartLPage
, gTempLPage
, &asc
, &ascq
,
170 ¤ttemp
, &triptemp
)) {
171 /* error message already announced */
176 cp
= scsiGetIEString(asc
, ascq
);
180 pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp
, asc
, ascq
);
182 } else if (gIecMPage
)
183 pout("SMART Health Status: OK\n");
185 if (attribs
&& !gTempLPage
) {
186 if (255 == currenttemp
)
187 pout("Current Drive Temperature: <not available>\n");
189 pout("Current Drive Temperature: %d C\n", currenttemp
);
191 pout("Drive Trip Temperature: <not available>\n");
193 pout("Drive Trip Temperature: %d C\n", triptemp
);
200 // Returns number of logged errors or zero if none or -1 if fetching
202 static const char * const severities
= "CWI";
205 scsiGetTapeAlertsData(scsi_device
* device
, int peripheral_type
)
207 unsigned short pagelength
;
208 unsigned short parametercode
;
215 if ((err
= scsiLogSense(device
, TAPE_ALERTS_LPAGE
, 0, gBuf
,
216 LOG_RESP_TAPE_ALERT_LEN
, LOG_RESP_TAPE_ALERT_LEN
))) {
217 pout("%s Failed [%s]\n", __func__
, scsiErrString(err
));
221 if (gBuf
[0] != 0x2e) {
222 pout("TapeAlerts Log Sense Failed\n");
226 pagelength
= (unsigned short) gBuf
[2] << 8 | gBuf
[3];
228 for (s
=severities
; *s
; s
++) {
229 for (i
= 4; i
< pagelength
; i
+= 5) {
230 parametercode
= (unsigned short) gBuf
[i
] << 8 | gBuf
[i
+1];
233 ts
= SCSI_PT_MEDIUM_CHANGER
== peripheral_type
?
234 scsiTapeAlertsChangerDevice(parametercode
) :
235 scsiTapeAlertsTapeDevice(parametercode
);
238 pout("TapeAlert Errors (C=Critical, W=Warning, "
239 "I=Informational):\n");
240 pout("[0x%02x] %s\n", parametercode
, ts
);
249 pout("TapeAlert: OK\n");
255 scsiGetStartStopData(scsi_device
* device
)
257 int err
, len
, k
, extra
;
260 if ((err
= scsiLogSense(device
, STARTSTOP_CYCLE_COUNTER_LPAGE
, 0, gBuf
,
263 pout("%s Failed [%s]\n", __func__
, scsiErrString(err
));
267 if ((gBuf
[0] & 0x3f) != STARTSTOP_CYCLE_COUNTER_LPAGE
) {
269 pout("StartStop Log Sense Failed, page mismatch\n");
273 len
= ((gBuf
[2] << 8) | gBuf
[3]);
275 for (k
= len
; k
> 0; k
-= extra
, ucp
+= extra
) {
278 pout("StartStop Log Sense Failed: short\n");
283 int pc
= (ucp
[0] << 8) + ucp
[1];
288 pout("Manufactured in week %.2s of year %.4s\n", ucp
+ 8,
292 /* ignore Accounting date */
296 u
= (ucp
[4] << 24) | (ucp
[5] << 16) | (ucp
[6] << 8) | ucp
[7];
298 pout("Specified cycle count over device lifetime: %u\n",
304 u
= (ucp
[4] << 24) | (ucp
[5] << 16) | (ucp
[6] << 8) | ucp
[7];
306 pout("Accumulated start-stop cycles: %u\n", u
);
311 u
= (ucp
[4] << 24) | (ucp
[5] << 16) | (ucp
[6] << 8) | ucp
[7];
313 pout("Specified load-unload count over device "
314 "lifetime: %u\n", u
);
319 u
= (ucp
[4] << 24) | (ucp
[5] << 16) | (ucp
[6] << 8) | ucp
[7];
321 pout("Accumulated load-unload cycles: %u\n", u
);
332 scsiPrintGrownDefectListLen(scsi_device
* device
)
334 int err
, dl_format
, got_rd12
;
335 unsigned int dl_len
, div
;
338 if ((err
= scsiReadDefect12(device
, 0 /* req_plist */, 1 /* req_glist */,
339 4 /* format: bytes from index */,
340 0 /* addr desc index */, gBuf
, 8))) {
341 if (2 == err
) { /* command not supported */
342 if ((err
= scsiReadDefect10(device
, 0 /* req_plist */, 1 /* req_glist */,
343 4 /* format: bytes from index */, gBuf
, 4))) {
344 if (scsi_debugmode
> 0) {
346 pout("Read defect list (10) Failed: %s\n", scsiErrString(err
));
352 } else if (101 == err
) /* Defect list not found, leave quietly */
355 if (scsi_debugmode
> 0) {
357 pout("Read defect list (12) Failed: %s\n", scsiErrString(err
));
366 int generation
= (gBuf
[2] << 8) + gBuf
[3];
367 if ((generation
> 1) && (scsi_debugmode
> 0)) {
369 pout("Read defect list (12): generation=%d\n", generation
);
372 dl_len
= (gBuf
[4] << 24) + (gBuf
[5] << 16) + (gBuf
[6] << 8) + gBuf
[7];
374 dl_len
= (gBuf
[2] << 8) + gBuf
[3];
376 if (0x8 != (gBuf
[1] & 0x18)) {
378 pout("Read defect list: asked for grown list but didn't get it\n");
383 dl_format
= (gBuf
[1] & 0x7);
385 case 0: /* short block */
388 case 1: /* extended bytes from index */
389 case 2: /* extended physical sector */
390 /* extended = 1; # might use in future */
393 case 3: /* long block */
394 case 4: /* bytes from index */
395 case 5: /* physical sector */
400 pout("defect list format %d unknown\n", dl_format
);
405 pout("Elements in grown defect list: 0\n\n");
408 pout("Grown defect list length=%u bytes [unknown "
409 "number of elements]\n\n", dl_len
);
411 pout("Elements in grown defect list: %u\n\n", dl_len
/ div
);
416 scsiPrintSeagateCacheLPage(scsi_device
* device
)
418 int num
, pl
, pc
, err
, len
;
422 if ((err
= scsiLogSense(device
, SEAGATE_CACHE_LPAGE
, 0, gBuf
,
425 pout("Seagate Cache Log Sense Failed: %s\n", scsiErrString(err
));
429 if ((gBuf
[0] & 0x3f) != SEAGATE_CACHE_LPAGE
) {
431 pout("Seagate Cache Log Sense Failed, page mismatch\n");
435 len
= ((gBuf
[2] << 8) | gBuf
[3]) + 4;
439 pc
= (ucp
[0] << 8) | ucp
[1];
442 case 0: case 1: case 2: case 3: case 4:
445 if (scsi_debugmode
> 0) {
447 pout("Vendor (Seagate) cache lpage has unexpected parameter"
456 pout("Vendor (Seagate) cache information\n");
460 pc
= (ucp
[0] << 8) | ucp
[1];
463 case 0: pout(" Blocks sent to initiator"); break;
464 case 1: pout(" Blocks received from initiator"); break;
465 case 2: pout(" Blocks read from cache and sent to initiator"); break;
466 case 3: pout(" Number of read and write commands whose size "
467 "<= segment size"); break;
468 case 4: pout(" Number of read and write commands whose size "
469 "> segment size"); break;
470 default: pout(" Unknown Seagate parameter code [0x%x]", pc
); break;
473 unsigned char * xp
= ucp
+ 4;
474 if (k
> (int)sizeof(ull
)) {
475 xp
+= (k
- (int)sizeof(ull
));
476 k
= (int)sizeof(ull
);
479 for (int j
= 0; j
< k
; ++j
) {
484 pout(" = %" PRIu64
"\n", ull
);
492 scsiPrintSeagateFactoryLPage(scsi_device
* device
)
494 int num
, pl
, pc
, len
, err
, good
, bad
;
498 if ((err
= scsiLogSense(device
, SEAGATE_FACTORY_LPAGE
, 0, gBuf
,
501 pout("%s Failed [%s]\n", __func__
, scsiErrString(err
));
505 if ((gBuf
[0] & 0x3f) != SEAGATE_FACTORY_LPAGE
) {
507 pout("Seagate/Hitachi Factory Log Sense Failed, page mismatch\n");
511 len
= ((gBuf
[2] << 8) | gBuf
[3]) + 4;
517 pc
= (ucp
[0] << 8) | ucp
[1];
530 if ((good
< 2) || (bad
> 4)) { /* heuristic */
531 if (scsi_debugmode
> 0) {
533 pout("\nVendor (Seagate/Hitachi) factory lpage has too many "
534 "unexpected parameters, skip\n");
539 pout("Vendor (Seagate/Hitachi) factory information\n");
543 pc
= (ucp
[0] << 8) | ucp
[1];
547 case 0: pout(" number of hours powered up");
550 case 8: pout(" number of minutes until next internal SMART test");
554 if (scsi_debugmode
> 0) {
556 pout("Vendor (Seagate/Hitachi) factory lpage: "
557 "unknown parameter code [0x%x]\n", pc
);
564 unsigned char * xp
= ucp
+ 4;
565 if (k
> (int)sizeof(ull
)) {
566 xp
+= (k
- (int)sizeof(ull
));
567 k
= (int)sizeof(ull
);
570 for (int j
= 0; j
< k
; ++j
) {
576 pout(" = %.2f\n", ull
/ 60.0 );
578 pout(" = %" PRIu64
"\n", ull
);
587 scsiPrintErrorCounterLog(scsi_device
* device
)
589 struct scsiErrorCounter errCounterArr
[3];
590 struct scsiErrorCounter
* ecp
;
591 int found
[3] = {0, 0, 0};
593 if (gReadECounterLPage
&& (0 == scsiLogSense(device
,
594 READ_ERROR_COUNTER_LPAGE
, 0, gBuf
, LOG_RESP_LEN
, 0))) {
595 scsiDecodeErrCounterPage(gBuf
, &errCounterArr
[0]);
598 if (gWriteECounterLPage
&& (0 == scsiLogSense(device
,
599 WRITE_ERROR_COUNTER_LPAGE
, 0, gBuf
, LOG_RESP_LEN
, 0))) {
600 scsiDecodeErrCounterPage(gBuf
, &errCounterArr
[1]);
603 if (gVerifyECounterLPage
&& (0 == scsiLogSense(device
,
604 VERIFY_ERROR_COUNTER_LPAGE
, 0, gBuf
, LOG_RESP_LEN
, 0))) {
605 scsiDecodeErrCounterPage(gBuf
, &errCounterArr
[2]);
606 ecp
= &errCounterArr
[2];
607 for (int k
= 0; k
< 7; ++k
) {
608 if (ecp
->gotPC
[k
] && ecp
->counter
[k
]) {
614 if (found
[0] || found
[1] || found
[2]) {
615 pout("Error counter log:\n");
616 pout(" Errors Corrected by Total "
617 "Correction Gigabytes Total\n");
618 pout(" ECC rereads/ errors "
619 "algorithm processed uncorrected\n");
620 pout(" fast | delayed rewrites corrected "
621 "invocations [10^9 bytes] errors\n");
622 for (int k
= 0; k
< 3; ++k
) {
625 ecp
= &errCounterArr
[k
];
626 static const char * const pageNames
[3] = {"read: ", "write: ", "verify: "};
627 pout("%s%8" PRIu64
" %8" PRIu64
" %8" PRIu64
" %8" PRIu64
" %8" PRIu64
,
628 pageNames
[k
], ecp
->counter
[0], ecp
->counter
[1],
629 ecp
->counter
[2], ecp
->counter
[3], ecp
->counter
[4]);
630 double processed_gb
= ecp
->counter
[5] / 1000000000.0;
631 pout(" %12.3f %8" PRIu64
"\n", processed_gb
, ecp
->counter
[6]);
635 pout("Error Counter logging not supported\n");
636 if (gNonMediumELPage
&& (0 == scsiLogSense(device
,
637 NON_MEDIUM_ERROR_LPAGE
, 0, gBuf
, LOG_RESP_LEN
, 0))) {
638 struct scsiNonMediumError nme
;
639 scsiDecodeNonMediumErrPage(gBuf
, &nme
);
641 pout("\nNon-medium error count: %8" PRIu64
"\n", nme
.counterPC0
);
643 pout("Track following error count [Hitachi]: %8" PRIu64
"\n",
646 pout("Positioning error count [Hitachi]: %8" PRIu64
"\n",
649 if (gLastNErrorLPage
&& (0 == scsiLogSense(device
,
650 LAST_N_ERROR_LPAGE
, 0, gBuf
, LOG_RESP_LONG_LEN
, 0))) {
651 int num
= (gBuf
[2] << 8) + gBuf
[3] + 4;
652 int truncated
= (num
> LOG_RESP_LONG_LEN
) ? num
: 0;
654 num
= LOG_RESP_LONG_LEN
;
655 unsigned char * ucp
= gBuf
+ 4;
658 pout("\nNo error events logged\n");
660 pout("\nLast n error events log page\n");
661 for (int k
= num
, pl
; k
> 0; k
-= pl
, ucp
+= pl
) {
663 pout(" <<short Last n error events log page>>\n");
667 int pc
= (ucp
[0] << 8) + ucp
[1];
669 if ((ucp
[2] & 0x1) && (ucp
[2] & 0x2)) {
670 pout(" Error event %d:\n", pc
);
671 pout(" [binary]:\n");
672 dStrHex((const char *)ucp
+ 4, pl
- 4, 1);
673 } else if (ucp
[2] & 0x1) {
674 pout(" Error event %d:\n", pc
);
675 pout(" %.*s\n", pl
- 4, (const char *)(ucp
+ 4));
677 if (scsi_debugmode
> 0) {
678 pout(" Error event %d:\n", pc
);
679 pout(" [data counter??]:\n");
680 dStrHex((const char *)ucp
+ 4, pl
- 4, 1);
686 pout(" >>>> log truncated, fetched %d of %d available "
687 "bytes\n", LOG_RESP_LONG_LEN
, truncated
);
693 static const char * self_test_code
[] = {
704 static const char * self_test_result
[] = {
706 "Aborted (by user command)",
707 "Aborted (device reset ?) ",
708 "Unknown error, incomplete",
709 "Completed, segment failed",
710 "Failed in first segment ",
711 "Failed in second segment ",
712 "Failed in segment --> ",
720 "Self test in progress ..."
723 // See SCSI Primary Commands - 3 (SPC-3) rev 23 (draft) section 7.2.10 .
724 // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent
725 // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or
726 // FAILSMART is returned.
728 scsiPrintSelfTest(scsi_device
* device
)
730 int num
, k
, err
, durationSec
;
735 struct scsi_sense_disect sense_info
;
737 // check if test is running
738 if (!scsiRequestSense(device
, &sense_info
) &&
739 (sense_info
.asc
== 0x04 && sense_info
.ascq
== 0x09 &&
740 sense_info
.progress
!= -1)) {
741 pout("Self-test execution status:\t\t%d%% of test remaining\n",
742 100 - ((sense_info
.progress
* 100) / 65535));
745 if ((err
= scsiLogSense(device
, SELFTEST_RESULTS_LPAGE
, 0, gBuf
,
746 LOG_RESP_SELF_TEST_LEN
, 0))) {
748 pout("%s: Failed [%s]\n", __func__
, scsiErrString(err
));
752 if ((gBuf
[0] & 0x3f) != SELFTEST_RESULTS_LPAGE
) {
754 pout("Self-test Log Sense Failed, page mismatch\n");
758 // compute page length
759 num
= (gBuf
[2] << 8) + gBuf
[3];
760 // Log sense page length 0x190 bytes
763 pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n",num
);
767 // loop through the twenty possible entries
768 for (k
= 0, ucp
= gBuf
+ 4; k
< 20; ++k
, ucp
+= 20 ) {
771 // timestamp in power-on hours (or zero if test in progress)
772 int n
= (ucp
[6] << 8) | ucp
[7];
774 // The spec says "all 20 bytes will be zero if no test" but
775 // DG has found otherwise. So this is a heuristic.
776 if ((0 == n
) && (0 == ucp
[4]))
779 // only print header if needed
781 pout("SMART Self-test log\n");
782 pout("Num Test Status segment "
783 "LifeTime LBA_first_err [SK ASC ASQ]\n");
784 pout(" Description number "
789 // print parameter code (test number) & self-test code text
790 pout("#%2d %s", (ucp
[0] << 8) | ucp
[1],
791 self_test_code
[(ucp
[4] >> 5) & 0x7]);
793 // check the self-test result nibble, using the self-test results
794 // field table from T10/1416-D (SPC-3) Rev. 23, section 7.2.10:
796 switch ((res
= ucp
[4] & 0xf)) {
798 // an unknown error occurred while the device server
799 // was processing the self-test and the device server
800 // was unable to complete the self-test
804 // the self-test completed with a failure in a test
805 // segment, and the test segment that failed is not
810 // the first segment of the self-test failed
814 // the second segment of the self-test failed
818 // another segment of the self-test failed and which
819 // test is indicated by the contents of the SELF-TEST
826 pout(" %s", self_test_result
[res
]);
828 // self-test number identifies test that failed and consists
829 // of either the number of the segment that failed during
830 // the test, or the number of the test that failed and the
831 // number of the segment in which the test was run, using a
832 // vendor-specific method of putting both numbers into a
835 pout(" %3d", (int)ucp
[5]);
839 // print time that the self-test was completed
840 if (n
==0 && res
==0xf)
841 // self-test in progress
846 // construct 8-byte integer address of first failure
847 for (i
= 0; i
< 8; i
++) {
851 // print Address of First Failure, if sensible
852 if ((~(uint64_t)0 != ull
) && (res
> 0) && (res
< 0xf)) {
855 // was hex but change to decimal to conform with ATA
856 snprintf(buff
, sizeof(buff
), "%" PRIu64
, ull
);
857 // snprintf(buff, sizeof(buff), "0x%" PRIx64, ull);
862 // if sense key nonzero, then print it, along with
863 // additional sense code and additional sense code qualifier
865 pout(" [0x%x 0x%x 0x%x]\n", ucp
[16] & 0xf, ucp
[17], ucp
[18]);
870 // if header never printed, then there was no output
872 pout("No self-tests have been logged\n");
874 if ((0 == scsiFetchExtendedSelfTestTime(device
, &durationSec
,
875 modese_len
)) && (durationSec
> 0)) {
876 pout("\nLong (extended) Self Test duration: %d seconds "
877 "[%.1f minutes]\n", durationSec
, durationSec
/ 60.0);
883 static const char * bms_status
[] = {
886 "pre-scan is active",
887 "halted due to fatal error",
888 "halted due to a vendor specific pattern of error",
889 "halted due to medium formatted without P-List",
890 "halted - vendor specific cause",
891 "halted due to temperature out of range",
892 "waiting until BMS interval timer expires", /* 8 */
895 static const char * reassign_status
[] = {
897 "Require Write or Reassign Blocks command",
898 "Successfully reassigned",
900 "Reassignment by disk failed",
901 "Recovered via rewrite in-place",
902 "Reassigned by app, has valid data",
903 "Reassigned by app, has no valid data",
904 "Unsuccessfully reassigned by app", /* 8 */
907 // See SCSI Block Commands - 3 (SBC-3) rev 6 (draft) section 6.2.2 .
908 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
909 // and up to 2048 events (although would hope to have less). May set
910 // FAILLOG if serious errors detected (in the future).
912 scsiPrintBackgroundResults(scsi_device
* device
)
914 int num
, j
, m
, err
, truncated
;
920 if ((err
= scsiLogSense(device
, BACKGROUND_RESULTS_LPAGE
, 0, gBuf
,
921 LOG_RESP_LONG_LEN
, 0))) {
923 pout("%s Failed [%s]\n", __func__
, scsiErrString(err
));
927 if ((gBuf
[0] & 0x3f) != BACKGROUND_RESULTS_LPAGE
) {
929 pout("Background scan results Log Sense Failed, page mismatch\n");
933 // compute page length
934 num
= (gBuf
[2] << 8) + gBuf
[3] + 4;
937 pout("Background scan results Log Sense length is %d, no scan "
942 truncated
= (num
> LOG_RESP_LONG_LEN
) ? num
: 0;
944 num
= LOG_RESP_LONG_LEN
;
948 int pc
= (ucp
[0] << 8) | ucp
[1];
955 pout("Background scan results log\n");
958 if ((pl
< 16) || (num
< 16)) {
963 if (j
< (int)(sizeof(bms_status
) / sizeof(bms_status
[0])))
964 pout("%s\n", bms_status
[j
]);
966 pout("unknown [0x%x] background scan status value\n", j
);
967 j
= (ucp
[4] << 24) + (ucp
[5] << 16) + (ucp
[6] << 8) + ucp
[7];
968 pout(" Accumulated power on time, hours:minutes %d:%02d "
969 "[%d minutes]\n", (j
/ 60), (j
% 60), j
);
970 pout(" Number of background scans performed: %d, ",
971 (ucp
[10] << 8) + ucp
[11]);
972 pout("scan progress: %.2f%%\n",
973 (double)((ucp
[12] << 8) + ucp
[13]) * 100.0 / 65536.0);
974 pout(" Number of background medium scans performed: %d\n",
975 (ucp
[14] << 8) + ucp
[15]);
980 pout("\nBackground scan results log\n");
984 pout("\n # when lba(hex) [sk,asc,ascq] "
985 "reassign_status\n");
988 if ((pl
< 24) || (num
< 24)) {
990 pout("parameter length >= 24 expected, got %d\n", pl
);
993 j
= (ucp
[4] << 24) + (ucp
[5] << 16) + (ucp
[6] << 8) + ucp
[7];
994 pout("%4d:%02d ", (j
/ 60), (j
% 60));
995 for (m
= 0; m
< 8; ++m
)
996 pout("%02x", ucp
[16 + m
]);
997 pout(" [%x,%x,%x] ", ucp
[8] & 0xf, ucp
[9], ucp
[10]);
998 j
= (ucp
[8] >> 4) & 0xf;
1000 (int)(sizeof(reassign_status
) / sizeof(reassign_status
[0])))
1001 pout("%s\n", reassign_status
[j
]);
1003 pout("Reassign status: reserved [0x%x]\n", j
);
1010 pout(" >>>> log truncated, fetched %d of %d available "
1011 "bytes\n", LOG_RESP_LONG_LEN
, truncated
);
1016 // See SCSI Block Commands - 3 (SBC-3) rev 27 (draft) section 6.3.6 .
1017 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
1018 // and up to 2048 events (although would hope to have less). May set
1019 // FAILLOG if serious errors detected (in the future).
1021 scsiPrintSSMedia(scsi_device
* device
)
1023 int num
, err
, truncated
;
1027 if ((err
= scsiLogSense(device
, SS_MEDIA_LPAGE
, 0, gBuf
,
1028 LOG_RESP_LONG_LEN
, 0))) {
1030 pout("%s: Failed [%s]\n", __func__
, scsiErrString(err
));
1034 if ((gBuf
[0] & 0x3f) != SS_MEDIA_LPAGE
) {
1036 pout("Solid state media Log Sense Failed, page mismatch\n");
1040 // compute page length
1041 num
= (gBuf
[2] << 8) + gBuf
[3] + 4;
1044 pout("Solid state media Log Sense length is %d, too short\n", num
);
1048 truncated
= (num
> LOG_RESP_LONG_LEN
) ? num
: 0;
1050 num
= LOG_RESP_LONG_LEN
;
1054 int pc
= (ucp
[0] << 8) | ucp
[1];
1056 int pl
= ucp
[3] + 4;
1061 pout("SS Media Percentage used endurance indicator parameter "
1062 "too short (pl=%d)\n", pl
);
1066 pout("Percentage used endurance indicator: %d%%\n", ucp
[7]);
1067 default: /* ignore other parameter codes */
1077 show_sas_phy_event_info(int peis
, unsigned int val
, unsigned thresh_val
)
1083 pout(" No event\n");
1086 pout(" Invalid word count: %u\n", val
);
1089 pout(" Running disparity error count: %u\n", val
);
1092 pout(" Loss of dword synchronization count: %u\n", val
);
1095 pout(" Phy reset problem count: %u\n", val
);
1098 pout(" Elasticity buffer overflow count: %u\n", val
);
1101 pout(" Received ERROR count: %u\n", val
);
1104 pout(" Received address frame error count: %u\n", val
);
1107 pout(" Transmitted abandon-class OPEN_REJECT count: %u\n", val
);
1110 pout(" Received abandon-class OPEN_REJECT count: %u\n", val
);
1113 pout(" Transmitted retry-class OPEN_REJECT count: %u\n", val
);
1116 pout(" Received retry-class OPEN_REJECT count: %u\n", val
);
1119 pout(" Received AIP (WATING ON PARTIAL) count: %u\n", val
);
1122 pout(" Received AIP (WAITING ON CONNECTION) count: %u\n", val
);
1125 pout(" Transmitted BREAK count: %u\n", val
);
1128 pout(" Received BREAK count: %u\n", val
);
1131 pout(" Break timeout count: %u\n", val
);
1134 pout(" Connection count: %u\n", val
);
1137 pout(" Peak transmitted pathway blocked count: %u\n",
1139 pout(" Peak value detector threshold: %u\n",
1145 pout(" Peak transmitted arbitration wait time (us): "
1148 pout(" Peak transmitted arbitration wait time (ms): "
1149 "%u\n", 33 + (u
- 0x8000));
1150 u
= thresh_val
& 0xffff;
1152 pout(" Peak value detector threshold (us): %u\n",
1155 pout(" Peak value detector threshold (ms): %u\n",
1159 pout(" Peak arbitration time (us): %u\n", val
);
1160 pout(" Peak value detector threshold: %u\n", thresh_val
);
1163 pout(" Peak connection time (us): %u\n", val
);
1164 pout(" Peak value detector threshold: %u\n", thresh_val
);
1167 pout(" Transmitted SSP frame count: %u\n", val
);
1170 pout(" Received SSP frame count: %u\n", val
);
1173 pout(" Transmitted SSP frame error count: %u\n", val
);
1176 pout(" Received SSP frame error count: %u\n", val
);
1179 pout(" Transmitted CREDIT_BLOCKED count: %u\n", val
);
1182 pout(" Received CREDIT_BLOCKED count: %u\n", val
);
1185 pout(" Transmitted SATA frame count: %u\n", val
);
1188 pout(" Received SATA frame count: %u\n", val
);
1191 pout(" SATA flow control buffer overflow count: %u\n", val
);
1194 pout(" Transmitted SMP frame count: %u\n", val
);
1197 pout(" Received SMP frame count: %u\n", val
);
1200 pout(" Received SMP frame error count: %u\n", val
);
1208 show_sas_port_param(unsigned char * ucp
, int param_len
)
1210 int j
, m
, n
, nphys
, t
, sz
, spld_len
;
1211 unsigned char * vcp
;
1217 t
= (ucp
[0] << 8) | ucp
[1];
1218 pout("relative target port id = %d\n", t
);
1219 pout(" generation code = %d\n", ucp
[6]);
1221 pout(" number of phys = %d\n", nphys
);
1223 for (j
= 0, vcp
= ucp
+ 8; j
< (param_len
- 8);
1224 vcp
+= spld_len
, j
+= spld_len
) {
1225 pout(" phy identifier = %d\n", vcp
[1]);
1228 spld_len
= 48; /* in SAS-1 and SAS-1.1 vcp[3]==0 */
1231 t
= ((0x70 & vcp
[4]) >> 4);
1233 case 0: snprintf(s
, sz
, "no device attached"); break;
1234 case 1: snprintf(s
, sz
, "SAS or SATA device"); break;
1235 case 2: snprintf(s
, sz
, "expander device"); break;
1236 case 3: snprintf(s
, sz
, "expander device (fanout)"); break;
1237 default: snprintf(s
, sz
, "reserved [%d]", t
); break;
1239 pout(" attached device type: %s\n", s
);
1242 case 0: snprintf(s
, sz
, "unknown"); break;
1243 case 1: snprintf(s
, sz
, "power on"); break;
1244 case 2: snprintf(s
, sz
, "hard reset"); break;
1245 case 3: snprintf(s
, sz
, "SMP phy control function"); break;
1246 case 4: snprintf(s
, sz
, "loss of dword synchronization"); break;
1247 case 5: snprintf(s
, sz
, "mux mix up"); break;
1248 case 6: snprintf(s
, sz
, "I_T nexus loss timeout for STP/SATA");
1250 case 7: snprintf(s
, sz
, "break timeout timer expired"); break;
1251 case 8: snprintf(s
, sz
, "phy test function stopped"); break;
1252 case 9: snprintf(s
, sz
, "expander device reduced functionality");
1254 default: snprintf(s
, sz
, "reserved [0x%x]", t
); break;
1256 pout(" attached reason: %s\n", s
);
1257 t
= (vcp
[5] & 0xf0) >> 4;
1259 case 0: snprintf(s
, sz
, "unknown"); break;
1260 case 1: snprintf(s
, sz
, "power on"); break;
1261 case 2: snprintf(s
, sz
, "hard reset"); break;
1262 case 3: snprintf(s
, sz
, "SMP phy control function"); break;
1263 case 4: snprintf(s
, sz
, "loss of dword synchronization"); break;
1264 case 5: snprintf(s
, sz
, "mux mix up"); break;
1265 case 6: snprintf(s
, sz
, "I_T nexus loss timeout for STP/SATA");
1267 case 7: snprintf(s
, sz
, "break timeout timer expired"); break;
1268 case 8: snprintf(s
, sz
, "phy test function stopped"); break;
1269 case 9: snprintf(s
, sz
, "expander device reduced functionality");
1271 default: snprintf(s
, sz
, "reserved [0x%x]", t
); break;
1273 pout(" reason: %s\n", s
);
1276 case 0: snprintf(s
, sz
, "phy enabled; unknown");
1278 case 1: snprintf(s
, sz
, "phy disabled"); break;
1279 case 2: snprintf(s
, sz
, "phy enabled; speed negotiation failed");
1281 case 3: snprintf(s
, sz
, "phy enabled; SATA spinup hold state");
1283 case 4: snprintf(s
, sz
, "phy enabled; port selector");
1285 case 5: snprintf(s
, sz
, "phy enabled; reset in progress");
1287 case 6: snprintf(s
, sz
, "phy enabled; unsupported phy attached");
1289 case 8: snprintf(s
, sz
, "phy enabled; 1.5 Gbps"); break;
1290 case 9: snprintf(s
, sz
, "phy enabled; 3 Gbps"); break;
1291 case 0xa: snprintf(s
, sz
, "phy enabled; 6 Gbps"); break;
1292 case 0xb: snprintf(s
, sz
, "phy enabled; 12 Gbps"); break;
1293 default: snprintf(s
, sz
, "reserved [%d]", t
); break;
1295 pout(" negotiated logical link rate: %s\n", s
);
1296 pout(" attached initiator port: ssp=%d stp=%d smp=%d\n",
1297 !! (vcp
[6] & 8), !! (vcp
[6] & 4), !! (vcp
[6] & 2));
1298 pout(" attached target port: ssp=%d stp=%d smp=%d\n",
1299 !! (vcp
[7] & 8), !! (vcp
[7] & 4), !! (vcp
[7] & 2));
1300 for (n
= 0, ull
= vcp
[8]; n
< 8; ++n
) {
1301 ull
<<= 8; ull
|= vcp
[8 + n
];
1303 pout(" SAS address = 0x%" PRIx64
"\n", ull
);
1304 for (n
= 0, ull
= vcp
[16]; n
< 8; ++n
) {
1305 ull
<<= 8; ull
|= vcp
[16 + n
];
1307 pout(" attached SAS address = 0x%" PRIx64
"\n", ull
);
1308 pout(" attached phy identifier = %d\n", vcp
[24]);
1310 ui
= (vcp
[32] << 24) | (vcp
[33] << 16) | (vcp
[34] << 8) | vcp
[35];
1311 pout(" Invalid DWORD count = %u\n", ui
);
1312 ui
= (vcp
[36] << 24) | (vcp
[37] << 16) | (vcp
[38] << 8) | vcp
[39];
1313 pout(" Running disparity error count = %u\n", ui
);
1314 ui
= (vcp
[40] << 24) | (vcp
[41] << 16) | (vcp
[42] << 8) | vcp
[43];
1315 pout(" Loss of DWORD synchronization = %u\n", ui
);
1316 ui
= (vcp
[44] << 24) | (vcp
[45] << 16) | (vcp
[46] << 8) | vcp
[47];
1317 pout(" Phy reset problem = %u\n", ui
);
1318 if (spld_len
> 51) {
1320 unsigned char * xcp
;
1324 pout(" Phy event descriptors:\n");
1326 for (m
= 0; m
< (num_ped
* 12); m
+= 12, xcp
+= 12) {
1330 ui
= (xcp
[4] << 24) | (xcp
[5] << 16) | (xcp
[6] << 8) |
1332 pvdt
= (xcp
[8] << 24) | (xcp
[9] << 16) | (xcp
[10] << 8) |
1334 show_sas_phy_event_info(peis
, ui
, pvdt
);
1340 // Returns 1 if okay, 0 if non SAS descriptors
1342 show_protocol_specific_page(unsigned char * resp
, int len
)
1345 unsigned char * ucp
;
1348 for (k
= 0, ucp
= resp
+ 4; k
< num
; ) {
1349 int param_len
= ucp
[3] + 4;
1350 if (6 != (0xf & ucp
[4]))
1351 return 0; /* only decode SAS log page */
1353 pout("Protocol Specific port log page for SAS SSP\n");
1354 show_sas_port_param(ucp
, param_len
);
1363 // See Serial Attached SCSI (SPL-3) (e.g. revision 6g) the Protocol Specific
1364 // log page [0x18]. Returns 0 if ok else FAIL* bitmask.
1366 scsiPrintSasPhy(scsi_device
* device
, int reset
)
1370 if ((err
= scsiLogSense(device
, PROTOCOL_SPECIFIC_LPAGE
, 0, gBuf
,
1371 LOG_RESP_LONG_LEN
, 0))) {
1373 pout("%s Log Sense Failed [%s]\n\n", __func__
, scsiErrString(err
));
1377 if ((gBuf
[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE
) {
1379 pout("Protocol specific Log Sense Failed, page mismatch\n\n");
1383 // compute page length
1384 num
= (gBuf
[2] << 8) + gBuf
[3];
1385 if (1 != show_protocol_specific_page(gBuf
, num
+ 4)) {
1387 pout("Only support protocol specific log page on SAS devices\n\n");
1392 if ((err
= scsiLogSelect(device
, 1 /* pcr */, 0 /* sp */, 0 /* pc */,
1393 PROTOCOL_SPECIFIC_LPAGE
, 0, NULL
, 0))) {
1395 pout("%s Log Select (reset) Failed [%s]\n\n", __func__
,
1396 scsiErrString(err
));
1405 static const char * peripheral_dt_arr
[32] = {
1421 "optical card reader",
1423 "object based storage",
1424 "automation/driver interface",
1425 "security manager device",
1426 "host managed zoned block device",
1436 "well known logical unit",
1437 "unknown or no device type",
1440 static const char * transport_proto_arr
[] = {
1441 "Fibre channel (FCP-2)",
1442 "Parallel SCSI (SPI-4)",
1444 "IEEE 1394 (SBP-2)",
1459 /* Returns 0 on success, 1 on general error and 2 for early, clean exit */
1461 scsiGetDriveInfo(scsi_device
* device
, UINT8
* peripheral_type
, bool all
)
1463 char timedatetz
[DATEANDEPOCHLEN
];
1464 struct scsi_iec_mode_page iec
;
1465 int err
, iec_err
, len
, req_len
, avail_len
, scsi_version
;
1466 bool is_tape
= false;
1469 int form_factor
= 0;
1473 memset(gBuf
, 0, 96);
1475 if ((err
= scsiStdInquiry(device
, gBuf
, req_len
))) {
1477 pout("Standard Inquiry (36 bytes) failed [%s]\n", scsiErrString(err
));
1478 pout("Retrying with a 64 byte Standard Inquiry\n");
1480 /* Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices */
1482 if ((err
= scsiStdInquiry(device
, gBuf
, req_len
))) {
1484 pout("Standard Inquiry (64 bytes) failed [%s]\n",
1485 scsiErrString(err
));
1490 avail_len
= gBuf
[4] + 5;
1491 len
= (avail_len
< req_len
) ? avail_len
: req_len
;
1492 peri_dt
= gBuf
[0] & 0x1f;
1493 *peripheral_type
= peri_dt
;
1494 if ((SCSI_PT_SEQUENTIAL_ACCESS
== peri_dt
) ||
1495 (SCSI_PT_MEDIUM_CHANGER
== peri_dt
))
1500 pout("Short INQUIRY response, skip product id\n");
1504 // Upper bits of version bytes were used in older standards
1505 // Only interested in SPC-4 (0x6) and SPC-5 (assumed to be 0x7)
1506 scsi_version
= gBuf
[2] & 0x7;
1508 if (all
&& (0 != strncmp((char *)&gBuf
[8], "ATA", 3))) {
1509 char vendor
[8+1], product
[16+1], revision
[4+1];
1510 scsi_format_id_string(vendor
, (const unsigned char *)&gBuf
[8], 8);
1511 scsi_format_id_string(product
, (const unsigned char *)&gBuf
[16], 16);
1512 scsi_format_id_string(revision
, (const unsigned char *)&gBuf
[32], 4);
1514 pout("=== START OF INFORMATION SECTION ===\n");
1515 pout("Vendor: %.8s\n", vendor
);
1516 pout("Product: %.16s\n", product
);
1517 if (gBuf
[32] >= ' ')
1518 pout("Revision: %.4s\n", revision
);
1519 if (scsi_version
== 0x6)
1520 pout("Compliance: SPC-4\n");
1521 else if (scsi_version
== 0x7)
1522 pout("Compliance: SPC-5\n");
1525 if (!*device
->get_req_type()/*no type requested*/ &&
1526 (0 == strncmp((char *)&gBuf
[8], "ATA", 3))) {
1527 pout("\nProbable ATA device behind a SAT layer\n"
1528 "Try an additional '-d ata' or '-d sat' argument.\n");
1534 protect
= gBuf
[5] & 0x1; /* from and including SPC-3 */
1536 if (! is_tape
) { /* assume disk if not tape drive (or tape changer) */
1537 unsigned int lb_size
= 0;
1538 unsigned char lb_prov_resp
[8];
1540 int lb_per_pb_exp
= 0;
1541 uint64_t capacity
= scsiGetSize(device
, &lb_size
, &lb_per_pb_exp
);
1544 char cap_str
[64], si_str
[64];
1545 format_with_thousands_sep(cap_str
, sizeof(cap_str
), capacity
);
1546 format_capacity(si_str
, sizeof(si_str
), capacity
);
1547 pout("User Capacity: %s bytes [%s]\n", cap_str
, si_str
);
1548 snprintf(lb_str
, sizeof(lb_str
) - 1, "%u", lb_size
);
1549 pout("Logical block size: %s bytes\n", lb_str
);
1553 if (protect
|| lb_per_pb_exp
) {
1554 unsigned char rc16_12
[20] = {0, };
1556 if (0 == scsiGetProtPBInfo(device
, rc16_12
)) {
1557 lb_per_pb_exp
= rc16_12
[1] & 0xf; /* just in case */
1558 if (lb_per_pb_exp
> 0) {
1559 snprintf(lb_str
, sizeof(lb_str
) - 1, "%u",
1560 (lb_size
* (1 << lb_per_pb_exp
)));
1561 pout("Physical block size: %s bytes\n", lb_str
);
1562 int n
= ((rc16_12
[2] & 0x3f) << 8) + rc16_12
[3];
1563 if (n
> 0) // not common so cut the clutter
1564 pout("Lowest aligned LBA: %d\n", n
);
1566 if (rc16_12
[0] & 0x1) { /* PROT_EN set */
1567 int p_type
= ((rc16_12
[0] >> 1) & 0x7);
1571 pout("Formatted with type 1 protection\n");
1574 pout("Formatted with type 2 protection\n");
1577 pout("Formatted with type 3 protection\n");
1580 pout("Formatted with unknown protection type [%d]\n",
1584 int p_i_exp
= ((rc16_12
[1] >> 4) & 0xf);
1587 pout("%d protection information intervals per "
1588 "logical block\n", (1 << p_i_exp
));
1590 /* Pick up some LB provisioning info since its available */
1591 lbpme
= !! (rc16_12
[2] & 0x80);
1592 lbprz
= !! (rc16_12
[2] & 0x40);
1595 /* Thin Provisioning VPD page renamed Logical Block Provisioning VPD
1596 * page in sbc3r25; some fields changed their meaning so that the
1597 * new page covered both thin and resource provisioned LUs. */
1598 if (0 == scsiInquiryVpd(device
, SCSI_VPD_LOGICAL_BLOCK_PROVISIONING
,
1599 lb_prov_resp
, sizeof(lb_prov_resp
))) {
1600 int prov_type
= lb_prov_resp
[6] & 0x7; /* added sbc3r27 */
1601 int vpd_lbprz
= ((lb_prov_resp
[5] >> 2) & 0x7); /* sbc4r07 */
1605 else if ((0 == vpd_lbprz
) && (1 == lbprz
))
1606 ; /* vpd_lbprz introduced in sbc3r27, expanded in sbc4r07 */
1609 switch (prov_type
) {
1612 pout("LU is fully provisioned");
1614 pout(" [LBPRZ=%d]\n", lbprz
);
1618 pout("LB provisioning type: not reported [LBPME=1, "
1619 "LBPRZ=%d]\n", lbprz
);
1622 pout("LU is resource provisioned, LBPRZ=%d\n", lbprz
);
1625 pout("LU is thin provisioned, LBPRZ=%d\n", lbprz
);
1628 pout("LU provisioning type reserved [%d], LBPRZ=%d\n",
1632 } else if (1 == lbpme
) {
1633 if (scsi_debugmode
> 0)
1634 pout("rcap_16 sets LBPME but no LB provisioning VPD page\n");
1635 pout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz
);
1638 int rpm
= scsiGetRPM(device
, modese_len
, &form_factor
, &haw_zbc
);
1643 pout("Rotation Rate: Solid State Device\n");
1644 else if ((rpm
<= 0x400) || (0xffff == rpm
))
1647 pout("Rotation Rate: %d rpm\n", rpm
);
1649 if (form_factor
> 0) {
1650 const char * cp
= NULL
;
1652 switch (form_factor
) {
1670 pout("Form Factor: %s inches\n", cp
);
1673 pout("Host aware zoned block capable\n");
1676 /* Do this here to try and detect badly conforming devices (some USB
1677 keys) that will lock up on a InquiryVpd or log sense or ... */
1678 if ((iec_err
= scsiFetchIECmpage(device
, &iec
, modese_len
))) {
1679 if (SIMPLE_ERR_BAD_RESP
== iec_err
) {
1680 pout(">> Terminate command early due to bad response to IEC "
1687 modese_len
= iec
.modese_len
;
1689 if (! dont_print_serial_number
) {
1690 if (0 == (err
= scsiInquiryVpd(device
, SCSI_VPD_DEVICE_IDENTIFICATION
,
1695 scsi_decode_lu_dev_id(gBuf
+ 4, len
, s
, sizeof(s
), &transport
);
1697 pout("Logical Unit id: %s\n", s
);
1698 } else if (scsi_debugmode
> 0) {
1700 if (SIMPLE_ERR_BAD_RESP
== err
)
1701 pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
1703 pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err
);
1706 if (0 == (err
= scsiInquiryVpd(device
, SCSI_VPD_UNIT_SERIAL_NUMBER
,
1711 gBuf
[4 + len
] = '\0';
1712 scsi_format_id_string(serial
, &gBuf
[4], len
);
1713 pout("Serial number: %s\n", serial
);
1714 } else if (scsi_debugmode
> 0) {
1716 if (SIMPLE_ERR_BAD_RESP
== err
)
1717 pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
1719 pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err
);
1724 // print SCSI peripheral device type
1725 if (peri_dt
< (int)(sizeof(peripheral_dt_arr
) /
1726 sizeof(peripheral_dt_arr
[0])))
1727 pout("Device type: %s\n", peripheral_dt_arr
[peri_dt
]);
1729 pout("Device type: <%d>\n", peri_dt
);
1731 // See if transport protocol is known
1733 transport
= scsiFetchTransportProtocol(device
, modese_len
);
1734 if ((transport
>= 0) && (transport
<= 0xf))
1735 pout("Transport protocol: %s\n", transport_proto_arr
[transport
]);
1737 // print current time and date and timezone
1738 dateandtimezone(timedatetz
);
1739 pout("Local Time is: %s\n", timedatetz
);
1741 // See if unit accepts SCSI commmands from us
1742 if ((err
= scsiTestUnitReady(device
))) {
1743 if (SIMPLE_ERR_NOT_READY
== err
) {
1746 pout("device is NOT READY (e.g. spun down, busy)\n");
1748 pout("device is NOT READY (e.g. no tape)\n");
1750 } else if (SIMPLE_ERR_NO_MEDIUM
== err
) {
1753 pout("NO tape present in drive\n");
1755 pout("NO MEDIUM present in device\n");
1757 } else if (SIMPLE_ERR_BECOMING_READY
== err
) {
1759 pout("device becoming ready (wait)\n");
1763 pout("device Test Unit Ready [%s]\n", scsiErrString(err
));
1767 int returnval
= 0; // TODO: exit with FAILID if failuretest returns
1769 failuretest(MANDATORY_CMD
, returnval
|=FAILID
);
1776 pout("SMART support is: Unavailable - device lacks SMART capability.\n");
1777 if (scsi_debugmode
> 0)
1778 pout(" [%s]\n", scsiErrString(iec_err
));
1786 pout("SMART support is: Available - device has SMART capability.\n"
1787 "SMART support is: %s\n",
1788 (scsi_IsExceptionControlEnabled(&iec
)) ? "Enabled" : "Disabled");
1789 pout("%s\n", (scsi_IsWarningEnabled(&iec
)) ?
1790 "Temperature Warning: Enabled" :
1791 "Temperature Warning: Disabled or Not Supported");
1796 scsiSmartEnable(scsi_device
* device
)
1798 struct scsi_iec_mode_page iec
;
1801 if ((err
= scsiFetchIECmpage(device
, &iec
, modese_len
))) {
1803 pout("unable to fetch IEC (SMART) mode page [%s]\n",
1804 scsiErrString(err
));
1808 modese_len
= iec
.modese_len
;
1810 if ((err
= scsiSetExceptionControlAndWarning(device
, 1, &iec
))) {
1812 pout("unable to enable Exception control and warning [%s]\n",
1813 scsiErrString(err
));
1817 /* Need to refetch 'iec' since could be modified by previous call */
1818 if ((err
= scsiFetchIECmpage(device
, &iec
, modese_len
))) {
1819 pout("unable to fetch IEC (SMART) mode page [%s]\n",
1820 scsiErrString(err
));
1823 modese_len
= iec
.modese_len
;
1825 pout("Informational Exceptions (SMART) %s\n",
1826 scsi_IsExceptionControlEnabled(&iec
) ? "enabled" : "disabled");
1827 pout("Temperature warning %s\n",
1828 scsi_IsWarningEnabled(&iec
) ? "enabled" : "disabled");
1833 scsiSmartDisable(scsi_device
* device
)
1835 struct scsi_iec_mode_page iec
;
1838 if ((err
= scsiFetchIECmpage(device
, &iec
, modese_len
))) {
1840 pout("unable to fetch IEC (SMART) mode page [%s]\n",
1841 scsiErrString(err
));
1845 modese_len
= iec
.modese_len
;
1847 if ((err
= scsiSetExceptionControlAndWarning(device
, 0, &iec
))) {
1849 pout("unable to disable Exception control and warning [%s]\n",
1850 scsiErrString(err
));
1854 /* Need to refetch 'iec' since could be modified by previous call */
1855 if ((err
= scsiFetchIECmpage(device
, &iec
, modese_len
))) {
1856 pout("unable to fetch IEC (SMART) mode page [%s]\n",
1857 scsiErrString(err
));
1860 modese_len
= iec
.modese_len
;
1862 pout("Informational Exceptions (SMART) %s\n",
1863 scsi_IsExceptionControlEnabled(&iec
) ? "enabled" : "disabled");
1864 pout("Temperature warning %s\n",
1865 scsi_IsWarningEnabled(&iec
) ? "enabled" : "disabled");
1870 scsiPrintTemp(scsi_device
* device
)
1875 if (scsiGetTemp(device
, &temp
, &trip
))
1879 pout("Current Drive Temperature: <not available>\n");
1881 pout("Current Drive Temperature: %d C\n", temp
);
1883 pout("Drive Trip Temperature: <not available>\n");
1885 pout("Drive Trip Temperature: %d C\n", trip
);
1889 /* Main entry point used by smartctl command. Return 0 for success */
1891 scsiPrintMain(scsi_device
* device
, const scsi_print_options
& options
)
1893 int checkedSupportedLogPages
= 0;
1894 UINT8 peripheral_type
= 0;
1896 int res
, durationSec
;
1897 struct scsi_sense_disect sense_info
;
1901 bool any_output
= options
.drive_info
;
1903 if (supported_vpd_pages_p
) {
1904 delete supported_vpd_pages_p
;
1905 supported_vpd_pages_p
= NULL
;
1907 supported_vpd_pages_p
= new supported_vpd_pages(device
);
1909 res
= scsiGetDriveInfo(device
, &peripheral_type
, options
.drive_info
);
1914 failuretest(MANDATORY_CMD
, returnval
|= FAILID
);
1917 is_disk
= (SCSI_PT_DIRECT_ACCESS
== peripheral_type
);
1918 is_tape
= ((SCSI_PT_SEQUENTIAL_ACCESS
== peripheral_type
) ||
1919 (SCSI_PT_MEDIUM_CHANGER
== peripheral_type
));
1921 short int wce
= -1, rcd
= -1;
1922 // Print read look-ahead status for disks
1923 if (options
.get_rcd
|| options
.get_wce
) {
1925 res
= scsiGetSetCache(device
, modese_len
, &wce
, &rcd
);
1926 if (options
.get_rcd
)
1927 pout("Read Cache is: %s\n",
1928 res
? "Unavailable" : // error
1929 rcd
? "Disabled" : "Enabled");
1930 if (options
.get_wce
)
1931 pout("Writeback Cache is: %s\n",
1932 res
? "Unavailable" : // error
1933 !wce
? "Disabled" : "Enabled");
1938 if (options
.drive_info
)
1941 // START OF THE ENABLE/DISABLE SECTION OF THE CODE
1942 if (options
.smart_disable
|| options
.smart_enable
||
1943 options
.smart_auto_save_disable
|| options
.smart_auto_save_enable
)
1944 pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
1946 if (options
.smart_enable
) {
1947 if (scsiSmartEnable(device
))
1948 failuretest(MANDATORY_CMD
, returnval
|= FAILSMART
);
1952 if (options
.smart_disable
) {
1953 if (scsiSmartDisable(device
))
1954 failuretest(MANDATORY_CMD
,returnval
|= FAILSMART
);
1958 if (options
.smart_auto_save_enable
) {
1959 if (scsiSetControlGLTSD(device
, 0, modese_len
)) {
1960 pout("Enable autosave (clear GLTSD bit) failed\n");
1961 failuretest(OPTIONAL_CMD
,returnval
|= FAILSMART
);
1963 pout("Autosave enabled (GLTSD bit cleared).\n");
1967 // Enable/Disable write cache
1968 if (options
.set_wce
&& is_disk
) {
1969 short int enable
= wce
= (options
.set_wce
> 0);
1972 if (scsiGetSetCache(device
, modese_len
, &wce
, &rcd
)) {
1973 pout("Write cache %sable failed: %s\n", (enable
? "en" : "dis"),
1974 device
->get_errmsg());
1975 failuretest(OPTIONAL_CMD
,returnval
|= FAILSMART
);
1977 pout("Write cache %sabled\n", (enable
? "en" : "dis"));
1981 // Enable/Disable read cache
1982 if (options
.set_rcd
&& is_disk
) {
1983 short int enable
= (options
.set_rcd
> 0);
1987 if (scsiGetSetCache(device
, modese_len
, &wce
, &rcd
)) {
1988 pout("Read cache %sable failed: %s\n", (enable
? "en" : "dis"),
1989 device
->get_errmsg());
1990 failuretest(OPTIONAL_CMD
,returnval
|= FAILSMART
);
1992 pout("Read cache %sabled\n", (enable
? "en" : "dis"));
1996 if (options
.smart_auto_save_disable
) {
1997 if (scsiSetControlGLTSD(device
, 1, modese_len
)) {
1998 pout("Disable autosave (set GLTSD bit) failed\n");
1999 failuretest(OPTIONAL_CMD
,returnval
|= FAILSMART
);
2001 pout("Autosave disabled (GLTSD bit set).\n");
2004 if (options
.smart_disable
|| options
.smart_enable
||
2005 options
.smart_auto_save_disable
|| options
.smart_auto_save_enable
)
2006 pout("\n"); // END OF THE ENABLE/DISABLE SECTION OF THE CODE
2008 // START OF READ-ONLY OPTIONS APART FROM -V and -i
2009 if (options
.smart_check_status
|| options
.smart_ss_media_log
||
2010 options
.smart_vendor_attrib
|| options
.smart_error_log
||
2011 options
.smart_selftest_log
|| options
.smart_background_log
||
2013 pout("=== START OF READ SMART DATA SECTION ===\n");
2015 if (options
.smart_check_status
) {
2016 scsiGetSupportedLogPages(device
);
2017 checkedSupportedLogPages
= 1;
2019 if (gTapeAlertsLPage
) {
2020 if (options
.drive_info
)
2021 pout("TapeAlert Supported\n");
2022 if (-1 == scsiGetTapeAlertsData(device
, peripheral_type
))
2023 failuretest(OPTIONAL_CMD
, returnval
|= FAILSMART
);
2026 pout("TapeAlert Not Supported\n");
2027 } else { /* disk, cd/dvd, enclosure, etc */
2028 if ((res
= scsiGetSmartData(device
, options
.smart_vendor_attrib
))) {
2030 returnval
|= FAILSTATUS
;
2032 returnval
|= FAILSMART
;
2038 if (is_disk
&& options
.smart_ss_media_log
) {
2039 if (! checkedSupportedLogPages
)
2040 scsiGetSupportedLogPages(device
);
2043 res
= scsiPrintSSMedia(device
);
2045 failuretest(OPTIONAL_CMD
, returnval
|=res
);
2048 if (options
.smart_vendor_attrib
) {
2049 if (! checkedSupportedLogPages
)
2050 scsiGetSupportedLogPages(device
);
2052 scsiPrintTemp(device
);
2053 if (gStartStopLPage
)
2054 scsiGetStartStopData(device
);
2056 scsiPrintGrownDefectListLen(device
);
2057 if (gSeagateCacheLPage
)
2058 scsiPrintSeagateCacheLPage(device
);
2059 if (gSeagateFactoryLPage
)
2060 scsiPrintSeagateFactoryLPage(device
);
2064 if (options
.smart_error_log
) {
2065 if (! checkedSupportedLogPages
)
2066 scsiGetSupportedLogPages(device
);
2067 scsiPrintErrorCounterLog(device
);
2068 if (1 == scsiFetchControlGLTSD(device
, modese_len
, 1))
2069 pout("\n[GLTSD (Global Logging Target Save Disable) set. "
2070 "Enable Save with '-S on']\n");
2073 if (options
.smart_selftest_log
) {
2074 if (! checkedSupportedLogPages
)
2075 scsiGetSupportedLogPages(device
);
2078 res
= scsiPrintSelfTest(device
);
2080 pout("Device does not support Self Test logging\n");
2081 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
2084 failuretest(OPTIONAL_CMD
, returnval
|=res
);
2087 if (options
.smart_background_log
&& is_disk
) {
2088 if (! checkedSupportedLogPages
)
2089 scsiGetSupportedLogPages(device
);
2091 if (gBackgroundResultsLPage
)
2092 res
= scsiPrintBackgroundResults(device
);
2094 pout("Device does not support Background scan results logging\n");
2095 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
2098 failuretest(OPTIONAL_CMD
, returnval
|=res
);
2101 if (options
.smart_default_selftest
) {
2102 if (scsiSmartDefaultSelfTest(device
))
2103 return returnval
| FAILSMART
;
2104 pout("Default Self Test Successful\n");
2107 if (options
.smart_short_cap_selftest
) {
2108 if (scsiSmartShortCapSelfTest(device
))
2109 return returnval
| FAILSMART
;
2110 pout("Short Foreground Self Test Successful\n");
2113 // check if another test is running
2114 if (options
.smart_short_selftest
|| options
.smart_extend_selftest
) {
2115 if (!scsiRequestSense(device
, &sense_info
) &&
2116 (sense_info
.asc
== 0x04 && sense_info
.ascq
== 0x09)) {
2117 if (!options
.smart_selftest_force
) {
2118 pout("Can't start self-test without aborting current test");
2119 if (sense_info
.progress
!= -1)
2120 pout(" (%d%% remaining)",
2121 100 - sense_info
.progress
* 100 / 65535);
2122 pout(",\nadd '-t force' option to override, or run "
2123 "'smartctl -X' to abort test.\n");
2126 scsiSmartSelfTestAbort(device
);
2129 if (options
.smart_short_selftest
) {
2130 if (scsiSmartShortSelfTest(device
))
2131 return returnval
| FAILSMART
;
2132 pout("Short Background Self Test has begun\n");
2133 pout("Use smartctl -X to abort test\n");
2136 if (options
.smart_extend_selftest
) {
2137 if (scsiSmartExtendSelfTest(device
))
2138 return returnval
| FAILSMART
;
2139 pout("Extended Background Self Test has begun\n");
2140 if ((0 == scsiFetchExtendedSelfTestTime(device
, &durationSec
,
2141 modese_len
)) && (durationSec
> 0)) {
2142 time_t t
= time(NULL
);
2145 pout("Please wait %d minutes for test to complete.\n",
2147 pout("Estimated completion time: %s\n", ctime(&t
));
2149 pout("Use smartctl -X to abort test\n");
2152 if (options
.smart_extend_cap_selftest
) {
2153 if (scsiSmartExtendCapSelfTest(device
))
2154 return returnval
| FAILSMART
;
2155 pout("Extended Foreground Self Test Successful\n");
2157 if (options
.smart_selftest_abort
) {
2158 if (scsiSmartSelfTestAbort(device
))
2159 return returnval
| FAILSMART
;
2160 pout("Self Test returned without error\n");
2163 if (options
.sasphy
&& gProtocolSpecificLPage
) {
2164 if (scsiPrintSasPhy(device
, options
.sasphy_reset
))
2165 return returnval
| FAILSMART
;
2170 pout("SCSI device successfully opened\n\nUse 'smartctl -a' (or '-x') "
2171 "to print SMART (and more) information\n\n");