Diff for /embedaddon/smartmontools/scsiprint.cpp between versions 1.1 and 1.1.1.3

version 1.1, 2012/02/21 16:32:16 version 1.1.1.3, 2013/10/14 07:54:04
Line 7 Line 7
  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>   * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
  *   *
  * Additional SCSI work:   * Additional SCSI work:
 * Copyright (C) 2003-10 Douglas Gilbert <dgilbert@interlog.com> * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
  *   *
  * This program is free software; you can redistribute it and/or modify   * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
Line 15 Line 15
  * any later version.   * any later version.
  *   *
  * You should have received a copy of the GNU General Public License   * You should have received a copy of the GNU General Public License
 * (for example COPYING); if not, write to the Free * (for example COPYING); if not, write to the Free Software Foundation,
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *   *
  * This code was originally developed as a Senior Thesis by Michael Cornwell   * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems   * at the Concurrent Systems Laboratory (now part of the Storage Systems
Line 76  static int gIecMPage = 1;     /* N.B. assume it until  Line 76  static int gIecMPage = 1;     /* N.B. assume it until 
 /* Remember last successful mode sense/select command */  /* Remember last successful mode sense/select command */
 static int modese_len = 0;  static int modese_len = 0;
   
static void scsiGetSupportedLogPages(scsi_device * device)
 static void
 scsiGetSupportedLogPages(scsi_device * device)
 {  {
     int i, err;      int i, err;
   
     if ((err = scsiLogSense(device, SUPPORTED_LPAGES, 0, gBuf,      if ((err = scsiLogSense(device, SUPPORTED_LPAGES, 0, gBuf,
                             LOG_RESP_LEN, 0))) {                              LOG_RESP_LEN, 0))) {
         if (scsi_debugmode > 0)          if (scsi_debugmode > 0)
            pout("Log Sense for supported pages failed [%s]\n",             pout("Log Sense for supported pages failed [%s]\n",
                 scsiErrString(err));                  scsiErrString(err));
         return;          return;
    }     }
   
     for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) {      for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) {
         switch (gBuf[i])          switch (gBuf[i])
Line 144  static void scsiGetSupportedLogPages(scsi_device * dev Line 146  static void scsiGetSupportedLogPages(scsi_device * dev
   
 /* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad  /* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad
    (or at least something to report). */     (or at least something to report). */
static int scsiGetSmartData(scsi_device * device, bool attribs)static int
 scsiGetSmartData(scsi_device * device, bool attribs)
 {  {
     UINT8 asc;      UINT8 asc;
     UINT8 ascq;      UINT8 ascq;
Line 152  static int scsiGetSmartData(scsi_device * device, bool Line 155  static int scsiGetSmartData(scsi_device * device, bool
     UINT8 triptemp = 0;      UINT8 triptemp = 0;
     const char * cp;      const char * cp;
     int err = 0;      int err = 0;
   
     print_on();      print_on();
     if (scsiCheckIE(device, gSmartLPage, gTempLPage, &asc, &ascq,      if (scsiCheckIE(device, gSmartLPage, gTempLPage, &asc, &ascq,
                     &currenttemp, &triptemp)) {                      &currenttemp, &triptemp)) {
Line 165  static int scsiGetSmartData(scsi_device * device, bool Line 167  static int scsiGetSmartData(scsi_device * device, bool
     if (cp) {      if (cp) {
         err = -2;          err = -2;
         print_on();          print_on();
        pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq);         pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq);
         print_off();          print_off();
     } else if (gIecMPage)      } else if (gIecMPage)
         pout("SMART Health Status: OK\n");          pout("SMART Health Status: OK\n");
   
     if (attribs && !gTempLPage) {      if (attribs && !gTempLPage) {
         if (currenttemp || triptemp)  
             pout("\n");  
         if (currenttemp) {          if (currenttemp) {
             if (255 != currenttemp)              if (255 != currenttemp)
                 pout("Current Drive Temperature:     %d C\n", currenttemp);                  pout("Current Drive Temperature:     %d C\n", currenttemp);
Line 182  static int scsiGetSmartData(scsi_device * device, bool Line 182  static int scsiGetSmartData(scsi_device * device, bool
         if (triptemp)          if (triptemp)
             pout("Drive Trip Temperature:        %d C\n", triptemp);              pout("Drive Trip Temperature:        %d C\n", triptemp);
     }      }
       pout("\n");
     return err;      return err;
 }  }
   
Line 190  static int scsiGetSmartData(scsi_device * device, bool Line 191  static int scsiGetSmartData(scsi_device * device, bool
 // TapeAlerts fails  // TapeAlerts fails
 static const char * const severities = "CWI";  static const char * const severities = "CWI";
   
static int scsiGetTapeAlertsData(scsi_device * device, int peripheral_type)static int
 scsiGetTapeAlertsData(scsi_device * device, int peripheral_type)
 {  {
     unsigned short pagelength;      unsigned short pagelength;
     unsigned short parametercode;      unsigned short parametercode;
Line 223  static int scsiGetTapeAlertsData(scsi_device * device, Line 225  static int scsiGetTapeAlertsData(scsi_device * device,
                     scsiTapeAlertsTapeDevice(parametercode);                      scsiTapeAlertsTapeDevice(parametercode);
                 if (*ts == *s) {                  if (*ts == *s) {
                     if (!failures)                      if (!failures)
                        pout("TapeAlert Errors (C=Critical, W=Warning, I=Informational):\n");                        pout("TapeAlert Errors (C=Critical, W=Warning, "
                              "I=Informational):\n");
                     pout("[0x%02x] %s\n", parametercode, ts);                      pout("[0x%02x] %s\n", parametercode, ts);
                    failures += 1;                     failures += 1;
                 }                  }
             }              }
         }          }
Line 238  static int scsiGetTapeAlertsData(scsi_device * device, Line 241  static int scsiGetTapeAlertsData(scsi_device * device,
     return failures;      return failures;
 }  }
   
static void scsiGetStartStopData(scsi_device * device)static void
 scsiGetStartStopData(scsi_device * device)
 {  {
     UINT32 u;      UINT32 u;
     int err, len, k, extra, pc;      int err, len, k, extra, pc;
Line 312  static void scsiGetStartStopData(scsi_device * device) Line 316  static void scsiGetStartStopData(scsi_device * device)
             break;              break;
         }          }
     }      }
}
   
static void scsiPrintGrownDefectListLen(scsi_device * device)static void
 scsiPrintGrownDefectListLen(scsi_device * device)
 {  {
    int err, dl_format, dl_len, div;    int err, dl_format, got_rd12, generation;
     unsigned int dl_len, div;
   
    memset(gBuf, 0, 4);    memset(gBuf, 0, 8);
    if ((err = scsiReadDefect10(device, 0 /* req_plist */, 1 /* req_glist */,    if ((err = scsiReadDefect12(device, 0 /* req_plist */, 1 /* req_glist */,
                                4 /* bytes from index */, gBuf, 4))) {                                4 /* format: bytes from index */,
        if (scsi_debugmode > 0) {                                0 /* addr desc index */, gBuf, 8))) {
         if (2 == err) { /* command not supported */
             if ((err = scsiReadDefect10(device, 0 /* req_plist */, 1 /* req_glist */,
                                         4 /* format: bytes from index */, gBuf, 4))) {
                 if (scsi_debugmode > 0) {
                     print_on();
                     pout("Read defect list (10) Failed: %s\n", scsiErrString(err));
                     print_off();
                 }
                 return;
             } else
                 got_rd12 = 0;
         } else {
             if (scsi_debugmode > 0) {
                 print_on();
                 pout("Read defect list (12) Failed: %s\n", scsiErrString(err));
                 print_off();
             }
             return;
         }
     } else
         got_rd12 = 1;
 
     if (got_rd12) {
         generation = (gBuf[2] << 8) + gBuf[3];
         if ((generation > 1) && (scsi_debugmode > 0)) {
             print_on();              print_on();
            pout("Read defect list (10) Failed: %s\n", scsiErrString(err));            pout("Read defect list (12): generation=%d\n", generation);
             print_off();              print_off();
         }          }
        return;        dl_len = (gBuf[4] << 24) + (gBuf[5] << 16) + (gBuf[6] << 8) + gBuf[7];
     } else {
         dl_len = (gBuf[2] << 8) + gBuf[3];
     }      }
     if (0x8 != (gBuf[1] & 0x18)) {      if (0x8 != (gBuf[1] & 0x18)) {
         print_on();          print_on();
Line 340  static void scsiPrintGrownDefectListLen(scsi_device *  Line 373  static void scsiPrintGrownDefectListLen(scsi_device * 
         case 0:     /* short block */          case 0:     /* short block */
             div = 4;              div = 4;
             break;              break;
           case 1:     /* extended bytes from index */
           case 2:     /* extended physical sector */
               /* extended = 1; # might use in future */
               div = 8;
               break;
         case 3:     /* long block */          case 3:     /* long block */
         case 4:     /* bytes from index */          case 4:     /* bytes from index */
         case 5:     /* physical sector */          case 5:     /* physical sector */
Line 351  static void scsiPrintGrownDefectListLen(scsi_device *  Line 389  static void scsiPrintGrownDefectListLen(scsi_device * 
             print_off();              print_off();
             break;              break;
     }      }
     dl_len = (gBuf[2] << 8) + gBuf[3];  
     if (0 == dl_len)      if (0 == dl_len)
        pout("Elements in grown defect list: 0\n");        pout("Elements in grown defect list: 0\n\n");
     else {      else {
         if (0 == div)          if (0 == div)
            pout("Grown defect list length=%d bytes [unknown "            pout("Grown defect list length=%u bytes [unknown "
                 "number of elements]\n", dl_len);                 "number of elements]\n\n", dl_len);
         else          else
            pout("Elements in grown defect list: %d\n", dl_len / div);            pout("Elements in grown defect list: %u\n\n", dl_len / div);
     }      }
 }  }
   
static void scsiPrintSeagateCacheLPage(scsi_device * device)static void
 scsiPrintSeagateCacheLPage(scsi_device * device)
 {  {
     int k, j, num, pl, pc, err, len;      int k, j, num, pl, pc, err, len;
     unsigned char * ucp;      unsigned char * ucp;
Line 392  static void scsiPrintSeagateCacheLPage(scsi_device * d Line 430  static void scsiPrintSeagateCacheLPage(scsi_device * d
         switch (pc) {          switch (pc) {
         case 0: case 1: case 2: case 3: case 4:          case 0: case 1: case 2: case 3: case 4:
             break;              break;
        default:         default:
             if (scsi_debugmode > 0) {              if (scsi_debugmode > 0) {
                 print_on();                  print_on();
                 pout("Vendor (Seagate) cache lpage has unexpected parameter"                  pout("Vendor (Seagate) cache lpage has unexpected parameter"
Line 436  static void scsiPrintSeagateCacheLPage(scsi_device * d Line 474  static void scsiPrintSeagateCacheLPage(scsi_device * d
         num -= pl;          num -= pl;
         ucp += pl;          ucp += pl;
     }      }
       pout("\n");
 }  }
   
static void scsiPrintSeagateFactoryLPage(scsi_device * device)static void
 scsiPrintSeagateFactoryLPage(scsi_device * device)
 {  {
     int k, j, num, pl, pc, len, err, good, bad;      int k, j, num, pl, pc, len, err, good, bad;
     unsigned char * ucp;      unsigned char * ucp;
Line 470  static void scsiPrintSeagateFactoryLPage(scsi_device * Line 510  static void scsiPrintSeagateFactoryLPage(scsi_device *
         case 0: case 8:          case 0: case 8:
             ++good;              ++good;
             break;              break;
        default:         default:
             ++bad;              ++bad;
             break;              break;
         }          }
Line 530  static void scsiPrintSeagateFactoryLPage(scsi_device * Line 570  static void scsiPrintSeagateFactoryLPage(scsi_device *
         num -= pl;          num -= pl;
         ucp += pl;          ucp += pl;
     }      }
       pout("\n");
 }  }
   
static void scsiPrintErrorCounterLog(scsi_device * device)static void
 scsiPrintErrorCounterLog(scsi_device * device)
 {  {
     struct scsiErrorCounter errCounterArr[3];      struct scsiErrorCounter errCounterArr[3];
     struct scsiErrorCounter * ecp;      struct scsiErrorCounter * ecp;
Line 563  static void scsiPrintErrorCounterLog(scsi_device * dev Line 605  static void scsiPrintErrorCounterLog(scsi_device * dev
         }          }
     }      }
     if (found[0] || found[1] || found[2]) {      if (found[0] || found[1] || found[2]) {
        pout("\nError counter log:\n");        pout("Error counter log:\n");
         pout("           Errors Corrected by           Total   "          pout("           Errors Corrected by           Total   "
              "Correction     Gigabytes    Total\n");               "Correction     Gigabytes    Total\n");
         pout("               ECC          rereads/    errors   "          pout("               ECC          rereads/    errors   "
Line 574  static void scsiPrintErrorCounterLog(scsi_device * dev Line 616  static void scsiPrintErrorCounterLog(scsi_device * dev
             if (! found[k])              if (! found[k])
                 continue;                  continue;
             ecp = &errCounterArr[k];              ecp = &errCounterArr[k];
            pout("%s%8"PRIu64" %8"PRIu64"  %8"PRIu64"  %8"PRIu64"   %8"PRIu64,             pout("%s%8"PRIu64" %8"PRIu64"  %8"PRIu64"  %8"PRIu64"   %8"PRIu64,
                 pageNames[k], ecp->counter[0], ecp->counter[1],                  pageNames[k], ecp->counter[0], ecp->counter[1],
                  ecp->counter[2], ecp->counter[3], ecp->counter[4]);                   ecp->counter[2], ecp->counter[3], ecp->counter[4]);
             processed_gb = ecp->counter[5] / 1000000000.0;              processed_gb = ecp->counter[5] / 1000000000.0;
             pout("   %12.3f    %8"PRIu64"\n", processed_gb, ecp->counter[6]);              pout("   %12.3f    %8"PRIu64"\n", processed_gb, ecp->counter[6]);
         }          }
     }      }
    else     else
        pout("\nError Counter logging not supported\n");        pout("Error Counter logging not supported\n");
     if (gNonMediumELPage && (0 == scsiLogSense(device,      if (gNonMediumELPage && (0 == scsiLogSense(device,
                 NON_MEDIUM_ERROR_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) {                  NON_MEDIUM_ERROR_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) {
         scsiDecodeNonMediumErrPage(gBuf, &nme);          scsiDecodeNonMediumErrPage(gBuf, &nme);
Line 636  static void scsiPrintErrorCounterLog(scsi_device * dev Line 678  static void scsiPrintErrorCounterLog(scsi_device * dev
                      "bytes\n", LOG_RESP_LONG_LEN, truncated);                       "bytes\n", LOG_RESP_LONG_LEN, truncated);
         }          }
     }      }
       pout("\n");
 }  }
   
 static const char * self_test_code[] = {  static const char * self_test_code[] = {
        "Default         ",         "Default         ",
        "Background short",         "Background short",
        "Background long ",         "Background long ",
         "Reserved(3)     ",          "Reserved(3)     ",
        "Abort background",         "Abort background",
        "Foreground short",         "Foreground short",
         "Foreground long ",          "Foreground long ",
         "Reserved(7)     "          "Reserved(7)     "
 };  };
Line 658  static const char * self_test_result[] = { Line 701  static const char * self_test_result[] = {
         "Failed in first segment  ",          "Failed in first segment  ",
         "Failed in second segment ",          "Failed in second segment ",
         "Failed in segment -->    ",          "Failed in segment -->    ",
        "Reserved(8)              ",         "Reserved(8)              ",
        "Reserved(9)              ",         "Reserved(9)              ",
        "Reserved(10)             ",         "Reserved(10)             ",
        "Reserved(11)             ",         "Reserved(11)             ",
        "Reserved(12)             ",         "Reserved(12)             ",
        "Reserved(13)             ",         "Reserved(13)             ",
         "Reserved(14)             ",          "Reserved(14)             ",
         "Self test in progress ..."          "Self test in progress ..."
 };  };
Line 672  static const char * self_test_result[] = { Line 715  static const char * self_test_result[] = {
 // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent  // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent
 // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or  // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or
 // FAILSMART is returned.  // FAILSMART is returned.
static int scsiPrintSelfTest(scsi_device * device)static int
 scsiPrintSelfTest(scsi_device * device)
 {  {
     int num, k, n, res, err, durationSec;      int num, k, n, res, err, durationSec;
     int noheader = 1;      int noheader = 1;
     int retval = 0;      int retval = 0;
     UINT8 * ucp;      UINT8 * ucp;
     uint64_t ull=0;      uint64_t ull=0;
       struct scsi_sense_disect sense_info;
   
       // check if test is running
       if (!scsiRequestSense(device, &sense_info) &&
                           (sense_info.asc == 0x04 && sense_info.ascq == 0x09 &&
                           sense_info.progress != -1)) {
           pout("Self-test execution status:\t\t%d%% of test remaining\n",
                100 - ((sense_info.progress * 100) / 65535));
       }
   
     if ((err = scsiLogSense(device, SELFTEST_RESULTS_LPAGE, 0, gBuf,      if ((err = scsiLogSense(device, SELFTEST_RESULTS_LPAGE, 0, gBuf,
                             LOG_RESP_SELF_TEST_LEN, 0))) {                              LOG_RESP_SELF_TEST_LEN, 0))) {
         print_on();          print_on();
Line 716  static int scsiPrintSelfTest(scsi_device * device) Line 769  static int scsiPrintSelfTest(scsi_device * device)
   
         // only print header if needed          // only print header if needed
         if (noheader) {          if (noheader) {
            pout("\nSMART Self-test log\n");            pout("SMART Self-test log\n");
             pout("Num  Test              Status                 segment  "              pout("Num  Test              Status                 segment  "
                    "LifeTime  LBA_first_err [SK ASC ASQ]\n");                     "LifeTime  LBA_first_err [SK ASC ASQ]\n");
             pout("     Description                              number   "              pout("     Description                              number   "
Line 725  static int scsiPrintSelfTest(scsi_device * device) Line 778  static int scsiPrintSelfTest(scsi_device * device)
         }          }
   
         // print parameter code (test number) & self-test code text          // print parameter code (test number) & self-test code text
        pout("#%2d  %s", (ucp[0] << 8) | ucp[1],         pout("#%2d  %s", (ucp[0] << 8) | ucp[1],
             self_test_code[(ucp[4] >> 5) & 0x7]);              self_test_code[(ucp[4] >> 5) & 0x7]);
   
         // check the self-test result nibble, using the self-test results          // check the self-test result nibble, using the self-test results
Line 777  static int scsiPrintSelfTest(scsi_device * device) Line 830  static int scsiPrintSelfTest(scsi_device * device)
         if (n==0 && res==0xf)          if (n==0 && res==0xf)
         // self-test in progress          // self-test in progress
             pout("     NOW");              pout("     NOW");
        else           else
             pout("   %5d", n);              pout("   %5d", n);
          
         // construct 8-byte integer address of first failure          // construct 8-byte integer address of first failure
         for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
             ull <<= 8;              ull <<= 8;
Line 808  static int scsiPrintSelfTest(scsi_device * device) Line 861  static int scsiPrintSelfTest(scsi_device * device)
     if (noheader)      if (noheader)
         pout("No self-tests have been logged\n");          pout("No self-tests have been logged\n");
     else      else
         pout("\n");  
     if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec,      if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec,
                         modese_len)) && (durationSec > 0)) {                          modese_len)) && (durationSec > 0)) {
         pout("Long (extended) Self Test duration: %d seconds "          pout("Long (extended) Self Test duration: %d seconds "
              "[%.1f minutes]\n", durationSec, durationSec / 60.0);               "[%.1f minutes]\n", durationSec, durationSec / 60.0);
     }      }
       pout("\n");
     return retval;      return retval;
 }  }
   
Line 845  static const char * reassign_status[] = { Line 898  static const char * reassign_status[] = {
 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry  // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
 // and up to 2048 events (although would hope to have less). May set  // and up to 2048 events (although would hope to have less). May set
 // FAILLOG if serious errors detected (in the future).  // FAILLOG if serious errors detected (in the future).
static int scsiPrintBackgroundResults(scsi_device * device)static int
 scsiPrintBackgroundResults(scsi_device * device)
 {  {
     int num, j, m, err, pc, pl, truncated;      int num, j, m, err, pc, pl, truncated;
     int noheader = 1;      int noheader = 1;
Line 888  static int scsiPrintBackgroundResults(scsi_device * de Line 942  static int scsiPrintBackgroundResults(scsi_device * de
         case 0:          case 0:
             if (noheader) {              if (noheader) {
                 noheader = 0;                  noheader = 0;
                pout("\nBackground scan results log\n");                pout("Background scan results log\n");
             }              }
             pout("  Status: ");              pout("  Status: ");
             if ((pl < 16) || (num < 16)) {              if ((pl < 16) || (num < 16)) {
Line 945  static int scsiPrintBackgroundResults(scsi_device * de Line 999  static int scsiPrintBackgroundResults(scsi_device * de
     if (truncated)      if (truncated)
         pout(" >>>> log truncated, fetched %d of %d available "          pout(" >>>> log truncated, fetched %d of %d available "
              "bytes\n", LOG_RESP_LONG_LEN, truncated);               "bytes\n", LOG_RESP_LONG_LEN, truncated);
       pout("\n");
     return retval;      return retval;
 }  }
   
Line 952  static int scsiPrintBackgroundResults(scsi_device * de Line 1007  static int scsiPrintBackgroundResults(scsi_device * de
 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry  // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
 // and up to 2048 events (although would hope to have less). May set  // and up to 2048 events (although would hope to have less). May set
 // FAILLOG if serious errors detected (in the future).  // FAILLOG if serious errors detected (in the future).
static int scsiPrintSSMedia(scsi_device * device)static int
 scsiPrintSSMedia(scsi_device * device)
 {  {
     int num, err, pc, pl, truncated;      int num, err, pc, pl, truncated;
     int retval = 0;      int retval = 0;
Line 990  static int scsiPrintSSMedia(scsi_device * device) Line 1046  static int scsiPrintSSMedia(scsi_device * device)
         pl = ucp[3] + 4;          pl = ucp[3] + 4;
         switch (pc) {          switch (pc) {
         case 1:          case 1:
            if (pl < 8) {            if (pl < 8) {
                 print_on();                  print_on();
                 pout("Percentage used endurance indicator too short (pl=%d)\n", pl);                  pout("Percentage used endurance indicator too short (pl=%d)\n", pl);
                 print_off();                  print_off();
                 return FAILSMART;                  return FAILSMART;
            }            }
             pout("SS Media used endurance indicator: %d%%\n", ucp[7]);              pout("SS Media used endurance indicator: %d%%\n", ucp[7]);
        default:        /* ignore other parameter codes */        default:        /* ignore other parameter codes */
             break;              break;
         }          }
         num -= pl;          num -= pl;
Line 1006  static int scsiPrintSSMedia(scsi_device * device) Line 1062  static int scsiPrintSSMedia(scsi_device * device)
     return retval;      return retval;
 }  }
   
static void show_sas_phy_event_info(int peis, unsigned int val,static void
                                    unsigned thresh_val)show_sas_phy_event_info(int peis, unsigned int val, unsigned thresh_val)
 {  {
     unsigned int u;      unsigned int u;
   
Line 1137  static void show_sas_phy_event_info(int peis, unsigned Line 1193  static void show_sas_phy_event_info(int peis, unsigned
     }      }
 }  }
   
static void show_sas_port_param(unsigned char * ucp, int param_len)static void
 show_sas_port_param(unsigned char * ucp, int param_len)
 {  {
     int j, m, n, nphys, t, sz, spld_len;      int j, m, n, nphys, t, sz, spld_len;
     unsigned char * vcp;      unsigned char * vcp;
Line 1268  static void show_sas_port_param(unsigned char * ucp, i Line 1325  static void show_sas_port_param(unsigned char * ucp, i
 }  }
   
 // Returns 1 if okay, 0 if non SAS descriptors  // Returns 1 if okay, 0 if non SAS descriptors
static int show_protocol_specific_page(unsigned char * resp, int len)static int
 show_protocol_specific_page(unsigned char * resp, int len)
 {  {
     int k, num, param_len;      int k, num, param_len;
     unsigned char * ucp;      unsigned char * ucp;
Line 1284  static int show_protocol_specific_page(unsigned char * Line 1342  static int show_protocol_specific_page(unsigned char *
         k += param_len;          k += param_len;
         ucp += param_len;          ucp += param_len;
     }      }
       pout("\n");
     return 1;      return 1;
 }  }
   
Line 1294  static int show_protocol_specific_page(unsigned char * Line 1353  static int show_protocol_specific_page(unsigned char *
 // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent  // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent
 // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or  // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or
 // FAILSMART is returned.  // FAILSMART is returned.
static int scsiPrintSasPhy(scsi_device * device, int reset)static int
 scsiPrintSasPhy(scsi_device * device, int reset)
 {  {
     int num, err;      int num, err;
   
     if ((err = scsiLogSense(device, PROTOCOL_SPECIFIC_LPAGE, 0, gBuf,      if ((err = scsiLogSense(device, PROTOCOL_SPECIFIC_LPAGE, 0, gBuf,
                             LOG_RESP_LONG_LEN, 0))) {                              LOG_RESP_LONG_LEN, 0))) {
         print_on();          print_on();
        pout("scsiPrintSasPhy Log Sense Failed [%s]\n", scsiErrString(err));        pout("scsiPrintSasPhy Log Sense Failed [%s]\n\n", scsiErrString(err));
         print_off();          print_off();
         return FAILSMART;          return FAILSMART;
     }      }
     if ((gBuf[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE) {      if ((gBuf[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE) {
         print_on();          print_on();
        pout("Protocol specific Log Sense Failed, page mismatch\n");        pout("Protocol specific Log Sense Failed, page mismatch\n\n");
         print_off();          print_off();
         return FAILSMART;          return FAILSMART;
     }      }
Line 1315  static int scsiPrintSasPhy(scsi_device * device, int r Line 1375  static int scsiPrintSasPhy(scsi_device * device, int r
     num = (gBuf[2] << 8) + gBuf[3];      num = (gBuf[2] << 8) + gBuf[3];
     if (1 != show_protocol_specific_page(gBuf, num + 4)) {      if (1 != show_protocol_specific_page(gBuf, num + 4)) {
         print_on();          print_on();
        pout("Only support protocol specific log page on SAS devices\n");        pout("Only support protocol specific log page on SAS devices\n\n");
         print_off();          print_off();
         return FAILSMART;          return FAILSMART;
     }      }
Line 1323  static int scsiPrintSasPhy(scsi_device * device, int r Line 1383  static int scsiPrintSasPhy(scsi_device * device, int r
         if ((err = scsiLogSelect(device, 1 /* pcr */, 0 /* sp */, 0 /* pc */,          if ((err = scsiLogSelect(device, 1 /* pcr */, 0 /* sp */, 0 /* pc */,
                                  PROTOCOL_SPECIFIC_LPAGE, 0, NULL, 0))) {                                   PROTOCOL_SPECIFIC_LPAGE, 0, NULL, 0))) {
             print_on();              print_on();
            pout("scsiPrintSasPhy Log Select (reset) Failed [%s]\n",            pout("scsiPrintSasPhy Log Select (reset) Failed [%s]\n\n",
                  scsiErrString(err));                   scsiErrString(err));
             print_off();              print_off();
             return FAILSMART;              return FAILSMART;
Line 1372  static const char * transport_proto_arr[] = { Line 1432  static const char * transport_proto_arr[] = {
 };  };
   
 /* Returns 0 on success, 1 on general error and 2 for early, clean exit */  /* Returns 0 on success, 1 on general error and 2 for early, clean exit */
static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all)static int
 scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all)
 {  {
     char timedatetz[DATEANDEPOCHLEN];      char timedatetz[DATEANDEPOCHLEN];
     struct scsi_iec_mode_page iec;      struct scsi_iec_mode_page iec;
    int err, iec_err, len, req_len, avail_len;    int err, iec_err, len, req_len, avail_len, n;
     int is_tape = 0;      int is_tape = 0;
     int peri_dt = 0;      int peri_dt = 0;
     int returnval = 0;      int returnval = 0;
     int transport = -1;      int transport = -1;
            int form_factor = 0;
     int protect = 0;
 
     memset(gBuf, 0, 96);      memset(gBuf, 0, 96);
     req_len = 36;      req_len = 36;
     if ((err = scsiStdInquiry(device, gBuf, req_len))) {      if ((err = scsiStdInquiry(device, gBuf, req_len))) {
Line 1411  static int scsiGetDriveInfo(scsi_device * device, UINT Line 1474  static int scsiGetDriveInfo(scsi_device * device, UINT
         print_off();          print_off();
         return 1;          return 1;
     }      }
   
     if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) {      if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) {
        pout("Vendor:               %.8s\n", (char *)&gBuf[8]);        char vendor[8+1], product[16+1], revision[4+1];
        pout("Product:              %.16s\n", (char *)&gBuf[16]);        scsi_format_id_string(vendor, (const unsigned char *)&gBuf[8], 8);
        if (gBuf[32] >= ' ')        scsi_format_id_string(product, (const unsigned char *)&gBuf[16], 16);
            pout("Revision:             %.4s\n", (char *)&gBuf[32]);        scsi_format_id_string(revision, (const unsigned char *)&gBuf[32], 4);
 
         pout("=== START OF INFORMATION SECTION ===\n");
         pout("Vendor:               %.8s\n", vendor);
         pout("Product:              %.16s\n", product);
         if (gBuf[32] >= ' ')
             pout("Revision:             %.4s\n", revision);
     }      }
   
     if (!*device->get_req_type()/*no type requested*/ &&      if (!*device->get_req_type()/*no type requested*/ &&
Line 1427  static int scsiGetDriveInfo(scsi_device * device, UINT Line 1497  static int scsiGetDriveInfo(scsi_device * device, UINT
     if (! all)      if (! all)
         return 0;          return 0;
   
    unsigned int lb_size;    protect = gBuf[5] & 0x1;    /* from and including SPC-3 */
    char cap_str[64]; 
    char si_str[64]; 
    char lb_str[16]; 
    uint64_t capacity = scsiGetSize(device, &lb_size); 
   
    if (capacity) {    if (! is_tape) {    /* only do this for disks */
        format_with_thousands_sep(cap_str, sizeof(cap_str), capacity);        unsigned int lb_size = 0;
        format_capacity(si_str, sizeof(si_str), capacity);        unsigned char lb_prov_resp[8];
        pout("User Capacity:        %s bytes [%s]\n", cap_str, si_str);        char cap_str[64];
        snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size);        char si_str[64];
        pout("Logical block size:   %s bytes\n", lb_str);        char lb_str[16];
         int lb_per_pb_exp = 0;
         uint64_t capacity = scsiGetSize(device, &lb_size, &lb_per_pb_exp);
 
         if (capacity) {
             format_with_thousands_sep(cap_str, sizeof(cap_str), capacity);
             format_capacity(si_str, sizeof(si_str), capacity);
             pout("User Capacity:        %s bytes [%s]\n", cap_str, si_str);
             snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size);
             pout("Logical block size:   %s bytes\n", lb_str);
         }
         int lbpme = -1;
         int lbprz = -1;
         if (protect || lb_per_pb_exp) {
             unsigned char rc16_12[20] = {0, };
 
             if (0 == scsiGetProtPBInfo(device, rc16_12)) {
                 lb_per_pb_exp = rc16_12[1] & 0xf;       /* just in case */
                 if (lb_per_pb_exp > 0) {
                     snprintf(lb_str, sizeof(lb_str) - 1, "%u",
                              (lb_size * (1 << lb_per_pb_exp)));
                     pout("Physical block size:  %s bytes\n", lb_str);
                     n = ((rc16_12[2] & 0x3f) << 8) + rc16_12[3];
                     pout("Lowest aligned LBA:   %d\n", n);
                 }
                 if (rc16_12[0] & 0x1) { /* PROT_EN set */
                     int p_type = ((rc16_12[0] >> 1) & 0x7);
 
                     switch (p_type) {
                     case 0 :
                         pout("Formatted with type 1 protection\n");
                         break;
                     case 1 :
                         pout("Formatted with type 2 protection\n");
                         break;
                     case 2 :
                         pout("Formatted with type 3 protection\n");
                         break;
                     default:
                         pout("Formatted with unknown protection type [%d]\n",
                              p_type);
                         break;
                     }
                     int p_i_exp = ((rc16_12[1] >> 4) & 0xf);
 
                     if (p_i_exp > 0)
                         pout("%d protection information intervals per "
                              "logical block\n", (1 << p_i_exp));
                 }
                 /* Pick up some LB provisioning info since its available */
                 lbpme = !! (rc16_12[2] & 0x80);
                 lbprz = !! (rc16_12[2] & 0x40);
             }
         }
         if (0 == scsiInquiryVpd(device, SCSI_VPD_LOGICAL_BLOCK_PROVISIONING,
                                 lb_prov_resp, sizeof(lb_prov_resp))) {
             int prov_type = lb_prov_resp[6] & 0x7;
 
             if (-1 == lbprz)
                 lbprz = !! (lb_prov_resp[5] & 0x4);
             switch (prov_type) {
             case 0:
                 pout("Logical block provisioning type unreported, "
                      "LBPME=%d, LBPRZ=%d\n", lbpme, lbprz);
                 break;
             case 1:
                 pout("LU is resource provisioned, LBPRZ=%d\n", lbprz);
                 break;
             case 2:
                 pout("LU is thin provisioned, LBPRZ=%d\n", lbprz);
                 break;
             default:
                 pout("LU provisioning type reserved [%d], LBPRZ=%d\n",
                      prov_type, lbprz);
                 break;
             }
         } else if (1 == lbpme)
             pout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz);
 
         int rpm = scsiGetRPM(device, modese_len, &form_factor);
         if (rpm > 0) {
             if (1 == rpm)
                 pout("Rotation Rate:        Solid State Device\n");
             else
                 pout("Rotation Rate:        %d rpm\n", rpm);
         }
         if (form_factor > 0) {
             const char * cp = NULL;
 
             switch (form_factor) {
             case 1:
                 cp = "5.25";
                 break;
             case 2:
                 cp = "3.5";
                 break;
             case 3:
                 cp = "2.5";
                 break;
             case 4:
                 cp = "1.8";
                 break;
             case 5:
                 cp = "< 1.8";
                 break;
             }
             if (cp)
                 pout("Form Factor:          %s inches\n", cp);
         }
     }      }
   
     /* Do this here to try and detect badly conforming devices (some USB      /* Do this here to try and detect badly conforming devices (some USB
Line 1455  static int scsiGetDriveInfo(scsi_device * device, UINT Line 1629  static int scsiGetDriveInfo(scsi_device * device, UINT
         modese_len = iec.modese_len;          modese_len = iec.modese_len;
   
     if (! dont_print_serial_number) {      if (! dont_print_serial_number) {
        if (0 == (err = scsiInquiryVpd(device, 0x83, gBuf, 200))) {        if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_DEVICE_IDENTIFICATION,
            char s[256];                                       gBuf, 252))) {
             char s[256];
   
             len = gBuf[3];              len = gBuf[3];
            scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport);            scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport);
            if (strlen(s) > 0)            if (strlen(s) > 0)
                 pout("Logical Unit id:      %s\n", s);                  pout("Logical Unit id:      %s\n", s);
         } else if (scsi_debugmode > 0) {          } else if (scsi_debugmode > 0) {
             print_on();              print_on();
Line 1470  static int scsiGetDriveInfo(scsi_device * device, UINT Line 1645  static int scsiGetDriveInfo(scsi_device * device, UINT
                 pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);                  pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
             print_off();              print_off();
         }          }
        if (0 == (err = scsiInquiryVpd(device, 0x80, gBuf, 64))) {        if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_UNIT_SERIAL_NUMBER,
                                        gBuf, 252))) {
             char serial[256];
             len = gBuf[3];              len = gBuf[3];
   
             gBuf[4 + len] = '\0';              gBuf[4 + len] = '\0';
            pout("Serial number:        %s\n", &gBuf[4]);            scsi_format_id_string(serial, &gBuf[4], len);
             pout("Serial number:        %s\n", serial);
         } else if (scsi_debugmode > 0) {          } else if (scsi_debugmode > 0) {
             print_on();              print_on();
             if (SIMPLE_ERR_BAD_RESP == err)              if (SIMPLE_ERR_BAD_RESP == err)
Line 1485  static int scsiGetDriveInfo(scsi_device * device, UINT Line 1664  static int scsiGetDriveInfo(scsi_device * device, UINT
     }      }
   
     // print SCSI peripheral device type      // print SCSI peripheral device type
    if (peri_dt < (int)(sizeof(peripheral_dt_arr) /     if (peri_dt < (int)(sizeof(peripheral_dt_arr) /
                         sizeof(peripheral_dt_arr[0])))                          sizeof(peripheral_dt_arr[0])))
         pout("Device type:          %s\n", peripheral_dt_arr[peri_dt]);          pout("Device type:          %s\n", peripheral_dt_arr[peri_dt]);
     else      else
Line 1528  static int scsiGetDriveInfo(scsi_device * device, UINT Line 1707  static int scsiGetDriveInfo(scsi_device * device, UINT
         }          }
         failuretest(MANDATORY_CMD, returnval|=FAILID);          failuretest(MANDATORY_CMD, returnval|=FAILID);
     }      }
   
     if (iec_err) {      if (iec_err) {
         if (!is_tape) {          if (!is_tape) {
             print_on();              print_on();
            pout("Device does not support SMART");            pout("SMART support is:     Unavailable - device lacks SMART capability.\n");
             if (scsi_debugmode > 0)              if (scsi_debugmode > 0)
                 pout(" [%s]\n", scsiErrString(iec_err));                  pout(" [%s]\n", scsiErrString(iec_err));
             else  
                 pout("\n");  
             print_off();              print_off();
         }          }
         gIecMPage = 0;          gIecMPage = 0;
Line 1544  static int scsiGetDriveInfo(scsi_device * device, UINT Line 1721  static int scsiGetDriveInfo(scsi_device * device, UINT
     }      }
   
     if (!is_tape)      if (!is_tape)
        pout("Device supports SMART and is %s\n",        pout("SMART support is:     Available - device has SMART capability.\n"
              "SMART support is:     %s\n",
              (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled");               (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled");
    pout("%s\n", (scsi_IsWarningEnabled(&iec)) ?     pout("%s\n", (scsi_IsWarningEnabled(&iec)) ?
                  "Temperature Warning Enabled" :                  "Temperature Warning:  Enabled" :
                  "Temperature Warning Disabled or Not Supported");                  "Temperature Warning:  Disabled or Not Supported");
     return 0;      return 0;
 }  }
   
static int scsiSmartEnable(scsi_device * device)static int
 scsiSmartEnable(scsi_device * device)
 {  {
     struct scsi_iec_mode_page iec;      struct scsi_iec_mode_page iec;
     int err;      int err;
   
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {      if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
         print_on();          print_on();
        pout("unable to fetch IEC (SMART) mode page [%s]\n",         pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));               scsiErrString(err));
         print_off();          print_off();
         return 1;          return 1;
Line 1575  static int scsiSmartEnable(scsi_device * device) Line 1754  static int scsiSmartEnable(scsi_device * device)
     }      }
     /* Need to refetch 'iec' since could be modified by previous call */      /* Need to refetch 'iec' since could be modified by previous call */
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {      if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
        pout("unable to fetch IEC (SMART) mode page [%s]\n",         pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));               scsiErrString(err));
         return 1;          return 1;
     } else      } else
Line 1587  static int scsiSmartEnable(scsi_device * device) Line 1766  static int scsiSmartEnable(scsi_device * device)
          scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled");           scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled");
     return 0;      return 0;
 }  }
        
static int scsiSmartDisable(scsi_device * device)static int
 scsiSmartDisable(scsi_device * device)
 {  {
     struct scsi_iec_mode_page iec;      struct scsi_iec_mode_page iec;
     int err;      int err;
   
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {      if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
         print_on();          print_on();
        pout("unable to fetch IEC (SMART) mode page [%s]\n",         pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));               scsiErrString(err));
         print_off();          print_off();
         return 1;          return 1;
Line 1611  static int scsiSmartDisable(scsi_device * device) Line 1791  static int scsiSmartDisable(scsi_device * device)
     }      }
     /* Need to refetch 'iec' since could be modified by previous call */      /* Need to refetch 'iec' since could be modified by previous call */
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {      if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
        pout("unable to fetch IEC (SMART) mode page [%s]\n",         pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));               scsiErrString(err));
         return 1;          return 1;
     } else      } else
Line 1624  static int scsiSmartDisable(scsi_device * device) Line 1804  static int scsiSmartDisable(scsi_device * device)
     return 0;      return 0;
 }  }
   
static void scsiPrintTemp(scsi_device * device)static void
 scsiPrintTemp(scsi_device * device)
 {  {
     UINT8 temp = 0;      UINT8 temp = 0;
     UINT8 trip = 0;      UINT8 trip = 0;
   
     if (scsiGetTemp(device, &temp, &trip))      if (scsiGetTemp(device, &temp, &trip))
         return;          return;
  
     if (temp) {      if (temp) {
         if (255 != temp)          if (255 != temp)
             pout("Current Drive Temperature:     %d C\n", temp);              pout("Current Drive Temperature:     %d C\n", temp);
Line 1640  static void scsiPrintTemp(scsi_device * device) Line 1821  static void scsiPrintTemp(scsi_device * device)
     }      }
     if (trip)      if (trip)
         pout("Drive Trip Temperature:        %d C\n", trip);          pout("Drive Trip Temperature:        %d C\n", trip);
       if (temp || trip)
           pout("\n");
 }  }
   
 /* Main entry point used by smartctl command. Return 0 for success */  /* Main entry point used by smartctl command. Return 0 for success */
int scsiPrintMain(scsi_device * device, const scsi_print_options & options)int
 scsiPrintMain(scsi_device * device, const scsi_print_options & options)
 {  {
     int checkedSupportedLogPages = 0;      int checkedSupportedLogPages = 0;
     UINT8 peripheral_type = 0;      UINT8 peripheral_type = 0;
     int returnval = 0;      int returnval = 0;
     int res, durationSec;      int res, durationSec;
       struct scsi_sense_disect sense_info;
   
     bool any_output = options.drive_info;      bool any_output = options.drive_info;
   
       if (supported_vpd_pages_p) {
           delete supported_vpd_pages_p;
           supported_vpd_pages_p = NULL;
       }
       supported_vpd_pages_p = new supported_vpd_pages(device);
   
     res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info);      res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info);
     if (res) {      if (res) {
         if (2 == res)          if (2 == res)
             return 0;              return 0;
         else          else
             failuretest(MANDATORY_CMD, returnval |= FAILID);              failuretest(MANDATORY_CMD, returnval |= FAILID);
        any_output = true;        any_output = true;
     }      }
   
     // Print read look-ahead status for disks
     short int wce = -1, rcd = -1;
     if (options.get_rcd || options.get_wce) {
       if (SCSI_PT_DIRECT_ACCESS == peripheral_type)
          res = scsiGetSetCache(device, modese_len, &wce, &rcd);
       else
          res = -1; // fetch for disks only
       any_output = true;
     }
   
     if (options.get_rcd) {
       pout("Read Cache is:        %s\n",
         res ? "Unavailable" : // error
         rcd ? "Disabled" : "Enabled");
      }
   
     if (options.get_wce) {
       pout("Writeback Cache is:   %s\n",
         res ? "Unavailable" : // error
         !wce ? "Disabled" : "Enabled");
      }
      if (options.drive_info)
        pout("\n");
   
     // START OF THE ENABLE/DISABLE SECTION OF THE CODE
     if (   options.smart_disable           || options.smart_enable
         || options.smart_auto_save_disable || options.smart_auto_save_enable)
       pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
   
     if (options.smart_enable) {      if (options.smart_enable) {
         if (scsiSmartEnable(device))          if (scsiSmartEnable(device))
             failuretest(MANDATORY_CMD, returnval |= FAILSMART);              failuretest(MANDATORY_CMD, returnval |= FAILSMART);
        any_output = true;        any_output = true;
     }      }
   
     if (options.smart_disable) {      if (options.smart_disable) {
         if (scsiSmartDisable(device))          if (scsiSmartDisable(device))
             failuretest(MANDATORY_CMD,returnval |= FAILSMART);              failuretest(MANDATORY_CMD,returnval |= FAILSMART);
        any_output = true;        any_output = true;
     }      }
    
     if (options.smart_auto_save_enable) {      if (options.smart_auto_save_enable) {
       if (scsiSetControlGLTSD(device, 0, modese_len)) {        if (scsiSetControlGLTSD(device, 0, modese_len)) {
         pout("Enable autosave (clear GLTSD bit) failed\n");          pout("Enable autosave (clear GLTSD bit) failed\n");
         failuretest(OPTIONAL_CMD,returnval |= FAILSMART);          failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
       }        }
         else {
            pout("Autosave enabled (GLTSD bit set).\n");
         }
       any_output = true;        any_output = true;
     }      }
    
     // Enable/Disable write cache
     if (options.set_wce && SCSI_PT_DIRECT_ACCESS == peripheral_type) {
       short int enable = wce = (options.set_wce > 0);
       rcd = -1;
       if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
           pout("Write cache %sable failed: %s\n", (enable ? "en" : "dis"),
                device->get_errmsg());
           failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
       }
       else
         pout("Write cache %sabled\n", (enable ? "en" : "dis"));
       any_output = true;
     }
 
     // Enable/Disable read cache
     if (options.set_rcd && SCSI_PT_DIRECT_ACCESS == peripheral_type) {
       short int enable =  (options.set_rcd > 0);
       rcd = !enable;
       wce = -1;
       if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
           pout("Read cache %sable failed: %s\n", (enable ? "en" : "dis"),
                 device->get_errmsg());
           failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
       }
       else
         pout("Read cache %sabled\n", (enable ? "en" : "dis"));
       any_output = true;
     }
 
     if (options.smart_auto_save_disable) {      if (options.smart_auto_save_disable) {
       if (scsiSetControlGLTSD(device, 1, modese_len)) {        if (scsiSetControlGLTSD(device, 1, modese_len)) {
         pout("Disable autosave (set GLTSD bit) failed\n");          pout("Disable autosave (set GLTSD bit) failed\n");
         failuretest(OPTIONAL_CMD,returnval |= FAILSMART);          failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
       }        }
         else {
            pout("Autosave disabled (GLTSD bit cleared).\n");
         }
       any_output = true;        any_output = true;
     }      }
      if (   options.smart_disable           || options.smart_enable
       || options.smart_auto_save_disable || options.smart_auto_save_enable)
     pout("\n"); // END OF THE ENABLE/DISABLE SECTION OF THE CODE
 
     // START OF READ-ONLY OPTIONS APART FROM -V and -i
     if (    options.smart_check_status  || options.smart_ss_media_log
            || options.smart_vendor_attrib || options.smart_error_log
            || options.smart_selftest_log  || options.smart_vendor_attrib
            || options.smart_background_log || options.sasphy
          )
     pout("=== START OF READ SMART DATA SECTION ===\n");
 
     if (options.smart_check_status) {      if (options.smart_check_status) {
         scsiGetSupportedLogPages(device);          scsiGetSupportedLogPages(device);
         checkedSupportedLogPages = 1;          checkedSupportedLogPages = 1;
Line 1711  int scsiPrintMain(scsi_device * device, const scsi_pri Line 1977  int scsiPrintMain(scsi_device * device, const scsi_pri
             }              }
         }          }
         any_output = true;          any_output = true;
    }       }
 
     if (options.smart_ss_media_log) {      if (options.smart_ss_media_log) {
         if (! checkedSupportedLogPages)          if (! checkedSupportedLogPages)
             scsiGetSupportedLogPages(device);              scsiGetSupportedLogPages(device);
Line 1726  int scsiPrintMain(scsi_device * device, const scsi_pri Line 1993  int scsiPrintMain(scsi_device * device, const scsi_pri
         if (! checkedSupportedLogPages)          if (! checkedSupportedLogPages)
             scsiGetSupportedLogPages(device);              scsiGetSupportedLogPages(device);
         if (gTempLPage) {          if (gTempLPage) {
             if (options.smart_check_status)  
                 pout("\n");  
             scsiPrintTemp(device);              scsiPrintTemp(device);
         }          }
         if (gStartStopLPage)          if (gStartStopLPage)
Line 1790  int scsiPrintMain(scsi_device * device, const scsi_pri Line 2055  int scsiPrintMain(scsi_device * device, const scsi_pri
         pout("Short Foreground Self Test Successful\n");          pout("Short Foreground Self Test Successful\n");
         any_output = true;          any_output = true;
     }      }
       // check if another test is running
       if (options.smart_short_selftest || options.smart_extend_selftest) {
         if (!scsiRequestSense(device, &sense_info) &&
               (sense_info.asc == 0x04 && sense_info.ascq == 0x09)) {
            if (!options.smart_selftest_force) {
              pout("Can't start self-test without aborting current test");
              if (sense_info.progress != -1) {
                pout(" (%d%% remaining)",
                     100 - sense_info.progress * 100 / 65535);
              }
              pout(",\nadd '-t force' option to override, or run 'smartctl -X' "
                   "to abort test.\n");
               return -1;
            }
            else
               scsiSmartSelfTestAbort(device);
          }
       }
     if (options.smart_short_selftest) {      if (options.smart_short_selftest) {
         if (scsiSmartShortSelfTest(device))          if (scsiSmartShortSelfTest(device))
             return returnval | FAILSMART;              return returnval | FAILSMART;
Line 1806  int scsiPrintMain(scsi_device * device, const scsi_pri Line 2089  int scsiPrintMain(scsi_device * device, const scsi_pri
             time_t t = time(NULL);              time_t t = time(NULL);
   
             t += durationSec;              t += durationSec;
            pout("Please wait %d minutes for test to complete.\n",             pout("Please wait %d minutes for test to complete.\n",
                  durationSec / 60);                   durationSec / 60);
             pout("Estimated completion time: %s\n", ctime(&t));              pout("Estimated completion time: %s\n", ctime(&t));
         }          }
        pout("Use smartctl -X to abort test\n");                pout("Use smartctl -X to abort test\n");
         any_output = true;          any_output = true;
     }      }
     if (options.smart_extend_cap_selftest) {      if (options.smart_extend_cap_selftest) {
Line 1823  int scsiPrintMain(scsi_device * device, const scsi_pri Line 2106  int scsiPrintMain(scsi_device * device, const scsi_pri
             return returnval | FAILSMART;              return returnval | FAILSMART;
         pout("Self Test returned without error\n");          pout("Self Test returned without error\n");
         any_output = true;          any_output = true;
    }               }
     if (options.sasphy) {      if (options.sasphy) {
         if (scsiPrintSasPhy(device, options.sasphy_reset))          if (scsiPrintSasPhy(device, options.sasphy_reset))
             return returnval | FAILSMART;              return returnval | FAILSMART;
         any_output = true;          any_output = true;
    }               }
   
     if (!any_output)      if (!any_output)
       pout("SCSI device successfully opened\n\n"        pout("SCSI device successfully opened\n\n"

Removed from v.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>