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