File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / atacmds.cpp
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:36:45 2012 UTC (11 years, 10 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v5_43, HEAD
smartmontools

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

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