atactl.c revision 1.41 1 /* $NetBSD: atactl.c,v 1.41 2005/11/29 08:47:22 dbj 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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * atactl(8) - a program to control ATA devices.
41 */
42 #include <sys/cdefs.h>
43
44 #ifndef lint
45 __RCSID("$NetBSD: atactl.c,v 1.41 2005/11/29 08:47:22 dbj Exp $");
46 #endif
47
48
49 #include <sys/param.h>
50 #include <sys/ioctl.h>
51 #include <err.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58 #include <util.h>
59
60 #include <dev/ata/atareg.h>
61 #include <sys/ataio.h>
62
63 struct ata_smart_error {
64 struct {
65 u_int8_t device_control;
66 u_int8_t features;
67 u_int8_t sector_count;
68 u_int8_t sector_number;
69 u_int8_t cylinder_low;
70 u_int8_t cylinder_high;
71 u_int8_t device_head;
72 u_int8_t command;
73 u_int8_t timestamp[4];
74 } command[5];
75 struct {
76 u_int8_t reserved;
77 u_int8_t error;
78 u_int8_t sector_count;
79 u_int8_t sector_number;
80 u_int8_t cylinder_low;
81 u_int8_t cylinder_high;
82 u_int8_t device_head;
83 u_int8_t status;
84 u_int8_t extended_error[19];
85 u_int8_t state;
86 u_int8_t lifetime[2];
87 } error_data;
88 } __attribute__((packed));
89
90 struct ata_smart_errorlog {
91 u_int8_t data_structure_revision;
92 u_int8_t mostrecenterror;
93 struct ata_smart_error log_entries[5];
94 u_int16_t device_error_count;
95 u_int8_t reserved[57];
96 u_int8_t checksum;
97 } __attribute__((packed));
98
99 struct command {
100 const char *cmd_name;
101 const char *arg_names;
102 void (*cmd_func)(int, char *[]);
103 };
104
105 struct bitinfo {
106 u_int bitmask;
107 const char *string;
108 };
109
110 void usage(void);
111 void ata_command(struct atareq *);
112 void print_bitinfo(const char *, const char *, u_int, struct bitinfo *);
113 void print_bitinfo2(const char *, const char *, u_int, u_int, struct bitinfo *);
114 void print_smart_status(void *, void *);
115 void print_error_entry(int, struct ata_smart_error *);
116 void print_selftest_entry(int, struct ata_smart_selftest *);
117
118 void print_error(void *);
119 void print_selftest(void *);
120
121 struct ataparams *getataparams(void);
122
123 int is_smart(void);
124
125 int fd; /* file descriptor for device */
126 const char *dvname; /* device name */
127 char dvname_store[MAXPATHLEN]; /* for opendisk(3) */
128 const char *cmdname; /* command user issued */
129 const char *argnames; /* helpstring: expected arguments */
130
131 void device_identify(int, char *[]);
132 void device_setidle(int, char *[]);
133 void device_idle(int, char *[]);
134 void device_checkpower(int, char *[]);
135 void device_smart(int, char *[]);
136 void device_security(int, char *[]);
137
138 void device_smart_temp(struct ata_smart_attr *, uint64_t);
139
140 struct command device_commands[] = {
141 { "identify", "", device_identify },
142 { "setidle", "idle-timer", device_setidle },
143 { "setstandby", "standby-timer", device_setidle },
144 { "idle", "", device_idle },
145 { "standby", "", device_idle },
146 { "sleep", "", device_idle },
147 { "checkpower", "", device_checkpower },
148 { "smart", "enable|disable|status|offline #|error-log|selftest-log",
149 device_smart },
150 { "security", "freeze|status", device_security },
151 { NULL, NULL, NULL },
152 };
153
154 void bus_reset(int, char *[]);
155
156 struct command bus_commands[] = {
157 { "reset", "", bus_reset },
158 { NULL, NULL, NULL },
159 };
160
161 /*
162 * Tables containing bitmasks used for error reporting and
163 * device identification.
164 */
165
166 struct bitinfo ata_caps[] = {
167 { WDC_CAP_DMA, "DMA" },
168 { WDC_CAP_LBA, "LBA" },
169 { ATA_CAP_STBY, "ATA standby timer values" },
170 { WDC_CAP_IORDY, "IORDY operation" },
171 { WDC_CAP_IORDY_DSBL, "IORDY disabling" },
172 { 0, NULL },
173 };
174
175 struct bitinfo ata_vers[] = {
176 { WDC_VER_ATA1, "ATA-1" },
177 { WDC_VER_ATA2, "ATA-2" },
178 { WDC_VER_ATA3, "ATA-3" },
179 { WDC_VER_ATA4, "ATA-4" },
180 { WDC_VER_ATA5, "ATA-5" },
181 { WDC_VER_ATA6, "ATA-6" },
182 { WDC_VER_ATA7, "ATA-7" },
183 { 0, NULL },
184 };
185
186 struct bitinfo ata_cmd_set1[] = {
187 { WDC_CMD1_NOP, "NOP command" },
188 { WDC_CMD1_RB, "READ BUFFER command" },
189 { WDC_CMD1_WB, "WRITE BUFFER command" },
190 { WDC_CMD1_HPA, "Host Protected Area feature set" },
191 { WDC_CMD1_DVRST, "DEVICE RESET command" },
192 { WDC_CMD1_SRV, "SERVICE interrupt" },
193 { WDC_CMD1_RLSE, "release interrupt" },
194 { WDC_CMD1_AHEAD, "look-ahead" },
195 { WDC_CMD1_CACHE, "write cache" },
196 { WDC_CMD1_PKT, "PACKET command feature set" },
197 { WDC_CMD1_PM, "Power Management feature set" },
198 { WDC_CMD1_REMOV, "Removable Media feature set" },
199 { WDC_CMD1_SEC, "Security Mode feature set" },
200 { WDC_CMD1_SMART, "SMART feature set" },
201 { 0, NULL },
202 };
203
204 struct bitinfo ata_cmd_set2[] = {
205 { ATA_CMD2_FCE, "FLUSH CACHE EXT command" },
206 { WDC_CMD2_FC, "FLUSH CACHE command" },
207 { WDC_CMD2_DCO, "Device Configuration Overlay feature set" },
208 { ATA_CMD2_LBA48, "48-bit Address feature set" },
209 { WDC_CMD2_AAM, "Automatic Acoustic Management feature set" },
210 { WDC_CMD2_SM, "SET MAX security extension" },
211 { WDC_CMD2_SFREQ, "SET FEATURES required to spin-up after power-up" },
212 { WDC_CMD2_PUIS, "Power-Up In Standby feature set" },
213 { WDC_CMD2_RMSN, "Removable Media Status Notification feature set" },
214 { ATA_CMD2_APM, "Advanced Power Management feature set" },
215 { ATA_CMD2_CFA, "CFA feature set" },
216 { ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" },
217 { WDC_CMD2_DM, "DOWNLOAD MICROCODE command" },
218 { 0, NULL },
219 };
220
221 struct bitinfo ata_cmd_ext[] = {
222 { ATA_CMDE_TLCONT, "Time-limited R/W feature set R/W Continuous mode" },
223 { ATA_CMDE_TL, "Time-limited Read/Write" },
224 { ATA_CMDE_URGW, "URG bit for WRITE STREAM DMA/PIO" },
225 { ATA_CMDE_URGR, "URG bit for READ STREAM DMA/PIO" },
226 { ATA_CMDE_WWN, "World Wide name" },
227 { ATA_CMDE_WQFE, "WRITE DMA QUEUED FUA EXT command" },
228 { ATA_CMDE_WFE, "WRITE DMA/MULTIPLE FUA EXT commands" },
229 { ATA_CMDE_GPL, "General Purpose Logging feature set" },
230 { ATA_CMDE_STREAM, "Streaming feature set" },
231 { ATA_CMDE_MCPTC, "Media Card Pass Through Command feature set" },
232 { ATA_CMDE_MS, "Media serial number" },
233 { ATA_CMDE_SST, "SMART self-test" },
234 { ATA_CMDE_SEL, "SMART error logging" },
235 { 0, NULL },
236 };
237
238 static const struct {
239 const int id;
240 const char *name;
241 void (*special)(struct ata_smart_attr *, uint64_t);
242 } smart_attrs[] = {
243 { 1, "Raw read error rate" },
244 { 2, "Throughput performance" },
245 { 3, "Spin-up time" },
246 { 4, "Start/stop count" },
247 { 5, "Reallocated sector count" },
248 { 6, "Read channel margin" },
249 { 7, "Seek error rate" },
250 { 8, "Seek time performance" },
251 { 9, "Power-on hours count" },
252 { 10, "Spin retry count" },
253 { 11, "Calibration retry count" },
254 { 12, "Device power cycle count" },
255 { 191, "Gsense error rate" },
256 { 192, "Power-off retract count" },
257 { 193, "Load cycle count" },
258 { 194, "Temperature", device_smart_temp},
259 { 195, "Hardware ECC Recovered" },
260 { 196, "Reallocated event count" },
261 { 197, "Current pending sector" },
262 { 198, "Offline uncorrectable" },
263 { 199, "Ultra DMA CRC error count" },
264 { 200, "Write error rate" },
265 { 201, "Soft read error rate" },
266 { 202, "Data address mark errors" },
267 { 203, "Run out cancel" },
268 { 204, "Soft ECC correction" },
269 { 205, "Thermal asperity check" },
270 { 206, "Flying height" },
271 { 207, "Spin high current" },
272 { 208, "Spin buzz" },
273 { 209, "Offline seek performance" },
274 { 220, "Disk shift" },
275 { 221, "G-Sense error rate" },
276 { 222, "Loaded hours" },
277 { 223, "Load/unload retry count" },
278 { 224, "Load friction" },
279 { 225, "Load/unload cycle count" },
280 { 226, "Load-in time" },
281 { 227, "Torque amplification count" },
282 { 228, "Power-off retract count" },
283 { 230, "GMR head amplitude" },
284 { 231, "Temperature", device_smart_temp },
285 { 240, "Head flying hours" },
286 { 250, "Read error retry rate" },
287 { 0, "Unknown" },
288 };
289
290 struct bitinfo ata_sec_st[] = {
291 { WDC_SEC_SUPP, "supported" },
292 { WDC_SEC_EN, "enabled" },
293 { WDC_SEC_LOCKED, "locked" },
294 { WDC_SEC_FROZEN, "frozen" },
295 { WDC_SEC_EXP, "expired" },
296 { WDC_SEC_ESE_SUPP, "enhanced erase support" },
297 { WDC_SEC_LEV_MAX, "maximum level" },
298 { 0, NULL },
299 };
300
301 int
302 main(int argc, char *argv[])
303 {
304 int i;
305 struct command *commands = NULL;
306
307 /* Must have at least: device command */
308 if (argc < 3)
309 usage();
310
311 /* Skip program name, get and skip device name and command. */
312 dvname = argv[1];
313 cmdname = argv[2];
314 argv += 3;
315 argc -= 3;
316
317 /*
318 * Open the device
319 */
320 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0);
321 if (fd == -1) {
322 if (errno == ENOENT) {
323 /*
324 * Device doesn't exist. Probably trying to open
325 * a device which doesn't use disk semantics for
326 * device name. Try again, specifying "cooked",
327 * which leaves off the "r" in front of the device's
328 * name.
329 */
330 fd = opendisk(dvname, O_RDWR, dvname_store,
331 sizeof(dvname_store), 1);
332 if (fd == -1)
333 err(1, "%s", dvname);
334 } else
335 err(1, "%s", dvname);
336 }
337
338 /*
339 * Point the dvname at the actual device name that opendisk() opened.
340 */
341 dvname = dvname_store;
342
343 /* Look up and call the command. */
344 for (i = 0; device_commands[i].cmd_name != NULL; i++) {
345 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
346 commands = &device_commands[i];
347 break;
348 }
349 }
350 if (commands == NULL) {
351 for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
352 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
353 commands = &bus_commands[i];
354 break;
355 }
356 }
357 }
358 if (commands == NULL)
359 errx(1, "unknown command: %s", cmdname);
360
361 argnames = commands->arg_names;
362
363 (*commands->cmd_func)(argc, argv);
364 exit(0);
365 }
366
367 void
368 usage(void)
369 {
370 int i;
371
372 fprintf(stderr, "usage: %s device command [arg [...]]\n",
373 getprogname());
374
375 fprintf(stderr, " Available device commands:\n");
376 for (i=0; device_commands[i].cmd_name != NULL; i++)
377 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
378 device_commands[i].arg_names);
379
380 fprintf(stderr, " Available bus commands:\n");
381 for (i=0; bus_commands[i].cmd_name != NULL; i++)
382 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
383 bus_commands[i].arg_names);
384
385 exit(1);
386 }
387
388 /*
389 * Wrapper that calls ATAIOCCOMMAND and checks for errors
390 */
391
392 void
393 ata_command(struct atareq *req)
394 {
395 int error;
396
397 error = ioctl(fd, ATAIOCCOMMAND, req);
398
399 if (error == -1)
400 err(1, "ATAIOCCOMMAND failed");
401
402 switch (req->retsts) {
403
404 case ATACMD_OK:
405 return;
406 case ATACMD_TIMEOUT:
407 fprintf(stderr, "ATA command timed out\n");
408 exit(1);
409 case ATACMD_DF:
410 fprintf(stderr, "ATA device returned a Device Fault\n");
411 exit(1);
412 case ATACMD_ERROR:
413 if (req->error & WDCE_ABRT)
414 fprintf(stderr, "ATA device returned Aborted "
415 "Command\n");
416 else
417 fprintf(stderr, "ATA device returned error register "
418 "%0x\n", req->error);
419 exit(1);
420 default:
421 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code "
422 "%d\n", req->retsts);
423 exit(1);
424 }
425 }
426
427 /*
428 * Print out strings associated with particular bitmasks
429 */
430
431 void
432 print_bitinfo(const char *bf, const char *af, u_int bits, struct bitinfo *binfo)
433 {
434
435 for (; binfo->bitmask != 0; binfo++)
436 if (bits & binfo->bitmask)
437 printf("%s%s%s", bf, binfo->string, af);
438 }
439
440 void
441 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables, struct bitinfo *binfo)
442 {
443
444 for (; binfo->bitmask != 0; binfo++)
445 if (bits & binfo->bitmask)
446 printf("%s%s (%s)%s", bf, binfo->string,
447 (enables & binfo->bitmask) ? "enabled" : "disabled",
448 af);
449 }
450
451
452 /*
453 * Try to print SMART temperature field
454 */
455
456 void
457 device_smart_temp(struct ata_smart_attr *attr, uint64_t raw_value)
458 {
459 printf("%" PRIu8, attr->raw[0]);
460 if (attr->raw[0] != raw_value)
461 printf(" Lifetime max/min %" PRIu8 "/%" PRIu8,
462 attr->raw[2], attr->raw[4]);
463 }
464
465
466 /*
467 * Print out SMART attribute thresholds and values
468 */
469
470 void
471 print_smart_status(void *vbuf, void *tbuf)
472 {
473 struct ata_smart_attributes *value_buf = vbuf;
474 struct ata_smart_thresholds *threshold_buf = tbuf;
475 struct ata_smart_attr *attr;
476 uint64_t raw_value;
477 int flags;
478 int i, j;
479 int aid;
480 u_int8_t checksum;
481
482 for (i = checksum = 0; i < 512; i++)
483 checksum += ((u_int8_t *) value_buf)[i];
484 if (checksum != 0) {
485 fprintf(stderr, "SMART attribute values checksum error\n");
486 return;
487 }
488
489 for (i = checksum = 0; i < 512; i++)
490 checksum += ((u_int8_t *) threshold_buf)[i];
491 if (checksum != 0) {
492 fprintf(stderr, "SMART attribute thresholds checksum error\n");
493 return;
494 }
495
496 printf("id value thresh crit collect reliability description\t\t\traw\n");
497 for (i = 0; i < 256; i++) {
498 int thresh = 0;
499
500 attr = NULL;
501
502 for (j = 0; j < 30; j++) {
503 if (value_buf->attributes[j].id == i)
504 attr = &value_buf->attributes[j];
505 if (threshold_buf->thresholds[j].id == i)
506 thresh = threshold_buf->thresholds[j].value;
507 }
508
509 if (thresh && attr == NULL)
510 errx(1, "threshold but not attr %d", i);
511 if (attr == NULL)
512 continue;
513
514 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF)
515 continue;
516
517 for (aid = 0;
518 smart_attrs[aid].id != i && smart_attrs[aid].id != 0;
519 aid++)
520 ;
521
522 flags = le16toh(attr->flags);
523
524 printf("%3d %3d %3d %-3s %-7s %stive %-24s\t",
525 i, attr->value, thresh,
526 flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
527 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
528 attr->value > thresh ? "posi" : "nega",
529 smart_attrs[aid].name);
530
531 for (j = 0, raw_value = 0; j < 6; j++)
532 raw_value += ((uint64_t)attr->raw[j]) << (8*j);
533
534 if (smart_attrs[aid].special)
535 (*smart_attrs[aid].special)(attr, raw_value);
536 else
537 printf("%" PRIu64, raw_value);
538 printf("\n");
539 }
540 }
541
542 struct {
543 int number;
544 const char *name;
545 } selftest_name[] = {
546 { 0, "Off-line" },
547 { 1, "Short off-line" },
548 { 2, "Extended off-line" },
549 { 127, "Abort off-line test" },
550 { 129, "Short captive" },
551 { 130, "Extended captive" },
552 { 256, "Unknown test" }, /* larger then u_int8_t */
553 { 0, NULL }
554 };
555
556 const char *selftest_status[] = {
557 "No error",
558 "Aborted by the host",
559 "Interruped by the host by reset",
560 "Fatal error or unknown test error",
561 "Unknown test element failed",
562 "Electrical test element failed",
563 "The Servo (and/or seek) test element failed",
564 "Read element of test failed",
565 "Reserved",
566 "Reserved",
567 "Reserved",
568 "Reserved",
569 "Reserved",
570 "Reserved",
571 "Reserved",
572 "Self-test in progress"
573 };
574
575 void
576 print_error_entry(int num, struct ata_smart_error *le)
577 {
578 int i;
579
580 printf("Log entry: %d\n", num);
581
582 for (i = 0; i < 5; i++)
583 printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i,
584 le->command[i].device_control,
585 le->command[i].features,
586 le->command[i].sector_count,
587 le->command[i].sector_number,
588 le->command[i].cylinder_low,
589 le->command[i].cylinder_high,
590 le->command[i].device_head,
591 le->command[i].command,
592 le->command[i].timestamp[3],
593 le->command[i].timestamp[2],
594 le->command[i].timestamp[1],
595 le->command[i].timestamp[0]);
596 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x status=%02x state=%02x lifetime=%02x%02x\n",
597 le->error_data.error,
598 le->error_data.sector_count,
599 le->error_data.sector_number,
600 le->error_data.cylinder_low,
601 le->error_data.cylinder_high,
602 le->error_data.device_head,
603 le->error_data.status,
604 le->error_data.state,
605 le->error_data.lifetime[1],
606 le->error_data.lifetime[0]);
607 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
608 le->error_data.extended_error[0],
609 le->error_data.extended_error[1],
610 le->error_data.extended_error[2],
611 le->error_data.extended_error[3],
612 le->error_data.extended_error[4],
613 le->error_data.extended_error[5],
614 le->error_data.extended_error[6],
615 le->error_data.extended_error[7],
616 le->error_data.extended_error[8],
617 le->error_data.extended_error[9],
618 le->error_data.extended_error[10],
619 le->error_data.extended_error[11],
620 le->error_data.extended_error[12],
621 le->error_data.extended_error[13],
622 le->error_data.extended_error[14],
623 le->error_data.extended_error[15],
624 le->error_data.extended_error[15],
625 le->error_data.extended_error[17],
626 le->error_data.extended_error[18]);
627 }
628
629 void
630 print_error(void *buf)
631 {
632 struct ata_smart_errorlog *erlog = buf;
633 u_int8_t checksum;
634 int i;
635
636 for (i = checksum = 0; i < 512; i++)
637 checksum += ((u_int8_t *) buf)[i];
638 if (checksum != 0) {
639 fprintf(stderr, "SMART error log checksum error\n");
640 return;
641 }
642
643 if (erlog->data_structure_revision != 1) {
644 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n",
645 erlog->data_structure_revision);
646 return;
647 }
648
649 if (erlog->mostrecenterror == 0) {
650 printf("No errors have been logged\n");
651 return;
652 }
653
654 if (erlog->mostrecenterror > 5) {
655 fprintf(stderr, "Most recent error is too large\n");
656 return;
657 }
658
659 for (i = erlog->mostrecenterror; i < 5; i++)
660 print_error_entry(i, &erlog->log_entries[i]);
661 for (i = 0; i < erlog->mostrecenterror; i++)
662 print_error_entry(i, &erlog->log_entries[i]);
663 printf("device error count: %d\n", erlog->device_error_count);
664 }
665
666 void
667 print_selftest_entry(int num, struct ata_smart_selftest *le)
668 {
669 unsigned char *p;
670 int i;
671
672 /* check if all zero */
673 for (p = (void *)le, i = 0; i < sizeof(*le); i++)
674 if (p[i] != 0)
675 break;
676 if (i == sizeof(*le))
677 return;
678
679 printf("Log entry: %d\n", num);
680
681 /* Get test name */
682 for (i = 0; selftest_name[i].name != NULL; i++)
683 if (selftest_name[i].number == le->number)
684 break;
685
686 if (selftest_name[i].name == NULL)
687 printf("\tName: (%d)\n", le->number);
688 else
689 printf("\tName: %s\n", selftest_name[i].name);
690 printf("\tStatus: %s\n", selftest_status[le->status >> 4]);
691 /* XXX This generally should not be set when a self-test is completed,
692 and at any rate is useless. - mycroft */
693 if (le->status >> 4 == 15)
694 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf);
695 else if (le->status >> 4 != 0)
696 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error));
697 }
698
699 void
700 print_selftest(void *buf)
701 {
702 struct ata_smart_selftestlog *stlog = buf;
703 u_int8_t checksum;
704 int i;
705
706 for (i = checksum = 0; i < 512; i++)
707 checksum += ((u_int8_t *) buf)[i];
708 if (checksum != 0) {
709 fprintf(stderr, "SMART selftest log checksum error\n");
710 return;
711 }
712
713 if (le16toh(stlog->data_structure_revision) != 1) {
714 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n",
715 le16toh(stlog->data_structure_revision));
716 return;
717 }
718
719 if (stlog->mostrecenttest == 0) {
720 printf("No self-tests have been logged\n");
721 return;
722 }
723
724 if (stlog->mostrecenttest > 22) {
725 fprintf(stderr, "Most recent test is too large\n");
726 return;
727 }
728
729 for (i = stlog->mostrecenttest; i < 22; i++)
730 print_selftest_entry(i, &stlog->log_entries[i]);
731 for (i = 0; i < stlog->mostrecenttest; i++)
732 print_selftest_entry(i, &stlog->log_entries[i]);
733 }
734
735 struct ataparams *
736 getataparams()
737 {
738 struct atareq req;
739 static union {
740 unsigned char inbuf[DEV_BSIZE];
741 struct ataparams inqbuf;
742 } inbuf;
743
744 memset(&inbuf, 0, sizeof(inbuf));
745 memset(&req, 0, sizeof(req));
746
747 req.flags = ATACMD_READ;
748 req.command = WDCC_IDENTIFY;
749 req.databuf = (caddr_t)&inbuf;
750 req.datalen = sizeof(inbuf);
751 req.timeout = 1000;
752
753 ata_command(&req);
754
755 return (&inbuf.inqbuf);
756 }
757
758 /*
759 * is_smart:
760 *
761 * Detect whether device supports SMART and SMART is enabled.
762 */
763
764 int
765 is_smart(void)
766 {
767 int retval = 0;
768 struct ataparams *inqbuf;
769 const char *status;
770
771 inqbuf = getataparams();
772
773 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
774 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
775 fprintf(stderr, "SMART unsupported\n");
776 } else {
777 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
778 inqbuf->atap_cmd_set2 == 0xffff ||
779 inqbuf->atap_cmd_set2 == 0x0000) {
780 status = "status unknown";
781 retval = 2;
782 } else {
783 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) {
784 status = "enabled";
785 retval = 1;
786 } else {
787 status = "disabled";
788 }
789 }
790 printf("SMART supported, SMART %s\n", status);
791 }
792 }
793 return retval;
794 }
795
796 /*
797 * DEVICE COMMANDS
798 */
799
800 /*
801 * device_identify:
802 *
803 * Display the identity of the device
804 */
805 void
806 device_identify(int argc, char *argv[])
807 {
808 struct ataparams *inqbuf;
809 #if BYTE_ORDER == LITTLE_ENDIAN
810 int i;
811 u_int16_t *p;
812 #endif
813
814 /* No arguments. */
815 if (argc != 0)
816 usage();
817
818 inqbuf = getataparams();
819
820 #if BYTE_ORDER == LITTLE_ENDIAN
821 /*
822 * On little endian machines, we need to shuffle the string
823 * byte order. However, we don't have to do this for NEC or
824 * Mitsumi ATAPI devices
825 */
826
827 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
828 ((inqbuf->atap_model[0] == 'N' &&
829 inqbuf->atap_model[1] == 'E') ||
830 (inqbuf->atap_model[0] == 'F' &&
831 inqbuf->atap_model[1] == 'X')))) {
832 for (i = 0 ; i < sizeof(inqbuf->atap_model); i += 2) {
833 p = (u_short *) (inqbuf->atap_model + i);
834 *p = ntohs(*p);
835 }
836 for (i = 0 ; i < sizeof(inqbuf->atap_serial); i += 2) {
837 p = (u_short *) (inqbuf->atap_serial + i);
838 *p = ntohs(*p);
839 }
840 for (i = 0 ; i < sizeof(inqbuf->atap_revision); i += 2) {
841 p = (u_short *) (inqbuf->atap_revision + i);
842 *p = ntohs(*p);
843 }
844 }
845 #endif
846
847 /*
848 * Strip blanks off of the info strings. Yuck, I wish this was
849 * cleaner.
850 */
851
852 if (inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] == ' ') {
853 inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] = '\0';
854 while (inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] == ' ')
855 inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] = '\0';
856 }
857
858 if (inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] == ' ') {
859 inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] = '\0';
860 while (inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] == ' ')
861 inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] = '\0';
862 }
863
864 if (inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] == ' ') {
865 inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] = '\0';
866 while (inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] == ' ')
867 inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] = '\0';
868 }
869
870 printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n",
871 (int) sizeof(inqbuf->atap_model), inqbuf->atap_model,
872 (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision,
873 (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial);
874
875 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
876 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
877 "removable");
878
879 if ((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == 0)
880 printf("Cylinders: %d, heads: %d, sec/track: %d, total "
881 "sectors: %d\n", inqbuf->atap_cylinders,
882 inqbuf->atap_heads, inqbuf->atap_sectors,
883 (inqbuf->atap_capacity[1] << 16) |
884 inqbuf->atap_capacity[0]);
885
886 if (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK)
887 printf("Device supports command queue depth of %d\n",
888 inqbuf->atap_queuedepth & 0xf);
889
890 printf("Device capabilities:\n");
891 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
892
893 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
894 printf("Device supports following standards:\n");
895 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
896 printf("\n");
897 }
898
899 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
900 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
901 printf("Command set support:\n");
902 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
903 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
904 inqbuf->atap_cmd1_en, ata_cmd_set1);
905 else
906 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
907 ata_cmd_set1);
908 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
909 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
910 inqbuf->atap_cmd2_en, ata_cmd_set2);
911 else
912 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
913 ata_cmd_set2);
914 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
915 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
916 ata_cmd_ext);
917 }
918
919 return;
920 }
921
922 /*
923 * device idle:
924 *
925 * issue the IDLE IMMEDIATE command to the drive
926 */
927
928 void
929 device_idle(int argc, char *argv[])
930 {
931 struct atareq req;
932
933 /* No arguments. */
934 if (argc != 0)
935 usage();
936
937 memset(&req, 0, sizeof(req));
938
939 if (strcmp(cmdname, "idle") == 0)
940 req.command = WDCC_IDLE_IMMED;
941 else if (strcmp(cmdname, "standby") == 0)
942 req.command = WDCC_STANDBY_IMMED;
943 else
944 req.command = WDCC_SLEEP;
945
946 req.timeout = 1000;
947
948 ata_command(&req);
949
950 return;
951 }
952
953 /*
954 * Set the idle timer on the disk. Set it for either idle mode or
955 * standby mode, depending on how we were invoked.
956 */
957
958 void
959 device_setidle(int argc, char *argv[])
960 {
961 unsigned long idle;
962 struct atareq req;
963 char *end;
964
965 /* Only one argument */
966 if (argc != 1)
967 usage();
968
969 idle = strtoul(argv[0], &end, 0);
970
971 if (*end != '\0') {
972 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
973 exit(1);
974 }
975
976 if (idle > 19800) {
977 fprintf(stderr, "Idle time has a maximum value of 5.5 "
978 "hours\n");
979 exit(1);
980 }
981
982 if (idle != 0 && idle < 5) {
983 fprintf(stderr, "Idle timer must be at least 5 seconds\n");
984 exit(1);
985 }
986
987 memset(&req, 0, sizeof(req));
988
989 if (idle <= 240*5)
990 req.sec_count = idle / 5;
991 else
992 req.sec_count = idle / (30*60) + 240;
993
994 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
995 req.timeout = 1000;
996
997 ata_command(&req);
998
999 return;
1000 }
1001
1002 /*
1003 * Query the device for the current power mode
1004 */
1005
1006 void
1007 device_checkpower(int argc, char *argv[])
1008 {
1009 struct atareq req;
1010
1011 /* No arguments. */
1012 if (argc != 0)
1013 usage();
1014
1015 memset(&req, 0, sizeof(req));
1016
1017 req.command = WDCC_CHECK_PWR;
1018 req.timeout = 1000;
1019 req.flags = ATACMD_READREG;
1020
1021 ata_command(&req);
1022
1023 printf("Current power status: ");
1024
1025 switch (req.sec_count) {
1026 case 0x00:
1027 printf("Standby mode\n");
1028 break;
1029 case 0x80:
1030 printf("Idle mode\n");
1031 break;
1032 case 0xff:
1033 printf("Active mode\n");
1034 break;
1035 default:
1036 printf("Unknown power code (%02x)\n", req.sec_count);
1037 }
1038
1039 return;
1040 }
1041
1042 /*
1043 * device_smart:
1044 *
1045 * Display SMART status
1046 */
1047 void
1048 device_smart(int argc, char *argv[])
1049 {
1050 struct atareq req;
1051 unsigned char inbuf[DEV_BSIZE];
1052 unsigned char inbuf2[DEV_BSIZE];
1053
1054 if (argc < 1)
1055 usage();
1056
1057 if (strcmp(argv[0], "enable") == 0) {
1058 memset(&req, 0, sizeof(req));
1059
1060 req.features = WDSM_ENABLE_OPS;
1061 req.command = WDCC_SMART;
1062 req.cylinder = WDSMART_CYL;
1063 req.timeout = 1000;
1064
1065 ata_command(&req);
1066
1067 is_smart();
1068 } else if (strcmp(argv[0], "disable") == 0) {
1069 memset(&req, 0, sizeof(req));
1070
1071 req.features = WDSM_DISABLE_OPS;
1072 req.command = WDCC_SMART;
1073 req.cylinder = WDSMART_CYL;
1074 req.timeout = 1000;
1075
1076 ata_command(&req);
1077
1078 is_smart();
1079 } else if (strcmp(argv[0], "status") == 0) {
1080 if (!is_smart()) {
1081 fprintf(stderr, "SMART not supported\n");
1082 return;
1083 }
1084
1085 memset(&inbuf, 0, sizeof(inbuf));
1086 memset(&req, 0, sizeof(req));
1087
1088 req.features = WDSM_STATUS;
1089 req.command = WDCC_SMART;
1090 req.cylinder = WDSMART_CYL;
1091 req.timeout = 1000;
1092
1093 ata_command(&req);
1094
1095 if (req.cylinder != WDSMART_CYL) {
1096 fprintf(stderr, "Threshold exceeds condition\n");
1097 }
1098
1099 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
1100 * features, the following ata_command()'s may error
1101 * and exit().
1102 */
1103
1104 memset(&inbuf, 0, sizeof(inbuf));
1105 memset(&req, 0, sizeof(req));
1106
1107 req.flags = ATACMD_READ;
1108 req.features = WDSM_RD_DATA;
1109 req.command = WDCC_SMART;
1110 req.databuf = (caddr_t) inbuf;
1111 req.datalen = sizeof(inbuf);
1112 req.cylinder = WDSMART_CYL;
1113 req.timeout = 1000;
1114
1115 ata_command(&req);
1116
1117 memset(&inbuf2, 0, sizeof(inbuf2));
1118 memset(&req, 0, sizeof(req));
1119
1120 req.flags = ATACMD_READ;
1121 req.features = WDSM_RD_THRESHOLDS;
1122 req.command = WDCC_SMART;
1123 req.databuf = (caddr_t) inbuf2;
1124 req.datalen = sizeof(inbuf2);
1125 req.cylinder = WDSMART_CYL;
1126 req.timeout = 1000;
1127
1128 ata_command(&req);
1129
1130 print_smart_status(inbuf, inbuf2);
1131
1132 } else if (strcmp(argv[0], "offline") == 0) {
1133 if (argc != 2)
1134 usage();
1135 if (!is_smart()) {
1136 fprintf(stderr, "SMART not supported\n");
1137 return;
1138 }
1139
1140 memset(&req, 0, sizeof(req));
1141
1142 req.features = WDSM_EXEC_OFFL_IMM;
1143 req.command = WDCC_SMART;
1144 req.cylinder = WDSMART_CYL;
1145 req.sec_num = atol(argv[1]);
1146 req.timeout = 10000;
1147
1148 ata_command(&req);
1149 } else if (strcmp(argv[0], "error-log") == 0) {
1150 if (!is_smart()) {
1151 fprintf(stderr, "SMART not supported\n");
1152 return;
1153 }
1154
1155 memset(&inbuf, 0, sizeof(inbuf));
1156 memset(&req, 0, sizeof(req));
1157
1158 req.flags = ATACMD_READ;
1159 req.features = WDSM_RD_LOG;
1160 req.sec_count = 1;
1161 req.sec_num = 1;
1162 req.command = WDCC_SMART;
1163 req.databuf = (caddr_t) inbuf;
1164 req.datalen = sizeof(inbuf);
1165 req.cylinder = WDSMART_CYL;
1166 req.timeout = 1000;
1167
1168 ata_command(&req);
1169
1170 print_error(inbuf);
1171 } else if (strcmp(argv[0], "selftest-log") == 0) {
1172 if (!is_smart()) {
1173 fprintf(stderr, "SMART not supported\n");
1174 return;
1175 }
1176
1177 memset(&inbuf, 0, sizeof(inbuf));
1178 memset(&req, 0, sizeof(req));
1179
1180 req.flags = ATACMD_READ;
1181 req.features = WDSM_RD_LOG;
1182 req.sec_count = 1;
1183 req.sec_num = 6;
1184 req.command = WDCC_SMART;
1185 req.databuf = (caddr_t) inbuf;
1186 req.datalen = sizeof(inbuf);
1187 req.cylinder = WDSMART_CYL;
1188 req.timeout = 1000;
1189
1190 ata_command(&req);
1191
1192 print_selftest(inbuf);
1193
1194 } else {
1195 usage();
1196 }
1197 return;
1198 }
1199
1200 void
1201 device_security(int argc, char *argv[])
1202 {
1203 struct atareq req;
1204 struct ataparams *inqbuf;
1205
1206 /* need subcommand */
1207 if (argc < 1)
1208 usage();
1209
1210 if (strcmp(argv[0], "freeze") == 0) {
1211 memset(&req, 0, sizeof(req));
1212 req.command = WCDD_SECURITY_FREEZE;
1213 req.timeout = 1000;
1214 ata_command(&req);
1215 } else if (strcmp(argv[0], "status") == 0) {
1216 inqbuf = getataparams();
1217 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
1218 } else
1219 usage();
1220
1221 return;
1222 }
1223
1224 /*
1225 * bus_reset:
1226 * Reset an ATA bus (will reset all devices on the bus)
1227 */
1228 void
1229 bus_reset(int argc, char *argv[])
1230 {
1231 int error;
1232
1233 /* no args */
1234 if (argc != 0)
1235 usage();
1236
1237 error = ioctl(fd, ATABUSIORESET, NULL);
1238
1239 if (error == -1)
1240 err(1, "ATABUSIORESET failed");
1241 }
1242