smartmontools  SVN Rev 4039
Utility to control and monitor storage systems with "S.M.A.R.T."
scsiprint.cpp
Go to the documentation of this file.
1 /*
2  * scsiprint.cpp
3  *
4  * Home page of code is: http://smartmontools.sourceforge.net
5  *
6  * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
7  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
8  *
9  * Additional SCSI work:
10  * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2, or (at your option)
15  * any later version.
16  *
17  * You should have received a copy of the GNU General Public License
18  * (for example COPYING); if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * This code was originally developed as a Senior Thesis by Michael Cornwell
22  * at the Concurrent Systems Laboratory (now part of the Storage Systems
23  * Research Center), Jack Baskin School of Engineering, University of
24  * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
25  *
26  */
27 
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 
34 #include "config.h"
35 #include "int64.h"
36 #include "scsicmds.h"
37 #include "atacmds.h" // smart_command_set
38 #include "dev_interface.h"
39 #include "scsiprint.h"
40 #include "smartctl.h"
41 #include "utility.h"
42 
43 #define GBUF_SIZE 65535
44 
45 const char * scsiprint_c_cvsid = "$Id: scsiprint.cpp 3898 2014-04-30 17:44:13Z dpgilbert $"
47 
48 
50 #define LOG_RESP_LEN 252
51 #define LOG_RESP_LONG_LEN ((62 * 256) + 252)
52 #define LOG_RESP_TAPE_ALERT_LEN 0x144
53 
54 /* Log pages supported */
55 static int gSmartLPage = 0; /* Informational Exceptions log page */
56 static int gTempLPage = 0;
57 static int gSelfTestLPage = 0;
58 static int gStartStopLPage = 0;
59 static int gReadECounterLPage = 0;
60 static int gWriteECounterLPage = 0;
61 static int gVerifyECounterLPage = 0;
62 static int gNonMediumELPage = 0;
63 static int gLastNErrorLPage = 0;
64 static int gBackgroundResultsLPage = 0;
65 static int gProtocolSpecificLPage = 0;
66 static int gTapeAlertsLPage = 0;
67 static int gSSMediaLPage = 0;
68 
69 /* Vendor specific log pages */
70 static int gSeagateCacheLPage = 0;
71 static int gSeagateFactoryLPage = 0;
72 
73 /* Mode pages supported */
74 static int gIecMPage = 1; /* N.B. assume it until we know otherwise */
75 
76 /* Remember last successful mode sense/select command */
77 static int modese_len = 0;
78 
79 
80 static void
82 {
83  int i, err;
84 
85  if ((err = scsiLogSense(device, SUPPORTED_LPAGES, 0, gBuf,
86  LOG_RESP_LEN, 0))) {
87  if (scsi_debugmode > 0)
88  pout("Log Sense for supported pages failed [%s]\n",
89  scsiErrString(err));
90  return;
91  }
92 
93  for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) {
94  switch (gBuf[i])
95  {
98  break;
101  break;
104  break;
105  case LAST_N_ERROR_LPAGE:
106  gLastNErrorLPage = 1;
107  break;
109  gNonMediumELPage = 1;
110  break;
111  case TEMPERATURE_LPAGE:
112  gTempLPage = 1;
113  break;
115  gStartStopLPage = 1;
116  break;
118  gSelfTestLPage = 1;
119  break;
120  case IE_LPAGE:
121  gSmartLPage = 1;
122  break;
125  break;
128  break;
129  case TAPE_ALERTS_LPAGE:
130  gTapeAlertsLPage = 1;
131  break;
132  case SS_MEDIA_LPAGE:
133  gSSMediaLPage = 1;
134  break;
135  case SEAGATE_CACHE_LPAGE:
136  gSeagateCacheLPage = 1;
137  break;
140  break;
141  default:
142  break;
143  }
144  }
145 }
146 
147 /* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad
148  (or at least something to report). */
149 static int
150 scsiGetSmartData(scsi_device * device, bool attribs)
151 {
152  UINT8 asc;
153  UINT8 ascq;
154  UINT8 currenttemp = 0;
155  UINT8 triptemp = 0;
156  const char * cp;
157  int err = 0;
158  print_on();
159  if (scsiCheckIE(device, gSmartLPage, gTempLPage, &asc, &ascq,
160  &currenttemp, &triptemp)) {
161  /* error message already announced */
162  print_off();
163  return -1;
164  }
165  print_off();
166  cp = scsiGetIEString(asc, ascq);
167  if (cp) {
168  err = -2;
169  print_on();
170  pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq);
171  print_off();
172  } else if (gIecMPage)
173  pout("SMART Health Status: OK\n");
174 
175  if (attribs && !gTempLPage) {
176  if (currenttemp) {
177  if (255 != currenttemp)
178  pout("Current Drive Temperature: %d C\n", currenttemp);
179  else
180  pout("Current Drive Temperature: <not available>\n");
181  }
182  if (triptemp)
183  pout("Drive Trip Temperature: %d C\n", triptemp);
184  }
185  pout("\n");
186  return err;
187 }
188 
189 
190 // Returns number of logged errors or zero if none or -1 if fetching
191 // TapeAlerts fails
192 static const char * const severities = "CWI";
193 
194 static int
195 scsiGetTapeAlertsData(scsi_device * device, int peripheral_type)
196 {
197  unsigned short pagelength;
198  unsigned short parametercode;
199  int i, err;
200  const char *s;
201  const char *ts;
202  int failures = 0;
203 
204  print_on();
205  if ((err = scsiLogSense(device, TAPE_ALERTS_LPAGE, 0, gBuf,
207  pout("scsiGetTapesAlertData Failed [%s]\n", scsiErrString(err));
208  print_off();
209  return -1;
210  }
211  if (gBuf[0] != 0x2e) {
212  pout("TapeAlerts Log Sense Failed\n");
213  print_off();
214  return -1;
215  }
216  pagelength = (unsigned short) gBuf[2] << 8 | gBuf[3];
217 
218  for (s=severities; *s; s++) {
219  for (i = 4; i < pagelength; i += 5) {
220  parametercode = (unsigned short) gBuf[i] << 8 | gBuf[i+1];
221 
222  if (gBuf[i + 4]) {
223  ts = SCSI_PT_MEDIUM_CHANGER == peripheral_type ?
224  scsiTapeAlertsChangerDevice(parametercode) :
225  scsiTapeAlertsTapeDevice(parametercode);
226  if (*ts == *s) {
227  if (!failures)
228  pout("TapeAlert Errors (C=Critical, W=Warning, "
229  "I=Informational):\n");
230  pout("[0x%02x] %s\n", parametercode, ts);
231  failures += 1;
232  }
233  }
234  }
235  }
236  print_off();
237 
238  if (! failures)
239  pout("TapeAlert: OK\n");
240 
241  return failures;
242 }
243 
244 static void
246 {
247  UINT32 u;
248  int err, len, k, extra, pc;
249  unsigned char * ucp;
250 
251  if ((err = scsiLogSense(device, STARTSTOP_CYCLE_COUNTER_LPAGE, 0, gBuf,
252  LOG_RESP_LEN, 0))) {
253  print_on();
254  pout("scsiGetStartStopData Failed [%s]\n", scsiErrString(err));
255  print_off();
256  return;
257  }
258  if ((gBuf[0] & 0x3f) != STARTSTOP_CYCLE_COUNTER_LPAGE) {
259  print_on();
260  pout("StartStop Log Sense Failed, page mismatch\n");
261  print_off();
262  return;
263  }
264  len = ((gBuf[2] << 8) | gBuf[3]);
265  ucp = gBuf + 4;
266  for (k = len; k > 0; k -= extra, ucp += extra) {
267  if (k < 3) {
268  print_on();
269  pout("StartStop Log Sense Failed: short\n");
270  print_off();
271  return;
272  }
273  extra = ucp[3] + 4;
274  pc = (ucp[0] << 8) + ucp[1];
275  switch (pc) {
276  case 1:
277  if (10 == extra)
278  pout("Manufactured in week %.2s of year %.4s\n", ucp + 8,
279  ucp + 4);
280  break;
281  case 2:
282  /* ignore Accounting date */
283  break;
284  case 3:
285  if (extra > 7) {
286  u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
287  if (0xffffffff != u)
288  pout("Specified cycle count over device lifetime: %u\n",
289  u);
290  }
291  break;
292  case 4:
293  if (extra > 7) {
294  u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
295  if (0xffffffff != u)
296  pout("Accumulated start-stop cycles: %u\n", u);
297  }
298  break;
299  case 5:
300  if (extra > 7) {
301  u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
302  if (0xffffffff != u)
303  pout("Specified load-unload count over device "
304  "lifetime: %u\n", u);
305  }
306  break;
307  case 6:
308  if (extra > 7) {
309  u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
310  if (0xffffffff != u)
311  pout("Accumulated load-unload cycles: %u\n", u);
312  }
313  break;
314  default:
315  /* ignore */
316  break;
317  }
318  }
319 }
320 
321 static void
323 {
324  int err, dl_format, got_rd12, generation;
325  unsigned int dl_len, div;
326 
327  memset(gBuf, 0, 8);
328  if ((err = scsiReadDefect12(device, 0 /* req_plist */, 1 /* req_glist */,
329  4 /* format: bytes from index */,
330  0 /* addr desc index */, gBuf, 8))) {
331  if (2 == err) { /* command not supported */
332  if ((err = scsiReadDefect10(device, 0 /* req_plist */, 1 /* req_glist */,
333  4 /* format: bytes from index */, gBuf, 4))) {
334  if (scsi_debugmode > 0) {
335  print_on();
336  pout("Read defect list (10) Failed: %s\n", scsiErrString(err));
337  print_off();
338  }
339  return;
340  } else
341  got_rd12 = 0;
342  } else {
343  if (scsi_debugmode > 0) {
344  print_on();
345  pout("Read defect list (12) Failed: %s\n", scsiErrString(err));
346  print_off();
347  }
348  return;
349  }
350  } else
351  got_rd12 = 1;
352 
353  if (got_rd12) {
354  generation = (gBuf[2] << 8) + gBuf[3];
355  if ((generation > 1) && (scsi_debugmode > 0)) {
356  print_on();
357  pout("Read defect list (12): generation=%d\n", generation);
358  print_off();
359  }
360  dl_len = (gBuf[4] << 24) + (gBuf[5] << 16) + (gBuf[6] << 8) + gBuf[7];
361  } else {
362  dl_len = (gBuf[2] << 8) + gBuf[3];
363  }
364  if (0x8 != (gBuf[1] & 0x18)) {
365  print_on();
366  pout("Read defect list: asked for grown list but didn't get it\n");
367  print_off();
368  return;
369  }
370  div = 0;
371  dl_format = (gBuf[1] & 0x7);
372  switch (dl_format) {
373  case 0: /* short block */
374  div = 4;
375  break;
376  case 1: /* extended bytes from index */
377  case 2: /* extended physical sector */
378  /* extended = 1; # might use in future */
379  div = 8;
380  break;
381  case 3: /* long block */
382  case 4: /* bytes from index */
383  case 5: /* physical sector */
384  div = 8;
385  break;
386  default:
387  print_on();
388  pout("defect list format %d unknown\n", dl_format);
389  print_off();
390  break;
391  }
392  if (0 == dl_len)
393  pout("Elements in grown defect list: 0\n\n");
394  else {
395  if (0 == div)
396  pout("Grown defect list length=%u bytes [unknown "
397  "number of elements]\n\n", dl_len);
398  else
399  pout("Elements in grown defect list: %u\n\n", dl_len / div);
400  }
401 }
402 
403 static void
405 {
406  int k, j, num, pl, pc, err, len;
407  unsigned char * ucp;
408  unsigned char * xp;
409  uint64_t ull;
410 
411  if ((err = scsiLogSense(device, SEAGATE_CACHE_LPAGE, 0, gBuf,
412  LOG_RESP_LEN, 0))) {
413  print_on();
414  pout("Seagate Cache Log Sense Failed: %s\n", scsiErrString(err));
415  print_off();
416  return;
417  }
418  if ((gBuf[0] & 0x3f) != SEAGATE_CACHE_LPAGE) {
419  print_on();
420  pout("Seagate Cache Log Sense Failed, page mismatch\n");
421  print_off();
422  return;
423  }
424  len = ((gBuf[2] << 8) | gBuf[3]) + 4;
425  num = len - 4;
426  ucp = &gBuf[0] + 4;
427  while (num > 3) {
428  pc = (ucp[0] << 8) | ucp[1];
429  pl = ucp[3] + 4;
430  switch (pc) {
431  case 0: case 1: case 2: case 3: case 4:
432  break;
433  default:
434  if (scsi_debugmode > 0) {
435  print_on();
436  pout("Vendor (Seagate) cache lpage has unexpected parameter"
437  ", skip\n");
438  print_off();
439  }
440  return;
441  }
442  num -= pl;
443  ucp += pl;
444  }
445  pout("Vendor (Seagate) cache information\n");
446  num = len - 4;
447  ucp = &gBuf[0] + 4;
448  while (num > 3) {
449  pc = (ucp[0] << 8) | ucp[1];
450  pl = ucp[3] + 4;
451  switch (pc) {
452  case 0: pout(" Blocks sent to initiator"); break;
453  case 1: pout(" Blocks received from initiator"); break;
454  case 2: pout(" Blocks read from cache and sent to initiator"); break;
455  case 3: pout(" Number of read and write commands whose size "
456  "<= segment size"); break;
457  case 4: pout(" Number of read and write commands whose size "
458  "> segment size"); break;
459  default: pout(" Unknown Seagate parameter code [0x%x]", pc); break;
460  }
461  k = pl - 4;
462  xp = ucp + 4;
463  if (k > (int)sizeof(ull)) {
464  xp += (k - (int)sizeof(ull));
465  k = (int)sizeof(ull);
466  }
467  ull = 0;
468  for (j = 0; j < k; ++j) {
469  if (j > 0)
470  ull <<= 8;
471  ull |= xp[j];
472  }
473  pout(" = %" PRIu64 "\n", ull);
474  num -= pl;
475  ucp += pl;
476  }
477  pout("\n");
478 }
479 
480 static void
482 {
483  int k, j, num, pl, pc, len, err, good, bad;
484  unsigned char * ucp;
485  unsigned char * xp;
486  uint64_t ull;
487 
488  if ((err = scsiLogSense(device, SEAGATE_FACTORY_LPAGE, 0, gBuf,
489  LOG_RESP_LEN, 0))) {
490  print_on();
491  pout("scsiPrintSeagateFactoryLPage Failed [%s]\n", scsiErrString(err));
492  print_off();
493  return;
494  }
495  if ((gBuf[0] & 0x3f) != SEAGATE_FACTORY_LPAGE) {
496  print_on();
497  pout("Seagate/Hitachi Factory Log Sense Failed, page mismatch\n");
498  print_off();
499  return;
500  }
501  len = ((gBuf[2] << 8) | gBuf[3]) + 4;
502  num = len - 4;
503  ucp = &gBuf[0] + 4;
504  good = 0;
505  bad = 0;
506  while (num > 3) {
507  pc = (ucp[0] << 8) | ucp[1];
508  pl = ucp[3] + 4;
509  switch (pc) {
510  case 0: case 8:
511  ++good;
512  break;
513  default:
514  ++bad;
515  break;
516  }
517  num -= pl;
518  ucp += pl;
519  }
520  if ((good < 2) || (bad > 4)) { /* heuristic */
521  if (scsi_debugmode > 0) {
522  print_on();
523  pout("\nVendor (Seagate/Hitachi) factory lpage has too many "
524  "unexpected parameters, skip\n");
525  print_off();
526  }
527  return;
528  }
529  pout("Vendor (Seagate/Hitachi) factory information\n");
530  num = len - 4;
531  ucp = &gBuf[0] + 4;
532  while (num > 3) {
533  pc = (ucp[0] << 8) | ucp[1];
534  pl = ucp[3] + 4;
535  good = 0;
536  switch (pc) {
537  case 0: pout(" number of hours powered up");
538  good = 1;
539  break;
540  case 8: pout(" number of minutes until next internal SMART test");
541  good = 1;
542  break;
543  default:
544  if (scsi_debugmode > 0) {
545  print_on();
546  pout("Vendor (Seagate/Hitachi) factory lpage: "
547  "unknown parameter code [0x%x]\n", pc);
548  print_off();
549  }
550  break;
551  }
552  if (good) {
553  k = pl - 4;
554  xp = ucp + 4;
555  if (k > (int)sizeof(ull)) {
556  xp += (k - (int)sizeof(ull));
557  k = (int)sizeof(ull);
558  }
559  ull = 0;
560  for (j = 0; j < k; ++j) {
561  if (j > 0)
562  ull <<= 8;
563  ull |= xp[j];
564  }
565  if (0 == pc)
566  pout(" = %.2f\n", ull / 60.0 );
567  else
568  pout(" = %" PRIu64 "\n", ull);
569  }
570  num -= pl;
571  ucp += pl;
572  }
573  pout("\n");
574 }
575 
576 static void
578 {
579  struct scsiErrorCounter errCounterArr[3];
580  struct scsiErrorCounter * ecp;
581  struct scsiNonMediumError nme;
582  int found[3] = {0, 0, 0};
583  const char * pageNames[3] = {"read: ", "write: ", "verify: "};
584  double processed_gb;
585 
586  if (gReadECounterLPage && (0 == scsiLogSense(device,
588  scsiDecodeErrCounterPage(gBuf, &errCounterArr[0]);
589  found[0] = 1;
590  }
591  if (gWriteECounterLPage && (0 == scsiLogSense(device,
593  scsiDecodeErrCounterPage(gBuf, &errCounterArr[1]);
594  found[1] = 1;
595  }
596  if (gVerifyECounterLPage && (0 == scsiLogSense(device,
598  scsiDecodeErrCounterPage(gBuf, &errCounterArr[2]);
599  ecp = &errCounterArr[2];
600  for (int k = 0; k < 7; ++k) {
601  if (ecp->gotPC[k] && ecp->counter[k]) {
602  found[2] = 1;
603  break;
604  }
605  }
606  }
607  if (found[0] || found[1] || found[2]) {
608  pout("Error counter log:\n");
609  pout(" Errors Corrected by Total "
610  "Correction Gigabytes Total\n");
611  pout(" ECC rereads/ errors "
612  "algorithm processed uncorrected\n");
613  pout(" fast | delayed rewrites corrected "
614  "invocations [10^9 bytes] errors\n");
615  for (int k = 0; k < 3; ++k) {
616  if (! found[k])
617  continue;
618  ecp = &errCounterArr[k];
619  pout("%s%8" PRIu64 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64,
620  pageNames[k], ecp->counter[0], ecp->counter[1],
621  ecp->counter[2], ecp->counter[3], ecp->counter[4]);
622  processed_gb = ecp->counter[5] / 1000000000.0;
623  pout(" %12.3f %8" PRIu64 "\n", processed_gb, ecp->counter[6]);
624  }
625  }
626  else
627  pout("Error Counter logging not supported\n");
628  if (gNonMediumELPage && (0 == scsiLogSense(device,
631  if (nme.gotPC0)
632  pout("\nNon-medium error count: %8" PRIu64 "\n", nme.counterPC0);
633  if (nme.gotTFE_H)
634  pout("Track following error count [Hitachi]: %8" PRIu64 "\n",
635  nme.counterTFE_H);
636  if (nme.gotPE_H)
637  pout("Positioning error count [Hitachi]: %8" PRIu64 "\n",
638  nme.counterPE_H);
639  }
640  if (gLastNErrorLPage && (0 == scsiLogSense(device,
642  int num = (gBuf[2] << 8) + gBuf[3] + 4;
643  int truncated = (num > LOG_RESP_LONG_LEN) ? num : 0;
644  if (truncated)
645  num = LOG_RESP_LONG_LEN;
646  unsigned char * ucp = gBuf + 4;
647  num -= 4;
648  if (num < 4)
649  pout("\nNo error events logged\n");
650  else {
651  pout("\nLast n error events log page\n");
652  for (int k = num, pl; k > 0; k -= pl, ucp += pl) {
653  if (k < 3) {
654  pout(" <<short Last n error events log page>>\n");
655  break;
656  }
657  pl = ucp[3] + 4;
658  int pc = (ucp[0] << 8) + ucp[1];
659  if (pl > 4) {
660  if ((ucp[2] & 0x1) && (ucp[2] & 0x2)) {
661  pout(" Error event %d:\n", pc);
662  pout(" [binary]:\n");
663  dStrHex((const char *)ucp + 4, pl - 4, 1);
664  } else if (ucp[2] & 0x1) {
665  pout(" Error event %d:\n", pc);
666  pout(" %.*s\n", pl - 4, (const char *)(ucp + 4));
667  } else {
668  if (scsi_debugmode > 0) {
669  pout(" Error event %d:\n", pc);
670  pout(" [data counter??]:\n");
671  dStrHex((const char *)ucp + 4, pl - 4, 1);
672  }
673  }
674  }
675  }
676  if (truncated)
677  pout(" >>>> log truncated, fetched %d of %d available "
678  "bytes\n", LOG_RESP_LONG_LEN, truncated);
679  }
680  }
681  pout("\n");
682 }
683 
684 static const char * self_test_code[] = {
685  "Default ",
686  "Background short",
687  "Background long ",
688  "Reserved(3) ",
689  "Abort background",
690  "Foreground short",
691  "Foreground long ",
692  "Reserved(7) "
693 };
694 
695 static const char * self_test_result[] = {
696  "Completed ",
697  "Aborted (by user command)",
698  "Aborted (device reset ?) ",
699  "Unknown error, incomplete",
700  "Completed, segment failed",
701  "Failed in first segment ",
702  "Failed in second segment ",
703  "Failed in segment --> ",
704  "Reserved(8) ",
705  "Reserved(9) ",
706  "Reserved(10) ",
707  "Reserved(11) ",
708  "Reserved(12) ",
709  "Reserved(13) ",
710  "Reserved(14) ",
711  "Self test in progress ..."
712 };
713 
714 // See SCSI Primary Commands - 3 (SPC-3) rev 23 (draft) section 7.2.10 .
715 // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent
716 // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or
717 // FAILSMART is returned.
718 static int
720 {
721  int num, k, n, res, err, durationSec;
722  int noheader = 1;
723  int retval = 0;
724  UINT8 * ucp;
725  uint64_t ull=0;
726  struct scsi_sense_disect sense_info;
727 
728  // check if test is running
729  if (!scsiRequestSense(device, &sense_info) &&
730  (sense_info.asc == 0x04 && sense_info.ascq == 0x09 &&
731  sense_info.progress != -1)) {
732  pout("Self-test execution status:\t\t%d%% of test remaining\n",
733  100 - ((sense_info.progress * 100) / 65535));
734  }
735 
736  if ((err = scsiLogSense(device, SELFTEST_RESULTS_LPAGE, 0, gBuf,
737  LOG_RESP_SELF_TEST_LEN, 0))) {
738  print_on();
739  pout("scsiPrintSelfTest Failed [%s]\n", scsiErrString(err));
740  print_off();
741  return FAILSMART;
742  }
743  if ((gBuf[0] & 0x3f) != SELFTEST_RESULTS_LPAGE) {
744  print_on();
745  pout("Self-test Log Sense Failed, page mismatch\n");
746  print_off();
747  return FAILSMART;
748  }
749  // compute page length
750  num = (gBuf[2] << 8) + gBuf[3];
751  // Log sense page length 0x190 bytes
752  if (num != 0x190) {
753  print_on();
754  pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n",num);
755  print_off();
756  return FAILSMART;
757  }
758  // loop through the twenty possible entries
759  for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) {
760  int i;
761 
762  // timestamp in power-on hours (or zero if test in progress)
763  n = (ucp[6] << 8) | ucp[7];
764 
765  // The spec says "all 20 bytes will be zero if no test" but
766  // DG has found otherwise. So this is a heuristic.
767  if ((0 == n) && (0 == ucp[4]))
768  break;
769 
770  // only print header if needed
771  if (noheader) {
772  pout("SMART Self-test log\n");
773  pout("Num Test Status segment "
774  "LifeTime LBA_first_err [SK ASC ASQ]\n");
775  pout(" Description number "
776  "(hours)\n");
777  noheader=0;
778  }
779 
780  // print parameter code (test number) & self-test code text
781  pout("#%2d %s", (ucp[0] << 8) | ucp[1],
782  self_test_code[(ucp[4] >> 5) & 0x7]);
783 
784  // check the self-test result nibble, using the self-test results
785  // field table from T10/1416-D (SPC-3) Rev. 23, section 7.2.10:
786  switch ((res = ucp[4] & 0xf)) {
787  case 0x3:
788  // an unknown error occurred while the device server
789  // was processing the self-test and the device server
790  // was unable to complete the self-test
791  retval|=FAILSMART;
792  break;
793  case 0x4:
794  // the self-test completed with a failure in a test
795  // segment, and the test segment that failed is not
796  // known
797  retval|=FAILLOG;
798  break;
799  case 0x5:
800  // the first segment of the self-test failed
801  retval|=FAILLOG;
802  break;
803  case 0x6:
804  // the second segment of the self-test failed
805  retval|=FAILLOG;
806  break;
807  case 0x7:
808  // another segment of the self-test failed and which
809  // test is indicated by the contents of the SELF-TEST
810  // NUMBER field
811  retval|=FAILLOG;
812  break;
813  default:
814  break;
815  }
816  pout(" %s", self_test_result[res]);
817 
818  // self-test number identifies test that failed and consists
819  // of either the number of the segment that failed during
820  // the test, or the number of the test that failed and the
821  // number of the segment in which the test was run, using a
822  // vendor-specific method of putting both numbers into a
823  // single byte.
824  if (ucp[5])
825  pout(" %3d", (int)ucp[5]);
826  else
827  pout(" -");
828 
829  // print time that the self-test was completed
830  if (n==0 && res==0xf)
831  // self-test in progress
832  pout(" NOW");
833  else
834  pout(" %5d", n);
835 
836  // construct 8-byte integer address of first failure
837  for (i = 0; i < 8; i++) {
838  ull <<= 8;
839  ull |= ucp[i+8];
840  }
841  // print Address of First Failure, if sensible
842  if ((~(uint64_t)0 != ull) && (res > 0) && (res < 0xf)) {
843  char buff[32];
844 
845  // was hex but change to decimal to conform with ATA
846  snprintf(buff, sizeof(buff), "%" PRIu64, ull);
847  // snprintf(buff, sizeof(buff), "0x%" PRIx64, ull);
848  pout("%18s", buff);
849  } else
850  pout(" -");
851 
852  // if sense key nonzero, then print it, along with
853  // additional sense code and additional sense code qualifier
854  if (ucp[16] & 0xf)
855  pout(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]);
856  else
857  pout(" [- - -]\n");
858  }
859 
860  // if header never printed, then there was no output
861  if (noheader)
862  pout("No self-tests have been logged\n");
863  else
864  if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec,
865  modese_len)) && (durationSec > 0)) {
866  pout("\nLong (extended) Self Test duration: %d seconds "
867  "[%.1f minutes]\n", durationSec, durationSec / 60.0);
868  }
869  pout("\n");
870  return retval;
871 }
872 
873 static const char * bms_status[] = {
874  "no scans active",
875  "scan is active",
876  "pre-scan is active",
877  "halted due to fatal error",
878  "halted due to a vendor specific pattern of error",
879  "halted due to medium formatted without P-List",
880  "halted - vendor specific cause",
881  "halted due to temperature out of range",
882  "waiting until BMS interval timer expires", /* 8 */
883 };
884 
885 static const char * reassign_status[] = {
886  "Reserved [0x0]",
887  "Require Write or Reassign Blocks command",
888  "Successfully reassigned",
889  "Reserved [0x3]",
890  "Reassignment by disk failed",
891  "Recovered via rewrite in-place",
892  "Reassigned by app, has valid data",
893  "Reassigned by app, has no valid data",
894  "Unsuccessfully reassigned by app", /* 8 */
895 };
896 
897 // See SCSI Block Commands - 3 (SBC-3) rev 6 (draft) section 6.2.2 .
898 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
899 // and up to 2048 events (although would hope to have less). May set
900 // FAILLOG if serious errors detected (in the future).
901 static int
903 {
904  int num, j, m, err, pc, pl, truncated;
905  int noheader = 1;
906  int firstresult = 1;
907  int retval = 0;
908  UINT8 * ucp;
909 
910  if ((err = scsiLogSense(device, BACKGROUND_RESULTS_LPAGE, 0, gBuf,
911  LOG_RESP_LONG_LEN, 0))) {
912  print_on();
913  pout("scsiPrintBackgroundResults Failed [%s]\n", scsiErrString(err));
914  print_off();
915  return FAILSMART;
916  }
917  if ((gBuf[0] & 0x3f) != BACKGROUND_RESULTS_LPAGE) {
918  print_on();
919  pout("Background scan results Log Sense Failed, page mismatch\n");
920  print_off();
921  return FAILSMART;
922  }
923  // compute page length
924  num = (gBuf[2] << 8) + gBuf[3] + 4;
925  if (num < 20) {
926  print_on();
927  pout("Background scan results Log Sense length is %d, no scan "
928  "status\n", num);
929  print_off();
930  return FAILSMART;
931  }
932  truncated = (num > LOG_RESP_LONG_LEN) ? num : 0;
933  if (truncated)
934  num = LOG_RESP_LONG_LEN;
935  ucp = gBuf + 4;
936  num -= 4;
937  while (num > 3) {
938  pc = (ucp[0] << 8) | ucp[1];
939  // pcb = ucp[2];
940  pl = ucp[3] + 4;
941  switch (pc) {
942  case 0:
943  if (noheader) {
944  noheader = 0;
945  pout("Background scan results log\n");
946  }
947  pout(" Status: ");
948  if ((pl < 16) || (num < 16)) {
949  pout("\n");
950  break;
951  }
952  j = ucp[9];
953  if (j < (int)(sizeof(bms_status) / sizeof(bms_status[0])))
954  pout("%s\n", bms_status[j]);
955  else
956  pout("unknown [0x%x] background scan status value\n", j);
957  j = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
958  pout(" Accumulated power on time, hours:minutes %d:%02d "
959  "[%d minutes]\n", (j / 60), (j % 60), j);
960  pout(" Number of background scans performed: %d, ",
961  (ucp[10] << 8) + ucp[11]);
962  pout("scan progress: %.2f%%\n",
963  (double)((ucp[12] << 8) + ucp[13]) * 100.0 / 65536.0);
964  pout(" Number of background medium scans performed: %d\n",
965  (ucp[14] << 8) + ucp[15]);
966  break;
967  default:
968  if (noheader) {
969  noheader = 0;
970  pout("\nBackground scan results log\n");
971  }
972  if (firstresult) {
973  firstresult = 0;
974  pout("\n # when lba(hex) [sk,asc,ascq] "
975  "reassign_status\n");
976  }
977  pout(" %3d ", pc);
978  if ((pl < 24) || (num < 24)) {
979  if (pl < 24)
980  pout("parameter length >= 24 expected, got %d\n", pl);
981  break;
982  }
983  j = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
984  pout("%4d:%02d ", (j / 60), (j % 60));
985  for (m = 0; m < 8; ++m)
986  pout("%02x", ucp[16 + m]);
987  pout(" [%x,%x,%x] ", ucp[8] & 0xf, ucp[9], ucp[10]);
988  j = (ucp[8] >> 4) & 0xf;
989  if (j <
990  (int)(sizeof(reassign_status) / sizeof(reassign_status[0])))
991  pout("%s\n", reassign_status[j]);
992  else
993  pout("Reassign status: reserved [0x%x]\n", j);
994  break;
995  }
996  num -= pl;
997  ucp += pl;
998  }
999  if (truncated)
1000  pout(" >>>> log truncated, fetched %d of %d available "
1001  "bytes\n", LOG_RESP_LONG_LEN, truncated);
1002  pout("\n");
1003  return retval;
1004 }
1005 
1006 // See SCSI Block Commands - 3 (SBC-3) rev 27 (draft) section 6.3.6 .
1007 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
1008 // and up to 2048 events (although would hope to have less). May set
1009 // FAILLOG if serious errors detected (in the future).
1010 static int
1012 {
1013  int num, err, pc, pl, truncated;
1014  int retval = 0;
1015  UINT8 * ucp;
1016 
1017  if ((err = scsiLogSense(device, SS_MEDIA_LPAGE, 0, gBuf,
1018  LOG_RESP_LONG_LEN, 0))) {
1019  print_on();
1020  pout("scsiPrintSSMedia Failed [%s]\n", scsiErrString(err));
1021  print_off();
1022  return FAILSMART;
1023  }
1024  if ((gBuf[0] & 0x3f) != SS_MEDIA_LPAGE) {
1025  print_on();
1026  pout("Solid state media Log Sense Failed, page mismatch\n");
1027  print_off();
1028  return FAILSMART;
1029  }
1030  // compute page length
1031  num = (gBuf[2] << 8) + gBuf[3] + 4;
1032  if (num < 12) {
1033  print_on();
1034  pout("Solid state media Log Sense length is %d, too short\n", num);
1035  print_off();
1036  return FAILSMART;
1037  }
1038  truncated = (num > LOG_RESP_LONG_LEN) ? num : 0;
1039  if (truncated)
1040  num = LOG_RESP_LONG_LEN;
1041  ucp = gBuf + 4;
1042  num -= 4;
1043  while (num > 3) {
1044  pc = (ucp[0] << 8) | ucp[1];
1045  // pcb = ucp[2];
1046  pl = ucp[3] + 4;
1047  switch (pc) {
1048  case 1:
1049  if (pl < 8) {
1050  print_on();
1051  pout("SS Media Percentage used endurance indicator parameter "
1052  "too short (pl=%d)\n", pl);
1053  print_off();
1054  return FAILSMART;
1055  }
1056  pout("Percentage used endurance indicator: %d%%\n", ucp[7]);
1057  default: /* ignore other parameter codes */
1058  break;
1059  }
1060  num -= pl;
1061  ucp += pl;
1062  }
1063  return retval;
1064 }
1065 
1066 static void
1067 show_sas_phy_event_info(int peis, unsigned int val, unsigned thresh_val)
1068 {
1069  unsigned int u;
1070 
1071  switch (peis) {
1072  case 0:
1073  pout(" No event\n");
1074  break;
1075  case 0x1:
1076  pout(" Invalid word count: %u\n", val);
1077  break;
1078  case 0x2:
1079  pout(" Running disparity error count: %u\n", val);
1080  break;
1081  case 0x3:
1082  pout(" Loss of dword synchronization count: %u\n", val);
1083  break;
1084  case 0x4:
1085  pout(" Phy reset problem count: %u\n", val);
1086  break;
1087  case 0x5:
1088  pout(" Elasticity buffer overflow count: %u\n", val);
1089  break;
1090  case 0x6:
1091  pout(" Received ERROR count: %u\n", val);
1092  break;
1093  case 0x20:
1094  pout(" Received address frame error count: %u\n", val);
1095  break;
1096  case 0x21:
1097  pout(" Transmitted abandon-class OPEN_REJECT count: %u\n", val);
1098  break;
1099  case 0x22:
1100  pout(" Received abandon-class OPEN_REJECT count: %u\n", val);
1101  break;
1102  case 0x23:
1103  pout(" Transmitted retry-class OPEN_REJECT count: %u\n", val);
1104  break;
1105  case 0x24:
1106  pout(" Received retry-class OPEN_REJECT count: %u\n", val);
1107  break;
1108  case 0x25:
1109  pout(" Received AIP (WATING ON PARTIAL) count: %u\n", val);
1110  break;
1111  case 0x26:
1112  pout(" Received AIP (WAITING ON CONNECTION) count: %u\n", val);
1113  break;
1114  case 0x27:
1115  pout(" Transmitted BREAK count: %u\n", val);
1116  break;
1117  case 0x28:
1118  pout(" Received BREAK count: %u\n", val);
1119  break;
1120  case 0x29:
1121  pout(" Break timeout count: %u\n", val);
1122  break;
1123  case 0x2a:
1124  pout(" Connection count: %u\n", val);
1125  break;
1126  case 0x2b:
1127  pout(" Peak transmitted pathway blocked count: %u\n",
1128  val & 0xff);
1129  pout(" Peak value detector threshold: %u\n",
1130  thresh_val & 0xff);
1131  break;
1132  case 0x2c:
1133  u = val & 0xffff;
1134  if (u < 0x8000)
1135  pout(" Peak transmitted arbitration wait time (us): "
1136  "%u\n", u);
1137  else
1138  pout(" Peak transmitted arbitration wait time (ms): "
1139  "%u\n", 33 + (u - 0x8000));
1140  u = thresh_val & 0xffff;
1141  if (u < 0x8000)
1142  pout(" Peak value detector threshold (us): %u\n",
1143  u);
1144  else
1145  pout(" Peak value detector threshold (ms): %u\n",
1146  33 + (u - 0x8000));
1147  break;
1148  case 0x2d:
1149  pout(" Peak arbitration time (us): %u\n", val);
1150  pout(" Peak value detector threshold: %u\n", thresh_val);
1151  break;
1152  case 0x2e:
1153  pout(" Peak connection time (us): %u\n", val);
1154  pout(" Peak value detector threshold: %u\n", thresh_val);
1155  break;
1156  case 0x40:
1157  pout(" Transmitted SSP frame count: %u\n", val);
1158  break;
1159  case 0x41:
1160  pout(" Received SSP frame count: %u\n", val);
1161  break;
1162  case 0x42:
1163  pout(" Transmitted SSP frame error count: %u\n", val);
1164  break;
1165  case 0x43:
1166  pout(" Received SSP frame error count: %u\n", val);
1167  break;
1168  case 0x44:
1169  pout(" Transmitted CREDIT_BLOCKED count: %u\n", val);
1170  break;
1171  case 0x45:
1172  pout(" Received CREDIT_BLOCKED count: %u\n", val);
1173  break;
1174  case 0x50:
1175  pout(" Transmitted SATA frame count: %u\n", val);
1176  break;
1177  case 0x51:
1178  pout(" Received SATA frame count: %u\n", val);
1179  break;
1180  case 0x52:
1181  pout(" SATA flow control buffer overflow count: %u\n", val);
1182  break;
1183  case 0x60:
1184  pout(" Transmitted SMP frame count: %u\n", val);
1185  break;
1186  case 0x61:
1187  pout(" Received SMP frame count: %u\n", val);
1188  break;
1189  case 0x63:
1190  pout(" Received SMP frame error count: %u\n", val);
1191  break;
1192  default:
1193  break;
1194  }
1195 }
1196 
1197 static void
1198 show_sas_port_param(unsigned char * ucp, int param_len)
1199 {
1200  int j, m, n, nphys, t, sz, spld_len;
1201  unsigned char * vcp;
1202  uint64_t ull;
1203  unsigned int ui;
1204  char s[64];
1205 
1206  sz = sizeof(s);
1207  // pcb = ucp[2];
1208  t = (ucp[0] << 8) | ucp[1];
1209  pout("relative target port id = %d\n", t);
1210  pout(" generation code = %d\n", ucp[6]);
1211  nphys = ucp[7];
1212  pout(" number of phys = %d\n", nphys);
1213 
1214  for (j = 0, vcp = ucp + 8; j < (param_len - 8);
1215  vcp += spld_len, j += spld_len) {
1216  pout(" phy identifier = %d\n", vcp[1]);
1217  spld_len = vcp[3];
1218  if (spld_len < 44)
1219  spld_len = 48; /* in SAS-1 and SAS-1.1 vcp[3]==0 */
1220  else
1221  spld_len += 4;
1222  t = ((0x70 & vcp[4]) >> 4);
1223  switch (t) {
1224  case 0: snprintf(s, sz, "no device attached"); break;
1225  case 1: snprintf(s, sz, "SAS or SATA device"); break;
1226  case 2: snprintf(s, sz, "expander device"); break;
1227  case 3: snprintf(s, sz, "expander device (fanout)"); break;
1228  default: snprintf(s, sz, "reserved [%d]", t); break;
1229  }
1230  pout(" attached device type: %s\n", s);
1231  t = 0xf & vcp[4];
1232  switch (t) {
1233  case 0: snprintf(s, sz, "unknown"); break;
1234  case 1: snprintf(s, sz, "power on"); break;
1235  case 2: snprintf(s, sz, "hard reset"); break;
1236  case 3: snprintf(s, sz, "SMP phy control function"); break;
1237  case 4: snprintf(s, sz, "loss of dword synchronization"); break;
1238  case 5: snprintf(s, sz, "mux mix up"); break;
1239  case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
1240  break;
1241  case 7: snprintf(s, sz, "break timeout timer expired"); break;
1242  case 8: snprintf(s, sz, "phy test function stopped"); break;
1243  case 9: snprintf(s, sz, "expander device reduced functionality");
1244  break;
1245  default: snprintf(s, sz, "reserved [0x%x]", t); break;
1246  }
1247  pout(" attached reason: %s\n", s);
1248  t = (vcp[5] & 0xf0) >> 4;
1249  switch (t) {
1250  case 0: snprintf(s, sz, "unknown"); break;
1251  case 1: snprintf(s, sz, "power on"); break;
1252  case 2: snprintf(s, sz, "hard reset"); break;
1253  case 3: snprintf(s, sz, "SMP phy control function"); break;
1254  case 4: snprintf(s, sz, "loss of dword synchronization"); break;
1255  case 5: snprintf(s, sz, "mux mix up"); break;
1256  case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
1257  break;
1258  case 7: snprintf(s, sz, "break timeout timer expired"); break;
1259  case 8: snprintf(s, sz, "phy test function stopped"); break;
1260  case 9: snprintf(s, sz, "expander device reduced functionality");
1261  break;
1262  default: snprintf(s, sz, "reserved [0x%x]", t); break;
1263  }
1264  pout(" reason: %s\n", s);
1265  t = (0xf & vcp[5]);
1266  switch (t) {
1267  case 0: snprintf(s, sz, "phy enabled; unknown");
1268  break;
1269  case 1: snprintf(s, sz, "phy disabled"); break;
1270  case 2: snprintf(s, sz, "phy enabled; speed negotiation failed");
1271  break;
1272  case 3: snprintf(s, sz, "phy enabled; SATA spinup hold state");
1273  break;
1274  case 4: snprintf(s, sz, "phy enabled; port selector");
1275  break;
1276  case 5: snprintf(s, sz, "phy enabled; reset in progress");
1277  break;
1278  case 6: snprintf(s, sz, "phy enabled; unsupported phy attached");
1279  break;
1280  case 8: snprintf(s, sz, "phy enabled; 1.5 Gbps"); break;
1281  case 9: snprintf(s, sz, "phy enabled; 3 Gbps"); break;
1282  case 0xa: snprintf(s, sz, "phy enabled; 6 Gbps"); break;
1283  case 0xb: snprintf(s, sz, "phy enabled; 12 Gbps"); break;
1284  default: snprintf(s, sz, "reserved [%d]", t); break;
1285  }
1286  pout(" negotiated logical link rate: %s\n", s);
1287  pout(" attached initiator port: ssp=%d stp=%d smp=%d\n",
1288  !! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2));
1289  pout(" attached target port: ssp=%d stp=%d smp=%d\n",
1290  !! (vcp[7] & 8), !! (vcp[7] & 4), !! (vcp[7] & 2));
1291  for (n = 0, ull = vcp[8]; n < 8; ++n) {
1292  ull <<= 8; ull |= vcp[8 + n];
1293  }
1294  pout(" SAS address = 0x%" PRIx64 "\n", ull);
1295  for (n = 0, ull = vcp[16]; n < 8; ++n) {
1296  ull <<= 8; ull |= vcp[16 + n];
1297  }
1298  pout(" attached SAS address = 0x%" PRIx64 "\n", ull);
1299  pout(" attached phy identifier = %d\n", vcp[24]);
1300  ui = (vcp[32] << 24) | (vcp[33] << 16) | (vcp[34] << 8) | vcp[35];
1301  pout(" Invalid DWORD count = %u\n", ui);
1302  ui = (vcp[36] << 24) | (vcp[37] << 16) | (vcp[38] << 8) | vcp[39];
1303  pout(" Running disparity error count = %u\n", ui);
1304  ui = (vcp[40] << 24) | (vcp[41] << 16) | (vcp[42] << 8) | vcp[43];
1305  pout(" Loss of DWORD synchronization = %u\n", ui);
1306  ui = (vcp[44] << 24) | (vcp[45] << 16) | (vcp[46] << 8) | vcp[47];
1307  pout(" Phy reset problem = %u\n", ui);
1308  if (spld_len > 51) {
1309  int num_ped, peis;
1310  unsigned char * xcp;
1311  unsigned int pvdt;
1312 
1313  num_ped = vcp[51];
1314  if (num_ped > 0)
1315  pout(" Phy event descriptors:\n");
1316  xcp = vcp + 52;
1317  for (m = 0; m < (num_ped * 12); m += 12, xcp += 12) {
1318  peis = xcp[3];
1319  ui = (xcp[4] << 24) | (xcp[5] << 16) | (xcp[6] << 8) |
1320  xcp[7];
1321  pvdt = (xcp[8] << 24) | (xcp[9] << 16) | (xcp[10] << 8) |
1322  xcp[11];
1323  show_sas_phy_event_info(peis, ui, pvdt);
1324  }
1325  }
1326  }
1327 }
1328 
1329 // Returns 1 if okay, 0 if non SAS descriptors
1330 static int
1331 show_protocol_specific_page(unsigned char * resp, int len)
1332 {
1333  int k, num, param_len;
1334  unsigned char * ucp;
1335 
1336  num = len - 4;
1337  for (k = 0, ucp = resp + 4; k < num; ) {
1338  param_len = ucp[3] + 4;
1339  if (6 != (0xf & ucp[4]))
1340  return 0; /* only decode SAS log page */
1341  if (0 == k)
1342  pout("Protocol Specific port log page for SAS SSP\n");
1343  show_sas_port_param(ucp, param_len);
1344  k += param_len;
1345  ucp += param_len;
1346  }
1347  pout("\n");
1348  return 1;
1349 }
1350 
1351 
1352 // See Serial Attached SCSI (SPL-3) (e.g. revision 6g) the Protocol Specific
1353 // log page [0x18]. Returns 0 if ok else FAIL* bitmask.
1354 static int
1355 scsiPrintSasPhy(scsi_device * device, int reset)
1356 {
1357  int num, err;
1358 
1359  if ((err = scsiLogSense(device, PROTOCOL_SPECIFIC_LPAGE, 0, gBuf,
1360  LOG_RESP_LONG_LEN, 0))) {
1361  print_on();
1362  pout("scsiPrintSasPhy Log Sense Failed [%s]\n\n", scsiErrString(err));
1363  print_off();
1364  return FAILSMART;
1365  }
1366  if ((gBuf[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE) {
1367  print_on();
1368  pout("Protocol specific Log Sense Failed, page mismatch\n\n");
1369  print_off();
1370  return FAILSMART;
1371  }
1372  // compute page length
1373  num = (gBuf[2] << 8) + gBuf[3];
1374  if (1 != show_protocol_specific_page(gBuf, num + 4)) {
1375  print_on();
1376  pout("Only support protocol specific log page on SAS devices\n\n");
1377  print_off();
1378  return FAILSMART;
1379  }
1380  if (reset) {
1381  if ((err = scsiLogSelect(device, 1 /* pcr */, 0 /* sp */, 0 /* pc */,
1382  PROTOCOL_SPECIFIC_LPAGE, 0, NULL, 0))) {
1383  print_on();
1384  pout("scsiPrintSasPhy Log Select (reset) Failed [%s]\n\n",
1385  scsiErrString(err));
1386  print_off();
1387  return FAILSMART;
1388  }
1389  }
1390  return 0;
1391 }
1392 
1393 
1394 static const char * peripheral_dt_arr[] = {
1395  "disk",
1396  "tape",
1397  "printer",
1398  "processor",
1399  "optical disk(4)",
1400  "CD/DVD",
1401  "scanner",
1402  "optical disk(7)",
1403  "medium changer",
1404  "communications",
1405  "graphics(10)",
1406  "graphics(11)",
1407  "storage array",
1408  "enclosure",
1409  "simplified disk",
1410  "optical card reader"
1411  "reserved [0x10]"
1412  "object based storage"
1413  "automation/driver interface"
1414  "security manager device"
1415  "host managed zoned block device"
1416  "reserved [0x15]"
1417  "reserved [0x16]"
1418  "reserved [0x17]"
1419  "reserved [0x18]"
1420  "reserved [0x19]"
1421  "reserved [0x1a]"
1422  "reserved [0x1b]"
1423  "reserved [0x1c]"
1424  "reserved [0x1d]"
1425  "well known logical unit"
1426  "unknown or no device type"
1427 };
1428 
1429 static const char * transport_proto_arr[] = {
1430  "Fibre channel (FCP-2)",
1431  "Parallel SCSI (SPI-4)",
1432  "SSA",
1433  "IEEE 1394 (SBP-2)",
1434  "RDMA (SRP)",
1435  "iSCSI",
1436  "SAS (SPL-3)",
1437  "ADT",
1438  "ATA (ACS-2)",
1439  "UAS",
1440  "SOP",
1441  "0xb",
1442  "0xc",
1443  "0xd",
1444  "0xe",
1445  "0xf"
1446 };
1447 
1448 /* Returns 0 on success, 1 on general error and 2 for early, clean exit */
1449 static int
1450 scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all)
1451 {
1452  char timedatetz[DATEANDEPOCHLEN];
1453  struct scsi_iec_mode_page iec;
1454  int err, iec_err, len, req_len, avail_len, n, scsi_version;
1455  int is_tape = 0;
1456  int peri_dt = 0;
1457  int returnval = 0;
1458  int transport = -1;
1459  int form_factor = 0;
1460  int haw_zbc = 0;
1461  int protect = 0;
1462 
1463  memset(gBuf, 0, 96);
1464  req_len = 36;
1465  if ((err = scsiStdInquiry(device, gBuf, req_len))) {
1466  print_on();
1467  pout("Standard Inquiry (36 bytes) failed [%s]\n", scsiErrString(err));
1468  pout("Retrying with a 64 byte Standard Inquiry\n");
1469  print_off();
1470  /* Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices */
1471  req_len = 64;
1472  if ((err = scsiStdInquiry(device, gBuf, req_len))) {
1473  print_on();
1474  pout("Standard Inquiry (64 bytes) failed [%s]\n",
1475  scsiErrString(err));
1476  print_off();
1477  return 1;
1478  }
1479  }
1480  avail_len = gBuf[4] + 5;
1481  len = (avail_len < req_len) ? avail_len : req_len;
1482  peri_dt = gBuf[0] & 0x1f;
1483  if (peripheral_type)
1484  *peripheral_type = peri_dt;
1485 
1486  if (len < 36) {
1487  print_on();
1488  pout("Short INQUIRY response, skip product id\n");
1489  print_off();
1490  return 1;
1491  }
1492  // Upper bits of version bytes were used in older standards
1493  // Only interested in SPC-4 (0x6) and SPC-5 (assumed to be 0x7)
1494  scsi_version = gBuf[2] & 0x7;
1495 
1496  if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) {
1497  char vendor[8+1], product[16+1], revision[4+1];
1498  scsi_format_id_string(vendor, (const unsigned char *)&gBuf[8], 8);
1499  scsi_format_id_string(product, (const unsigned char *)&gBuf[16], 16);
1500  scsi_format_id_string(revision, (const unsigned char *)&gBuf[32], 4);
1501 
1502  pout("=== START OF INFORMATION SECTION ===\n");
1503  pout("Vendor: %.8s\n", vendor);
1504  pout("Product: %.16s\n", product);
1505  if (gBuf[32] >= ' ')
1506  pout("Revision: %.4s\n", revision);
1507  if (scsi_version == 0x6)
1508  pout("Compliance: SPC-4\n");
1509  else if (scsi_version == 0x7)
1510  pout("Compliance: SPC-5\n");
1511  }
1512 
1513  if (!*device->get_req_type()/*no type requested*/ &&
1514  (0 == strncmp((char *)&gBuf[8], "ATA", 3))) {
1515  pout("\nProbable ATA device behind a SAT layer\n"
1516  "Try an additional '-d ata' or '-d sat' argument.\n");
1517  return 2;
1518  }
1519  if (! all)
1520  return 0;
1521 
1522  protect = gBuf[5] & 0x1; /* from and including SPC-3 */
1523 
1524  if (! is_tape) { /* only do this for disks */
1525  unsigned int lb_size = 0;
1526  unsigned char lb_prov_resp[8];
1527  char cap_str[64];
1528  char si_str[64];
1529  char lb_str[16];
1530  int lb_per_pb_exp = 0;
1531  uint64_t capacity = scsiGetSize(device, &lb_size, &lb_per_pb_exp);
1532 
1533  if (capacity) {
1534  format_with_thousands_sep(cap_str, sizeof(cap_str), capacity);
1535  format_capacity(si_str, sizeof(si_str), capacity);
1536  pout("User Capacity: %s bytes [%s]\n", cap_str, si_str);
1537  snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size);
1538  pout("Logical block size: %s bytes\n", lb_str);
1539  }
1540  int lbpme = -1;
1541  int lbprz = -1;
1542  if (protect || lb_per_pb_exp) {
1543  unsigned char rc16_12[20] = {0, };
1544 
1545  if (0 == scsiGetProtPBInfo(device, rc16_12)) {
1546  lb_per_pb_exp = rc16_12[1] & 0xf; /* just in case */
1547  if (lb_per_pb_exp > 0) {
1548  snprintf(lb_str, sizeof(lb_str) - 1, "%u",
1549  (lb_size * (1 << lb_per_pb_exp)));
1550  pout("Physical block size: %s bytes\n", lb_str);
1551  n = ((rc16_12[2] & 0x3f) << 8) + rc16_12[3];
1552  if (n > 0) // not common so cut the clutter
1553  pout("Lowest aligned LBA: %d\n", n);
1554  }
1555  if (rc16_12[0] & 0x1) { /* PROT_EN set */
1556  int p_type = ((rc16_12[0] >> 1) & 0x7);
1557 
1558  switch (p_type) {
1559  case 0 :
1560  pout("Formatted with type 1 protection\n");
1561  break;
1562  case 1 :
1563  pout("Formatted with type 2 protection\n");
1564  break;
1565  case 2 :
1566  pout("Formatted with type 3 protection\n");
1567  break;
1568  default:
1569  pout("Formatted with unknown protection type [%d]\n",
1570  p_type);
1571  break;
1572  }
1573  int p_i_exp = ((rc16_12[1] >> 4) & 0xf);
1574 
1575  if (p_i_exp > 0)
1576  pout("%d protection information intervals per "
1577  "logical block\n", (1 << p_i_exp));
1578  }
1579  /* Pick up some LB provisioning info since its available */
1580  lbpme = !! (rc16_12[2] & 0x80);
1581  lbprz = !! (rc16_12[2] & 0x40);
1582  }
1583  }
1585  lb_prov_resp, sizeof(lb_prov_resp))) {
1586  int prov_type = lb_prov_resp[6] & 0x7;
1587 
1588  if (-1 == lbprz)
1589  lbprz = !! (lb_prov_resp[5] & 0x4);
1590  switch (prov_type) {
1591  case 0:
1592  pout("LB provisioning type: unreported, LBPME=%d, LBPRZ=%d\n",
1593  lbpme, lbprz);
1594  break;
1595  case 1:
1596  pout("LU is resource provisioned, LBPRZ=%d\n", lbprz);
1597  break;
1598  case 2:
1599  pout("LU is thin provisioned, LBPRZ=%d\n", lbprz);
1600  break;
1601  default:
1602  pout("LU provisioning type reserved [%d], LBPRZ=%d\n",
1603  prov_type, lbprz);
1604  break;
1605  }
1606  } else if (1 == lbpme)
1607  pout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz);
1608 
1609  int rpm = scsiGetRPM(device, modese_len, &form_factor, &haw_zbc);
1610  if (rpm >= 0) {
1611  if (0 == rpm)
1612  ; // Not reported
1613  else if (1 == rpm)
1614  pout("Rotation Rate: Solid State Device\n");
1615  else if ((rpm <= 0x400) || (0xffff == rpm))
1616  ; // Reserved
1617  else
1618  pout("Rotation Rate: %d rpm\n", rpm);
1619  }
1620  if (form_factor > 0) {
1621  const char * cp = NULL;
1622 
1623  switch (form_factor) {
1624  case 1:
1625  cp = "5.25";
1626  break;
1627  case 2:
1628  cp = "3.5";
1629  break;
1630  case 3:
1631  cp = "2.5";
1632  break;
1633  case 4:
1634  cp = "1.8";
1635  break;
1636  case 5:
1637  cp = "< 1.8";
1638  break;
1639  }
1640  if (cp)
1641  pout("Form Factor: %s inches\n", cp);
1642  }
1643  if (haw_zbc > 0)
1644  pout("Host aware zoned block capable\n");
1645  }
1646 
1647  /* Do this here to try and detect badly conforming devices (some USB
1648  keys) that will lock up on a InquiryVpd or log sense or ... */
1649  if ((iec_err = scsiFetchIECmpage(device, &iec, modese_len))) {
1650  if (SIMPLE_ERR_BAD_RESP == iec_err) {
1651  pout(">> Terminate command early due to bad response to IEC "
1652  "mode page\n");
1653  print_off();
1654  gIecMPage = 0;
1655  return 1;
1656  }
1657  } else
1658  modese_len = iec.modese_len;
1659 
1660  if (! dont_print_serial_number) {
1661  if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_DEVICE_IDENTIFICATION,
1662  gBuf, 252))) {
1663  char s[256];
1664 
1665  len = gBuf[3];
1666  scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport);
1667  if (strlen(s) > 0)
1668  pout("Logical Unit id: %s\n", s);
1669  } else if (scsi_debugmode > 0) {
1670  print_on();
1671  if (SIMPLE_ERR_BAD_RESP == err)
1672  pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
1673  else
1674  pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
1675  print_off();
1676  }
1677  if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_UNIT_SERIAL_NUMBER,
1678  gBuf, 252))) {
1679  char serial[256];
1680  len = gBuf[3];
1681 
1682  gBuf[4 + len] = '\0';
1683  scsi_format_id_string(serial, &gBuf[4], len);
1684  pout("Serial number: %s\n", serial);
1685  } else if (scsi_debugmode > 0) {
1686  print_on();
1687  if (SIMPLE_ERR_BAD_RESP == err)
1688  pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
1689  else
1690  pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
1691  print_off();
1692  }
1693  }
1694 
1695  // print SCSI peripheral device type
1696  if (peri_dt < (int)(sizeof(peripheral_dt_arr) /
1697  sizeof(peripheral_dt_arr[0])))
1698  pout("Device type: %s\n", peripheral_dt_arr[peri_dt]);
1699  else
1700  pout("Device type: <%d>\n", peri_dt);
1701 
1702  // See if transport protocol is known
1703  if (transport < 0)
1704  transport = scsiFetchTransportProtocol(device, modese_len);
1705  if ((transport >= 0) && (transport <= 0xf))
1706  pout("Transport protocol: %s\n", transport_proto_arr[transport]);
1707 
1708  // print current time and date and timezone
1709  dateandtimezone(timedatetz);
1710  pout("Local Time is: %s\n", timedatetz);
1711 
1712  if ((SCSI_PT_SEQUENTIAL_ACCESS == *peripheral_type) ||
1713  (SCSI_PT_MEDIUM_CHANGER == *peripheral_type))
1714  is_tape = 1;
1715  // See if unit accepts SCSI commmands from us
1716  if ((err = scsiTestUnitReady(device))) {
1717  if (SIMPLE_ERR_NOT_READY == err) {
1718  print_on();
1719  if (!is_tape)
1720  pout("device is NOT READY (e.g. spun down, busy)\n");
1721  else
1722  pout("device is NOT READY (e.g. no tape)\n");
1723  print_off();
1724  } else if (SIMPLE_ERR_NO_MEDIUM == err) {
1725  print_on();
1726  pout("NO MEDIUM present on device\n");
1727  print_off();
1728  } else if (SIMPLE_ERR_BECOMING_READY == err) {
1729  print_on();
1730  pout("device becoming ready (wait)\n");
1731  print_off();
1732  } else {
1733  print_on();
1734  pout("device Test Unit Ready [%s]\n", scsiErrString(err));
1735  print_off();
1736  }
1737  failuretest(MANDATORY_CMD, returnval|=FAILID);
1738  }
1739 
1740  if (iec_err) {
1741  if (!is_tape) {
1742  print_on();
1743  pout("SMART support is: Unavailable - device lacks SMART capability.\n");
1744  if (scsi_debugmode > 0)
1745  pout(" [%s]\n", scsiErrString(iec_err));
1746  print_off();
1747  }
1748  gIecMPage = 0;
1749  return 0;
1750  }
1751 
1752  if (!is_tape)
1753  pout("SMART support is: Available - device has SMART capability.\n"
1754  "SMART support is: %s\n",
1755  (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled");
1756  pout("%s\n", (scsi_IsWarningEnabled(&iec)) ?
1757  "Temperature Warning: Enabled" :
1758  "Temperature Warning: Disabled or Not Supported");
1759  return 0;
1760 }
1761 
1762 static int
1764 {
1765  struct scsi_iec_mode_page iec;
1766  int err;
1767 
1768  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1769  print_on();
1770  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1771  scsiErrString(err));
1772  print_off();
1773  return 1;
1774  } else
1775  modese_len = iec.modese_len;
1776 
1777  if ((err = scsiSetExceptionControlAndWarning(device, 1, &iec))) {
1778  print_on();
1779  pout("unable to enable Exception control and warning [%s]\n",
1780  scsiErrString(err));
1781  print_off();
1782  return 1;
1783  }
1784  /* Need to refetch 'iec' since could be modified by previous call */
1785  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1786  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1787  scsiErrString(err));
1788  return 1;
1789  } else
1790  modese_len = iec.modese_len;
1791 
1792  pout("Informational Exceptions (SMART) %s\n",
1793  scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled");
1794  pout("Temperature warning %s\n",
1795  scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled");
1796  return 0;
1797 }
1798 
1799 static int
1801 {
1802  struct scsi_iec_mode_page iec;
1803  int err;
1804 
1805  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1806  print_on();
1807  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1808  scsiErrString(err));
1809  print_off();
1810  return 1;
1811  } else
1812  modese_len = iec.modese_len;
1813 
1814  if ((err = scsiSetExceptionControlAndWarning(device, 0, &iec))) {
1815  print_on();
1816  pout("unable to disable Exception control and warning [%s]\n",
1817  scsiErrString(err));
1818  print_off();
1819  return 1;
1820  }
1821  /* Need to refetch 'iec' since could be modified by previous call */
1822  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1823  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1824  scsiErrString(err));
1825  return 1;
1826  } else
1827  modese_len = iec.modese_len;
1828 
1829  pout("Informational Exceptions (SMART) %s\n",
1830  scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled");
1831  pout("Temperature warning %s\n",
1832  scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled");
1833  return 0;
1834 }
1835 
1836 static void
1838 {
1839  UINT8 temp = 0;
1840  UINT8 trip = 0;
1841 
1842  if (scsiGetTemp(device, &temp, &trip))
1843  return;
1844 
1845  if (temp) {
1846  if (255 != temp)
1847  pout("Current Drive Temperature: %d C\n", temp);
1848  else
1849  pout("Current Drive Temperature: <not available>\n");
1850  }
1851  if (trip)
1852  pout("Drive Trip Temperature: %d C\n", trip);
1853  if (temp || trip)
1854  pout("\n");
1855 }
1856 
1857 /* Main entry point used by smartctl command. Return 0 for success */
1858 int
1860 {
1861  int checkedSupportedLogPages = 0;
1862  UINT8 peripheral_type = 0;
1863  int returnval = 0;
1864  int res, durationSec;
1865  struct scsi_sense_disect sense_info;
1866 
1867  bool any_output = options.drive_info;
1868 
1869  if (supported_vpd_pages_p) {
1870  delete supported_vpd_pages_p;
1871  supported_vpd_pages_p = NULL;
1872  }
1874 
1875  res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info);
1876  if (res) {
1877  if (2 == res)
1878  return 0;
1879  else
1880  failuretest(MANDATORY_CMD, returnval |= FAILID);
1881  any_output = true;
1882  }
1883 
1884  // Print read look-ahead status for disks
1885  short int wce = -1, rcd = -1;
1886  if (options.get_rcd || options.get_wce) {
1887  if (SCSI_PT_DIRECT_ACCESS == peripheral_type)
1888  res = scsiGetSetCache(device, modese_len, &wce, &rcd);
1889  else
1890  res = -1; // fetch for disks only
1891  any_output = true;
1892  }
1893 
1894  if (options.get_rcd) {
1895  pout("Read Cache is: %s\n",
1896  res ? "Unavailable" : // error
1897  rcd ? "Disabled" : "Enabled");
1898  }
1899 
1900  if (options.get_wce) {
1901  pout("Writeback Cache is: %s\n",
1902  res ? "Unavailable" : // error
1903  !wce ? "Disabled" : "Enabled");
1904  }
1905  if (options.drive_info)
1906  pout("\n");
1907 
1908  // START OF THE ENABLE/DISABLE SECTION OF THE CODE
1909  if ( options.smart_disable || options.smart_enable
1910  || options.smart_auto_save_disable || options.smart_auto_save_enable)
1911  pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
1912 
1913  if (options.smart_enable) {
1914  if (scsiSmartEnable(device))
1915  failuretest(MANDATORY_CMD, returnval |= FAILSMART);
1916  any_output = true;
1917  }
1918 
1919  if (options.smart_disable) {
1920  if (scsiSmartDisable(device))
1921  failuretest(MANDATORY_CMD,returnval |= FAILSMART);
1922  any_output = true;
1923  }
1924 
1925  if (options.smart_auto_save_enable) {
1926  if (scsiSetControlGLTSD(device, 0, modese_len)) {
1927  pout("Enable autosave (clear GLTSD bit) failed\n");
1928  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1929  }
1930  else {
1931  pout("Autosave enabled (GLTSD bit set).\n");
1932  }
1933  any_output = true;
1934  }
1935 
1936  // Enable/Disable write cache
1937  if (options.set_wce && SCSI_PT_DIRECT_ACCESS == peripheral_type) {
1938  short int enable = wce = (options.set_wce > 0);
1939  rcd = -1;
1940  if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
1941  pout("Write cache %sable failed: %s\n", (enable ? "en" : "dis"),
1942  device->get_errmsg());
1943  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1944  }
1945  else
1946  pout("Write cache %sabled\n", (enable ? "en" : "dis"));
1947  any_output = true;
1948  }
1949 
1950  // Enable/Disable read cache
1951  if (options.set_rcd && SCSI_PT_DIRECT_ACCESS == peripheral_type) {
1952  short int enable = (options.set_rcd > 0);
1953  rcd = !enable;
1954  wce = -1;
1955  if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
1956  pout("Read cache %sable failed: %s\n", (enable ? "en" : "dis"),
1957  device->get_errmsg());
1958  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1959  }
1960  else
1961  pout("Read cache %sabled\n", (enable ? "en" : "dis"));
1962  any_output = true;
1963  }
1964 
1965  if (options.smart_auto_save_disable) {
1966  if (scsiSetControlGLTSD(device, 1, modese_len)) {
1967  pout("Disable autosave (set GLTSD bit) failed\n");
1968  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1969  }
1970  else {
1971  pout("Autosave disabled (GLTSD bit cleared).\n");
1972  }
1973  any_output = true;
1974  }
1975  if ( options.smart_disable || options.smart_enable
1976  || options.smart_auto_save_disable || options.smart_auto_save_enable)
1977  pout("\n"); // END OF THE ENABLE/DISABLE SECTION OF THE CODE
1978 
1979  // START OF READ-ONLY OPTIONS APART FROM -V and -i
1980  if ( options.smart_check_status || options.smart_ss_media_log
1981  || options.smart_vendor_attrib || options.smart_error_log
1982  || options.smart_selftest_log || options.smart_vendor_attrib
1983  || options.smart_background_log || options.sasphy
1984  )
1985  pout("=== START OF READ SMART DATA SECTION ===\n");
1986 
1987  if (options.smart_check_status) {
1988  scsiGetSupportedLogPages(device);
1989  checkedSupportedLogPages = 1;
1990  if ((SCSI_PT_SEQUENTIAL_ACCESS == peripheral_type) ||
1991  (SCSI_PT_MEDIUM_CHANGER == peripheral_type)) { /* tape device */
1992  if (gTapeAlertsLPage) {
1993  if (options.drive_info)
1994  pout("TapeAlert Supported\n");
1995  if (-1 == scsiGetTapeAlertsData(device, peripheral_type))
1996  failuretest(OPTIONAL_CMD, returnval |= FAILSMART);
1997  }
1998  else
1999  pout("TapeAlert Not Supported\n");
2000  } else { /* disk, cd/dvd, enclosure, etc */
2001  if ((res = scsiGetSmartData(device, options.smart_vendor_attrib))) {
2002  if (-2 == res)
2003  returnval |= FAILSTATUS;
2004  else
2005  returnval |= FAILSMART;
2006  }
2007  }
2008  any_output = true;
2009  }
2010 
2011  if (options.smart_ss_media_log) {
2012  if (! checkedSupportedLogPages)
2013  scsiGetSupportedLogPages(device);
2014  res = 0;
2015  if (gSSMediaLPage)
2016  res = scsiPrintSSMedia(device);
2017  if (0 != res)
2018  failuretest(OPTIONAL_CMD, returnval|=res);
2019  any_output = true;
2020  }
2021  if (options.smart_vendor_attrib) {
2022  if (! checkedSupportedLogPages)
2023  scsiGetSupportedLogPages(device);
2024  if (gTempLPage) {
2025  scsiPrintTemp(device);
2026  }
2027  if (gStartStopLPage)
2028  scsiGetStartStopData(device);
2029  if (SCSI_PT_DIRECT_ACCESS == peripheral_type) {
2031  if (gSeagateCacheLPage)
2035  }
2036  any_output = true;
2037  }
2038  if (options.smart_error_log) {
2039  if (! checkedSupportedLogPages)
2040  scsiGetSupportedLogPages(device);
2041  scsiPrintErrorCounterLog(device);
2042  if (1 == scsiFetchControlGLTSD(device, modese_len, 1))
2043  pout("\n[GLTSD (Global Logging Target Save Disable) set. "
2044  "Enable Save with '-S on']\n");
2045  any_output = true;
2046  }
2047  if (options.smart_selftest_log) {
2048  if (! checkedSupportedLogPages)
2049  scsiGetSupportedLogPages(device);
2050  res = 0;
2051  if (gSelfTestLPage)
2052  res = scsiPrintSelfTest(device);
2053  else {
2054  pout("Device does not support Self Test logging\n");
2055  failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
2056  }
2057  if (0 != res)
2058  failuretest(OPTIONAL_CMD, returnval|=res);
2059  any_output = true;
2060  }
2061  if (options.smart_background_log) {
2062  if (! checkedSupportedLogPages)
2063  scsiGetSupportedLogPages(device);
2064  res = 0;
2066  res = scsiPrintBackgroundResults(device);
2067  else {
2068  pout("Device does not support Background scan results logging\n");
2069  failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
2070  }
2071  if (0 != res)
2072  failuretest(OPTIONAL_CMD, returnval|=res);
2073  any_output = true;
2074  }
2075  if (options.smart_default_selftest) {
2076  if (scsiSmartDefaultSelfTest(device))
2077  return returnval | FAILSMART;
2078  pout("Default Self Test Successful\n");
2079  any_output = true;
2080  }
2081  if (options.smart_short_cap_selftest) {
2082  if (scsiSmartShortCapSelfTest(device))
2083  return returnval | FAILSMART;
2084  pout("Short Foreground Self Test Successful\n");
2085  any_output = true;
2086  }
2087  // check if another test is running
2088  if (options.smart_short_selftest || options.smart_extend_selftest) {
2089  if (!scsiRequestSense(device, &sense_info) &&
2090  (sense_info.asc == 0x04 && sense_info.ascq == 0x09)) {
2091  if (!options.smart_selftest_force) {
2092  pout("Can't start self-test without aborting current test");
2093  if (sense_info.progress != -1) {
2094  pout(" (%d%% remaining)",
2095  100 - sense_info.progress * 100 / 65535);
2096  }
2097  pout(",\nadd '-t force' option to override, or run 'smartctl -X' "
2098  "to abort test.\n");
2099  return -1;
2100  }
2101  else
2102  scsiSmartSelfTestAbort(device);
2103  }
2104  }
2105  if (options.smart_short_selftest) {
2106  if (scsiSmartShortSelfTest(device))
2107  return returnval | FAILSMART;
2108  pout("Short Background Self Test has begun\n");
2109  pout("Use smartctl -X to abort test\n");
2110  any_output = true;
2111  }
2112  if (options.smart_extend_selftest) {
2113  if (scsiSmartExtendSelfTest(device))
2114  return returnval | FAILSMART;
2115  pout("Extended Background Self Test has begun\n");
2116  if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec,
2117  modese_len)) && (durationSec > 0)) {
2118  time_t t = time(NULL);
2119 
2120  t += durationSec;
2121  pout("Please wait %d minutes for test to complete.\n",
2122  durationSec / 60);
2123  pout("Estimated completion time: %s\n", ctime(&t));
2124  }
2125  pout("Use smartctl -X to abort test\n");
2126  any_output = true;
2127  }
2128  if (options.smart_extend_cap_selftest) {
2129  if (scsiSmartExtendCapSelfTest(device))
2130  return returnval | FAILSMART;
2131  pout("Extended Foreground Self Test Successful\n");
2132  }
2133  if (options.smart_selftest_abort) {
2134  if (scsiSmartSelfTestAbort(device))
2135  return returnval | FAILSMART;
2136  pout("Self Test returned without error\n");
2137  any_output = true;
2138  }
2139  if (options.sasphy && gProtocolSpecificLPage) {
2140  if (scsiPrintSasPhy(device, options.sasphy_reset))
2141  return returnval | FAILSMART;
2142  any_output = true;
2143  }
2144 
2145  if (!any_output)
2146  pout("SCSI device successfully opened\n\n"
2147  "Use 'smartctl -a' (or '-x') to print SMART (and more) information\n\n");
2148 
2149  return returnval;
2150 }
int scsiSmartShortSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2148
#define SCSI_PT_MEDIUM_CHANGER
Definition: scsicmds.h:177
UINT8 gBuf[GBUF_SIZE]
Definition: scsiprint.cpp:49
#define PRIu64
Definition: int64.h:76
#define SELFTEST_RESULTS_LPAGE
Definition: scsicmds.h:194
static int gWriteECounterLPage
Definition: scsiprint.cpp:60
static int scsiSmartEnable(scsi_device *device)
Definition: scsiprint.cpp:1763
u16 s[6]
Definition: megaraid.h:97
static int show_protocol_specific_page(unsigned char *resp, int len)
Definition: scsiprint.cpp:1331
static int gProtocolSpecificLPage
Definition: scsiprint.cpp:65
static const char * self_test_code[]
Definition: scsiprint.cpp:684
#define VERIFY_ERROR_COUNTER_LPAGE
Definition: scsicmds.h:186
short int set_rcd
Definition: scsiprint.h:57
static int scsiGetTapeAlertsData(scsi_device *device, int peripheral_type)
Definition: scsiprint.cpp:195
int scsiGetSetCache(scsi_device *device, int modese_len, short int *wcep, short int *rcdp)
Definition: scsicmds.cpp:2529
static const char * peripheral_dt_arr[]
Definition: scsiprint.cpp:1394
#define SUPPORTED_LPAGES
Definition: scsicmds.h:181
#define LAST_N_ERROR_LPAGE
Definition: scsicmds.h:188
bool smart_auto_save_enable
Definition: scsiprint.h:46
int scsiFetchTransportProtocol(scsi_device *device, int modese_len)
Definition: scsicmds.cpp:2703
#define STARTSTOP_CYCLE_COUNTER_LPAGE
Definition: scsicmds.h:192
int scsiReadDefect12(scsi_device *device, int req_plist, int req_glist, int dl_format, int addrDescIndex, UINT8 *pBuf, int bufLen)
Definition: scsicmds.cpp:1112
void dateandtimezone(char *buffer)
Definition: utility.cpp:337
#define SEAGATE_FACTORY_LPAGE
Definition: scsicmds.h:203
void scsiDecodeErrCounterPage(unsigned char *resp, struct scsiErrorCounter *ecp)
Definition: scsicmds.cpp:2245
static const char * reassign_status[]
Definition: scsiprint.cpp:885
const char * scsiTapeAlertsTapeDevice(unsigned short code)
Definition: scsicmds.cpp:1812
static int scsiGetSmartData(scsi_device *device, bool attribs)
Definition: scsiprint.cpp:150
bool smart_default_selftest
Definition: scsiprint.h:48
#define SCSI_PT_DIRECT_ACCESS
Definition: scsicmds.h:174
int scsiInquiryVpd(scsi_device *device, int vpd_page, UINT8 *pBuf, int bufLen)
Definition: scsicmds.cpp:814
int scsiFetchExtendedSelfTestTime(scsi_device *device, int *durationSec, int modese_len)
Definition: scsicmds.cpp:2207
bool smart_background_log
Definition: scsiprint.h:42
int scsiSmartDefaultSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2137
#define NON_MEDIUM_ERROR_LPAGE
Definition: scsicmds.h:187
int scsiCheckIE(scsi_device *device, int hasIELogPage, int hasTempLogPage, UINT8 *asc, UINT8 *ascq, UINT8 *currenttemp, UINT8 *triptemp)
Definition: scsicmds.cpp:1529
static int gVerifyECounterLPage
Definition: scsiprint.cpp:61
#define FAILSMART
Definition: smartctl.h:46
#define snprintf
Definition: utility.h:68
int scsi_decode_lu_dev_id(const unsigned char *b, int blen, char *s, int slen, int *transport)
Definition: scsicmds.cpp:330
bool smart_selftest_force
Definition: scsiprint.h:52
int scsiSmartExtendCapSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2182
#define LOGPAGEHDRSIZE
Definition: scsicmds.h:316
const char * scsiTapeAlertsChangerDevice(unsigned short code)
Definition: scsicmds.cpp:1948
bool smart_check_status
Definition: scsiprint.h:38
unsigned int UINT32
Definition: scsicmds.h:109
uint64_t counterPC0
Definition: scsicmds.h:166
int scsiSmartSelfTestAbort(scsi_device *device)
Definition: scsicmds.cpp:2194
#define SIMPLE_ERR_NOT_READY
Definition: scsicmds.h:285
#define TEMPERATURE_LPAGE
Definition: scsicmds.h:191
void scsi_format_id_string(char *out, const unsigned char *in, int n)
Definition: scsicmds.cpp:2764
void print_off()
Definition: smartctl.h:92
static void scsiPrintSeagateCacheLPage(scsi_device *device)
Definition: scsiprint.cpp:404
static void scsiPrintErrorCounterLog(scsi_device *device)
Definition: scsiprint.cpp:577
#define SCSI_PT_SEQUENTIAL_ACCESS
Definition: scsicmds.h:175
#define SCSI_VPD_DEVICE_IDENTIFICATION
Definition: scsicmds.h:250
int scsiSmartExtendSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2159
bool smart_short_cap_selftest
Definition: scsiprint.h:49
#define IE_LPAGE
Definition: scsicmds.h:199
bool smart_auto_save_disable
Definition: scsiprint.h:46
UINT8 gotPC[7]
Definition: scsicmds.h:157
#define TAPE_ALERTS_LPAGE
Definition: scsicmds.h:210
short int set_wce
Definition: scsiprint.h:57
#define WRITE_ERROR_COUNTER_LPAGE
Definition: scsicmds.h:183
static int scsiPrintBackgroundResults(scsi_device *device)
Definition: scsiprint.cpp:902
#define DATEANDEPOCHLEN
Definition: utility.h:80
#define SCSI_VPD_LOGICAL_BLOCK_PROVISIONING
Definition: scsicmds.h:257
#define LOG_RESP_LEN
Definition: scsiprint.cpp:50
#define SIMPLE_ERR_NO_MEDIUM
Definition: scsicmds.h:290
const char * scsiGetIEString(UINT8 asc, UINT8 ascq)
Definition: scsicmds.cpp:2083
#define SS_MEDIA_LPAGE
Definition: scsicmds.h:195
#define FAILSTATUS
Definition: smartctl.h:49
static int modese_len
Definition: scsiprint.cpp:77
int scsiFetchControlGLTSD(scsi_device *device, int modese_len, int current)
Definition: scsicmds.cpp:2448
const char * get_errmsg() const
Get last error message.
static int gSSMediaLPage
Definition: scsiprint.cpp:67
void print_on()
Definition: smartctl.h:87
static void scsiGetSupportedLogPages(scsi_device *device)
Definition: scsiprint.cpp:81
int scsiFetchIECmpage(scsi_device *device, struct scsi_iec_mode_page *iecp, int modese_len)
Definition: scsicmds.cpp:1335
bool dont_print_serial_number
Definition: atacmds.cpp:46
void dStrHex(const char *str, int len, int no_ascii)
Definition: scsicmds.cpp:91
static int gSeagateFactoryLPage
Definition: scsiprint.cpp:71
#define GBUF_SIZE
Definition: scsiprint.cpp:43
#define FAILID
Definition: smartctl.h:43
unsigned char scsi_debugmode
Definition: scsicmds.cpp:56
uint64_t counterTFE_H
Definition: scsicmds.h:168
static void scsiPrintSeagateFactoryLPage(scsi_device *device)
Definition: scsiprint.cpp:481
static void show_sas_phy_event_info(int peis, unsigned int val, unsigned thresh_val)
Definition: scsiprint.cpp:1067
static int gSelfTestLPage
Definition: scsiprint.cpp:57
int scsiLogSelect(scsi_device *device, int pcr, int sp, int pc, int pagenum, int subpagenum, UINT8 *pBuf, int bufLen)
Definition: scsicmds.cpp:549
int scsiReadDefect10(scsi_device *device, int req_plist, int req_glist, int dl_format, UINT8 *pBuf, int bufLen)
Definition: scsicmds.cpp:1078
int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
Definition: scsicmds.cpp:1382
static const char * self_test_result[]
Definition: scsiprint.cpp:695
const char * format_capacity(char *str, int strsize, uint64_t val, const char *decimal_point)
Definition: utility.cpp:736
void scsiDecodeNonMediumErrPage(unsigned char *resp, struct scsiNonMediumError *nmep)
Definition: scsicmds.cpp:2292
void pout(const char *fmt,...)
Definition: smartctl.cpp:1091
#define SCSIPRINT_H_CVSID
Definition: scsiprint.h:32
static const char * transport_proto_arr[]
Definition: scsiprint.cpp:1429
static int gNonMediumELPage
Definition: scsiprint.cpp:62
#define LOG_RESP_SELF_TEST_LEN
Definition: scsicmds.h:206
static int gBackgroundResultsLPage
Definition: scsiprint.cpp:64
static int gSmartLPage
Definition: scsiprint.cpp:55
#define SIMPLE_ERR_BECOMING_READY
Definition: scsicmds.h:291
static void show_sas_port_param(unsigned char *ucp, int param_len)
Definition: scsiprint.cpp:1198
SCSI device access.
int scsiGetRPM(scsi_device *device, int modese_len, int *form_factorp, int *haw_zbcp)
Definition: scsicmds.cpp:2483
static int gStartStopLPage
Definition: scsiprint.cpp:58
#define BACKGROUND_RESULTS_LPAGE
Definition: scsicmds.h:196
static void scsiGetStartStopData(scsi_device *device)
Definition: scsiprint.cpp:245
static const char *const severities
Definition: scsiprint.cpp:192
int scsiSetExceptionControlAndWarning(scsi_device *device, int enabled, const struct scsi_iec_mode_page *iecp)
Definition: scsicmds.cpp:1429
bool smart_ss_media_log
Definition: scsiprint.h:43
const char * format_with_thousands_sep(char *str, int strsize, uint64_t val, const char *thousands_sep)
Definition: utility.cpp:704
#define SEAGATE_CACHE_LPAGE
Definition: scsicmds.h:202
int scsiLogSense(scsi_device *device, int pagenum, int subpagenum, UINT8 *pBuf, int bufLen, int known_resp_len)
Definition: scsicmds.cpp:456
#define SCSI_VPD_UNIT_SERIAL_NUMBER
Definition: scsicmds.h:249
static const char * bms_status[]
Definition: scsiprint.cpp:873
int scsiPrintMain(scsi_device *device, const scsi_print_options &options)
Definition: scsiprint.cpp:1859
uint64_t counter[8]
Definition: scsicmds.h:159
static int scsiSmartDisable(scsi_device *device)
Definition: scsiprint.cpp:1800
static int gIecMPage
Definition: scsiprint.cpp:74
unsigned long long uint64_t
Definition: int64.h:54
#define PROTOCOL_SPECIFIC_LPAGE
Definition: scsicmds.h:198
#define READ_ERROR_COUNTER_LPAGE
Definition: scsicmds.h:184
static int scsiPrintSasPhy(scsi_device *device, int reset)
Definition: scsiprint.cpp:1355
static int scsiGetDriveInfo(scsi_device *device, UINT8 *peripheral_type, bool all)
Definition: scsiprint.cpp:1450
static void scsiPrintTemp(scsi_device *device)
Definition: scsiprint.cpp:1837
static int gSeagateCacheLPage
Definition: scsiprint.cpp:70
bool smart_selftest_log
Definition: scsiprint.h:41
bool smart_short_selftest
Definition: scsiprint.h:49
int scsiGetProtPBInfo(scsi_device *device, unsigned char *rc16_12_31p)
Definition: scsicmds.cpp:1273
bool smart_extend_selftest
Definition: scsiprint.h:50
bool smart_extend_cap_selftest
Definition: scsiprint.h:50
int scsiStdInquiry(scsi_device *device, UINT8 *pBuf, int bufLen)
Definition: scsicmds.cpp:780
static int scsiPrintSelfTest(scsi_device *device)
Definition: scsiprint.cpp:719
static int gReadECounterLPage
Definition: scsiprint.cpp:59
const char * scsiprint_c_cvsid
Definition: scsiprint.cpp:45
static void scsiPrintGrownDefectListLen(scsi_device *device)
Definition: scsiprint.cpp:322
void failuretest(failure_type type, int returnvalue)
Definition: smartctl.cpp:1115
static int gLastNErrorLPage
Definition: scsiprint.cpp:63
int scsiGetTemp(scsi_device *device, UINT8 *currenttemp, UINT8 *triptemp)
Definition: scsicmds.cpp:1506
int scsiTestUnitReady(scsi_device *device)
Definition: scsicmds.cpp:1055
uint64_t scsiGetSize(scsi_device *device, unsigned int *lb_sizep, int *lb_per_pb_expp)
Definition: scsicmds.cpp:1228
static int scsiPrintSSMedia(scsi_device *device)
Definition: scsiprint.cpp:1011
int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
Definition: scsicmds.cpp:1398
#define SIMPLE_ERR_BAD_RESP
Definition: scsicmds.h:289
int scsiSmartShortCapSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2171
int scsiRequestSense(scsi_device *device, struct scsi_sense_disect *sense_info)
Definition: scsicmds.cpp:876
bool smart_selftest_abort
Definition: scsiprint.h:51
unsigned char UINT8
Definition: scsicmds.h:107
static int gTempLPage
Definition: scsiprint.cpp:56
const char * get_req_type() const
Get type requested by user, empty if none.
#define LOG_RESP_LONG_LEN
Definition: scsiprint.cpp:51
int scsiSetControlGLTSD(scsi_device *device, int enabled, int modese_len)
Definition: scsicmds.cpp:2632
#define PRIx64
Definition: int64.h:80
supported_vpd_pages * supported_vpd_pages_p
Definition: scsicmds.cpp:58
const char * scsiErrString(int scsiErr)
Definition: scsicmds.cpp:257
uint64_t counterPE_H
Definition: scsicmds.h:170
#define LOG_RESP_TAPE_ALERT_LEN
Definition: scsiprint.cpp:52
#define FAILLOG
Definition: smartctl.h:62
static int gTapeAlertsLPage
Definition: scsiprint.cpp:66
bool smart_vendor_attrib
Definition: scsiprint.h:39