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