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