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