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.189 2008/01/07 20:07:55 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 32 of T13/1699-D Revision 4c)
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 0x0039: desc
= "ATA-8-ACS revision 4c"; break;
807 case 0x0042: desc
= "ATA-8-ACS revision 3f"; break;
808 case 0x0052: desc
= "ATA-8-ACS revision 3b"; break;
809 case 0x0107: desc
= "ATA-8-ACS revision 2d"; break;
810 default: desc
= 0; break;
817 // HDPARM has a very complicated algorithm from here on. Since SMART only
818 // exists on ATA-3 and later standards, let's punt on this. If you don't
819 // like it, please fix it. The code's in CVS.
821 if (major
& (0x1<<i
))
831 // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
832 int ataSmartSupport(struct ata_identify_device
*drive
){
833 unsigned short word82
=drive
->command_set_1
;
834 unsigned short word83
=drive
->command_set_2
;
836 // check if words 82/83 contain valid info
837 if ((word83
>>14) == 0x01)
838 // return value of SMART support bit
839 return word82
& 0x0001;
841 // since we can're rely on word 82, we don't know if SMART supported
845 // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
846 int ataIsSmartEnabled(struct ata_identify_device
*drive
){
847 unsigned short word85
=drive
->cfs_enable_1
;
848 unsigned short word87
=drive
->csf_default
;
850 // check if words 85/86/87 contain valid info
851 if ((word87
>>14) == 0x01)
852 // return value of SMART enabled bit
853 return word85
& 0x0001;
855 // Since we can't rely word85, we don't know if SMART is enabled.
860 // Reads SMART attributes into *data
861 int ataReadSmartValues(int device
, struct ata_smart_values
*data
){
863 if (smartcommandhandler(device
, READ_VALUES
, 0, (char *)data
)){
864 syserror("Error SMART Values Read failed");
869 if (checksum((unsigned char *)data
))
870 checksumwarning("SMART Attribute Data Structure");
872 // swap endian order if needed
875 swap2((char *)&(data
->revnumber
));
876 swap2((char *)&(data
->total_time_to_complete_off_line
));
877 swap2((char *)&(data
->smart_capability
));
878 for (i
=0; i
<NUMBER_ATA_SMART_ATTRIBUTES
; i
++){
879 struct ata_smart_attribute
*x
=data
->vendor_attributes
+i
;
880 swap2((char *)&(x
->flags
));
888 // This corrects some quantities that are byte reversed in the SMART
890 void fixsamsungselftestlog(struct ata_smart_selftestlog
*data
){
893 // bytes 508/509 (numbered from 0) swapped (swap of self-test index
894 // with one byte of reserved.
895 swap2((char *)&(data
->mostrecenttest
));
897 // LBA low register (here called 'selftestnumber", containing
898 // information about the TYPE of the self-test) is byte swapped with
899 // Self-test execution status byte. These are bytes N, N+1 in the
902 swap2((char *)&(data
->selftest_struct
[i
].selftestnumber
));
907 // Reads the Self Test Log (log #6)
908 int ataReadSelfTestLog (int device
, struct ata_smart_selftestlog
*data
){
910 // get data from device
911 if (smartcommandhandler(device
, READ_LOG
, 0x06, (char *)data
)){
912 syserror("Error SMART Error Self-Test Log Read failed");
916 // compute its checksum, and issue a warning if needed
917 if (checksum((unsigned char *)data
))
918 checksumwarning("SMART Self-Test Log Structure");
920 // fix firmware bugs in self-test log
921 if (con
->fixfirmwarebug
== FIX_SAMSUNG
)
922 fixsamsungselftestlog(data
);
924 // swap endian order if needed
927 swap2((char*)&(data
->revnumber
));
928 for (i
=0; i
<21; i
++){
929 struct ata_smart_selftestlog_struct
*x
=data
->selftest_struct
+i
;
930 swap2((char *)&(x
->timestamp
));
931 swap4((char *)&(x
->lbafirstfailure
));
939 // Reads the Log Directory (log #0). Note: NO CHECKSUM!!
940 int ataReadLogDirectory (int device
, struct ata_smart_log_directory
*data
){
942 // get data from device
943 if (smartcommandhandler(device
, READ_LOG
, 0x00, (char *)data
)){
947 // swap endian order if needed
949 swap2((char *)&(data
->logversion
));
956 // Reads the selective self-test log (log #9)
957 int ataReadSelectiveSelfTestLog(int device
, struct ata_selective_self_test_log
*data
){
959 // get data from device
960 if (smartcommandhandler(device
, READ_LOG
, 0x09, (char *)data
)){
961 syserror("Error SMART Read Selective Self-Test Log failed");
965 // compute its checksum, and issue a warning if needed
966 if (checksum((unsigned char *)data
))
967 checksumwarning("SMART Selective Self-Test Log Structure");
969 // swap endian order if needed
972 swap2((char *)&(data
->logversion
));
974 swap8((char *)&(data
->span
[i
].start
));
975 swap8((char *)&(data
->span
[i
].end
));
977 swap8((char *)&(data
->currentlba
));
978 swap2((char *)&(data
->currentspan
));
979 swap2((char *)&(data
->flags
));
980 swap2((char *)&(data
->pendingtime
));
983 if (data
->logversion
!= 1)
984 pout("SMART Selective Self-Test Log Data Structure Revision Number (%d) should be 1\n", data
->logversion
);
989 // Writes the selective self-test log (log #9)
990 int ataWriteSelectiveSelfTestLog(int device
, struct ata_smart_values
*sv
, uint64_t num_sectors
){
992 // Disk size must be known
994 pout("Disk size is unknown, unable to check selective self-test spans\n");
999 struct ata_selective_self_test_log sstlog
, *data
=&sstlog
;
1000 unsigned char *ptr
=(unsigned char *)data
;
1001 if (ataReadSelectiveSelfTestLog(device
, data
)) {
1002 pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n");
1006 // Fix logversion if needed
1007 if (data
->logversion
!=1) {
1008 if (!con
->permissive
) {
1009 pout("Error SMART Selective Self-Test Log Data Structure Revision not recognized\n"
1010 "Revision number should be 1 but is %d. To be safe, aborting WRITE LOG.\n"
1011 "To fix revision number, add one '-T permissive' option.\n", data
->logversion
);
1015 pout("SMART Selective Self-Test Log Data Structure Revision should be 1 but is %d\n"
1016 "'-T permissive' specified, now trying to fix it by WRITE LOG.\n", data
->logversion
);
1017 data
->logversion
= 1;
1020 // Host is NOT allowed to write selective self-test log if a selective
1021 // self-test is in progress.
1022 if (0<data
->currentspan
&& data
->currentspan
<6 && ((sv
->self_test_exec_status
)>>4)==15) {
1023 pout("Error SMART Selective or other Self-Test in progress.\n");
1027 // Set start/end values based on old spans for special -t select,... options
1029 for (i
=0; i
<con
->smartselectivenumspans
; i
++) {
1030 char mode
= con
->smartselectivemode
[i
];
1031 uint64_t start
= con
->smartselectivespan
[i
][0];
1032 uint64_t end
= con
->smartselectivespan
[i
][1];
1033 if (mode
== SEL_CONT
) {// redo or next dependig on last test status
1034 switch (sv
->self_test_exec_status
>> 4) {
1035 case 1: case 2: // Aborted/Interrupted by host
1036 pout("Continue Selective Self-Test: Redo last span\n");
1039 default: // All others
1040 pout("Continue Selective Self-Test: Start next span\n");
1046 case SEL_RANGE
: // -t select,START-END
1048 case SEL_REDO
: // -t select,redo... => Redo current
1049 start
= data
->span
[i
].start
;
1050 if (end
> 0) { // -t select,redo+SIZE
1051 end
--; end
+= start
; // [oldstart, oldstart+SIZE)
1053 else // -t select,redo
1054 end
= data
->span
[i
].end
; // [oldstart, oldend]
1056 case SEL_NEXT
: // -t select,next... => Do next
1057 if (data
->span
[i
].end
== 0) {
1058 start
= end
= 0; break; // skip empty spans
1060 start
= data
->span
[i
].end
+ 1;
1061 if (start
>= num_sectors
)
1062 start
= 0; // wrap around
1063 if (end
> 0) { // -t select,next+SIZE
1064 end
--; end
+= start
; // (oldend, oldend+SIZE]
1066 else { // -t select,next
1067 uint64_t oldsize
= data
->span
[i
].end
- data
->span
[i
].start
+ 1;
1068 end
= start
+ oldsize
- 1; // (oldend, oldend+oldsize]
1069 if (end
>= num_sectors
) {
1070 // Adjust size to allow round-robin testing without future size decrease
1071 uint64_t spans
= (num_sectors
+ oldsize
-1) / oldsize
;
1072 uint64_t newsize
= (num_sectors
+ spans
-1) / spans
;
1073 uint64_t newstart
= num_sectors
- newsize
, newend
= num_sectors
- 1;
1074 pout("Span %d changed from %"PRIu64
"-%"PRIu64
" (%"PRIu64
" sectors)\n"
1075 " to %"PRIu64
"-%"PRIu64
" (%"PRIu64
" sectors) (%"PRIu64
" spans)\n",
1076 i
, start
, end
, oldsize
, newstart
, newend
, newsize
, spans
);
1077 start
= newstart
; end
= newend
;
1082 pout("ataWriteSelectiveSelfTestLog: Invalid mode %d\n", mode
);
1086 if (start
< num_sectors
&& num_sectors
<= end
) {
1087 if (end
!= ~(uint64_t)0) // -t select,N-max
1088 pout("Size of self-test span %d decreased according to disk size\n", i
);
1089 end
= num_sectors
- 1;
1091 if (!(start
<= end
&& end
< num_sectors
)) {
1092 pout("Invalid selective self-test span %d: %"PRIu64
"-%"PRIu64
" (%"PRIu64
" sectors)\n",
1093 i
, start
, end
, num_sectors
);
1096 // Write back to allow ataSmartTest() to print the actual values
1097 con
->smartselectivespan
[i
][0] = start
;
1098 con
->smartselectivespan
[i
][1] = end
;
1103 memset(data
->span
+i
, 0, sizeof(struct test_span
));
1105 // Set spans for testing
1106 for (i
=0; i
<con
->smartselectivenumspans
; i
++){
1107 data
->span
[i
].start
= con
->smartselectivespan
[i
][0];
1108 data
->span
[i
].end
= con
->smartselectivespan
[i
][1];
1111 // host must initialize to zero before initiating selective self-test
1113 data
->currentspan
=0;
1115 // Perform off-line scan after selective test?
1116 if (1 == con
->scanafterselect
)
1118 data
->flags
&= ~SELECTIVE_FLAG_DOSCAN
;
1119 else if (2 == con
->scanafterselect
)
1121 data
->flags
|= SELECTIVE_FLAG_DOSCAN
;
1123 // Must clear active and pending flags before writing
1124 data
->flags
&= ~(SELECTIVE_FLAG_ACTIVE
);
1125 data
->flags
&= ~(SELECTIVE_FLAG_PENDING
);
1127 // modify pending time?
1128 if (con
->pendingtime
)
1129 data
->pendingtime
=(unsigned short)(con
->pendingtime
-1);
1131 // Set checksum to zero, then compute checksum
1133 unsigned char cksum
=0;
1134 for (i
=0; i
<512; i
++)
1138 data
->checksum
=cksum
;
1140 // swap endian order if needed
1142 swap2((char *)&(data
->logversion
));
1143 for (int i
=0;i
<5;i
++){
1144 swap8((char *)&(data
->span
[i
].start
));
1145 swap8((char *)&(data
->span
[i
].end
));
1147 swap8((char *)&(data
->currentlba
));
1148 swap2((char *)&(data
->currentspan
));
1149 swap2((char *)&(data
->flags
));
1150 swap2((char *)&(data
->pendingtime
));
1153 // write new selective self-test log
1154 if (smartcommandhandler(device
, WRITE_LOG
, 0x09, (char *)data
)){
1155 syserror("Error Write Selective Self-Test Log failed");
1162 // This corrects some quantities that are byte reversed in the SMART
1164 void fixsamsungerrorlog(struct ata_smart_errorlog
*data
){
1167 // FIXED IN SAMSUNG -25 FIRMWARE???
1168 // Device error count in bytes 452-3
1169 swap2((char *)&(data
->ata_error_count
));
1171 // FIXED IN SAMSUNG -22a FIRMWARE
1172 // step through 5 error log data structures
1173 for (i
=0; i
<5; i
++){
1174 // step through 5 command data structures
1176 // Command data structure 4-byte millisec timestamp. These are
1177 // bytes (N+8, N+9, N+10, N+11).
1178 swap4((char *)&(data
->errorlog_struct
[i
].commands
[j
].timestamp
));
1179 // Error data structure two-byte hour life timestamp. These are
1180 // bytes (N+28, N+29).
1181 swap2((char *)&(data
->errorlog_struct
[i
].error_struct
.timestamp
));
1186 // NEEDED ONLY FOR SAMSUNG -22 (some) -23 AND -24?? FIRMWARE
1187 void fixsamsungerrorlog2(struct ata_smart_errorlog
*data
){
1188 // Device error count in bytes 452-3
1189 swap2((char *)&(data
->ata_error_count
));
1193 // Reads the Summary SMART Error Log (log #1). The Comprehensive SMART
1194 // Error Log is #2, and the Extended Comprehensive SMART Error log is
1196 int ataReadErrorLog (int device
, struct ata_smart_errorlog
*data
){
1198 // get data from device
1199 if (smartcommandhandler(device
, READ_LOG
, 0x01, (char *)data
)){
1200 syserror("Error SMART Error Log Read failed");
1204 // compute its checksum, and issue a warning if needed
1205 if (checksum((unsigned char *)data
))
1206 checksumwarning("SMART ATA Error Log Structure");
1208 // Some disks have the byte order reversed in some SMART Summary
1209 // Error log entries
1210 if (con
->fixfirmwarebug
== FIX_SAMSUNG
)
1211 fixsamsungerrorlog(data
);
1212 else if (con
->fixfirmwarebug
== FIX_SAMSUNG2
)
1213 fixsamsungerrorlog2(data
);
1215 // swap endian order if needed
1219 // Device error count in bytes 452-3
1220 swap2((char *)&(data
->ata_error_count
));
1222 // step through 5 error log data structures
1223 for (i
=0; i
<5; i
++){
1224 // step through 5 command data structures
1226 // Command data structure 4-byte millisec timestamp
1227 swap4((char *)&(data
->errorlog_struct
[i
].commands
[j
].timestamp
));
1228 // Error data structure life timestamp
1229 swap2((char *)&(data
->errorlog_struct
[i
].error_struct
.timestamp
));
1236 int ataReadSmartThresholds (int device
, struct ata_smart_thresholds_pvt
*data
){
1238 // get data from device
1239 if (smartcommandhandler(device
, READ_THRESHOLDS
, 0, (char *)data
)){
1240 syserror("Error SMART Thresholds Read failed");
1244 // compute its checksum, and issue a warning if needed
1245 if (checksum((unsigned char *)data
))
1246 checksumwarning("SMART Attribute Thresholds Structure");
1248 // swap endian order if needed
1250 swap2((char *)&(data
->revnumber
));
1255 int ataEnableSmart (int device
){
1256 if (smartcommandhandler(device
, ENABLE
, 0, NULL
)){
1257 syserror("Error SMART Enable failed");
1263 int ataDisableSmart (int device
){
1265 if (smartcommandhandler(device
, DISABLE
, 0, NULL
)){
1266 syserror("Error SMART Disable failed");
1272 int ataEnableAutoSave(int device
){
1273 if (smartcommandhandler(device
, AUTOSAVE
, 241, NULL
)){
1274 syserror("Error SMART Enable Auto-save failed");
1280 int ataDisableAutoSave(int device
){
1282 if (smartcommandhandler(device
, AUTOSAVE
, 0, NULL
)){
1283 syserror("Error SMART Disable Auto-save failed");
1289 // In *ALL* ATA standards the Enable/Disable AutoOffline command is
1290 // marked "OBSOLETE". It is defined in SFF-8035i Revision 2, and most
1291 // vendors still support it for backwards compatibility. IBM documents
1292 // it for some drives.
1293 int ataEnableAutoOffline (int device
){
1295 /* timer hard coded to 4 hours */
1296 if (smartcommandhandler(device
, AUTO_OFFLINE
, 248, NULL
)){
1297 syserror("Error SMART Enable Automatic Offline failed");
1303 // Another Obsolete Command. See comments directly above, associated
1304 // with the corresponding Enable command.
1305 int ataDisableAutoOffline (int device
){
1307 if (smartcommandhandler(device
, AUTO_OFFLINE
, 0, NULL
)){
1308 syserror("Error SMART Disable Automatic Offline failed");
1314 // If SMART is enabled, supported, and working, then this call is
1315 // guaranteed to return 1, else zero. Note that it should return 1
1316 // regardless of whether the disk's SMART status is 'healthy' or
1318 int ataDoesSmartWork(int device
){
1319 int retval
=smartcommandhandler(device
, STATUS
, 0, NULL
);
1327 // This function uses a different interface (DRIVE_TASK) than the
1328 // other commands in this file.
1329 int ataSmartStatus2(int device
){
1330 return smartcommandhandler(device
, STATUS_CHECK
, 0, NULL
);
1333 // This is the way to execute ALL tests: offline, short self-test,
1334 // extended self test, with and without captive mode, etc.
1335 int ataSmartTest(int device
, int testtype
, struct ata_smart_values
*sv
, uint64_t num_sectors
)
1337 char cmdmsg
[128],*type
,*captive
;
1338 int errornum
, cap
, retval
, select
=0;
1340 // Boolean, if set, says test is captive
1341 cap
=testtype
& CAPTIVE_MASK
;
1343 // Set up strings that describe the type of test
1349 if (testtype
==OFFLINE_FULL_SCAN
)
1351 else if (testtype
==SHORT_SELF_TEST
|| testtype
==SHORT_CAPTIVE_SELF_TEST
)
1352 type
="Short self-test";
1353 else if (testtype
==EXTEND_SELF_TEST
|| testtype
==EXTEND_CAPTIVE_SELF_TEST
)
1354 type
="Extended self-test";
1355 else if (testtype
==CONVEYANCE_SELF_TEST
|| testtype
==CONVEYANCE_CAPTIVE_SELF_TEST
)
1356 type
="Conveyance self-test";
1357 else if ((select
=(testtype
==SELECTIVE_SELF_TEST
|| testtype
==SELECTIVE_CAPTIVE_SELF_TEST
)))
1358 type
="Selective self-test";
1360 type
="[Unrecognized] self-test";
1362 // If doing a selective self-test, first use WRITE_LOG to write the
1363 // selective self-test log.
1364 if (select
&& (retval
=ataWriteSelectiveSelfTestLog(device
, sv
, num_sectors
))) {
1366 pout("Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");
1370 // Print ouf message that we are sending the command to test
1371 if (testtype
==ABORT_SELF_TEST
)
1372 sprintf(cmdmsg
,"Abort SMART off-line mode self-test routine");
1374 sprintf(cmdmsg
,"Execute SMART %s routine immediately in %s mode",type
,captive
);
1375 pout("Sending command: \"%s\".\n",cmdmsg
);
1379 pout("SPAN STARTING_LBA ENDING_LBA\n");
1380 for (i
= 0; i
< con
->smartselectivenumspans
; i
++)
1381 pout(" %d %20"PRId64
" %20"PRId64
"\n", i
,
1382 con
->smartselectivespan
[i
][0],
1383 con
->smartselectivespan
[i
][1]);
1386 // Now send the command to test
1387 errornum
=smartcommandhandler(device
, IMMEDIATE_OFFLINE
, testtype
, NULL
);
1389 if (errornum
&& !(cap
&& errno
==EIO
)){
1391 sprintf(errormsg
,"Command \"%s\" failed",cmdmsg
);
1397 // Since the command succeeded, tell user
1398 if (testtype
==ABORT_SELF_TEST
)
1399 pout("Self-testing aborted!\n");
1401 pout("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg
);
1405 /* Test Time Functions */
1406 int TestTime(struct ata_smart_values
*data
,int testtype
){
1408 case OFFLINE_FULL_SCAN
:
1409 return (int) data
->total_time_to_complete_off_line
;
1410 case SHORT_SELF_TEST
:
1411 case SHORT_CAPTIVE_SELF_TEST
:
1412 return (int) data
->short_test_completion_time
;
1413 case EXTEND_SELF_TEST
:
1414 case EXTEND_CAPTIVE_SELF_TEST
:
1415 return (int) data
->extend_test_completion_time
;
1416 case CONVEYANCE_SELF_TEST
:
1417 case CONVEYANCE_CAPTIVE_SELF_TEST
:
1418 return (int) data
->conveyance_test_completion_time
;
1424 // This function tells you both about the ATA error log and the
1425 // self-test error log capability (introduced in ATA-5). The bit is
1426 // poorly documented in the ATA/ATAPI standard. Starting with ATA-6,
1427 // SMART error logging is also indicated in bit 0 of DEVICE IDENTIFY
1428 // word 84 and 87. Top two bits must match the pattern 01. BEFORE
1429 // ATA-6 these top two bits still had to match the pattern 01, but the
1430 // remaining bits were reserved (==0).
1431 int isSmartErrorLogCapable (struct ata_smart_values
*data
, struct ata_identify_device
*identity
){
1433 unsigned short word84
=identity
->command_set_extension
;
1434 unsigned short word87
=identity
->csf_default
;
1435 int isata6
=identity
->major_rev_num
& (0x01<<6);
1436 int isata7
=identity
->major_rev_num
& (0x01<<7);
1438 if ((isata6
|| isata7
) && (word84
>>14) == 0x01 && (word84
& 0x01))
1441 if ((isata6
|| isata7
) && (word87
>>14) == 0x01 && (word87
& 0x01))
1444 // otherwise we'll use the poorly documented capability bit
1445 return data
->errorlog_capability
& 0x01;
1448 // See previous function. If the error log exists then the self-test
1449 // log should (must?) also exist.
1450 int isSmartTestLogCapable (struct ata_smart_values
*data
, struct ata_identify_device
*identity
){
1452 unsigned short word84
=identity
->command_set_extension
;
1453 unsigned short word87
=identity
->csf_default
;
1454 int isata6
=identity
->major_rev_num
& (0x01<<6);
1455 int isata7
=identity
->major_rev_num
& (0x01<<7);
1457 if ((isata6
|| isata7
) && (word84
>>14) == 0x01 && (word84
& 0x02))
1460 if ((isata6
|| isata7
) && (word87
>>14) == 0x01 && (word87
& 0x02))
1464 // otherwise we'll use the poorly documented capability bit
1465 return data
->errorlog_capability
& 0x01;
1469 int isGeneralPurposeLoggingCapable(struct ata_identify_device
*identity
){
1470 unsigned short word84
=identity
->command_set_extension
;
1471 unsigned short word87
=identity
->csf_default
;
1473 // If bit 14 of word 84 is set to one and bit 15 of word 84 is
1474 // cleared to zero, the contents of word 84 contains valid support
1475 // information. If not, support information is not valid in this
1477 if ((word84
>>14) == 0x01)
1478 // If bit 5 of word 84 is set to one, the device supports the
1479 // General Purpose Logging feature set.
1480 return (word84
& (0x01 << 5));
1482 // If bit 14 of word 87 is set to one and bit 15 of word 87 is
1483 // cleared to zero, the contents of words (87:85) contain valid
1484 // information. If not, information is not valid in these words.
1485 if ((word87
>>14) == 0x01)
1486 // If bit 5 of word 87 is set to one, the device supports
1487 // the General Purpose Logging feature set.
1488 return (word87
& (0x01 << 5));
1495 // SMART self-test capability is also indicated in bit 1 of DEVICE
1496 // IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
1497 // However this was only introduced in ATA-6 (but self-test log was in
1499 int isSupportExecuteOfflineImmediate(struct ata_smart_values
*data
){
1500 return data
->offline_data_collection_capability
& 0x01;
1502 // Note in the ATA-5 standard, the following bit is listed as "Vendor
1503 // Specific". So it may not be reliable. The only use of this that I
1504 // have found is in IBM drives, where it is well-documented. See for
1505 // example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
1506 // hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
1507 int isSupportAutomaticTimer(struct ata_smart_values
*data
){
1508 return data
->offline_data_collection_capability
& 0x02;
1510 int isSupportOfflineAbort(struct ata_smart_values
*data
){
1511 return data
->offline_data_collection_capability
& 0x04;
1513 int isSupportOfflineSurfaceScan(struct ata_smart_values
*data
){
1514 return data
->offline_data_collection_capability
& 0x08;
1516 int isSupportSelfTest (struct ata_smart_values
*data
){
1517 return data
->offline_data_collection_capability
& 0x10;
1519 int isSupportConveyanceSelfTest(struct ata_smart_values
*data
){
1520 return data
->offline_data_collection_capability
& 0x20;
1522 int isSupportSelectiveSelfTest(struct ata_smart_values
*data
){
1523 return data
->offline_data_collection_capability
& 0x40;
1528 // Loop over all valid attributes. If they are prefailure attributes
1529 // and are at or below the threshold value, then return the ID of the
1530 // first failing attribute found. Return 0 if all prefailure
1531 // attributes are in bounds. The spec says "Bit 0
1532 // -Pre-failure/advisory - If the value of this bit equals zero, an
1533 // attribute value less than or equal to its corresponding attribute
1534 // threshold indicates an advisory condition where the usage or age of
1535 // the device has exceeded its intended design life period. If the
1536 // value of this bit equals one, an atribute value less than or equal
1537 // to its corresponding attribute threshold indicates a pre-failure
1538 // condition where imminent loss of data is being predicted."
1541 // onlyfailed=0 : are or were any age or prefailure attributes <= threshold
1542 // onlyfailed=1: are any prefailure attributes <= threshold now
1543 int ataCheckSmart(struct ata_smart_values
*data
,
1544 struct ata_smart_thresholds_pvt
*thresholds
,
1548 // loop over all attributes
1549 for (i
=0; i
<NUMBER_ATA_SMART_ATTRIBUTES
; i
++){
1551 // pointers to disk's values and vendor's thresholds
1552 struct ata_smart_attribute
*disk
=data
->vendor_attributes
+i
;
1553 struct ata_smart_threshold_entry
*thre
=thresholds
->thres_entries
+i
;
1555 // consider only valid attributes
1556 if (disk
->id
&& thre
->id
){
1557 int failednow
,failedever
;
1559 failednow
=disk
->current
<= thre
->threshold
;
1560 failedever
=disk
->worst
<= thre
->threshold
;
1562 if (!onlyfailed
&& failedever
)
1565 if (onlyfailed
&& failednow
&& ATTRIBUTE_FLAGS_PREFAILURE(disk
->flags
))
1574 // This checks the n'th attribute in the attribute list, NOT the
1575 // attribute with id==n. If the attribute does not exist, or the
1576 // attribute is > threshold, then returns zero. If the attribute is
1577 // <= threshold (failing) then we the attribute number if it is a
1578 // prefail attribute. Else we return minus the attribute number if it
1579 // is a usage attribute.
1580 int ataCheckAttribute(struct ata_smart_values
*data
,
1581 struct ata_smart_thresholds_pvt
*thresholds
,
1583 struct ata_smart_attribute
*disk
;
1584 struct ata_smart_threshold_entry
*thre
;
1586 if (n
<0 || n
>=NUMBER_ATA_SMART_ATTRIBUTES
|| !data
|| !thresholds
)
1589 // pointers to disk's values and vendor's thresholds
1590 disk
=data
->vendor_attributes
+n
;
1591 thre
=thresholds
->thres_entries
+n
;
1596 // consider only valid attributes, check for failure
1597 if (!disk
->id
|| !thre
->id
|| (disk
->id
!= thre
->id
) || disk
->current
> thre
->threshold
)
1600 // We have found a failed attribute. Return positive or negative?
1601 if (ATTRIBUTE_FLAGS_PREFAILURE(disk
->flags
))
1604 return -1*(disk
->id
);
1608 // Print temperature value and Min/Max value if present
1609 static void ataPrintTemperatureValue(char *out
, const unsigned char *raw
, const unsigned *word
)
1611 out
+=sprintf(out
, "%u", word
[0]);
1612 if (!word
[1] && !word
[2])
1613 return; // No Min/Max
1615 unsigned lo
= ~0, hi
= ~0;
1617 // 00 HH 00 LL 00 TT (IBM)
1618 hi
= word
[2]; lo
= word
[1];
1620 else if (!word
[2]) {
1621 // 00 00 HH LL 00 TT (Maxtor)
1622 hi
= raw
[3]; lo
= raw
[2];
1625 unsigned t
= lo
; lo
= hi
; hi
= t
;
1627 if (lo
<= word
[0] && word
[0] <= hi
)
1628 sprintf(out
, " (Lifetime Min/Max %u/%u)", lo
, hi
);
1630 sprintf(out
, " (%u %u %u %u)", raw
[5], raw
[4], raw
[3], raw
[2]);
1634 // This routine prints the raw value of an attribute as a text string
1635 // into out. It also returns this 48-bit number as a long long. The
1636 // array defs[] contains non-zero values if particular attributes have
1637 // non-default interpretations.
1639 int64_t ataPrintSmartAttribRawValue(char *out
,
1640 struct ata_smart_attribute
*attribute
,
1641 unsigned char *defs
){
1645 unsigned char select
;
1647 // convert the six individual bytes to a long long (8 byte) integer.
1648 // This is the value that we'll eventually return.
1650 for (j
=0; j
<6; j
++) {
1651 // This looks a bit roundabout, but is necessary. Don't
1652 // succumb to the temptation to use raw[j]<<(8*j) since under
1653 // the normal rules this will be promoted to the native type.
1654 // On a 32 bit machine this might then overflow.
1656 temp
= attribute
->raw
[j
];
1661 // convert quantities to three two-byte words
1662 for (j
=0; j
<3; j
++){
1663 word
[j
] = attribute
->raw
[2*j
+1];
1665 word
[j
] |= attribute
->raw
[2*j
];
1668 // if no data array, Attributes have default interpretations
1670 select
=defs
[attribute
->id
];
1674 // Print six one-byte quantities.
1677 out
+=sprintf(out
, "%d ", attribute
->raw
[5-j
]);
1678 out
+=sprintf(out
, "%d ", attribute
->raw
[0]);
1682 // Print three two-byte quantities
1684 out
+=sprintf(out
, "%d %d %d", word
[2], word
[1], word
[0]);
1688 // Print one six-byte quantity
1690 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1694 // This switch statement is where we handle Raw attributes
1695 // that are stored in an unusual vendor-specific format,
1696 switch (attribute
->id
){
1699 out
+=sprintf(out
, "%d", word
[0]);
1700 // if second nonzero then it stores the average spin-up time
1702 out
+=sprintf(out
, " (Average %d)", word
[1]);
1708 int64_t tmp1
=rawvalue
/60;
1709 int64_t tmp2
=rawvalue
%60;
1710 out
+=sprintf(out
, "%"PRIu64
"h+%02"PRIu64
"m", tmp1
, tmp2
);
1712 else if (select
==3){
1714 int64_t hours
=rawvalue
/3600;
1715 int64_t minutes
=(rawvalue
-3600*hours
)/60;
1716 int64_t seconds
=rawvalue
%60;
1717 out
+=sprintf(out
, "%"PRIu64
"h+%02"PRIu64
"m+%02"PRIu64
"s", hours
, minutes
, seconds
);
1719 else if (select
==4){
1720 // 30-second counter
1721 int64_t tmp1
=rawvalue
/120;
1722 int64_t tmp2
=(rawvalue
-120*tmp1
)/2;
1723 out
+=sprintf(out
, "%"PRIu64
"h+%02"PRIu64
"m", tmp1
, tmp2
);
1727 out
+=sprintf(out
, "%"PRIu64
, rawvalue
); //stored in hours
1731 ataPrintTemperatureValue(out
, attribute
->raw
, word
);
1733 // Load unload cycles
1737 long load
=attribute
->raw
[0] + (attribute
->raw
[1]<<8) + (attribute
->raw
[2]<<16);
1738 long unload
=attribute
->raw
[3] + (attribute
->raw
[4]<<8) + (attribute
->raw
[5]<<16);
1739 out
+=sprintf(out
, "%lu/%lu", load
, unload
);
1743 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1748 // ten times temperature in Celsius
1750 int tenths
=word
[0]%10;
1751 out
+=sprintf(out
, "%d.%d", deg
, tenths
);
1754 // unknown attribute
1755 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1757 ataPrintTemperatureValue(out
, attribute
->raw
, word
);
1760 out
+=sprintf(out
, "%"PRIu64
, rawvalue
);
1763 // Return the full value
1768 // Note some attribute names appear redundant because different
1769 // manufacturers use different attribute IDs for an attribute with the
1770 // same name. The variable val should contain a non-zero value if a particular
1771 // attributes has a non-default interpretation.
1772 void ataPrintSmartAttribName(char *out
, unsigned char id
, unsigned char *definitions
){
1776 // If no data array, use default interpretations
1778 val
=definitions
[id
];
1785 name
="Raw_Read_Error_Rate";
1788 name
="Throughput_Performance";
1791 name
="Spin_Up_Time";
1794 name
="Start_Stop_Count";
1797 name
="Reallocated_Sector_Ct";
1800 name
="Read_Channel_Margin";
1803 name
="Seek_Error_Rate";
1806 name
="Seek_Time_Performance";
1811 name
="Power_On_Minutes";
1814 name
="Temperature_Celsius";
1817 name
="Power_On_Seconds";
1820 name
="Power_On_Half_Minutes";
1823 name
="Power_On_Hours";
1828 name
="Spin_Retry_Count";
1831 name
="Calibration_Retry_Count";
1834 name
="Power_Cycle_Count";
1837 name
="Read_Soft_Error_Rate";
1840 name
="Reported_Uncorrect";
1843 name
="High_Fly_Writes";
1846 // Western Digital uses this for temperature.
1847 // It's identical to Attribute 194 except that it
1848 // has a failure threshold set to correspond to the
1849 // max allowed operating temperature of the drive, which
1850 // is typically 55C. So if this attribute has failed
1851 // in the past, it indicates that the drive temp exceeded
1852 // 55C sometime in the past.
1853 name
="Airflow_Temperature_Cel";
1856 name
="G-Sense_Error_Rate";
1862 name
="Emergency_Retract_Cycle_Ct";
1865 name
="Power-Off_Retract_Count";
1870 name
="Load_Cycle_Count";
1875 // Samsung SV1204H with RK100-13 firmware
1876 name
="Temperature_Celsius_x10";
1879 // for disks with no temperature Attribute
1880 name
="Unknown_Attribute";
1883 name
="Temperature_Celsius";
1888 // Fujitsu name="ECC_On_The_Fly_Count";
1889 name
="Hardware_ECC_Recovered";
1892 name
="Reallocated_Event_Count";
1895 name
="Current_Pending_Sector";
1901 name
="Off-line_Scan_UNC_Sector_Ct";
1904 name
="Offline_Uncorrectable";
1909 name
="UDMA_CRC_Error_Count";
1914 // Fujitsu MHS2020AT
1915 name
="Write_Error_Count";
1919 name
="Multi_Zone_Error_Rate";
1927 name
="Detected_TA_Count";
1930 name
="Soft_Read_Error_Rate";
1936 name
="TA_Increase_Count";
1937 // Maxtor: Data Address Mark Errors
1941 name
="Run_Out_Cancel";
1942 // Maxtor: ECC Errors
1946 name
="Shock_Count_Write_Opern";
1947 // Maxtor: Soft ECC Correction
1951 name
="Shock_Rate_Write_Opern";
1952 // Maxtor: Thermal Aspirates
1956 name
="Flying_Height";
1960 name
="Spin_High_Current";
1968 name
="Offline_Seek_Performnce";
1973 name
="Temperature_Celsius";
1981 name
="G-Sense_Error_Rate";
1984 name
="Loaded_Hours";
1987 name
="Load_Retry_Count";
1990 name
="Load_Friction";
1993 name
="Load_Cycle_Count";
1996 name
="Load-in_Time";
1999 name
="Torq-amp_Count";
2002 name
="Power-off_Retract_Count";
2005 // seen in IBM DTPA-353750
2006 name
="Head_Amplitude";
2009 name
="Temperature_Celsius";
2012 name
="Head_Flying_Hours";
2015 name
="Read_Error_Retry_Rate";
2018 name
="Unknown_Attribute";
2021 sprintf(out
,"%3hu %s",(short int)id
,name
);
2025 // Returns raw value of Attribute with ID==id. This will be in the
2026 // range 0 to 2^48-1 inclusive. If the Attribute does not exist,
2028 int64_t ATAReturnAttributeRawValue(unsigned char id
, struct ata_smart_values
*data
) {
2031 // valid Attribute IDs are in the range 1 to 255 inclusive.
2035 // loop over Attributes to see if there is one with the desired ID
2036 for (i
=0; i
<NUMBER_ATA_SMART_ATTRIBUTES
; i
++) {
2037 struct ata_smart_attribute
*ap
= data
->vendor_attributes
+ i
;
2039 // we've found the desired Attribute. Return its value
2043 for (j
=0; j
<6; j
++) {
2044 // This looks a bit roundabout, but is necessary. Don't
2045 // succumb to the temptation to use raw[j]<<(8*j) since under
2046 // the normal rules this will be promoted to the native type.
2047 // On a 32 bit machine this might then overflow.
2054 } // found desired Attribute
2055 } // loop over Attributes
2057 // fall-through: no such Attribute found
2061 // Return Temperature Attribute raw value selected according to possible
2062 // non-default interpretations. If the Attribute does not exist, return 0
2063 unsigned char ATAReturnTemperatureValue(/*const*/ struct ata_smart_values
*data
, const unsigned char *defs
){
2065 for (i
= 0; i
< 3; i
++) {
2066 static const unsigned char ids
[3] = {194, 9, 220};
2067 unsigned char id
= ids
[i
];
2068 unsigned char select
= (defs
? defs
[id
] : 0);
2069 int64_t raw
; unsigned temp
;
2070 if (!( (id
== 194 && select
<= 1) // ! -v 194,unknown
2071 || (id
== 9 && select
== 2) // -v 9,temp
2072 || (id
== 220 && select
== 1))) // -v 220,temp
2074 raw
= ATAReturnAttributeRawValue(id
, data
);
2077 temp
= (unsigned short)raw
; // ignore possible min/max values in high words
2078 if (id
== 194 && select
== 1) // -v 194,10xCelsius
2079 temp
= (temp
+5) / 10;
2080 if (!(0 < temp
&& temp
<= 255))
2084 // No valid attribute found
2089 int ataReadSCTStatus(int device
, ata_sct_status_response
* sts
)
2091 // read SCT status via SMART log 0xe0
2092 memset(sts
, 0, sizeof(*sts
));
2093 if (smartcommandhandler(device
, READ_LOG
, 0xe0, (char *)sts
)){
2094 syserror("Error Read SCT Status failed");
2098 // swap endian order if needed
2100 swapx(&sts
->format_version
);
2101 swapx(&sts
->sct_version
);
2102 swapx(&sts
->sct_spec
);
2103 swapx(&sts
->ext_status_code
);
2104 swapx(&sts
->action_code
);
2105 swapx(&sts
->function_code
);
2106 swapx(&sts
->over_limit_count
);
2107 swapx(&sts
->under_limit_count
);
2110 // Check format version
2111 if (!(sts
->format_version
== 2 || sts
->format_version
== 3)) {
2112 pout("Error unknown SCT Status format version %u, should be 2 or 3.\n", sts
->format_version
);
2118 // Read SCT Temperature History Table and Status
2119 int ataReadSCTTempHist(int device
, ata_sct_temperature_history_table
* tmh
,
2120 ata_sct_status_response
* sts
)
2122 // Check initial status
2123 if (ataReadSCTStatus(device
, sts
))
2126 // Do nothing if other SCT command is executing
2127 if (sts
->ext_status_code
== 0xffff) {
2128 pout("Another SCT command is executing, abort Read Data Table\n"
2129 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2130 sts
->ext_status_code
, sts
->action_code
, sts
->function_code
);
2134 ata_sct_data_table_command cmd
; memset(&cmd
, 0, sizeof(cmd
));
2135 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2136 cmd
.action_code
= 5; // Data table command
2137 cmd
.function_code
= 1; // Read table
2138 cmd
.table_id
= 2; // Temperature History Table
2140 // write command via SMART log page 0xe0
2141 if (smartcommandhandler(device
, WRITE_LOG
, 0xe0, (char *)&cmd
)){
2142 syserror("Error Write SCT Data Table command failed");
2146 // read SCT data via SMART log page 0xe1
2147 memset(tmh
, 0, sizeof(*tmh
));
2148 if (smartcommandhandler(device
, READ_LOG
, 0xe1, (char *)tmh
)){
2149 syserror("Error Read SCT Data Table failed");
2153 // re-read and check SCT status
2154 if (ataReadSCTStatus(device
, sts
))
2157 if (!(sts
->ext_status_code
== 0 && sts
->action_code
== 5 && sts
->function_code
== 1)) {
2158 pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2159 sts
->ext_status_code
, sts
->action_code
, sts
->function_code
);
2163 // swap endian order if needed
2165 swapx(&tmh
->format_version
);
2166 swapx(&tmh
->sampling_period
);
2167 swapx(&tmh
->interval
);
2170 // Check format version
2171 if (tmh
->format_version
!= 2) {
2172 pout("Error unknown SCT Temperature History Format Version (%u), should be 2.\n", tmh
->format_version
);
2178 // Set SCT Temperature Logging Interval
2179 int ataSetSCTTempInterval(int device
, unsigned interval
, bool persistent
)
2181 // Check initial status
2182 ata_sct_status_response sts
;
2183 if (ataReadSCTStatus(device
, &sts
))
2186 // Do nothing if other SCT command is executing
2187 if (sts
.ext_status_code
== 0xffff) {
2188 pout("Another SCT command is executing, abort Feature Control\n"
2189 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2190 sts
.ext_status_code
, sts
.action_code
, sts
.function_code
);
2194 ata_sct_feature_control_command cmd
; memset(&cmd
, 0, sizeof(cmd
));
2195 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2196 cmd
.action_code
= 4; // Feature Control command
2197 cmd
.function_code
= 1; // Set state
2198 cmd
.feature_code
= 3; // Temperature logging interval
2199 cmd
.state
= interval
;
2200 cmd
.option_flags
= (persistent
? 0x01 : 0x00);
2202 // write command via SMART log page 0xe0
2203 if (smartcommandhandler(device
, WRITE_LOG
, 0xe0, (char *)&cmd
)){
2204 syserror("Error Write SCT Feature Control Command failed");
2208 // re-read and check SCT status
2209 if (ataReadSCTStatus(device
, &sts
))
2212 if (!(sts
.ext_status_code
== 0 && sts
.action_code
== 4 && sts
.function_code
== 1)) {
2213 pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2214 sts
.ext_status_code
, sts
.action_code
, sts
.function_code
);
2221 /////////////////////////////////////////////////////////////////////////////
2222 // Pseudo-device to parse "smartctl -r ataioctl,2 ..." output and simulate
2223 // an ATA device with same behaviour
2225 // Table of parsed commands, return value, data
2226 struct parsed_ata_command
2228 smart_command_set command
;
2234 const int max_num_parsed_commands
= 32;
2235 static parsed_ata_command parsed_command_table
[max_num_parsed_commands
];
2236 static int num_parsed_commands
;
2237 static int next_replay_command
;
2238 static bool replay_out_of_sync
;
2241 static const char * nextline(const char * s
, int & lineno
)
2243 for (s
+= strcspn(s
, "\r\n"); *s
== '\r' || *s
== '\n'; s
++) {
2244 if (*s
== '\r' && s
[1] == '\n')
2251 static int name2command(const char * s
)
2253 for (int i
= 0; i
< (int)(sizeof(commandstrings
)/sizeof(commandstrings
[0])); i
++) {
2254 if (!strcmp(s
, commandstrings
[i
]))
2260 static bool matchcpy(char * dest
, size_t size
, const char * src
, const regmatch_t
& srcmatch
)
2262 if (srcmatch
.rm_so
< 0)
2264 size_t n
= srcmatch
.rm_eo
- srcmatch
.rm_so
;
2267 memcpy(dest
, src
+ srcmatch
.rm_so
, n
);
2272 static inline int matchtoi(const char * src
, const regmatch_t
& srcmatch
, int defval
)
2274 if (srcmatch
.rm_so
< 0)
2276 return atoi(src
+ srcmatch
.rm_so
);
2280 // Parse stdin and build command table
2281 int parsedev_open(const char * pathname
)
2283 if (strcmp(pathname
, "-")) {
2284 errno
= EINVAL
; return -1;
2286 pathname
= "<stdin>";
2288 char buffer
[64*1024];
2290 while (size
< (int)sizeof(buffer
)) {
2291 int nr
= fread(buffer
, 1, sizeof(buffer
), stdin
);
2297 pout("%s: Unexpected EOF\n", pathname
);
2298 errno
= ENOENT
; return -1;
2300 if (size
>= (int)sizeof(buffer
)) {
2301 pout("%s: Buffer overflow\n", pathname
);
2302 errno
= EIO
; return -1;
2306 // Regex to match output from "-r ataioctl,2"
2307 static const char pattern
[] = "^"
2309 "REPORT-IOCTL: DeviceFD=[0-9]+ Command=([A-Z ]*[A-Z])" // (2)
2311 "( InputParameter=([0-9]+))?" // (4 (5))
2313 "( returned (-?[0-9]+)( errno=([0-9]+)[^\r\n]*)?)" // (6 (7) (8 (9)))
2315 "[\r\n]" // EOL match necessary to match optional parts above
2317 "===== \\[([A-Z ]*[A-Z])\\] DATA START " // (10)
2322 if (compileregex(&rex
, pattern
, REG_EXTENDED
)) {
2323 errno
= EIO
; return -1;
2327 const char * errmsg
= 0;
2328 int i
= -1, state
= 0, lineno
= 1;
2329 for (const char * line
= buffer
; *line
; line
= nextline(line
, lineno
)) {
2331 if (!(line
[0] == 'R' || line
[0] == '='))
2333 const int nmatch
= 1+10;
2334 regmatch_t match
[nmatch
];
2335 if (regexec(&rex
, line
, nmatch
, match
, 0))
2339 if (matchcpy(cmdname
, sizeof(cmdname
), line
, match
[2])) { // "REPORT-IOCTL:... Command=%s ..."
2340 int nc
= name2command(cmdname
);
2342 errmsg
= "Unknown ATA command name"; break;
2344 if (match
[7].rm_so
< 0) { // "returned %d"
2346 if (!(state
== 0 || state
== 2)) {
2347 errmsg
= "Missing REPORT-IOCTL result"; break;
2349 if (++i
>= max_num_parsed_commands
) {
2350 errmsg
= "Too many ATA commands"; break;
2352 parsed_command_table
[i
].command
= (smart_command_set
)nc
;
2353 parsed_command_table
[i
].select
= matchtoi(line
, match
[5], 0); // "InputParameter=%d"
2358 if (!(state
== 1 && (int)parsed_command_table
[i
].command
== nc
)) {
2359 errmsg
= "Missing REPORT-IOCTL start"; break;
2361 parsed_command_table
[i
].retval
= matchtoi(line
, match
[7], -1); // "returned %d"
2362 parsed_command_table
[i
].errval
= matchtoi(line
, match
[9], 0); // "errno=%d"
2366 else if (matchcpy(cmdname
, sizeof(cmdname
), line
, match
[10])) { // "===== [%s] DATA START "
2367 // Start of sector hexdump
2368 int nc
= name2command(cmdname
);
2369 if (!(state
== (nc
== WRITE_LOG
? 1 : 2) && (int)parsed_command_table
[i
].command
== nc
)) {
2370 errmsg
= "Unexpected DATA START"; break;
2372 line
= nextline(line
, lineno
);
2373 char * data
= (char *)malloc(512);
2375 for (j
= 0; j
< 32; j
++) {
2377 unsigned u1
, u2
; int n1
= -1;
2378 if (!(sscanf(line
, "%3u-%3u: "
2379 "%2x %2x %2x %2x %2x %2x %2x %2x "
2380 "%2x %2x %2x %2x %2x %2x %2x %2x%n",
2382 b
+ 0, b
+ 1, b
+ 2, b
+ 3, b
+ 4, b
+ 5, b
+ 6, b
+ 7,
2383 b
+ 8, b
+ 9, b
+10, b
+11, b
+12, b
+13, b
+14, b
+15, &n1
) == 18
2384 && n1
>= 56 && u1
== j
*16 && u2
== j
*16+15))
2386 for (unsigned k
= 0; k
< 16; k
++)
2387 data
[j
*16+k
] = b
[k
];
2388 line
= nextline(line
, lineno
);
2392 errmsg
= "Incomplete sector hex dump"; break;
2394 parsed_command_table
[i
].data
= data
;
2395 if (nc
!= WRITE_LOG
)
2400 if (!(state
== 0 || state
== 2))
2401 errmsg
= "Missing REPORT-IOCTL result";
2403 if (!errmsg
&& i
< 0)
2404 errmsg
= "No information found";
2406 num_parsed_commands
= i
+1;
2407 next_replay_command
= 0;
2408 replay_out_of_sync
= false;
2411 pout("%s(%d): Syntax error: %s\n", pathname
, lineno
, errmsg
);
2419 // Report warnings and free command table
2420 void parsedev_close(int /*fd*/)
2422 if (replay_out_of_sync
)
2423 pout("REPLAY-IOCTL: Warning: commands replayed out of sync\n");
2424 else if (next_replay_command
!= 0)
2425 pout("REPLAY-IOCTL: Warning: %d command(s) not replayed\n", num_parsed_commands
-next_replay_command
);
2427 for (int i
= 0; i
< num_parsed_commands
; i
++) {
2428 if (parsed_command_table
[i
].data
) {
2429 free(parsed_command_table
[i
].data
); parsed_command_table
[i
].data
= 0;
2432 num_parsed_commands
= 0;
2435 // Simulate ATA command from command table
2436 static int parsedev_command_interface(int /*fd*/, smart_command_set command
, int select
, char * data
)
2438 // Find command, try round-robin of out of sync
2439 int i
= next_replay_command
;
2440 for (int j
= 0; ; j
++) {
2441 if (j
>= num_parsed_commands
) {
2442 pout("REPLAY-IOCTL: Warning: Command not found\n");
2446 if (parsed_command_table
[i
].command
== command
&& parsed_command_table
[i
].select
== select
)
2448 if (!replay_out_of_sync
) {
2449 replay_out_of_sync
= true;
2450 pout("REPLAY-IOCTL: Warning: Command #%d is out of sync\n", i
+1);
2452 if (++i
>= num_parsed_commands
)
2455 next_replay_command
= i
;
2456 if (++next_replay_command
>= num_parsed_commands
)
2457 next_replay_command
= 0;
2459 // Return command data
2464 case READ_THRESHOLDS
:
2466 if (parsed_command_table
[i
].data
)
2467 memcpy(data
, parsed_command_table
[i
].data
, 512);
2470 if (!(parsed_command_table
[i
].data
&& !memcmp(data
, parsed_command_table
[i
].data
, 512)))
2471 pout("REPLAY-IOCTL: Warning: WRITE LOG data does not match\n");
2473 case CHECK_POWER_MODE
:
2474 data
[0] = (char)0xff;
2479 if (parsed_command_table
[i
].errval
)
2480 errno
= parsed_command_table
[i
].errval
;
2481 return parsed_command_table
[i
].retval
;