atactl.c revision 1.47 1 /* $NetBSD: atactl.c,v 1.47 2007/11/04 02:34:27 xtraeme 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.47 2007/11/04 02:34:27 xtraeme 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 struct bitinfo ata_sata_caps[] = {
239 { SATA_SIGNAL_GEN1, "1.5Gb/s signaling" },
240 { SATA_SIGNAL_GEN2, "3.0Gb/s signaling" },
241 { SATA_NATIVE_CMDQ, "Native Command Queuing" },
242 { SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" },
243 { SATA_PHY_EVNT_CNT, "PHY Event Counters" },
244 { 0, NULL },
245 };
246
247 struct bitinfo ata_sata_feat[] = {
248 { SATA_NONZERO_OFFSETS, "Non-zero Offset DMA" },
249 { SATA_DMA_SETUP_AUTO, "DMA Setup Auto Activate" },
250 { SATA_DRIVE_PWR_MGMT, "Device-Initiated Interface Power Managment" },
251 { SATA_IN_ORDER_DATA, "In-order Data Delivery" },
252 { SATA_SW_STTNGS_PRS, "Software Settings Preservation" },
253 { 0, NULL },
254 };
255
256 static const struct {
257 const int id;
258 const char *name;
259 void (*special)(struct ata_smart_attr *, uint64_t);
260 } smart_attrs[] = {
261 { 1, "Raw read error rate", NULL },
262 { 2, "Throughput performance", NULL },
263 { 3, "Spin-up time", NULL },
264 { 4, "Start/stop count", NULL },
265 { 5, "Reallocated sector count", NULL },
266 { 6, "Read channel margin", NULL },
267 { 7, "Seek error rate", NULL },
268 { 8, "Seek time performance", NULL },
269 { 9, "Power-on hours count", NULL },
270 { 10, "Spin retry count", NULL },
271 { 11, "Calibration retry count", NULL },
272 { 12, "Device power cycle count", NULL },
273 { 191, "Gsense error rate", NULL },
274 { 192, "Power-off retract count", NULL },
275 { 193, "Load cycle count", NULL },
276 { 194, "Temperature", device_smart_temp},
277 { 195, "Hardware ECC Recovered", NULL },
278 { 196, "Reallocated event count", NULL },
279 { 197, "Current pending sector", NULL },
280 { 198, "Offline uncorrectable", NULL },
281 { 199, "Ultra DMA CRC error count", NULL },
282 { 200, "Write error rate", NULL },
283 { 201, "Soft read error rate", NULL },
284 { 202, "Data address mark errors", NULL },
285 { 203, "Run out cancel", NULL },
286 { 204, "Soft ECC correction", NULL },
287 { 205, "Thermal asperity check", NULL },
288 { 206, "Flying height", NULL },
289 { 207, "Spin high current", NULL },
290 { 208, "Spin buzz", NULL },
291 { 209, "Offline seek performance", NULL },
292 { 220, "Disk shift", NULL },
293 { 221, "G-Sense error rate", NULL },
294 { 222, "Loaded hours", NULL },
295 { 223, "Load/unload retry count", NULL },
296 { 224, "Load friction", NULL },
297 { 225, "Load/unload cycle count", NULL },
298 { 226, "Load-in time", NULL },
299 { 227, "Torque amplification count", NULL },
300 { 228, "Power-off retract count", NULL },
301 { 230, "GMR head amplitude", NULL },
302 { 231, "Temperature", device_smart_temp },
303 { 240, "Head flying hours", NULL },
304 { 250, "Read error retry rate", NULL },
305 { 0, "Unknown", NULL },
306 };
307
308 struct bitinfo ata_sec_st[] = {
309 { WDC_SEC_SUPP, "supported" },
310 { WDC_SEC_EN, "enabled" },
311 { WDC_SEC_LOCKED, "locked" },
312 { WDC_SEC_FROZEN, "frozen" },
313 { WDC_SEC_EXP, "expired" },
314 { WDC_SEC_ESE_SUPP, "enhanced erase support" },
315 { WDC_SEC_LEV_MAX, "maximum level" },
316 { 0, NULL },
317 };
318
319 int
320 main(int argc, char *argv[])
321 {
322 int i;
323 struct command *commands = NULL;
324
325 /* Must have at least: device command */
326 if (argc < 3)
327 usage();
328
329 /* Skip program name, get and skip device name and command. */
330 dvname = argv[1];
331 cmdname = argv[2];
332 argv += 3;
333 argc -= 3;
334
335 /*
336 * Open the device
337 */
338 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0);
339 if (fd == -1) {
340 if (errno == ENOENT) {
341 /*
342 * Device doesn't exist. Probably trying to open
343 * a device which doesn't use disk semantics for
344 * device name. Try again, specifying "cooked",
345 * which leaves off the "r" in front of the device's
346 * name.
347 */
348 fd = opendisk(dvname, O_RDWR, dvname_store,
349 sizeof(dvname_store), 1);
350 if (fd == -1)
351 err(1, "%s", dvname);
352 } else
353 err(1, "%s", dvname);
354 }
355
356 /*
357 * Point the dvname at the actual device name that opendisk() opened.
358 */
359 dvname = dvname_store;
360
361 /* Look up and call the command. */
362 for (i = 0; device_commands[i].cmd_name != NULL; i++) {
363 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
364 commands = &device_commands[i];
365 break;
366 }
367 }
368 if (commands == NULL) {
369 for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
370 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
371 commands = &bus_commands[i];
372 break;
373 }
374 }
375 }
376 if (commands == NULL)
377 errx(1, "unknown command: %s", cmdname);
378
379 argnames = commands->arg_names;
380
381 (*commands->cmd_func)(argc, argv);
382 exit(0);
383 }
384
385 void
386 usage(void)
387 {
388 int i;
389
390 fprintf(stderr, "usage: %s device command [arg [...]]\n",
391 getprogname());
392
393 fprintf(stderr, " Available device commands:\n");
394 for (i=0; device_commands[i].cmd_name != NULL; i++)
395 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
396 device_commands[i].arg_names);
397
398 fprintf(stderr, " Available bus commands:\n");
399 for (i=0; bus_commands[i].cmd_name != NULL; i++)
400 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
401 bus_commands[i].arg_names);
402
403 exit(1);
404 }
405
406 /*
407 * Wrapper that calls ATAIOCCOMMAND and checks for errors
408 */
409
410 void
411 ata_command(struct atareq *req)
412 {
413 int error;
414
415 error = ioctl(fd, ATAIOCCOMMAND, req);
416
417 if (error == -1)
418 err(1, "ATAIOCCOMMAND failed");
419
420 switch (req->retsts) {
421
422 case ATACMD_OK:
423 return;
424 case ATACMD_TIMEOUT:
425 fprintf(stderr, "ATA command timed out\n");
426 exit(1);
427 case ATACMD_DF:
428 fprintf(stderr, "ATA device returned a Device Fault\n");
429 exit(1);
430 case ATACMD_ERROR:
431 if (req->error & WDCE_ABRT)
432 fprintf(stderr, "ATA device returned Aborted "
433 "Command\n");
434 else
435 fprintf(stderr, "ATA device returned error register "
436 "%0x\n", req->error);
437 exit(1);
438 default:
439 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code "
440 "%d\n", req->retsts);
441 exit(1);
442 }
443 }
444
445 /*
446 * Print out strings associated with particular bitmasks
447 */
448
449 void
450 print_bitinfo(const char *bf, const char *af, u_int bits, struct bitinfo *binfo)
451 {
452
453 for (; binfo->bitmask != 0; binfo++)
454 if (bits & binfo->bitmask)
455 printf("%s%s%s", bf, binfo->string, af);
456 }
457
458 void
459 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables, struct bitinfo *binfo)
460 {
461
462 for (; binfo->bitmask != 0; binfo++)
463 if (bits & binfo->bitmask)
464 printf("%s%s (%s)%s", bf, binfo->string,
465 (enables & binfo->bitmask) ? "enabled" : "disabled",
466 af);
467 }
468
469
470 /*
471 * Try to print SMART temperature field
472 */
473
474 void
475 device_smart_temp(struct ata_smart_attr *attr, uint64_t raw_value)
476 {
477 printf("%" PRIu8, attr->raw[0]);
478 if (attr->raw[0] != raw_value)
479 printf(" Lifetime max/min %" PRIu8 "/%" PRIu8,
480 attr->raw[2], attr->raw[4]);
481 }
482
483
484 /*
485 * Print out SMART attribute thresholds and values
486 */
487
488 void
489 print_smart_status(void *vbuf, void *tbuf)
490 {
491 struct ata_smart_attributes *value_buf = vbuf;
492 struct ata_smart_thresholds *threshold_buf = tbuf;
493 struct ata_smart_attr *attr;
494 uint64_t raw_value;
495 int flags;
496 int i, j;
497 int aid;
498 u_int8_t checksum;
499
500 for (i = checksum = 0; i < 512; i++)
501 checksum += ((u_int8_t *) value_buf)[i];
502 if (checksum != 0) {
503 fprintf(stderr, "SMART attribute values checksum error\n");
504 return;
505 }
506
507 for (i = checksum = 0; i < 512; i++)
508 checksum += ((u_int8_t *) threshold_buf)[i];
509 if (checksum != 0) {
510 fprintf(stderr, "SMART attribute thresholds checksum error\n");
511 return;
512 }
513
514 printf("id value thresh crit collect reliability description\t\t\traw\n");
515 for (i = 0; i < 256; i++) {
516 int thresh = 0;
517
518 attr = NULL;
519
520 for (j = 0; j < 30; j++) {
521 if (value_buf->attributes[j].id == i)
522 attr = &value_buf->attributes[j];
523 if (threshold_buf->thresholds[j].id == i)
524 thresh = threshold_buf->thresholds[j].value;
525 }
526
527 if (thresh && attr == NULL)
528 errx(1, "threshold but not attr %d", i);
529 if (attr == NULL)
530 continue;
531
532 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF)
533 continue;
534
535 for (aid = 0;
536 smart_attrs[aid].id != i && smart_attrs[aid].id != 0;
537 aid++)
538 ;
539
540 flags = le16toh(attr->flags);
541
542 printf("%3d %3d %3d %-3s %-7s %stive %-24s\t",
543 i, attr->value, thresh,
544 flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
545 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
546 attr->value > thresh ? "posi" : "nega",
547 smart_attrs[aid].name);
548
549 for (j = 0, raw_value = 0; j < 6; j++)
550 raw_value += ((uint64_t)attr->raw[j]) << (8*j);
551
552 if (smart_attrs[aid].special)
553 (*smart_attrs[aid].special)(attr, raw_value);
554 else
555 printf("%" PRIu64, raw_value);
556 printf("\n");
557 }
558 }
559
560 struct {
561 int number;
562 const char *name;
563 } selftest_name[] = {
564 { 0, "Off-line" },
565 { 1, "Short off-line" },
566 { 2, "Extended off-line" },
567 { 127, "Abort off-line test" },
568 { 129, "Short captive" },
569 { 130, "Extended captive" },
570 { 256, "Unknown test" }, /* larger then u_int8_t */
571 { 0, NULL }
572 };
573
574 const char *selftest_status[] = {
575 "No error",
576 "Aborted by the host",
577 "Interrupted by the host by reset",
578 "Fatal error or unknown test error",
579 "Unknown test element failed",
580 "Electrical test element failed",
581 "The Servo (and/or seek) test element failed",
582 "Read element of test failed",
583 "Reserved",
584 "Reserved",
585 "Reserved",
586 "Reserved",
587 "Reserved",
588 "Reserved",
589 "Reserved",
590 "Self-test in progress"
591 };
592
593 void
594 print_error_entry(int num, struct ata_smart_error *le)
595 {
596 int i;
597
598 printf("Log entry: %d\n", num);
599
600 for (i = 0; i < 5; i++)
601 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,
602 le->command[i].device_control,
603 le->command[i].features,
604 le->command[i].sector_count,
605 le->command[i].sector_number,
606 le->command[i].cylinder_low,
607 le->command[i].cylinder_high,
608 le->command[i].device_head,
609 le->command[i].command,
610 le->command[i].timestamp[3],
611 le->command[i].timestamp[2],
612 le->command[i].timestamp[1],
613 le->command[i].timestamp[0]);
614 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x status=%02x state=%02x lifetime=%02x%02x\n",
615 le->error_data.error,
616 le->error_data.sector_count,
617 le->error_data.sector_number,
618 le->error_data.cylinder_low,
619 le->error_data.cylinder_high,
620 le->error_data.device_head,
621 le->error_data.status,
622 le->error_data.state,
623 le->error_data.lifetime[1],
624 le->error_data.lifetime[0]);
625 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
626 le->error_data.extended_error[0],
627 le->error_data.extended_error[1],
628 le->error_data.extended_error[2],
629 le->error_data.extended_error[3],
630 le->error_data.extended_error[4],
631 le->error_data.extended_error[5],
632 le->error_data.extended_error[6],
633 le->error_data.extended_error[7],
634 le->error_data.extended_error[8],
635 le->error_data.extended_error[9],
636 le->error_data.extended_error[10],
637 le->error_data.extended_error[11],
638 le->error_data.extended_error[12],
639 le->error_data.extended_error[13],
640 le->error_data.extended_error[14],
641 le->error_data.extended_error[15],
642 le->error_data.extended_error[15],
643 le->error_data.extended_error[17],
644 le->error_data.extended_error[18]);
645 }
646
647 void
648 print_error(void *buf)
649 {
650 struct ata_smart_errorlog *erlog = buf;
651 u_int8_t checksum;
652 int i;
653
654 for (i = checksum = 0; i < 512; i++)
655 checksum += ((u_int8_t *) buf)[i];
656 if (checksum != 0) {
657 fprintf(stderr, "SMART error log checksum error\n");
658 return;
659 }
660
661 if (erlog->data_structure_revision != 1) {
662 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n",
663 erlog->data_structure_revision);
664 return;
665 }
666
667 if (erlog->mostrecenterror == 0) {
668 printf("No errors have been logged\n");
669 return;
670 }
671
672 if (erlog->mostrecenterror > 5) {
673 fprintf(stderr, "Most recent error is too large\n");
674 return;
675 }
676
677 for (i = erlog->mostrecenterror; i < 5; i++)
678 print_error_entry(i, &erlog->log_entries[i]);
679 for (i = 0; i < erlog->mostrecenterror; i++)
680 print_error_entry(i, &erlog->log_entries[i]);
681 printf("device error count: %d\n", erlog->device_error_count);
682 }
683
684 void
685 print_selftest_entry(int num, struct ata_smart_selftest *le)
686 {
687 unsigned char *p;
688 int i;
689
690 /* check if all zero */
691 for (p = (void *)le, i = 0; i < sizeof(*le); i++)
692 if (p[i] != 0)
693 break;
694 if (i == sizeof(*le))
695 return;
696
697 printf("Log entry: %d\n", num);
698
699 /* Get test name */
700 for (i = 0; selftest_name[i].name != NULL; i++)
701 if (selftest_name[i].number == le->number)
702 break;
703
704 if (selftest_name[i].name == NULL)
705 printf("\tName: (%d)\n", le->number);
706 else
707 printf("\tName: %s\n", selftest_name[i].name);
708 printf("\tStatus: %s\n", selftest_status[le->status >> 4]);
709 /* XXX This generally should not be set when a self-test is completed,
710 and at any rate is useless. - mycroft */
711 if (le->status >> 4 == 15)
712 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf);
713 else if (le->status >> 4 != 0)
714 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error));
715 }
716
717 void
718 print_selftest(void *buf)
719 {
720 struct ata_smart_selftestlog *stlog = buf;
721 u_int8_t checksum;
722 int i;
723
724 for (i = checksum = 0; i < 512; i++)
725 checksum += ((u_int8_t *) buf)[i];
726 if (checksum != 0) {
727 fprintf(stderr, "SMART selftest log checksum error\n");
728 return;
729 }
730
731 if (le16toh(stlog->data_structure_revision) != 1) {
732 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n",
733 le16toh(stlog->data_structure_revision));
734 return;
735 }
736
737 if (stlog->mostrecenttest == 0) {
738 printf("No self-tests have been logged\n");
739 return;
740 }
741
742 if (stlog->mostrecenttest > 22) {
743 fprintf(stderr, "Most recent test is too large\n");
744 return;
745 }
746
747 for (i = stlog->mostrecenttest; i < 22; i++)
748 print_selftest_entry(i, &stlog->log_entries[i]);
749 for (i = 0; i < stlog->mostrecenttest; i++)
750 print_selftest_entry(i, &stlog->log_entries[i]);
751 }
752
753 struct ataparams *
754 getataparams()
755 {
756 struct atareq req;
757 static union {
758 unsigned char inbuf[DEV_BSIZE];
759 struct ataparams inqbuf;
760 } inbuf;
761
762 memset(&inbuf, 0, sizeof(inbuf));
763 memset(&req, 0, sizeof(req));
764
765 req.flags = ATACMD_READ;
766 req.command = WDCC_IDENTIFY;
767 req.databuf = (caddr_t)&inbuf;
768 req.datalen = sizeof(inbuf);
769 req.timeout = 1000;
770
771 ata_command(&req);
772
773 return (&inbuf.inqbuf);
774 }
775
776 /*
777 * is_smart:
778 *
779 * Detect whether device supports SMART and SMART is enabled.
780 */
781
782 int
783 is_smart(void)
784 {
785 int retval = 0;
786 struct ataparams *inqbuf;
787 const char *status;
788
789 inqbuf = getataparams();
790
791 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
792 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
793 fprintf(stderr, "SMART unsupported\n");
794 } else {
795 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
796 inqbuf->atap_cmd_set2 == 0xffff ||
797 inqbuf->atap_cmd_set2 == 0x0000) {
798 status = "status unknown";
799 retval = 2;
800 } else {
801 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) {
802 status = "enabled";
803 retval = 1;
804 } else {
805 status = "disabled";
806 retval = 3;
807 }
808 }
809 printf("SMART supported, SMART %s\n", status);
810 }
811 }
812 return retval;
813 }
814
815 /*
816 * DEVICE COMMANDS
817 */
818
819 /*
820 * device_identify:
821 *
822 * Display the identity of the device
823 */
824 void
825 device_identify(int argc, char *argv[])
826 {
827 struct ataparams *inqbuf;
828 #if BYTE_ORDER == LITTLE_ENDIAN
829 int i;
830 u_int16_t *p;
831 #endif
832
833 /* No arguments. */
834 if (argc != 0)
835 usage();
836
837 inqbuf = getataparams();
838
839 #if BYTE_ORDER == LITTLE_ENDIAN
840 /*
841 * On little endian machines, we need to shuffle the string
842 * byte order. However, we don't have to do this for NEC or
843 * Mitsumi ATAPI devices
844 */
845
846 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
847 ((inqbuf->atap_model[0] == 'N' &&
848 inqbuf->atap_model[1] == 'E') ||
849 (inqbuf->atap_model[0] == 'F' &&
850 inqbuf->atap_model[1] == 'X')))) {
851 for (i = 0 ; i < sizeof(inqbuf->atap_model); i += 2) {
852 p = (u_short *) (inqbuf->atap_model + i);
853 *p = ntohs(*p);
854 }
855 for (i = 0 ; i < sizeof(inqbuf->atap_serial); i += 2) {
856 p = (u_short *) (inqbuf->atap_serial + i);
857 *p = ntohs(*p);
858 }
859 for (i = 0 ; i < sizeof(inqbuf->atap_revision); i += 2) {
860 p = (u_short *) (inqbuf->atap_revision + i);
861 *p = ntohs(*p);
862 }
863 }
864 #endif
865
866 /*
867 * Strip blanks off of the info strings. Yuck, I wish this was
868 * cleaner.
869 */
870
871 if (inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] == ' ') {
872 inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1] = '\0';
873 while (inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] == ' ')
874 inqbuf->atap_model[strlen(inqbuf->atap_model) - 1] = '\0';
875 }
876
877 if (inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] == ' ') {
878 inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1] = '\0';
879 while (inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] == ' ')
880 inqbuf->atap_revision[strlen(inqbuf->atap_revision) - 1] = '\0';
881 }
882
883 if (inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] == ' ') {
884 inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1] = '\0';
885 while (inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] == ' ')
886 inqbuf->atap_serial[strlen(inqbuf->atap_serial) - 1] = '\0';
887 }
888
889 printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n",
890 (int) sizeof(inqbuf->atap_model), inqbuf->atap_model,
891 (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision,
892 (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial);
893
894 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
895 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
896 "removable");
897
898 if ((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == 0)
899 printf("Cylinders: %d, heads: %d, sec/track: %d, total "
900 "sectors: %d\n", inqbuf->atap_cylinders,
901 inqbuf->atap_heads, inqbuf->atap_sectors,
902 (inqbuf->atap_capacity[1] << 16) |
903 inqbuf->atap_capacity[0]);
904
905 if (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK)
906 printf("Device supports command queue depth of %d\n",
907 inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK);
908
909 printf("Device capabilities:\n");
910 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
911
912 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
913 printf("Device supports following standards:\n");
914 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
915 printf("\n");
916 }
917
918 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
919 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
920 printf("Command set support:\n");
921 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
922 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
923 inqbuf->atap_cmd1_en, ata_cmd_set1);
924 else
925 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
926 ata_cmd_set1);
927 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
928 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
929 inqbuf->atap_cmd2_en, ata_cmd_set2);
930 else
931 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
932 ata_cmd_set2);
933 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
934 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
935 ata_cmd_ext);
936 }
937
938 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) {
939 printf("Serial ATA capabilities:\n");
940 print_bitinfo("\t", "\n", inqbuf->atap_sata_caps, ata_sata_caps);
941 }
942
943 if (inqbuf->atap_sata_features_supp != 0 && inqbuf->atap_sata_features_supp != 0xffff) {
944 printf("Serial ATA features:\n");
945 if (inqbuf->atap_sata_features_en != 0 && inqbuf->atap_sata_features_en != 0xffff)
946 print_bitinfo2("\t", "\n", inqbuf->atap_sata_features_supp, inqbuf->atap_sata_features_en, ata_sata_feat);
947 else
948 print_bitinfo("\t", "\n", inqbuf->atap_sata_features_supp, ata_sata_feat);
949 }
950
951 return;
952 }
953
954 /*
955 * device idle:
956 *
957 * issue the IDLE IMMEDIATE command to the drive
958 */
959
960 void
961 device_idle(int argc, char *argv[])
962 {
963 struct atareq req;
964
965 /* No arguments. */
966 if (argc != 0)
967 usage();
968
969 memset(&req, 0, sizeof(req));
970
971 if (strcmp(cmdname, "idle") == 0)
972 req.command = WDCC_IDLE_IMMED;
973 else if (strcmp(cmdname, "standby") == 0)
974 req.command = WDCC_STANDBY_IMMED;
975 else
976 req.command = WDCC_SLEEP;
977
978 req.timeout = 1000;
979
980 ata_command(&req);
981
982 return;
983 }
984
985 /*
986 * Set the idle timer on the disk. Set it for either idle mode or
987 * standby mode, depending on how we were invoked.
988 */
989
990 void
991 device_setidle(int argc, char *argv[])
992 {
993 unsigned long idle;
994 struct atareq req;
995 char *end;
996
997 /* Only one argument */
998 if (argc != 1)
999 usage();
1000
1001 idle = strtoul(argv[0], &end, 0);
1002
1003 if (*end != '\0') {
1004 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
1005 exit(1);
1006 }
1007
1008 if (idle > 19800) {
1009 fprintf(stderr, "Idle time has a maximum value of 5.5 "
1010 "hours\n");
1011 exit(1);
1012 }
1013
1014 if (idle != 0 && idle < 5) {
1015 fprintf(stderr, "Idle timer must be at least 5 seconds\n");
1016 exit(1);
1017 }
1018
1019 memset(&req, 0, sizeof(req));
1020
1021 if (idle <= 240*5)
1022 req.sec_count = idle / 5;
1023 else
1024 req.sec_count = idle / (30*60) + 240;
1025
1026 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
1027 req.timeout = 1000;
1028
1029 ata_command(&req);
1030
1031 return;
1032 }
1033
1034 /*
1035 * Query the device for the current power mode
1036 */
1037
1038 void
1039 device_checkpower(int argc, char *argv[])
1040 {
1041 struct atareq req;
1042
1043 /* No arguments. */
1044 if (argc != 0)
1045 usage();
1046
1047 memset(&req, 0, sizeof(req));
1048
1049 req.command = WDCC_CHECK_PWR;
1050 req.timeout = 1000;
1051 req.flags = ATACMD_READREG;
1052
1053 ata_command(&req);
1054
1055 printf("Current power status: ");
1056
1057 switch (req.sec_count) {
1058 case 0x00:
1059 printf("Standby mode\n");
1060 break;
1061 case 0x80:
1062 printf("Idle mode\n");
1063 break;
1064 case 0xff:
1065 printf("Active mode\n");
1066 break;
1067 default:
1068 printf("Unknown power code (%02x)\n", req.sec_count);
1069 }
1070
1071 return;
1072 }
1073
1074 /*
1075 * device_smart:
1076 *
1077 * Display SMART status
1078 */
1079 void
1080 device_smart(int argc, char *argv[])
1081 {
1082 struct atareq req;
1083 unsigned char inbuf[DEV_BSIZE];
1084 unsigned char inbuf2[DEV_BSIZE];
1085
1086 if (argc < 1)
1087 usage();
1088
1089 if (strcmp(argv[0], "enable") == 0) {
1090 memset(&req, 0, sizeof(req));
1091
1092 req.features = WDSM_ENABLE_OPS;
1093 req.command = WDCC_SMART;
1094 req.cylinder = WDSMART_CYL;
1095 req.timeout = 1000;
1096
1097 ata_command(&req);
1098
1099 is_smart();
1100 } else if (strcmp(argv[0], "disable") == 0) {
1101 memset(&req, 0, sizeof(req));
1102
1103 req.features = WDSM_DISABLE_OPS;
1104 req.command = WDCC_SMART;
1105 req.cylinder = WDSMART_CYL;
1106 req.timeout = 1000;
1107
1108 ata_command(&req);
1109
1110 is_smart();
1111 } else if (strcmp(argv[0], "status") == 0) {
1112 int rv;
1113
1114 rv = is_smart();
1115
1116 if (!rv) {
1117 fprintf(stderr, "SMART not supported\n");
1118 return;
1119 } else if (rv == 3)
1120 return;
1121
1122 memset(&inbuf, 0, sizeof(inbuf));
1123 memset(&req, 0, sizeof(req));
1124
1125 req.features = WDSM_STATUS;
1126 req.command = WDCC_SMART;
1127 req.cylinder = WDSMART_CYL;
1128 req.timeout = 1000;
1129
1130 ata_command(&req);
1131
1132 if (req.cylinder != WDSMART_CYL) {
1133 fprintf(stderr, "Threshold exceeds condition\n");
1134 }
1135
1136 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
1137 * features, the following ata_command()'s may error
1138 * and exit().
1139 */
1140
1141 memset(&inbuf, 0, sizeof(inbuf));
1142 memset(&req, 0, sizeof(req));
1143
1144 req.flags = ATACMD_READ;
1145 req.features = WDSM_RD_DATA;
1146 req.command = WDCC_SMART;
1147 req.databuf = (caddr_t) inbuf;
1148 req.datalen = sizeof(inbuf);
1149 req.cylinder = WDSMART_CYL;
1150 req.timeout = 1000;
1151
1152 ata_command(&req);
1153
1154 memset(&inbuf2, 0, sizeof(inbuf2));
1155 memset(&req, 0, sizeof(req));
1156
1157 req.flags = ATACMD_READ;
1158 req.features = WDSM_RD_THRESHOLDS;
1159 req.command = WDCC_SMART;
1160 req.databuf = (caddr_t) inbuf2;
1161 req.datalen = sizeof(inbuf2);
1162 req.cylinder = WDSMART_CYL;
1163 req.timeout = 1000;
1164
1165 ata_command(&req);
1166
1167 print_smart_status(inbuf, inbuf2);
1168
1169 } else if (strcmp(argv[0], "offline") == 0) {
1170 if (argc != 2)
1171 usage();
1172 if (!is_smart()) {
1173 fprintf(stderr, "SMART not supported\n");
1174 return;
1175 }
1176
1177 memset(&req, 0, sizeof(req));
1178
1179 req.features = WDSM_EXEC_OFFL_IMM;
1180 req.command = WDCC_SMART;
1181 req.cylinder = WDSMART_CYL;
1182 req.sec_num = atol(argv[1]);
1183 req.timeout = 10000;
1184
1185 ata_command(&req);
1186 } else if (strcmp(argv[0], "error-log") == 0) {
1187 if (!is_smart()) {
1188 fprintf(stderr, "SMART not supported\n");
1189 return;
1190 }
1191
1192 memset(&inbuf, 0, sizeof(inbuf));
1193 memset(&req, 0, sizeof(req));
1194
1195 req.flags = ATACMD_READ;
1196 req.features = WDSM_RD_LOG;
1197 req.sec_count = 1;
1198 req.sec_num = 1;
1199 req.command = WDCC_SMART;
1200 req.databuf = (caddr_t) inbuf;
1201 req.datalen = sizeof(inbuf);
1202 req.cylinder = WDSMART_CYL;
1203 req.timeout = 1000;
1204
1205 ata_command(&req);
1206
1207 print_error(inbuf);
1208 } else if (strcmp(argv[0], "selftest-log") == 0) {
1209 if (!is_smart()) {
1210 fprintf(stderr, "SMART not supported\n");
1211 return;
1212 }
1213
1214 memset(&inbuf, 0, sizeof(inbuf));
1215 memset(&req, 0, sizeof(req));
1216
1217 req.flags = ATACMD_READ;
1218 req.features = WDSM_RD_LOG;
1219 req.sec_count = 1;
1220 req.sec_num = 6;
1221 req.command = WDCC_SMART;
1222 req.databuf = (caddr_t) inbuf;
1223 req.datalen = sizeof(inbuf);
1224 req.cylinder = WDSMART_CYL;
1225 req.timeout = 1000;
1226
1227 ata_command(&req);
1228
1229 print_selftest(inbuf);
1230
1231 } else {
1232 usage();
1233 }
1234 return;
1235 }
1236
1237 void
1238 device_security(int argc, char *argv[])
1239 {
1240 struct atareq req;
1241 struct ataparams *inqbuf;
1242
1243 /* need subcommand */
1244 if (argc < 1)
1245 usage();
1246
1247 if (strcmp(argv[0], "freeze") == 0) {
1248 memset(&req, 0, sizeof(req));
1249 req.command = WDCC_SECURITY_FREEZE;
1250 req.timeout = 1000;
1251 ata_command(&req);
1252 } else if (strcmp(argv[0], "status") == 0) {
1253 inqbuf = getataparams();
1254 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
1255 } else
1256 usage();
1257
1258 return;
1259 }
1260
1261 /*
1262 * bus_reset:
1263 * Reset an ATA bus (will reset all devices on the bus)
1264 */
1265 void
1266 bus_reset(int argc, char *argv[])
1267 {
1268 int error;
1269
1270 /* no args */
1271 if (argc != 0)
1272 usage();
1273
1274 error = ioctl(fd, ATABUSIORESET, NULL);
1275
1276 if (error == -1)
1277 err(1, "ATABUSIORESET failed");
1278 }
1279