smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
atacmds.cpp
Go to the documentation of this file.
00001 /*
00002  * atacmds.cpp
00003  * 
00004  * Home page of code is: http://smartmontools.sourceforge.net
00005  *
00006  * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
00007  * Copyright (C) 2008-14 Christian Franke <smartmontools-support@lists.sourceforge.net>
00008  * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
00009  * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2, or (at your option)
00014  * any later version.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
00018  *
00019  * This code was originally developed as a Senior Thesis by Michael Cornwell
00020  * at the Concurrent Systems Laboratory (now part of the Storage Systems
00021  * Research Center), Jack Baskin School of Engineering, University of
00022  * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
00023  * 
00024  */
00025 
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <errno.h>
00029 #include <stdlib.h>
00030 #include <ctype.h>
00031 
00032 #include "config.h"
00033 #include "int64.h"
00034 #include "atacmds.h"
00035 #include "utility.h"
00036 #include "dev_ata_cmd_set.h" // for parsed_ata_device
00037 
00038 const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 3881 2014-03-05 17:49:47Z chrfranke $"
00039                                  ATACMDS_H_CVSID;
00040 
00041 // Print ATA debug messages?
00042 unsigned char ata_debugmode = 0;
00043 
00044 // Suppress serial number?
00045 // (also used in scsiprint.cpp)
00046 bool dont_print_serial_number = false;
00047 
00048 
00049 #define SMART_CYL_LOW  0x4F
00050 #define SMART_CYL_HI   0xC2
00051 
00052 // SMART RETURN STATUS yields SMART_CYL_HI,SMART_CYL_LOW to indicate drive
00053 // is healthy and SRET_STATUS_HI_EXCEEDED,SRET_STATUS_MID_EXCEEDED to
00054 // indicate that a threshhold exceeded condition has been detected.
00055 // Those values (byte pairs) are placed in ATA register "LBA 23:8".
00056 #define SRET_STATUS_HI_EXCEEDED 0x2C
00057 #define SRET_STATUS_MID_EXCEEDED 0xF4
00058 
00059 
00060 // Get ID and increase flag of current pending or offline
00061 // uncorrectable attribute.
00062 unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs,
00063                               bool & increase)
00064 {
00065   unsigned char id = (!offline ? 197 : 198);
00066   const ata_vendor_attr_defs::entry & def = defs[id];
00067   if (def.flags & ATTRFLAG_INCREASING)
00068     increase = true; // '-v 19[78],increasing' option
00069   else if (def.name.empty() || (id == 198 && def.name == "Offline_Scan_UNC_SectCt"))
00070     increase = false; // no or '-v 198,offlinescanuncsectorct' option
00071   else
00072     id = 0; // other '-v 19[78],...' option
00073   return id;
00074 }
00075 
00076 #if 0 // TODO: never used
00077 // This are the meanings of the Self-test failure checkpoint byte.
00078 // This is in the self-test log at offset 4 bytes into the self-test
00079 // descriptor and in the SMART READ DATA structure at byte offset
00080 // 371. These codes are not well documented.  The meanings returned by
00081 // this routine are used (at least) by Maxtor and IBM. Returns NULL if
00082 // not recognized.  Currently the maximum length is 15 bytes.
00083 const char *SelfTestFailureCodeName(unsigned char which){
00084   
00085   switch (which) {
00086   case 0:
00087     return "Write_Test";
00088   case 1:
00089     return "Servo_Basic";
00090   case 2:
00091     return "Servo_Random";
00092   case 3:
00093     return "G-list_Scan";
00094   case 4:
00095     return "Handling_Damage";
00096   case 5:
00097     return "Read_Scan";
00098   default:
00099     return NULL;
00100   }
00101 }
00102 #endif
00103 
00104 
00105 // Table of raw print format names
00106 struct format_name_entry
00107 {
00108   const char * name;
00109   ata_attr_raw_format format;
00110 };
00111 
00112 const format_name_entry format_names[] = {
00113   {"raw8"           , RAWFMT_RAW8},
00114   {"raw16"          , RAWFMT_RAW16},
00115   {"raw48"          , RAWFMT_RAW48},
00116   {"hex48"          , RAWFMT_HEX48},
00117   {"raw56"          , RAWFMT_RAW56},
00118   {"hex56"          , RAWFMT_HEX56},
00119   {"raw64"          , RAWFMT_RAW64},
00120   {"hex64"          , RAWFMT_HEX64},
00121   {"raw16(raw16)"   , RAWFMT_RAW16_OPT_RAW16},
00122   {"raw16(avg16)"   , RAWFMT_RAW16_OPT_AVG16},
00123   {"raw24(raw8)"    , RAWFMT_RAW24_OPT_RAW8},
00124   {"raw24/raw24"    , RAWFMT_RAW24_DIV_RAW24},
00125   {"raw24/raw32"    , RAWFMT_RAW24_DIV_RAW32},
00126   {"sec2hour"       , RAWFMT_SEC2HOUR},
00127   {"min2hour"       , RAWFMT_MIN2HOUR},
00128   {"halfmin2hour"   , RAWFMT_HALFMIN2HOUR},
00129   {"msec24hour32"   , RAWFMT_MSEC24_HOUR32},
00130   {"tempminmax"     , RAWFMT_TEMPMINMAX},
00131   {"temp10x"        , RAWFMT_TEMP10X},
00132 };
00133 
00134 const unsigned num_format_names = sizeof(format_names)/sizeof(format_names[0]);
00135 
00136 // Table to map old to new '-v' option arguments
00137 const char * map_old_vendor_opts[][2] = {
00138   {  "9,halfminutes"              , "9,halfmin2hour,Power_On_Half_Minutes"},
00139   {  "9,minutes"                  , "9,min2hour,Power_On_Minutes"},
00140   {  "9,seconds"                  , "9,sec2hour,Power_On_Seconds"},
00141   {  "9,temp"                     , "9,tempminmax,Temperature_Celsius"},
00142   {"192,emergencyretractcyclect"  , "192,raw48,Emerg_Retract_Cycle_Ct"},
00143   {"193,loadunload"               , "193,raw24/raw24"},
00144   {"194,10xCelsius"               , "194,temp10x,Temperature_Celsius_x10"},
00145   {"194,unknown"                  , "194,raw48,Unknown_Attribute"},
00146   {"197,increasing"               , "197,raw48+,Total_Pending_Sectors"}, // '+' sets flag
00147   {"198,offlinescanuncsectorct"   , "198,raw48,Offline_Scan_UNC_SectCt"}, // see also get_unc_attr_id() above
00148   {"198,increasing"               , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag
00149   {"200,writeerrorcount"          , "200,raw48,Write_Error_Count"},
00150   {"201,detectedtacount"          , "201,raw48,Detected_TA_Count"},
00151   {"220,temp"                     , "220,tempminmax,Temperature_Celsius"},
00152 };
00153 
00154 const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]);
00155 
00156 // Parse vendor attribute display def (-v option).
00157 // Return false on error.
00158 bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
00159                          ata_vendor_def_prior priority)
00160 {
00161   // Map old -> new options
00162   unsigned i;
00163   for (i = 0; i < num_old_vendor_opts; i++) {
00164     if (!strcmp(opt, map_old_vendor_opts[i][0])) {
00165       opt = map_old_vendor_opts[i][1];
00166       break;
00167     }
00168   }
00169 
00170   // Parse option
00171   int len = strlen(opt);
00172   int id = 0, n1 = -1, n2 = -1;
00173   char fmtname[32+1], attrname[32+1];
00174   if (opt[0] == 'N') {
00175     // "N,format"
00176     if (!(   sscanf(opt, "N,%32[^,]%n,%32[^,]%n", fmtname, &n1, attrname, &n2) >= 1
00177           && (n1 == len || n2 == len)))
00178       return false;
00179   }
00180   else {
00181     // "id,format[+][,name]"
00182     if (!(   sscanf(opt, "%d,%32[^,]%n,%32[^,]%n", &id, fmtname, &n1, attrname, &n2) >= 2
00183           && 1 <= id && id <= 255 && (n1 == len || n2 == len)))
00184       return false;
00185   }
00186   if (n1 == len)
00187     attrname[0] = 0;
00188 
00189   unsigned flags = 0;
00190   // For "-v 19[78],increasing" above
00191   if (fmtname[strlen(fmtname)-1] == '+') {
00192     fmtname[strlen(fmtname)-1] = 0;
00193     flags = ATTRFLAG_INCREASING;
00194   }
00195 
00196   // Split "format[:byteorder]"
00197   char byteorder[8+1] = "";
00198   if (strchr(fmtname, ':')) {
00199     if (!(   sscanf(fmtname, "%*[^:]%n:%8[012345rvwz]%n", &n1, byteorder, &n2) >= 1
00200           && n2 == (int)strlen(fmtname)))
00201       return false;
00202     fmtname[n1] = 0;
00203     if (strchr(byteorder, 'v'))
00204       flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
00205     if (strchr(byteorder, 'w'))
00206       flags |= ATTRFLAG_NO_WORSTVAL;
00207   }
00208 
00209   // Find format name
00210   for (i = 0; ; i++) {
00211     if (i >= num_format_names)
00212       return false; // Not found
00213     if (!strcmp(fmtname, format_names[i].name))
00214       break;
00215   }
00216   ata_attr_raw_format format = format_names[i].format;
00217 
00218   // 64-bit formats use the normalized and worst value bytes.
00219   if (!*byteorder && (format == RAWFMT_RAW64 || format == RAWFMT_HEX64))
00220     flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
00221 
00222   if (!id) {
00223     // "N,format" -> set format for all entries
00224     for (i = 0; i < MAX_ATTRIBUTE_NUM; i++) {
00225       if (defs[i].priority >= priority)
00226         continue;
00227       if (attrname[0])
00228         defs[i].name = attrname;
00229       defs[i].priority = priority;
00230       defs[i].raw_format = format;
00231       defs[i].flags = flags;
00232       snprintf(defs[i].byteorder, sizeof(defs[i].byteorder), "%s", byteorder);
00233     }
00234   }
00235   else if (defs[id].priority <= priority) {
00236     // "id,format[,name]"
00237     if (attrname[0])
00238       defs[id].name = attrname;
00239     defs[id].raw_format = format;
00240     defs[id].priority = priority;
00241     defs[id].flags = flags;
00242     snprintf(defs[id].byteorder, sizeof(defs[id].byteorder), "%s", byteorder);
00243   }
00244 
00245   return true;
00246 }
00247 
00248 
00249 // Return a multiline string containing a list of valid arguments for
00250 // parse_attribute_def().  The strings are preceeded by tabs and followed
00251 // (except for the last) by newlines.
00252 std::string create_vendor_attribute_arg_list()
00253 {
00254   std::string s;
00255   unsigned i;
00256   for (i = 0; i < num_format_names; i++)
00257     s += strprintf("%s\tN,%s[:012345rvwz][,ATTR_NAME]",
00258       (i>0 ? "\n" : ""), format_names[i].name);
00259   for (i = 0; i < num_old_vendor_opts; i++)
00260     s += strprintf("\n\t%s", map_old_vendor_opts[i][0]);
00261   return s;
00262 }
00263 
00264 
00265 // Parse firmwarebug def (-F option).
00266 // Return false on error.
00267 bool parse_firmwarebug_def(const char * opt, firmwarebug_defs & firmwarebugs)
00268 {
00269     if (!strcmp(opt, "none"))
00270       firmwarebugs.set(BUG_NONE);
00271     else if (!strcmp(opt, "nologdir"))
00272       firmwarebugs.set(BUG_NOLOGDIR);
00273     else if (!strcmp(opt, "samsung"))
00274       firmwarebugs.set(BUG_SAMSUNG);
00275     else if (!strcmp(opt, "samsung2"))
00276       firmwarebugs.set(BUG_SAMSUNG2);
00277     else if (!strcmp(opt, "samsung3"))
00278       firmwarebugs.set(BUG_SAMSUNG3);
00279     else if (!strcmp(opt, "xerrorlba"))
00280       firmwarebugs.set(BUG_XERRORLBA);
00281     else
00282       return false;
00283     return true;
00284 }
00285 
00286 // Return a string of valid argument words for parse_firmwarebug_def()
00287 const char * get_valid_firmwarebug_args()
00288 {
00289   return "none, nologdir, samsung, samsung2, samsung3, xerrorlba";
00290 }
00291 
00292 
00293 // swap two bytes.  Point to low address
00294 void swap2(char *location){
00295   char tmp=*location;
00296   *location=*(location+1);
00297   *(location+1)=tmp;
00298   return;
00299 }
00300 
00301 // swap four bytes.  Point to low address
00302 void swap4(char *location){
00303   char tmp=*location;
00304   *location=*(location+3);
00305   *(location+3)=tmp;
00306   swap2(location+1);
00307   return;
00308 }
00309 
00310 // swap eight bytes.  Points to low address
00311 void swap8(char *location){
00312   char tmp=*location;
00313   *location=*(location+7);
00314   *(location+7)=tmp;
00315   tmp=*(location+1);
00316   *(location+1)=*(location+6);
00317   *(location+6)=tmp;
00318   swap4(location+2);
00319   return;
00320 }
00321 
00322 // Invalidate serial number and WWN and adjust checksum in IDENTIFY data
00323 static void invalidate_serno(ata_identify_device * id)
00324 {
00325   unsigned char sum = 0;
00326   unsigned i;
00327   for (i = 0; i < sizeof(id->serial_no); i++) {
00328     sum += id->serial_no[i]; sum -= id->serial_no[i] = 'X';
00329   }
00330   unsigned char * b = (unsigned char *)id;
00331   for (i = 2*108; i < 2*112; i++) { // words108-111: WWN
00332     sum += b[i]; sum -= b[i] = 0x00;
00333   }
00334 
00335 #ifndef __NetBSD__
00336   bool must_swap = !!isbigendian();
00337   if (must_swap)
00338     swapx(id->words088_255+255-88);
00339 #endif
00340   if ((id->words088_255[255-88] & 0x00ff) == 0x00a5)
00341     id->words088_255[255-88] += sum << 8;
00342 #ifndef __NetBSD__
00343   if (must_swap)
00344     swapx(id->words088_255+255-88);
00345 #endif
00346 }
00347 
00348 static const char * const commandstrings[]={
00349   "SMART ENABLE",
00350   "SMART DISABLE",
00351   "SMART AUTOMATIC ATTRIBUTE SAVE",
00352   "SMART IMMEDIATE OFFLINE",
00353   "SMART AUTO OFFLINE",
00354   "SMART STATUS",
00355   "SMART STATUS CHECK",
00356   "SMART READ ATTRIBUTE VALUES",
00357   "SMART READ ATTRIBUTE THRESHOLDS",
00358   "SMART READ LOG",
00359   "IDENTIFY DEVICE",
00360   "IDENTIFY PACKET DEVICE",
00361   "CHECK POWER MODE",
00362   "SMART WRITE LOG",
00363   "WARNING (UNDEFINED COMMAND -- CONTACT DEVELOPERS AT " PACKAGE_BUGREPORT ")\n"
00364 };
00365 
00366 
00367 static const char * preg(const ata_register & r, char (& buf)[8])
00368 {
00369   if (!r.is_set())
00370     //return "n/a ";
00371     return "....";
00372   snprintf(buf, sizeof(buf), "0x%02x", r.val());
00373   return buf;
00374 }
00375 
00376 static void print_regs(const char * prefix, const ata_in_regs & r, const char * suffix = "\n")
00377 {
00378   char bufs[7][8];
00379   pout("%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix,
00380     preg(r.features, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
00381     preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
00382     preg(r.command, bufs[6]), suffix);
00383 }
00384 
00385 static void print_regs(const char * prefix, const ata_out_regs & r, const char * suffix = "\n")
00386 {
00387   char bufs[7][8];
00388   pout("%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix,
00389     preg(r.error, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
00390     preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
00391     preg(r.status, bufs[6]), suffix);
00392 }
00393 
00394 static void prettyprint(const unsigned char *p, const char *name){
00395   pout("\n===== [%s] DATA START (BASE-16) =====\n", name);
00396   for (int i=0; i<512; i+=16, p+=16)
00397 #define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.')
00398     // print complete line to avoid slow tty output and extra lines in syslog.
00399     pout("%03d-%03d: %02x %02x %02x %02x %02x %02x %02x %02x "
00400                     "%02x %02x %02x %02x %02x %02x %02x %02x"
00401                     " |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c|"
00402          "%c",
00403          i, i+16-1,
00404          p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
00405          p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15], 
00406          P( 0), P( 1), P( 2), P( 3), P( 4), P( 5), P( 6), P( 7),
00407          P( 8), P( 9), P(10), P(11), P(12), P(13), P(14), P(15),
00408          '\n');
00409 #undef P
00410   pout("===== [%s] DATA END (512 Bytes) =====\n\n", name);
00411 }
00412 
00413 // This function provides the pretty-print reporting for SMART
00414 // commands: it implements the various -r "reporting" options for ATA
00415 // ioctls.
00416 int smartcommandhandler(ata_device * device, smart_command_set command, int select, char *data){
00417   // TODO: Rework old stuff below
00418   // This conditional is true for commands that return data
00419   int getsdata=(command==PIDENTIFY || 
00420                 command==IDENTIFY || 
00421                 command==READ_LOG || 
00422                 command==READ_THRESHOLDS || 
00423                 command==READ_VALUES ||
00424                 command==CHECK_POWER_MODE);
00425 
00426   int sendsdata=(command==WRITE_LOG);
00427   
00428   // If reporting is enabled, say what the command will be before it's executed
00429   if (ata_debugmode) {
00430           // conditional is true for commands that use parameters
00431           int usesparam=(command==READ_LOG || 
00432                          command==AUTO_OFFLINE || 
00433                          command==AUTOSAVE || 
00434                          command==IMMEDIATE_OFFLINE ||
00435                          command==WRITE_LOG);
00436                   
00437     pout("\nREPORT-IOCTL: Device=%s Command=%s", device->get_dev_name(), commandstrings[command]);
00438     if (usesparam)
00439       pout(" InputParameter=%d\n", select);
00440     else
00441       pout("\n");
00442   }
00443   
00444   if ((getsdata || sendsdata) && !data){
00445     pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]);
00446     return -1;
00447   }
00448   
00449   // The reporting is cleaner, and we will find coding bugs faster, if
00450   // the commands that failed clearly return empty (zeroed) data
00451   // structures
00452   if (getsdata) {
00453     if (command==CHECK_POWER_MODE)
00454       data[0]=0;
00455     else
00456       memset(data, '\0', 512);
00457   }
00458 
00459 
00460   // if requested, pretty-print the input data structure
00461   if (ata_debugmode > 1 && sendsdata)
00462     //pout("REPORT-IOCTL: Device=%s Command=%s\n", device->get_dev_name(), commandstrings[command]);
00463     prettyprint((unsigned char *)data, commandstrings[command]);
00464 
00465   // now execute the command
00466   int retval = -1;
00467   {
00468     ata_cmd_in in;
00469     // Set common register values
00470     switch (command) {
00471       default: // SMART commands
00472         in.in_regs.command = ATA_SMART_CMD;
00473         in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
00474         break;
00475       case IDENTIFY: case PIDENTIFY: case CHECK_POWER_MODE: // Non SMART commands
00476         break;
00477     }
00478     // Set specific values
00479     switch (command) {
00480       case IDENTIFY:
00481         in.in_regs.command = ATA_IDENTIFY_DEVICE;
00482         in.set_data_in(data, 1);
00483         break;
00484       case PIDENTIFY:
00485         in.in_regs.command = ATA_IDENTIFY_PACKET_DEVICE;
00486         in.set_data_in(data, 1);
00487         break;
00488       case CHECK_POWER_MODE:
00489         in.in_regs.command = ATA_CHECK_POWER_MODE;
00490         in.out_needed.sector_count = true; // Powermode returned here
00491         break;
00492       case READ_VALUES:
00493         in.in_regs.features = ATA_SMART_READ_VALUES;
00494         in.set_data_in(data, 1);
00495         break;
00496       case READ_THRESHOLDS:
00497         in.in_regs.features = ATA_SMART_READ_THRESHOLDS;
00498         in.in_regs.lba_low = 1; // TODO: CORRECT ???
00499         in.set_data_in(data, 1);
00500         break;
00501       case READ_LOG:
00502         in.in_regs.features = ATA_SMART_READ_LOG_SECTOR;
00503         in.in_regs.lba_low = select;
00504         in.set_data_in(data, 1);
00505         break;
00506       case WRITE_LOG:
00507         in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
00508         in.in_regs.lba_low = select;
00509         in.set_data_out(data, 1);
00510         break;
00511       case ENABLE:
00512         in.in_regs.features = ATA_SMART_ENABLE;
00513         in.in_regs.lba_low = 1; // TODO: CORRECT ???
00514         break;
00515       case DISABLE:
00516         in.in_regs.features = ATA_SMART_DISABLE;
00517         in.in_regs.lba_low = 1;  // TODO: CORRECT ???
00518         break;
00519       case STATUS_CHECK:
00520         in.out_needed.lba_high = in.out_needed.lba_mid = true; // Status returned here
00521       case STATUS:
00522         in.in_regs.features = ATA_SMART_STATUS;
00523         break;
00524       case AUTO_OFFLINE:
00525         in.in_regs.features = ATA_SMART_AUTO_OFFLINE;
00526         in.in_regs.sector_count = select;  // Caution: Non-DATA command!
00527         break;
00528       case AUTOSAVE:
00529         in.in_regs.features = ATA_SMART_AUTOSAVE;
00530         in.in_regs.sector_count = select;  // Caution: Non-DATA command!
00531         break;
00532       case IMMEDIATE_OFFLINE:
00533         in.in_regs.features = ATA_SMART_IMMEDIATE_OFFLINE;
00534         in.in_regs.lba_low = select;
00535         break;
00536       default:
00537         pout("Unrecognized command %d in smartcommandhandler()\n"
00538              "Please contact " PACKAGE_BUGREPORT "\n", command);
00539         device->set_err(ENOSYS);
00540         return -1;
00541     }
00542 
00543     if (ata_debugmode)
00544       print_regs(" Input:  ", in.in_regs,
00545         (in.direction==ata_cmd_in::data_in ? " IN\n":
00546          in.direction==ata_cmd_in::data_out ? " OUT\n":"\n"));
00547 
00548     ata_cmd_out out;
00549 
00550     int64_t start_usec = -1;
00551     if (ata_debugmode)
00552       start_usec = smi()->get_timer_usec();
00553 
00554     bool ok = device->ata_pass_through(in, out);
00555 
00556     if (start_usec >= 0) {
00557       int64_t duration_usec = smi()->get_timer_usec() - start_usec;
00558       if (duration_usec >= 500)
00559         pout(" [Duration: %.3fs]\n", duration_usec / 1000000.0);
00560     }
00561 
00562     if (ata_debugmode && out.out_regs.is_set())
00563       print_regs(" Output: ", out.out_regs);
00564 
00565     if (ok) switch (command) {
00566       default:
00567         retval = 0;
00568         break;
00569       case CHECK_POWER_MODE:
00570         if (out.out_regs.sector_count.is_set()) {
00571           data[0] = out.out_regs.sector_count;
00572           retval = 0;
00573         }
00574         else {
00575           pout("CHECK POWER MODE: incomplete response, ATA output registers missing\n");
00576           device->set_err(ENOSYS);
00577           retval = -1;
00578         }
00579         break;
00580       case STATUS_CHECK:
00581         // Cyl low and Cyl high unchanged means "Good SMART status"
00582         if ((out.out_regs.lba_high == SMART_CYL_HI) &&
00583             (out.out_regs.lba_mid == SMART_CYL_LOW))
00584           retval = 0;
00585         // These values mean "Bad SMART status"
00586         else if ((out.out_regs.lba_high == SRET_STATUS_HI_EXCEEDED) &&
00587                  (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED))
00588           retval = 1;
00589         else if (out.out_regs.lba_mid == SMART_CYL_LOW) {
00590           retval = 0;
00591           if (ata_debugmode)
00592             pout("SMART STATUS RETURN: half healthy response sequence, "
00593                  "probable SAT/USB truncation\n");
00594           } else if (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED) {
00595           retval = 1;
00596           if (ata_debugmode)
00597             pout("SMART STATUS RETURN: half unhealthy response sequence, "
00598                  "probable SAT/USB truncation\n");
00599         }
00600         else if (!out.out_regs.is_set()) {
00601           pout("SMART STATUS RETURN: incomplete response, ATA output registers missing\n");
00602           device->set_err(ENOSYS);
00603           retval = -1;
00604         }
00605         else {
00606           // We haven't gotten output that makes sense; print out some debugging info
00607           pout("SMART Status command failed\n");
00608           pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE);
00609           pout("Register values returned from SMART Status command are:\n");
00610           print_regs(" ", out.out_regs);
00611           device->set_err(EIO);
00612           retval = -1;
00613         }
00614         break;
00615     }
00616   }
00617 
00618   // If requested, invalidate serial number before any printing is done
00619   if ((command == IDENTIFY || command == PIDENTIFY) && !retval && dont_print_serial_number)
00620     invalidate_serno((ata_identify_device *)data);
00621 
00622   // If reporting is enabled, say what output was produced by the command
00623   if (ata_debugmode) {
00624     if (device->get_errno())
00625       pout("REPORT-IOCTL: Device=%s Command=%s returned %d errno=%d [%s]\n",
00626            device->get_dev_name(), commandstrings[command], retval,
00627            device->get_errno(), device->get_errmsg());
00628     else
00629       pout("REPORT-IOCTL: Device=%s Command=%s returned %d\n",
00630            device->get_dev_name(), commandstrings[command], retval);
00631     
00632     // if requested, pretty-print the output data structure
00633     if (ata_debugmode > 1 && getsdata) {
00634       if (command==CHECK_POWER_MODE)
00635         pout("Sector Count Register (BASE-16): %02x\n", (unsigned char)(*data));
00636       else
00637         prettyprint((unsigned char *)data, commandstrings[command]);
00638     }
00639   }
00640 
00641   return retval;
00642 }
00643 
00644 // Get capacity and sector sizes from IDENTIFY data
00645 void ata_get_size_info(const ata_identify_device * id, ata_size_info & sizes)
00646 {
00647   sizes.sectors = sizes.capacity = 0;
00648   sizes.log_sector_size = sizes.phy_sector_size = 0;
00649   sizes.log_sector_offset = 0;
00650 
00651   // Return if no LBA support
00652   if (!(id->words047_079[49-47] & 0x0200))
00653     return;
00654 
00655   // Determine 28-bit LBA capacity
00656   unsigned lba28 = (unsigned)id->words047_079[61-47] << 16
00657                  | (unsigned)id->words047_079[60-47]      ;
00658 
00659   // Determine 48-bit LBA capacity if supported
00660   uint64_t lba48 = 0;
00661   if ((id->command_set_2 & 0xc400) == 0x4400)
00662     lba48 = (uint64_t)id->words088_255[103-88] << 48
00663           | (uint64_t)id->words088_255[102-88] << 32
00664           | (uint64_t)id->words088_255[101-88] << 16
00665           | (uint64_t)id->words088_255[100-88]      ;
00666 
00667   // Return if capacity unknown (ATAPI CD/DVD)
00668   if (!(lba28 || lba48))
00669     return;
00670 
00671   // Determine sector sizes
00672   sizes.log_sector_size = sizes.phy_sector_size = 512;
00673 
00674   unsigned short word106 = id->words088_255[106-88];
00675   if ((word106 & 0xc000) == 0x4000) {
00676     // Long Logical/Physical Sectors (LLS/LPS) ?
00677     if (word106 & 0x1000)
00678       // Logical sector size is specified in 16-bit words
00679       sizes.log_sector_size = sizes.phy_sector_size =
00680         ((id->words088_255[118-88] << 16) | id->words088_255[117-88]) << 1;
00681 
00682     if (word106 & 0x2000)
00683       // Physical sector size is multiple of logical sector size
00684       sizes.phy_sector_size <<= (word106 & 0x0f);
00685 
00686     unsigned short word209 = id->words088_255[209-88];
00687     if ((word209 & 0xc000) == 0x4000)
00688       sizes.log_sector_offset = (word209 & 0x3fff) * sizes.log_sector_size;
00689   }
00690 
00691   // Some early 4KiB LLS disks (Samsung N3U-3) return bogus lba28 value
00692   if (lba48 >= lba28 || (lba48 && sizes.log_sector_size > 512))
00693     sizes.sectors = lba48;
00694   else
00695     sizes.sectors = lba28;
00696 
00697   sizes.capacity = sizes.sectors * sizes.log_sector_size;
00698 }
00699 
00700 // This function computes the checksum of a single disk sector (512
00701 // bytes).  Returns zero if checksum is OK, nonzero if the checksum is
00702 // incorrect.  The size (512) is correct for all SMART structures.
00703 unsigned char checksum(const void * data)
00704 {
00705   unsigned char sum = 0;
00706   for (int i = 0; i < 512; i++)
00707     sum += ((const unsigned char *)data)[i];
00708   return sum;
00709 }
00710 
00711 // Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents
00712 // bytes.
00713 static void swapbytes(char * out, const char * in, size_t n)
00714 {
00715   for (size_t i = 0; i < n; i += 2) {
00716     out[i]   = in[i+1];
00717     out[i+1] = in[i];
00718   }
00719 }
00720 
00721 // Copies in to out, but removes leading and trailing whitespace.
00722 static void trim(char * out, const char * in)
00723 {
00724   // Find the first non-space character (maybe none).
00725   int first = -1;
00726   int i;
00727   for (i = 0; in[i]; i++)
00728     if (!isspace((int)in[i])) {
00729       first = i;
00730       break;
00731     }
00732 
00733   if (first == -1) {
00734     // There are no non-space characters.
00735     out[0] = '\0';
00736     return;
00737   }
00738 
00739   // Find the last non-space character.
00740   for (i = strlen(in)-1; i >= first && isspace((int)in[i]); i--)
00741     ;
00742   int last = i;
00743 
00744   strncpy(out, in+first, last-first+1);
00745   out[last-first+1] = '\0';
00746 }
00747 
00748 // Convenience function for formatting strings from ata_identify_device
00749 void ata_format_id_string(char * out, const unsigned char * in, int n)
00750 {
00751   bool must_swap = true;
00752 #ifdef __NetBSD__
00753   /* NetBSD kernel delivers IDENTIFY data in host byte order (but all else is LE) */
00754   // TODO: Handle NetBSD case in os_netbsd.cpp
00755   if (isbigendian())
00756     must_swap = !must_swap;
00757 #endif
00758 
00759   char tmp[65];
00760   n = n > 64 ? 64 : n;
00761   if (!must_swap)
00762     strncpy(tmp, (const char *)in, n);
00763   else
00764     swapbytes(tmp, (const char *)in, n);
00765   tmp[n] = '\0';
00766   trim(out, tmp);
00767 }
00768 
00769 // returns -1 if command fails or the device is in Sleep mode, else
00770 // value of Sector Count register.  Sector Count result values:
00771 //   00h device is in Standby mode. 
00772 //   80h device is in Idle mode.
00773 //   FFh device is in Active mode or Idle mode.
00774 
00775 int ataCheckPowerMode(ata_device * device) {
00776   unsigned char result;
00777 
00778   if ((smartcommandhandler(device, CHECK_POWER_MODE, 0, (char *)&result)))
00779     return -1;
00780 
00781   if (result!=0 && result!=0x80 && result!=0xff)
00782     pout("ataCheckPowerMode(): ATA CHECK POWER MODE returned unknown Sector Count Register value %02x\n", result);
00783 
00784   return (int)result;
00785 }
00786 
00787 // Issue a no-data ATA command with optional sector count register value
00788 bool ata_nodata_command(ata_device * device, unsigned char command,
00789                         int sector_count /* = -1 */)
00790 {
00791   ata_cmd_in in;
00792   in.in_regs.command = command;
00793   if (sector_count >= 0)
00794     in.in_regs.sector_count = sector_count;
00795 
00796   return device->ata_pass_through(in);
00797 }
00798 
00799 // Issue SET FEATURES command with optional sector count register value
00800 bool ata_set_features(ata_device * device, unsigned char features,
00801                       int sector_count /* = -1 */)
00802 {
00803   ata_cmd_in in;
00804   in.in_regs.command = ATA_SET_FEATURES;
00805   in.in_regs.features = features;
00806   if (sector_count >= 0)
00807     in.in_regs.sector_count = sector_count;
00808 
00809   return device->ata_pass_through(in);
00810 }
00811 
00812 // Reads current Device Identity info (512 bytes) into buf.  Returns 0
00813 // if all OK.  Returns -1 if no ATA Device identity can be
00814 // established.  Returns >0 if Device is ATA Packet Device (not SMART
00815 // capable).  The value of the integer helps identify the type of
00816 // Packet device, which is useful so that the user can connect the
00817 // formal device number with whatever object is inside their computer.
00818 int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id,
00819                       unsigned char * raw_buf /* = 0 */)
00820 {
00821   unsigned short *rawshort=(unsigned short *)buf;
00822   unsigned char  *rawbyte =(unsigned char  *)buf;
00823 
00824   // See if device responds either to IDENTIFY DEVICE or IDENTIFY
00825   // PACKET DEVICE
00826   bool packet = false;
00827   if ((smartcommandhandler(device, IDENTIFY, 0, (char *)buf))){
00828     if (smartcommandhandler(device, PIDENTIFY, 0, (char *)buf)){
00829       return -1; 
00830     }
00831     packet = true;
00832   }
00833 
00834   unsigned i;
00835   if (fix_swapped_id) {
00836     // Swap ID strings
00837     for (i = 0; i < sizeof(buf->serial_no)-1; i += 2)
00838       swap2((char *)(buf->serial_no+i));
00839     for (i = 0; i < sizeof(buf->fw_rev)-1; i += 2)
00840       swap2((char *)(buf->fw_rev+i));
00841     for (i = 0; i < sizeof(buf->model)-1; i += 2)
00842       swap2((char *)(buf->model+i));
00843   }
00844 
00845   // If requested, save raw data before endianness adjustments
00846   if (raw_buf)
00847     memcpy(raw_buf, buf, sizeof(*buf));
00848 
00849 #ifndef __NetBSD__
00850   // if machine is big-endian, swap byte order as needed
00851   // NetBSD kernel delivers IDENTIFY data in host byte order
00852   // TODO: Handle NetBSD case in os_netbsd.cpp
00853   if (isbigendian()){
00854     
00855     // swap various capability words that are needed
00856     for (i=0; i<33; i++)
00857       swap2((char *)(buf->words047_079+i));
00858     
00859     for (i=80; i<=87; i++)
00860       swap2((char *)(rawshort+i));
00861     
00862     for (i=0; i<168; i++)
00863       swap2((char *)(buf->words088_255+i));
00864   }
00865 #endif
00866   
00867   // If there is a checksum there, validate it
00868   if ((rawshort[255] & 0x00ff) == 0x00a5 && checksum(rawbyte))
00869     checksumwarning("Drive Identity Structure");
00870 
00871   // AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
00872   // T13/1699-D Revision 6a (Final Draft), September 6, 2008.
00873   // Sections 7.16.7 and 7.17.6:
00874   //
00875   // Word 0 of IDENTIFY DEVICE data:
00876   // Bit 15 = 0 : ATA device
00877   //
00878   // Word 0 of IDENTIFY PACKET DEVICE data:
00879   // Bits 15:14 = 10b : ATAPI device
00880   // Bits 15:14 = 11b : Reserved
00881   // Bits 12:8        : Device type (SPC-4, e.g 0x05 = CD/DVD)
00882 
00883   // CF+ and CompactFlash Specification Revision 4.0, May 24, 2006.
00884   // Section 6.2.1.6:
00885   //
00886   // Word 0 of IDENTIFY DEVICE data:
00887   // 848Ah = Signature for CompactFlash Storage Card
00888   // 044Ah = Alternate value turns on ATA device while preserving all retired bits
00889   // 0040h = Alternate value turns on ATA device while zeroing all retired bits
00890 
00891   // Assume ATA if IDENTIFY DEVICE returns CompactFlash Signature
00892   if (!packet && rawbyte[1] == 0x84 && rawbyte[0] == 0x8a)
00893     return 0;
00894 
00895   // If this is a PACKET DEVICE, return device type
00896   if (rawbyte[1] & 0x80)
00897     return 1+(rawbyte[1] & 0x1f);
00898   
00899   // Not a PACKET DEVICE
00900   return 0;
00901 }
00902 
00903 // Get World Wide Name (WWN) fields.
00904 // Return NAA field or -1 if WWN is unsupported.
00905 // Table 34 of T13/1699-D Revision 6a (ATA8-ACS), September 6, 2008.
00906 // (WWN was introduced in ATA/ATAPI-7 and is mandatory since ATA8-ACS Revision 3b)
00907 int ata_get_wwn(const ata_identify_device * id, unsigned & oui, uint64_t & unique_id)
00908 {
00909   // Don't use word 84 to be compatible with some older ATA-7 disks
00910   unsigned short word087 = id->csf_default;
00911   if ((word087 & 0xc100) != 0x4100)
00912     return -1; // word not valid or WWN support bit 8 not set
00913 
00914   unsigned short word108 = id->words088_255[108-88];
00915   unsigned short word109 = id->words088_255[109-88];
00916   unsigned short word110 = id->words088_255[110-88];
00917   unsigned short word111 = id->words088_255[111-88];
00918 
00919   oui = ((word108 & 0x0fff) << 12) | (word109 >> 4);
00920   unique_id = ((uint64_t)(word109 & 0xf) << 32)
00921             | (unsigned)((word110 << 16) | word111);
00922   return (word108 >> 12);
00923 }
00924 
00925 // Get nominal media rotation rate.
00926 // Returns: 0 = not reported, 1 = SSD, >1 = HDD rpm, < 0 = -(Unknown value)
00927 int ata_get_rotation_rate(const ata_identify_device * id)
00928 {
00929   // Table 37 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
00930   // Table A.31 of T13/2161-D (ACS-3) Revision 3b, August 25, 2012
00931   unsigned short word217 = id->words088_255[217-88];
00932   if (word217 == 0x0000 || word217 == 0xffff)
00933     return 0;
00934   else if (word217 == 0x0001)
00935     return 1;
00936   else if (word217 > 0x0400)
00937     return word217;
00938   else
00939     return -(int)word217;
00940 }
00941 
00942 // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
00943 int ataSmartSupport(const ata_identify_device * drive)
00944 {
00945   unsigned short word82=drive->command_set_1;
00946   unsigned short word83=drive->command_set_2;
00947   
00948   // check if words 82/83 contain valid info
00949   if ((word83>>14) == 0x01)
00950     // return value of SMART support bit 
00951     return word82 & 0x0001;
00952   
00953   // since we can're rely on word 82, we don't know if SMART supported
00954   return -1;
00955 }
00956 
00957 // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
00958 int ataIsSmartEnabled(const ata_identify_device * drive)
00959 {
00960   unsigned short word85=drive->cfs_enable_1;
00961   unsigned short word87=drive->csf_default;
00962   
00963   // check if words 85/86/87 contain valid info
00964   if ((word87>>14) == 0x01)
00965     // return value of SMART enabled bit
00966     return word85 & 0x0001;
00967   
00968   // Since we can't rely word85, we don't know if SMART is enabled.
00969   return -1;
00970 }
00971 
00972 
00973 // Reads SMART attributes into *data
00974 int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){
00975   
00976   if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){
00977     return -1;
00978   }
00979 
00980   // compute checksum
00981   if (checksum(data))
00982     checksumwarning("SMART Attribute Data Structure");
00983   
00984   // swap endian order if needed
00985   if (isbigendian()){
00986     int i;
00987     swap2((char *)&(data->revnumber));
00988     swap2((char *)&(data->total_time_to_complete_off_line));
00989     swap2((char *)&(data->smart_capability));
00990     swapx(&data->extend_test_completion_time_w);
00991     for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
00992       struct ata_smart_attribute *x=data->vendor_attributes+i;
00993       swap2((char *)&(x->flags));
00994     }
00995   }
00996 
00997   return 0;
00998 }
00999 
01000 
01001 // This corrects some quantities that are byte reversed in the SMART
01002 // SELF TEST LOG
01003 static void fixsamsungselftestlog(ata_smart_selftestlog * data)
01004 {
01005   // bytes 508/509 (numbered from 0) swapped (swap of self-test index
01006   // with one byte of reserved.
01007   swap2((char *)&(data->mostrecenttest));
01008 
01009   // LBA low register (here called 'selftestnumber", containing
01010   // information about the TYPE of the self-test) is byte swapped with
01011   // Self-test execution status byte.  These are bytes N, N+1 in the
01012   // entries.
01013   for (int i = 0; i < 21; i++)
01014     swap2((char *)&(data->selftest_struct[i].selftestnumber));
01015 
01016   return;
01017 }
01018 
01019 // Reads the Self Test Log (log #6)
01020 int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data,
01021                         firmwarebug_defs firmwarebugs)
01022 {
01023 
01024   // get data from device
01025   if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){
01026     return -1;
01027   }
01028 
01029   // compute its checksum, and issue a warning if needed
01030   if (checksum(data))
01031     checksumwarning("SMART Self-Test Log Structure");
01032   
01033   // fix firmware bugs in self-test log
01034   if (firmwarebugs.is_set(BUG_SAMSUNG))
01035     fixsamsungselftestlog(data);
01036 
01037   // swap endian order if needed
01038   if (isbigendian()){
01039     int i;
01040     swap2((char*)&(data->revnumber));
01041     for (i=0; i<21; i++){
01042       struct ata_smart_selftestlog_struct *x=data->selftest_struct+i;
01043       swap2((char *)&(x->timestamp));
01044       swap4((char *)&(x->lbafirstfailure));
01045     }
01046   }
01047 
01048   return 0;
01049 }
01050 
01051 // Print checksum warning for multi sector log
01052 static void check_multi_sector_sum(const void * data, unsigned nsectors, const char * msg)
01053 {
01054   unsigned errs = 0;
01055   for (unsigned i = 0; i < nsectors; i++) {
01056     if (checksum((const unsigned char *)data + i*512))
01057       errs++;
01058   }
01059   if (errs > 0) {
01060     if (nsectors == 1)
01061       checksumwarning(msg);
01062     else
01063       checksumwarning(strprintf("%s (%u/%u)", msg, errs, nsectors).c_str());
01064   }
01065 }
01066 
01067 // Read SMART Extended Self-test Log
01068 bool ataReadExtSelfTestLog(ata_device * device, ata_smart_extselftestlog * log,
01069                            unsigned nsectors)
01070 {
01071   if (!ataReadLogExt(device, 0x07, 0x00, 0, log, nsectors))
01072     return false;
01073 
01074   check_multi_sector_sum(log, nsectors, "SMART Extended Self-test Log Structure");
01075 
01076   if (isbigendian()) {
01077     swapx(&log->log_desc_index);
01078     for (unsigned i = 0; i < nsectors; i++) {
01079       for (unsigned j = 0; j < 19; j++)
01080         swapx(&log->log_descs[i].timestamp);
01081     }
01082   }
01083   return true;
01084 }
01085 
01086 
01087 // Read GP Log page(s)
01088 bool ataReadLogExt(ata_device * device, unsigned char logaddr,
01089                    unsigned char features, unsigned page,
01090                    void * data, unsigned nsectors)
01091 {
01092   ata_cmd_in in;
01093   in.in_regs.command      = ATA_READ_LOG_EXT;
01094   in.in_regs.features     = features; // log specific
01095   in.set_data_in_48bit(data, nsectors);
01096   in.in_regs.lba_low      = logaddr;
01097   in.in_regs.lba_mid_16   = page;
01098 
01099   if (!device->ata_pass_through(in)) { // TODO: Debug output
01100     if (nsectors <= 1) {
01101       pout("ATA_READ_LOG_EXT (addr=0x%02x:0x%02x, page=%u, n=%u) failed: %s\n",
01102            logaddr, features, page, nsectors, device->get_errmsg());
01103       return false;
01104     }
01105 
01106     // Recurse to retry with single sectors,
01107     // multi-sector reads may not be supported by ioctl.
01108     for (unsigned i = 0; i < nsectors; i++) {
01109       if (!ataReadLogExt(device, logaddr,
01110                          features, page + i,
01111                          (char *)data + 512*i, 1))
01112         return false;
01113     }
01114   }
01115 
01116   return true;
01117 }
01118 
01119 // Read SMART Log page(s)
01120 bool ataReadSmartLog(ata_device * device, unsigned char logaddr,
01121                      void * data, unsigned nsectors)
01122 {
01123   ata_cmd_in in;
01124   in.in_regs.command  = ATA_SMART_CMD;
01125   in.in_regs.features = ATA_SMART_READ_LOG_SECTOR;
01126   in.set_data_in(data, nsectors);
01127   in.in_regs.lba_high = SMART_CYL_HI;
01128   in.in_regs.lba_mid  = SMART_CYL_LOW;
01129   in.in_regs.lba_low  = logaddr;
01130 
01131   if (!device->ata_pass_through(in)) { // TODO: Debug output
01132     pout("ATA_SMART_READ_LOG failed: %s\n", device->get_errmsg());
01133     return false;
01134   }
01135   return true;
01136 }
01137 
01138 
01139 
01140 // Reads the SMART or GPL Log Directory (log #0)
01141 int ataReadLogDirectory(ata_device * device, ata_smart_log_directory * data, bool gpl)
01142 {
01143   if (!gpl) { // SMART Log directory
01144     if (smartcommandhandler(device, READ_LOG, 0x00, (char *)data))
01145       return -1;
01146   }
01147   else { // GP Log directory
01148     if (!ataReadLogExt(device, 0x00, 0x00, 0, data, 1))
01149       return -1;
01150   }
01151 
01152   // swap endian order if needed
01153   if (isbigendian())
01154     swapx(&data->logversion);
01155 
01156   return 0;
01157 }
01158 
01159 
01160 // Reads the selective self-test log (log #9)
01161 int ataReadSelectiveSelfTestLog(ata_device * device, struct ata_selective_self_test_log *data){
01162   
01163   // get data from device
01164   if (smartcommandhandler(device, READ_LOG, 0x09, (char *)data)){
01165     return -1;
01166   }
01167    
01168   // compute its checksum, and issue a warning if needed
01169   if (checksum(data))
01170     checksumwarning("SMART Selective Self-Test Log Structure");
01171   
01172   // swap endian order if needed
01173   if (isbigendian()){
01174     int i;
01175     swap2((char *)&(data->logversion));
01176     for (i=0;i<5;i++){
01177       swap8((char *)&(data->span[i].start));
01178       swap8((char *)&(data->span[i].end));
01179     }
01180     swap8((char *)&(data->currentlba));
01181     swap2((char *)&(data->currentspan));
01182     swap2((char *)&(data->flags));
01183     swap2((char *)&(data->pendingtime));
01184   }
01185   
01186   return 0;
01187 }
01188 
01189 // Writes the selective self-test log (log #9)
01190 int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_args & args,
01191                                  const ata_smart_values * sv, uint64_t num_sectors,
01192                                  const ata_selective_selftest_args * prev_args)
01193 {
01194   // Disk size must be known
01195   if (!num_sectors) {
01196     pout("Disk size is unknown, unable to check selective self-test spans\n");
01197     return -1;
01198   }
01199 
01200   // Read log
01201   struct ata_selective_self_test_log sstlog, *data=&sstlog;
01202   unsigned char *ptr=(unsigned char *)data;
01203   if (ataReadSelectiveSelfTestLog(device, data)) {
01204     pout("SMART Read Selective Self-test Log failed: %s\n", device->get_errmsg());
01205     pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n");
01206     return -1;
01207   }
01208   
01209   // Set log version
01210   data->logversion = 1;
01211 
01212   // Host is NOT allowed to write selective self-test log if a selective
01213   // self-test is in progress.
01214   if (0<data->currentspan && data->currentspan<6 && ((sv->self_test_exec_status)>>4)==15) {
01215     pout("SMART Selective or other Self-test in progress\n");
01216     return -4;
01217   }
01218 
01219   // Set start/end values based on old spans for special -t select,... options
01220   int i;
01221   for (i = 0; i < args.num_spans; i++) {
01222     int mode = args.span[i].mode;
01223     uint64_t start = args.span[i].start;
01224     uint64_t end   = args.span[i].end;
01225     if (mode == SEL_CONT) {// redo or next dependig on last test status
01226       switch (sv->self_test_exec_status >> 4) {
01227         case 1: case 2: // Aborted/Interrupted by host
01228           pout("Continue Selective Self-Test: Redo last span\n");
01229           mode = SEL_REDO;
01230           break;
01231         default: // All others
01232           pout("Continue Selective Self-Test: Start next span\n");
01233           mode = SEL_NEXT;
01234           break;
01235       }
01236     }
01237 
01238     if (   (mode == SEL_REDO || mode == SEL_NEXT)
01239         && prev_args && i < prev_args->num_spans
01240         && !data->span[i].start && !data->span[i].end) {
01241       // Some drives do not preserve the selective self-test log accross
01242       // power-cyles.  If old span on drive is cleared use span provided
01243       // by caller.  This is used by smartd (first span only).
01244       data->span[i].start = prev_args->span[i].start;
01245       data->span[i].end   = prev_args->span[i].end;
01246     }
01247 
01248     switch (mode) {
01249       case SEL_RANGE: // -t select,START-END
01250         break;
01251       case SEL_REDO: // -t select,redo... => Redo current
01252         start = data->span[i].start;
01253         if (end > 0) { // -t select,redo+SIZE
01254           end--; end += start; // [oldstart, oldstart+SIZE)
01255         }
01256         else // -t select,redo
01257           end = data->span[i].end; // [oldstart, oldend]
01258         break;
01259       case SEL_NEXT: // -t select,next... => Do next
01260         if (data->span[i].end == 0) {
01261           start = end = 0; break; // skip empty spans
01262         }
01263         start = data->span[i].end + 1;
01264         if (start >= num_sectors)
01265           start = 0; // wrap around
01266         if (end > 0) { // -t select,next+SIZE
01267           end--; end += start; // (oldend, oldend+SIZE]
01268         }
01269         else { // -t select,next
01270           uint64_t oldsize = data->span[i].end - data->span[i].start + 1;
01271           end = start + oldsize - 1; // (oldend, oldend+oldsize]
01272           if (end >= num_sectors) {
01273             // Adjust size to allow round-robin testing without future size decrease
01274             uint64_t spans = (num_sectors + oldsize-1) / oldsize;
01275             uint64_t newsize = (num_sectors + spans-1) / spans;
01276             uint64_t newstart = num_sectors - newsize, newend = num_sectors - 1;
01277             pout("Span %d changed from %" PRIu64 "-%" PRIu64 " (%" PRIu64 " sectors)\n",
01278                  i, start, end, oldsize);
01279             pout("                 to %" PRIu64 "-%" PRIu64 " (%" PRIu64 " sectors) (%" PRIu64 " spans)\n",
01280                  newstart, newend, newsize, spans);
01281             start = newstart; end = newend;
01282           }
01283         }
01284         break;
01285       default:
01286         pout("ataWriteSelectiveSelfTestLog: Invalid mode %d\n", mode);
01287         return -1;
01288     }
01289     // Range check
01290     if (start < num_sectors && num_sectors <= end) {
01291       if (end != ~(uint64_t)0) // -t select,N-max
01292         pout("Size of self-test span %d decreased according to disk size\n", i);
01293       end = num_sectors - 1;
01294     }
01295     if (!(start <= end && end < num_sectors)) {
01296       pout("Invalid selective self-test span %d: %" PRIu64 "-%" PRIu64 " (%" PRIu64 " sectors)\n",
01297         i, start, end, num_sectors);
01298       return -1;
01299     }
01300     // Return the actual mode and range to caller.
01301     args.span[i].mode  = mode;
01302     args.span[i].start = start;
01303     args.span[i].end   = end;
01304   }
01305 
01306   // Clear spans
01307   for (i=0; i<5; i++)
01308     memset(data->span+i, 0, sizeof(struct test_span));
01309   
01310   // Set spans for testing 
01311   for (i = 0; i < args.num_spans; i++){
01312     data->span[i].start = args.span[i].start;
01313     data->span[i].end   = args.span[i].end;
01314   }
01315 
01316   // host must initialize to zero before initiating selective self-test
01317   data->currentlba=0;
01318   data->currentspan=0;
01319   
01320   // Perform off-line scan after selective test?
01321   if (args.scan_after_select == 1)
01322     // NO
01323     data->flags &= ~SELECTIVE_FLAG_DOSCAN;
01324   else if (args.scan_after_select == 2)
01325     // YES
01326     data->flags |= SELECTIVE_FLAG_DOSCAN;
01327   
01328   // Must clear active and pending flags before writing
01329   data->flags &= ~(SELECTIVE_FLAG_ACTIVE);  
01330   data->flags &= ~(SELECTIVE_FLAG_PENDING);
01331 
01332   // modify pending time?
01333   if (args.pending_time)
01334     data->pendingtime = (unsigned short)(args.pending_time-1);
01335 
01336   // Set checksum to zero, then compute checksum
01337   data->checksum=0;
01338   unsigned char cksum=0;
01339   for (i=0; i<512; i++)
01340     cksum+=ptr[i];
01341   cksum=~cksum;
01342   cksum+=1;
01343   data->checksum=cksum;
01344 
01345   // swap endian order if needed
01346   if (isbigendian()){
01347     swap2((char *)&(data->logversion));
01348     for (int b = 0; b < 5; b++) {
01349       swap8((char *)&(data->span[b].start));
01350       swap8((char *)&(data->span[b].end));
01351     }
01352     swap8((char *)&(data->currentlba));
01353     swap2((char *)&(data->currentspan));
01354     swap2((char *)&(data->flags));
01355     swap2((char *)&(data->pendingtime));
01356   }
01357 
01358   // write new selective self-test log
01359   if (smartcommandhandler(device, WRITE_LOG, 0x09, (char *)data)){
01360     pout("Write Selective Self-test Log failed: %s\n", device->get_errmsg());
01361     return -3;
01362   }
01363 
01364   return 0;
01365 }
01366 
01367 // This corrects some quantities that are byte reversed in the SMART
01368 // ATA ERROR LOG.
01369 static void fixsamsungerrorlog(ata_smart_errorlog * data)
01370 {
01371   // FIXED IN SAMSUNG -25 FIRMWARE???
01372   // Device error count in bytes 452-3
01373   swap2((char *)&(data->ata_error_count));
01374   
01375   // FIXED IN SAMSUNG -22a FIRMWARE
01376   // step through 5 error log data structures
01377   for (int i = 0; i < 5; i++){
01378     // step through 5 command data structures
01379     for (int j = 0; j < 5; j++)
01380       // Command data structure 4-byte millisec timestamp.  These are
01381       // bytes (N+8, N+9, N+10, N+11).
01382       swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp));
01383     // Error data structure two-byte hour life timestamp.  These are
01384     // bytes (N+28, N+29).
01385     swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp));
01386   }
01387   return;
01388 }
01389 
01390 // NEEDED ONLY FOR SAMSUNG -22 (some) -23 AND -24?? FIRMWARE
01391 static void fixsamsungerrorlog2(ata_smart_errorlog * data)
01392 {
01393   // Device error count in bytes 452-3
01394   swap2((char *)&(data->ata_error_count));
01395   return;
01396 }
01397 
01398 // Reads the Summary SMART Error Log (log #1). The Comprehensive SMART
01399 // Error Log is #2, and the Extended Comprehensive SMART Error log is
01400 // #3
01401 int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
01402                      firmwarebug_defs firmwarebugs)
01403 {
01404   
01405   // get data from device
01406   if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){
01407     return -1;
01408   }
01409   
01410   // compute its checksum, and issue a warning if needed
01411   if (checksum(data))
01412     checksumwarning("SMART ATA Error Log Structure");
01413   
01414   // Some disks have the byte order reversed in some SMART Summary
01415   // Error log entries
01416   if (firmwarebugs.is_set(BUG_SAMSUNG))
01417     fixsamsungerrorlog(data);
01418   else if (firmwarebugs.is_set(BUG_SAMSUNG2))
01419     fixsamsungerrorlog2(data);
01420 
01421   // swap endian order if needed
01422   if (isbigendian()){
01423     int i,j;
01424     
01425     // Device error count in bytes 452-3
01426     swap2((char *)&(data->ata_error_count));
01427     
01428     // step through 5 error log data structures
01429     for (i=0; i<5; i++){
01430       // step through 5 command data structures
01431       for (j=0; j<5; j++)
01432         // Command data structure 4-byte millisec timestamp
01433         swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp));
01434       // Error data structure life timestamp
01435       swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp));
01436     }
01437   }
01438   
01439   return 0;
01440 }
01441 
01442 
01443 // Fix LBA byte ordering of Extended Comprehensive Error Log
01444 // if little endian instead of ATA register ordering is provided
01445 template <class T>
01446 static inline void fix_exterrlog_lba_cmd(T & cmd)
01447 {
01448   T org = cmd;
01449   cmd.lba_mid_register_hi = org.lba_high_register;
01450   cmd.lba_low_register_hi = org.lba_mid_register_hi;
01451   cmd.lba_high_register   = org.lba_mid_register;
01452   cmd.lba_mid_register    = org.lba_low_register_hi;
01453 }
01454 
01455 static void fix_exterrlog_lba(ata_smart_exterrlog * log, unsigned nsectors)
01456 {
01457    for (unsigned i = 0; i < nsectors; i++) {
01458      for (int ei = 0; ei < 4; ei++) {
01459        ata_smart_exterrlog_error_log & entry = log[i].error_logs[ei];
01460        fix_exterrlog_lba_cmd(entry.error);
01461        for (int ci = 0; ci < 5; ci++)
01462          fix_exterrlog_lba_cmd(entry.commands[ci]);
01463      }
01464    }
01465 }
01466 
01467 // Read Extended Comprehensive Error Log
01468 bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log,
01469                         unsigned nsectors, firmwarebug_defs firmwarebugs)
01470 {
01471   if (!ataReadLogExt(device, 0x03, 0x00, 0, log, nsectors))
01472     return false;
01473 
01474   check_multi_sector_sum(log, nsectors, "SMART Extended Comprehensive Error Log Structure");
01475 
01476   if (isbigendian()) {
01477     swapx(&log->device_error_count);
01478     swapx(&log->error_log_index);
01479     for (unsigned i = 0; i < nsectors; i++) {
01480       for (unsigned j = 0; j < 4; j++) {
01481         for (unsigned k = 0; k < 5; k++)
01482            swapx(&log[i].error_logs[j].commands[k].timestamp);
01483         swapx(&log[i].error_logs[j].error.timestamp);
01484       }
01485     }
01486   }
01487 
01488   if (firmwarebugs.is_set(BUG_XERRORLBA))
01489     fix_exterrlog_lba(log, nsectors);
01490 
01491   return true;
01492 }
01493 
01494 
01495 int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt *data){
01496   
01497   // get data from device
01498   if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){
01499     return -1;
01500   }
01501   
01502   // compute its checksum, and issue a warning if needed
01503   if (checksum(data))
01504     checksumwarning("SMART Attribute Thresholds Structure");
01505   
01506   // swap endian order if needed
01507   if (isbigendian())
01508     swap2((char *)&(data->revnumber));
01509 
01510   return 0;
01511 }
01512 
01513 int ataEnableSmart (ata_device * device ){
01514   if (smartcommandhandler(device, ENABLE, 0, NULL)){
01515     return -1;
01516   }
01517   return 0;
01518 }
01519 
01520 int ataDisableSmart (ata_device * device ){
01521   
01522   if (smartcommandhandler(device, DISABLE, 0, NULL)){
01523     return -1;
01524   }  
01525   return 0;
01526 }
01527 
01528 int ataEnableAutoSave(ata_device * device){
01529   if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){
01530     return -1;
01531   }
01532   return 0;
01533 }
01534 
01535 int ataDisableAutoSave(ata_device * device){
01536   
01537   if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){
01538     return -1;
01539   }
01540   return 0;
01541 }
01542 
01543 // In *ALL* ATA standards the Enable/Disable AutoOffline command is
01544 // marked "OBSOLETE". It is defined in SFF-8035i Revision 2, and most
01545 // vendors still support it for backwards compatibility. IBM documents
01546 // it for some drives.
01547 int ataEnableAutoOffline (ata_device * device){
01548   
01549   /* timer hard coded to 4 hours */  
01550   if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){
01551     return -1;
01552   }
01553   return 0;
01554 }
01555 
01556 // Another Obsolete Command.  See comments directly above, associated
01557 // with the corresponding Enable command.
01558 int ataDisableAutoOffline (ata_device * device){
01559   
01560   if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){
01561     return -1;
01562   }
01563   return 0;
01564 }
01565 
01566 // If SMART is enabled, supported, and working, then this call is
01567 // guaranteed to return 1, else zero.  Note that it should return 1
01568 // regardless of whether the disk's SMART status is 'healthy' or
01569 // 'failing'.
01570 int ataDoesSmartWork(ata_device * device){
01571   int retval=smartcommandhandler(device, STATUS, 0, NULL);
01572 
01573   if (-1 == retval)
01574     return 0;
01575 
01576   return 1;
01577 }
01578 
01579 // This function uses a different interface (DRIVE_TASK) than the
01580 // other commands in this file.
01581 int ataSmartStatus2(ata_device * device){
01582   return smartcommandhandler(device, STATUS_CHECK, 0, NULL);  
01583 }
01584 
01585 // This is the way to execute ALL tests: offline, short self-test,
01586 // extended self test, with and without captive mode, etc.
01587 // TODO: Move to ataprint.cpp ?
01588 int ataSmartTest(ata_device * device, int testtype, bool force,
01589                  const ata_selective_selftest_args & selargs,
01590                  const ata_smart_values * sv, uint64_t num_sectors)
01591 {
01592   char cmdmsg[128]; const char *type, *captive;
01593   int cap, retval, select=0;
01594 
01595   // Boolean, if set, says test is captive
01596   cap=testtype & CAPTIVE_MASK;
01597 
01598   // Set up strings that describe the type of test
01599   if (cap)
01600     captive="captive";
01601   else
01602     captive="off-line";
01603   
01604   if (testtype==OFFLINE_FULL_SCAN)
01605     type="off-line";
01606   else  if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST)
01607     type="Short self-test";
01608   else if (testtype==EXTEND_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST)
01609     type="Extended self-test";
01610   else if (testtype==CONVEYANCE_SELF_TEST || testtype==CONVEYANCE_CAPTIVE_SELF_TEST)
01611     type="Conveyance self-test";
01612   else if ((select=(testtype==SELECTIVE_SELF_TEST || testtype==SELECTIVE_CAPTIVE_SELF_TEST)))
01613     type="Selective self-test";
01614   else
01615     type = 0;
01616 
01617   // Check whether another test is already running
01618   if (type && (sv->self_test_exec_status >> 4) == 0xf) {
01619     if (!force) {
01620       pout("Can't start self-test without aborting current test (%d0%% remaining),\n"
01621            "%srun 'smartctl -X' to abort test.\n",
01622            sv->self_test_exec_status & 0x0f,
01623            (!select ? "add '-t force' option to override, or " : ""));
01624       return -1;
01625     }
01626   }
01627   else
01628     force = false;
01629 
01630   // If doing a selective self-test, first use WRITE_LOG to write the
01631   // selective self-test log.
01632   ata_selective_selftest_args selargs_io = selargs; // filled with info about actual spans
01633   if (select && (retval = ataWriteSelectiveSelfTestLog(device, selargs_io, sv, num_sectors))) {
01634     if (retval==-4)
01635       pout("Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");
01636     return retval;
01637   }
01638 
01639   //  Print ouf message that we are sending the command to test
01640   if (testtype==ABORT_SELF_TEST)
01641     snprintf(cmdmsg, sizeof(cmdmsg), "Abort SMART off-line mode self-test routine");
01642   else if (!type)
01643     snprintf(cmdmsg, sizeof(cmdmsg), "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype);
01644   else
01645     snprintf(cmdmsg, sizeof(cmdmsg), "Execute SMART %s routine immediately in %s mode", type, captive);
01646   pout("Sending command: \"%s\".\n",cmdmsg);
01647 
01648   if (select) {
01649     int i;
01650     pout("SPAN         STARTING_LBA           ENDING_LBA\n");
01651     for (i = 0; i < selargs_io.num_spans; i++)
01652       pout("   %d %20" PRId64 " %20" PRId64 "\n", i,
01653            selargs_io.span[i].start,
01654            selargs_io.span[i].end);
01655   }
01656   
01657   // Now send the command to test
01658   if (smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL)) {
01659     if (!(cap && device->get_errno() == EIO)) {
01660       pout("Command \"%s\" failed: %s\n", cmdmsg, device->get_errmsg());
01661       return -1;
01662     }
01663   }
01664   
01665   // Since the command succeeded, tell user
01666   if (testtype==ABORT_SELF_TEST)
01667     pout("Self-testing aborted!\n");
01668   else {
01669     pout("Drive command \"%s\" successful.\n", cmdmsg);
01670     if (type)
01671       pout("Testing has begun%s.\n", (force ? " (previous test aborted)" : ""));
01672   }
01673   return 0;
01674 }
01675 
01676 /* Test Time Functions */
01677 int TestTime(const ata_smart_values *data, int testtype)
01678 {
01679   switch (testtype){
01680   case OFFLINE_FULL_SCAN:
01681     return (int) data->total_time_to_complete_off_line;
01682   case SHORT_SELF_TEST:
01683   case SHORT_CAPTIVE_SELF_TEST:
01684     return (int) data->short_test_completion_time;
01685   case EXTEND_SELF_TEST:
01686   case EXTEND_CAPTIVE_SELF_TEST:
01687     if (data->extend_test_completion_time_b == 0xff
01688         && data->extend_test_completion_time_w != 0x0000
01689         && data->extend_test_completion_time_w != 0xffff)
01690       return data->extend_test_completion_time_w; // ATA-8
01691     else
01692       return data->extend_test_completion_time_b;
01693   case CONVEYANCE_SELF_TEST:
01694   case CONVEYANCE_CAPTIVE_SELF_TEST:
01695     return (int) data->conveyance_test_completion_time;
01696   default:
01697     return 0;
01698   }
01699 }
01700 
01701 // This function tells you both about the ATA error log and the
01702 // self-test error log capability (introduced in ATA-5).  The bit is
01703 // poorly documented in the ATA/ATAPI standard.  Starting with ATA-6,
01704 // SMART error logging is also indicated in bit 0 of DEVICE IDENTIFY
01705 // word 84 and 87.  Top two bits must match the pattern 01. BEFORE
01706 // ATA-6 these top two bits still had to match the pattern 01, but the
01707 // remaining bits were reserved (==0).
01708 int isSmartErrorLogCapable (const ata_smart_values * data, const ata_identify_device * identity)
01709 {
01710   unsigned short word84=identity->command_set_extension;
01711   unsigned short word87=identity->csf_default;
01712   int isata6=identity->major_rev_num & (0x01<<6);
01713   int isata7=identity->major_rev_num & (0x01<<7);
01714 
01715   if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x01))
01716     return 1;
01717   
01718   if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x01))
01719     return 1;
01720   
01721   // otherwise we'll use the poorly documented capability bit
01722   return data->errorlog_capability & 0x01;
01723 }
01724 
01725 // See previous function.  If the error log exists then the self-test
01726 // log should (must?) also exist.
01727 int isSmartTestLogCapable (const ata_smart_values * data, const ata_identify_device *identity)
01728 {
01729   unsigned short word84=identity->command_set_extension;
01730   unsigned short word87=identity->csf_default;
01731   int isata6=identity->major_rev_num & (0x01<<6);
01732   int isata7=identity->major_rev_num & (0x01<<7);
01733 
01734   if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x02))
01735     return 1;
01736   
01737   if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x02))
01738     return 1;
01739 
01740 
01741   // otherwise we'll use the poorly documented capability bit
01742   return data->errorlog_capability & 0x01;
01743 }
01744 
01745 
01746 int isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
01747 {
01748   unsigned short word84=identity->command_set_extension;
01749   unsigned short word87=identity->csf_default;
01750 
01751   // If bit 14 of word 84 is set to one and bit 15 of word 84 is
01752   // cleared to zero, the contents of word 84 contains valid support
01753   // information. If not, support information is not valid in this
01754   // word.
01755   if ((word84>>14) == 0x01)
01756     // If bit 5 of word 84 is set to one, the device supports the
01757     // General Purpose Logging feature set.
01758     return (word84 & (0x01 << 5));
01759   
01760   // If bit 14 of word 87 is set to one and bit 15 of word 87 is
01761   // cleared to zero, the contents of words (87:85) contain valid
01762   // information. If not, information is not valid in these words.  
01763   if ((word87>>14) == 0x01)
01764     // If bit 5 of word 87 is set to one, the device supports
01765     // the General Purpose Logging feature set.
01766     return (word87 & (0x01 << 5));
01767 
01768   // not capable
01769   return 0;
01770 }
01771 
01772 
01773 // SMART self-test capability is also indicated in bit 1 of DEVICE
01774 // IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
01775 // However this was only introduced in ATA-6 (but self-test log was in
01776 // ATA-5).
01777 int isSupportExecuteOfflineImmediate(const ata_smart_values *data)
01778 {
01779   return data->offline_data_collection_capability & 0x01;
01780 }
01781 
01782 // Note in the ATA-5 standard, the following bit is listed as "Vendor
01783 // Specific".  So it may not be reliable. The only use of this that I
01784 // have found is in IBM drives, where it is well-documented.  See for
01785 // example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
01786 // hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
01787 int isSupportAutomaticTimer(const ata_smart_values * data)
01788 {
01789   return data->offline_data_collection_capability & 0x02;
01790 }
01791 int isSupportOfflineAbort(const ata_smart_values *data)
01792 {
01793   return data->offline_data_collection_capability & 0x04;
01794 }
01795 int isSupportOfflineSurfaceScan(const ata_smart_values * data)
01796 {
01797    return data->offline_data_collection_capability & 0x08;
01798 }
01799 int isSupportSelfTest (const ata_smart_values * data)
01800 {
01801    return data->offline_data_collection_capability & 0x10;
01802 }
01803 int isSupportConveyanceSelfTest(const ata_smart_values * data)
01804 {
01805    return data->offline_data_collection_capability & 0x20;
01806 }
01807 int isSupportSelectiveSelfTest(const ata_smart_values * data)
01808 {
01809    return data->offline_data_collection_capability & 0x40;
01810 }
01811 
01812 // Get attribute state
01813 ata_attr_state ata_get_attr_state(const ata_smart_attribute & attr,
01814                                   int attridx,
01815                                   const ata_smart_threshold_entry * thresholds,
01816                                   const ata_vendor_attr_defs & defs,
01817                                   unsigned char * threshval /* = 0 */)
01818 {
01819   if (!attr.id)
01820     return ATTRSTATE_NON_EXISTING;
01821 
01822   // Normalized values (current,worst,threshold) not valid
01823   // if specified by '-v' option.
01824   // (Some SSD disks uses these bytes to store raw value).
01825   if (defs[attr.id].flags & ATTRFLAG_NO_NORMVAL)
01826     return ATTRSTATE_NO_NORMVAL;
01827 
01828   // Normally threshold is at same index as attribute
01829   int i = attridx;
01830   if (thresholds[i].id != attr.id) {
01831     // Find threshold id in table
01832     for (i = 0; thresholds[i].id != attr.id; ) {
01833       if (++i >= NUMBER_ATA_SMART_ATTRIBUTES)
01834         // Threshold id missing or thresholds cannot be read
01835         return ATTRSTATE_NO_THRESHOLD;
01836     }
01837   }
01838   unsigned char threshold = thresholds[i].threshold;
01839 
01840   // Return threshold if requested
01841   if (threshval)
01842     *threshval = threshold;
01843 
01844   // Don't report a failed attribute if its threshold is 0.
01845   // ATA-3 (X3T13/2008D Revision 7b) declares 0x00 as the "always passing"
01846   // threshold (Later ATA versions declare all thresholds as "obsolete").
01847   // In practice, threshold value 0 is often used for usage attributes.
01848   if (!threshold)
01849     return ATTRSTATE_OK;
01850 
01851   // Failed now if current value is below threshold
01852   if (attr.current <= threshold)
01853     return ATTRSTATE_FAILED_NOW;
01854 
01855   // Failed in the past if worst value is below threshold
01856   if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL) && attr.worst <= threshold)
01857     return ATTRSTATE_FAILED_PAST;
01858 
01859   return ATTRSTATE_OK;
01860 }
01861 
01862 // Get default raw value print format
01863 static ata_attr_raw_format get_default_raw_format(unsigned char id)
01864 {
01865   switch (id) {
01866   case 3:   // Spin-up time
01867     return RAWFMT_RAW16_OPT_AVG16;
01868 
01869   case 5:   // Reallocated sector count
01870   case 196: // Reallocated event count
01871     return RAWFMT_RAW16_OPT_RAW16;
01872 
01873   case 9:  // Power on hours
01874     return RAWFMT_RAW24_OPT_RAW8;
01875 
01876   case 190: // Temperature
01877   case 194:
01878     return RAWFMT_TEMPMINMAX;
01879 
01880   default:
01881     return RAWFMT_RAW48;
01882   }
01883 }
01884 
01885 // Get attribute raw value.
01886 uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr,
01887                                 const ata_vendor_attr_defs & defs)
01888 {
01889   const ata_vendor_attr_defs::entry & def = defs[attr.id];
01890 
01891   // Use default byteorder if not specified
01892   const char * byteorder = def.byteorder;
01893   if (!*byteorder) {
01894     switch (def.raw_format) {
01895       case RAWFMT_RAW64:
01896       case RAWFMT_HEX64:
01897         byteorder = "543210wv"; break;
01898       case RAWFMT_RAW56:
01899       case RAWFMT_HEX56:
01900       case RAWFMT_RAW24_DIV_RAW32:
01901       case RAWFMT_MSEC24_HOUR32:
01902         byteorder = "r543210"; break;
01903       default:
01904         byteorder = "543210"; break;
01905     }
01906   }
01907 
01908   // Build 64-bit value from selected bytes
01909   uint64_t rawvalue = 0;
01910   for (int i = 0; byteorder[i]; i++) {
01911     unsigned char b;
01912     switch (byteorder[i]) {
01913       case '0': b = attr.raw[0];  break;
01914       case '1': b = attr.raw[1];  break;
01915       case '2': b = attr.raw[2];  break;
01916       case '3': b = attr.raw[3];  break;
01917       case '4': b = attr.raw[4];  break;
01918       case '5': b = attr.raw[5];  break;
01919       case 'r': b = attr.reserv;  break;
01920       case 'v': b = attr.current; break;
01921       case 'w': b = attr.worst;   break;
01922       default : b = 0;            break;
01923     }
01924     rawvalue <<= 8; rawvalue |= b;
01925   }
01926 
01927   return rawvalue;
01928 }
01929 
01930 
01931 // Format attribute raw value.
01932 std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
01933                                       const ata_vendor_attr_defs & defs)
01934 {
01935   // Get 48 bit or 64 bit raw value
01936   uint64_t rawvalue = ata_get_attr_raw_value(attr, defs);
01937 
01938   // Split into bytes and words
01939   unsigned char raw[6];
01940   raw[0] = (unsigned char) rawvalue;
01941   raw[1] = (unsigned char)(rawvalue >>  8);
01942   raw[2] = (unsigned char)(rawvalue >> 16);
01943   raw[3] = (unsigned char)(rawvalue >> 24);
01944   raw[4] = (unsigned char)(rawvalue >> 32);
01945   raw[5] = (unsigned char)(rawvalue >> 40);
01946   unsigned word[3];
01947   word[0] = raw[0] | (raw[1] << 8);
01948   word[1] = raw[2] | (raw[3] << 8);
01949   word[2] = raw[4] | (raw[5] << 8);
01950 
01951   // Get print format
01952   ata_attr_raw_format format = defs[attr.id].raw_format;
01953   if (format == RAWFMT_DEFAULT)
01954     format = get_default_raw_format(attr.id);
01955 
01956   // Print
01957   std::string s;
01958   switch (format) {
01959   case RAWFMT_RAW8:
01960     s = strprintf("%d %d %d %d %d %d",
01961       raw[5], raw[4], raw[3], raw[2], raw[1], raw[0]);
01962     break;
01963 
01964   case RAWFMT_RAW16:
01965     s = strprintf("%u %u %u", word[2], word[1], word[0]);
01966     break;
01967 
01968   case RAWFMT_RAW48:
01969   case RAWFMT_RAW56:
01970   case RAWFMT_RAW64:
01971     s = strprintf("%" PRIu64, rawvalue);
01972     break;
01973 
01974   case RAWFMT_HEX48:
01975     s = strprintf("0x%012" PRIx64, rawvalue);
01976     break;
01977 
01978   case RAWFMT_HEX56:
01979     s = strprintf("0x%014" PRIx64, rawvalue);
01980     break;
01981 
01982   case RAWFMT_HEX64:
01983     s = strprintf("0x%016" PRIx64, rawvalue);
01984     break;
01985 
01986   case RAWFMT_RAW16_OPT_RAW16:
01987     s = strprintf("%u", word[0]);
01988     if (word[1] || word[2])
01989       s += strprintf(" (%u %u)", word[2], word[1]);
01990     break;
01991 
01992   case RAWFMT_RAW16_OPT_AVG16:
01993     s = strprintf("%u", word[0]);
01994     if (word[1])
01995       s += strprintf(" (Average %u)", word[1]);
01996     break;
01997 
01998   case RAWFMT_RAW24_OPT_RAW8:
01999     s = strprintf("%u", (unsigned)(rawvalue & 0x00ffffffULL));
02000     if (raw[3] || raw[4] || raw[5])
02001       s += strprintf(" (%d %d %d)", raw[5], raw[4], raw[3]);
02002     break;
02003 
02004   case RAWFMT_RAW24_DIV_RAW24:
02005     s = strprintf("%u/%u",
02006       (unsigned)(rawvalue >> 24), (unsigned)(rawvalue & 0x00ffffffULL));
02007     break;
02008 
02009   case RAWFMT_RAW24_DIV_RAW32:
02010     s = strprintf("%u/%u",
02011       (unsigned)(rawvalue >> 32), (unsigned)(rawvalue & 0xffffffffULL));
02012     break;
02013 
02014   case RAWFMT_MIN2HOUR:
02015     {
02016       // minutes
02017       int64_t temp = word[0]+(word[1]<<16);
02018       int64_t tmp1 = temp/60;
02019       int64_t tmp2 = temp%60;
02020       s = strprintf("%" PRIu64 "h+%02" PRIu64 "m", tmp1, tmp2);
02021       if (word[2])
02022         s += strprintf(" (%u)", word[2]);
02023     }
02024     break;
02025 
02026   case RAWFMT_SEC2HOUR:
02027     {
02028       // seconds
02029       int64_t hours = rawvalue/3600;
02030       int64_t minutes = (rawvalue-3600*hours)/60;
02031       int64_t seconds = rawvalue%60;
02032       s = strprintf("%" PRIu64 "h+%02" PRIu64 "m+%02" PRIu64 "s", hours, minutes, seconds);
02033     }
02034     break;
02035 
02036   case RAWFMT_HALFMIN2HOUR:
02037     {
02038       // 30-second counter
02039       int64_t hours = rawvalue/120;
02040       int64_t minutes = (rawvalue-120*hours)/2;
02041       s += strprintf("%" PRIu64 "h+%02" PRIu64 "m", hours, minutes);
02042     }
02043     break;
02044 
02045   case RAWFMT_MSEC24_HOUR32:
02046     {
02047       // hours + milliseconds
02048       unsigned hours = (unsigned)(rawvalue & 0xffffffffULL);
02049       unsigned milliseconds = (unsigned)(rawvalue >> 32);
02050       unsigned seconds = milliseconds / 1000;
02051       s = strprintf("%uh+%02um+%02u.%03us",
02052         hours, seconds / 60, seconds % 60, milliseconds % 1000);
02053     }
02054     break;
02055 
02056   case RAWFMT_TEMPMINMAX:
02057     // Temperature
02058     {
02059       // Search for possible min/max values
02060       // 00 HH 00 LL 00 TT (Hitachi/IBM)
02061       // 00 00 HH LL 00 TT (Maxtor, Samsung)
02062       // 00 00 00 HH LL TT (WDC)
02063       unsigned char lo = 0, hi = 0;
02064       int cnt = 0;
02065       for (int i = 1; i < 6; i++) {
02066         if (raw[i])
02067           switch (cnt++) {
02068             case 0:
02069               lo = raw[i];
02070               break;
02071             case 1:
02072               if (raw[i] < lo) {
02073                 hi = lo; lo = raw[i];
02074               }
02075               else
02076                 hi = raw[i];
02077               break;
02078           }
02079       }
02080 
02081       unsigned char t = raw[0];
02082       if (cnt == 0)
02083         s = strprintf("%d", t);
02084       else if (cnt == 2 && 0 < lo && lo <= t && t <= hi && hi < 128)
02085         s = strprintf("%d (Min/Max %d/%d)", t, lo, hi);
02086       else
02087         s = strprintf("%d (%d %d %d %d %d)", t, raw[5], raw[4], raw[3], raw[2], raw[1]);
02088     }
02089     break;
02090 
02091   case RAWFMT_TEMP10X:
02092     // ten times temperature in Celsius
02093     s = strprintf("%d.%d", word[0]/10, word[0]%10);
02094     break;
02095 
02096   default:
02097     s = "?"; // Should not happen
02098     break;
02099   }
02100 
02101   return s;
02102 }
02103 
02104 // Attribute names shouldn't be longer than 23 chars, otherwise they break the
02105 // output of smartctl.
02106 static const char * get_default_attr_name(unsigned char id, int rpm)
02107 {
02108   bool hdd = (rpm > 1), ssd = (rpm == 1);
02109 
02110   static const char Unknown_HDD_Attribute[] = "Unknown_HDD_Attribute";
02111   static const char Unknown_SSD_Attribute[] = "Unknown_SSD_Attribute";
02112 
02113   switch (id) {
02114   case 1:
02115     return "Raw_Read_Error_Rate";
02116   case 2:
02117     return "Throughput_Performance";
02118   case 3:
02119     return "Spin_Up_Time";
02120   case 4:
02121     return "Start_Stop_Count";
02122   case 5:
02123     return "Reallocated_Sector_Ct";
02124   case 6:
02125     if (ssd) return Unknown_SSD_Attribute;
02126     return "Read_Channel_Margin";
02127   case 7:
02128     if (ssd) return Unknown_SSD_Attribute;
02129     return "Seek_Error_Rate";
02130   case 8:
02131     if (ssd) return Unknown_SSD_Attribute;
02132     return "Seek_Time_Performance";
02133   case 9:
02134     return "Power_On_Hours";
02135   case 10:
02136     if (ssd) return Unknown_SSD_Attribute;
02137     return "Spin_Retry_Count";
02138   case 11:
02139     if (ssd) return Unknown_SSD_Attribute;
02140     return "Calibration_Retry_Count";
02141   case 12:
02142     return "Power_Cycle_Count";
02143   case 13:
02144     return "Read_Soft_Error_Rate";
02145   case 175:
02146     if (hdd) return Unknown_HDD_Attribute;
02147     return "Program_Fail_Count_Chip";
02148   case 176:
02149     if (hdd) return Unknown_HDD_Attribute;
02150     return "Erase_Fail_Count_Chip";
02151   case 177:
02152     if (hdd) return Unknown_HDD_Attribute;
02153     return "Wear_Leveling_Count";
02154   case 178:
02155     if (hdd) return Unknown_HDD_Attribute;
02156     return "Used_Rsvd_Blk_Cnt_Chip";
02157   case 179:
02158     if (hdd) return Unknown_HDD_Attribute;
02159     return "Used_Rsvd_Blk_Cnt_Tot";
02160   case 180:
02161     if (hdd) return Unknown_HDD_Attribute;
02162     return "Unused_Rsvd_Blk_Cnt_Tot";
02163   case 181:
02164     return "Program_Fail_Cnt_Total";
02165   case 182:
02166     if (hdd) return Unknown_HDD_Attribute;
02167     return "Erase_Fail_Count_Total";
02168   case 183:
02169     return "Runtime_Bad_Block";
02170   case 184:
02171     return "End-to-End_Error";
02172   case 187:
02173     return "Reported_Uncorrect";
02174   case 188:
02175     return "Command_Timeout";
02176   case 189:
02177     if (ssd) return Unknown_SSD_Attribute;
02178     return "High_Fly_Writes";
02179   case 190:
02180     // Western Digital uses this for temperature.
02181     // It's identical to Attribute 194 except that it
02182     // has a failure threshold set to correspond to the
02183     // max allowed operating temperature of the drive, which 
02184     // is typically 55C.  So if this attribute has failed
02185     // in the past, it indicates that the drive temp exceeded
02186     // 55C sometime in the past.
02187     return "Airflow_Temperature_Cel";
02188   case 191:
02189     if (ssd) return Unknown_SSD_Attribute;
02190     return "G-Sense_Error_Rate";
02191   case 192:
02192     return "Power-Off_Retract_Count";
02193   case 193:
02194     if (ssd) return Unknown_SSD_Attribute;
02195     return "Load_Cycle_Count";
02196   case 194:
02197     return "Temperature_Celsius";
02198   case 195:
02199     // Fujitsu: "ECC_On_The_Fly_Count";
02200     return "Hardware_ECC_Recovered";
02201   case 196:
02202     return "Reallocated_Event_Count";
02203   case 197:
02204     return "Current_Pending_Sector";
02205   case 198:
02206     return "Offline_Uncorrectable";
02207   case 199:
02208     return "UDMA_CRC_Error_Count";
02209   case 200:
02210     if (ssd) return Unknown_SSD_Attribute;
02211     // Western Digital
02212     return "Multi_Zone_Error_Rate";
02213   case 201:
02214     if (ssd) return Unknown_SSD_Attribute;
02215     return "Soft_Read_Error_Rate";
02216   case 202:
02217     if (ssd) return Unknown_SSD_Attribute;
02218     // Fujitsu: "TA_Increase_Count"
02219     return "Data_Address_Mark_Errs";
02220   case 203:
02221     // Fujitsu
02222     return "Run_Out_Cancel";
02223     // Maxtor: ECC Errors
02224   case 204:
02225     // Fujitsu: "Shock_Count_Write_Opern"
02226     return "Soft_ECC_Correction";
02227   case 205:
02228     // Fujitsu: "Shock_Rate_Write_Opern"
02229     return "Thermal_Asperity_Rate";
02230   case 206:
02231     // Fujitsu
02232     if (ssd) return Unknown_SSD_Attribute;
02233     return "Flying_Height";
02234   case 207:
02235     // Maxtor
02236     if (ssd) return Unknown_SSD_Attribute;
02237     return "Spin_High_Current";
02238   case 208:
02239     // Maxtor
02240     if (ssd) return Unknown_SSD_Attribute;
02241     return "Spin_Buzz";
02242   case 209:
02243     // Maxtor
02244     if (ssd) return Unknown_SSD_Attribute;
02245     return "Offline_Seek_Performnce";
02246   case 220:
02247     if (ssd) return Unknown_SSD_Attribute;
02248     return "Disk_Shift";
02249   case 221:
02250     if (ssd) return Unknown_SSD_Attribute;
02251     return "G-Sense_Error_Rate";
02252   case 222:
02253     if (ssd) return Unknown_SSD_Attribute;
02254     return "Loaded_Hours";
02255   case 223:
02256     if (ssd) return Unknown_SSD_Attribute;
02257     return "Load_Retry_Count";
02258   case 224:
02259     if (ssd) return Unknown_SSD_Attribute;
02260     return "Load_Friction";
02261   case 225:
02262     if (ssd) return Unknown_SSD_Attribute;
02263     return "Load_Cycle_Count";
02264   case 226:
02265     if (ssd) return Unknown_SSD_Attribute;
02266     return "Load-in_Time";
02267   case 227:
02268     if (ssd) return Unknown_SSD_Attribute;
02269     return "Torq-amp_Count";
02270   case 228:
02271     return "Power-off_Retract_Count";
02272   case 230:
02273     // seen in IBM DTPA-353750
02274     if (ssd) return Unknown_SSD_Attribute;
02275     return "Head_Amplitude";
02276   case 231:
02277     return "Temperature_Celsius";
02278   case 232:
02279     // seen in Intel X25-E SSD
02280     return "Available_Reservd_Space";
02281   case 233:
02282     // seen in Intel X25-E SSD
02283     if (hdd) return Unknown_HDD_Attribute;
02284     return "Media_Wearout_Indicator";
02285   case 240:
02286     if (ssd) return Unknown_SSD_Attribute;
02287     return "Head_Flying_Hours";
02288   case 241:
02289     return "Total_LBAs_Written";
02290   case 242:
02291     return "Total_LBAs_Read";
02292   case 250:
02293     return "Read_Error_Retry_Rate";
02294   case 254:
02295     if (ssd) return Unknown_SSD_Attribute;
02296     return "Free_Fall_Sensor";
02297   default:
02298     return "Unknown_Attribute";
02299   }
02300 }
02301 
02302 // Get attribute name
02303 std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs,
02304                                     int rpm /* = 0 */)
02305 {
02306   if (!defs[id].name.empty())
02307     return defs[id].name;
02308   else
02309     return get_default_attr_name(id, rpm);
02310 }
02311 
02312 // Find attribute index for attribute id, -1 if not found.
02313 int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval)
02314 {
02315   if (!id)
02316     return -1;
02317   for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
02318     if (smartval.vendor_attributes[i].id == id)
02319       return i;
02320   }
02321   return -1;
02322 }
02323 
02324 // Return Temperature Attribute raw value selected according to possible
02325 // non-default interpretations. If the Attribute does not exist, return 0
02326 unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs)
02327 {
02328   for (int i = 0; i < 4; i++) {
02329     static const unsigned char ids[4] = {194, 190, 9, 220};
02330     unsigned char id = ids[i];
02331     const ata_attr_raw_format format = defs[id].raw_format;
02332     if (!(   ((id == 194 || id == 190) && format == RAWFMT_DEFAULT)
02333           || format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X))
02334       continue;
02335     int idx = ata_find_attr_index(id, *data);
02336     if (idx < 0)
02337       continue;
02338     uint64_t raw = ata_get_attr_raw_value(data->vendor_attributes[idx], defs);
02339     unsigned temp;
02340     // ignore possible min/max values in high words
02341     if (format == RAWFMT_TEMP10X) // -v N,temp10x
02342       temp = ((unsigned short)raw + 5) / 10;
02343     else
02344       temp = (unsigned char)raw;
02345     if (!(0 < temp && temp < 128))
02346       continue;
02347     return temp;
02348   }
02349   // No valid attribute found
02350   return 0;
02351 }
02352 
02353 
02354 // Read SCT Status
02355 int ataReadSCTStatus(ata_device * device, ata_sct_status_response * sts)
02356 {
02357   // read SCT status via SMART log 0xe0
02358   memset(sts, 0, sizeof(*sts));
02359   if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){
02360     pout("Read SCT Status failed: %s\n", device->get_errmsg());
02361     return -1;
02362   }
02363 
02364   // swap endian order if needed
02365   if (isbigendian()){
02366     swapx(&sts->format_version);
02367     swapx(&sts->sct_version);
02368     swapx(&sts->sct_spec);
02369     swapx(&sts->ext_status_code);
02370     swapx(&sts->action_code);
02371     swapx(&sts->function_code);
02372     swapx(&sts->over_limit_count);
02373     swapx(&sts->under_limit_count);
02374   }
02375 
02376   // Check format version
02377   if (!(sts->format_version == 2 || sts->format_version == 3)) {
02378     pout("Unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version);
02379     return -1;
02380   }
02381   return 0;
02382 }
02383 
02384 // Read SCT Temperature History Table and Status
02385 int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table * tmh,
02386                        ata_sct_status_response * sts)
02387 {
02388   // Check initial status
02389   if (ataReadSCTStatus(device, sts))
02390     return -1;
02391 
02392   // Do nothing if other SCT command is executing
02393   if (sts->ext_status_code == 0xffff) {
02394     pout("Another SCT command is executing, abort Read Data Table\n"
02395          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
02396       sts->ext_status_code, sts->action_code, sts->function_code);
02397     return -1;
02398   }
02399 
02400   ata_sct_data_table_command cmd; memset(&cmd, 0, sizeof(cmd));
02401   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
02402   cmd.action_code   = 5; // Data table command
02403   cmd.function_code = 1; // Read table
02404   cmd.table_id      = 2; // Temperature History Table
02405 
02406   // swap endian order if needed
02407   if (isbigendian()) {
02408     swapx(&cmd.action_code);
02409     swapx(&cmd.function_code);
02410     swapx(&cmd.table_id);
02411   }
02412 
02413   // write command via SMART log page 0xe0
02414   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
02415     pout("Write SCT Data Table failed: %s\n", device->get_errmsg());
02416     return -1;
02417   }
02418 
02419   // read SCT data via SMART log page 0xe1
02420   memset(tmh, 0, sizeof(*tmh));
02421   if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){
02422     pout("Read SCT Data Table failed: %s\n", device->get_errmsg());
02423     return -1;
02424   }
02425 
02426   // re-read and check SCT status
02427   if (ataReadSCTStatus(device, sts))
02428     return -1;
02429 
02430   if (!(sts->ext_status_code == 0 && sts->action_code == 5 && sts->function_code == 1)) {
02431     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
02432       sts->ext_status_code, sts->action_code, sts->function_code);
02433     return -1;
02434   }
02435 
02436   // swap endian order if needed
02437   if (isbigendian()){
02438     swapx(&tmh->format_version);
02439     swapx(&tmh->sampling_period);
02440     swapx(&tmh->interval);
02441     swapx(&tmh->cb_index);
02442     swapx(&tmh->cb_size);
02443   }
02444   return 0;
02445 }
02446 
02447 // Get/Set Write Cache Reordering
02448 int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool persistent, bool set)
02449 {
02450   // Check initial status
02451   ata_sct_status_response sts;
02452   if (ataReadSCTStatus(device, &sts))
02453     return -1;
02454 
02455   // Do nothing if other SCT command is executing
02456   if (sts.ext_status_code == 0xffff) {
02457     pout("Another SCT command is executing, abort Feature Control\n"
02458          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
02459       sts.ext_status_code, sts.action_code, sts.function_code);
02460     return -1;
02461   }
02462 
02463   ata_sct_feature_control_command cmd; memset(&cmd, 0, sizeof(cmd));
02464   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
02465   cmd.action_code   = 4; // Feature Control command
02466   cmd.function_code  = (set ? 1 : 2); // 1=Set, 2=Get
02467   cmd.feature_code  = 2; //  Enable/Disable Write Cache Reordering 
02468   cmd.state         = (enable ? 1 : 2); // 1 enable, 2 disable
02469   cmd.option_flags  = (persistent ? 0x01 : 0x00);
02470 
02471   // swap endian order if needed
02472   if (isbigendian()) {
02473     swapx(&cmd.action_code);
02474     swapx(&cmd.function_code);
02475     swapx(&cmd.feature_code);
02476     swapx(&cmd.state);
02477     swapx(&cmd.option_flags);
02478   }
02479 
02480   // write command via SMART log page 0xe0
02481   // TODO: Debug output
02482   ata_cmd_in in;
02483   in.in_regs.command = ATA_SMART_CMD;
02484   in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
02485   in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
02486   in.in_regs.lba_low = 0xe0;
02487   in.set_data_out(&cmd, 1);
02488 
02489   if (!set)
02490     // Time limit returned in ATA registers
02491     in.out_needed.sector_count = in.out_needed.lba_low = true;
02492 
02493   ata_cmd_out out;
02494   if (!device->ata_pass_through(in, out)) {
02495     pout("Write SCT (%cet) Feature Control Command failed: %s\n",
02496       (!set ? 'G' : 'S'), device->get_errmsg());
02497     return -1;
02498   }
02499   int state = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
02500 
02501   // re-read and check SCT status
02502   if (ataReadSCTStatus(device, &sts))
02503     return -1;
02504 
02505   if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == (set ? 1 : 2))) {
02506     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
02507       sts.ext_status_code, sts.action_code, sts.function_code);
02508     return -1;
02509   }
02510   return state;
02511 }
02512 
02513 
02514 // Set SCT Temperature Logging Interval
02515 int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent)
02516 {
02517   // Check initial status
02518   ata_sct_status_response sts;
02519   if (ataReadSCTStatus(device, &sts))
02520     return -1;
02521 
02522   // Do nothing if other SCT command is executing
02523   if (sts.ext_status_code == 0xffff) {
02524     pout("Another SCT command is executing, abort Feature Control\n"
02525          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
02526       sts.ext_status_code, sts.action_code, sts.function_code);
02527     return -1;
02528   }
02529 
02530   ata_sct_feature_control_command cmd; memset(&cmd, 0, sizeof(cmd));
02531   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
02532   cmd.action_code   = 4; // Feature Control command
02533   cmd.function_code = 1; // Set state
02534   cmd.feature_code  = 3; // Temperature logging interval
02535   cmd.state         = interval;
02536   cmd.option_flags  = (persistent ? 0x01 : 0x00);
02537 
02538   // swap endian order if needed
02539   if (isbigendian()) {
02540     swapx(&cmd.action_code);
02541     swapx(&cmd.function_code);
02542     swapx(&cmd.feature_code);
02543     swapx(&cmd.state);
02544     swapx(&cmd.option_flags);
02545   }
02546 
02547   // write command via SMART log page 0xe0
02548   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
02549     pout("Write SCT Feature Control Command failed: %s\n", device->get_errmsg());
02550     return -1;
02551   }
02552 
02553   // re-read and check SCT status
02554   if (ataReadSCTStatus(device, &sts))
02555     return -1;
02556 
02557   if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == 1)) {
02558     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
02559       sts.ext_status_code, sts.action_code, sts.function_code);
02560     return -1;
02561   }
02562   return 0;
02563 }
02564 
02565 // Get/Set SCT Error Recovery Control
02566 static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned type,
02567                                                 bool set, unsigned short & time_limit)
02568 {
02569   // Check initial status
02570   ata_sct_status_response sts;
02571   if (ataReadSCTStatus(device, &sts))
02572     return -1;
02573 
02574   // Do nothing if other SCT command is executing
02575   if (sts.ext_status_code == 0xffff) {
02576     pout("Another SCT command is executing, abort Error Recovery Control\n"
02577          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
02578       sts.ext_status_code, sts.action_code, sts.function_code);
02579     return -1;
02580   }
02581 
02582   ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd));
02583   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
02584   cmd.action_code    = 3; // Error Recovery Control command
02585   cmd.function_code  = (set ? 1 : 2); // 1=Set timer, 2=Get timer
02586   cmd.selection_code = type; // 1=Read timer, 2=Write timer
02587   if (set)
02588     cmd.time_limit   = time_limit;
02589 
02590   // swap endian order if needed
02591   if (isbigendian()) {
02592     swapx(&cmd.action_code);
02593     swapx(&cmd.function_code);
02594     swapx(&cmd.selection_code);
02595     swapx(&cmd.time_limit);
02596   }
02597 
02598   // write command via SMART log page 0xe0
02599   // TODO: Debug output
02600   ata_cmd_in in;
02601   in.in_regs.command = ATA_SMART_CMD;
02602   in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
02603   in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
02604   in.in_regs.lba_low = 0xe0;
02605   in.set_data_out(&cmd, 1);
02606 
02607   if (!set)
02608     // Time limit returned in ATA registers
02609     in.out_needed.sector_count = in.out_needed.lba_low = true;
02610 
02611   ata_cmd_out out;
02612   if (!device->ata_pass_through(in, out)) {
02613     pout("Write SCT (%cet) Error Recovery Control Command failed: %s\n",
02614       (!set ? 'G' : 'S'), device->get_errmsg());
02615     return -1;
02616   }
02617 
02618   // re-read and check SCT status
02619   if (ataReadSCTStatus(device, &sts))
02620     return -1;
02621 
02622   if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) {
02623     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
02624       sts.ext_status_code, sts.action_code, sts.function_code);
02625     return -1;
02626   }
02627 
02628   if (!set) {
02629     // Check whether registers are properly returned by ioctl()
02630     if (!(out.out_regs.sector_count.is_set() && out.out_regs.lba_low.is_set())) {
02631       // TODO: Output register support should be checked within each ata_pass_through()
02632       // implementation before command is issued.
02633       pout("SMART WRITE LOG does not return COUNT and LBA_LOW register\n");
02634       return -1;
02635     }
02636     if (   out.out_regs.sector_count == in.in_regs.sector_count
02637         && out.out_regs.lba_low      == in.in_regs.lba_low     ) {
02638       // 0xe001 (5734.5s) - this is most likely a broken ATA pass-through implementation
02639       pout("SMART WRITE LOG returns COUNT and LBA_LOW register unchanged\n");
02640       return -1;
02641     }
02642 
02643     // Return value to caller
02644     time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
02645   }
02646 
02647   return 0;
02648 }
02649 
02650 // Get SCT Error Recovery Control
02651 int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit)
02652 {
02653   return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit);
02654 }
02655 
02656 // Set SCT Error Recovery Control
02657 int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit)
02658 {
02659   return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit);
02660 }
02661 
02662 
02663 // Print one self-test log entry.
02664 // Returns:
02665 // -1: self-test failed
02666 //  1: extended self-test completed without error
02667 //  0: otherwise
02668 int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
02669                                unsigned char test_status,
02670                                unsigned short timestamp,
02671                                uint64_t failing_lba,
02672                                bool print_error_only, bool & print_header)
02673 {
02674   // Check status and type for return value
02675   int retval = 0;
02676   switch (test_status >> 4) {
02677     case 0x0:
02678       if ((test_type & 0x0f) == 0x02)
02679         retval = 1; // extended self-test completed without error
02680       break;
02681     case 0x3: case 0x4:
02682     case 0x5: case 0x6:
02683     case 0x7: case 0x8:
02684       retval = -1; // self-test failed
02685       break;
02686   }
02687 
02688   if (retval >= 0 && print_error_only)
02689     return retval;
02690 
02691   std::string msgtest;
02692   switch (test_type) {
02693     case 0x00: msgtest = "Offline";            break;
02694     case 0x01: msgtest = "Short offline";      break;
02695     case 0x02: msgtest = "Extended offline";   break;
02696     case 0x03: msgtest = "Conveyance offline"; break;
02697     case 0x04: msgtest = "Selective offline";  break;
02698     case 0x7f: msgtest = "Abort offline test"; break;
02699     case 0x81: msgtest = "Short captive";      break;
02700     case 0x82: msgtest = "Extended captive";   break;
02701     case 0x83: msgtest = "Conveyance captive"; break;
02702     case 0x84: msgtest = "Selective captive";  break;
02703     default:
02704       if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
02705         msgtest = strprintf("Vendor (0x%02x)", test_type);
02706       else
02707         msgtest = strprintf("Reserved (0x%02x)", test_type);
02708   }
02709 
02710   std::string msgstat;
02711   switch (test_status >> 4) {
02712     case 0x0: msgstat = "Completed without error";       break;
02713     case 0x1: msgstat = "Aborted by host";               break;
02714     case 0x2: msgstat = "Interrupted (host reset)";      break;
02715     case 0x3: msgstat = "Fatal or unknown error";        break;
02716     case 0x4: msgstat = "Completed: unknown failure";    break;
02717     case 0x5: msgstat = "Completed: electrical failure"; break;
02718     case 0x6: msgstat = "Completed: servo/seek failure"; break;
02719     case 0x7: msgstat = "Completed: read failure";       break;
02720     case 0x8: msgstat = "Completed: handling damage??";  break;
02721     case 0xf: msgstat = "Self-test routine in progress"; break;
02722     default:  msgstat = strprintf("Unknown status (0x%x)", test_status >> 4);
02723   }
02724 
02725   // Print header once
02726   if (print_header) {
02727     print_header = false;
02728     pout("Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
02729   }
02730 
02731   char msglba[32];
02732   if (retval < 0 && failing_lba < 0xffffffffffffULL)
02733     snprintf(msglba, sizeof(msglba), "%" PRIu64, failing_lba);
02734   else {
02735     msglba[0] = '-'; msglba[1] = 0;
02736   }
02737 
02738   pout("#%2u  %-19s %-29s %1d0%%  %8u         %s\n", testnum,
02739        msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
02740 
02741   return retval;
02742 }
02743 
02744 // Print Smart self-test log, used by smartctl and smartd.
02745 // return value is:
02746 // bottom 8 bits: number of entries found where self-test showed an error
02747 // remaining bits: if nonzero, power on hours of last self-test where error was found
02748 int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
02749                              firmwarebug_defs firmwarebugs)
02750 {
02751   if (allentries)
02752     pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber);
02753   if (data->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG))
02754     pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
02755   if (data->mostrecenttest==0){
02756     if (allentries)
02757       pout("No self-tests have been logged.  [To run self-tests, use: smartctl -t]\n\n");
02758     return 0;
02759   }
02760 
02761   bool noheaderprinted = true;
02762   int errcnt = 0, hours = 0, igncnt = 0;
02763   int testno = 0, ext_ok_testno = -1;
02764 
02765   // print log
02766   for (int i = 20; i >= 0; i--) {
02767     // log is a circular buffer
02768     int j = (i+data->mostrecenttest)%21;
02769     const ata_smart_selftestlog_struct * log = data->selftest_struct+j;
02770 
02771     if (nonempty(log, sizeof(*log))) {
02772       // count entry based on non-empty structures -- needed for
02773       // Seagate only -- other vendors don't have blank entries 'in
02774       // the middle'
02775       testno++;
02776 
02777       // T13/1321D revision 1c: (Data structure Rev #1)
02778 
02779       //The failing LBA shall be the LBA of the uncorrectable sector
02780       //that caused the test to fail. If the device encountered more
02781       //than one uncorrectable sector during the test, this field
02782       //shall indicate the LBA of the first uncorrectable sector
02783       //encountered. If the test passed or the test failed for some
02784       //reason other than an uncorrectable sector, the value of this
02785       //field is undefined.
02786 
02787       // This is true in ALL ATA-5 specs
02788       uint64_t lba48 = (log->lbafirstfailure < 0xffffffff ? log->lbafirstfailure : 0xffffffffffffULL);
02789 
02790       // Print entry
02791       int state = ataPrintSmartSelfTestEntry(testno,
02792         log->selftestnumber, log->selfteststatus,
02793         log->timestamp, lba48, !allentries, noheaderprinted);
02794 
02795       if (state < 0) {
02796         // Self-test showed an error
02797         if (ext_ok_testno < 0) {
02798           errcnt++;
02799 
02800           // keep track of time of most recent error
02801           if (!hours)
02802             hours = log->timestamp;
02803         }
02804         else
02805           // Newer successful extended self-test exits
02806           igncnt++;
02807       }
02808       else if (state > 0 && ext_ok_testno < 0) {
02809         // Latest successful extended self-test
02810         ext_ok_testno = testno;
02811       }
02812     }
02813   }
02814 
02815   if (igncnt)
02816     pout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
02817       igncnt, igncnt+errcnt, ext_ok_testno);
02818 
02819   if (!allentries && !noheaderprinted)
02820     pout("\n");
02821 
02822   return ((hours << 8) | errcnt);
02823 }
02824 
02825 
02826 /////////////////////////////////////////////////////////////////////////////
02827 // Pseudo-device to parse "smartctl -r ataioctl,2 ..." output and simulate
02828 // an ATA device with same behaviour
02829 
02830 namespace {
02831 
02832 class parsed_ata_device
02833 : public /*implements*/ ata_device_with_command_set
02834 {
02835 public:
02836   parsed_ata_device(smart_interface * intf, const char * dev_name);
02837 
02838   virtual ~parsed_ata_device() throw();
02839 
02840   virtual bool is_open() const;
02841 
02842   virtual bool open();
02843 
02844   virtual bool close();
02845 
02846   virtual bool ata_identify_is_cached() const;
02847 
02848 protected:
02849   virtual int ata_command_interface(smart_command_set command, int select, char * data);
02850 
02851 private:
02852   // Table of parsed commands, return value, data
02853   struct parsed_ata_command
02854   {
02855     smart_command_set command;
02856     int select;
02857     int retval, errval;
02858     char * data;
02859   };
02860 
02861   enum { max_num_commands = 32 };
02862   parsed_ata_command m_command_table[max_num_commands];
02863 
02864   int m_num_commands;
02865   int m_next_replay_command;
02866   bool m_replay_out_of_sync;
02867   bool m_ata_identify_is_cached;
02868 };
02869 
02870 static const char * nextline(const char * s, int & lineno)
02871 {
02872   for (s += strcspn(s, "\r\n"); *s == '\r' || *s == '\n'; s++) {
02873     if (*s == '\r' && s[1] == '\n')
02874       s++;
02875     lineno++;
02876   }
02877   return s;
02878 }
02879 
02880 static int name2command(const char * s)
02881 {
02882   for (int i = 0; i < (int)(sizeof(commandstrings)/sizeof(commandstrings[0])); i++) {
02883     if (!strcmp(s, commandstrings[i]))
02884       return i;
02885   }
02886   return -1;
02887 }
02888 
02889 static bool matchcpy(char * dest, size_t size, const char * src, const regmatch_t & srcmatch)
02890 {
02891   if (srcmatch.rm_so < 0)
02892     return false;
02893   size_t n = srcmatch.rm_eo - srcmatch.rm_so;
02894   if (n >= size)
02895     n = size-1;
02896   memcpy(dest, src + srcmatch.rm_so, n);
02897   dest[n] = 0;
02898   return true;
02899 }
02900 
02901 static inline int matchtoi(const char * src, const regmatch_t & srcmatch, int defval)
02902 {
02903   if (srcmatch.rm_so < 0)
02904     return defval;
02905   return atoi(src + srcmatch.rm_so);
02906 }
02907 
02908 parsed_ata_device::parsed_ata_device(smart_interface * intf, const char * dev_name)
02909 : smart_device(intf, dev_name, "ata", ""),
02910   m_num_commands(0),
02911   m_next_replay_command(0),
02912   m_replay_out_of_sync(false),
02913   m_ata_identify_is_cached(false)
02914 {
02915   memset(m_command_table, 0, sizeof(m_command_table));
02916 }
02917 
02918 parsed_ata_device::~parsed_ata_device() throw()
02919 {
02920   close();
02921 }
02922 
02923 bool parsed_ata_device::is_open() const
02924 {
02925   return (m_num_commands > 0);
02926 }
02927 
02928 // Parse stdin and build command table
02929 bool parsed_ata_device::open()
02930 {
02931   const char * pathname = get_dev_name();
02932   if (strcmp(pathname, "-"))
02933     return set_err(EINVAL);
02934   pathname = "<stdin>";
02935   // Fill buffer
02936   char buffer[64*1024];
02937   int size = 0;
02938   while (size < (int)sizeof(buffer)) {
02939     int nr = fread(buffer, 1, sizeof(buffer), stdin);
02940     if (nr <= 0)
02941       break;
02942     size += nr;
02943   }
02944   if (size <= 0)
02945     return set_err(ENOENT, "%s: Unexpected EOF", pathname);
02946   if (size >= (int)sizeof(buffer))
02947     return set_err(EIO, "%s: Buffer overflow", pathname);
02948   buffer[size] = 0;
02949 
02950   // Regex to match output from "-r ataioctl,2"
02951   static const char pattern[] = "^"
02952   "(" // (1
02953     "REPORT-IOCTL: DeviceF?D?=[^ ]+ Command=([A-Z ]*[A-Z])" // (2)
02954     "(" // (3
02955       "( InputParameter=([0-9]+))?" // (4 (5))
02956     "|"
02957       "( returned (-?[0-9]+)( errno=([0-9]+)[^\r\n]*)?)" // (6 (7) (8 (9)))
02958     ")" // )
02959     "[\r\n]" // EOL match necessary to match optional parts above
02960   "|"
02961     "===== \\[([A-Z ]*[A-Z])\\] DATA START " // (10)
02962   "|"
02963     "    *(En|Dis)abled status cached by OS, " // (11)
02964   ")"; // )
02965 
02966   // Compile regex
02967   const regular_expression regex(pattern, REG_EXTENDED);
02968 
02969   // Parse buffer
02970   const char * errmsg = 0;
02971   int i = -1, state = 0, lineno = 1;
02972   for (const char * line = buffer; *line; line = nextline(line, lineno)) {
02973     // Match line
02974     if (!(line[0] == 'R' || line[0] == '=' || line[0] == ' '))
02975       continue;
02976     const int nmatch = 1+11;
02977     regmatch_t match[nmatch];
02978     if (!regex.execute(line, nmatch, match))
02979       continue;
02980 
02981     char cmdname[40];
02982     if (matchcpy(cmdname, sizeof(cmdname), line, match[2])) { // "REPORT-IOCTL:... Command=%s ..."
02983       int nc = name2command(cmdname);
02984       if (nc < 0) {
02985         errmsg = "Unknown ATA command name"; break;
02986       }
02987       if (match[7].rm_so < 0) { // "returned %d"
02988         // Start of command
02989         if (!(state == 0 || state == 2)) {
02990           errmsg = "Missing REPORT-IOCTL result"; break;
02991         }
02992         if (++i >= max_num_commands) {
02993           errmsg = "Too many ATA commands"; break;
02994         }
02995         m_command_table[i].command = (smart_command_set)nc;
02996         m_command_table[i].select = matchtoi(line, match[5], 0); // "InputParameter=%d"
02997         state = 1;
02998       }
02999       else {
03000         // End of command
03001         if (!(state == 1 && (int)m_command_table[i].command == nc)) {
03002           errmsg = "Missing REPORT-IOCTL start"; break;
03003         }
03004         m_command_table[i].retval = matchtoi(line, match[7], -1); // "returned %d"
03005         m_command_table[i].errval = matchtoi(line, match[9], 0); // "errno=%d"
03006         state = 2;
03007       }
03008     }
03009     else if (matchcpy(cmdname, sizeof(cmdname), line, match[10])) { // "===== [%s] DATA START "
03010       // Start of sector hexdump
03011       int nc = name2command(cmdname);
03012       if (!(state == (nc == WRITE_LOG ? 1 : 2) && (int)m_command_table[i].command == nc)) {
03013           errmsg = "Unexpected DATA START"; break;
03014       }
03015       line = nextline(line, lineno);
03016       char * data = (char *)malloc(512);
03017       unsigned j;
03018       for (j = 0; j < 32; j++) {
03019         unsigned b[16];
03020         unsigned u1, u2; int n1 = -1;
03021         if (!(sscanf(line, "%3u-%3u: "
03022                         "%2x %2x %2x %2x %2x %2x %2x %2x "
03023                         "%2x %2x %2x %2x %2x %2x %2x %2x%n",
03024                      &u1, &u2,
03025                      b+ 0, b+ 1, b+ 2, b+ 3, b+ 4, b+ 5, b+ 6, b+ 7,
03026                      b+ 8, b+ 9, b+10, b+11, b+12, b+13, b+14, b+15, &n1) == 18
03027               && n1 >= 56 && u1 == j*16 && u2 == j*16+15))
03028           break;
03029         for (unsigned k = 0; k < 16; k++)
03030           data[j*16+k] = b[k];
03031         line = nextline(line, lineno);
03032       }
03033       if (j < 32) {
03034         free(data);
03035         errmsg = "Incomplete sector hex dump"; break;
03036       }
03037       m_command_table[i].data = data;
03038       if (nc != WRITE_LOG)
03039         state = 0;
03040     }
03041     else if (match[11].rm_so > 0) { // "(En|Dis)abled status cached by OS"
03042       m_ata_identify_is_cached = true;
03043     }
03044   }
03045 
03046   if (!(state == 0 || state == 2))
03047     errmsg = "Missing REPORT-IOCTL result";
03048 
03049   if (!errmsg && i < 0)
03050     errmsg = "No information found";
03051 
03052   m_num_commands = i+1;
03053   m_next_replay_command = 0;
03054   m_replay_out_of_sync = false;
03055 
03056   if (errmsg) {
03057     close();
03058     return set_err(EIO, "%s(%d): Syntax error: %s", pathname, lineno, errmsg);
03059   }
03060   return true;
03061 }
03062 
03063 // Report warnings and free command table 
03064 bool parsed_ata_device::close()
03065 {
03066   if (m_replay_out_of_sync)
03067       pout("REPLAY-IOCTL: Warning: commands replayed out of sync\n");
03068   else if (m_next_replay_command != 0)
03069       pout("REPLAY-IOCTL: Warning: %d command(s) not replayed\n", m_num_commands-m_next_replay_command);
03070 
03071   for (int i = 0; i < m_num_commands; i++) {
03072     if (m_command_table[i].data) {
03073       free(m_command_table[i].data); m_command_table[i].data = 0;
03074     }
03075   }
03076   m_num_commands = 0;
03077   m_next_replay_command = 0;
03078   m_replay_out_of_sync = false;
03079   return true;
03080 }
03081 
03082 
03083 bool parsed_ata_device::ata_identify_is_cached() const
03084 {
03085   return m_ata_identify_is_cached;
03086 }
03087 
03088 
03089 // Simulate ATA command from command table
03090 int parsed_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
03091 {
03092   // Find command, try round-robin if out of sync
03093   int i = m_next_replay_command;
03094   for (int j = 0; ; j++) {
03095     if (j >= m_num_commands) {
03096       pout("REPLAY-IOCTL: Warning: Command not found\n");
03097       errno = ENOSYS;
03098       return -1;
03099     }
03100     if (m_command_table[i].command == command && m_command_table[i].select == select)
03101       break;
03102     if (!m_replay_out_of_sync) {
03103       m_replay_out_of_sync = true;
03104       pout("REPLAY-IOCTL: Warning: Command #%d is out of sync\n", i+1);
03105     }
03106     if (++i >= m_num_commands)
03107       i = 0;
03108   }
03109   m_next_replay_command = i;
03110   if (++m_next_replay_command >= m_num_commands)
03111     m_next_replay_command = 0;
03112 
03113   // Return command data
03114   switch (command) {
03115     case IDENTIFY:
03116     case PIDENTIFY:
03117     case READ_VALUES:
03118     case READ_THRESHOLDS:
03119     case READ_LOG:
03120       if (m_command_table[i].data)
03121         memcpy(data, m_command_table[i].data, 512);
03122       break;
03123     case WRITE_LOG:
03124       if (!(m_command_table[i].data && !memcmp(data, m_command_table[i].data, 512)))
03125         pout("REPLAY-IOCTL: Warning: WRITE LOG data does not match\n");
03126       break;
03127     case CHECK_POWER_MODE:
03128       data[0] = (char)0xff;
03129     default:
03130       break;
03131   }
03132 
03133   if (m_command_table[i].errval)
03134     errno = m_command_table[i].errval;
03135   return m_command_table[i].retval;
03136 }
03137 
03138 } // namespace
03139 
03140 ata_device * get_parsed_ata_device(smart_interface * intf, const char * dev_name)
03141 {
03142   return new parsed_ata_device(intf, dev_name);
03143 }