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