1 /* $OpenBSD: atactl.c,v 1.49 2023/04/30 00:58:38 yasuoka Exp $ */
2 /* $NetBSD: atactl.c,v 1.4 1999/02/24 18:49:14 jwise Exp $ */
3
4 /*-
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Ken Hornstein.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * atactl(8) - a program to control ATA devices.
35 */
36
37 #include <sys/param.h> /* DEV_BSIZE */
38 #include <sys/ioctl.h>
39
40 #include <err.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <util.h>
48
49 #include <dev/ata/atareg.h>
50 #include <dev/ic/wdcreg.h>
51 #include <dev/ic/wdcevent.h>
52 #include <sys/ataio.h>
53
54 #include "atasec.h"
55 #include "atasmart.h"
56
57 struct command {
58 const char *cmd_name;
59 void (*cmd_func)(int, char *[]);
60 };
61
62 struct bitinfo {
63 u_int bitmask;
64 const char *string;
65 };
66
67 struct valinfo {
68 int value;
69 const char *string;
70 };
71
72 int main(int, char *[]);
73 __dead void usage(void);
74 void ata_command(struct atareq *);
75 void print_bitinfo(const char *, u_int, struct bitinfo *);
76 int strtoval(const char *, struct valinfo *);
77 const char *valtostr(int, struct valinfo *, const char *);
78
79 int fd; /* file descriptor for device */
80
81 extern char *__progname; /* from crt0.o */
82
83 void device_dump(int, char*[]);
84 void device_identify(int, char *[]);
85 void device_setidle(int, char *[]);
86 void device_idle(int, char *[]);
87 void device_checkpower(int, char *[]);
88 void device_acoustic(int, char *[]);
89 void device_apm(int, char *[]);
90 void device_feature(int, char *[]);
91 void device_sec_setpass(int, char *[]);
92 void device_sec_unlock(int, char *[]);
93 void device_sec_erase(int, char *[]);
94 void device_sec_freeze(int, char *[]);
95 void device_sec_disablepass(int, char *[]);
96 void device_smart_enable(int, char *[]);
97 void device_smart_disable(int, char *[]);
98 void device_smart_status(int, char *[]);
99 void device_smart_autosave(int, char *[]);
100 void device_smart_offline(int, char *[]);
101 void device_smart_read(int, char *[]);
102 void device_smart_readlog(int, char *[]);
103 void device_attr(int, char *[]);
104
105 void smart_print_errdata(struct smart_log_errdata *);
106 int smart_cksum(u_int8_t *, size_t);
107
108 char *sec_getpass(int, int);
109
110 struct command commands[] = {
111 { "dump", device_dump },
112 { "identify", device_identify },
113 { "setidle", device_setidle },
114 { "setstandby", device_setidle },
115 { "idle", device_idle },
116 { "standby", device_idle },
117 { "sleep", device_idle },
118 { "checkpower", device_checkpower },
119 { "acousticdisable", device_feature },
120 { "acousticset", device_acoustic },
121 { "apmdisable", device_feature },
122 { "apmset", device_apm },
123 { "poddisable", device_feature },
124 { "podenable", device_feature },
125 { "puisdisable", device_feature },
126 { "puisenable", device_feature },
127 { "puisspinup", device_feature },
128 { "readaheaddisable", device_feature },
129 { "readaheadenable", device_feature },
130 { "secsetpass", device_sec_setpass },
131 { "secunlock", device_sec_unlock },
132 { "secerase", device_sec_erase },
133 { "secfreeze", device_sec_freeze },
134 { "secdisablepass", device_sec_disablepass },
135 { "smartenable", device_smart_enable },
136 { "smartdisable", device_smart_disable },
137 { "smartstatus", device_smart_status },
138 { "smartautosave", device_smart_autosave },
139 { "smartoffline", device_smart_offline },
140 { "smartread", device_smart_read },
141 { "smartreadlog", device_smart_readlog },
142 { "readattr", device_attr },
143 { "writecachedisable", device_feature },
144 { "writecacheenable", device_feature },
145 { NULL, NULL },
146 };
147
148 /*
149 * Tables containing bitmasks used for error reporting and
150 * device identification.
151 */
152
153 struct bitinfo ata_caps[] = {
154 { ATA_CAP_STBY, "ATA standby timer values" },
155 { WDC_CAP_IORDY, "IORDY operation" },
156 { WDC_CAP_IORDY_DSBL, "IORDY disabling" },
157 { 0, NULL },
158 };
159
160 struct bitinfo ata_vers[] = {
161 { WDC_VER_ATA1, "ATA-1" },
162 { WDC_VER_ATA2, "ATA-2" },
163 { WDC_VER_ATA3, "ATA-3" },
164 { WDC_VER_ATA4, "ATA-4" },
165 { WDC_VER_ATA5, "ATA-5" },
166 { WDC_VER_ATA6, "ATA-6" },
167 { WDC_VER_ATA7, "ATA-7" },
168 { WDC_VER_ATA8, "ATA-8" },
169 { WDC_VER_ATA9, "ATA-9" },
170 { WDC_VER_ATA10, "ATA-10" },
171 { WDC_VER_ATA11, "ATA-11" },
172 { WDC_VER_ATA12, "ATA-12" },
173 { WDC_VER_ATA13, "ATA-13" },
174 { WDC_VER_ATA14, "ATA-14" },
175 { 0, NULL },
176 };
177
178 struct bitinfo ata_cmd_set1[] = {
179 { WDC_CMD1_NOP, "NOP command" },
180 { WDC_CMD1_RB, "READ BUFFER command" },
181 { WDC_CMD1_WB, "WRITE BUFFER command" },
182 { WDC_CMD1_HPA, "Host Protected Area feature set" },
183 { WDC_CMD1_DVRST, "DEVICE RESET command" },
184 { WDC_CMD1_SRV, "SERVICE interrupt" },
185 { WDC_CMD1_RLSE, "Release interrupt" },
186 { WDC_CMD1_AHEAD, "Read look-ahead" },
187 { WDC_CMD1_CACHE, "Write cache" },
188 { WDC_CMD1_PKT, "PACKET command feature set" },
189 { WDC_CMD1_PM, "Power Management feature set" },
190 { WDC_CMD1_REMOV, "Removable Media feature set" },
191 { WDC_CMD1_SEC, "Security Mode feature set" },
192 { WDC_CMD1_SMART, "SMART feature set" },
193 { 0, NULL },
194 };
195
196 struct bitinfo ata_cmd_set2[] = {
197 { ATAPI_CMD2_FCE, "Flush Cache Ext command" },
198 { ATAPI_CMD2_FC, "Flush Cache command" },
199 { ATAPI_CMD2_DCO, "Device Configuration Overlay feature set" },
200 { ATAPI_CMD2_48AD, "48bit address feature set" },
201 { ATAPI_CMD2_AAM, "Automatic Acoustic Management feature set" },
202 { ATAPI_CMD2_SM, "Set Max security extension commands" },
203 { ATAPI_CMD2_SF, "Set Features subcommand required" },
204 { ATAPI_CMD2_PUIS, "Power-up in standby feature set" },
205 { WDC_CMD2_RMSN, "Removable Media Status Notification feature set" },
206 { ATA_CMD2_APM, "Advanced Power Management feature set" },
207 { ATA_CMD2_CFA, "CFA feature set" },
208 { ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" },
209 { WDC_CMD2_DM, "DOWNLOAD MICROCODE command" },
210 { 0, NULL },
211 };
212
213 struct bitinfo ata_cmd_ext[] = {
214 { ATAPI_CMDE_IIUF, "IDLE IMMEDIATE with UNLOAD FEATURE" },
215 { ATAPI_CMDE_MSER, "Media serial number" },
216 { ATAPI_CMDE_TEST, "SMART self-test" },
217 { ATAPI_CMDE_SLOG, "SMART error logging" },
218 { 0, NULL },
219 };
220
221 /*
222 * Tables containing bitmasks and values used for
223 * SMART commands.
224 */
225
226 struct bitinfo smart_offcap[] = {
227 { SMART_OFFCAP_EXEC, "execute immediate" },
228 { SMART_OFFCAP_ABORT, "abort/restart" },
229 { SMART_OFFCAP_READSCAN, "read scanning" },
230 { SMART_OFFCAP_SELFTEST, "self-test routines" },
231 { 0, NULL}
232 };
233
234 struct bitinfo smart_smartcap[] = {
235 { SMART_SMARTCAP_SAVE, "saving SMART data" },
236 { SMART_SMARTCAP_AUTOSAVE, "enable/disable attribute autosave" },
237 { 0, NULL }
238 };
239
240 struct valinfo smart_autosave[] = {
241 { SMART_AUTOSAVE_EN, "enable" },
242 { SMART_AUTOSAVE_DS, "disable" },
243 { 0, NULL }
244 };
245
246 struct valinfo smart_offline[] = {
247 { SMART_OFFLINE_COLLECT, "collect" },
248 { SMART_OFFLINE_SHORTOFF, "shortoffline" },
249 { SMART_OFFLINE_EXTENOFF, "extenoffline" },
250 { SMART_OFFLINE_ABORT, "abort" },
251 { SMART_OFFLINE_SHORTCAP, "shortcaptive" },
252 { SMART_OFFLINE_EXTENCAP, "extencaptive" },
253 { 0, NULL }
254 };
255
256 struct valinfo smart_readlog[] = {
257 { SMART_READLOG_DIR, "directory" },
258 { SMART_READLOG_SUM, "summary" },
259 { SMART_READLOG_COMP, "comp" },
260 { SMART_READLOG_SELF, "selftest" },
261 { 0, NULL }
262 };
263
264 struct valinfo smart_offstat[] = {
265 { SMART_OFFSTAT_NOTSTART, "never started" },
266 { SMART_OFFSTAT_COMPLETE, "completed ok" },
267 { SMART_OFFSTAT_SUSPEND, "suspended by an interrupting command" },
268 { SMART_OFFSTAT_INTR, "aborted by an interrupting command" },
269 { SMART_OFFSTAT_ERROR, "aborted due to fatal error" },
270 { 0, NULL }
271 };
272
273 struct valinfo smart_selfstat[] = {
274 { SMART_SELFSTAT_COMPLETE, "completed ok or not started" },
275 { SMART_SELFSTAT_ABORT, "aborted" },
276 { SMART_SELFSTAT_INTR, "hardware or software reset" },
277 { SMART_SELFSTAT_ERROR, "fatal error" },
278 { SMART_SELFSTAT_UNKFAIL, "unknown test element failed" },
279 { SMART_SELFSTAT_ELFAIL, "electrical test element failed" },
280 { SMART_SELFSTAT_SRVFAIL, "servo test element failed" },
281 { SMART_SELFSTAT_RDFAIL, "read test element failed" },
282 { 0, NULL }
283 };
284
285 struct valinfo smart_logstat[] = {
286 { SMART_LOG_STATE_UNK, "unknown" },
287 { SMART_LOG_STATE_SLEEP, "sleep" },
288 { SMART_LOG_STATE_ACTIDL, "active/idle" },
289 { SMART_LOG_STATE_OFFSELF, "off-line or self-test" },
290 { 0, NULL }
291 };
292
293 /*
294 * Tables containing values used for reading
295 * device attributes.
296 */
297
298 struct valinfo ibm_attr_names[] = {
299 { 1, "Raw Read Error Rate" },
300 { 2, "Throughput Performance" },
301 { 3, "Spin Up Time" },
302 { 4, "Start/Stop Count" },
303 { 5, "Reallocated Sector Count" },
304 { 6, "Read Channel Margin" },
305 { 7, "Seek Error Rate" },
306 { 8, "Seek Time Performance" },
307 { 9, "Power-On Hours Count" },
308 { 10, "Spin Retry Count" },
309 { 11, "Calibration Retry Count" },
310 { 12, "Device Power Cycle Count" },
311 { 13, "Soft Read Error Rate" },
312 { 100, "Erase/Program Cycles" },
313 { 103, "Translation Table Rebuild" },
314 { 160, "Uncorrectable Error Count" },
315 { 170, "Reserved Block Count" },
316 { 171, "Program Fail Count" },
317 { 172, "Erase Fail Count" },
318 { 173, "Wear Worst Case Erase Count" },
319 { 174, "Power-Off Retract Count" },
320 { 175, "Program Fail Count" },
321 { 176, "Erase Fail Count" },
322 { 177, "Wear Leveling Count" },
323 { 178, "Used Reserved Block Count" },
324 { 179, "Used Reserved Block Count Total" },
325 { 180, "Unused Reserved Block Count Total" },
326 { 181, "Program Fail Count Total" },
327 { 182, "Erase Fail Count" },
328 { 183, "Runtime Bad Block" },
329 { 184, "End-to-End error" },
330 { 185, "Head Stability" },
331 { 186, "Induced Op-Vibration Detection" },
332 { 187, "Reported Uncorrectable Errors" },
333 { 188, "Command Timeout" },
334 { 189, "High Fly Writes" },
335 { 190, "Airflow Temperature" },
336 { 191, "G-Sense Error Rate" },
337 { 192, "Power-Off Retract Count" },
338 { 193, "Load Cycle Count" },
339 { 194, "Temperature" },
340 { 195, "Hardware ECC Recovered" },
341 { 196, "Reallocation Event Count" },
342 { 197, "Current Pending Sector Count" },
343 { 198, "Off-Line Scan Uncorrectable Sector Count" },
344 { 199, "Ultra DMA CRC Error Count" },
345 { 200, "Write Error Rate" },
346 { 201, "Soft Read Error Rate" },
347 { 202, "Data Address Mark Errors" },
348 { 203, "Run Out Cancel" },
349 { 204, "Soft ECC Correction" },
350 { 205, "Thermal Asperity Check" },
351 { 206, "Flying Height" },
352 { 207, "Spin High Current" },
353 { 208, "Spin Buzz" },
354 { 209, "Offline Seek Performance" },
355 { 220, "Disk Shift" },
356 { 221, "G-Sense Error Rate" },
357 { 222, "Loaded Hours" },
358 { 223, "Load/Unload Retry Count" },
359 { 224, "Load Friction" },
360 { 225, "Load/Unload Cycle Count" },
361 { 226, "Load-In Time" },
362 { 227, "Torque Amplification Count" },
363 { 228, "Power-Off Retract Count" },
364 { 230, "GMR Head Amplitude" },
365 { 231, "Temperature" },
366 { 232, "Available reserved space" },
367 { 233, "Media wearout indicator" },
368 { 235, "Power-Off Retract Count" },
369 { 240, "Head Flying Hours" },
370 { 241, "Total LBAs Written" },
371 { 242, "Total LBAs Read" },
372 { 249, "NAND Writes (1GB)" },
373 { 250, "Read Error Retry Rate" },
374 { 254, "Free Fall Sensor" },
375 { 0, NULL },
376 };
377
378 #define MAKEWORD(b1, b2) \
379 (b2 << 8 | b1)
380 #define MAKEDWORD(b1, b2, b3, b4) \
381 (b4 << 24 | b3 << 16 | b2 << 8 | b1)
382
383 int
main(int argc,char * argv[])384 main(int argc, char *argv[])
385 {
386 struct command *cmdp;
387
388 if (argc < 2)
389 usage();
390
391 /*
392 * Open the device
393 */
394 if ((fd = opendev(argv[1], O_RDWR, OPENDEV_PART, NULL)) == -1)
395 err(1, "%s", argv[1]);
396
397 /* Skip program name and device name. */
398 if (argc != 2) {
399 argv += 2;
400 argc -= 2;
401 } else {
402 argv[1] = "identify";
403 argv += 1;
404 argc -= 1;
405 }
406
407 /* Look up and call the command. */
408 for (cmdp = commands; cmdp->cmd_name != NULL; cmdp++)
409 if (strcmp(argv[0], cmdp->cmd_name) == 0)
410 break;
411 if (cmdp->cmd_name == NULL)
412 errx(1, "unknown command: %s", argv[0]);
413
414 (cmdp->cmd_func)(argc, argv);
415
416 return (0);
417 }
418
419 __dead void
usage(void)420 usage(void)
421 {
422
423 fprintf(stderr, "usage: %s device [command [arg]]\n", __progname);
424 exit(1);
425 }
426
427 /*
428 * Wrapper that calls ATAIOCCOMMAND and checks for errors
429 */
430 void
ata_command(struct atareq * req)431 ata_command(struct atareq *req)
432 {
433 if (ioctl(fd, ATAIOCCOMMAND, req) == -1)
434 err(1, "ATAIOCCOMMAND failed");
435
436 switch (req->retsts) {
437
438 case ATACMD_OK:
439 return;
440 case ATACMD_TIMEOUT:
441 errx(1, "ATA command timed out");
442 case ATACMD_DF:
443 errx(1, "ATA device returned a Device Fault");
444 case ATACMD_ERROR:
445 if (req->error & WDCE_ABRT)
446 errx(1, "ATA device returned Aborted Command");
447 else
448 errx(1, "ATA device returned error register %0x",
449 req->error);
450 default:
451 errx(1, "ATAIOCCOMMAND returned unknown result code %d",
452 req->retsts);
453 }
454 }
455
456 /*
457 * Print out strings associated with particular bitmasks
458 */
459 void
print_bitinfo(const char * f,u_int bits,struct bitinfo * binfo)460 print_bitinfo(const char *f, u_int bits, struct bitinfo *binfo)
461 {
462
463 for (; binfo->bitmask != 0; binfo++)
464 if (bits & binfo->bitmask)
465 printf(f, binfo->string);
466 }
467
468 /*
469 * strtoval():
470 * returns value associated with given string,
471 * if no value found -1 is returned.
472 */
473 int
strtoval(const char * str,struct valinfo * vinfo)474 strtoval(const char *str, struct valinfo *vinfo)
475 {
476 for (; vinfo->string != NULL; vinfo++)
477 if (strcmp(str, vinfo->string) == 0)
478 return (vinfo->value);
479 return (-1);
480 }
481
482 /*
483 * valtostr():
484 * returns string associated with given value,
485 * if no string found def value is returned.
486 */
487 const char *
valtostr(int val,struct valinfo * vinfo,const char * def)488 valtostr(int val, struct valinfo *vinfo, const char *def)
489 {
490 for (; vinfo->string != NULL; vinfo++)
491 if (val == vinfo->value)
492 return (vinfo->string);
493 return (def);
494 }
495
496 /*
497 * DEVICE COMMANDS
498 */
499
500 /*
501 * device dump:
502 *
503 * extract issued ATA requests from the log buffer
504 */
505 void
device_dump(int argc,char * argv[])506 device_dump(int argc, char *argv[])
507 {
508 unsigned char buf[131072];
509 atagettrace_t agt;
510 unsigned int total;
511 unsigned int p = 0;
512 int type;
513 const char *types[] = { NULL, "status", "error", "ATAPI",
514 "ATAPI done", "ATA cmd", "ATA", "select slave",
515 "select master", "register read", "ATA LBA48" };
516 int num_types = sizeof(types) / sizeof(types[0]);
517 int info;
518 int entrysize;
519 int i;
520 int flags;
521
522 if (argc != 1)
523 goto usage;
524
525 memset(&agt, 0, sizeof(agt));
526 agt.buf_size = sizeof(buf);
527 agt.buf = buf;
528
529 if (ioctl(fd, ATAIOGETTRACE, &agt) == -1)
530 err(1, "ATAIOGETTRACE failed");
531
532 total = agt.bytes_copied;
533
534 /* Parse entries */
535 while (p < total) {
536 type = buf[p++];
537 if (p >= total)
538 return;
539 if (type <= 0 || type >= num_types)
540 return;
541
542 info = buf[p++];
543 if (p >= total)
544 return;
545 entrysize = (info & 0x1f);
546
547 printf ("ch %d", (info >> 5) & 0x7);
548 printf(": %s", types[type]);
549
550 switch (type) {
551 case WDCEVENT_STATUS:
552 if (entrysize != 1)
553 return;
554
555 printf(": 0x%x", buf[p]);
556 if (buf[p] & WDCS_BSY)
557 printf(" BSY");
558 if (buf[p] & WDCS_DRDY)
559 printf(" DRDY");
560 if (buf[p] & WDCS_DWF)
561 printf(" DWF");
562 if (buf[p] & WDCS_DSC)
563 printf(" DSC");
564 if (buf[p] & WDCS_DRQ)
565 printf(" DRQ");
566 if (buf[p] & WDCS_CORR)
567 printf(" CORR");
568 if (buf[p] & WDCS_IDX)
569 printf(" IDX");
570 if (buf[p] & WDCS_ERR)
571 printf(" ERR");
572
573 p++;
574 entrysize = 0;
575 break;
576 case WDCEVENT_ERROR:
577 if (entrysize != 1)
578 return;
579
580 printf(": 0x%x", buf[p]);
581 if (buf[p] & WDCE_BBK)
582 printf(" BBK/CRC");
583 if (buf[p] & WDCE_UNC)
584 printf(" UNC");
585 if (buf[p] & WDCE_MC)
586 printf(" MC");
587 if (buf[p] & WDCE_IDNF)
588 printf(" IDNF");
589 if (buf[p] & WDCE_MCR)
590 printf(" MCR");
591 if (buf[p] & WDCE_ABRT)
592 printf(" ABRT");
593 if (buf[p] & WDCE_TK0NF)
594 printf(" TK0NF");
595 if (buf[p] & WDCE_AMNF)
596 printf(" AMNF");
597
598 p++;
599 entrysize = 0;
600 break;
601 case WDCEVENT_ATAPI_CMD:
602 if (entrysize < 2 || p + 2 > total)
603 return;
604
605 flags = (buf[p] << 8) + buf[p + 1];
606 printf(": flags 0x%x", flags);
607 if (flags & 0x0100)
608 printf(" MEDIA");
609 if (flags & 0x0080)
610 printf(" SENSE");
611 if (flags & 0x0040)
612 printf(" DMA");
613 if (flags & 0x0020)
614 printf(" POLL");
615 if (flags & 0x0004)
616 printf(" TIMEOUT");
617 if (flags & 0x0002)
618 printf(" ATAPI");
619
620 p += 2;
621 entrysize -= 2;
622 break;
623 case WDCEVENT_ATAPI_DONE:
624 if (entrysize != 3 || p + 3 > total)
625 return;
626
627 flags = (buf[p] << 8) + buf[p + 1];
628 printf(": flags 0x%x", flags);
629 if (flags & 0x0100)
630 printf(" MEDIA");
631 if (flags & 0x0080)
632 printf(" SENSE");
633 if (flags & 0x0040)
634 printf(" DMA");
635 if (flags & 0x0020)
636 printf(" POLL");
637 if (flags & 0x0004)
638 printf(" TIMEOUT");
639 if (flags & 0x0002)
640 printf(" ATAPI");
641
642 printf(", error 0x%x", buf[p + 2]);
643 switch (buf[p + 2]) {
644 case 1:
645 printf(" (sense)");
646 break;
647 case 2:
648 printf(" (driver failure)");
649 break;
650 case 3:
651 printf(" (timeout)");
652 break;
653 case 4:
654 printf(" (busy)");
655 break;
656 case 5:
657 printf(" (ATAPI sense)");
658 break;
659 case 8:
660 printf(" (reset)");
661 break;
662 }
663
664 p += 3;
665 entrysize = 0;
666 break;
667 case WDCEVENT_ATA_LONG:
668 if (entrysize != 7 || p + 7 > total)
669 return;
670
671 printf(": ");
672 switch (buf[p + 6]) {
673 case WDCC_READDMA:
674 printf("READ DMA");
675 break;
676 case WDCC_WRITEDMA:
677 printf("WRITE DMA");
678 break;
679 default:
680 printf("CMD 0x%x", buf[p + 6]);
681 }
682 printf(" head %d, precomp %d, cyl_hi %d, "
683 "cyl_lo %d, sec %d, cnt %d",
684 buf[p], buf[p + 1], buf[p + 2], buf[p + 3],
685 buf[p + 4], buf[p + 5]);
686
687 p += 7;
688 entrysize = 0;
689 break;
690 case WDCEVENT_REG:
691 if (entrysize != 3 || p + 3 > total)
692 return;
693
694 switch (buf[p]) {
695 case 1:
696 printf(": error");
697 break;
698 case 2:
699 printf(": ireason");
700 break;
701 case 3:
702 printf(": lba_lo");
703 break;
704 case 4:
705 printf(": lba_mi");
706 break;
707 case 5:
708 printf(": lba_hi");
709 break;
710 case 6:
711 printf(": sdh");
712 break;
713 case 7:
714 printf(": status");
715 break;
716 case 8:
717 printf(": altstatus");
718 break;
719 default:
720 printf(": unknown register %d", buf[p]);
721 }
722 printf(": 0x%x", (buf[p + 1] << 8) + buf[p + 2]);
723
724 p += 3;
725 entrysize = 0;
726 break;
727 case WDCEVENT_ATA_EXT:
728 if (entrysize != 9 || p + 9 > total)
729 return;
730
731 printf(": ");
732 switch (buf[p + 8]) {
733 case WDCC_READDMA_EXT:
734 printf("READ DMA EXT");
735 break;
736 case WDCC_WRITEDMA_EXT:
737 printf("WRITE DMA EXT");
738 break;
739 default:
740 printf("CMD 0x%x", buf[p + 8]);
741 }
742 printf(" lba_hi1 %d, lba_hi2 %d, "
743 "lba_mi1 %d, lba_mi2 %d, lba_lo1 %d, lba_lo2 %d, "
744 "count1 %d, count2 %d",
745 buf[p], buf[p + 1], buf[p + 2], buf[p + 3],
746 buf[p + 4], buf[p + 5], buf[p + 6],
747 buf[p + 7]);
748
749 p += 9;
750 entrysize = 0;
751 break;
752 }
753
754 if (entrysize > 0)
755 printf(":");
756 for (i = 0; i < entrysize; i++) {
757 printf (" 0x%02x", buf[p]);
758 if (++p >= total)
759 break;
760 }
761 printf("\n");
762 }
763
764 return;
765
766 usage:
767 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
768 exit(1);
769 }
770
771 /*
772 * device_identify:
773 *
774 * Display the identity of the device
775 */
776 void
device_identify(int argc,char * argv[])777 device_identify(int argc, char *argv[])
778 {
779 struct ataparams *inqbuf;
780 struct atareq req;
781 char inbuf[DEV_BSIZE];
782 u_int64_t capacity;
783 u_int8_t *s;
784
785 if (argc != 1)
786 goto usage;
787
788 memset(&inbuf, 0, sizeof(inbuf));
789 memset(&req, 0, sizeof(req));
790
791 inqbuf = (struct ataparams *) inbuf;
792
793 req.flags = ATACMD_READ;
794 req.command = WDCC_IDENTIFY;
795 req.databuf = (caddr_t) inbuf;
796 req.datalen = sizeof(inbuf);
797 req.timeout = 1000;
798
799 ata_command(&req);
800
801 if (BYTE_ORDER == BIG_ENDIAN) {
802 swap16_multi((u_int16_t *)inbuf, 10);
803 swap16_multi(((u_int16_t *)inbuf) + 20, 3);
804 swap16_multi(((u_int16_t *)inbuf) + 47, sizeof(inbuf) / 2 - 47);
805 }
806
807 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
808 ((inqbuf->atap_model[0] == 'N' &&
809 inqbuf->atap_model[1] == 'E') ||
810 (inqbuf->atap_model[0] == 'F' &&
811 inqbuf->atap_model[1] == 'X')))) {
812 swap16_multi((u_int16_t *)(inqbuf->atap_model),
813 sizeof(inqbuf->atap_model) / 2);
814 swap16_multi((u_int16_t *)(inqbuf->atap_serial),
815 sizeof(inqbuf->atap_serial) / 2);
816 swap16_multi((u_int16_t *)(inqbuf->atap_revision),
817 sizeof(inqbuf->atap_revision) / 2);
818 }
819
820 /*
821 * Strip blanks off of the info strings.
822 */
823
824 for (s = &inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1];
825 s >= inqbuf->atap_model && *s == ' '; s--)
826 *s = '\0';
827
828 for (s = &inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1];
829 s >= inqbuf->atap_revision && *s == ' '; s--)
830 *s = '\0';
831
832 for (s = &inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1];
833 s >= inqbuf->atap_serial && *s == ' '; s--)
834 *s = '\0';
835
836 printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n",
837 (int) sizeof(inqbuf->atap_model), inqbuf->atap_model,
838 (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision,
839 (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial);
840
841 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
842 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
843 "removable");
844
845 if (inqbuf->atap_cmd2_en & ATAPI_CMD2_48AD)
846 capacity = ((u_int64_t)inqbuf->atap_max_lba[3] << 48) |
847 ((u_int64_t)inqbuf->atap_max_lba[2] << 32) |
848 ((u_int64_t)inqbuf->atap_max_lba[1] << 16) |
849 (u_int64_t)inqbuf->atap_max_lba[0];
850 else
851 capacity = (inqbuf->atap_capacity[1] << 16) |
852 inqbuf->atap_capacity[0];
853 printf("Cylinders: %d, heads: %d, sec/track: %d, total "
854 "sectors: %llu\n", inqbuf->atap_cylinders,
855 inqbuf->atap_heads, inqbuf->atap_sectors, capacity);
856
857 if ((inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ) &&
858 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
859 printf("Device supports command queue depth of %d\n",
860 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
861
862 printf("Device capabilities:\n");
863 print_bitinfo("\t%s\n", inqbuf->atap_capabilities1, ata_caps);
864
865 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
866 printf("Device supports the following standards:\n");
867 print_bitinfo("%s ", inqbuf->atap_ata_major, ata_vers);
868 printf("\n");
869 }
870
871 if ((inqbuf->atap_cmd_set1 & WDC_CMD1_SEC) &&
872 inqbuf->atap_mpasswd_rev != 0 &&
873 inqbuf->atap_mpasswd_rev != 0xffff)
874 printf("Master password revision code 0x%04x\n",
875 inqbuf->atap_mpasswd_rev);
876
877 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
878 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
879 printf("Device supports the following command sets:\n");
880 print_bitinfo("\t%s\n", inqbuf->atap_cmd_set1, ata_cmd_set1);
881 print_bitinfo("\t%s\n", inqbuf->atap_cmd_set2, ata_cmd_set2);
882 print_bitinfo("\t%s\n", inqbuf->atap_cmd_ext, ata_cmd_ext);
883 }
884
885 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
886 printf("Device has enabled the following command "
887 "sets/features:\n");
888 print_bitinfo("\t%s\n", inqbuf->atap_cmd1_en, ata_cmd_set1);
889 print_bitinfo("\t%s\n", inqbuf->atap_cmd2_en, ata_cmd_set2);
890 }
891
892 return;
893
894 usage:
895 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
896 exit(1);
897 }
898
899 /*
900 * device idle:
901 *
902 * issue the IDLE IMMEDIATE command to the drive
903 */
904 void
device_idle(int argc,char * argv[])905 device_idle(int argc, char *argv[])
906 {
907 struct atareq req;
908
909 if (argc != 1)
910 goto usage;
911
912 memset(&req, 0, sizeof(req));
913
914 if (strcmp(argv[0], "idle") == 0)
915 req.command = WDCC_IDLE_IMMED;
916 else if (strcmp(argv[0], "standby") == 0)
917 req.command = WDCC_STANDBY_IMMED;
918 else
919 req.command = WDCC_SLEEP;
920
921 req.timeout = 1000;
922
923 ata_command(&req);
924
925 return;
926 usage:
927 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
928 exit(1);
929 }
930
931 /*
932 * SECURITY SET PASSWORD command
933 */
934 void
device_sec_setpass(int argc,char * argv[])935 device_sec_setpass(int argc, char *argv[])
936 {
937 struct atareq req;
938 struct sec_password pwd;
939 char *pass, inbuf[DEV_BSIZE];
940 struct ataparams *inqbuf = (struct ataparams *)inbuf;
941
942 if (argc < 2)
943 goto usage;
944
945 memset(&pwd, 0, sizeof(pwd));
946
947 if (strcmp(argv[1], "user") == 0 && argc == 3)
948 pwd.ctrl |= SEC_PASSWORD_USER;
949 else if (strcmp(argv[1], "master") == 0 && argc == 2)
950 pwd.ctrl |= SEC_PASSWORD_MASTER;
951 else
952 goto usage;
953 if (argc == 3) {
954 if (strcmp(argv[2], "high") == 0)
955 pwd.ctrl |= SEC_LEVEL_HIGH;
956 else if (strcmp(argv[2], "maximum") == 0)
957 pwd.ctrl |= SEC_LEVEL_MAX;
958 else
959 goto usage;
960 }
961
962 /*
963 * Issue IDENTIFY command to obtain master password
964 * revision code and decrement its value.
965 * The valid revision codes are 0x0001 through 0xfffe.
966 * If the device returns 0x0000 or 0xffff as a revision
967 * code then the master password revision code is not
968 * supported so don't touch it.
969 */
970 memset(&inbuf, 0, sizeof(inbuf));
971 memset(&req, 0, sizeof(req));
972
973 req.command = WDCC_IDENTIFY;
974 req.timeout = 1000;
975 req.flags = ATACMD_READ;
976 req.databuf = (caddr_t)inbuf;
977 req.datalen = sizeof(inbuf);
978
979 ata_command(&req);
980
981 pwd.revision = inqbuf->atap_mpasswd_rev;
982 if (pwd.revision != 0 && pwd.revision != 0xffff && --pwd.revision == 0)
983 pwd.revision = 0xfffe;
984
985 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 1);
986 memcpy(pwd.password, pass, strlen(pass));
987
988 memset(&req, 0, sizeof(req));
989
990 req.command = ATA_SEC_SET_PASSWORD;
991 req.timeout = 1000;
992 req.flags = ATACMD_WRITE;
993 req.databuf = (caddr_t)&pwd;
994 req.datalen = sizeof(pwd);
995
996 ata_command(&req);
997
998 return;
999 usage:
1000 fprintf(stderr, "usage: %s device %s user high | maximum\n",
1001 __progname, argv[0]);
1002 fprintf(stderr, " %s device %s master\n", __progname, argv[0]);
1003 exit(1);
1004 }
1005
1006 /*
1007 * SECURITY UNLOCK command
1008 */
1009 void
device_sec_unlock(int argc,char * argv[])1010 device_sec_unlock(int argc, char *argv[])
1011 {
1012 struct atareq req;
1013 struct sec_password pwd;
1014 char *pass;
1015
1016 if (argc != 2)
1017 goto usage;
1018
1019 memset(&pwd, 0, sizeof(pwd));
1020
1021 if (strcmp(argv[1], "user") == 0)
1022 pwd.ctrl |= SEC_PASSWORD_USER;
1023 else if (strcmp(argv[1], "master") == 0)
1024 pwd.ctrl |= SEC_PASSWORD_MASTER;
1025 else
1026 goto usage;
1027
1028 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1029 memcpy(pwd.password, pass, strlen(pass));
1030
1031 memset(&req, 0, sizeof(req));
1032
1033 req.command = ATA_SEC_UNLOCK;
1034 req.timeout = 1000;
1035 req.flags = ATACMD_WRITE;
1036 req.databuf = (caddr_t)&pwd;
1037 req.datalen = sizeof(pwd);
1038
1039 ata_command(&req);
1040
1041 return;
1042 usage:
1043 fprintf(stderr, "usage: %s device %s user | master\n", __progname,
1044 argv[0]);
1045 exit(1);
1046 }
1047
1048 /*
1049 * SECURITY ERASE UNIT command
1050 */
1051 void
device_sec_erase(int argc,char * argv[])1052 device_sec_erase(int argc, char *argv[])
1053 {
1054 struct atareq req;
1055 struct sec_password pwd;
1056 char *pass;
1057
1058 if (argc < 2)
1059 goto usage;
1060
1061 memset(&pwd, 0, sizeof(pwd));
1062
1063 if (strcmp(argv[1], "user") == 0)
1064 pwd.ctrl |= SEC_PASSWORD_USER;
1065 else if (strcmp(argv[1], "master") == 0)
1066 pwd.ctrl |= SEC_PASSWORD_MASTER;
1067 else
1068 goto usage;
1069 if (argc == 2)
1070 pwd.ctrl |= SEC_ERASE_NORMAL;
1071 else if (argc == 3 && strcmp(argv[2], "enhanced") == 0)
1072 pwd.ctrl |= SEC_ERASE_ENHANCED;
1073 else
1074 goto usage;
1075
1076 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1077 memcpy(pwd.password, pass, strlen(pass));
1078
1079 /* Issue SECURITY ERASE PREPARE command before */
1080 memset(&req, 0, sizeof(req));
1081
1082 req.command = ATA_SEC_ERASE_PREPARE;
1083 req.timeout = 1000;
1084
1085 ata_command(&req);
1086
1087 memset(&req, 0, sizeof(req));
1088
1089 req.command = ATA_SEC_ERASE_UNIT;
1090 req.timeout = 1000;
1091 req.flags = ATACMD_WRITE;
1092 req.databuf = (caddr_t)&pwd;
1093 req.datalen = sizeof(pwd);
1094
1095 ata_command(&req);
1096
1097 return;
1098 usage:
1099 fprintf(stderr, "usage: %s device %s user | master [enhanced]\n",
1100 __progname, argv[0]);
1101 exit(1);
1102 }
1103
1104 /*
1105 * SECURITY FREEZE LOCK command
1106 */
1107 void
device_sec_freeze(int argc,char * argv[])1108 device_sec_freeze(int argc, char *argv[])
1109 {
1110 struct atareq req;
1111
1112 if (argc != 1)
1113 goto usage;
1114
1115 memset(&req, 0, sizeof(req));
1116
1117 req.command = ATA_SEC_FREEZE_LOCK;
1118 req.timeout = 1000;
1119
1120 ata_command(&req);
1121
1122 return;
1123 usage:
1124 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1125 exit(1);
1126 }
1127
1128 /*
1129 * SECURITY DISABLE PASSWORD command
1130 */
1131 void
device_sec_disablepass(int argc,char * argv[])1132 device_sec_disablepass(int argc, char *argv[])
1133 {
1134 struct atareq req;
1135 struct sec_password pwd;
1136 char *pass;
1137
1138 if (argc != 2)
1139 goto usage;
1140
1141 memset(&pwd, 0, sizeof(pwd));
1142
1143 if (strcmp(argv[1], "user") == 0)
1144 pwd.ctrl |= SEC_PASSWORD_USER;
1145 else if (strcmp(argv[1], "master") == 0)
1146 pwd.ctrl |= SEC_PASSWORD_MASTER;
1147 else
1148 goto usage;
1149
1150 pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1151 memcpy(pwd.password, pass, strlen(pass));
1152
1153 memset(&req, 0, sizeof(req));
1154
1155 req.command = ATA_SEC_DISABLE_PASSWORD;
1156 req.timeout = 1000;
1157 req.flags = ATACMD_WRITE;
1158 req.databuf = (caddr_t)&pwd;
1159 req.datalen = sizeof(pwd);
1160
1161 ata_command(&req);
1162
1163 return;
1164 usage:
1165 fprintf(stderr, "usage: %s device %s user | master\n", __progname,
1166 argv[0]);
1167 exit(1);
1168 }
1169
1170 char *
sec_getpass(int ident,int confirm)1171 sec_getpass(int ident, int confirm)
1172 {
1173 char *pass, buf[33];
1174
1175 if ((pass = getpass(ident ? "Master password:" :
1176 "User password:")) == NULL)
1177 err(1, "getpass()");
1178 if (strlen(pass) > 32)
1179 errx(1, "password too long");
1180 if (confirm) {
1181 strlcpy(buf, pass, sizeof(buf));
1182 if ((pass = getpass(ident ? "Retype master password:" :
1183 "Retype user password:")) == NULL)
1184 err(1, "getpass()");
1185 if (strcmp(pass, buf) != 0)
1186 errx(1, "password mismatch");
1187 }
1188
1189 return (pass);
1190 }
1191
1192 /*
1193 * SMART ENABLE OPERATIONS command
1194 */
1195 void
device_smart_enable(int argc,char * argv[])1196 device_smart_enable(int argc, char *argv[])
1197 {
1198 struct atareq req;
1199
1200 if (argc != 1)
1201 goto usage;
1202
1203 memset(&req, 0, sizeof(req));
1204
1205 req.command = ATAPI_SMART;
1206 req.cylinder = 0xc24f;
1207 req.timeout = 1000;
1208 req.features = ATA_SMART_EN;
1209
1210 ata_command(&req);
1211
1212 return;
1213 usage:
1214 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1215 exit(1);
1216 }
1217
1218 /*
1219 * SMART DISABLE OPERATIONS command
1220 */
1221 void
device_smart_disable(int argc,char * argv[])1222 device_smart_disable(int argc, char *argv[])
1223 {
1224 struct atareq req;
1225
1226 if (argc != 1)
1227 goto usage;
1228
1229 memset(&req, 0, sizeof(req));
1230
1231 req.command = ATAPI_SMART;
1232 req.cylinder = 0xc24f;
1233 req.timeout = 1000;
1234 req.features = ATA_SMART_DS;
1235
1236 ata_command(&req);
1237
1238 return;
1239 usage:
1240 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1241 exit(1);
1242 }
1243
1244 /*
1245 * SMART STATUS command
1246 */
1247 void
device_smart_status(int argc,char * argv[])1248 device_smart_status(int argc, char *argv[])
1249 {
1250 struct atareq req;
1251
1252 if (argc != 1)
1253 goto usage;
1254
1255 memset(&req, 0, sizeof(req));
1256
1257 req.command = ATAPI_SMART;
1258 req.cylinder = 0xc24f;
1259 req.timeout = 1000;
1260 req.features = ATA_SMART_STATUS;
1261
1262 ata_command(&req);
1263
1264 if (req.cylinder == 0xc24f)
1265 printf("No SMART threshold exceeded\n");
1266 else if (req.cylinder == 0x2cf4) {
1267 errx(2, "SMART threshold exceeded!");
1268 } else {
1269 errx(1, "Unknown response %02x!", req.cylinder);
1270 }
1271
1272 return;
1273 usage:
1274 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1275 exit(1);
1276 }
1277
1278 /*
1279 * SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE command
1280 */
1281 void
device_smart_autosave(int argc,char * argv[])1282 device_smart_autosave(int argc, char *argv[])
1283 {
1284 struct atareq req;
1285 int val;
1286
1287 if (argc != 2)
1288 goto usage;
1289
1290 memset(&req, 0, sizeof(req));
1291
1292 req.command = ATAPI_SMART;
1293 req.cylinder = 0xc24f;
1294 req.timeout = 1000;
1295 req.features = ATA_SMART_AUTOSAVE;
1296 if ((val = strtoval(argv[1], smart_autosave)) == -1)
1297 goto usage;
1298 req.sec_num = val;
1299
1300 ata_command(&req);
1301
1302 return;
1303 usage:
1304 fprintf(stderr, "usage: %s device %s enable | disable\n", __progname,
1305 argv[0]);
1306 exit(1);
1307 }
1308
1309 /*
1310 * SMART EXECUTE OFF-LINE IMMEDIATE command
1311 */
1312 void
device_smart_offline(int argc,char * argv[])1313 device_smart_offline(int argc, char *argv[])
1314 {
1315 struct atareq req;
1316 int val;
1317
1318 if (argc != 2)
1319 goto usage;
1320
1321 memset(&req, 0, sizeof(req));
1322
1323 req.command = ATAPI_SMART;
1324 req.cylinder = 0xc24f;
1325 req.timeout = 1000;
1326 req.features = ATA_SMART_OFFLINE;
1327 if ((val = strtoval(argv[1], smart_offline)) == -1)
1328 goto usage;
1329 req.sec_num = val;
1330
1331 ata_command(&req);
1332
1333 return;
1334 usage:
1335 fprintf(stderr, "usage: %s device %s subcommand\n", __progname,
1336 argv[0]);
1337 exit(1);
1338 }
1339
1340 /*
1341 * SMART READ DATA command
1342 */
1343 void
device_smart_read(int argc,char * argv[])1344 device_smart_read(int argc, char *argv[])
1345 {
1346 struct atareq req;
1347 struct smart_read data;
1348
1349 if (argc != 1)
1350 goto usage;
1351
1352 memset(&req, 0, sizeof(req));
1353 memset(&data, 0, sizeof(data));
1354
1355 req.command = ATAPI_SMART;
1356 req.cylinder = 0xc24f;
1357 req.timeout = 1000;
1358 req.features = ATA_SMART_READ;
1359 req.flags = ATACMD_READ;
1360 req.databuf = (caddr_t)&data;
1361 req.datalen = sizeof(data);
1362
1363 ata_command(&req);
1364
1365 if (smart_cksum((u_int8_t *)&data, sizeof(data)) != 0)
1366 errx(1, "Checksum mismatch");
1367
1368 printf("Off-line data collection:\n");
1369 printf(" status: %s\n",
1370 valtostr(data.offstat & 0x7f, smart_offstat, "?"));
1371 printf(" activity completion time: %d seconds\n",
1372 letoh16(data.time));
1373 printf(" capabilities:\n");
1374 print_bitinfo("\t%s\n", data.offcap, smart_offcap);
1375 printf("Self-test execution:\n");
1376 printf(" status: %s\n", valtostr(SMART_SELFSTAT_STAT(data.selfstat),
1377 smart_selfstat, "?"));
1378 if (SMART_SELFSTAT_STAT(data.selfstat) == SMART_SELFSTAT_PROGRESS)
1379 printf("remains %d%% of total time\n",
1380 SMART_SELFSTAT_PCNT(data.selfstat));
1381 printf(" recommended polling time:\n");
1382 printf("\tshort routine: %d minutes\n", data.shtime);
1383 printf("\textended routine: %d minutes\n", data.extime);
1384 printf("SMART capabilities:\n");
1385 print_bitinfo(" %s\n", letoh16(data.smartcap), smart_smartcap);
1386 printf("Error logging: ");
1387 if (data.errcap & SMART_ERRCAP_ERRLOG)
1388 printf("supported\n");
1389 else
1390 printf("not supported\n");
1391
1392 return;
1393 usage:
1394 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1395 exit(1);
1396 }
1397
1398 /*
1399 * SMART READ LOG command
1400 */
1401 void
device_smart_readlog(int argc,char * argv[])1402 device_smart_readlog(int argc, char *argv[])
1403 {
1404 struct atareq req;
1405 int val;
1406 u_int8_t inbuf[DEV_BSIZE];
1407
1408 if (argc != 2)
1409 goto usage;
1410
1411 memset(&req, 0, sizeof(req));
1412 memset(&inbuf, 0, sizeof(inbuf));
1413
1414 req.command = ATAPI_SMART;
1415 req.cylinder = 0xc24f;
1416 req.timeout = 1000;
1417 req.features = ATA_SMART_READLOG;
1418 req.flags = ATACMD_READ;
1419 req.sec_count = 1;
1420 req.databuf = (caddr_t)inbuf;
1421 req.datalen = sizeof(inbuf);
1422 if ((val = strtoval(argv[1], smart_readlog)) == -1)
1423 goto usage;
1424 req.sec_num = val;
1425
1426 ata_command(&req);
1427
1428 if (strcmp(argv[1], "directory") == 0) {
1429 struct smart_log_dir *data = (struct smart_log_dir *)inbuf;
1430 int i;
1431
1432 if (data->version != SMART_LOG_MSECT) {
1433 printf("Device doesn't support multi-sector logs\n");
1434 return;
1435 }
1436
1437 for (i = 0; i < 255; i++)
1438 printf("Log address %d: %d sectors\n", i + 1,
1439 data->entry[i].sec_num);
1440 } else if (strcmp(argv[1], "summary") == 0) {
1441 struct smart_log_sum *data = (struct smart_log_sum *)inbuf;
1442 int i, n, nerr;
1443
1444 if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1445 errx(1, "Checksum mismatch");
1446
1447 if (data->index == 0) {
1448 printf("No log entries\n");
1449 return;
1450 }
1451
1452 nerr = letoh16(data->err_cnt);
1453 printf("Error count: %d\n\n", nerr);
1454 /*
1455 * Five error log data structures form a circular
1456 * buffer. data->index points to the most recent
1457 * record and err_cnt contains total error number.
1458 * We pass from the most recent record to the
1459 * latest one.
1460 */
1461 i = data->index - 1;
1462 n = 0;
1463 do {
1464 printf("Error %d:\n", n + 1);
1465 smart_print_errdata(&data->errdata[i--]);
1466 if (i == -1)
1467 i = 4;
1468 } while (++n < (nerr > 5 ? 5 : nerr));
1469 } else if (strcmp(argv[1], "comp") == 0) {
1470 struct smart_log_comp *data = (struct smart_log_comp *)inbuf;
1471 u_int8_t *newbuf;
1472 int i, n, nerr, nsect;
1473
1474 if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1475 errx(1, "Checksum mismatch");
1476
1477 if (data->index == 0) {
1478 printf("No log entries\n");
1479 return;
1480 }
1481
1482 i = data->index - 1;
1483 nerr = letoh16(data->err_cnt);
1484 printf("Error count: %d\n", nerr);
1485 /*
1486 * From the first sector we obtain total error number
1487 * and calculate necessary number of sectors to read.
1488 * All read error data structures form a circular
1489 * buffer and we pass from the most recent record to
1490 * the latest one.
1491 */
1492 nsect = nerr / 5 + (nerr % 5 != 0 ? 1 : 0);
1493 if ((newbuf = calloc(nsect, DEV_BSIZE)) == NULL)
1494 err(1, "calloc()");
1495 memset(&req, 0, sizeof(req));
1496 req.flags = ATACMD_READ;
1497 req.command = ATAPI_SMART;
1498 req.features = ATA_SMART_READLOG;
1499 req.sec_count = nsect;
1500 req.sec_num = SMART_READLOG_COMP;
1501 req.cylinder = 0xc24f;
1502 req.databuf = (caddr_t)newbuf;
1503 req.datalen = nsect * DEV_BSIZE;
1504 req.timeout = 1000;
1505 ata_command(&req);
1506
1507 n = 0;
1508 data = (struct smart_log_comp *)
1509 (newbuf + (nsect - 1) * DEV_BSIZE);
1510 do {
1511 printf("Error %d:\n", n + 1);
1512 smart_print_errdata(&data->errdata[i-- % 5]);
1513 if (i == -1)
1514 i = 254;
1515 if (i % 5 == 4)
1516 data = (struct smart_log_comp *)
1517 (newbuf + (i / 5) * DEV_BSIZE);
1518 } while (++n < nerr);
1519 } else if (strcmp(argv[1], "selftest") == 0) {
1520 struct smart_log_self *data = (struct smart_log_self *)inbuf;
1521 int i, n;
1522
1523 if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1524 errx(1, "Checksum mismatch");
1525
1526 if (data->index == 0) {
1527 printf("No log entries\n");
1528 return;
1529 }
1530
1531 /* circular buffer of 21 entries */
1532 i = data->index - 1;
1533 n = 0;
1534 do {
1535 /* don't print empty entries */
1536 if ((data->desc[i].time1 | data->desc[i].time2) == 0)
1537 break;
1538 printf("Test %d\n", n + 1);
1539 printf(" LBA Low: 0x%x\n", data->desc[i].reg_lbalo);
1540 printf(" status: %s\n",
1541 valtostr(SMART_SELFSTAT_STAT(
1542 data->desc[i].selfstat),
1543 smart_selfstat, "?"));
1544 printf(" timestamp: %d\n",
1545 MAKEWORD(data->desc[i].time1,
1546 data->desc[i].time2));
1547 printf(" failure checkpoint byte: 0x%x\n",
1548 data->desc[i].chkpnt);
1549 printf(" failing LBA: 0x%x\n",
1550 MAKEDWORD(data->desc[i].lbafail1,
1551 data->desc[i].lbafail2,
1552 data->desc[i].lbafail3,
1553 data->desc[i].lbafail4));
1554 if (--i == -1)
1555 i = 20;
1556 } while (++n < 21);
1557 }
1558
1559 return;
1560 usage:
1561 fprintf(stderr, "usage: %s device %s log\n", __progname, argv[0]);
1562 exit(1);
1563 }
1564
1565 #define SMART_PRINTREG(str, reg) \
1566 printf(str "0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\n", \
1567 data->cmd[0].reg, \
1568 data->cmd[1].reg, \
1569 data->cmd[2].reg, \
1570 data->cmd[3].reg, \
1571 data->cmd[4].reg)
1572
1573 void
smart_print_errdata(struct smart_log_errdata * data)1574 smart_print_errdata(struct smart_log_errdata *data)
1575 {
1576 printf(" error register: 0x%x\n", data->err.reg_err);
1577 printf(" sector count register: 0x%x\n", data->err.reg_seccnt);
1578 printf(" LBA Low register: 0x%x\n", data->err.reg_lbalo);
1579 printf(" LBA Mid register: 0x%x\n", data->err.reg_lbamid);
1580 printf(" LBA High register: 0x%x\n", data->err.reg_lbahi);
1581 printf(" device register: 0x%x\n", data->err.reg_dev);
1582 printf(" status register: 0x%x\n", data->err.reg_stat);
1583 printf(" state: %s\n", valtostr(data->err.state, smart_logstat, "?"));
1584 printf(" timestamp: %d\n", MAKEWORD(data->err.time1,
1585 data->err.time2));
1586 printf(" history:\n");
1587 SMART_PRINTREG("\tcontrol register:\t", reg_ctl);
1588 SMART_PRINTREG("\tfeatures register:\t", reg_feat);
1589 SMART_PRINTREG("\tsector count register:\t", reg_seccnt);
1590 SMART_PRINTREG("\tLBA Low register:\t", reg_lbalo);
1591 SMART_PRINTREG("\tLBA Mid register:\t", reg_lbamid);
1592 SMART_PRINTREG("\tLBA High register:\t", reg_lbahi);
1593 SMART_PRINTREG("\tdevice register:\t", reg_dev);
1594 SMART_PRINTREG("\tcommand register:\t", reg_cmd);
1595 printf("\ttimestamp:\t\t"
1596 "%d\t%d\t%d\t%d\t%d\n",
1597 MAKEDWORD(data->cmd[0].time1, data->cmd[0].time2,
1598 data->cmd[0].time3, data->cmd[0].time4),
1599 MAKEDWORD(data->cmd[1].time1, data->cmd[1].time2,
1600 data->cmd[1].time3, data->cmd[1].time4),
1601 MAKEDWORD(data->cmd[2].time1, data->cmd[2].time2,
1602 data->cmd[2].time3, data->cmd[2].time4),
1603 MAKEDWORD(data->cmd[3].time1, data->cmd[3].time2,
1604 data->cmd[3].time3, data->cmd[3].time4),
1605 MAKEDWORD(data->cmd[4].time1, data->cmd[4].time2,
1606 data->cmd[4].time3, data->cmd[4].time4));
1607 }
1608
1609 int
smart_cksum(u_int8_t * data,size_t len)1610 smart_cksum(u_int8_t *data, size_t len)
1611 {
1612 u_int8_t sum = 0;
1613 size_t i;
1614
1615 for (i = 0; i < len; i++)
1616 sum += data[i];
1617
1618 return (sum);
1619 }
1620
1621 /*
1622 * Read device attributes
1623 */
1624 void
device_attr(int argc,char * argv[])1625 device_attr(int argc, char *argv[])
1626 {
1627 struct atareq req;
1628 struct smart_read attr_val;
1629 struct smart_threshold attr_thr;
1630 struct attribute *attr;
1631 struct threshold *thr;
1632 const char *attr_name;
1633 static const char hex[]="0123456789abcdef";
1634 char raw[13], *format;
1635 int i, k, threshold_exceeded = 0;
1636
1637 if (argc != 1)
1638 goto usage;
1639
1640 memset(&req, 0, sizeof(req));
1641 memset(&attr_val, 0, sizeof(attr_val)); /* XXX */
1642 memset(&attr_thr, 0, sizeof(attr_thr)); /* XXX */
1643
1644 req.command = ATAPI_SMART;
1645 req.cylinder = 0xc24f; /* LBA High = C2h, LBA Mid = 4Fh */
1646 req.timeout = 1000;
1647
1648 req.features = ATA_SMART_READ;
1649 req.flags = ATACMD_READ;
1650 req.databuf = (caddr_t)&attr_val;
1651 req.datalen = sizeof(attr_val);
1652 ata_command(&req);
1653
1654 req.features = ATA_SMART_THRESHOLD;
1655 req.flags = ATACMD_READ;
1656 req.databuf = (caddr_t)&attr_thr;
1657 req.datalen = sizeof(attr_thr);
1658 ata_command(&req);
1659
1660 if (smart_cksum((u_int8_t *)&attr_val, sizeof(attr_val)) != 0)
1661 errx(1, "Checksum mismatch (attr_val)");
1662
1663 if (smart_cksum((u_int8_t *)&attr_thr, sizeof(attr_thr)) != 0)
1664 errx(1, "Checksum mismatch (attr_thr)");
1665
1666 attr = attr_val.attribute;
1667 thr = attr_thr.threshold;
1668
1669 printf("Attributes table revision: %d\n", attr_val.revision);
1670 printf("ID\tAttribute name\t\t\tThreshold\tValue\tRaw\n");
1671 for (i = 0; i < 30; i++) {
1672 if (thr[i].id != 0 && thr[i].id == attr[i].id) {
1673 attr_name = valtostr(thr[i].id, ibm_attr_names,
1674 "Unknown");
1675
1676 for (k = 0; k < 6; k++) {
1677 u_int8_t b;
1678 b = attr[i].raw[6 - k];
1679 raw[k + k] = hex[b >> 4];
1680 raw[k + k + 1] = hex[b & 0x0f];
1681 }
1682 raw[k + k] = '\0';
1683 if (thr[i].value >= attr[i].value) {
1684 ++threshold_exceeded;
1685 format = "%3d *%-32.32s %3d\t\t%3d\t0x%s\n";
1686 } else {
1687 format = "%3d\t%-32.32s %3d\t\t%3d\t0x%s\n";
1688 }
1689 printf(format, thr[i].id, attr_name,
1690 thr[i].value, attr[i].value, raw);
1691 }
1692 }
1693 if (threshold_exceeded)
1694 fprintf(stderr, "One or more threshold values exceeded!\n");
1695
1696 return;
1697
1698 usage:
1699 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1700 exit(1);
1701 }
1702
1703 /*
1704 * Set the automatic acoustic management on the disk.
1705 */
1706 void
device_acoustic(int argc,char * argv[])1707 device_acoustic(int argc, char *argv[])
1708 {
1709 u_char acoustic;
1710 struct atareq req;
1711 const char *errstr;
1712
1713 if (argc != 2)
1714 goto usage;
1715
1716 acoustic = strtonum(argv[1], 0, 126, &errstr);
1717 if (errstr)
1718 errx(1, "Acoustic management value \"%s\" is %s "
1719 "(valid values: 0 - 126)", argv[1], errstr);
1720
1721 memset(&req, 0, sizeof(req));
1722
1723 req.sec_count = acoustic + 0x80;
1724
1725 req.command = SET_FEATURES ;
1726 req.features = WDSF_AAM_EN ;
1727 req.timeout = 1000;
1728
1729 ata_command(&req);
1730
1731 return;
1732
1733 usage:
1734 fprintf(stderr, "usage: %s device %s acoustic-management-level\n",
1735 __progname, argv[0]);
1736 exit(1);
1737 }
1738
1739 /*
1740 * Set the advanced power managmement on the disk. Power management
1741 * levels are translated from user-range 0-253 to ATAPI levels 1-0xFD
1742 * to keep a uniform interface to the user.
1743 */
1744 void
device_apm(int argc,char * argv[])1745 device_apm(int argc, char *argv[])
1746 {
1747 u_char power;
1748 struct atareq req;
1749 const char *errstr;
1750
1751 if (argc != 2)
1752 goto usage;
1753
1754 power = strtonum(argv[1], 0, 253, &errstr);
1755 if (errstr)
1756 errx(1, "Advanced power management value \"%s\" is %s "
1757 "(valid values: 0 - 253)", argv[1], errstr);
1758
1759 memset(&req, 0, sizeof(req));
1760
1761 req.sec_count = power + 0x01;
1762
1763 req.command = SET_FEATURES ;
1764 req.features = WDSF_APM_EN ;
1765 req.timeout = 1000;
1766
1767 ata_command(&req);
1768
1769 return;
1770
1771 usage:
1772 fprintf(stderr, "usage: %s device %s power-management-level\n",
1773 __progname, argv[0]);
1774 exit(1);
1775 }
1776
1777 /*
1778 * En/disable features (the automatic acoustic managmement, Advanced Power
1779 * Management) on the disk.
1780 */
1781 void
device_feature(int argc,char * argv[])1782 device_feature(int argc, char *argv[])
1783 {
1784 struct atareq req;
1785
1786 if (argc != 1)
1787 goto usage;
1788
1789 memset(&req, 0, sizeof(req));
1790
1791 req.command = SET_FEATURES ;
1792
1793 if (strcmp(argv[0], "acousticdisable") == 0)
1794 req.features = WDSF_AAM_DS;
1795 else if (strcmp(argv[0], "readaheadenable") == 0)
1796 req.features = WDSF_READAHEAD_EN;
1797 else if (strcmp(argv[0], "readaheaddisable") == 0)
1798 req.features = WDSF_READAHEAD_DS;
1799 else if (strcmp(argv[0], "writecacheenable") == 0)
1800 req.features = WDSF_EN_WR_CACHE;
1801 else if (strcmp(argv[0], "writecachedisable") == 0)
1802 req.features = WDSF_WRITE_CACHE_DS;
1803 else if (strcmp(argv[0], "apmdisable") == 0)
1804 req.features = WDSF_APM_DS;
1805 else if (strcmp(argv[0], "podenable") == 0)
1806 req.features = WDSF_POD_EN;
1807 else if (strcmp(argv[0], "poddisable") == 0)
1808 req.features = WDSF_POD_DS;
1809 else if (strcmp(argv[0], "puisenable") == 0)
1810 req.features = WDSF_PUIS_EN;
1811 else if (strcmp(argv[0], "puisdisable") == 0)
1812 req.features = WDSF_PUIS_DS;
1813 else if (strcmp(argv[0], "puisspinup") == 0)
1814 req.features = WDSF_PUIS_SPINUP;
1815 else
1816 goto usage;
1817
1818 req.timeout = 1000;
1819
1820 ata_command(&req);
1821
1822 return;
1823
1824 usage:
1825 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1826 exit(1);
1827 }
1828
1829 /*
1830 * Set the idle timer on the disk. Set it for either idle mode or
1831 * standby mode, depending on how we were invoked.
1832 */
1833 void
device_setidle(int argc,char * argv[])1834 device_setidle(int argc, char *argv[])
1835 {
1836 unsigned long idle;
1837 struct atareq req;
1838 char *end;
1839
1840 if (argc != 2)
1841 goto usage;
1842
1843 idle = strtoul(argv[1], &end, 0);
1844
1845 if (*end != '\0' || idle > 19800)
1846 errx(1, "Invalid idle time: \"%s\" "
1847 "(valid values: 1 - 19800)", argv[1]);
1848
1849 if (idle != 0 && idle < 5)
1850 errx(1, "Idle timer must be at least 5 seconds");
1851
1852 memset(&req, 0, sizeof(req));
1853
1854 if (idle <= 240 * 5)
1855 req.sec_count = idle / 5;
1856 else
1857 req.sec_count = idle / (30 * 60) + 240;
1858
1859 if (strcmp(argv[0], "setstandby") == 0)
1860 req.command = WDCC_STANDBY;
1861 else if (strcmp(argv[0], "setidle") == 0)
1862 req.command = WDCC_IDLE;
1863 else
1864 goto usage;
1865 req.timeout = 1000;
1866
1867 ata_command(&req);
1868
1869 return;
1870
1871 usage:
1872 fprintf(stderr, "usage: %s device %s %s\n", __progname, argv[0],
1873 (strcmp(argv[0], "setidle") == 0) ? "idle-timer" : "standby-timer");
1874 exit(1);
1875 }
1876
1877 /*
1878 * Query the device for the current power mode
1879 */
1880 void
device_checkpower(int argc,char * argv[])1881 device_checkpower(int argc, char *argv[])
1882 {
1883 struct atareq req;
1884
1885 if (argc != 1)
1886 goto usage;
1887
1888 memset(&req, 0, sizeof(req));
1889
1890 req.command = WDCC_CHECK_PWR;
1891 req.timeout = 1000;
1892 req.flags = ATACMD_READREG;
1893
1894 ata_command(&req);
1895
1896 printf("Current power status: ");
1897
1898 switch (req.sec_count) {
1899 case 0x00:
1900 printf("Standby mode\n");
1901 break;
1902 case 0x80:
1903 printf("Idle mode\n");
1904 break;
1905 case 0xff:
1906 printf("Active mode\n");
1907 break;
1908 default:
1909 printf("Unknown power code (%02x)\n", req.sec_count);
1910 }
1911
1912 return;
1913 usage:
1914 fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1915 exit(1);
1916 }
1917