|
smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
|
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 }
1.7.4