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