smartmontools  SVN Rev 4430
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 4415 2017-03-27 21:14:53Z chrfranke $"
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  char s[64];
1209 
1210  sz = sizeof(s);
1211  // pcb = ucp[2];
1212  t = (ucp[0] << 8) | ucp[1];
1213  pout("relative target port id = %d\n", t);
1214  pout(" generation code = %d\n", ucp[6]);
1215  nphys = ucp[7];
1216  pout(" number of phys = %d\n", nphys);
1217 
1218  for (j = 0, vcp = ucp + 8; j < (param_len - 8);
1219  vcp += spld_len, j += spld_len) {
1220  pout(" phy identifier = %d\n", vcp[1]);
1221  spld_len = vcp[3];
1222  if (spld_len < 44)
1223  spld_len = 48; /* in SAS-1 and SAS-1.1 vcp[3]==0 */
1224  else
1225  spld_len += 4;
1226  t = ((0x70 & vcp[4]) >> 4);
1227  switch (t) {
1228  case 0: snprintf(s, sz, "no device attached"); break;
1229  case 1: snprintf(s, sz, "SAS or SATA device"); break;
1230  case 2: snprintf(s, sz, "expander device"); break;
1231  case 3: snprintf(s, sz, "expander device (fanout)"); break;
1232  default: snprintf(s, sz, "reserved [%d]", t); break;
1233  }
1234  pout(" attached device type: %s\n", s);
1235  t = 0xf & vcp[4];
1236  switch (t) {
1237  case 0: snprintf(s, sz, "unknown"); break;
1238  case 1: snprintf(s, sz, "power on"); break;
1239  case 2: snprintf(s, sz, "hard reset"); break;
1240  case 3: snprintf(s, sz, "SMP phy control function"); break;
1241  case 4: snprintf(s, sz, "loss of dword synchronization"); break;
1242  case 5: snprintf(s, sz, "mux mix up"); break;
1243  case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
1244  break;
1245  case 7: snprintf(s, sz, "break timeout timer expired"); break;
1246  case 8: snprintf(s, sz, "phy test function stopped"); break;
1247  case 9: snprintf(s, sz, "expander device reduced functionality");
1248  break;
1249  default: snprintf(s, sz, "reserved [0x%x]", t); break;
1250  }
1251  pout(" attached reason: %s\n", s);
1252  t = (vcp[5] & 0xf0) >> 4;
1253  switch (t) {
1254  case 0: snprintf(s, sz, "unknown"); break;
1255  case 1: snprintf(s, sz, "power on"); break;
1256  case 2: snprintf(s, sz, "hard reset"); break;
1257  case 3: snprintf(s, sz, "SMP phy control function"); break;
1258  case 4: snprintf(s, sz, "loss of dword synchronization"); break;
1259  case 5: snprintf(s, sz, "mux mix up"); break;
1260  case 6: snprintf(s, sz, "I_T nexus loss timeout for STP/SATA");
1261  break;
1262  case 7: snprintf(s, sz, "break timeout timer expired"); break;
1263  case 8: snprintf(s, sz, "phy test function stopped"); break;
1264  case 9: snprintf(s, sz, "expander device reduced functionality");
1265  break;
1266  default: snprintf(s, sz, "reserved [0x%x]", t); break;
1267  }
1268  pout(" reason: %s\n", s);
1269  t = (0xf & vcp[5]);
1270  switch (t) {
1271  case 0: snprintf(s, sz, "phy enabled; unknown");
1272  break;
1273  case 1: snprintf(s, sz, "phy disabled"); break;
1274  case 2: snprintf(s, sz, "phy enabled; speed negotiation failed");
1275  break;
1276  case 3: snprintf(s, sz, "phy enabled; SATA spinup hold state");
1277  break;
1278  case 4: snprintf(s, sz, "phy enabled; port selector");
1279  break;
1280  case 5: snprintf(s, sz, "phy enabled; reset in progress");
1281  break;
1282  case 6: snprintf(s, sz, "phy enabled; unsupported phy attached");
1283  break;
1284  case 8: snprintf(s, sz, "phy enabled; 1.5 Gbps"); break;
1285  case 9: snprintf(s, sz, "phy enabled; 3 Gbps"); break;
1286  case 0xa: snprintf(s, sz, "phy enabled; 6 Gbps"); break;
1287  case 0xb: snprintf(s, sz, "phy enabled; 12 Gbps"); break;
1288  default: snprintf(s, sz, "reserved [%d]", t); break;
1289  }
1290  pout(" negotiated logical link rate: %s\n", s);
1291  pout(" attached initiator port: ssp=%d stp=%d smp=%d\n",
1292  !! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2));
1293  pout(" attached target port: ssp=%d stp=%d smp=%d\n",
1294  !! (vcp[7] & 8), !! (vcp[7] & 4), !! (vcp[7] & 2));
1295  if (!dont_print_serial_number) {
1296  uint64_t ull;
1297  for (n = 0, ull = vcp[8]; n < 8; ++n) {
1298  ull <<= 8; ull |= vcp[8 + n];
1299  }
1300  pout(" SAS address = 0x%" PRIx64 "\n", ull);
1301  for (n = 0, ull = vcp[16]; n < 8; ++n) {
1302  ull <<= 8; ull |= vcp[16 + n];
1303  }
1304  pout(" attached SAS address = 0x%" PRIx64 "\n", ull);
1305  }
1306  pout(" attached phy identifier = %d\n", vcp[24]);
1307  unsigned int ui;
1308  ui = (vcp[32] << 24) | (vcp[33] << 16) | (vcp[34] << 8) | vcp[35];
1309  pout(" Invalid DWORD count = %u\n", ui);
1310  ui = (vcp[36] << 24) | (vcp[37] << 16) | (vcp[38] << 8) | vcp[39];
1311  pout(" Running disparity error count = %u\n", ui);
1312  ui = (vcp[40] << 24) | (vcp[41] << 16) | (vcp[42] << 8) | vcp[43];
1313  pout(" Loss of DWORD synchronization = %u\n", ui);
1314  ui = (vcp[44] << 24) | (vcp[45] << 16) | (vcp[46] << 8) | vcp[47];
1315  pout(" Phy reset problem = %u\n", ui);
1316  if (spld_len > 51) {
1317  int num_ped;
1318  unsigned char * xcp;
1319 
1320  num_ped = vcp[51];
1321  if (num_ped > 0)
1322  pout(" Phy event descriptors:\n");
1323  xcp = vcp + 52;
1324  for (m = 0; m < (num_ped * 12); m += 12, xcp += 12) {
1325  int peis;
1326  unsigned int pvdt;
1327  peis = xcp[3];
1328  ui = (xcp[4] << 24) | (xcp[5] << 16) | (xcp[6] << 8) |
1329  xcp[7];
1330  pvdt = (xcp[8] << 24) | (xcp[9] << 16) | (xcp[10] << 8) |
1331  xcp[11];
1332  show_sas_phy_event_info(peis, ui, pvdt);
1333  }
1334  }
1335  }
1336 }
1337 
1338 // Returns 1 if okay, 0 if non SAS descriptors
1339 static int
1340 show_protocol_specific_page(unsigned char * resp, int len)
1341 {
1342  int k, num;
1343  unsigned char * ucp;
1344 
1345  num = len - 4;
1346  for (k = 0, ucp = resp + 4; k < num; ) {
1347  int param_len = ucp[3] + 4;
1348  if (6 != (0xf & ucp[4]))
1349  return 0; /* only decode SAS log page */
1350  if (0 == k)
1351  pout("Protocol Specific port log page for SAS SSP\n");
1352  show_sas_port_param(ucp, param_len);
1353  k += param_len;
1354  ucp += param_len;
1355  }
1356  pout("\n");
1357  return 1;
1358 }
1359 
1360 
1361 // See Serial Attached SCSI (SPL-3) (e.g. revision 6g) the Protocol Specific
1362 // log page [0x18]. Returns 0 if ok else FAIL* bitmask.
1363 static int
1364 scsiPrintSasPhy(scsi_device * device, int reset)
1365 {
1366  int num, err;
1367 
1368  if ((err = scsiLogSense(device, PROTOCOL_SPECIFIC_LPAGE, 0, gBuf,
1369  LOG_RESP_LONG_LEN, 0))) {
1370  print_on();
1371  pout("%s Log Sense Failed [%s]\n\n", __func__, scsiErrString(err));
1372  print_off();
1373  return FAILSMART;
1374  }
1375  if ((gBuf[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE) {
1376  print_on();
1377  pout("Protocol specific Log Sense Failed, page mismatch\n\n");
1378  print_off();
1379  return FAILSMART;
1380  }
1381  // compute page length
1382  num = (gBuf[2] << 8) + gBuf[3];
1383  if (1 != show_protocol_specific_page(gBuf, num + 4)) {
1384  print_on();
1385  pout("Only support protocol specific log page on SAS devices\n\n");
1386  print_off();
1387  return FAILSMART;
1388  }
1389  if (reset) {
1390  if ((err = scsiLogSelect(device, 1 /* pcr */, 0 /* sp */, 0 /* pc */,
1391  PROTOCOL_SPECIFIC_LPAGE, 0, NULL, 0))) {
1392  print_on();
1393  pout("%s Log Select (reset) Failed [%s]\n\n", __func__,
1394  scsiErrString(err));
1395  print_off();
1396  return FAILSMART;
1397  }
1398  }
1399  return 0;
1400 }
1401 
1402 
1403 static const char * peripheral_dt_arr[32] = {
1404  "disk",
1405  "tape",
1406  "printer",
1407  "processor",
1408  "optical disk(4)",
1409  "CD/DVD",
1410  "scanner",
1411  "optical disk(7)",
1412  "medium changer",
1413  "communications",
1414  "graphics(10)",
1415  "graphics(11)",
1416  "storage array",
1417  "enclosure",
1418  "simplified disk",
1419  "optical card reader",
1420  "reserved [0x10]",
1421  "object based storage",
1422  "automation/driver interface",
1423  "security manager device",
1424  "host managed zoned block device",
1425  "reserved [0x15]",
1426  "reserved [0x16]",
1427  "reserved [0x17]",
1428  "reserved [0x18]",
1429  "reserved [0x19]",
1430  "reserved [0x1a]",
1431  "reserved [0x1b]",
1432  "reserved [0x1c]",
1433  "reserved [0x1d]",
1434  "well known logical unit",
1435  "unknown or no device type",
1436 };
1437 
1438 static const char * transport_proto_arr[] = {
1439  "Fibre channel (FCP-2)",
1440  "Parallel SCSI (SPI-4)",
1441  "SSA",
1442  "IEEE 1394 (SBP-2)",
1443  "RDMA (SRP)",
1444  "iSCSI",
1445  "SAS (SPL-3)",
1446  "ADT",
1447  "ATA (ACS-2)",
1448  "UAS",
1449  "SOP",
1450  "0xb",
1451  "0xc",
1452  "0xd",
1453  "0xe",
1454  "0xf"
1455 };
1456 
1457 /* Returns 0 on success, 1 on general error and 2 for early, clean exit */
1458 static int
1459 scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all)
1460 {
1461  char timedatetz[DATEANDEPOCHLEN];
1462  struct scsi_iec_mode_page iec;
1463  int err, iec_err, len, req_len, avail_len, scsi_version;
1464  bool is_tape = false;
1465  int peri_dt = 0;
1466  int transport = -1;
1467  int form_factor = 0;
1468  int haw_zbc = 0;
1469  int protect = 0;
1470 
1471  memset(gBuf, 0, 96);
1472  req_len = 36;
1473  if ((err = scsiStdInquiry(device, gBuf, req_len))) {
1474  print_on();
1475  pout("Standard Inquiry (36 bytes) failed [%s]\n", scsiErrString(err));
1476  pout("Retrying with a 64 byte Standard Inquiry\n");
1477  print_off();
1478  /* Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices */
1479  req_len = 64;
1480  if ((err = scsiStdInquiry(device, gBuf, req_len))) {
1481  print_on();
1482  pout("Standard Inquiry (64 bytes) failed [%s]\n",
1483  scsiErrString(err));
1484  print_off();
1485  return 1;
1486  }
1487  }
1488  avail_len = gBuf[4] + 5;
1489  len = (avail_len < req_len) ? avail_len : req_len;
1490  peri_dt = gBuf[0] & 0x1f;
1491  *peripheral_type = peri_dt;
1492  if ((SCSI_PT_SEQUENTIAL_ACCESS == peri_dt) ||
1493  (SCSI_PT_MEDIUM_CHANGER == peri_dt))
1494  is_tape = true;
1495 
1496  if (len < 36) {
1497  print_on();
1498  pout("Short INQUIRY response, skip product id\n");
1499  print_off();
1500  return 1;
1501  }
1502  // Upper bits of version bytes were used in older standards
1503  // Only interested in SPC-4 (0x6) and SPC-5 (assumed to be 0x7)
1504  scsi_version = gBuf[2] & 0x7;
1505 
1506  if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) {
1507  char vendor[8+1], product[16+1], revision[4+1];
1508  scsi_format_id_string(vendor, (const unsigned char *)&gBuf[8], 8);
1509  scsi_format_id_string(product, (const unsigned char *)&gBuf[16], 16);
1510  scsi_format_id_string(revision, (const unsigned char *)&gBuf[32], 4);
1511 
1512  pout("=== START OF INFORMATION SECTION ===\n");
1513  pout("Vendor: %.8s\n", vendor);
1514  pout("Product: %.16s\n", product);
1515  if (gBuf[32] >= ' ')
1516  pout("Revision: %.4s\n", revision);
1517  if (scsi_version == 0x6)
1518  pout("Compliance: SPC-4\n");
1519  else if (scsi_version == 0x7)
1520  pout("Compliance: SPC-5\n");
1521  }
1522 
1523  if (!*device->get_req_type()/*no type requested*/ &&
1524  (0 == strncmp((char *)&gBuf[8], "ATA", 3))) {
1525  pout("\nProbable ATA device behind a SAT layer\n"
1526  "Try an additional '-d ata' or '-d sat' argument.\n");
1527  return 2;
1528  }
1529  if (! all)
1530  return 0;
1531 
1532  protect = gBuf[5] & 0x1; /* from and including SPC-3 */
1533 
1534  if (! is_tape) { /* assume disk if not tape drive (or tape changer) */
1535  unsigned int lb_size = 0;
1536  unsigned char lb_prov_resp[8];
1537  char lb_str[16];
1538  int lb_per_pb_exp = 0;
1539  uint64_t capacity = scsiGetSize(device, &lb_size, &lb_per_pb_exp);
1540 
1541  if (capacity) {
1542  char cap_str[64], si_str[64];
1543  format_with_thousands_sep(cap_str, sizeof(cap_str), capacity);
1544  format_capacity(si_str, sizeof(si_str), capacity);
1545  pout("User Capacity: %s bytes [%s]\n", cap_str, si_str);
1546  snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size);
1547  pout("Logical block size: %s bytes\n", lb_str);
1548  }
1549  int lbpme = -1;
1550  int lbprz = -1;
1551  if (protect || lb_per_pb_exp) {
1552  unsigned char rc16_12[20] = {0, };
1553 
1554  if (0 == scsiGetProtPBInfo(device, rc16_12)) {
1555  lb_per_pb_exp = rc16_12[1] & 0xf; /* just in case */
1556  if (lb_per_pb_exp > 0) {
1557  snprintf(lb_str, sizeof(lb_str) - 1, "%u",
1558  (lb_size * (1 << lb_per_pb_exp)));
1559  pout("Physical block size: %s bytes\n", lb_str);
1560  int n = ((rc16_12[2] & 0x3f) << 8) + rc16_12[3];
1561  if (n > 0) // not common so cut the clutter
1562  pout("Lowest aligned LBA: %d\n", n);
1563  }
1564  if (rc16_12[0] & 0x1) { /* PROT_EN set */
1565  int p_type = ((rc16_12[0] >> 1) & 0x7);
1566 
1567  switch (p_type) {
1568  case 0 :
1569  pout("Formatted with type 1 protection\n");
1570  break;
1571  case 1 :
1572  pout("Formatted with type 2 protection\n");
1573  break;
1574  case 2 :
1575  pout("Formatted with type 3 protection\n");
1576  break;
1577  default:
1578  pout("Formatted with unknown protection type [%d]\n",
1579  p_type);
1580  break;
1581  }
1582  int p_i_exp = ((rc16_12[1] >> 4) & 0xf);
1583 
1584  if (p_i_exp > 0)
1585  pout("%d protection information intervals per "
1586  "logical block\n", (1 << p_i_exp));
1587  }
1588  /* Pick up some LB provisioning info since its available */
1589  lbpme = !! (rc16_12[2] & 0x80);
1590  lbprz = !! (rc16_12[2] & 0x40);
1591  }
1592  }
1593  /* Thin Provisioning VPD page renamed Logical Block Provisioning VPD
1594  * page in sbc3r25; some fields changed their meaning so that the
1595  * new page covered both thin and resource provisioned LUs. */
1597  lb_prov_resp, sizeof(lb_prov_resp))) {
1598  int prov_type = lb_prov_resp[6] & 0x7; /* added sbc3r27 */
1599  int vpd_lbprz = ((lb_prov_resp[5] >> 2) & 0x7); /* sbc4r07 */
1600 
1601  if (-1 == lbprz)
1602  lbprz = vpd_lbprz;
1603  else if ((0 == vpd_lbprz) && (1 == lbprz))
1604  ; /* vpd_lbprz introduced in sbc3r27, expanded in sbc4r07 */
1605  else
1606  lbprz = vpd_lbprz;
1607  switch (prov_type) {
1608  case 0:
1609  if (lbpme <= 0) {
1610  pout("LU is fully provisioned");
1611  if (lbprz)
1612  pout(" [LBPRZ=%d]\n", lbprz);
1613  else
1614  pout("\n");
1615  } else
1616  pout("LB provisioning type: not reported [LBPME=1, "
1617  "LBPRZ=%d]\n", lbprz);
1618  break;
1619  case 1:
1620  pout("LU is resource provisioned, LBPRZ=%d\n", lbprz);
1621  break;
1622  case 2:
1623  pout("LU is thin provisioned, LBPRZ=%d\n", lbprz);
1624  break;
1625  default:
1626  pout("LU provisioning type reserved [%d], LBPRZ=%d\n",
1627  prov_type, lbprz);
1628  break;
1629  }
1630  } else if (1 == lbpme) {
1631  if (scsi_debugmode > 0)
1632  pout("rcap_16 sets LBPME but no LB provisioning VPD page\n");
1633  pout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz);
1634  }
1635 
1636  int rpm = scsiGetRPM(device, modese_len, &form_factor, &haw_zbc);
1637  if (rpm >= 0) {
1638  if (0 == rpm)
1639  ; // Not reported
1640  else if (1 == rpm)
1641  pout("Rotation Rate: Solid State Device\n");
1642  else if ((rpm <= 0x400) || (0xffff == rpm))
1643  ; // Reserved
1644  else
1645  pout("Rotation Rate: %d rpm\n", rpm);
1646  }
1647  if (form_factor > 0) {
1648  const char * cp = NULL;
1649 
1650  switch (form_factor) {
1651  case 1:
1652  cp = "5.25";
1653  break;
1654  case 2:
1655  cp = "3.5";
1656  break;
1657  case 3:
1658  cp = "2.5";
1659  break;
1660  case 4:
1661  cp = "1.8";
1662  break;
1663  case 5:
1664  cp = "< 1.8";
1665  break;
1666  }
1667  if (cp)
1668  pout("Form Factor: %s inches\n", cp);
1669  }
1670  if (haw_zbc > 0)
1671  pout("Host aware zoned block capable\n");
1672  }
1673 
1674  /* Do this here to try and detect badly conforming devices (some USB
1675  keys) that will lock up on a InquiryVpd or log sense or ... */
1676  if ((iec_err = scsiFetchIECmpage(device, &iec, modese_len))) {
1677  if (SIMPLE_ERR_BAD_RESP == iec_err) {
1678  pout(">> Terminate command early due to bad response to IEC "
1679  "mode page\n");
1680  print_off();
1681  gIecMPage = 0;
1682  return 1;
1683  }
1684  } else
1685  modese_len = iec.modese_len;
1686 
1687  if (! dont_print_serial_number) {
1688  if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_DEVICE_IDENTIFICATION,
1689  gBuf, 252))) {
1690  char s[256];
1691 
1692  len = gBuf[3];
1693  scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport);
1694  if (strlen(s) > 0)
1695  pout("Logical Unit id: %s\n", s);
1696  } else if (scsi_debugmode > 0) {
1697  print_on();
1698  if (SIMPLE_ERR_BAD_RESP == err)
1699  pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
1700  else
1701  pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
1702  print_off();
1703  }
1704  if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_UNIT_SERIAL_NUMBER,
1705  gBuf, 252))) {
1706  char serial[256];
1707  len = gBuf[3];
1708 
1709  gBuf[4 + len] = '\0';
1710  scsi_format_id_string(serial, &gBuf[4], len);
1711  pout("Serial number: %s\n", serial);
1712  } else if (scsi_debugmode > 0) {
1713  print_on();
1714  if (SIMPLE_ERR_BAD_RESP == err)
1715  pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
1716  else
1717  pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
1718  print_off();
1719  }
1720  }
1721 
1722  // print SCSI peripheral device type
1723  if (peri_dt < (int)(sizeof(peripheral_dt_arr) /
1724  sizeof(peripheral_dt_arr[0])))
1725  pout("Device type: %s\n", peripheral_dt_arr[peri_dt]);
1726  else
1727  pout("Device type: <%d>\n", peri_dt);
1728 
1729  // See if transport protocol is known
1730  if (transport < 0)
1731  transport = scsiFetchTransportProtocol(device, modese_len);
1732  if ((transport >= 0) && (transport <= 0xf))
1733  pout("Transport protocol: %s\n", transport_proto_arr[transport]);
1734 
1735  // print current time and date and timezone
1736  dateandtimezone(timedatetz);
1737  pout("Local Time is: %s\n", timedatetz);
1738 
1739  // See if unit accepts SCSI commmands from us
1740  if ((err = scsiTestUnitReady(device))) {
1741  if (SIMPLE_ERR_NOT_READY == err) {
1742  print_on();
1743  if (!is_tape)
1744  pout("device is NOT READY (e.g. spun down, busy)\n");
1745  else
1746  pout("device is NOT READY (e.g. no tape)\n");
1747  print_off();
1748  } else if (SIMPLE_ERR_NO_MEDIUM == err) {
1749  print_on();
1750  if (is_tape)
1751  pout("NO tape present in drive\n");
1752  else
1753  pout("NO MEDIUM present in device\n");
1754  print_off();
1755  } else if (SIMPLE_ERR_BECOMING_READY == err) {
1756  print_on();
1757  pout("device becoming ready (wait)\n");
1758  print_off();
1759  } else {
1760  print_on();
1761  pout("device Test Unit Ready [%s]\n", scsiErrString(err));
1762  print_off();
1763  }
1764  if (! is_tape) {
1765  int returnval = 0; // TODO: exit with FAILID if failuretest returns
1766 
1767  failuretest(MANDATORY_CMD, returnval|=FAILID);
1768  }
1769  }
1770 
1771  if (iec_err) {
1772  if (!is_tape) {
1773  print_on();
1774  pout("SMART support is: Unavailable - device lacks SMART capability.\n");
1775  if (scsi_debugmode > 0)
1776  pout(" [%s]\n", scsiErrString(iec_err));
1777  print_off();
1778  }
1779  gIecMPage = 0;
1780  return 0;
1781  }
1782 
1783  if (!is_tape)
1784  pout("SMART support is: Available - device has SMART capability.\n"
1785  "SMART support is: %s\n",
1786  (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled");
1787  pout("%s\n", (scsi_IsWarningEnabled(&iec)) ?
1788  "Temperature Warning: Enabled" :
1789  "Temperature Warning: Disabled or Not Supported");
1790  return 0;
1791 }
1792 
1793 static int
1795 {
1796  struct scsi_iec_mode_page iec;
1797  int err;
1798 
1799  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1800  print_on();
1801  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1802  scsiErrString(err));
1803  print_off();
1804  return 1;
1805  } else
1806  modese_len = iec.modese_len;
1807 
1808  if ((err = scsiSetExceptionControlAndWarning(device, 1, &iec))) {
1809  print_on();
1810  pout("unable to enable Exception control and warning [%s]\n",
1811  scsiErrString(err));
1812  print_off();
1813  return 1;
1814  }
1815  /* Need to refetch 'iec' since could be modified by previous call */
1816  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1817  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1818  scsiErrString(err));
1819  return 1;
1820  } else
1821  modese_len = iec.modese_len;
1822 
1823  pout("Informational Exceptions (SMART) %s\n",
1824  scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled");
1825  pout("Temperature warning %s\n",
1826  scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled");
1827  return 0;
1828 }
1829 
1830 static int
1832 {
1833  struct scsi_iec_mode_page iec;
1834  int err;
1835 
1836  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1837  print_on();
1838  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1839  scsiErrString(err));
1840  print_off();
1841  return 1;
1842  } else
1843  modese_len = iec.modese_len;
1844 
1845  if ((err = scsiSetExceptionControlAndWarning(device, 0, &iec))) {
1846  print_on();
1847  pout("unable to disable Exception control and warning [%s]\n",
1848  scsiErrString(err));
1849  print_off();
1850  return 1;
1851  }
1852  /* Need to refetch 'iec' since could be modified by previous call */
1853  if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
1854  pout("unable to fetch IEC (SMART) mode page [%s]\n",
1855  scsiErrString(err));
1856  return 1;
1857  } else
1858  modese_len = iec.modese_len;
1859 
1860  pout("Informational Exceptions (SMART) %s\n",
1861  scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled");
1862  pout("Temperature warning %s\n",
1863  scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled");
1864  return 0;
1865 }
1866 
1867 static void
1869 {
1870  UINT8 temp = 255;
1871  UINT8 trip = 255;
1872 
1873  if (scsiGetTemp(device, &temp, &trip))
1874  return;
1875 
1876  if (255 == temp)
1877  pout("Current Drive Temperature: <not available>\n");
1878  else
1879  pout("Current Drive Temperature: %d C\n", temp);
1880  if (255 == trip)
1881  pout("Drive Trip Temperature: <not available>\n");
1882  else
1883  pout("Drive Trip Temperature: %d C\n", trip);
1884  pout("\n");
1885 }
1886 
1887 /* Main entry point used by smartctl command. Return 0 for success */
1888 int
1890 {
1891  int checkedSupportedLogPages = 0;
1892  UINT8 peripheral_type = 0;
1893  int returnval = 0;
1894  int res, durationSec;
1895  struct scsi_sense_disect sense_info;
1896  bool is_disk;
1897  bool is_tape;
1898 
1899  bool any_output = options.drive_info;
1900 
1901  if (supported_vpd_pages_p) {
1902  delete supported_vpd_pages_p;
1903  supported_vpd_pages_p = NULL;
1904  }
1906 
1907  res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info);
1908  if (res) {
1909  if (2 == res)
1910  return 0;
1911  else
1912  failuretest(MANDATORY_CMD, returnval |= FAILID);
1913  any_output = true;
1914  }
1915  is_disk = (SCSI_PT_DIRECT_ACCESS == peripheral_type);
1916  is_tape = ((SCSI_PT_SEQUENTIAL_ACCESS == peripheral_type) ||
1917  (SCSI_PT_MEDIUM_CHANGER == peripheral_type));
1918 
1919  short int wce = -1, rcd = -1;
1920  // Print read look-ahead status for disks
1921  if (options.get_rcd || options.get_wce) {
1922  if (is_disk) {
1923  res = scsiGetSetCache(device, modese_len, &wce, &rcd);
1924  if (options.get_rcd)
1925  pout("Read Cache is: %s\n",
1926  res ? "Unavailable" : // error
1927  rcd ? "Disabled" : "Enabled");
1928  if (options.get_wce)
1929  pout("Writeback Cache is: %s\n",
1930  res ? "Unavailable" : // error
1931  !wce ? "Disabled" : "Enabled");
1932  }
1933  } else
1934  any_output = true;
1935 
1936  if (options.drive_info)
1937  pout("\n");
1938 
1939  // START OF THE ENABLE/DISABLE SECTION OF THE CODE
1940  if (options.smart_disable || options.smart_enable ||
1942  pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
1943 
1944  if (options.smart_enable) {
1945  if (scsiSmartEnable(device))
1946  failuretest(MANDATORY_CMD, returnval |= FAILSMART);
1947  any_output = true;
1948  }
1949 
1950  if (options.smart_disable) {
1951  if (scsiSmartDisable(device))
1952  failuretest(MANDATORY_CMD,returnval |= FAILSMART);
1953  any_output = true;
1954  }
1955 
1956  if (options.smart_auto_save_enable) {
1957  if (scsiSetControlGLTSD(device, 0, modese_len)) {
1958  pout("Enable autosave (clear GLTSD bit) failed\n");
1959  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1960  } else
1961  pout("Autosave enabled (GLTSD bit cleared).\n");
1962  any_output = true;
1963  }
1964 
1965  // Enable/Disable write cache
1966  if (options.set_wce && is_disk) {
1967  short int enable = wce = (options.set_wce > 0);
1968 
1969  rcd = -1;
1970  if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
1971  pout("Write cache %sable failed: %s\n", (enable ? "en" : "dis"),
1972  device->get_errmsg());
1973  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1974  } else
1975  pout("Write cache %sabled\n", (enable ? "en" : "dis"));
1976  any_output = true;
1977  }
1978 
1979  // Enable/Disable read cache
1980  if (options.set_rcd && is_disk) {
1981  short int enable = (options.set_rcd > 0);
1982 
1983  rcd = !enable;
1984  wce = -1;
1985  if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
1986  pout("Read cache %sable failed: %s\n", (enable ? "en" : "dis"),
1987  device->get_errmsg());
1988  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1989  } else
1990  pout("Read cache %sabled\n", (enable ? "en" : "dis"));
1991  any_output = true;
1992  }
1993 
1994  if (options.smart_auto_save_disable) {
1995  if (scsiSetControlGLTSD(device, 1, modese_len)) {
1996  pout("Disable autosave (set GLTSD bit) failed\n");
1997  failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
1998  } else
1999  pout("Autosave disabled (GLTSD bit set).\n");
2000  any_output = true;
2001  }
2002  if (options.smart_disable || options.smart_enable ||
2004  pout("\n"); // END OF THE ENABLE/DISABLE SECTION OF THE CODE
2005 
2006  // START OF READ-ONLY OPTIONS APART FROM -V and -i
2007  if (options.smart_check_status || options.smart_ss_media_log ||
2008  options.smart_vendor_attrib || options.smart_error_log ||
2009  options.smart_selftest_log || options.smart_background_log ||
2010  options.sasphy)
2011  pout("=== START OF READ SMART DATA SECTION ===\n");
2012 
2013  if (options.smart_check_status) {
2014  scsiGetSupportedLogPages(device);
2015  checkedSupportedLogPages = 1;
2016  if (is_tape) {
2017  if (gTapeAlertsLPage) {
2018  if (options.drive_info)
2019  pout("TapeAlert Supported\n");
2020  if (-1 == scsiGetTapeAlertsData(device, peripheral_type))
2021  failuretest(OPTIONAL_CMD, returnval |= FAILSMART);
2022  }
2023  else
2024  pout("TapeAlert Not Supported\n");
2025  } else { /* disk, cd/dvd, enclosure, etc */
2026  if ((res = scsiGetSmartData(device, options.smart_vendor_attrib))) {
2027  if (-2 == res)
2028  returnval |= FAILSTATUS;
2029  else
2030  returnval |= FAILSMART;
2031  }
2032  }
2033  any_output = true;
2034  }
2035 
2036  if (is_disk && options.smart_ss_media_log) {
2037  if (! checkedSupportedLogPages)
2038  scsiGetSupportedLogPages(device);
2039  res = 0;
2040  if (gSSMediaLPage)
2041  res = scsiPrintSSMedia(device);
2042  if (0 != res)
2043  failuretest(OPTIONAL_CMD, returnval|=res);
2044  any_output = true;
2045  }
2046  if (options.smart_vendor_attrib) {
2047  if (! checkedSupportedLogPages)
2048  scsiGetSupportedLogPages(device);
2049  if (gTempLPage)
2050  scsiPrintTemp(device);
2051  if (gStartStopLPage)
2052  scsiGetStartStopData(device);
2053  if (is_disk) {
2055  if (gSeagateCacheLPage)
2059  }
2060  any_output = true;
2061  }
2062  if (options.smart_error_log) {
2063  if (! checkedSupportedLogPages)
2064  scsiGetSupportedLogPages(device);
2065  scsiPrintErrorCounterLog(device);
2066  if (1 == scsiFetchControlGLTSD(device, modese_len, 1))
2067  pout("\n[GLTSD (Global Logging Target Save Disable) set. "
2068  "Enable Save with '-S on']\n");
2069  any_output = true;
2070  }
2071  if (options.smart_selftest_log) {
2072  if (! checkedSupportedLogPages)
2073  scsiGetSupportedLogPages(device);
2074  res = 0;
2075  if (gSelfTestLPage)
2076  res = scsiPrintSelfTest(device);
2077  else {
2078  pout("Device does not support Self Test logging\n");
2079  failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
2080  }
2081  if (0 != res)
2082  failuretest(OPTIONAL_CMD, returnval|=res);
2083  any_output = true;
2084  }
2085  if (options.smart_background_log && is_disk) {
2086  if (! checkedSupportedLogPages)
2087  scsiGetSupportedLogPages(device);
2088  res = 0;
2090  res = scsiPrintBackgroundResults(device);
2091  else {
2092  pout("Device does not support Background scan results logging\n");
2093  failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
2094  }
2095  if (0 != res)
2096  failuretest(OPTIONAL_CMD, returnval|=res);
2097  any_output = true;
2098  }
2099  if (options.smart_default_selftest) {
2100  if (scsiSmartDefaultSelfTest(device))
2101  return returnval | FAILSMART;
2102  pout("Default Self Test Successful\n");
2103  any_output = true;
2104  }
2105  if (options.smart_short_cap_selftest) {
2106  if (scsiSmartShortCapSelfTest(device))
2107  return returnval | FAILSMART;
2108  pout("Short Foreground Self Test Successful\n");
2109  any_output = true;
2110  }
2111  // check if another test is running
2112  if (options.smart_short_selftest || options.smart_extend_selftest) {
2113  if (!scsiRequestSense(device, &sense_info) &&
2114  (sense_info.asc == 0x04 && sense_info.ascq == 0x09)) {
2115  if (!options.smart_selftest_force) {
2116  pout("Can't start self-test without aborting current test");
2117  if (sense_info.progress != -1)
2118  pout(" (%d%% remaining)",
2119  100 - sense_info.progress * 100 / 65535);
2120  pout(",\nadd '-t force' option to override, or run "
2121  "'smartctl -X' to abort test.\n");
2122  return -1;
2123  } else
2124  scsiSmartSelfTestAbort(device);
2125  }
2126  }
2127  if (options.smart_short_selftest) {
2128  if (scsiSmartShortSelfTest(device))
2129  return returnval | FAILSMART;
2130  pout("Short Background Self Test has begun\n");
2131  pout("Use smartctl -X to abort test\n");
2132  any_output = true;
2133  }
2134  if (options.smart_extend_selftest) {
2135  if (scsiSmartExtendSelfTest(device))
2136  return returnval | FAILSMART;
2137  pout("Extended Background Self Test has begun\n");
2138  if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec,
2139  modese_len)) && (durationSec > 0)) {
2140  time_t t = time(NULL);
2141 
2142  t += durationSec;
2143  pout("Please wait %d minutes for test to complete.\n",
2144  durationSec / 60);
2145  pout("Estimated completion time: %s\n", ctime(&t));
2146  }
2147  pout("Use smartctl -X to abort test\n");
2148  any_output = true;
2149  }
2150  if (options.smart_extend_cap_selftest) {
2151  if (scsiSmartExtendCapSelfTest(device))
2152  return returnval | FAILSMART;
2153  pout("Extended Foreground Self Test Successful\n");
2154  }
2155  if (options.smart_selftest_abort) {
2156  if (scsiSmartSelfTestAbort(device))
2157  return returnval | FAILSMART;
2158  pout("Self Test returned without error\n");
2159  any_output = true;
2160  }
2161  if (options.sasphy && gProtocolSpecificLPage) {
2162  if (scsiPrintSasPhy(device, options.sasphy_reset))
2163  return returnval | FAILSMART;
2164  any_output = true;
2165  }
2166 
2167  if (!any_output)
2168  pout("SCSI device successfully opened\n\nUse 'smartctl -a' (or '-x') "
2169  "to print SMART (and more) information\n\n");
2170 
2171  return returnval;
2172 }
int scsiSmartShortSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2083
#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:1794
u16 s[6]
Definition: megaraid.h:97
static int show_protocol_specific_page(unsigned char *resp, int len)
Definition: scsiprint.cpp:1340
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:2458
#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:2632
#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:2180
static const char * reassign_status[]
Definition: scsiprint.cpp:891
const char * scsiTapeAlertsTapeDevice(unsigned short code)
Definition: scsicmds.cpp:1771
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:2142
bool smart_background_log
Definition: scsiprint.h:42
int scsiSmartDefaultSelfTest(scsi_device *device)
Definition: scsicmds.cpp:2072
#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:2117
#define LOGPAGEHDRSIZE
Definition: scsicmds.h:314
const char * scsiTapeAlertsChangerDevice(unsigned short code)
Definition: scsicmds.cpp:1907
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:2129
#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:2693
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:2094
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:2042
#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:2377
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:2223
void pout(const char *fmt,...)
Definition: smartctl.cpp:1196
#define SCSIPRINT_H_CVSID
Definition: scsiprint.h:32
static const char * transport_proto_arr[]
Definition: scsiprint.cpp:1438
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:2412
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:1889
uint64_t counter[8]
Definition: scsicmds.h:157
static int scsiSmartDisable(scsi_device *device)
Definition: scsiprint.cpp:1831
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:1364
static int scsiGetDriveInfo(scsi_device *device, UINT8 *peripheral_type, bool all)
Definition: scsiprint.cpp:1459
static void scsiPrintTemp(scsi_device *device)
Definition: scsiprint.cpp:1868
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:1220
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:1403
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:2106
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:2561
#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