File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / atacmds.cpp
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:17:35 2013 UTC (10 years, 11 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v6_1p0, v6_1, HEAD
6.1

    1: /*
    2:  * atacmds.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) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
    8:  * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
    9:  * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
   10:  *
   11:  * This program is free software; you can redistribute it and/or modify
   12:  * it under the terms of the GNU General Public License as published by
   13:  * the Free Software Foundation; either version 2, or (at your option)
   14:  * any later version.
   15:  *
   16:  * You should have received a copy of the GNU General Public License
   17:  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
   18:  *
   19:  * This code was originally developed as a Senior Thesis by Michael Cornwell
   20:  * at the Concurrent Systems Laboratory (now part of the Storage Systems
   21:  * Research Center), Jack Baskin School of Engineering, University of
   22:  * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
   23:  * 
   24:  */
   25: 
   26: #include <stdio.h>
   27: #include <string.h>
   28: #include <errno.h>
   29: #include <stdlib.h>
   30: #include <ctype.h>
   31: 
   32: #include "config.h"
   33: #include "int64.h"
   34: #include "atacmds.h"
   35: #include "utility.h"
   36: #include "dev_ata_cmd_set.h" // for parsed_ata_device
   37: 
   38: const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp,v 1.1.1.3 2013/07/22 01:17:35 misho Exp $"
   39:                                  ATACMDS_H_CVSID;
   40: 
   41: // Print ATA debug messages?
   42: unsigned char ata_debugmode = 0;
   43: 
   44: // Suppress serial number?
   45: // (also used in scsiprint.cpp)
   46: bool dont_print_serial_number = false;
   47: 
   48: 
   49: #define SMART_CYL_LOW  0x4F
   50: #define SMART_CYL_HI   0xC2
   51: 
   52: // SMART RETURN STATUS yields SMART_CYL_HI,SMART_CYL_LOW to indicate drive
   53: // is healthy and SRET_STATUS_HI_EXCEEDED,SRET_STATUS_MID_EXCEEDED to
   54: // indicate that a threshhold exceeded condition has been detected.
   55: // Those values (byte pairs) are placed in ATA register "LBA 23:8".
   56: #define SRET_STATUS_HI_EXCEEDED 0x2C
   57: #define SRET_STATUS_MID_EXCEEDED 0xF4
   58: 
   59: 
   60: // Get ID and increase flag of current pending or offline
   61: // uncorrectable attribute.
   62: unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs,
   63:                               bool & increase)
   64: {
   65:   unsigned char id = (!offline ? 197 : 198);
   66:   const ata_vendor_attr_defs::entry & def = defs[id];
   67:   if (def.flags & ATTRFLAG_INCREASING)
   68:     increase = true; // '-v 19[78],increasing' option
   69:   else if (def.name.empty() || (id == 198 && def.name == "Offline_Scan_UNC_SectCt"))
   70:     increase = false; // no or '-v 198,offlinescanuncsectorct' option
   71:   else
   72:     id = 0; // other '-v 19[78],...' option
   73:   return id;
   74: }
   75: 
   76: #if 0 // TODO: never used
   77: // This are the meanings of the Self-test failure checkpoint byte.
   78: // This is in the self-test log at offset 4 bytes into the self-test
   79: // descriptor and in the SMART READ DATA structure at byte offset
   80: // 371. These codes are not well documented.  The meanings returned by
   81: // this routine are used (at least) by Maxtor and IBM. Returns NULL if
   82: // not recognized.  Currently the maximum length is 15 bytes.
   83: const char *SelfTestFailureCodeName(unsigned char which){
   84:   
   85:   switch (which) {
   86:   case 0:
   87:     return "Write_Test";
   88:   case 1:
   89:     return "Servo_Basic";
   90:   case 2:
   91:     return "Servo_Random";
   92:   case 3:
   93:     return "G-list_Scan";
   94:   case 4:
   95:     return "Handling_Damage";
   96:   case 5:
   97:     return "Read_Scan";
   98:   default:
   99:     return NULL;
  100:   }
  101: }
  102: #endif
  103: 
  104: 
  105: // Table of raw print format names
  106: struct format_name_entry
  107: {
  108:   const char * name;
  109:   ata_attr_raw_format format;
  110: };
  111: 
  112: const format_name_entry format_names[] = {
  113:   {"raw8"           , RAWFMT_RAW8},
  114:   {"raw16"          , RAWFMT_RAW16},
  115:   {"raw48"          , RAWFMT_RAW48},
  116:   {"hex48"          , RAWFMT_HEX48},
  117:   {"raw56"          , RAWFMT_RAW56},
  118:   {"hex56"          , RAWFMT_HEX56},
  119:   {"raw64"          , RAWFMT_RAW64},
  120:   {"hex64"          , RAWFMT_HEX64},
  121:   {"raw16(raw16)"   , RAWFMT_RAW16_OPT_RAW16},
  122:   {"raw16(avg16)"   , RAWFMT_RAW16_OPT_AVG16},
  123:   {"raw24(raw8)"    , RAWFMT_RAW24_OPT_RAW8},
  124:   {"raw24/raw24"    , RAWFMT_RAW24_DIV_RAW24},
  125:   {"raw24/raw32"    , RAWFMT_RAW24_DIV_RAW32},
  126:   {"sec2hour"       , RAWFMT_SEC2HOUR},
  127:   {"min2hour"       , RAWFMT_MIN2HOUR},
  128:   {"halfmin2hour"   , RAWFMT_HALFMIN2HOUR},
  129:   {"msec24hour32"   , RAWFMT_MSEC24_HOUR32},
  130:   {"tempminmax"     , RAWFMT_TEMPMINMAX},
  131:   {"temp10x"        , RAWFMT_TEMP10X},
  132: };
  133: 
  134: const unsigned num_format_names = sizeof(format_names)/sizeof(format_names[0]);
  135: 
  136: // Table to map old to new '-v' option arguments
  137: const char * map_old_vendor_opts[][2] = {
  138:   {  "9,halfminutes"              , "9,halfmin2hour,Power_On_Half_Minutes"},
  139:   {  "9,minutes"                  , "9,min2hour,Power_On_Minutes"},
  140:   {  "9,seconds"                  , "9,sec2hour,Power_On_Seconds"},
  141:   {  "9,temp"                     , "9,tempminmax,Temperature_Celsius"},
  142:   {"192,emergencyretractcyclect"  , "192,raw48,Emerg_Retract_Cycle_Ct"},
  143:   {"193,loadunload"               , "193,raw24/raw24"},
  144:   {"194,10xCelsius"               , "194,temp10x,Temperature_Celsius_x10"},
  145:   {"194,unknown"                  , "194,raw48,Unknown_Attribute"},
  146:   {"197,increasing"               , "197,raw48+,Total_Pending_Sectors"}, // '+' sets flag
  147:   {"198,offlinescanuncsectorct"   , "198,raw48,Offline_Scan_UNC_SectCt"}, // see also get_unc_attr_id() above
  148:   {"198,increasing"               , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag
  149:   {"200,writeerrorcount"          , "200,raw48,Write_Error_Count"},
  150:   {"201,detectedtacount"          , "201,raw48,Detected_TA_Count"},
  151:   {"220,temp"                     , "220,tempminmax,Temperature_Celsius"},
  152: };
  153: 
  154: const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]);
  155: 
  156: // Parse vendor attribute display def (-v option).
  157: // Return false on error.
  158: bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
  159:                          ata_vendor_def_prior priority)
  160: {
  161:   // Map old -> new options
  162:   unsigned i;
  163:   for (i = 0; i < num_old_vendor_opts; i++) {
  164:     if (!strcmp(opt, map_old_vendor_opts[i][0])) {
  165:       opt = map_old_vendor_opts[i][1];
  166:       break;
  167:     }
  168:   }
  169: 
  170:   // Parse option
  171:   int len = strlen(opt);
  172:   int id = 0, n1 = -1, n2 = -1;
  173:   char fmtname[32+1], attrname[32+1];
  174:   if (opt[0] == 'N') {
  175:     // "N,format"
  176:     if (!(   sscanf(opt, "N,%32[^,]%n,%32[^,]%n", fmtname, &n1, attrname, &n2) >= 1
  177:           && (n1 == len || n2 == len)))
  178:       return false;
  179:   }
  180:   else {
  181:     // "id,format[+][,name]"
  182:     if (!(   sscanf(opt, "%d,%32[^,]%n,%32[^,]%n", &id, fmtname, &n1, attrname, &n2) >= 2
  183:           && 1 <= id && id <= 255 && (n1 == len || n2 == len)))
  184:       return false;
  185:   }
  186:   if (n1 == len)
  187:     attrname[0] = 0;
  188: 
  189:   unsigned flags = 0;
  190:   // For "-v 19[78],increasing" above
  191:   if (fmtname[strlen(fmtname)-1] == '+') {
  192:     fmtname[strlen(fmtname)-1] = 0;
  193:     flags = ATTRFLAG_INCREASING;
  194:   }
  195: 
  196:   // Split "format[:byteorder]"
  197:   char byteorder[8+1] = "";
  198:   if (strchr(fmtname, ':')) {
  199:     if (!(   sscanf(fmtname, "%*[^:]%n:%8[012345rvwz]%n", &n1, byteorder, &n2) >= 1
  200:           && n2 == (int)strlen(fmtname)))
  201:       return false;
  202:     fmtname[n1] = 0;
  203:     if (strchr(byteorder, 'v'))
  204:       flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
  205:     if (strchr(byteorder, 'w'))
  206:       flags |= ATTRFLAG_NO_WORSTVAL;
  207:   }
  208: 
  209:   // Find format name
  210:   for (i = 0; ; i++) {
  211:     if (i >= num_format_names)
  212:       return false; // Not found
  213:     if (!strcmp(fmtname, format_names[i].name))
  214:       break;
  215:   }
  216:   ata_attr_raw_format format = format_names[i].format;
  217: 
  218:   // 64-bit formats use the normalized and worst value bytes.
  219:   if (!*byteorder && (format == RAWFMT_RAW64 || format == RAWFMT_HEX64))
  220:     flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
  221: 
  222:   if (!id) {
  223:     // "N,format" -> set format for all entries
  224:     for (i = 0; i < MAX_ATTRIBUTE_NUM; i++) {
  225:       if (defs[i].priority >= priority)
  226:         continue;
  227:       if (attrname[0])
  228:         defs[i].name = attrname;
  229:       defs[i].priority = priority;
  230:       defs[i].raw_format = format;
  231:       defs[i].flags = flags;
  232:       snprintf(defs[i].byteorder, sizeof(defs[i].byteorder), "%s", byteorder);
  233:     }
  234:   }
  235:   else if (defs[id].priority <= priority) {
  236:     // "id,format[,name]"
  237:     if (attrname[0])
  238:       defs[id].name = attrname;
  239:     defs[id].raw_format = format;
  240:     defs[id].priority = priority;
  241:     defs[id].flags = flags;
  242:     snprintf(defs[id].byteorder, sizeof(defs[id].byteorder), "%s", byteorder);
  243:   }
  244: 
  245:   return true;
  246: }
  247: 
  248: 
  249: // Return a multiline string containing a list of valid arguments for
  250: // parse_attribute_def().  The strings are preceeded by tabs and followed
  251: // (except for the last) by newlines.
  252: std::string create_vendor_attribute_arg_list()
  253: {
  254:   std::string s;
  255:   unsigned i;
  256:   for (i = 0; i < num_format_names; i++)
  257:     s += strprintf("%s\tN,%s[:012345rvwz][,ATTR_NAME]",
  258:       (i>0 ? "\n" : ""), format_names[i].name);
  259:   for (i = 0; i < num_old_vendor_opts; i++)
  260:     s += strprintf("\n\t%s", map_old_vendor_opts[i][0]);
  261:   return s;
  262: }
  263: 
  264: 
  265: // Parse firmwarebug def (-F option).
  266: // Return false on error.
  267: bool parse_firmwarebug_def(const char * opt, firmwarebug_defs & firmwarebugs)
  268: {
  269:     if (!strcmp(opt, "none"))
  270:       firmwarebugs.set(BUG_NONE);
  271:     else if (!strcmp(opt, "nologdir"))
  272:       firmwarebugs.set(BUG_NOLOGDIR);
  273:     else if (!strcmp(opt, "samsung"))
  274:       firmwarebugs.set(BUG_SAMSUNG);
  275:     else if (!strcmp(opt, "samsung2"))
  276:       firmwarebugs.set(BUG_SAMSUNG2);
  277:     else if (!strcmp(opt, "samsung3"))
  278:       firmwarebugs.set(BUG_SAMSUNG3);
  279:     else if (!strcmp(opt, "xerrorlba"))
  280:       firmwarebugs.set(BUG_XERRORLBA);
  281:     else
  282:       return false;
  283:     return true;
  284: }
  285: 
  286: // Return a string of valid argument words for parse_firmwarebug_def()
  287: const char * get_valid_firmwarebug_args()
  288: {
  289:   return "none, nologdir, samsung, samsung2, samsung3, xerrorlba";
  290: }
  291: 
  292: 
  293: // swap two bytes.  Point to low address
  294: void swap2(char *location){
  295:   char tmp=*location;
  296:   *location=*(location+1);
  297:   *(location+1)=tmp;
  298:   return;
  299: }
  300: 
  301: // swap four bytes.  Point to low address
  302: void swap4(char *location){
  303:   char tmp=*location;
  304:   *location=*(location+3);
  305:   *(location+3)=tmp;
  306:   swap2(location+1);
  307:   return;
  308: }
  309: 
  310: // swap eight bytes.  Points to low address
  311: void swap8(char *location){
  312:   char tmp=*location;
  313:   *location=*(location+7);
  314:   *(location+7)=tmp;
  315:   tmp=*(location+1);
  316:   *(location+1)=*(location+6);
  317:   *(location+6)=tmp;
  318:   swap4(location+2);
  319:   return;
  320: }
  321: 
  322: // Invalidate serial number and WWN and adjust checksum in IDENTIFY data
  323: static void invalidate_serno(ata_identify_device * id)
  324: {
  325:   unsigned char sum = 0;
  326:   unsigned i;
  327:   for (i = 0; i < sizeof(id->serial_no); i++) {
  328:     sum += id->serial_no[i]; sum -= id->serial_no[i] = 'X';
  329:   }
  330:   unsigned char * b = (unsigned char *)id;
  331:   for (i = 2*108; i < 2*112; i++) { // words108-111: WWN
  332:     sum += b[i]; sum -= b[i] = 0x00;
  333:   }
  334: 
  335: #ifndef __NetBSD__
  336:   bool must_swap = !!isbigendian();
  337:   if (must_swap)
  338:     swapx(id->words088_255+255-88);
  339: #endif
  340:   if ((id->words088_255[255-88] & 0x00ff) == 0x00a5)
  341:     id->words088_255[255-88] += sum << 8;
  342: #ifndef __NetBSD__
  343:   if (must_swap)
  344:     swapx(id->words088_255+255-88);
  345: #endif
  346: }
  347: 
  348: static const char * const commandstrings[]={
  349:   "SMART ENABLE",
  350:   "SMART DISABLE",
  351:   "SMART AUTOMATIC ATTRIBUTE SAVE",
  352:   "SMART IMMEDIATE OFFLINE",
  353:   "SMART AUTO OFFLINE",
  354:   "SMART STATUS",
  355:   "SMART STATUS CHECK",
  356:   "SMART READ ATTRIBUTE VALUES",
  357:   "SMART READ ATTRIBUTE THRESHOLDS",
  358:   "SMART READ LOG",
  359:   "IDENTIFY DEVICE",
  360:   "IDENTIFY PACKET DEVICE",
  361:   "CHECK POWER MODE",
  362:   "SMART WRITE LOG",
  363:   "WARNING (UNDEFINED COMMAND -- CONTACT DEVELOPERS AT " PACKAGE_BUGREPORT ")\n"
  364: };
  365: 
  366: 
  367: static const char * preg(const ata_register & r, char (& buf)[8])
  368: {
  369:   if (!r.is_set())
  370:     //return "n/a ";
  371:     return "....";
  372:   snprintf(buf, sizeof(buf), "0x%02x", r.val());
  373:   return buf;
  374: }
  375: 
  376: static void print_regs(const char * prefix, const ata_in_regs & r, const char * suffix = "\n")
  377: {
  378:   char bufs[7][8];
  379:   pout("%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix,
  380:     preg(r.features, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
  381:     preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
  382:     preg(r.command, bufs[6]), suffix);
  383: }
  384: 
  385: static void print_regs(const char * prefix, const ata_out_regs & r, const char * suffix = "\n")
  386: {
  387:   char bufs[7][8];
  388:   pout("%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix,
  389:     preg(r.error, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
  390:     preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
  391:     preg(r.status, bufs[6]), suffix);
  392: }
  393: 
  394: static void prettyprint(const unsigned char *p, const char *name){
  395:   pout("\n===== [%s] DATA START (BASE-16) =====\n", name);
  396:   for (int i=0; i<512; i+=16, p+=16)
  397: #define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.')
  398:     // print complete line to avoid slow tty output and extra lines in syslog.
  399:     pout("%03d-%03d: %02x %02x %02x %02x %02x %02x %02x %02x "
  400:                     "%02x %02x %02x %02x %02x %02x %02x %02x"
  401:                     " |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c|"
  402:          "%c",
  403:          i, i+16-1,
  404:          p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
  405:          p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15], 
  406:          P( 0), P( 1), P( 2), P( 3), P( 4), P( 5), P( 6), P( 7),
  407:          P( 8), P( 9), P(10), P(11), P(12), P(13), P(14), P(15),
  408:          '\n');
  409: #undef P
  410:   pout("===== [%s] DATA END (512 Bytes) =====\n\n", name);
  411: }
  412: 
  413: // This function provides the pretty-print reporting for SMART
  414: // commands: it implements the various -r "reporting" options for ATA
  415: // ioctls.
  416: int smartcommandhandler(ata_device * device, smart_command_set command, int select, char *data){
  417:   // TODO: Rework old stuff below
  418:   // This conditional is true for commands that return data
  419:   int getsdata=(command==PIDENTIFY || 
  420:                 command==IDENTIFY || 
  421:                 command==READ_LOG || 
  422:                 command==READ_THRESHOLDS || 
  423:                 command==READ_VALUES ||
  424:                 command==CHECK_POWER_MODE);
  425: 
  426:   int sendsdata=(command==WRITE_LOG);
  427:   
  428:   // If reporting is enabled, say what the command will be before it's executed
  429:   if (ata_debugmode) {
  430:           // conditional is true for commands that use parameters
  431:           int usesparam=(command==READ_LOG || 
  432:                          command==AUTO_OFFLINE || 
  433:                          command==AUTOSAVE || 
  434:                          command==IMMEDIATE_OFFLINE ||
  435:                          command==WRITE_LOG);
  436:                   
  437:     pout("\nREPORT-IOCTL: Device=%s Command=%s", device->get_dev_name(), commandstrings[command]);
  438:     if (usesparam)
  439:       pout(" InputParameter=%d\n", select);
  440:     else
  441:       pout("\n");
  442:   }
  443:   
  444:   if ((getsdata || sendsdata) && !data){
  445:     pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]);
  446:     return -1;
  447:   }
  448:   
  449:   // The reporting is cleaner, and we will find coding bugs faster, if
  450:   // the commands that failed clearly return empty (zeroed) data
  451:   // structures
  452:   if (getsdata) {
  453:     if (command==CHECK_POWER_MODE)
  454:       data[0]=0;
  455:     else
  456:       memset(data, '\0', 512);
  457:   }
  458: 
  459: 
  460:   // if requested, pretty-print the input data structure
  461:   if (ata_debugmode > 1 && sendsdata)
  462:     //pout("REPORT-IOCTL: Device=%s Command=%s\n", device->get_dev_name(), commandstrings[command]);
  463:     prettyprint((unsigned char *)data, commandstrings[command]);
  464: 
  465:   // now execute the command
  466:   int retval = -1;
  467:   {
  468:     ata_cmd_in in;
  469:     // Set common register values
  470:     switch (command) {
  471:       default: // SMART commands
  472:         in.in_regs.command = ATA_SMART_CMD;
  473:         in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
  474:         break;
  475:       case IDENTIFY: case PIDENTIFY: case CHECK_POWER_MODE: // Non SMART commands
  476:         break;
  477:     }
  478:     // Set specific values
  479:     switch (command) {
  480:       case IDENTIFY:
  481:         in.in_regs.command = ATA_IDENTIFY_DEVICE;
  482:         in.set_data_in(data, 1);
  483:         break;
  484:       case PIDENTIFY:
  485:         in.in_regs.command = ATA_IDENTIFY_PACKET_DEVICE;
  486:         in.set_data_in(data, 1);
  487:         break;
  488:       case CHECK_POWER_MODE:
  489:         in.in_regs.command = ATA_CHECK_POWER_MODE;
  490:         in.out_needed.sector_count = true; // Powermode returned here
  491:         break;
  492:       case READ_VALUES:
  493:         in.in_regs.features = ATA_SMART_READ_VALUES;
  494:         in.set_data_in(data, 1);
  495:         break;
  496:       case READ_THRESHOLDS:
  497:         in.in_regs.features = ATA_SMART_READ_THRESHOLDS;
  498:         in.in_regs.lba_low = 1; // TODO: CORRECT ???
  499:         in.set_data_in(data, 1);
  500:         break;
  501:       case READ_LOG:
  502:         in.in_regs.features = ATA_SMART_READ_LOG_SECTOR;
  503:         in.in_regs.lba_low = select;
  504:         in.set_data_in(data, 1);
  505:         break;
  506:       case WRITE_LOG:
  507:         in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
  508:         in.in_regs.lba_low = select;
  509:         in.set_data_out(data, 1);
  510:         break;
  511:       case ENABLE:
  512:         in.in_regs.features = ATA_SMART_ENABLE;
  513:         in.in_regs.lba_low = 1; // TODO: CORRECT ???
  514:         break;
  515:       case DISABLE:
  516:         in.in_regs.features = ATA_SMART_DISABLE;
  517:         in.in_regs.lba_low = 1;  // TODO: CORRECT ???
  518:         break;
  519:       case STATUS_CHECK:
  520:         in.out_needed.lba_high = in.out_needed.lba_mid = true; // Status returned here
  521:       case STATUS:
  522:         in.in_regs.features = ATA_SMART_STATUS;
  523:         break;
  524:       case AUTO_OFFLINE:
  525:         in.in_regs.features = ATA_SMART_AUTO_OFFLINE;
  526:         in.in_regs.sector_count = select;  // Caution: Non-DATA command!
  527:         break;
  528:       case AUTOSAVE:
  529:         in.in_regs.features = ATA_SMART_AUTOSAVE;
  530:         in.in_regs.sector_count = select;  // Caution: Non-DATA command!
  531:         break;
  532:       case IMMEDIATE_OFFLINE:
  533:         in.in_regs.features = ATA_SMART_IMMEDIATE_OFFLINE;
  534:         in.in_regs.lba_low = select;
  535:         break;
  536:       default:
  537:         pout("Unrecognized command %d in smartcommandhandler()\n"
  538:              "Please contact " PACKAGE_BUGREPORT "\n", command);
  539:         device->set_err(ENOSYS);
  540:         return -1;
  541:     }
  542: 
  543:     if (ata_debugmode)
  544:       print_regs(" Input:  ", in.in_regs,
  545:         (in.direction==ata_cmd_in::data_in ? " IN\n":
  546:          in.direction==ata_cmd_in::data_out ? " OUT\n":"\n"));
  547: 
  548:     ata_cmd_out out;
  549: 
  550:     int64_t start_usec = -1;
  551:     if (ata_debugmode)
  552:       start_usec = smi()->get_timer_usec();
  553: 
  554:     bool ok = device->ata_pass_through(in, out);
  555: 
  556:     if (start_usec >= 0) {
  557:       int64_t duration_usec = smi()->get_timer_usec() - start_usec;
  558:       if (duration_usec >= 500)
  559:         pout(" [Duration: %.3fs]\n", duration_usec / 1000000.0);
  560:     }
  561: 
  562:     if (ata_debugmode && out.out_regs.is_set())
  563:       print_regs(" Output: ", out.out_regs);
  564: 
  565:     if (ok) switch (command) {
  566:       default:
  567:         retval = 0;
  568:         break;
  569:       case CHECK_POWER_MODE:
  570:         if (out.out_regs.sector_count.is_set()) {
  571:           data[0] = out.out_regs.sector_count;
  572:           retval = 0;
  573:         }
  574:         else {
  575:           pout("CHECK POWER MODE: incomplete response, ATA output registers missing\n");
  576:           device->set_err(ENOSYS);
  577:           retval = -1;
  578:         }
  579:         break;
  580:       case STATUS_CHECK:
  581:         // Cyl low and Cyl high unchanged means "Good SMART status"
  582:         if ((out.out_regs.lba_high == SMART_CYL_HI) &&
  583:             (out.out_regs.lba_mid == SMART_CYL_LOW))
  584:           retval = 0;
  585:         // These values mean "Bad SMART status"
  586:         else if ((out.out_regs.lba_high == SRET_STATUS_HI_EXCEEDED) &&
  587:                  (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED))
  588:           retval = 1;
  589:         else if (out.out_regs.lba_mid == SMART_CYL_LOW) {
  590:           retval = 0;
  591:           if (ata_debugmode)
  592:             pout("SMART STATUS RETURN: half healthy response sequence, "
  593:                  "probable SAT/USB truncation\n");
  594:           } else if (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED) {
  595:           retval = 1;
  596:           if (ata_debugmode)
  597:             pout("SMART STATUS RETURN: half unhealthy response sequence, "
  598:                  "probable SAT/USB truncation\n");
  599:         }
  600:         else if (!out.out_regs.is_set()) {
  601:           pout("SMART STATUS RETURN: incomplete response, ATA output registers missing\n");
  602:           device->set_err(ENOSYS);
  603:           retval = -1;
  604:         }
  605:         else {
  606:           // We haven't gotten output that makes sense; print out some debugging info
  607:           pout("SMART Status command failed\n");
  608:           pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE);
  609:           pout("Register values returned from SMART Status command are:\n");
  610:           print_regs(" ", out.out_regs);
  611:           device->set_err(EIO);
  612:           retval = -1;
  613:         }
  614:         break;
  615:     }
  616:   }
  617: 
  618:   // If requested, invalidate serial number before any printing is done
  619:   if ((command == IDENTIFY || command == PIDENTIFY) && !retval && dont_print_serial_number)
  620:     invalidate_serno((ata_identify_device *)data);
  621: 
  622:   // If reporting is enabled, say what output was produced by the command
  623:   if (ata_debugmode) {
  624:     if (device->get_errno())
  625:       pout("REPORT-IOCTL: Device=%s Command=%s returned %d errno=%d [%s]\n",
  626:            device->get_dev_name(), commandstrings[command], retval,
  627:            device->get_errno(), device->get_errmsg());
  628:     else
  629:       pout("REPORT-IOCTL: Device=%s Command=%s returned %d\n",
  630:            device->get_dev_name(), commandstrings[command], retval);
  631:     
  632:     // if requested, pretty-print the output data structure
  633:     if (ata_debugmode > 1 && getsdata) {
  634:       if (command==CHECK_POWER_MODE)
  635: 	pout("Sector Count Register (BASE-16): %02x\n", (unsigned char)(*data));
  636:       else
  637: 	prettyprint((unsigned char *)data, commandstrings[command]);
  638:     }
  639:   }
  640: 
  641:   return retval;
  642: }
  643: 
  644: // Get capacity and sector sizes from IDENTIFY data
  645: void ata_get_size_info(const ata_identify_device * id, ata_size_info & sizes)
  646: {
  647:   sizes.sectors = sizes.capacity = 0;
  648:   sizes.log_sector_size = sizes.phy_sector_size = 0;
  649:   sizes.log_sector_offset = 0;
  650: 
  651:   // Return if no LBA support
  652:   if (!(id->words047_079[49-47] & 0x0200))
  653:     return;
  654: 
  655:   // Determine 28-bit LBA capacity
  656:   unsigned lba28 = (unsigned)id->words047_079[61-47] << 16
  657:                  | (unsigned)id->words047_079[60-47]      ;
  658: 
  659:   // Determine 48-bit LBA capacity if supported
  660:   uint64_t lba48 = 0;
  661:   if ((id->command_set_2 & 0xc400) == 0x4400)
  662:     lba48 = (uint64_t)id->words088_255[103-88] << 48
  663:           | (uint64_t)id->words088_255[102-88] << 32
  664:           | (uint64_t)id->words088_255[101-88] << 16
  665:           | (uint64_t)id->words088_255[100-88]      ;
  666: 
  667:   // Return if capacity unknown (ATAPI CD/DVD)
  668:   if (!(lba28 || lba48))
  669:     return;
  670: 
  671:   // Determine sector sizes
  672:   sizes.log_sector_size = sizes.phy_sector_size = 512;
  673: 
  674:   unsigned short word106 = id->words088_255[106-88];
  675:   if ((word106 & 0xc000) == 0x4000) {
  676:     // Long Logical/Physical Sectors (LLS/LPS) ?
  677:     if (word106 & 0x1000)
  678:       // Logical sector size is specified in 16-bit words
  679:       sizes.log_sector_size = sizes.phy_sector_size =
  680:         ((id->words088_255[118-88] << 16) | id->words088_255[117-88]) << 1;
  681: 
  682:     if (word106 & 0x2000)
  683:       // Physical sector size is multiple of logical sector size
  684:       sizes.phy_sector_size <<= (word106 & 0x0f);
  685: 
  686:     unsigned short word209 = id->words088_255[209-88];
  687:     if ((word209 & 0xc000) == 0x4000)
  688:       sizes.log_sector_offset = (word209 & 0x3fff) * sizes.log_sector_size;
  689:   }
  690: 
  691:   // Some early 4KiB LLS disks (Samsung N3U-3) return bogus lba28 value
  692:   if (lba48 >= lba28 || (lba48 && sizes.log_sector_size > 512))
  693:     sizes.sectors = lba48;
  694:   else
  695:     sizes.sectors = lba28;
  696: 
  697:   sizes.capacity = sizes.sectors * sizes.log_sector_size;
  698: }
  699: 
  700: // This function computes the checksum of a single disk sector (512
  701: // bytes).  Returns zero if checksum is OK, nonzero if the checksum is
  702: // incorrect.  The size (512) is correct for all SMART structures.
  703: unsigned char checksum(const void * data)
  704: {
  705:   unsigned char sum = 0;
  706:   for (int i = 0; i < 512; i++)
  707:     sum += ((const unsigned char *)data)[i];
  708:   return sum;
  709: }
  710: 
  711: // Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents
  712: // bytes.
  713: static void swapbytes(char * out, const char * in, size_t n)
  714: {
  715:   for (size_t i = 0; i < n; i += 2) {
  716:     out[i]   = in[i+1];
  717:     out[i+1] = in[i];
  718:   }
  719: }
  720: 
  721: // Copies in to out, but removes leading and trailing whitespace.
  722: static void trim(char * out, const char * in)
  723: {
  724:   // Find the first non-space character (maybe none).
  725:   int first = -1;
  726:   int i;
  727:   for (i = 0; in[i]; i++)
  728:     if (!isspace((int)in[i])) {
  729:       first = i;
  730:       break;
  731:     }
  732: 
  733:   if (first == -1) {
  734:     // There are no non-space characters.
  735:     out[0] = '\0';
  736:     return;
  737:   }
  738: 
  739:   // Find the last non-space character.
  740:   for (i = strlen(in)-1; i >= first && isspace((int)in[i]); i--)
  741:     ;
  742:   int last = i;
  743: 
  744:   strncpy(out, in+first, last-first+1);
  745:   out[last-first+1] = '\0';
  746: }
  747: 
  748: // Convenience function for formatting strings from ata_identify_device
  749: void ata_format_id_string(char * out, const unsigned char * in, int n)
  750: {
  751:   bool must_swap = true;
  752: #ifdef __NetBSD__
  753:   /* NetBSD kernel delivers IDENTIFY data in host byte order (but all else is LE) */
  754:   // TODO: Handle NetBSD case in os_netbsd.cpp
  755:   if (isbigendian())
  756:     must_swap = !must_swap;
  757: #endif
  758: 
  759:   char tmp[65];
  760:   n = n > 64 ? 64 : n;
  761:   if (!must_swap)
  762:     strncpy(tmp, (const char *)in, n);
  763:   else
  764:     swapbytes(tmp, (const char *)in, n);
  765:   tmp[n] = '\0';
  766:   trim(out, tmp);
  767: }
  768: 
  769: // returns -1 if command fails or the device is in Sleep mode, else
  770: // value of Sector Count register.  Sector Count result values:
  771: //   00h device is in Standby mode. 
  772: //   80h device is in Idle mode.
  773: //   FFh device is in Active mode or Idle mode.
  774: 
  775: int ataCheckPowerMode(ata_device * device) {
  776:   unsigned char result;
  777: 
  778:   if ((smartcommandhandler(device, CHECK_POWER_MODE, 0, (char *)&result)))
  779:     return -1;
  780: 
  781:   if (result!=0 && result!=0x80 && result!=0xff)
  782:     pout("ataCheckPowerMode(): ATA CHECK POWER MODE returned unknown Sector Count Register value %02x\n", result);
  783: 
  784:   return (int)result;
  785: }
  786: 
  787: // Issue a no-data ATA command with optional sector count register value
  788: bool ata_nodata_command(ata_device * device, unsigned char command,
  789:                         int sector_count /* = -1 */)
  790: {
  791:   ata_cmd_in in;
  792:   in.in_regs.command = command;
  793:   if (sector_count >= 0)
  794:     in.in_regs.sector_count = sector_count;
  795: 
  796:   return device->ata_pass_through(in);
  797: }
  798: 
  799: // Issue SET FEATURES command with optional sector count register value
  800: bool ata_set_features(ata_device * device, unsigned char features,
  801:                       int sector_count /* = -1 */)
  802: {
  803:   ata_cmd_in in;
  804:   in.in_regs.command = ATA_SET_FEATURES;
  805:   in.in_regs.features = features;
  806:   if (sector_count >= 0)
  807:     in.in_regs.sector_count = sector_count;
  808: 
  809:   return device->ata_pass_through(in);
  810: }
  811: 
  812: // Reads current Device Identity info (512 bytes) into buf.  Returns 0
  813: // if all OK.  Returns -1 if no ATA Device identity can be
  814: // established.  Returns >0 if Device is ATA Packet Device (not SMART
  815: // capable).  The value of the integer helps identify the type of
  816: // Packet device, which is useful so that the user can connect the
  817: // formal device number with whatever object is inside their computer.
  818: int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id,
  819:                       unsigned char * raw_buf /* = 0 */)
  820: {
  821:   unsigned short *rawshort=(unsigned short *)buf;
  822:   unsigned char  *rawbyte =(unsigned char  *)buf;
  823: 
  824:   // See if device responds either to IDENTIFY DEVICE or IDENTIFY
  825:   // PACKET DEVICE
  826:   bool packet = false;
  827:   if ((smartcommandhandler(device, IDENTIFY, 0, (char *)buf))){
  828:     if (smartcommandhandler(device, PIDENTIFY, 0, (char *)buf)){
  829:       return -1; 
  830:     }
  831:     packet = true;
  832:   }
  833: 
  834:   unsigned i;
  835:   if (fix_swapped_id) {
  836:     // Swap ID strings
  837:     for (i = 0; i < sizeof(buf->serial_no)-1; i += 2)
  838:       swap2((char *)(buf->serial_no+i));
  839:     for (i = 0; i < sizeof(buf->fw_rev)-1; i += 2)
  840:       swap2((char *)(buf->fw_rev+i));
  841:     for (i = 0; i < sizeof(buf->model)-1; i += 2)
  842:       swap2((char *)(buf->model+i));
  843:   }
  844: 
  845:   // If requested, save raw data before endianness adjustments
  846:   if (raw_buf)
  847:     memcpy(raw_buf, buf, sizeof(*buf));
  848: 
  849: #ifndef __NetBSD__
  850:   // if machine is big-endian, swap byte order as needed
  851:   // NetBSD kernel delivers IDENTIFY data in host byte order
  852:   // TODO: Handle NetBSD case in os_netbsd.cpp
  853:   if (isbigendian()){
  854:     
  855:     // swap various capability words that are needed
  856:     for (i=0; i<33; i++)
  857:       swap2((char *)(buf->words047_079+i));
  858:     
  859:     for (i=80; i<=87; i++)
  860:       swap2((char *)(rawshort+i));
  861:     
  862:     for (i=0; i<168; i++)
  863:       swap2((char *)(buf->words088_255+i));
  864:   }
  865: #endif
  866:   
  867:   // If there is a checksum there, validate it
  868:   if ((rawshort[255] & 0x00ff) == 0x00a5 && checksum(rawbyte))
  869:     checksumwarning("Drive Identity Structure");
  870: 
  871:   // AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
  872:   // T13/1699-D Revision 6a (Final Draft), September 6, 2008.
  873:   // Sections 7.16.7 and 7.17.6:
  874:   //
  875:   // Word 0 of IDENTIFY DEVICE data:
  876:   // Bit 15 = 0 : ATA device
  877:   //
  878:   // Word 0 of IDENTIFY PACKET DEVICE data:
  879:   // Bits 15:14 = 10b : ATAPI device
  880:   // Bits 15:14 = 11b : Reserved
  881:   // Bits 12:8        : Device type (SPC-4, e.g 0x05 = CD/DVD)
  882: 
  883:   // CF+ and CompactFlash Specification Revision 4.0, May 24, 2006.
  884:   // Section 6.2.1.6:
  885:   //
  886:   // Word 0 of IDENTIFY DEVICE data:
  887:   // 848Ah = Signature for CompactFlash Storage Card
  888:   // 044Ah = Alternate value turns on ATA device while preserving all retired bits
  889:   // 0040h = Alternate value turns on ATA device while zeroing all retired bits
  890: 
  891:   // Assume ATA if IDENTIFY DEVICE returns CompactFlash Signature
  892:   if (!packet && rawbyte[1] == 0x84 && rawbyte[0] == 0x8a)
  893:     return 0;
  894: 
  895:   // If this is a PACKET DEVICE, return device type
  896:   if (rawbyte[1] & 0x80)
  897:     return 1+(rawbyte[1] & 0x1f);
  898:   
  899:   // Not a PACKET DEVICE
  900:   return 0;
  901: }
  902: 
  903: // Get World Wide Name (WWN) fields.
  904: // Return NAA field or -1 if WWN is unsupported.
  905: // Table 34 of T13/1699-D Revision 6a (ATA8-ACS), September 6, 2008.
  906: // (WWN was introduced in ATA/ATAPI-7 and is mandatory since ATA8-ACS Revision 3b)
  907: int ata_get_wwn(const ata_identify_device * id, unsigned & oui, uint64_t & unique_id)
  908: {
  909:   // Don't use word 84 to be compatible with some older ATA-7 disks
  910:   unsigned short word087 = id->csf_default;
  911:   if ((word087 & 0xc100) != 0x4100)
  912:     return -1; // word not valid or WWN support bit 8 not set
  913: 
  914:   unsigned short word108 = id->words088_255[108-88];
  915:   unsigned short word109 = id->words088_255[109-88];
  916:   unsigned short word110 = id->words088_255[110-88];
  917:   unsigned short word111 = id->words088_255[111-88];
  918: 
  919:   oui = ((word108 & 0x0fff) << 12) | (word109 >> 4);
  920:   unique_id = ((uint64_t)(word109 & 0xf) << 32)
  921:             | (unsigned)((word110 << 16) | word111);
  922:   return (word108 >> 12);
  923: }
  924: 
  925: // Get nominal media rotation rate.
  926: // Returns: 0 = not reported, 1 = SSD, >1 = HDD rpm, < 0 = -(Unknown value)
  927: int ata_get_rotation_rate(const ata_identify_device * id)
  928: {
  929:   // Table 37 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
  930:   // Table A.31 of T13/2161-D (ACS-3) Revision 3b, August 25, 2012
  931:   unsigned short word217 = id->words088_255[217-88];
  932:   if (word217 == 0x0000 || word217 == 0xffff)
  933:     return 0;
  934:   else if (word217 == 0x0001)
  935:     return 1;
  936:   else if (word217 > 0x0400)
  937:     return word217;
  938:   else
  939:     return -(int)word217;
  940: }
  941: 
  942: // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
  943: int ataSmartSupport(const ata_identify_device * drive)
  944: {
  945:   unsigned short word82=drive->command_set_1;
  946:   unsigned short word83=drive->command_set_2;
  947:   
  948:   // check if words 82/83 contain valid info
  949:   if ((word83>>14) == 0x01)
  950:     // return value of SMART support bit 
  951:     return word82 & 0x0001;
  952:   
  953:   // since we can're rely on word 82, we don't know if SMART supported
  954:   return -1;
  955: }
  956: 
  957: // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
  958: int ataIsSmartEnabled(const ata_identify_device * drive)
  959: {
  960:   unsigned short word85=drive->cfs_enable_1;
  961:   unsigned short word87=drive->csf_default;
  962:   
  963:   // check if words 85/86/87 contain valid info
  964:   if ((word87>>14) == 0x01)
  965:     // return value of SMART enabled bit
  966:     return word85 & 0x0001;
  967:   
  968:   // Since we can't rely word85, we don't know if SMART is enabled.
  969:   return -1;
  970: }
  971: 
  972: 
  973: // Reads SMART attributes into *data
  974: int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){
  975:   
  976:   if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){
  977:     return -1;
  978:   }
  979: 
  980:   // compute checksum
  981:   if (checksum(data))
  982:     checksumwarning("SMART Attribute Data Structure");
  983:   
  984:   // swap endian order if needed
  985:   if (isbigendian()){
  986:     int i;
  987:     swap2((char *)&(data->revnumber));
  988:     swap2((char *)&(data->total_time_to_complete_off_line));
  989:     swap2((char *)&(data->smart_capability));
  990:     swapx(&data->extend_test_completion_time_w);
  991:     for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
  992:       struct ata_smart_attribute *x=data->vendor_attributes+i;
  993:       swap2((char *)&(x->flags));
  994:     }
  995:   }
  996: 
  997:   return 0;
  998: }
  999: 
 1000: 
 1001: // This corrects some quantities that are byte reversed in the SMART
 1002: // SELF TEST LOG
 1003: static void fixsamsungselftestlog(ata_smart_selftestlog * data)
 1004: {
 1005:   // bytes 508/509 (numbered from 0) swapped (swap of self-test index
 1006:   // with one byte of reserved.
 1007:   swap2((char *)&(data->mostrecenttest));
 1008: 
 1009:   // LBA low register (here called 'selftestnumber", containing
 1010:   // information about the TYPE of the self-test) is byte swapped with
 1011:   // Self-test execution status byte.  These are bytes N, N+1 in the
 1012:   // entries.
 1013:   for (int i = 0; i < 21; i++)
 1014:     swap2((char *)&(data->selftest_struct[i].selftestnumber));
 1015: 
 1016:   return;
 1017: }
 1018: 
 1019: // Reads the Self Test Log (log #6)
 1020: int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data,
 1021:                         firmwarebug_defs firmwarebugs)
 1022: {
 1023: 
 1024:   // get data from device
 1025:   if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){
 1026:     return -1;
 1027:   }
 1028: 
 1029:   // compute its checksum, and issue a warning if needed
 1030:   if (checksum(data))
 1031:     checksumwarning("SMART Self-Test Log Structure");
 1032:   
 1033:   // fix firmware bugs in self-test log
 1034:   if (firmwarebugs.is_set(BUG_SAMSUNG))
 1035:     fixsamsungselftestlog(data);
 1036: 
 1037:   // swap endian order if needed
 1038:   if (isbigendian()){
 1039:     int i;
 1040:     swap2((char*)&(data->revnumber));
 1041:     for (i=0; i<21; i++){
 1042:       struct ata_smart_selftestlog_struct *x=data->selftest_struct+i;
 1043:       swap2((char *)&(x->timestamp));
 1044:       swap4((char *)&(x->lbafirstfailure));
 1045:     }
 1046:   }
 1047: 
 1048:   return 0;
 1049: }
 1050: 
 1051: // Print checksum warning for multi sector log
 1052: static void check_multi_sector_sum(const void * data, unsigned nsectors, const char * msg)
 1053: {
 1054:   unsigned errs = 0;
 1055:   for (unsigned i = 0; i < nsectors; i++) {
 1056:     if (checksum((const unsigned char *)data + i*512))
 1057:       errs++;
 1058:   }
 1059:   if (errs > 0) {
 1060:     if (nsectors == 1)
 1061:       checksumwarning(msg);
 1062:     else
 1063:       checksumwarning(strprintf("%s (%u/%u)", msg, errs, nsectors).c_str());
 1064:   }
 1065: }
 1066: 
 1067: // Read SMART Extended Self-test Log
 1068: bool ataReadExtSelfTestLog(ata_device * device, ata_smart_extselftestlog * log,
 1069:                            unsigned nsectors)
 1070: {
 1071:   if (!ataReadLogExt(device, 0x07, 0x00, 0, log, nsectors))
 1072:     return false;
 1073: 
 1074:   check_multi_sector_sum(log, nsectors, "SMART Extended Self-test Log Structure");
 1075: 
 1076:   if (isbigendian()) {
 1077:     swapx(&log->log_desc_index);
 1078:     for (unsigned i = 0; i < nsectors; i++) {
 1079:       for (unsigned j = 0; j < 19; j++)
 1080:         swapx(&log->log_descs[i].timestamp);
 1081:     }
 1082:   }
 1083:   return true;
 1084: }
 1085: 
 1086: 
 1087: // Read GP Log page(s)
 1088: bool ataReadLogExt(ata_device * device, unsigned char logaddr,
 1089:                    unsigned char features, unsigned page,
 1090:                    void * data, unsigned nsectors)
 1091: {
 1092:   ata_cmd_in in;
 1093:   in.in_regs.command      = ATA_READ_LOG_EXT;
 1094:   in.in_regs.features     = features; // log specific
 1095:   in.set_data_in_48bit(data, nsectors);
 1096:   in.in_regs.lba_low      = logaddr;
 1097:   in.in_regs.lba_mid_16   = page;
 1098: 
 1099:   if (!device->ata_pass_through(in)) { // TODO: Debug output
 1100:     if (nsectors <= 1) {
 1101:       pout("ATA_READ_LOG_EXT (addr=0x%02x:0x%02x, page=%u, n=%u) failed: %s\n",
 1102:            logaddr, features, page, nsectors, device->get_errmsg());
 1103:       return false;
 1104:     }
 1105: 
 1106:     // Recurse to retry with single sectors,
 1107:     // multi-sector reads may not be supported by ioctl.
 1108:     for (unsigned i = 0; i < nsectors; i++) {
 1109:       if (!ataReadLogExt(device, logaddr,
 1110:                          features, page + i,
 1111:                          (char *)data + 512*i, 1))
 1112:         return false;
 1113:     }
 1114:   }
 1115: 
 1116:   return true;
 1117: }
 1118: 
 1119: // Read SMART Log page(s)
 1120: bool ataReadSmartLog(ata_device * device, unsigned char logaddr,
 1121:                      void * data, unsigned nsectors)
 1122: {
 1123:   ata_cmd_in in;
 1124:   in.in_regs.command  = ATA_SMART_CMD;
 1125:   in.in_regs.features = ATA_SMART_READ_LOG_SECTOR;
 1126:   in.set_data_in(data, nsectors);
 1127:   in.in_regs.lba_high = SMART_CYL_HI;
 1128:   in.in_regs.lba_mid  = SMART_CYL_LOW;
 1129:   in.in_regs.lba_low  = logaddr;
 1130: 
 1131:   if (!device->ata_pass_through(in)) { // TODO: Debug output
 1132:     pout("ATA_SMART_READ_LOG failed: %s\n", device->get_errmsg());
 1133:     return false;
 1134:   }
 1135:   return true;
 1136: }
 1137: 
 1138: 
 1139: 
 1140: // Reads the SMART or GPL Log Directory (log #0)
 1141: int ataReadLogDirectory(ata_device * device, ata_smart_log_directory * data, bool gpl)
 1142: {
 1143:   if (!gpl) { // SMART Log directory
 1144:     if (smartcommandhandler(device, READ_LOG, 0x00, (char *)data))
 1145:       return -1;
 1146:   }
 1147:   else { // GP Log directory
 1148:     if (!ataReadLogExt(device, 0x00, 0x00, 0, data, 1))
 1149:       return -1;
 1150:   }
 1151: 
 1152:   // swap endian order if needed
 1153:   if (isbigendian())
 1154:     swapx(&data->logversion);
 1155: 
 1156:   return 0;
 1157: }
 1158: 
 1159: 
 1160: // Reads the selective self-test log (log #9)
 1161: int ataReadSelectiveSelfTestLog(ata_device * device, struct ata_selective_self_test_log *data){
 1162:   
 1163:   // get data from device
 1164:   if (smartcommandhandler(device, READ_LOG, 0x09, (char *)data)){
 1165:     return -1;
 1166:   }
 1167:    
 1168:   // compute its checksum, and issue a warning if needed
 1169:   if (checksum(data))
 1170:     checksumwarning("SMART Selective Self-Test Log Structure");
 1171:   
 1172:   // swap endian order if needed
 1173:   if (isbigendian()){
 1174:     int i;
 1175:     swap2((char *)&(data->logversion));
 1176:     for (i=0;i<5;i++){
 1177:       swap8((char *)&(data->span[i].start));
 1178:       swap8((char *)&(data->span[i].end));
 1179:     }
 1180:     swap8((char *)&(data->currentlba));
 1181:     swap2((char *)&(data->currentspan));
 1182:     swap2((char *)&(data->flags));
 1183:     swap2((char *)&(data->pendingtime));
 1184:   }
 1185:   
 1186:   return 0;
 1187: }
 1188: 
 1189: // Writes the selective self-test log (log #9)
 1190: int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_args & args,
 1191:                                  const ata_smart_values * sv, uint64_t num_sectors,
 1192:                                  const ata_selective_selftest_args * prev_args)
 1193: {
 1194:   // Disk size must be known
 1195:   if (!num_sectors) {
 1196:     pout("Disk size is unknown, unable to check selective self-test spans\n");
 1197:     return -1;
 1198:   }
 1199: 
 1200:   // Read log
 1201:   struct ata_selective_self_test_log sstlog, *data=&sstlog;
 1202:   unsigned char *ptr=(unsigned char *)data;
 1203:   if (ataReadSelectiveSelfTestLog(device, data)) {
 1204:     pout("SMART Read Selective Self-test Log failed: %s\n", device->get_errmsg());
 1205:     pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n");
 1206:     return -1;
 1207:   }
 1208:   
 1209:   // Set log version
 1210:   data->logversion = 1;
 1211: 
 1212:   // Host is NOT allowed to write selective self-test log if a selective
 1213:   // self-test is in progress.
 1214:   if (0<data->currentspan && data->currentspan<6 && ((sv->self_test_exec_status)>>4)==15) {
 1215:     pout("SMART Selective or other Self-test in progress\n");
 1216:     return -4;
 1217:   }
 1218: 
 1219:   // Set start/end values based on old spans for special -t select,... options
 1220:   int i;
 1221:   for (i = 0; i < args.num_spans; i++) {
 1222:     int mode = args.span[i].mode;
 1223:     uint64_t start = args.span[i].start;
 1224:     uint64_t end   = args.span[i].end;
 1225:     if (mode == SEL_CONT) {// redo or next dependig on last test status
 1226:       switch (sv->self_test_exec_status >> 4) {
 1227:         case 1: case 2: // Aborted/Interrupted by host
 1228:           pout("Continue Selective Self-Test: Redo last span\n");
 1229:           mode = SEL_REDO;
 1230:           break;
 1231:         default: // All others
 1232:           pout("Continue Selective Self-Test: Start next span\n");
 1233:           mode = SEL_NEXT;
 1234:           break;
 1235:       }
 1236:     }
 1237: 
 1238:     if (   (mode == SEL_REDO || mode == SEL_NEXT)
 1239:         && prev_args && i < prev_args->num_spans
 1240:         && !data->span[i].start && !data->span[i].end) {
 1241:       // Some drives do not preserve the selective self-test log accross
 1242:       // power-cyles.  If old span on drive is cleared use span provided
 1243:       // by caller.  This is used by smartd (first span only).
 1244:       data->span[i].start = prev_args->span[i].start;
 1245:       data->span[i].end   = prev_args->span[i].end;
 1246:     }
 1247: 
 1248:     switch (mode) {
 1249:       case SEL_RANGE: // -t select,START-END
 1250:         break;
 1251:       case SEL_REDO: // -t select,redo... => Redo current
 1252:         start = data->span[i].start;
 1253:         if (end > 0) { // -t select,redo+SIZE
 1254:           end--; end += start; // [oldstart, oldstart+SIZE)
 1255:         }
 1256:         else // -t select,redo
 1257:           end = data->span[i].end; // [oldstart, oldend]
 1258:         break;
 1259:       case SEL_NEXT: // -t select,next... => Do next
 1260:         if (data->span[i].end == 0) {
 1261:           start = end = 0; break; // skip empty spans
 1262:         }
 1263:         start = data->span[i].end + 1;
 1264:         if (start >= num_sectors)
 1265:           start = 0; // wrap around
 1266:         if (end > 0) { // -t select,next+SIZE
 1267:           end--; end += start; // (oldend, oldend+SIZE]
 1268:         }
 1269:         else { // -t select,next
 1270:           uint64_t oldsize = data->span[i].end - data->span[i].start + 1;
 1271:           end = start + oldsize - 1; // (oldend, oldend+oldsize]
 1272:           if (end >= num_sectors) {
 1273:             // Adjust size to allow round-robin testing without future size decrease
 1274:             uint64_t spans = (num_sectors + oldsize-1) / oldsize;
 1275:             uint64_t newsize = (num_sectors + spans-1) / spans;
 1276:             uint64_t newstart = num_sectors - newsize, newend = num_sectors - 1;
 1277:             pout("Span %d changed from %"PRIu64"-%"PRIu64" (%"PRIu64" sectors)\n",
 1278:                  i, start, end, oldsize);
 1279:             pout("                 to %"PRIu64"-%"PRIu64" (%"PRIu64" sectors) (%"PRIu64" spans)\n",
 1280:                  newstart, newend, newsize, spans);
 1281:             start = newstart; end = newend;
 1282:           }
 1283:         }
 1284:         break;
 1285:       default:
 1286:         pout("ataWriteSelectiveSelfTestLog: Invalid mode %d\n", mode);
 1287:         return -1;
 1288:     }
 1289:     // Range check
 1290:     if (start < num_sectors && num_sectors <= end) {
 1291:       if (end != ~(uint64_t)0) // -t select,N-max
 1292:         pout("Size of self-test span %d decreased according to disk size\n", i);
 1293:       end = num_sectors - 1;
 1294:     }
 1295:     if (!(start <= end && end < num_sectors)) {
 1296:       pout("Invalid selective self-test span %d: %"PRIu64"-%"PRIu64" (%"PRIu64" sectors)\n",
 1297:         i, start, end, num_sectors);
 1298:       return -1;
 1299:     }
 1300:     // Return the actual mode and range to caller.
 1301:     args.span[i].mode  = mode;
 1302:     args.span[i].start = start;
 1303:     args.span[i].end   = end;
 1304:   }
 1305: 
 1306:   // Clear spans
 1307:   for (i=0; i<5; i++)
 1308:     memset(data->span+i, 0, sizeof(struct test_span));
 1309:   
 1310:   // Set spans for testing 
 1311:   for (i = 0; i < args.num_spans; i++){
 1312:     data->span[i].start = args.span[i].start;
 1313:     data->span[i].end   = args.span[i].end;
 1314:   }
 1315: 
 1316:   // host must initialize to zero before initiating selective self-test
 1317:   data->currentlba=0;
 1318:   data->currentspan=0;
 1319:   
 1320:   // Perform off-line scan after selective test?
 1321:   if (args.scan_after_select == 1)
 1322:     // NO
 1323:     data->flags &= ~SELECTIVE_FLAG_DOSCAN;
 1324:   else if (args.scan_after_select == 2)
 1325:     // YES
 1326:     data->flags |= SELECTIVE_FLAG_DOSCAN;
 1327:   
 1328:   // Must clear active and pending flags before writing
 1329:   data->flags &= ~(SELECTIVE_FLAG_ACTIVE);  
 1330:   data->flags &= ~(SELECTIVE_FLAG_PENDING);
 1331: 
 1332:   // modify pending time?
 1333:   if (args.pending_time)
 1334:     data->pendingtime = (unsigned short)(args.pending_time-1);
 1335: 
 1336:   // Set checksum to zero, then compute checksum
 1337:   data->checksum=0;
 1338:   unsigned char cksum=0;
 1339:   for (i=0; i<512; i++)
 1340:     cksum+=ptr[i];
 1341:   cksum=~cksum;
 1342:   cksum+=1;
 1343:   data->checksum=cksum;
 1344: 
 1345:   // swap endian order if needed
 1346:   if (isbigendian()){
 1347:     swap2((char *)&(data->logversion));
 1348:     for (int b = 0; b < 5; b++) {
 1349:       swap8((char *)&(data->span[b].start));
 1350:       swap8((char *)&(data->span[b].end));
 1351:     }
 1352:     swap8((char *)&(data->currentlba));
 1353:     swap2((char *)&(data->currentspan));
 1354:     swap2((char *)&(data->flags));
 1355:     swap2((char *)&(data->pendingtime));
 1356:   }
 1357: 
 1358:   // write new selective self-test log
 1359:   if (smartcommandhandler(device, WRITE_LOG, 0x09, (char *)data)){
 1360:     pout("Write Selective Self-test Log failed: %s\n", device->get_errmsg());
 1361:     return -3;
 1362:   }
 1363: 
 1364:   return 0;
 1365: }
 1366: 
 1367: // This corrects some quantities that are byte reversed in the SMART
 1368: // ATA ERROR LOG.
 1369: static void fixsamsungerrorlog(ata_smart_errorlog * data)
 1370: {
 1371:   // FIXED IN SAMSUNG -25 FIRMWARE???
 1372:   // Device error count in bytes 452-3
 1373:   swap2((char *)&(data->ata_error_count));
 1374:   
 1375:   // FIXED IN SAMSUNG -22a FIRMWARE
 1376:   // step through 5 error log data structures
 1377:   for (int i = 0; i < 5; i++){
 1378:     // step through 5 command data structures
 1379:     for (int j = 0; j < 5; j++)
 1380:       // Command data structure 4-byte millisec timestamp.  These are
 1381:       // bytes (N+8, N+9, N+10, N+11).
 1382:       swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp));
 1383:     // Error data structure two-byte hour life timestamp.  These are
 1384:     // bytes (N+28, N+29).
 1385:     swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp));
 1386:   }
 1387:   return;
 1388: }
 1389: 
 1390: // NEEDED ONLY FOR SAMSUNG -22 (some) -23 AND -24?? FIRMWARE
 1391: static void fixsamsungerrorlog2(ata_smart_errorlog * data)
 1392: {
 1393:   // Device error count in bytes 452-3
 1394:   swap2((char *)&(data->ata_error_count));
 1395:   return;
 1396: }
 1397: 
 1398: // Reads the Summary SMART Error Log (log #1). The Comprehensive SMART
 1399: // Error Log is #2, and the Extended Comprehensive SMART Error log is
 1400: // #3
 1401: int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
 1402:                      firmwarebug_defs firmwarebugs)
 1403: {
 1404:   
 1405:   // get data from device
 1406:   if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){
 1407:     return -1;
 1408:   }
 1409:   
 1410:   // compute its checksum, and issue a warning if needed
 1411:   if (checksum(data))
 1412:     checksumwarning("SMART ATA Error Log Structure");
 1413:   
 1414:   // Some disks have the byte order reversed in some SMART Summary
 1415:   // Error log entries
 1416:   if (firmwarebugs.is_set(BUG_SAMSUNG))
 1417:     fixsamsungerrorlog(data);
 1418:   else if (firmwarebugs.is_set(BUG_SAMSUNG2))
 1419:     fixsamsungerrorlog2(data);
 1420: 
 1421:   // swap endian order if needed
 1422:   if (isbigendian()){
 1423:     int i,j;
 1424:     
 1425:     // Device error count in bytes 452-3
 1426:     swap2((char *)&(data->ata_error_count));
 1427:     
 1428:     // step through 5 error log data structures
 1429:     for (i=0; i<5; i++){
 1430:       // step through 5 command data structures
 1431:       for (j=0; j<5; j++)
 1432:         // Command data structure 4-byte millisec timestamp
 1433:         swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp));
 1434:       // Error data structure life timestamp
 1435:       swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp));
 1436:     }
 1437:   }
 1438:   
 1439:   return 0;
 1440: }
 1441: 
 1442: 
 1443: // Fix LBA byte ordering of Extended Comprehensive Error Log
 1444: // if little endian instead of ATA register ordering is provided
 1445: template <class T>
 1446: static inline void fix_exterrlog_lba_cmd(T & cmd)
 1447: {
 1448:   T org = cmd;
 1449:   cmd.lba_mid_register_hi = org.lba_high_register;
 1450:   cmd.lba_low_register_hi = org.lba_mid_register_hi;
 1451:   cmd.lba_high_register   = org.lba_mid_register;
 1452:   cmd.lba_mid_register    = org.lba_low_register_hi;
 1453: }
 1454: 
 1455: static void fix_exterrlog_lba(ata_smart_exterrlog * log, unsigned nsectors)
 1456: {
 1457:    for (unsigned i = 0; i < nsectors; i++) {
 1458:      for (int ei = 0; ei < 4; ei++) {
 1459:        ata_smart_exterrlog_error_log & entry = log[i].error_logs[ei];
 1460:        fix_exterrlog_lba_cmd(entry.error);
 1461:        for (int ci = 0; ci < 5; ci++)
 1462:          fix_exterrlog_lba_cmd(entry.commands[ci]);
 1463:      }
 1464:    }
 1465: }
 1466: 
 1467: // Read Extended Comprehensive Error Log
 1468: bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log,
 1469:                         unsigned nsectors, firmwarebug_defs firmwarebugs)
 1470: {
 1471:   if (!ataReadLogExt(device, 0x03, 0x00, 0, log, nsectors))
 1472:     return false;
 1473: 
 1474:   check_multi_sector_sum(log, nsectors, "SMART Extended Comprehensive Error Log Structure");
 1475: 
 1476:   if (isbigendian()) {
 1477:     swapx(&log->device_error_count);
 1478:     swapx(&log->error_log_index);
 1479: 
 1480:     for (unsigned i = 0; i < nsectors; i++) {
 1481:       for (unsigned j = 0; j < 4; j++)
 1482:         swapx(&log->error_logs[i].commands[j].timestamp);
 1483:       swapx(&log->error_logs[i].error.timestamp);
 1484:     }
 1485:   }
 1486: 
 1487:   if (firmwarebugs.is_set(BUG_XERRORLBA))
 1488:     fix_exterrlog_lba(log, nsectors);
 1489: 
 1490:   return true;
 1491: }
 1492: 
 1493: 
 1494: int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt *data){
 1495:   
 1496:   // get data from device
 1497:   if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){
 1498:     return -1;
 1499:   }
 1500:   
 1501:   // compute its checksum, and issue a warning if needed
 1502:   if (checksum(data))
 1503:     checksumwarning("SMART Attribute Thresholds Structure");
 1504:   
 1505:   // swap endian order if needed
 1506:   if (isbigendian())
 1507:     swap2((char *)&(data->revnumber));
 1508: 
 1509:   return 0;
 1510: }
 1511: 
 1512: int ataEnableSmart (ata_device * device ){
 1513:   if (smartcommandhandler(device, ENABLE, 0, NULL)){
 1514:     return -1;
 1515:   }
 1516:   return 0;
 1517: }
 1518: 
 1519: int ataDisableSmart (ata_device * device ){
 1520:   
 1521:   if (smartcommandhandler(device, DISABLE, 0, NULL)){
 1522:     return -1;
 1523:   }  
 1524:   return 0;
 1525: }
 1526: 
 1527: int ataEnableAutoSave(ata_device * device){
 1528:   if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){
 1529:     return -1;
 1530:   }
 1531:   return 0;
 1532: }
 1533: 
 1534: int ataDisableAutoSave(ata_device * device){
 1535:   
 1536:   if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){
 1537:     return -1;
 1538:   }
 1539:   return 0;
 1540: }
 1541: 
 1542: // In *ALL* ATA standards the Enable/Disable AutoOffline command is
 1543: // marked "OBSOLETE". It is defined in SFF-8035i Revision 2, and most
 1544: // vendors still support it for backwards compatibility. IBM documents
 1545: // it for some drives.
 1546: int ataEnableAutoOffline (ata_device * device){
 1547:   
 1548:   /* timer hard coded to 4 hours */  
 1549:   if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){
 1550:     return -1;
 1551:   }
 1552:   return 0;
 1553: }
 1554: 
 1555: // Another Obsolete Command.  See comments directly above, associated
 1556: // with the corresponding Enable command.
 1557: int ataDisableAutoOffline (ata_device * device){
 1558:   
 1559:   if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){
 1560:     return -1;
 1561:   }
 1562:   return 0;
 1563: }
 1564: 
 1565: // If SMART is enabled, supported, and working, then this call is
 1566: // guaranteed to return 1, else zero.  Note that it should return 1
 1567: // regardless of whether the disk's SMART status is 'healthy' or
 1568: // 'failing'.
 1569: int ataDoesSmartWork(ata_device * device){
 1570:   int retval=smartcommandhandler(device, STATUS, 0, NULL);
 1571: 
 1572:   if (-1 == retval)
 1573:     return 0;
 1574: 
 1575:   return 1;
 1576: }
 1577: 
 1578: // This function uses a different interface (DRIVE_TASK) than the
 1579: // other commands in this file.
 1580: int ataSmartStatus2(ata_device * device){
 1581:   return smartcommandhandler(device, STATUS_CHECK, 0, NULL);  
 1582: }
 1583: 
 1584: // This is the way to execute ALL tests: offline, short self-test,
 1585: // extended self test, with and without captive mode, etc.
 1586: // TODO: Move to ataprint.cpp ?
 1587: int ataSmartTest(ata_device * device, int testtype, bool force,
 1588:                  const ata_selective_selftest_args & selargs,
 1589:                  const ata_smart_values * sv, uint64_t num_sectors)
 1590: {
 1591:   char cmdmsg[128]; const char *type, *captive;
 1592:   int cap, retval, select=0;
 1593: 
 1594:   // Boolean, if set, says test is captive
 1595:   cap=testtype & CAPTIVE_MASK;
 1596: 
 1597:   // Set up strings that describe the type of test
 1598:   if (cap)
 1599:     captive="captive";
 1600:   else
 1601:     captive="off-line";
 1602:   
 1603:   if (testtype==OFFLINE_FULL_SCAN)
 1604:     type="off-line";
 1605:   else  if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST)
 1606:     type="Short self-test";
 1607:   else if (testtype==EXTEND_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST)
 1608:     type="Extended self-test";
 1609:   else if (testtype==CONVEYANCE_SELF_TEST || testtype==CONVEYANCE_CAPTIVE_SELF_TEST)
 1610:     type="Conveyance self-test";
 1611:   else if ((select=(testtype==SELECTIVE_SELF_TEST || testtype==SELECTIVE_CAPTIVE_SELF_TEST)))
 1612:     type="Selective self-test";
 1613:   else
 1614:     type = 0;
 1615: 
 1616:   // Check whether another test is already running
 1617:   if (type && (sv->self_test_exec_status >> 4) == 0xf) {
 1618:     if (!force) {
 1619:       pout("Can't start self-test without aborting current test (%d0%% remaining),\n"
 1620:            "%srun 'smartctl -X' to abort test.\n",
 1621:            sv->self_test_exec_status & 0x0f,
 1622:            (!select ? "add '-t force' option to override, or " : ""));
 1623:       return -1;
 1624:     }
 1625:   }
 1626:   else
 1627:     force = false;
 1628: 
 1629:   // If doing a selective self-test, first use WRITE_LOG to write the
 1630:   // selective self-test log.
 1631:   ata_selective_selftest_args selargs_io = selargs; // filled with info about actual spans
 1632:   if (select && (retval = ataWriteSelectiveSelfTestLog(device, selargs_io, sv, num_sectors))) {
 1633:     if (retval==-4)
 1634:       pout("Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");
 1635:     return retval;
 1636:   }
 1637: 
 1638:   //  Print ouf message that we are sending the command to test
 1639:   if (testtype==ABORT_SELF_TEST)
 1640:     snprintf(cmdmsg, sizeof(cmdmsg), "Abort SMART off-line mode self-test routine");
 1641:   else if (!type)
 1642:     snprintf(cmdmsg, sizeof(cmdmsg), "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype);
 1643:   else
 1644:     snprintf(cmdmsg, sizeof(cmdmsg), "Execute SMART %s routine immediately in %s mode", type, captive);
 1645:   pout("Sending command: \"%s\".\n",cmdmsg);
 1646: 
 1647:   if (select) {
 1648:     int i;
 1649:     pout("SPAN         STARTING_LBA           ENDING_LBA\n");
 1650:     for (i = 0; i < selargs_io.num_spans; i++)
 1651:       pout("   %d %20"PRId64" %20"PRId64"\n", i,
 1652:            selargs_io.span[i].start,
 1653:            selargs_io.span[i].end);
 1654:   }
 1655:   
 1656:   // Now send the command to test
 1657:   if (smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL)) {
 1658:     if (!(cap && device->get_errno() == EIO)) {
 1659:       pout("Command \"%s\" failed: %s\n", cmdmsg, device->get_errmsg());
 1660:       return -1;
 1661:     }
 1662:   }
 1663:   
 1664:   // Since the command succeeded, tell user
 1665:   if (testtype==ABORT_SELF_TEST)
 1666:     pout("Self-testing aborted!\n");
 1667:   else {
 1668:     pout("Drive command \"%s\" successful.\n", cmdmsg);
 1669:     if (type)
 1670:       pout("Testing has begun%s.\n", (force ? " (previous test aborted)" : ""));
 1671:   }
 1672:   return 0;
 1673: }
 1674: 
 1675: /* Test Time Functions */
 1676: int TestTime(const ata_smart_values *data, int testtype)
 1677: {
 1678:   switch (testtype){
 1679:   case OFFLINE_FULL_SCAN:
 1680:     return (int) data->total_time_to_complete_off_line;
 1681:   case SHORT_SELF_TEST:
 1682:   case SHORT_CAPTIVE_SELF_TEST:
 1683:     return (int) data->short_test_completion_time;
 1684:   case EXTEND_SELF_TEST:
 1685:   case EXTEND_CAPTIVE_SELF_TEST:
 1686:     if (data->extend_test_completion_time_b == 0xff
 1687:         && data->extend_test_completion_time_w != 0x0000
 1688:         && data->extend_test_completion_time_w != 0xffff)
 1689:       return data->extend_test_completion_time_w; // ATA-8
 1690:     else
 1691:       return data->extend_test_completion_time_b;
 1692:   case CONVEYANCE_SELF_TEST:
 1693:   case CONVEYANCE_CAPTIVE_SELF_TEST:
 1694:     return (int) data->conveyance_test_completion_time;
 1695:   default:
 1696:     return 0;
 1697:   }
 1698: }
 1699: 
 1700: // This function tells you both about the ATA error log and the
 1701: // self-test error log capability (introduced in ATA-5).  The bit is
 1702: // poorly documented in the ATA/ATAPI standard.  Starting with ATA-6,
 1703: // SMART error logging is also indicated in bit 0 of DEVICE IDENTIFY
 1704: // word 84 and 87.  Top two bits must match the pattern 01. BEFORE
 1705: // ATA-6 these top two bits still had to match the pattern 01, but the
 1706: // remaining bits were reserved (==0).
 1707: int isSmartErrorLogCapable (const ata_smart_values * data, const ata_identify_device * identity)
 1708: {
 1709:   unsigned short word84=identity->command_set_extension;
 1710:   unsigned short word87=identity->csf_default;
 1711:   int isata6=identity->major_rev_num & (0x01<<6);
 1712:   int isata7=identity->major_rev_num & (0x01<<7);
 1713: 
 1714:   if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x01))
 1715:     return 1;
 1716:   
 1717:   if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x01))
 1718:     return 1;
 1719:   
 1720:   // otherwise we'll use the poorly documented capability bit
 1721:   return data->errorlog_capability & 0x01;
 1722: }
 1723: 
 1724: // See previous function.  If the error log exists then the self-test
 1725: // log should (must?) also exist.
 1726: int isSmartTestLogCapable (const ata_smart_values * data, const ata_identify_device *identity)
 1727: {
 1728:   unsigned short word84=identity->command_set_extension;
 1729:   unsigned short word87=identity->csf_default;
 1730:   int isata6=identity->major_rev_num & (0x01<<6);
 1731:   int isata7=identity->major_rev_num & (0x01<<7);
 1732: 
 1733:   if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x02))
 1734:     return 1;
 1735:   
 1736:   if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x02))
 1737:     return 1;
 1738: 
 1739: 
 1740:   // otherwise we'll use the poorly documented capability bit
 1741:   return data->errorlog_capability & 0x01;
 1742: }
 1743: 
 1744: 
 1745: int isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
 1746: {
 1747:   unsigned short word84=identity->command_set_extension;
 1748:   unsigned short word87=identity->csf_default;
 1749: 
 1750:   // If bit 14 of word 84 is set to one and bit 15 of word 84 is
 1751:   // cleared to zero, the contents of word 84 contains valid support
 1752:   // information. If not, support information is not valid in this
 1753:   // word.
 1754:   if ((word84>>14) == 0x01)
 1755:     // If bit 5 of word 84 is set to one, the device supports the
 1756:     // General Purpose Logging feature set.
 1757:     return (word84 & (0x01 << 5));
 1758:   
 1759:   // If bit 14 of word 87 is set to one and bit 15 of word 87 is
 1760:   // cleared to zero, the contents of words (87:85) contain valid
 1761:   // information. If not, information is not valid in these words.  
 1762:   if ((word87>>14) == 0x01)
 1763:     // If bit 5 of word 87 is set to one, the device supports
 1764:     // the General Purpose Logging feature set.
 1765:     return (word87 & (0x01 << 5));
 1766: 
 1767:   // not capable
 1768:   return 0;
 1769: }
 1770: 
 1771: 
 1772: // SMART self-test capability is also indicated in bit 1 of DEVICE
 1773: // IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
 1774: // However this was only introduced in ATA-6 (but self-test log was in
 1775: // ATA-5).
 1776: int isSupportExecuteOfflineImmediate(const ata_smart_values *data)
 1777: {
 1778:   return data->offline_data_collection_capability & 0x01;
 1779: }
 1780: 
 1781: // Note in the ATA-5 standard, the following bit is listed as "Vendor
 1782: // Specific".  So it may not be reliable. The only use of this that I
 1783: // have found is in IBM drives, where it is well-documented.  See for
 1784: // example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
 1785: // hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
 1786: int isSupportAutomaticTimer(const ata_smart_values * data)
 1787: {
 1788:   return data->offline_data_collection_capability & 0x02;
 1789: }
 1790: int isSupportOfflineAbort(const ata_smart_values *data)
 1791: {
 1792:   return data->offline_data_collection_capability & 0x04;
 1793: }
 1794: int isSupportOfflineSurfaceScan(const ata_smart_values * data)
 1795: {
 1796:    return data->offline_data_collection_capability & 0x08;
 1797: }
 1798: int isSupportSelfTest (const ata_smart_values * data)
 1799: {
 1800:    return data->offline_data_collection_capability & 0x10;
 1801: }
 1802: int isSupportConveyanceSelfTest(const ata_smart_values * data)
 1803: {
 1804:    return data->offline_data_collection_capability & 0x20;
 1805: }
 1806: int isSupportSelectiveSelfTest(const ata_smart_values * data)
 1807: {
 1808:    return data->offline_data_collection_capability & 0x40;
 1809: }
 1810: 
 1811: // Get attribute state
 1812: ata_attr_state ata_get_attr_state(const ata_smart_attribute & attr,
 1813:                                   int attridx,
 1814:                                   const ata_smart_threshold_entry * thresholds,
 1815:                                   const ata_vendor_attr_defs & defs,
 1816:                                   unsigned char * threshval /* = 0 */)
 1817: {
 1818:   if (!attr.id)
 1819:     return ATTRSTATE_NON_EXISTING;
 1820: 
 1821:   // Normalized values (current,worst,threshold) not valid
 1822:   // if specified by '-v' option.
 1823:   // (Some SSD disks uses these bytes to store raw value).
 1824:   if (defs[attr.id].flags & ATTRFLAG_NO_NORMVAL)
 1825:     return ATTRSTATE_NO_NORMVAL;
 1826: 
 1827:   // Normally threshold is at same index as attribute
 1828:   int i = attridx;
 1829:   if (thresholds[i].id != attr.id) {
 1830:     // Find threshold id in table
 1831:     for (i = 0; thresholds[i].id != attr.id; ) {
 1832:       if (++i >= NUMBER_ATA_SMART_ATTRIBUTES)
 1833:         // Threshold id missing or thresholds cannot be read
 1834:         return ATTRSTATE_NO_THRESHOLD;
 1835:     }
 1836:   }
 1837:   unsigned char threshold = thresholds[i].threshold;
 1838: 
 1839:   // Return threshold if requested
 1840:   if (threshval)
 1841:     *threshval = threshold;
 1842: 
 1843:   // Don't report a failed attribute if its threshold is 0.
 1844:   // ATA-3 (X3T13/2008D Revision 7b) declares 0x00 as the "always passing"
 1845:   // threshold (Later ATA versions declare all thresholds as "obsolete").
 1846:   // In practice, threshold value 0 is often used for usage attributes.
 1847:   if (!threshold)
 1848:     return ATTRSTATE_OK;
 1849: 
 1850:   // Failed now if current value is below threshold
 1851:   if (attr.current <= threshold)
 1852:     return ATTRSTATE_FAILED_NOW;
 1853: 
 1854:   // Failed in the past if worst value is below threshold
 1855:   if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL) && attr.worst <= threshold)
 1856:     return ATTRSTATE_FAILED_PAST;
 1857: 
 1858:   return ATTRSTATE_OK;
 1859: }
 1860: 
 1861: // Get default raw value print format
 1862: static ata_attr_raw_format get_default_raw_format(unsigned char id)
 1863: {
 1864:   switch (id) {
 1865:   case 3:   // Spin-up time
 1866:     return RAWFMT_RAW16_OPT_AVG16;
 1867: 
 1868:   case 5:   // Reallocated sector count
 1869:   case 196: // Reallocated event count
 1870:     return RAWFMT_RAW16_OPT_RAW16;
 1871: 
 1872:   case 9:  // Power on hours
 1873:     return RAWFMT_RAW24_OPT_RAW8;
 1874: 
 1875:   case 190: // Temperature
 1876:   case 194:
 1877:     return RAWFMT_TEMPMINMAX;
 1878: 
 1879:   default:
 1880:     return RAWFMT_RAW48;
 1881:   }
 1882: }
 1883: 
 1884: // Get attribute raw value.
 1885: uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr,
 1886:                                 const ata_vendor_attr_defs & defs)
 1887: {
 1888:   const ata_vendor_attr_defs::entry & def = defs[attr.id];
 1889: 
 1890:   // Use default byteorder if not specified
 1891:   const char * byteorder = def.byteorder;
 1892:   if (!*byteorder) {
 1893:     switch (def.raw_format) {
 1894:       case RAWFMT_RAW64:
 1895:       case RAWFMT_HEX64:
 1896:         byteorder = "543210wv"; break;
 1897:       case RAWFMT_RAW56:
 1898:       case RAWFMT_HEX56:
 1899:       case RAWFMT_RAW24_DIV_RAW32:
 1900:       case RAWFMT_MSEC24_HOUR32:
 1901:         byteorder = "r543210"; break;
 1902:       default:
 1903:         byteorder = "543210"; break;
 1904:     }
 1905:   }
 1906: 
 1907:   // Build 64-bit value from selected bytes
 1908:   uint64_t rawvalue = 0;
 1909:   for (int i = 0; byteorder[i]; i++) {
 1910:     unsigned char b;
 1911:     switch (byteorder[i]) {
 1912:       case '0': b = attr.raw[0];  break;
 1913:       case '1': b = attr.raw[1];  break;
 1914:       case '2': b = attr.raw[2];  break;
 1915:       case '3': b = attr.raw[3];  break;
 1916:       case '4': b = attr.raw[4];  break;
 1917:       case '5': b = attr.raw[5];  break;
 1918:       case 'r': b = attr.reserv;  break;
 1919:       case 'v': b = attr.current; break;
 1920:       case 'w': b = attr.worst;   break;
 1921:       default : b = 0;            break;
 1922:     }
 1923:     rawvalue <<= 8; rawvalue |= b;
 1924:   }
 1925: 
 1926:   return rawvalue;
 1927: }
 1928: 
 1929: 
 1930: // Format attribute raw value.
 1931: std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
 1932:                                       const ata_vendor_attr_defs & defs)
 1933: {
 1934:   // Get 48 bit or 64 bit raw value
 1935:   uint64_t rawvalue = ata_get_attr_raw_value(attr, defs);
 1936: 
 1937:   // Split into bytes and words
 1938:   unsigned char raw[6];
 1939:   raw[0] = (unsigned char) rawvalue;
 1940:   raw[1] = (unsigned char)(rawvalue >>  8);
 1941:   raw[2] = (unsigned char)(rawvalue >> 16);
 1942:   raw[3] = (unsigned char)(rawvalue >> 24);
 1943:   raw[4] = (unsigned char)(rawvalue >> 32);
 1944:   raw[5] = (unsigned char)(rawvalue >> 40);
 1945:   unsigned word[3];
 1946:   word[0] = raw[0] | (raw[1] << 8);
 1947:   word[1] = raw[2] | (raw[3] << 8);
 1948:   word[2] = raw[4] | (raw[5] << 8);
 1949: 
 1950:   // Get print format
 1951:   ata_attr_raw_format format = defs[attr.id].raw_format;
 1952:   if (format == RAWFMT_DEFAULT)
 1953:     format = get_default_raw_format(attr.id);
 1954: 
 1955:   // Print
 1956:   std::string s;
 1957:   switch (format) {
 1958:   case RAWFMT_RAW8:
 1959:     s = strprintf("%d %d %d %d %d %d",
 1960:       raw[5], raw[4], raw[3], raw[2], raw[1], raw[0]);
 1961:     break;
 1962: 
 1963:   case RAWFMT_RAW16:
 1964:     s = strprintf("%u %u %u", word[2], word[1], word[0]);
 1965:     break;
 1966: 
 1967:   case RAWFMT_RAW48:
 1968:   case RAWFMT_RAW56:
 1969:   case RAWFMT_RAW64:
 1970:     s = strprintf("%"PRIu64, rawvalue);
 1971:     break;
 1972: 
 1973:   case RAWFMT_HEX48:
 1974:     s = strprintf("0x%012"PRIx64, rawvalue);
 1975:     break;
 1976: 
 1977:   case RAWFMT_HEX56:
 1978:     s = strprintf("0x%014"PRIx64, rawvalue);
 1979:     break;
 1980: 
 1981:   case RAWFMT_HEX64:
 1982:     s = strprintf("0x%016"PRIx64, rawvalue);
 1983:     break;
 1984: 
 1985:   case RAWFMT_RAW16_OPT_RAW16:
 1986:     s = strprintf("%u", word[0]);
 1987:     if (word[1] || word[2])
 1988:       s += strprintf(" (%u %u)", word[2], word[1]);
 1989:     break;
 1990: 
 1991:   case RAWFMT_RAW16_OPT_AVG16:
 1992:     s = strprintf("%u", word[0]);
 1993:     if (word[1])
 1994:       s += strprintf(" (Average %u)", word[1]);
 1995:     break;
 1996: 
 1997:   case RAWFMT_RAW24_OPT_RAW8:
 1998:     s = strprintf("%u", (unsigned)(rawvalue & 0x00ffffffULL));
 1999:     if (raw[3] || raw[4] || raw[5])
 2000:       s += strprintf(" (%d %d %d)", raw[5], raw[4], raw[3]);
 2001:     break;
 2002: 
 2003:   case RAWFMT_RAW24_DIV_RAW24:
 2004:     s = strprintf("%u/%u",
 2005:       (unsigned)(rawvalue >> 24), (unsigned)(rawvalue & 0x00ffffffULL));
 2006:     break;
 2007: 
 2008:   case RAWFMT_RAW24_DIV_RAW32:
 2009:     s = strprintf("%u/%u",
 2010:       (unsigned)(rawvalue >> 32), (unsigned)(rawvalue & 0xffffffffULL));
 2011:     break;
 2012: 
 2013:   case RAWFMT_MIN2HOUR:
 2014:     {
 2015:       // minutes
 2016:       int64_t temp = word[0]+(word[1]<<16);
 2017:       int64_t tmp1 = temp/60;
 2018:       int64_t tmp2 = temp%60;
 2019:       s = strprintf("%"PRIu64"h+%02"PRIu64"m", tmp1, tmp2);
 2020:       if (word[2])
 2021:         s += strprintf(" (%u)", word[2]);
 2022:     }
 2023:     break;
 2024: 
 2025:   case RAWFMT_SEC2HOUR:
 2026:     {
 2027:       // seconds
 2028:       int64_t hours = rawvalue/3600;
 2029:       int64_t minutes = (rawvalue-3600*hours)/60;
 2030:       int64_t seconds = rawvalue%60;
 2031:       s = strprintf("%"PRIu64"h+%02"PRIu64"m+%02"PRIu64"s", hours, minutes, seconds);
 2032:     }
 2033:     break;
 2034: 
 2035:   case RAWFMT_HALFMIN2HOUR:
 2036:     {
 2037:       // 30-second counter
 2038:       int64_t hours = rawvalue/120;
 2039:       int64_t minutes = (rawvalue-120*hours)/2;
 2040:       s += strprintf("%"PRIu64"h+%02"PRIu64"m", hours, minutes);
 2041:     }
 2042:     break;
 2043: 
 2044:   case RAWFMT_MSEC24_HOUR32:
 2045:     {
 2046:       // hours + milliseconds
 2047:       unsigned hours = (unsigned)(rawvalue & 0xffffffffULL);
 2048:       unsigned milliseconds = (unsigned)(rawvalue >> 32);
 2049:       unsigned seconds = milliseconds / 1000;
 2050:       s = strprintf("%uh+%02um+%02u.%03us",
 2051:         hours, seconds / 60, seconds % 60, milliseconds % 1000);
 2052:     }
 2053:     break;
 2054: 
 2055:   case RAWFMT_TEMPMINMAX:
 2056:     // Temperature
 2057:     {
 2058:       // Search for possible min/max values
 2059:       // 00 HH 00 LL 00 TT (Hitachi/IBM)
 2060:       // 00 00 HH LL 00 TT (Maxtor, Samsung)
 2061:       // 00 00 00 HH LL TT (WDC)
 2062:       unsigned char lo = 0, hi = 0;
 2063:       int cnt = 0;
 2064:       for (int i = 1; i < 6; i++) {
 2065:         if (raw[i])
 2066:           switch (cnt++) {
 2067:             case 0:
 2068:               lo = raw[i];
 2069:               break;
 2070:             case 1:
 2071:               if (raw[i] < lo) {
 2072:                 hi = lo; lo = raw[i];
 2073:               }
 2074:               else
 2075:                 hi = raw[i];
 2076:               break;
 2077:           }
 2078:       }
 2079: 
 2080:       unsigned char t = raw[0];
 2081:       if (cnt == 0)
 2082:         s = strprintf("%d", t);
 2083:       else if (cnt == 2 && 0 < lo && lo <= t && t <= hi && hi < 128)
 2084:         s = strprintf("%d (Min/Max %d/%d)", t, lo, hi);
 2085:       else
 2086:         s = strprintf("%d (%d %d %d %d %d)", t, raw[5], raw[4], raw[3], raw[2], raw[1]);
 2087:     }
 2088:     break;
 2089: 
 2090:   case RAWFMT_TEMP10X:
 2091:     // ten times temperature in Celsius
 2092:     s = strprintf("%d.%d", word[0]/10, word[0]%10);
 2093:     break;
 2094: 
 2095:   default:
 2096:     s = "?"; // Should not happen
 2097:     break;
 2098:   }
 2099: 
 2100:   return s;
 2101: }
 2102: 
 2103: // Attribute names shouldn't be longer than 23 chars, otherwise they break the
 2104: // output of smartctl.
 2105: static const char * get_default_attr_name(unsigned char id, int rpm)
 2106: {
 2107:   bool hdd = (rpm > 1), ssd = (rpm == 1);
 2108: 
 2109:   static const char Unknown_HDD_Attribute[] = "Unknown_HDD_Attribute";
 2110:   static const char Unknown_SSD_Attribute[] = "Unknown_SSD_Attribute";
 2111: 
 2112:   switch (id) {
 2113:   case 1:
 2114:     return "Raw_Read_Error_Rate";
 2115:   case 2:
 2116:     return "Throughput_Performance";
 2117:   case 3:
 2118:     return "Spin_Up_Time";
 2119:   case 4:
 2120:     return "Start_Stop_Count";
 2121:   case 5:
 2122:     return "Reallocated_Sector_Ct";
 2123:   case 6:
 2124:     if (ssd) return Unknown_SSD_Attribute;
 2125:     return "Read_Channel_Margin";
 2126:   case 7:
 2127:     if (ssd) return Unknown_SSD_Attribute;
 2128:     return "Seek_Error_Rate";
 2129:   case 8:
 2130:     if (ssd) return Unknown_SSD_Attribute;
 2131:     return "Seek_Time_Performance";
 2132:   case 9:
 2133:     return "Power_On_Hours";
 2134:   case 10:
 2135:     if (ssd) return Unknown_SSD_Attribute;
 2136:     return "Spin_Retry_Count";
 2137:   case 11:
 2138:     if (ssd) return Unknown_SSD_Attribute;
 2139:     return "Calibration_Retry_Count";
 2140:   case 12:
 2141:     return "Power_Cycle_Count";
 2142:   case 13:
 2143:     return "Read_Soft_Error_Rate";
 2144:   case 175:
 2145:     if (hdd) return Unknown_HDD_Attribute;
 2146:     return "Program_Fail_Count_Chip";
 2147:   case 176:
 2148:     if (hdd) return Unknown_HDD_Attribute;
 2149:     return "Erase_Fail_Count_Chip";
 2150:   case 177:
 2151:     if (hdd) return Unknown_HDD_Attribute;
 2152:     return "Wear_Leveling_Count";
 2153:   case 178:
 2154:     if (hdd) return Unknown_HDD_Attribute;
 2155:     return "Used_Rsvd_Blk_Cnt_Chip";
 2156:   case 179:
 2157:     if (hdd) return Unknown_HDD_Attribute;
 2158:     return "Used_Rsvd_Blk_Cnt_Tot";
 2159:   case 180:
 2160:     if (hdd) return Unknown_HDD_Attribute;
 2161:     return "Unused_Rsvd_Blk_Cnt_Tot";
 2162:   case 181:
 2163:     return "Program_Fail_Cnt_Total";
 2164:   case 182:
 2165:     if (hdd) return Unknown_HDD_Attribute;
 2166:     return "Erase_Fail_Count_Total";
 2167:   case 183:
 2168:     return "Runtime_Bad_Block";
 2169:   case 184:
 2170:     return "End-to-End_Error";
 2171:   case 187:
 2172:     return "Reported_Uncorrect";
 2173:   case 188:
 2174:     return "Command_Timeout";
 2175:   case 189:
 2176:     if (ssd) return Unknown_SSD_Attribute;
 2177:     return "High_Fly_Writes";
 2178:   case 190:
 2179:     // Western Digital uses this for temperature.
 2180:     // It's identical to Attribute 194 except that it
 2181:     // has a failure threshold set to correspond to the
 2182:     // max allowed operating temperature of the drive, which 
 2183:     // is typically 55C.  So if this attribute has failed
 2184:     // in the past, it indicates that the drive temp exceeded
 2185:     // 55C sometime in the past.
 2186:     return "Airflow_Temperature_Cel";
 2187:   case 191:
 2188:     if (ssd) return Unknown_SSD_Attribute;
 2189:     return "G-Sense_Error_Rate";
 2190:   case 192:
 2191:     return "Power-Off_Retract_Count";
 2192:   case 193:
 2193:     if (ssd) return Unknown_SSD_Attribute;
 2194:     return "Load_Cycle_Count";
 2195:   case 194:
 2196:     return "Temperature_Celsius";
 2197:   case 195:
 2198:     // Fujitsu: "ECC_On_The_Fly_Count";
 2199:     return "Hardware_ECC_Recovered";
 2200:   case 196:
 2201:     return "Reallocated_Event_Count";
 2202:   case 197:
 2203:     return "Current_Pending_Sector";
 2204:   case 198:
 2205:     return "Offline_Uncorrectable";
 2206:   case 199:
 2207:     return "UDMA_CRC_Error_Count";
 2208:   case 200:
 2209:     if (ssd) return Unknown_SSD_Attribute;
 2210:     // Western Digital
 2211:     return "Multi_Zone_Error_Rate";
 2212:   case 201:
 2213:     if (ssd) return Unknown_SSD_Attribute;
 2214:     return "Soft_Read_Error_Rate";
 2215:   case 202:
 2216:     if (ssd) return Unknown_SSD_Attribute;
 2217:     // Fujitsu: "TA_Increase_Count"
 2218:     return "Data_Address_Mark_Errs";
 2219:   case 203:
 2220:     // Fujitsu
 2221:     return "Run_Out_Cancel";
 2222:     // Maxtor: ECC Errors
 2223:   case 204:
 2224:     // Fujitsu: "Shock_Count_Write_Opern"
 2225:     return "Soft_ECC_Correction";
 2226:   case 205:
 2227:     // Fujitsu: "Shock_Rate_Write_Opern"
 2228:     return "Thermal_Asperity_Rate";
 2229:   case 206:
 2230:     // Fujitsu
 2231:     if (ssd) return Unknown_SSD_Attribute;
 2232:     return "Flying_Height";
 2233:   case 207:
 2234:     // Maxtor
 2235:     if (ssd) return Unknown_SSD_Attribute;
 2236:     return "Spin_High_Current";
 2237:   case 208:
 2238:     // Maxtor
 2239:     if (ssd) return Unknown_SSD_Attribute;
 2240:     return "Spin_Buzz";
 2241:   case 209:
 2242:     // Maxtor
 2243:     if (ssd) return Unknown_SSD_Attribute;
 2244:     return "Offline_Seek_Performnce";
 2245:   case 220:
 2246:     if (ssd) return Unknown_SSD_Attribute;
 2247:     return "Disk_Shift";
 2248:   case 221:
 2249:     if (ssd) return Unknown_SSD_Attribute;
 2250:     return "G-Sense_Error_Rate";
 2251:   case 222:
 2252:     if (ssd) return Unknown_SSD_Attribute;
 2253:     return "Loaded_Hours";
 2254:   case 223:
 2255:     if (ssd) return Unknown_SSD_Attribute;
 2256:     return "Load_Retry_Count";
 2257:   case 224:
 2258:     if (ssd) return Unknown_SSD_Attribute;
 2259:     return "Load_Friction";
 2260:   case 225:
 2261:     if (ssd) return Unknown_SSD_Attribute;
 2262:     return "Load_Cycle_Count";
 2263:   case 226:
 2264:     if (ssd) return Unknown_SSD_Attribute;
 2265:     return "Load-in_Time";
 2266:   case 227:
 2267:     if (ssd) return Unknown_SSD_Attribute;
 2268:     return "Torq-amp_Count";
 2269:   case 228:
 2270:     return "Power-off_Retract_Count";
 2271:   case 230:
 2272:     // seen in IBM DTPA-353750
 2273:     if (ssd) return Unknown_SSD_Attribute;
 2274:     return "Head_Amplitude";
 2275:   case 231:
 2276:     return "Temperature_Celsius";
 2277:   case 232:
 2278:     // seen in Intel X25-E SSD
 2279:     return "Available_Reservd_Space";
 2280:   case 233:
 2281:     // seen in Intel X25-E SSD
 2282:     if (hdd) return Unknown_HDD_Attribute;
 2283:     return "Media_Wearout_Indicator";
 2284:   case 240:
 2285:     if (ssd) return Unknown_SSD_Attribute;
 2286:     return "Head_Flying_Hours";
 2287:   case 241:
 2288:     return "Total_LBAs_Written";
 2289:   case 242:
 2290:     return "Total_LBAs_Read";
 2291:   case 250:
 2292:     return "Read_Error_Retry_Rate";
 2293:   case 254:
 2294:     if (ssd) return Unknown_SSD_Attribute;
 2295:     return "Free_Fall_Sensor";
 2296:   default:
 2297:     return "Unknown_Attribute";
 2298:   }
 2299: }
 2300: 
 2301: // Get attribute name
 2302: std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs,
 2303:                                     int rpm /* = 0 */)
 2304: {
 2305:   if (!defs[id].name.empty())
 2306:     return defs[id].name;
 2307:   else
 2308:     return get_default_attr_name(id, rpm);
 2309: }
 2310: 
 2311: // Find attribute index for attribute id, -1 if not found.
 2312: int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval)
 2313: {
 2314:   if (!id)
 2315:     return -1;
 2316:   for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
 2317:     if (smartval.vendor_attributes[i].id == id)
 2318:       return i;
 2319:   }
 2320:   return -1;
 2321: }
 2322: 
 2323: // Return Temperature Attribute raw value selected according to possible
 2324: // non-default interpretations. If the Attribute does not exist, return 0
 2325: unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs)
 2326: {
 2327:   for (int i = 0; i < 4; i++) {
 2328:     static const unsigned char ids[4] = {194, 190, 9, 220};
 2329:     unsigned char id = ids[i];
 2330:     const ata_attr_raw_format format = defs[id].raw_format;
 2331:     if (!(   ((id == 194 || id == 190) && format == RAWFMT_DEFAULT)
 2332:           || format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X))
 2333:       continue;
 2334:     int idx = ata_find_attr_index(id, *data);
 2335:     if (idx < 0)
 2336:       continue;
 2337:     uint64_t raw = ata_get_attr_raw_value(data->vendor_attributes[idx], defs);
 2338:     unsigned temp;
 2339:     // ignore possible min/max values in high words
 2340:     if (format == RAWFMT_TEMP10X) // -v N,temp10x
 2341:       temp = ((unsigned short)raw + 5) / 10;
 2342:     else
 2343:       temp = (unsigned char)raw;
 2344:     if (!(0 < temp && temp < 128))
 2345:       continue;
 2346:     return temp;
 2347:   }
 2348:   // No valid attribute found
 2349:   return 0;
 2350: }
 2351: 
 2352: 
 2353: // Read SCT Status
 2354: int ataReadSCTStatus(ata_device * device, ata_sct_status_response * sts)
 2355: {
 2356:   // read SCT status via SMART log 0xe0
 2357:   memset(sts, 0, sizeof(*sts));
 2358:   if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){
 2359:     pout("Read SCT Status failed: %s\n", device->get_errmsg());
 2360:     return -1;
 2361:   }
 2362: 
 2363:   // swap endian order if needed
 2364:   if (isbigendian()){
 2365:     swapx(&sts->format_version);
 2366:     swapx(&sts->sct_version);
 2367:     swapx(&sts->sct_spec);
 2368:     swapx(&sts->ext_status_code);
 2369:     swapx(&sts->action_code);
 2370:     swapx(&sts->function_code);
 2371:     swapx(&sts->over_limit_count);
 2372:     swapx(&sts->under_limit_count);
 2373:   }
 2374: 
 2375:   // Check format version
 2376:   if (!(sts->format_version == 2 || sts->format_version == 3)) {
 2377:     pout("Unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version);
 2378:     return -1;
 2379:   }
 2380:   return 0;
 2381: }
 2382: 
 2383: // Read SCT Temperature History Table and Status
 2384: int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table * tmh,
 2385:                        ata_sct_status_response * sts)
 2386: {
 2387:   // Check initial status
 2388:   if (ataReadSCTStatus(device, sts))
 2389:     return -1;
 2390: 
 2391:   // Do nothing if other SCT command is executing
 2392:   if (sts->ext_status_code == 0xffff) {
 2393:     pout("Another SCT command is executing, abort Read Data Table\n"
 2394:          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
 2395:       sts->ext_status_code, sts->action_code, sts->function_code);
 2396:     return -1;
 2397:   }
 2398: 
 2399:   ata_sct_data_table_command cmd; memset(&cmd, 0, sizeof(cmd));
 2400:   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
 2401:   cmd.action_code   = 5; // Data table command
 2402:   cmd.function_code = 1; // Read table
 2403:   cmd.table_id      = 2; // Temperature History Table
 2404: 
 2405:   // swap endian order if needed
 2406:   if (isbigendian()) {
 2407:     swapx(&cmd.action_code);
 2408:     swapx(&cmd.function_code);
 2409:     swapx(&cmd.table_id);
 2410:   }
 2411: 
 2412:   // write command via SMART log page 0xe0
 2413:   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
 2414:     pout("Write SCT Data Table failed: %s\n", device->get_errmsg());
 2415:     return -1;
 2416:   }
 2417: 
 2418:   // read SCT data via SMART log page 0xe1
 2419:   memset(tmh, 0, sizeof(*tmh));
 2420:   if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){
 2421:     pout("Read SCT Data Table failed: %s\n", device->get_errmsg());
 2422:     return -1;
 2423:   }
 2424: 
 2425:   // re-read and check SCT status
 2426:   if (ataReadSCTStatus(device, sts))
 2427:     return -1;
 2428: 
 2429:   if (!(sts->ext_status_code == 0 && sts->action_code == 5 && sts->function_code == 1)) {
 2430:     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
 2431:       sts->ext_status_code, sts->action_code, sts->function_code);
 2432:     return -1;
 2433:   }
 2434: 
 2435:   // swap endian order if needed
 2436:   if (isbigendian()){
 2437:     swapx(&tmh->format_version);
 2438:     swapx(&tmh->sampling_period);
 2439:     swapx(&tmh->interval);
 2440:     swapx(&tmh->cb_index);
 2441:     swapx(&tmh->cb_size);
 2442:   }
 2443:   return 0;
 2444: }
 2445: 
 2446: // Set SCT Temperature Logging Interval
 2447: int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent)
 2448: {
 2449:   // Check initial status
 2450:   ata_sct_status_response sts;
 2451:   if (ataReadSCTStatus(device, &sts))
 2452:     return -1;
 2453: 
 2454:   // Do nothing if other SCT command is executing
 2455:   if (sts.ext_status_code == 0xffff) {
 2456:     pout("Another SCT command is executing, abort Feature Control\n"
 2457:          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
 2458:       sts.ext_status_code, sts.action_code, sts.function_code);
 2459:     return -1;
 2460:   }
 2461: 
 2462:   ata_sct_feature_control_command cmd; memset(&cmd, 0, sizeof(cmd));
 2463:   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
 2464:   cmd.action_code   = 4; // Feature Control command
 2465:   cmd.function_code = 1; // Set state
 2466:   cmd.feature_code  = 3; // Temperature logging interval
 2467:   cmd.state         = interval;
 2468:   cmd.option_flags  = (persistent ? 0x01 : 0x00);
 2469: 
 2470:   // swap endian order if needed
 2471:   if (isbigendian()) {
 2472:     swapx(&cmd.action_code);
 2473:     swapx(&cmd.function_code);
 2474:     swapx(&cmd.feature_code);
 2475:     swapx(&cmd.state);
 2476:     swapx(&cmd.option_flags);
 2477:   }
 2478: 
 2479:   // write command via SMART log page 0xe0
 2480:   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
 2481:     pout("Write SCT Feature Control Command failed: %s\n", device->get_errmsg());
 2482:     return -1;
 2483:   }
 2484: 
 2485:   // re-read and check SCT status
 2486:   if (ataReadSCTStatus(device, &sts))
 2487:     return -1;
 2488: 
 2489:   if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == 1)) {
 2490:     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
 2491:       sts.ext_status_code, sts.action_code, sts.function_code);
 2492:     return -1;
 2493:   }
 2494:   return 0;
 2495: }
 2496: 
 2497: // Get/Set SCT Error Recovery Control
 2498: static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned type,
 2499:                                                 bool set, unsigned short & time_limit)
 2500: {
 2501:   // Check initial status
 2502:   ata_sct_status_response sts;
 2503:   if (ataReadSCTStatus(device, &sts))
 2504:     return -1;
 2505: 
 2506:   // Do nothing if other SCT command is executing
 2507:   if (sts.ext_status_code == 0xffff) {
 2508:     pout("Another SCT command is executing, abort Error Recovery Control\n"
 2509:          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
 2510:       sts.ext_status_code, sts.action_code, sts.function_code);
 2511:     return -1;
 2512:   }
 2513: 
 2514:   ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd));
 2515:   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
 2516:   cmd.action_code    = 3; // Error Recovery Control command
 2517:   cmd.function_code  = (set ? 1 : 2); // 1=Set timer, 2=Get timer
 2518:   cmd.selection_code = type; // 1=Read timer, 2=Write timer
 2519:   if (set)
 2520:     cmd.time_limit   = time_limit;
 2521: 
 2522:   // swap endian order if needed
 2523:   if (isbigendian()) {
 2524:     swapx(&cmd.action_code);
 2525:     swapx(&cmd.function_code);
 2526:     swapx(&cmd.selection_code);
 2527:     swapx(&cmd.time_limit);
 2528:   }
 2529: 
 2530:   // write command via SMART log page 0xe0
 2531:   // TODO: Debug output
 2532:   ata_cmd_in in;
 2533:   in.in_regs.command = ATA_SMART_CMD;
 2534:   in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
 2535:   in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
 2536:   in.in_regs.lba_low = 0xe0;
 2537:   in.set_data_out(&cmd, 1);
 2538: 
 2539:   if (!set)
 2540:     // Time limit returned in ATA registers
 2541:     in.out_needed.sector_count = in.out_needed.lba_low = true;
 2542: 
 2543:   ata_cmd_out out;
 2544:   if (!device->ata_pass_through(in, out)) {
 2545:     pout("Write SCT (%cet) Error Recovery Control Command failed: %s\n",
 2546:       (!set ? 'G' : 'S'), device->get_errmsg());
 2547:     return -1;
 2548:   }
 2549: 
 2550:   // re-read and check SCT status
 2551:   if (ataReadSCTStatus(device, &sts))
 2552:     return -1;
 2553: 
 2554:   if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) {
 2555:     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
 2556:       sts.ext_status_code, sts.action_code, sts.function_code);
 2557:     return -1;
 2558:   }
 2559: 
 2560:   if (!set) {
 2561:     // Check whether registers are properly returned by ioctl()
 2562:     if (!(out.out_regs.sector_count.is_set() && out.out_regs.lba_low.is_set())) {
 2563:       // TODO: Output register support should be checked within each ata_pass_through()
 2564:       // implementation before command is issued.
 2565:       pout("SMART WRITE LOG does not return COUNT and LBA_LOW register\n");
 2566:       return -1;
 2567:     }
 2568:     if (   out.out_regs.sector_count == in.in_regs.sector_count
 2569:         && out.out_regs.lba_low      == in.in_regs.lba_low     ) {
 2570:       // 0xe001 (5734.5s) - this is most likely a broken ATA pass-through implementation
 2571:       pout("SMART WRITE LOG returns COUNT and LBA_LOW register unchanged\n");
 2572:       return -1;
 2573:     }
 2574: 
 2575:     // Return value to caller
 2576:     time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
 2577:   }
 2578: 
 2579:   return 0;
 2580: }
 2581: 
 2582: // Get SCT Error Recovery Control
 2583: int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit)
 2584: {
 2585:   return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit);
 2586: }
 2587: 
 2588: // Set SCT Error Recovery Control
 2589: int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit)
 2590: {
 2591:   return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit);
 2592: }
 2593: 
 2594: 
 2595: // Print one self-test log entry.
 2596: // Returns:
 2597: // -1: self-test failed
 2598: //  1: extended self-test completed without error
 2599: //  0: otherwise
 2600: int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
 2601:                                unsigned char test_status,
 2602:                                unsigned short timestamp,
 2603:                                uint64_t failing_lba,
 2604:                                bool print_error_only, bool & print_header)
 2605: {
 2606:   // Check status and type for return value
 2607:   int retval = 0;
 2608:   switch (test_status >> 4) {
 2609:     case 0x0:
 2610:       if ((test_type & 0x0f) == 0x02)
 2611:         retval = 1; // extended self-test completed without error
 2612:       break;
 2613:     case 0x3: case 0x4:
 2614:     case 0x5: case 0x6:
 2615:     case 0x7: case 0x8:
 2616:       retval = -1; // self-test failed
 2617:       break;
 2618:   }
 2619: 
 2620:   if (retval >= 0 && print_error_only)
 2621:     return retval;
 2622: 
 2623:   std::string msgtest;
 2624:   switch (test_type) {
 2625:     case 0x00: msgtest = "Offline";            break;
 2626:     case 0x01: msgtest = "Short offline";      break;
 2627:     case 0x02: msgtest = "Extended offline";   break;
 2628:     case 0x03: msgtest = "Conveyance offline"; break;
 2629:     case 0x04: msgtest = "Selective offline";  break;
 2630:     case 0x7f: msgtest = "Abort offline test"; break;
 2631:     case 0x81: msgtest = "Short captive";      break;
 2632:     case 0x82: msgtest = "Extended captive";   break;
 2633:     case 0x83: msgtest = "Conveyance captive"; break;
 2634:     case 0x84: msgtest = "Selective captive";  break;
 2635:     default:
 2636:       if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
 2637:         msgtest = strprintf("Vendor (0x%02x)", test_type);
 2638:       else
 2639:         msgtest = strprintf("Reserved (0x%02x)", test_type);
 2640:   }
 2641: 
 2642:   std::string msgstat;
 2643:   switch (test_status >> 4) {
 2644:     case 0x0: msgstat = "Completed without error";       break;
 2645:     case 0x1: msgstat = "Aborted by host";               break;
 2646:     case 0x2: msgstat = "Interrupted (host reset)";      break;
 2647:     case 0x3: msgstat = "Fatal or unknown error";        break;
 2648:     case 0x4: msgstat = "Completed: unknown failure";    break;
 2649:     case 0x5: msgstat = "Completed: electrical failure"; break;
 2650:     case 0x6: msgstat = "Completed: servo/seek failure"; break;
 2651:     case 0x7: msgstat = "Completed: read failure";       break;
 2652:     case 0x8: msgstat = "Completed: handling damage??";  break;
 2653:     case 0xf: msgstat = "Self-test routine in progress"; break;
 2654:     default:  msgstat = strprintf("Unknown status (0x%x)", test_status >> 4);
 2655:   }
 2656: 
 2657:   // Print header once
 2658:   if (print_header) {
 2659:     print_header = false;
 2660:     pout("Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
 2661:   }
 2662: 
 2663:   char msglba[32];
 2664:   if (retval < 0 && failing_lba < 0xffffffffffffULL)
 2665:     snprintf(msglba, sizeof(msglba), "%"PRIu64, failing_lba);
 2666:   else {
 2667:     msglba[0] = '-'; msglba[1] = 0;
 2668:   }
 2669: 
 2670:   pout("#%2u  %-19s %-29s %1d0%%  %8u         %s\n", testnum,
 2671:        msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
 2672: 
 2673:   return retval;
 2674: }
 2675: 
 2676: // Print Smart self-test log, used by smartctl and smartd.
 2677: // return value is:
 2678: // bottom 8 bits: number of entries found where self-test showed an error
 2679: // remaining bits: if nonzero, power on hours of last self-test where error was found
 2680: int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
 2681:                              firmwarebug_defs firmwarebugs)
 2682: {
 2683:   if (allentries)
 2684:     pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber);
 2685:   if (data->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG))
 2686:     pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
 2687:   if (data->mostrecenttest==0){
 2688:     if (allentries)
 2689:       pout("No self-tests have been logged.  [To run self-tests, use: smartctl -t]\n\n");
 2690:     return 0;
 2691:   }
 2692: 
 2693:   bool noheaderprinted = true;
 2694:   int errcnt = 0, hours = 0, igncnt = 0;
 2695:   int testno = 0, ext_ok_testno = -1;
 2696: 
 2697:   // print log
 2698:   for (int i = 20; i >= 0; i--) {
 2699:     // log is a circular buffer
 2700:     int j = (i+data->mostrecenttest)%21;
 2701:     const ata_smart_selftestlog_struct * log = data->selftest_struct+j;
 2702: 
 2703:     if (nonempty(log, sizeof(*log))) {
 2704:       // count entry based on non-empty structures -- needed for
 2705:       // Seagate only -- other vendors don't have blank entries 'in
 2706:       // the middle'
 2707:       testno++;
 2708: 
 2709:       // T13/1321D revision 1c: (Data structure Rev #1)
 2710: 
 2711:       //The failing LBA shall be the LBA of the uncorrectable sector
 2712:       //that caused the test to fail. If the device encountered more
 2713:       //than one uncorrectable sector during the test, this field
 2714:       //shall indicate the LBA of the first uncorrectable sector
 2715:       //encountered. If the test passed or the test failed for some
 2716:       //reason other than an uncorrectable sector, the value of this
 2717:       //field is undefined.
 2718: 
 2719:       // This is true in ALL ATA-5 specs
 2720:       uint64_t lba48 = (log->lbafirstfailure < 0xffffffff ? log->lbafirstfailure : 0xffffffffffffULL);
 2721: 
 2722:       // Print entry
 2723:       int state = ataPrintSmartSelfTestEntry(testno,
 2724:         log->selftestnumber, log->selfteststatus,
 2725:         log->timestamp, lba48, !allentries, noheaderprinted);
 2726: 
 2727:       if (state < 0) {
 2728:         // Self-test showed an error
 2729:         if (ext_ok_testno < 0) {
 2730:           errcnt++;
 2731: 
 2732:           // keep track of time of most recent error
 2733:           if (!hours)
 2734:             hours = log->timestamp;
 2735:         }
 2736:         else
 2737:           // Newer successful extended self-test exits
 2738:           igncnt++;
 2739:       }
 2740:       else if (state > 0 && ext_ok_testno < 0) {
 2741:         // Latest successful extended self-test
 2742:         ext_ok_testno = testno;
 2743:       }
 2744:     }
 2745:   }
 2746: 
 2747:   if (igncnt)
 2748:     pout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
 2749:       igncnt, igncnt+errcnt, ext_ok_testno);
 2750: 
 2751:   if (!allentries && !noheaderprinted)
 2752:     pout("\n");
 2753: 
 2754:   return ((hours << 8) | errcnt);
 2755: }
 2756: 
 2757: 
 2758: /////////////////////////////////////////////////////////////////////////////
 2759: // Pseudo-device to parse "smartctl -r ataioctl,2 ..." output and simulate
 2760: // an ATA device with same behaviour
 2761: 
 2762: namespace {
 2763: 
 2764: class parsed_ata_device
 2765: : public /*implements*/ ata_device_with_command_set
 2766: {
 2767: public:
 2768:   parsed_ata_device(smart_interface * intf, const char * dev_name);
 2769: 
 2770:   virtual ~parsed_ata_device() throw();
 2771: 
 2772:   virtual bool is_open() const;
 2773: 
 2774:   virtual bool open();
 2775: 
 2776:   virtual bool close();
 2777: 
 2778:   virtual bool ata_identify_is_cached() const;
 2779: 
 2780: protected:
 2781:   virtual int ata_command_interface(smart_command_set command, int select, char * data);
 2782: 
 2783: private:
 2784:   // Table of parsed commands, return value, data
 2785:   struct parsed_ata_command
 2786:   {
 2787:     smart_command_set command;
 2788:     int select;
 2789:     int retval, errval;
 2790:     char * data;
 2791:   };
 2792: 
 2793:   enum { max_num_commands = 32 };
 2794:   parsed_ata_command m_command_table[max_num_commands];
 2795: 
 2796:   int m_num_commands;
 2797:   int m_next_replay_command;
 2798:   bool m_replay_out_of_sync;
 2799:   bool m_ata_identify_is_cached;
 2800: };
 2801: 
 2802: static const char * nextline(const char * s, int & lineno)
 2803: {
 2804:   for (s += strcspn(s, "\r\n"); *s == '\r' || *s == '\n'; s++) {
 2805:     if (*s == '\r' && s[1] == '\n')
 2806:       s++;
 2807:     lineno++;
 2808:   }
 2809:   return s;
 2810: }
 2811: 
 2812: static int name2command(const char * s)
 2813: {
 2814:   for (int i = 0; i < (int)(sizeof(commandstrings)/sizeof(commandstrings[0])); i++) {
 2815:     if (!strcmp(s, commandstrings[i]))
 2816:       return i;
 2817:   }
 2818:   return -1;
 2819: }
 2820: 
 2821: static bool matchcpy(char * dest, size_t size, const char * src, const regmatch_t & srcmatch)
 2822: {
 2823:   if (srcmatch.rm_so < 0)
 2824:     return false;
 2825:   size_t n = srcmatch.rm_eo - srcmatch.rm_so;
 2826:   if (n >= size)
 2827:     n = size-1;
 2828:   memcpy(dest, src + srcmatch.rm_so, n);
 2829:   dest[n] = 0;
 2830:   return true;
 2831: }
 2832: 
 2833: static inline int matchtoi(const char * src, const regmatch_t & srcmatch, int defval)
 2834: {
 2835:   if (srcmatch.rm_so < 0)
 2836:     return defval;
 2837:   return atoi(src + srcmatch.rm_so);
 2838: }
 2839: 
 2840: parsed_ata_device::parsed_ata_device(smart_interface * intf, const char * dev_name)
 2841: : smart_device(intf, dev_name, "ata", ""),
 2842:   m_num_commands(0),
 2843:   m_next_replay_command(0),
 2844:   m_replay_out_of_sync(false),
 2845:   m_ata_identify_is_cached(false)
 2846: {
 2847:   memset(m_command_table, 0, sizeof(m_command_table));
 2848: }
 2849: 
 2850: parsed_ata_device::~parsed_ata_device() throw()
 2851: {
 2852:   close();
 2853: }
 2854: 
 2855: bool parsed_ata_device::is_open() const
 2856: {
 2857:   return (m_num_commands > 0);
 2858: }
 2859: 
 2860: // Parse stdin and build command table
 2861: bool parsed_ata_device::open()
 2862: {
 2863:   const char * pathname = get_dev_name();
 2864:   if (strcmp(pathname, "-"))
 2865:     return set_err(EINVAL);
 2866:   pathname = "<stdin>";
 2867:   // Fill buffer
 2868:   char buffer[64*1024];
 2869:   int size = 0;
 2870:   while (size < (int)sizeof(buffer)) {
 2871:     int nr = fread(buffer, 1, sizeof(buffer), stdin);
 2872:     if (nr <= 0)
 2873:       break;
 2874:     size += nr;
 2875:   }
 2876:   if (size <= 0)
 2877:     return set_err(ENOENT, "%s: Unexpected EOF", pathname);
 2878:   if (size >= (int)sizeof(buffer))
 2879:     return set_err(EIO, "%s: Buffer overflow", pathname);
 2880:   buffer[size] = 0;
 2881: 
 2882:   // Regex to match output from "-r ataioctl,2"
 2883:   static const char pattern[] = "^"
 2884:   "(" // (1
 2885:     "REPORT-IOCTL: DeviceF?D?=[^ ]+ Command=([A-Z ]*[A-Z])" // (2)
 2886:     "(" // (3
 2887:       "( InputParameter=([0-9]+))?" // (4 (5))
 2888:     "|"
 2889:       "( returned (-?[0-9]+)( errno=([0-9]+)[^\r\n]*)?)" // (6 (7) (8 (9)))
 2890:     ")" // )
 2891:     "[\r\n]" // EOL match necessary to match optional parts above
 2892:   "|"
 2893:     "===== \\[([A-Z ]*[A-Z])\\] DATA START " // (10)
 2894:   "|"
 2895:     "    *(En|Dis)abled status cached by OS, " // (11)
 2896:   ")"; // )
 2897: 
 2898:   // Compile regex
 2899:   const regular_expression regex(pattern, REG_EXTENDED);
 2900: 
 2901:   // Parse buffer
 2902:   const char * errmsg = 0;
 2903:   int i = -1, state = 0, lineno = 1;
 2904:   for (const char * line = buffer; *line; line = nextline(line, lineno)) {
 2905:     // Match line
 2906:     if (!(line[0] == 'R' || line[0] == '=' || line[0] == ' '))
 2907:       continue;
 2908:     const int nmatch = 1+11;
 2909:     regmatch_t match[nmatch];
 2910:     if (!regex.execute(line, nmatch, match))
 2911:       continue;
 2912: 
 2913:     char cmdname[40];
 2914:     if (matchcpy(cmdname, sizeof(cmdname), line, match[2])) { // "REPORT-IOCTL:... Command=%s ..."
 2915:       int nc = name2command(cmdname);
 2916:       if (nc < 0) {
 2917:         errmsg = "Unknown ATA command name"; break;
 2918:       }
 2919:       if (match[7].rm_so < 0) { // "returned %d"
 2920:         // Start of command
 2921:         if (!(state == 0 || state == 2)) {
 2922:           errmsg = "Missing REPORT-IOCTL result"; break;
 2923:         }
 2924:         if (++i >= max_num_commands) {
 2925:           errmsg = "Too many ATA commands"; break;
 2926:         }
 2927:         m_command_table[i].command = (smart_command_set)nc;
 2928:         m_command_table[i].select = matchtoi(line, match[5], 0); // "InputParameter=%d"
 2929:         state = 1;
 2930:       }
 2931:       else {
 2932:         // End of command
 2933:         if (!(state == 1 && (int)m_command_table[i].command == nc)) {
 2934:           errmsg = "Missing REPORT-IOCTL start"; break;
 2935:         }
 2936:         m_command_table[i].retval = matchtoi(line, match[7], -1); // "returned %d"
 2937:         m_command_table[i].errval = matchtoi(line, match[9], 0); // "errno=%d"
 2938:         state = 2;
 2939:       }
 2940:     }
 2941:     else if (matchcpy(cmdname, sizeof(cmdname), line, match[10])) { // "===== [%s] DATA START "
 2942:       // Start of sector hexdump
 2943:       int nc = name2command(cmdname);
 2944:       if (!(state == (nc == WRITE_LOG ? 1 : 2) && (int)m_command_table[i].command == nc)) {
 2945:           errmsg = "Unexpected DATA START"; break;
 2946:       }
 2947:       line = nextline(line, lineno);
 2948:       char * data = (char *)malloc(512);
 2949:       unsigned j;
 2950:       for (j = 0; j < 32; j++) {
 2951:         unsigned b[16];
 2952:         unsigned u1, u2; int n1 = -1;
 2953:         if (!(sscanf(line, "%3u-%3u: "
 2954:                         "%2x %2x %2x %2x %2x %2x %2x %2x "
 2955:                         "%2x %2x %2x %2x %2x %2x %2x %2x%n",
 2956:                      &u1, &u2,
 2957:                      b+ 0, b+ 1, b+ 2, b+ 3, b+ 4, b+ 5, b+ 6, b+ 7,
 2958:                      b+ 8, b+ 9, b+10, b+11, b+12, b+13, b+14, b+15, &n1) == 18
 2959:               && n1 >= 56 && u1 == j*16 && u2 == j*16+15))
 2960:           break;
 2961:         for (unsigned k = 0; k < 16; k++)
 2962:           data[j*16+k] = b[k];
 2963:         line = nextline(line, lineno);
 2964:       }
 2965:       if (j < 32) {
 2966:         free(data);
 2967:         errmsg = "Incomplete sector hex dump"; break;
 2968:       }
 2969:       m_command_table[i].data = data;
 2970:       if (nc != WRITE_LOG)
 2971:         state = 0;
 2972:     }
 2973:     else if (match[11].rm_so > 0) { // "(En|Dis)abled status cached by OS"
 2974:       m_ata_identify_is_cached = true;
 2975:     }
 2976:   }
 2977: 
 2978:   if (!(state == 0 || state == 2))
 2979:     errmsg = "Missing REPORT-IOCTL result";
 2980: 
 2981:   if (!errmsg && i < 0)
 2982:     errmsg = "No information found";
 2983: 
 2984:   m_num_commands = i+1;
 2985:   m_next_replay_command = 0;
 2986:   m_replay_out_of_sync = false;
 2987: 
 2988:   if (errmsg) {
 2989:     close();
 2990:     return set_err(EIO, "%s(%d): Syntax error: %s", pathname, lineno, errmsg);
 2991:   }
 2992:   return true;
 2993: }
 2994: 
 2995: // Report warnings and free command table 
 2996: bool parsed_ata_device::close()
 2997: {
 2998:   if (m_replay_out_of_sync)
 2999:       pout("REPLAY-IOCTL: Warning: commands replayed out of sync\n");
 3000:   else if (m_next_replay_command != 0)
 3001:       pout("REPLAY-IOCTL: Warning: %d command(s) not replayed\n", m_num_commands-m_next_replay_command);
 3002: 
 3003:   for (int i = 0; i < m_num_commands; i++) {
 3004:     if (m_command_table[i].data) {
 3005:       free(m_command_table[i].data); m_command_table[i].data = 0;
 3006:     }
 3007:   }
 3008:   m_num_commands = 0;
 3009:   m_next_replay_command = 0;
 3010:   m_replay_out_of_sync = false;
 3011:   return true;
 3012: }
 3013: 
 3014: 
 3015: bool parsed_ata_device::ata_identify_is_cached() const
 3016: {
 3017:   return m_ata_identify_is_cached;
 3018: }
 3019: 
 3020: 
 3021: // Simulate ATA command from command table
 3022: int parsed_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
 3023: {
 3024:   // Find command, try round-robin if out of sync
 3025:   int i = m_next_replay_command;
 3026:   for (int j = 0; ; j++) {
 3027:     if (j >= m_num_commands) {
 3028:       pout("REPLAY-IOCTL: Warning: Command not found\n");
 3029:       errno = ENOSYS;
 3030:       return -1;
 3031:     }
 3032:     if (m_command_table[i].command == command && m_command_table[i].select == select)
 3033:       break;
 3034:     if (!m_replay_out_of_sync) {
 3035:       m_replay_out_of_sync = true;
 3036:       pout("REPLAY-IOCTL: Warning: Command #%d is out of sync\n", i+1);
 3037:     }
 3038:     if (++i >= m_num_commands)
 3039:       i = 0;
 3040:   }
 3041:   m_next_replay_command = i;
 3042:   if (++m_next_replay_command >= m_num_commands)
 3043:     m_next_replay_command = 0;
 3044: 
 3045:   // Return command data
 3046:   switch (command) {
 3047:     case IDENTIFY:
 3048:     case PIDENTIFY:
 3049:     case READ_VALUES:
 3050:     case READ_THRESHOLDS:
 3051:     case READ_LOG:
 3052:       if (m_command_table[i].data)
 3053:         memcpy(data, m_command_table[i].data, 512);
 3054:       break;
 3055:     case WRITE_LOG:
 3056:       if (!(m_command_table[i].data && !memcmp(data, m_command_table[i].data, 512)))
 3057:         pout("REPLAY-IOCTL: Warning: WRITE LOG data does not match\n");
 3058:       break;
 3059:     case CHECK_POWER_MODE:
 3060:       data[0] = (char)0xff;
 3061:     default:
 3062:       break;
 3063:   }
 3064: 
 3065:   if (m_command_table[i].errval)
 3066:     errno = m_command_table[i].errval;
 3067:   return m_command_table[i].retval;
 3068: }
 3069: 
 3070: } // namespace
 3071: 
 3072: ata_device * get_parsed_ata_device(smart_interface * intf, const char * dev_name)
 3073: {
 3074:   return new parsed_ata_device(intf, dev_name);
 3075: }

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