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