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-13 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 3777 2013-02-19 18:32:15Z samm2 $"
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 
01480     for (unsigned i = 0; i < nsectors; i++) {
01481       for (unsigned j = 0; j < 4; j++)
01482         swapx(&log->error_logs[i].commands[j].timestamp);
01483       swapx(&log->error_logs[i].error.timestamp);
01484     }
01485   }
01486 
01487   if (firmwarebugs.is_set(BUG_XERRORLBA))
01488     fix_exterrlog_lba(log, nsectors);
01489 
01490   return true;
01491 }
01492 
01493 
01494 int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt *data){
01495   
01496   // get data from device
01497   if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){
01498     return -1;
01499   }
01500   
01501   // compute its checksum, and issue a warning if needed
01502   if (checksum(data))
01503     checksumwarning("SMART Attribute Thresholds Structure");
01504   
01505   // swap endian order if needed
01506   if (isbigendian())
01507     swap2((char *)&(data->revnumber));
01508 
01509   return 0;
01510 }
01511 
01512 int ataEnableSmart (ata_device * device ){
01513   if (smartcommandhandler(device, ENABLE, 0, NULL)){
01514     return -1;
01515   }
01516   return 0;
01517 }
01518 
01519 int ataDisableSmart (ata_device * device ){
01520   
01521   if (smartcommandhandler(device, DISABLE, 0, NULL)){
01522     return -1;
01523   }  
01524   return 0;
01525 }
01526 
01527 int ataEnableAutoSave(ata_device * device){
01528   if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){
01529     return -1;
01530   }
01531   return 0;
01532 }
01533 
01534 int ataDisableAutoSave(ata_device * device){
01535   
01536   if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){
01537     return -1;
01538   }
01539   return 0;
01540 }
01541 
01542 // In *ALL* ATA standards the Enable/Disable AutoOffline command is
01543 // marked "OBSOLETE". It is defined in SFF-8035i Revision 2, and most
01544 // vendors still support it for backwards compatibility. IBM documents
01545 // it for some drives.
01546 int ataEnableAutoOffline (ata_device * device){
01547   
01548   /* timer hard coded to 4 hours */  
01549   if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){
01550     return -1;
01551   }
01552   return 0;
01553 }
01554 
01555 // Another Obsolete Command.  See comments directly above, associated
01556 // with the corresponding Enable command.
01557 int ataDisableAutoOffline (ata_device * device){
01558   
01559   if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){
01560     return -1;
01561   }
01562   return 0;
01563 }
01564 
01565 // If SMART is enabled, supported, and working, then this call is
01566 // guaranteed to return 1, else zero.  Note that it should return 1
01567 // regardless of whether the disk's SMART status is 'healthy' or
01568 // 'failing'.
01569 int ataDoesSmartWork(ata_device * device){
01570   int retval=smartcommandhandler(device, STATUS, 0, NULL);
01571 
01572   if (-1 == retval)
01573     return 0;
01574 
01575   return 1;
01576 }
01577 
01578 // This function uses a different interface (DRIVE_TASK) than the
01579 // other commands in this file.
01580 int ataSmartStatus2(ata_device * device){
01581   return smartcommandhandler(device, STATUS_CHECK, 0, NULL);  
01582 }
01583 
01584 // This is the way to execute ALL tests: offline, short self-test,
01585 // extended self test, with and without captive mode, etc.
01586 // TODO: Move to ataprint.cpp ?
01587 int ataSmartTest(ata_device * device, int testtype, bool force,
01588                  const ata_selective_selftest_args & selargs,
01589                  const ata_smart_values * sv, uint64_t num_sectors)
01590 {
01591   char cmdmsg[128]; const char *type, *captive;
01592   int cap, retval, select=0;
01593 
01594   // Boolean, if set, says test is captive
01595   cap=testtype & CAPTIVE_MASK;
01596 
01597   // Set up strings that describe the type of test
01598   if (cap)
01599     captive="captive";
01600   else
01601     captive="off-line";
01602   
01603   if (testtype==OFFLINE_FULL_SCAN)
01604     type="off-line";
01605   else  if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST)
01606     type="Short self-test";
01607   else if (testtype==EXTEND_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST)
01608     type="Extended self-test";
01609   else if (testtype==CONVEYANCE_SELF_TEST || testtype==CONVEYANCE_CAPTIVE_SELF_TEST)
01610     type="Conveyance self-test";
01611   else if ((select=(testtype==SELECTIVE_SELF_TEST || testtype==SELECTIVE_CAPTIVE_SELF_TEST)))
01612     type="Selective self-test";
01613   else
01614     type = 0;
01615 
01616   // Check whether another test is already running
01617   if (type && (sv->self_test_exec_status >> 4) == 0xf) {
01618     if (!force) {
01619       pout("Can't start self-test without aborting current test (%d0%% remaining),\n"
01620            "%srun 'smartctl -X' to abort test.\n",
01621            sv->self_test_exec_status & 0x0f,
01622            (!select ? "add '-t force' option to override, or " : ""));
01623       return -1;
01624     }
01625   }
01626   else
01627     force = false;
01628 
01629   // If doing a selective self-test, first use WRITE_LOG to write the
01630   // selective self-test log.
01631   ata_selective_selftest_args selargs_io = selargs; // filled with info about actual spans
01632   if (select && (retval = ataWriteSelectiveSelfTestLog(device, selargs_io, sv, num_sectors))) {
01633     if (retval==-4)
01634       pout("Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");
01635     return retval;
01636   }
01637 
01638   //  Print ouf message that we are sending the command to test
01639   if (testtype==ABORT_SELF_TEST)
01640     snprintf(cmdmsg, sizeof(cmdmsg), "Abort SMART off-line mode self-test routine");
01641   else if (!type)
01642     snprintf(cmdmsg, sizeof(cmdmsg), "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype);
01643   else
01644     snprintf(cmdmsg, sizeof(cmdmsg), "Execute SMART %s routine immediately in %s mode", type, captive);
01645   pout("Sending command: \"%s\".\n",cmdmsg);
01646 
01647   if (select) {
01648     int i;
01649     pout("SPAN         STARTING_LBA           ENDING_LBA\n");
01650     for (i = 0; i < selargs_io.num_spans; i++)
01651       pout("   %d %20"PRId64" %20"PRId64"\n", i,
01652            selargs_io.span[i].start,
01653            selargs_io.span[i].end);
01654   }
01655   
01656   // Now send the command to test
01657   if (smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL)) {
01658     if (!(cap && device->get_errno() == EIO)) {
01659       pout("Command \"%s\" failed: %s\n", cmdmsg, device->get_errmsg());
01660       return -1;
01661     }
01662   }
01663   
01664   // Since the command succeeded, tell user
01665   if (testtype==ABORT_SELF_TEST)
01666     pout("Self-testing aborted!\n");
01667   else {
01668     pout("Drive command \"%s\" successful.\n", cmdmsg);
01669     if (type)
01670       pout("Testing has begun%s.\n", (force ? " (previous test aborted)" : ""));
01671   }
01672   return 0;
01673 }
01674 
01675 /* Test Time Functions */
01676 int TestTime(const ata_smart_values *data, int testtype)
01677 {
01678   switch (testtype){
01679   case OFFLINE_FULL_SCAN:
01680     return (int) data->total_time_to_complete_off_line;
01681   case SHORT_SELF_TEST:
01682   case SHORT_CAPTIVE_SELF_TEST:
01683     return (int) data->short_test_completion_time;
01684   case EXTEND_SELF_TEST:
01685   case EXTEND_CAPTIVE_SELF_TEST:
01686     if (data->extend_test_completion_time_b == 0xff
01687         && data->extend_test_completion_time_w != 0x0000
01688         && data->extend_test_completion_time_w != 0xffff)
01689       return data->extend_test_completion_time_w; // ATA-8
01690     else
01691       return data->extend_test_completion_time_b;
01692   case CONVEYANCE_SELF_TEST:
01693   case CONVEYANCE_CAPTIVE_SELF_TEST:
01694     return (int) data->conveyance_test_completion_time;
01695   default:
01696     return 0;
01697   }
01698 }
01699 
01700 // This function tells you both about the ATA error log and the
01701 // self-test error log capability (introduced in ATA-5).  The bit is
01702 // poorly documented in the ATA/ATAPI standard.  Starting with ATA-6,
01703 // SMART error logging is also indicated in bit 0 of DEVICE IDENTIFY
01704 // word 84 and 87.  Top two bits must match the pattern 01. BEFORE
01705 // ATA-6 these top two bits still had to match the pattern 01, but the
01706 // remaining bits were reserved (==0).
01707 int isSmartErrorLogCapable (const ata_smart_values * data, const ata_identify_device * identity)
01708 {
01709   unsigned short word84=identity->command_set_extension;
01710   unsigned short word87=identity->csf_default;
01711   int isata6=identity->major_rev_num & (0x01<<6);
01712   int isata7=identity->major_rev_num & (0x01<<7);
01713 
01714   if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x01))
01715     return 1;
01716   
01717   if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x01))
01718     return 1;
01719   
01720   // otherwise we'll use the poorly documented capability bit
01721   return data->errorlog_capability & 0x01;
01722 }
01723 
01724 // See previous function.  If the error log exists then the self-test
01725 // log should (must?) also exist.
01726 int isSmartTestLogCapable (const ata_smart_values * data, const ata_identify_device *identity)
01727 {
01728   unsigned short word84=identity->command_set_extension;
01729   unsigned short word87=identity->csf_default;
01730   int isata6=identity->major_rev_num & (0x01<<6);
01731   int isata7=identity->major_rev_num & (0x01<<7);
01732 
01733   if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x02))
01734     return 1;
01735   
01736   if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x02))
01737     return 1;
01738 
01739 
01740   // otherwise we'll use the poorly documented capability bit
01741   return data->errorlog_capability & 0x01;
01742 }
01743 
01744 
01745 int isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
01746 {
01747   unsigned short word84=identity->command_set_extension;
01748   unsigned short word87=identity->csf_default;
01749 
01750   // If bit 14 of word 84 is set to one and bit 15 of word 84 is
01751   // cleared to zero, the contents of word 84 contains valid support
01752   // information. If not, support information is not valid in this
01753   // word.
01754   if ((word84>>14) == 0x01)
01755     // If bit 5 of word 84 is set to one, the device supports the
01756     // General Purpose Logging feature set.
01757     return (word84 & (0x01 << 5));
01758   
01759   // If bit 14 of word 87 is set to one and bit 15 of word 87 is
01760   // cleared to zero, the contents of words (87:85) contain valid
01761   // information. If not, information is not valid in these words.  
01762   if ((word87>>14) == 0x01)
01763     // If bit 5 of word 87 is set to one, the device supports
01764     // the General Purpose Logging feature set.
01765     return (word87 & (0x01 << 5));
01766 
01767   // not capable
01768   return 0;
01769 }
01770 
01771 
01772 // SMART self-test capability is also indicated in bit 1 of DEVICE
01773 // IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
01774 // However this was only introduced in ATA-6 (but self-test log was in
01775 // ATA-5).
01776 int isSupportExecuteOfflineImmediate(const ata_smart_values *data)
01777 {
01778   return data->offline_data_collection_capability & 0x01;
01779 }
01780 
01781 // Note in the ATA-5 standard, the following bit is listed as "Vendor
01782 // Specific".  So it may not be reliable. The only use of this that I
01783 // have found is in IBM drives, where it is well-documented.  See for
01784 // example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
01785 // hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
01786 int isSupportAutomaticTimer(const ata_smart_values * data)
01787 {
01788   return data->offline_data_collection_capability & 0x02;
01789 }
01790 int isSupportOfflineAbort(const ata_smart_values *data)
01791 {
01792   return data->offline_data_collection_capability & 0x04;
01793 }
01794 int isSupportOfflineSurfaceScan(const ata_smart_values * data)
01795 {
01796    return data->offline_data_collection_capability & 0x08;
01797 }
01798 int isSupportSelfTest (const ata_smart_values * data)
01799 {
01800    return data->offline_data_collection_capability & 0x10;
01801 }
01802 int isSupportConveyanceSelfTest(const ata_smart_values * data)
01803 {
01804    return data->offline_data_collection_capability & 0x20;
01805 }
01806 int isSupportSelectiveSelfTest(const ata_smart_values * data)
01807 {
01808    return data->offline_data_collection_capability & 0x40;
01809 }
01810 
01811 // Get attribute state
01812 ata_attr_state ata_get_attr_state(const ata_smart_attribute & attr,
01813                                   int attridx,
01814                                   const ata_smart_threshold_entry * thresholds,
01815                                   const ata_vendor_attr_defs & defs,
01816                                   unsigned char * threshval /* = 0 */)
01817 {
01818   if (!attr.id)
01819     return ATTRSTATE_NON_EXISTING;
01820 
01821   // Normalized values (current,worst,threshold) not valid
01822   // if specified by '-v' option.
01823   // (Some SSD disks uses these bytes to store raw value).
01824   if (defs[attr.id].flags & ATTRFLAG_NO_NORMVAL)
01825     return ATTRSTATE_NO_NORMVAL;
01826 
01827   // Normally threshold is at same index as attribute
01828   int i = attridx;
01829   if (thresholds[i].id != attr.id) {
01830     // Find threshold id in table
01831     for (i = 0; thresholds[i].id != attr.id; ) {
01832       if (++i >= NUMBER_ATA_SMART_ATTRIBUTES)
01833         // Threshold id missing or thresholds cannot be read
01834         return ATTRSTATE_NO_THRESHOLD;
01835     }
01836   }
01837   unsigned char threshold = thresholds[i].threshold;
01838 
01839   // Return threshold if requested
01840   if (threshval)
01841     *threshval = threshold;
01842 
01843   // Don't report a failed attribute if its threshold is 0.
01844   // ATA-3 (X3T13/2008D Revision 7b) declares 0x00 as the "always passing"
01845   // threshold (Later ATA versions declare all thresholds as "obsolete").
01846   // In practice, threshold value 0 is often used for usage attributes.
01847   if (!threshold)
01848     return ATTRSTATE_OK;
01849 
01850   // Failed now if current value is below threshold
01851   if (attr.current <= threshold)
01852     return ATTRSTATE_FAILED_NOW;
01853 
01854   // Failed in the past if worst value is below threshold
01855   if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL) && attr.worst <= threshold)
01856     return ATTRSTATE_FAILED_PAST;
01857 
01858   return ATTRSTATE_OK;
01859 }
01860 
01861 // Get default raw value print format
01862 static ata_attr_raw_format get_default_raw_format(unsigned char id)
01863 {
01864   switch (id) {
01865   case 3:   // Spin-up time
01866     return RAWFMT_RAW16_OPT_AVG16;
01867 
01868   case 5:   // Reallocated sector count
01869   case 196: // Reallocated event count
01870     return RAWFMT_RAW16_OPT_RAW16;
01871 
01872   case 9:  // Power on hours
01873     return RAWFMT_RAW24_OPT_RAW8;
01874 
01875   case 190: // Temperature
01876   case 194:
01877     return RAWFMT_TEMPMINMAX;
01878 
01879   default:
01880     return RAWFMT_RAW48;
01881   }
01882 }
01883 
01884 // Get attribute raw value.
01885 uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr,
01886                                 const ata_vendor_attr_defs & defs)
01887 {
01888   const ata_vendor_attr_defs::entry & def = defs[attr.id];
01889 
01890   // Use default byteorder if not specified
01891   const char * byteorder = def.byteorder;
01892   if (!*byteorder) {
01893     switch (def.raw_format) {
01894       case RAWFMT_RAW64:
01895       case RAWFMT_HEX64:
01896         byteorder = "543210wv"; break;
01897       case RAWFMT_RAW56:
01898       case RAWFMT_HEX56:
01899       case RAWFMT_RAW24_DIV_RAW32:
01900       case RAWFMT_MSEC24_HOUR32:
01901         byteorder = "r543210"; break;
01902       default:
01903         byteorder = "543210"; break;
01904     }
01905   }
01906 
01907   // Build 64-bit value from selected bytes
01908   uint64_t rawvalue = 0;
01909   for (int i = 0; byteorder[i]; i++) {
01910     unsigned char b;
01911     switch (byteorder[i]) {
01912       case '0': b = attr.raw[0];  break;
01913       case '1': b = attr.raw[1];  break;
01914       case '2': b = attr.raw[2];  break;
01915       case '3': b = attr.raw[3];  break;
01916       case '4': b = attr.raw[4];  break;
01917       case '5': b = attr.raw[5];  break;
01918       case 'r': b = attr.reserv;  break;
01919       case 'v': b = attr.current; break;
01920       case 'w': b = attr.worst;   break;
01921       default : b = 0;            break;
01922     }
01923     rawvalue <<= 8; rawvalue |= b;
01924   }
01925 
01926   return rawvalue;
01927 }
01928 
01929 
01930 // Format attribute raw value.
01931 std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
01932                                       const ata_vendor_attr_defs & defs)
01933 {
01934   // Get 48 bit or 64 bit raw value
01935   uint64_t rawvalue = ata_get_attr_raw_value(attr, defs);
01936 
01937   // Split into bytes and words
01938   unsigned char raw[6];
01939   raw[0] = (unsigned char) rawvalue;
01940   raw[1] = (unsigned char)(rawvalue >>  8);
01941   raw[2] = (unsigned char)(rawvalue >> 16);
01942   raw[3] = (unsigned char)(rawvalue >> 24);
01943   raw[4] = (unsigned char)(rawvalue >> 32);
01944   raw[5] = (unsigned char)(rawvalue >> 40);
01945   unsigned word[3];
01946   word[0] = raw[0] | (raw[1] << 8);
01947   word[1] = raw[2] | (raw[3] << 8);
01948   word[2] = raw[4] | (raw[5] << 8);
01949 
01950   // Get print format
01951   ata_attr_raw_format format = defs[attr.id].raw_format;
01952   if (format == RAWFMT_DEFAULT)
01953     format = get_default_raw_format(attr.id);
01954 
01955   // Print
01956   std::string s;
01957   switch (format) {
01958   case RAWFMT_RAW8:
01959     s = strprintf("%d %d %d %d %d %d",
01960       raw[5], raw[4], raw[3], raw[2], raw[1], raw[0]);
01961     break;
01962 
01963   case RAWFMT_RAW16:
01964     s = strprintf("%u %u %u", word[2], word[1], word[0]);
01965     break;
01966 
01967   case RAWFMT_RAW48:
01968   case RAWFMT_RAW56:
01969   case RAWFMT_RAW64:
01970     s = strprintf("%"PRIu64, rawvalue);
01971     break;
01972 
01973   case RAWFMT_HEX48:
01974     s = strprintf("0x%012"PRIx64, rawvalue);
01975     break;
01976 
01977   case RAWFMT_HEX56:
01978     s = strprintf("0x%014"PRIx64, rawvalue);
01979     break;
01980 
01981   case RAWFMT_HEX64:
01982     s = strprintf("0x%016"PRIx64, rawvalue);
01983     break;
01984 
01985   case RAWFMT_RAW16_OPT_RAW16:
01986     s = strprintf("%u", word[0]);
01987     if (word[1] || word[2])
01988       s += strprintf(" (%u %u)", word[2], word[1]);
01989     break;
01990 
01991   case RAWFMT_RAW16_OPT_AVG16:
01992     s = strprintf("%u", word[0]);
01993     if (word[1])
01994       s += strprintf(" (Average %u)", word[1]);
01995     break;
01996 
01997   case RAWFMT_RAW24_OPT_RAW8:
01998     s = strprintf("%u", (unsigned)(rawvalue & 0x00ffffffULL));
01999     if (raw[3] || raw[4] || raw[5])
02000       s += strprintf(" (%d %d %d)", raw[5], raw[4], raw[3]);
02001     break;
02002 
02003   case RAWFMT_RAW24_DIV_RAW24:
02004     s = strprintf("%u/%u",
02005       (unsigned)(rawvalue >> 24), (unsigned)(rawvalue & 0x00ffffffULL));
02006     break;
02007 
02008   case RAWFMT_RAW24_DIV_RAW32:
02009     s = strprintf("%u/%u",
02010       (unsigned)(rawvalue >> 32), (unsigned)(rawvalue & 0xffffffffULL));
02011     break;
02012 
02013   case RAWFMT_MIN2HOUR:
02014     {
02015       // minutes
02016       int64_t temp = word[0]+(word[1]<<16);
02017       int64_t tmp1 = temp/60;
02018       int64_t tmp2 = temp%60;
02019       s = strprintf("%"PRIu64"h+%02"PRIu64"m", tmp1, tmp2);
02020       if (word[2])
02021         s += strprintf(" (%u)", word[2]);
02022     }
02023     break;
02024 
02025   case RAWFMT_SEC2HOUR:
02026     {
02027       // seconds
02028       int64_t hours = rawvalue/3600;
02029       int64_t minutes = (rawvalue-3600*hours)/60;
02030       int64_t seconds = rawvalue%60;
02031       s = strprintf("%"PRIu64"h+%02"PRIu64"m+%02"PRIu64"s", hours, minutes, seconds);
02032     }
02033     break;
02034 
02035   case RAWFMT_HALFMIN2HOUR:
02036     {
02037       // 30-second counter
02038       int64_t hours = rawvalue/120;
02039       int64_t minutes = (rawvalue-120*hours)/2;
02040       s += strprintf("%"PRIu64"h+%02"PRIu64"m", hours, minutes);
02041     }
02042     break;
02043 
02044   case RAWFMT_MSEC24_HOUR32:
02045     {
02046       // hours + milliseconds
02047       unsigned hours = (unsigned)(rawvalue & 0xffffffffULL);
02048       unsigned milliseconds = (unsigned)(rawvalue >> 32);
02049       unsigned seconds = milliseconds / 1000;
02050       s = strprintf("%uh+%02um+%02u.%03us",
02051         hours, seconds / 60, seconds % 60, milliseconds % 1000);
02052     }
02053     break;
02054 
02055   case RAWFMT_TEMPMINMAX:
02056     // Temperature
02057     {
02058       // Search for possible min/max values
02059       // 00 HH 00 LL 00 TT (Hitachi/IBM)
02060       // 00 00 HH LL 00 TT (Maxtor, Samsung)
02061       // 00 00 00 HH LL TT (WDC)
02062       unsigned char lo = 0, hi = 0;
02063       int cnt = 0;
02064       for (int i = 1; i < 6; i++) {
02065         if (raw[i])
02066           switch (cnt++) {
02067             case 0:
02068               lo = raw[i];
02069               break;
02070             case 1:
02071               if (raw[i] < lo) {
02072                 hi = lo; lo = raw[i];
02073               }
02074               else
02075                 hi = raw[i];
02076               break;
02077           }
02078       }
02079 
02080       unsigned char t = raw[0];
02081       if (cnt == 0)
02082         s = strprintf("%d", t);
02083       else if (cnt == 2 && 0 < lo && lo <= t && t <= hi && hi < 128)
02084         s = strprintf("%d (Min/Max %d/%d)", t, lo, hi);
02085       else
02086         s = strprintf("%d (%d %d %d %d %d)", t, raw[5], raw[4], raw[3], raw[2], raw[1]);
02087     }
02088     break;
02089 
02090   case RAWFMT_TEMP10X:
02091     // ten times temperature in Celsius
02092     s = strprintf("%d.%d", word[0]/10, word[0]%10);
02093     break;
02094 
02095   default:
02096     s = "?"; // Should not happen
02097     break;
02098   }
02099 
02100   return s;
02101 }
02102 
02103 // Attribute names shouldn't be longer than 23 chars, otherwise they break the
02104 // output of smartctl.
02105 static const char * get_default_attr_name(unsigned char id, int rpm)
02106 {
02107   bool hdd = (rpm > 1), ssd = (rpm == 1);
02108 
02109   static const char Unknown_HDD_Attribute[] = "Unknown_HDD_Attribute";
02110   static const char Unknown_SSD_Attribute[] = "Unknown_SSD_Attribute";
02111 
02112   switch (id) {
02113   case 1:
02114     return "Raw_Read_Error_Rate";
02115   case 2:
02116     return "Throughput_Performance";
02117   case 3:
02118     return "Spin_Up_Time";
02119   case 4:
02120     return "Start_Stop_Count";
02121   case 5:
02122     return "Reallocated_Sector_Ct";
02123   case 6:
02124     if (ssd) return Unknown_SSD_Attribute;
02125     return "Read_Channel_Margin";
02126   case 7:
02127     if (ssd) return Unknown_SSD_Attribute;
02128     return "Seek_Error_Rate";
02129   case 8:
02130     if (ssd) return Unknown_SSD_Attribute;
02131     return "Seek_Time_Performance";
02132   case 9:
02133     return "Power_On_Hours";
02134   case 10:
02135     if (ssd) return Unknown_SSD_Attribute;
02136     return "Spin_Retry_Count";
02137   case 11:
02138     if (ssd) return Unknown_SSD_Attribute;
02139     return "Calibration_Retry_Count";
02140   case 12:
02141     return "Power_Cycle_Count";
02142   case 13:
02143     return "Read_Soft_Error_Rate";
02144   case 175:
02145     if (hdd) return Unknown_HDD_Attribute;
02146     return "Program_Fail_Count_Chip";
02147   case 176:
02148     if (hdd) return Unknown_HDD_Attribute;
02149     return "Erase_Fail_Count_Chip";
02150   case 177:
02151     if (hdd) return Unknown_HDD_Attribute;
02152     return "Wear_Leveling_Count";
02153   case 178:
02154     if (hdd) return Unknown_HDD_Attribute;
02155     return "Used_Rsvd_Blk_Cnt_Chip";
02156   case 179:
02157     if (hdd) return Unknown_HDD_Attribute;
02158     return "Used_Rsvd_Blk_Cnt_Tot";
02159   case 180:
02160     if (hdd) return Unknown_HDD_Attribute;
02161     return "Unused_Rsvd_Blk_Cnt_Tot";
02162   case 181:
02163     return "Program_Fail_Cnt_Total";
02164   case 182:
02165     if (hdd) return Unknown_HDD_Attribute;
02166     return "Erase_Fail_Count_Total";
02167   case 183:
02168     return "Runtime_Bad_Block";
02169   case 184:
02170     return "End-to-End_Error";
02171   case 187:
02172     return "Reported_Uncorrect";
02173   case 188:
02174     return "Command_Timeout";
02175   case 189:
02176     if (ssd) return Unknown_SSD_Attribute;
02177     return "High_Fly_Writes";
02178   case 190:
02179     // Western Digital uses this for temperature.
02180     // It's identical to Attribute 194 except that it
02181     // has a failure threshold set to correspond to the
02182     // max allowed operating temperature of the drive, which 
02183     // is typically 55C.  So if this attribute has failed
02184     // in the past, it indicates that the drive temp exceeded
02185     // 55C sometime in the past.
02186     return "Airflow_Temperature_Cel";
02187   case 191:
02188     if (ssd) return Unknown_SSD_Attribute;
02189     return "G-Sense_Error_Rate";
02190   case 192:
02191     return "Power-Off_Retract_Count";
02192   case 193:
02193     if (ssd) return Unknown_SSD_Attribute;
02194     return "Load_Cycle_Count";
02195   case 194:
02196     return "Temperature_Celsius";
02197   case 195:
02198     // Fujitsu: "ECC_On_The_Fly_Count";
02199     return "Hardware_ECC_Recovered";
02200   case 196:
02201     return "Reallocated_Event_Count";
02202   case 197:
02203     return "Current_Pending_Sector";
02204   case 198:
02205     return "Offline_Uncorrectable";
02206   case 199:
02207     return "UDMA_CRC_Error_Count";
02208   case 200:
02209     if (ssd) return Unknown_SSD_Attribute;
02210     // Western Digital
02211     return "Multi_Zone_Error_Rate";
02212   case 201:
02213     if (ssd) return Unknown_SSD_Attribute;
02214     return "Soft_Read_Error_Rate";
02215   case 202:
02216     if (ssd) return Unknown_SSD_Attribute;
02217     // Fujitsu: "TA_Increase_Count"
02218     return "Data_Address_Mark_Errs";
02219   case 203:
02220     // Fujitsu
02221     return "Run_Out_Cancel";
02222     // Maxtor: ECC Errors
02223   case 204:
02224     // Fujitsu: "Shock_Count_Write_Opern"
02225     return "Soft_ECC_Correction";
02226   case 205:
02227     // Fujitsu: "Shock_Rate_Write_Opern"
02228     return "Thermal_Asperity_Rate";
02229   case 206:
02230     // Fujitsu
02231     if (ssd) return Unknown_SSD_Attribute;
02232     return "Flying_Height";
02233   case 207:
02234     // Maxtor
02235     if (ssd) return Unknown_SSD_Attribute;
02236     return "Spin_High_Current";
02237   case 208:
02238     // Maxtor
02239     if (ssd) return Unknown_SSD_Attribute;
02240     return "Spin_Buzz";
02241   case 209:
02242     // Maxtor
02243     if (ssd) return Unknown_SSD_Attribute;
02244     return "Offline_Seek_Performnce";
02245   case 220:
02246     if (ssd) return Unknown_SSD_Attribute;
02247     return "Disk_Shift";
02248   case 221:
02249     if (ssd) return Unknown_SSD_Attribute;
02250     return "G-Sense_Error_Rate";
02251   case 222:
02252     if (ssd) return Unknown_SSD_Attribute;
02253     return "Loaded_Hours";
02254   case 223:
02255     if (ssd) return Unknown_SSD_Attribute;
02256     return "Load_Retry_Count";
02257   case 224:
02258     if (ssd) return Unknown_SSD_Attribute;
02259     return "Load_Friction";
02260   case 225:
02261     if (ssd) return Unknown_SSD_Attribute;
02262     return "Load_Cycle_Count";
02263   case 226:
02264     if (ssd) return Unknown_SSD_Attribute;
02265     return "Load-in_Time";
02266   case 227:
02267     if (ssd) return Unknown_SSD_Attribute;
02268     return "Torq-amp_Count";
02269   case 228:
02270     return "Power-off_Retract_Count";
02271   case 230:
02272     // seen in IBM DTPA-353750
02273     if (ssd) return Unknown_SSD_Attribute;
02274     return "Head_Amplitude";
02275   case 231:
02276     return "Temperature_Celsius";
02277   case 232:
02278     // seen in Intel X25-E SSD
02279     return "Available_Reservd_Space";
02280   case 233:
02281     // seen in Intel X25-E SSD
02282     if (hdd) return Unknown_HDD_Attribute;
02283     return "Media_Wearout_Indicator";
02284   case 240:
02285     if (ssd) return Unknown_SSD_Attribute;
02286     return "Head_Flying_Hours";
02287   case 241:
02288     return "Total_LBAs_Written";
02289   case 242:
02290     return "Total_LBAs_Read";
02291   case 250:
02292     return "Read_Error_Retry_Rate";
02293   case 254:
02294     if (ssd) return Unknown_SSD_Attribute;
02295     return "Free_Fall_Sensor";
02296   default:
02297     return "Unknown_Attribute";
02298   }
02299 }
02300 
02301 // Get attribute name
02302 std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs,
02303                                     int rpm /* = 0 */)
02304 {
02305   if (!defs[id].name.empty())
02306     return defs[id].name;
02307   else
02308     return get_default_attr_name(id, rpm);
02309 }
02310 
02311 // Find attribute index for attribute id, -1 if not found.
02312 int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval)
02313 {
02314   if (!id)
02315     return -1;
02316   for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
02317     if (smartval.vendor_attributes[i].id == id)
02318       return i;
02319   }
02320   return -1;
02321 }
02322 
02323 // Return Temperature Attribute raw value selected according to possible
02324 // non-default interpretations. If the Attribute does not exist, return 0
02325 unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs)
02326 {
02327   for (int i = 0; i < 4; i++) {
02328     static const unsigned char ids[4] = {194, 190, 9, 220};
02329     unsigned char id = ids[i];
02330     const ata_attr_raw_format format = defs[id].raw_format;
02331     if (!(   ((id == 194 || id == 190) && format == RAWFMT_DEFAULT)
02332           || format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X))
02333       continue;
02334     int idx = ata_find_attr_index(id, *data);
02335     if (idx < 0)
02336       continue;
02337     uint64_t raw = ata_get_attr_raw_value(data->vendor_attributes[idx], defs);
02338     unsigned temp;
02339     // ignore possible min/max values in high words
02340     if (format == RAWFMT_TEMP10X) // -v N,temp10x
02341       temp = ((unsigned short)raw + 5) / 10;
02342     else
02343       temp = (unsigned char)raw;
02344     if (!(0 < temp && temp < 128))
02345       continue;
02346     return temp;
02347   }
02348   // No valid attribute found
02349   return 0;
02350 }
02351 
02352 
02353 // Read SCT Status
02354 int ataReadSCTStatus(ata_device * device, ata_sct_status_response * sts)
02355 {
02356   // read SCT status via SMART log 0xe0
02357   memset(sts, 0, sizeof(*sts));
02358   if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){
02359     pout("Read SCT Status failed: %s\n", device->get_errmsg());
02360     return -1;
02361   }
02362 
02363   // swap endian order if needed
02364   if (isbigendian()){
02365     swapx(&sts->format_version);
02366     swapx(&sts->sct_version);
02367     swapx(&sts->sct_spec);
02368     swapx(&sts->ext_status_code);
02369     swapx(&sts->action_code);
02370     swapx(&sts->function_code);
02371     swapx(&sts->over_limit_count);
02372     swapx(&sts->under_limit_count);
02373   }
02374 
02375   // Check format version
02376   if (!(sts->format_version == 2 || sts->format_version == 3)) {
02377     pout("Unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version);
02378     return -1;
02379   }
02380   return 0;
02381 }
02382 
02383 // Read SCT Temperature History Table and Status
02384 int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table * tmh,
02385                        ata_sct_status_response * sts)
02386 {
02387   // Check initial status
02388   if (ataReadSCTStatus(device, sts))
02389     return -1;
02390 
02391   // Do nothing if other SCT command is executing
02392   if (sts->ext_status_code == 0xffff) {
02393     pout("Another SCT command is executing, abort Read Data Table\n"
02394          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
02395       sts->ext_status_code, sts->action_code, sts->function_code);
02396     return -1;
02397   }
02398 
02399   ata_sct_data_table_command cmd; memset(&cmd, 0, sizeof(cmd));
02400   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
02401   cmd.action_code   = 5; // Data table command
02402   cmd.function_code = 1; // Read table
02403   cmd.table_id      = 2; // Temperature History Table
02404 
02405   // swap endian order if needed
02406   if (isbigendian()) {
02407     swapx(&cmd.action_code);
02408     swapx(&cmd.function_code);
02409     swapx(&cmd.table_id);
02410   }
02411 
02412   // write command via SMART log page 0xe0
02413   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
02414     pout("Write SCT Data Table failed: %s\n", device->get_errmsg());
02415     return -1;
02416   }
02417 
02418   // read SCT data via SMART log page 0xe1
02419   memset(tmh, 0, sizeof(*tmh));
02420   if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){
02421     pout("Read SCT Data Table failed: %s\n", device->get_errmsg());
02422     return -1;
02423   }
02424 
02425   // re-read and check SCT status
02426   if (ataReadSCTStatus(device, sts))
02427     return -1;
02428 
02429   if (!(sts->ext_status_code == 0 && sts->action_code == 5 && sts->function_code == 1)) {
02430     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
02431       sts->ext_status_code, sts->action_code, sts->function_code);
02432     return -1;
02433   }
02434 
02435   // swap endian order if needed
02436   if (isbigendian()){
02437     swapx(&tmh->format_version);
02438     swapx(&tmh->sampling_period);
02439     swapx(&tmh->interval);
02440     swapx(&tmh->cb_index);
02441     swapx(&tmh->cb_size);
02442   }
02443   return 0;
02444 }
02445 
02446 // Set SCT Temperature Logging Interval
02447 int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent)
02448 {
02449   // Check initial status
02450   ata_sct_status_response sts;
02451   if (ataReadSCTStatus(device, &sts))
02452     return -1;
02453 
02454   // Do nothing if other SCT command is executing
02455   if (sts.ext_status_code == 0xffff) {
02456     pout("Another SCT command is executing, abort Feature Control\n"
02457          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
02458       sts.ext_status_code, sts.action_code, sts.function_code);
02459     return -1;
02460   }
02461 
02462   ata_sct_feature_control_command cmd; memset(&cmd, 0, sizeof(cmd));
02463   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
02464   cmd.action_code   = 4; // Feature Control command
02465   cmd.function_code = 1; // Set state
02466   cmd.feature_code  = 3; // Temperature logging interval
02467   cmd.state         = interval;
02468   cmd.option_flags  = (persistent ? 0x01 : 0x00);
02469 
02470   // swap endian order if needed
02471   if (isbigendian()) {
02472     swapx(&cmd.action_code);
02473     swapx(&cmd.function_code);
02474     swapx(&cmd.feature_code);
02475     swapx(&cmd.state);
02476     swapx(&cmd.option_flags);
02477   }
02478 
02479   // write command via SMART log page 0xe0
02480   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
02481     pout("Write SCT Feature Control Command failed: %s\n", device->get_errmsg());
02482     return -1;
02483   }
02484 
02485   // re-read and check SCT status
02486   if (ataReadSCTStatus(device, &sts))
02487     return -1;
02488 
02489   if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == 1)) {
02490     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
02491       sts.ext_status_code, sts.action_code, sts.function_code);
02492     return -1;
02493   }
02494   return 0;
02495 }
02496 
02497 // Get/Set SCT Error Recovery Control
02498 static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned type,
02499                                                 bool set, unsigned short & time_limit)
02500 {
02501   // Check initial status
02502   ata_sct_status_response sts;
02503   if (ataReadSCTStatus(device, &sts))
02504     return -1;
02505 
02506   // Do nothing if other SCT command is executing
02507   if (sts.ext_status_code == 0xffff) {
02508     pout("Another SCT command is executing, abort Error Recovery Control\n"
02509          "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
02510       sts.ext_status_code, sts.action_code, sts.function_code);
02511     return -1;
02512   }
02513 
02514   ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd));
02515   // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
02516   cmd.action_code    = 3; // Error Recovery Control command
02517   cmd.function_code  = (set ? 1 : 2); // 1=Set timer, 2=Get timer
02518   cmd.selection_code = type; // 1=Read timer, 2=Write timer
02519   if (set)
02520     cmd.time_limit   = time_limit;
02521 
02522   // swap endian order if needed
02523   if (isbigendian()) {
02524     swapx(&cmd.action_code);
02525     swapx(&cmd.function_code);
02526     swapx(&cmd.selection_code);
02527     swapx(&cmd.time_limit);
02528   }
02529 
02530   // write command via SMART log page 0xe0
02531   // TODO: Debug output
02532   ata_cmd_in in;
02533   in.in_regs.command = ATA_SMART_CMD;
02534   in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
02535   in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
02536   in.in_regs.lba_low = 0xe0;
02537   in.set_data_out(&cmd, 1);
02538 
02539   if (!set)
02540     // Time limit returned in ATA registers
02541     in.out_needed.sector_count = in.out_needed.lba_low = true;
02542 
02543   ata_cmd_out out;
02544   if (!device->ata_pass_through(in, out)) {
02545     pout("Write SCT (%cet) Error Recovery Control Command failed: %s\n",
02546       (!set ? 'G' : 'S'), device->get_errmsg());
02547     return -1;
02548   }
02549 
02550   // re-read and check SCT status
02551   if (ataReadSCTStatus(device, &sts))
02552     return -1;
02553 
02554   if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) {
02555     pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
02556       sts.ext_status_code, sts.action_code, sts.function_code);
02557     return -1;
02558   }
02559 
02560   if (!set) {
02561     // Check whether registers are properly returned by ioctl()
02562     if (!(out.out_regs.sector_count.is_set() && out.out_regs.lba_low.is_set())) {
02563       // TODO: Output register support should be checked within each ata_pass_through()
02564       // implementation before command is issued.
02565       pout("SMART WRITE LOG does not return COUNT and LBA_LOW register\n");
02566       return -1;
02567     }
02568     if (   out.out_regs.sector_count == in.in_regs.sector_count
02569         && out.out_regs.lba_low      == in.in_regs.lba_low     ) {
02570       // 0xe001 (5734.5s) - this is most likely a broken ATA pass-through implementation
02571       pout("SMART WRITE LOG returns COUNT and LBA_LOW register unchanged\n");
02572       return -1;
02573     }
02574 
02575     // Return value to caller
02576     time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
02577   }
02578 
02579   return 0;
02580 }
02581 
02582 // Get SCT Error Recovery Control
02583 int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit)
02584 {
02585   return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit);
02586 }
02587 
02588 // Set SCT Error Recovery Control
02589 int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit)
02590 {
02591   return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit);
02592 }
02593 
02594 
02595 // Print one self-test log entry.
02596 // Returns:
02597 // -1: self-test failed
02598 //  1: extended self-test completed without error
02599 //  0: otherwise
02600 int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
02601                                unsigned char test_status,
02602                                unsigned short timestamp,
02603                                uint64_t failing_lba,
02604                                bool print_error_only, bool & print_header)
02605 {
02606   // Check status and type for return value
02607   int retval = 0;
02608   switch (test_status >> 4) {
02609     case 0x0:
02610       if ((test_type & 0x0f) == 0x02)
02611         retval = 1; // extended self-test completed without error
02612       break;
02613     case 0x3: case 0x4:
02614     case 0x5: case 0x6:
02615     case 0x7: case 0x8:
02616       retval = -1; // self-test failed
02617       break;
02618   }
02619 
02620   if (retval >= 0 && print_error_only)
02621     return retval;
02622 
02623   std::string msgtest;
02624   switch (test_type) {
02625     case 0x00: msgtest = "Offline";            break;
02626     case 0x01: msgtest = "Short offline";      break;
02627     case 0x02: msgtest = "Extended offline";   break;
02628     case 0x03: msgtest = "Conveyance offline"; break;
02629     case 0x04: msgtest = "Selective offline";  break;
02630     case 0x7f: msgtest = "Abort offline test"; break;
02631     case 0x81: msgtest = "Short captive";      break;
02632     case 0x82: msgtest = "Extended captive";   break;
02633     case 0x83: msgtest = "Conveyance captive"; break;
02634     case 0x84: msgtest = "Selective captive";  break;
02635     default:
02636       if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
02637         msgtest = strprintf("Vendor (0x%02x)", test_type);
02638       else
02639         msgtest = strprintf("Reserved (0x%02x)", test_type);
02640   }
02641 
02642   std::string msgstat;
02643   switch (test_status >> 4) {
02644     case 0x0: msgstat = "Completed without error";       break;
02645     case 0x1: msgstat = "Aborted by host";               break;
02646     case 0x2: msgstat = "Interrupted (host reset)";      break;
02647     case 0x3: msgstat = "Fatal or unknown error";        break;
02648     case 0x4: msgstat = "Completed: unknown failure";    break;
02649     case 0x5: msgstat = "Completed: electrical failure"; break;
02650     case 0x6: msgstat = "Completed: servo/seek failure"; break;
02651     case 0x7: msgstat = "Completed: read failure";       break;
02652     case 0x8: msgstat = "Completed: handling damage??";  break;
02653     case 0xf: msgstat = "Self-test routine in progress"; break;
02654     default:  msgstat = strprintf("Unknown status (0x%x)", test_status >> 4);
02655   }
02656 
02657   // Print header once
02658   if (print_header) {
02659     print_header = false;
02660     pout("Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error\n");
02661   }
02662 
02663   char msglba[32];
02664   if (retval < 0 && failing_lba < 0xffffffffffffULL)
02665     snprintf(msglba, sizeof(msglba), "%"PRIu64, failing_lba);
02666   else {
02667     msglba[0] = '-'; msglba[1] = 0;
02668   }
02669 
02670   pout("#%2u  %-19s %-29s %1d0%%  %8u         %s\n", testnum,
02671        msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
02672 
02673   return retval;
02674 }
02675 
02676 // Print Smart self-test log, used by smartctl and smartd.
02677 // return value is:
02678 // bottom 8 bits: number of entries found where self-test showed an error
02679 // remaining bits: if nonzero, power on hours of last self-test where error was found
02680 int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
02681                              firmwarebug_defs firmwarebugs)
02682 {
02683   if (allentries)
02684     pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber);
02685   if (data->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG))
02686     pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
02687   if (data->mostrecenttest==0){
02688     if (allentries)
02689       pout("No self-tests have been logged.  [To run self-tests, use: smartctl -t]\n\n");
02690     return 0;
02691   }
02692 
02693   bool noheaderprinted = true;
02694   int errcnt = 0, hours = 0, igncnt = 0;
02695   int testno = 0, ext_ok_testno = -1;
02696 
02697   // print log
02698   for (int i = 20; i >= 0; i--) {
02699     // log is a circular buffer
02700     int j = (i+data->mostrecenttest)%21;
02701     const ata_smart_selftestlog_struct * log = data->selftest_struct+j;
02702 
02703     if (nonempty(log, sizeof(*log))) {
02704       // count entry based on non-empty structures -- needed for
02705       // Seagate only -- other vendors don't have blank entries 'in
02706       // the middle'
02707       testno++;
02708 
02709       // T13/1321D revision 1c: (Data structure Rev #1)
02710 
02711       //The failing LBA shall be the LBA of the uncorrectable sector
02712       //that caused the test to fail. If the device encountered more
02713       //than one uncorrectable sector during the test, this field
02714       //shall indicate the LBA of the first uncorrectable sector
02715       //encountered. If the test passed or the test failed for some
02716       //reason other than an uncorrectable sector, the value of this
02717       //field is undefined.
02718 
02719       // This is true in ALL ATA-5 specs
02720       uint64_t lba48 = (log->lbafirstfailure < 0xffffffff ? log->lbafirstfailure : 0xffffffffffffULL);
02721 
02722       // Print entry
02723       int state = ataPrintSmartSelfTestEntry(testno,
02724         log->selftestnumber, log->selfteststatus,
02725         log->timestamp, lba48, !allentries, noheaderprinted);
02726 
02727       if (state < 0) {
02728         // Self-test showed an error
02729         if (ext_ok_testno < 0) {
02730           errcnt++;
02731 
02732           // keep track of time of most recent error
02733           if (!hours)
02734             hours = log->timestamp;
02735         }
02736         else
02737           // Newer successful extended self-test exits
02738           igncnt++;
02739       }
02740       else if (state > 0 && ext_ok_testno < 0) {
02741         // Latest successful extended self-test
02742         ext_ok_testno = testno;
02743       }
02744     }
02745   }
02746 
02747   if (igncnt)
02748     pout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
02749       igncnt, igncnt+errcnt, ext_ok_testno);
02750 
02751   if (!allentries && !noheaderprinted)
02752     pout("\n");
02753 
02754   return ((hours << 8) | errcnt);
02755 }
02756 
02757 
02758 /////////////////////////////////////////////////////////////////////////////
02759 // Pseudo-device to parse "smartctl -r ataioctl,2 ..." output and simulate
02760 // an ATA device with same behaviour
02761 
02762 namespace {
02763 
02764 class parsed_ata_device
02765 : public /*implements*/ ata_device_with_command_set
02766 {
02767 public:
02768   parsed_ata_device(smart_interface * intf, const char * dev_name);
02769 
02770   virtual ~parsed_ata_device() throw();
02771 
02772   virtual bool is_open() const;
02773 
02774   virtual bool open();
02775 
02776   virtual bool close();
02777 
02778   virtual bool ata_identify_is_cached() const;
02779 
02780 protected:
02781   virtual int ata_command_interface(smart_command_set command, int select, char * data);
02782 
02783 private:
02784   // Table of parsed commands, return value, data
02785   struct parsed_ata_command
02786   {
02787     smart_command_set command;
02788     int select;
02789     int retval, errval;
02790     char * data;
02791   };
02792 
02793   enum { max_num_commands = 32 };
02794   parsed_ata_command m_command_table[max_num_commands];
02795 
02796   int m_num_commands;
02797   int m_next_replay_command;
02798   bool m_replay_out_of_sync;
02799   bool m_ata_identify_is_cached;
02800 };
02801 
02802 static const char * nextline(const char * s, int & lineno)
02803 {
02804   for (s += strcspn(s, "\r\n"); *s == '\r' || *s == '\n'; s++) {
02805     if (*s == '\r' && s[1] == '\n')
02806       s++;
02807     lineno++;
02808   }
02809   return s;
02810 }
02811 
02812 static int name2command(const char * s)
02813 {
02814   for (int i = 0; i < (int)(sizeof(commandstrings)/sizeof(commandstrings[0])); i++) {
02815     if (!strcmp(s, commandstrings[i]))
02816       return i;
02817   }
02818   return -1;
02819 }
02820 
02821 static bool matchcpy(char * dest, size_t size, const char * src, const regmatch_t & srcmatch)
02822 {
02823   if (srcmatch.rm_so < 0)
02824     return false;
02825   size_t n = srcmatch.rm_eo - srcmatch.rm_so;
02826   if (n >= size)
02827     n = size-1;
02828   memcpy(dest, src + srcmatch.rm_so, n);
02829   dest[n] = 0;
02830   return true;
02831 }
02832 
02833 static inline int matchtoi(const char * src, const regmatch_t & srcmatch, int defval)
02834 {
02835   if (srcmatch.rm_so < 0)
02836     return defval;
02837   return atoi(src + srcmatch.rm_so);
02838 }
02839 
02840 parsed_ata_device::parsed_ata_device(smart_interface * intf, const char * dev_name)
02841 : smart_device(intf, dev_name, "ata", ""),
02842   m_num_commands(0),
02843   m_next_replay_command(0),
02844   m_replay_out_of_sync(false),
02845   m_ata_identify_is_cached(false)
02846 {
02847   memset(m_command_table, 0, sizeof(m_command_table));
02848 }
02849 
02850 parsed_ata_device::~parsed_ata_device() throw()
02851 {
02852   close();
02853 }
02854 
02855 bool parsed_ata_device::is_open() const
02856 {
02857   return (m_num_commands > 0);
02858 }
02859 
02860 // Parse stdin and build command table
02861 bool parsed_ata_device::open()
02862 {
02863   const char * pathname = get_dev_name();
02864   if (strcmp(pathname, "-"))
02865     return set_err(EINVAL);
02866   pathname = "<stdin>";
02867   // Fill buffer
02868   char buffer[64*1024];
02869   int size = 0;
02870   while (size < (int)sizeof(buffer)) {
02871     int nr = fread(buffer, 1, sizeof(buffer), stdin);
02872     if (nr <= 0)
02873       break;
02874     size += nr;
02875   }
02876   if (size <= 0)
02877     return set_err(ENOENT, "%s: Unexpected EOF", pathname);
02878   if (size >= (int)sizeof(buffer))
02879     return set_err(EIO, "%s: Buffer overflow", pathname);
02880   buffer[size] = 0;
02881 
02882   // Regex to match output from "-r ataioctl,2"
02883   static const char pattern[] = "^"
02884   "(" // (1
02885     "REPORT-IOCTL: DeviceF?D?=[^ ]+ Command=([A-Z ]*[A-Z])" // (2)
02886     "(" // (3
02887       "( InputParameter=([0-9]+))?" // (4 (5))
02888     "|"
02889       "( returned (-?[0-9]+)( errno=([0-9]+)[^\r\n]*)?)" // (6 (7) (8 (9)))
02890     ")" // )
02891     "[\r\n]" // EOL match necessary to match optional parts above
02892   "|"
02893     "===== \\[([A-Z ]*[A-Z])\\] DATA START " // (10)
02894   "|"
02895     "    *(En|Dis)abled status cached by OS, " // (11)
02896   ")"; // )
02897 
02898   // Compile regex
02899   const regular_expression regex(pattern, REG_EXTENDED);
02900 
02901   // Parse buffer
02902   const char * errmsg = 0;
02903   int i = -1, state = 0, lineno = 1;
02904   for (const char * line = buffer; *line; line = nextline(line, lineno)) {
02905     // Match line
02906     if (!(line[0] == 'R' || line[0] == '=' || line[0] == ' '))
02907       continue;
02908     const int nmatch = 1+11;
02909     regmatch_t match[nmatch];
02910     if (!regex.execute(line, nmatch, match))
02911       continue;
02912 
02913     char cmdname[40];
02914     if (matchcpy(cmdname, sizeof(cmdname), line, match[2])) { // "REPORT-IOCTL:... Command=%s ..."
02915       int nc = name2command(cmdname);
02916       if (nc < 0) {
02917         errmsg = "Unknown ATA command name"; break;
02918       }
02919       if (match[7].rm_so < 0) { // "returned %d"
02920         // Start of command
02921         if (!(state == 0 || state == 2)) {
02922           errmsg = "Missing REPORT-IOCTL result"; break;
02923         }
02924         if (++i >= max_num_commands) {
02925           errmsg = "Too many ATA commands"; break;
02926         }
02927         m_command_table[i].command = (smart_command_set)nc;
02928         m_command_table[i].select = matchtoi(line, match[5], 0); // "InputParameter=%d"
02929         state = 1;
02930       }
02931       else {
02932         // End of command
02933         if (!(state == 1 && (int)m_command_table[i].command == nc)) {
02934           errmsg = "Missing REPORT-IOCTL start"; break;
02935         }
02936         m_command_table[i].retval = matchtoi(line, match[7], -1); // "returned %d"
02937         m_command_table[i].errval = matchtoi(line, match[9], 0); // "errno=%d"
02938         state = 2;
02939       }
02940     }
02941     else if (matchcpy(cmdname, sizeof(cmdname), line, match[10])) { // "===== [%s] DATA START "
02942       // Start of sector hexdump
02943       int nc = name2command(cmdname);
02944       if (!(state == (nc == WRITE_LOG ? 1 : 2) && (int)m_command_table[i].command == nc)) {
02945           errmsg = "Unexpected DATA START"; break;
02946       }
02947       line = nextline(line, lineno);
02948       char * data = (char *)malloc(512);
02949       unsigned j;
02950       for (j = 0; j < 32; j++) {
02951         unsigned b[16];
02952         unsigned u1, u2; int n1 = -1;
02953         if (!(sscanf(line, "%3u-%3u: "
02954                         "%2x %2x %2x %2x %2x %2x %2x %2x "
02955                         "%2x %2x %2x %2x %2x %2x %2x %2x%n",
02956                      &u1, &u2,
02957                      b+ 0, b+ 1, b+ 2, b+ 3, b+ 4, b+ 5, b+ 6, b+ 7,
02958                      b+ 8, b+ 9, b+10, b+11, b+12, b+13, b+14, b+15, &n1) == 18
02959               && n1 >= 56 && u1 == j*16 && u2 == j*16+15))
02960           break;
02961         for (unsigned k = 0; k < 16; k++)
02962           data[j*16+k] = b[k];
02963         line = nextline(line, lineno);
02964       }
02965       if (j < 32) {
02966         free(data);
02967         errmsg = "Incomplete sector hex dump"; break;
02968       }
02969       m_command_table[i].data = data;
02970       if (nc != WRITE_LOG)
02971         state = 0;
02972     }
02973     else if (match[11].rm_so > 0) { // "(En|Dis)abled status cached by OS"
02974       m_ata_identify_is_cached = true;
02975     }
02976   }
02977 
02978   if (!(state == 0 || state == 2))
02979     errmsg = "Missing REPORT-IOCTL result";
02980 
02981   if (!errmsg && i < 0)
02982     errmsg = "No information found";
02983 
02984   m_num_commands = i+1;
02985   m_next_replay_command = 0;
02986   m_replay_out_of_sync = false;
02987 
02988   if (errmsg) {
02989     close();
02990     return set_err(EIO, "%s(%d): Syntax error: %s", pathname, lineno, errmsg);
02991   }
02992   return true;
02993 }
02994 
02995 // Report warnings and free command table 
02996 bool parsed_ata_device::close()
02997 {
02998   if (m_replay_out_of_sync)
02999       pout("REPLAY-IOCTL: Warning: commands replayed out of sync\n");
03000   else if (m_next_replay_command != 0)
03001       pout("REPLAY-IOCTL: Warning: %d command(s) not replayed\n", m_num_commands-m_next_replay_command);
03002 
03003   for (int i = 0; i < m_num_commands; i++) {
03004     if (m_command_table[i].data) {
03005       free(m_command_table[i].data); m_command_table[i].data = 0;
03006     }
03007   }
03008   m_num_commands = 0;
03009   m_next_replay_command = 0;
03010   m_replay_out_of_sync = false;
03011   return true;
03012 }
03013 
03014 
03015 bool parsed_ata_device::ata_identify_is_cached() const
03016 {
03017   return m_ata_identify_is_cached;
03018 }
03019 
03020 
03021 // Simulate ATA command from command table
03022 int parsed_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
03023 {
03024   // Find command, try round-robin if out of sync
03025   int i = m_next_replay_command;
03026   for (int j = 0; ; j++) {
03027     if (j >= m_num_commands) {
03028       pout("REPLAY-IOCTL: Warning: Command not found\n");
03029       errno = ENOSYS;
03030       return -1;
03031     }
03032     if (m_command_table[i].command == command && m_command_table[i].select == select)
03033       break;
03034     if (!m_replay_out_of_sync) {
03035       m_replay_out_of_sync = true;
03036       pout("REPLAY-IOCTL: Warning: Command #%d is out of sync\n", i+1);
03037     }
03038     if (++i >= m_num_commands)
03039       i = 0;
03040   }
03041   m_next_replay_command = i;
03042   if (++m_next_replay_command >= m_num_commands)
03043     m_next_replay_command = 0;
03044 
03045   // Return command data
03046   switch (command) {
03047     case IDENTIFY:
03048     case PIDENTIFY:
03049     case READ_VALUES:
03050     case READ_THRESHOLDS:
03051     case READ_LOG:
03052       if (m_command_table[i].data)
03053         memcpy(data, m_command_table[i].data, 512);
03054       break;
03055     case WRITE_LOG:
03056       if (!(m_command_table[i].data && !memcmp(data, m_command_table[i].data, 512)))
03057         pout("REPLAY-IOCTL: Warning: WRITE LOG data does not match\n");
03058       break;
03059     case CHECK_POWER_MODE:
03060       data[0] = (char)0xff;
03061     default:
03062       break;
03063   }
03064 
03065   if (m_command_table[i].errval)
03066     errno = m_command_table[i].errval;
03067   return m_command_table[i].retval;
03068 }
03069 
03070 } // namespace
03071 
03072 ata_device * get_parsed_ata_device(smart_interface * intf, const char * dev_name)
03073 {
03074   return new parsed_ata_device(intf, dev_name);
03075 }