xref: /openbsd-src/sbin/atactl/atactl.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: atactl.c,v 1.41 2008/08/10 17:40:10 sobrado 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>
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 *);
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 	{ NULL, 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 	{ NULL, 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 	{ NULL, 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 	{ NULL, 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 	{ NULL, 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 	{ 7, "Seek Error Rate" },
305 	{ 8, "Seek Time Performance" },
306 	{ 9, "Power-on Hours Count" },
307 	{ 10, "Spin Retry Count" },
308 	{ 12, "Device Power Cycle Count" },
309 	{ 192, "Power-off Retract Count" },
310 	{ 193, "Load Cycle Count" },
311 	{ 194, "Temperature" },
312 	{ 196, "Reallocation Event Count" },
313 	{ 197, "Current Pending Sector Count" },
314 	{ 198, "Off-line Scan Uncorrectable Sector Count" },
315 	{ 199, "Ultra DMA CRC Error Count" },
316 	{ 0, NULL },
317 };
318 
319 #define MAKEWORD(b1, b2) \
320 	(b2 << 8 | b1)
321 #define MAKEDWORD(b1, b2, b3, b4) \
322 	(b4 << 24 | b3 << 16 | b2 << 8 | b1)
323 
324 int
325 main(int argc, char *argv[])
326 {
327 	struct command	*cmdp;
328 	char dvname_store[MAXPATHLEN];
329 
330 	if (argc < 2)
331 		usage();
332 
333 	/*
334 	 * Open the device
335 	 */
336 	fd = opendisk(argv[1], O_RDWR, dvname_store, sizeof(dvname_store), 0);
337 	if (fd == -1) {
338 		if (errno == ENOENT) {
339 			/*
340 			 * Device doesn't exist.  Probably trying to open
341 			 * a device which doesn't use disk semantics for
342 			 * device name.  Try again, specifying "cooked",
343 			 * which leaves off the "r" in front of the device's
344 			 * name.
345 			 */
346 			fd = opendisk(argv[1], O_RDWR, dvname_store,
347 			    sizeof(dvname_store), 1);
348 			if (fd == -1)
349 				err(1, "%s", argv[1]);
350 		} else
351 			err(1, "%s", argv[1]);
352 	}
353 
354 	/* Skip program name and device name. */
355 	if (argc != 2) {
356 		argv += 2;
357 		argc -= 2;
358 	} else {
359 		argv[1] = "identify";
360 		argv += 1;
361 		argc -= 1;
362 	}
363 
364 	/* Look up and call the command. */
365 	for (cmdp = commands; cmdp->cmd_name != NULL; cmdp++)
366 		if (strcmp(argv[0], cmdp->cmd_name) == 0)
367 			break;
368 	if (cmdp->cmd_name == NULL)
369 		errx(1, "unknown command: %s", argv[0]);
370 
371 	(cmdp->cmd_func)(argc, argv);
372 
373 	return (0);
374 }
375 
376 __dead void
377 usage(void)
378 {
379 
380 	fprintf(stderr, "usage: %s device [command [arg]]\n", __progname);
381 	exit(1);
382 }
383 
384 /*
385  * Wrapper that calls ATAIOCCOMMAND and checks for errors
386  */
387 void
388 ata_command(struct atareq *req)
389 {
390 	if (ioctl(fd, ATAIOCCOMMAND, req) == -1)
391 		err(1, "ATAIOCCOMMAND failed");
392 
393 	switch (req->retsts) {
394 
395 	case ATACMD_OK:
396 		return;
397 	case ATACMD_TIMEOUT:
398 		errx(1, "ATA command timed out");
399 	case ATACMD_DF:
400 		errx(1, "ATA device returned a Device Fault");
401 	case ATACMD_ERROR:
402 		if (req->error & WDCE_ABRT)
403 			errx(1, "ATA device returned Aborted Command");
404 		else
405 			errx(1, "ATA device returned error register %0x",
406 			    req->error);
407 	default:
408 		errx(1, "ATAIOCCOMMAND returned unknown result code %d",
409 		    req->retsts);
410 	}
411 }
412 
413 /*
414  * Print out strings associated with particular bitmasks
415  */
416 void
417 print_bitinfo(const char *f, u_int bits, struct bitinfo *binfo)
418 {
419 
420 	for (; binfo->bitmask != NULL; binfo++)
421 		if (bits & binfo->bitmask)
422 			printf(f, binfo->string);
423 }
424 
425 /*
426  * strtoval():
427  *    returns value associated with given string,
428  *    if no value found -1 is returned.
429  */
430 int
431 strtoval(const char *str, struct valinfo *vinfo)
432 {
433 	for (; vinfo->string != NULL; vinfo++)
434 		if (strcmp(str, vinfo->string) == 0)
435 			return (vinfo->value);
436 	return (-1);
437 }
438 
439 /*
440  * valtostr():
441  *    returns string associated with given value,
442  *    if no string found NULL is returned.
443  */
444 const char *
445 valtostr(int val, struct valinfo *vinfo)
446 {
447 	for (; vinfo->string != NULL; vinfo++)
448 		if (val == vinfo->value)
449 			return (vinfo->string);
450 	return (NULL);
451 }
452 
453 /*
454  * DEVICE COMMANDS
455  */
456 
457 /*
458  * device dump:
459  *
460  * extract issued ATA requests from the log buffer
461  */
462 void
463 device_dump(int argc, char *argv[])
464 {
465 	unsigned char buf[131072];
466 	atagettrace_t agt;
467 	unsigned int total;
468 	unsigned int p = 0;
469 	int type;
470 	const char *types[] = { NULL, "status", "error", "ATAPI",
471 	    "ATAPI done", "ATA cmd", "ATA", "select slave",
472 	    "select master", "register read", "ATA LBA48" };
473 	int num_types = sizeof(types) / sizeof(types[0]);
474 	int info;
475 	int entrysize;
476 	int i;
477 	int flags;
478 
479 	if (argc != 1)
480 		goto usage;
481 
482 	memset(&agt, 0, sizeof(agt));
483 	agt.buf_size = sizeof(buf);
484 	agt.buf = buf;
485 
486 	if (ioctl(fd, ATAIOGETTRACE, &agt) == -1)
487 		err(1, "ATAIOGETTRACE failed");
488 
489 	total = agt.bytes_copied;
490 
491 	/* Parse entries */
492 	while (p < total) {
493 		type = buf[p++];
494 		if (p >= total)
495 			return;
496 		if (type <= 0 || type >= num_types)
497 			return;
498 
499 		info = buf[p++];
500 		if (p >= total)
501 			return;
502 		entrysize = (info & 0x1f);
503 
504 		printf ("ch %d", (info >> 5) & 0x7);
505 		printf(": %s", types[type]);
506 
507 		switch (type) {
508 		case WDCEVENT_STATUS:
509 			if (entrysize != 1)
510 				return;
511 
512 			printf(": 0x%x", buf[p]);
513 			if (buf[p] & WDCS_BSY)
514 				printf(" BSY");
515 			if (buf[p] & WDCS_DRDY)
516 				printf(" DRDY");
517 			if (buf[p] & WDCS_DWF)
518 				printf(" DWF");
519 			if (buf[p] & WDCS_DSC)
520 				printf(" DSC");
521 			if (buf[p] & WDCS_DRQ)
522 				printf(" DRQ");
523 			if (buf[p] & WDCS_CORR)
524 				printf(" CORR");
525 			if (buf[p] & WDCS_IDX)
526 				printf(" IDX");
527 			if (buf[p] & WDCS_ERR)
528 				printf(" ERR");
529 
530 			p++;
531 			entrysize = 0;
532 			break;
533 		case WDCEVENT_ERROR:
534 			if (entrysize != 1)
535 				return;
536 
537 			printf(": 0x%x", buf[p]);
538 			if (buf[p] & WDCE_BBK)
539 				printf(" BBK/CRC");
540 			if (buf[p] & WDCE_UNC)
541 				printf(" UNC");
542 			if (buf[p] & WDCE_MC)
543 				printf(" MC");
544 			if (buf[p] & WDCE_IDNF)
545 				printf(" IDNF");
546 			if (buf[p] & WDCE_MCR)
547 				printf(" MCR");
548 			if (buf[p] & WDCE_ABRT)
549 				printf(" ABRT");
550 			if (buf[p] & WDCE_TK0NF)
551 				printf(" TK0NF");
552 			if (buf[p] & WDCE_AMNF)
553 				printf(" AMNF");
554 
555 			p++;
556 			entrysize = 0;
557 			break;
558 		case WDCEVENT_ATAPI_CMD:
559 			if (entrysize < 2 || p + 2 > total)
560 				return;
561 
562 			flags = (buf[p] << 8) + buf[p + 1];
563 			printf(": flags 0x%x", flags);
564 			if (flags & 0x0100)
565 				printf(" MEDIA");
566 			if (flags & 0x0080)
567 				printf(" SENSE");
568 			if (flags & 0x0040)
569 				printf(" DMA");
570 			if (flags & 0x0020)
571 				printf(" POLL");
572 			if (flags & 0x0004)
573 				printf(" TIMEOUT");
574 			if (flags & 0x0002)
575 				printf(" ATAPI");
576 
577 			p += 2;
578 			entrysize -= 2;
579 			break;
580 		case WDCEVENT_ATAPI_DONE:
581 			if (entrysize != 3 || p + 3 > total)
582 				return;
583 
584 			flags = (buf[p] << 8) + buf[p + 1];
585 			printf(": flags 0x%x", flags);
586 			if (flags & 0x0100)
587 				printf(" MEDIA");
588 			if (flags & 0x0080)
589 				printf(" SENSE");
590 			if (flags & 0x0040)
591 				printf(" DMA");
592 			if (flags & 0x0020)
593 				printf(" POLL");
594 			if (flags & 0x0004)
595 				printf(" TIMEOUT");
596 			if (flags & 0x0002)
597 				printf(" ATAPI");
598 
599 			printf(", error 0x%x", buf[p + 2]);
600 			switch (buf[p + 2]) {
601 			case 1:
602 				printf(" (sense)");
603 				break;
604 			case 2:
605 				printf(" (driver failure)");
606 				break;
607 			case 3:
608 				printf(" (timeout)");
609 				break;
610 			case 4:
611 				printf(" (busy)");
612 				break;
613 			case 5:
614 				printf(" (ATAPI sense)");
615 				break;
616 			case 8:
617 				printf(" (reset)");
618 				break;
619 			}
620 
621 			p += 3;
622 			entrysize  = 0;
623 			break;
624 		case WDCEVENT_ATA_LONG:
625 			if (entrysize != 7 || p + 7 > total)
626 				return;
627 
628 			printf(": ");
629 			switch (buf[p + 6]) {
630 			case WDCC_READDMA:
631 				printf("READ DMA");
632 				break;
633 			case WDCC_WRITEDMA:
634 				printf("WRITE DMA");
635 				break;
636 			default:
637 				printf("CMD 0x%x", buf[p + 6]);
638 			}
639 			printf(" head %d, precomp %d, cyl_hi %d, "
640 			    "cyl_lo %d, sec %d, cnt %d",
641 			    buf[p], buf[p + 1], buf[p + 2], buf[p + 3],
642 			    buf[p + 4], buf[p + 5]);
643 
644 			p += 7;
645 			entrysize = 0;
646 			break;
647 		case WDCEVENT_REG:
648 			if (entrysize != 3 || p + 3 > total)
649 				return;
650 
651 			switch (buf[p]) {
652 			case 1:
653 				printf(": error");
654 				break;
655 			case 2:
656 				printf(": ireason");
657 				break;
658 			case 3:
659 				printf(": lba_lo");
660 				break;
661 			case 4:
662 				printf(": lba_mi");
663 				break;
664 			case 5:
665 				printf(": lba_hi");
666 				break;
667 			case 6:
668 				printf(": sdh");
669 				break;
670 			case 7:
671 				printf(": status");
672 				break;
673 			case 8:
674 				printf(": altstatus");
675 				break;
676 			default:
677 				printf(": unknown register %d", buf[p]);
678 			}
679 			printf(": 0x%x", (buf[p + 1] << 8) + buf[p + 2]);
680 
681 			p += 3;
682 			entrysize = 0;
683 			break;
684 		case WDCEVENT_ATA_EXT:
685 			if (entrysize != 9 || p + 9 > total)
686 				return;
687 
688 			printf(": ");
689 			switch (buf[p + 8]) {
690 			case WDCC_READDMA_EXT:
691 				printf("READ DMA EXT");
692 				break;
693 			case WDCC_WRITEDMA_EXT:
694 				printf("WRITE DMA EXT");
695 				break;
696 			default:
697 				printf("CMD 0x%x", buf[p + 8]);
698 			}
699 			printf(" lba_hi1 %d, lba_hi2 %d, "
700 			    "lba_mi1 %d, lba_mi2 %d, lba_lo1 %d, lba_lo2 %d, "
701 			    "count1 %d, count2 %d",
702 			    buf[p], buf[p + 1], buf[p + 2], buf[p + 3],
703 			    buf[p + 4], buf[p + 5], buf[p + 6],
704 			    buf[p + 7]);
705 
706 			p += 9;
707 			entrysize = 0;
708 			break;
709 		}
710 
711 		if (entrysize > 0)
712 			printf(":");
713 		for (i = 0; i < entrysize; i++) {
714 			printf (" 0x%02x", buf[p]);
715 			if (++p >= total)
716 				break;
717 		}
718 		printf("\n");
719 	}
720 
721 	return;
722 
723 usage:
724 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
725 	exit(1);
726 }
727 
728 /*
729  * device_identify:
730  *
731  *	Display the identity of the device
732  */
733 void
734 device_identify(int argc, char *argv[])
735 {
736 	struct ataparams *inqbuf;
737 	struct atareq req;
738 	char inbuf[DEV_BSIZE];
739 	u_int64_t capacity;
740 	u_int8_t *s;
741 
742 	if (argc != 1)
743 		goto usage;
744 
745 	memset(&inbuf, 0, sizeof(inbuf));
746 	memset(&req, 0, sizeof(req));
747 
748 	inqbuf = (struct ataparams *) inbuf;
749 
750 	req.flags = ATACMD_READ;
751 	req.command = WDCC_IDENTIFY;
752 	req.databuf = (caddr_t) inbuf;
753 	req.datalen = sizeof(inbuf);
754 	req.timeout = 1000;
755 
756 	ata_command(&req);
757 
758 	if (BYTE_ORDER == BIG_ENDIAN) {
759 		swap16_multi((u_int16_t *)inbuf, 10);
760 		swap16_multi(((u_int16_t *)inbuf) + 20, 3);
761 		swap16_multi(((u_int16_t *)inbuf) + 47, sizeof(inbuf) / 2 - 47);
762 	}
763 
764 	if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
765 	      ((inqbuf->atap_model[0] == 'N' &&
766 		  inqbuf->atap_model[1] == 'E') ||
767 	       (inqbuf->atap_model[0] == 'F' &&
768 		  inqbuf->atap_model[1] == 'X')))) {
769 		swap16_multi((u_int16_t *)(inqbuf->atap_model),
770 		    sizeof(inqbuf->atap_model) / 2);
771 		swap16_multi((u_int16_t *)(inqbuf->atap_serial),
772 		    sizeof(inqbuf->atap_serial) / 2);
773 		swap16_multi((u_int16_t *)(inqbuf->atap_revision),
774 		    sizeof(inqbuf->atap_revision) / 2);
775 	}
776 
777 	/*
778 	 * Strip blanks off of the info strings.
779 	 */
780 
781 	for (s = &inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1];
782 	    s >= inqbuf->atap_model && *s == ' '; s--)
783 		*s = '\0';
784 
785 	for (s = &inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1];
786 	    s >= inqbuf->atap_revision && *s == ' '; s--)
787 		*s = '\0';
788 
789 	for (s = &inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1];
790 	    s >= inqbuf->atap_serial && *s == ' '; s--)
791 		*s = '\0';
792 
793 	printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n",
794 	    (int) sizeof(inqbuf->atap_model), inqbuf->atap_model,
795 	    (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision,
796 	    (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial);
797 
798 	printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
799 	       "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
800 	       "removable");
801 
802 	if (inqbuf->atap_cmd2_en & ATAPI_CMD2_48AD)
803 		capacity = ((u_int64_t)inqbuf->atap_max_lba[3] << 48) |
804 		    ((u_int64_t)inqbuf->atap_max_lba[2] << 32) |
805 		    ((u_int64_t)inqbuf->atap_max_lba[1] << 16) |
806 		    (u_int64_t)inqbuf->atap_max_lba[0];
807 	else
808 		capacity = (inqbuf->atap_capacity[1] << 16) |
809 		    inqbuf->atap_capacity[0];
810 	printf("Cylinders: %d, heads: %d, sec/track: %d, total "
811 	    "sectors: %llu\n", inqbuf->atap_cylinders,
812 	    inqbuf->atap_heads, inqbuf->atap_sectors, capacity);
813 
814 	if ((inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ) &&
815 	    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
816 		printf("Device supports command queue depth of %d\n",
817 		    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
818 
819 	printf("Device capabilities:\n");
820 	print_bitinfo("\t%s\n", inqbuf->atap_capabilities1, ata_caps);
821 
822 	if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
823 		printf("Device supports the following standards:\n");
824 		print_bitinfo("%s ", inqbuf->atap_ata_major, ata_vers);
825 		printf("\n");
826 	}
827 
828 	if ((inqbuf->atap_cmd_set1 & WDC_CMD1_SEC) &&
829 	    inqbuf->atap_mpasswd_rev != 0 &&
830 	    inqbuf->atap_mpasswd_rev != 0xffff)
831 		printf("Master password revision code 0x%04x\n",
832 		    inqbuf->atap_mpasswd_rev);
833 
834 	if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
835 	    inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
836 		printf("Device supports the following command sets:\n");
837 		print_bitinfo("\t%s\n", inqbuf->atap_cmd_set1, ata_cmd_set1);
838 		print_bitinfo("\t%s\n", inqbuf->atap_cmd_set2, ata_cmd_set2);
839 		print_bitinfo("\t%s\n", inqbuf->atap_cmd_ext, ata_cmd_ext);
840 	}
841 
842 	if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
843 		printf("Device has enabled the following command "
844 		    "sets/features:\n");
845 		print_bitinfo("\t%s\n", inqbuf->atap_cmd1_en, ata_cmd_set1);
846 		print_bitinfo("\t%s\n", inqbuf->atap_cmd2_en, ata_cmd_set2);
847 	}
848 
849 	return;
850 
851 usage:
852 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
853 	exit(1);
854 }
855 
856 /*
857  * device idle:
858  *
859  * issue the IDLE IMMEDIATE command to the drive
860  */
861 void
862 device_idle(int argc, char *argv[])
863 {
864 	struct atareq req;
865 
866 	if (argc != 1)
867 		goto usage;
868 
869 	memset(&req, 0, sizeof(req));
870 
871 	if (strcmp(argv[0], "idle") == 0)
872 		req.command = WDCC_IDLE_IMMED;
873 	else if (strcmp(argv[0], "standby") == 0)
874 		req.command = WDCC_STANDBY_IMMED;
875 	else
876 		req.command = WDCC_SLEEP;
877 
878 	req.timeout = 1000;
879 
880 	ata_command(&req);
881 
882 	return;
883 usage:
884 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
885 	exit(1);
886 }
887 
888 /*
889  * SECURITY SET PASSWORD command
890  */
891 void
892 device_sec_setpass(int argc, char *argv[])
893 {
894 	struct atareq req;
895 	struct sec_password pwd;
896 	char *pass, inbuf[DEV_BSIZE];
897 	struct ataparams *inqbuf = (struct ataparams *)inbuf;
898 
899 	if (argc < 2)
900 		goto usage;
901 
902 	memset(&pwd, 0, sizeof(pwd));
903 
904 	if (strcmp(argv[1], "user") == 0 && argc == 3)
905 		pwd.ctrl |= SEC_PASSWORD_USER;
906 	else if (strcmp(argv[1], "master") == 0 && argc == 2)
907 		pwd.ctrl |= SEC_PASSWORD_MASTER;
908 	else
909 		goto usage;
910 	if (argc == 3) {
911 		if (strcmp(argv[2], "high") == 0)
912 			pwd.ctrl |= SEC_LEVEL_HIGH;
913 		else if (strcmp(argv[2], "maximum") == 0)
914 			pwd.ctrl |= SEC_LEVEL_MAX;
915 		else
916 			goto usage;
917 	}
918 
919 	/*
920 	 * Issue IDENTIFY command to obtain master password
921 	 * revision code and decrement its value.
922 	 * The valid revision codes are 0x0001 through 0xfffe.
923 	 * If the device returns 0x0000 or 0xffff as a revision
924 	 * code then the master password revision code is not
925 	 * supported so don't touch it.
926 	 */
927 	memset(&inbuf, 0, sizeof(inbuf));
928 	memset(&req, 0, sizeof(req));
929 
930 	req.command = WDCC_IDENTIFY;
931 	req.timeout = 1000;
932 	req.flags = ATACMD_READ;
933 	req.databuf = (caddr_t)inbuf;
934 	req.datalen = sizeof(inbuf);
935 
936 	ata_command(&req);
937 
938 	pwd.revision = inqbuf->atap_mpasswd_rev;
939 	if (pwd.revision != 0 && pwd.revision != 0xffff && --pwd.revision == 0)
940 		pwd.revision = 0xfffe;
941 
942 	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 1);
943 	memcpy(pwd.password, pass, strlen(pass));
944 
945 	memset(&req, 0, sizeof(req));
946 
947 	req.command = ATA_SEC_SET_PASSWORD;
948 	req.timeout = 1000;
949 	req.flags = ATACMD_WRITE;
950 	req.databuf = (caddr_t)&pwd;
951 	req.datalen = sizeof(pwd);
952 
953 	ata_command(&req);
954 
955 	return;
956 usage:
957 	fprintf(stderr, "usage: %s device %s user high | maximum\n",
958 	    __progname, argv[0]);
959 	fprintf(stderr, "       %s device %s master\n", __progname, argv[0]);
960 	exit(1);
961 }
962 
963 /*
964  * SECURITY UNLOCK command
965  */
966 void
967 device_sec_unlock(int argc, char *argv[])
968 {
969 	struct atareq req;
970 	struct sec_password pwd;
971 	char *pass;
972 
973 	if (argc != 2)
974 		goto usage;
975 
976 	memset(&pwd, 0, sizeof(pwd));
977 
978 	if (strcmp(argv[1], "user") == 0)
979 		pwd.ctrl |= SEC_PASSWORD_USER;
980 	else if (strcmp(argv[1], "master") == 0)
981 		pwd.ctrl |= SEC_PASSWORD_MASTER;
982 	else
983 		goto usage;
984 
985 	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
986 	memcpy(pwd.password, pass, strlen(pass));
987 
988 	memset(&req, 0, sizeof(req));
989 
990 	req.command = ATA_SEC_UNLOCK;
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 | master\n", __progname,
1001 	    argv[0]);
1002 	exit(1);
1003 }
1004 
1005 /*
1006  * SECURITY ERASE UNIT command
1007  */
1008 void
1009 device_sec_erase(int argc, char *argv[])
1010 {
1011 	struct atareq req;
1012 	struct sec_password pwd;
1013 	char *pass;
1014 
1015 	if (argc < 2)
1016 		goto usage;
1017 
1018 	memset(&pwd, 0, sizeof(pwd));
1019 
1020 	if (strcmp(argv[1], "user") == 0)
1021 		pwd.ctrl |= SEC_PASSWORD_USER;
1022 	else if (strcmp(argv[1], "master") == 0)
1023 		pwd.ctrl |= SEC_PASSWORD_MASTER;
1024 	else
1025 		goto usage;
1026 	if (argc == 2)
1027 		pwd.ctrl |= SEC_ERASE_NORMAL;
1028 	else if (argc == 3 && strcmp(argv[2], "enhanced") == 0)
1029 		pwd.ctrl |= SEC_ERASE_ENHANCED;
1030 	else
1031 		goto usage;
1032 
1033 	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1034 	memcpy(pwd.password, pass, strlen(pass));
1035 
1036 	 /* Issue SECURITY ERASE PREPARE command before */
1037 	memset(&req, 0, sizeof(req));
1038 
1039 	req.command = ATA_SEC_ERASE_PREPARE;
1040 	req.timeout = 1000;
1041 
1042 	ata_command(&req);
1043 
1044 	memset(&req, 0, sizeof(req));
1045 
1046 	req.command = ATA_SEC_ERASE_UNIT;
1047 	req.timeout = 1000;
1048 	req.flags = ATACMD_WRITE;
1049 	req.databuf = (caddr_t)&pwd;
1050 	req.datalen = sizeof(pwd);
1051 
1052 	ata_command(&req);
1053 
1054 	return;
1055 usage:
1056 	fprintf(stderr, "usage: %s device %s user | master [enhanced]\n",
1057 	    __progname, argv[0]);
1058 	exit(1);
1059 }
1060 
1061 /*
1062  * SECURITY FREEZE LOCK command
1063  */
1064 void
1065 device_sec_freeze(int argc, char *argv[])
1066 {
1067 	struct atareq req;
1068 
1069 	if (argc != 1)
1070 		goto usage;
1071 
1072 	memset(&req, 0, sizeof(req));
1073 
1074 	req.command = ATA_SEC_FREEZE_LOCK;
1075 	req.timeout = 1000;
1076 
1077 	ata_command(&req);
1078 
1079 	return;
1080 usage:
1081 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1082 	exit(1);
1083 }
1084 
1085 /*
1086  * SECURITY DISABLE PASSWORD command
1087  */
1088 void
1089 device_sec_disablepass(int argc, char *argv[])
1090 {
1091 	struct atareq req;
1092 	struct sec_password pwd;
1093 	char *pass;
1094 
1095 	if (argc != 2)
1096 		goto usage;
1097 
1098 	memset(&pwd, 0, sizeof(pwd));
1099 
1100 	if (strcmp(argv[1], "user") == 0)
1101 		pwd.ctrl |= SEC_PASSWORD_USER;
1102 	else if (strcmp(argv[1], "master") == 0)
1103 		pwd.ctrl |= SEC_PASSWORD_MASTER;
1104 	else
1105 		goto usage;
1106 
1107 	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1108 	memcpy(pwd.password, pass, strlen(pass));
1109 
1110 	memset(&req, 0, sizeof(req));
1111 
1112 	req.command = ATA_SEC_DISABLE_PASSWORD;
1113 	req.timeout = 1000;
1114 	req.flags = ATACMD_WRITE;
1115 	req.databuf = (caddr_t)&pwd;
1116 	req.datalen = sizeof(pwd);
1117 
1118 	ata_command(&req);
1119 
1120 	return;
1121 usage:
1122 	fprintf(stderr, "usage: %s device %s user | master\n", __progname,
1123 	    argv[0]);
1124 	exit(1);
1125 }
1126 
1127 char *
1128 sec_getpass(int ident, int confirm)
1129 {
1130 	char *pass, buf[33];
1131 
1132 	if ((pass = getpass(ident ? "Master password:" :
1133 	    "User password:")) == NULL)
1134 		err(1, "getpass()");
1135 	if (strlen(pass) > 32)
1136 		errx(1, "password too long");
1137 	if (confirm) {
1138 		strlcpy(buf, pass, sizeof(buf));
1139 		if ((pass = getpass(ident ? "Retype master password:" :
1140 		    "Retype user password:")) == NULL)
1141 			err(1, "getpass()");
1142 		if (strcmp(pass, buf) != 0)
1143 			errx(1, "password mismatch");
1144 	}
1145 
1146 	return (pass);
1147 }
1148 
1149 /*
1150  * SMART ENABLE OPERATIONS command
1151  */
1152 void
1153 device_smart_enable(int argc, char *argv[])
1154 {
1155 	struct atareq req;
1156 
1157 	if (argc != 1)
1158 		goto usage;
1159 
1160 	memset(&req, 0, sizeof(req));
1161 
1162 	req.command = ATAPI_SMART;
1163 	req.cylinder = 0xc24f;
1164 	req.timeout = 1000;
1165 	req.features = ATA_SMART_EN;
1166 
1167 	ata_command(&req);
1168 
1169 	return;
1170 usage:
1171 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1172 	exit(1);
1173 }
1174 
1175 /*
1176  * SMART DISABLE OPERATIONS command
1177  */
1178 void
1179 device_smart_disable(int argc, char *argv[])
1180 {
1181 	struct atareq req;
1182 
1183 	if (argc != 1)
1184 		goto usage;
1185 
1186 	memset(&req, 0, sizeof(req));
1187 
1188 	req.command = ATAPI_SMART;
1189 	req.cylinder = 0xc24f;
1190 	req.timeout = 1000;
1191 	req.features = ATA_SMART_DS;
1192 
1193 	ata_command(&req);
1194 
1195 	return;
1196 usage:
1197 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1198 	exit(1);
1199 }
1200 
1201 /*
1202  * SMART STATUS command
1203  */
1204 void
1205 device_smart_status(int argc, char *argv[])
1206 {
1207 	struct atareq req;
1208 
1209 	if (argc != 1)
1210 		goto usage;
1211 
1212 	memset(&req, 0, sizeof(req));
1213 
1214 	req.command = ATAPI_SMART;
1215 	req.cylinder = 0xc24f;
1216 	req.timeout = 1000;
1217 	req.features = ATA_SMART_STATUS;
1218 
1219 	ata_command(&req);
1220 
1221 	if (req.cylinder == 0xc24f)
1222 		printf("No SMART threshold exceeded\n");
1223 	else if (req.cylinder == 0x2cf4) {
1224 		errx(2, "SMART threshold exceeded!");
1225 	} else {
1226 		errx(1, "Unknown response %02x!", req.cylinder);
1227 	}
1228 
1229 	return;
1230 usage:
1231 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1232 	exit(1);
1233 }
1234 
1235 /*
1236  * SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE command
1237  */
1238 void
1239 device_smart_autosave(int argc, char *argv[])
1240 {
1241 	struct atareq req;
1242 	int val;
1243 
1244 	if (argc != 2)
1245 		goto usage;
1246 
1247 	memset(&req, 0, sizeof(req));
1248 
1249 	req.command = ATAPI_SMART;
1250 	req.cylinder = 0xc24f;
1251 	req.timeout = 1000;
1252 	req.features = ATA_SMART_AUTOSAVE;
1253 	if ((val = strtoval(argv[1], smart_autosave)) == -1)
1254 		goto usage;
1255 	req.sec_num = val;
1256 
1257 	ata_command(&req);
1258 
1259 	return;
1260 usage:
1261 	fprintf(stderr, "usage: %s device %s enable | disable\n", __progname,
1262 	    argv[0]);
1263 	exit(1);
1264 }
1265 
1266 /*
1267  * SMART EXECUTE OFF-LINE IMMEDIATE command
1268  */
1269 void
1270 device_smart_offline(int argc, char *argv[])
1271 {
1272 	struct atareq req;
1273 	int val;
1274 
1275 	if (argc != 2)
1276 		goto usage;
1277 
1278 	memset(&req, 0, sizeof(req));
1279 
1280 	req.command = ATAPI_SMART;
1281 	req.cylinder = 0xc24f;
1282 	req.timeout = 1000;
1283 	req.features = ATA_SMART_OFFLINE;
1284 	if ((val = strtoval(argv[1], smart_offline)) == -1)
1285 		goto usage;
1286 	req.sec_num = val;
1287 
1288 	ata_command(&req);
1289 
1290 	return;
1291 usage:
1292 	fprintf(stderr, "usage: %s device %s subcommand\n", __progname,
1293 	    argv[0]);
1294 	exit(1);
1295 }
1296 
1297 /*
1298  * SMART READ DATA command
1299  */
1300 void
1301 device_smart_read(int argc, char *argv[])
1302 {
1303 	struct atareq req;
1304 	struct smart_read data;
1305 
1306 	if (argc != 1)
1307 		goto usage;
1308 
1309 	memset(&req, 0, sizeof(req));
1310 	memset(&data, 0, sizeof(data));
1311 
1312 	req.command = ATAPI_SMART;
1313 	req.cylinder = 0xc24f;
1314 	req.timeout = 1000;
1315 	req.features = ATA_SMART_READ;
1316 	req.flags = ATACMD_READ;
1317 	req.databuf = (caddr_t)&data;
1318 	req.datalen = sizeof(data);
1319 
1320 	ata_command(&req);
1321 
1322 	if (smart_cksum((u_int8_t *)&data, sizeof(data)) != 0)
1323 		errx(1, "Checksum mismatch");
1324 
1325 	printf("Off-line data collection:\n");
1326 	printf("    status: %s\n",
1327 	    valtostr(data.offstat & 0x7f, smart_offstat));
1328 	printf("    activity completion time: %d seconds\n",
1329 	    letoh16(data.time));
1330 	printf("    capabilities:\n");
1331 	print_bitinfo("\t%s\n", data.offcap, smart_offcap);
1332 	printf("Self-test execution:\n");
1333 	printf("    status: %s\n", valtostr(SMART_SELFSTAT_STAT(data.selfstat),
1334 	    smart_selfstat));
1335 	if (SMART_SELFSTAT_STAT(data.selfstat) == SMART_SELFSTAT_PROGRESS)
1336 		printf("remains %d%% of total time\n",
1337 		    SMART_SELFSTAT_PCNT(data.selfstat));
1338 	printf("    recommended polling time:\n");
1339 	printf("\tshort routine: %d minutes\n", data.shtime);
1340 	printf("\textended routine: %d minutes\n", data.extime);
1341 	printf("SMART capabilities:\n");
1342 	print_bitinfo("    %s\n", letoh16(data.smartcap), smart_smartcap);
1343 	printf("Error logging: ");
1344 	if (data.errcap & SMART_ERRCAP_ERRLOG)
1345 		printf("supported\n");
1346 	else
1347 		printf("not supported\n");
1348 
1349 	return;
1350 usage:
1351 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1352 	exit(1);
1353 }
1354 
1355 /*
1356  * SMART READ LOG command
1357  */
1358 void
1359 device_smart_readlog(int argc, char *argv[])
1360 {
1361 	struct atareq req;
1362 	int val;
1363 	u_int8_t inbuf[DEV_BSIZE];
1364 
1365 	if (argc != 2)
1366 		goto usage;
1367 
1368 	memset(&req, 0, sizeof(req));
1369 	memset(&inbuf, 0, sizeof(inbuf));
1370 
1371 	req.command = ATAPI_SMART;
1372 	req.cylinder = 0xc24f;
1373 	req.timeout = 1000;
1374 	req.features = ATA_SMART_READLOG;
1375 	req.flags = ATACMD_READ;
1376 	req.sec_count = 1;
1377 	req.databuf = (caddr_t)inbuf;
1378 	req.datalen = sizeof(inbuf);
1379 	if ((val = strtoval(argv[1], smart_readlog)) == -1)
1380 		goto usage;
1381 	req.sec_num = val;
1382 
1383 	ata_command(&req);
1384 
1385 	if (strcmp(argv[1], "directory") == 0) {
1386 		struct smart_log_dir *data = (struct smart_log_dir *)inbuf;
1387 		int i;
1388 
1389 		if (data->version != SMART_LOG_MSECT) {
1390 			printf("Device doesn't support multi-sector logs\n");
1391 			return;
1392 		}
1393 
1394 		for (i = 0; i < 255; i++)
1395 			printf("Log address %d: %d sectors\n", i + 1,
1396 			    data->entry[i].sec_num);
1397 	} else if (strcmp(argv[1], "summary") == 0) {
1398 		struct smart_log_sum *data = (struct smart_log_sum *)inbuf;
1399 		int i, n, nerr;
1400 
1401 		if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1402 			errx(1, "Checksum mismatch");
1403 
1404 		if (data->index == 0) {
1405 			printf("No log entries\n");
1406 			return;
1407 		}
1408 
1409 		nerr = letoh16(data->err_cnt);
1410 		printf("Error count: %d\n\n", nerr);
1411 		/*
1412 		 * Five error log data structures form a circular
1413 		 * buffer. data->index points to the most recent
1414 		 * record and err_cnt contains total error number.
1415 		 * We pass from the most recent record to the
1416 		 * latest one.
1417 		 */
1418 		i = data->index - 1;
1419 		n = 0;
1420 		do {
1421 			printf("Error %d:\n", n + 1);
1422 			smart_print_errdata(&data->errdata[i--]);
1423 			if (i == -1)
1424 				i = 4;
1425 		} while (++n < (nerr > 5 ? 5 : nerr));
1426 	} else if (strcmp(argv[1], "comp") == 0) {
1427 		struct smart_log_comp *data = (struct smart_log_comp *)inbuf;
1428 		u_int8_t *newbuf;
1429 		int i, n, nerr, nsect;
1430 
1431 		if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1432 			errx(1, "Checksum mismatch");
1433 
1434 		if (data->index == 0) {
1435 			printf("No log entries\n");
1436 			return;
1437 		}
1438 
1439 		i = data->index - 1;
1440 		nerr = letoh16(data->err_cnt);
1441 		printf("Error count: %d\n", nerr);
1442 		/*
1443 		 * From the first sector we obtain total error number
1444 		 * and calculate necessary number of sectors to read.
1445 		 * All read error data structures form a circular
1446 		 * buffer and we pass from the most recent record to
1447 		 * the latest one.
1448 		 */
1449 		nsect = nerr / 5 + (nerr % 5 != 0 ? 1 : 0);
1450 		if ((newbuf = (u_int8_t *)calloc(nsect, DEV_BSIZE)) == NULL)
1451 			err(1, "calloc()");
1452 		memset(&req, 0, sizeof(req));
1453 		req.flags = ATACMD_READ;
1454 		req.command = ATAPI_SMART;
1455 		req.features = ATA_SMART_READLOG;
1456 		req.sec_count = nsect;
1457 		req.sec_num = SMART_READLOG_COMP;
1458 		req.cylinder = 0xc24f;
1459 		req.databuf = (caddr_t)newbuf;
1460 		req.datalen = nsect * DEV_BSIZE;
1461 		req.timeout = 1000;
1462 		ata_command(&req);
1463 
1464 		n = 0;
1465 		data = (struct smart_log_comp *)
1466 		    (newbuf + (nsect - 1) * DEV_BSIZE);
1467 		do {
1468 			printf("Error %d:\n", n + 1);
1469 			smart_print_errdata(&data->errdata[i-- % 5]);
1470 			if (i == -1)
1471 				i = 254;
1472 			if (i % 5 == 4)
1473 				data = (struct smart_log_comp *)
1474 				    (newbuf + (i / 5) * DEV_BSIZE);
1475 		} while (++n < nerr);
1476 	} else if (strcmp(argv[1], "selftest") == 0) {
1477 		struct smart_log_self *data = (struct smart_log_self *)inbuf;
1478 		int i, n;
1479 
1480 		if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1481 			errx(1, "Checksum mismatch");
1482 
1483 		if (data->index == 0) {
1484 			printf("No log entries\n");
1485 			return;
1486 		}
1487 
1488 		/* circular buffer of 21 entries */
1489 		i = data->index - 1;
1490 		n = 0;
1491 		do {
1492 			/* don't print empty entries */
1493 			if ((data->desc[i].time1 | data->desc[i].time2) == 0)
1494 				break;
1495 			printf("Test %d\n", n + 1);
1496 			printf("    LBA Low: 0x%x\n", data->desc[i].reg_lbalo);
1497 			printf("    status: %s\n",
1498 			    valtostr(SMART_SELFSTAT_STAT(
1499 			    data->desc[i].selfstat),
1500 			    smart_selfstat));
1501 			printf("    timestamp: %d\n",
1502 			    MAKEWORD(data->desc[i].time1,
1503 				     data->desc[i].time2));
1504 			printf("    failure checkpoint byte: 0x%x\n",
1505 			    data->desc[i].chkpnt);
1506 			printf("    failing LBA: 0x%x\n",
1507 			    MAKEDWORD(data->desc[i].lbafail1,
1508 				      data->desc[i].lbafail2,
1509 				      data->desc[i].lbafail3,
1510 				      data->desc[i].lbafail4));
1511 			if (--i == -1)
1512 				i = 20;
1513 		} while (++n < 21);
1514 	}
1515 
1516 	return;
1517 usage:
1518 	fprintf(stderr, "usage: %s device %s log\n", __progname, argv[0]);
1519 	exit(1);
1520 }
1521 
1522 #define SMART_PRINTREG(str, reg)				\
1523 	printf(str "0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\n",	\
1524 	    data->cmd[0].reg,					\
1525 	    data->cmd[1].reg,					\
1526 	    data->cmd[2].reg,					\
1527 	    data->cmd[3].reg,					\
1528 	    data->cmd[4].reg)
1529 
1530 void
1531 smart_print_errdata(struct smart_log_errdata *data)
1532 {
1533 	printf("    error register: 0x%x\n", data->err.reg_err);
1534 	printf("    sector count register: 0x%x\n", data->err.reg_seccnt);
1535 	printf("    LBA Low register: 0x%x\n", data->err.reg_lbalo);
1536 	printf("    LBA Mid register: 0x%x\n", data->err.reg_lbamid);
1537 	printf("    LBA High register: 0x%x\n", data->err.reg_lbahi);
1538 	printf("    device register: 0x%x\n", data->err.reg_dev);
1539 	printf("    status register: 0x%x\n", data->err.reg_stat);
1540 	printf("    state: %s\n", valtostr(data->err.state, smart_logstat));
1541 	printf("    timestamp: %d\n", MAKEWORD(data->err.time1,
1542 					       data->err.time2));
1543 	printf("    history:\n");
1544 	SMART_PRINTREG("\tcontrol register:\t", reg_ctl);
1545 	SMART_PRINTREG("\tfeatures register:\t", reg_feat);
1546 	SMART_PRINTREG("\tsector count register:\t", reg_seccnt);
1547 	SMART_PRINTREG("\tLBA Low register:\t", reg_lbalo);
1548 	SMART_PRINTREG("\tLBA Mid register:\t", reg_lbamid);
1549 	SMART_PRINTREG("\tLBA High register:\t", reg_lbahi);
1550 	SMART_PRINTREG("\tdevice register:\t", reg_dev);
1551 	SMART_PRINTREG("\tcommand register:\t", reg_cmd);
1552 	printf("\ttimestamp:\t\t"
1553 	    "%d\t%d\t%d\t%d\t%d\n",
1554 	    MAKEDWORD(data->cmd[0].time1, data->cmd[0].time2,
1555 		      data->cmd[0].time3, data->cmd[0].time4),
1556 	    MAKEDWORD(data->cmd[1].time1, data->cmd[1].time2,
1557 		      data->cmd[1].time3, data->cmd[1].time4),
1558 	    MAKEDWORD(data->cmd[2].time1, data->cmd[2].time2,
1559 		      data->cmd[2].time3, data->cmd[2].time4),
1560 	    MAKEDWORD(data->cmd[3].time1, data->cmd[3].time2,
1561 		      data->cmd[3].time3, data->cmd[3].time4),
1562 	    MAKEDWORD(data->cmd[4].time1, data->cmd[4].time2,
1563 		      data->cmd[4].time3, data->cmd[4].time4));
1564 }
1565 
1566 int
1567 smart_cksum(u_int8_t *data, size_t len)
1568 {
1569 	u_int8_t sum = 0;
1570 	size_t i;
1571 
1572 	for (i = 0; i < len; i++)
1573 		sum += data[i];
1574 
1575 	return (sum);
1576 }
1577 
1578 /*
1579  * Read device attributes
1580  */
1581 void
1582 device_attr(int argc, char *argv[])
1583 {
1584 	struct atareq req;
1585 	struct smart_read attr_val;
1586 	struct smart_threshold attr_thr;
1587 	struct attribute *attr;
1588 	struct threshold *thr;
1589 	const char *attr_name;
1590 	static const char hex[]="0123456789abcdef";
1591 	char raw[13], *format;
1592 	int i, k, threshold_exceeded = 0;
1593 
1594 	if (argc != 1)
1595 		goto usage;
1596 
1597 	memset(&req, 0, sizeof(req));
1598 	memset(&attr_val, 0, sizeof(attr_val));	/* XXX */
1599 	memset(&attr_thr, 0, sizeof(attr_thr));	/* XXX */
1600 
1601 	req.command = ATAPI_SMART;
1602 	req.cylinder = 0xc24f;		/* LBA High = C2h, LBA Mid = 4Fh */
1603 	req.timeout = 1000;
1604 
1605 	req.features = ATA_SMART_READ;
1606 	req.flags = ATACMD_READ;
1607 	req.databuf = (caddr_t)&attr_val;
1608 	req.datalen = sizeof(attr_val);
1609 	ata_command(&req);
1610 
1611 	req.features = ATA_SMART_THRESHOLD;
1612 	req.flags = ATACMD_READ;
1613 	req.databuf = (caddr_t)&attr_thr;
1614 	req.datalen = sizeof(attr_thr);
1615 	ata_command(&req);
1616 
1617 	if (attr_val.revision != attr_thr.revision) {
1618 		/*
1619 		 * Non standard vendor implementation.
1620 		 * Return, since we don't know how to use this.
1621 		 */
1622 		return;
1623 	}
1624 
1625 	attr = attr_val.attribute;
1626 	thr = attr_thr.threshold;
1627 
1628 	printf("Attributes table revision: %d\n", attr_val.revision);
1629 	printf("ID\tAttribute name\t\t\tThreshold\tValue\tRaw\n");
1630 	for (i = 0; i < 30; i++) {
1631 		if (thr[i].id != 0 && thr[i].id == attr[i].id) {
1632 			attr_name = valtostr(thr[i].id, ibm_attr_names);
1633 			if (attr_name == NULL)
1634 				attr_name = "Unknown";
1635 
1636 			for (k = 0; k < 6; k++) {
1637 				u_int8_t b;
1638 				b = attr[i].raw[6 - k];
1639 				raw[k + k] = hex[b >> 4];
1640 				raw[k + k + 1] = hex[b & 0x0f];
1641 			}
1642 			raw[k + k] = '\0';
1643 			if (thr[i].value >= attr[i].value) {
1644 				++threshold_exceeded;
1645 				format = "%3d    *%-32.32s %3d\t\t%3d\t0x%s\n";
1646 			} else {
1647 				format = "%3d\t%-32.32s %3d\t\t%3d\t0x%s\n";
1648 			}
1649 			printf(format, thr[i].id, attr_name,
1650 			    thr[i].value, attr[i].value, raw);
1651 		}
1652 	}
1653 	if (threshold_exceeded)
1654 		fprintf(stderr, "One or more threshold values exceeded!\n");
1655 
1656 	return;
1657 
1658 usage:
1659 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1660 	exit(1);
1661 }
1662 
1663 /*
1664  * Set the automatic acoustic management on the disk.
1665  */
1666 void
1667 device_acoustic(int argc, char *argv[])
1668 {
1669 	u_char acoustic;
1670 	struct atareq req;
1671 	const char *errstr;
1672 
1673 	if (argc != 2)
1674 		goto usage;
1675 
1676 	acoustic = strtonum(argv[1], 0, 126, &errstr);
1677 	if (errstr)
1678 		errx(1, "Acoustic management value \"%s\" is %s "
1679 		    "(valid values: 0 - 126)", argv[1], errstr);
1680 
1681 	memset(&req, 0, sizeof(req));
1682 
1683 	req.sec_count = acoustic + 0x80;
1684 
1685 	req.command = SET_FEATURES ;
1686 	req.features = WDSF_AAM_EN ;
1687 	req.timeout = 1000;
1688 
1689 	ata_command(&req);
1690 
1691 	return;
1692 
1693 usage:
1694 	fprintf(stderr, "usage: %s device %s acoustic-management-level\n",
1695 	    __progname, argv[0]);
1696 	exit(1);
1697 }
1698 
1699 /*
1700  * Set the advanced power managmement on the disk. Power management
1701  * levels are translated from user-range 0-253 to ATAPI levels 1-0xFD
1702  * to keep a uniform interface to the user.
1703  */
1704 void
1705 device_apm(int argc, char *argv[])
1706 {
1707 	u_char power;
1708 	struct atareq req;
1709 	const char *errstr;
1710 
1711 	if (argc != 2)
1712 		goto usage;
1713 
1714 	power = strtonum(argv[1], 0, 253, &errstr);
1715 	if (errstr)
1716 		errx(1, "Advanced power management value \"%s\" is %s "
1717 		    "(valid values: 0 - 253)", argv[1], errstr);
1718 
1719 	memset(&req, 0, sizeof(req));
1720 
1721 	req.sec_count = power + 0x01;
1722 
1723 	req.command = SET_FEATURES ;
1724 	req.features = WDSF_APM_EN ;
1725 	req.timeout = 1000;
1726 
1727 	ata_command(&req);
1728 
1729 	return;
1730 
1731 usage:
1732 	fprintf(stderr, "usage: %s device %s power-management-level\n",
1733 	    __progname, argv[0]);
1734 	exit(1);
1735 }
1736 
1737 /*
1738  * En/disable features (the automatic acoustic managmement, Advanced Power
1739  * Management) on the disk.
1740  */
1741 void
1742 device_feature(int argc, char *argv[])
1743 {
1744 	struct atareq req;
1745 
1746 	if (argc != 1)
1747 		goto usage;
1748 
1749 	memset(&req, 0, sizeof(req));
1750 
1751 	req.command = SET_FEATURES ;
1752 
1753 	if (strcmp(argv[0], "acousticdisable") == 0)
1754 		req.features = WDSF_AAM_DS;
1755 	else if (strcmp(argv[0], "readaheadenable") == 0)
1756 		req.features = WDSF_READAHEAD_EN;
1757 	else if (strcmp(argv[0], "readaheaddisable") == 0)
1758 		req.features = WDSF_READAHEAD_DS;
1759 	else if (strcmp(argv[0], "writecacheenable") == 0)
1760 		req.features = WDSF_EN_WR_CACHE;
1761 	else if (strcmp(argv[0], "writecachedisable") == 0)
1762 		req.features = WDSF_WRITE_CACHE_DS;
1763 	else if (strcmp(argv[0], "apmdisable") == 0)
1764 		req.features = WDSF_APM_DS;
1765 	else if (strcmp(argv[0], "podenable") == 0)
1766 		req.features = WDSF_POD_EN;
1767 	else if (strcmp(argv[0], "poddisable") == 0)
1768 		req.features = WDSF_POD_DS;
1769 	else if (strcmp(argv[0], "puisenable") == 0)
1770 		req.features = WDSF_PUIS_EN;
1771 	else if (strcmp(argv[0], "puisdisable") == 0)
1772 		req.features = WDSF_PUIS_DS;
1773 	else if (strcmp(argv[0], "puisspinup") == 0)
1774 		req.features = WDSF_PUIS_SPINUP;
1775 	else
1776 		goto usage;
1777 
1778 	req.timeout = 1000;
1779 
1780 	ata_command(&req);
1781 
1782 	return;
1783 
1784 usage:
1785 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1786 	exit(1);
1787 }
1788 
1789 /*
1790  * Set the idle timer on the disk.  Set it for either idle mode or
1791  * standby mode, depending on how we were invoked.
1792  */
1793 void
1794 device_setidle(int argc, char *argv[])
1795 {
1796 	unsigned long idle;
1797 	struct atareq req;
1798 	char *end;
1799 
1800 	if (argc != 2)
1801 		goto usage;
1802 
1803 	idle = strtoul(argv[1], &end, 0);
1804 
1805 	if (*end != '\0' || idle > 19800)
1806 		errx(1, "Invalid idle time: \"%s\" "
1807 		    "(valid values: 1 - 19800)", argv[1]);
1808 
1809 	if (idle != 0 && idle < 5)
1810 		errx(1, "Idle timer must be at least 5 seconds");
1811 
1812 	memset(&req, 0, sizeof(req));
1813 
1814 	if (idle <= 240 * 5)
1815 		req.sec_count = idle / 5;
1816 	else
1817 		req.sec_count = idle / (30 * 60) + 240;
1818 
1819 	if (strcmp(argv[0], "setstandby") == 0)
1820 		req.command = WDCC_STANDBY;
1821 	else if (strcmp(argv[0], "setidle") == 0)
1822 		req.command = WDCC_IDLE;
1823 	else
1824 		goto usage;
1825 	req.timeout = 1000;
1826 
1827 	ata_command(&req);
1828 
1829 	return;
1830 
1831 usage:
1832 	fprintf(stderr, "usage: %s device %s %s\n", __progname, argv[0],
1833 	    (strcmp(argv[0], "setidle") == 0) ? "idle-timer" : "standby-timer");
1834 	exit(1);
1835 }
1836 
1837 /*
1838  * Query the device for the current power mode
1839  */
1840 void
1841 device_checkpower(int argc, char *argv[])
1842 {
1843 	struct atareq req;
1844 
1845 	if (argc != 1)
1846 		goto usage;
1847 
1848 	memset(&req, 0, sizeof(req));
1849 
1850 	req.command = WDCC_CHECK_PWR;
1851 	req.timeout = 1000;
1852 	req.flags = ATACMD_READREG;
1853 
1854 	ata_command(&req);
1855 
1856 	printf("Current power status: ");
1857 
1858 	switch (req.sec_count) {
1859 	case 0x00:
1860 		printf("Standby mode\n");
1861 		break;
1862 	case 0x80:
1863 		printf("Idle mode\n");
1864 		break;
1865 	case 0xff:
1866 		printf("Active mode\n");
1867 		break;
1868 	default:
1869 		printf("Unknown power code (%02x)\n", req.sec_count);
1870 	}
1871 
1872 	return;
1873 usage:
1874 	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1875 	exit(1);
1876 }
1877