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