File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / atacmds.cpp
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:32:16 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

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

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