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