4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2002-7 Bruce Allen <smartmontools-support@lists.sourceforge.net>
7 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
8 * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
15 * You should have received a copy of the GNU General Public License
16 * (for example COPYING); if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * This code was originally developed as a Senior Thesis by Michael Cornwell
20 * at the Concurrent Systems Laboratory (now part of the Storage Systems
21 * Research Center), Jack Baskin School of Engineering, University of
22 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
39 const char *atacmds_c_cvsid
="$Id: atacmds.cpp,v 1.188 2007/07/26 20:58:50 chrfranke Exp $"
40 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID
;
42 // to hold onto exit code for atexit routine
43 extern int exitstatus
;
45 // for passing global control variables
46 extern smartmonctrl
*con
;
48 // These Drive Identity tables are taken from hdparm 5.2, and are also
49 // given in the ATA/ATAPI specs for the IDENTIFY DEVICE command. Note
50 // that SMART was first added into the ATA/ATAPI-3 Standard with
51 // Revision 3 of the document, July 25, 1995. Look at the "Document
52 // Status" revision commands at the beginning of
53 // http://www.t13.org/project/d2008r6.pdf to see this.
54 #define NOVAL_0 0x0000
55 #define NOVAL_1 0xffff
56 /* word 81: minor version number */
57 #define MINOR_MAX 0x22
58 const char *minor_str
[] = { /* word 81 value: */
59 "Device does not report version", /* 0x0000 */
60 "ATA-1 X3T9.2 781D prior to revision 4", /* 0x0001 */
61 "ATA-1 published, ANSI X3.221-1994", /* 0x0002 */
62 "ATA-1 X3T9.2 781D revision 4", /* 0x0003 */
63 "ATA-2 published, ANSI X3.279-1996", /* 0x0004 */
64 "ATA-2 X3T10 948D prior to revision 2k", /* 0x0005 */
65 "ATA-3 X3T10 2008D revision 1", /* 0x0006 */ /* SMART NOT INCLUDED */
66 "ATA-2 X3T10 948D revision 2k", /* 0x0007 */
67 "ATA-3 X3T10 2008D revision 0", /* 0x0008 */
68 "ATA-2 X3T10 948D revision 3", /* 0x0009 */
69 "ATA-3 published, ANSI X3.298-199x", /* 0x000a */
70 "ATA-3 X3T10 2008D revision 6", /* 0x000b */ /* 1st VERSION WITH SMART */
71 "ATA-3 X3T13 2008D revision 7 and 7a", /* 0x000c */
72 "ATA/ATAPI-4 X3T13 1153D revision 6", /* 0x000d */
73 "ATA/ATAPI-4 T13 1153D revision 13", /* 0x000e */
74 "ATA/ATAPI-4 X3T13 1153D revision 7", /* 0x000f */
75 "ATA/ATAPI-4 T13 1153D revision 18", /* 0x0010 */
76 "ATA/ATAPI-4 T13 1153D revision 15", /* 0x0011 */
77 "ATA/ATAPI-4 published, ANSI NCITS 317-1998", /* 0x0012 */
78 "ATA/ATAPI-5 T13 1321D revision 3", /* 0x0013 */
79 "ATA/ATAPI-4 T13 1153D revision 14", /* 0x0014 */
80 "ATA/ATAPI-5 T13 1321D revision 1", /* 0x0015 */
81 "ATA/ATAPI-5 published, ANSI NCITS 340-2000", /* 0x0016 */
82 "ATA/ATAPI-4 T13 1153D revision 17", /* 0x0017 */
83 "ATA/ATAPI-6 T13 1410D revision 0", /* 0x0018 */
84 "ATA/ATAPI-6 T13 1410D revision 3a", /* 0x0019 */
85 "ATA/ATAPI-7 T13 1532D revision 1", /* 0x001a */
86 "ATA/ATAPI-6 T13 1410D revision 2", /* 0x001b */
87 "ATA/ATAPI-6 T13 1410D revision 1", /* 0x001c */
88 "ATA/ATAPI-7 published, ANSI INCITS 397-2005",/* 0x001d */
89 "ATA/ATAPI-7 T13 1532D revision 0", /* 0x001e */
90 "reserved", /* 0x001f */
91 "reserved", /* 0x0020 */
92 "ATA/ATAPI-7 T13 1532D revision 4a", /* 0x0021 */
93 "ATA/ATAPI-6 published, ANSI INCITS 361-2002" /* 0x0022 */
96 // NOTE ATA/ATAPI-4 REV 4 was the LAST revision where the device
97 // attribute structures were NOT completely vendor specific. So any
98 // disk that is ATA/ATAPI-4 or above can not be trusted to show the
99 // vendor values in sensible format.
101 // Negative values below are because it doesn't support SMART
102 const int actual_ver
[] = {
104 0, /* 0x0000 WARNING: */
105 1, /* 0x0001 WARNING: */
106 1, /* 0x0002 WARNING: */
107 1, /* 0x0003 WARNING: */
108 2, /* 0x0004 WARNING: This array */
109 2, /* 0x0005 WARNING: corresponds */
110 -3, /*<== */ /* 0x0006 WARNING: *exactly* */
111 2, /* 0x0007 WARNING: to the ATA/ */
112 -3, /*<== */ /* 0x0008 WARNING: ATAPI version */
113 2, /* 0x0009 WARNING: listed in */
114 3, /* 0x000a WARNING: the */
115 3, /* 0x000b WARNING: minor_str */
116 3, /* 0x000c WARNING: array */
117 4, /* 0x000d WARNING: above. */
118 4, /* 0x000e WARNING: */
119 4, /* 0x000f WARNING: If you change */
120 4, /* 0x0010 WARNING: that one, */
121 4, /* 0x0011 WARNING: change this one */
122 4, /* 0x0012 WARNING: too!!! */
123 5, /* 0x0013 WARNING: */
124 4, /* 0x0014 WARNING: */
125 5, /* 0x0015 WARNING: */
126 5, /* 0x0016 WARNING: */
127 4, /* 0x0017 WARNING: */
128 6, /* 0x0018 WARNING: */
129 6, /* 0x0019 WARNING: */
130 7, /* 0x001a WARNING: */
131 6, /* 0x001b WARNING: */
132 6, /* 0x001c WARNING: */
133 7, /* 0x001d WARNING: */
134 7, /* 0x001e WARNING: */
135 0, /* 0x001f WARNING: */
136 0, /* 0x0020 WARNING: */
137 7, /* 0x0021 WARNING: */
138 6 /* 0x0022 WARNING: */
141 // When you add additional items to this list, you should then:
142 // 0 -- update this list
143 // 1 -- modify the following function parse_attribute_def()
144 // 2 -- if needed, modify ataPrintSmartAttribRawValue()
145 // 3 - if needed, modify ataPrintSmartAttribName()
146 // 4 -- add #define PRESET_N_DESCRIPTION at top of knowndrives.c
147 // 5 -- add drive in question into knowndrives[] table in knowndrives.c
148 // 6 -- update smartctl.8
149 // 7 -- update smartd.8
150 // 8 -- do "make smartd.conf.5" to update smartd.conf.5
151 // 9 -- update CHANGELOG file
152 const char *vendorattributeargs
[] = {
168 "200,writeerrorcount",
178 "201,detectedtacount",
180 "192,emergencyretractcyclect",
182 "198,offlinescanuncsectorct",
183 // NULL should always terminate the array
187 // This are the meanings of the Self-test failure checkpoint byte.
188 // This is in the self-test log at offset 4 bytes into the self-test
189 // descriptor and in the SMART READ DATA structure at byte offset
190 // 371. These codes are not well documented. The meanings returned by
191 // this routine are used (at least) by Maxtor and IBM. Returns NULL if
192 // not recognized. Currently the maximum length is 15 bytes.
193 const char *SelfTestFailureCodeName(unsigned char which
){
199 return "Servo_Basic";
201 return "Servo_Random";
203 return "G-list_Scan";
205 return "Handling_Damage";
213 // This is a utility function for parsing pairs like "9,minutes" or
214 // "220,temp", and putting the correct flag into the attributedefs
215 // array. Returns 1 if problem, 0 if pair has been recongized.
216 int parse_attribute_def(char *pair
, unsigned char **defsptr
){
221 // If array does not exist, allocate it
222 if (!*defsptr
&& !(*defsptr
=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM
, 1))){
223 pout("Out of memory in parse_attribute_def\n");
229 // look along list and see if we find the pair
230 for (i
=0; vendorattributeargs
[i
] && strcmp(pair
, vendorattributeargs
[i
]); i
++);
234 // attribute 9 is power on time in minutes
238 // attribute 9 is power-on-time in seconds
242 // attribute 9 is temperature in celsius
246 // attribute 220 is temperature in celsius
250 // print all attributes in raw 8-bit form
251 for (j
=0; j
<MAX_ATTRIBUTE_NUM
; j
++)
255 // print all attributes in raw 16-bit form
256 for (j
=0; j
<MAX_ATTRIBUTE_NUM
; j
++)
260 // print all attributes in raw 48-bit form
261 for (j
=0; j
<MAX_ATTRIBUTE_NUM
; j
++)
265 // attribute 200 is write error count
269 // attribute 9 increments once every 30 seconds (power on time
274 // attribute 194 is ten times disk temp in Celsius
278 // attribute 194 is unknown
282 // Hitachi : Attributes 193 has 2 values : 1 load, 1 normal unload
301 // At this point, either the pair was not found, or it is of the
302 // form N,uninterpreted, in which case we need to parse N
303 j
=sscanf(pair
,"%d,%14s", &i
, temp
);
305 // if no match to pattern, unrecognized
306 if (j
!=2 || i
<0 || i
>255)
309 // check for recognized strings
310 if (!strcmp(temp
, "raw8")) {
315 // check for recognized strings
316 if (!strcmp(temp
, "raw16")) {
321 // check for recognized strings
322 if (!strcmp(temp
, "raw48")) {
327 // didn't recognize the string
331 // Structure used in sorting the array vendorattributeargs[].
332 typedef struct vaa_pair_s
{
334 const char *padded_vaa
;
337 // Returns a copy of s with all numbers of less than three digits padded with
338 // leading zeros. Returns NULL if there isn't enough memory available. The
339 // memory for the string is dynamically allocated and should be freed by the
341 char *pad_numbers(const char *s
)
345 int i
, len
, ndigits
= 0;
347 // Allocate the maximum possible amount of memory needed.
348 if (!(t
= (char *)malloc(strlen(s
)*2+2)))
351 // Copy the string s to t, padding any numbers of less than three digits
352 // with leading zeros. The string is copied backwards to simplify the code.
355 while (( r
-- >= s
)) {
356 if (isdigit((int)*r
))
358 else if (ndigits
> 0) {
359 while (ndigits
++ < 3)
367 // Reverse the string in t.
369 for (i
= 0; i
< len
/2; i
++) {
378 // Comparison function for qsort(). Used by sort_vendorattributeargs().
379 int compare_vaa_pairs(const void *a
, const void *b
)
381 vaa_pair
*p
= (vaa_pair
*)a
;
382 vaa_pair
*q
= (vaa_pair
*)b
;
384 return strcmp(p
->padded_vaa
, q
->padded_vaa
);
387 // Returns a sorted list of vendorattributeargs or NULL if there is not enough
388 // memory available. The memory for the list is allocated dynamically and
389 // should be freed by the caller.
390 // To perform the sort, any numbers in the strings are padded out to three
391 // digits by adding leading zeros. For example,
393 // "9,minutes" becomes "009,minutes"
394 // "N,raw16" becomes "N,raw016"
396 // and the original strings are paired with the padded strings. The list of
397 // pairs is then sorted by comparing the padded strings (using strcmp) and the
398 // result is then the list of unpadded strings.
400 const char **sort_vendorattributeargs(void) {
401 const char **ps
, **sorted_list
= NULL
;
402 vaa_pair
*pairs
, *pp
;
405 // Figure out how many strings are in vendorattributeargs[] (not including
406 // the terminating NULL).
407 count
= (sizeof vendorattributeargs
) / sizeof(char *) - 1;
409 // Construct a list of pairs of strings from vendorattributeargs[] and their
410 // padded equivalents.
411 if (!(pairs
= (vaa_pair
*)malloc(sizeof(vaa_pair
) * count
)))
413 for (ps
= vendorattributeargs
, pp
= pairs
; *ps
; ps
++, pp
++) {
415 if (!(pp
->padded_vaa
= pad_numbers(*ps
)))
419 // Sort the array of vaa_pair structures by comparing the padded strings
421 qsort(pairs
, count
, sizeof(vaa_pair
), compare_vaa_pairs
);
423 // Construct the sorted list of strings.
424 if (!(sorted_list
= (const char **)malloc(sizeof vendorattributeargs
)))
426 for (ps
= sorted_list
, pp
= pairs
, i
= 0; i
< count
; ps
++, pp
++, i
++)
432 for (i
= 0; i
< count
; i
++)
433 if (pairs
[i
].padded_vaa
)
434 free((void *)pairs
[i
].padded_vaa
);
438 // If there was a problem creating the list then sorted_list should now
443 // Function to return a multiline string containing a list of the arguments in
444 // vendorattributeargs[]. The strings are preceeded by tabs and followed
445 // (except for the last) by newlines.
446 // This function allocates the required memory for the string and the caller
447 // must use free() to free it. It returns NULL if the required memory can't
449 char *create_vendor_attribute_arg_list(void){
450 const char **ps
, **sorted
;
454 // Get a sorted list of vendor attribute arguments. If the sort fails
455 // (which should only happen if the system is really low on memory) then just
456 // use the unordered list.
457 if (!(sorted
= (const char **) sort_vendorattributeargs()))
458 sorted
= vendorattributeargs
;
460 // Calculate the required number of characters
461 len
= 1; // At least one char ('\0')
462 for (ps
= sorted
; *ps
!= NULL
; ps
++) {
463 len
+= 1; // For the tab
464 len
+= strlen(*ps
); // For the actual argument string
466 len
++; // For the newline if required
469 // Attempt to allocate memory for the string
470 if (!(s
= (char *)malloc(len
)))
473 // Construct the string
475 for (ps
= sorted
; *ps
!= NULL
; ps
++) {
482 free((char **)sorted
);
484 // Return a pointer to the string
488 // swap two bytes. Point to low address
489 void swap2(char *location
){
491 *location
=*(location
+1);
496 // swap four bytes. Point to low address
497 void swap4(char *location
){
499 *location
=*(location
+3);
505 // swap eight bytes. Points to low address
506 void swap8(char *location
){
508 *location
=*(location
+7);
511 *(location
+1)=*(location
+6);
517 // Invalidate serial number and adjust checksum in IDENTIFY data
518 static void invalidate_serno(ata_identify_device
* id
){
519 unsigned char sum
= 0;
520 for (unsigned i
= 0; i
< sizeof(id
->serial_no
); i
++) {
521 sum
+= id
->serial_no
[i
]; sum
-= id
->serial_no
[i
] = 'X';
524 bool must_swap
= !!isbigendian();
526 swapx(id
->words088_255
+255-88);
528 if ((id
->words088_255
[255-88] & 0x00ff) == 0x00a5)
529 id
->words088_255
[255-88] += sum
<< 8;
532 swapx(id
->words088_255
+255-88);
536 static char *commandstrings
[]={
539 "SMART AUTOMATIC ATTRIBUTE SAVE",
540 "SMART IMMEDIATE OFFLINE",
541 "SMART AUTO OFFLINE",
543 "SMART STATUS CHECK",
544 "SMART READ ATTRIBUTE VALUES",
545 "SMART READ ATTRIBUTE THRESHOLDS",
548 "IDENTIFY PACKET DEVICE",
551 "WARNING (UNDEFINED COMMAND -- CONTACT DEVELOPERS AT " PACKAGE_BUGREPORT
")\n"
554 static void prettyprint(const unsigned char *p
, const char *name
){
555 pout("\n===== [%s] DATA START (BASE-16) =====\n", name
);
556 for (int i
=0; i
<512; i
+=16, p
+=16)
557 // print complete line to avoid slow tty output and extra lines in syslog.
558 pout("%03d-%03d: %02x %02x %02x %02x %02x %02x %02x %02x "
559 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
561 p
[ 0], p
[ 1], p
[ 2], p
[ 3], p
[ 4], p
[ 5], p
[ 6], p
[ 7],
562 p
[ 8], p
[ 9], p
[10], p
[11], p
[12], p
[13], p
[14], p
[15]);
563 pout("===== [%s] DATA END (512 Bytes) =====\n\n", name
);
566 static int parsedev_command_interface(int fd
, smart_command_set command
, int select
, char * data
);
568 // This function provides the pretty-print reporting for SMART
569 // commands: it implements the various -r "reporting" options for ATA
571 int smartcommandhandler(int device
, smart_command_set command
, int select
, char *data
){
574 // This conditional is true for commands that return data
575 int getsdata
=(command
==PIDENTIFY
||
578 command
==READ_THRESHOLDS
||
579 command
==READ_VALUES
||
580 command
==CHECK_POWER_MODE
);
582 int sendsdata
=(command
==WRITE_LOG
);
584 // If reporting is enabled, say what the command will be before it's executed
585 if (con
->reportataioctl
){
586 // conditional is true for commands that use parameters
587 int usesparam
=(command
==READ_LOG
||
588 command
==AUTO_OFFLINE
||
590 command
==IMMEDIATE_OFFLINE
||
593 pout("\nREPORT-IOCTL: DeviceFD=%d Command=%s", device
, commandstrings
[command
]);
595 pout(" InputParameter=%d\n", select
);
600 if ((getsdata
|| sendsdata
) && !data
){
601 pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings
[command
]);
605 // The reporting is cleaner, and we will find coding bugs faster, if
606 // the commands that failed clearly return empty (zeroed) data
609 if (command
==CHECK_POWER_MODE
)
612 memset(data
, '\0', 512);
616 // if requested, pretty-print the input data structure
617 if (con
->reportataioctl
>1 && sendsdata
)
618 prettyprint((unsigned char *)data
, commandstrings
[command
]);
620 // In case the command produces an error, we'll want to know what it is:
623 // now execute the command
624 switch (con
->controller_type
) {
625 case CONTROLLER_3WARE_678K
:
626 case CONTROLLER_3WARE_678K_CHAR
:
627 case CONTROLLER_3WARE_9000_CHAR
:
628 retval
=escalade_command_interface(device
, con
->controller_port
-1, con
->controller_type
, command
, select
, data
);
629 if (retval
&& con
->controller_port
<=0)
630 pout("WARNING: apparently missing '-d 3ware,N' disk specification\n");
632 case CONTROLLER_MARVELL_SATA
:
633 retval
=marvell_command_interface(device
, command
, select
, data
);
636 retval
=sat_command_interface(device
, command
, select
, data
);
639 retval
=highpoint_command_interface(device
, command
, select
, data
);
641 case CONTROLLER_PARSEDEV
:
642 retval
=parsedev_command_interface(device
, command
, select
, data
);
645 retval
=ata_command_interface(device
, command
, select
, data
);
648 // If requested, invalidate serial number before any printing is done
649 if ((command
== IDENTIFY
|| command
== PIDENTIFY
) && !retval
&& con
->dont_print_serial
)
650 invalidate_serno((ata_identify_device
*)data
);
652 // If reporting is enabled, say what output was produced by the command
653 if (con
->reportataioctl
){
655 pout("REPORT-IOCTL: DeviceFD=%d Command=%s returned %d errno=%d [%s]\n",
656 device
, commandstrings
[command
], retval
, errno
, strerror(errno
));
658 pout("REPORT-IOCTL: DeviceFD=%d Command=%s returned %d\n",
659 device
, commandstrings
[command
], retval
);
661 // if requested, pretty-print the output data structure
662 if (con
->reportataioctl
>1 && getsdata
) {
663 if (command
==CHECK_POWER_MODE
)
664 pout("Sector Count Register (BASE-16): %02x\n", (unsigned char)(*data
));
666 prettyprint((unsigned char *)data
, commandstrings
[command
]);
673 // This function computes the checksum of a single disk sector (512
674 // bytes). Returns zero if checksum is OK, nonzero if the checksum is
675 // incorrect. The size (512) is correct for all SMART structures.
676 unsigned char checksum(unsigned char *buffer
){
680 for (i
=0; i
<512; i
++)
686 // returns -1 if command fails or the device is in Sleep mode, else
687 // value of Sector Count register. Sector Count result values:
688 // 00h device is in Standby mode.
689 // 80h device is in Idle mode.
690 // FFh device is in Active mode or Idle mode.
692 int ataCheckPowerMode(int device
) {
693 unsigned char result
;
695 if ((smartcommandhandler(device
, CHECK_POWER_MODE
, 0, (char *)&result
)))
698 if (result
!=0 && result
!=0x80 && result
!=0xff)
699 pout("ataCheckPowerMode(): ATA CHECK POWER MODE returned unknown Sector Count Register value %02x\n", result
);
707 // Reads current Device Identity info (512 bytes) into buf. Returns 0
708 // if all OK. Returns -1 if no ATA Device identity can be
709 // established. Returns >0 if Device is ATA Packet Device (not SMART
710 // capable). The value of the integer helps identify the type of
711 // Packet device, which is useful so that the user can connect the
712 // formal device number with whatever object is inside their computer.
713 int ataReadHDIdentity (int device
, struct ata_identify_device
*buf
){
714 unsigned short *rawshort
=(unsigned short *)buf
;
715 unsigned char *rawbyte
=(unsigned char *)buf
;
717 // See if device responds either to IDENTIFY DEVICE or IDENTIFY
719 if ((smartcommandhandler(device
, IDENTIFY
, 0, (char *)buf
))){
720 if (smartcommandhandler(device
, PIDENTIFY
, 0, (char *)buf
)){
726 // if machine is big-endian, swap byte order as needed
727 // NetBSD kernel delivers IDENTIFY data in host byte order
731 // swap various capability words that are needed
733 swap2((char *)(buf
->words047_079
+i
));
735 for (i
=80; i
<=87; i
++)
736 swap2((char *)(rawshort
+i
));
738 for (i
=0; i
<168; i
++)
739 swap2((char *)(buf
->words088_255
+i
));
743 // If there is a checksum there, validate it
744 if ((rawshort
[255] & 0x00ff) == 0x00a5 && checksum(rawbyte
))
745 checksumwarning("Drive Identity Structure");
747 // If this is a PACKET DEVICE, return device type
748 if (rawbyte
[1] & 0x80)
749 return 1+(rawbyte
[1] & 0x1f);
751 // Not a PACKET DEVICE
755 // Returns ATA version as an integer, and a pointer to a string
756 // describing which revision. Note that Revision 0 of ATA-3 does NOT
757 // support SMART. For this one case we return -3 rather than +3 as
758 // the version number. See notes above.
759 int ataVersionInfo (const char** description
, struct ata_identify_device
*drive
, unsigned short *minor
){
760 unsigned short major
;
763 // check that arrays at the top of this file are defined
765 if (sizeof(minor_str
) != sizeof(char *)*(1+MINOR_MAX
)){
766 pout("Internal error in ataVersionInfo(). minor_str[] size %d\n"
767 "is not consistent with value of MINOR_MAX+1 = %d\n",
768 (int)(sizeof(minor_str
)/sizeof(char *)), MINOR_MAX
+1);
772 if (sizeof(actual_ver
) != sizeof(int)*(1+MINOR_MAX
)){
773 pout("Internal error in ataVersionInfo(). actual_ver[] size %d\n"
774 "is not consistent with value of MINOR_MAX = %d\n",
775 (int)(sizeof(actual_ver
)/sizeof(int)), MINOR_MAX
+1);
780 // get major and minor ATA revision numbers
781 major
=drive
->major_rev_num
;
782 *minor
=drive
->minor_rev_num
;
784 // First check if device has ANY ATA version information in it
785 if (major
==NOVAL_0
|| major
==NOVAL_1
) {
790 // The minor revision number has more information - try there first
791 if (*minor
&& (*minor
<=MINOR_MAX
)){
792 int std
= actual_ver
[*minor
];
794 *description
=minor_str
[*minor
];
799 // Try new ATA-8 minor revision numbers (Table 30 of T13/1699-D Revision 4b)
800 // (not in actual_ver/minor_str to avoid large sparse tables)
803 case 0x0027: desc
= "ATA-8-ACS revision 3c"; break;
804 case 0x0029: desc
= "ATA-8-ACS revision 4"; break;
805 case 0x0033: desc
= "ATA-8-ACS revision 3e"; break;
806 case 0x0042: desc
= "ATA-8-ACS revision 3f"; break;
807 case 0x0052: desc
= "ATA-8-ACS revision 3b"; break;
808 case 0x0107: desc
= "ATA-8-ACS revision 2d"; break;
809 default: desc
= 0; break;
816 // HDPARM has a very complicated algorithm from here on. Since SMART only
817 // exists on ATA-3 and later standards, let's punt on this. If you don't
818 // like it, please fix it. The code's in CVS.
820 if (major
& (0x1<<i
))
830 // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
831 int ataSmartSupport(struct ata_identify_device
*drive
){
832 unsigned short word82
=drive
->command_set_1
;
833 unsigned short word83
=drive
->command_set_2
;
835 // check if words 82/83 contain valid info
836 if ((word83
>>14) == 0x01)
837 // return value of SMART support bit
838 return word82
& 0x0001;
840 // since we can're rely on word 82, we don't know if SMART supported
844 // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
845 int ataIsSmartEnabled(struct ata_identify_device
*drive
){
846 unsigned short word85
=drive
->cfs_enable_1
;
847 unsigned short word87
=drive
->csf_default
;
849 // check if words 85/86/87 contain valid info
850 if ((word87
>>14) == 0x01)
851 // return value of SMART enabled bit
852 return word85
& 0x0001;
854 // Since we can't rely word85, we don't know if SMART is enabled.
859 // Reads SMART attributes into *data
860 int ataReadSmartValues(int device
, struct ata_smart_values
*data
){
862 if (smartcommandhandler(device
, READ_VALUES
, 0, (char *)data
)){
863 syserror("Error SMART Values Read failed");
868 if (checksum((unsigned char *)data
))
869 checksumwarning("SMART Attribute Data Structure");
871 // swap endian order if needed
874 swap2((char *)&(data
->revnumber
));
875 swap2((char *)&(data
->total_time_to_complete_off_line
));
876 swap2((char *)&(data
->smart_capability
));
877 for (i
=0; i
<NUMBER_ATA_SMART_ATTRIBUTES
; i
++){
878 struct ata_smart_attribute
*x
=data
->vendor_attributes
+i
;
879 swap2((char *)&(x
->flags
));
887 // This corrects some quantities that are byte reversed in the SMART
889 void fixsamsungselftestlog(struct ata_smart_selftestlog
*data
){
892 // bytes 508/509 (numbered from 0) swapped (swap of self-test index
893 // with one byte of reserved.
894 swap2((char *)&(data
->mostrecenttest
));
896 // LBA low register (here called 'selftestnumber", containing
897 // information about the TYPE of the self-test) is byte swapped with
898 // Self-test execution status byte. These are bytes N, N+1 in the
901 swap2((char *)&(data
->selftest_struct
[i
].selftestnumber
));
906 // Reads the Self Test Log (log #6)
907 int ataReadSelfTestLog (int device
, struct ata_smart_selftestlog
*data
){
909 // get data from device
910 if (smartcommandhandler(device
, READ_LOG
, 0x06, (char *)data
)){
911 syserror("Error SMART Error Self-Test Log Read failed");
915 // compute its checksum, and issue a warning if needed
916 if (checksum((unsigned char *)data
))
917 checksumwarning("SMART Self-Test Log Structure");
919 // fix firmware bugs in self-test log
920 if (con
->fixfirmwarebug
== FIX_SAMSUNG
)
921 fixsamsungselftestlog(data
);
923 // swap endian order if needed
926 swap2((char*)&(data
->revnumber
));
927 for (i
=0; i
<21; i
++){
928 struct ata_smart_selftestlog_struct
*x
=data
->selftest_struct
+i
;
929 swap2((char *)&(x
->timestamp
));
930 swap4((char *)&(x
->lbafirstfailure
));
938 // Reads the Log Directory (log #0). Note: NO CHECKSUM!!
939 int ataReadLogDirectory (int device
, struct ata_smart_log_directory
*data
){
941 // get data from device
942 if (smartcommandhandler(device
, READ_LOG
, 0x00, (char *)data
)){
946 // swap endian order if needed
948 swap2((char *)&(data
->logversion
));
955 // Reads the selective self-test log (log #9)
956 int ataReadSelectiveSelfTestLog(int device
, struct ata_selective_self_test_log
*data
){
958 // get data from device
959 if (smartcommandhandler(device
, READ_LOG
, 0x09, (char *)data
)){
960 syserror("Error SMART Read Selective Self-Test Log failed");
964 // compute its checksum, and issue a warning if needed
965 if (checksum((unsigned char *)data
))
966 checksumwarning("SMART Selective Self-Test Log Structure");
968 // swap endian order if needed
971 swap2((char *)&(data
->logversion
));
973 swap8((char *)&(data
->span
[i
].start
));
974 swap8((char *)&(data
->span
[i
].end
));
976 swap8((char *)&(data
->currentlba
));
977 swap2((char *)&(data
->currentspan
));
978 swap2((char *)&(data
->flags
));
979 swap2((char *)&(data
->pendingtime
));
982 if (data
->logversion
!= 1)
983 pout("SMART Selective Self-Test Log Data Structure Revision Number (%d) should be 1\n", data
->logversion
);
988 // Writes the selective self-test log (log #9)
989 int ataWriteSelectiveSelfTestLog(int device
, struct ata_smart_values
*sv
, uint64_t num_sectors
){
991 // Disk size must be known
993 pout("Disk size is unknown, unable to check selective self-test spans\n");
998 struct ata_selective_self_test_log sstlog
, *data
=&sstlog
;
999 unsigned char *ptr
=(unsigned char *)data
;
1000 if (ataReadSelectiveSelfTestLog(device
, data
)) {
1001 pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n");
1005 // Fix logversion if needed
1006 if (data
->logversion
!=1) {
1007 if (!con
->permissive
) {
1008 pout("Error SMART Selective Self-Test Log Data Structure Revision not recognized\n"
1009 "Revision number should be 1 but is %d. To be safe, aborting WRITE LOG.\n"
1010 "To fix revision number, add one '-T permissive' option.\n", data
->logversion
);
1014 pout("SMART Selective Self-Test Log Data Structure Revision should be 1 but is %d\n"
1015 "'-T permissive' specified, now trying to fix it by WRITE LOG.\n", data
->logversion
);
1016 data
->logversion
= 1;
1019 // Host is NOT allowed to write selective self-test log if a selective
1020 // self-test is in progress.
1021 if (0<data
->currentspan
&& data
->currentspan
<6 && ((sv
->self_test_exec_status
)>>4)==15) {
1022 pout("Error SMART Selective or other Self-Test in progress.\n");
1026 // Set start/end values based on old spans for special -t select,... options
1028 for (i
=0; i
<con
->smartselectivenumspans
; i
++) {
1029 char mode
= con
->smartselectivemode
[i
];
1030 uint64_t start
= con
->smartselectivespan
[i
][0];
1031 uint64_t end
= con
->smartselectivespan
[i
][1];
1032 if (mode
== SEL_CONT
) {// redo or next dependig on last test status
1033 switch (sv
->self_test_exec_status
>> 4) {
1034 case 1: case 2: // Aborted/Interrupted by host
1035 pout("Continue Selective Self-Test: Redo last span\n");
1038 default: // All others
1039 pout("Continue Selective Self-Test: Start next span\n");
1045 case SEL_RANGE
: // -t select,START-END
1047 case SEL_REDO
: // -t select,redo... => Redo current
1048 start
= data
->span
[i
].start
;
1049 if (end
> 0) { // -t select,redo+SIZE
1050 end
--; end
+= start
; // [oldstart, oldstart+SIZE)
1052 else // -t select,redo
1053 end
= data
->span
[i
].end
; // [oldstart, oldend]
1055 case SEL_NEXT
: // -t select,next... => Do next
1056 if (data
->span
[i
].end
== 0) {
1057 start
= end
= 0; break; // skip empty spans
1059 start
= data
->span
[i
].end
+ 1;
1060 if (start
>= num_sectors
)
1061 start
= 0; // wrap around
1062 if (end
> 0) { // -t select,next+SIZE
1063 end
--; end
+= start
; // (oldend, oldend+SIZE]
1065 else { // -t select,next
1066 uint64_t oldsize
= data
->span
[i
].end
- data
->span
[i
].start
+ 1;
1067 end
= start
+ oldsize
- 1; // (oldend, oldend+oldsize]
1068 if (end
>= num_sectors
) {
1069 // Adjust size to allow round-robin testing without future size decrease
1070 uint64_t spans
= (num_sectors
+ oldsize
-1) / oldsize
;
1071 uint64_t newsize
= (num_sectors
+ spans
-1) / spans
;
1072 uint64_t newstart
= num_sectors
- newsize
, newend
= num_sectors
- 1;
1073 pout("Span %d changed from %"PRIu64
"-%"PRIu64
" (%"PRIu64
" sectors)\n"
1074 " to %"PRIu64
"-%"PRIu64
" (%"PRIu64
" sectors) (%"PRIu64
" spans)\n",
1075 i
, start
, end
, oldsize
, newstart
, newend
, newsize
, spans
);
1076 start
= newstart
; end
= newend
;
1081 pout("ataWriteSelectiveSelfTestLog: Invalid mode %d\n", mode
);
1085 if (start
< num_sectors
&& num_sectors
<= end
) {
1086 if (end
!= ~(uint64_t)0) // -t select,N-max
1087 pout("Size of self-test span %d decreased according to disk size\n", i
);
1088 end
= num_sectors
- 1;
1090 if (!(start
<= end
&& end
< num_sectors
)) {
1091 pout("Invalid selective self-test span %d: %"PRIu64
"-%"PRIu64
" (%"PRIu64
" sectors)\n",
1092 i
, start
, end
, num_sectors
);
1095 // Write back to allow ataSmartTest() to print the actual values
1096 con
->smartselectivespan
[i
][0] = start
;
1097 con
->smartselectivespan
[i
][1] = end
;
1102 memset(data
->span
+i
, 0, sizeof(struct test_span
));
1104 // Set spans for testing
1105 for (i
=0; i
<con
->smartselectivenumspans
; i
++){
1106 data
->span
[i
].start
= con
->smartselectivespan
[i
][0];
1107 data
->span
[i
].end
= con
->smartselectivespan
[i
][1];
1110 // host must initialize to zero before initiating selective self-test
1112 data
->currentspan
=0;
1114 // Perform off-line scan after selective test?
1115 if (1 == con
->scanafterselect
)
1117 data
->flags
&= ~SELECTIVE_FLAG_DOSCAN
;
1118 else if (2 == con
->scanafterselect
)
1120 data
->flags
|= SELECTIVE_FLAG_DOSCAN
;
1122 // Must clear active and pending flags before writing
1123 data
->flags
&= ~(SELECTIVE_FLAG_ACTIVE
);
1124 data
->flags
&= ~(SELECTIVE_FLAG_PENDING
);
1126 // modify pending time?
1127 if (con
->pendingtime
)
1128 data
->pendingtime
=(unsigned short)(con
->pendingtime
-1);
1130 // Set checksum to zero, then compute checksum
1132 unsigned char cksum
=0;
1133 for (i
=0; i
<512; i
++)
1137 data
->checksum
=cksum
;
1139 // swap endian order if needed
1141 swap2((char *)&(data
->logversion
));
1142 for (int i
=0;i
<5;i
++){
1143 swap8((char *)&(data
->span
[i
].start
));
1144 swap8((char *)&(data
->span
[i
].end
));
1146 swap8((char *)&(data
->currentlba
));
1147 swap2((char *)&(data
->currentspan
));
1148 swap2((char *)&(data
->flags
));
1149 swap2((char *)&(data
->pendingtime
));
1152 // write new selective self-test log
1153 if (smartcommandhandler(device
, WRITE_LOG
, 0x09, (char *)data
)){
1154 syserror("Error Write Selective Self-Test Log failed");
1161 // This corrects some quantities that are byte reversed in the SMART
1163 void fixsamsungerrorlog(struct ata_smart_errorlog
*data
){
1166 // FIXED IN SAMSUNG -25 FIRMWARE???
1167 // Device error count in bytes 452-3
1168 swap2((char *)&(data
->ata_error_count
));
1170 // FIXED IN SAMSUNG -22a FIRMWARE
1171 // step through 5 error log data structures
1172 for (i
=0; i
<5; i
++){
1173 // step through 5 command data structures
1175 // Command data structure 4-byte millisec timestamp. These are
1176 // bytes (N+8, N+9, N+10, N+11).
1177 swap4((char *)&(data
->errorlog_struct
[i
].commands
[j
].timestamp
));
1178 // Error data structure two-byte hour life timestamp. These are
1179 // bytes (N+28, N+29).
1180 swap2((char *)&(data
->errorlog_struct
[i
].error_struct
.timestamp
));
1185 // NEEDED ONLY FOR SAMSUNG -22 (some) -23 AND -24?? FIRMWARE
1186 void fixsamsungerrorlog2(struct ata_smart_errorlog
*data
){
1187 // Device error count in bytes 452-3
1188 swap2((char *)&(data
->ata_error_count
));
1192 // Reads the Summary SMART Error Log (log #1). The Comprehensive SMART
1193 // Error Log is #2, and the Extended Comprehensive SMART Error log is
1195 int ataReadErrorLog (int device
, struct ata_smart_errorlog
*data
){
1197 // get data from device
1198 if (smartcommandhandler(device
, READ_LOG
, 0x01, (char *)data
)){
1199 syserror("Error SMART Error Log Read failed");
1203 // compute its checksum, and issue a warning if needed
1204 if (checksum((unsigned char *)data
))
1205 checksumwarning("SMART ATA Error Log Structure");
1207 // Some disks have the byte order reversed in some SMART Summary
1208 // Error log entries
1209 if (con
->fixfirmwarebug
== FIX_SAMSUNG
)
1210 fixsamsungerrorlog(data
);
1211 else if (con
->fixfirmwarebug
== FIX_SAMSUNG2
)
1212 fixsamsungerrorlog2(data
);
1214 // swap endian order if needed
1218 // Device error count in bytes 452-3
1219 swap2((char *)&(data
->ata_error_count
));
1221 // step through 5 error log data structures
1222 for (i
=0; i
<5; i
++){
1223 // step through 5 command data structures
1225 // Command data structure 4-byte millisec timestamp
1226 swap4((char *)&(data
->errorlog_struct
[i
].commands
[j
].timestamp
));
1227 // Error data structure life timestamp
1228 swap2((char *)&(data
->errorlog_struct
[i
].error_struct
.timestamp
));
1235 int ataReadSmartThresholds (int device
, struct ata_smart_thresholds_pvt
*data
){
1237 // get data from device
1238 if (smartcommandhandler(device
, READ_THRESHOLDS
, 0, (char *)data
)){
1239 syserror("Error SMART Thresholds Read failed");
1243 // compute its checksum, and issue a warning if needed
1244 if (checksum((unsigned char *)data
))
1245 checksumwarning("SMART Attribute Thresholds Structure");
1247 // swap endian order if needed
1249 swap2((char *)&(data
->revnumber
));
1254 int ataEnableSmart (int device
){
1255 if (smartcommandhandler(device
, ENABLE
, 0, NULL
)){
1256 syserror("Error SMART Enable failed");
1262 int ataDisableSmart (int device
){
1264 if (smartcommandhandler(device
, DISABLE
, 0, NULL
)){
1265 syserror("Error SMART Disable failed");
1271 int ataEnableAutoSave(int device
){
1272 if (smartcommandhandler(device
, AUTOSAVE
, 241, NULL
)){
1273 syserror("Error SMART Enable Auto-save failed");
1279 int ataDisableAutoSave(int device
){
1281 if (smartcommandhandler(device
, AUTOSAVE
, 0, NULL
)){
1282 syserror("Error SMART Disable Auto-save failed");
1288 // In *ALL* ATA standards the Enable/Disable AutoOffline command is
1289 // marked "OBSOLETE". It is defined in SFF-8035i Revision 2, and most
1290 // vendors still support it for backwards compatibility. IBM documents
1291 // it for some drives.
1292 int ataEnableAutoOffline (int device
){
1294 /* timer hard coded to 4 hours */
1295 if (smartcommandhandler(device
, AUTO_OFFLINE
, 248, NULL
)){
1296 syserror("Error SMART Enable Automatic Offline failed");
1302 // Another Obsolete Command. See comments directly above, associated
1303 // with the corresponding Enable command.
1304 int ataDisableAutoOffline (int device
){
1306 if (smartcommandhandler(device
, AUTO_OFFLINE
, 0, NULL
)){
1307 syserror("Error SMART Disable Automatic Offline failed");
1313 // If SMART is enabled, supported, and working, then this call is
1314 // guaranteed to return 1, else zero. Note that it should return 1
1315 // regardless of whether the disk's SMART status is 'healthy' or
1317 int ataDoesSmartWork(int device
){
1318 int retval
=smartcommandhandler(device
, STATUS
, 0, NULL
);
1326 // This function uses a different interface (DRIVE_TASK) than the
1327 // other commands in this file.
1328 int ataSmartStatus2(int device
){
1329 return smartcommandhandler(device
, STATUS_CHECK
, 0, NULL
);
1332 // This is the way to execute ALL tests: offline, short self-test,
1333 // extended self test, with and without captive mode, etc.
1334 int ataSmartTest(int device
, int testtype
, struct ata_smart_values
*sv
, uint64_t num_sectors
)
1336 char cmdmsg
[128],*type
,*captive
;
1337 int errornum
, cap
, retval
, select
=0;
1339 // Boolean, if set, says test is captive
1340 cap
=testtype
& CAPTIVE_MASK
;
1342 // Set up strings that describe the type of test
1348 if (testtype
==OFFLINE_FULL_SCAN
)
1350 else if (testtype
==SHORT_SELF_TEST
|| testtype
==SHORT_CAPTIVE_SELF_TEST
)
1351 type
="Short self-test";
1352 else if (testtype
==EXTEND_SELF_TEST
|| testtype
==EXTEND_CAPTIVE_SELF_TEST
)
1353 type
="Extended self-test";
1354 else if (testtype
==CONVEYANCE_SELF_TEST
|| testtype
==CONVEYANCE_CAPTIVE_SELF_TEST
)
1355 type
="Conveyance self-test";
1356 else if ((select
=(testtype
==SELECTIVE_SELF_TEST
|| testtype
==SELECTIVE_CAPTIVE_SELF_TEST
)))
1357 type
="Selective self-test";
1359 type
="[Unrecognized] self-test";
1361 // If doing a selective self-test, first use WRITE_LOG to write the
1362 // selective self-test log.
1363 if (select
&& (retval
=ataWriteSelectiveSelfTestLog(device
, sv
, num_sectors
))) {
1365 pout("Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");
1369 // Print ouf message that we are sending the command to test
1370 if (testtype
==ABORT_SELF_TEST
)
1371 sprintf(cmdmsg
,"Abort SMART off-line mode self-test routine");
1373 sprintf(cmdmsg
,"Execute SMART %s routine immediately in %s mode",type
,captive
);
1374 pout("Sending command: \"%s\".\n",cmdmsg
);
1378 pout("SPAN STARTING_LBA ENDING_LBA\n");
1379 for (i
= 0; i
< con
->smartselectivenumspans
; i
++)
1380 pout(" %d %20"PRId64
" %20"PRId64
"\n", i
,
1381 con
->smartselectivespan
[i
][0],
1382 con
->smartselectivespan
[i
][1]);
1385 // Now send the command to test
1386 errornum
=smartcommandhandler(device
, IMMEDIATE_OFFLINE
, testtype
, NULL
);
1388 if (errornum
&& !(cap
&& errno
==EIO
)){
1390 sprintf(errormsg
,"Command \"%s\" failed",cmdmsg
);
1396 // Since the command succeeded, tell user
1397 if (testtype
==ABORT_SELF_TEST
)
1398 pout("Self-testing aborted!\n");
1400 pout("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg
);
1404 /* Test Time Functions */
1405 int TestTime(struct ata_smart_values
*data
,int testtype
){
1407 case OFFLINE_FULL_SCAN
:
1408 return (int) data
->total_time_to_complete_off_line
;
1409 case SHORT_SELF_TEST
:
1410 case SHORT_CAPTIVE_SELF_TEST
:
1411 return (int) data
->short_test_completion_time
;
1412 case EXTEND_SELF_TEST
:
1413 case EXTEND_CAPTIVE_SELF_TEST
:
1414 return (int) data
->extend_test_completion_time
;
1415 case CONVEYANCE_SELF_TEST
:
1416 case CONVEYANCE_CAPTIVE_SELF_TEST
:
1417 return (int) data
->conveyance_test_completion_time
;
1423 // This function tells you both about the ATA error log and the
1424 // self-test error log capability (introduced in ATA-5). The bit is
1425 // poorly documented in the ATA/ATAPI standard. Starting with ATA-6,
1426 // SMART error logging is also indicated in bit 0 of DEVICE IDENTIFY
1427 // word 84 and 87. Top two bits must match the pattern 01. BEFORE
1428 // ATA-6 these top two bits still had to match the pattern 01, but the
1429 // remaining bits were reserved (==0).
1430 int isSmartErrorLogCapable (struct ata_smart_values
*data
, struct ata_identify_device
*identity
){
1432 unsigned short word84
=identity
->command_set_extension
;
1433 unsigned short word87
=identity
->csf_default
;
1434 int isata6
=identity
->major_rev_num
& (0x01<<6);
1435 int isata7
=identity
->major_rev_num
& (0x01<<7);
1437 if ((isata6
|| isata7
) && (word84
>>14) == 0x01 && (word84
& 0x01))
1440 if ((isata6
|| isata7
) && (word87
>>14) == 0x01 && (word87
& 0x01))
1443 // otherwise we'll use the poorly documented capability bit
1444 return data
->errorlog_capability
& 0x01;
1447 // See previous function. If the error log exists then the self-test
1448 // log should (must?) also exist.
1449 int isSmartTestLogCapable (struct ata_smart_values
*data
, struct ata_identify_device
*identity
){
1451 unsigned short word84
=identity
->command_set_extension
;
1452 unsigned short word87
=identity
->csf_default
;
1453 int isata6
=identity
->major_rev_num
& (0x01<<6);
1454 int isata7
=identity
->major_rev_num
& (0x01<<7);
1456 if ((isata6
|| isata7
) && (word84
>>14) == 0x01 && (word84
& 0x02))
1459 if ((isata6
|| isata7
) && (word87
>>14) == 0x01 && (word87
& 0x02))
1463 // otherwise we'll use the poorly documented capability bit
1464 return data
->errorlog_capability
& 0x01;
1468 int isGeneralPurposeLoggingCapable(struct ata_identify_device
*identity
){
1469 unsigned short word84
=identity
->command_set_extension
;
1470 unsigned short word87
=identity
->csf_default
;
1472 // If bit 14 of word 84 is set to one and bit 15 of word 84 is
1473 // cleared to zero, the contents of word 84 contains valid support
1474 // information. If not, support information is not valid in this
1476 if ((word84
>>14) == 0x01)
1477 // If bit 5 of word 84 is set to one, the device supports the
1478 // General Purpose Logging feature set.
1479 return (word84
& (0x01 << 5));
1481 // If bit 14 of word 87 is set to one and bit 15 of word 87 is
1482 // cleared to zero, the contents of words (87:85) contain valid
1483 // information. If not, information is not valid in these words.
1484 if ((word87
>>14) == 0x01)
1485 // If bit 5 of word 87 is set to one, the device supports
1486 // the General Purpose Logging feature set.
1487 return (word87
& (0x01 << 5));
1494 // SMART self-test capability is also indicated in bit 1 of DEVICE
1495 // IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
1496 // However this was only introduced in ATA-6 (but self-test log was in
1498 int isSupportExecuteOfflineImmediate(struct ata_smart_values
*data
){
1499 return data
->offline_data_collection_capability
& 0x01;
1501 // Note in the ATA-5 standard, the following bit is listed as "Vendor
1502 // Specific". So it may not be reliable. The only use of this that I
1503 // have found is in IBM drives, where it is well-documented. See for
1504 // example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
1505 // hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
1506 int isSupportAutomaticTimer(struct ata_smart_values
*data
){
1507 return data
->offline_data_collection_capability
& 0x02;
1509 int isSupportOfflineAbort(struct ata_smart_values
*data
){
1510 return data
->offline_data_collection_capability
& 0x04;
1512 int isSupportOfflineSurfaceScan(struct ata_smart_values
*data
){
1513 return data
->offline_data_collection_capability
& 0x08;
1515 int isSupportSelfTest (struct ata_smart_values
*data
){
1516 return data
->offline_data_collection_capability
& 0x10;
1518 int isSupportConveyanceSelfTest(struct ata_smart_values
*data
){
1519 return data
->offline_data_collection_capability
& 0x20;
1521 int isSupportSelectiveSelfTest(struct ata_smart_values
*data
){
1522 return data
->offline_data_collection_capability
& 0x40;
1527 // Loop over all valid attributes. If they are prefailure attributes
1528 // and are at or below the threshold value, then return the ID of the
1529 // first failing attribute found. Return 0 if all prefailure
1530 // attributes are in bounds. The spec says "Bit 0
1531 // -Pre-failure/advisory - If the value of this bit equals zero, an
1532 // attribute value less than or equal to its corresponding attribute
1533 // threshold indicates an advisory condition where the usage or age of
1534 // the device has exceeded its intended design life period. If the
1535 // value of this bit equals one, an atribute value less than or equal
1536 // to its corresponding attribute threshold indicates a pre-failure
1537 // condition where imminent loss of data is being predicted."
1540 // onlyfailed=0 : are or were any age or prefailure attributes <= threshold
1541 // onlyfailed=1: are any prefailure attributes <= threshold now
1542 int ataCheckSmart(struct ata_smart_values
*data
,
1543 struct ata_smart_thresholds_pvt
*thresholds
,
1547 // loop over all attributes
1548 for (i
=0; i
<NUMBER_ATA_SMART_ATTRIBUTES
; i
++){
1550 // pointers to disk's values and vendor's thresholds
1551 struct ata_smart_attribute
*disk
=data
->vendor_attributes
+i
;
1552 struct ata_smart_threshold_entry
*thre
=thresholds
->thres_entries
+i
;
1554 // consider only valid attributes
1555 if (disk
->id
&& thre
->id
){
1556 int failednow
,failedever
;
1558 failednow
=disk
->current
<= thre
->threshold
;
1559 failedever
=disk
->worst
<= thre
->threshold
;
1561 if (!onlyfailed
&& failedever
)
1564 if (onlyfailed
&& failednow
&& ATTRIBUTE_FLAGS_PREFAILURE(disk
->flags
))
1573 // This checks the n'th attribute in the attribute list, NOT the
1574 // attribute with id==n. If the attribute does not exist, or the
1575 // attribute is > threshold, then returns zero. If the attribute is
1576 // <= threshold (failing) then we the attribute number if it is a
1577 // prefail attribute. Else we return minus the attribute number if it
1578 // is a usage attribute.
1579 int ataCheckAttribute(struct ata_smart_values
*data
,
1580 struct ata_smart_thresholds_pvt
*thresholds
,
1582 struct ata_smart_attribute
*disk
;
1583 struct ata_smart_threshold_entry
*thre
;
1585 if (n
<0 || n
>=NUMBER_ATA_SMART_ATTRIBUTES
|| !data
|| !thresholds
)
1588 // pointers to disk's values and vendor's thresholds
1589 disk
=data
->vendor_attributes
+n
;
1590 thre
=thresholds
->thres_entries
+n
;
1595 // consider only valid attributes, check for failure
1596 if (!disk
->id
|| !thre
->id
|| (disk
->id
!= thre
->id
) || disk
->current
> thre
->threshold
)
1599 // We have found a failed attribute. Return positive or negative?
1600 if (ATTRIBUTE_FLAGS_PREFAILURE(disk
->flags
))
1603 return -1*(disk
->id
);
1607 // Print temperature value and Min/Max value if present
1608 static void ataPrintTemperatureValue(char *out
, const unsigned char *raw
, const unsigned *word
)
1610 out
+=sprintf(out
, "%u", word
[0]);
1611 if (!word
[1] && !word
[2])
1612 return; // No Min/Max
1614 unsigned lo
= ~0, hi
= ~0;
1616 // 00 HH 00 LL 00 TT (IBM)
1617 hi
= word
[2]; lo
= word
[1];
1619 else if (!word
[2]) {
1620 // 00 00 HH LL 00 TT (Maxtor)
1621 hi
= raw
[3]; lo
= raw
[2];
1624 unsigned t
= lo
; lo
= hi
; hi
= t
;
1626 if (lo
<= word
[0] && word
[0] <= hi
)
1627 sprintf(out
, " (Lifetime Min/Max %u/%u)", lo
, hi
);
1629 sprintf(out
, " (%u %u %u %u)", raw
[5], raw
[4], raw
[3], raw
[2]);
1633 // This routine prints the raw value of an attribute as a text string
1634 // into out. It also returns this 48-bit number as a long long. The
1635 // array defs[] contains non-zero values if particular attributes have
1636 // non-default interpretations.
1638 int64_t ataPrintSmartAttribRawValue(char *out
,
1639 struct ata_smart_attribute
*attribute
,
1640 unsigned char *defs
){
1644 unsigned char select
;
1646 // convert the six individual bytes to a long long (8 byte) integer.
1647 // This is the value that we'll eventually return.
1649 for (j
=0; j
<6; j
++) {
1650 // This looks a bit roundabout, but is necessary. Don't
1651 // succumb to the temptation to use raw[j]<<(8*j) since under
1652 // the normal rules this will be promoted to the native type.
1653 // On a 32 bit machine this might then overflow.
1655 temp
= attribute
->raw
[j
];
1660 // convert quantities to three two-byte words
1661 for (j
=0; j
<3; j
++){
1662 word
[j
] = attribute
->raw
[2*j
+1];
1664 word
[j
] |= attribute
->raw
[2*j
];
1667 // if no data array, Attributes have default interpretations
1669 select
=defs
[attribute
->id
];
1673 // Print six one-byte quantities.
1676 out
+=sprintf(out
, "%d ", attribute
->raw
[5-j
]);
1677 out
+=sprintf(out
, "%d ", attribute
->raw
[0]);
1681 // Print three two-byte quantities
1683 out
+=sprintf(out
, "%d %d %d", word
[2], word
[1], word
[0]);
1687 // Print one six-byte quantity
1689 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1693 // This switch statement is where we handle Raw attributes
1694 // that are stored in an unusual vendor-specific format,
1695 switch (attribute
->id
){
1698 out
+=sprintf(out
, "%d", word
[0]);
1699 // if second nonzero then it stores the average spin-up time
1701 out
+=sprintf(out
, " (Average %d)", word
[1]);
1707 int64_t tmp1
=rawvalue
/60;
1708 int64_t tmp2
=rawvalue
%60;
1709 out
+=sprintf(out
, "%"PRIu64
"h+%02"PRIu64
"m", tmp1
, tmp2
);
1711 else if (select
==3){
1713 int64_t hours
=rawvalue
/3600;
1714 int64_t minutes
=(rawvalue
-3600*hours
)/60;
1715 int64_t seconds
=rawvalue
%60;
1716 out
+=sprintf(out
, "%"PRIu64
"h+%02"PRIu64
"m+%02"PRIu64
"s", hours
, minutes
, seconds
);
1718 else if (select
==4){
1719 // 30-second counter
1720 int64_t tmp1
=rawvalue
/120;
1721 int64_t tmp2
=(rawvalue
-120*tmp1
)/2;
1722 out
+=sprintf(out
, "%"PRIu64
"h+%02"PRIu64
"m", tmp1
, tmp2
);
1726 out
+=sprintf(out
, "%"PRIu64
, rawvalue
); //stored in hours
1730 ataPrintTemperatureValue(out
, attribute
->raw
, word
);
1732 // Load unload cycles
1736 long load
=attribute
->raw
[0] + (attribute
->raw
[1]<<8) + (attribute
->raw
[2]<<16);
1737 long unload
=attribute
->raw
[3] + (attribute
->raw
[4]<<8) + (attribute
->raw
[5]<<16);
1738 out
+=sprintf(out
, "%lu/%lu", load
, unload
);
1742 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1747 // ten times temperature in Celsius
1749 int tenths
=word
[0]%10;
1750 out
+=sprintf(out
, "%d.%d", deg
, tenths
);
1753 // unknown attribute
1754 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1756 ataPrintTemperatureValue(out
, attribute
->raw
, word
);
1759 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1762 // Return the full value
1767 // Note some attribute names appear redundant because different
1768 // manufacturers use different attribute IDs for an attribute with the
1769 // same name. The variable val should contain a non-zero value if a particular
1770 // attributes has a non-default interpretation.
1771 void ataPrintSmartAttribName(char *out
, unsigned char id
, unsigned char *definitions
){
1775 // If no data array, use default interpretations
1777 val
=definitions
[id
];
1784 name
="Raw_Read_Error_Rate";
1787 name
="Throughput_Performance";
1790 name
="Spin_Up_Time";
1793 name
="Start_Stop_Count";
1796 name
="Reallocated_Sector_Ct";
1799 name
="Read_Channel_Margin";
1802 name
="Seek_Error_Rate";
1805 name
="Seek_Time_Performance";
1810 name
="Power_On_Minutes";
1813 name
="Temperature_Celsius";
1816 name
="Power_On_Seconds";
1819 name
="Power_On_Half_Minutes";
1822 name
="Power_On_Hours";
1827 name
="Spin_Retry_Count";
1830 name
="Calibration_Retry_Count";
1833 name
="Power_Cycle_Count";
1836 name
="Read_Soft_Error_Rate";
1839 name
="Reported_Uncorrect";
1842 name
="High_Fly_Writes";
1845 // Western Digital uses this for temperature.
1846 // It's identical to Attribute 194 except that it
1847 // has a failure threshold set to correspond to the
1848 // max allowed operating temperature of the drive, which
1849 // is typically 55C. So if this attribute has failed
1850 // in the past, it indicates that the drive temp exceeded
1851 // 55C sometime in the past.
1852 name
="Airflow_Temperature_Cel";
1855 name
="G-Sense_Error_Rate";
1861 name
="Emergency_Retract_Cycle_Ct";
1864 name
="Power-Off_Retract_Count";
1869 name
="Load_Cycle_Count";
1874 // Samsung SV1204H with RK100-13 firmware
1875 name
="Temperature_Celsius_x10";
1878 // for disks with no temperature Attribute
1879 name
="Unknown_Attribute";
1882 name
="Temperature_Celsius";
1887 // Fujitsu name="ECC_On_The_Fly_Count";
1888 name
="Hardware_ECC_Recovered";
1891 name
="Reallocated_Event_Count";
1894 name
="Current_Pending_Sector";
1900 name
="Off-line_Scan_UNC_Sector_Ct";
1903 name
="Offline_Uncorrectable";
1908 name
="UDMA_CRC_Error_Count";
1913 // Fujitsu MHS2020AT
1914 name
="Write_Error_Count";
1918 name
="Multi_Zone_Error_Rate";
1926 name
="Detected_TA_Count";
1929 name
="Soft_Read_Error_Rate";
1935 name
="TA_Increase_Count";
1936 // Maxtor: Data Address Mark Errors
1940 name
="Run_Out_Cancel";
1941 // Maxtor: ECC Errors
1945 name
="Shock_Count_Write_Opern";
1946 // Maxtor: Soft ECC Correction
1950 name
="Shock_Rate_Write_Opern";
1951 // Maxtor: Thermal Aspirates
1955 name
="Flying_Height";
1959 name
="Spin_High_Current";
1967 name
="Offline_Seek_Performnce";
1972 name
="Temperature_Celsius";
1980 name
="G-Sense_Error_Rate";
1983 name
="Loaded_Hours";
1986 name
="Load_Retry_Count";
1989 name
="Load_Friction";
1992 name
="Load_Cycle_Count";
1995 name
="Load-in_Time";
1998 name
="Torq-amp_Count";
2001 name
="Power-off_Retract_Count";
2004 // seen in IBM DTPA-353750
2005 name
="Head_Amplitude";
2008 name
="Temperature_Celsius";
2011 name
="Head_Flying_Hours";
2014 name
="Read_Error_Retry_Rate";
2017 name
="Unknown_Attribute";
2020 sprintf(out
,"%3hu %s",(short int)id
,name
);
2024 // Returns raw value of Attribute with ID==id. This will be in the
2025 // range 0 to 2^48-1 inclusive. If the Attribute does not exist,
2027 int64_t ATAReturnAttributeRawValue(unsigned char id
, struct ata_smart_values
*data
) {
2030 // valid Attribute IDs are in the range 1 to 255 inclusive.
2034 // loop over Attributes to see if there is one with the desired ID
2035 for (i
=0; i
<NUMBER_ATA_SMART_ATTRIBUTES
; i
++) {
2036 struct ata_smart_attribute
*ap
= data
->vendor_attributes
+ i
;
2038 // we've found the desired Attribute. Return its value
2042 for (j
=0; j
<6; j
++) {
2043 // This looks a bit roundabout, but is necessary. Don't
2044 // succumb to the temptation to use raw[j]<<(8*j) since under
2045 // the normal rules this will be promoted to the native type.
2046 // On a 32 bit machine this might then overflow.
2053 } // found desired Attribute
2054 } // loop over Attributes
2056 // fall-through: no such Attribute found
2060 // Return Temperature Attribute raw value selected according to possible
2061 // non-default interpretations. If the Attribute does not exist, return 0
2062 unsigned char ATAReturnTemperatureValue(/*const*/ struct ata_smart_values
*data
, const unsigned char *defs
){
2064 for (i
= 0; i
< 3; i
++) {
2065 static const unsigned char ids
[3] = {194, 9, 220};
2066 unsigned char id
= ids
[i
];
2067 unsigned char select
= (defs
? defs
[id
] : 0);
2068 int64_t raw
; unsigned temp
;
2069 if (!( (id
== 194 && select
<= 1) // ! -v 194,unknown
2070 || (id
== 9 && select
== 2) // -v 9,temp
2071 || (id
== 220 && select
== 1))) // -v 220,temp
2073 raw
= ATAReturnAttributeRawValue(id
, data
);
2076 temp
= (unsigned short)raw
; // ignore possible min/max values in high words
2077 if (id
== 194 && select
== 1) // -v 194,10xCelsius
2078 temp
= (temp
+5) / 10;
2079 if (!(0 < temp
&& temp
<= 255))
2083 // No valid attribute found
2088 int ataReadSCTStatus(int device
, ata_sct_status_response
* sts
)
2090 // read SCT status via SMART log 0xe0
2091 memset(sts
, 0, sizeof(*sts
));
2092 if (smartcommandhandler(device
, READ_LOG
, 0xe0, (char *)sts
)){
2093 syserror("Error Read SCT Status failed");
2097 // swap endian order if needed
2099 swapx(&sts
->format_version
);
2100 swapx(&sts
->sct_version
);
2101 swapx(&sts
->sct_spec
);
2102 swapx(&sts
->ext_status_code
);
2103 swapx(&sts
->action_code
);
2104 swapx(&sts
->function_code
);
2105 swapx(&sts
->over_limit_count
);
2106 swapx(&sts
->under_limit_count
);
2109 // Check format version
2110 if (!(sts
->format_version
== 2 || sts
->format_version
== 3)) {
2111 pout("Error unknown SCT Status format version %u, should be 2 or 3.\n", sts
->format_version
);
2117 // Read SCT Temperature History Table and Status
2118 int ataReadSCTTempHist(int device
, ata_sct_temperature_history_table
* tmh
,
2119 ata_sct_status_response
* sts
)
2121 // Check initial status
2122 if (ataReadSCTStatus(device
, sts
))
2125 // Do nothing if other SCT command is executing
2126 if (sts
->ext_status_code
== 0xffff) {
2127 pout("Another SCT command is executing, abort Read Data Table\n"
2128 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2129 sts
->ext_status_code
, sts
->action_code
, sts
->function_code
);
2133 ata_sct_data_table_command cmd
; memset(&cmd
, 0, sizeof(cmd
));
2134 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2135 cmd
.action_code
= 5; // Data table command
2136 cmd
.function_code
= 1; // Read table
2137 cmd
.table_id
= 2; // Temperature History Table
2139 // write command via SMART log page 0xe0
2140 if (smartcommandhandler(device
, WRITE_LOG
, 0xe0, (char *)&cmd
)){
2141 syserror("Error Write SCT Data Table command failed");
2145 // read SCT data via SMART log page 0xe1
2146 memset(tmh
, 0, sizeof(*tmh
));
2147 if (smartcommandhandler(device
, READ_LOG
, 0xe1, (char *)tmh
)){
2148 syserror("Error Read SCT Data Table failed");
2152 // re-read and check SCT status
2153 if (ataReadSCTStatus(device
, sts
))
2156 if (!(sts
->ext_status_code
== 0 && sts
->action_code
== 5 && sts
->function_code
== 1)) {
2157 pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2158 sts
->ext_status_code
, sts
->action_code
, sts
->function_code
);
2162 // swap endian order if needed
2164 swapx(&tmh
->format_version
);
2165 swapx(&tmh
->sampling_period
);
2166 swapx(&tmh
->interval
);
2169 // Check format version
2170 if (tmh
->format_version
!= 2) {
2171 pout("Error unknown SCT Temperature History Format Version (%u), should be 2.\n", tmh
->format_version
);
2177 // Set SCT Temperature Logging Interval
2178 int ataSetSCTTempInterval(int device
, unsigned interval
, bool persistent
)
2180 // Check initial status
2181 ata_sct_status_response sts
;
2182 if (ataReadSCTStatus(device
, &sts
))
2185 // Do nothing if other SCT command is executing
2186 if (sts
.ext_status_code
== 0xffff) {
2187 pout("Another SCT command is executing, abort Feature Control\n"
2188 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2189 sts
.ext_status_code
, sts
.action_code
, sts
.function_code
);
2193 ata_sct_feature_control_command cmd
; memset(&cmd
, 0, sizeof(cmd
));
2194 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2195 cmd
.action_code
= 4; // Feature Control command
2196 cmd
.function_code
= 1; // Set state
2197 cmd
.feature_code
= 3; // Temperature logging interval
2198 cmd
.state
= interval
;
2199 cmd
.option_flags
= (persistent
? 0x01 : 0x00);
2201 // write command via SMART log page 0xe0
2202 if (smartcommandhandler(device
, WRITE_LOG
, 0xe0, (char *)&cmd
)){
2203 syserror("Error Write SCT Feature Control Command failed");
2207 // re-read and check SCT status
2208 if (ataReadSCTStatus(device
, &sts
))
2211 if (!(sts
.ext_status_code
== 0 && sts
.action_code
== 4 && sts
.function_code
== 1)) {
2212 pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2213 sts
.ext_status_code
, sts
.action_code
, sts
.function_code
);
2220 /////////////////////////////////////////////////////////////////////////////
2221 // Pseudo-device to parse "smartctl -r ataioctl,2 ..." output and simulate
2222 // an ATA device with same behaviour
2224 // Table of parsed commands, return value, data
2225 struct parsed_ata_command
2227 smart_command_set command
;
2233 const int max_num_parsed_commands
= 32;
2234 static parsed_ata_command parsed_command_table
[max_num_parsed_commands
];
2235 static int num_parsed_commands
;
2236 static int next_replay_command
;
2237 static bool replay_out_of_sync
;
2240 static const char * nextline(const char * s
, int & lineno
)
2242 for (s
+= strcspn(s
, "\r\n"); *s
== '\r' || *s
== '\n'; s
++) {
2243 if (*s
== '\r' && s
[1] == '\n')
2250 static int name2command(const char * s
)
2252 for (int i
= 0; i
< (int)(sizeof(commandstrings
)/sizeof(commandstrings
[0])); i
++) {
2253 if (!strcmp(s
, commandstrings
[i
]))
2259 static bool matchcpy(char * dest
, size_t size
, const char * src
, const regmatch_t
& srcmatch
)
2261 if (srcmatch
.rm_so
< 0)
2263 size_t n
= srcmatch
.rm_eo
- srcmatch
.rm_so
;
2266 memcpy(dest
, src
+ srcmatch
.rm_so
, n
);
2271 static inline int matchtoi(const char * src
, const regmatch_t
& srcmatch
, int defval
)
2273 if (srcmatch
.rm_so
< 0)
2275 return atoi(src
+ srcmatch
.rm_so
);
2279 // Parse stdin and build command table
2280 int parsedev_open(const char * pathname
)
2282 if (strcmp(pathname
, "-")) {
2283 errno
= EINVAL
; return -1;
2285 pathname
= "<stdin>";
2287 char buffer
[64*1024];
2289 while (size
< (int)sizeof(buffer
)) {
2290 int nr
= fread(buffer
, 1, sizeof(buffer
), stdin
);
2296 pout("%s: Unexpected EOF\n", pathname
);
2297 errno
= ENOENT
; return -1;
2299 if (size
>= (int)sizeof(buffer
)) {
2300 pout("%s: Buffer overflow\n", pathname
);
2301 errno
= EIO
; return -1;
2305 // Regex to match output from "-r ataioctl,2"
2306 static const char pattern
[] = "^"
2308 "REPORT-IOCTL: DeviceFD=[0-9]+ Command=([A-Z ]*[A-Z])" // (2)
2310 "( InputParameter=([0-9]+))?" // (4 (5))
2312 "( returned (-?[0-9]+)( errno=([0-9]+)[^\r\n]*)?)" // (6 (7) (8 (9)))
2314 "[\r\n]" // EOL match necessary to match optional parts above
2316 "===== \\[([A-Z ]*[A-Z])\\] DATA START " // (10)
2321 if (compileregex(&rex
, pattern
, REG_EXTENDED
)) {
2322 errno
= EIO
; return -1;
2326 const char * errmsg
= 0;
2327 int i
= -1, state
= 0, lineno
= 1;
2328 for (const char * line
= buffer
; *line
; line
= nextline(line
, lineno
)) {
2330 if (!(line
[0] == 'R' || line
[0] == '='))
2332 const int nmatch
= 1+10;
2333 regmatch_t match
[nmatch
];
2334 if (regexec(&rex
, line
, nmatch
, match
, 0))
2338 if (matchcpy(cmdname
, sizeof(cmdname
), line
, match
[2])) { // "REPORT-IOCTL:... Command=%s ..."
2339 int nc
= name2command(cmdname
);
2341 errmsg
= "Unknown ATA command name"; break;
2343 if (match
[7].rm_so
< 0) { // "returned %d"
2345 if (!(state
== 0 || state
== 2)) {
2346 errmsg
= "Missing REPORT-IOCTL result"; break;
2348 if (++i
>= max_num_parsed_commands
) {
2349 errmsg
= "Too many ATA commands"; break;
2351 parsed_command_table
[i
].command
= (smart_command_set
)nc
;
2352 parsed_command_table
[i
].select
= matchtoi(line
, match
[5], 0); // "InputParameter=%d"
2357 if (!(state
== 1 && (int)parsed_command_table
[i
].command
== nc
)) {
2358 errmsg
= "Missing REPORT-IOCTL start"; break;
2360 parsed_command_table
[i
].retval
= matchtoi(line
, match
[7], -1); // "returned %d"
2361 parsed_command_table
[i
].errval
= matchtoi(line
, match
[9], 0); // "errno=%d"
2365 else if (matchcpy(cmdname
, sizeof(cmdname
), line
, match
[10])) { // "===== [%s] DATA START "
2366 // Start of sector hexdump
2367 int nc
= name2command(cmdname
);
2368 if (!(state
== (nc
== WRITE_LOG
? 1 : 2) && (int)parsed_command_table
[i
].command
== nc
)) {
2369 errmsg
= "Unexpected DATA START"; break;
2371 line
= nextline(line
, lineno
);
2372 char * data
= (char *)malloc(512);
2374 for (j
= 0; j
< 32; j
++) {
2376 unsigned u1
, u2
; int n1
= -1;
2377 if (!(sscanf(line
, "%3u-%3u: "
2378 "%2x %2x %2x %2x %2x %2x %2x %2x "
2379 "%2x %2x %2x %2x %2x %2x %2x %2x%n",
2381 b
+ 0, b
+ 1, b
+ 2, b
+ 3, b
+ 4, b
+ 5, b
+ 6, b
+ 7,
2382 b
+ 8, b
+ 9, b
+10, b
+11, b
+12, b
+13, b
+14, b
+15, &n1
) == 18
2383 && n1
>= 56 && u1
== j
*16 && u2
== j
*16+15))
2385 for (unsigned k
= 0; k
< 16; k
++)
2386 data
[j
*16+k
] = b
[k
];
2387 line
= nextline(line
, lineno
);
2391 errmsg
= "Incomplete sector hex dump"; break;
2393 parsed_command_table
[i
].data
= data
;
2394 if (nc
!= WRITE_LOG
)
2399 if (!(state
== 0 || state
== 2))
2400 errmsg
= "Missing REPORT-IOCTL result";
2402 if (!errmsg
&& i
< 0)
2403 errmsg
= "No information found";
2405 num_parsed_commands
= i
+1;
2406 next_replay_command
= 0;
2407 replay_out_of_sync
= false;
2410 pout("%s(%d): Syntax error: %s\n", pathname
, lineno
, errmsg
);
2418 // Report warnings and free command table
2419 void parsedev_close(int /*fd*/)
2421 if (replay_out_of_sync
)
2422 pout("REPLAY-IOCTL: Warning: commands replayed out of sync\n");
2423 else if (next_replay_command
!= 0)
2424 pout("REPLAY-IOCTL: Warning: %d command(s) not replayed\n", num_parsed_commands
-next_replay_command
);
2426 for (int i
= 0; i
< num_parsed_commands
; i
++) {
2427 if (parsed_command_table
[i
].data
) {
2428 free(parsed_command_table
[i
].data
); parsed_command_table
[i
].data
= 0;
2431 num_parsed_commands
= 0;
2434 // Simulate ATA command from command table
2435 static int parsedev_command_interface(int /*fd*/, smart_command_set command
, int select
, char * data
)
2437 // Find command, try round-robin of out of sync
2438 int i
= next_replay_command
;
2439 for (int j
= 0; ; j
++) {
2440 if (j
>= num_parsed_commands
) {
2441 pout("REPLAY-IOCTL: Warning: Command not found\n");
2445 if (parsed_command_table
[i
].command
== command
&& parsed_command_table
[i
].select
== select
)
2447 if (!replay_out_of_sync
) {
2448 replay_out_of_sync
= true;
2449 pout("REPLAY-IOCTL: Warning: Command #%d is out of sync\n", i
+1);
2451 if (++i
>= num_parsed_commands
)
2454 next_replay_command
= i
;
2455 if (++next_replay_command
>= num_parsed_commands
)
2456 next_replay_command
= 0;
2458 // Return command data
2463 case READ_THRESHOLDS
:
2465 if (parsed_command_table
[i
].data
)
2466 memcpy(data
, parsed_command_table
[i
].data
, 512);
2469 if (!(parsed_command_table
[i
].data
&& !memcmp(data
, parsed_command_table
[i
].data
, 512)))
2470 pout("REPLAY-IOCTL: Warning: WRITE LOG data does not match\n");
2472 case CHECK_POWER_MODE
:
2473 data
[0] = (char)0xff;
2478 if (parsed_command_table
[i
].errval
)
2479 errno
= parsed_command_table
[i
].errval
;
2480 return parsed_command_table
[i
].retval
;