atactl.c revision 1.79 1 /* $NetBSD: atactl.c,v 1.79 2018/12/05 06:49:54 mrg Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ken Hornstein.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * atactl(8) - a program to control ATA devices.
34 */
35 #include <sys/cdefs.h>
36
37 #ifndef lint
38 __RCSID("$NetBSD: atactl.c,v 1.79 2018/12/05 06:49:54 mrg Exp $");
39 #endif
40
41
42 #include <sys/param.h>
43 #include <sys/ioctl.h>
44 #include <err.h>
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <pwd.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <util.h>
53
54 #include <dev/ata/atareg.h>
55 #include <sys/ataio.h>
56
57 struct ata_smart_error {
58 struct {
59 uint8_t device_control;
60 uint8_t features;
61 uint8_t sector_count;
62 uint8_t sector_number;
63 uint8_t cylinder_low;
64 uint8_t cylinder_high;
65 uint8_t device_head;
66 uint8_t command;
67 uint8_t timestamp[4];
68 } command[5];
69 struct {
70 uint8_t reserved;
71 uint8_t error;
72 uint8_t sector_count;
73 uint8_t sector_number;
74 uint8_t cylinder_low;
75 uint8_t cylinder_high;
76 uint8_t device_head;
77 uint8_t status;
78 uint8_t extended_error[19];
79 uint8_t state;
80 uint8_t lifetime[2];
81 } error_data;
82 } __packed;
83
84 struct ata_smart_errorlog {
85 uint8_t data_structure_revision;
86 uint8_t mostrecenterror;
87 struct ata_smart_error log_entries[5];
88 uint16_t device_error_count;
89 uint8_t reserved[57];
90 uint8_t checksum;
91 } __packed;
92
93 struct command {
94 const char *cmd_name;
95 const char *arg_names;
96 void (*cmd_func)(int, char *[]);
97 };
98
99 struct bitinfo {
100 u_int bitmask;
101 const char *string;
102 };
103
104 __dead static void usage(void);
105 static void ata_command(struct atareq *);
106 static void print_bitinfo(const char *, const char *, u_int,
107 const struct bitinfo *);
108 static void print_bitinfo2(const char *, const char *, u_int, u_int,
109 const struct bitinfo *);
110 static void print_smart_status(void *, void *, const char *);
111 static void print_error_entry(int, const struct ata_smart_error *);
112 static void print_selftest_entry(int, const struct ata_smart_selftest *);
113
114 static void print_error(const void *);
115 static void print_selftest(const void *);
116
117 static void fillataparams(void);
118
119 static int is_smart(void);
120
121 static int fd; /* file descriptor for device */
122 static const char *dvname; /* device name */
123 static char dvname_store[MAXPATHLEN]; /* for opendisk(3) */
124 static const char *cmdname; /* command user issued */
125 static const struct ataparams *inqbuf; /* inquiry buffer */
126 static char model[sizeof(inqbuf->atap_model)+1];
127 static char revision[sizeof(inqbuf->atap_revision)+1];
128 static char serial[sizeof(inqbuf->atap_serial)+1];
129
130 static void device_identify(int, char *[]);
131 static void device_setidle(int, char *[]);
132 static void device_idle(int, char *[]);
133 static void device_apm(int, char *[]);
134 static void device_checkpower(int, char *[]);
135 static void device_smart(int, char *[]);
136 static void device_security(int, char *[]);
137
138 static void device_smart_temp(const struct ata_smart_attr *, uint64_t);
139
140 static const struct command device_commands[] = {
141 { "identify", "", device_identify },
142 { "setidle", "idle-timer", device_setidle },
143 { "apm", "disable|set #", device_apm },
144 { "setstandby", "standby-timer", device_setidle },
145 { "idle", "", device_idle },
146 { "standby", "", device_idle },
147 { "sleep", "", device_idle },
148 { "checkpower", "", device_checkpower },
149 { "smart",
150 "enable|disable|status [vendor]|offline #|error-log|selftest-log",
151 device_smart },
152 { "security",
153 "status|freeze|[setpass|unlock|disable|erase] [user|master]",
154 device_security },
155 { NULL, NULL, NULL },
156 };
157
158 static void bus_reset(int, char *[]);
159
160 static const struct command bus_commands[] = {
161 { "reset", "", bus_reset },
162 { NULL, NULL, NULL },
163 };
164
165 /*
166 * Tables containing bitmasks used for error reporting and
167 * device identification.
168 */
169
170 static const struct bitinfo ata_caps[] = {
171 { WDC_CAP_DMA, "DMA" },
172 { WDC_CAP_LBA, "LBA" },
173 { ATA_CAP_STBY, "ATA standby timer values" },
174 { WDC_CAP_IORDY, "IORDY operation" },
175 { WDC_CAP_IORDY_DSBL, "IORDY disabling" },
176 { 0, NULL },
177 };
178
179 static const struct bitinfo ata_vers[] = {
180 { WDC_VER_ATA1, "ATA-1" },
181 { WDC_VER_ATA2, "ATA-2" },
182 { WDC_VER_ATA3, "ATA-3" },
183 { WDC_VER_ATA4, "ATA-4" },
184 { WDC_VER_ATA5, "ATA-5" },
185 { WDC_VER_ATA6, "ATA-6" },
186 { WDC_VER_ATA7, "ATA-7" },
187 { WDC_VER_ATA8, "ATA-8" },
188 { 0, NULL },
189 };
190
191 static const struct bitinfo ata_cmd_set1[] = {
192 { WDC_CMD1_NOP, "NOP command" },
193 { WDC_CMD1_RB, "READ BUFFER command" },
194 { WDC_CMD1_WB, "WRITE BUFFER command" },
195 { WDC_CMD1_HPA, "Host Protected Area feature set" },
196 { WDC_CMD1_DVRST, "DEVICE RESET command" },
197 { WDC_CMD1_SRV, "SERVICE interrupt" },
198 { WDC_CMD1_RLSE, "Release interrupt" },
199 { WDC_CMD1_AHEAD, "Look-ahead" },
200 { WDC_CMD1_CACHE, "Write cache" },
201 { WDC_CMD1_PKT, "PACKET command feature set" },
202 { WDC_CMD1_PM, "Power Management feature set" },
203 { WDC_CMD1_REMOV, "Removable Media feature set" },
204 { WDC_CMD1_SEC, "Security Mode feature set" },
205 { WDC_CMD1_SMART, "SMART feature set" },
206 { 0, NULL },
207 };
208
209 static const struct bitinfo ata_cmd_set2[] = {
210 { ATA_CMD2_FCE, "FLUSH CACHE EXT command" },
211 { WDC_CMD2_FC, "FLUSH CACHE command" },
212 { WDC_CMD2_DCO, "Device Configuration Overlay feature set" },
213 { ATA_CMD2_LBA48, "48-bit Address feature set" },
214 { WDC_CMD2_AAM, "Automatic Acoustic Management feature set" },
215 { WDC_CMD2_SM, "SET MAX security extension" },
216 { WDC_CMD2_SFREQ, "SET FEATURES required to spin-up after power-up" },
217 { WDC_CMD2_PUIS, "Power-Up In Standby feature set" },
218 { WDC_CMD2_RMSN, "Removable Media Status Notification feature set" },
219 { ATA_CMD2_APM, "Advanced Power Management feature set" },
220 { ATA_CMD2_CFA, "CFA feature set" },
221 { ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" },
222 { WDC_CMD2_DM, "DOWNLOAD MICROCODE command" },
223 { 0, NULL },
224 };
225
226 static const struct bitinfo ata_cmd_ext[] = {
227 { ATA_CMDE_TLCONT, "Time-limited R/W feature set R/W Continuous mode" },
228 { ATA_CMDE_TL, "Time-limited Read/Write" },
229 { ATA_CMDE_URGW, "URG bit for WRITE STREAM DMA/PIO" },
230 { ATA_CMDE_URGR, "URG bit for READ STREAM DMA/PIO" },
231 { ATA_CMDE_WWN, "World Wide Name" },
232 { ATA_CMDE_WQFE, "WRITE DMA QUEUED FUA EXT command" },
233 { ATA_CMDE_WFE, "WRITE DMA/MULTIPLE FUA EXT commands" },
234 { ATA_CMDE_GPL, "General Purpose Logging feature set" },
235 { ATA_CMDE_STREAM, "Streaming feature set" },
236 { ATA_CMDE_MCPTC, "Media Card Pass Through Command feature set" },
237 { ATA_CMDE_MS, "Media serial number" },
238 { ATA_CMDE_SST, "SMART self-test" },
239 { ATA_CMDE_SEL, "SMART error logging" },
240 { 0, NULL },
241 };
242
243 static const struct bitinfo ata_sata_caps[] = {
244 { SATA_SIGNAL_GEN1, "1.5Gb/s signaling" },
245 { SATA_SIGNAL_GEN2, "3.0Gb/s signaling" },
246 { SATA_SIGNAL_GEN3, "6.0Gb/s signaling" },
247 { SATA_NATIVE_CMDQ, "Native Command Queuing" },
248 { SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" },
249 { SATA_PHY_EVNT_CNT, "PHY Event Counters" },
250 { 0, NULL },
251 };
252
253 static const struct bitinfo ata_sata_feat[] = {
254 { SATA_NONZERO_OFFSETS, "Non-zero Offset DMA" },
255 { SATA_DMA_SETUP_AUTO, "DMA Setup Auto Activate" },
256 { SATA_DRIVE_PWR_MGMT, "Device-Initiated Interface Power Managment" },
257 { SATA_IN_ORDER_DATA, "In-order Data Delivery" },
258 { SATA_SW_STTNGS_PRS, "Software Settings Preservation" },
259 { 0, NULL },
260 };
261
262 /*
263 * Global SMART attribute table. All known attributes should be defined
264 * here with overrides outside of the standard in a vendor specific table.
265 *
266 * XXX Some of these should be duplicated to vendor-specific tables now that
267 * XXX they exist and have non generic names.
268 */
269 static const struct attr_table {
270 const unsigned id;
271 const char *name;
272 void (*special)(const struct ata_smart_attr *, uint64_t);
273 } smart_attrs[] = {
274 { 1, "Raw read error rate", NULL },
275 { 2, "Throughput performance", NULL },
276 { 3, "Spin-up time", NULL },
277 { 4, "Start/stop count", NULL },
278 { 5, "Reallocated sector count", NULL },
279 { 6, "Read channel margin", NULL },
280 { 7, "Seek error rate", NULL },
281 { 8, "Seek time performance", NULL },
282 { 9, "Power-on hours count", NULL },
283 { 10, "Spin retry count", NULL },
284 { 11, "Calibration retry count", NULL },
285 { 12, "Device power cycle count", NULL },
286 { 13, "Soft read error rate", NULL },
287 { 100, "Erase/Program Cycles", NULL },
288 { 103, "Translation Table Rebuild", NULL },
289 { 170, "Reserved Block Count", NULL },
290 { 171, "Program Fail Count", NULL },
291 { 172, "Erase Fail Count", NULL },
292 { 173, "Wear Leveller Worst Case Erase Count", NULL },
293 { 174, "Unexpected Power Loss Count", NULL },
294 { 175, "Program Fail Count", NULL },
295 { 176, "Erase Fail Count", NULL },
296 { 177, "Wear Leveling Count", NULL },
297 { 178, "Used Reserved Block Count", NULL },
298 { 179, "Used Reserved Block Count", NULL },
299 { 180, "Unused Reserved Block Count", NULL },
300 { 181, "Program Fail Count", NULL },
301 { 182, "Erase Fail Count", NULL },
302 { 183, "SATA Downshift Error Count", NULL },
303 { 184, "End-to-end error", NULL },
304 { 185, "Head Stability", NULL },
305 { 186, "Induced Op-Vibration Detection", NULL },
306 { 187, "Reported Uncorrectable Errors", NULL },
307 { 188, "Command Timeout", NULL },
308 { 189, "High Fly Writes", NULL },
309 { 190, "Airflow Temperature", device_smart_temp },
310 { 191, "G-sense error rate", NULL },
311 { 192, "Power-off retract count", NULL },
312 { 193, "Load cycle count", NULL },
313 { 194, "Temperature", device_smart_temp},
314 { 195, "Hardware ECC Recovered", NULL },
315 { 196, "Reallocated event count", NULL },
316 { 197, "Current pending sector", NULL },
317 { 198, "Offline uncorrectable", NULL },
318 { 199, "Ultra DMA CRC error count", NULL },
319 { 200, "Write error rate", NULL },
320 { 201, "Soft read error rate", NULL },
321 { 202, "Data address mark errors", NULL },
322 { 203, "Run out cancel", NULL },
323 { 204, "Soft ECC correction", NULL },
324 { 205, "Thermal asperity check", NULL },
325 { 206, "Flying height", NULL },
326 { 207, "Spin high current", NULL },
327 { 208, "Spin buzz", NULL },
328 { 209, "Offline seek performance", NULL },
329 { 210, "Successful RAIN Recovery Count", NULL },
330 { 220, "Disk shift", NULL },
331 { 221, "G-Sense error rate", NULL },
332 { 222, "Loaded hours", NULL },
333 { 223, "Load/unload retry count", NULL },
334 { 224, "Load friction", NULL },
335 { 225, "Load/unload cycle count", NULL },
336 { 226, "Load-in time", NULL },
337 { 227, "Torque amplification count", NULL },
338 { 228, "Power-off retract count", NULL },
339 { 230, "GMR head amplitude", NULL },
340 { 231, "Temperature", device_smart_temp },
341 { 232, "Available reserved space", NULL },
342 { 233, "Media wearout indicator", NULL },
343 { 240, "Head flying hours", NULL },
344 { 241, "Total LBAs Written", NULL },
345 { 242, "Total LBAs Read", NULL },
346 { 246, "Total Host Sector Writes", NULL },
347 { 247, "Host Program NAND Pages Count", NULL },
348 { 248, "FTL Program Pages Count", NULL },
349 { 249, "Total Raw NAND Writes (1GiB units)", NULL },
350 { 250, "Read error retry rate", NULL },
351 { 254, "Free Fall Sensor", NULL },
352 { 0, "Unknown", NULL },
353 };
354
355 /*
356 * Micron specific SMART attributes published by Micron in:
357 * "TN-FD-22: Client SATA SSD SMART Attribute Reference"
358 */
359 static const struct attr_table micron_smart_names[] = {
360 { 5, "Reallocated NAND block count", NULL },
361 { 173, "Average block erase count", NULL },
362 { 181, "Non 4K aligned access count", NULL },
363 { 184, "Error correction count", NULL },
364 { 189, "Factory bad block count", NULL },
365 { 197, "Current pending ECC count", NULL },
366 { 198, "SMART offline scan uncorrectable error count", NULL },
367 { 202, "Percent lifetime remaining", NULL },
368 { 206, "Write error rate", NULL },
369 { 247, "Number of NAND pages of data written by the host", NULL },
370 { 248, "Number of NAND pages written by the FTL", NULL },
371 { 0, "Unknown", NULL },
372 };
373
374 /*
375 * Vendor-specific SMART attribute table. Can be used to override
376 * a particular attribute name and special printer function, with the
377 * default is the main table.
378 */
379 const struct vendor_name_table {
380 const char *name;
381 const struct attr_table *table;
382 } vendor_smart_names[] = {
383 { .name = "Micron", .table = micron_smart_names },
384 };
385
386 static const struct bitinfo ata_sec_st[] = {
387 { WDC_SEC_SUPP, "supported" },
388 { WDC_SEC_EN, "enabled" },
389 { WDC_SEC_LOCKED, "locked" },
390 { WDC_SEC_FROZEN, "frozen" },
391 { WDC_SEC_EXP, "expired" },
392 { WDC_SEC_ESE_SUPP, "enhanced erase support" },
393 { WDC_SEC_LEV_MAX, "maximum level" },
394 { 0, NULL },
395 };
396
397 int
398 main(int argc, char *argv[])
399 {
400 int i;
401 const struct command *commands = NULL;
402
403 /* Must have at least: device command */
404 if (argc < 3)
405 usage();
406
407 /* Skip program name, get and skip device name and command. */
408 dvname = argv[1];
409 cmdname = argv[2];
410 argv += 3;
411 argc -= 3;
412
413 /*
414 * Open the device
415 */
416 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0);
417 if (fd == -1) {
418 if (errno == ENOENT) {
419 /*
420 * Device doesn't exist. Probably trying to open
421 * a device which doesn't use disk semantics for
422 * device name. Try again, specifying "cooked",
423 * which leaves off the "r" in front of the device's
424 * name.
425 */
426 fd = opendisk(dvname, O_RDWR, dvname_store,
427 sizeof(dvname_store), 1);
428 if (fd == -1)
429 err(1, "%s", dvname);
430 } else
431 err(1, "%s", dvname);
432 }
433
434 /*
435 * Point the dvname at the actual device name that opendisk() opened.
436 */
437 dvname = dvname_store;
438
439 /* Look up and call the command. */
440 for (i = 0; device_commands[i].cmd_name != NULL; i++) {
441 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
442 commands = &device_commands[i];
443 break;
444 }
445 }
446 if (commands == NULL) {
447 for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
448 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
449 commands = &bus_commands[i];
450 break;
451 }
452 }
453 }
454 if (commands == NULL)
455 errx(1, "unknown command: %s", cmdname);
456
457 (*commands->cmd_func)(argc, argv);
458 exit(0);
459 }
460
461 static void
462 usage(void)
463 {
464 int i;
465
466 fprintf(stderr, "usage: %s device command [arg [...]]\n",
467 getprogname());
468
469 fprintf(stderr, " Available device commands:\n");
470 for (i=0; device_commands[i].cmd_name != NULL; i++)
471 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
472 device_commands[i].arg_names);
473
474 fprintf(stderr, " Available bus commands:\n");
475 for (i=0; bus_commands[i].cmd_name != NULL; i++)
476 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
477 bus_commands[i].arg_names);
478
479 exit(1);
480 }
481
482 /*
483 * Wrapper that calls ATAIOCCOMMAND and checks for errors
484 */
485
486 static void
487 ata_command(struct atareq *req)
488 {
489 int error;
490
491 error = ioctl(fd, ATAIOCCOMMAND, req);
492
493 if (error == -1)
494 err(1, "ATAIOCCOMMAND failed");
495
496 switch (req->retsts) {
497
498 case ATACMD_OK:
499 return;
500 case ATACMD_TIMEOUT:
501 fprintf(stderr, "ATA command timed out\n");
502 exit(1);
503 case ATACMD_DF:
504 fprintf(stderr, "ATA device returned a Device Fault\n");
505 exit(1);
506 case ATACMD_ERROR:
507 if (req->error & WDCE_ABRT)
508 fprintf(stderr, "ATA device returned Aborted "
509 "Command\n");
510 else
511 fprintf(stderr, "ATA device returned error register "
512 "%0x\n", req->error);
513 exit(1);
514 default:
515 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code "
516 "%d\n", req->retsts);
517 exit(1);
518 }
519 }
520
521 /*
522 * Print out strings associated with particular bitmasks
523 */
524
525 static void
526 print_bitinfo(const char *bf, const char *af, u_int bits,
527 const struct bitinfo *binfo)
528 {
529
530 for (; binfo->bitmask != 0; binfo++)
531 if (bits & binfo->bitmask)
532 printf("%s%s%s", bf, binfo->string, af);
533 }
534
535 static void
536 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables,
537 const struct bitinfo *binfo)
538 {
539
540 for (; binfo->bitmask != 0; binfo++)
541 if (bits & binfo->bitmask)
542 printf("%s%s (%s)%s", bf, binfo->string,
543 (enables & binfo->bitmask) ? "enabled" : "disabled",
544 af);
545 }
546
547
548 /*
549 * Try to print SMART temperature field
550 */
551
552 static void
553 device_smart_temp(const struct ata_smart_attr *attr, uint64_t raw_value)
554 {
555 printf("%" PRIu8, attr->raw[0]);
556 if (attr->raw[0] != raw_value)
557 printf(" Lifetime min/max %" PRIu8 "/%" PRIu8,
558 attr->raw[2], attr->raw[4]);
559 }
560
561 /*
562 * Print out SMART attribute thresholds and values
563 */
564
565 static void
566 print_smart_status(void *vbuf, void *tbuf, const char *vendor)
567 {
568 const struct ata_smart_attributes *value_buf = vbuf;
569 const struct ata_smart_thresholds *threshold_buf = tbuf;
570 const struct ata_smart_attr *attr;
571 uint64_t raw_value;
572 int flags;
573 unsigned i, j;
574 unsigned aid, vid;
575 uint8_t checksum;
576 const struct attr_table *vendor_table = NULL;
577 void (*special)(const struct ata_smart_attr *, uint64_t);
578
579 if (vendor) {
580 for (i = 0; i < __arraycount(vendor_smart_names); i++) {
581 if (strcasecmp(vendor,
582 vendor_smart_names[i].name) == 0) {
583 vendor_table = vendor_smart_names[i].table;
584 break;
585 }
586 }
587 if (vendor_table == NULL)
588 fprintf(stderr,
589 "SMART vendor '%s' has no special table\n", vendor);
590 }
591
592 for (i = checksum = 0; i < 512; i++)
593 checksum += ((const uint8_t *) value_buf)[i];
594 if (checksum != 0) {
595 fprintf(stderr, "SMART attribute values checksum error\n");
596 return;
597 }
598
599 for (i = checksum = 0; i < 512; i++)
600 checksum += ((const uint8_t *) threshold_buf)[i];
601 if (checksum != 0) {
602 fprintf(stderr, "SMART attribute thresholds checksum error\n");
603 return;
604 }
605
606 printf("id value thresh crit collect reliability description"
607 " raw\n");
608 for (i = 0; i < 256; i++) {
609 int thresh = 0;
610 const char *name = NULL;
611
612 attr = NULL;
613
614 for (j = 0; j < 30; j++) {
615 if (value_buf->attributes[j].id == i)
616 attr = &value_buf->attributes[j];
617 if (threshold_buf->thresholds[j].id == i)
618 thresh = threshold_buf->thresholds[j].value;
619 }
620
621 if (thresh && attr == NULL)
622 errx(1, "threshold but not attr %d", i);
623 if (attr == NULL)
624 continue;
625
626 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF)
627 continue;
628
629 for (aid = 0;
630 smart_attrs[aid].id != i && smart_attrs[aid].id != 0;
631 aid++)
632 ;
633
634 if (vendor_table) {
635 for (vid = 0;
636 vendor_table[vid].id != i && vendor_table[vid].id != 0;
637 vid++)
638 ;
639 if (vendor_table[vid].id != 0) {
640 name = vendor_table[vid].name;
641 special = vendor_table[vid].special;
642 }
643 }
644 if (name == NULL) {
645 name = smart_attrs[aid].name;
646 special = smart_attrs[aid].special;
647 }
648
649 flags = le16toh(attr->flags);
650
651 printf("%3d %3d %3d %-3s %-7s %stive %-27s ",
652 i, attr->value, thresh,
653 flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
654 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
655 attr->value > thresh ? "posi" : "nega", name);
656
657 for (j = 0, raw_value = 0; j < 6; j++)
658 raw_value += ((uint64_t)attr->raw[j]) << (8*j);
659
660 if (special)
661 (*special)(attr, raw_value);
662 else
663 printf("%" PRIu64, raw_value);
664 printf("\n");
665 }
666 }
667
668 static const struct {
669 int number;
670 const char *name;
671 } selftest_name[] = {
672 { 0, "Off-line" },
673 { 1, "Short off-line" },
674 { 2, "Extended off-line" },
675 { 127, "Abort off-line test" },
676 { 129, "Short captive" },
677 { 130, "Extended captive" },
678 { 256, "Unknown test" }, /* larger than uint8_t */
679 { 0, NULL }
680 };
681
682 static const char *selftest_status[] = {
683 "No error",
684 "Aborted by the host",
685 "Interrupted by the host by reset",
686 "Fatal error or unknown test error",
687 "Unknown test element failed",
688 "Electrical test element failed",
689 "The Servo (and/or seek) test element failed",
690 "Read element of test failed",
691 "Reserved",
692 "Reserved",
693 "Reserved",
694 "Reserved",
695 "Reserved",
696 "Reserved",
697 "Reserved",
698 "Self-test in progress"
699 };
700
701 static void
702 print_error_entry(int num, const struct ata_smart_error *le)
703 {
704 int i;
705
706 printf("Log entry: %d\n", num);
707
708 for (i = 0; i < 5; i++)
709 printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x "
710 "ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i,
711 le->command[i].device_control,
712 le->command[i].features,
713 le->command[i].sector_count,
714 le->command[i].sector_number,
715 le->command[i].cylinder_low,
716 le->command[i].cylinder_high,
717 le->command[i].device_head,
718 le->command[i].command,
719 le->command[i].timestamp[3],
720 le->command[i].timestamp[2],
721 le->command[i].timestamp[1],
722 le->command[i].timestamp[0]);
723 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x "
724 "status=%02x state=%02x lifetime=%02x%02x\n",
725 le->error_data.error,
726 le->error_data.sector_count,
727 le->error_data.sector_number,
728 le->error_data.cylinder_low,
729 le->error_data.cylinder_high,
730 le->error_data.device_head,
731 le->error_data.status,
732 le->error_data.state,
733 le->error_data.lifetime[1],
734 le->error_data.lifetime[0]);
735 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
736 "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
737 le->error_data.extended_error[0],
738 le->error_data.extended_error[1],
739 le->error_data.extended_error[2],
740 le->error_data.extended_error[3],
741 le->error_data.extended_error[4],
742 le->error_data.extended_error[5],
743 le->error_data.extended_error[6],
744 le->error_data.extended_error[7],
745 le->error_data.extended_error[8],
746 le->error_data.extended_error[9],
747 le->error_data.extended_error[10],
748 le->error_data.extended_error[11],
749 le->error_data.extended_error[12],
750 le->error_data.extended_error[13],
751 le->error_data.extended_error[14],
752 le->error_data.extended_error[15],
753 le->error_data.extended_error[15],
754 le->error_data.extended_error[17],
755 le->error_data.extended_error[18]);
756 }
757
758 static void
759 print_error(const void *buf)
760 {
761 const struct ata_smart_errorlog *erlog = buf;
762 uint8_t checksum;
763 int i;
764
765 for (i = checksum = 0; i < 512; i++)
766 checksum += ((const uint8_t *) buf)[i];
767 if (checksum != 0) {
768 fprintf(stderr, "SMART error log checksum error\n");
769 return;
770 }
771
772 if (erlog->data_structure_revision != 1) {
773 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n",
774 erlog->data_structure_revision);
775 return;
776 }
777
778 if (erlog->mostrecenterror == 0) {
779 printf("No errors have been logged\n");
780 return;
781 }
782
783 if (erlog->mostrecenterror > 5) {
784 fprintf(stderr, "Most recent error is too large\n");
785 return;
786 }
787
788 for (i = erlog->mostrecenterror; i < 5; i++)
789 print_error_entry(i, &erlog->log_entries[i]);
790 for (i = 0; i < erlog->mostrecenterror; i++)
791 print_error_entry(i, &erlog->log_entries[i]);
792 printf("device error count: %d\n", erlog->device_error_count);
793 }
794
795 static void
796 print_selftest_entry(int num, const struct ata_smart_selftest *le)
797 {
798 const unsigned char *p;
799 size_t i;
800
801 /* check if all zero */
802 for (p = (const void *)le, i = 0; i < sizeof(*le); i++)
803 if (p[i] != 0)
804 break;
805 if (i == sizeof(*le))
806 return;
807
808 printf("Log entry: %d\n", num);
809
810 /* Get test name */
811 for (i = 0; selftest_name[i].name != NULL; i++)
812 if (selftest_name[i].number == le->number)
813 break;
814
815 if (selftest_name[i].name == NULL)
816 printf("\tName: (%d)\n", le->number);
817 else
818 printf("\tName: %s\n", selftest_name[i].name);
819 printf("\tStatus: %s\n", selftest_status[le->status >> 4]);
820 /* XXX This generally should not be set when a self-test is completed,
821 and at any rate is useless. - mycroft */
822 if (le->status >> 4 == 15)
823 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf);
824 else if (le->status >> 4 != 0)
825 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error));
826 }
827
828 static void
829 print_selftest(const void *buf)
830 {
831 const struct ata_smart_selftestlog *stlog = buf;
832 uint8_t checksum;
833 int i;
834
835 for (i = checksum = 0; i < 512; i++)
836 checksum += ((const uint8_t *) buf)[i];
837 if (checksum != 0) {
838 fprintf(stderr, "SMART selftest log checksum error\n");
839 return;
840 }
841
842 if (le16toh(stlog->data_structure_revision) != 1) {
843 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n",
844 le16toh(stlog->data_structure_revision));
845 return;
846 }
847
848 if (stlog->mostrecenttest == 0) {
849 printf("No self-tests have been logged\n");
850 return;
851 }
852
853 if (stlog->mostrecenttest > 22) {
854 fprintf(stderr, "Most recent test is too large\n");
855 return;
856 }
857
858 for (i = stlog->mostrecenttest; i < 22; i++)
859 print_selftest_entry(i, &stlog->log_entries[i]);
860 for (i = 0; i < stlog->mostrecenttest; i++)
861 print_selftest_entry(i, &stlog->log_entries[i]);
862 }
863
864 static void
865 fillataparams(void)
866 {
867 struct atareq req;
868 static union {
869 unsigned char inbuf[DEV_BSIZE];
870 struct ataparams inqbuf;
871 } inbuf;
872 static int first = 1;
873
874 if (!first)
875 return;
876 first = 0;
877
878 memset(&inbuf, 0, sizeof(inbuf));
879 memset(&req, 0, sizeof(req));
880
881 req.flags = ATACMD_READ;
882 req.command = WDCC_IDENTIFY;
883 req.databuf = &inbuf;
884 req.datalen = sizeof(inbuf);
885 req.timeout = 1000;
886
887 ata_command(&req);
888
889 inqbuf = &inbuf.inqbuf;
890 }
891
892 /*
893 * is_smart:
894 *
895 * Detect whether device supports SMART and SMART is enabled.
896 */
897
898 static int
899 is_smart(void)
900 {
901 int retval = 0;
902 const char *status;
903
904 fillataparams();
905
906 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
907 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
908 fprintf(stderr, "SMART unsupported\n");
909 } else {
910 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
911 inqbuf->atap_cmd_set2 == 0xffff ||
912 inqbuf->atap_cmd_set2 == 0x0000) {
913 status = "status unknown";
914 retval = 2;
915 } else {
916 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) {
917 status = "enabled";
918 retval = 1;
919 } else {
920 status = "disabled";
921 retval = 3;
922 }
923 }
924 printf("SMART supported, SMART %s\n", status);
925 }
926 }
927 return retval;
928 }
929
930 /*
931 * extract_string: copy a block of bytes out of ataparams and make
932 * a proper string out of it, truncating trailing spaces and preserving
933 * strict typing. And also, not doing unaligned accesses.
934 */
935 static void
936 extract_string(char *buf, size_t bufmax,
937 const uint8_t *bytes, size_t numbytes,
938 int needswap)
939 {
940 unsigned i;
941 size_t j;
942 unsigned char ch1, ch2;
943
944 for (i = 0, j = 0; i < numbytes; i += 2) {
945 ch1 = bytes[i];
946 ch2 = bytes[i+1];
947 if (needswap && j < bufmax-1) {
948 buf[j++] = ch2;
949 }
950 if (j < bufmax-1) {
951 buf[j++] = ch1;
952 }
953 if (!needswap && j < bufmax-1) {
954 buf[j++] = ch2;
955 }
956 }
957 while (j > 0 && buf[j-1] == ' ') {
958 j--;
959 }
960 buf[j] = '\0';
961 }
962
963 static void
964 compute_capacity(uint64_t *capacityp, uint64_t *sectorsp, uint32_t *secsizep)
965 {
966 uint64_t capacity;
967 uint64_t sectors;
968 uint32_t secsize;
969
970 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&
971 inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {
972 sectors =
973 ((uint64_t)inqbuf->atap_max_lba[3] << 48) |
974 ((uint64_t)inqbuf->atap_max_lba[2] << 32) |
975 ((uint64_t)inqbuf->atap_max_lba[1] << 16) |
976 ((uint64_t)inqbuf->atap_max_lba[0] << 0);
977 } else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {
978 sectors = (inqbuf->atap_capacity[1] << 16) |
979 inqbuf->atap_capacity[0];
980 } else {
981 sectors = inqbuf->atap_cylinders *
982 inqbuf->atap_heads * inqbuf->atap_sectors;
983 }
984
985 secsize = 512;
986
987 if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
988 if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {
989 secsize = 2 * /* words to bytes */
990 (inqbuf->atap_lls_secsz[1] << 16 |
991 inqbuf->atap_lls_secsz[0] << 0);
992 }
993 }
994
995 capacity = sectors * secsize;
996
997 if (capacityp)
998 *capacityp = capacity;
999 if (sectorsp)
1000 *sectorsp = sectors;
1001 if (secsizep)
1002 *secsizep = secsize;
1003 }
1004
1005 /*
1006 * Inspect the inqbuf and guess what vendor to use. This list is fairly
1007 * basic, and probably should be converted into a regexp scheme.
1008 */
1009 static const char *
1010 guess_vendor(void)
1011 {
1012 struct {
1013 const char *model;
1014 const char *vendor;
1015 } model_to_vendor[] = {
1016 { "Crucial", "Micron" },
1017 { "Micron", "Micron" },
1018 { "C300-CT", "Micron" },
1019 { "C400-MT", "Micron" },
1020 { "M4-CT", "Micron" },
1021 { "M500", "Micron" },
1022 { "M510", "Micron" },
1023 { "M550", "Micron" },
1024 { "MTFDDA", "Micron" },
1025 { "EEFDDA", "Micron" },
1026 };
1027 unsigned i;
1028
1029 for (i = 0; i < __arraycount(model_to_vendor); i++)
1030 if (strncasecmp(model, model_to_vendor[i].model,
1031 strlen(model_to_vendor[i].model)) == 0)
1032 return model_to_vendor[i].vendor;
1033
1034 return NULL;
1035 }
1036
1037 /*
1038 * identify_fixup() - Given an obtained ataparams, fix up the endian and
1039 * other issues before using them.
1040 */
1041 static void
1042 identify_fixup(void)
1043 {
1044 int needswap = 0;
1045
1046 if ((inqbuf->atap_integrity & WDC_INTEGRITY_MAGIC_MASK) ==
1047 WDC_INTEGRITY_MAGIC) {
1048 int i;
1049 uint8_t checksum;
1050
1051 for (i = checksum = 0; i < 512; i++)
1052 checksum += ((const uint8_t *)inqbuf)[i];
1053 if (checksum != 0)
1054 puts("IDENTIFY DEVICE data checksum invalid\n");
1055 }
1056
1057 #if BYTE_ORDER == LITTLE_ENDIAN
1058 /*
1059 * On little endian machines, we need to shuffle the string
1060 * byte order. However, we don't have to do this for NEC or
1061 * Mitsumi ATAPI devices
1062 */
1063
1064 if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC &&
1065 (inqbuf->atap_config & WDC_CFG_ATAPI) &&
1066 ((inqbuf->atap_model[0] == 'N' &&
1067 inqbuf->atap_model[1] == 'E') ||
1068 (inqbuf->atap_model[0] == 'F' &&
1069 inqbuf->atap_model[1] == 'X')))) {
1070 needswap = 1;
1071 }
1072 #endif
1073
1074 /*
1075 * Copy the info strings out, stripping off blanks.
1076 */
1077 extract_string(model, sizeof(model),
1078 inqbuf->atap_model, sizeof(inqbuf->atap_model),
1079 needswap);
1080 extract_string(revision, sizeof(revision),
1081 inqbuf->atap_revision, sizeof(inqbuf->atap_revision),
1082 needswap);
1083 extract_string(serial, sizeof(serial),
1084 inqbuf->atap_serial, sizeof(inqbuf->atap_serial),
1085 needswap);
1086
1087 }
1088
1089 /*
1090 * DEVICE COMMANDS
1091 */
1092
1093 /*
1094 * device_identify:
1095 *
1096 * Display the identity of the device
1097 */
1098 static void
1099 device_identify(int argc, char *argv[])
1100 {
1101 char hnum[12];
1102 uint64_t capacity;
1103 uint64_t sectors;
1104 uint32_t secsize;
1105 int lb_per_pb;
1106
1107 /* No arguments. */
1108 if (argc != 0)
1109 usage();
1110
1111 fillataparams();
1112 identify_fixup();
1113
1114 printf("Model: %s, Rev: %s, Serial #: %s\n",
1115 model, revision, serial);
1116
1117 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff &&
1118 inqbuf->atap_cmd_ext & ATA_CMDE_WWN)
1119 printf("World Wide Name: %016" PRIX64 "\n",
1120 ((uint64_t)inqbuf->atap_wwn[0] << 48) |
1121 ((uint64_t)inqbuf->atap_wwn[1] << 32) |
1122 ((uint64_t)inqbuf->atap_wwn[2] << 16) |
1123 ((uint64_t)inqbuf->atap_wwn[3] << 0));
1124
1125 printf("Device type: %s",
1126 inqbuf->atap_config == WDC_CFG_CFA_MAGIC ? "CF-ATA" :
1127 (inqbuf->atap_config & WDC_CFG_ATAPI ? "ATAPI" : "ATA"));
1128 if (inqbuf->atap_config != WDC_CFG_CFA_MAGIC)
1129 printf(", %s",
1130 inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : "removable");
1131 printf("\n");
1132
1133 compute_capacity(&capacity, §ors, &secsize);
1134
1135 humanize_number(hnum, sizeof(hnum), capacity, "bytes",
1136 HN_AUTOSCALE, HN_DIVISOR_1000);
1137
1138 printf("Capacity %s, %" PRIu64 " sectors, %" PRIu32 " bytes/sector\n",
1139 hnum, sectors, secsize);
1140
1141 printf("Cylinders: %d, heads: %d, sec/track: %d\n",
1142 inqbuf->atap_cylinders, inqbuf->atap_heads,
1143 inqbuf->atap_sectors);
1144
1145 lb_per_pb = 1;
1146
1147 if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
1148 if (inqbuf->atap_secsz & ATA_SECSZ_LPS) {
1149 lb_per_pb <<= inqbuf->atap_secsz & ATA_SECSZ_LPS_SZMSK;
1150 printf("Physical sector size: %d bytes\n",
1151 lb_per_pb * secsize);
1152 if ((inqbuf->atap_logical_align &
1153 ATA_LA_VALID_MASK) == ATA_LA_VALID) {
1154 printf("First physically aligned sector: %d\n",
1155 lb_per_pb - (inqbuf->atap_logical_align &
1156 ATA_LA_MASK));
1157 }
1158 }
1159 }
1160
1161 if (((inqbuf->atap_sata_caps & SATA_NATIVE_CMDQ) ||
1162 (inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ)) &&
1163 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
1164 printf("Command queue depth: %d\n",
1165 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
1166
1167 printf("Device capabilities:\n");
1168 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
1169
1170 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
1171 printf("Device supports following standards:\n");
1172 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
1173 printf("\n");
1174 }
1175
1176 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
1177 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
1178 printf("Command set support:\n");
1179 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
1180 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
1181 inqbuf->atap_cmd1_en, ata_cmd_set1);
1182 else
1183 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
1184 ata_cmd_set1);
1185 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
1186 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
1187 inqbuf->atap_cmd2_en, ata_cmd_set2);
1188 else
1189 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
1190 ata_cmd_set2);
1191 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
1192 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
1193 ata_cmd_ext);
1194 }
1195
1196 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) {
1197 printf("Serial ATA capabilities:\n");
1198 print_bitinfo("\t", "\n",
1199 inqbuf->atap_sata_caps, ata_sata_caps);
1200
1201 }
1202
1203 if (inqbuf->atap_sata_features_supp != 0 &&
1204 inqbuf->atap_sata_features_supp != 0xffff) {
1205 printf("Serial ATA features:\n");
1206 if (inqbuf->atap_sata_features_en != 0 &&
1207 inqbuf->atap_sata_features_en != 0xffff)
1208 print_bitinfo2("\t", "\n",
1209 inqbuf->atap_sata_features_supp,
1210 inqbuf->atap_sata_features_en, ata_sata_feat);
1211 else
1212 print_bitinfo("\t", "\n",
1213 inqbuf->atap_sata_features_supp, ata_sata_feat);
1214 }
1215
1216 if ((inqbuf->atap_ata_major & WDC_VER_ATA7) &&
1217 (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM))
1218 printf("TRIM supported\n");
1219
1220 return;
1221 }
1222
1223 /*
1224 * device idle:
1225 *
1226 * issue the IDLE IMMEDIATE command to the drive
1227 */
1228 static void
1229 device_idle(int argc, char *argv[])
1230 {
1231 struct atareq req;
1232
1233 /* No arguments. */
1234 if (argc != 0)
1235 usage();
1236
1237 memset(&req, 0, sizeof(req));
1238
1239 if (strcmp(cmdname, "idle") == 0)
1240 req.command = WDCC_IDLE_IMMED;
1241 else if (strcmp(cmdname, "standby") == 0)
1242 req.command = WDCC_STANDBY_IMMED;
1243 else
1244 req.command = WDCC_SLEEP;
1245
1246 req.timeout = 1000;
1247
1248 ata_command(&req);
1249
1250 return;
1251 }
1252
1253 /*
1254 * device apm:
1255 *
1256 * enable/disable/control the APM feature of the drive
1257 */
1258 static void
1259 device_apm(int argc, char *argv[])
1260 {
1261 struct atareq req;
1262 long l;
1263
1264 memset(&req, 0, sizeof(req));
1265 if (argc >= 1) {
1266 req.command = SET_FEATURES;
1267 req.timeout = 1000;
1268
1269 if (strcmp(argv[0], "disable") == 0)
1270 req.features = WDSF_APM_DS;
1271 else if (strcmp(argv[0], "set") == 0 && argc >= 2 &&
1272 (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) {
1273
1274 req.features = WDSF_APM_EN;
1275 req.sec_count = l + 1;
1276 } else
1277 usage();
1278 } else
1279 usage();
1280
1281 ata_command(&req);
1282 }
1283
1284
1285 /*
1286 * Set the idle timer on the disk. Set it for either idle mode or
1287 * standby mode, depending on how we were invoked.
1288 */
1289
1290 static void
1291 device_setidle(int argc, char *argv[])
1292 {
1293 unsigned long idle;
1294 struct atareq req;
1295 char *end;
1296
1297 /* Only one argument */
1298 if (argc != 1)
1299 usage();
1300
1301 idle = strtoul(argv[0], &end, 0);
1302
1303 if (*end != '\0') {
1304 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
1305 exit(1);
1306 }
1307
1308 if (idle > 19800) {
1309 fprintf(stderr, "Idle time has a maximum value of 5.5 "
1310 "hours\n");
1311 exit(1);
1312 }
1313
1314 if (idle != 0 && idle < 5) {
1315 fprintf(stderr, "Idle timer must be at least 5 seconds\n");
1316 exit(1);
1317 }
1318
1319 memset(&req, 0, sizeof(req));
1320
1321 if (idle <= 240*5)
1322 req.sec_count = idle / 5;
1323 else
1324 req.sec_count = idle / (30*60) + 240;
1325
1326 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
1327 req.timeout = 1000;
1328
1329 ata_command(&req);
1330
1331 return;
1332 }
1333
1334 /*
1335 * Query the device for the current power mode
1336 */
1337
1338 static void
1339 device_checkpower(int argc, char *argv[])
1340 {
1341 struct atareq req;
1342
1343 /* No arguments. */
1344 if (argc != 0)
1345 usage();
1346
1347 memset(&req, 0, sizeof(req));
1348
1349 req.command = WDCC_CHECK_PWR;
1350 req.timeout = 1000;
1351 req.flags = ATACMD_READREG;
1352
1353 ata_command(&req);
1354
1355 printf("Current power status: ");
1356
1357 switch (req.sec_count) {
1358 case 0x00:
1359 printf("Standby mode\n");
1360 break;
1361 case 0x80:
1362 printf("Idle mode\n");
1363 break;
1364 case 0xff:
1365 printf("Active mode\n");
1366 break;
1367 default:
1368 printf("Unknown power code (%02x)\n", req.sec_count);
1369 }
1370
1371 return;
1372 }
1373
1374 /*
1375 * device_smart:
1376 *
1377 * Display SMART status
1378 */
1379 static void
1380 device_smart(int argc, char *argv[])
1381 {
1382 struct atareq req;
1383 unsigned char inbuf[DEV_BSIZE];
1384 unsigned char inbuf2[DEV_BSIZE];
1385
1386 if (argc < 1)
1387 usage();
1388
1389 if (strcmp(argv[0], "enable") == 0) {
1390 memset(&req, 0, sizeof(req));
1391
1392 req.features = WDSM_ENABLE_OPS;
1393 req.command = WDCC_SMART;
1394 req.cylinder = WDSMART_CYL;
1395 req.timeout = 1000;
1396
1397 ata_command(&req);
1398
1399 is_smart();
1400 } else if (strcmp(argv[0], "disable") == 0) {
1401 memset(&req, 0, sizeof(req));
1402
1403 req.features = WDSM_DISABLE_OPS;
1404 req.command = WDCC_SMART;
1405 req.cylinder = WDSMART_CYL;
1406 req.timeout = 1000;
1407
1408 ata_command(&req);
1409
1410 is_smart();
1411 } else if (strcmp(argv[0], "status") == 0) {
1412 int rv;
1413 const char *vendor = argc > 1 ? argv[1] : NULL;
1414
1415 rv = is_smart();
1416
1417 if (!rv) {
1418 fprintf(stderr, "SMART not supported\n");
1419 return;
1420 } else if (rv == 3)
1421 return;
1422
1423 memset(&inbuf, 0, sizeof(inbuf));
1424 memset(&req, 0, sizeof(req));
1425
1426 req.features = WDSM_STATUS;
1427 req.command = WDCC_SMART;
1428 req.cylinder = WDSMART_CYL;
1429 req.timeout = 1000;
1430
1431 ata_command(&req);
1432
1433 if (req.cylinder != WDSMART_CYL) {
1434 fprintf(stderr, "Threshold exceeds condition\n");
1435 }
1436
1437 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
1438 * features, the following ata_command()'s may error
1439 * and exit().
1440 */
1441
1442 memset(&inbuf, 0, sizeof(inbuf));
1443 memset(&req, 0, sizeof(req));
1444
1445 req.flags = ATACMD_READ;
1446 req.features = WDSM_RD_DATA;
1447 req.command = WDCC_SMART;
1448 req.databuf = (caddr_t) inbuf;
1449 req.datalen = sizeof(inbuf);
1450 req.cylinder = WDSMART_CYL;
1451 req.timeout = 1000;
1452
1453 ata_command(&req);
1454
1455 memset(&inbuf2, 0, sizeof(inbuf2));
1456 memset(&req, 0, sizeof(req));
1457
1458 req.flags = ATACMD_READ;
1459 req.features = WDSM_RD_THRESHOLDS;
1460 req.command = WDCC_SMART;
1461 req.databuf = (caddr_t) inbuf2;
1462 req.datalen = sizeof(inbuf2);
1463 req.cylinder = WDSMART_CYL;
1464 req.timeout = 1000;
1465
1466 ata_command(&req);
1467
1468 if (!vendor || strcmp(vendor, "noauto") == 0) {
1469 fillataparams();
1470 identify_fixup();
1471 vendor = guess_vendor();
1472 }
1473 print_smart_status(inbuf, inbuf2, vendor);
1474
1475 } else if (strcmp(argv[0], "offline") == 0) {
1476 if (argc != 2)
1477 usage();
1478 if (!is_smart()) {
1479 fprintf(stderr, "SMART not supported\n");
1480 return;
1481 }
1482
1483 memset(&req, 0, sizeof(req));
1484
1485 req.features = WDSM_EXEC_OFFL_IMM;
1486 req.command = WDCC_SMART;
1487 req.cylinder = WDSMART_CYL;
1488 req.sec_num = atol(argv[1]);
1489 req.timeout = 10000;
1490
1491 ata_command(&req);
1492 } else if (strcmp(argv[0], "error-log") == 0) {
1493 if (!is_smart()) {
1494 fprintf(stderr, "SMART not supported\n");
1495 return;
1496 }
1497
1498 memset(&inbuf, 0, sizeof(inbuf));
1499 memset(&req, 0, sizeof(req));
1500
1501 req.flags = ATACMD_READ;
1502 req.features = WDSM_RD_LOG;
1503 req.sec_count = 1;
1504 req.sec_num = 1;
1505 req.command = WDCC_SMART;
1506 req.databuf = (caddr_t) inbuf;
1507 req.datalen = sizeof(inbuf);
1508 req.cylinder = WDSMART_CYL;
1509 req.timeout = 1000;
1510
1511 ata_command(&req);
1512
1513 print_error(inbuf);
1514 } else if (strcmp(argv[0], "selftest-log") == 0) {
1515 if (!is_smart()) {
1516 fprintf(stderr, "SMART not supported\n");
1517 return;
1518 }
1519
1520 memset(&inbuf, 0, sizeof(inbuf));
1521 memset(&req, 0, sizeof(req));
1522
1523 req.flags = ATACMD_READ;
1524 req.features = WDSM_RD_LOG;
1525 req.sec_count = 1;
1526 req.sec_num = 6;
1527 req.command = WDCC_SMART;
1528 req.databuf = (caddr_t) inbuf;
1529 req.datalen = sizeof(inbuf);
1530 req.cylinder = WDSMART_CYL;
1531 req.timeout = 1000;
1532
1533 ata_command(&req);
1534
1535 print_selftest(inbuf);
1536
1537 } else {
1538 usage();
1539 }
1540 return;
1541 }
1542
1543 static void
1544 device_security(int argc, char *argv[])
1545 {
1546 struct atareq req;
1547 unsigned char data[DEV_BSIZE];
1548 char *pass;
1549
1550 /* need subcommand */
1551 if (argc < 1)
1552 usage();
1553
1554 memset(&req, 0, sizeof(req));
1555 if (strcmp(argv[0], "status") == 0) {
1556 fillataparams();
1557 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
1558 } else if (strcmp(argv[0], "freeze") == 0) {
1559 req.command = WDCC_SECURITY_FREEZE;
1560 req.timeout = 1000;
1561 ata_command(&req);
1562 } else if ((strcmp(argv[0], "setpass") == 0) ||
1563 (strcmp(argv[0], "unlock") == 0) ||
1564 (strcmp(argv[0], "disable") == 0) ||
1565 (strcmp(argv[0], "erase") == 0)) {
1566 if (argc != 2)
1567 usage();
1568 if (strcmp(argv[1], "user") != 0) {
1569 if (strcmp(argv[1], "master") == 0) {
1570 fprintf(stderr,
1571 "Master passwords not supported\n");
1572 exit(1);
1573 } else {
1574 usage();
1575 }
1576 }
1577
1578 pass = getpass("Password:");
1579 if (strlen(pass) > 32) {
1580 fprintf(stderr, "Password must be <=32 characters\n");
1581 exit(1);
1582 }
1583
1584 req.flags |= ATACMD_WRITE;
1585 req.timeout = 1000;
1586 req.databuf = data;
1587 req.datalen = sizeof(data);
1588 memset(data, 0, sizeof(data));
1589 strlcpy((void *)&data[2], pass, 32 + 1);
1590
1591 if (strcmp(argv[0], "setpass") == 0) {
1592 char orig[32 + 1];
1593 strlcpy(orig, pass, 32 + 1);
1594 pass = getpass("Confirm password:");
1595 if (0 != strcmp(orig, pass)) {
1596 fprintf(stderr, "Passwords do not match\n");
1597 exit(1);
1598 }
1599 req.command = WDCC_SECURITY_SET_PASSWORD;
1600 } else if (strcmp(argv[0], "unlock") == 0) {
1601 req.command = WDCC_SECURITY_UNLOCK;
1602 } else if (strcmp(argv[0], "disable") == 0) {
1603 req.command = WDCC_SECURITY_DISABLE_PASSWORD;
1604 } else if (strcmp(argv[0], "erase") == 0) {
1605 struct atareq prepare;
1606
1607 fillataparams();
1608
1609 /*
1610 * XXX Any way to lock the device to make sure
1611 * this really is the command preceding the
1612 * SECURITY ERASE UNIT command? This would
1613 * probably have to be moved into the kernel to
1614 * do that.
1615 */
1616 memset(&prepare, 0, sizeof(prepare));
1617 prepare.command = WDCC_SECURITY_ERASE_PREPARE;
1618 prepare.timeout = 1000;
1619 ata_command(&prepare);
1620
1621 req.command = WDCC_SECURITY_ERASE_UNIT;
1622
1623 /*
1624 * Enable enhanced erase if it's supported.
1625 *
1626 * XXX should be a command-line option
1627 */
1628 if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) {
1629 data[0] |= 0x2;
1630 req.timeout = (inqbuf->atap_eseu_time & 0xff)
1631 * 2 * 60 * 1000;
1632 } else {
1633 req.timeout = (inqbuf->atap_seu_time & 0xff)
1634 * 2 * 60 * 1000;
1635 }
1636
1637 /*
1638 * If the estimated time was 0xff (* 2 * 60 *
1639 * 1000 = 30600000), that means `>508 minutes'.
1640 * Estimate that we can handle 16 MB/sec, a
1641 * rate I just pulled out of my arse.
1642 */
1643 if (req.timeout == 30600000) {
1644 uint64_t bytes, timeout;
1645 compute_capacity(&bytes, NULL, NULL);
1646 timeout = (bytes / (16 * 1024 * 1024)) * 1000;
1647 if (timeout > (uint64_t)INT_MAX)
1648 req.timeout = INT_MAX;
1649 else
1650 req.timeout = timeout;
1651 }
1652
1653 printf("Erasing may take up to %dh %dm %ds...\n",
1654 (req.timeout / 1000 / 60) / 60,
1655 (req.timeout / 1000 / 60) % 60,
1656 req.timeout % 60);
1657 } else {
1658 abort();
1659 }
1660
1661 ata_command(&req);
1662 } else {
1663 usage();
1664 }
1665 }
1666
1667 /*
1668 * bus_reset:
1669 * Reset an ATA bus (will reset all devices on the bus)
1670 */
1671 static void
1672 bus_reset(int argc, char *argv[])
1673 {
1674 int error;
1675
1676 /* no args */
1677 if (argc != 0)
1678 usage();
1679
1680 error = ioctl(fd, ATABUSIORESET, NULL);
1681
1682 if (error == -1)
1683 err(1, "ATABUSIORESET failed");
1684 }
1685